From f22383f50f0ef3a2a3009c31770ecb1d613ee61d Mon Sep 17 00:00:00 2001 From: Alexander B Date: Sat, 28 Jun 2025 04:44:08 -0400 Subject: [PATCH] Rainmaker Table lights --- .../bootloader-patch-info.txt | 6 + .../bootloader-source_dirinfo.txt | 9 + .../bootloader-update-info.txt | 7 + .../tmp/bootloader-cfgcmd.txt | 1 + .../tmp/bootloader-mkdirs.cmake | 27 + RainMaker_Table-Lights/build/config.env | 12 + .../build/config/kconfig_menus.json | 32272 ++++++++++++++++ .../build/config/sdkconfig.cmake | 1790 + .../build/config/sdkconfig.h | 1154 + .../build/config/sdkconfig.json | 1564 + .../build/gdbinit/prefix_map | 1 + RainMaker_Table-Lights/build/kconfigs.in | 89 + .../build/kconfigs_projbuild.in | 8 + .../build/local_components_list.temp.yml | 225 - .../.component_hash | 1 + .../espressif__esp_diagnostics/CHECKSUMS.json | 1 + .../espressif__esp_diagnostics/CMakeLists.txt | 52 + .../espressif__esp_diagnostics/Kconfig | 134 + .../espressif__esp_diagnostics/LICENSE | 202 + .../espressif__esp_diagnostics/README.md | 5 + .../idf_component.yml | 14 + .../include/esp_diagnostics.h | 339 + .../include/esp_diagnostics_metrics.h | 309 + .../esp_diagnostics_network_variables.h | 34 + .../include/esp_diagnostics_system_metrics.h | 104 + .../include/esp_diagnostics_variables.h | 336 + .../src/esp_diagnostics_heap_metrics.c | 239 + .../src/esp_diagnostics_internal.h | 25 + .../src/esp_diagnostics_log_hook.c | 481 + .../src/esp_diagnostics_metrics.c | 350 + .../src/esp_diagnostics_network_variables.c | 353 + .../src/esp_diagnostics_utils.c | 359 + .../src/esp_diagnostics_variables.c | 344 + .../src/esp_diagnostics_wifi_metrics.c | 244 + .../espressif__esp_insights/.component_hash | 1 + .../espressif__esp_insights/CHECKSUMS.json | 1 + .../espressif__esp_insights/CMakeLists.txt | 47 + .../espressif__esp_insights/Kconfig | 90 + .../espressif__esp_insights/LICENSE | 202 + .../espressif__esp_insights/README.md | 6 + .../espressif__esp_insights/idf_component.yml | 22 + .../include/esp_insights.h | 253 + .../project_include.cmake | 29 + .../scripts/gen_tar_dir.cmake | 94 + .../scripts/get_projbuild_gitconfig.py | 120 + .../server_certs/https_server.crt | 20 + .../server_certs/mqtt_server.crt | 20 + .../src/esp_insights.c | 1076 + .../src/esp_insights_cbor_decoder.c | 382 + .../src/esp_insights_cbor_decoder.h | 49 + .../src/esp_insights_cbor_encoder.c | 947 + .../src/esp_insights_cbor_encoder.h | 92 + .../src/esp_insights_client_data.c | 118 + .../src/esp_insights_client_data.h | 23 + .../src/esp_insights_cmd_resp.c | 676 + .../src/esp_insights_encoder.c | 217 + .../src/esp_insights_encoder.h | 42 + .../src/esp_insights_internal.h | 63 + .../src/esp_insights_transport.c | 88 + .../src/transport/esp_insights_https.c | 158 + .../src/transport/esp_insights_mqtt.c | 201 + .../espressif__esp_rcp_update/.component_hash | 1 + .../espressif__esp_rcp_update/CHECKSUMS.json | 1 + .../espressif__esp_rcp_update/CMakeLists.txt | 28 + .../espressif__esp_rcp_update/Kconfig | 31 + .../espressif__esp_rcp_update/LICENSE | 202 + .../create_ota_image.py | 94 + .../idf_component.yml | 12 + .../include/esp_rcp_firmware.h | 38 + .../include/esp_rcp_ota.h | 100 + .../include/esp_rcp_update.h | 156 + .../src/esp_rcp_ota.c | 291 + .../src/esp_rcp_update.c | 343 + .../espressif__esp_schedule/.component_hash | 1 + .../espressif__esp_schedule/CHECKSUMS.json | 1 + .../espressif__esp_schedule/CMakeLists.txt | 10 + .../espressif__esp_schedule/LICENSE | 201 + .../espressif__esp_schedule/README.md | 50 + .../espressif__esp_schedule/component.mk | 5 + .../espressif__esp_schedule/idf_component.yml | 11 + .../include/esp_schedule.h | 236 + .../src/esp_schedule.c | 600 + .../src/esp_schedule_internal.h | 28 + .../src/esp_schedule_nvs.c | 296 + .../.component_hash | 1 + .../espressif__esp_secure_cert_mgr/.gitignore | 2 + .../.pre-commit-config.yaml | 16 + .../CHECKSUMS.json | 1 + .../CMakeLists.txt | 17 + .../Changelog.md | 88 + .../espressif__esp_secure_cert_mgr/Kconfig | 22 + .../espressif__esp_secure_cert_mgr/LICENSE | 202 + .../espressif__esp_secure_cert_mgr/README.md | 51 + .../ci/build_test.sh | 90 + .../docs/_static/tlv_format.png | Bin 0 -> 49394 bytes .../docs/format.md | 75 + .../esp_secure_cert_app/CMakeLists.txt | 6 + .../examples/esp_secure_cert_app/README.md | 61 + .../esp_secure_cert_app/main/CMakeLists.txt | 4 + .../esp_secure_cert_app/main/app_main.c | 259 + .../main/idf_component.yml | 6 + .../esp_secure_cert_app/partitions.csv | 4 + .../esp_secure_cert_app/qemu_test/README.md | 40 + .../qemu_test/build_qemu_images.sh | 82 + .../qemu_test/cust_flash/cust_flash.bin | Bin 0 -> 24576 bytes .../qemu_test/cust_flash/partition-table.bin | Bin 0 -> 3072 bytes .../cust_flash_legacy/cust_flash_legacy.bin | Bin 0 -> 24576 bytes .../cust_flash_legacy/partition-table.bin | Bin 0 -> 3072 bytes .../cust_flash_tlv/cust_flash_tlv.bin | Bin 0 -> 8192 bytes .../cust_flash_tlv/partition-table.bin | Bin 0 -> 3072 bytes .../qemu_test/make-qemu-img.sh | 18 + .../esp_secure_cert_app/qemu_test/nvs/nvs.bin | Bin 0 -> 12288 bytes .../qemu_test/nvs/partition-table.bin | Bin 0 -> 3072 bytes .../qemu_test/nvs_legacy/nvs_legacy.bin | Bin 0 -> 12288 bytes .../qemu_test/nvs_legacy/partition-table.bin | Bin 0 -> 3072 bytes .../qemu_test/requirements.txt | 3 + .../esp_secure_cert_app/sdkconfig.ci.legacy | 2 + .../esp_secure_cert_app/sdkconfig.ci.tlv | 1 + .../esp_secure_cert_app/sdkconfig.defaults | 3 + .../test_esp_secure_cert.py | 24 + .../examples/pytest.ini | 13 + .../idf_component.yml | 10 + .../include/esp_secure_cert_crypto.h | 28 + .../include/esp_secure_cert_read.h | 235 + .../include/esp_secure_cert_tlv_config.h | 65 + .../include/esp_secure_cert_tlv_read.h | 124 + .../private_include/esp_secure_cert_config.h | 87 + .../esp_secure_cert_tlv_private.h | 202 + .../srcs/esp_secure_cert_crypto.c | 93 + .../srcs/esp_secure_cert_read.c | 699 + .../srcs/esp_secure_cert_tlv_read.c | 884 + .../tools/LICENSE | 202 + .../tools/MANIFEST.in | 1 + .../tools/README.md | 91 + .../tools/__init__.py | 0 .../tools/configure_esp_secure_cert.py | 370 + .../tools/esp_secure_cert/__init__.py | 0 .../tools/esp_secure_cert/configure_ds.py | 172 + .../tools/esp_secure_cert/custflash_format.py | 178 + .../tools/esp_secure_cert/efuse_helper.py | 221 + .../esp_secure_cert/esp_secure_cert_helper.py | 126 + .../tools/esp_secure_cert/nvs_format.py | 84 + .../tools/esp_secure_cert/tlv_format.py | 367 + .../tools/requirements.txt | 1 + .../tools/setup.py | 90 + .../espressif__jsmn/.component_hash | 1 + .../espressif__jsmn/CHECKSUMS.json | 1 + .../espressif__jsmn/CMakeLists.txt | 13 + .../espressif__jsmn/Kconfig | 22 + .../espressif__jsmn/LICENSE | 19 + .../espressif__jsmn/README.md | 182 + .../espressif__jsmn/idf_component.yml | 6 + .../espressif__jsmn/include/jsmn.h | 477 + .../espressif__json_generator/.component_hash | 1 + .../espressif__json_generator/CHECKSUMS.json | 1 + .../espressif__json_generator/CMakeLists.txt | 3 + .../espressif__json_generator/LICENSE | 201 + .../espressif__json_generator/README.md | 16 + .../idf_component.yml | 3 + .../include/json_generator.h | 511 + .../src/json_generator.c | 312 + .../espressif__json_parser/.component_hash | 1 + .../espressif__json_parser/CHECKSUMS.json | 1 + .../espressif__json_parser/CMakeLists.txt | 4 + .../espressif__json_parser/LICENSE | 201 + .../espressif__json_parser/README.md | 10 + .../espressif__json_parser/idf_component.yml | 8 + .../include/json_parser.h | 80 + .../espressif__json_parser/src/json_parser.c | 474 + .../test/CMakeLists.txt | 2 + .../test/test_json_parser.c | 61 + .../espressif__mdns/.component_hash | 1 + .../espressif__mdns/.cz.yaml | 8 + .../espressif__mdns/CHANGELOG.md | 580 + .../espressif__mdns/CHECKSUMS.json | 1 + .../espressif__mdns/CMakeLists.txt | 42 + .../espressif__mdns/Kconfig | 190 + .../espressif__mdns/LICENSE | 202 + .../espressif__mdns/README.md | 14 + .../examples/query_advertise/CMakeLists.txt | 6 + .../examples/query_advertise/README.md | 91 + .../query_advertise/main/CMakeLists.txt | 2 + .../query_advertise/main/Kconfig.projbuild | 55 + .../query_advertise/main/idf_component.yml | 8 + .../query_advertise/main/mdns_example_main.c | 423 + .../examples/query_advertise/pytest_mdns.py | 203 + .../sdkconfig.ci.eth_custom_netif | 20 + .../query_advertise/sdkconfig.ci.eth_def | 15 + .../query_advertise/sdkconfig.ci.eth_no_ipv4 | 15 + .../query_advertise/sdkconfig.ci.eth_no_ipv6 | 16 + .../query_advertise/sdkconfig.ci.eth_socket | 16 + .../espressif__mdns/idf_component.yml | 13 + .../espressif__mdns/include/mdns.h | 937 + .../espressif__mdns/include/mdns_console.h | 14 + .../managed_components/espressif__mdns/mdns.c | 7863 ++++ .../espressif__mdns/mdns_console.c | 1452 + .../espressif__mdns/mdns_mem_caps.c | 96 + .../espressif__mdns/mdns_networking_lwip.c | 398 + .../espressif__mdns/mdns_networking_socket.c | 499 + .../espressif__mdns/mem_prefix_script.py | 54 + .../private_include/mdns_mem_caps.h | 65 + .../private_include/mdns_networking.h | 60 + .../private_include/mdns_private.h | 468 + .../tests/host_test/CMakeLists.txt | 16 + .../espressif__mdns/tests/host_test/README.md | 33 + .../components/esp_netif_linux/CMakeLists.txt | 8 + .../components/esp_netif_linux/Kconfig | 15 + .../esp_netif_linux/esp_netif_linux.c | 197 + .../esp_netif_linux/include/esp_wifi_types.h | 7 + .../esp_netif_linux/include/machine/endian.h | 8 + .../tests/host_test/dnsfixture.py | 130 + .../tests/host_test/main/CMakeLists.txt | 4 + .../tests/host_test/main/Kconfig.projbuild | 21 + .../tests/host_test/main/idf_component.yml | 7 + .../tests/host_test/main/main.c | 126 + .../tests/host_test/pytest_mdns.py | 180 + .../tests/host_test/sdkconfig.ci.app | 4 + .../tests/host_test/sdkconfig.ci.console | 4 + .../tests/host_test/sdkconfig.ci.target | 1 + .../tests/host_test/sdkconfig.defaults | 6 + .../tests/test_afl_fuzz_host/CMakeLists.txt | 7 + .../tests/test_afl_fuzz_host/Makefile | 82 + .../tests/test_afl_fuzz_host/README.md | 80 + .../tests/test_afl_fuzz_host/esp32_mock.c | 162 + .../tests/test_afl_fuzz_host/esp32_mock.h | 142 + .../tests/test_afl_fuzz_host/esp_attr.h | 14 + .../tests/test_afl_fuzz_host/esp_netif_mock.c | 55 + .../tests/test_afl_fuzz_host/in/file2.bin | Bin 0 -> 33 bytes .../test_afl_fuzz_host/in/minif_4a_txt.bin | Bin 0 -> 39 bytes .../test_afl_fuzz_host/in/minif_aaaa.bin | Bin 0 -> 33 bytes .../tests/test_afl_fuzz_host/in/minif_any.bin | Bin 0 -> 109 bytes .../test_afl_fuzz_host/in/minif_disc.bin | Bin 0 -> 65 bytes .../tests/test_afl_fuzz_host/in/minif_ptr.bin | Bin 0 -> 36 bytes .../test_afl_fuzz_host/in/minif_query.bin | Bin 0 -> 77 bytes .../test_afl_fuzz_host/in/minif_query2.bin | Bin 0 -> 64 bytes .../test_afl_fuzz_host/in/sub_fritz_m.bin | Bin 0 -> 72 bytes .../test_afl_fuzz_host/in/telnet_ptr.bin | Bin 0 -> 72 bytes .../tests/test_afl_fuzz_host/in/test-14.bin | Bin 0 -> 568 bytes .../tests/test_afl_fuzz_host/in/test-15.bin | Bin 0 -> 524 bytes .../tests/test_afl_fuzz_host/in/test-16.bin | Bin 0 -> 254 bytes .../tests/test_afl_fuzz_host/in/test-28.bin | Bin 0 -> 62 bytes .../tests/test_afl_fuzz_host/in/test-29.bin | Bin 0 -> 39 bytes .../tests/test_afl_fuzz_host/in/test-31.bin | Bin 0 -> 91 bytes .../tests/test_afl_fuzz_host/in/test-53.bin | Bin 0 -> 140 bytes .../tests/test_afl_fuzz_host/in/test-56.bin | Bin 0 -> 262 bytes .../tests/test_afl_fuzz_host/in/test-63.bin | Bin 0 -> 147 bytes .../tests/test_afl_fuzz_host/in/test-83.bin | Bin 0 -> 105 bytes .../tests/test_afl_fuzz_host/in/test-88.bin | Bin 0 -> 48 bytes .../tests/test_afl_fuzz_host/in/test-89.bin | Bin 0 -> 459 bytes .../tests/test_afl_fuzz_host/in/test-95.bin | Bin 0 -> 286 bytes .../tests/test_afl_fuzz_host/in/test-96.bin | Bin 0 -> 319 bytes .../test_afl_fuzz_host/input_packets.txt | 166 + .../tests/test_afl_fuzz_host/mdns_di.h | 61 + .../tests/test_afl_fuzz_host/mdns_mock.h | 31 + .../tests/test_afl_fuzz_host/sdkconfig.h | 424 + .../tests/test_afl_fuzz_host/test.c | 276 + .../tests/test_apps/CMakeLists.txt | 7 + .../espressif__mdns/tests/test_apps/README.md | 49 + .../tests/test_apps/main/CMakeLists.txt | 2 + .../tests/test_apps/main/Kconfig.projbuild | 40 + .../tests/test_apps/main/idf_component.yml | 8 + .../tests/test_apps/main/main.c | 117 + .../tests/test_apps/main/mdns_test.c | 189 + .../tests/test_apps/pytest_mdns_app.py | 320 + .../tests/test_apps/sdkconfig.ci | 13 + .../tests/test_apps/sdkconfig.defaults | 2 + .../tests/unit_test/CMakeLists.txt | 7 + .../tests/unit_test/main/CMakeLists.txt | 5 + .../tests/unit_test/main/test_mdns.c | 299 + .../tests/unit_test/pytest_app_mdns.py | 8 + .../tests/unit_test/sdkconfig.ci | 3 + .../tests/unit_test/sdkconfig.defaults | 2 + .../.component_hash | 1 + .../CHANGELOG.md | 22 + .../CHECKSUMS.json | 1 + .../CMakeLists.txt | 29 + .../espressif__network_provisioning/Kconfig | 80 + .../espressif__network_provisioning/LICENSE | 201 + .../espressif__network_provisioning/README.md | 9 + .../examples/README.md | 11 + .../examples/thread_prov/CMakeLists.txt | 6 + .../examples/thread_prov/README.md | 375 + .../examples/thread_prov/main/CMakeLists.txt | 2 + .../thread_prov/main/Kconfig.projbuild | 82 + .../examples/thread_prov/main/app_main.c | 495 + .../examples/thread_prov/main/esp_ot_config.h | 67 + .../thread_prov/main/idf_component.yml | 8 + .../examples/thread_prov/partitions.csv | 5 + .../examples/thread_prov/sdkconfig.defaults | 34 + .../examples/wifi_prov/CMakeLists.txt | 7 + .../examples/wifi_prov/README.md | 402 + .../examples/wifi_prov/main/CMakeLists.txt | 2 + .../examples/wifi_prov/main/Kconfig.projbuild | 107 + .../examples/wifi_prov/main/app_main.c | 525 + .../examples/wifi_prov/main/idf_component.yml | 8 + .../examples/wifi_prov/partitions.csv | 5 + .../examples/wifi_prov/sdkconfig.defaults | 11 + .../idf_component.yml | 9 + .../include/network_provisioning/manager.h | 760 + .../network_provisioning/network_config.h | 206 + .../network_provisioning/network_scan.h | 193 + .../include/network_provisioning/scheme_ble.h | 97 + .../network_provisioning/scheme_console.h | 26 + .../network_provisioning/scheme_softap.h | 39 + .../proto-c/network_config.pb-c.c | 1332 + .../proto-c/network_config.pb-c.h | 554 + .../proto-c/network_constants.pb-c.c | 426 + .../proto-c/network_constants.pb-c.h | 152 + .../proto-c/network_ctrl.pb-c.c | 756 + .../proto-c/network_ctrl.pb-c.h | 374 + .../proto-c/network_scan.pb-c.c | 1626 + .../proto-c/network_scan.pb-c.h | 614 + .../proto/CMakeLists.txt | 29 + .../proto/README.md | 29 + .../proto/makefile | 7 + .../proto/network_config.proto | 95 + .../proto/network_constants.proto | 51 + .../proto/network_ctrl.proto | 55 + .../proto/network_scan.proto | 109 + .../python/network_config_pb2.py | 53 + .../python/network_constants_pb2.py | 37 + .../python/network_ctrl_pb2.py | 44 + .../python/network_scan_pb2.py | 57 + .../src/handlers.c | 408 + .../src/manager.c | 2476 ++ .../src/network_config.c | 505 + .../src/network_ctrl.c | 247 + .../src/network_ctrl.h | 55 + .../src/network_provisioning_priv.h | 153 + .../src/network_scan.c | 480 + .../src/scheme_ble.c | 289 + .../src/scheme_console.c | 86 + .../src/scheme_softap.c | 188 + .../tool/esp_prov/README.md | 122 + .../tool/esp_prov/__init__.py | 5 + .../tool/esp_prov/esp_prov.py | 758 + .../tool/esp_prov/proto/__init__.py | 38 + .../tool/esp_prov/prov/__init__.py | 8 + .../tool/esp_prov/prov/custom_prov.py | 26 + .../tool/esp_prov/prov/network_ctrl.py | 61 + .../tool/esp_prov/prov/network_prov.py | 135 + .../tool/esp_prov/prov/network_scan.py | 129 + .../tool/esp_prov/security/__init__.py | 7 + .../tool/esp_prov/security/security.py | 10 + .../tool/esp_prov/security/security0.py | 53 + .../tool/esp_prov/security/security1.py | 140 + .../tool/esp_prov/security/security2.py | 182 + .../tool/esp_prov/security/srp6a.py | 301 + .../tool/esp_prov/transport/__init__.py | 7 + .../tool/esp_prov/transport/ble_cli.py | 213 + .../tool/esp_prov/transport/transport.py | 21 + .../tool/esp_prov/transport/transport_ble.py | 50 + .../esp_prov/transport/transport_console.py | 19 + .../tool/esp_prov/transport/transport_http.py | 49 + .../tool/esp_prov/utils/__init__.py | 5 + .../tool/esp_prov/utils/convenience.py | 31 + .../espressif__qrcode/.component_hash | 1 + .../espressif__qrcode/CHECKSUMS.json | 1 + .../espressif__qrcode/CMakeLists.txt | 3 + .../espressif__qrcode/LICENSE | 202 + .../espressif__qrcode/README.md | 9 + .../espressif__qrcode/esp_qrcode_main.c | 113 + .../espressif__qrcode/esp_qrcode_wrapper.c | 21 + .../espressif__qrcode/idf_component.yml | 3 + .../espressif__qrcode/include/qrcode.h | 97 + .../espressif__qrcode/qrcodegen.c | 1124 + .../espressif__qrcode/qrcodegen.h | 311 + .../espressif__rmaker_common/.component_hash | 1 + .../espressif__rmaker_common/CHECKSUMS.json | 1 + .../espressif__rmaker_common/CMakeLists.txt | 23 + .../espressif__rmaker_common/Kconfig | 180 + .../espressif__rmaker_common/LICENSE | 201 + .../espressif__rmaker_common/README.md | 9 + .../espressif__rmaker_common/component.mk | 5 + .../idf_component.yml | 7 + .../include/esp_rmaker_cmd_resp.h | 184 + .../include/esp_rmaker_common_console.h | 47 + .../include/esp_rmaker_common_events.h | 60 + .../include/esp_rmaker_factory.h | 73 + .../include/esp_rmaker_mqtt_glue.h | 177 + .../include/esp_rmaker_utils.h | 212 + .../include/esp_rmaker_work_queue.h | 82 + .../espressif__rmaker_common/src/cmd_resp.c | 429 + .../src/console/rmaker_common_cmds.c | 359 + .../src/console/rmaker_console.c | 117 + .../src/console/rmaker_console_internal.h | 9 + .../src/create_APN3_PPI_string.c | 246 + .../src/esp-mqtt/esp-mqtt-glue.c | 655 + .../espressif__rmaker_common/src/factory.c | 120 + .../espressif__rmaker_common/src/time.c | 277 + .../espressif__rmaker_common/src/timezone.c | 516 + .../espressif__rmaker_common/src/utils.c | 177 + .../espressif__rmaker_common/src/work_queue.c | 148 + RainMaker_Table-Lights/sdkconfig | 2623 ++ 394 files changed, 100141 insertions(+), 225 deletions(-) create mode 100644 RainMaker_Table-Lights/build/bootloader-prefix/src/bootloader-stamp/bootloader-patch-info.txt create mode 100644 RainMaker_Table-Lights/build/bootloader-prefix/src/bootloader-stamp/bootloader-source_dirinfo.txt create mode 100644 RainMaker_Table-Lights/build/bootloader-prefix/src/bootloader-stamp/bootloader-update-info.txt create mode 100644 RainMaker_Table-Lights/build/bootloader-prefix/tmp/bootloader-cfgcmd.txt create mode 100644 RainMaker_Table-Lights/build/bootloader-prefix/tmp/bootloader-mkdirs.cmake create mode 100644 RainMaker_Table-Lights/build/config.env create mode 100644 RainMaker_Table-Lights/build/config/kconfig_menus.json create mode 100644 RainMaker_Table-Lights/build/config/sdkconfig.cmake create mode 100644 RainMaker_Table-Lights/build/config/sdkconfig.h create mode 100644 RainMaker_Table-Lights/build/config/sdkconfig.json create mode 100644 RainMaker_Table-Lights/build/gdbinit/prefix_map create mode 100644 RainMaker_Table-Lights/build/kconfigs.in create mode 100644 RainMaker_Table-Lights/build/kconfigs_projbuild.in delete mode 100644 RainMaker_Table-Lights/build/local_components_list.temp.yml create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/.component_hash create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/CHECKSUMS.json create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/CMakeLists.txt create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/Kconfig create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/LICENSE create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/README.md create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/idf_component.yml create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/include/esp_diagnostics.h create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/include/esp_diagnostics_metrics.h create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/include/esp_diagnostics_network_variables.h create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/include/esp_diagnostics_system_metrics.h create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/include/esp_diagnostics_variables.h create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/src/esp_diagnostics_heap_metrics.c create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/src/esp_diagnostics_internal.h create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/src/esp_diagnostics_log_hook.c create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/src/esp_diagnostics_metrics.c create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/src/esp_diagnostics_network_variables.c create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/src/esp_diagnostics_utils.c create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/src/esp_diagnostics_variables.c create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/src/esp_diagnostics_wifi_metrics.c create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_insights/.component_hash create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_insights/CHECKSUMS.json create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_insights/CMakeLists.txt create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_insights/Kconfig create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_insights/LICENSE create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_insights/README.md create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_insights/idf_component.yml create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_insights/include/esp_insights.h create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_insights/project_include.cmake create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_insights/scripts/gen_tar_dir.cmake create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_insights/scripts/get_projbuild_gitconfig.py create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_insights/server_certs/https_server.crt create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_insights/server_certs/mqtt_server.crt create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_insights/src/esp_insights.c create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_insights/src/esp_insights_cbor_decoder.c create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_insights/src/esp_insights_cbor_decoder.h create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_insights/src/esp_insights_cbor_encoder.c create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_insights/src/esp_insights_cbor_encoder.h create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_insights/src/esp_insights_client_data.c create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_insights/src/esp_insights_client_data.h create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_insights/src/esp_insights_cmd_resp.c create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_insights/src/esp_insights_encoder.c create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_insights/src/esp_insights_encoder.h create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_insights/src/esp_insights_internal.h create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_insights/src/esp_insights_transport.c create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_insights/src/transport/esp_insights_https.c create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_insights/src/transport/esp_insights_mqtt.c create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_rcp_update/.component_hash create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_rcp_update/CHECKSUMS.json create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_rcp_update/CMakeLists.txt create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_rcp_update/Kconfig create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_rcp_update/LICENSE create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_rcp_update/create_ota_image.py create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_rcp_update/idf_component.yml create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_rcp_update/include/esp_rcp_firmware.h create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_rcp_update/include/esp_rcp_ota.h create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_rcp_update/include/esp_rcp_update.h create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_rcp_update/src/esp_rcp_ota.c create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_rcp_update/src/esp_rcp_update.c create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_schedule/.component_hash create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_schedule/CHECKSUMS.json create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_schedule/CMakeLists.txt create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_schedule/LICENSE create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_schedule/README.md create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_schedule/component.mk create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_schedule/idf_component.yml create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_schedule/include/esp_schedule.h create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_schedule/src/esp_schedule.c create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_schedule/src/esp_schedule_internal.h create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_schedule/src/esp_schedule_nvs.c create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/.component_hash create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/.gitignore create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/.pre-commit-config.yaml create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/CHECKSUMS.json create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/CMakeLists.txt create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/Changelog.md create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/Kconfig create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/LICENSE create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/README.md create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/ci/build_test.sh create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/docs/_static/tlv_format.png create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/docs/format.md create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/CMakeLists.txt create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/README.md create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/main/CMakeLists.txt create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/main/app_main.c create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/main/idf_component.yml create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/partitions.csv create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/qemu_test/README.md create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/qemu_test/build_qemu_images.sh create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/qemu_test/cust_flash/cust_flash.bin create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/qemu_test/cust_flash/partition-table.bin create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/qemu_test/cust_flash_legacy/cust_flash_legacy.bin create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/qemu_test/cust_flash_legacy/partition-table.bin create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/qemu_test/cust_flash_tlv/cust_flash_tlv.bin create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/qemu_test/cust_flash_tlv/partition-table.bin create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/qemu_test/make-qemu-img.sh create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/qemu_test/nvs/nvs.bin create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/qemu_test/nvs/partition-table.bin create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/qemu_test/nvs_legacy/nvs_legacy.bin create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/qemu_test/nvs_legacy/partition-table.bin create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/qemu_test/requirements.txt create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/sdkconfig.ci.legacy create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/sdkconfig.ci.tlv create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/sdkconfig.defaults create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/test_esp_secure_cert.py create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/pytest.ini create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/idf_component.yml create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/include/esp_secure_cert_crypto.h create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/include/esp_secure_cert_read.h create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/include/esp_secure_cert_tlv_config.h create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/include/esp_secure_cert_tlv_read.h create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/private_include/esp_secure_cert_config.h create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/private_include/esp_secure_cert_tlv_private.h create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/srcs/esp_secure_cert_crypto.c create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/srcs/esp_secure_cert_read.c create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/srcs/esp_secure_cert_tlv_read.c create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/tools/LICENSE create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/tools/MANIFEST.in create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/tools/README.md create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/tools/__init__.py create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/tools/configure_esp_secure_cert.py create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/tools/esp_secure_cert/__init__.py create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/tools/esp_secure_cert/configure_ds.py create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/tools/esp_secure_cert/custflash_format.py create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/tools/esp_secure_cert/efuse_helper.py create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/tools/esp_secure_cert/esp_secure_cert_helper.py create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/tools/esp_secure_cert/nvs_format.py create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/tools/esp_secure_cert/tlv_format.py create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/tools/requirements.txt create mode 100644 RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/tools/setup.py create mode 100644 RainMaker_Table-Lights/managed_components/espressif__jsmn/.component_hash create mode 100644 RainMaker_Table-Lights/managed_components/espressif__jsmn/CHECKSUMS.json create mode 100644 RainMaker_Table-Lights/managed_components/espressif__jsmn/CMakeLists.txt create mode 100644 RainMaker_Table-Lights/managed_components/espressif__jsmn/Kconfig create mode 100644 RainMaker_Table-Lights/managed_components/espressif__jsmn/LICENSE create mode 100644 RainMaker_Table-Lights/managed_components/espressif__jsmn/README.md create mode 100644 RainMaker_Table-Lights/managed_components/espressif__jsmn/idf_component.yml create mode 100644 RainMaker_Table-Lights/managed_components/espressif__jsmn/include/jsmn.h create mode 100644 RainMaker_Table-Lights/managed_components/espressif__json_generator/.component_hash create mode 100644 RainMaker_Table-Lights/managed_components/espressif__json_generator/CHECKSUMS.json create mode 100644 RainMaker_Table-Lights/managed_components/espressif__json_generator/CMakeLists.txt create mode 100644 RainMaker_Table-Lights/managed_components/espressif__json_generator/LICENSE create mode 100644 RainMaker_Table-Lights/managed_components/espressif__json_generator/README.md create mode 100644 RainMaker_Table-Lights/managed_components/espressif__json_generator/idf_component.yml create mode 100644 RainMaker_Table-Lights/managed_components/espressif__json_generator/include/json_generator.h create mode 100644 RainMaker_Table-Lights/managed_components/espressif__json_generator/src/json_generator.c create mode 100644 RainMaker_Table-Lights/managed_components/espressif__json_parser/.component_hash create mode 100644 RainMaker_Table-Lights/managed_components/espressif__json_parser/CHECKSUMS.json create mode 100644 RainMaker_Table-Lights/managed_components/espressif__json_parser/CMakeLists.txt create mode 100644 RainMaker_Table-Lights/managed_components/espressif__json_parser/LICENSE create mode 100644 RainMaker_Table-Lights/managed_components/espressif__json_parser/README.md create mode 100644 RainMaker_Table-Lights/managed_components/espressif__json_parser/idf_component.yml create mode 100644 RainMaker_Table-Lights/managed_components/espressif__json_parser/include/json_parser.h create mode 100644 RainMaker_Table-Lights/managed_components/espressif__json_parser/src/json_parser.c create mode 100644 RainMaker_Table-Lights/managed_components/espressif__json_parser/test/CMakeLists.txt create mode 100644 RainMaker_Table-Lights/managed_components/espressif__json_parser/test/test_json_parser.c create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/.component_hash create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/.cz.yaml create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/CHANGELOG.md create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/CHECKSUMS.json create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/CMakeLists.txt create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/Kconfig create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/LICENSE create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/README.md create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/examples/query_advertise/CMakeLists.txt create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/examples/query_advertise/README.md create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/examples/query_advertise/main/CMakeLists.txt create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/examples/query_advertise/main/Kconfig.projbuild create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/examples/query_advertise/main/idf_component.yml create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/examples/query_advertise/main/mdns_example_main.c create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/examples/query_advertise/pytest_mdns.py create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/examples/query_advertise/sdkconfig.ci.eth_custom_netif create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/examples/query_advertise/sdkconfig.ci.eth_def create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/examples/query_advertise/sdkconfig.ci.eth_no_ipv4 create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/examples/query_advertise/sdkconfig.ci.eth_no_ipv6 create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/examples/query_advertise/sdkconfig.ci.eth_socket create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/idf_component.yml create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/include/mdns.h create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/include/mdns_console.h create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/mdns.c create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/mdns_console.c create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/mdns_mem_caps.c create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/mdns_networking_lwip.c create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/mdns_networking_socket.c create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/mem_prefix_script.py create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/private_include/mdns_mem_caps.h create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/private_include/mdns_networking.h create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/private_include/mdns_private.h create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/tests/host_test/CMakeLists.txt create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/tests/host_test/README.md create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/tests/host_test/components/esp_netif_linux/CMakeLists.txt create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/tests/host_test/components/esp_netif_linux/Kconfig create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/tests/host_test/components/esp_netif_linux/esp_netif_linux.c create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/tests/host_test/components/esp_netif_linux/include/esp_wifi_types.h create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/tests/host_test/components/esp_netif_linux/include/machine/endian.h create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/tests/host_test/dnsfixture.py create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/tests/host_test/main/CMakeLists.txt create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/tests/host_test/main/Kconfig.projbuild create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/tests/host_test/main/idf_component.yml create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/tests/host_test/main/main.c create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/tests/host_test/pytest_mdns.py create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/tests/host_test/sdkconfig.ci.app create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/tests/host_test/sdkconfig.ci.console create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/tests/host_test/sdkconfig.ci.target create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/tests/host_test/sdkconfig.defaults create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/CMakeLists.txt create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/Makefile create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/README.md create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/esp32_mock.c create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/esp32_mock.h create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/esp_attr.h create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/esp_netif_mock.c create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/in/file2.bin create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/in/minif_4a_txt.bin create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/in/minif_aaaa.bin create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/in/minif_any.bin create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/in/minif_disc.bin create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/in/minif_ptr.bin create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/in/minif_query.bin create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/in/minif_query2.bin create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/in/sub_fritz_m.bin create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/in/telnet_ptr.bin create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/in/test-14.bin create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/in/test-15.bin create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/in/test-16.bin create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/in/test-28.bin create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/in/test-29.bin create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/in/test-31.bin create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/in/test-53.bin create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/in/test-56.bin create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/in/test-63.bin create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/in/test-83.bin create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/in/test-88.bin create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/in/test-89.bin create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/in/test-95.bin create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/in/test-96.bin create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/input_packets.txt create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/mdns_di.h create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/mdns_mock.h create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/sdkconfig.h create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/test.c create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_apps/CMakeLists.txt create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_apps/README.md create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_apps/main/CMakeLists.txt create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_apps/main/Kconfig.projbuild create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_apps/main/idf_component.yml create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_apps/main/main.c create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_apps/main/mdns_test.c create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_apps/pytest_mdns_app.py create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_apps/sdkconfig.ci create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_apps/sdkconfig.defaults create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/tests/unit_test/CMakeLists.txt create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/tests/unit_test/main/CMakeLists.txt create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/tests/unit_test/main/test_mdns.c create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/tests/unit_test/pytest_app_mdns.py create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/tests/unit_test/sdkconfig.ci create mode 100644 RainMaker_Table-Lights/managed_components/espressif__mdns/tests/unit_test/sdkconfig.defaults create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/.component_hash create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/CHANGELOG.md create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/CHECKSUMS.json create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/CMakeLists.txt create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/Kconfig create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/LICENSE create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/README.md create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/examples/README.md create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/examples/thread_prov/CMakeLists.txt create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/examples/thread_prov/README.md create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/examples/thread_prov/main/CMakeLists.txt create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/examples/thread_prov/main/Kconfig.projbuild create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/examples/thread_prov/main/app_main.c create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/examples/thread_prov/main/esp_ot_config.h create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/examples/thread_prov/main/idf_component.yml create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/examples/thread_prov/partitions.csv create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/examples/thread_prov/sdkconfig.defaults create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/examples/wifi_prov/CMakeLists.txt create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/examples/wifi_prov/README.md create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/examples/wifi_prov/main/CMakeLists.txt create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/examples/wifi_prov/main/Kconfig.projbuild create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/examples/wifi_prov/main/app_main.c create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/examples/wifi_prov/main/idf_component.yml create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/examples/wifi_prov/partitions.csv create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/examples/wifi_prov/sdkconfig.defaults create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/idf_component.yml create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/include/network_provisioning/manager.h create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/include/network_provisioning/network_config.h create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/include/network_provisioning/network_scan.h create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/include/network_provisioning/scheme_ble.h create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/include/network_provisioning/scheme_console.h create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/include/network_provisioning/scheme_softap.h create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/proto-c/network_config.pb-c.c create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/proto-c/network_config.pb-c.h create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/proto-c/network_constants.pb-c.c create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/proto-c/network_constants.pb-c.h create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/proto-c/network_ctrl.pb-c.c create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/proto-c/network_ctrl.pb-c.h create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/proto-c/network_scan.pb-c.c create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/proto-c/network_scan.pb-c.h create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/proto/CMakeLists.txt create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/proto/README.md create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/proto/makefile create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/proto/network_config.proto create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/proto/network_constants.proto create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/proto/network_ctrl.proto create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/proto/network_scan.proto create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/python/network_config_pb2.py create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/python/network_constants_pb2.py create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/python/network_ctrl_pb2.py create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/python/network_scan_pb2.py create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/src/handlers.c create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/src/manager.c create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/src/network_config.c create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/src/network_ctrl.c create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/src/network_ctrl.h create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/src/network_provisioning_priv.h create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/src/network_scan.c create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/src/scheme_ble.c create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/src/scheme_console.c create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/src/scheme_softap.c create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/README.md create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/__init__.py create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/esp_prov.py create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/proto/__init__.py create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/prov/__init__.py create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/prov/custom_prov.py create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/prov/network_ctrl.py create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/prov/network_prov.py create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/prov/network_scan.py create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/security/__init__.py create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/security/security.py create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/security/security0.py create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/security/security1.py create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/security/security2.py create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/security/srp6a.py create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/transport/__init__.py create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/transport/ble_cli.py create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/transport/transport.py create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/transport/transport_ble.py create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/transport/transport_console.py create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/transport/transport_http.py create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/utils/__init__.py create mode 100644 RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/utils/convenience.py create mode 100644 RainMaker_Table-Lights/managed_components/espressif__qrcode/.component_hash create mode 100644 RainMaker_Table-Lights/managed_components/espressif__qrcode/CHECKSUMS.json create mode 100644 RainMaker_Table-Lights/managed_components/espressif__qrcode/CMakeLists.txt create mode 100644 RainMaker_Table-Lights/managed_components/espressif__qrcode/LICENSE create mode 100644 RainMaker_Table-Lights/managed_components/espressif__qrcode/README.md create mode 100644 RainMaker_Table-Lights/managed_components/espressif__qrcode/esp_qrcode_main.c create mode 100644 RainMaker_Table-Lights/managed_components/espressif__qrcode/esp_qrcode_wrapper.c create mode 100644 RainMaker_Table-Lights/managed_components/espressif__qrcode/idf_component.yml create mode 100644 RainMaker_Table-Lights/managed_components/espressif__qrcode/include/qrcode.h create mode 100644 RainMaker_Table-Lights/managed_components/espressif__qrcode/qrcodegen.c create mode 100644 RainMaker_Table-Lights/managed_components/espressif__qrcode/qrcodegen.h create mode 100644 RainMaker_Table-Lights/managed_components/espressif__rmaker_common/.component_hash create mode 100644 RainMaker_Table-Lights/managed_components/espressif__rmaker_common/CHECKSUMS.json create mode 100644 RainMaker_Table-Lights/managed_components/espressif__rmaker_common/CMakeLists.txt create mode 100644 RainMaker_Table-Lights/managed_components/espressif__rmaker_common/Kconfig create mode 100644 RainMaker_Table-Lights/managed_components/espressif__rmaker_common/LICENSE create mode 100644 RainMaker_Table-Lights/managed_components/espressif__rmaker_common/README.md create mode 100644 RainMaker_Table-Lights/managed_components/espressif__rmaker_common/component.mk create mode 100644 RainMaker_Table-Lights/managed_components/espressif__rmaker_common/idf_component.yml create mode 100644 RainMaker_Table-Lights/managed_components/espressif__rmaker_common/include/esp_rmaker_cmd_resp.h create mode 100644 RainMaker_Table-Lights/managed_components/espressif__rmaker_common/include/esp_rmaker_common_console.h create mode 100644 RainMaker_Table-Lights/managed_components/espressif__rmaker_common/include/esp_rmaker_common_events.h create mode 100644 RainMaker_Table-Lights/managed_components/espressif__rmaker_common/include/esp_rmaker_factory.h create mode 100644 RainMaker_Table-Lights/managed_components/espressif__rmaker_common/include/esp_rmaker_mqtt_glue.h create mode 100644 RainMaker_Table-Lights/managed_components/espressif__rmaker_common/include/esp_rmaker_utils.h create mode 100644 RainMaker_Table-Lights/managed_components/espressif__rmaker_common/include/esp_rmaker_work_queue.h create mode 100644 RainMaker_Table-Lights/managed_components/espressif__rmaker_common/src/cmd_resp.c create mode 100644 RainMaker_Table-Lights/managed_components/espressif__rmaker_common/src/console/rmaker_common_cmds.c create mode 100644 RainMaker_Table-Lights/managed_components/espressif__rmaker_common/src/console/rmaker_console.c create mode 100644 RainMaker_Table-Lights/managed_components/espressif__rmaker_common/src/console/rmaker_console_internal.h create mode 100644 RainMaker_Table-Lights/managed_components/espressif__rmaker_common/src/create_APN3_PPI_string.c create mode 100644 RainMaker_Table-Lights/managed_components/espressif__rmaker_common/src/esp-mqtt/esp-mqtt-glue.c create mode 100644 RainMaker_Table-Lights/managed_components/espressif__rmaker_common/src/factory.c create mode 100644 RainMaker_Table-Lights/managed_components/espressif__rmaker_common/src/time.c create mode 100644 RainMaker_Table-Lights/managed_components/espressif__rmaker_common/src/timezone.c create mode 100644 RainMaker_Table-Lights/managed_components/espressif__rmaker_common/src/utils.c create mode 100644 RainMaker_Table-Lights/managed_components/espressif__rmaker_common/src/work_queue.c create mode 100644 RainMaker_Table-Lights/sdkconfig diff --git a/RainMaker_Table-Lights/build/bootloader-prefix/src/bootloader-stamp/bootloader-patch-info.txt b/RainMaker_Table-Lights/build/bootloader-prefix/src/bootloader-stamp/bootloader-patch-info.txt new file mode 100644 index 000000000..53e1e1e68 --- /dev/null +++ b/RainMaker_Table-Lights/build/bootloader-prefix/src/bootloader-stamp/bootloader-patch-info.txt @@ -0,0 +1,6 @@ +# This is a generated file and its contents are an internal implementation detail. +# The update step will be re-executed if anything in this file changes. +# No other meaning or use of this file is supported. + +command= +work_dir= diff --git a/RainMaker_Table-Lights/build/bootloader-prefix/src/bootloader-stamp/bootloader-source_dirinfo.txt b/RainMaker_Table-Lights/build/bootloader-prefix/src/bootloader-stamp/bootloader-source_dirinfo.txt new file mode 100644 index 000000000..43cacfa38 --- /dev/null +++ b/RainMaker_Table-Lights/build/bootloader-prefix/src/bootloader-stamp/bootloader-source_dirinfo.txt @@ -0,0 +1,9 @@ +# This is a generated file and its contents are an internal implementation detail. +# The download step will be re-executed if anything in this file changes. +# No other meaning or use of this file is supported. + +method=source_dir +command= +source_dir=/home/alex/esp/v5.4.1/esp-idf/components/bootloader/subproject +work_dir= + diff --git a/RainMaker_Table-Lights/build/bootloader-prefix/src/bootloader-stamp/bootloader-update-info.txt b/RainMaker_Table-Lights/build/bootloader-prefix/src/bootloader-stamp/bootloader-update-info.txt new file mode 100644 index 000000000..31617d15d --- /dev/null +++ b/RainMaker_Table-Lights/build/bootloader-prefix/src/bootloader-stamp/bootloader-update-info.txt @@ -0,0 +1,7 @@ +# This is a generated file and its contents are an internal implementation detail. +# The patch step will be re-executed if anything in this file changes. +# No other meaning or use of this file is supported. + +command (connected)= +command (disconnected)= +work_dir= diff --git a/RainMaker_Table-Lights/build/bootloader-prefix/tmp/bootloader-cfgcmd.txt b/RainMaker_Table-Lights/build/bootloader-prefix/tmp/bootloader-cfgcmd.txt new file mode 100644 index 000000000..8c9844ef8 --- /dev/null +++ b/RainMaker_Table-Lights/build/bootloader-prefix/tmp/bootloader-cfgcmd.txt @@ -0,0 +1 @@ +cmd='/home/alex/.espressif/tools/cmake/3.30.2/bin/cmake;-DSDKCONFIG=/home/alex/github/ESP-Nodes/RainMaker_Table-Lights/sdkconfig;-DIDF_PATH=/home/alex/esp/v5.4.1/esp-idf;-DIDF_TARGET=esp32c3;-DPYTHON_DEPS_CHECKED=1;-DPYTHON=/home/alex/.espressif/python_env/idf5.4_py3.13_env/bin/python;-DEXTRA_COMPONENT_DIRS=/home/alex/esp/v5.4.1/esp-idf/components/bootloader;-DPROJECT_SOURCE_DIR=/home/alex/github/ESP-Nodes/RainMaker_Table-Lights;-DIGNORE_EXTRA_COMPONENT=;-GNinja;-S;;-B;' diff --git a/RainMaker_Table-Lights/build/bootloader-prefix/tmp/bootloader-mkdirs.cmake b/RainMaker_Table-Lights/build/bootloader-prefix/tmp/bootloader-mkdirs.cmake new file mode 100644 index 000000000..f085f892d --- /dev/null +++ b/RainMaker_Table-Lights/build/bootloader-prefix/tmp/bootloader-mkdirs.cmake @@ -0,0 +1,27 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +cmake_minimum_required(VERSION 3.5) + +# If CMAKE_DISABLE_SOURCE_CHANGES is set to true and the source directory is an +# existing directory in our source tree, calling file(MAKE_DIRECTORY) on it +# would cause a fatal error, even though it would be a no-op. +if(NOT EXISTS "/home/alex/esp/v5.4.1/esp-idf/components/bootloader/subproject") + file(MAKE_DIRECTORY "/home/alex/esp/v5.4.1/esp-idf/components/bootloader/subproject") +endif() +file(MAKE_DIRECTORY + "/home/alex/github/ESP-Nodes/RainMaker_Table-Lights/build/bootloader" + "/home/alex/github/ESP-Nodes/RainMaker_Table-Lights/build/bootloader-prefix" + "/home/alex/github/ESP-Nodes/RainMaker_Table-Lights/build/bootloader-prefix/tmp" + "/home/alex/github/ESP-Nodes/RainMaker_Table-Lights/build/bootloader-prefix/src/bootloader-stamp" + "/home/alex/github/ESP-Nodes/RainMaker_Table-Lights/build/bootloader-prefix/src" + "/home/alex/github/ESP-Nodes/RainMaker_Table-Lights/build/bootloader-prefix/src/bootloader-stamp" +) + +set(configSubDirs ) +foreach(subDir IN LISTS configSubDirs) + file(MAKE_DIRECTORY "/home/alex/github/ESP-Nodes/RainMaker_Table-Lights/build/bootloader-prefix/src/bootloader-stamp/${subDir}") +endforeach() +if(cfgdir) + file(MAKE_DIRECTORY "/home/alex/github/ESP-Nodes/RainMaker_Table-Lights/build/bootloader-prefix/src/bootloader-stamp${cfgdir}") # cfgdir has leading slash +endif() diff --git a/RainMaker_Table-Lights/build/config.env b/RainMaker_Table-Lights/build/config.env new file mode 100644 index 000000000..14dec8969 --- /dev/null +++ b/RainMaker_Table-Lights/build/config.env @@ -0,0 +1,12 @@ +{ + "COMPONENT_KCONFIGS": "/home/alex/esp/v5.4.1/esp-idf/components/app_trace/Kconfig;/home/alex/esp/v5.4.1/esp-idf/components/bt/Kconfig;/home/alex/esp/v5.4.1/esp-idf/components/console/Kconfig;/home/alex/esp/v5.4.1/esp-idf/components/driver/Kconfig;/home/alex/esp/v5.4.1/esp-idf/components/efuse/Kconfig;/home/alex/esp/v5.4.1/esp-idf/components/esp-tls/Kconfig;/home/alex/esp/v5.4.1/esp-idf/components/esp_adc/Kconfig;/home/alex/esp/v5.4.1/esp-idf/components/esp_coex/Kconfig;/home/alex/esp/v5.4.1/esp-idf/components/esp_common/Kconfig;/home/alex/esp/v5.4.1/esp-idf/components/esp_driver_ana_cmpr/Kconfig;/home/alex/esp/v5.4.1/esp-idf/components/esp_driver_cam/Kconfig;/home/alex/esp/v5.4.1/esp-idf/components/esp_driver_dac/Kconfig;/home/alex/esp/v5.4.1/esp-idf/components/esp_driver_gpio/Kconfig;/home/alex/esp/v5.4.1/esp-idf/components/esp_driver_gptimer/Kconfig;/home/alex/esp/v5.4.1/esp-idf/components/esp_driver_i2c/Kconfig;/home/alex/esp/v5.4.1/esp-idf/components/esp_driver_i2s/Kconfig;/home/alex/esp/v5.4.1/esp-idf/components/esp_driver_isp/Kconfig;/home/alex/esp/v5.4.1/esp-idf/components/esp_driver_jpeg/Kconfig;/home/alex/esp/v5.4.1/esp-idf/components/esp_driver_ledc/Kconfig;/home/alex/esp/v5.4.1/esp-idf/components/esp_driver_mcpwm/Kconfig;/home/alex/esp/v5.4.1/esp-idf/components/esp_driver_parlio/Kconfig;/home/alex/esp/v5.4.1/esp-idf/components/esp_driver_pcnt/Kconfig;/home/alex/esp/v5.4.1/esp-idf/components/esp_driver_rmt/Kconfig;/home/alex/esp/v5.4.1/esp-idf/components/esp_driver_sdm/Kconfig;/home/alex/esp/v5.4.1/esp-idf/components/esp_driver_spi/Kconfig;/home/alex/esp/v5.4.1/esp-idf/components/esp_driver_touch_sens/Kconfig;/home/alex/esp/v5.4.1/esp-idf/components/esp_driver_tsens/Kconfig;/home/alex/esp/v5.4.1/esp-idf/components/esp_driver_uart/Kconfig;/home/alex/esp/v5.4.1/esp-idf/components/esp_driver_usb_serial_jtag/Kconfig;/home/alex/esp/v5.4.1/esp-idf/components/esp_eth/Kconfig;/home/alex/esp/v5.4.1/esp-idf/components/esp_event/Kconfig;/home/alex/esp/v5.4.1/esp-idf/components/esp_gdbstub/Kconfig;/home/alex/esp/v5.4.1/esp-idf/components/esp_hid/Kconfig;/home/alex/esp/v5.4.1/esp-idf/components/esp_http_client/Kconfig;/home/alex/esp/v5.4.1/esp-idf/components/esp_http_server/Kconfig;/home/alex/esp/v5.4.1/esp-idf/components/esp_https_ota/Kconfig;/home/alex/esp/v5.4.1/esp-idf/components/esp_https_server/Kconfig;/home/alex/esp/v5.4.1/esp-idf/components/esp_hw_support/Kconfig;/home/alex/esp/v5.4.1/esp-idf/components/esp_lcd/Kconfig;/home/alex/esp/v5.4.1/esp-idf/components/esp_mm/Kconfig;/home/alex/esp/v5.4.1/esp-idf/components/esp_netif/Kconfig;/home/alex/esp/v5.4.1/esp-idf/components/esp_partition/Kconfig;/home/alex/esp/v5.4.1/esp-idf/components/esp_phy/Kconfig;/home/alex/esp/v5.4.1/esp-idf/components/esp_pm/Kconfig;/home/alex/esp/v5.4.1/esp-idf/components/esp_psram/Kconfig;/home/alex/esp/v5.4.1/esp-idf/components/esp_ringbuf/Kconfig;/home/alex/esp/v5.4.1/esp-idf/components/esp_security/Kconfig;/home/alex/esp/v5.4.1/esp-idf/components/esp_system/Kconfig;/home/alex/esp/v5.4.1/esp-idf/components/esp_timer/Kconfig;/home/alex/esp/v5.4.1/esp-idf/components/esp_wifi/Kconfig;/home/alex/esp/v5.4.1/esp-idf/components/espcoredump/Kconfig;/home/alex/esp/v5.4.1/esp-idf/components/fatfs/Kconfig;/home/alex/esp/v5.4.1/esp-idf/components/freertos/Kconfig;/home/alex/esp/v5.4.1/esp-idf/components/hal/Kconfig;/home/alex/esp/v5.4.1/esp-idf/components/heap/Kconfig;/home/alex/esp/v5.4.1/esp-idf/components/ieee802154/Kconfig;/home/alex/esp/v5.4.1/esp-idf/components/log/Kconfig;/home/alex/esp/v5.4.1/esp-idf/components/lwip/Kconfig;/home/alex/esp/v5.4.1/esp-idf/components/mbedtls/Kconfig;/home/alex/esp/v5.4.1/esp-idf/components/mqtt/esp-mqtt/Kconfig;/home/alex/esp/v5.4.1/esp-idf/components/newlib/Kconfig;/home/alex/esp/v5.4.1/esp-idf/components/nvs_flash/Kconfig;/home/alex/esp/v5.4.1/esp-idf/components/nvs_sec_provider/Kconfig;/home/alex/esp/v5.4.1/esp-idf/components/openthread/Kconfig;/home/alex/esp/v5.4.1/esp-idf/components/protocomm/Kconfig;/home/alex/esp/v5.4.1/esp-idf/components/pthread/Kconfig;/home/alex/esp/v5.4.1/esp-idf/components/soc/Kconfig;/home/alex/esp/v5.4.1/esp-idf/components/spi_flash/Kconfig;/home/alex/esp/v5.4.1/esp-idf/components/spiffs/Kconfig;/home/alex/esp/v5.4.1/esp-idf/components/tcp_transport/Kconfig;/home/alex/esp/v5.4.1/esp-idf/components/ulp/Kconfig;/home/alex/esp/v5.4.1/esp-idf/components/unity/Kconfig;/home/alex/esp/v5.4.1/esp-idf/components/usb/Kconfig;/home/alex/esp/v5.4.1/esp-idf/components/vfs/Kconfig;/home/alex/esp/v5.4.1/esp-idf/components/wear_levelling/Kconfig;/home/alex/esp/v5.4.1/esp-idf/components/wifi_provisioning/Kconfig;/home/alex/.espressif/esp-rainmaker/examples/common/app_insights/Kconfig;/home/alex/.espressif/esp-rainmaker/examples/common/gpio_button/Kconfig;/home/alex/.espressif/esp-rainmaker/examples/common/ws2812_led/Kconfig;/home/alex/github/ESP-Nodes/RainMaker_Table-Lights/managed_components/espressif__esp-serial-flasher/Kconfig;/home/alex/github/ESP-Nodes/RainMaker_Table-Lights/managed_components/espressif__esp_diag_data_store/Kconfig;/home/alex/github/ESP-Nodes/RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/Kconfig;/home/alex/github/ESP-Nodes/RainMaker_Table-Lights/managed_components/espressif__esp_insights/Kconfig;/home/alex/github/ESP-Nodes/RainMaker_Table-Lights/managed_components/espressif__esp_rcp_update/Kconfig;/home/alex/github/ESP-Nodes/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/Kconfig;/home/alex/github/ESP-Nodes/RainMaker_Table-Lights/managed_components/espressif__jsmn/Kconfig;/home/alex/github/ESP-Nodes/RainMaker_Table-Lights/managed_components/espressif__mdns/Kconfig;/home/alex/github/ESP-Nodes/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/Kconfig;/home/alex/github/ESP-Nodes/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/Kconfig", + "COMPONENT_KCONFIGS_PROJBUILD": "/home/alex/esp/v5.4.1/esp-idf/components/bootloader/Kconfig.projbuild;/home/alex/esp/v5.4.1/esp-idf/components/esp_app_format/Kconfig.projbuild;/home/alex/esp/v5.4.1/esp-idf/components/esp_rom/Kconfig.projbuild;/home/alex/esp/v5.4.1/esp-idf/components/esptool_py/Kconfig.projbuild;/home/alex/esp/v5.4.1/esp-idf/components/partition_table/Kconfig.projbuild;/home/alex/github/ESP-Nodes/RainMaker_Table-Lights/main/Kconfig.projbuild;/home/alex/.espressif/esp-rainmaker/examples/common/app_network/Kconfig.projbuild;/home/alex/.espressif/esp-rainmaker/components/esp_rainmaker/Kconfig.projbuild", + "COMPONENT_SDKCONFIG_RENAMES": "/home/alex/esp/v5.4.1/esp-idf/components/app_trace/sdkconfig.rename;/home/alex/esp/v5.4.1/esp-idf/components/bootloader/sdkconfig.rename;/home/alex/esp/v5.4.1/esp-idf/components/bt/sdkconfig.rename;/home/alex/esp/v5.4.1/esp-idf/components/bt/sdkconfig.rename.esp32c3;/home/alex/esp/v5.4.1/esp-idf/components/driver/sdkconfig.rename;/home/alex/esp/v5.4.1/esp-idf/components/esp_coex/sdkconfig.rename;/home/alex/esp/v5.4.1/esp-idf/components/esp_event/sdkconfig.rename;/home/alex/esp/v5.4.1/esp-idf/components/esp_gdbstub/sdkconfig.rename;/home/alex/esp/v5.4.1/esp-idf/components/esp_https_ota/sdkconfig.rename;/home/alex/esp/v5.4.1/esp-idf/components/esp_hw_support/sdkconfig.rename;/home/alex/esp/v5.4.1/esp-idf/components/esp_hw_support/sdkconfig.rename.esp32c3;/home/alex/esp/v5.4.1/esp-idf/components/esp_phy/sdkconfig.rename;/home/alex/esp/v5.4.1/esp-idf/components/esp_pm/sdkconfig.rename;/home/alex/esp/v5.4.1/esp-idf/components/esp_system/sdkconfig.rename;/home/alex/esp/v5.4.1/esp-idf/components/esp_system/sdkconfig.rename.esp32c3;/home/alex/esp/v5.4.1/esp-idf/components/esp_timer/sdkconfig.rename;/home/alex/esp/v5.4.1/esp-idf/components/esp_wifi/sdkconfig.rename;/home/alex/esp/v5.4.1/esp-idf/components/espcoredump/sdkconfig.rename;/home/alex/esp/v5.4.1/esp-idf/components/esptool_py/sdkconfig.rename;/home/alex/esp/v5.4.1/esp-idf/components/freertos/sdkconfig.rename;/home/alex/esp/v5.4.1/esp-idf/components/hal/sdkconfig.rename;/home/alex/esp/v5.4.1/esp-idf/components/lwip/sdkconfig.rename;/home/alex/esp/v5.4.1/esp-idf/components/newlib/sdkconfig.rename.esp32c3;/home/alex/esp/v5.4.1/esp-idf/components/pthread/sdkconfig.rename;/home/alex/esp/v5.4.1/esp-idf/components/spi_flash/sdkconfig.rename;/home/alex/esp/v5.4.1/esp-idf/components/vfs/sdkconfig.rename;/home/alex/.espressif/esp-rainmaker/examples/common/app_network/sdkconfig.rename;/home/alex/.espressif/esp-rainmaker/components/esp_rainmaker/sdkconfig.rename", + "IDF_TARGET": "esp32c3", + "IDF_TOOLCHAIN": "gcc", + "IDF_VERSION": "5.4.1", + "IDF_ENV_FPGA": "", + "IDF_PATH": "/home/alex/esp/v5.4.1/esp-idf", + "COMPONENT_KCONFIGS_SOURCE_FILE": "/home/alex/github/ESP-Nodes/RainMaker_Table-Lights/build/kconfigs.in", + "COMPONENT_KCONFIGS_PROJBUILD_SOURCE_FILE": "/home/alex/github/ESP-Nodes/RainMaker_Table-Lights/build/kconfigs_projbuild.in" +} diff --git a/RainMaker_Table-Lights/build/config/kconfig_menus.json b/RainMaker_Table-Lights/build/config/kconfig_menus.json new file mode 100644 index 000000000..018a7f201 --- /dev/null +++ b/RainMaker_Table-Lights/build/config/kconfig_menus.json @@ -0,0 +1,32272 @@ +[ + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_ADC_SUPPORTED", + "name": "SOC_ADC_SUPPORTED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_DEDICATED_GPIO_SUPPORTED", + "name": "SOC_DEDICATED_GPIO_SUPPORTED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_UART_SUPPORTED", + "name": "SOC_UART_SUPPORTED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_GDMA_SUPPORTED", + "name": "SOC_GDMA_SUPPORTED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_AHB_GDMA_SUPPORTED", + "name": "SOC_AHB_GDMA_SUPPORTED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_GPTIMER_SUPPORTED", + "name": "SOC_GPTIMER_SUPPORTED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_TWAI_SUPPORTED", + "name": "SOC_TWAI_SUPPORTED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_BT_SUPPORTED", + "name": "SOC_BT_SUPPORTED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_ASYNC_MEMCPY_SUPPORTED", + "name": "SOC_ASYNC_MEMCPY_SUPPORTED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_USB_SERIAL_JTAG_SUPPORTED", + "name": "SOC_USB_SERIAL_JTAG_SUPPORTED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_TEMP_SENSOR_SUPPORTED", + "name": "SOC_TEMP_SENSOR_SUPPORTED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_XT_WDT_SUPPORTED", + "name": "SOC_XT_WDT_SUPPORTED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_PHY_SUPPORTED", + "name": "SOC_PHY_SUPPORTED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_WIFI_SUPPORTED", + "name": "SOC_WIFI_SUPPORTED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_SUPPORTS_SECURE_DL_MODE", + "name": "SOC_SUPPORTS_SECURE_DL_MODE", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_EFUSE_KEY_PURPOSE_FIELD", + "name": "SOC_EFUSE_KEY_PURPOSE_FIELD", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_EFUSE_HAS_EFUSE_RST_BUG", + "name": "SOC_EFUSE_HAS_EFUSE_RST_BUG", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_EFUSE_SUPPORTED", + "name": "SOC_EFUSE_SUPPORTED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_RTC_FAST_MEM_SUPPORTED", + "name": "SOC_RTC_FAST_MEM_SUPPORTED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_RTC_MEM_SUPPORTED", + "name": "SOC_RTC_MEM_SUPPORTED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_I2S_SUPPORTED", + "name": "SOC_I2S_SUPPORTED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_RMT_SUPPORTED", + "name": "SOC_RMT_SUPPORTED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_SDM_SUPPORTED", + "name": "SOC_SDM_SUPPORTED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_GPSPI_SUPPORTED", + "name": "SOC_GPSPI_SUPPORTED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_LEDC_SUPPORTED", + "name": "SOC_LEDC_SUPPORTED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_I2C_SUPPORTED", + "name": "SOC_I2C_SUPPORTED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_SYSTIMER_SUPPORTED", + "name": "SOC_SYSTIMER_SUPPORTED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_SUPPORT_COEXISTENCE", + "name": "SOC_SUPPORT_COEXISTENCE", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_AES_SUPPORTED", + "name": "SOC_AES_SUPPORTED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_MPI_SUPPORTED", + "name": "SOC_MPI_SUPPORTED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_SHA_SUPPORTED", + "name": "SOC_SHA_SUPPORTED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_HMAC_SUPPORTED", + "name": "SOC_HMAC_SUPPORTED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_DIG_SIGN_SUPPORTED", + "name": "SOC_DIG_SIGN_SUPPORTED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_FLASH_ENC_SUPPORTED", + "name": "SOC_FLASH_ENC_SUPPORTED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_SECURE_BOOT_SUPPORTED", + "name": "SOC_SECURE_BOOT_SUPPORTED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_MEMPROT_SUPPORTED", + "name": "SOC_MEMPROT_SUPPORTED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_BOD_SUPPORTED", + "name": "SOC_BOD_SUPPORTED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_CLK_TREE_SUPPORTED", + "name": "SOC_CLK_TREE_SUPPORTED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_ASSIST_DEBUG_SUPPORTED", + "name": "SOC_ASSIST_DEBUG_SUPPORTED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_WDT_SUPPORTED", + "name": "SOC_WDT_SUPPORTED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_SPI_FLASH_SUPPORTED", + "name": "SOC_SPI_FLASH_SUPPORTED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_RNG_SUPPORTED", + "name": "SOC_RNG_SUPPORTED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_LIGHT_SLEEP_SUPPORTED", + "name": "SOC_LIGHT_SLEEP_SUPPORTED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_DEEP_SLEEP_SUPPORTED", + "name": "SOC_DEEP_SLEEP_SUPPORTED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_LP_PERIPH_SHARE_INTERRUPT", + "name": "SOC_LP_PERIPH_SHARE_INTERRUPT", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_PM_SUPPORTED", + "name": "SOC_PM_SUPPORTED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_XTAL_SUPPORT_40M", + "name": "SOC_XTAL_SUPPORT_40M", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_AES_SUPPORT_DMA", + "name": "SOC_AES_SUPPORT_DMA", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_AES_GDMA", + "name": "SOC_AES_GDMA", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_AES_SUPPORT_AES_128", + "name": "SOC_AES_SUPPORT_AES_128", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_AES_SUPPORT_AES_256", + "name": "SOC_AES_SUPPORT_AES_256", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_ADC_DIG_CTRL_SUPPORTED", + "name": "SOC_ADC_DIG_CTRL_SUPPORTED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_ADC_ARBITER_SUPPORTED", + "name": "SOC_ADC_ARBITER_SUPPORTED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_ADC_DIG_IIR_FILTER_SUPPORTED", + "name": "SOC_ADC_DIG_IIR_FILTER_SUPPORTED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_ADC_MONITOR_SUPPORTED", + "name": "SOC_ADC_MONITOR_SUPPORTED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_ADC_DMA_SUPPORTED", + "name": "SOC_ADC_DMA_SUPPORTED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_ADC_PERIPH_NUM", + "name": "SOC_ADC_PERIPH_NUM", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_ADC_MAX_CHANNEL_NUM", + "name": "SOC_ADC_MAX_CHANNEL_NUM", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_ADC_ATTEN_NUM", + "name": "SOC_ADC_ATTEN_NUM", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_ADC_DIGI_CONTROLLER_NUM", + "name": "SOC_ADC_DIGI_CONTROLLER_NUM", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_ADC_PATT_LEN_MAX", + "name": "SOC_ADC_PATT_LEN_MAX", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_ADC_DIGI_MIN_BITWIDTH", + "name": "SOC_ADC_DIGI_MIN_BITWIDTH", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_ADC_DIGI_MAX_BITWIDTH", + "name": "SOC_ADC_DIGI_MAX_BITWIDTH", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_ADC_DIGI_RESULT_BYTES", + "name": "SOC_ADC_DIGI_RESULT_BYTES", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_ADC_DIGI_DATA_BYTES_PER_CONV", + "name": "SOC_ADC_DIGI_DATA_BYTES_PER_CONV", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_ADC_DIGI_IIR_FILTER_NUM", + "name": "SOC_ADC_DIGI_IIR_FILTER_NUM", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_ADC_DIGI_MONITOR_NUM", + "name": "SOC_ADC_DIGI_MONITOR_NUM", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_ADC_SAMPLE_FREQ_THRES_HIGH", + "name": "SOC_ADC_SAMPLE_FREQ_THRES_HIGH", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_ADC_SAMPLE_FREQ_THRES_LOW", + "name": "SOC_ADC_SAMPLE_FREQ_THRES_LOW", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_ADC_RTC_MIN_BITWIDTH", + "name": "SOC_ADC_RTC_MIN_BITWIDTH", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_ADC_RTC_MAX_BITWIDTH", + "name": "SOC_ADC_RTC_MAX_BITWIDTH", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_ADC_CALIBRATION_V1_SUPPORTED", + "name": "SOC_ADC_CALIBRATION_V1_SUPPORTED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_ADC_SELF_HW_CALI_SUPPORTED", + "name": "SOC_ADC_SELF_HW_CALI_SUPPORTED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_ADC_SHARED_POWER", + "name": "SOC_ADC_SHARED_POWER", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_APB_BACKUP_DMA", + "name": "SOC_APB_BACKUP_DMA", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_BROWNOUT_RESET_SUPPORTED", + "name": "SOC_BROWNOUT_RESET_SUPPORTED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_SHARED_IDCACHE_SUPPORTED", + "name": "SOC_SHARED_IDCACHE_SUPPORTED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_CACHE_MEMORY_IBANK_SIZE", + "name": "SOC_CACHE_MEMORY_IBANK_SIZE", + "range": null, + "title": null, + "type": "hex" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_CPU_CORES_NUM", + "name": "SOC_CPU_CORES_NUM", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_CPU_INTR_NUM", + "name": "SOC_CPU_INTR_NUM", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_CPU_HAS_FLEXIBLE_INTC", + "name": "SOC_CPU_HAS_FLEXIBLE_INTC", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_CPU_HAS_CSR_PC", + "name": "SOC_CPU_HAS_CSR_PC", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_CPU_BREAKPOINTS_NUM", + "name": "SOC_CPU_BREAKPOINTS_NUM", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_CPU_WATCHPOINTS_NUM", + "name": "SOC_CPU_WATCHPOINTS_NUM", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_CPU_WATCHPOINT_MAX_REGION_SIZE", + "name": "SOC_CPU_WATCHPOINT_MAX_REGION_SIZE", + "range": null, + "title": null, + "type": "hex" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_DS_SIGNATURE_MAX_BIT_LEN", + "name": "SOC_DS_SIGNATURE_MAX_BIT_LEN", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_DS_KEY_PARAM_MD_IV_LENGTH", + "name": "SOC_DS_KEY_PARAM_MD_IV_LENGTH", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_DS_KEY_CHECK_MAX_WAIT_US", + "name": "SOC_DS_KEY_CHECK_MAX_WAIT_US", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_AHB_GDMA_VERSION", + "name": "SOC_AHB_GDMA_VERSION", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_GDMA_NUM_GROUPS_MAX", + "name": "SOC_GDMA_NUM_GROUPS_MAX", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_GDMA_PAIRS_PER_GROUP_MAX", + "name": "SOC_GDMA_PAIRS_PER_GROUP_MAX", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_GPIO_PORT", + "name": "SOC_GPIO_PORT", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_GPIO_PIN_COUNT", + "name": "SOC_GPIO_PIN_COUNT", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_GPIO_SUPPORT_PIN_GLITCH_FILTER", + "name": "SOC_GPIO_SUPPORT_PIN_GLITCH_FILTER", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_GPIO_FILTER_CLK_SUPPORT_APB", + "name": "SOC_GPIO_FILTER_CLK_SUPPORT_APB", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_GPIO_SUPPORT_FORCE_HOLD", + "name": "SOC_GPIO_SUPPORT_FORCE_HOLD", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP", + "name": "SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_GPIO_IN_RANGE_MAX", + "name": "SOC_GPIO_IN_RANGE_MAX", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_GPIO_OUT_RANGE_MAX", + "name": "SOC_GPIO_OUT_RANGE_MAX", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_GPIO_DEEP_SLEEP_WAKE_VALID_GPIO_MASK", + "name": "SOC_GPIO_DEEP_SLEEP_WAKE_VALID_GPIO_MASK", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_GPIO_DEEP_SLEEP_WAKE_SUPPORTED_PIN_CNT", + "name": "SOC_GPIO_DEEP_SLEEP_WAKE_SUPPORTED_PIN_CNT", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_GPIO_VALID_DIGITAL_IO_PAD_MASK", + "name": "SOC_GPIO_VALID_DIGITAL_IO_PAD_MASK", + "range": null, + "title": null, + "type": "hex" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_GPIO_CLOCKOUT_BY_GPIO_MATRIX", + "name": "SOC_GPIO_CLOCKOUT_BY_GPIO_MATRIX", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_GPIO_CLOCKOUT_CHANNEL_NUM", + "name": "SOC_GPIO_CLOCKOUT_CHANNEL_NUM", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_GPIO_SUPPORT_HOLD_IO_IN_DSLP", + "name": "SOC_GPIO_SUPPORT_HOLD_IO_IN_DSLP", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_DEDIC_GPIO_OUT_CHANNELS_NUM", + "name": "SOC_DEDIC_GPIO_OUT_CHANNELS_NUM", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_DEDIC_GPIO_IN_CHANNELS_NUM", + "name": "SOC_DEDIC_GPIO_IN_CHANNELS_NUM", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_DEDIC_PERIPH_ALWAYS_ENABLE", + "name": "SOC_DEDIC_PERIPH_ALWAYS_ENABLE", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_I2C_NUM", + "name": "SOC_I2C_NUM", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_HP_I2C_NUM", + "name": "SOC_HP_I2C_NUM", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_I2C_FIFO_LEN", + "name": "SOC_I2C_FIFO_LEN", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_I2C_CMD_REG_NUM", + "name": "SOC_I2C_CMD_REG_NUM", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_I2C_SUPPORT_SLAVE", + "name": "SOC_I2C_SUPPORT_SLAVE", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_I2C_SUPPORT_HW_CLR_BUS", + "name": "SOC_I2C_SUPPORT_HW_CLR_BUS", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_I2C_SUPPORT_XTAL", + "name": "SOC_I2C_SUPPORT_XTAL", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_I2C_SUPPORT_RTC", + "name": "SOC_I2C_SUPPORT_RTC", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_I2C_SUPPORT_10BIT_ADDR", + "name": "SOC_I2C_SUPPORT_10BIT_ADDR", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_I2C_SLAVE_SUPPORT_BROADCAST", + "name": "SOC_I2C_SLAVE_SUPPORT_BROADCAST", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_I2C_SLAVE_CAN_GET_STRETCH_CAUSE", + "name": "SOC_I2C_SLAVE_CAN_GET_STRETCH_CAUSE", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_I2C_SLAVE_SUPPORT_I2CRAM_ACCESS", + "name": "SOC_I2C_SLAVE_SUPPORT_I2CRAM_ACCESS", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_I2S_NUM", + "name": "SOC_I2S_NUM", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_I2S_HW_VERSION_2", + "name": "SOC_I2S_HW_VERSION_2", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_I2S_SUPPORTS_XTAL", + "name": "SOC_I2S_SUPPORTS_XTAL", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_I2S_SUPPORTS_PLL_F160M", + "name": "SOC_I2S_SUPPORTS_PLL_F160M", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_I2S_SUPPORTS_PCM", + "name": "SOC_I2S_SUPPORTS_PCM", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_I2S_SUPPORTS_PDM", + "name": "SOC_I2S_SUPPORTS_PDM", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_I2S_SUPPORTS_PDM_TX", + "name": "SOC_I2S_SUPPORTS_PDM_TX", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_I2S_PDM_MAX_TX_LINES", + "name": "SOC_I2S_PDM_MAX_TX_LINES", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_I2S_SUPPORTS_TDM", + "name": "SOC_I2S_SUPPORTS_TDM", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_LEDC_SUPPORT_APB_CLOCK", + "name": "SOC_LEDC_SUPPORT_APB_CLOCK", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_LEDC_SUPPORT_XTAL_CLOCK", + "name": "SOC_LEDC_SUPPORT_XTAL_CLOCK", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_LEDC_TIMER_NUM", + "name": "SOC_LEDC_TIMER_NUM", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_LEDC_CHANNEL_NUM", + "name": "SOC_LEDC_CHANNEL_NUM", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_LEDC_TIMER_BIT_WIDTH", + "name": "SOC_LEDC_TIMER_BIT_WIDTH", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_LEDC_SUPPORT_FADE_STOP", + "name": "SOC_LEDC_SUPPORT_FADE_STOP", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_MMU_LINEAR_ADDRESS_REGION_NUM", + "name": "SOC_MMU_LINEAR_ADDRESS_REGION_NUM", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_MMU_PERIPH_NUM", + "name": "SOC_MMU_PERIPH_NUM", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_MPU_CONFIGURABLE_REGIONS_SUPPORTED", + "name": "SOC_MPU_CONFIGURABLE_REGIONS_SUPPORTED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_MPU_MIN_REGION_SIZE", + "name": "SOC_MPU_MIN_REGION_SIZE", + "range": null, + "title": null, + "type": "hex" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_MPU_REGIONS_MAX_NUM", + "name": "SOC_MPU_REGIONS_MAX_NUM", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_MPU_REGION_RO_SUPPORTED", + "name": "SOC_MPU_REGION_RO_SUPPORTED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_MPU_REGION_WO_SUPPORTED", + "name": "SOC_MPU_REGION_WO_SUPPORTED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_RMT_GROUPS", + "name": "SOC_RMT_GROUPS", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_RMT_TX_CANDIDATES_PER_GROUP", + "name": "SOC_RMT_TX_CANDIDATES_PER_GROUP", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_RMT_RX_CANDIDATES_PER_GROUP", + "name": "SOC_RMT_RX_CANDIDATES_PER_GROUP", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_RMT_CHANNELS_PER_GROUP", + "name": "SOC_RMT_CHANNELS_PER_GROUP", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_RMT_MEM_WORDS_PER_CHANNEL", + "name": "SOC_RMT_MEM_WORDS_PER_CHANNEL", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_RMT_SUPPORT_RX_PINGPONG", + "name": "SOC_RMT_SUPPORT_RX_PINGPONG", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_RMT_SUPPORT_RX_DEMODULATION", + "name": "SOC_RMT_SUPPORT_RX_DEMODULATION", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_RMT_SUPPORT_TX_ASYNC_STOP", + "name": "SOC_RMT_SUPPORT_TX_ASYNC_STOP", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_RMT_SUPPORT_TX_LOOP_COUNT", + "name": "SOC_RMT_SUPPORT_TX_LOOP_COUNT", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_RMT_SUPPORT_TX_SYNCHRO", + "name": "SOC_RMT_SUPPORT_TX_SYNCHRO", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_RMT_SUPPORT_TX_CARRIER_DATA_ONLY", + "name": "SOC_RMT_SUPPORT_TX_CARRIER_DATA_ONLY", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_RMT_SUPPORT_XTAL", + "name": "SOC_RMT_SUPPORT_XTAL", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_RMT_SUPPORT_APB", + "name": "SOC_RMT_SUPPORT_APB", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_RMT_SUPPORT_RC_FAST", + "name": "SOC_RMT_SUPPORT_RC_FAST", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_RTC_CNTL_CPU_PD_DMA_BUS_WIDTH", + "name": "SOC_RTC_CNTL_CPU_PD_DMA_BUS_WIDTH", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_RTC_CNTL_CPU_PD_REG_FILE_NUM", + "name": "SOC_RTC_CNTL_CPU_PD_REG_FILE_NUM", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_SLEEP_SYSTIMER_STALL_WORKAROUND", + "name": "SOC_SLEEP_SYSTIMER_STALL_WORKAROUND", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_SLEEP_TGWDT_STOP_WORKAROUND", + "name": "SOC_SLEEP_TGWDT_STOP_WORKAROUND", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_RTCIO_PIN_COUNT", + "name": "SOC_RTCIO_PIN_COUNT", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_MPI_MEM_BLOCKS_NUM", + "name": "SOC_MPI_MEM_BLOCKS_NUM", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_MPI_OPERATIONS_NUM", + "name": "SOC_MPI_OPERATIONS_NUM", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_RSA_MAX_BIT_LEN", + "name": "SOC_RSA_MAX_BIT_LEN", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_SHA_DMA_MAX_BUFFER_SIZE", + "name": "SOC_SHA_DMA_MAX_BUFFER_SIZE", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_SHA_SUPPORT_DMA", + "name": "SOC_SHA_SUPPORT_DMA", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_SHA_SUPPORT_RESUME", + "name": "SOC_SHA_SUPPORT_RESUME", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_SHA_GDMA", + "name": "SOC_SHA_GDMA", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_SHA_SUPPORT_SHA1", + "name": "SOC_SHA_SUPPORT_SHA1", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_SHA_SUPPORT_SHA224", + "name": "SOC_SHA_SUPPORT_SHA224", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_SHA_SUPPORT_SHA256", + "name": "SOC_SHA_SUPPORT_SHA256", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_SDM_GROUPS", + "name": "SOC_SDM_GROUPS", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_SDM_CHANNELS_PER_GROUP", + "name": "SOC_SDM_CHANNELS_PER_GROUP", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_SDM_CLK_SUPPORT_APB", + "name": "SOC_SDM_CLK_SUPPORT_APB", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_SPI_PERIPH_NUM", + "name": "SOC_SPI_PERIPH_NUM", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_SPI_MAX_CS_NUM", + "name": "SOC_SPI_MAX_CS_NUM", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_SPI_MAXIMUM_BUFFER_SIZE", + "name": "SOC_SPI_MAXIMUM_BUFFER_SIZE", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_SPI_SUPPORT_DDRCLK", + "name": "SOC_SPI_SUPPORT_DDRCLK", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_SPI_SLAVE_SUPPORT_SEG_TRANS", + "name": "SOC_SPI_SLAVE_SUPPORT_SEG_TRANS", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_SPI_SUPPORT_CD_SIG", + "name": "SOC_SPI_SUPPORT_CD_SIG", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_SPI_SUPPORT_CONTINUOUS_TRANS", + "name": "SOC_SPI_SUPPORT_CONTINUOUS_TRANS", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_SPI_SUPPORT_SLAVE_HD_VER2", + "name": "SOC_SPI_SUPPORT_SLAVE_HD_VER2", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_SPI_SUPPORT_CLK_APB", + "name": "SOC_SPI_SUPPORT_CLK_APB", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_SPI_SUPPORT_CLK_XTAL", + "name": "SOC_SPI_SUPPORT_CLK_XTAL", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_SPI_PERIPH_SUPPORT_CONTROL_DUMMY_OUT", + "name": "SOC_SPI_PERIPH_SUPPORT_CONTROL_DUMMY_OUT", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_SPI_SCT_SUPPORTED", + "name": "SOC_SPI_SCT_SUPPORTED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_SPI_SCT_REG_NUM", + "name": "SOC_SPI_SCT_REG_NUM", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_SPI_SCT_BUFFER_NUM_MAX", + "name": "SOC_SPI_SCT_BUFFER_NUM_MAX", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_SPI_SCT_CONF_BITLEN_MAX", + "name": "SOC_SPI_SCT_CONF_BITLEN_MAX", + "range": null, + "title": null, + "type": "hex" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_MEMSPI_IS_INDEPENDENT", + "name": "SOC_MEMSPI_IS_INDEPENDENT", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_SPI_MAX_PRE_DIVIDER", + "name": "SOC_SPI_MAX_PRE_DIVIDER", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_SPI_MEM_SUPPORT_AUTO_WAIT_IDLE", + "name": "SOC_SPI_MEM_SUPPORT_AUTO_WAIT_IDLE", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_SPI_MEM_SUPPORT_AUTO_SUSPEND", + "name": "SOC_SPI_MEM_SUPPORT_AUTO_SUSPEND", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_SPI_MEM_SUPPORT_AUTO_RESUME", + "name": "SOC_SPI_MEM_SUPPORT_AUTO_RESUME", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_SPI_MEM_SUPPORT_IDLE_INTR", + "name": "SOC_SPI_MEM_SUPPORT_IDLE_INTR", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_SPI_MEM_SUPPORT_SW_SUSPEND", + "name": "SOC_SPI_MEM_SUPPORT_SW_SUSPEND", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_SPI_MEM_SUPPORT_CHECK_SUS", + "name": "SOC_SPI_MEM_SUPPORT_CHECK_SUS", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_SPI_MEM_SUPPORT_CONFIG_GPIO_BY_EFUSE", + "name": "SOC_SPI_MEM_SUPPORT_CONFIG_GPIO_BY_EFUSE", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_SPI_MEM_SUPPORT_WRAP", + "name": "SOC_SPI_MEM_SUPPORT_WRAP", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_MEMSPI_SRC_FREQ_80M_SUPPORTED", + "name": "SOC_MEMSPI_SRC_FREQ_80M_SUPPORTED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_MEMSPI_SRC_FREQ_40M_SUPPORTED", + "name": "SOC_MEMSPI_SRC_FREQ_40M_SUPPORTED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_MEMSPI_SRC_FREQ_26M_SUPPORTED", + "name": "SOC_MEMSPI_SRC_FREQ_26M_SUPPORTED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_MEMSPI_SRC_FREQ_20M_SUPPORTED", + "name": "SOC_MEMSPI_SRC_FREQ_20M_SUPPORTED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_SYSTIMER_COUNTER_NUM", + "name": "SOC_SYSTIMER_COUNTER_NUM", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_SYSTIMER_ALARM_NUM", + "name": "SOC_SYSTIMER_ALARM_NUM", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_SYSTIMER_BIT_WIDTH_LO", + "name": "SOC_SYSTIMER_BIT_WIDTH_LO", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_SYSTIMER_BIT_WIDTH_HI", + "name": "SOC_SYSTIMER_BIT_WIDTH_HI", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_SYSTIMER_FIXED_DIVIDER", + "name": "SOC_SYSTIMER_FIXED_DIVIDER", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_SYSTIMER_INT_LEVEL", + "name": "SOC_SYSTIMER_INT_LEVEL", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_SYSTIMER_ALARM_MISS_COMPENSATE", + "name": "SOC_SYSTIMER_ALARM_MISS_COMPENSATE", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_TIMER_GROUPS", + "name": "SOC_TIMER_GROUPS", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_TIMER_GROUP_TIMERS_PER_GROUP", + "name": "SOC_TIMER_GROUP_TIMERS_PER_GROUP", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_TIMER_GROUP_COUNTER_BIT_WIDTH", + "name": "SOC_TIMER_GROUP_COUNTER_BIT_WIDTH", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_TIMER_GROUP_SUPPORT_XTAL", + "name": "SOC_TIMER_GROUP_SUPPORT_XTAL", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_TIMER_GROUP_SUPPORT_APB", + "name": "SOC_TIMER_GROUP_SUPPORT_APB", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_TIMER_GROUP_TOTAL_TIMERS", + "name": "SOC_TIMER_GROUP_TOTAL_TIMERS", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_LP_TIMER_BIT_WIDTH_LO", + "name": "SOC_LP_TIMER_BIT_WIDTH_LO", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_LP_TIMER_BIT_WIDTH_HI", + "name": "SOC_LP_TIMER_BIT_WIDTH_HI", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_MWDT_SUPPORT_XTAL", + "name": "SOC_MWDT_SUPPORT_XTAL", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_TWAI_CONTROLLER_NUM", + "name": "SOC_TWAI_CONTROLLER_NUM", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_TWAI_CLK_SUPPORT_APB", + "name": "SOC_TWAI_CLK_SUPPORT_APB", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_TWAI_BRP_MIN", + "name": "SOC_TWAI_BRP_MIN", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_TWAI_BRP_MAX", + "name": "SOC_TWAI_BRP_MAX", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_TWAI_SUPPORTS_RX_STATUS", + "name": "SOC_TWAI_SUPPORTS_RX_STATUS", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_EFUSE_DIS_DOWNLOAD_ICACHE", + "name": "SOC_EFUSE_DIS_DOWNLOAD_ICACHE", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_EFUSE_DIS_PAD_JTAG", + "name": "SOC_EFUSE_DIS_PAD_JTAG", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_EFUSE_DIS_USB_JTAG", + "name": "SOC_EFUSE_DIS_USB_JTAG", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_EFUSE_DIS_DIRECT_BOOT", + "name": "SOC_EFUSE_DIS_DIRECT_BOOT", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_EFUSE_SOFT_DIS_JTAG", + "name": "SOC_EFUSE_SOFT_DIS_JTAG", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_EFUSE_DIS_ICACHE", + "name": "SOC_EFUSE_DIS_ICACHE", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_EFUSE_BLOCK9_KEY_PURPOSE_QUIRK", + "name": "SOC_EFUSE_BLOCK9_KEY_PURPOSE_QUIRK", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_SECURE_BOOT_V2_RSA", + "name": "SOC_SECURE_BOOT_V2_RSA", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS", + "name": "SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_EFUSE_REVOKE_BOOT_KEY_DIGESTS", + "name": "SOC_EFUSE_REVOKE_BOOT_KEY_DIGESTS", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_SUPPORT_SECURE_BOOT_REVOKE_KEY", + "name": "SOC_SUPPORT_SECURE_BOOT_REVOKE_KEY", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_FLASH_ENCRYPTED_XTS_AES_BLOCK_MAX", + "name": "SOC_FLASH_ENCRYPTED_XTS_AES_BLOCK_MAX", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_FLASH_ENCRYPTION_XTS_AES", + "name": "SOC_FLASH_ENCRYPTION_XTS_AES", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_FLASH_ENCRYPTION_XTS_AES_128", + "name": "SOC_FLASH_ENCRYPTION_XTS_AES_128", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_MEMPROT_CPU_PREFETCH_PAD_SIZE", + "name": "SOC_MEMPROT_CPU_PREFETCH_PAD_SIZE", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_MEMPROT_MEM_ALIGN_SIZE", + "name": "SOC_MEMPROT_MEM_ALIGN_SIZE", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_UART_NUM", + "name": "SOC_UART_NUM", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_UART_HP_NUM", + "name": "SOC_UART_HP_NUM", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_UART_FIFO_LEN", + "name": "SOC_UART_FIFO_LEN", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_UART_BITRATE_MAX", + "name": "SOC_UART_BITRATE_MAX", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_UART_SUPPORT_APB_CLK", + "name": "SOC_UART_SUPPORT_APB_CLK", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_UART_SUPPORT_RTC_CLK", + "name": "SOC_UART_SUPPORT_RTC_CLK", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_UART_SUPPORT_XTAL_CLK", + "name": "SOC_UART_SUPPORT_XTAL_CLK", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_UART_SUPPORT_WAKEUP_INT", + "name": "SOC_UART_SUPPORT_WAKEUP_INT", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_UART_SUPPORT_FSM_TX_WAIT_SEND", + "name": "SOC_UART_SUPPORT_FSM_TX_WAIT_SEND", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_COEX_HW_PTI", + "name": "SOC_COEX_HW_PTI", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_EXTERNAL_COEX_ADVANCE", + "name": "SOC_EXTERNAL_COEX_ADVANCE", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_EXTERNAL_COEX_LEADER_TX_LINE", + "name": "SOC_EXTERNAL_COEX_LEADER_TX_LINE", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_PHY_DIG_REGS_MEM_SIZE", + "name": "SOC_PHY_DIG_REGS_MEM_SIZE", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_MAC_BB_PD_MEM_SIZE", + "name": "SOC_MAC_BB_PD_MEM_SIZE", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_WIFI_LIGHT_SLEEP_CLK_WIDTH", + "name": "SOC_WIFI_LIGHT_SLEEP_CLK_WIDTH", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_PM_SUPPORT_WIFI_WAKEUP", + "name": "SOC_PM_SUPPORT_WIFI_WAKEUP", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_PM_SUPPORT_BT_WAKEUP", + "name": "SOC_PM_SUPPORT_BT_WAKEUP", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_PM_SUPPORT_CPU_PD", + "name": "SOC_PM_SUPPORT_CPU_PD", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_PM_SUPPORT_WIFI_PD", + "name": "SOC_PM_SUPPORT_WIFI_PD", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_PM_SUPPORT_BT_PD", + "name": "SOC_PM_SUPPORT_BT_PD", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_PM_SUPPORT_RC_FAST_PD", + "name": "SOC_PM_SUPPORT_RC_FAST_PD", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_PM_SUPPORT_VDDSDIO_PD", + "name": "SOC_PM_SUPPORT_VDDSDIO_PD", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_PM_SUPPORT_MAC_BB_PD", + "name": "SOC_PM_SUPPORT_MAC_BB_PD", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_PM_CPU_RETENTION_BY_RTCCNTL", + "name": "SOC_PM_CPU_RETENTION_BY_RTCCNTL", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_PM_MODEM_RETENTION_BY_BACKUPDMA", + "name": "SOC_PM_MODEM_RETENTION_BY_BACKUPDMA", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_PM_MODEM_PD_BY_SW", + "name": "SOC_PM_MODEM_PD_BY_SW", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_CLK_RC_FAST_D256_SUPPORTED", + "name": "SOC_CLK_RC_FAST_D256_SUPPORTED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_RTC_SLOW_CLK_SUPPORT_RC_FAST_D256", + "name": "SOC_RTC_SLOW_CLK_SUPPORT_RC_FAST_D256", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_CLK_RC_FAST_SUPPORT_CALIBRATION", + "name": "SOC_CLK_RC_FAST_SUPPORT_CALIBRATION", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_CLK_XTAL32K_SUPPORTED", + "name": "SOC_CLK_XTAL32K_SUPPORTED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_TEMPERATURE_SENSOR_SUPPORT_FAST_RC", + "name": "SOC_TEMPERATURE_SENSOR_SUPPORT_FAST_RC", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_TEMPERATURE_SENSOR_SUPPORT_XTAL", + "name": "SOC_TEMPERATURE_SENSOR_SUPPORT_XTAL", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_WIFI_HW_TSF", + "name": "SOC_WIFI_HW_TSF", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_WIFI_FTM_SUPPORT", + "name": "SOC_WIFI_FTM_SUPPORT", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_WIFI_GCMP_SUPPORT", + "name": "SOC_WIFI_GCMP_SUPPORT", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_WIFI_WAPI_SUPPORT", + "name": "SOC_WIFI_WAPI_SUPPORT", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_WIFI_CSI_SUPPORT", + "name": "SOC_WIFI_CSI_SUPPORT", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_WIFI_MESH_SUPPORT", + "name": "SOC_WIFI_MESH_SUPPORT", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_WIFI_SUPPORT_VARIABLE_BEACON_WINDOW", + "name": "SOC_WIFI_SUPPORT_VARIABLE_BEACON_WINDOW", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_WIFI_PHY_NEEDS_USB_WORKAROUND", + "name": "SOC_WIFI_PHY_NEEDS_USB_WORKAROUND", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_BLE_SUPPORTED", + "name": "SOC_BLE_SUPPORTED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_BLE_MESH_SUPPORTED", + "name": "SOC_BLE_MESH_SUPPORTED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_BLE_50_SUPPORTED", + "name": "SOC_BLE_50_SUPPORTED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_BLE_DEVICE_PRIVACY_SUPPORTED", + "name": "SOC_BLE_DEVICE_PRIVACY_SUPPORTED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_BLUFI_SUPPORTED", + "name": "SOC_BLUFI_SUPPORTED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SOC_PHY_COMBO_MODULE", + "name": "SOC_PHY_COMBO_MODULE", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "IDF_CMAKE", + "name": "IDF_CMAKE", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "- This option is for internal use only.\n- Enabling this option will help enable all FPGA support so as to\n run ESP-IDF on an FPGA. This can help reproduce some issues that\n only happens on FPGA condition, or when you have to burn some\n efuses multiple times.", + "id": "IDF_ENV_FPGA", + "name": "IDF_ENV_FPGA", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "- This option is ONLY used when doing new chip bringup.\n- This option will only enable necessary hw / sw settings for running\n a hello_world application.", + "id": "IDF_ENV_BRINGUP", + "name": "IDF_ENV_BRINGUP", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "IDF_CI_BUILD", + "name": "IDF_CI_BUILD", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "IDF_DOC_BUILD", + "name": "IDF_DOC_BUILD", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "IDF_TOOLCHAIN", + "name": "IDF_TOOLCHAIN", + "range": null, + "title": null, + "type": "string" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "IDF_TOOLCHAIN_CLANG", + "name": "IDF_TOOLCHAIN_CLANG", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "IDF_TOOLCHAIN_GCC", + "name": "IDF_TOOLCHAIN_GCC", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "IDF_TARGET_ARCH_RISCV", + "name": "IDF_TARGET_ARCH_RISCV", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "IDF_TARGET_ARCH_XTENSA", + "name": "IDF_TARGET_ARCH_XTENSA", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "IDF_TARGET_ARCH", + "name": "IDF_TARGET_ARCH", + "range": null, + "title": null, + "type": "string" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "IDF_TARGET", + "name": "IDF_TARGET", + "range": null, + "title": null, + "type": "string" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "IDF_INIT_VERSION", + "name": "IDF_INIT_VERSION", + "range": null, + "title": null, + "type": "string" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "IDF_TARGET_ESP32", + "name": "IDF_TARGET_ESP32", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "IDF_TARGET_ESP32S2", + "name": "IDF_TARGET_ESP32S2", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "IDF_TARGET_ESP32S3", + "name": "IDF_TARGET_ESP32S3", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "IDF_TARGET_ESP32C3", + "name": "IDF_TARGET_ESP32C3", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "IDF_TARGET_ESP32C2", + "name": "IDF_TARGET_ESP32C2", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "IDF_TARGET_ESP32C6", + "name": "IDF_TARGET_ESP32C6", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "IDF_TARGET_ESP32C5", + "name": "IDF_TARGET_ESP32C5", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "IDF_TARGET_ESP32P4", + "name": "IDF_TARGET_ESP32P4", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "IDF_TARGET_ESP32H2", + "name": "IDF_TARGET_ESP32H2", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "IDF_TARGET_ESP32C61", + "name": "IDF_TARGET_ESP32C61", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "IDF_TARGET_LINUX", + "name": "IDF_TARGET_LINUX", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "IDF_FIRMWARE_CHIP_ID", + "name": "IDF_FIRMWARE_CHIP_ID", + "range": null, + "title": null, + "type": "hex" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "!IDF_TARGET_LINUX && ", + "help": null, + "id": "APP_BUILD_TYPE_APP_2NDBOOT", + "name": "APP_BUILD_TYPE_APP_2NDBOOT", + "range": null, + "title": "Default (binary application + 2nd stage bootloader)", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "APP_BUILD_TYPE_RAM", + "name": "APP_BUILD_TYPE_RAM", + "range": null, + "title": "Build app runs entirely in RAM (EXPERIMENTAL)", + "type": "bool" + } + ], + "depends_on": null, + "help": "Select the way the application is built.\n\nBy default, the application is built as a binary file in a format compatible with\nthe ESP-IDF bootloader. In addition to this application, 2nd stage bootloader is\nalso built. Application and bootloader binaries can be written into flash and\nloaded/executed from there.\n\nAnother option, useful for only very small and limited applications, is to only link\nthe .elf file of the application, such that it can be loaded directly into RAM over\nJTAG or UART. Note that since IRAM and DRAM sizes are very limited, it is not possible\nto build any complex application this way. However for some kinds of testing and debugging,\nthis option may provide faster iterations, since the application does not need to be\nwritten into flash.\n\nNote: when APP_BUILD_TYPE_RAM is selected and loaded with JTAG, ESP-IDF does not contain\nall the startup code required to initialize the CPUs and ROM memory (data/bss).\nTherefore it is necessary to execute a bit of ROM code prior to executing the application.\nA gdbinit file may look as follows (for ESP32):\n\n # Connect to a running instance of OpenOCD\n target remote :3333\n # Reset and halt the target\n mon reset halt\n # Run to a specific point in ROM code,\n # where most of initialization is complete.\n thb *0x40007d54\n c\n # Load the application into RAM\n load\n # Run till app_main\n tb app_main\n c\n\nExecute this gdbinit file as follows:\n\n xtensa-esp32-elf-gdb build/app-name.elf -x gdbinit\n\nExample gdbinit files for other targets can be found in tools/test_apps/system/gdb_loadable_elf/\n\nWhen loading the BIN with UART, the ROM will jump to ram and run the app after finishing the ROM\nstartup code, so there's no additional startup initialization required. You can use the\n`load_ram` in esptool.py to load the generated .bin file into ram and execute.\n\nExample:\n esptool.py --chip {chip} -p {port} -b {baud} --no-stub load_ram {app.bin}\n\nRecommended sdkconfig.defaults for building loadable ELF files is as follows.\nCONFIG_APP_BUILD_TYPE_RAM is required, other options help reduce application\nmemory footprint.\n\n CONFIG_APP_BUILD_TYPE_RAM=y\n CONFIG_VFS_SUPPORT_TERMIOS=\n CONFIG_NEWLIB_NANO_FORMAT=y\n CONFIG_ESP_SYSTEM_PANIC_PRINT_HALT=y\n CONFIG_ESP_DEBUG_STUBS_ENABLE=\n CONFIG_ESP_ERR_TO_NAME_LOOKUP=", + "id": "build-type-application-build-type", + "name": "APP_BUILD_TYPE", + "title": "Application build type", + "type": "choice" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "APP_BUILD_GENERATE_BINARIES", + "name": "APP_BUILD_GENERATE_BINARIES", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "APP_BUILD_BOOTLOADER", + "name": "APP_BUILD_BOOTLOADER", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": "APP_BUILD_TYPE_RAM", + "help": "If this option is enabled, external memory and related peripherals, such as Cache, MMU,\nFlash and PSRAM, won't be initialized. Corresponding drivers won't be introduced either.\nComponents that depend on the spi_flash component will also be unavailable, such as\napp_update, etc. When this option is enabled, about 26KB of RAM space can be saved.", + "id": "APP_BUILD_TYPE_PURE_RAM_APP", + "name": "APP_BUILD_TYPE_PURE_RAM_APP", + "range": null, + "title": "Build app without SPI_FLASH/PSRAM support (saves ram)", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "APP_BUILD_USE_FLASH_SECTIONS", + "name": "APP_BUILD_USE_FLASH_SECTIONS", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "If enabled, all date, time, and path information would be eliminated. A .gdbinit file would be create\nautomatically. (or will be append if you have one already)", + "id": "APP_REPRODUCIBLE_BUILD", + "name": "APP_REPRODUCIBLE_BUILD", + "range": null, + "title": "Enable reproducible build", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "If enabled, this disables the linking of binary libraries in the application build. Note\nthat after enabling this Wi-Fi/Bluetooth will not work.", + "id": "APP_NO_BLOBS", + "name": "APP_NO_BLOBS", + "range": null, + "title": "No Binary Blobs", + "type": "bool" + }, + { + "children": [], + "depends_on": "IDF_TARGET_ESP32", + "help": "Bootloaders before ESP-IDF v2.1 did less initialisation of the\nsystem clock. This setting needs to be enabled to build an app\nwhich can be booted by these older bootloaders.\n\nIf this setting is enabled, the app can be booted by any bootloader\nfrom IDF v1.0 up to the current version.\n\nIf this setting is disabled, the app can only be booted by bootloaders\nfrom IDF v2.1 or newer.\n\nEnabling this setting adds approximately 1KB to the app's IRAM usage.", + "id": "APP_COMPATIBLE_PRE_V2_1_BOOTLOADERS", + "name": "APP_COMPATIBLE_PRE_V2_1_BOOTLOADERS", + "range": null, + "title": "App compatible with bootloaders before ESP-IDF v2.1", + "type": "bool" + }, + { + "children": [], + "depends_on": "IDF_TARGET_ESP32", + "help": "Partition tables before ESP-IDF V3.1 do not contain an MD5 checksum\nfield, and the bootloader before ESP-IDF v3.1 cannot read a partition\ntable that contains an MD5 checksum field.\n\nEnable this option only if your app needs to boot on a bootloader and/or\npartition table that was generated from a version *before* ESP-IDF v3.1.\n\nIf this option and Flash Encryption are enabled at the same time, and any\ndata partitions in the partition table are marked Encrypted, then the\npartition encrypted flag should be manually verified in the app before accessing\nthe partition (see CVE-2021-27926).", + "id": "APP_COMPATIBLE_PRE_V3_1_BOOTLOADERS", + "name": "APP_COMPATIBLE_PRE_V3_1_BOOTLOADERS", + "range": null, + "title": "App compatible with bootloader and partition table before ESP-IDF v3.1", + "type": "bool" + }, + { + "children": [], + "depends_on": "IDF_TARGET_ESP32", + "help": null, + "id": "APP_INIT_CLK", + "name": "APP_INIT_CLK", + "range": null, + "title": null, + "type": "bool" + } + ], + "depends_on": null, + "id": "build-type", + "title": "Build type", + "type": "menu" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "!APP_REPRODUCIBLE_BUILD", + "help": "If set, then the bootloader will be built with the current time/date stamp.\nIt is stored in the bootloader description\nstructure. If not set, time/date stamp will be excluded from bootloader image.\nThis can be useful for getting the\nsame binary image files made from the same source, but at different times.", + "id": "BOOTLOADER_COMPILE_TIME_DATE", + "name": "BOOTLOADER_COMPILE_TIME_DATE", + "range": null, + "title": "Use time/date stamp for bootloader", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Project version. It is placed in \"version\" field of the esp_bootloader_desc structure.\nThe type of this field is \"uint32_t\".", + "id": "BOOTLOADER_PROJECT_VER", + "name": "BOOTLOADER_PROJECT_VER", + "range": [ + 0, + 4294967295 + ], + "title": "Project version", + "type": "int" + } + ], + "depends_on": null, + "id": "bootloader-config-bootloader-manager", + "title": "Bootloader manager", + "type": "menu" + }, + { + "children": [], + "depends_on": null, + "help": "Offset address that 2nd bootloader will be flashed to.\nThe value is determined by the ROM bootloader.\nIt's not configurable in ESP-IDF.", + "id": "BOOTLOADER_OFFSET_IN_FLASH", + "name": "BOOTLOADER_OFFSET_IN_FLASH", + "range": null, + "title": null, + "type": "hex" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "BOOTLOADER_COMPILER_OPTIMIZATION_SIZE", + "name": "BOOTLOADER_COMPILER_OPTIMIZATION_SIZE", + "range": null, + "title": "Size (-Os with GCC, -Oz with Clang)", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BOOTLOADER_COMPILER_OPTIMIZATION_DEBUG", + "name": "BOOTLOADER_COMPILER_OPTIMIZATION_DEBUG", + "range": null, + "title": "Debug (-Og)", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BOOTLOADER_COMPILER_OPTIMIZATION_PERF", + "name": "BOOTLOADER_COMPILER_OPTIMIZATION_PERF", + "range": null, + "title": "Optimize for performance (-O2)", + "type": "bool" + }, + { + "children": [], + "depends_on": "(IDF_TARGET_ARCH_XTENSA || IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32C2) && ", + "help": null, + "id": "BOOTLOADER_COMPILER_OPTIMIZATION_NONE", + "name": "BOOTLOADER_COMPILER_OPTIMIZATION_NONE", + "range": null, + "title": "Debug without optimization (-O0) (Deprecated, will be removed in IDF v6.0)", + "type": "bool" + } + ], + "depends_on": null, + "help": "This option sets compiler optimization level (gcc -O argument)\nfor the bootloader.\n\n- The default \"Size\" setting will add the -Os (-Oz with clang) flag to CFLAGS.\n- The \"Debug\" setting will add the -Og flag to CFLAGS.\n- The \"Performance\" setting will add the -O2 flag to CFLAGS.\n\nNote that custom optimization levels may be unsupported.", + "id": "bootloader-config-bootloader-optimization-level", + "name": "BOOTLOADER_COMPILER_OPTIMIZATION", + "title": "Bootloader optimization Level", + "type": "choice" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "BOOTLOADER_LOG_LEVEL_NONE", + "name": "BOOTLOADER_LOG_LEVEL_NONE", + "range": null, + "title": "No output", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BOOTLOADER_LOG_LEVEL_ERROR", + "name": "BOOTLOADER_LOG_LEVEL_ERROR", + "range": null, + "title": "Error", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BOOTLOADER_LOG_LEVEL_WARN", + "name": "BOOTLOADER_LOG_LEVEL_WARN", + "range": null, + "title": "Warning", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BOOTLOADER_LOG_LEVEL_INFO", + "name": "BOOTLOADER_LOG_LEVEL_INFO", + "range": null, + "title": "Info", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BOOTLOADER_LOG_LEVEL_DEBUG", + "name": "BOOTLOADER_LOG_LEVEL_DEBUG", + "range": null, + "title": "Debug", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BOOTLOADER_LOG_LEVEL_VERBOSE", + "name": "BOOTLOADER_LOG_LEVEL_VERBOSE", + "range": null, + "title": "Verbose", + "type": "bool" + } + ], + "depends_on": null, + "help": "Specify how much output to see in bootloader logs.", + "id": "bootloader-config-log-bootloader-log-verbosity", + "name": "BOOTLOADER_LOG_LEVEL", + "title": "Bootloader log verbosity", + "type": "choice" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "BOOTLOADER_LOG_LEVEL", + "name": "BOOTLOADER_LOG_LEVEL", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": null, + "help": "Use ANSI terminal colors in log output\nEnable ANSI terminal color codes.\nIn order to view these, your terminal program must support ANSI color codes.", + "id": "BOOTLOADER_LOG_COLORS", + "name": "BOOTLOADER_LOG_COLORS", + "range": null, + "title": "Color", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "NO_SYMBOL && ", + "help": null, + "id": "BOOTLOADER_LOG_TIMESTAMP_SOURCE_NONE", + "name": "BOOTLOADER_LOG_TIMESTAMP_SOURCE_NONE", + "range": null, + "title": "None", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BOOTLOADER_LOG_TIMESTAMP_SOURCE_CPU_TICKS", + "name": "BOOTLOADER_LOG_TIMESTAMP_SOURCE_CPU_TICKS", + "range": null, + "title": "Milliseconds Since Boot", + "type": "bool" + } + ], + "depends_on": null, + "help": "Choose what sort of timestamp is displayed in the log output:\n\n- \"None\" - The log will only contain the actual log messages themselves\n without any time-related information. Avoiding timestamps can help conserve\n processing power and memory. It might useful when you\n perform log analysis or debugging, sometimes it's more straightforward\n to work with logs that lack timestamps, especially if the time of occurrence\n is not critical for understanding the issues.\n \"I log_test: info message\"\n\n- \"Milliseconds since boot\" is calculated from the RTOS tick count multiplied\n by the tick period. This time will reset after a software reboot.\n \"I (112500) log_test: info message\"", + "id": "bootloader-config-log-format-timestamp", + "name": "BOOTLOADER_LOG_TIMESTAMP_SOURCE", + "title": "Timestamp", + "type": "choice" + } + ], + "depends_on": null, + "id": "bootloader-config-log-format", + "title": "Format", + "type": "menu" + } + ], + "depends_on": null, + "id": "bootloader-config-log", + "title": "Log", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": "IDF_TARGET_ESP32 && (ESPTOOLPY_FLASHMODE_QIO || ESPTOOLPY_FLASHMODE_QOUT)", + "help": "This setting is only used if the SPI flash pins have been overridden by setting the eFuses\nSPI_PAD_CONFIG_xxx, and the SPI flash mode is QIO or QOUT.\n\nWhen this is the case, the eFuse config only defines 3 of the 4 Quad I/O data pins. The WP pin (aka\nESP32 pin \"SD_DATA_3\" or SPI flash pin \"IO2\") is not specified in eFuse. The same pin is also used\nfor external SPIRAM if it is enabled.\n\nIf this config item is set to N (default), the correct WP pin will be automatically used for any\nEspressif chip or module with integrated flash. If a custom setting is needed, set this config item to\nY and specify the GPIO number connected to the WP.", + "id": "BOOTLOADER_SPI_CUSTOM_WP_PIN", + "name": "BOOTLOADER_SPI_CUSTOM_WP_PIN", + "range": null, + "title": "Use custom SPI Flash WP Pin when flash pins set in eFuse (read help)", + "type": "bool" + }, + { + "children": [], + "depends_on": "IDF_TARGET_ESP32 && (ESPTOOLPY_FLASHMODE_QIO || ESPTOOLPY_FLASHMODE_QOUT)", + "help": "The option \"Use custom SPI Flash WP Pin\" must be set or this value is ignored\n\nIf burning a customized set of SPI flash pins in eFuse and using QIO or QOUT mode for flash, set this\nvalue to the GPIO number of the SPI flash WP pin.", + "id": "BOOTLOADER_SPI_WP_PIN", + "name": "BOOTLOADER_SPI_WP_PIN", + "range": null, + "title": "Custom SPI Flash WP Pin", + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": "This will force 2nd bootloader to be loaded by DOUT mode, and will restore Dummy Cycle setting by\nresetting the Flash", + "id": "BOOTLOADER_FLASH_DC_AWARE", + "name": "BOOTLOADER_FLASH_DC_AWARE", + "range": null, + "title": "Allow app adjust Dummy Cycle bits in SPI Flash for higher frequency (READ HELP FIRST)", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Perform the startup flow recommended by XMC. Please consult XMC for the details of this flow.\nXMC chips will be forbidden to be used, when this option is disabled.\n\nDON'T DISABLE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n\ncomment \"Features below require specific hardware (READ DOCS FIRST!)\"", + "id": "BOOTLOADER_FLASH_XMC_SUPPORT", + "name": "BOOTLOADER_FLASH_XMC_SUPPORT", + "range": null, + "title": "Enable the support for flash chips of XMC (READ DOCS FIRST)", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "This is a helper config for 32bits address flash. Invisible for users.", + "id": "BOOTLOADER_FLASH_32BIT_ADDR", + "name": "BOOTLOADER_FLASH_32BIT_ADDR", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "This is a helper config for 32bits address flash. Invisible for users.", + "id": "BOOTLOADER_FLASH_NEEDS_32BIT_FEAT", + "name": "BOOTLOADER_FLASH_NEEDS_32BIT_FEAT", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "This is a helper config for 32bits address quad flash. Invisible for users.", + "id": "BOOTLOADER_FLASH_NEEDS_32BIT_ADDR_QUAD_FLASH", + "name": "BOOTLOADER_FLASH_NEEDS_32BIT_ADDR_QUAD_FLASH", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": "BOOTLOADER_FLASH_NEEDS_32BIT_ADDR_QUAD_FLASH && IDF_EXPERIMENTAL_FEATURES", + "help": "Enabling this option allows the CPU to access 32-bit-address flash beyond 16M range.\n1. This option only valid for 4-line flash. Octal flash doesn't need this.\n2. This option is experimental, which means it can\u2019t use on all flash chips stable, for more\ninformation, please contact Espressif Business support.", + "id": "BOOTLOADER_CACHE_32BIT_ADDR_QUAD_FLASH", + "name": "BOOTLOADER_CACHE_32BIT_ADDR_QUAD_FLASH", + "range": null, + "title": "Enable cache access to 32-bit-address (over 16MB) range of SPI Flash (READ DOCS FIRST)", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "BOOTLOADER_CACHE_32BIT_ADDR_OCTAL_FLASH", + "name": "BOOTLOADER_CACHE_32BIT_ADDR_OCTAL_FLASH", + "range": null, + "title": null, + "type": "bool" + } + ], + "depends_on": null, + "id": "bootloader-config-serial-flash-configurations", + "title": "Serial Flash Configurations", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": "!ESPTOOLPY_FLASHFREQ_80M && ", + "help": null, + "id": "BOOTLOADER_VDDSDIO_BOOST_1_8V", + "name": "BOOTLOADER_VDDSDIO_BOOST_1_8V", + "range": null, + "title": "1.8V", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BOOTLOADER_VDDSDIO_BOOST_1_9V", + "name": "BOOTLOADER_VDDSDIO_BOOST_1_9V", + "range": null, + "title": "1.9V", + "type": "bool" + } + ], + "depends_on": "SOC_CONFIGURABLE_VDDSDIO_SUPPORTED", + "help": "If this option is enabled, and VDDSDIO LDO is set to 1.8V (using eFuse\nor MTDI bootstrapping pin), bootloader will change LDO settings to\noutput 1.9V instead. This helps prevent flash chip from browning out\nduring flash programming operations.\n\nThis option has no effect if VDDSDIO is set to 3.3V, or if the internal\nVDDSDIO regulator is disabled via eFuse.", + "id": "bootloader-config-vddsdio-ldo-voltage", + "name": "BOOTLOADER_VDDSDIO_BOOST", + "title": "VDDSDIO LDO voltage", + "type": "choice" + }, + { + "children": [ + { + "children": [], + "depends_on": "BOOTLOADER_FACTORY_RESET", + "help": "The selected GPIO will be configured as an input with internal pull-up enabled. To trigger a factory\nreset, this GPIO must be held high or low (as configured) on startup.\n\nNote that on some SoCs not all pins have an internal pull-up and certain pins are already\nused by ROM bootloader as bootstrapping. Refer to the technical reference manual for further\ndetails on the selected SoC.", + "id": "BOOTLOADER_NUM_PIN_FACTORY_RESET", + "name": "BOOTLOADER_NUM_PIN_FACTORY_RESET", + "range": null, + "title": "Number of the GPIO input for factory reset", + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "BOOTLOADER_FACTORY_RESET_PIN_LOW", + "name": "BOOTLOADER_FACTORY_RESET_PIN_LOW", + "range": null, + "title": "Reset on GPIO low", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BOOTLOADER_FACTORY_RESET_PIN_HIGH", + "name": "BOOTLOADER_FACTORY_RESET_PIN_HIGH", + "range": null, + "title": "Reset on GPIO high", + "type": "bool" + } + ], + "depends_on": "BOOTLOADER_FACTORY_RESET", + "help": "Pin level for factory reset, can be triggered on low or high.", + "id": "bootloader-config-gpio-triggers-factory-reset-factory-reset-gpio-level", + "name": "BOOTLOADER_FACTORY_RESET_PIN_LEVEL", + "title": "Factory reset GPIO level", + "type": "choice" + }, + { + "children": [], + "depends_on": "BOOTLOADER_FACTORY_RESET", + "help": "The device will boot from \"factory\" partition (or OTA slot 0 if no factory partition is present) after a\nfactory reset.", + "id": "BOOTLOADER_OTA_DATA_ERASE", + "name": "BOOTLOADER_OTA_DATA_ERASE", + "range": null, + "title": "Clear OTA data on factory reset (select factory partition)", + "type": "bool" + }, + { + "children": [], + "depends_on": "BOOTLOADER_FACTORY_RESET", + "help": "Allows customers to select which data partitions will be erased while factory reset.\n\nSpecify the names of partitions as a comma-delimited with optional spaces for readability. (Like this:\n\"nvs, phy_init, ...\")\nMake sure that the name specified in the partition table and here are the same.\nPartitions of type \"app\" cannot be specified here.", + "id": "BOOTLOADER_DATA_FACTORY_RESET", + "name": "BOOTLOADER_DATA_FACTORY_RESET", + "range": null, + "title": "Comma-separated names of partitions to clear on factory reset", + "type": "string" + } + ], + "depends_on": null, + "help": "Allows to reset the device to factory settings:\n- clear one or more data partitions;\n- boot from \"factory\" partition.\nThe factory reset will occur if there is a GPIO input held at the configured level while\ndevice starts up. See settings below.", + "id": "BOOTLOADER_FACTORY_RESET", + "name": "BOOTLOADER_FACTORY_RESET", + "range": null, + "title": "GPIO triggers factory reset", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "BOOTLOADER_APP_TEST", + "help": "The selected GPIO will be configured as an input with internal pull-up enabled.\nTo trigger a test app, this GPIO must be pulled low on reset.\nAfter the GPIO input is deactivated and the device reboots, the old application will boot.\n(factory or OTA[x]).\n\nNote that on some SoCs not all pins have an internal pull-up and certain pins are already\nused by ROM bootloader as bootstrapping. Refer to the technical reference manual for further\ndetails on the selected SoC.", + "id": "BOOTLOADER_NUM_PIN_APP_TEST", + "name": "BOOTLOADER_NUM_PIN_APP_TEST", + "range": null, + "title": "Number of the GPIO input to boot TEST partition", + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "BOOTLOADER_APP_TEST_PIN_LOW", + "name": "BOOTLOADER_APP_TEST_PIN_LOW", + "range": null, + "title": "Enter test app on GPIO low", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BOOTLOADER_APP_TEST_PIN_HIGH", + "name": "BOOTLOADER_APP_TEST_PIN_HIGH", + "range": null, + "title": "Enter test app on GPIO high", + "type": "bool" + } + ], + "depends_on": "BOOTLOADER_APP_TEST", + "help": "Pin level for app test, can be triggered on low or high.", + "id": "bootloader-config-gpio-triggers-boot-from-test-app-partition-app-test-gpio-level", + "name": "BOOTLOADER_APP_TEST_PIN_LEVEL", + "title": "App test GPIO level", + "type": "choice" + } + ], + "depends_on": "!BOOTLOADER_APP_ANTI_ROLLBACK", + "help": "Allows to run the test app from \"TEST\" partition.\nA boot from \"test\" partition will occur if there is a GPIO input pulled low while device starts up.\nSee settings below.", + "id": "BOOTLOADER_APP_TEST", + "name": "BOOTLOADER_APP_TEST", + "range": null, + "title": "GPIO triggers boot from test app partition", + "type": "bool" + }, + { + "children": [], + "depends_on": "BOOTLOADER_FACTORY_RESET || BOOTLOADER_APP_TEST", + "help": "The GPIO must be held low continuously for this period of time after reset\nbefore a factory reset or test partition boot (as applicable) is performed.", + "id": "BOOTLOADER_HOLD_TIME_GPIO", + "name": "BOOTLOADER_HOLD_TIME_GPIO", + "range": null, + "title": "Hold time of GPIO for reset/test mode (seconds)", + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": "Protects the unmapped memory regions of the entire address space from unintended accesses.\nThis will ensure that an exception will be triggered whenever the CPU performs a memory\noperation on unmapped regions of the address space.\nNOTE: Disabling this config on some targets (ESP32-C6, ESP32-H2, ESP32-C5) would not generate\nan exception when reading from or writing to 0x0.", + "id": "BOOTLOADER_REGION_PROTECTION_ENABLE", + "name": "BOOTLOADER_REGION_PROTECTION_ENABLE", + "range": null, + "title": "Enable protection for unmapped memory regions", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "BOOTLOADER_WDT_ENABLE", + "help": "If this option is set, the ESP-IDF app must explicitly reset, feed, or disable the rtc_wdt in\nthe app's own code.\nIf this option is not set (default), then rtc_wdt will be disabled by ESP-IDF before calling\nthe app_main() function.\n\nUse function wdt_hal_feed() for resetting counter of RTC_WDT.\nFor esp32/s2 you can also use rtc_wdt_feed().\n\nUse function wdt_hal_disable() for disabling RTC_WDT.\nFor esp32/s2 you can also use rtc_wdt_disable().", + "id": "BOOTLOADER_WDT_DISABLE_IN_USER_CODE", + "name": "BOOTLOADER_WDT_DISABLE_IN_USER_CODE", + "range": null, + "title": "Allows RTC watchdog disable in user code", + "type": "bool" + }, + { + "children": [], + "depends_on": "BOOTLOADER_WDT_ENABLE", + "help": "Verify that this parameter is correct and more then the execution time.\nPay attention to options such as reset to factory, trigger test partition and encryption on boot\n- these options can increase the execution time.\nNote: RTC_WDT will reset while encryption operations will be performed.", + "id": "BOOTLOADER_WDT_TIME_MS", + "name": "BOOTLOADER_WDT_TIME_MS", + "range": [ + 0, + 120000 + ], + "title": "Timeout for RTC watchdog (ms)", + "type": "int" + } + ], + "depends_on": null, + "help": "Tracks the execution time of startup code.\nIf the execution time is exceeded, the RTC_WDT will restart system.\nIt is also useful to prevent a lock up in start code caused by an unstable power source.\nNOTE: Tracks the execution time starts from the bootloader code - re-set timeout, while selecting the\nsource for slow_clk - and ends calling app_main.\nRe-set timeout is needed due to WDT uses a SLOW_CLK clock source. After changing a frequency slow_clk a\ntime of WDT needs to re-set for new frequency.\nslow_clk depends on RTC_CLK_SRC (INTERNAL_RC or EXTERNAL_CRYSTAL).", + "id": "BOOTLOADER_WDT_ENABLE", + "name": "BOOTLOADER_WDT_ENABLE", + "range": null, + "title": "Use RTC watchdog in start code", + "type": "bool" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "BOOTLOADER_APP_ANTI_ROLLBACK", + "help": "The secure version is the sequence number stored in the header of each firmware.\nThe security version is set in the bootloader, version is recorded in the eFuse field\nas the number of set ones. The allocated number of bits in the efuse field\nfor storing the security version is limited (see BOOTLOADER_APP_SEC_VER_SIZE_EFUSE_FIELD option).\n\nBootloader: When bootloader selects an app to boot, an app is selected that has\na security version greater or equal that recorded in eFuse field.\nThe app is booted with a higher (or equal) secure version.\n\nThe security version is worth increasing if in previous versions there is\na significant vulnerability and their use is not acceptable.\n\nYour partition table should has a scheme with ota_0 + ota_1 (without factory).", + "id": "BOOTLOADER_APP_SECURE_VERSION", + "name": "BOOTLOADER_APP_SECURE_VERSION", + "range": null, + "title": "eFuse secure version of app", + "type": "int" + }, + { + "children": [], + "depends_on": "BOOTLOADER_APP_ANTI_ROLLBACK", + "help": "The size of the efuse secure version field.\nIts length is limited to 32 bits for ESP32 and 16 bits for ESP32-S2.\nThis determines how many times the security version can be increased.", + "id": "BOOTLOADER_APP_SEC_VER_SIZE_EFUSE_FIELD", + "name": "BOOTLOADER_APP_SEC_VER_SIZE_EFUSE_FIELD", + "range": null, + "title": "Size of the efuse secure version field", + "type": "int" + }, + { + "children": [], + "depends_on": "BOOTLOADER_APP_ANTI_ROLLBACK", + "help": "This option allows to emulate read/write operations with all eFuses and efuse secure version.\nIt allows to test anti-rollback implementation without permanent write eFuse bits.\nThere should be an entry in partition table with following details: `emul_efuse, data, efuse, , 0x2000`.\n\nThis option enables: EFUSE_VIRTUAL and EFUSE_VIRTUAL_KEEP_IN_FLASH.", + "id": "BOOTLOADER_EFUSE_SECURE_VERSION_EMULATE", + "name": "BOOTLOADER_EFUSE_SECURE_VERSION_EMULATE", + "range": null, + "title": "Emulate operations with efuse secure version(only test)", + "type": "bool" + } + ], + "depends_on": "BOOTLOADER_APP_ROLLBACK_ENABLE", + "help": "This option prevents rollback to previous firmware/application image with lower security version.", + "id": "BOOTLOADER_APP_ANTI_ROLLBACK", + "name": "BOOTLOADER_APP_ANTI_ROLLBACK", + "range": null, + "title": "Enable app anti-rollback support", + "type": "bool" + } + ], + "depends_on": null, + "help": "After updating the app, the bootloader runs a new app with the \"ESP_OTA_IMG_PENDING_VERIFY\" state set.\nThis state prevents the re-run of this app. After the first boot of the new app in the user code, the\nfunction should be called to confirm the operability of the app or vice versa about its non-operability.\nIf the app is working, then it is marked as valid. Otherwise, it is marked as not valid and rolls back to\nthe previous working app. A reboot is performed, and the app is booted before the software update.\nNote: If during the first boot a new app the power goes out or the WDT works, then roll back will happen.\nRollback is possible only between the apps with the same security versions.", + "id": "BOOTLOADER_APP_ROLLBACK_ENABLE", + "name": "BOOTLOADER_APP_ROLLBACK_ENABLE", + "range": null, + "title": "Enable app rollback support", + "type": "bool" + }, + { + "children": [], + "depends_on": "(SECURE_BOOT && SECURE_BOOT_INSECURE) || !SECURE_BOOT", + "help": "This option disables the normal validation of an image coming out of\ndeep sleep (checksums, SHA256, and signature). This is a trade-off\nbetween wakeup performance from deep sleep, and image integrity checks.\n\nOnly enable this if you know what you are doing. It should not be used\nin conjunction with using deep_sleep() entry and changing the active OTA\npartition as this would skip the validation upon first load of the new\nOTA partition.\n\nIt is possible to enable this option with Secure Boot if \"allow insecure\noptions\" is enabled, however it's strongly recommended to NOT enable it as\nit may allow a Secure Boot bypass.", + "id": "BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP", + "name": "BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP", + "range": null, + "title": "Skip image validation when exiting deep sleep", + "type": "bool" + }, + { + "children": [], + "depends_on": "!SECURE_SIGNED_ON_BOOT", + "help": "Some applications need to boot very quickly from power on. By default, the entire app binary\nis read from flash and verified which takes up a significant portion of the boot time.\n\nEnabling this option will skip validation of the app when the SoC boots from power on.\nNote that in this case it's not possible for the bootloader to detect if an app image is\ncorrupted in the flash, therefore it's not possible to safely fall back to a different app\npartition. Flash corruption of this kind is unlikely but can happen if there is a serious\nfirmware bug or physical damage.\n\nFollowing other reset types, the bootloader will still validate the app image. This increases\nthe chances that flash corruption resulting in a crash can be detected following soft reset, and\nthe bootloader will fall back to a valid app image. To increase the chances of successfully recovering\nfrom a flash corruption event, keep the option BOOTLOADER_WDT_ENABLE enabled and consider also enabling\nBOOTLOADER_WDT_DISABLE_IN_USER_CODE - then manually disable the RTC Watchdog once the app is running.\nIn addition, enable both the Task and Interrupt watchdog timers with reset options set.", + "id": "BOOTLOADER_SKIP_VALIDATE_ON_POWER_ON", + "name": "BOOTLOADER_SKIP_VALIDATE_ON_POWER_ON", + "range": null, + "title": "Skip image validation from power on reset (READ HELP FIRST)", + "type": "bool" + }, + { + "children": [], + "depends_on": "!SECURE_SIGNED_ON_BOOT", + "help": "Selecting this option prevents the bootloader from ever validating the app image before\nbooting it. Any flash corruption of the selected app partition will make the entire SoC\nunbootable.\n\nAlthough flash corruption is a very rare case, it is not recommended to select this option.\nConsider selecting \"Skip image validation from power on reset\" instead. However, if boot time\nis the only important factor then it can be enabled.", + "id": "BOOTLOADER_SKIP_VALIDATE_ALWAYS", + "name": "BOOTLOADER_SKIP_VALIDATE_ALWAYS", + "range": null, + "title": "Skip image validation always (READ HELP FIRST)", + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_RTC_FAST_MEM_SUPPORTED", + "help": "Reserve RTC FAST memory for Skip image validation. This option in bytes.\nThis option reserves an area in the RTC FAST memory (access only PRO_CPU).\nUsed to save the addresses of the selected application.\nWhen a wakeup occurs (from Deep sleep), the bootloader retrieves it and\nloads the application without validation.", + "id": "BOOTLOADER_RESERVE_RTC_SIZE", + "name": "BOOTLOADER_RESERVE_RTC_SIZE", + "range": null, + "title": null, + "type": "hex" + }, + { + "children": [ + { + "children": [], + "depends_on": "BOOTLOADER_CUSTOM_RESERVE_RTC", + "help": "This option allows the customer to use the legacy bootloader behavior when the\nRTC FAST memory CRC calculation takes place. When this option is enabled, the\nallocated user custom data will be taken into account in the CRC calculation.\nThis means that any change to the custom data would need a CRC update to prevent\nthe bootloader from marking this data as corrupted.\nIf this option is disabled, the custom data will not be taken into account when\ncalculating the RTC FAST memory CRC. The user custom data can be changed freely,\nwithout the need to update the CRC.\nTHIS OPTION MUST BE THE SAME FOR BOTH THE BOOTLOADER AND THE APPLICATION BUILDS.", + "id": "BOOTLOADER_CUSTOM_RESERVE_RTC_IN_CRC", + "name": "BOOTLOADER_CUSTOM_RESERVE_RTC_IN_CRC", + "range": null, + "title": "Include custom memory in the CRC calculation", + "type": "bool" + }, + { + "children": [], + "depends_on": "BOOTLOADER_CUSTOM_RESERVE_RTC", + "help": "This option reserves in RTC FAST memory the area for custom purposes.\nIf you want to create your own bootloader and save more information\nin this area of memory, you can increase it. It must be a multiple of 4 bytes.\nThis area (rtc_retain_mem_t) is reserved and has access from the bootloader and an application.", + "id": "BOOTLOADER_CUSTOM_RESERVE_RTC_SIZE", + "name": "BOOTLOADER_CUSTOM_RESERVE_RTC_SIZE", + "range": null, + "title": "Size in bytes for custom purposes", + "type": "hex" + } + ], + "depends_on": "SOC_RTC_FAST_MEM_SUPPORTED", + "help": "This option allows the customer to place data in the RTC FAST memory,\nthis area remains valid when rebooted, except for power loss.\nThis memory is located at a fixed address and is available\nfor both the bootloader and the application.\n(The application and bootloader must be compiled with the same option).\nThe RTC FAST memory has access only through PRO_CPU.", + "id": "BOOTLOADER_CUSTOM_RESERVE_RTC", + "name": "BOOTLOADER_CUSTOM_RESERVE_RTC", + "range": null, + "title": "Reserve RTC FAST memory for custom purposes", + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_RTC_FAST_MEM_SUPPORTED", + "help": "This option reserves an area in RTC FAST memory for the following features:\n- \"Skip image validation when exiting deep sleep\"\n- \"Reserve RTC FAST memory for custom purposes\"\n- \"GPIO triggers factory reset\"", + "id": "BOOTLOADER_RESERVE_RTC_MEM", + "name": "BOOTLOADER_RESERVE_RTC_MEM", + "range": null, + "title": null, + "type": "bool" + } + ], + "depends_on": null, + "id": "bootloader-config", + "title": "Bootloader config", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": "SECURE_BOOT || SECURE_SIGNED_ON_BOOT_NO_SECURE_BOOT", + "help": null, + "id": "SECURE_SIGNED_ON_BOOT", + "name": "SECURE_SIGNED_ON_BOOT", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": "SECURE_BOOT || SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT", + "help": null, + "id": "SECURE_SIGNED_ON_UPDATE", + "name": "SECURE_SIGNED_ON_UPDATE", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": "SECURE_SIGNED_ON_BOOT || SECURE_SIGNED_ON_UPDATE", + "help": null, + "id": "SECURE_SIGNED_APPS", + "name": "SECURE_SIGNED_APPS", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": "(IDF_TARGET_ESP32 && ESP32_REV_MIN_FULL >= 300) || SOC_SECURE_BOOT_V2_RSA", + "help": null, + "id": "SECURE_BOOT_V2_RSA_SUPPORTED", + "name": "SECURE_BOOT_V2_RSA_SUPPORTED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_SECURE_BOOT_V2_ECC", + "help": null, + "id": "SECURE_BOOT_V2_ECC_SUPPORTED", + "name": "SECURE_BOOT_V2_ECC_SUPPORTED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_SECURE_BOOT_V1", + "help": null, + "id": "SECURE_BOOT_V1_SUPPORTED", + "name": "SECURE_BOOT_V1_SUPPORTED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": "ESP32_REV_MIN_FULL >= 300", + "help": null, + "id": "SECURE_BOOT_V2_PREFERRED", + "name": "SECURE_BOOT_V2_PREFERRED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SECURE_BOOT_V2_ECDSA_ENABLED", + "name": "SECURE_BOOT_V2_ECDSA_ENABLED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SECURE_BOOT_V2_RSA_ENABLED", + "name": "SECURE_BOOT_V2_RSA_ENABLED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SECURE_BOOT_FLASH_ENC_KEYS_BURN_TOGETHER", + "name": "SECURE_BOOT_FLASH_ENC_KEYS_BURN_TOGETHER", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": "!SECURE_BOOT", + "help": "Require apps to be signed to verify their integrity.\n\nThis option uses the same app signature scheme as hardware secure boot, but unlike hardware secure boot it\ndoes not prevent the bootloader from being physically updated. This means that the device can be secured\nagainst remote network access, but not physical access. Compared to using hardware Secure Boot this option\nis much simpler to implement.", + "id": "SECURE_SIGNED_APPS_NO_SECURE_BOOT", + "name": "SECURE_SIGNED_APPS_NO_SECURE_BOOT", + "range": null, + "title": "Require signed app images", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "SECURE_BOOT_V1_SUPPORTED && (SECURE_SIGNED_APPS_NO_SECURE_BOOT || SECURE_BOOT_V1_ENABLED) && ", + "help": "Embeds the ECDSA public key in the bootloader and signs the application with an ECDSA key.\nRefer to the documentation before enabling.", + "id": "SECURE_SIGNED_APPS_ECDSA_SCHEME", + "name": "SECURE_SIGNED_APPS_ECDSA_SCHEME", + "range": null, + "title": "ECDSA", + "type": "bool" + }, + { + "children": [], + "depends_on": "SECURE_BOOT_V2_RSA_SUPPORTED && (SECURE_SIGNED_APPS_NO_SECURE_BOOT || SECURE_BOOT_V2_ENABLED) && ", + "help": "Appends the RSA-3072 based Signature block to the application.\nRefer to before enabling.", + "id": "SECURE_SIGNED_APPS_RSA_SCHEME", + "name": "SECURE_SIGNED_APPS_RSA_SCHEME", + "range": null, + "title": "RSA", + "type": "bool" + }, + { + "children": [], + "depends_on": "SECURE_BOOT_V2_ECC_SUPPORTED && (SECURE_SIGNED_APPS_NO_SECURE_BOOT || SECURE_BOOT_V2_ENABLED) && ", + "help": "For Secure boot V2 (e.g., ESP32-C2 SoC), appends ECDSA based signature block to the application.\nRefer to documentation before enabling.", + "id": "SECURE_SIGNED_APPS_ECDSA_V2_SCHEME", + "name": "SECURE_SIGNED_APPS_ECDSA_V2_SCHEME", + "range": null, + "title": "ECDSA (V2)", + "type": "bool" + } + ], + "depends_on": "SECURE_BOOT || SECURE_SIGNED_APPS_NO_SECURE_BOOT", + "help": "Select the Secure App signing scheme. Depends on the Chip Revision.\nThere are two secure boot versions:\n\n1. Secure boot V1\n - Legacy custom secure boot scheme. Supported in ESP32 SoC.\n\n2. Secure boot V2\n - RSA based secure boot scheme.\n Supported in ESP32-ECO3 (ESP32 Chip Revision 3 onwards), ESP32-S2, ESP32-C3, ESP32-S3 SoCs.\n\n - ECDSA based secure boot scheme. Supported in ESP32-C2 SoC.", + "id": "security-features-app-signing-scheme", + "name": "SECURE_SIGNED_APPS_SCHEME", + "title": "App Signing Scheme", + "type": "choice" + }, + { + "children": [ + { + "children": [], + "depends_on": "SECURE_SIGNED_APPS_ECDSA_V2_SCHEME && ", + "help": null, + "id": "SECURE_BOOT_ECDSA_KEY_LEN_192_BITS", + "name": "SECURE_BOOT_ECDSA_KEY_LEN_192_BITS", + "range": null, + "title": "Using ECC curve NISTP192", + "type": "bool" + }, + { + "children": [], + "depends_on": "SECURE_SIGNED_APPS_ECDSA_V2_SCHEME && ", + "help": null, + "id": "SECURE_BOOT_ECDSA_KEY_LEN_256_BITS", + "name": "SECURE_BOOT_ECDSA_KEY_LEN_256_BITS", + "range": null, + "title": "Using ECC curve NISTP256 (Recommended)", + "type": "bool" + } + ], + "depends_on": "SECURE_SIGNED_APPS_ECDSA_V2_SCHEME", + "help": "Select the ECDSA key size. Two key sizes are supported\n\n- 192 bit key using NISTP192 curve\n- 256 bit key using NISTP256 curve (Recommended)\n\nThe advantage of using 256 bit key is the extra randomness which makes it difficult to be\nbruteforced compared to 192 bit key.\nAt present, both key sizes are practically implausible to bruteforce.", + "id": "security-features-ecdsa-key-size", + "name": "SECURE_BOOT_ECDSA_KEY_LEN_SIZE", + "title": "ECDSA key size", + "type": "choice" + }, + { + "children": [], + "depends_on": "SECURE_SIGNED_APPS_NO_SECURE_BOOT && SECURE_SIGNED_APPS_ECDSA_SCHEME", + "help": "If this option is set, the bootloader will be compiled with code to verify that an app is signed before\nbooting it.\n\nIf hardware secure boot is enabled, this option is always enabled and cannot be disabled.\nIf hardware secure boot is not enabled, this option doesn't add significant security by itself so most\nusers will want to leave it disabled.", + "id": "SECURE_SIGNED_ON_BOOT_NO_SECURE_BOOT", + "name": "SECURE_SIGNED_ON_BOOT_NO_SECURE_BOOT", + "range": null, + "title": "Bootloader verifies app signatures", + "type": "bool" + }, + { + "children": [], + "depends_on": "SECURE_SIGNED_APPS_NO_SECURE_BOOT", + "help": "If this option is set, any OTA updated apps will have the signature verified before being considered valid.\n\nWhen enabled, the signature is automatically checked whenever the esp_ota_ops.h APIs are used for OTA\nupdates, or esp_image_format.h APIs are used to verify apps.\n\nIf hardware secure boot is enabled, this option is always enabled and cannot be disabled.\nIf hardware secure boot is not enabled, this option still adds significant security against network-based\nattackers by preventing spoofing of OTA updates.", + "id": "SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT", + "name": "SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT", + "range": null, + "title": "Verify app signature on update", + "type": "bool" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "SECURE_BOOT_V1_SUPPORTED && ", + "help": "Build a bootloader which enables secure boot version 1 on first boot.\nRefer to the Secure Boot section of the ESP-IDF Programmer's Guide for this version before enabling.", + "id": "SECURE_BOOT_V1_ENABLED", + "name": "SECURE_BOOT_V1_ENABLED", + "range": null, + "title": "Enable Secure Boot version 1", + "type": "bool" + }, + { + "children": [], + "depends_on": "(SECURE_BOOT_V2_RSA_SUPPORTED || SECURE_BOOT_V2_ECC_SUPPORTED) && ", + "help": "Build a bootloader which enables Secure Boot version 2 on first boot.\nRefer to Secure Boot V2 section of the ESP-IDF Programmer's Guide for this version before enabling.", + "id": "SECURE_BOOT_V2_ENABLED", + "name": "SECURE_BOOT_V2_ENABLED", + "range": null, + "title": "Enable Secure Boot version 2", + "type": "bool" + } + ], + "depends_on": "SECURE_BOOT", + "help": "Select the Secure Boot Version. Depends on the Chip Revision.\nSecure Boot V2 is the new RSA / ECDSA based secure boot scheme.\n\n - RSA based scheme is supported in ESP32 (Revision 3 onwards), ESP32-S2, ESP32-C3 (ECO3), ESP32-S3.\n - ECDSA based scheme is supported in ESP32-C2 SoC.\n\nPlease note that, RSA or ECDSA secure boot is property of specific SoC based on its HW design, supported\ncrypto accelerators, die-size, cost and similar parameters. Please note that RSA scheme has requirement\nfor bigger key sizes but at the same time it is comparatively faster than ECDSA verification.\n\nSecure Boot V1 is the AES based (custom) secure boot scheme supported in ESP32 SoC.", + "id": "security-features-enable-hardware-secure-boot-in-bootloader-read-docs-first--select-secure-boot-version", + "name": "SECURE_BOOT_VERSION", + "title": "Select secure boot version", + "type": "choice" + } + ], + "depends_on": "SOC_SECURE_BOOT_SUPPORTED && !(IDF_TARGET_ESP32C3 && ESP32C3_REV_MIN_FULL < 3)", + "help": "Build a bootloader which enables Secure Boot on first boot.\n\nOnce enabled, Secure Boot will not boot a modified bootloader. The bootloader will only load a partition\ntable or boot an app if the data has a verified digital signature. There are implications for reflashing\nupdated apps once secure boot is enabled.\n\nWhen enabling secure boot, JTAG and ROM BASIC Interpreter are permanently disabled by default.", + "id": "SECURE_BOOT", + "name": "SECURE_BOOT", + "range": null, + "title": "Enable hardware Secure Boot in bootloader (READ DOCS FIRST)", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": "On first boot, the bootloader will generate a key which is not readable externally or by software. A\ndigest is generated from the bootloader image itself. This digest will be verified on each subsequent\nboot.\n\nEnabling this option means that the bootloader cannot be changed after the first time it is booted.", + "id": "SECURE_BOOTLOADER_ONE_TIME_FLASH", + "name": "SECURE_BOOTLOADER_ONE_TIME_FLASH", + "range": null, + "title": "One-time flash", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": "Generate a reusable secure bootloader key, derived (via SHA-256) from the secure boot signing key.\n\nThis allows the secure bootloader to be re-flashed by anyone with access to the secure boot signing\nkey.\n\nThis option is less secure than one-time flash, because a leak of the digest key from one device\nallows reflashing of any device that uses it.", + "id": "SECURE_BOOTLOADER_REFLASHABLE", + "name": "SECURE_BOOTLOADER_REFLASHABLE", + "range": null, + "title": "Reflashable", + "type": "bool" + } + ], + "depends_on": "SECURE_BOOT_V1_ENABLED", + "help": null, + "id": "security-features-secure-bootloader-mode", + "name": "SECURE_BOOTLOADER_MODE", + "title": "Secure bootloader mode", + "type": "choice" + }, + { + "children": [ + { + "children": [], + "depends_on": "SECURE_BOOT_BUILD_SIGNED_BINARIES", + "help": "Path to the key file used to sign app images.\n\nKey file is an ECDSA private key (NIST256p curve) in PEM format for Secure Boot V1.\nKey file is an RSA private key in PEM format for Secure Boot V2.\n\nPath is evaluated relative to the project directory.\n\nYou can generate a new signing key by running the following command:\nespsecure.py generate_signing_key secure_boot_signing_key.pem\n\nSee the Secure Boot section of the ESP-IDF Programmer's Guide for this version for details.", + "id": "SECURE_BOOT_SIGNING_KEY", + "name": "SECURE_BOOT_SIGNING_KEY", + "range": null, + "title": "Secure boot private signing key", + "type": "string" + } + ], + "depends_on": "SECURE_SIGNED_APPS", + "help": "Once secure boot or signed app requirement is enabled, app images are required to be signed.\n\nIf enabled (default), these binary files are signed as part of the build process. The file named in\n\"Secure boot private signing key\" will be used to sign the image.\n\nIf disabled, unsigned app/partition data will be built. They must be signed manually using espsecure.py.\nVersion 1 to enable ECDSA Based Secure Boot and Version 2 to enable RSA based Secure Boot.\n(for example, on a remote signing server.)", + "id": "SECURE_BOOT_BUILD_SIGNED_BINARIES", + "name": "SECURE_BOOT_BUILD_SIGNED_BINARIES", + "range": null, + "title": "Sign binaries during build", + "type": "bool" + }, + { + "children": [], + "depends_on": "SECURE_SIGNED_APPS && SECURE_SIGNED_APPS_ECDSA_SCHEME && !SECURE_BOOT_BUILD_SIGNED_BINARIES", + "help": "Path to a public key file used to verify signed images.\nSecure Boot V1: This ECDSA public key is compiled into the bootloader and/or\napp, to verify app images.\n\nKey file is in raw binary format, and can be extracted from a\nPEM formatted private key using the espsecure.py\nextract_public_key command.\n\nRefer to the Secure Boot section of the ESP-IDF Programmer's Guide for this version before enabling.", + "id": "SECURE_BOOT_VERIFICATION_KEY", + "name": "SECURE_BOOT_VERIFICATION_KEY", + "range": null, + "title": "Secure boot public signature verification key", + "type": "string" + }, + { + "children": [], + "depends_on": "SECURE_BOOT && SOC_SUPPORT_SECURE_BOOT_REVOKE_KEY", + "help": "If this option is set, ROM bootloader will revoke the public key digest burned in efuse block\nif it fails to verify the signature of software bootloader with it.\nRevocation of keys does not happen when enabling secure boot. Once secure boot is enabled,\nkey revocation checks will be done on subsequent boot-up, while verifying the software bootloader\n\nThis feature provides a strong resistance against physical attacks on the device.\n\nNOTE: Once a digest slot is revoked, it can never be used again to verify an image\nThis can lead to permanent bricking of the device, in case all keys are revoked\nbecause of signature verification failure.", + "id": "SECURE_BOOT_ENABLE_AGGRESSIVE_KEY_REVOKE", + "name": "SECURE_BOOT_ENABLE_AGGRESSIVE_KEY_REVOKE", + "range": null, + "title": "Enable Aggressive key revoke strategy", + "type": "bool" + }, + { + "children": [], + "depends_on": "SECURE_BOOT_V2_ENABLED", + "help": "If not set (default, recommended), on first boot the bootloader will burn the WR_DIS_RD_DIS\nefuse when Secure Boot is enabled. This prevents any more efuses from being read protected.\n\nIf this option is set, it will remain possible to write the EFUSE_RD_DIS efuse field after Secure\nBoot is enabled. This may allow an attacker to read-protect the BLK2 efuse (for ESP32) and\nBLOCK4-BLOCK10 (i.e. BLOCK_KEY0-BLOCK_KEY5)(for other chips) holding the secure boot public key digest,\ncausing an immediate denial of service and possibly allowing an additional fault injection attack to\nbypass the signature protection.\n\nThe option must be set when you need to program any read-protected key type into the efuses,\ne.g., HMAC, ECDSA etc. after secure boot has already been enabled on the device.\nPlease refer to secure boot V2 documentation guide for more details.\n\nNOTE: Once a BLOCK is read-protected, the application will read all zeros from that block\n\nNOTE: If \"UART ROM download mode (Permanently disabled (recommended))\" or\n\"UART ROM download mode (Permanently switch to Secure mode (recommended))\" is set,\nthen it is __NOT__ possible to read/write efuses using espefuse.py utility.\nHowever, efuse can be read/written from the application\n\nPlease refer to the Secure Boot V2 documentation guide for more information.", + "id": "SECURE_BOOT_V2_ALLOW_EFUSE_RD_DIS", + "name": "SECURE_BOOT_V2_ALLOW_EFUSE_RD_DIS", + "range": null, + "title": "Do not disable the ability to further read protect eFuses", + "type": "bool" + }, + { + "children": [], + "depends_on": "SECURE_BOOT_V2_ENABLED && SECURE_BOOT_BUILD_SIGNED_BINARIES", + "help": "When Secure Boot V2 is enabled, by default the bootloader is not flashed along with other artifacts\nlike the application and the partition table images, i.e. bootloader has to be separately flashed\nusing the command `idf.py bootloader flash`, whereas, the application and partition table can be flashed\nusing the command `idf.py flash` itself.\nEnabling this option allows flashing the bootloader along with the other artifacts\nby invocation of the command `idf.py flash`.\n\nIf this option is enabled make sure that even the bootloader is signed using the correct secure boot key,\notherwise the bootloader signature verification would fail, as hash of the public key which is present in\nthe bootloader signature would not match with the digest stored into the efuses\nand thus the device will not be able to boot up.", + "id": "SECURE_BOOT_FLASH_BOOTLOADER_DEFAULT", + "name": "SECURE_BOOT_FLASH_BOOTLOADER_DEFAULT", + "range": null, + "title": "Flash bootloader along with other artifacts when using the default flash command", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "SECURE_BOOTLOADER_KEY_ENCODING_256BIT", + "name": "SECURE_BOOTLOADER_KEY_ENCODING_256BIT", + "range": null, + "title": "No encoding (256 bit key)", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "SECURE_BOOTLOADER_KEY_ENCODING_192BIT", + "name": "SECURE_BOOTLOADER_KEY_ENCODING_192BIT", + "range": null, + "title": "3/4 encoding (192 bit key)", + "type": "bool" + } + ], + "depends_on": "SECURE_BOOTLOADER_REFLASHABLE", + "help": "In reflashable secure bootloader mode, a hardware key is derived from the signing key (with SHA-256) and\ncan be written to eFuse with espefuse.py.\n\nNormally this is a 256-bit key, but if 3/4 Coding Scheme is used on the device then the eFuse key is\ntruncated to 192 bits.\n\nThis configuration item doesn't change any firmware code, it only changes the size of key binary which is\ngenerated at build time.", + "id": "security-features-hardware-key-encoding", + "name": "SECURE_BOOTLOADER_KEY_ENCODING", + "title": "Hardware Key Encoding", + "type": "choice" + }, + { + "children": [], + "depends_on": "SECURE_BOOT", + "help": "You can disable some of the default protections offered by secure boot, in order to enable testing or a\ncustom combination of security features.\n\nOnly enable these options if you are very sure.\n\nRefer to the Secure Boot section of the ESP-IDF Programmer's Guide for this version before enabling.", + "id": "SECURE_BOOT_INSECURE", + "name": "SECURE_BOOT_INSECURE", + "range": null, + "title": "Allow potentially insecure options", + "type": "bool" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "SOC_FLASH_ENCRYPTION_XTS_AES_128_DERIVED && ", + "help": null, + "id": "SECURE_FLASH_ENCRYPTION_AES128_DERIVED", + "name": "SECURE_FLASH_ENCRYPTION_AES128_DERIVED", + "range": null, + "title": "AES-128 key derived from 128 bits (SHA256(128 bits))", + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_FLASH_ENCRYPTION_XTS_AES_128 && !(IDF_TARGET_ESP32C2 && SECURE_BOOT) && ", + "help": null, + "id": "SECURE_FLASH_ENCRYPTION_AES128", + "name": "SECURE_FLASH_ENCRYPTION_AES128", + "range": null, + "title": "AES-128 (256-bit key)", + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_FLASH_ENCRYPTION_XTS_AES_256 && ", + "help": null, + "id": "SECURE_FLASH_ENCRYPTION_AES256", + "name": "SECURE_FLASH_ENCRYPTION_AES256", + "range": null, + "title": "AES-256 (512-bit key)", + "type": "bool" + } + ], + "depends_on": "SOC_FLASH_ENCRYPTION_XTS_AES_OPTIONS && SECURE_FLASH_ENC_ENABLED", + "help": "Size of generated XTS-AES key.\n\n- AES-128 uses a 256-bit key (32 bytes) derived from 128 bits (16 bytes) burned in half Efuse key block.\n Internally, it calculates SHA256(128 bits)\n- AES-128 uses a 256-bit key (32 bytes) which occupies one Efuse key block.\n- AES-256 uses a 512-bit key (64 bytes) which occupies two Efuse key blocks.\n\nThis setting is ignored if either type of key is already burned to Efuse before the first boot.\nIn this case, the pre-burned key is used and no new key is generated.", + "id": "security-features-enable-flash-encryption-on-boot-read-docs-first--size-of-generated-xts-aes-key", + "name": "SECURE_FLASH_ENCRYPTION_KEYSIZE", + "title": "Size of generated XTS-AES key", + "type": "choice" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT", + "name": "SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT", + "range": null, + "title": "Development (NOT SECURE)", + "type": "bool" + }, + { + "children": [], + "depends_on": "(!EFUSE_VIRTUAL || IDF_CI_BUILD) && ", + "help": null, + "id": "SECURE_FLASH_ENCRYPTION_MODE_RELEASE", + "name": "SECURE_FLASH_ENCRYPTION_MODE_RELEASE", + "range": null, + "title": "Release", + "type": "bool" + } + ], + "depends_on": "SECURE_FLASH_ENC_ENABLED", + "help": "By default Development mode is enabled which allows ROM download mode to perform flash encryption\noperations (plaintext is sent to the device, and it encrypts it internally and writes ciphertext\nto flash.) This mode is not secure, it's possible for an attacker to write their own chosen plaintext\nto flash.\n\nRelease mode should always be selected for production or manufacturing. Once enabled it's no longer\npossible for the device in ROM Download Mode to use the flash encryption hardware.\n\nWhen EFUSE_VIRTUAL is enabled, SECURE_FLASH_ENCRYPTION_MODE_RELEASE is not available.\nFor CI tests we use IDF_CI_BUILD to bypass it (\"export IDF_CI_BUILD=1\").\nWe do not recommend bypassing it for other purposes.\n\nRefer to the Flash Encryption section of the ESP-IDF Programmer's Guide for details.", + "id": "security-features-enable-flash-encryption-on-boot-read-docs-first--enable-usage-mode", + "name": "SECURE_FLASH_ENCRYPTION_MODE", + "title": "Enable usage mode", + "type": "choice" + } + ], + "depends_on": null, + "help": "If this option is set, flash contents will be encrypted by the bootloader on first boot.\n\nNote: After first boot, the system will be permanently encrypted. Re-flashing an encrypted\nsystem is complicated and not always possible.\n\nRead https://docs.espressif.com/projects/esp-idf/en/latest/security/flash-encryption.html\nbefore enabling.", + "id": "SECURE_FLASH_ENC_ENABLED", + "name": "SECURE_FLASH_ENC_ENABLED", + "range": null, + "title": "Enable flash encryption on boot (READ DOCS FIRST)", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SECURE_FLASH_HAS_WRITE_PROTECTION_CACHE", + "name": "SECURE_FLASH_HAS_WRITE_PROTECTION_CACHE", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "(SECURE_BOOT_INSECURE || SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT) && IDF_TARGET_ESP32", + "help": "By default, the BASIC ROM Console starts on reset if no valid bootloader is\nread from the flash.\n\nWhen either flash encryption or secure boot are enabled, the default is to\ndisable this BASIC fallback mode permanently via eFuse.\n\nIf this option is set, this eFuse is not burned and the BASIC ROM Console may\nremain accessible. Only set this option in testing environments.", + "id": "SECURE_BOOT_ALLOW_ROM_BASIC", + "name": "SECURE_BOOT_ALLOW_ROM_BASIC", + "range": null, + "title": "Leave ROM BASIC Interpreter available on reset", + "type": "bool" + }, + { + "children": [], + "depends_on": "SECURE_BOOT_INSECURE || SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT", + "help": "If not set (default), the bootloader will permanently disable JTAG (across entire chip) on first boot\nwhen either secure boot or flash encryption is enabled.\n\nSetting this option leaves JTAG on for debugging, which negates all protections of flash encryption\nand some of the protections of secure boot.\n\nOnly set this option in testing environments.", + "id": "SECURE_BOOT_ALLOW_JTAG", + "name": "SECURE_BOOT_ALLOW_JTAG", + "range": null, + "title": "Allow JTAG Debugging", + "type": "bool" + }, + { + "children": [], + "depends_on": "SECURE_BOOT_INSECURE || SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT", + "help": "If not set (default), app partition size must be a multiple of 64KB. App images are padded to 64KB\nlength, and the bootloader checks any trailing bytes after the signature (before the next 64KB\nboundary) have not been written. This is because flash cache maps entire 64KB pages into the address\nspace. This prevents an attacker from appending unverified data after the app image in the flash,\ncausing it to be mapped into the address space.\n\nSetting this option allows the app partition length to be unaligned, and disables padding of the app\nimage to this length. It is generally not recommended to set this option, unless you have a legacy\npartitioning scheme which doesn't support 64KB aligned partition lengths.", + "id": "SECURE_BOOT_ALLOW_SHORT_APP_PARTITION", + "name": "SECURE_BOOT_ALLOW_SHORT_APP_PARTITION", + "range": null, + "title": "Allow app partition length not 64KB aligned", + "type": "bool" + }, + { + "children": [], + "depends_on": "SECURE_BOOT_INSECURE && SOC_EFUSE_REVOKE_BOOT_KEY_DIGESTS", + "help": "If not set (default), during startup in the app all unused digest slots will be revoked.\nTo revoke unused slot will be called esp_efuse_set_digest_revoke(num_digest) for each digest.\nRevoking unused digest slots makes ensures that no trusted keys can be added later by an attacker.\nIf set, it means that you have a plan to use unused digests slots later.\n\nNote that if you plan to enable secure boot during the first boot up, the bootloader will intentionally\nrevoke the unused digest slots while enabling secure boot, even if the above config is enabled because\nkeeping the unused key slots un-revoked would a security hazard.\nIn case for any development workflow if you need to avoid this revocation, you should enable\nsecure boot externally (host based mechanism) rather than enabling it during the boot up,\nso that the bootloader would not need to enable secure boot and thus you could avoid its revocation\nstrategy.", + "id": "SECURE_BOOT_ALLOW_UNUSED_DIGEST_SLOTS", + "name": "SECURE_BOOT_ALLOW_UNUSED_DIGEST_SLOTS", + "range": null, + "title": "Leave unused digest slots available (not revoke)", + "type": "bool" + }, + { + "children": [], + "depends_on": "SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT", + "help": "If not set (default), the bootloader will permanently disable UART bootloader encryption access on\nfirst boot. If set, the UART bootloader will still be able to access hardware encryption.\n\nIt is recommended to only set this option in testing environments.", + "id": "SECURE_FLASH_UART_BOOTLOADER_ALLOW_ENC", + "name": "SECURE_FLASH_UART_BOOTLOADER_ALLOW_ENC", + "range": null, + "title": "Leave UART bootloader encryption enabled", + "type": "bool" + }, + { + "children": [], + "depends_on": "SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT && IDF_TARGET_ESP32", + "help": "If not set (default), the bootloader will permanently disable UART bootloader decryption access on\nfirst boot. If set, the UART bootloader will still be able to access hardware decryption.\n\nOnly set this option in testing environments. Setting this option allows complete bypass of flash\nencryption.", + "id": "SECURE_FLASH_UART_BOOTLOADER_ALLOW_DEC", + "name": "SECURE_FLASH_UART_BOOTLOADER_ALLOW_DEC", + "range": null, + "title": "Leave UART bootloader decryption enabled", + "type": "bool" + }, + { + "children": [], + "depends_on": "SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT && (IDF_TARGET_ESP32 || SOC_EFUSE_DIS_DOWNLOAD_ICACHE || SOC_EFUSE_DIS_DOWNLOAD_DCACHE)", + "help": "If not set (default), the bootloader will permanently disable UART bootloader flash cache access on\nfirst boot. If set, the UART bootloader will still be able to access the flash cache.\n\nOnly set this option in testing environments.", + "id": "SECURE_FLASH_UART_BOOTLOADER_ALLOW_CACHE", + "name": "SECURE_FLASH_UART_BOOTLOADER_ALLOW_CACHE", + "range": null, + "title": "Leave UART bootloader flash cache enabled", + "type": "bool" + }, + { + "children": [], + "depends_on": "SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT", + "help": "If not set (default), and flash encryption is not yet enabled in eFuses, the 2nd stage bootloader\nwill enable flash encryption: generate the flash encryption key and program eFuses.\nIf this option is set, and flash encryption is not yet enabled, the bootloader will error out and\nreboot.\nIf flash encryption is enabled in eFuses, this option does not change the bootloader behavior.\n\nOnly use this option in testing environments, to avoid accidentally enabling flash encryption on\nthe wrong device. The device needs to have flash encryption already enabled using espefuse.py.", + "id": "SECURE_FLASH_REQUIRE_ALREADY_ENABLED", + "name": "SECURE_FLASH_REQUIRE_ALREADY_ENABLED", + "range": null, + "title": "Require flash encryption to be already enabled", + "type": "bool" + }, + { + "children": [], + "depends_on": "SECURE_FLASH_HAS_WRITE_PROTECTION_CACHE", + "help": "If not set (default, recommended), on the first boot the bootloader will burn the write-protection of\nDIS_CACHE(for ESP32) or DIS_ICACHE/DIS_DCACHE(for other chips) eFuse when Flash Encryption is enabled.\nWrite protection for cache disable efuse prevents the chip from being blocked if it is set by accident.\nApp and bootloader use cache so disabling it makes the chip useless for IDF.\nDue to other eFuses are linked with the same write protection bit (see the list below) then\nwrite-protection will not be done if these SECURE_FLASH_UART_BOOTLOADER_ALLOW_ENC,\nSECURE_BOOT_ALLOW_JTAG or SECURE_FLASH_UART_BOOTLOADER_ALLOW_CACHE options are selected\nto give a chance to turn on the chip into the release mode later.\n\nList of eFuses with the same write protection bit:\nESP32: MAC, MAC_CRC, DISABLE_APP_CPU, DISABLE_BT, DIS_CACHE, VOL_LEVEL_HP_INV.\n\nESP32-C3: DIS_ICACHE, DIS_USB_JTAG, DIS_DOWNLOAD_ICACHE, DIS_USB_SERIAL_JTAG,\nDIS_FORCE_DOWNLOAD, DIS_TWAI, JTAG_SEL_ENABLE, DIS_PAD_JTAG, DIS_DOWNLOAD_MANUAL_ENCRYPT.\n\nESP32-C6: SWAP_UART_SDIO_EN, DIS_ICACHE, DIS_USB_JTAG, DIS_DOWNLOAD_ICACHE,\nDIS_USB_SERIAL_JTAG, DIS_FORCE_DOWNLOAD, DIS_TWAI, JTAG_SEL_ENABLE,\nDIS_PAD_JTAG, DIS_DOWNLOAD_MANUAL_ENCRYPT.\n\nESP32-H2: DIS_ICACHE, DIS_USB_JTAG, POWERGLITCH_EN, DIS_FORCE_DOWNLOAD, SPI_DOWNLOAD_MSPI_DIS,\nDIS_TWAI, JTAG_SEL_ENABLE, DIS_PAD_JTAG, DIS_DOWNLOAD_MANUAL_ENCRYPT.\n\nESP32-S2: DIS_ICACHE, DIS_DCACHE, DIS_DOWNLOAD_ICACHE, DIS_DOWNLOAD_DCACHE,\nDIS_FORCE_DOWNLOAD, DIS_USB, DIS_TWAI, DIS_BOOT_REMAP, SOFT_DIS_JTAG,\nHARD_DIS_JTAG, DIS_DOWNLOAD_MANUAL_ENCRYPT.\n\nESP32-S3: DIS_ICACHE, DIS_DCACHE, DIS_DOWNLOAD_ICACHE, DIS_DOWNLOAD_DCACHE,\nDIS_FORCE_DOWNLOAD, DIS_USB_OTG, DIS_TWAI, DIS_APP_CPU, DIS_PAD_JTAG,\nDIS_DOWNLOAD_MANUAL_ENCRYPT, DIS_USB_JTAG, DIS_USB_SERIAL_JTAG, STRAP_JTAG_SEL, USB_PHY_SEL.", + "id": "SECURE_FLASH_SKIP_WRITE_PROTECTION_CACHE", + "name": "SECURE_FLASH_SKIP_WRITE_PROTECTION_CACHE", + "range": null, + "title": "Skip write-protection of DIS_CACHE (DIS_ICACHE, DIS_DCACHE)", + "type": "bool" + } + ], + "depends_on": null, + "id": "security-features-potentially-insecure-options", + "title": "Potentially insecure options", + "type": "menu" + }, + { + "children": [], + "depends_on": "SECURE_FLASH_ENC_ENABLED && !SECURE_FLASH_REQUIRE_ALREADY_ENABLED", + "help": "If set (default), optimise encryption time for the partition of type APP,\nby only encrypting the app image that is present in the partition,\ninstead of the whole partition.\nThe image length used for encryption is derived from the image metadata, which\nincludes the size of the app image, checksum, hash and also the signature sector\nwhen secure boot is enabled.\n\nIf not set, the whole partition of type APP would be encrypted,\nwhich increases the encryption time but might be useful if there\nis any custom data appended to the firmware image.", + "id": "SECURE_FLASH_ENCRYPT_ONLY_IMAGE_LEN_IN_APP_PART", + "name": "SECURE_FLASH_ENCRYPT_ONLY_IMAGE_LEN_IN_APP_PART", + "range": null, + "title": "Encrypt only the app image that is present in the partition of type app", + "type": "bool" + }, + { + "children": [], + "depends_on": "SECURE_FLASH_ENC_ENABLED", + "help": "If set (default), in an app during startup code,\nthere is a check of the flash encryption eFuse bit is on\n(as the bootloader should already have set it).\nThe app requires this bit is on to continue work otherwise abort.\n\nIf not set, the app does not care if the flash encryption eFuse bit is set or not.", + "id": "SECURE_FLASH_CHECK_ENC_EN_IN_APP", + "name": "SECURE_FLASH_CHECK_ENC_EN_IN_APP", + "range": null, + "title": "Check Flash Encryption enabled on app startup", + "type": "bool" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "SECURE_FLASH_PSEUDO_ROUND_FUNC_STRENGTH_LOW", + "name": "SECURE_FLASH_PSEUDO_ROUND_FUNC_STRENGTH_LOW", + "range": null, + "title": "Low", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "SECURE_FLASH_PSEUDO_ROUND_FUNC_STRENGTH_MEDIUM", + "name": "SECURE_FLASH_PSEUDO_ROUND_FUNC_STRENGTH_MEDIUM", + "range": null, + "title": "Medium", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "SECURE_FLASH_PSEUDO_ROUND_FUNC_STRENGTH_HIGH", + "name": "SECURE_FLASH_PSEUDO_ROUND_FUNC_STRENGTH_HIGH", + "range": null, + "title": "High", + "type": "bool" + } + ], + "depends_on": "SECURE_FLASH_PSEUDO_ROUND_FUNC", + "help": "The strength of the pseudo rounds functions can be configured to low, medium and high,\neach denoting the values that would be stored in the efuses field.\nBy default the value to set to low.\nYou can configure the strength of the pseudo rounds functions according to your use cases,\nfor example, increasing the strength would provide higher security but would slow down the\nflash encryption/decryption operations.\nFor more info regarding the performance impact, please checkout the pseudo round function section of the\nsecurity guide documentation.", + "id": "security-features-permanently-enable-xts-aes-s-pseudo-rounds-function-strength-of-the-pseudo-rounds-function", + "name": "SECURE_FLASH_PSEUDO_ROUND_FUNC_STRENGTH", + "title": "Strength of the pseudo rounds function", + "type": "choice" + } + ], + "depends_on": "SECURE_FLASH_ENCRYPTION_MODE_RELEASE && SOC_FLASH_ENCRYPTION_XTS_AES_SUPPORT_PSEUDO_ROUND", + "help": "If set (default), the bootloader will permanently enable the XTS-AES peripheral's pseudo rounds function.\nNote: Enabling this config would burn an efuse.", + "id": "SECURE_FLASH_PSEUDO_ROUND_FUNC", + "name": "SECURE_FLASH_PSEUDO_ROUND_FUNC", + "range": null, + "title": "Permanently enable XTS-AES's pseudo rounds function", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SECURE_FLASH_PSEUDO_ROUND_FUNC_STRENGTH", + "name": "SECURE_FLASH_PSEUDO_ROUND_FUNC_STRENGTH", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SECURE_ROM_DL_MODE_ENABLED", + "name": "SECURE_ROM_DL_MODE_ENABLED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": "If set, during startup the app will burn an eFuse bit to permanently disable the UART ROM\nDownload Mode. This prevents any future use of esptool.py, espefuse.py and similar tools.\n\nOnce disabled, if the SoC is booted with strapping pins set for ROM Download Mode\nthen an error is printed instead.\n\nIt is recommended to enable this option in any production application where Flash\nEncryption and/or Secure Boot is enabled and access to Download Mode is not required.\n\nIt is also possible to permanently disable Download Mode by calling\nesp_efuse_disable_rom_download_mode() at runtime.", + "id": "SECURE_DISABLE_ROM_DL_MODE", + "name": "SECURE_DISABLE_ROM_DL_MODE", + "range": null, + "title": "UART ROM download mode (Permanently disabled (recommended))", + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_SUPPORTS_SECURE_DL_MODE && ", + "help": "If set, during startup the app will burn an eFuse bit to permanently switch the UART ROM\nDownload Mode into a separate Secure Download mode. This option can only work if\nDownload Mode is not already disabled by eFuse.\n\nSecure Download mode limits the use of Download Mode functions to update SPI config,\nchanging baud rate, basic flash write and a command to return a summary of currently\nenabled security features (`get_security_info`).\n\nSecure Download mode is not compatible with the esptool.py flasher stub feature,\nespefuse.py, read/writing memory or registers, encrypted download, or any other\nfeatures that interact with unsupported Download Mode commands.\n\nSecure Download mode should be enabled in any application where Flash Encryption\nand/or Secure Boot is enabled. Disabling this option does not immediately cancel\nthe benefits of the security features, but it increases the potential \"attack\nsurface\" for an attacker to try and bypass them with a successful physical attack.\n\nIt is also possible to enable secure download mode at runtime by calling\nesp_efuse_enable_rom_secure_download_mode()\n\nNote: Secure Download mode is not available for ESP32 (includes revisions till ECO3).", + "id": "SECURE_ENABLE_SECURE_ROM_DL_MODE", + "name": "SECURE_ENABLE_SECURE_ROM_DL_MODE", + "range": null, + "title": "UART ROM download mode (Permanently switch to Secure mode (recommended))", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": "This is a potentially insecure option.\nEnabling this option will allow the full UART download mode to stay enabled.\nThis option SHOULD NOT BE ENABLED for production use cases.", + "id": "SECURE_INSECURE_ALLOW_DL_MODE", + "name": "SECURE_INSECURE_ALLOW_DL_MODE", + "range": null, + "title": "UART ROM download mode (Enabled (not recommended))", + "type": "bool" + } + ], + "depends_on": "(SECURE_BOOT_V2_ENABLED || SECURE_FLASH_ENC_ENABLED) && !(IDF_TARGET_ESP32 && ESP32_REV_MIN_FULL < 300)", + "help": null, + "id": "security-features-uart-rom-download-mode", + "name": "SECURE_UART_ROM_DL_MODE", + "title": "UART ROM download mode", + "type": "choice" + } + ], + "depends_on": null, + "id": "security-features", + "title": "Security features", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": "!APP_REPRODUCIBLE_BUILD", + "help": "If set, then the app will be built with the current time/date stamp. It is stored in the app description\nstructure. If not set, time/date stamp will be excluded from app image. This can be useful for getting the\nsame binary image files made from the same source, but at different times.", + "id": "APP_COMPILE_TIME_DATE", + "name": "APP_COMPILE_TIME_DATE", + "range": null, + "title": "Use time/date stamp for app", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "The PROJECT_VER variable from the build system will not affect the firmware image.\nThis value will not be contained in the esp_app_desc structure.", + "id": "APP_EXCLUDE_PROJECT_VER_VAR", + "name": "APP_EXCLUDE_PROJECT_VER_VAR", + "range": null, + "title": "Exclude PROJECT_VER from firmware image", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "The PROJECT_NAME variable from the build system will not affect the firmware image.\nThis value will not be contained in the esp_app_desc structure.", + "id": "APP_EXCLUDE_PROJECT_NAME_VAR", + "name": "APP_EXCLUDE_PROJECT_NAME_VAR", + "range": null, + "title": "Exclude PROJECT_NAME from firmware image", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "APP_PROJECT_VER_FROM_CONFIG", + "help": "Project version", + "id": "APP_PROJECT_VER", + "name": "APP_PROJECT_VER", + "range": null, + "title": "Project version", + "type": "string" + } + ], + "depends_on": null, + "help": "If this is enabled, then config item APP_PROJECT_VER will be used for the variable PROJECT_VER.\nOther ways to set PROJECT_VER will be ignored.", + "id": "APP_PROJECT_VER_FROM_CONFIG", + "name": "APP_PROJECT_VER_FROM_CONFIG", + "range": null, + "title": "Get the project version from Kconfig", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "At startup, the app will read the embedded APP ELF SHA-256 hash value from flash\nand convert it into a string and store it in a RAM buffer.\nThis ensures the panic handler and core dump will be able to print this string\neven when cache is disabled.\nThe size of the buffer is APP_RETRIEVE_LEN_ELF_SHA plus the null terminator.\nChanging this value will change the size of this buffer, in bytes.", + "id": "APP_RETRIEVE_LEN_ELF_SHA", + "name": "APP_RETRIEVE_LEN_ELF_SHA", + "range": [ + 8, + 64 + ], + "title": "The length of APP ELF SHA is stored in RAM(chars)", + "type": "int" + } + ], + "depends_on": null, + "id": "application-manager", + "title": "Application manager", + "type": "menu" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "ESP_ROM_HAS_CRC_LE", + "name": "ESP_ROM_HAS_CRC_LE", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "ESP_ROM_HAS_CRC_BE", + "name": "ESP_ROM_HAS_CRC_BE", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "ESP_ROM_HAS_MZ_CRC32", + "name": "ESP_ROM_HAS_MZ_CRC32", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "ESP_ROM_HAS_JPEG_DECODE", + "name": "ESP_ROM_HAS_JPEG_DECODE", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "ESP_ROM_UART_CLK_IS_XTAL", + "name": "ESP_ROM_UART_CLK_IS_XTAL", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "ESP_ROM_USB_SERIAL_DEVICE_NUM", + "name": "ESP_ROM_USB_SERIAL_DEVICE_NUM", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "ESP_ROM_HAS_RETARGETABLE_LOCKING", + "name": "ESP_ROM_HAS_RETARGETABLE_LOCKING", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "ESP_ROM_HAS_ERASE_0_REGION_BUG", + "name": "ESP_ROM_HAS_ERASE_0_REGION_BUG", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "ESP_ROM_HAS_ENCRYPTED_WRITES_USING_LEGACY_DRV", + "name": "ESP_ROM_HAS_ENCRYPTED_WRITES_USING_LEGACY_DRV", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "ESP_ROM_GET_CLK_FREQ", + "name": "ESP_ROM_GET_CLK_FREQ", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "ESP_ROM_NEEDS_SWSETUP_WORKAROUND", + "name": "ESP_ROM_NEEDS_SWSETUP_WORKAROUND", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "ESP_ROM_HAS_LAYOUT_TABLE", + "name": "ESP_ROM_HAS_LAYOUT_TABLE", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "ESP_ROM_HAS_SPI_FLASH", + "name": "ESP_ROM_HAS_SPI_FLASH", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "ESP_ROM_HAS_ETS_PRINTF_BUG", + "name": "ESP_ROM_HAS_ETS_PRINTF_BUG", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "ESP_ROM_HAS_NEWLIB", + "name": "ESP_ROM_HAS_NEWLIB", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "ESP_ROM_HAS_NEWLIB_NANO_FORMAT", + "name": "ESP_ROM_HAS_NEWLIB_NANO_FORMAT", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "ESP_ROM_HAS_NEWLIB_32BIT_TIME", + "name": "ESP_ROM_HAS_NEWLIB_32BIT_TIME", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "ESP_ROM_NEEDS_SET_CACHE_MMU_SIZE", + "name": "ESP_ROM_NEEDS_SET_CACHE_MMU_SIZE", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "ESP_ROM_RAM_APP_NEEDS_MMU_INIT", + "name": "ESP_ROM_RAM_APP_NEEDS_MMU_INIT", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "ESP_ROM_HAS_SW_FLOAT", + "name": "ESP_ROM_HAS_SW_FLOAT", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "ESP_ROM_USB_OTG_NUM", + "name": "ESP_ROM_USB_OTG_NUM", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "ESP_ROM_HAS_VERSION", + "name": "ESP_ROM_HAS_VERSION", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "ESP_ROM_SUPPORT_DEEP_SLEEP_WAKEUP_STUB", + "name": "ESP_ROM_SUPPORT_DEEP_SLEEP_WAKEUP_STUB", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "", + "help": "Always print ROM logs, this is the default behavior.", + "id": "BOOT_ROM_LOG_ALWAYS_ON", + "name": "BOOT_ROM_LOG_ALWAYS_ON", + "range": null, + "title": "Always Log", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": "Don't print ROM logs.", + "id": "BOOT_ROM_LOG_ALWAYS_OFF", + "name": "BOOT_ROM_LOG_ALWAYS_OFF", + "range": null, + "title": "Permanently disable logging", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": "Print ROM logs when GPIO level is high during start up.\nThe GPIO number is chip dependent,\ne.g. on ESP32-S2, the control GPIO is GPIO46.", + "id": "BOOT_ROM_LOG_ON_GPIO_HIGH", + "name": "BOOT_ROM_LOG_ON_GPIO_HIGH", + "range": null, + "title": "Log on GPIO High", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": "Print ROM logs when GPIO level is low during start up.\nThe GPIO number is chip dependent,\ne.g. on ESP32-S2, the control GPIO is GPIO46.", + "id": "BOOT_ROM_LOG_ON_GPIO_LOW", + "name": "BOOT_ROM_LOG_ON_GPIO_LOW", + "range": null, + "title": "Log on GPIO Low", + "type": "bool" + } + ], + "depends_on": "!IDF_TARGET_ESP32", + "help": "Controls the Boot ROM log behavior.\nThe rom log behavior can only be changed for once,\nspecific eFuse bit(s) will be burned at app boot stage.", + "id": "boot-rom-behavior-permanently-change-boot-rom-output", + "name": "BOOT_ROM_LOG_SCHEME", + "title": "Permanently change Boot ROM output", + "type": "choice" + } + ], + "depends_on": null, + "id": "boot-rom-behavior", + "title": "Boot ROM Behavior", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": "!APP_BUILD_TYPE_PURE_RAM_APP", + "help": "The flasher tool sends a precompiled download stub first by default. That stub allows things\nlike compressed downloads and more. Usually you should not need to disable that feature", + "id": "ESPTOOLPY_NO_STUB", + "name": "ESPTOOLPY_NO_STUB", + "range": null, + "title": "Disable download stub", + "type": "bool" + }, + { + "children": [], + "depends_on": "IDF_TARGET_ESP32S3 && !APP_BUILD_TYPE_PURE_RAM_APP", + "help": null, + "id": "ESPTOOLPY_OCT_FLASH", + "name": "ESPTOOLPY_OCT_FLASH", + "range": null, + "title": "Enable Octal Flash", + "type": "bool" + }, + { + "children": [], + "depends_on": "IDF_TARGET_ESP32S3 && !APP_BUILD_TYPE_PURE_RAM_APP", + "help": "This config option helps decide whether flash is Quad or Octal, but please note some limitations:\n\n1. If the flash chip is an Octal one, even if one of \"QIO\", \"QOUT\", \"DIO\", \"DOUT\" options is\n selected in `ESPTOOLPY_FLASHMODE`, our code will automatically change the\n mode to \"OPI\" and the sample mode will be STR.\n2. If the flash chip is a Quad one, even if \"OPI\" is selected in `ESPTOOLPY_FLASHMODE`, our code will\n automatically change the mode to \"DIO\".\n3. This option is mainly to improve the out-of-box experience of developers. It doesn't guarantee\n the feature-complete. Some code still rely on `ESPTOOLPY_OCT_FLASH`. Please do not rely on this option\n when you are pretty sure that you are using Octal flash.\n In this case, please enable `ESPTOOLPY_OCT_FLASH` option, then you can choose `DTR` sample mode\n in `ESPTOOLPY_FLASH_SAMPLE_MODE`. Otherwise, only `STR` mode is available.\n4. Enabling this feature reduces available internal RAM size (around 900 bytes).\n If your IRAM space is insufficient and you're aware of your flash type,\n disable this option and select corresponding flash type options.", + "id": "ESPTOOLPY_FLASH_MODE_AUTO_DETECT", + "name": "ESPTOOLPY_FLASH_MODE_AUTO_DETECT", + "range": null, + "title": "Choose flash mode automatically (please read help)", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "!ESPTOOLPY_OCT_FLASH && ", + "help": null, + "id": "ESPTOOLPY_FLASHMODE_QIO", + "name": "ESPTOOLPY_FLASHMODE_QIO", + "range": null, + "title": "QIO", + "type": "bool" + }, + { + "children": [], + "depends_on": "!ESPTOOLPY_OCT_FLASH && ", + "help": null, + "id": "ESPTOOLPY_FLASHMODE_QOUT", + "name": "ESPTOOLPY_FLASHMODE_QOUT", + "range": null, + "title": "QOUT", + "type": "bool" + }, + { + "children": [], + "depends_on": "!ESPTOOLPY_OCT_FLASH && ", + "help": null, + "id": "ESPTOOLPY_FLASHMODE_DIO", + "name": "ESPTOOLPY_FLASHMODE_DIO", + "range": null, + "title": "DIO", + "type": "bool" + }, + { + "children": [], + "depends_on": "!ESPTOOLPY_OCT_FLASH && ", + "help": null, + "id": "ESPTOOLPY_FLASHMODE_DOUT", + "name": "ESPTOOLPY_FLASHMODE_DOUT", + "range": null, + "title": "DOUT", + "type": "bool" + }, + { + "children": [], + "depends_on": "ESPTOOLPY_OCT_FLASH && ", + "help": null, + "id": "ESPTOOLPY_FLASHMODE_OPI", + "name": "ESPTOOLPY_FLASHMODE_OPI", + "range": null, + "title": "OPI", + "type": "bool" + } + ], + "depends_on": "!APP_BUILD_TYPE_PURE_RAM_APP", + "help": "Mode the flash chip is flashed in, as well as the default mode for the\nbinary to run in.", + "id": "serial-flasher-config-flash-spi-mode", + "name": "ESPTOOLPY_FLASHMODE", + "title": "Flash SPI mode", + "type": "choice" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "ESPTOOLPY_FLASH_SAMPLE_MODE_STR", + "name": "ESPTOOLPY_FLASH_SAMPLE_MODE_STR", + "range": null, + "title": "STR Mode", + "type": "bool" + }, + { + "children": [], + "depends_on": "ESPTOOLPY_OCT_FLASH && ", + "help": null, + "id": "ESPTOOLPY_FLASH_SAMPLE_MODE_DTR", + "name": "ESPTOOLPY_FLASH_SAMPLE_MODE_DTR", + "range": null, + "title": "DTR Mode", + "type": "bool" + } + ], + "depends_on": "!APP_BUILD_TYPE_PURE_RAM_APP", + "help": null, + "id": "serial-flasher-config-flash-sampling-mode", + "name": "ESPTOOLPY_FLASH_SAMPLE_MODE", + "title": "Flash Sampling Mode", + "type": "choice" + }, + { + "children": [], + "depends_on": "!APP_BUILD_TYPE_PURE_RAM_APP", + "help": null, + "id": "ESPTOOLPY_FLASHMODE", + "name": "ESPTOOLPY_FLASHMODE", + "range": null, + "title": null, + "type": "string" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "ESPTOOLPY_FLASHFREQ_80M", + "name": "ESPTOOLPY_FLASHFREQ_80M", + "range": null, + "title": "80 MHz", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "ESPTOOLPY_FLASHFREQ_40M", + "name": "ESPTOOLPY_FLASHFREQ_40M", + "range": null, + "title": "40 MHz", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "ESPTOOLPY_FLASHFREQ_26M", + "name": "ESPTOOLPY_FLASHFREQ_26M", + "range": null, + "title": "26 MHz", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "ESPTOOLPY_FLASHFREQ_20M", + "name": "ESPTOOLPY_FLASHFREQ_20M", + "range": null, + "title": "20 MHz", + "type": "bool" + } + ], + "depends_on": "!APP_BUILD_TYPE_PURE_RAM_APP", + "help": null, + "id": "serial-flasher-config-flash-spi-speed", + "name": "ESPTOOLPY_FLASHFREQ", + "title": "Flash SPI speed", + "type": "choice" + }, + { + "children": [], + "depends_on": "!APP_BUILD_TYPE_PURE_RAM_APP", + "help": null, + "id": "ESPTOOLPY_FLASHFREQ", + "name": "ESPTOOLPY_FLASHFREQ", + "range": null, + "title": null, + "type": "string" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "ESPTOOLPY_FLASHSIZE_1MB", + "name": "ESPTOOLPY_FLASHSIZE_1MB", + "range": null, + "title": "1 MB", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "ESPTOOLPY_FLASHSIZE_2MB", + "name": "ESPTOOLPY_FLASHSIZE_2MB", + "range": null, + "title": "2 MB", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "ESPTOOLPY_FLASHSIZE_4MB", + "name": "ESPTOOLPY_FLASHSIZE_4MB", + "range": null, + "title": "4 MB", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "ESPTOOLPY_FLASHSIZE_8MB", + "name": "ESPTOOLPY_FLASHSIZE_8MB", + "range": null, + "title": "8 MB", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "ESPTOOLPY_FLASHSIZE_16MB", + "name": "ESPTOOLPY_FLASHSIZE_16MB", + "range": null, + "title": "16 MB", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "ESPTOOLPY_FLASHSIZE_32MB", + "name": "ESPTOOLPY_FLASHSIZE_32MB", + "range": null, + "title": "32 MB", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "ESPTOOLPY_FLASHSIZE_64MB", + "name": "ESPTOOLPY_FLASHSIZE_64MB", + "range": null, + "title": "64 MB", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "ESPTOOLPY_FLASHSIZE_128MB", + "name": "ESPTOOLPY_FLASHSIZE_128MB", + "range": null, + "title": "128 MB", + "type": "bool" + } + ], + "depends_on": "!APP_BUILD_TYPE_PURE_RAM_APP", + "help": "SPI flash size, in megabytes", + "id": "serial-flasher-config-flash-size", + "name": "ESPTOOLPY_FLASHSIZE", + "title": "Flash size", + "type": "choice" + }, + { + "children": [], + "depends_on": "!APP_BUILD_TYPE_PURE_RAM_APP", + "help": null, + "id": "ESPTOOLPY_FLASHSIZE", + "name": "ESPTOOLPY_FLASHSIZE", + "range": null, + "title": null, + "type": "string" + }, + { + "children": [], + "depends_on": "!APP_BUILD_TYPE_PURE_RAM_APP", + "help": "If this option is set, flashing the project will automatically detect\nthe flash size of the target chip and update the bootloader image\nbefore it is flashed.\n\nEnabling this option turns off the image protection against corruption\nby a SHA256 digest. Updating the bootloader image before flashing would\ninvalidate the digest.", + "id": "ESPTOOLPY_HEADER_FLASHSIZE_UPDATE", + "name": "ESPTOOLPY_HEADER_FLASHSIZE_UPDATE", + "range": null, + "title": "Detect flash size when flashing bootloader", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "ESPTOOLPY_BEFORE_RESET", + "name": "ESPTOOLPY_BEFORE_RESET", + "range": null, + "title": "Reset to bootloader", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "ESPTOOLPY_BEFORE_NORESET", + "name": "ESPTOOLPY_BEFORE_NORESET", + "range": null, + "title": "No reset", + "type": "bool" + } + ], + "depends_on": "!APP_BUILD_TYPE_PURE_RAM_APP", + "help": "Configure whether esptool.py should reset the ESP32 before flashing.\n\nAutomatic resetting depends on the RTS & DTR signals being\nwired from the serial port to the ESP32. Most USB development\nboards do this internally.", + "id": "serial-flasher-config-before-flashing", + "name": "ESPTOOLPY_BEFORE", + "title": "Before flashing", + "type": "choice" + }, + { + "children": [], + "depends_on": "!APP_BUILD_TYPE_PURE_RAM_APP", + "help": null, + "id": "ESPTOOLPY_BEFORE", + "name": "ESPTOOLPY_BEFORE", + "range": null, + "title": null, + "type": "string" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "ESPTOOLPY_AFTER_RESET", + "name": "ESPTOOLPY_AFTER_RESET", + "range": null, + "title": "Reset after flashing", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "ESPTOOLPY_AFTER_NORESET", + "name": "ESPTOOLPY_AFTER_NORESET", + "range": null, + "title": "Stay in bootloader", + "type": "bool" + } + ], + "depends_on": "!APP_BUILD_TYPE_PURE_RAM_APP", + "help": "Configure whether esptool.py should reset the ESP32 after flashing.\n\nAutomatic resetting depends on the RTS & DTR signals being\nwired from the serial port to the ESP32. Most USB development\nboards do this internally.", + "id": "serial-flasher-config-after-flashing", + "name": "ESPTOOLPY_AFTER", + "title": "After flashing", + "type": "choice" + }, + { + "children": [], + "depends_on": "!APP_BUILD_TYPE_PURE_RAM_APP", + "help": null, + "id": "ESPTOOLPY_AFTER", + "name": "ESPTOOLPY_AFTER", + "range": null, + "title": null, + "type": "string" + }, + { + "children": [], + "depends_on": "!APP_BUILD_TYPE_PURE_RAM_APP", + "help": null, + "id": "ESPTOOLPY_MONITOR_BAUD", + "name": "ESPTOOLPY_MONITOR_BAUD", + "range": null, + "title": null, + "type": "int" + } + ], + "depends_on": "!APP_BUILD_TYPE_PURE_RAM_APP", + "id": "serial-flasher-config", + "title": "Serial flasher config", + "type": "menu" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "", + "help": "This is the default partition table, designed to fit into a 2MB or\nlarger flash with a single 1MB app partition.\n\nThe corresponding CSV file in the IDF directory is\ncomponents/partition_table/partitions_singleapp.csv\n\nThis partition table is not suitable for an app that needs OTA\n(over the air update) capability.", + "id": "PARTITION_TABLE_SINGLE_APP", + "name": "PARTITION_TABLE_SINGLE_APP", + "range": null, + "title": "Single factory app, no OTA", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": "This is a variation of the default partition table, that expands\nthe 1MB app partition size to 1.5MB to fit more code.\n\nThe corresponding CSV file in the IDF directory is\ncomponents/partition_table/partitions_singleapp_large.csv\n\nThis partition table is not suitable for an app that needs OTA\n(over the air update) capability.", + "id": "PARTITION_TABLE_SINGLE_APP_LARGE", + "name": "PARTITION_TABLE_SINGLE_APP_LARGE", + "range": null, + "title": "Single factory app (large), no OTA", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": "This is a basic OTA-enabled partition table with a factory app\npartition plus two OTA app partitions. All are 1MB, so this\npartition table requires 4MB or larger flash size.\n\nThe corresponding CSV file in the IDF directory is\ncomponents/partition_table/partitions_two_ota.csv", + "id": "PARTITION_TABLE_TWO_OTA", + "name": "PARTITION_TABLE_TWO_OTA", + "range": null, + "title": "Factory app, two OTA definitions", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": "This is a basic OTA-enabled partition table with\ntwo OTA app partitions. Both app partition sizes are 1700K,\nso this partition table requires 4MB or larger flash size.\n\nThe corresponding CSV file in the IDF directory is\ncomponents/partition_table/partitions_two_ota_large.csv", + "id": "PARTITION_TABLE_TWO_OTA_LARGE", + "name": "PARTITION_TABLE_TWO_OTA_LARGE", + "range": null, + "title": "Two large size OTA partitions", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": "Specify the path to the partition table CSV to use for your project.\n\nConsult the Partition Table section in the ESP-IDF Programmers Guide\nfor more information.", + "id": "PARTITION_TABLE_CUSTOM", + "name": "PARTITION_TABLE_CUSTOM", + "range": null, + "title": "Custom partition table CSV", + "type": "bool" + }, + { + "children": [], + "depends_on": "!ESP32_COREDUMP_ENABLE_TO_FLASH && NVS_SEC_KEY_PROTECT_USING_FLASH_ENC && ", + "help": "This is a variation of the default \"Single factory app, no OTA\" partition table\nthat supports encrypted NVS when using flash encryption. See the Flash Encryption section\nin the ESP-IDF Programmers Guide for more information.\n\nThe corresponding CSV file in the IDF directory is\ncomponents/partition_table/partitions_singleapp_encr_nvs.csv", + "id": "PARTITION_TABLE_SINGLE_APP_ENCRYPTED_NVS", + "name": "PARTITION_TABLE_SINGLE_APP_ENCRYPTED_NVS", + "range": null, + "title": "Single factory app, no OTA, encrypted NVS", + "type": "bool" + }, + { + "children": [], + "depends_on": "!ESP32_COREDUMP_ENABLE_TO_FLASH && NVS_SEC_KEY_PROTECT_USING_FLASH_ENC && ", + "help": "This is a variation of the \"Single factory app (large), no OTA\" partition table\nthat supports encrypted NVS when using flash encryption. See the Flash Encryption section\nin the ESP-IDF Programmers Guide for more information.\n\nThe corresponding CSV file in the IDF directory is\ncomponents/partition_table/partitions_singleapp_large_encr_nvs.csv", + "id": "PARTITION_TABLE_SINGLE_APP_LARGE_ENC_NVS", + "name": "PARTITION_TABLE_SINGLE_APP_LARGE_ENC_NVS", + "range": null, + "title": "Single factory app (large), no OTA, encrypted NVS", + "type": "bool" + }, + { + "children": [], + "depends_on": "!ESP_COREDUMP_ENABLE_TO_FLASH && NVS_SEC_KEY_PROTECT_USING_FLASH_ENC && ", + "help": "This is a variation of the \"Factory app, two OTA definitions\" partition table\nthat supports encrypted NVS when using flash encryption. See the Flash Encryption section\nin the ESP-IDF Programmers Guide for more information.\n\nThe corresponding CSV file in the IDF directory is\ncomponents/partition_table/partitions_two_ota_encr_nvs.csv", + "id": "PARTITION_TABLE_TWO_OTA_ENCRYPTED_NVS", + "name": "PARTITION_TABLE_TWO_OTA_ENCRYPTED_NVS", + "range": null, + "title": "Factory app, two OTA definitions, encrypted NVS", + "type": "bool" + } + ], + "depends_on": null, + "help": "The partition table to flash to the ESP32. The partition table\ndetermines where apps, data and other resources are expected to\nbe found.\n\nThe predefined partition table CSV descriptions can be found\nin the components/partition_table directory. These are mostly intended\nfor example and development use, it's expect that for production use you\nwill copy one of these CSV files and create a custom partition CSV for\nyour application.", + "id": "partition-table-partition-table", + "name": "PARTITION_TABLE_TYPE", + "title": "Partition Table", + "type": "choice" + }, + { + "children": [], + "depends_on": null, + "help": "Name of the custom partition CSV filename.\nThis path is evaluated relative to the project root directory by default.\nHowever, if the absolute path for the CSV file is provided, then the absolute path is configured.", + "id": "PARTITION_TABLE_CUSTOM_FILENAME", + "name": "PARTITION_TABLE_CUSTOM_FILENAME", + "range": null, + "title": "Custom partition CSV file", + "type": "string" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "PARTITION_TABLE_FILENAME", + "name": "PARTITION_TABLE_FILENAME", + "range": null, + "title": null, + "type": "string" + }, + { + "children": [], + "depends_on": null, + "help": "The address of partition table (by default 0x8000).\nAllows you to move the partition table, it gives more space for the bootloader.\nNote that the bootloader and app will both need to be compiled with the same PARTITION_TABLE_OFFSET value.\n\nThis number should be a multiple of 0x1000.\n\nNote that partition offsets in the partition table CSV file may need to be changed if this value is set to\na higher value. To have each partition offset adapt to the configured partition table offset, leave all\npartition offsets blank in the CSV file.", + "id": "PARTITION_TABLE_OFFSET", + "name": "PARTITION_TABLE_OFFSET", + "range": null, + "title": "Offset of partition table", + "type": "hex" + }, + { + "children": [], + "depends_on": "!APP_COMPATIBLE_PRE_V3_1_BOOTLOADERS && !IDF_TARGET_LINUX", + "help": "Generate an MD5 checksum for the partition table for protecting the\nintegrity of the table. The generation should be turned off for legacy\nbootloaders which cannot recognize the MD5 checksum in the partition\ntable.", + "id": "PARTITION_TABLE_MD5", + "name": "PARTITION_TABLE_MD5", + "range": null, + "title": "Generate an MD5 checksum for the partition table", + "type": "bool" + } + ], + "depends_on": null, + "id": "partition-table", + "title": "Partition Table", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": null, + "help": "GPIO number on which the \"Boot\" button is connected. This is generally used\nby the application for custom operations like toggling states, resetting to defaults, etc.", + "id": "EXAMPLE_BOARD_BUTTON_GPIO", + "name": "EXAMPLE_BOARD_BUTTON_GPIO", + "range": null, + "title": "Boot Button GPIO", + "type": "int" + } + ], + "depends_on": null, + "id": "example-configuration", + "title": "Example Configuration", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": null, + "help": "Show the QR code for provisioning.", + "id": "APP_NETWORK_PROV_SHOW_QR", + "name": "APP_NETWORK_PROV_SHOW_QR", + "range": null, + "title": "Show provisioning QR code", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Set the maximum wrong pop attempts allowed before stopping provisioning.\nSet 0 for the feature to be disabled.\nThis safeguards the device from brute-force attempt by limiting the wrong pop allowed.\nNeeds IDF version >= 5.1.3", + "id": "APP_NETWORK_PROV_MAX_POP_MISMATCH", + "name": "APP_NETWORK_PROV_MAX_POP_MISMATCH", + "range": [ + 0, + 20 + ], + "title": "Max wrong pop attempts allowed", + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "!IDF_TARGET_ESP32H2 && ", + "help": null, + "id": "APP_NETWORK_PROV_TRANSPORT_SOFTAP", + "name": "APP_NETWORK_PROV_TRANSPORT_SOFTAP", + "range": null, + "title": "Soft AP", + "type": "bool" + }, + { + "children": [], + "depends_on": "!IDF_TARGET_ESP32S2 && ", + "help": null, + "id": "APP_NETWORK_PROV_TRANSPORT_BLE", + "name": "APP_NETWORK_PROV_TRANSPORT_BLE", + "range": null, + "title": "BLE", + "type": "bool" + } + ], + "depends_on": null, + "help": "Wi-Fi/Network provisioning component offers both, SoftAP and BLE transports. Choose any one.", + "id": "esp-rainmaker-app-wi-fi-provisioning-provisioning-transport-method", + "name": "APP_NETWORK_PROV_TRANSPORT", + "title": "Provisioning Transport method", + "type": "choice" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "APP_NETWORK_PROV_TRANSPORT", + "name": "APP_NETWORK_PROV_TRANSPORT", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "APP_NETWORK_RESET_PROV_ON_FAILURE", + "help": "Set the Maximum retry to avoid reconnecting to an inexistent network or if credentials\nare misconfigured. Provisioned credentials are erased and internal state machine\nis reset after this threshold is reached.", + "id": "APP_NETWORK_PROV_MAX_RETRY_CNT", + "name": "APP_NETWORK_PROV_MAX_RETRY_CNT", + "range": null, + "title": "Max retries before reseting provisioning state machine", + "type": "int" + } + ], + "depends_on": null, + "help": "Enable reseting provisioned credentials and state machine after session failure.\nThis will restart the provisioning service after retries are exhausted.", + "id": "APP_NETWORK_RESET_PROV_ON_FAILURE", + "name": "APP_NETWORK_RESET_PROV_ON_FAILURE", + "range": null, + "title": "Reset provisioned credentials and state machine after session failure", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Show some intro text for demos in order to help users understand more about ESP RainMaker.", + "id": "APP_NETWORK_SHOW_DEMO_INTRO_TEXT", + "name": "APP_NETWORK_SHOW_DEMO_INTRO_TEXT", + "range": null, + "title": "Show intro text for demos", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Timeout (in minutes) after which the provisioning will auto stop. A reboot will be required\nto restart provisioning. It is always recommended to set this to some non zero value, especially\nif you are not using PoP. Set to 0 if you do not want provisioning to auto stop.", + "id": "APP_NETWORK_PROV_TIMEOUT_PERIOD", + "name": "APP_NETWORK_PROV_TIMEOUT_PERIOD", + "range": null, + "title": "Provisioning Timeout", + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": "Provisioning Name Prefix.", + "id": "APP_NETWORK_PROV_NAME_PREFIX", + "name": "APP_NETWORK_PROV_NAME_PREFIX", + "range": null, + "title": "Provisioning Name Prefix", + "type": "string" + }, + { + "children": [], + "depends_on": "ESP_RMAKER_NETWORK_OVER_WIFI", + "help": "Stay compatible with Previous App Wi-Fi component", + "id": "APP_WIFI_PROV_COMPAT", + "name": "APP_WIFI_PROV_COMPAT", + "range": null, + "title": "Stay compatible with App Wi-Fi component", + "type": "bool" + } + ], + "depends_on": null, + "id": "esp-rainmaker-app-wi-fi-provisioning", + "title": "ESP RainMaker App Wi-Fi Provisioning", + "type": "menu" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "", + "help": "Do not use any claiming. The MQTT credentials need to\nbe pre-programmed for this to work. This should be used\nfor all private RainMaker deployments.", + "id": "ESP_RMAKER_NO_CLAIM", + "name": "ESP_RMAKER_NO_CLAIM", + "range": null, + "title": "Do not use Claiming", + "type": "bool" + }, + { + "children": [], + "depends_on": "!IDF_TARGET_ESP32 && !IDF_TARGET_ESP32C2 && ", + "help": "Use Self Claiming i.e. get the MQTT credentials\ndirectly from the claiming service.", + "id": "ESP_RMAKER_SELF_CLAIM", + "name": "ESP_RMAKER_SELF_CLAIM", + "range": null, + "title": "Use Self Claiming", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_ENABLED && !IDF_TARGET_ESP32S2 && ", + "help": "Use Assisted Claiming i.e. get the MQTT credentials\nfrom the claiming service via assistance from clients,\nlike the phone apps.", + "id": "ESP_RMAKER_ASSISTED_CLAIM", + "name": "ESP_RMAKER_ASSISTED_CLAIM", + "range": null, + "title": "Use Assisted Claiming", + "type": "bool" + } + ], + "depends_on": null, + "help": "Claiming type to be used.", + "id": "esp-rainmaker-config-claiming-type", + "name": "ESP_RMAKER_CLAIM_TYPE", + "title": "Claiming Type", + "type": "choice" + }, + { + "children": [ + { + "children": [], + "depends_on": "ESP_RMAKER_NO_CLAIM && ", + "help": "Enable the use of ESP Secure Certificate Manager APIs for the example.\nPlease refer to ESP Secure Certificate Manager documentation for more details.", + "id": "ESP_RMAKER_USE_ESP_SECURE_CERT_MGR", + "name": "ESP_RMAKER_USE_ESP_SECURE_CERT_MGR", + "range": null, + "title": "Use ESP Secure Certificate Manager", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": "This option expects the Private key and Device certificate to be in the NVS.\nThis is the default behaviour.", + "id": "ESP_RMAKER_USE_NVS", + "name": "ESP_RMAKER_USE_NVS", + "range": null, + "title": "Use NVS (default)", + "type": "bool" + } + ], + "depends_on": null, + "help": "ESP devices support multiple ways to secure store the PKI credentials.\nCurrently, NVS and ESP Secure Cert Manager are supported.\nThe default behaviour is to access the PKI credentials from the NVS.\nConsult the ESP-TLS documentation in ESP-IDF Programming guide for more details.", + "id": "esp-rainmaker-config-choose-pki-credentials-access-method", + "name": "ESP_RMAKER_CHOOSE_PKI_ACCESS_METHOD", + "title": "Choose PKI credentials access method", + "type": "choice" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "ESP_RMAKER_CLAIM_TYPE", + "name": "ESP_RMAKER_CLAIM_TYPE", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": "ESP_RMAKER_SELF_CLAIM", + "help": "ESP RainMaker Claiming Service Base URL.", + "id": "ESP_RMAKER_CLAIM_SERVICE_BASE_URL", + "name": "ESP_RMAKER_CLAIM_SERVICE_BASE_URL", + "range": null, + "title": "ESP RainMaker Claiming Service Base URL", + "type": "string" + }, + { + "children": [], + "depends_on": null, + "help": "Normally, if self claiming or assisted claiming is used, the MQTT Host is anyways read from\nESP_RMAKER_MQTT_HOST, independent of this config option. However, if this is set, even if\nan MQTT host value is found in NVS, it will be overriden with ESP_RMAKER_MQTT_HOST.", + "id": "ESP_RMAKER_READ_MQTT_HOST_FROM_CONFIG", + "name": "ESP_RMAKER_READ_MQTT_HOST_FROM_CONFIG", + "range": null, + "title": "Read MQTT Host from ESP_RMAKER_MQTT_HOST (Read Docs)", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "If enabled, the device will get its node id from the device certificate's CN field. If not enabled,\nit will read the node id either from nvs factory partition or mac address, depending on the configuration.", + "id": "ESP_RMAKER_READ_NODE_ID_FROM_CERT_CN", + "name": "ESP_RMAKER_READ_NODE_ID_FROM_CERT_CN", + "range": null, + "title": "Read Node ID from Device Certificate", + "type": "bool" + }, + { + "children": [], + "depends_on": "ESP_RMAKER_SELF_CLAIM || ESP_RMAKER_ASSISTED_CLAIM || ESP_RMAKER_READ_MQTT_HOST_FROM_CONFIG", + "help": "ESP RainMaker MQTT Host name.", + "id": "ESP_RMAKER_MQTT_HOST", + "name": "ESP_RMAKER_MQTT_HOST", + "range": null, + "title": "ESP RainMaker MQTT Host", + "type": "string" + }, + { + "children": [], + "depends_on": null, + "help": "This config enables the use of AWS Basic Ingest Topics for Node to Cloud communication,\nwhich eliminates the MQTT Broker and thus reduces messaging cost.", + "id": "ESP_RMAKER_MQTT_USE_BASIC_INGEST_TOPICS", + "name": "ESP_RMAKER_MQTT_USE_BASIC_INGEST_TOPICS", + "range": null, + "title": "Use Basic Ingest Topics", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "ESP_RMAKER_MQTT_ENABLE_BUDGETING", + "help": "Default MQTT budget. Budget will reduce on sending an MQTT message and increase based on\nESP_RMAKER_MQTT_BUDGET_REVIVE_PERIOD. If no budget is available, MQTT message will be dropped.", + "id": "ESP_RMAKER_MQTT_DEFAULT_BUDGET", + "name": "ESP_RMAKER_MQTT_DEFAULT_BUDGET", + "range": [ + 64, + 1024 + ], + "title": "Default MQTT Budget", + "type": "int" + }, + { + "children": [], + "depends_on": "ESP_RMAKER_MQTT_ENABLE_BUDGETING", + "help": "Maximum budget that the node can have. No additional budget will be allocated if this count is reached.", + "id": "ESP_RMAKER_MQTT_MAX_BUDGET", + "name": "ESP_RMAKER_MQTT_MAX_BUDGET", + "range": [ + 64, + 2048 + ], + "title": "Max MQTT Budget", + "type": "int" + }, + { + "children": [], + "depends_on": "ESP_RMAKER_MQTT_ENABLE_BUDGETING", + "help": "Period in seconds after which the MQTT budget should revive (by ESP_RMAKER_MQTT_BUDGET_REVIVE_COUNT).\nThis is used to limit the messages being sent by the node.", + "id": "ESP_RMAKER_MQTT_BUDGET_REVIVE_PERIOD", + "name": "ESP_RMAKER_MQTT_BUDGET_REVIVE_PERIOD", + "range": [ + 5, + 600 + ], + "title": "MQTT Budget revive period", + "type": "int" + }, + { + "children": [], + "depends_on": "ESP_RMAKER_MQTT_ENABLE_BUDGETING", + "help": "The count by which the budget will be increased periodically based on ESP_RMAKER_MQTT_BUDGET_REVIVE_PERIOD.", + "id": "ESP_RMAKER_MQTT_BUDGET_REVIVE_COUNT", + "name": "ESP_RMAKER_MQTT_BUDGET_REVIVE_COUNT", + "range": [ + 1, + 16 + ], + "title": "MQTT Budget revive count", + "type": "int" + } + ], + "depends_on": null, + "help": "Enable MQTT budgeting, which will control the number of MQTT messages sent by the node.", + "id": "ESP_RMAKER_MQTT_ENABLE_BUDGETING", + "name": "ESP_RMAKER_MQTT_ENABLE_BUDGETING", + "range": null, + "title": "Enable MQTT budgeting", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Maximum size of the payload for reporting parameter values.", + "id": "ESP_RMAKER_MAX_PARAM_DATA_SIZE", + "name": "ESP_RMAKER_MAX_PARAM_DATA_SIZE", + "range": [ + 64, + 8192 + ], + "title": "Maximum Parameters' data size", + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": "The handlers for User Node Mapping are now registered internally by ESP RainMaker core,\nby registering to appropriate Wi-Fi Provisioning events. If your application code also\nhas the calls to create and register the user mapping handlers, enable this config\noption to prevent duplication.", + "id": "ESP_RMAKER_DISABLE_USER_MAPPING_PROV", + "name": "ESP_RMAKER_DISABLE_USER_MAPPING_PROV", + "range": null, + "title": "Disable User Mapping during Provisioning", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "This enables the additional user id checks during user node mapping. Whenever a new user\nid is received, it is checked against the existing user id in NVS. If there is a mismatch,\nor if no user id exists in NVS, this is considered as a reset state and the same is reported\nto the ESP RainMaker Cloud during the User Node association MQTT Publish so that the cloud\ncan take appropriate action w.r.t user permissions. It is recommended to enable this option\nfor security reasons.", + "id": "ESP_RMAKER_USER_ID_CHECK", + "name": "ESP_RMAKER_USER_ID_CHECK", + "range": null, + "title": "User id check for User Node mapping", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "By default, the \"Name\" parameter (esp.param.name) changes are handled internally. If Applications\nwant to handle this themselves, this config option can be enabled. Please ensure that you update\nand report the name parameter in your callback so that it reflects correctly everywhere.\nIf no device callback is registered, the name paramater will be handled internally.", + "id": "RMAKER_NAME_PARAM_CB", + "name": "RMAKER_NAME_PARAM_CB", + "range": null, + "title": "Call device callback for Name param", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Enabling this allows to discover and control the node over local Wi-Fi network.\nNote that this uses only Wi-Fi level security and so, any client on the same\nWi-Fi network can potentially control the node. The communication is not encrypted\nand uses plain HTTP. Please Check the RainMaker documentation for additional details.\nNote that enabling this just means that the APIs to enable/disable local\ncontrol will be compiled in and can be used in application code. If CONFIG_ESP_RMAKER_LOCAL_CTRL_AUTO_ENABLE\nis also enabled, then no additional APIs are required for actually enabling local control.", + "id": "ESP_RMAKER_LOCAL_CTRL_FEATURE_ENABLE", + "name": "ESP_RMAKER_LOCAL_CTRL_FEATURE_ENABLE", + "range": null, + "title": "ESP RainMaker Local Control Feature", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Automatically enabled local control when RainMaker starts.", + "id": "ESP_RMAKER_LOCAL_CTRL_AUTO_ENABLE", + "name": "ESP_RMAKER_LOCAL_CTRL_AUTO_ENABLE", + "range": null, + "title": "Auto ESP RainMaker Local Control", + "type": "bool" + }, + { + "children": [], + "depends_on": "ESP_RMAKER_LOCAL_CTRL_FEATURE_ENABLE", + "help": "The port number to be used for http for local control.", + "id": "ESP_RMAKER_LOCAL_CTRL_HTTP_PORT", + "name": "ESP_RMAKER_LOCAL_CTRL_HTTP_PORT", + "range": null, + "title": "Local Control HTTP Port", + "type": "int" + }, + { + "children": [], + "depends_on": "ESP_RMAKER_LOCAL_CTRL_FEATURE_ENABLE", + "help": "The task stack size to be used for http server for local control.", + "id": "ESP_RMAKER_LOCAL_CTRL_STACK_SIZE", + "name": "ESP_RMAKER_LOCAL_CTRL_STACK_SIZE", + "range": null, + "title": "Local Control HTTP Server task stack size", + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "ESP_RMAKER_LOCAL_CTRL_SECURITY_0", + "name": "ESP_RMAKER_LOCAL_CTRL_SECURITY_0", + "range": null, + "title": "sec0", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "ESP_RMAKER_LOCAL_CTRL_SECURITY_1", + "name": "ESP_RMAKER_LOCAL_CTRL_SECURITY_1", + "range": null, + "title": "sec1", + "type": "bool" + } + ], + "depends_on": "ESP_RMAKER_LOCAL_CTRL_FEATURE_ENABLE", + "help": "Security type to be selected for local control.", + "id": "esp-rainmaker-config-local-control-security-type", + "name": "ESP_RMAKER_LOCAL_CTRL_SECURITY", + "title": "Local Control Security Type", + "type": "choice" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "ESP_RMAKER_LOCAL_CTRL_SECURITY", + "name": "ESP_RMAKER_LOCAL_CTRL_SECURITY", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": "ESP_RMAKER_LOCAL_CTRL_FEATURE_ENABLE && ESP_RMAKER_NETWORK_OVER_THREAD", + "help": "This parameter defines, in seconds, how long a Thread Border Router waits before removing an SRP service\nafter the Thread End Device powers off. To minimize unnecessary packet exchanges, we set the lease interval\nto 180 seconds (3 minutes) by default.", + "id": "ESP_RMAKER_LOCAL_CTRL_LEASE_INTERVAL_SECONDS", + "name": "ESP_RMAKER_LOCAL_CTRL_LEASE_INTERVAL_SECONDS", + "range": null, + "title": "Local Control SRP Service Lease Interval (Seconds)", + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "ESP_RMAKER_CONSOLE_UART_NUM_0", + "name": "ESP_RMAKER_CONSOLE_UART_NUM_0", + "range": null, + "title": "UART0", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "ESP_RMAKER_CONSOLE_UART_NUM_1", + "name": "ESP_RMAKER_CONSOLE_UART_NUM_1", + "range": null, + "title": "UART1", + "type": "bool" + } + ], + "depends_on": null, + "help": "UART to be selected for serial console.", + "id": "esp-rainmaker-config-uart-for-console-input", + "name": "ESP_RMAKER_CONSOLE_UART_NUM", + "title": "UART for console input", + "type": "choice" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "ESP_RMAKER_CONSOLE_UART_NUM", + "name": "ESP_RMAKER_CONSOLE_UART_NUM", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": "Use Certificate Bundle for server authentication. Enabling this is recommended to safeguard\nagainst any changes in the server certificates in future. This has an impact on the binary\nsize as well as heap requirement.", + "id": "ESP_RMAKER_USE_CERT_BUNDLE", + "name": "ESP_RMAKER_USE_CERT_BUNDLE", + "range": null, + "title": "Use Certificate Bundle", + "type": "bool" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "ESP_RMAKER_OTA_AUTOFETCH", + "help": "Periodically send an OTA fetch request. If set to 0, the request will be sent only once,\nwhen the node connects to the ESP RainMaker Cloud first time after a boot.\nElse, this defines the period (in hours) for the periodic fetch request.", + "id": "ESP_RMAKER_OTA_AUTOFETCH_PERIOD", + "name": "ESP_RMAKER_OTA_AUTOFETCH_PERIOD", + "range": [ + 0, + 168 + ], + "title": "OTA Auto Fetch Period", + "type": "int" + } + ], + "depends_on": null, + "help": "Applicable only for OTA using Topics.\nFetch the OTA (i.e. get the URL and other details) by actively sending an\nOTA fetch request to ESP RainMaker Cloud. If this is disabled, the node\nwill stay subscribed to the OTA Topics, but will get the information only\nif someone explicitly triggers it.", + "id": "ESP_RMAKER_OTA_AUTOFETCH", + "name": "ESP_RMAKER_OTA_AUTOFETCH", + "range": null, + "title": "Auto Fetch OTA", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "This allows you to skip the validation of OTA server certificate CN field.", + "id": "ESP_RMAKER_SKIP_COMMON_NAME_CHECK", + "name": "ESP_RMAKER_SKIP_COMMON_NAME_CHECK", + "range": null, + "title": "Skip server certificate CN field check", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "This allows you to skip the firmware version check. Useful during development,\nbut not for production.", + "id": "ESP_RMAKER_SKIP_VERSION_CHECK", + "name": "ESP_RMAKER_SKIP_VERSION_CHECK", + "range": null, + "title": "Skip firmware version check", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "This allows you to skip the secure version check. Useful during development,\nbut not for production. Check out ESP IDF's Anti-rollback feature for more details.", + "id": "ESP_RMAKER_SKIP_SECURE_VERSION_CHECK", + "name": "ESP_RMAKER_SKIP_SECURE_VERSION_CHECK", + "range": null, + "title": "Skip secure version check", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "This allows you to skip the project name check.", + "id": "ESP_RMAKER_SKIP_PROJECT_NAME_CHECK", + "name": "ESP_RMAKER_SKIP_PROJECT_NAME_CHECK", + "range": null, + "title": "Skip project name check", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Increasing this value beyond the default would speed up the OTA download process.\nHowever, please ensure that your application has enough memory headroom to allow this,\nelse, the OTA may fail.", + "id": "ESP_RMAKER_OTA_HTTP_RX_BUFFER_SIZE", + "name": "ESP_RMAKER_OTA_HTTP_RX_BUFFER_SIZE", + "range": [ + 512, + 5760 + ], + "title": "OTA HTTP receive buffer size", + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": "After an OTA Update, if CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE is set, then the firmware will wait for MQTT\nconnection to mark the new firmware as valid. However, if it is not able to do so within\nthis wait period (in seconds), the firmware will be marked as invalid and the older\nfirmware will be booted into.", + "id": "ESP_RMAKER_OTA_ROLLBACK_WAIT_PERIOD", + "name": "ESP_RMAKER_OTA_ROLLBACK_WAIT_PERIOD", + "range": [ + 30, + 600 + ], + "title": "OTA Rollback Wait Period (Seconds)", + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": "After OTA image is flashed and active partition changed, the device automatically reboots. To disable this\nbehaviour and handle reboot on your own, based on RMAKER_OTA event, enable this option.", + "id": "ESP_RMAKER_OTA_DISABLE_AUTO_REBOOT", + "name": "ESP_RMAKER_OTA_DISABLE_AUTO_REBOOT", + "range": null, + "title": "Disable auto reboot", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "OTA Jobs can include additional metadata for time to indicate a range of valid date and the time within\nthose dates. Eg. Perform OTA between 1 Dec 2022 and 10 Dec 2022 that too only between 2:00am and 5:00am.\nIf you want to ignore this, disable this option.", + "id": "ESP_RMAKER_OTA_TIME_SUPPORT", + "name": "ESP_RMAKER_OTA_TIME_SUPPORT", + "range": null, + "title": "Enable OTA Time Support", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "ESP_RMAKER_OTA_PROGRESS_SUPPORT", + "help": "If you set the reported upgrade progress interval to 10, it will report 10% of the progress every time 10%\nof the firmware is downloaded, range from 10%, 20%, 30% until 90%. For example, when downloaded 10% firmware size,\nthe ota_status is OTA_STATUS_IN_PROGRESS and the additional_info is `Downloaded 10% Firmware Image`.\nThe additional_info `Downloading Firmware Image` is 0% progress and `Firmware Image download complete` is 100% progress.", + "id": "ESP_RMAKER_OTA_PROGRESS_INTERVAL", + "name": "ESP_RMAKER_OTA_PROGRESS_INTERVAL", + "range": null, + "title": "OTA Progress Interval (%)", + "type": "int" + } + ], + "depends_on": null, + "help": "When the device do OTA, it will report upgrade progress to cloud. If the APP need show the progress bar,\nplease enable it and APP can get the progress value in additional_info by API ota_status.", + "id": "ESP_RMAKER_OTA_PROGRESS_SUPPORT", + "name": "ESP_RMAKER_OTA_PROGRESS_SUPPORT", + "range": null, + "title": "Enable OTA Progress Support", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Maximum number of times the device will retry OTA download on failure before giving up.", + "id": "ESP_RMAKER_OTA_MAX_RETRIES", + "name": "ESP_RMAKER_OTA_MAX_RETRIES", + "range": [ + 1, + 10 + ], + "title": "Maximum OTA Retry Attempts", + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": "Delay (in minutes) before re-fetching OTA details after all retry attempts fail (for OTA using topics).", + "id": "ESP_RMAKER_OTA_RETRY_DELAY_MINUTES", + "name": "ESP_RMAKER_OTA_RETRY_DELAY_MINUTES", + "range": [ + 1, + 60 + ], + "title": "OTA Retry Delay (Minutes)", + "type": "int" + } + ], + "depends_on": null, + "id": "esp-rainmaker-config-esp-rainmaker-ota-config", + "title": "ESP RainMaker OTA Config", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": null, + "help": "Maximum Number of schedules allowed. The json size for report params increases as the number of schedules increases.", + "id": "ESP_RMAKER_SCHEDULING_MAX_SCHEDULES", + "name": "ESP_RMAKER_SCHEDULING_MAX_SCHEDULES", + "range": [ + 1, + 50 + ], + "title": "Maximum schedules", + "type": "int" + } + ], + "depends_on": null, + "id": "esp-rainmaker-config-esp-rainmaker-scheduling", + "title": "ESP RainMaker Scheduling", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": null, + "help": "Maximum Number of scenes allowed. The json size for report params increases as the number of scenes increases.", + "id": "ESP_RMAKER_SCENES_MAX_SCENES", + "name": "ESP_RMAKER_SCENES_MAX_SCENES", + "range": [ + 1, + 50 + ], + "title": "Maximum scenes", + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": "This enables the deactivate callback support. The application callback will be invoked with the source\nset to ESP_RMAKER_REQ_SRC_SCENE_DEACTIVATE when the deactivate operation is received. However, the\nparam values would be the same as those for activate, since the RainMaker core does not know what the\nexpected values are for scene deactivation.", + "id": "ESP_RMAKER_SCENES_DEACTIVATE_SUPPORT", + "name": "ESP_RMAKER_SCENES_DEACTIVATE_SUPPORT", + "range": null, + "title": "Enable Deactivate support", + "type": "bool" + } + ], + "depends_on": null, + "id": "esp-rainmaker-config-esp-rainmaker-scenes", + "title": "ESP RainMaker Scenes", + "type": "menu" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "ESP_RMAKER_CMD_RESP_ENABLE", + "help": "Enable testing for Command-Response module. This enables triggering commands and parsing response from the node itself,\nrather than receiving the commands from cloud. C API or the serial console can be used to trigger the commands.\nThis should be enabled only while testing commands, but should always be disabled in production firmware.", + "id": "ESP_RMAKER_CMD_RESP_TEST_ENABLE", + "name": "ESP_RMAKER_CMD_RESP_TEST_ENABLE", + "range": null, + "title": "Enable Command-Response Testing", + "type": "bool" + } + ], + "depends_on": null, + "help": "Enable the ESP RainMaker Command-Response module for semi-synchronous communication. Please refer the RainMaker documents\nfor additional information.", + "id": "ESP_RMAKER_CMD_RESP_ENABLE", + "name": "ESP_RMAKER_CMD_RESP_ENABLE", + "range": null, + "title": "Enable Command-Response Module", + "type": "bool" + } + ], + "depends_on": null, + "id": "esp-rainmaker-config-esp-rainmaker-command-response", + "title": "ESP RainMaker Command-Response", + "type": "menu" + }, + { + "children": [], + "depends_on": null, + "help": "RainMaker will use network_provisioning component to provision a device to a Wi-Fi/Thread network if enabling this option.\nIf the option is not enabled, it will use wifi_provisioning instead. This option only works when IDF verson is later than\nv5.1.", + "id": "ESP_RMAKER_USING_NETWORK_PROV", + "name": "ESP_RMAKER_USING_NETWORK_PROV", + "range": null, + "title": "Using Network Provisioning", + "type": "bool" + } + ], + "depends_on": null, + "id": "esp-rainmaker-config", + "title": "ESP RainMaker Config", + "type": "menu" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "COMPILER_OPTIMIZATION_DEBUG", + "name": "COMPILER_OPTIMIZATION_DEBUG", + "range": null, + "title": "Debug (-Og)", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "COMPILER_OPTIMIZATION_SIZE", + "name": "COMPILER_OPTIMIZATION_SIZE", + "range": null, + "title": "Optimize for size (-Os with GCC, -Oz with Clang)", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "COMPILER_OPTIMIZATION_PERF", + "name": "COMPILER_OPTIMIZATION_PERF", + "range": null, + "title": "Optimize for performance (-O2)", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "COMPILER_OPTIMIZATION_NONE", + "name": "COMPILER_OPTIMIZATION_NONE", + "range": null, + "title": "Debug without optimization (-O0)", + "type": "bool" + } + ], + "depends_on": null, + "help": "This option sets compiler optimization level (gcc -O argument) for the app.\n\n- The \"Debug\" setting will add the -Og flag to CFLAGS.\n- The \"Size\" setting will add the -Os flag to CFLAGS (-Oz with Clang).\n- The \"Performance\" setting will add the -O2 flag to CFLAGS.\n- The \"None\" setting will add the -O0 flag to CFLAGS.\n\nThe \"Size\" setting cause the compiled code to be smaller and faster, but\nmay lead to difficulties of correlating code addresses to source file\nlines when debugging.\n\nThe \"Performance\" setting causes the compiled code to be larger and faster,\nbut will be easier to correlated code addresses to source file lines.\n\n\"None\" with -O0 produces compiled code without optimization.\n\nNote that custom optimization levels may be unsupported.\n\nCompiler optimization for the IDF bootloader is set separately,\nsee the BOOTLOADER_COMPILER_OPTIMIZATION setting.", + "id": "compiler-options-optimization-level", + "name": "COMPILER_OPTIMIZATION", + "title": "Optimization Level", + "type": "choice" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": "Enable assertions. Assertion content and line number will be printed on failure.", + "id": "COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE", + "name": "COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE", + "range": null, + "title": "Enabled", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": "Enable silent assertions. Failed assertions will abort(), user needs to\nuse the aborting address to find the line number with the failed assertion.", + "id": "COMPILER_OPTIMIZATION_ASSERTIONS_SILENT", + "name": "COMPILER_OPTIMIZATION_ASSERTIONS_SILENT", + "range": null, + "title": "Silent (saves code size)", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": "If assertions are disabled, -DNDEBUG is added to CPPFLAGS.", + "id": "COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE", + "name": "COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE", + "range": null, + "title": "Disabled (sets -DNDEBUG)", + "type": "bool" + } + ], + "depends_on": null, + "help": "Assertions can be:\n\n- Enabled. Failure will print verbose assertion details. This is the default.\n\n- Set to \"silent\" to save code size (failed assertions will abort() but user\n needs to use the aborting address to find the line number with the failed assertion.)\n\n- Disabled entirely (not recommended for most configurations.) -DNDEBUG is added\n to CPPFLAGS in this case.", + "id": "compiler-options-assertion-level", + "name": "COMPILER_OPTIMIZATION_ASSERTION_LEVEL", + "title": "Assertion level", + "type": "choice" + }, + { + "children": [], + "depends_on": null, + "help": "When NDEBUG is set, assert(X) will not cause code to trigger an assertion.\nWith this option set, assert(X) will still evaluate the expression X, though\nthe result will never cause an assertion. This means that if X is a function\nthen the function will be called.\n\nThis is not according to the standard, which states that the assert(X) should\nbe replaced with ((void)0) if NDEBUG is defined.\n\nIn ESP-IDF v6.0 the default behavior will change to \"no\" to be in line with the\nstandard.", + "id": "COMPILER_ASSERT_NDEBUG_EVALUATE", + "name": "COMPILER_ASSERT_NDEBUG_EVALUATE", + "range": null, + "title": "Enable the evaluation of the expression inside assert(X) when NDEBUG is set", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "COMPILER_FLOAT_LIB_FROM_GCCLIB", + "name": "COMPILER_FLOAT_LIB_FROM_GCCLIB", + "range": null, + "title": "libgcc", + "type": "bool" + }, + { + "children": [], + "depends_on": "ESP_ROM_HAS_RVFPLIB && ", + "help": null, + "id": "COMPILER_FLOAT_LIB_FROM_RVFPLIB", + "name": "COMPILER_FLOAT_LIB_FROM_RVFPLIB", + "range": null, + "title": "librvfp", + "type": "bool" + } + ], + "depends_on": null, + "help": "In the soft-fp part of libgcc, riscv version is written in C,\nand handles all edge cases in IEEE754, which makes it larger\nand performance is slow.\n\nRVfplib is an optimized RISC-V library for FP arithmetic on 32-bit\ninteger processors, for single and double-precision FP.\nRVfplib is \"fast\", but it has a few exceptions from IEEE 754 compliance.", + "id": "compiler-options-compiler-float-lib-source", + "name": "COMPILER_FLOAT_LIB_FROM", + "title": "Compiler float lib source", + "type": "choice" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "COMPILER_OPTIMIZATION_ASSERTION_LEVEL", + "name": "COMPILER_OPTIMIZATION_ASSERTION_LEVEL", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": "If enabled, the error messages will be discarded in following check macros:\n- ESP_RETURN_ON_ERROR\n- ESP_EXIT_ON_ERROR\n- ESP_RETURN_ON_FALSE\n- ESP_EXIT_ON_FALSE", + "id": "COMPILER_OPTIMIZATION_CHECKS_SILENT", + "name": "COMPILER_OPTIMIZATION_CHECKS_SILENT", + "range": null, + "title": "Disable messages in ESP_RETURN_ON_* and ESP_EXIT_ON_* macros", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "When expanding the __FILE__ and __BASE_FILE__ macros, replace paths inside ESP-IDF\nwith paths relative to the placeholder string \"IDF\", and convert paths inside the\nproject directory to relative paths.\n\nThis allows building the project with assertions or other code that embeds file paths,\nwithout the binary containing the exact path to the IDF or project directories.\n\nThis option passes -fmacro-prefix-map options to the GCC command line. To replace additional\npaths in your binaries, modify the project CMakeLists.txt file to pass custom -fmacro-prefix-map or\n-ffile-prefix-map arguments.", + "id": "COMPILER_HIDE_PATHS_MACROS", + "is_menuconfig": true, + "name": "COMPILER_HIDE_PATHS_MACROS", + "range": null, + "title": "Replace ESP-IDF and project paths in binaries", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": "COMPILER_CXX_EXCEPTIONS", + "help": "Size (in bytes) of the emergency memory pool for C++ exceptions. This pool will be used to allocate\nmemory for thrown exceptions when there is not enough memory on the heap.", + "id": "COMPILER_CXX_EXCEPTIONS_EMG_POOL_SIZE", + "name": "COMPILER_CXX_EXCEPTIONS_EMG_POOL_SIZE", + "range": null, + "title": "Emergency Pool Size", + "type": "int" + } + ], + "depends_on": null, + "help": "Enabling this option compiles all IDF C++ files with exception support enabled.\n\nDisabling this option disables C++ exception support in all compiled files, and any libstdc++ code\nwhich throws an exception will abort instead.\n\nEnabling this option currently adds an additional ~500 bytes of heap overhead\nwhen an exception is thrown in user code for the first time.", + "id": "COMPILER_CXX_EXCEPTIONS", + "is_menuconfig": true, + "name": "COMPILER_CXX_EXCEPTIONS", + "range": null, + "title": "Enable C++ exceptions", + "type": "menu" + }, + { + "children": [], + "depends_on": null, + "help": "Enabling this option compiles all C++ files with RTTI support enabled.\nThis increases binary size (typically by tens of kB) but allows using\ndynamic_cast conversion and typeid operator.", + "id": "COMPILER_CXX_RTTI", + "name": "COMPILER_CXX_RTTI", + "range": null, + "title": "Enable C++ run-time type info (RTTI)", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "COMPILER_STACK_CHECK_MODE_NONE", + "name": "COMPILER_STACK_CHECK_MODE_NONE", + "range": null, + "title": "None", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "COMPILER_STACK_CHECK_MODE_NORM", + "name": "COMPILER_STACK_CHECK_MODE_NORM", + "range": null, + "title": "Normal", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "COMPILER_STACK_CHECK_MODE_STRONG", + "name": "COMPILER_STACK_CHECK_MODE_STRONG", + "range": null, + "title": "Strong", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "COMPILER_STACK_CHECK_MODE_ALL", + "name": "COMPILER_STACK_CHECK_MODE_ALL", + "range": null, + "title": "Overall", + "type": "bool" + } + ], + "depends_on": null, + "help": "Stack smashing protection mode. Emit extra code to check for buffer overflows, such as stack\nsmashing attacks. This is done by adding a guard variable to functions with vulnerable objects.\nThe guards are initialized when a function is entered and then checked when the function exits.\nIf a guard check fails, program is halted. Protection has the following modes:\n\n- In NORMAL mode (GCC flag: -fstack-protector) only functions that call alloca, and functions with\n buffers larger than 8 bytes are protected.\n\n- STRONG mode (GCC flag: -fstack-protector-strong) is like NORMAL, but includes additional functions\n to be protected -- those that have local array definitions, or have references to local frame\n addresses.\n\n- In OVERALL mode (GCC flag: -fstack-protector-all) all functions are protected.\n\nModes have the following impact on code performance and coverage:\n\n- performance: NORMAL > STRONG > OVERALL\n\n- coverage: NORMAL < STRONG < OVERALL\n\nThe performance impact includes increasing the amount of stack memory required for each task.", + "id": "compiler-options-stack-smashing-protection-mode", + "name": "COMPILER_STACK_CHECK_MODE", + "title": "Stack smashing protection mode", + "type": "choice" + }, + { + "children": [], + "depends_on": null, + "help": "Stack smashing protection.", + "id": "COMPILER_STACK_CHECK", + "name": "COMPILER_STACK_CHECK", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": "IDF_TOOLCHAIN_GCC", + "help": "Disable merging identical constants (string/floating-point) across compilation units.\nThis helps in better size analysis of the application binary as the rodata section\ndistribution is more uniform across libraries. On downside, it may increase\nthe binary size and hence should be used during development phase only.", + "id": "COMPILER_NO_MERGE_CONSTANTS", + "name": "COMPILER_NO_MERGE_CONSTANTS", + "range": null, + "title": "Disable merging const sections", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Adds -Wwrite-strings flag for the C/C++ compilers.\n\nFor C, this gives string constants the type ``const char[]`` so that\ncopying the address of one into a non-const ``char *`` pointer\nproduces a warning. This warning helps to find at compile time code\nthat tries to write into a string constant.\n\nFor C++, this warns about the deprecated conversion from string\nliterals to ``char *``.", + "id": "COMPILER_WARN_WRITE_STRINGS", + "name": "COMPILER_WARN_WRITE_STRINGS", + "range": null, + "title": "Enable -Wwrite-strings warning flag", + "type": "bool" + }, + { + "children": [], + "depends_on": "IDF_TARGET_ARCH_RISCV", + "help": "Adds -msave-restore to C/C++ compilation flags.\n\nWhen this flag is enabled, compiler will call library functions to\nsave/restore registers in function prologues/epilogues. This results\nin lower overall code size, at the expense of slightly reduced performance.\n\nThis option can be enabled for RISC-V targets only.", + "id": "COMPILER_SAVE_RESTORE_LIBCALLS", + "name": "COMPILER_SAVE_RESTORE_LIBCALLS", + "range": null, + "title": "Enable -msave-restore flag to reduce code size", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Enable this option if you do not want default warnings to be considered as errors,\nespecially when updating IDF.\n\nThis is a temporary flag that could help to allow upgrade while having\nsome time to address the warnings raised by those default warnings.\nAlternatives are:\n1) fix code (preferred),\n2) remove specific warnings,\n3) do not consider specific warnings as error.", + "id": "COMPILER_DISABLE_DEFAULT_ERRORS", + "name": "COMPILER_DISABLE_DEFAULT_ERRORS", + "range": null, + "title": "Disable errors for default warnings", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Enable this option if use GCC 12 or newer, and want to disable warnings which don't appear with\nGCC 11.", + "id": "COMPILER_DISABLE_GCC12_WARNINGS", + "name": "COMPILER_DISABLE_GCC12_WARNINGS", + "range": null, + "title": "Disable new warnings introduced in GCC 12", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Enable this option if use GCC 13 or newer, and want to disable warnings which don't appear with\nGCC 12.", + "id": "COMPILER_DISABLE_GCC13_WARNINGS", + "name": "COMPILER_DISABLE_GCC13_WARNINGS", + "range": null, + "title": "Disable new warnings introduced in GCC 13", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Enable this option if use GCC 14 or newer, and want to disable warnings which don't appear with\nGCC 13.", + "id": "COMPILER_DISABLE_GCC14_WARNINGS", + "name": "COMPILER_DISABLE_GCC14_WARNINGS", + "range": null, + "title": "Disable new warnings introduced in GCC 14", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "If enabled, RTL files will be produced during compilation. These files\ncan be used by other tools, for example to calculate call graphs.", + "id": "COMPILER_DUMP_RTL_FILES", + "name": "COMPILER_DUMP_RTL_FILES", + "range": null, + "title": "Dump RTL files during compilation", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "!IDF_TARGET_LINUX && ", + "help": null, + "id": "COMPILER_RT_LIB_GCCLIB", + "name": "COMPILER_RT_LIB_GCCLIB", + "range": null, + "title": "libgcc", + "type": "bool" + }, + { + "children": [], + "depends_on": "IDF_TOOLCHAIN_CLANG && !IDF_TARGET_LINUX && ", + "help": null, + "id": "COMPILER_RT_LIB_CLANGRT", + "name": "COMPILER_RT_LIB_CLANGRT", + "range": null, + "title": "libclang_rt", + "type": "bool" + }, + { + "children": [], + "depends_on": "IDF_TARGET_LINUX && ", + "help": null, + "id": "COMPILER_RT_LIB_HOST", + "name": "COMPILER_RT_LIB_HOST", + "range": null, + "title": "Host", + "type": "bool" + } + ], + "depends_on": null, + "help": "Select runtime library to be used by compiler.\n- GCC toolchain supports libgcc only.\n- Clang allows to choose between libgcc or libclang_rt.\n- For host builds (\"linux\" target), uses the default library.", + "id": "compiler-options-compiler-runtime-library", + "name": "COMPILER_RT_LIB", + "title": "Compiler runtime library", + "type": "choice" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "COMPILER_RT_LIB_NAME", + "name": "COMPILER_RT_LIB_NAME", + "range": null, + "title": null, + "type": "string" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": "Places orphan sections with a warning message.", + "id": "COMPILER_ORPHAN_SECTIONS_WARNING", + "name": "COMPILER_ORPHAN_SECTIONS_WARNING", + "range": null, + "title": "Place with warning", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": "Places orphan sections without a warning/error message.", + "id": "COMPILER_ORPHAN_SECTIONS_PLACE", + "name": "COMPILER_ORPHAN_SECTIONS_PLACE", + "range": null, + "title": "Place silently", + "type": "bool" + } + ], + "depends_on": "!IDF_TARGET_LINUX", + "help": "If the linker finds orphan sections, it attempts to place orphan sections after sections of the same\nattribute such as code vs data, loadable vs non-loadable, etc.\nThat means that orphan sections could placed between sections defined in IDF linker scripts.\nThis could lead to corruption of the binary image. Configure the linker action here.", + "id": "compiler-options-orphan-sections-handling", + "name": "COMPILER_ORPHAN_SECTIONS", + "title": "Orphan sections handling", + "type": "choice" + }, + { + "children": [], + "depends_on": "IDF_TOOLCHAIN_GCC", + "help": "Enable compiler static analyzer. This may produce false-positive results and increases compile time.", + "id": "COMPILER_STATIC_ANALYZER", + "name": "COMPILER_STATIC_ANALYZER", + "range": null, + "title": "Enable compiler static analyzer", + "type": "bool" + } + ], + "depends_on": null, + "id": "compiler-options", + "title": "Compiler options", + "type": "menu" + }, + { + "children": [ + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "APPTRACE_DEST_JTAG", + "name": "APPTRACE_DEST_JTAG", + "range": null, + "title": "JTAG", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "APPTRACE_DEST_NONE", + "name": "APPTRACE_DEST_NONE", + "range": null, + "title": "None", + "type": "bool" + } + ], + "depends_on": null, + "help": "Select destination for application trace: JTAG or none (to disable).", + "id": "component-config-application-level-tracing-data-destination-1", + "name": "APPTRACE_DESTINATION1", + "title": "Data Destination 1", + "type": "choice" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "APPTRACE_DEST_UART", + "name": "APPTRACE_DEST_UART", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "APPTRACE_DEST_UART_NOUSB", + "name": "APPTRACE_DEST_UART_NOUSB", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "ESP_CONSOLE_UART_NUM != 0 && ", + "help": null, + "id": "APPTRACE_DEST_UART0", + "name": "APPTRACE_DEST_UART0", + "range": null, + "title": "UART0", + "type": "bool" + }, + { + "children": [], + "depends_on": "ESP_CONSOLE_UART_NUM != 1 && ", + "help": null, + "id": "APPTRACE_DEST_UART1", + "name": "APPTRACE_DEST_UART1", + "range": null, + "title": "UART1", + "type": "bool" + }, + { + "children": [], + "depends_on": "ESP_CONSOLE_UART_NUM != 2 && SOC_UART_NUM > 2 && ", + "help": null, + "id": "APPTRACE_DEST_UART2", + "name": "APPTRACE_DEST_UART2", + "range": null, + "title": "UART2", + "type": "bool" + }, + { + "children": [], + "depends_on": "!ESP_CONSOLE_USB_CDC && (IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S3) && !USB_ENABLED && ", + "help": null, + "id": "APPTRACE_DEST_USB_CDC", + "name": "APPTRACE_DEST_USB_CDC", + "range": null, + "title": "USB_CDC", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "APPTRACE_DEST_UART_NONE", + "name": "APPTRACE_DEST_UART_NONE", + "range": null, + "title": "None", + "type": "bool" + } + ], + "depends_on": null, + "help": "Select destination for application trace: UART(XX) or none (to disable).", + "id": "component-config-application-level-tracing-data-destination-2", + "name": "APPTRACE_DESTINATION2", + "title": "Data Destination 2", + "type": "choice" + }, + { + "children": [], + "depends_on": "APPTRACE_DEST_UART_NOUSB", + "help": "This GPIO is used for UART TX pin.", + "id": "APPTRACE_UART_TX_GPIO", + "name": "APPTRACE_UART_TX_GPIO", + "range": null, + "title": "UART TX on GPIO", + "type": "int" + }, + { + "children": [], + "depends_on": "APPTRACE_DEST_UART_NOUSB", + "help": "This GPIO is used for UART RX pin.", + "id": "APPTRACE_UART_RX_GPIO", + "name": "APPTRACE_UART_RX_GPIO", + "range": null, + "title": "UART RX on GPIO", + "type": "int" + }, + { + "children": [], + "depends_on": "APPTRACE_DEST_UART", + "help": "This baud rate is used for UART.\n\nThe app's maximum baud rate depends on the UART clock source. If Power Management is disabled,\nthe UART clock source is the APB clock and all baud rates in the available range will be sufficiently\naccurate. If Power Management is enabled, REF_TICK clock source is used so the baud rate is divided\nfrom 1MHz. Baud rates above 1Mbps are not possible and values between 500Kbps and 1Mbps may not be\naccurate.", + "id": "APPTRACE_UART_BAUDRATE", + "name": "APPTRACE_UART_BAUDRATE", + "range": null, + "title": "UART baud rate", + "type": "int" + }, + { + "children": [], + "depends_on": "APPTRACE_DEST_UART", + "help": "Size of the UART input ring buffer.\nThis size related to the baudrate, system tick frequency and amount of data to transfer.\nThe data placed to this buffer before sent out to the interface.", + "id": "APPTRACE_UART_RX_BUFF_SIZE", + "name": "APPTRACE_UART_RX_BUFF_SIZE", + "range": null, + "title": "UART RX ring buffer size", + "type": "int" + }, + { + "children": [], + "depends_on": "APPTRACE_DEST_UART", + "help": "Size of the UART output ring buffer.\nThis size related to the baudrate, system tick frequency and amount of data to transfer.", + "id": "APPTRACE_UART_TX_BUFF_SIZE", + "name": "APPTRACE_UART_TX_BUFF_SIZE", + "range": null, + "title": "UART TX ring buffer size", + "type": "int" + }, + { + "children": [], + "depends_on": "APPTRACE_DEST_UART", + "help": "Maximum size of the single message to transfer.", + "id": "APPTRACE_UART_TX_MSG_SIZE", + "name": "APPTRACE_UART_TX_MSG_SIZE", + "range": null, + "title": "UART TX message size", + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": "UART task priority. In case of high events rate,\nthis parameter could be changed up to (configMAX_PRIORITIES-1).", + "id": "APPTRACE_UART_TASK_PRIO", + "name": "APPTRACE_UART_TASK_PRIO", + "range": [ + 1, + 32 + ], + "title": "UART Task Priority", + "type": "int" + }, + { + "children": [], + "depends_on": "IDF_TARGET_ARCH_XTENSA && !ESP32_TRAX && !ESP32S2_TRAX && !ESP32S3_TRAX", + "help": "Enables/disable TRAX tracing HW.", + "id": "APPTRACE_DEST_TRAX", + "name": "APPTRACE_DEST_TRAX", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Enables/disable swapping memory buffers tracing protocol.", + "id": "APPTRACE_MEMBUFS_APPTRACE_PROTO_ENABLE", + "name": "APPTRACE_MEMBUFS_APPTRACE_PROTO_ENABLE", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Enables/disable application tracing module.", + "id": "APPTRACE_ENABLE", + "name": "APPTRACE_ENABLE", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Enables/disable application tracing module internal sync lock.", + "id": "APPTRACE_LOCK_ENABLE", + "name": "APPTRACE_LOCK_ENABLE", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": "APPTRACE_ENABLE", + "help": "Timeout for flushing last trace data to host in case of panic. In ms.\nUse -1 to disable timeout and wait forever.", + "id": "APPTRACE_ONPANIC_HOST_FLUSH_TMO", + "name": "APPTRACE_ONPANIC_HOST_FLUSH_TMO", + "range": null, + "title": "Timeout for flushing last trace data to host on panic", + "type": "int" + }, + { + "children": [], + "depends_on": "APPTRACE_ENABLE", + "help": "Threshold for flushing last trace data to host on panic in post-mortem mode.\nThis is minimal amount of data needed to perform flush. In bytes.", + "id": "APPTRACE_POSTMORTEM_FLUSH_THRESH", + "name": "APPTRACE_POSTMORTEM_FLUSH_THRESH", + "range": null, + "title": "Threshold for flushing last trace data to host on panic", + "type": "int" + }, + { + "children": [], + "depends_on": "APPTRACE_MEMBUFS_APPTRACE_PROTO_ENABLE && !APPTRACE_DEST_TRAX", + "help": "Size of the memory buffer for trace data in bytes.", + "id": "APPTRACE_BUF_SIZE", + "name": "APPTRACE_BUF_SIZE", + "range": null, + "title": "Size of the apptrace buffer", + "type": "int" + }, + { + "children": [], + "depends_on": "APPTRACE_MEMBUFS_APPTRACE_PROTO_ENABLE", + "help": "Size of the buffer for events in bytes. It is useful for buffering events from\nthe time critical code (scheduler, ISRs etc). If this parameter is 0 then\nevents will be discarded when main HW buffer is full.", + "id": "APPTRACE_PENDING_DATA_SIZE_MAX", + "name": "APPTRACE_PENDING_DATA_SIZE_MAX", + "range": null, + "title": "Size of the pending data buffer", + "type": "int" + }, + { + "children": [ + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "!PM_ENABLE && !APPTRACE_DEST_NONE && ", + "help": "Send SEGGER SystemView events through JTAG interface.", + "id": "APPTRACE_SV_DEST_JTAG", + "name": "APPTRACE_SV_DEST_JTAG", + "range": null, + "title": "Data destination JTAG", + "type": "bool" + }, + { + "children": [], + "depends_on": "APPTRACE_DEST_UART && ", + "help": "Send SEGGER SystemView events through UART interface.", + "id": "APPTRACE_SV_DEST_UART", + "name": "APPTRACE_SV_DEST_UART", + "range": null, + "title": "Data destination UART", + "type": "bool" + } + ], + "depends_on": "APPTRACE_SV_ENABLE && APPTRACE_ENABLE", + "help": "SystemView will transfer data through the defined interface.", + "id": "component-config-application-level-tracing-freertos-systemview-tracing-systemview-tracing-enable-systemview-destination", + "name": "APPTRACE_SV_DEST", + "title": "SystemView destination", + "type": "choice" + } + ], + "depends_on": "APPTRACE_ENABLE && APPTRACE_ENABLE", + "help": "Enables supporrt for SEGGER SystemView tracing functionality.", + "id": "APPTRACE_SV_ENABLE", + "name": "APPTRACE_SV_ENABLE", + "range": null, + "title": "SystemView Tracing Enable", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": "Send SEGGER SystemView events for Pro CPU.", + "id": "APPTRACE_SV_DEST_CPU_0", + "name": "APPTRACE_SV_DEST_CPU_0", + "range": null, + "title": "CPU0", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": "Send SEGGER SystemView events for App CPU.", + "id": "APPTRACE_SV_DEST_CPU_1", + "name": "APPTRACE_SV_DEST_CPU_1", + "range": null, + "title": "CPU1", + "type": "bool" + } + ], + "depends_on": "APPTRACE_SV_DEST_UART && !ESP_SYSTEM_SINGLE_CORE_MODE && APPTRACE_ENABLE", + "help": "Define the CPU to trace by SystemView.", + "id": "component-config-application-level-tracing-freertos-systemview-tracing-cpu-to-trace", + "name": "APPTRACE_SV_CPU", + "title": "CPU to trace", + "type": "choice" + }, + { + "children": [ + { + "children": [], + "depends_on": "ESP_SYSTEM_SINGLE_CORE_MODE && !PM_ENABLE && !IDF_TARGET_ESP32C3 && ", + "help": null, + "id": "APPTRACE_SV_TS_SOURCE_CCOUNT", + "name": "APPTRACE_SV_TS_SOURCE_CCOUNT", + "range": null, + "title": "CPU cycle counter (CCOUNT)", + "type": "bool" + }, + { + "children": [], + "depends_on": "!PM_ENABLE && !IDF_TARGET_ESP32C3 && ", + "help": null, + "id": "APPTRACE_SV_TS_SOURCE_GPTIMER", + "name": "APPTRACE_SV_TS_SOURCE_GPTIMER", + "range": null, + "title": "General Purpose Timer (Timer Group)", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "APPTRACE_SV_TS_SOURCE_ESP_TIMER", + "name": "APPTRACE_SV_TS_SOURCE_ESP_TIMER", + "range": null, + "title": "esp_timer high resolution timer", + "type": "bool" + } + ], + "depends_on": "APPTRACE_SV_ENABLE && APPTRACE_ENABLE", + "help": "SystemView needs to use a hardware timer as the source of timestamps\nwhen tracing. This option selects the timer for it.", + "id": "component-config-application-level-tracing-freertos-systemview-tracing-timer-to-use-as-timestamp-source", + "name": "APPTRACE_SV_TS_SOURCE", + "title": "Timer to use as timestamp source", + "type": "choice" + }, + { + "children": [], + "depends_on": "APPTRACE_SV_ENABLE && APPTRACE_ENABLE", + "help": "Configures maximum supported tasks in sysview debug", + "id": "APPTRACE_SV_MAX_TASKS", + "name": "APPTRACE_SV_MAX_TASKS", + "range": null, + "title": "Maximum supported tasks", + "type": "int" + }, + { + "children": [], + "depends_on": "APPTRACE_SV_ENABLE && APPTRACE_ENABLE", + "help": "Configures timeout (in us) to wait for free space in trace buffer.\nSet to -1 to wait forever and avoid lost events.", + "id": "APPTRACE_SV_BUF_WAIT_TMO", + "name": "APPTRACE_SV_BUF_WAIT_TMO", + "range": null, + "title": "Trace buffer wait timeout", + "type": "int" + }, + { + "children": [], + "depends_on": "APPTRACE_SV_ENABLE && APPTRACE_ENABLE", + "help": "Enables \"Trace Buffer Overflow\" event.", + "id": "APPTRACE_SV_EVT_OVERFLOW_ENABLE", + "name": "APPTRACE_SV_EVT_OVERFLOW_ENABLE", + "range": null, + "title": "Trace Buffer Overflow Event", + "type": "bool" + }, + { + "children": [], + "depends_on": "APPTRACE_SV_ENABLE && APPTRACE_ENABLE", + "help": "Enables \"ISR Enter\" event.", + "id": "APPTRACE_SV_EVT_ISR_ENTER_ENABLE", + "name": "APPTRACE_SV_EVT_ISR_ENTER_ENABLE", + "range": null, + "title": "ISR Enter Event", + "type": "bool" + }, + { + "children": [], + "depends_on": "APPTRACE_SV_ENABLE && APPTRACE_ENABLE", + "help": "Enables \"ISR Exit\" event.", + "id": "APPTRACE_SV_EVT_ISR_EXIT_ENABLE", + "name": "APPTRACE_SV_EVT_ISR_EXIT_ENABLE", + "range": null, + "title": "ISR Exit Event", + "type": "bool" + }, + { + "children": [], + "depends_on": "APPTRACE_SV_ENABLE && APPTRACE_ENABLE", + "help": "Enables \"ISR to Scheduler\" event.", + "id": "APPTRACE_SV_EVT_ISR_TO_SCHED_ENABLE", + "name": "APPTRACE_SV_EVT_ISR_TO_SCHED_ENABLE", + "range": null, + "title": "ISR Exit to Scheduler Event", + "type": "bool" + }, + { + "children": [], + "depends_on": "APPTRACE_SV_ENABLE && APPTRACE_ENABLE", + "help": "Enables \"Task Start Execution\" event.", + "id": "APPTRACE_SV_EVT_TASK_START_EXEC_ENABLE", + "name": "APPTRACE_SV_EVT_TASK_START_EXEC_ENABLE", + "range": null, + "title": "Task Start Execution Event", + "type": "bool" + }, + { + "children": [], + "depends_on": "APPTRACE_SV_ENABLE && APPTRACE_ENABLE", + "help": "Enables \"Task Stop Execution\" event.", + "id": "APPTRACE_SV_EVT_TASK_STOP_EXEC_ENABLE", + "name": "APPTRACE_SV_EVT_TASK_STOP_EXEC_ENABLE", + "range": null, + "title": "Task Stop Execution Event", + "type": "bool" + }, + { + "children": [], + "depends_on": "APPTRACE_SV_ENABLE && APPTRACE_ENABLE", + "help": "Enables \"Task Start Ready State\" event.", + "id": "APPTRACE_SV_EVT_TASK_START_READY_ENABLE", + "name": "APPTRACE_SV_EVT_TASK_START_READY_ENABLE", + "range": null, + "title": "Task Start Ready State Event", + "type": "bool" + }, + { + "children": [], + "depends_on": "APPTRACE_SV_ENABLE && APPTRACE_ENABLE", + "help": "Enables \"Task Stop Ready State\" event.", + "id": "APPTRACE_SV_EVT_TASK_STOP_READY_ENABLE", + "name": "APPTRACE_SV_EVT_TASK_STOP_READY_ENABLE", + "range": null, + "title": "Task Stop Ready State Event", + "type": "bool" + }, + { + "children": [], + "depends_on": "APPTRACE_SV_ENABLE && APPTRACE_ENABLE", + "help": "Enables \"Task Create\" event.", + "id": "APPTRACE_SV_EVT_TASK_CREATE_ENABLE", + "name": "APPTRACE_SV_EVT_TASK_CREATE_ENABLE", + "range": null, + "title": "Task Create Event", + "type": "bool" + }, + { + "children": [], + "depends_on": "APPTRACE_SV_ENABLE && APPTRACE_ENABLE", + "help": "Enables \"Task Terminate\" event.", + "id": "APPTRACE_SV_EVT_TASK_TERMINATE_ENABLE", + "name": "APPTRACE_SV_EVT_TASK_TERMINATE_ENABLE", + "range": null, + "title": "Task Terminate Event", + "type": "bool" + }, + { + "children": [], + "depends_on": "APPTRACE_SV_ENABLE && APPTRACE_ENABLE", + "help": "Enables \"System Idle\" event.", + "id": "APPTRACE_SV_EVT_IDLE_ENABLE", + "name": "APPTRACE_SV_EVT_IDLE_ENABLE", + "range": null, + "title": "System Idle Event", + "type": "bool" + }, + { + "children": [], + "depends_on": "APPTRACE_SV_ENABLE && APPTRACE_ENABLE", + "help": "Enables \"Timer Enter\" event.", + "id": "APPTRACE_SV_EVT_TIMER_ENTER_ENABLE", + "name": "APPTRACE_SV_EVT_TIMER_ENTER_ENABLE", + "range": null, + "title": "Timer Enter Event", + "type": "bool" + }, + { + "children": [], + "depends_on": "APPTRACE_SV_ENABLE && APPTRACE_ENABLE", + "help": "Enables \"Timer Exit\" event.", + "id": "APPTRACE_SV_EVT_TIMER_EXIT_ENABLE", + "name": "APPTRACE_SV_EVT_TIMER_EXIT_ENABLE", + "range": null, + "title": "Timer Exit Event", + "type": "bool" + } + ], + "depends_on": "APPTRACE_ENABLE", + "id": "component-config-application-level-tracing-freertos-systemview-tracing", + "title": "FreeRTOS SystemView Tracing", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": "APPTRACE_GCOV_ENABLE", + "help": "Configures stack size of Gcov dump task", + "id": "APPTRACE_GCOV_DUMP_TASK_STACK_SIZE", + "name": "APPTRACE_GCOV_DUMP_TASK_STACK_SIZE", + "range": null, + "title": "Gcov dump task stack size", + "type": "int" + } + ], + "depends_on": "APPTRACE_ENABLE && !APPTRACE_SV_ENABLE", + "help": "Enables support for GCOV data transfer to host.", + "id": "APPTRACE_GCOV_ENABLE", + "name": "APPTRACE_GCOV_ENABLE", + "range": null, + "title": "GCOV to Host Enable", + "type": "bool" + } + ], + "depends_on": null, + "id": "component-config-application-level-tracing", + "title": "Application Level Tracing", + "type": "menu" + }, + { + "children": [ + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "", + "help": "This option is recommended for classic Bluetooth or for dual-mode\nusecases", + "id": "BT_BLUEDROID_ENABLED", + "name": "BT_BLUEDROID_ENABLED", + "range": null, + "title": "Bluedroid - Dual-mode", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": "This option is recommended for BLE only usecases to save on memory", + "id": "BT_NIMBLE_ENABLED", + "name": "BT_NIMBLE_ENABLED", + "range": null, + "title": "NimBLE - BLE only", + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_BT_SUPPORTED && ", + "help": "This option is recommended when you want to communicate directly with the\ncontroller (without any host) or when you are using any other host stack\nnot supported by Espressif (not mentioned here).", + "id": "BT_CONTROLLER_ONLY", + "name": "BT_CONTROLLER_ONLY", + "range": null, + "title": "Disabled", + "type": "bool" + } + ], + "depends_on": "BT_ENABLED", + "help": "This helps to choose Bluetooth host stack", + "id": "component-config-bluetooth-bluetooth-host", + "name": "BT_HOST", + "title": "Host", + "type": "choice" + }, + { + "children": [ + { + "children": [], + "depends_on": "SOC_BT_SUPPORTED && ", + "help": "This option is recommended for Bluetooth controller usecases", + "id": "BT_CONTROLLER_ENABLED", + "name": "BT_CONTROLLER_ENABLED", + "range": null, + "title": "Enabled", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": "This option is recommended for Bluetooth Host only usecases", + "id": "BT_CONTROLLER_DISABLED", + "name": "BT_CONTROLLER_DISABLED", + "range": null, + "title": "Disabled", + "type": "bool" + } + ], + "depends_on": "BT_ENABLED", + "help": "This helps to choose Bluetooth controller stack", + "id": "component-config-bluetooth-bluetooth-controller", + "name": "BT_CONTROLLER", + "title": "Controller", + "type": "choice" + } + ], + "depends_on": "!APP_NO_BLOBS", + "help": "Select this option to enable Bluetooth and show the submenu with Bluetooth configuration choices.", + "id": "BT_ENABLED", + "name": "BT_ENABLED", + "range": null, + "title": "Bluetooth", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "BT_BLUEDROID_ENABLED && BT_BLUEDROID_ENABLED", + "help": "This select btc task stack size", + "id": "BT_BTC_TASK_STACK_SIZE", + "name": "BT_BTC_TASK_STACK_SIZE", + "range": null, + "title": "Bluetooth event (callback to application) task stack size", + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_BLUEDROID_PINNED_TO_CORE_0", + "name": "BT_BLUEDROID_PINNED_TO_CORE_0", + "range": null, + "title": "Core 0 (PRO CPU)", + "type": "bool" + }, + { + "children": [], + "depends_on": "!FREERTOS_UNICORE && ", + "help": null, + "id": "BT_BLUEDROID_PINNED_TO_CORE_1", + "name": "BT_BLUEDROID_PINNED_TO_CORE_1", + "range": null, + "title": "Core 1 (APP CPU)", + "type": "bool" + } + ], + "depends_on": "BT_BLUEDROID_ENABLED && !FREERTOS_UNICORE && BT_BLUEDROID_ENABLED", + "help": "Which the cpu core to run Bluedroid. Can choose core0 and core1.\nCan not specify no-affinity.", + "id": "component-config-bluetooth-bluedroid-options-the-cpu-core-which-bluedroid-run", + "name": "BT_BLUEDROID_PINNED_TO_CORE_CHOICE", + "title": "The cpu core which Bluedroid run", + "type": "choice" + }, + { + "children": [], + "depends_on": "BT_BLUEDROID_ENABLED && BT_BLUEDROID_ENABLED", + "help": null, + "id": "BT_BLUEDROID_PINNED_TO_CORE", + "name": "BT_BLUEDROID_PINNED_TO_CORE", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": "BT_BLUEDROID_ENABLED && BT_BLUEDROID_ENABLED", + "help": "This select btu task stack size", + "id": "BT_BTU_TASK_STACK_SIZE", + "name": "BT_BTU_TASK_STACK_SIZE", + "range": null, + "title": "Bluetooth Bluedroid Host Stack task stack size", + "type": "int" + }, + { + "children": [], + "depends_on": "BT_BLUEDROID_ENABLED && BT_BLUEDROID_ENABLED", + "help": "Bluedroid memory debug", + "id": "BT_BLUEDROID_MEM_DEBUG", + "name": "BT_BLUEDROID_MEM_DEBUG", + "range": null, + "title": "Bluedroid memory debug", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_BLUEDROID_ENABLED && BT_BLUEDROID_ENABLED", + "help": "Enable Espressif Vendor-specific HCI commands for coexist status configuration", + "id": "BT_BLUEDROID_ESP_COEX_VSC", + "name": "BT_BLUEDROID_ESP_COEX_VSC", + "range": null, + "title": "Enable Espressif Vendor-specific HCI commands for coexist status configuration", + "type": "bool" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "(BT_CONTROLLER_DISABLED || (BT_CONTROLLER_ENABLED && SOC_BT_H2C_ENC_KEY_CTRL_ENH_STD_SUPPORTED)) && ", + "help": null, + "id": "BT_ENC_KEY_SIZE_CTRL_STD", + "name": "BT_ENC_KEY_SIZE_CTRL_STD", + "range": null, + "title": "Supported by standard HCI command", + "type": "bool" + }, + { + "children": [], + "depends_on": "(BT_CONTROLLER_DISABLED || (BT_CONTROLLER_ENABLED && SOC_BT_H2C_ENC_KEY_CTRL_ENH_VSC_SUPPORTED)) && ", + "help": null, + "id": "BT_ENC_KEY_SIZE_CTRL_VSC", + "name": "BT_ENC_KEY_SIZE_CTRL_VSC", + "range": null, + "title": "Supported by Vendor-specific HCI command", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_ENC_KEY_SIZE_CTRL_NONE", + "name": "BT_ENC_KEY_SIZE_CTRL_NONE", + "range": null, + "title": "Not supported", + "type": "bool" + } + ], + "depends_on": "BT_CLASSIC_ENABLED && BT_BLUEDROID_ENABLED", + "help": "This chooses the support status of configuring encryption key size", + "id": "component-config-bluetooth-bluedroid-options-classic-bluetooth-configure-encryption-key-size", + "name": "BT_ENC_KEY_SIZE_CTRL_ENABLED", + "title": "configure encryption key size", + "type": "choice" + }, + { + "children": [], + "depends_on": "BT_CLASSIC_ENABLED && BT_BLUEDROID_ENABLED", + "help": "This enables functionalities of Host qualification for Classic Bluetooth.", + "id": "BT_CLASSIC_BQB_ENABLED", + "name": "BT_CLASSIC_BQB_ENABLED", + "range": null, + "title": "Host Qualitifcation support for Classic Bluetooth", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "BT_A2DP_ENABLE && BT_BLUEDROID_ENABLED", + "help": "Audio/Video Remote Control Profile, AVRCP and A2DP are coupled in Bluedroid,\nAVRCP still controlled by A2DP option, this is a dummy option currently", + "id": "BT_AVRCP_ENABLED", + "name": "BT_AVRCP_ENABLED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "BT_AVRCP_ENABLED && BT_BLUEDROID_ENABLED", + "help": "This enable Cover Art feature of AVRCP CT role", + "id": "BT_AVRCP_CT_COVER_ART_ENABLED", + "name": "BT_AVRCP_CT_COVER_ART_ENABLED", + "range": null, + "title": "AVRCP CT Cover Art", + "type": "bool" + } + ], + "depends_on": "BT_AVRCP_ENABLED && BT_BLUEDROID_ENABLED", + "id": "component-config-bluetooth-bluedroid-options-classic-bluetooth-a2dp-avrcp-features", + "title": "AVRCP Features", + "type": "menu" + } + ], + "depends_on": "BT_CLASSIC_ENABLED && BT_BLUEDROID_ENABLED", + "help": "Advanced Audio Distribution Profile", + "id": "BT_A2DP_ENABLE", + "name": "BT_A2DP_ENABLE", + "range": null, + "title": "A2DP", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_CLASSIC_ENABLED && BT_BLUEDROID_ENABLED", + "help": "This enables the Serial Port Profile", + "id": "BT_SPP_ENABLED", + "name": "BT_SPP_ENABLED", + "range": null, + "title": "SPP", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_CLASSIC_ENABLED && BT_BLUEDROID_ENABLED", + "help": "This enables the Logical Link Control and Adaptation Layer Protocol.\nOnly supported classic bluetooth.", + "id": "BT_L2CAP_ENABLED", + "name": "BT_L2CAP_ENABLED", + "range": null, + "title": "BT L2CAP", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_CLASSIC_ENABLED && BT_BLUEDROID_ENABLED", + "help": "This enables common SDP operation, such as SDP record creation and deletion.", + "id": "BT_SDP_COMMON_ENABLED", + "name": "BT_SDP_COMMON_ENABLED", + "range": null, + "title": "BT SDP COMMON", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "BT_HFP_ENABLE && BT_BLUEDROID_ENABLED", + "help": null, + "id": "BT_HFP_CLIENT_ENABLE", + "name": "BT_HFP_CLIENT_ENABLE", + "range": null, + "title": "Hands Free Unit", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_HFP_ENABLE && BT_BLUEDROID_ENABLED", + "help": null, + "id": "BT_HFP_AG_ENABLE", + "name": "BT_HFP_AG_ENABLE", + "range": null, + "title": "Audio Gateway", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_HFP_AUDIO_DATA_PATH_PCM", + "name": "BT_HFP_AUDIO_DATA_PATH_PCM", + "range": null, + "title": "PCM", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_HFP_AUDIO_DATA_PATH_HCI", + "name": "BT_HFP_AUDIO_DATA_PATH_HCI", + "range": null, + "title": "HCI", + "type": "bool" + } + ], + "depends_on": "BT_HFP_ENABLE && BT_BLUEDROID_ENABLED", + "help": "SCO data path, i.e. HCI or PCM. This option is set using API\n\"esp_bredr_sco_datapath_set\" in Bluetooth host. Default SCO data\npath can also be set in Bluetooth Controller.", + "id": "component-config-bluetooth-bluedroid-options-classic-bluetooth-hands-free-handset-profile-audio-sco-data-path", + "name": "BT_HFP_AUDIO_DATA_PATH", + "title": "audio(SCO) data path", + "type": "choice" + }, + { + "children": [], + "depends_on": "BT_HFP_ENABLE && BT_HFP_AUDIO_DATA_PATH_HCI && BT_BLUEDROID_ENABLED", + "help": "This enables Wide Band Speech. Should disable it when SCO data path is PCM.\nOtherwise there will be no data transmitted via GPIOs.", + "id": "BT_HFP_WBS_ENABLE", + "name": "BT_HFP_WBS_ENABLE", + "range": null, + "title": "Wide Band Speech", + "type": "bool" + } + ], + "depends_on": "BT_CLASSIC_ENABLED && BT_BLUEDROID_ENABLED", + "help": "Hands Free Unit and Audio Gateway can be included simultaneously\nbut they cannot run simultaneously due to internal limitations.", + "id": "BT_HFP_ENABLE", + "is_menuconfig": true, + "name": "BT_HFP_ENABLE", + "range": null, + "title": "Hands Free/Handset Profile", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": "BT_HID_ENABLED && BT_BLUEDROID_ENABLED", + "help": "This enables the BT HID Host", + "id": "BT_HID_HOST_ENABLED", + "name": "BT_HID_HOST_ENABLED", + "range": null, + "title": "Classic BT HID Host", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_HID_ENABLED && BT_BLUEDROID_ENABLED", + "help": "This enables the BT HID Device", + "id": "BT_HID_DEVICE_ENABLED", + "name": "BT_HID_DEVICE_ENABLED", + "range": null, + "title": "Classic BT HID Device", + "type": "bool" + } + ], + "depends_on": "BT_CLASSIC_ENABLED && BT_BLUEDROID_ENABLED", + "help": "This enables the BT HID functionalities", + "id": "BT_HID_ENABLED", + "is_menuconfig": true, + "name": "BT_HID_ENABLED", + "range": null, + "title": "Classic BT HID", + "type": "menu" + }, + { + "children": [], + "depends_on": "BT_CLASSIC_ENABLED && BT_BLUEDROID_ENABLED", + "help": "This enables the BT GOEP Profile Client role", + "id": "BT_GOEPC_ENABLED", + "name": "BT_GOEPC_ENABLED", + "range": null, + "title": null, + "type": "bool" + } + ], + "depends_on": "BT_BLUEDROID_ENABLED && ((BT_CONTROLLER_ENABLED && SOC_BT_CLASSIC_SUPPORTED) || BT_CONTROLLER_DISABLED) && BT_BLUEDROID_ENABLED", + "help": "For now this option needs \"SMP_ENABLE\" to be set to yes", + "id": "BT_CLASSIC_ENABLED", + "name": "BT_CLASSIC_ENABLED", + "range": null, + "title": "Classic Bluetooth", + "type": "bool" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "BT_GATTS_ENABLE && BT_BLUEDROID_ENABLED", + "help": "This enables \"Peripheral Preferred Connection Parameters\" characteristic (UUID: 0x2A04) in GAP service that has\nconnection parameters like min/max connection interval, slave latency and supervision timeout multiplier", + "id": "BT_GATTS_PPCP_CHAR_GAP", + "name": "BT_GATTS_PPCP_CHAR_GAP", + "range": null, + "title": "Enable Peripheral Preferred Connection Parameters characteristic in GAP service", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_GATTS_ENABLE && BT_BLUEDROID_ENABLED", + "help": "This option can be close when the app does not require blufi function.", + "id": "BT_BLE_BLUFI_ENABLE", + "name": "BT_BLE_BLUFI_ENABLE", + "range": null, + "title": "Include blufi function", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_GATTS_ENABLE && BT_BLUEDROID_ENABLED && BT_BLUEDROID_ENABLED", + "help": "Maximum GATT Server Profiles Count", + "id": "BT_GATT_MAX_SR_PROFILES", + "name": "BT_GATT_MAX_SR_PROFILES", + "range": null, + "title": "Max GATT Server Profiles", + "type": "int" + }, + { + "children": [], + "depends_on": "BT_GATTS_ENABLE && BT_BLUEDROID_ENABLED && BT_BLUEDROID_ENABLED", + "help": "Maximum GATT Service Attributes Count", + "id": "BT_GATT_MAX_SR_ATTRIBUTES", + "name": "BT_GATT_MAX_SR_ATTRIBUTES", + "range": null, + "title": "Max GATT Service Attributes", + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": "Manually send service change indication through API esp_ble_gatts_send_service_change_indication()", + "id": "BT_GATTS_SEND_SERVICE_CHANGE_MANUAL", + "name": "BT_GATTS_SEND_SERVICE_CHANGE_MANUAL", + "range": null, + "title": "GATTS manually send service change indication", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": "Let Bluedroid handle the service change indication internally", + "id": "BT_GATTS_SEND_SERVICE_CHANGE_AUTO", + "name": "BT_GATTS_SEND_SERVICE_CHANGE_AUTO", + "range": null, + "title": "GATTS automatically send service change indication", + "type": "bool" + } + ], + "depends_on": "BT_GATTS_ENABLE && BT_BLUEDROID_ENABLED", + "help": "Service change indication mode for GATT Server.", + "id": "component-config-bluetooth-bluedroid-options-bluetooth-low-energy-include-gatt-server-module-gatts--gatts-service-change-mode", + "name": "BT_GATTS_SEND_SERVICE_CHANGE_MODE", + "title": "GATTS Service Change Mode", + "type": "choice" + }, + { + "children": [], + "depends_on": "BT_GATTS_ENABLE && BT_BLUEDROID_ENABLED", + "help": null, + "id": "BT_GATTS_SEND_SERVICE_CHANGE_MODE", + "name": "BT_GATTS_SEND_SERVICE_CHANGE_MODE", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": "BT_GATTS_ENABLE && BT_BLUEDROID_ENABLED", + "help": "This option enables the GATT robust caching feature on the server.\nif turned on, the Client Supported Features characteristic, Database Hash characteristic,\nand Server Supported Features characteristic will be included in the GAP SERVICE.", + "id": "BT_GATTS_ROBUST_CACHING_ENABLED", + "name": "BT_GATTS_ROBUST_CACHING_ENABLED", + "range": null, + "title": "Enable Robust Caching on Server Side", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_GATTS_ENABLE && BT_BLUEDROID_ENABLED", + "help": "Enabling this option allows remote GATT clients to write device name", + "id": "BT_GATTS_DEVICE_NAME_WRITABLE", + "name": "BT_GATTS_DEVICE_NAME_WRITABLE", + "range": null, + "title": "Allow to write device name by GATT clients", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_GATTS_ENABLE && BT_BLUEDROID_ENABLED", + "help": "Enabling this option allows remote GATT clients to write appearance", + "id": "BT_GATTS_APPEARANCE_WRITABLE", + "name": "BT_GATTS_APPEARANCE_WRITABLE", + "range": null, + "title": "Allow to write appearance by GATT clients", + "type": "bool" + } + ], + "depends_on": "BT_BLE_ENABLED && BT_BLUEDROID_ENABLED", + "help": "This option can be disabled when the app work only on gatt client mode", + "id": "BT_GATTS_ENABLE", + "name": "BT_GATTS_ENABLE", + "range": null, + "title": "Include GATT server module(GATTS)", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "BT_GATTC_ENABLE && BT_BLUEDROID_ENABLED", + "help": "Maximum GATTC cache characteristic count", + "id": "BT_GATTC_MAX_CACHE_CHAR", + "name": "BT_GATTC_MAX_CACHE_CHAR", + "range": null, + "title": "Max gattc cache characteristic for discover", + "type": "int" + }, + { + "children": [], + "depends_on": "BT_GATTC_ENABLE && BT_BLUEDROID_ENABLED", + "help": "Maximum GATTC notify(indication) register number", + "id": "BT_GATTC_NOTIF_REG_MAX", + "name": "BT_GATTC_NOTIF_REG_MAX", + "range": null, + "title": "Max gattc notify(indication) register number", + "type": "int" + }, + { + "children": [], + "depends_on": "BT_GATTC_ENABLE && BT_BLUEDROID_ENABLED", + "help": "This select can save gattc cache data to nvs flash", + "id": "BT_GATTC_CACHE_NVS_FLASH", + "name": "BT_GATTC_CACHE_NVS_FLASH", + "range": null, + "title": "Save gattc cache data to nvs flash", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_GATTC_ENABLE && BT_BLUEDROID_ENABLED", + "help": "The number of attempts to reconnect if the connection establishment failed", + "id": "BT_GATTC_CONNECT_RETRY_COUNT", + "name": "BT_GATTC_CONNECT_RETRY_COUNT", + "range": null, + "title": "The number of attempts to reconnect if the connection establishment failed", + "type": "int" + } + ], + "depends_on": "BT_BLE_ENABLED && BT_BLUEDROID_ENABLED", + "help": "This option can be close when the app work only on gatt server mode", + "id": "BT_GATTC_ENABLE", + "name": "BT_GATTC_ENABLE", + "range": null, + "title": "Include GATT client module(GATTC)", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "BT_BLE_SMP_ENABLE && BT_BLUEDROID_ENABLED", + "help": "In order to reduce the pairing time, slave actively initiates connection parameters\nupdate during pairing.", + "id": "BT_SMP_SLAVE_CON_PARAMS_UPD_ENABLE", + "name": "BT_SMP_SLAVE_CON_PARAMS_UPD_ENABLE", + "range": null, + "title": "Slave enable connection parameters update during pairing", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_BLE_SMP_ENABLE && BT_BLUEDROID_ENABLED", + "help": "There are tracking risks associated with using a fixed or static IRK.\nIf enabled this option, Bluedroid will assign a new randomly-generated IRK\nwhen all pairing and bonding records are deleted. This would decrease the ability\nof a previously paired peer to be used to determine whether a device\nwith which it previously shared an IRK is within range.", + "id": "BT_BLE_SMP_ID_RESET_ENABLE", + "name": "BT_BLE_SMP_ID_RESET_ENABLE", + "range": null, + "title": "Reset device identity when all bonding records are deleted", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_BLE_SMP_ENABLE && BT_BLUEDROID_ENABLED", + "help": "This select can save SMP bonding keys to nvs flash", + "id": "BT_BLE_SMP_BOND_NVS_FLASH", + "name": "BT_BLE_SMP_BOND_NVS_FLASH", + "range": null, + "title": "Save SMP bonding keys to nvs flash", + "type": "bool" + } + ], + "depends_on": "BT_BLE_ENABLED && BT_BLUEDROID_ENABLED", + "help": "This option can be close when the app not used the ble security connect.", + "id": "BT_BLE_SMP_ENABLE", + "name": "BT_BLE_SMP_ENABLE", + "range": null, + "title": "Include BLE security module(SMP)", + "type": "bool" + } + ], + "depends_on": "BT_BLUEDROID_ENABLED && BT_BLUEDROID_ENABLED", + "help": "This enables Bluetooth Low Energy", + "id": "BT_BLE_ENABLED", + "name": "BT_BLE_ENABLED", + "range": null, + "title": "Bluetooth Low Energy", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_BLUEDROID_ENABLED && BT_BLUEDROID_ENABLED", + "help": "This select can save the rodata code size", + "id": "BT_STACK_NO_LOG", + "name": "BT_STACK_NO_LOG", + "range": null, + "title": "Disable BT debug logs (minimize bin size)", + "type": "bool" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_HCI_TRACE_LEVEL_NONE", + "name": "BT_LOG_HCI_TRACE_LEVEL_NONE", + "range": null, + "title": "NONE", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_HCI_TRACE_LEVEL_ERROR", + "name": "BT_LOG_HCI_TRACE_LEVEL_ERROR", + "range": null, + "title": "ERROR", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_HCI_TRACE_LEVEL_WARNING", + "name": "BT_LOG_HCI_TRACE_LEVEL_WARNING", + "range": null, + "title": "WARNING", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_HCI_TRACE_LEVEL_API", + "name": "BT_LOG_HCI_TRACE_LEVEL_API", + "range": null, + "title": "API", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_HCI_TRACE_LEVEL_EVENT", + "name": "BT_LOG_HCI_TRACE_LEVEL_EVENT", + "range": null, + "title": "EVENT", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_HCI_TRACE_LEVEL_DEBUG", + "name": "BT_LOG_HCI_TRACE_LEVEL_DEBUG", + "range": null, + "title": "DEBUG", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_HCI_TRACE_LEVEL_VERBOSE", + "name": "BT_LOG_HCI_TRACE_LEVEL_VERBOSE", + "range": null, + "title": "VERBOSE", + "type": "bool" + } + ], + "depends_on": "BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG && BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG && BT_BLUEDROID_ENABLED", + "help": "Define BT trace level for HCI layer", + "id": "component-config-bluetooth-bluedroid-options-bt-debug-log-level-hci-layer", + "name": "BT_LOG_HCI_TRACE_LEVEL", + "title": "HCI layer", + "type": "choice" + }, + { + "children": [], + "depends_on": "BT_BLUEDROID_ENABLED && BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG && BT_BLUEDROID_ENABLED", + "help": null, + "id": "BT_LOG_HCI_TRACE_LEVEL", + "name": "BT_LOG_HCI_TRACE_LEVEL", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_BTM_TRACE_LEVEL_NONE", + "name": "BT_LOG_BTM_TRACE_LEVEL_NONE", + "range": null, + "title": "NONE", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_BTM_TRACE_LEVEL_ERROR", + "name": "BT_LOG_BTM_TRACE_LEVEL_ERROR", + "range": null, + "title": "ERROR", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_BTM_TRACE_LEVEL_WARNING", + "name": "BT_LOG_BTM_TRACE_LEVEL_WARNING", + "range": null, + "title": "WARNING", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_BTM_TRACE_LEVEL_API", + "name": "BT_LOG_BTM_TRACE_LEVEL_API", + "range": null, + "title": "API", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_BTM_TRACE_LEVEL_EVENT", + "name": "BT_LOG_BTM_TRACE_LEVEL_EVENT", + "range": null, + "title": "EVENT", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_BTM_TRACE_LEVEL_DEBUG", + "name": "BT_LOG_BTM_TRACE_LEVEL_DEBUG", + "range": null, + "title": "DEBUG", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_BTM_TRACE_LEVEL_VERBOSE", + "name": "BT_LOG_BTM_TRACE_LEVEL_VERBOSE", + "range": null, + "title": "VERBOSE", + "type": "bool" + } + ], + "depends_on": "BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG && BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG && BT_BLUEDROID_ENABLED", + "help": "Define BT trace level for BTM layer", + "id": "component-config-bluetooth-bluedroid-options-bt-debug-log-level-btm-layer", + "name": "BT_LOG_BTM_TRACE_LEVEL", + "title": "BTM layer", + "type": "choice" + }, + { + "children": [], + "depends_on": "BT_BLUEDROID_ENABLED && BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG && BT_BLUEDROID_ENABLED", + "help": null, + "id": "BT_LOG_BTM_TRACE_LEVEL", + "name": "BT_LOG_BTM_TRACE_LEVEL", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_L2CAP_TRACE_LEVEL_NONE", + "name": "BT_LOG_L2CAP_TRACE_LEVEL_NONE", + "range": null, + "title": "NONE", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_L2CAP_TRACE_LEVEL_ERROR", + "name": "BT_LOG_L2CAP_TRACE_LEVEL_ERROR", + "range": null, + "title": "ERROR", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_L2CAP_TRACE_LEVEL_WARNING", + "name": "BT_LOG_L2CAP_TRACE_LEVEL_WARNING", + "range": null, + "title": "WARNING", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_L2CAP_TRACE_LEVEL_API", + "name": "BT_LOG_L2CAP_TRACE_LEVEL_API", + "range": null, + "title": "API", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_L2CAP_TRACE_LEVEL_EVENT", + "name": "BT_LOG_L2CAP_TRACE_LEVEL_EVENT", + "range": null, + "title": "EVENT", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_L2CAP_TRACE_LEVEL_DEBUG", + "name": "BT_LOG_L2CAP_TRACE_LEVEL_DEBUG", + "range": null, + "title": "DEBUG", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_L2CAP_TRACE_LEVEL_VERBOSE", + "name": "BT_LOG_L2CAP_TRACE_LEVEL_VERBOSE", + "range": null, + "title": "VERBOSE", + "type": "bool" + } + ], + "depends_on": "BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG && BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG && BT_BLUEDROID_ENABLED", + "help": "Define BT trace level for L2CAP layer", + "id": "component-config-bluetooth-bluedroid-options-bt-debug-log-level-l2cap-layer", + "name": "BT_LOG_L2CAP_TRACE_LEVEL", + "title": "L2CAP layer", + "type": "choice" + }, + { + "children": [], + "depends_on": "BT_BLUEDROID_ENABLED && BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG && BT_BLUEDROID_ENABLED", + "help": null, + "id": "BT_LOG_L2CAP_TRACE_LEVEL", + "name": "BT_LOG_L2CAP_TRACE_LEVEL", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_RFCOMM_TRACE_LEVEL_NONE", + "name": "BT_LOG_RFCOMM_TRACE_LEVEL_NONE", + "range": null, + "title": "NONE", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_RFCOMM_TRACE_LEVEL_ERROR", + "name": "BT_LOG_RFCOMM_TRACE_LEVEL_ERROR", + "range": null, + "title": "ERROR", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_RFCOMM_TRACE_LEVEL_WARNING", + "name": "BT_LOG_RFCOMM_TRACE_LEVEL_WARNING", + "range": null, + "title": "WARNING", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_RFCOMM_TRACE_LEVEL_API", + "name": "BT_LOG_RFCOMM_TRACE_LEVEL_API", + "range": null, + "title": "API", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_RFCOMM_TRACE_LEVEL_EVENT", + "name": "BT_LOG_RFCOMM_TRACE_LEVEL_EVENT", + "range": null, + "title": "EVENT", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_RFCOMM_TRACE_LEVEL_DEBUG", + "name": "BT_LOG_RFCOMM_TRACE_LEVEL_DEBUG", + "range": null, + "title": "DEBUG", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_RFCOMM_TRACE_LEVEL_VERBOSE", + "name": "BT_LOG_RFCOMM_TRACE_LEVEL_VERBOSE", + "range": null, + "title": "VERBOSE", + "type": "bool" + } + ], + "depends_on": "BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG && BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG && BT_BLUEDROID_ENABLED", + "help": "Define BT trace level for RFCOMM layer", + "id": "component-config-bluetooth-bluedroid-options-bt-debug-log-level-rfcomm-layer", + "name": "BT_LOG_RFCOMM_TRACE_LEVEL", + "title": "RFCOMM layer", + "type": "choice" + }, + { + "children": [], + "depends_on": "BT_BLUEDROID_ENABLED && BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG && BT_BLUEDROID_ENABLED", + "help": null, + "id": "BT_LOG_RFCOMM_TRACE_LEVEL", + "name": "BT_LOG_RFCOMM_TRACE_LEVEL", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_SDP_TRACE_LEVEL_NONE", + "name": "BT_LOG_SDP_TRACE_LEVEL_NONE", + "range": null, + "title": "NONE", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_SDP_TRACE_LEVEL_ERROR", + "name": "BT_LOG_SDP_TRACE_LEVEL_ERROR", + "range": null, + "title": "ERROR", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_SDP_TRACE_LEVEL_WARNING", + "name": "BT_LOG_SDP_TRACE_LEVEL_WARNING", + "range": null, + "title": "WARNING", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_SDP_TRACE_LEVEL_API", + "name": "BT_LOG_SDP_TRACE_LEVEL_API", + "range": null, + "title": "API", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_SDP_TRACE_LEVEL_EVENT", + "name": "BT_LOG_SDP_TRACE_LEVEL_EVENT", + "range": null, + "title": "EVENT", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_SDP_TRACE_LEVEL_DEBUG", + "name": "BT_LOG_SDP_TRACE_LEVEL_DEBUG", + "range": null, + "title": "DEBUG", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_SDP_TRACE_LEVEL_VERBOSE", + "name": "BT_LOG_SDP_TRACE_LEVEL_VERBOSE", + "range": null, + "title": "VERBOSE", + "type": "bool" + } + ], + "depends_on": "BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG && BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG && BT_BLUEDROID_ENABLED", + "help": "Define BT trace level for SDP layer", + "id": "component-config-bluetooth-bluedroid-options-bt-debug-log-level-sdp-layer", + "name": "BT_LOG_SDP_TRACE_LEVEL", + "title": "SDP layer", + "type": "choice" + }, + { + "children": [], + "depends_on": "BT_BLUEDROID_ENABLED && BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG && BT_BLUEDROID_ENABLED", + "help": null, + "id": "BT_LOG_SDP_TRACE_LEVEL", + "name": "BT_LOG_SDP_TRACE_LEVEL", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_GAP_TRACE_LEVEL_NONE", + "name": "BT_LOG_GAP_TRACE_LEVEL_NONE", + "range": null, + "title": "NONE", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_GAP_TRACE_LEVEL_ERROR", + "name": "BT_LOG_GAP_TRACE_LEVEL_ERROR", + "range": null, + "title": "ERROR", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_GAP_TRACE_LEVEL_WARNING", + "name": "BT_LOG_GAP_TRACE_LEVEL_WARNING", + "range": null, + "title": "WARNING", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_GAP_TRACE_LEVEL_API", + "name": "BT_LOG_GAP_TRACE_LEVEL_API", + "range": null, + "title": "API", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_GAP_TRACE_LEVEL_EVENT", + "name": "BT_LOG_GAP_TRACE_LEVEL_EVENT", + "range": null, + "title": "EVENT", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_GAP_TRACE_LEVEL_DEBUG", + "name": "BT_LOG_GAP_TRACE_LEVEL_DEBUG", + "range": null, + "title": "DEBUG", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_GAP_TRACE_LEVEL_VERBOSE", + "name": "BT_LOG_GAP_TRACE_LEVEL_VERBOSE", + "range": null, + "title": "VERBOSE", + "type": "bool" + } + ], + "depends_on": "BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG && BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG && BT_BLUEDROID_ENABLED", + "help": "Define BT trace level for GAP layer", + "id": "component-config-bluetooth-bluedroid-options-bt-debug-log-level-gap-layer", + "name": "BT_LOG_GAP_TRACE_LEVEL", + "title": "GAP layer", + "type": "choice" + }, + { + "children": [], + "depends_on": "BT_BLUEDROID_ENABLED && BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG && BT_BLUEDROID_ENABLED", + "help": null, + "id": "BT_LOG_GAP_TRACE_LEVEL", + "name": "BT_LOG_GAP_TRACE_LEVEL", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_BNEP_TRACE_LEVEL_NONE", + "name": "BT_LOG_BNEP_TRACE_LEVEL_NONE", + "range": null, + "title": "NONE", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_BNEP_TRACE_LEVEL_ERROR", + "name": "BT_LOG_BNEP_TRACE_LEVEL_ERROR", + "range": null, + "title": "ERROR", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_BNEP_TRACE_LEVEL_WARNING", + "name": "BT_LOG_BNEP_TRACE_LEVEL_WARNING", + "range": null, + "title": "WARNING", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_BNEP_TRACE_LEVEL_API", + "name": "BT_LOG_BNEP_TRACE_LEVEL_API", + "range": null, + "title": "API", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_BNEP_TRACE_LEVEL_EVENT", + "name": "BT_LOG_BNEP_TRACE_LEVEL_EVENT", + "range": null, + "title": "EVENT", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_BNEP_TRACE_LEVEL_DEBUG", + "name": "BT_LOG_BNEP_TRACE_LEVEL_DEBUG", + "range": null, + "title": "DEBUG", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_BNEP_TRACE_LEVEL_VERBOSE", + "name": "BT_LOG_BNEP_TRACE_LEVEL_VERBOSE", + "range": null, + "title": "VERBOSE", + "type": "bool" + } + ], + "depends_on": "BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG && BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG && BT_BLUEDROID_ENABLED", + "help": "Define BT trace level for BNEP layer", + "id": "component-config-bluetooth-bluedroid-options-bt-debug-log-level-bnep-layer", + "name": "BT_LOG_BNEP_TRACE_LEVEL", + "title": "BNEP layer", + "type": "choice" + }, + { + "children": [], + "depends_on": "BT_BLUEDROID_ENABLED && BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG && BT_BLUEDROID_ENABLED", + "help": null, + "id": "BT_LOG_BNEP_TRACE_LEVEL", + "name": "BT_LOG_BNEP_TRACE_LEVEL", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_PAN_TRACE_LEVEL_NONE", + "name": "BT_LOG_PAN_TRACE_LEVEL_NONE", + "range": null, + "title": "NONE", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_PAN_TRACE_LEVEL_ERROR", + "name": "BT_LOG_PAN_TRACE_LEVEL_ERROR", + "range": null, + "title": "ERROR", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_PAN_TRACE_LEVEL_WARNING", + "name": "BT_LOG_PAN_TRACE_LEVEL_WARNING", + "range": null, + "title": "WARNING", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_PAN_TRACE_LEVEL_API", + "name": "BT_LOG_PAN_TRACE_LEVEL_API", + "range": null, + "title": "API", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_PAN_TRACE_LEVEL_EVENT", + "name": "BT_LOG_PAN_TRACE_LEVEL_EVENT", + "range": null, + "title": "EVENT", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_PAN_TRACE_LEVEL_DEBUG", + "name": "BT_LOG_PAN_TRACE_LEVEL_DEBUG", + "range": null, + "title": "DEBUG", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_PAN_TRACE_LEVEL_VERBOSE", + "name": "BT_LOG_PAN_TRACE_LEVEL_VERBOSE", + "range": null, + "title": "VERBOSE", + "type": "bool" + } + ], + "depends_on": "BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG && BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG && BT_BLUEDROID_ENABLED", + "help": "Define BT trace level for PAN layer", + "id": "component-config-bluetooth-bluedroid-options-bt-debug-log-level-pan-layer", + "name": "BT_LOG_PAN_TRACE_LEVEL", + "title": "PAN layer", + "type": "choice" + }, + { + "children": [], + "depends_on": "BT_BLUEDROID_ENABLED && BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG && BT_BLUEDROID_ENABLED", + "help": null, + "id": "BT_LOG_PAN_TRACE_LEVEL", + "name": "BT_LOG_PAN_TRACE_LEVEL", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_A2D_TRACE_LEVEL_NONE", + "name": "BT_LOG_A2D_TRACE_LEVEL_NONE", + "range": null, + "title": "NONE", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_A2D_TRACE_LEVEL_ERROR", + "name": "BT_LOG_A2D_TRACE_LEVEL_ERROR", + "range": null, + "title": "ERROR", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_A2D_TRACE_LEVEL_WARNING", + "name": "BT_LOG_A2D_TRACE_LEVEL_WARNING", + "range": null, + "title": "WARNING", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_A2D_TRACE_LEVEL_API", + "name": "BT_LOG_A2D_TRACE_LEVEL_API", + "range": null, + "title": "API", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_A2D_TRACE_LEVEL_EVENT", + "name": "BT_LOG_A2D_TRACE_LEVEL_EVENT", + "range": null, + "title": "EVENT", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_A2D_TRACE_LEVEL_DEBUG", + "name": "BT_LOG_A2D_TRACE_LEVEL_DEBUG", + "range": null, + "title": "DEBUG", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_A2D_TRACE_LEVEL_VERBOSE", + "name": "BT_LOG_A2D_TRACE_LEVEL_VERBOSE", + "range": null, + "title": "VERBOSE", + "type": "bool" + } + ], + "depends_on": "BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG && BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG && BT_BLUEDROID_ENABLED", + "help": "Define BT trace level for A2D layer", + "id": "component-config-bluetooth-bluedroid-options-bt-debug-log-level-a2d-layer", + "name": "BT_LOG_A2D_TRACE_LEVEL", + "title": "A2D layer", + "type": "choice" + }, + { + "children": [], + "depends_on": "BT_BLUEDROID_ENABLED && BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG && BT_BLUEDROID_ENABLED", + "help": null, + "id": "BT_LOG_A2D_TRACE_LEVEL", + "name": "BT_LOG_A2D_TRACE_LEVEL", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_AVDT_TRACE_LEVEL_NONE", + "name": "BT_LOG_AVDT_TRACE_LEVEL_NONE", + "range": null, + "title": "NONE", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_AVDT_TRACE_LEVEL_ERROR", + "name": "BT_LOG_AVDT_TRACE_LEVEL_ERROR", + "range": null, + "title": "ERROR", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_AVDT_TRACE_LEVEL_WARNING", + "name": "BT_LOG_AVDT_TRACE_LEVEL_WARNING", + "range": null, + "title": "WARNING", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_AVDT_TRACE_LEVEL_API", + "name": "BT_LOG_AVDT_TRACE_LEVEL_API", + "range": null, + "title": "API", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_AVDT_TRACE_LEVEL_EVENT", + "name": "BT_LOG_AVDT_TRACE_LEVEL_EVENT", + "range": null, + "title": "EVENT", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_AVDT_TRACE_LEVEL_DEBUG", + "name": "BT_LOG_AVDT_TRACE_LEVEL_DEBUG", + "range": null, + "title": "DEBUG", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_AVDT_TRACE_LEVEL_VERBOSE", + "name": "BT_LOG_AVDT_TRACE_LEVEL_VERBOSE", + "range": null, + "title": "VERBOSE", + "type": "bool" + } + ], + "depends_on": "BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG && BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG && BT_BLUEDROID_ENABLED", + "help": "Define BT trace level for AVDT layer", + "id": "component-config-bluetooth-bluedroid-options-bt-debug-log-level-avdt-layer", + "name": "BT_LOG_AVDT_TRACE_LEVEL", + "title": "AVDT layer", + "type": "choice" + }, + { + "children": [], + "depends_on": "BT_BLUEDROID_ENABLED && BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG && BT_BLUEDROID_ENABLED", + "help": null, + "id": "BT_LOG_AVDT_TRACE_LEVEL", + "name": "BT_LOG_AVDT_TRACE_LEVEL", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_AVCT_TRACE_LEVEL_NONE", + "name": "BT_LOG_AVCT_TRACE_LEVEL_NONE", + "range": null, + "title": "NONE", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_AVCT_TRACE_LEVEL_ERROR", + "name": "BT_LOG_AVCT_TRACE_LEVEL_ERROR", + "range": null, + "title": "ERROR", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_AVCT_TRACE_LEVEL_WARNING", + "name": "BT_LOG_AVCT_TRACE_LEVEL_WARNING", + "range": null, + "title": "WARNING", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_AVCT_TRACE_LEVEL_API", + "name": "BT_LOG_AVCT_TRACE_LEVEL_API", + "range": null, + "title": "API", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_AVCT_TRACE_LEVEL_EVENT", + "name": "BT_LOG_AVCT_TRACE_LEVEL_EVENT", + "range": null, + "title": "EVENT", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_AVCT_TRACE_LEVEL_DEBUG", + "name": "BT_LOG_AVCT_TRACE_LEVEL_DEBUG", + "range": null, + "title": "DEBUG", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_AVCT_TRACE_LEVEL_VERBOSE", + "name": "BT_LOG_AVCT_TRACE_LEVEL_VERBOSE", + "range": null, + "title": "VERBOSE", + "type": "bool" + } + ], + "depends_on": "BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG && BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG && BT_BLUEDROID_ENABLED", + "help": "Define BT trace level for AVCT layer", + "id": "component-config-bluetooth-bluedroid-options-bt-debug-log-level-avct-layer", + "name": "BT_LOG_AVCT_TRACE_LEVEL", + "title": "AVCT layer", + "type": "choice" + }, + { + "children": [], + "depends_on": "BT_BLUEDROID_ENABLED && BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG && BT_BLUEDROID_ENABLED", + "help": null, + "id": "BT_LOG_AVCT_TRACE_LEVEL", + "name": "BT_LOG_AVCT_TRACE_LEVEL", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_AVRC_TRACE_LEVEL_NONE", + "name": "BT_LOG_AVRC_TRACE_LEVEL_NONE", + "range": null, + "title": "NONE", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_AVRC_TRACE_LEVEL_ERROR", + "name": "BT_LOG_AVRC_TRACE_LEVEL_ERROR", + "range": null, + "title": "ERROR", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_AVRC_TRACE_LEVEL_WARNING", + "name": "BT_LOG_AVRC_TRACE_LEVEL_WARNING", + "range": null, + "title": "WARNING", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_AVRC_TRACE_LEVEL_API", + "name": "BT_LOG_AVRC_TRACE_LEVEL_API", + "range": null, + "title": "API", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_AVRC_TRACE_LEVEL_EVENT", + "name": "BT_LOG_AVRC_TRACE_LEVEL_EVENT", + "range": null, + "title": "EVENT", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_AVRC_TRACE_LEVEL_DEBUG", + "name": "BT_LOG_AVRC_TRACE_LEVEL_DEBUG", + "range": null, + "title": "DEBUG", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_AVRC_TRACE_LEVEL_VERBOSE", + "name": "BT_LOG_AVRC_TRACE_LEVEL_VERBOSE", + "range": null, + "title": "VERBOSE", + "type": "bool" + } + ], + "depends_on": "BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG && BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG && BT_BLUEDROID_ENABLED", + "help": "Define BT trace level for AVRC layer", + "id": "component-config-bluetooth-bluedroid-options-bt-debug-log-level-avrc-layer", + "name": "BT_LOG_AVRC_TRACE_LEVEL", + "title": "AVRC layer", + "type": "choice" + }, + { + "children": [], + "depends_on": "BT_BLUEDROID_ENABLED && BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG && BT_BLUEDROID_ENABLED", + "help": null, + "id": "BT_LOG_AVRC_TRACE_LEVEL", + "name": "BT_LOG_AVRC_TRACE_LEVEL", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_MCA_TRACE_LEVEL_NONE", + "name": "BT_LOG_MCA_TRACE_LEVEL_NONE", + "range": null, + "title": "NONE", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_MCA_TRACE_LEVEL_ERROR", + "name": "BT_LOG_MCA_TRACE_LEVEL_ERROR", + "range": null, + "title": "ERROR", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_MCA_TRACE_LEVEL_WARNING", + "name": "BT_LOG_MCA_TRACE_LEVEL_WARNING", + "range": null, + "title": "WARNING", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_MCA_TRACE_LEVEL_API", + "name": "BT_LOG_MCA_TRACE_LEVEL_API", + "range": null, + "title": "API", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_MCA_TRACE_LEVEL_EVENT", + "name": "BT_LOG_MCA_TRACE_LEVEL_EVENT", + "range": null, + "title": "EVENT", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_MCA_TRACE_LEVEL_DEBUG", + "name": "BT_LOG_MCA_TRACE_LEVEL_DEBUG", + "range": null, + "title": "DEBUG", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_MCA_TRACE_LEVEL_VERBOSE", + "name": "BT_LOG_MCA_TRACE_LEVEL_VERBOSE", + "range": null, + "title": "VERBOSE", + "type": "bool" + } + ], + "depends_on": "BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG && BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG && BT_BLUEDROID_ENABLED", + "help": "Define BT trace level for MCA layer", + "id": "component-config-bluetooth-bluedroid-options-bt-debug-log-level-mca-layer", + "name": "BT_LOG_MCA_TRACE_LEVEL", + "title": "MCA layer", + "type": "choice" + }, + { + "children": [], + "depends_on": "BT_BLUEDROID_ENABLED && BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG && BT_BLUEDROID_ENABLED", + "help": null, + "id": "BT_LOG_MCA_TRACE_LEVEL", + "name": "BT_LOG_MCA_TRACE_LEVEL", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_HID_TRACE_LEVEL_NONE", + "name": "BT_LOG_HID_TRACE_LEVEL_NONE", + "range": null, + "title": "NONE", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_HID_TRACE_LEVEL_ERROR", + "name": "BT_LOG_HID_TRACE_LEVEL_ERROR", + "range": null, + "title": "ERROR", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_HID_TRACE_LEVEL_WARNING", + "name": "BT_LOG_HID_TRACE_LEVEL_WARNING", + "range": null, + "title": "WARNING", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_HID_TRACE_LEVEL_API", + "name": "BT_LOG_HID_TRACE_LEVEL_API", + "range": null, + "title": "API", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_HID_TRACE_LEVEL_EVENT", + "name": "BT_LOG_HID_TRACE_LEVEL_EVENT", + "range": null, + "title": "EVENT", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_HID_TRACE_LEVEL_DEBUG", + "name": "BT_LOG_HID_TRACE_LEVEL_DEBUG", + "range": null, + "title": "DEBUG", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_HID_TRACE_LEVEL_VERBOSE", + "name": "BT_LOG_HID_TRACE_LEVEL_VERBOSE", + "range": null, + "title": "VERBOSE", + "type": "bool" + } + ], + "depends_on": "BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG && BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG && BT_BLUEDROID_ENABLED", + "help": "Define BT trace level for HID layer", + "id": "component-config-bluetooth-bluedroid-options-bt-debug-log-level-hid-layer", + "name": "BT_LOG_HID_TRACE_LEVEL", + "title": "HID layer", + "type": "choice" + }, + { + "children": [], + "depends_on": "BT_BLUEDROID_ENABLED && BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG && BT_BLUEDROID_ENABLED", + "help": null, + "id": "BT_LOG_HID_TRACE_LEVEL", + "name": "BT_LOG_HID_TRACE_LEVEL", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_APPL_TRACE_LEVEL_NONE", + "name": "BT_LOG_APPL_TRACE_LEVEL_NONE", + "range": null, + "title": "NONE", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_APPL_TRACE_LEVEL_ERROR", + "name": "BT_LOG_APPL_TRACE_LEVEL_ERROR", + "range": null, + "title": "ERROR", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_APPL_TRACE_LEVEL_WARNING", + "name": "BT_LOG_APPL_TRACE_LEVEL_WARNING", + "range": null, + "title": "WARNING", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_APPL_TRACE_LEVEL_API", + "name": "BT_LOG_APPL_TRACE_LEVEL_API", + "range": null, + "title": "API", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_APPL_TRACE_LEVEL_EVENT", + "name": "BT_LOG_APPL_TRACE_LEVEL_EVENT", + "range": null, + "title": "EVENT", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_APPL_TRACE_LEVEL_DEBUG", + "name": "BT_LOG_APPL_TRACE_LEVEL_DEBUG", + "range": null, + "title": "DEBUG", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_APPL_TRACE_LEVEL_VERBOSE", + "name": "BT_LOG_APPL_TRACE_LEVEL_VERBOSE", + "range": null, + "title": "VERBOSE", + "type": "bool" + } + ], + "depends_on": "BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG && BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG && BT_BLUEDROID_ENABLED", + "help": "Define BT trace level for APPL layer", + "id": "component-config-bluetooth-bluedroid-options-bt-debug-log-level-appl-layer", + "name": "BT_LOG_APPL_TRACE_LEVEL", + "title": "APPL layer", + "type": "choice" + }, + { + "children": [], + "depends_on": "BT_BLUEDROID_ENABLED && BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG && BT_BLUEDROID_ENABLED", + "help": null, + "id": "BT_LOG_APPL_TRACE_LEVEL", + "name": "BT_LOG_APPL_TRACE_LEVEL", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_GATT_TRACE_LEVEL_NONE", + "name": "BT_LOG_GATT_TRACE_LEVEL_NONE", + "range": null, + "title": "NONE", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_GATT_TRACE_LEVEL_ERROR", + "name": "BT_LOG_GATT_TRACE_LEVEL_ERROR", + "range": null, + "title": "ERROR", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_GATT_TRACE_LEVEL_WARNING", + "name": "BT_LOG_GATT_TRACE_LEVEL_WARNING", + "range": null, + "title": "WARNING", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_GATT_TRACE_LEVEL_API", + "name": "BT_LOG_GATT_TRACE_LEVEL_API", + "range": null, + "title": "API", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_GATT_TRACE_LEVEL_EVENT", + "name": "BT_LOG_GATT_TRACE_LEVEL_EVENT", + "range": null, + "title": "EVENT", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_GATT_TRACE_LEVEL_DEBUG", + "name": "BT_LOG_GATT_TRACE_LEVEL_DEBUG", + "range": null, + "title": "DEBUG", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_GATT_TRACE_LEVEL_VERBOSE", + "name": "BT_LOG_GATT_TRACE_LEVEL_VERBOSE", + "range": null, + "title": "VERBOSE", + "type": "bool" + } + ], + "depends_on": "BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG && BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG && BT_BLUEDROID_ENABLED", + "help": "Define BT trace level for GATT layer", + "id": "component-config-bluetooth-bluedroid-options-bt-debug-log-level-gatt-layer", + "name": "BT_LOG_GATT_TRACE_LEVEL", + "title": "GATT layer", + "type": "choice" + }, + { + "children": [], + "depends_on": "BT_BLUEDROID_ENABLED && BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG && BT_BLUEDROID_ENABLED", + "help": null, + "id": "BT_LOG_GATT_TRACE_LEVEL", + "name": "BT_LOG_GATT_TRACE_LEVEL", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_SMP_TRACE_LEVEL_NONE", + "name": "BT_LOG_SMP_TRACE_LEVEL_NONE", + "range": null, + "title": "NONE", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_SMP_TRACE_LEVEL_ERROR", + "name": "BT_LOG_SMP_TRACE_LEVEL_ERROR", + "range": null, + "title": "ERROR", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_SMP_TRACE_LEVEL_WARNING", + "name": "BT_LOG_SMP_TRACE_LEVEL_WARNING", + "range": null, + "title": "WARNING", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_SMP_TRACE_LEVEL_API", + "name": "BT_LOG_SMP_TRACE_LEVEL_API", + "range": null, + "title": "API", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_SMP_TRACE_LEVEL_EVENT", + "name": "BT_LOG_SMP_TRACE_LEVEL_EVENT", + "range": null, + "title": "EVENT", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_SMP_TRACE_LEVEL_DEBUG", + "name": "BT_LOG_SMP_TRACE_LEVEL_DEBUG", + "range": null, + "title": "DEBUG", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_SMP_TRACE_LEVEL_VERBOSE", + "name": "BT_LOG_SMP_TRACE_LEVEL_VERBOSE", + "range": null, + "title": "VERBOSE", + "type": "bool" + } + ], + "depends_on": "BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG && BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG && BT_BLUEDROID_ENABLED", + "help": "Define BT trace level for SMP layer", + "id": "component-config-bluetooth-bluedroid-options-bt-debug-log-level-smp-layer", + "name": "BT_LOG_SMP_TRACE_LEVEL", + "title": "SMP layer", + "type": "choice" + }, + { + "children": [], + "depends_on": "BT_BLUEDROID_ENABLED && BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG && BT_BLUEDROID_ENABLED", + "help": null, + "id": "BT_LOG_SMP_TRACE_LEVEL", + "name": "BT_LOG_SMP_TRACE_LEVEL", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_BTIF_TRACE_LEVEL_NONE", + "name": "BT_LOG_BTIF_TRACE_LEVEL_NONE", + "range": null, + "title": "NONE", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_BTIF_TRACE_LEVEL_ERROR", + "name": "BT_LOG_BTIF_TRACE_LEVEL_ERROR", + "range": null, + "title": "ERROR", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_BTIF_TRACE_LEVEL_WARNING", + "name": "BT_LOG_BTIF_TRACE_LEVEL_WARNING", + "range": null, + "title": "WARNING", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_BTIF_TRACE_LEVEL_API", + "name": "BT_LOG_BTIF_TRACE_LEVEL_API", + "range": null, + "title": "API", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_BTIF_TRACE_LEVEL_EVENT", + "name": "BT_LOG_BTIF_TRACE_LEVEL_EVENT", + "range": null, + "title": "EVENT", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_BTIF_TRACE_LEVEL_DEBUG", + "name": "BT_LOG_BTIF_TRACE_LEVEL_DEBUG", + "range": null, + "title": "DEBUG", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_BTIF_TRACE_LEVEL_VERBOSE", + "name": "BT_LOG_BTIF_TRACE_LEVEL_VERBOSE", + "range": null, + "title": "VERBOSE", + "type": "bool" + } + ], + "depends_on": "BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG && BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG && BT_BLUEDROID_ENABLED", + "help": "Define BT trace level for BTIF layer", + "id": "component-config-bluetooth-bluedroid-options-bt-debug-log-level-btif-layer", + "name": "BT_LOG_BTIF_TRACE_LEVEL", + "title": "BTIF layer", + "type": "choice" + }, + { + "children": [], + "depends_on": "BT_BLUEDROID_ENABLED && BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG && BT_BLUEDROID_ENABLED", + "help": null, + "id": "BT_LOG_BTIF_TRACE_LEVEL", + "name": "BT_LOG_BTIF_TRACE_LEVEL", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_BTC_TRACE_LEVEL_NONE", + "name": "BT_LOG_BTC_TRACE_LEVEL_NONE", + "range": null, + "title": "NONE", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_BTC_TRACE_LEVEL_ERROR", + "name": "BT_LOG_BTC_TRACE_LEVEL_ERROR", + "range": null, + "title": "ERROR", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_BTC_TRACE_LEVEL_WARNING", + "name": "BT_LOG_BTC_TRACE_LEVEL_WARNING", + "range": null, + "title": "WARNING", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_BTC_TRACE_LEVEL_API", + "name": "BT_LOG_BTC_TRACE_LEVEL_API", + "range": null, + "title": "API", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_BTC_TRACE_LEVEL_EVENT", + "name": "BT_LOG_BTC_TRACE_LEVEL_EVENT", + "range": null, + "title": "EVENT", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_BTC_TRACE_LEVEL_DEBUG", + "name": "BT_LOG_BTC_TRACE_LEVEL_DEBUG", + "range": null, + "title": "DEBUG", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_BTC_TRACE_LEVEL_VERBOSE", + "name": "BT_LOG_BTC_TRACE_LEVEL_VERBOSE", + "range": null, + "title": "VERBOSE", + "type": "bool" + } + ], + "depends_on": "BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG && BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG && BT_BLUEDROID_ENABLED", + "help": "Define BT trace level for BTC layer", + "id": "component-config-bluetooth-bluedroid-options-bt-debug-log-level-btc-layer", + "name": "BT_LOG_BTC_TRACE_LEVEL", + "title": "BTC layer", + "type": "choice" + }, + { + "children": [], + "depends_on": "BT_BLUEDROID_ENABLED && BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG && BT_BLUEDROID_ENABLED", + "help": null, + "id": "BT_LOG_BTC_TRACE_LEVEL", + "name": "BT_LOG_BTC_TRACE_LEVEL", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_OSI_TRACE_LEVEL_NONE", + "name": "BT_LOG_OSI_TRACE_LEVEL_NONE", + "range": null, + "title": "NONE", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_OSI_TRACE_LEVEL_ERROR", + "name": "BT_LOG_OSI_TRACE_LEVEL_ERROR", + "range": null, + "title": "ERROR", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_OSI_TRACE_LEVEL_WARNING", + "name": "BT_LOG_OSI_TRACE_LEVEL_WARNING", + "range": null, + "title": "WARNING", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_OSI_TRACE_LEVEL_API", + "name": "BT_LOG_OSI_TRACE_LEVEL_API", + "range": null, + "title": "API", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_OSI_TRACE_LEVEL_EVENT", + "name": "BT_LOG_OSI_TRACE_LEVEL_EVENT", + "range": null, + "title": "EVENT", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_OSI_TRACE_LEVEL_DEBUG", + "name": "BT_LOG_OSI_TRACE_LEVEL_DEBUG", + "range": null, + "title": "DEBUG", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_OSI_TRACE_LEVEL_VERBOSE", + "name": "BT_LOG_OSI_TRACE_LEVEL_VERBOSE", + "range": null, + "title": "VERBOSE", + "type": "bool" + } + ], + "depends_on": "BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG && BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG && BT_BLUEDROID_ENABLED", + "help": "Define BT trace level for OSI layer", + "id": "component-config-bluetooth-bluedroid-options-bt-debug-log-level-osi-layer", + "name": "BT_LOG_OSI_TRACE_LEVEL", + "title": "OSI layer", + "type": "choice" + }, + { + "children": [], + "depends_on": "BT_BLUEDROID_ENABLED && BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG && BT_BLUEDROID_ENABLED", + "help": null, + "id": "BT_LOG_OSI_TRACE_LEVEL", + "name": "BT_LOG_OSI_TRACE_LEVEL", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_BLUFI_TRACE_LEVEL_NONE", + "name": "BT_LOG_BLUFI_TRACE_LEVEL_NONE", + "range": null, + "title": "NONE", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_BLUFI_TRACE_LEVEL_ERROR", + "name": "BT_LOG_BLUFI_TRACE_LEVEL_ERROR", + "range": null, + "title": "ERROR", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_BLUFI_TRACE_LEVEL_WARNING", + "name": "BT_LOG_BLUFI_TRACE_LEVEL_WARNING", + "range": null, + "title": "WARNING", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_BLUFI_TRACE_LEVEL_API", + "name": "BT_LOG_BLUFI_TRACE_LEVEL_API", + "range": null, + "title": "API", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_BLUFI_TRACE_LEVEL_EVENT", + "name": "BT_LOG_BLUFI_TRACE_LEVEL_EVENT", + "range": null, + "title": "EVENT", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_BLUFI_TRACE_LEVEL_DEBUG", + "name": "BT_LOG_BLUFI_TRACE_LEVEL_DEBUG", + "range": null, + "title": "DEBUG", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_LOG_BLUFI_TRACE_LEVEL_VERBOSE", + "name": "BT_LOG_BLUFI_TRACE_LEVEL_VERBOSE", + "range": null, + "title": "VERBOSE", + "type": "bool" + } + ], + "depends_on": "BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG && BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG && BT_BLUEDROID_ENABLED", + "help": "Define BT trace level for BLUFI layer", + "id": "component-config-bluetooth-bluedroid-options-bt-debug-log-level-blufi-layer", + "name": "BT_LOG_BLUFI_TRACE_LEVEL", + "title": "BLUFI layer", + "type": "choice" + }, + { + "children": [], + "depends_on": "BT_BLUEDROID_ENABLED && BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG && BT_BLUEDROID_ENABLED", + "help": null, + "id": "BT_LOG_BLUFI_TRACE_LEVEL", + "name": "BT_LOG_BLUFI_TRACE_LEVEL", + "range": null, + "title": null, + "type": "int" + } + ], + "depends_on": "BT_BLUEDROID_ENABLED && !BT_STACK_NO_LOG && BT_BLUEDROID_ENABLED", + "id": "component-config-bluetooth-bluedroid-options-bt-debug-log-level", + "title": "BT DEBUG LOG LEVEL", + "type": "menu" + }, + { + "children": [], + "depends_on": "BT_BLUEDROID_ENABLED && BT_BLUEDROID_ENABLED", + "help": "Maximum BT/BLE connection count. The ESP32-C3/S3 chip supports a maximum of 10 instances,\nincluding ADV, SCAN and connections. The ESP32-C3/S3 chip can connect up to 9 devices if\nADV or SCAN uses only one. If ADV and SCAN are both used, The ESP32-C3/S3 chip is connected\nto a maximum of 8 devices. Because Bluetooth cannot reclaim used instances once ADV or SCAN\nis used.", + "id": "BT_ACL_CONNECTIONS", + "name": "BT_ACL_CONNECTIONS", + "range": null, + "title": "BT/BLE MAX ACL CONNECTIONS(1~9)", + "type": "int" + }, + { + "children": [], + "depends_on": "BT_BLE_ENABLED && BT_BLUEDROID_ENABLED", + "help": "Enable this option if there are multiple connections", + "id": "BT_MULTI_CONNECTION_ENBALE", + "name": "BT_MULTI_CONNECTION_ENBALE", + "range": null, + "title": "Enable BLE multi-connections", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_BLUEDROID_ENABLED && BT_BLUEDROID_ENABLED", + "help": "This select can save the internal RAM if there have the PSRAM", + "id": "BT_ALLOCATION_FROM_SPIRAM_FIRST", + "name": "BT_ALLOCATION_FROM_SPIRAM_FIRST", + "range": null, + "title": "BT/BLE will first malloc the memory from the PSRAM", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_BLUEDROID_ENABLED && BT_BLUEDROID_ENABLED", + "help": "This select can make the allocation of memory will become more flexible", + "id": "BT_BLE_DYNAMIC_ENV_MEMORY", + "name": "BT_BLE_DYNAMIC_ENV_MEMORY", + "range": null, + "title": "Use dynamic memory allocation in BT/BLE stack", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_BLE_ENABLED && BT_BLUEDROID_ENABLED", + "help": "When scanning and scan duplicate is not enabled, if there are a lot of adv packets around\nor application layer handling adv packets is slow, it will cause the controller memory\nto run out. if enabled, adv packets will be lost when host queue is congested.", + "id": "BT_BLE_HOST_QUEUE_CONG_CHECK", + "name": "BT_BLE_HOST_QUEUE_CONG_CHECK", + "range": null, + "title": "BLE queue congestion check", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_BLUEDROID_ENABLED && BT_BLUEDROID_ENABLED", + "help": null, + "id": "BT_SMP_ENABLE", + "name": "BT_SMP_ENABLE", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_SMP_ENABLE && BT_BLUEDROID_ENABLED", + "help": "The number of security records for peer devices.", + "id": "BT_SMP_MAX_BONDS", + "name": "BT_SMP_MAX_BONDS", + "range": null, + "title": "BT/BLE maximum bond device count", + "type": "int" + }, + { + "children": [], + "depends_on": "BT_BLUEDROID_ENABLED && BT_BLE_ENABLED && BT_BLUEDROID_ENABLED", + "help": "Originally, when doing BLE active scan, Bluedroid will not report adv to application layer\nuntil receive scan response. This option is used to disable the behavior. When enable this option,\nBluedroid will report adv data or scan response to application layer immediately.\n\n# Memory reserved at start of DRAM for Bluetooth stack", + "id": "BT_BLE_ACT_SCAN_REP_ADV_SCAN", + "name": "BT_BLE_ACT_SCAN_REP_ADV_SCAN", + "range": null, + "title": "Report adv data and scan response individually when BLE active scan", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_BLE_ENABLED && BT_BLUEDROID_ENABLED", + "help": "Bluetooth Connection establishment maximum time, if connection time exceeds this value, the connection\nestablishment fails, ESP_GATTC_OPEN_EVT or ESP_GATTS_OPEN_EVT is triggered.", + "id": "BT_BLE_ESTAB_LINK_CONN_TOUT", + "name": "BT_BLE_ESTAB_LINK_CONN_TOUT", + "range": null, + "title": "Timeout of BLE connection establishment", + "type": "int" + }, + { + "children": [], + "depends_on": "BT_BLUEDROID_ENABLED && BT_BLUEDROID_ENABLED", + "help": "Bluetooth Device name length shall be no larger than 248 octets, If the broadcast data cannot contain\nthe complete device name, then only the shortname will be displayed, the rest parts that can't fit in\nwill be truncated.", + "id": "BT_MAX_DEVICE_NAME_LEN", + "name": "BT_MAX_DEVICE_NAME_LEN", + "range": null, + "title": "length of bluetooth device name", + "type": "int" + }, + { + "children": [], + "depends_on": "BT_BLUEDROID_ENABLED && ((BT_CONTROLLER_ENABLED && !SOC_BLE_DEVICE_PRIVACY_SUPPORTED) || BT_CONTROLLER_DISABLED) && BT_BLUEDROID_ENABLED", + "help": "This enables controller RPA list function.\nFor ESP32, ESP32 only support network privacy mode. If this option is enabled, ESP32 will only accept\nadvertising packets from peer devices that contain private address, HW will not receive the advertising\npackets contain identity address after IRK changed. If this option is disabled, address resolution will\nbe performed in the host, so the functions that require controller to resolve address in the white list\ncannot be used. This option is disabled by default on ESP32, please enable or disable this option according\nto your own needs.\n\nFor other BLE chips, devices support network privacy mode and device privacy mode,\nusers can switch the two modes according to their own needs. So this option is enabled by default.", + "id": "BT_BLE_RPA_SUPPORTED", + "name": "BT_BLE_RPA_SUPPORTED", + "range": null, + "title": "Update RPA to Controller", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_BLE_ENABLED && BT_BLUEDROID_ENABLED", + "help": "This set RPA timeout of Controller and Host.\nDefault is 900 s (15 minutes). Range is 1 s to 1 hour (3600 s).", + "id": "BT_BLE_RPA_TIMEOUT", + "name": "BT_BLE_RPA_TIMEOUT", + "range": null, + "title": "Timeout of resolvable private address", + "type": "int" + }, + { + "children": [], + "depends_on": "BT_BLE_ENABLED && ((BT_CONTROLLER_ENABLED && SOC_BLE_50_SUPPORTED) || BT_CONTROLLER_DISABLED) && BT_BLUEDROID_ENABLED", + "help": "Enabling this option activates BLE 5.0 features.\nThis option is universally supported in chips that support BLE, except for ESP32.\nBLE 4.2 and BLE 5.0 cannot be used simultaneously.", + "id": "BT_BLE_50_FEATURES_SUPPORTED", + "name": "BT_BLE_50_FEATURES_SUPPORTED", + "range": null, + "title": "Enable BLE 5.0 features(please disable BLE 4.2 if enable BLE 5.0)", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_BLE_ENABLED && ((BT_CONTROLLER_ENABLED && SOC_BLE_50_SUPPORTED) || BT_CONTROLLER_DISABLED) && BT_BLUEDROID_ENABLED", + "help": "This enables BLE 4.2 features.\nThis option is universally supported by all ESP chips with BLE capabilities.\nBLE 4.2 and BLE 5.0 cannot be used simultaneously.", + "id": "BT_BLE_42_FEATURES_SUPPORTED", + "name": "BT_BLE_42_FEATURES_SUPPORTED", + "range": null, + "title": "Enable BLE 4.2 features(please disable BLE 5.0 if enable BLE 4.2)", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_BLUEDROID_ENABLED && BT_BLE_50_FEATURES_SUPPORTED && ((BT_CONTROLLER_ENABLED && SOC_ESP_NIMBLE_CONTROLLER) || BT_CONTROLLER_DISABLED) && BT_BLUEDROID_ENABLED", + "help": "This enables BLE periodic advertising sync transfer feature", + "id": "BT_BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER", + "name": "BT_BLE_FEAT_PERIODIC_ADV_SYNC_TRANSFER", + "range": null, + "title": "Enable BLE periodic advertising sync transfer feature", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_BLUEDROID_ENABLED && BT_BLE_50_FEATURES_SUPPORTED && ((BT_CONTROLLER_ENABLED && SOC_ESP_NIMBLE_CONTROLLER) || BT_CONTROLLER_DISABLED) && BT_BLUEDROID_ENABLED", + "help": "Enable the periodic advertising enhancements", + "id": "BT_BLE_FEAT_PERIODIC_ADV_ENH", + "name": "BT_BLE_FEAT_PERIODIC_ADV_ENH", + "range": null, + "title": "Enable periodic adv enhancements(adi support)", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_BLUEDROID_ENABLED && BT_BLE_50_FEATURES_SUPPORTED && ((BT_CONTROLLER_ENABLED && SOC_ESP_NIMBLE_CONTROLLER) || BT_CONTROLLER_DISABLED) && BT_BLUEDROID_ENABLED", + "help": "Enable the create sync enhancements", + "id": "BT_BLE_FEAT_CREATE_SYNC_ENH", + "name": "BT_BLE_FEAT_CREATE_SYNC_ENH", + "range": null, + "title": "Enable create sync enhancements(reporting disable and duplicate filtering enable support)", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_BLE_ENABLED && BT_BLUEDROID_ENABLED", + "help": "This enable BLE high duty advertising interval feature", + "id": "BT_BLE_HIGH_DUTY_ADV_INTERVAL", + "name": "BT_BLE_HIGH_DUTY_ADV_INTERVAL", + "range": null, + "title": "Enable BLE high duty advertising interval feature", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_BLUEDROID_ENABLED && BT_BLUEDROID_ENABLED", + "help": "This enables abort when memory allocation fails", + "id": "BT_ABORT_WHEN_ALLOCATION_FAILS", + "name": "BT_ABORT_WHEN_ALLOCATION_FAILS", + "range": null, + "title": "Abort when memory allocation fails in BT/BLE stack", + "type": "bool" + } + ], + "depends_on": "BT_BLUEDROID_ENABLED", + "id": "component-config-bluetooth-bluedroid-options", + "title": "Bluedroid Options", + "type": "menu" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_NIMBLE_MEM_ALLOC_MODE_INTERNAL", + "name": "BT_NIMBLE_MEM_ALLOC_MODE_INTERNAL", + "range": null, + "title": "Internal memory", + "type": "bool" + }, + { + "children": [], + "depends_on": "(SPIRAM_USE_CAPS_ALLOC || SPIRAM_USE_MALLOC) && ", + "help": null, + "id": "BT_NIMBLE_MEM_ALLOC_MODE_EXTERNAL", + "name": "BT_NIMBLE_MEM_ALLOC_MODE_EXTERNAL", + "range": null, + "title": "External SPIRAM", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_NIMBLE_MEM_ALLOC_MODE_DEFAULT", + "name": "BT_NIMBLE_MEM_ALLOC_MODE_DEFAULT", + "range": null, + "title": "Default alloc mode", + "type": "bool" + }, + { + "children": [], + "depends_on": "ESP32_IRAM_AS_8BIT_ACCESSIBLE_MEMORY && ", + "help": "Allows to use IRAM memory region as 8bit accessible region.\n\nEvery unaligned (8bit or 16bit) access will result in an exception\nand incur penalty of certain clock cycles per unaligned read/write.", + "id": "BT_NIMBLE_MEM_ALLOC_MODE_IRAM_8BIT", + "name": "BT_NIMBLE_MEM_ALLOC_MODE_IRAM_8BIT", + "range": null, + "title": "Internal IRAM", + "type": "bool" + } + ], + "depends_on": "BT_NIMBLE_ENABLED", + "help": "Allocation strategy for NimBLE host stack, essentially provides ability to\nallocate all required dynamic allocations from,\n\n- Internal DRAM memory only\n- External SPIRAM memory only\n- Either internal or external memory based on default malloc()\n behavior in ESP-IDF\n- Internal IRAM memory wherever applicable else internal DRAM", + "id": "component-config-bluetooth-nimble-options-memory-allocation-strategy", + "name": "BT_NIMBLE_MEM_ALLOC_MODE", + "title": "Memory allocation strategy", + "type": "choice" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_NIMBLE_LOG_LEVEL_NONE", + "name": "BT_NIMBLE_LOG_LEVEL_NONE", + "range": null, + "title": "No logs", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_NIMBLE_LOG_LEVEL_ERROR", + "name": "BT_NIMBLE_LOG_LEVEL_ERROR", + "range": null, + "title": "Error logs", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_NIMBLE_LOG_LEVEL_WARNING", + "name": "BT_NIMBLE_LOG_LEVEL_WARNING", + "range": null, + "title": "Warning logs", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_NIMBLE_LOG_LEVEL_INFO", + "name": "BT_NIMBLE_LOG_LEVEL_INFO", + "range": null, + "title": "Info logs", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_NIMBLE_LOG_LEVEL_DEBUG", + "name": "BT_NIMBLE_LOG_LEVEL_DEBUG", + "range": null, + "title": "Debug logs", + "type": "bool" + } + ], + "depends_on": "BT_NIMBLE_ENABLED && BT_NIMBLE_ENABLED", + "help": "Select NimBLE log level. Please make a note that the selected NimBLE log\nverbosity can not exceed the level set in \"Component config --> Log output\n--> Default log verbosity\".", + "id": "component-config-bluetooth-nimble-options-nimble-host-log-verbosity", + "name": "BT_NIMBLE_LOG_LEVEL", + "title": "NimBLE Host log verbosity", + "type": "choice" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLED", + "help": null, + "id": "BT_NIMBLE_LOG_LEVEL", + "name": "BT_NIMBLE_LOG_LEVEL", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLED && BT_NIMBLE_ENABLED", + "help": "Defines maximum number of concurrent BLE connections. For ESP32, user\nis expected to configure BTDM_CTRL_BLE_MAX_CONN from controller menu\nalong with this option. Similarly for ESP32-C3 or ESP32-S3, user is expected to\nconfigure BT_CTRL_BLE_MAX_ACT from controller menu.\nFor ESP32C2, ESP32C6 and ESP32H2, each connection will take about 1k DRAM.", + "id": "BT_NIMBLE_MAX_CONNECTIONS", + "name": "BT_NIMBLE_MAX_CONNECTIONS", + "range": [ + 1, + 9 + ], + "title": "Maximum number of concurrent connections", + "type": "int" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLED && BT_NIMBLE_ENABLED", + "help": "Defines maximum number of bonds to save for peer security and our security", + "id": "BT_NIMBLE_MAX_BONDS", + "name": "BT_NIMBLE_MAX_BONDS", + "range": null, + "title": "Maximum number of bonds to save across reboots", + "type": "int" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLED && BT_NIMBLE_ENABLED", + "help": "Defines maximum number of CCC descriptors to save", + "id": "BT_NIMBLE_MAX_CCCDS", + "name": "BT_NIMBLE_MAX_CCCDS", + "range": null, + "title": "Maximum number of CCC descriptors to save across reboots", + "type": "int" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLED && BT_NIMBLE_ENABLED", + "help": "Defines maximum number of BLE Connection Oriented Channels. When set to (0), BLE COC is not compiled in", + "id": "BT_NIMBLE_L2CAP_COC_MAX_NUM", + "name": "BT_NIMBLE_L2CAP_COC_MAX_NUM", + "range": [ + 0, + 9 + ], + "title": "Maximum number of connection oriented channels", + "type": "int" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLED && BT_NIMBLE_L2CAP_COC_MAX_NUM >= 1 && BT_NIMBLE_ENABLED", + "help": "Enable Enhanced Credit Based Flow Control Mode", + "id": "BT_NIMBLE_L2CAP_ENHANCED_COC", + "name": "BT_NIMBLE_L2CAP_ENHANCED_COC", + "range": null, + "title": "L2CAP Enhanced Connection Oriented Channel", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_NIMBLE_PINNED_TO_CORE_0", + "name": "BT_NIMBLE_PINNED_TO_CORE_0", + "range": null, + "title": "Core 0 (PRO CPU)", + "type": "bool" + }, + { + "children": [], + "depends_on": "!FREERTOS_UNICORE && ", + "help": null, + "id": "BT_NIMBLE_PINNED_TO_CORE_1", + "name": "BT_NIMBLE_PINNED_TO_CORE_1", + "range": null, + "title": "Core 1 (APP CPU)", + "type": "bool" + } + ], + "depends_on": "BT_NIMBLE_ENABLED && !FREERTOS_UNICORE && BT_NIMBLE_ENABLED", + "help": "The CPU core on which NimBLE host will run. You can choose Core 0 or Core 1.\nCannot specify no-affinity", + "id": "component-config-bluetooth-nimble-options-the-cpu-core-on-which-nimble-host-will-run", + "name": "BT_NIMBLE_PINNED_TO_CORE_CHOICE", + "title": "The CPU core on which NimBLE host will run", + "type": "choice" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLED && BT_NIMBLE_ENABLED", + "help": null, + "id": "BT_NIMBLE_PINNED_TO_CORE", + "name": "BT_NIMBLE_PINNED_TO_CORE", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLED && BT_NIMBLE_ENABLED", + "help": "This configures stack size of NimBLE host task", + "id": "BT_NIMBLE_HOST_TASK_STACK_SIZE", + "name": "BT_NIMBLE_HOST_TASK_STACK_SIZE", + "range": null, + "title": "NimBLE Host task stack size", + "type": "int" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLED && BT_NIMBLE_ENABLED", + "help": "Enables central role", + "id": "BT_NIMBLE_ROLE_CENTRAL", + "name": "BT_NIMBLE_ROLE_CENTRAL", + "range": null, + "title": "Enable BLE Central role", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLED && BT_NIMBLE_ENABLED", + "help": "Enable peripheral role", + "id": "BT_NIMBLE_ROLE_PERIPHERAL", + "name": "BT_NIMBLE_ROLE_PERIPHERAL", + "range": null, + "title": "Enable BLE Peripheral role", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLED && BT_NIMBLE_ENABLED", + "help": "Enables broadcaster role", + "id": "BT_NIMBLE_ROLE_BROADCASTER", + "name": "BT_NIMBLE_ROLE_BROADCASTER", + "range": null, + "title": "Enable BLE Broadcaster role", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLED && BT_NIMBLE_ENABLED", + "help": "Enables observer role", + "id": "BT_NIMBLE_ROLE_OBSERVER", + "name": "BT_NIMBLE_ROLE_OBSERVER", + "range": null, + "title": "Enable BLE Observer role", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLED && BT_NIMBLE_ENABLED", + "help": "Enable this flag to make bonding persistent across device reboots", + "id": "BT_NIMBLE_NVS_PERSIST", + "name": "BT_NIMBLE_NVS_PERSIST", + "range": null, + "title": "Persist the BLE Bonding keys in NVS", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLED", + "help": "There are tracking risks associated with using a fixed or static IRK.\nIf enabled this option, NimBLE will assign a new randomly-generated IRK\nwhen all pairing and bonding records are deleted. This would decrease the ability\nof a previously paired peer to be used to determine whether a device\nwith which it previously shared an IRK is within range.", + "id": "BT_NIMBLE_SMP_ID_RESET", + "name": "BT_NIMBLE_SMP_ID_RESET", + "range": null, + "title": "Reset device identity when all bonding records are deleted", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "BT_NIMBLE_SECURITY_ENABLE && BT_NIMBLE_ENABLED", + "help": "Enable security manager legacy pairing", + "id": "BT_NIMBLE_SM_LEGACY", + "name": "BT_NIMBLE_SM_LEGACY", + "range": null, + "title": "Security manager legacy pairing", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "BT_NIMBLE_SECURITY_ENABLE && BT_NIMBLE_SM_SC && BT_NIMBLE_ENABLED", + "help": "If this option is enabled, SM uses predefined DH key pair as described\nin Core Specification, Vol. 3, Part H, 2.3.5.6.1. This allows to\ndecrypt air traffic easily and thus should only be used for debugging.", + "id": "BT_NIMBLE_SM_SC_DEBUG_KEYS", + "name": "BT_NIMBLE_SM_SC_DEBUG_KEYS", + "range": null, + "title": "Use predefined public-private key pair", + "type": "bool" + } + ], + "depends_on": "BT_NIMBLE_SECURITY_ENABLE && BT_NIMBLE_ENABLED", + "help": "Enable security manager secure connections", + "id": "BT_NIMBLE_SM_SC", + "name": "BT_NIMBLE_SM_SC", + "range": null, + "title": "Security manager secure connections (4.2)", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_SECURITY_ENABLE && BT_NIMBLE_ENABLED && BT_NIMBLE_ENABLED", + "help": "Enable encryption connection", + "id": "BT_NIMBLE_LL_CFG_FEAT_LE_ENCRYPTION", + "name": "BT_NIMBLE_LL_CFG_FEAT_LE_ENCRYPTION", + "range": null, + "title": "Enable LE encryption", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_SECURITY_ENABLE && BT_NIMBLE_ENABLED", + "help": "LE Security Mode 1 Levels:\n1. No Security\n2. Unauthenticated pairing with encryption\n3. Authenticated pairing with encryption\n4. Authenticated LE Secure Connections pairing with encryption using a 128-bit strength encryption key.", + "id": "BT_NIMBLE_SM_LVL", + "name": "BT_NIMBLE_SM_LVL", + "range": null, + "title": "Security level", + "type": "int" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_SECURITY_ENABLE && BT_NIMBLE_ENABLED", + "help": "Enable Secure Connections Only Mode", + "id": "BT_NIMBLE_SM_SC_ONLY", + "name": "BT_NIMBLE_SM_SC_ONLY", + "range": null, + "title": "Enable Secure Connections Only Mode", + "type": "int" + } + ], + "depends_on": "BT_NIMBLE_ENABLED && BT_NIMBLE_ENABLED", + "help": "Enable BLE sm feature", + "id": "BT_NIMBLE_SECURITY_ENABLE", + "is_menuconfig": true, + "name": "BT_NIMBLE_SECURITY_ENABLE", + "range": null, + "title": "Enable BLE SM feature", + "type": "menu" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLED && BT_NIMBLE_ENABLED", + "help": "This enables extra runtime asserts and host debugging", + "id": "BT_NIMBLE_DEBUG", + "name": "BT_NIMBLE_DEBUG", + "range": null, + "title": "Enable extra runtime asserts and host debugging", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLED && BT_NIMBLE_ENABLED", + "help": "This enables user to add/remove Gatt services at runtime", + "id": "BT_NIMBLE_DYNAMIC_SERVICE", + "name": "BT_NIMBLE_DYNAMIC_SERVICE", + "range": null, + "title": "Enable dynamic services", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLED && BT_NIMBLE_ENABLED", + "help": "The Device Name characteristic shall contain the name of the device as an UTF-8 string.\nThis name can be changed by using API ble_svc_gap_device_name_set()", + "id": "BT_NIMBLE_SVC_GAP_DEVICE_NAME", + "name": "BT_NIMBLE_SVC_GAP_DEVICE_NAME", + "range": null, + "title": "BLE GAP default device name", + "type": "string" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLED && BT_NIMBLE_ENABLED", + "help": "Device Name characteristic value shall be 0 to 248 octets in length", + "id": "BT_NIMBLE_GAP_DEVICE_NAME_MAX_LEN", + "name": "BT_NIMBLE_GAP_DEVICE_NAME_MAX_LEN", + "range": null, + "title": "Maximum length of BLE device name in octets", + "type": "int" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLED && BT_NIMBLE_ENABLED", + "help": "This is the default value of ATT MTU indicated by the device during an ATT MTU exchange.\nThis value can be changed using API ble_att_set_preferred_mtu()", + "id": "BT_NIMBLE_ATT_PREFERRED_MTU", + "name": "BT_NIMBLE_ATT_PREFERRED_MTU", + "range": null, + "title": "Preferred MTU size in octets", + "type": "int" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLED && BT_NIMBLE_ENABLED", + "help": "Standard BLE GAP Appearance value in HEX format e.g. 0x02C0", + "id": "BT_NIMBLE_SVC_GAP_APPEARANCE", + "name": "BT_NIMBLE_SVC_GAP_APPEARANCE", + "range": null, + "title": "External appearance of the device", + "type": "hex" + }, + { + "children": [ + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLED", + "help": "MSYS is a system level mbuf registry. For prepare write & prepare\nresponses MBUFs are allocated out of msys_1 pool. For NIMBLE_MESH\nenabled cases, this block count is increased by 8 than user defined\ncount.", + "id": "BT_NIMBLE_MSYS_1_BLOCK_COUNT", + "name": "BT_NIMBLE_MSYS_1_BLOCK_COUNT", + "range": null, + "title": "MSYS_1 Block Count", + "type": "int" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLED", + "help": "Dynamic memory size of block 1", + "id": "BT_NIMBLE_MSYS_1_BLOCK_SIZE", + "name": "BT_NIMBLE_MSYS_1_BLOCK_SIZE", + "range": null, + "title": "MSYS_1 Block Size", + "type": "int" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLED", + "help": "Dynamic memory count", + "id": "BT_NIMBLE_MSYS_2_BLOCK_COUNT", + "name": "BT_NIMBLE_MSYS_2_BLOCK_COUNT", + "range": null, + "title": "MSYS_2 Block Count", + "type": "int" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLED", + "help": "Dynamic memory size of block 2", + "id": "BT_NIMBLE_MSYS_2_BLOCK_SIZE", + "name": "BT_NIMBLE_MSYS_2_BLOCK_SIZE", + "range": null, + "title": "MSYS_2 Block Size", + "type": "int" + }, + { + "children": [], + "depends_on": "BT_LE_MSYS_INIT_IN_CONTROLLER && BT_NIMBLE_ENABLED", + "help": "This option sets the source of the shared msys mbuf memory between\nthe Host and the Controller. Allocate the memory from the heap if\nthis option is sets, from the mempool otherwise.", + "id": "BT_NIMBLE_MSYS_BUF_FROM_HEAP", + "name": "BT_NIMBLE_MSYS_BUF_FROM_HEAP", + "range": null, + "title": "Get Msys Mbuf from heap", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLED && BT_NIMBLE_ENABLED", + "help": "The number of ACL data buffers allocated for host.", + "id": "BT_NIMBLE_TRANSPORT_ACL_FROM_LL_COUNT", + "name": "BT_NIMBLE_TRANSPORT_ACL_FROM_LL_COUNT", + "range": null, + "title": "ACL Buffer count", + "type": "int" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLED && BT_NIMBLE_ENABLED", + "help": "This is the maximum size of the data portion of HCI ACL data packets.\nIt does not include the HCI data header (of 4 bytes)", + "id": "BT_NIMBLE_TRANSPORT_ACL_SIZE", + "name": "BT_NIMBLE_TRANSPORT_ACL_SIZE", + "range": null, + "title": "Transport ACL Buffer size", + "type": "int" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLED && BT_NIMBLE_ENABLED", + "help": "This is the size of each HCI event buffer in bytes. In case of\nextended advertising, packets can be fragmented. 257 bytes is the\nmaximum size of a packet.", + "id": "BT_NIMBLE_TRANSPORT_EVT_SIZE", + "name": "BT_NIMBLE_TRANSPORT_EVT_SIZE", + "range": null, + "title": "Transport Event Buffer size", + "type": "int" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLED && BT_NIMBLE_ENABLED", + "help": "This is the high priority HCI events' buffer size. High-priority\nevent buffers are for everything except advertising reports. If there\nare no free high-priority event buffers then host will try to allocate a\nlow-priority buffer instead", + "id": "BT_NIMBLE_TRANSPORT_EVT_COUNT", + "name": "BT_NIMBLE_TRANSPORT_EVT_COUNT", + "range": null, + "title": "Transport Event Buffer count", + "type": "int" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLED && BT_NIMBLE_ENABLED", + "help": "This is the low priority HCI events' buffer size. Low-priority event\nbuffers are only used for advertising reports. If there are no free\nlow-priority event buffers, then an incoming advertising report will\nget dropped", + "id": "BT_NIMBLE_TRANSPORT_EVT_DISCARD_COUNT", + "name": "BT_NIMBLE_TRANSPORT_EVT_DISCARD_COUNT", + "range": null, + "title": "Discardable Transport Event Buffer count", + "type": "int" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLED && BT_NIMBLE_ENABLED", + "help": "This is the service data unit buffer count for l2cap coc.", + "id": "BT_NIMBLE_L2CAP_COC_SDU_BUFF_COUNT", + "name": "BT_NIMBLE_L2CAP_COC_SDU_BUFF_COUNT", + "range": null, + "title": "L2cap coc Service Data Unit Buffer count", + "type": "int" + } + ], + "depends_on": "BT_NIMBLE_ENABLED", + "id": "component-config-bluetooth-nimble-options-memory-settings", + "title": "Memory Settings", + "type": "menu" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLED && BT_NIMBLE_ENABLED", + "help": "Maximum number of GATT client procedures that can be executed.", + "id": "BT_NIMBLE_GATT_MAX_PROCS", + "name": "BT_NIMBLE_GATT_MAX_PROCS", + "range": null, + "title": "Maximum number of GATT client procedures", + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "BT_NIMBLE_HS_FLOW_CTRL && BT_NIMBLE_ENABLED", + "help": "Host flow control interval in msecs", + "id": "BT_NIMBLE_HS_FLOW_CTRL_ITVL", + "name": "BT_NIMBLE_HS_FLOW_CTRL_ITVL", + "range": null, + "title": "Host Flow control interval", + "type": "int" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_HS_FLOW_CTRL && BT_NIMBLE_ENABLED", + "help": "Host flow control threshold, if the number of free buffers are at or\nbelow this threshold, send an immediate number-of-completed-packets\nevent", + "id": "BT_NIMBLE_HS_FLOW_CTRL_THRESH", + "name": "BT_NIMBLE_HS_FLOW_CTRL_THRESH", + "range": null, + "title": "Host Flow control threshold", + "type": "int" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_HS_FLOW_CTRL && BT_NIMBLE_ENABLED", + "help": "Enable this option to send number-of-completed-packets event to\ncontroller after disconnection", + "id": "BT_NIMBLE_HS_FLOW_CTRL_TX_ON_DISCONNECT", + "name": "BT_NIMBLE_HS_FLOW_CTRL_TX_ON_DISCONNECT", + "range": null, + "title": "Host Flow control on disconnect", + "type": "bool" + } + ], + "depends_on": "BT_NIMBLE_ENABLED && BT_NIMBLE_ENABLED", + "help": "Enable Host Flow control", + "id": "BT_NIMBLE_HS_FLOW_CTRL", + "name": "BT_NIMBLE_HS_FLOW_CTRL", + "range": null, + "title": "Enable Host Flow control", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLED && BT_NIMBLE_ENABLED", + "help": "Time interval between RPA address change.", + "id": "BT_NIMBLE_RPA_TIMEOUT", + "name": "BT_NIMBLE_RPA_TIMEOUT", + "range": [ + 1, + 41400 + ], + "title": "RPA timeout in seconds", + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "BT_NIMBLE_MESH && BT_NIMBLE_ENABLED", + "help": "Enable proxy. This is automatically set whenever NIMBLE_MESH_PB_GATT or\nNIMBLE_MESH_GATT_PROXY is set", + "id": "BT_NIMBLE_MESH_PROXY", + "name": "BT_NIMBLE_MESH_PROXY", + "range": null, + "title": "Enable mesh proxy functionality", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "BT_NIMBLE_MESH_PROV && BT_NIMBLE_ENABLED", + "help": "Enable this option to allow the device to be provisioned over\nthe advertising bearer", + "id": "BT_NIMBLE_MESH_PB_ADV", + "name": "BT_NIMBLE_MESH_PB_ADV", + "range": null, + "title": "Enable mesh provisioning over advertising bearer", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_MESH_PROV && BT_NIMBLE_ENABLED", + "help": "Enable this option to allow the device to be provisioned over the GATT\nbearer", + "id": "BT_NIMBLE_MESH_PB_GATT", + "name": "BT_NIMBLE_MESH_PB_GATT", + "range": null, + "title": "Enable mesh provisioning over GATT bearer", + "type": "bool" + } + ], + "depends_on": "BT_NIMBLE_MESH && BT_NIMBLE_ENABLED", + "help": "Enable mesh provisioning", + "id": "BT_NIMBLE_MESH_PROV", + "name": "BT_NIMBLE_MESH_PROV", + "range": null, + "title": "Enable BLE mesh provisioning", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_MESH && BT_NIMBLE_ENABLED", + "help": "This option enables support for the Mesh GATT Proxy Service,\ni.e. the ability to act as a proxy between a Mesh GATT Client\nand a Mesh network", + "id": "BT_NIMBLE_MESH_GATT_PROXY", + "name": "BT_NIMBLE_MESH_GATT_PROXY", + "range": null, + "title": "Enable GATT Proxy functionality", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_MESH && BT_NIMBLE_ENABLED", + "help": "Support for acting as a Mesh Relay Node", + "id": "BT_NIMBLE_MESH_RELAY", + "name": "BT_NIMBLE_MESH_RELAY", + "range": null, + "title": "Enable mesh relay functionality", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_MESH && BT_NIMBLE_ENABLED", + "help": "Enable this option to be able to act as a Low Power Node", + "id": "BT_NIMBLE_MESH_LOW_POWER", + "name": "BT_NIMBLE_MESH_LOW_POWER", + "range": null, + "title": "Enable mesh low power mode", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_MESH && BT_NIMBLE_ENABLED", + "help": "Enable this option to be able to act as a Friend Node", + "id": "BT_NIMBLE_MESH_FRIEND", + "name": "BT_NIMBLE_MESH_FRIEND", + "range": null, + "title": "Enable mesh friend functionality", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_MESH && BT_NIMBLE_ENABLED", + "help": "This value defines Bluetooth Mesh device/node name", + "id": "BT_NIMBLE_MESH_DEVICE_NAME", + "name": "BT_NIMBLE_MESH_DEVICE_NAME", + "range": null, + "title": "Set mesh device name", + "type": "string" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_MESH && BT_NIMBLE_ENABLED", + "help": "Defines mesh node count.", + "id": "BT_NIMBLE_MESH_NODE_COUNT", + "name": "BT_NIMBLE_MESH_NODE_COUNT", + "range": null, + "title": "Set mesh node count", + "type": "int" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_MESH && BT_NIMBLE_ENABLED", + "help": "Enable mesh provisioner.", + "id": "BT_NIMBLE_MESH_PROVISIONER", + "name": "BT_NIMBLE_MESH_PROVISIONER", + "range": null, + "title": "Enable BLE mesh provisioner", + "type": "bool" + } + ], + "depends_on": "BT_NIMBLE_ENABLED && BT_NIMBLE_ENABLED", + "help": "Enable BLE Mesh example present in upstream mynewt-nimble and not maintained by Espressif.\n\nIDF maintains ESP-BLE-MESH as the official Mesh solution. Please refer to ESP-BLE-MESH guide at:\n`https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/esp-ble-mesh/ble-mesh-index.html`", + "id": "BT_NIMBLE_MESH", + "is_menuconfig": true, + "name": "BT_NIMBLE_MESH", + "range": null, + "title": "Enable BLE mesh functionality", + "type": "menu" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLED && BT_NIMBLE_ENABLED", + "help": "Enable this option to choose mbedTLS instead of TinyCrypt for crypto\ncomputations.", + "id": "BT_NIMBLE_CRYPTO_STACK_MBEDTLS", + "name": "BT_NIMBLE_CRYPTO_STACK_MBEDTLS", + "range": null, + "title": "Override TinyCrypt with mbedTLS for crypto computations", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLED && BT_NIMBLE_ENABLED", + "help": "BLE Host stop procedure timeout in milliseconds.", + "id": "BT_NIMBLE_HS_STOP_TIMEOUT_MS", + "name": "BT_NIMBLE_HS_STOP_TIMEOUT_MS", + "range": null, + "title": "BLE host stop timeout in msec", + "type": "int" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLED && IDF_TARGET_ESP32 && BT_NIMBLE_ENABLED", + "help": "Use this option to do host based Random Private Address resolution.\nIf this option is disabled then controller based privacy is used.", + "id": "BT_NIMBLE_HOST_BASED_PRIVACY", + "name": "BT_NIMBLE_HOST_BASED_PRIVACY", + "range": null, + "title": "Enable host based privacy for random address.", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLED && BT_NIMBLE_ENABLE_CONN_REATTEMPT && BT_NIMBLE_ENABLED", + "help": "Defines maximum number of connection reattempts.", + "id": "BT_NIMBLE_MAX_CONN_REATTEMPT", + "name": "BT_NIMBLE_MAX_CONN_REATTEMPT", + "range": [ + 1, + 255 + ], + "title": "Maximum number connection reattempts", + "type": "int" + } + ], + "depends_on": "BT_NIMBLE_ENABLED", + "help": "Enable to make the NimBLE host to reattempt GAP connection on connection\nestablishment failure.", + "id": "BT_NIMBLE_ENABLE_CONN_REATTEMPT", + "name": "BT_NIMBLE_ENABLE_CONN_REATTEMPT", + "range": null, + "title": "Enable connection reattempts on connection establishment error", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "BT_NIMBLE_50_FEATURE_SUPPORT && BT_NIMBLE_50_FEATURE_SUPPORT && BT_NIMBLE_ENABLED", + "help": "Enable 2M-PHY", + "id": "BT_NIMBLE_LL_CFG_FEAT_LE_2M_PHY", + "name": "BT_NIMBLE_LL_CFG_FEAT_LE_2M_PHY", + "range": null, + "title": "Enable 2M Phy", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_50_FEATURE_SUPPORT && BT_NIMBLE_50_FEATURE_SUPPORT && BT_NIMBLE_ENABLED", + "help": "Enable coded-PHY", + "id": "BT_NIMBLE_LL_CFG_FEAT_LE_CODED_PHY", + "name": "BT_NIMBLE_LL_CFG_FEAT_LE_CODED_PHY", + "range": null, + "title": "Enable coded Phy", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "BT_NIMBLE_EXT_ADV && BT_NIMBLE_EXT_ADV && BT_NIMBLE_50_FEATURE_SUPPORT && BT_NIMBLE_ENABLED", + "help": "Change this option to set maximum number of extended advertising\ninstances. Minimum there is always one instance of\nadvertising. Enter how many more advertising instances you\nwant.\nFor ESP32C2, ESP32C6 and ESP32H2, each extended advertising instance\nwill take about 0.5k DRAM.", + "id": "BT_NIMBLE_MAX_EXT_ADV_INSTANCES", + "name": "BT_NIMBLE_MAX_EXT_ADV_INSTANCES", + "range": null, + "title": "Maximum number of extended advertising instances.", + "type": "int" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_EXT_ADV && BT_NIMBLE_EXT_ADV && BT_NIMBLE_50_FEATURE_SUPPORT && BT_NIMBLE_ENABLED", + "help": "Defines the length of the extended adv data. The value should not\nexceed 1650.", + "id": "BT_NIMBLE_EXT_ADV_MAX_SIZE", + "name": "BT_NIMBLE_EXT_ADV_MAX_SIZE", + "range": null, + "title": "Maximum length of the advertising data.", + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLE_PERIODIC_ADV && SOC_BLE_PERIODIC_ADV_ENH_SUPPORTED && BT_NIMBLE_EXT_ADV && BT_NIMBLE_50_FEATURE_SUPPORT && BT_NIMBLE_ENABLED", + "help": "Enable the periodic advertising enhancements", + "id": "BT_NIMBLE_PERIODIC_ADV_ENH", + "name": "BT_NIMBLE_PERIODIC_ADV_ENH", + "range": null, + "title": "Periodic adv enhancements(adi support)", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLE_PERIODIC_ADV && BT_NIMBLE_EXT_ADV && BT_NIMBLE_50_FEATURE_SUPPORT && BT_NIMBLE_ENABLED", + "help": "This enables controller transfer periodic sync events to host", + "id": "BT_NIMBLE_PERIODIC_ADV_SYNC_TRANSFER", + "name": "BT_NIMBLE_PERIODIC_ADV_SYNC_TRANSFER", + "range": null, + "title": "Enable Transfer Sync Events", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLE_PERIODIC_ADV && BT_NIMBLE_EXT_ADV && BT_NIMBLE_50_FEATURE_SUPPORT && BT_NIMBLE_ENABLED", + "help": "This enables controller PAwR (Periodic Advertisement with Response).", + "id": "BT_NIMBLE_PERIODIC_ADV_WITH_RESPONSES", + "name": "BT_NIMBLE_PERIODIC_ADV_WITH_RESPONSES", + "range": null, + "title": "Enable Periodic Advertisement with Response (EXPERIMENTAL)", + "type": "bool" + } + ], + "depends_on": "BT_NIMBLE_EXT_ADV && BT_NIMBLE_EXT_ADV && BT_NIMBLE_50_FEATURE_SUPPORT && BT_NIMBLE_ENABLED", + "help": "Enable this option to start periodic advertisement.", + "id": "BT_NIMBLE_ENABLE_PERIODIC_ADV", + "name": "BT_NIMBLE_ENABLE_PERIODIC_ADV", + "range": null, + "title": "Enable periodic advertisement.", + "type": "bool" + } + ], + "depends_on": "BT_NIMBLE_50_FEATURE_SUPPORT && BT_NIMBLE_50_FEATURE_SUPPORT && BT_NIMBLE_ENABLED", + "help": "Enable this option to do extended advertising. Extended advertising\nwill be supported from BLE 5.0 onwards.", + "id": "BT_NIMBLE_EXT_ADV", + "name": "BT_NIMBLE_EXT_ADV", + "range": null, + "title": "Enable extended advertising", + "type": "bool" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLE_PERIODIC_SYNC && BT_NIMBLE_50_FEATURE_SUPPORT && BT_NIMBLE_ENABLED", + "help": "Set this option to set the upper limit for number of periodic sync\nconnections. This should be less than maximum connections allowed by\ncontroller.", + "id": "BT_NIMBLE_MAX_PERIODIC_SYNCS", + "name": "BT_NIMBLE_MAX_PERIODIC_SYNCS", + "range": [ + 0, + 8 + ], + "title": "Maximum number of periodic advertising syncs", + "type": "int" + }, + { + "children": [], + "depends_on": "SOC_ESP_NIMBLE_CONTROLLER && BT_NIMBLE_ENABLE_PERIODIC_SYNC && BT_NIMBLE_50_FEATURE_SUPPORT && BT_NIMBLE_ENABLED", + "help": "Set this option to set the upper limit for number of periodic advertiser list.", + "id": "BT_NIMBLE_MAX_PERIODIC_ADVERTISER_LIST", + "name": "BT_NIMBLE_MAX_PERIODIC_ADVERTISER_LIST", + "range": null, + "title": "Maximum number of periodic advertiser list", + "type": "int" + } + ], + "depends_on": "BT_NIMBLE_EXT_SCAN && BT_NIMBLE_50_FEATURE_SUPPORT && BT_NIMBLE_ENABLED", + "help": "Enable this option to receive periodic advertisement.", + "id": "BT_NIMBLE_ENABLE_PERIODIC_SYNC", + "name": "BT_NIMBLE_ENABLE_PERIODIC_SYNC", + "range": null, + "title": "Enable periodic sync", + "type": "bool" + } + ], + "depends_on": "BT_NIMBLE_50_FEATURE_SUPPORT && BT_NIMBLE_ROLE_OBSERVER && BT_NIMBLE_50_FEATURE_SUPPORT && BT_NIMBLE_ENABLED", + "help": "Enable this option to do extended scanning.", + "id": "BT_NIMBLE_EXT_SCAN", + "name": "BT_NIMBLE_EXT_SCAN", + "range": null, + "title": "Enable extended scanning", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_50_FEATURE_SUPPORT && SOC_BLE_POWER_CONTROL_SUPPORTED && BT_NIMBLE_50_FEATURE_SUPPORT && BT_NIMBLE_ENABLED", + "help": "Set this option to enable the Power Control feature", + "id": "BT_NIMBLE_BLE_POWER_CONTROL", + "name": "BT_NIMBLE_BLE_POWER_CONTROL", + "range": null, + "title": "Enable support for BLE Power Control", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_50_FEATURE_SUPPORT && (BT_CONTROLLER_DISABLED || SOC_BLE_CTE_SUPPORTED) && BT_NIMBLE_50_FEATURE_SUPPORT && BT_NIMBLE_ENABLED", + "help": "Enable support for Connectionless and Connection Oriented Direction Finding", + "id": "BT_NIMBLE_AOA_AOD", + "name": "BT_NIMBLE_AOA_AOD", + "range": null, + "title": "Direction Finding", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "BT_NIMBLE_GATT_CACHING && BT_NIMBLE_50_FEATURE_SUPPORT && BT_NIMBLE_ENABLED", + "help": "Set this option to set the upper limit on number of connections to be cached.", + "id": "BT_NIMBLE_GATT_CACHING_MAX_CONNS", + "name": "BT_NIMBLE_GATT_CACHING_MAX_CONNS", + "range": null, + "title": "Maximum connections to be cached", + "type": "int" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_GATT_CACHING && BT_NIMBLE_50_FEATURE_SUPPORT && BT_NIMBLE_ENABLED", + "help": "Set this option to set the upper limit on number of services per connection to be cached.", + "id": "BT_NIMBLE_GATT_CACHING_MAX_SVCS", + "name": "BT_NIMBLE_GATT_CACHING_MAX_SVCS", + "range": null, + "title": "Maximum number of services per connection", + "type": "int" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_GATT_CACHING && BT_NIMBLE_50_FEATURE_SUPPORT && BT_NIMBLE_ENABLED", + "help": "Set this option to set the upper limit on number of characteristics per connection to be cached.", + "id": "BT_NIMBLE_GATT_CACHING_MAX_CHRS", + "name": "BT_NIMBLE_GATT_CACHING_MAX_CHRS", + "range": null, + "title": "Maximum number of characteristics per connection", + "type": "int" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_GATT_CACHING && BT_NIMBLE_50_FEATURE_SUPPORT && BT_NIMBLE_ENABLED", + "help": "Set this option to set the upper limit on number of descriptors per connection to be cached.", + "id": "BT_NIMBLE_GATT_CACHING_MAX_DSCS", + "name": "BT_NIMBLE_GATT_CACHING_MAX_DSCS", + "range": null, + "title": "Maximum number of descriptors per connection", + "type": "int" + } + ], + "depends_on": "BT_NIMBLE_ENABLED && BT_NIMBLE_50_FEATURE_SUPPORT && BT_NIMBLE_50_FEATURE_SUPPORT && BT_NIMBLE_ENABLED", + "help": "Enable GATT caching", + "id": "BT_NIMBLE_GATT_CACHING", + "is_menuconfig": true, + "name": "BT_NIMBLE_GATT_CACHING", + "range": null, + "title": "Enable GATT caching", + "type": "menu" + } + ], + "depends_on": "BT_NIMBLE_ENABLED && (SOC_BLE_50_SUPPORTED || !BT_CONTROLLER_ENABLED) && BT_NIMBLE_ENABLED", + "help": "Enable BLE 5 feature", + "id": "BT_NIMBLE_50_FEATURE_SUPPORT", + "is_menuconfig": true, + "name": "BT_NIMBLE_50_FEATURE_SUPPORT", + "range": null, + "title": "Enable BLE 5 feature", + "type": "menu" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_GATT_CACHING && BT_NIMBLE_ENABLED", + "help": "When client receives ATT out-of-sync error message, it will not automatically start the discovery procedure\nto correct the invalid cache.", + "id": "BT_NIMBLE_GATT_CACHING_DISABLE_AUTO", + "name": "BT_NIMBLE_GATT_CACHING_DISABLE_AUTO", + "range": null, + "title": "Do not start discovery procedure automatically upon receiving Out of Sync", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLED && BT_NIMBLE_ENABLED", + "help": "BLE list size", + "id": "BT_NIMBLE_WHITELIST_SIZE", + "name": "BT_NIMBLE_WHITELIST_SIZE", + "range": [ + 1, + 15 + ], + "title": "BLE white list size", + "type": "int" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLED", + "help": "Enable the throughput test mode", + "id": "BT_NIMBLE_TEST_THROUGHPUT_TEST", + "name": "BT_NIMBLE_TEST_THROUGHPUT_TEST", + "range": null, + "title": "Throughput Test Mode enable", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLED && BT_NIMBLE_ENABLED", + "help": "Set this option to enable blufi functionality.", + "id": "BT_NIMBLE_BLUFI_ENABLE", + "name": "BT_NIMBLE_BLUFI_ENABLE", + "range": null, + "title": "Enable blufi functionality", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLED", + "help": "Set this option to use Esp Timer which has higher priority timer instead of FreeRTOS timer", + "id": "BT_NIMBLE_USE_ESP_TIMER", + "name": "BT_NIMBLE_USE_ESP_TIMER", + "range": null, + "title": "Enable Esp Timer for Nimble", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLED", + "help": "This option is used to distinguish whether a previous version of VHCI is being used", + "id": "BT_NIMBLE_LEGACY_VHCI_ENABLE", + "name": "BT_NIMBLE_LEGACY_VHCI_ENABLE", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLED", + "help": "This option is used when data to be sent is more than 512 bytes. For peripheral role,\nBT_NIMBLE_MSYS_1_BLOCK_COUNT needs to be increased according to the need.", + "id": "BT_NIMBLE_BLE_GATT_BLOB_TRANSFER", + "name": "BT_NIMBLE_BLE_GATT_BLOB_TRANSFER", + "range": null, + "title": "Blob transfer", + "type": "bool" + }, + { + "children": [ + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "BT_NIMBLE_SVC_GAP_APPEAR_WRITE && BT_NIMBLE_ENABLED", + "help": "Enable write with encryption permission (BLE_GATT_CHR_F_WRITE_ENC)", + "id": "BT_NIMBLE_SVC_GAP_APPEAR_WRITE_ENC", + "name": "BT_NIMBLE_SVC_GAP_APPEAR_WRITE_ENC", + "range": null, + "title": "Write with encryption", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_SVC_GAP_APPEAR_WRITE && BT_NIMBLE_ENABLED", + "help": "Enable write with authentication permission (BLE_GATT_CHR_F_WRITE_AUTHEN)", + "id": "BT_NIMBLE_SVC_GAP_APPEAR_WRITE_AUTHEN", + "name": "BT_NIMBLE_SVC_GAP_APPEAR_WRITE_AUTHEN", + "range": null, + "title": "Write with authentication", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_SVC_GAP_APPEAR_WRITE && BT_NIMBLE_ENABLED", + "help": "Enable write with authorisation permission (BLE_GATT_CHR_F_WRITE_AUTHOR)", + "id": "BT_NIMBLE_SVC_GAP_APPEAR_WRITE_AUTHOR", + "name": "BT_NIMBLE_SVC_GAP_APPEAR_WRITE_AUTHOR", + "range": null, + "title": "Write with authorisation", + "type": "bool" + } + ], + "depends_on": "BT_NIMBLE_ENABLED", + "help": "Enable write permission (BLE_GATT_CHR_F_WRITE)", + "id": "BT_NIMBLE_SVC_GAP_APPEAR_WRITE", + "name": "BT_NIMBLE_SVC_GAP_APPEAR_WRITE", + "range": null, + "title": "Write", + "type": "bool" + } + ], + "depends_on": "BT_NIMBLE_ENABLED", + "id": "component-config-bluetooth-nimble-options-gap-service-gap-appearance-write-permissions", + "title": "GAP Appearance write permissions", + "type": "menu" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLED", + "help": null, + "id": "BT_NIMBLE_SVC_GAP_APPEAR_WRITE_PERM", + "name": "BT_NIMBLE_SVC_GAP_APPEAR_WRITE_PERM", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLED", + "help": null, + "id": "BT_NIMBLE_SVC_GAP_APPEAR_WRITE_PERM_ENC", + "name": "BT_NIMBLE_SVC_GAP_APPEAR_WRITE_PERM_ENC", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLED", + "help": null, + "id": "BT_NIMBLE_SVC_GAP_APPEAR_WRITE_PERM_ATHN", + "name": "BT_NIMBLE_SVC_GAP_APPEAR_WRITE_PERM_ATHN", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLED", + "help": null, + "id": "BT_NIMBLE_SVC_GAP_APPEAR_WRITE_PERM_ATHR", + "name": "BT_NIMBLE_SVC_GAP_APPEAR_WRITE_PERM_ATHR", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_NIMBLE_SVC_GAP_CAR_CHAR_NOT_SUPP", + "name": "BT_NIMBLE_SVC_GAP_CAR_CHAR_NOT_SUPP", + "range": null, + "title": "Characteristic not supported", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_NIMBLE_SVC_GAP_CAR_NOT_SUPP", + "name": "BT_NIMBLE_SVC_GAP_CAR_NOT_SUPP", + "range": null, + "title": "Central Address Resolution not supported", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_NIMBLE_SVC_GAP_CAR_SUPP", + "name": "BT_NIMBLE_SVC_GAP_CAR_SUPP", + "range": null, + "title": "Central Address Resolution supported", + "type": "bool" + } + ], + "depends_on": "BT_NIMBLE_ENABLED", + "help": "Weather or not Central Address Resolution characteristic is supported on\nthe device, and if supported, weather or not Central Address Resolution\nis supported.\n\n- Central Address Resolution characteristic not supported\n- Central Address Resolution not supported\n- Central Address Resolution supported", + "id": "component-config-bluetooth-nimble-options-gap-service-gap-characteristic-central-address-resolution", + "name": "BT_NIMBLE_SVC_GAP_CENT_ADDR_RESOLUTION", + "title": "GAP Characteristic - Central Address Resolution", + "type": "choice" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLED", + "help": null, + "id": "BT_NIMBLE_SVC_GAP_CENT_ADDR_RESOLUTION", + "name": "BT_NIMBLE_SVC_GAP_CENT_ADDR_RESOLUTION", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "BT_NIMBLE_SVC_GAP_NAME_WRITE && BT_NIMBLE_ENABLED", + "help": "Enable write with encryption permission (BLE_GATT_CHR_F_WRITE_ENC)", + "id": "BT_NIMBLE_SVC_GAP_NAME_WRITE_ENC", + "name": "BT_NIMBLE_SVC_GAP_NAME_WRITE_ENC", + "range": null, + "title": "Write with encryption", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_SVC_GAP_NAME_WRITE && BT_NIMBLE_ENABLED", + "help": "Enable write with authentication permission (BLE_GATT_CHR_F_WRITE_AUTHEN)", + "id": "BT_NIMBLE_SVC_GAP_NAME_WRITE_AUTHEN", + "name": "BT_NIMBLE_SVC_GAP_NAME_WRITE_AUTHEN", + "range": null, + "title": "Write with authentication", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_SVC_GAP_NAME_WRITE && BT_NIMBLE_ENABLED", + "help": "Enable write with authorisation permission (BLE_GATT_CHR_F_WRITE_AUTHOR)", + "id": "BT_NIMBLE_SVC_GAP_NAME_WRITE_AUTHOR", + "name": "BT_NIMBLE_SVC_GAP_NAME_WRITE_AUTHOR", + "range": null, + "title": "Write with authorisation", + "type": "bool" + } + ], + "depends_on": "BT_NIMBLE_ENABLED", + "help": "Enable write permission (BLE_GATT_CHR_F_WRITE)", + "id": "BT_NIMBLE_SVC_GAP_NAME_WRITE", + "name": "BT_NIMBLE_SVC_GAP_NAME_WRITE", + "range": null, + "title": "Write", + "type": "bool" + } + ], + "depends_on": "BT_NIMBLE_ENABLED", + "id": "component-config-bluetooth-nimble-options-gap-service-gap-device-name-write-permissions", + "title": "GAP device name write permissions", + "type": "menu" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLED", + "help": null, + "id": "BT_NIMBLE_SVC_GAP_NAME_WRITE_PERM", + "name": "BT_NIMBLE_SVC_GAP_NAME_WRITE_PERM", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLED", + "help": null, + "id": "BT_NIMBLE_SVC_GAP_NAME_WRITE_PERM_ENC", + "name": "BT_NIMBLE_SVC_GAP_NAME_WRITE_PERM_ENC", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLED", + "help": null, + "id": "BT_NIMBLE_SVC_GAP_NAME_WRITE_PERM_AUTHEN", + "name": "BT_NIMBLE_SVC_GAP_NAME_WRITE_PERM_AUTHEN", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLED", + "help": null, + "id": "BT_NIMBLE_SVC_GAP_NAME_WRITE_PERM_AUTHOR", + "name": "BT_NIMBLE_SVC_GAP_NAME_WRITE_PERM_AUTHOR", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_ROLE_PERIPHERAL && BT_NIMBLE_ENABLED", + "help": "Peripheral Preferred Connection Parameter: Connection Interval maximum value\nInterval Max = value * 1.25 ms", + "id": "BT_NIMBLE_SVC_GAP_PPCP_MAX_CONN_INTERVAL", + "name": "BT_NIMBLE_SVC_GAP_PPCP_MAX_CONN_INTERVAL", + "range": null, + "title": "PPCP Connection Interval Max (Unit: 1.25 ms)", + "type": "int" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_ROLE_PERIPHERAL && BT_NIMBLE_ENABLED", + "help": "Peripheral Preferred Connection Parameter: Connection Interval minimum value\nInterval Min = value * 1.25 ms", + "id": "BT_NIMBLE_SVC_GAP_PPCP_MIN_CONN_INTERVAL", + "name": "BT_NIMBLE_SVC_GAP_PPCP_MIN_CONN_INTERVAL", + "range": null, + "title": "PPCP Connection Interval Min (Unit: 1.25 ms)", + "type": "int" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLED", + "help": "Peripheral Preferred Connection Parameter: Slave Latency", + "id": "BT_NIMBLE_SVC_GAP_PPCP_SLAVE_LATENCY", + "name": "BT_NIMBLE_SVC_GAP_PPCP_SLAVE_LATENCY", + "range": null, + "title": "PPCP Slave Latency", + "type": "int" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLED", + "help": "Peripheral Preferred Connection Parameter: Supervision Timeout\nTimeout = Value * 10 ms", + "id": "BT_NIMBLE_SVC_GAP_PPCP_SUPERVISION_TMO", + "name": "BT_NIMBLE_SVC_GAP_PPCP_SUPERVISION_TMO", + "range": null, + "title": "PPCP Supervision Timeout (Uint: 10 ms)", + "type": "int" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLED", + "help": "Enable the LE GATT Security Level Characteristic", + "id": "BT_NIMBLE_SVC_GAP_GATT_SECURITY_LEVEL", + "name": "BT_NIMBLE_SVC_GAP_GATT_SECURITY_LEVEL", + "range": null, + "title": "LE GATT Security Level Characteristic", + "type": "bool" + } + ], + "depends_on": "BT_NIMBLE_ENABLED", + "id": "component-config-bluetooth-nimble-options-gap-service", + "title": "GAP Service", + "type": "menu" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "BT_NIMBLE_HID_SERVICE && BT_NIMBLE_ENABLED", + "help": "Defines maximum number of HID service instances", + "id": "BT_NIMBLE_SVC_HID_MAX_INSTANCES", + "name": "BT_NIMBLE_SVC_HID_MAX_INSTANCES", + "range": null, + "title": "Maximum HID service instances", + "type": "int" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_HID_SERVICE && BT_NIMBLE_ENABLED", + "help": "Defines maximum number of report characteristics per service instance", + "id": "BT_NIMBLE_SVC_HID_MAX_RPTS", + "name": "BT_NIMBLE_SVC_HID_MAX_RPTS", + "range": null, + "title": "Maximum HID Report characteristics per service instance", + "type": "int" + } + ], + "depends_on": "BT_NIMBLE_ENABLED && BT_NIMBLE_ENABLED", + "help": "Enable HID service support", + "id": "BT_NIMBLE_HID_SERVICE", + "is_menuconfig": true, + "name": "BT_NIMBLE_HID_SERVICE", + "range": null, + "title": "HID service", + "type": "menu" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLED && BT_NIMBLE_ENABLED", + "help": "Enable/Disable notifications on BAS Battery Level Characteristic", + "id": "BT_NIMBLE_SVC_BAS_BATTERY_LEVEL_NOTIFY", + "name": "BT_NIMBLE_SVC_BAS_BATTERY_LEVEL_NOTIFY", + "range": null, + "title": "BAS Battery Level NOTIFY permission", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLED && BT_NIMBLE_ENABLED", + "help": "Enable the DIS characteristic Manufacturer Name String characteristic", + "id": "BT_NIMBLE_SVC_DIS_MANUFACTURER_NAME", + "name": "BT_NIMBLE_SVC_DIS_MANUFACTURER_NAME", + "range": null, + "title": "Manufacturer Name", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLED && BT_NIMBLE_ENABLED", + "help": "Enable the DIS Serial Number characteristic", + "id": "BT_NIMBLE_SVC_DIS_SERIAL_NUMBER", + "name": "BT_NIMBLE_SVC_DIS_SERIAL_NUMBER", + "range": null, + "title": "Serial Number", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLED && BT_NIMBLE_ENABLED", + "help": "Enable the DIS Hardware Revision characteristic", + "id": "BT_NIMBLE_SVC_DIS_HARDWARE_REVISION", + "name": "BT_NIMBLE_SVC_DIS_HARDWARE_REVISION", + "range": null, + "title": "Hardware Revision", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLED && BT_NIMBLE_ENABLED", + "help": "Enable the DIS Firmware Revision characteristic", + "id": "BT_NIMBLE_SVC_DIS_FIRMWARE_REVISION", + "name": "BT_NIMBLE_SVC_DIS_FIRMWARE_REVISION", + "range": null, + "title": "Firmware Revision", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLED && BT_NIMBLE_ENABLED", + "help": "Enable the DIS Software Revision characteristic", + "id": "BT_NIMBLE_SVC_DIS_SOFTWARE_REVISION", + "name": "BT_NIMBLE_SVC_DIS_SOFTWARE_REVISION", + "range": null, + "title": "Software Revision", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLED && BT_NIMBLE_ENABLED", + "help": "Enable the DIS System ID characteristic", + "id": "BT_NIMBLE_SVC_DIS_SYSTEM_ID", + "name": "BT_NIMBLE_SVC_DIS_SYSTEM_ID", + "range": null, + "title": "System ID", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLED && BT_NIMBLE_ENABLED", + "help": "Enable the DIS PnP ID characteristic", + "id": "BT_NIMBLE_SVC_DIS_PNP_ID", + "name": "BT_NIMBLE_SVC_DIS_PNP_ID", + "range": null, + "title": "PnP ID", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLED && BT_NIMBLE_ENABLED", + "help": "Use DIS as an included service", + "id": "BT_NIMBLE_SVC_DIS_INCLUDED", + "name": "BT_NIMBLE_SVC_DIS_INCLUDED", + "range": null, + "title": "DIS as an Included Service", + "type": "bool" + } + ], + "depends_on": "BT_NIMBLE_ENABLED", + "id": "component-config-bluetooth-nimble-options-ble-services-device-information-service", + "title": "Device Information Service", + "type": "menu" + } + ], + "depends_on": "BT_NIMBLE_ENABLED", + "id": "component-config-bluetooth-nimble-options-ble-services", + "title": "BLE Services", + "type": "menu" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLED", + "help": "This option is used to enable support for sending Vendor Specific HCI commands and handling\nVendor Specific HCI Events.", + "id": "BT_NIMBLE_VS_SUPPORT", + "name": "BT_NIMBLE_VS_SUPPORT", + "range": null, + "title": "Enable support for VSC and VSE", + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_BLE_MULTI_CONN_OPTIMIZATION && BT_NIMBLE_ENABLED", + "help": "This option enables the use of vendor-specific APIs for multi-connections, which can\ngreatly enhance the stability of coexistence between numerous central and peripheral\ndevices. It will prohibit the usage of standard APIs.", + "id": "BT_NIMBLE_OPTIMIZE_MULTI_CONN", + "name": "BT_NIMBLE_OPTIMIZE_MULTI_CONN", + "range": null, + "title": "Enable the optimization of multi-connection", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLED && BT_NIMBLE_ENC_ADV_DATA && BT_NIMBLE_ENABLED", + "help": "Defines maximum number of encrypted advertising data key material to save", + "id": "BT_NIMBLE_MAX_EADS", + "name": "BT_NIMBLE_MAX_EADS", + "range": null, + "title": "Maximum number of EAD devices to save across reboots", + "type": "int" + } + ], + "depends_on": "BT_NIMBLE_ENABLED", + "help": "This option is used to enable encrypted advertising data.", + "id": "BT_NIMBLE_ENC_ADV_DATA", + "name": "BT_NIMBLE_ENC_ADV_DATA", + "range": null, + "title": "Encrypted Advertising Data", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLED && BT_NIMBLE_ENABLED", + "help": "This enable BLE high duty advertising interval feature", + "id": "BT_NIMBLE_HIGH_DUTY_ADV_ITVL", + "name": "BT_NIMBLE_HIGH_DUTY_ADV_ITVL", + "range": null, + "title": "Enable BLE high duty advertising interval feature", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLED && (IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S3) && BT_NIMBLE_ENABLED", + "help": "This enables support for user to initiate a new connection with scan in progress", + "id": "BT_NIMBLE_HOST_ALLOW_CONNECT_WITH_SCAN", + "name": "BT_NIMBLE_HOST_ALLOW_CONNECT_WITH_SCAN", + "range": null, + "title": "Allow Connections with scanning in progress", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLED && BT_NIMBLE_ENABLED", + "help": "When scanning and scan duplicate is not enabled, if there are a lot of adv packets around\nor application layer handling adv packets is slow, it will cause the controller memory\nto run out. if enabled, adv packets will be lost when host queue is congested.", + "id": "BT_NIMBLE_HOST_QUEUE_CONG_CHECK", + "name": "BT_NIMBLE_HOST_QUEUE_CONG_CHECK", + "range": null, + "title": "BLE queue congestion check", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLED && BT_NIMBLE_ENABLED", + "help": "When BLE and Wireless protocol/IEEE 802.15.4 operate in coexistence, BLE preemption\ncan disrupt the GATT context,causing the service discovery callback to not be invoked.\nA temporary list is maintained to preserve the GATT context and use it in case of preemption.", + "id": "BT_NIMBLE_GATTC_PROC_PREEMPTION_PROTECT", + "name": "BT_NIMBLE_GATTC_PROC_PREEMPTION_PROTECT", + "range": null, + "title": "Gatt-proc preemption protect check", + "type": "bool" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "BT_CONTROLLER_DISABLED && BT_NIMBLE_TRANSPORT_UART && BT_NIMBLE_ENABLED", + "help": "Uart port", + "id": "BT_NIMBLE_TRANSPORT_UART_PORT", + "name": "BT_NIMBLE_TRANSPORT_UART_PORT", + "range": null, + "title": "Uart port", + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "UART_BAUDRATE_115200", + "name": "UART_BAUDRATE_115200", + "range": null, + "title": "115200", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "UART_BAUDRATE_230400", + "name": "UART_BAUDRATE_230400", + "range": null, + "title": "230400", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "UART_BAUDRATE_460800", + "name": "UART_BAUDRATE_460800", + "range": null, + "title": "460800", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "UART_BAUDRATE_921600", + "name": "UART_BAUDRATE_921600", + "range": null, + "title": "921600", + "type": "bool" + } + ], + "depends_on": "BT_CONTROLLER_DISABLED && BT_NIMBLE_TRANSPORT_UART && BT_NIMBLE_ENABLED", + "help": "Uart Baud Rate", + "id": "component-config-bluetooth-nimble-options-host-controller-transport-enable-uart-transport-uart-hci-baud-rate", + "name": "BT_NIMBLE_HCI_USE_UART_BAUDRATE", + "title": "Uart Hci Baud Rate", + "type": "choice" + }, + { + "children": [], + "depends_on": "BT_CONTROLLER_DISABLED && BT_NIMBLE_TRANSPORT_UART && BT_NIMBLE_ENABLED", + "help": null, + "id": "BT_NIMBLE_HCI_UART_BAUDRATE", + "name": "BT_NIMBLE_HCI_UART_BAUDRATE", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "UART_PARITY_NONE", + "name": "UART_PARITY_NONE", + "range": null, + "title": "None", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "UART_PARITY_ODD", + "name": "UART_PARITY_ODD", + "range": null, + "title": "Odd", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "UART_PARITY_EVEN", + "name": "UART_PARITY_EVEN", + "range": null, + "title": "Even", + "type": "bool" + } + ], + "depends_on": "BT_CONTROLLER_DISABLED && BT_NIMBLE_TRANSPORT_UART && BT_NIMBLE_ENABLED", + "help": "Uart Parity", + "id": "component-config-bluetooth-nimble-options-host-controller-transport-enable-uart-transport-uart-parity", + "name": "BT_NIMBLE_USE_HCI_UART_PARITY", + "title": "Uart PARITY", + "type": "choice" + }, + { + "children": [], + "depends_on": "BT_CONTROLLER_DISABLED && BT_NIMBLE_TRANSPORT_UART && BT_NIMBLE_ENABLED", + "help": null, + "id": "BT_NIMBLE_TRANSPORT_UART_PARITY_NONE", + "name": "BT_NIMBLE_TRANSPORT_UART_PARITY_NONE", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": "BT_CONTROLLER_DISABLED && BT_NIMBLE_TRANSPORT_UART && BT_NIMBLE_ENABLED", + "help": null, + "id": "BT_NIMBLE_TRANSPORT_UART_PARITY_ODD", + "name": "BT_NIMBLE_TRANSPORT_UART_PARITY_ODD", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": "BT_CONTROLLER_DISABLED && BT_NIMBLE_TRANSPORT_UART && BT_NIMBLE_ENABLED", + "help": null, + "id": "BT_NIMBLE_TRANSPORT_UART_PARITY_EVEN", + "name": "BT_NIMBLE_TRANSPORT_UART_PARITY_EVEN", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": "BT_CONTROLLER_DISABLED && BT_NIMBLE_TRANSPORT_UART && BT_NIMBLE_ENABLED", + "help": "Rx pin for Nimble Transport", + "id": "BT_NIMBLE_UART_RX_PIN", + "name": "BT_NIMBLE_UART_RX_PIN", + "range": null, + "title": "UART Rx pin", + "type": "int" + }, + { + "children": [], + "depends_on": "BT_CONTROLLER_DISABLED && BT_NIMBLE_TRANSPORT_UART && BT_NIMBLE_ENABLED", + "help": "Tx pin for Nimble Transport", + "id": "BT_NIMBLE_UART_TX_PIN", + "name": "BT_NIMBLE_UART_TX_PIN", + "range": null, + "title": "UART Tx pin", + "type": "int" + } + ], + "depends_on": "BT_CONTROLLER_DISABLED && BT_NIMBLE_ENABLED", + "help": "Use UART transport", + "id": "BT_NIMBLE_TRANSPORT_UART", + "name": "BT_NIMBLE_TRANSPORT_UART", + "range": null, + "title": "Enable Uart Transport", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "UART_HW_FLOWCTRL_DISABLE", + "name": "UART_HW_FLOWCTRL_DISABLE", + "range": null, + "title": "Disable", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "UART_HW_FLOWCTRL_CTS_RTS", + "name": "UART_HW_FLOWCTRL_CTS_RTS", + "range": null, + "title": "Enable hardware flow control", + "type": "bool" + } + ], + "depends_on": "BT_NIMBLE_ENABLED", + "help": "Uart Flow Control", + "id": "component-config-bluetooth-nimble-options-host-controller-transport-uart-flow-control", + "name": "BT_NIMBLE_USE_HCI_UART_FLOW_CTRL", + "title": "Uart Flow Control", + "type": "choice" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLED", + "help": null, + "id": "BT_NIMBLE_HCI_UART_FLOW_CTRL", + "name": "BT_NIMBLE_HCI_UART_FLOW_CTRL", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLED", + "help": "UART HCI RTS pin", + "id": "BT_NIMBLE_HCI_UART_RTS_PIN", + "name": "BT_NIMBLE_HCI_UART_RTS_PIN", + "range": null, + "title": "UART Rts Pin", + "type": "int" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLED", + "help": "UART HCI CTS pin", + "id": "BT_NIMBLE_HCI_UART_CTS_PIN", + "name": "BT_NIMBLE_HCI_UART_CTS_PIN", + "range": null, + "title": "UART Cts Pin", + "type": "int" + } + ], + "depends_on": "BT_NIMBLE_ENABLED", + "id": "component-config-bluetooth-nimble-options-host-controller-transport", + "title": "Host-controller Transport", + "type": "menu" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLED && BT_NIMBLE_ENABLED", + "help": "Defines the number of channels EATT bearers can use", + "id": "BT_NIMBLE_EATT_CHAN_NUM", + "name": "BT_NIMBLE_EATT_CHAN_NUM", + "range": null, + "title": "Maximum number of EATT channels", + "type": "int" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLED && BT_NIMBLE_ENABLED", + "help": "Enable connection subrate change feature", + "id": "BT_NIMBLE_SUBRATE", + "name": "BT_NIMBLE_SUBRATE", + "range": null, + "title": "Enable Subrate Change", + "type": "bool" + } + ], + "depends_on": "BT_NIMBLE_ENABLED", + "id": "component-config-bluetooth-nimble-options", + "title": "NimBLE Options", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": "BT_CONTROLLER_ENABLED", + "help": null, + "id": "BT_CTRL_MODE_EFF", + "name": "BT_CTRL_MODE_EFF", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": "BT_CONTROLLER_ENABLED", + "help": "BLE maximum activities of bluetooth controller\uff0cboth of connections,\nscan , sync and adv(periodic adv, multi-adv). Each instance needs to\nconsume 828 bytes, you can save RAM by modifying the instance value\naccording to actual needs.", + "id": "BT_CTRL_BLE_MAX_ACT", + "name": "BT_CTRL_BLE_MAX_ACT", + "range": [ + 1, + 10 + ], + "title": "BLE Max Instances", + "type": "int" + }, + { + "children": [], + "depends_on": "BT_CONTROLLER_ENABLED", + "help": null, + "id": "BT_CTRL_BLE_MAX_ACT_EFF", + "name": "BT_CTRL_BLE_MAX_ACT_EFF", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": "BT_CONTROLLER_ENABLED", + "help": "BLE ACL buffer have two methods to be allocated. One is persistent allocating\n(allocate when controller initialise, never free until controller de-initialise)\nanother is dynamically allocating (allocate before TX and free after TX).", + "id": "BT_CTRL_BLE_STATIC_ACL_TX_BUF_NB", + "name": "BT_CTRL_BLE_STATIC_ACL_TX_BUF_NB", + "range": [ + 0, + 12 + ], + "title": "BLE static ACL TX buffer numbers", + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_CTRL_PINNED_TO_CORE_0", + "name": "BT_CTRL_PINNED_TO_CORE_0", + "range": null, + "title": "Core 0 (PRO CPU)", + "type": "bool" + }, + { + "children": [], + "depends_on": "!FREERTOS_UNICORE && ", + "help": null, + "id": "BT_CTRL_PINNED_TO_CORE_1", + "name": "BT_CTRL_PINNED_TO_CORE_1", + "range": null, + "title": "Core 1 (APP CPU)", + "type": "bool" + } + ], + "depends_on": "!FREERTOS_UNICORE && BT_CONTROLLER_ENABLED", + "help": "Specify the cpu core to run bluetooth controller.\nCan not specify no-affinity.", + "id": "component-config-bluetooth-controller-options-the-cpu-core-which-bluetooth-controller-run", + "name": "BT_CTRL_PINNED_TO_CORE_CHOICE", + "title": "The cpu core which bluetooth controller run", + "type": "choice" + }, + { + "children": [], + "depends_on": "BT_CONTROLLER_ENABLED", + "help": null, + "id": "BT_CTRL_PINNED_TO_CORE", + "name": "BT_CTRL_PINNED_TO_CORE", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": "Normal option. Mostly, choose this VHCI when bluetooth host run on ESP32S3 or ESP32C3.", + "id": "BT_CTRL_HCI_MODE_VHCI", + "name": "BT_CTRL_HCI_MODE_VHCI", + "range": null, + "title": "VHCI", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": "If use external bluetooth host which run on other hardware and use UART as the HCI interface,\nchoose this option.", + "id": "BT_CTRL_HCI_MODE_UART_H4", + "name": "BT_CTRL_HCI_MODE_UART_H4", + "range": null, + "title": "UART(H4)", + "type": "bool" + } + ], + "depends_on": "BT_CONTROLLER_ENABLED", + "help": "Specify HCI mode as VHCI or UART(H4)", + "id": "component-config-bluetooth-controller-options-hci-mode", + "name": "BT_CTRL_HCI_MODE_CHOICE", + "title": "HCI mode", + "type": "choice" + }, + { + "children": [], + "depends_on": "BT_CONTROLLER_ENABLED", + "help": "HCI mode as VHCI or UART(H4)", + "id": "BT_CTRL_HCI_TL", + "name": "BT_CTRL_HCI_TL", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": "BT_CONTROLLER_ENABLED", + "help": "The maximum number of 5.0 extend duplicate", + "id": "BT_CTRL_ADV_DUP_FILT_MAX", + "name": "BT_CTRL_ADV_DUP_FILT_MAX", + "range": [ + 1, + 500 + ], + "title": "The maximum number of 5.0 extend duplicate scan filter", + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_BLE_CCA_MODE_NONE", + "name": "BT_BLE_CCA_MODE_NONE", + "range": null, + "title": "NONE", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_BLE_CCA_MODE_HW", + "name": "BT_BLE_CCA_MODE_HW", + "range": null, + "title": "Hardware", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_BLE_CCA_MODE_SW", + "name": "BT_BLE_CCA_MODE_SW", + "range": null, + "title": "Software", + "type": "bool" + } + ], + "depends_on": "BT_CONTROLLER_ENABLED", + "help": "Define BT BLE CCA mode", + "id": "component-config-bluetooth-controller-options-ble-cca-mode", + "name": "BT_BLE_CCA_MODE", + "title": "BLE CCA mode", + "type": "choice" + }, + { + "children": [], + "depends_on": "BT_CONTROLLER_ENABLED", + "help": null, + "id": "BT_BLE_CCA_MODE", + "name": "BT_BLE_CCA_MODE", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": "BT_CONTROLLER_ENABLED", + "help": "It is the threshold value of HW CCA, if the value is 30, it means CCA threshold is -30 dBm.", + "id": "BT_CTRL_HW_CCA_VAL", + "name": "BT_CTRL_HW_CCA_VAL", + "range": [ + 20, + 100 + ], + "title": "CCA threshold value", + "type": "int" + }, + { + "children": [], + "depends_on": "BT_CONTROLLER_ENABLED", + "help": "If other devices are sending packets in the air and the signal is strong,\nthe packet hw to be sent this time is cancelled.", + "id": "BT_CTRL_HW_CCA_EFF", + "name": "BT_CTRL_HW_CCA_EFF", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_CTRL_CE_LENGTH_TYPE_ORIG", + "name": "BT_CTRL_CE_LENGTH_TYPE_ORIG", + "range": null, + "title": "ORIGINAL", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_CTRL_CE_LENGTH_TYPE_CE", + "name": "BT_CTRL_CE_LENGTH_TYPE_CE", + "range": null, + "title": "Use CE parameter for HCI command", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_CTRL_CE_LENGTH_TYPE_SD", + "name": "BT_CTRL_CE_LENGTH_TYPE_SD", + "range": null, + "title": "Use Espressif self-defined method", + "type": "bool" + } + ], + "depends_on": "BT_CONTROLLER_ENABLED", + "help": "Specify connection event length determination", + "id": "component-config-bluetooth-controller-options-connection-event-length-determination-method", + "name": "BT_CTRL_CE_LENGTH_TYPE", + "title": "Connection event length determination method", + "type": "choice" + }, + { + "children": [], + "depends_on": "BT_CONTROLLER_ENABLED", + "help": null, + "id": "BT_CTRL_CE_LENGTH_TYPE_EFF", + "name": "BT_CTRL_CE_LENGTH_TYPE_EFF", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_CTRL_TX_ANTENNA_INDEX_0", + "name": "BT_CTRL_TX_ANTENNA_INDEX_0", + "range": null, + "title": "Antenna 0", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_CTRL_TX_ANTENNA_INDEX_1", + "name": "BT_CTRL_TX_ANTENNA_INDEX_1", + "range": null, + "title": "Antenna 1", + "type": "bool" + } + ], + "depends_on": "BT_CONTROLLER_ENABLED", + "help": "Specify default Tx antenna used for bluetooth", + "id": "component-config-bluetooth-controller-options-default-tx-anntena-used", + "name": "BT_CTRL_TX_ANTENNA_INDEX", + "title": "default Tx anntena used", + "type": "choice" + }, + { + "children": [], + "depends_on": "BT_CONTROLLER_ENABLED", + "help": null, + "id": "BT_CTRL_TX_ANTENNA_INDEX_EFF", + "name": "BT_CTRL_TX_ANTENNA_INDEX_EFF", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_CTRL_RX_ANTENNA_INDEX_0", + "name": "BT_CTRL_RX_ANTENNA_INDEX_0", + "range": null, + "title": "Antenna 0", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_CTRL_RX_ANTENNA_INDEX_1", + "name": "BT_CTRL_RX_ANTENNA_INDEX_1", + "range": null, + "title": "Antenna 1", + "type": "bool" + } + ], + "depends_on": "BT_CONTROLLER_ENABLED", + "help": "Specify default Rx antenna used for bluetooth", + "id": "component-config-bluetooth-controller-options-default-rx-anntena-used", + "name": "BT_CTRL_RX_ANTENNA_INDEX", + "title": "default Rx anntena used", + "type": "choice" + }, + { + "children": [], + "depends_on": "BT_CONTROLLER_ENABLED", + "help": null, + "id": "BT_CTRL_RX_ANTENNA_INDEX_EFF", + "name": "BT_CTRL_RX_ANTENNA_INDEX_EFF", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_CTRL_DFT_TX_POWER_LEVEL_N24", + "name": "BT_CTRL_DFT_TX_POWER_LEVEL_N24", + "range": null, + "title": "-24dBm", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_CTRL_DFT_TX_POWER_LEVEL_N21", + "name": "BT_CTRL_DFT_TX_POWER_LEVEL_N21", + "range": null, + "title": "-21dBm", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_CTRL_DFT_TX_POWER_LEVEL_N18", + "name": "BT_CTRL_DFT_TX_POWER_LEVEL_N18", + "range": null, + "title": "-18dBm", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_CTRL_DFT_TX_POWER_LEVEL_N15", + "name": "BT_CTRL_DFT_TX_POWER_LEVEL_N15", + "range": null, + "title": "-15dBm", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_CTRL_DFT_TX_POWER_LEVEL_N12", + "name": "BT_CTRL_DFT_TX_POWER_LEVEL_N12", + "range": null, + "title": "-12dBm", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_CTRL_DFT_TX_POWER_LEVEL_N9", + "name": "BT_CTRL_DFT_TX_POWER_LEVEL_N9", + "range": null, + "title": "-9dBm", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_CTRL_DFT_TX_POWER_LEVEL_N6", + "name": "BT_CTRL_DFT_TX_POWER_LEVEL_N6", + "range": null, + "title": "-6dBm", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_CTRL_DFT_TX_POWER_LEVEL_N3", + "name": "BT_CTRL_DFT_TX_POWER_LEVEL_N3", + "range": null, + "title": "-3dBm", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_CTRL_DFT_TX_POWER_LEVEL_N0", + "name": "BT_CTRL_DFT_TX_POWER_LEVEL_N0", + "range": null, + "title": "0dBm", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_CTRL_DFT_TX_POWER_LEVEL_P3", + "name": "BT_CTRL_DFT_TX_POWER_LEVEL_P3", + "range": null, + "title": "+3dBm", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_CTRL_DFT_TX_POWER_LEVEL_P6", + "name": "BT_CTRL_DFT_TX_POWER_LEVEL_P6", + "range": null, + "title": "+6dBm", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_CTRL_DFT_TX_POWER_LEVEL_P9", + "name": "BT_CTRL_DFT_TX_POWER_LEVEL_P9", + "range": null, + "title": "+9dBm", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_CTRL_DFT_TX_POWER_LEVEL_P12", + "name": "BT_CTRL_DFT_TX_POWER_LEVEL_P12", + "range": null, + "title": "+12dBm", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_CTRL_DFT_TX_POWER_LEVEL_P15", + "name": "BT_CTRL_DFT_TX_POWER_LEVEL_P15", + "range": null, + "title": "+15dBm", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_CTRL_DFT_TX_POWER_LEVEL_P18", + "name": "BT_CTRL_DFT_TX_POWER_LEVEL_P18", + "range": null, + "title": "+18dBm", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BT_CTRL_DFT_TX_POWER_LEVEL_P20", + "name": "BT_CTRL_DFT_TX_POWER_LEVEL_P20", + "range": null, + "title": "+20dBm", + "type": "bool" + } + ], + "depends_on": "BT_CONTROLLER_ENABLED", + "help": "Specify default Tx power level", + "id": "component-config-bluetooth-controller-options-ble-default-tx-power-level", + "name": "BT_CTRL_DFT_TX_POWER_LEVEL", + "title": "BLE default Tx power level", + "type": "choice" + }, + { + "children": [], + "depends_on": "BT_CONTROLLER_ENABLED", + "help": null, + "id": "BT_CTRL_DFT_TX_POWER_LEVEL_EFF", + "name": "BT_CTRL_DFT_TX_POWER_LEVEL_EFF", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "BT_CTRL_BLE_ADV_REPORT_FLOW_CTRL_SUPP && BT_CONTROLLER_ENABLED", + "help": "The number of unprocessed advertising report that bluetooth host can save.If you set\n`BT_CTRL_BLE_ADV_REPORT_FLOW_CTRL_NUM` to a small value, this may cause adv packets lost.\nIf you set `BT_CTRL_BLE_ADV_REPORT_FLOW_CTRL_NUM` to a large value, bluetooth host may cache a\nlot of adv packets and this may cause system memory run out. For example, if you set\nit to 50, the maximum memory consumed by host is 35 * 50 bytes. Please set\n`BT_CTRL_BLE_ADV_REPORT_FLOW_CTRL_NUM` according to your system free memory and handle adv\npackets as fast as possible, otherwise it will cause adv packets lost.", + "id": "BT_CTRL_BLE_ADV_REPORT_FLOW_CTRL_NUM", + "name": "BT_CTRL_BLE_ADV_REPORT_FLOW_CTRL_NUM", + "range": [ + 50, + 1000 + ], + "title": "BLE adv report flow control number", + "type": "int" + }, + { + "children": [], + "depends_on": "BT_CTRL_BLE_ADV_REPORT_FLOW_CTRL_SUPP && BT_CONTROLLER_ENABLED", + "help": "When adv report flow control is enabled, The ADV lost event will be generated when the number\nof ADV packets lost in the controller reaches this threshold. It is better to set a larger value.\nIf you set `BT_CTRL_BLE_ADV_REPORT_DISCARD_THRSHOLD` to a small value or printf every adv lost event, it\nmay cause adv packets lost more.", + "id": "BT_CTRL_BLE_ADV_REPORT_DISCARD_THRSHOLD", + "name": "BT_CTRL_BLE_ADV_REPORT_DISCARD_THRSHOLD", + "range": [ + 1, + 1000 + ], + "title": "BLE adv lost event threshold value", + "type": "int" + } + ], + "depends_on": "(!BT_CTRL_RUN_IN_FLASH_ONLY || (BT_CTRL_RUN_IN_FLASH_ONLY && BT_CTRL_BLE_SCAN)) && BT_CONTROLLER_ENABLED", + "help": "The function is mainly used to enable flow control for advertising reports. When it is enabled,\nadvertising reports will be discarded by the controller if the number of unprocessed advertising\nreports exceeds the size of BLE adv report flow control.", + "id": "BT_CTRL_BLE_ADV_REPORT_FLOW_CTRL_SUPP", + "name": "BT_CTRL_BLE_ADV_REPORT_FLOW_CTRL_SUPP", + "range": null, + "title": "BLE adv report flow control supported", + "type": "bool" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "", + "help": "Advertising packets with the same address, address type, and advertising type are reported once.", + "id": "BT_CTRL_SCAN_DUPL_TYPE_DEVICE", + "name": "BT_CTRL_SCAN_DUPL_TYPE_DEVICE", + "range": null, + "title": "Scan Duplicate By Device Address", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": "Advertising packets with identical advertising data, address type, and advertising type\nare reported only once, even if they originate from different devices.", + "id": "BT_CTRL_SCAN_DUPL_TYPE_DATA", + "name": "BT_CTRL_SCAN_DUPL_TYPE_DATA", + "range": null, + "title": "Scan Duplicate By Advertising Data", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": "Advertising packets with the same address, advertising data, address type,\nand advertising type are reported only once.", + "id": "BT_CTRL_SCAN_DUPL_TYPE_DATA_DEVICE", + "name": "BT_CTRL_SCAN_DUPL_TYPE_DATA_DEVICE", + "range": null, + "title": "Scan Duplicate By Device Address And Advertising Data", + "type": "bool" + } + ], + "depends_on": "BT_CTRL_BLE_SCAN_DUPL && BT_CONTROLLER_ENABLED", + "help": "Scan duplicate have three ways. one is \"Scan Duplicate By Device Address\", This way is to use\nadvertiser address filtering. The adv packet of the same address is only allowed to be reported once.\nAnother way is \"Scan Duplicate By Device Address And Advertising Data\". This way is to use advertising\ndata and device address filtering. All different adv packets with the same address are allowed to be\nreported. The last way is \"Scan Duplicate By Advertising Data\". This way is to use advertising data\nfiltering. All same advertising data only allow to be reported once even though they are from\ndifferent devices.", + "id": "component-config-bluetooth-controller-options-ble-scan-duplicate-options-scan-duplicate-type", + "name": "BT_CTRL_SCAN_DUPL_TYPE", + "title": "Scan Duplicate Type", + "type": "choice" + }, + { + "children": [], + "depends_on": "BT_CTRL_BLE_SCAN_DUPL && BT_CONTROLLER_ENABLED", + "help": null, + "id": "BT_CTRL_SCAN_DUPL_TYPE", + "name": "BT_CTRL_SCAN_DUPL_TYPE", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": "BT_CTRL_BLE_SCAN_DUPL && BT_CONTROLLER_ENABLED", + "help": "Maximum number of devices which can be recorded in scan duplicate filter.\nWhen the maximum amount of device in the filter is reached, the cache will be refreshed.", + "id": "BT_CTRL_SCAN_DUPL_CACHE_SIZE", + "name": "BT_CTRL_SCAN_DUPL_CACHE_SIZE", + "range": [ + 10, + 1000 + ], + "title": "Maximum number of devices in scan duplicate filter", + "type": "int" + }, + { + "children": [], + "depends_on": "BT_CTRL_BLE_SCAN_DUPL && BT_CONTROLLER_ENABLED", + "help": "If the period value is non-zero, the controller will periodically clear the device information\nstored in the scan duuplicate filter. If it is 0, the scan duuplicate filter will not be cleared\nuntil the scanning is disabled. Duplicate advertisements for this period should not be sent to the\nHost in advertising report events.\nThere are two scenarios where the ADV packet will be repeatedly reported:\n1. The duplicate scan cache is full, the controller will delete the oldest device information and\nadd new device information.\n2. When the refresh period is up, the controller will clear all device information and start filtering\nagain.", + "id": "BT_CTRL_DUPL_SCAN_CACHE_REFRESH_PERIOD", + "name": "BT_CTRL_DUPL_SCAN_CACHE_REFRESH_PERIOD", + "range": [ + 0, + 1000 + ], + "title": "Duplicate scan list refresh period (seconds)", + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "BT_CTRL_BLE_MESH_SCAN_DUPL_EN && BT_CONTROLLER_ENABLED", + "help": "Maximum number of adv packets which can be recorded in duplicate scan cache for BLE Mesh.\nWhen the maximum amount of device in the filter is reached, the cache will be refreshed.", + "id": "BT_CTRL_MESH_DUPL_SCAN_CACHE_SIZE", + "name": "BT_CTRL_MESH_DUPL_SCAN_CACHE_SIZE", + "range": null, + "title": "Maximum number of Mesh adv packets in scan duplicate filter", + "type": "int" + } + ], + "depends_on": "BT_CTRL_BLE_SCAN_DUPL && BT_CONTROLLER_ENABLED", + "help": "This enables the BLE scan duplicate for special BLE Mesh scan.", + "id": "BT_CTRL_BLE_MESH_SCAN_DUPL_EN", + "name": "BT_CTRL_BLE_MESH_SCAN_DUPL_EN", + "range": null, + "title": "Special duplicate scan mechanism for BLE Mesh scan", + "type": "bool" + } + ], + "depends_on": "BT_CONTROLLER_ENABLED", + "help": "This select enables parameters setting of BLE scan duplicate.", + "id": "BT_CTRL_BLE_SCAN_DUPL", + "name": "BT_CTRL_BLE_SCAN_DUPL", + "range": null, + "title": "BLE Scan Duplicate Options", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": "Always enable the limitation on max tx/rx time for Coded-PHY connection", + "id": "BT_CTRL_COEX_PHY_CODED_TX_RX_TLIM_EN", + "name": "BT_CTRL_COEX_PHY_CODED_TX_RX_TLIM_EN", + "range": null, + "title": "Force Enable", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": "Disable the limitation on max tx/rx time for Coded-PHY connection", + "id": "BT_CTRL_COEX_PHY_CODED_TX_RX_TLIM_DIS", + "name": "BT_CTRL_COEX_PHY_CODED_TX_RX_TLIM_DIS", + "range": null, + "title": "Force Disable", + "type": "bool" + } + ], + "depends_on": "ESP_COEX_SW_COEXIST_ENABLE && BT_CONTROLLER_ENABLED", + "help": "When using PHY-Coded in BLE connection, limitation on max tx/rx time can be applied to\nbetter avoid dramatic performance deterioration of Wi-Fi.", + "id": "component-config-bluetooth-controller-options-coexistence-limit-on-max-tx-rx-time-for-coded-phy-connection", + "name": "BT_CTRL_COEX_PHY_CODED_TX_RX_TLIM", + "title": "Coexistence: limit on MAX Tx/Rx time for coded-PHY connection", + "type": "choice" + }, + { + "children": [], + "depends_on": "BT_CONTROLLER_ENABLED", + "help": null, + "id": "BT_CTRL_COEX_PHY_CODED_TX_RX_TLIM_EFF", + "name": "BT_CTRL_COEX_PHY_CODED_TX_RX_TLIM_EFF", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [ + { + "children": [ + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "", + "help": "Main crystal can be used as low power clock for bluetooth modem sleep. If this option is\nselected, bluetooth modem sleep can work under Dynamic Frequency Scaling(DFS) enabled, and\nbluetooth can work under light sleep enabled. Main crystal has a relatively better performance\nthan other bluetooth low power clock sources.", + "id": "BT_CTRL_LPCLK_SEL_MAIN_XTAL", + "name": "BT_CTRL_LPCLK_SEL_MAIN_XTAL", + "range": null, + "title": "Main crystal", + "type": "bool" + }, + { + "children": [], + "depends_on": "(RTC_CLK_SRC_EXT_CRYS || RTC_CLK_SRC_EXT_OSC) && ", + "help": "External 32kHz crystal/oscillator has a nominal frequency of 32.768kHz and provides good frequency\nstability. If used as Bluetooth low power clock, External 32kHz can support Bluetooth\nmodem sleep to be used with both DFS and light sleep.", + "id": "BT_CTRL_LPCLK_SEL_EXT_32K_XTAL", + "name": "BT_CTRL_LPCLK_SEL_EXT_32K_XTAL", + "range": null, + "title": "External 32kHz crystal/oscillator", + "type": "bool" + }, + { + "children": [], + "depends_on": "RTC_CLK_SRC_INT_RC && ", + "help": "Internal 150kHz RC oscillator. The accuracy of this clock is a lot larger than 500ppm which is required\nin Bluetooth communication, so don't select this option in scenarios such as BLE connection state.", + "id": "BT_CTRL_LPCLK_SEL_RTC_SLOW", + "name": "BT_CTRL_LPCLK_SEL_RTC_SLOW", + "range": null, + "title": "Internal 150kHz RC oscillator", + "type": "bool" + } + ], + "depends_on": "BT_CTRL_MODEM_SLEEP_MODE_1 && BT_CONTROLLER_ENABLED", + "help": "Select the low power clock source for bluetooth controller", + "id": "component-config-bluetooth-controller-options-modem-sleep-options-bluetooth-modem-sleep-bluetooth-modem-sleep-mode-1-bluetooth-low-power-clock", + "name": "BT_CTRL_LOW_POWER_CLOCK", + "title": "Bluetooth low power clock", + "type": "choice" + } + ], + "depends_on": "BT_CTRL_MODEM_SLEEP && BT_CONTROLLER_ENABLED", + "help": "Mode 1 is the currently supported sleep mode. In this mode,\nbluetooth controller sleeps between and BLE events. A low\npower clock is used to maintain bluetooth reference clock.", + "id": "BT_CTRL_MODEM_SLEEP_MODE_1", + "name": "BT_CTRL_MODEM_SLEEP_MODE_1", + "range": null, + "title": "Bluetooth Modem sleep Mode 1", + "type": "bool" + } + ], + "depends_on": "!BT_CTRL_HCI_MODE_UART_H4 && BT_CONTROLLER_ENABLED", + "help": "Enable/disable bluetooth controller low power mode.\nModem sleep is not supported to be used with UART HCI.", + "id": "BT_CTRL_MODEM_SLEEP", + "name": "BT_CTRL_MODEM_SLEEP", + "range": null, + "title": "Bluetooth modem sleep", + "type": "bool" + }, + { + "children": [], + "depends_on": "(BT_CTRL_LPCLK_SEL_MAIN_XTAL || BT_CTRL_LPCLK_SEL_EXT_32K_XTAL) && FREERTOS_USE_TICKLESS_IDLE && BT_CONTROLLER_ENABLED", + "help": "If this option is selected, the main crystal will power up during light sleep when the low power clock\nselects an external 32kHz crystal but the external 32kHz crystal does not exist or the low power clock\nselects the main crystal.", + "id": "BT_CTRL_MAIN_XTAL_PU_DURING_LIGHT_SLEEP", + "name": "BT_CTRL_MAIN_XTAL_PU_DURING_LIGHT_SLEEP", + "range": null, + "title": "power up main XTAL during light sleep", + "type": "bool" + } + ], + "depends_on": "BT_CONTROLLER_ENABLED", + "id": "component-config-bluetooth-controller-options-modem-sleep-options", + "title": "MODEM SLEEP Options", + "type": "menu" + }, + { + "children": [], + "depends_on": "BT_CONTROLLER_ENABLED", + "help": null, + "id": "BT_CTRL_SLEEP_MODE_EFF", + "name": "BT_CTRL_SLEEP_MODE_EFF", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": "BT_CONTROLLER_ENABLED", + "help": null, + "id": "BT_CTRL_SLEEP_CLOCK_EFF", + "name": "BT_CTRL_SLEEP_CLOCK_EFF", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": "BT_CONTROLLER_ENABLED", + "help": null, + "id": "BT_CTRL_HCI_TL_EFF", + "name": "BT_CTRL_HCI_TL_EFF", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "BT_CTRL_AGC_RECORRECT_EN && BT_CONTROLLER_ENABLED", + "help": "Enable coded phy AGC recorrect", + "id": "BT_CTRL_CODED_AGC_RECORRECT_EN", + "name": "BT_CTRL_CODED_AGC_RECORRECT_EN", + "range": null, + "title": "Enable coded phy AGC recorrect", + "type": "bool" + } + ], + "depends_on": "BT_CONTROLLER_ENABLED", + "help": "Enable uncoded phy AGC recorrect", + "id": "BT_CTRL_AGC_RECORRECT_EN", + "name": "BT_CTRL_AGC_RECORRECT_EN", + "range": null, + "title": "Enable HW AGC recorrect", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_CONTROLLER_ENABLED", + "help": "Disable active scan backoff. The bluetooth spec requires that scanners should run a backoff procedure to\nminimize collision of scan request PDUs from nultiple scanners. If scan backoff is disabled, in active\nscanning, scan request PDU will be sent every time when HW receives scannable ADV PDU.", + "id": "BT_CTRL_SCAN_BACKOFF_UPPERLIMITMAX", + "name": "BT_CTRL_SCAN_BACKOFF_UPPERLIMITMAX", + "range": null, + "title": "Disable active scan backoff", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_CONTROLLER_ENABLED", + "help": "When this option is enabled, auxiliary packets will be present in the events of\n'Non-Connectable and Non-Scannable' regardless of whether the advertising length is 0.\nIf this option is not enabled, auxiliary packets will only be present when the advertising length is not 0.", + "id": "BT_BLE_ADV_DATA_LENGTH_ZERO_AUX", + "name": "BT_BLE_ADV_DATA_LENGTH_ZERO_AUX", + "range": null, + "title": "Enable aux packet when ext adv data length is zero", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_CONTROLLER_ENABLED", + "help": "If this option is enabled, The Controller will records the communication quality\nfor each channel and then start a timer to check and update the channel map every 4 seconds.", + "id": "BT_CTRL_CHAN_ASS_EN", + "name": "BT_CTRL_CHAN_ASS_EN", + "range": null, + "title": "Enable channel assessment", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_CONTROLLER_ENABLED", + "help": "If this option is disabled, The Controller will not start the LE authenticated payload timer.\nThis option is used for some compatibility problems related to LE ping procedure.", + "id": "BT_CTRL_LE_PING_EN", + "name": "BT_CTRL_LE_PING_EN", + "range": null, + "title": "Enable LE Ping procedure", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "BT_CONTROLLER_ENABLED", + "help": "If this option is enabled, Controller will terminate the connection\nwhen Instant Passed (0x28) error occurs during connection update procedure.", + "id": "BT_CTRL_BLE_LLCP_CONN_UPDATE", + "name": "BT_CTRL_BLE_LLCP_CONN_UPDATE", + "range": null, + "title": "BLE ACL connection update procedure", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_CONTROLLER_ENABLED", + "help": "If this option is enabled, Controller will terminate the connection\nwhen Instant Passed (0x28) error occurs in channel map update procedure.", + "id": "BT_CTRL_BLE_LLCP_CHAN_MAP_UPDATE", + "name": "BT_CTRL_BLE_LLCP_CHAN_MAP_UPDATE", + "range": null, + "title": "BLE ACL channel map update procedure", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_CONTROLLER_ENABLED", + "help": "If this option is enabled, Controller will terminate the connection\nwhen Instant Passed (0x28) error occurs in PHY update procedure.", + "id": "BT_CTRL_BLE_LLCP_PHY_UPDATE", + "name": "BT_CTRL_BLE_LLCP_PHY_UPDATE", + "range": null, + "title": "BLE ACL PHY update procedure", + "type": "bool" + } + ], + "depends_on": "BT_CONTROLLER_ENABLED", + "id": "component-config-bluetooth-controller-options-ble-disconnects-when-instant-passed-0x28-occurs", + "title": "BLE disconnects when Instant Passed (0x28) occurs", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": "BT_CTRL_RUN_IN_FLASH_ONLY && BT_CONTROLLER_ENABLED", + "help": null, + "id": "BT_CTRL_DTM_ENABLE", + "name": "BT_CTRL_DTM_ENABLE", + "range": null, + "title": "Enable direct test mode feature", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_CTRL_RUN_IN_FLASH_ONLY && BT_CONTROLLER_ENABLED", + "help": null, + "id": "BT_CTRL_BLE_MASTER", + "name": "BT_CTRL_BLE_MASTER", + "range": null, + "title": "Enable BLE master role feature", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_CTRL_RUN_IN_FLASH_ONLY && BT_CONTROLLER_ENABLED", + "help": null, + "id": "BT_CTRL_BLE_TEST", + "name": "BT_CTRL_BLE_TEST", + "range": null, + "title": "Enable BLE QA test feature", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_CTRL_RUN_IN_FLASH_ONLY && BT_CONTROLLER_ENABLED", + "help": null, + "id": "BT_CTRL_BLE_SCAN", + "name": "BT_CTRL_BLE_SCAN", + "range": null, + "title": "Enable BLE scan feature", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_CTRL_RUN_IN_FLASH_ONLY && BT_CONTROLLER_ONLY && BT_CONTROLLER_ENABLED", + "help": null, + "id": "BT_CTRL_BLE_SECURITY_ENABLE", + "name": "BT_CTRL_BLE_SECURITY_ENABLE", + "range": null, + "title": "Enable BLE security feature", + "type": "bool" + } + ], + "depends_on": "BT_CONTROLLER_ENABLED", + "help": "If this option is enabled, all code for the Bluetooth controller will be moved from ROM and IRAM\nto flash, saving over 20K bytes of memory. However, it will require more flash resources and the\nperformance of Bluetooth will decrease If this option is enabled, Bluetooth may not work properly\nduring erasing flash. It is recommended to turn on the auto suspend function of flash. After auto\nsuspend is turned on, Bluetooth interrupts can be executed normally during erasing flash, with less\nimpact on Bluetooth performance.", + "id": "BT_CTRL_RUN_IN_FLASH_ONLY", + "name": "BT_CTRL_RUN_IN_FLASH_ONLY", + "range": null, + "title": "Put all BLE Controller code in flash", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_CONTROLLER_ENABLED", + "help": "Enabling this option will add stricter verification of the Access Address in the CONNECT_IND PDU.\nThis improves security by ensuring that only connection requests with valid Access Addresses are accepted.\nIf disabled, only basic checks are applied, improving compatibility.", + "id": "BT_CTRL_CHECK_CONNECT_IND_ACCESS_ADDRESS", + "name": "BT_CTRL_CHECK_CONNECT_IND_ACCESS_ADDRESS", + "range": null, + "title": "Enable enhanced Access Address check in CONNECT_IND", + "type": "bool" + } + ], + "depends_on": "BT_CONTROLLER_ENABLED", + "id": "component-config-bluetooth-controller-options", + "title": "Controller Options", + "type": "menu" + }, + { + "children": [], + "depends_on": "BT_ENABLED && BT_LE_RELEASE_IRAM_SUPPORTED", + "help": "This option release Bluetooth text section and merge Bluetooth data, bss & text into\na large free heap region when esp_bt_mem_release is called, total saving ~21kB or more of IRAM.\nESP32-C2 only 3 configurable PMP entries available, rest of them are hard-coded.\nWe cannot split the memory into 3 different regions (IRAM, BLE-IRAM, DRAM).\nSo this option will disable the PMP (ESP_SYSTEM_PMP_IDRAM_SPLIT)", + "id": "BT_RELEASE_IRAM", + "name": "BT_RELEASE_IRAM", + "range": null, + "title": "Release Bluetooth text (READ DOCS FIRST)", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": null, + "help": "This option decides the maximum number of alarms which\ncould be used by Bluetooth host.", + "id": "BT_ALARM_MAX_NUM", + "name": "BT_ALARM_MAX_NUM", + "range": null, + "title": "Maximum number of Bluetooth alarms", + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "BT_BLE_LOG_SPI_OUT_ENABLED", + "help": "The number of ble log async SPI output queues", + "id": "BT_BLE_LOG_SPI_OUT_QUEUE_SIZE", + "name": "BT_BLE_LOG_SPI_OUT_QUEUE_SIZE", + "range": null, + "title": "Number of ble log async SPI output queues", + "type": "int" + }, + { + "children": [], + "depends_on": "BT_BLE_LOG_SPI_OUT_ENABLED", + "help": "The size of ble log async SPI output transaction buffer size", + "id": "BT_BLE_LOG_SPI_OUT_TRANS_BUF_SIZE", + "name": "BT_BLE_LOG_SPI_OUT_TRANS_BUF_SIZE", + "range": null, + "title": "Size of ble log async SPI output transaction buffer size", + "type": "int" + }, + { + "children": [], + "depends_on": "BT_BLE_LOG_SPI_OUT_ENABLED", + "help": "GPIO number of SPI MOSI", + "id": "BT_BLE_LOG_SPI_OUT_MOSI_IO_NUM", + "name": "BT_BLE_LOG_SPI_OUT_MOSI_IO_NUM", + "range": null, + "title": "GPIO number of SPI MOSI", + "type": "int" + }, + { + "children": [], + "depends_on": "BT_BLE_LOG_SPI_OUT_ENABLED", + "help": "GPIO number of SPI SCLK", + "id": "BT_BLE_LOG_SPI_OUT_SCLK_IO_NUM", + "name": "BT_BLE_LOG_SPI_OUT_SCLK_IO_NUM", + "range": null, + "title": "GPIO number of SPI SCLK", + "type": "int" + }, + { + "children": [], + "depends_on": "BT_BLE_LOG_SPI_OUT_ENABLED", + "help": "GPIO number of SPI CS", + "id": "BT_BLE_LOG_SPI_OUT_CS_IO_NUM", + "name": "BT_BLE_LOG_SPI_OUT_CS_IO_NUM", + "range": null, + "title": "GPIO number of SPI CS", + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "BT_BLE_LOG_SPI_OUT_TS_SYNC_ENABLED", + "help": "GPIO number of SYNC IO", + "id": "BT_BLE_LOG_SPI_OUT_SYNC_IO_NUM", + "name": "BT_BLE_LOG_SPI_OUT_SYNC_IO_NUM", + "range": null, + "title": "GPIO number of SYNC IO", + "type": "int" + } + ], + "depends_on": "BT_BLE_LOG_SPI_OUT_ENABLED", + "help": "Enable ble log & logic analyzer log time sync", + "id": "BT_BLE_LOG_SPI_OUT_TS_SYNC_ENABLED", + "name": "BT_BLE_LOG_SPI_OUT_TS_SYNC_ENABLED", + "range": null, + "title": "Enable ble log & logic analyzer log time sync", + "type": "bool" + } + ], + "depends_on": null, + "help": "Output ble logs to SPI bus", + "id": "BT_BLE_LOG_SPI_OUT_ENABLED", + "name": "BT_BLE_LOG_SPI_OUT_ENABLED", + "range": null, + "title": "Output ble logs to SPI bus (Experimental)", + "type": "bool" + } + ], + "depends_on": null, + "id": "component-config-bluetooth-common-options", + "title": "Common Options", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": "BT_HCI_LOG_DEBUG_EN", + "help": "This option is to configure the buffer size of the hci data steam cache in hci debug mode.\nThis is a ring buffer, the new data will overwrite the oldest data if the buffer is full.", + "id": "BT_HCI_LOG_DATA_BUFFER_SIZE", + "name": "BT_HCI_LOG_DATA_BUFFER_SIZE", + "range": null, + "title": "Size of the cache used for HCI data in Bluetooth HCI debug mode (N*1024 bytes)", + "type": "int" + }, + { + "children": [], + "depends_on": "BT_HCI_LOG_DEBUG_EN", + "help": "This option is to configure the buffer size of the hci adv report cache in hci debug mode.\nThis is a ring buffer, the new data will overwrite the oldest data if the buffer is full.", + "id": "BT_HCI_LOG_ADV_BUFFER_SIZE", + "name": "BT_HCI_LOG_ADV_BUFFER_SIZE", + "range": null, + "title": "Size of the cache used for adv report in Bluetooth HCI debug mode (N*1024 bytes)", + "type": "int" + } + ], + "depends_on": "BT_BLUEDROID_ENABLED || BT_NIMBLE_ENABLED", + "help": "This option is used to enable bluetooth debug mode, which saves the hci layer data stream.", + "id": "BT_HCI_LOG_DEBUG_EN", + "name": "BT_HCI_LOG_DEBUG_EN", + "range": null, + "title": "Enable Bluetooth HCI debug mode", + "type": "bool" + } + ], + "depends_on": null, + "id": "component-config-bluetooth", + "title": "Bluetooth", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": "BLE_MESH", + "help": "It is a temporary solution and needs further modifications.", + "id": "BLE_MESH_HCI_5_0", + "name": "BLE_MESH_HCI_5_0", + "range": null, + "title": "Support sending 20ms non-connectable adv packets", + "type": "bool" + }, + { + "children": [], + "depends_on": "BLE_MESH", + "help": "Support BLE Mesh v1.1 features", + "id": "BLE_MESH_V11_SUPPORT", + "name": "BLE_MESH_V11_SUPPORT", + "range": null, + "title": "Support ESP BLE Mesh v1.1 features (Preview)", + "type": "bool" + }, + { + "children": [], + "depends_on": "BLE_MESH", + "help": "Enable this option to allow using random advertising interval\nfor mesh packets. And this could help avoid collision of\nadvertising packets.", + "id": "BLE_MESH_RANDOM_ADV_INTERVAL", + "name": "BLE_MESH_RANDOM_ADV_INTERVAL", + "range": null, + "title": "Support using random adv interval for mesh packets", + "type": "bool" + }, + { + "children": [], + "depends_on": "BLE_MESH", + "help": "Enable this option to allow using specific duplicate scan filter\nin BLE Mesh, and Scan Duplicate Type must be set by choosing the\noption in the Bluetooth Controller section in menuconfig, which is\n\"Scan Duplicate By Device Address and Advertising Data\".", + "id": "BLE_MESH_USE_DUPLICATE_SCAN", + "name": "BLE_MESH_USE_DUPLICATE_SCAN", + "range": null, + "title": "Support Duplicate Scan in BLE Mesh", + "type": "bool" + }, + { + "children": [], + "depends_on": "BLE_MESH_V11_SUPPORT && BLE_MESH", + "help": "Enable this option to allow using BLE Active Scan for BLE Mesh.", + "id": "BLE_MESH_ACTIVE_SCAN", + "name": "BLE_MESH_ACTIVE_SCAN", + "range": null, + "title": "Support Active Scan in BLE Mesh", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "BLE_MESH_MEM_ALLOC_MODE_INTERNAL", + "name": "BLE_MESH_MEM_ALLOC_MODE_INTERNAL", + "range": null, + "title": "Internal DRAM", + "type": "bool" + }, + { + "children": [], + "depends_on": "(SPIRAM_USE_CAPS_ALLOC || SPIRAM_USE_MALLOC) && ", + "help": null, + "id": "BLE_MESH_MEM_ALLOC_MODE_EXTERNAL", + "name": "BLE_MESH_MEM_ALLOC_MODE_EXTERNAL", + "range": null, + "title": "External SPIRAM", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": "Enable this option to use the default memory allocation strategy when\nexternal SPIRAM is enabled. See the SPIRAM options for more details.", + "id": "BLE_MESH_MEM_ALLOC_MODE_DEFAULT", + "name": "BLE_MESH_MEM_ALLOC_MODE_DEFAULT", + "range": null, + "title": "Default alloc mode", + "type": "bool" + }, + { + "children": [], + "depends_on": "ESP32_IRAM_AS_8BIT_ACCESSIBLE_MEMORY && ", + "help": "Allows to use IRAM memory region as 8bit accessible region. Every\nunaligned (8bit or 16bit) access will result in an exception and\nincur penalty of certain clock cycles per unaligned read/write.", + "id": "BLE_MESH_MEM_ALLOC_MODE_IRAM_8BIT", + "name": "BLE_MESH_MEM_ALLOC_MODE_IRAM_8BIT", + "range": null, + "title": "Internal IRAM", + "type": "bool" + } + ], + "depends_on": "BLE_MESH", + "help": "Allocation strategy for BLE Mesh stack, essentially provides ability to\nallocate all required dynamic allocations from,\n\n- Internal DRAM memory only\n- External SPIRAM memory only\n- Either internal or external memory based on default malloc()\n behavior in ESP-IDF\n- Internal IRAM memory wherever applicable else internal DRAM\n\nRecommended mode here is always internal (*), since that is most preferred\nfrom security perspective. But if application requirement does not\nallow sufficient free internal memory then alternate mode can be\nselected.\n\n(*) In case of ESP32-S2/ESP32-S3, hardware allows encryption of external\nSPIRAM contents provided hardware flash encryption feature is enabled.\nIn that case, using external SPIRAM allocation strategy is also safe choice\nfrom security perspective.", + "id": "component-config-esp-ble-mesh-support-memory-allocation-strategy", + "name": "BLE_MESH_MEM_ALLOC_MODE", + "title": "Memory allocation strategy", + "type": "choice" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "IDF_TARGET_ESP32 && SPIRAM && ", + "help": "If enabled, BLE Mesh allocates dynamic memory from external SPIRAM for\nFreeRTOS objects, i.e. mutex, queue, and task stack. External SPIRAM\ncan only be used for task stack when SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY\nis enabled. See the SPIRAM options for more details.", + "id": "BLE_MESH_FREERTOS_STATIC_ALLOC_EXTERNAL", + "name": "BLE_MESH_FREERTOS_STATIC_ALLOC_EXTERNAL", + "range": null, + "title": "External SPIRAM", + "type": "bool" + }, + { + "children": [], + "depends_on": "ESP32_IRAM_AS_8BIT_ACCESSIBLE_MEMORY && ", + "help": "If enabled, BLE Mesh allocates dynamic memory from internal IRAM for\nFreeRTOS objects, i.e. mutex, queue. Note: IRAM region cannot be used\nas task stack.", + "id": "BLE_MESH_FREERTOS_STATIC_ALLOC_IRAM_8BIT", + "name": "BLE_MESH_FREERTOS_STATIC_ALLOC_IRAM_8BIT", + "range": null, + "title": "Internal IRAM", + "type": "bool" + } + ], + "depends_on": "BLE_MESH_FREERTOS_STATIC_ALLOC && BLE_MESH", + "help": "Choose the memory to be used for FreeRTOS objects.", + "id": "component-config-esp-ble-mesh-support-enable-freertos-static-allocation-memory-allocation-for-freertos-objects", + "name": "BLE_MESH_FREERTOS_STATIC_ALLOC_MODE", + "title": "Memory allocation for FreeRTOS objects", + "type": "choice" + } + ], + "depends_on": "FREERTOS_SUPPORT_STATIC_ALLOCATION && ((IDF_TARGET_ESP32 && SPIRAM) || ESP32_IRAM_AS_8BIT_ACCESSIBLE_MEMORY) && BLE_MESH", + "help": "Enable this option to use FreeRTOS static allocation APIs for BLE Mesh,\nwhich provides the ability to use different dynamic memory (i.e. SPIRAM\nor IRAM) for FreeRTOS objects.\nIf this option is disabled, the FreeRTOS static allocation APIs will not\nbe used, and internal DRAM will be allocated for FreeRTOS objects.", + "id": "BLE_MESH_FREERTOS_STATIC_ALLOC", + "name": "BLE_MESH_FREERTOS_STATIC_ALLOC", + "range": null, + "title": "Enable FreeRTOS static allocation", + "type": "bool" + }, + { + "children": [], + "depends_on": "BLE_MESH", + "help": "If enabled, users can use the function esp_ble_mesh_deinit() to de-initialize\nthe whole BLE Mesh stack.", + "id": "BLE_MESH_DEINIT", + "name": "BLE_MESH_DEINIT", + "range": null, + "title": "Support de-initialize BLE Mesh stack", + "type": "bool" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "BLE_MESH_SUPPORT_BLE_ADV && BLE_MESH", + "help": "Number of advertising buffers for BLE packets available.", + "id": "BLE_MESH_BLE_ADV_BUF_COUNT", + "name": "BLE_MESH_BLE_ADV_BUF_COUNT", + "range": null, + "title": "Number of advertising buffers for BLE advertising packets", + "type": "int" + } + ], + "depends_on": "BLE_MESH", + "help": "When selected, users can send normal BLE advertising packets\nwith specific API.", + "id": "BLE_MESH_SUPPORT_BLE_ADV", + "name": "BLE_MESH_SUPPORT_BLE_ADV", + "range": null, + "title": "Support sending normal BLE advertising packets", + "type": "bool" + }, + { + "children": [], + "depends_on": "BLE_MESH", + "help": "When selected, users can register a callback and receive normal BLE\nadvertising packets in the application layer.", + "id": "BLE_MESH_SUPPORT_BLE_SCAN", + "name": "BLE_MESH_SUPPORT_BLE_SCAN", + "range": null, + "title": "Support scanning normal BLE advertising packets", + "type": "bool" + } + ], + "depends_on": "BLE_MESH", + "id": "component-config-esp-ble-mesh-support-ble-mesh-and-ble-coexistence-support", + "title": "BLE Mesh and BLE coexistence support", + "type": "menu" + }, + { + "children": [], + "depends_on": "BLE_MESH", + "help": "Enable this option to allow BLE Mesh fast provisioning solution to be used.\nWhen there are multiple unprovisioned devices around, fast provisioning can\ngreatly reduce the time consumption of the whole provisioning process.\nWhen this option is enabled, and after an unprovisioned device is provisioned\ninto a node successfully, it can be changed to a temporary Provisioner.", + "id": "BLE_MESH_FAST_PROV", + "name": "BLE_MESH_FAST_PROV", + "range": null, + "title": "Enable BLE Mesh Fast Provisioning", + "type": "bool" + }, + { + "children": [], + "depends_on": "BLE_MESH", + "help": "Enable the device to be provisioned into a node. This option should be\nenabled when an unprovisioned device is going to be provisioned into a\nnode and communicate with other nodes in the BLE Mesh network.", + "id": "BLE_MESH_NODE", + "name": "BLE_MESH_NODE", + "range": null, + "title": "Support for BLE Mesh Node", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "BLE_MESH_PROVISIONER && BLE_MESH", + "help": "This option specifies how many unprovisioned devices can be added to device\nqueue for provisioning. Users can use this option to define the size of the\nqueue in the bottom layer which is used to store unprovisioned device\ninformation (e.g. Device UUID, address).", + "id": "BLE_MESH_WAIT_FOR_PROV_MAX_DEV_NUM", + "name": "BLE_MESH_WAIT_FOR_PROV_MAX_DEV_NUM", + "range": null, + "title": "Maximum number of unprovisioned devices that can be added to device queue", + "type": "int" + }, + { + "children": [], + "depends_on": "BLE_MESH_PROVISIONER && BLE_MESH", + "help": "This option specifies how many devices can be provisioned by a Provisioner.\nThis value indicates the maximum number of unprovisioned devices which can be\nprovisioned by a Provisioner. For instance, if the value is 6, it means the\nProvisioner can provision up to 6 unprovisioned devices.\nTheoretically a Provisioner without the limitation of its memory can provision\nup to 32766 unprovisioned devices, here we limit the maximum number to 100\njust to limit the memory used by a Provisioner. The bigger the value is, the\nmore memory it will cost by a Provisioner to store the information of nodes.", + "id": "BLE_MESH_MAX_PROV_NODES", + "name": "BLE_MESH_MAX_PROV_NODES", + "range": null, + "title": "Maximum number of devices that can be provisioned by Provisioner", + "type": "int" + }, + { + "children": [], + "depends_on": "BLE_MESH_PB_ADV && BLE_MESH_PROVISIONER && BLE_MESH", + "help": "This option specifies how many devices can be provisioned at the same time\nusing PB-ADV. For examples, if the value is 2, it means a Provisioner can\nprovision two unprovisioned devices with PB-ADV at the same time.", + "id": "BLE_MESH_PBA_SAME_TIME", + "name": "BLE_MESH_PBA_SAME_TIME", + "range": null, + "title": "Maximum number of PB-ADV running at the same time by Provisioner", + "type": "int" + }, + { + "children": [], + "depends_on": "BLE_MESH_PB_GATT && BLE_MESH_PROVISIONER && BLE_MESH", + "help": "This option specifies how many devices can be provisioned at the same\ntime using PB-GATT. For example, if the value is 2, it means a Provisioner\ncan provision two unprovisioned devices with PB-GATT at the same time.", + "id": "BLE_MESH_PBG_SAME_TIME", + "name": "BLE_MESH_PBG_SAME_TIME", + "range": null, + "title": "Maximum number of PB-GATT running at the same time by Provisioner", + "type": "int" + }, + { + "children": [], + "depends_on": "BLE_MESH_PROVISIONER && BLE_MESH", + "help": "This option specifies how many subnets per network a Provisioner can create.\nIndeed, this value decides the number of network keys which can be added by a Provisioner.", + "id": "BLE_MESH_PROVISIONER_SUBNET_COUNT", + "name": "BLE_MESH_PROVISIONER_SUBNET_COUNT", + "range": null, + "title": "Maximum number of mesh subnets that can be created by Provisioner", + "type": "int" + }, + { + "children": [], + "depends_on": "BLE_MESH_PROVISIONER && BLE_MESH", + "help": "This option specifies how many application keys the Provisioner can have.\nIndeed, this value decides the number of the application keys which can be added by a Provisioner.", + "id": "BLE_MESH_PROVISIONER_APP_KEY_COUNT", + "name": "BLE_MESH_PROVISIONER_APP_KEY_COUNT", + "range": null, + "title": "Maximum number of application keys that can be owned by Provisioner", + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "BLE_MESH_PROVISIONER_RECV_HB && BLE_MESH_PROVISIONER && BLE_MESH", + "help": "This option specifies how many heartbeat filter entries Provisioner supports.\nThe heartbeat filter (acceptlist or rejectlist) entries are used to store a\nlist of SRC and DST which can be used to decide if a heartbeat message will\nbe processed and notified to the application layer by Provisioner.\nNote: The filter is an empty rejectlist by default.", + "id": "BLE_MESH_PROVISIONER_RECV_HB_FILTER_SIZE", + "name": "BLE_MESH_PROVISIONER_RECV_HB_FILTER_SIZE", + "range": null, + "title": "Maximum number of filter entries for receiving Heartbeat messages", + "type": "int" + } + ], + "depends_on": "BLE_MESH_PROVISIONER && BLE_MESH", + "help": "When this option is enabled, Provisioner can call specific functions to enable\nor disable receiving Heartbeat messages and notify them to the application layer.", + "id": "BLE_MESH_PROVISIONER_RECV_HB", + "name": "BLE_MESH_PROVISIONER_RECV_HB", + "range": null, + "title": "Support receiving Heartbeat messages", + "type": "bool" + } + ], + "depends_on": "BLE_MESH", + "help": "Enable the device to be a Provisioner. The option should be enabled when\na device is going to act as a Provisioner and provision unprovisioned\ndevices into the BLE Mesh network.", + "id": "BLE_MESH_PROVISIONER", + "name": "BLE_MESH_PROVISIONER", + "range": null, + "title": "Support for BLE Mesh Provisioner", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "BLE_MESH_PROV && BLE_MESH_V11_SUPPORT && BLE_MESH", + "help": "Enable this option to support BLE Mesh enhanced provisioning authentication\nfunctionality. This option can increase the security level of provisioning.\nIt is recommended to enable this option.", + "id": "BLE_MESH_PROV_EPA", + "name": "BLE_MESH_PROV_EPA", + "range": null, + "title": "BLE Mesh enhanced provisioning authentication", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "BLE_MESH_CERT_BASED_PROV && BLE_MESH", + "help": "This option sets the maximum size of the provisioning record fragment that the\nProvisioner can receive. The range depends on provisioning bearer.", + "id": "BLE_MESH_RECORD_FRAG_MAX_SIZE", + "name": "BLE_MESH_RECORD_FRAG_MAX_SIZE", + "range": null, + "title": "Maximum size of the provisioning record fragment that Provisioner can receive", + "type": "int" + } + ], + "depends_on": "BLE_MESH_PROV && BLE_MESH_V11_SUPPORT && BLE_MESH", + "help": "Enable this option to support BLE Mesh Certificate-Based Provisioning.", + "id": "BLE_MESH_CERT_BASED_PROV", + "name": "BLE_MESH_CERT_BASED_PROV", + "range": null, + "title": "Support Certificate-based provisioning", + "type": "bool" + } + ], + "depends_on": "BLE_MESH", + "help": "Enable this option to support BLE Mesh Provisioning functionality. For\nBLE Mesh, this option should be always enabled.", + "id": "BLE_MESH_PROV", + "name": "BLE_MESH_PROV", + "range": null, + "title": "BLE Mesh Provisioning support", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "BLE_MESH_NODE && BLE_MESH_PB_ADV && BLE_MESH", + "help": "This option specifies the interval of sending two consecutive unprovisioned\ndevice beacon, users can use this option to change the frequency of sending\nunprovisioned device beacon. For example, if the value is 5, it means the\nunprovisioned device beacon will send every 5 seconds. When the option of\nBLE_MESH_FAST_PROV is selected, the value is better to be 3 seconds, or less.", + "id": "BLE_MESH_UNPROVISIONED_BEACON_INTERVAL", + "name": "BLE_MESH_UNPROVISIONED_BEACON_INTERVAL", + "range": null, + "title": "Interval between two consecutive Unprovisioned Device Beacon", + "type": "int" + } + ], + "depends_on": "BLE_MESH", + "help": "Enable this option to allow the device to be provisioned over the\nadvertising bearer. This option should be enabled if PB-ADV is\ngoing to be used during provisioning procedure.", + "id": "BLE_MESH_PB_ADV", + "name": "BLE_MESH_PB_ADV", + "range": null, + "title": "Provisioning support using the advertising bearer (PB-ADV)", + "type": "bool" + }, + { + "children": [], + "depends_on": "BLE_MESH", + "help": "Enable this option to allow the device to be provisioned over GATT.\nThis option should be enabled if PB-GATT is going to be used during\nprovisioning procedure.\n\n# Virtual option enabled whenever any Proxy protocol is needed", + "id": "BLE_MESH_PB_GATT", + "name": "BLE_MESH_PB_GATT", + "range": null, + "title": "Provisioning support using GATT (PB-GATT)", + "type": "bool" + }, + { + "children": [], + "depends_on": "BLE_MESH", + "help": "Enable this option to support BLE Mesh Proxy protocol used by PB-GATT\nand other proxy pdu transmission.", + "id": "BLE_MESH_PROXY", + "name": "BLE_MESH_PROXY", + "range": null, + "title": "BLE Mesh Proxy protocol support", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "BLE_MESH_GATT_PROXY_SERVER && BLE_MESH", + "help": "This option determines for how long the local node advertises using\nNode Identity. The given value is in seconds. The specification limits\nthis to 60 seconds and lists it as the recommended value as well.\nSo leaving the default value is the safest option.\nWhen an unprovisioned device is provisioned successfully and becomes a\nnode, it will start to advertise using Node Identity during the time\nset by this option. And after that, Network ID will be advertised.", + "id": "BLE_MESH_NODE_ID_TIMEOUT", + "name": "BLE_MESH_NODE_ID_TIMEOUT", + "range": null, + "title": "Node Identity advertising timeout", + "type": "int" + }, + { + "children": [], + "depends_on": "BLE_MESH_GATT_PROXY_SERVER && BLE_MESH", + "help": "This option specifies how many Proxy Filter entries the local node supports.\nThe entries of Proxy filter (whitelist or blacklist) are used to store a\nlist of addresses which can be used to decide which messages will be forwarded\nto the Proxy Client by the Proxy Server.", + "id": "BLE_MESH_PROXY_FILTER_SIZE", + "name": "BLE_MESH_PROXY_FILTER_SIZE", + "range": null, + "title": "Maximum number of filter entries per Proxy Client", + "type": "int" + }, + { + "children": [], + "depends_on": "BLE_MESH_PRB_SRV && BLE_MESH_GATT_PROXY_SERVER && BLE_MESH", + "help": "The Proxy Privacy parameter controls the privacy of the Proxy Server\nover the connection. The value of the Proxy Privacy parameter is\ncontrolled by the type of proxy connection, which is dependent on the\nbearer used by the proxy connection.", + "id": "BLE_MESH_PROXY_PRIVACY", + "name": "BLE_MESH_PROXY_PRIVACY", + "range": null, + "title": "Support Proxy Privacy", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "BLE_MESH_PROXY_SOLIC_PDU_RX && BLE_MESH", + "help": "This option specifies the maximum capacity of the solicitation replay\nprotection list. The solicitation replay protection list is used to\nreject Solicitation PDUs that were already processed by a node, which\nwill store the solicitation src and solicitation sequence number of\nthe received Solicitation PDU message.", + "id": "BLE_MESH_PROXY_SOLIC_RX_CRPL", + "name": "BLE_MESH_PROXY_SOLIC_RX_CRPL", + "range": null, + "title": "Maximum capacity of solicitation replay protection list", + "type": "int" + } + ], + "depends_on": "BLE_MESH_GATT_PROXY_SERVER && BLE_MESH_V11_SUPPORT && BLE_MESH", + "help": "Enable this option to support receiving Proxy Solicitation PDU.", + "id": "BLE_MESH_PROXY_SOLIC_PDU_RX", + "name": "BLE_MESH_PROXY_SOLIC_PDU_RX", + "range": null, + "title": "Support receiving Proxy Solicitation PDU", + "type": "bool" + } + ], + "depends_on": "BLE_MESH_NODE && BLE_MESH", + "help": "This option enables support for Mesh GATT Proxy Service, i.e. the\nability to act as a proxy between a Mesh GATT Client and a Mesh network.\nThis option should be enabled if a node is going to be a Proxy Server.", + "id": "BLE_MESH_GATT_PROXY_SERVER", + "name": "BLE_MESH_GATT_PROXY_SERVER", + "range": null, + "title": "BLE Mesh GATT Proxy Server", + "type": "bool" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "BLE_MESH_PROXY_SOLIC_PDU_TX && BLE_MESH", + "help": "This option specifies the maximum number of Solicitation Source (SSRC)\nthat can be used by Proxy Client for sending a Solicitation PDU.\nA Proxy Client may use the primary address or any of the secondary\naddresses as the SSRC for a Solicitation PDU.\nSo for a Proxy Client, it's better to choose the value based on its\nown element count.", + "id": "BLE_MESH_PROXY_SOLIC_TX_SRC_COUNT", + "name": "BLE_MESH_PROXY_SOLIC_TX_SRC_COUNT", + "range": null, + "title": "Maximum number of SSRC that can be used by Proxy Client", + "type": "int" + } + ], + "depends_on": "BLE_MESH_GATT_PROXY_CLIENT && BLE_MESH_V11_SUPPORT && BLE_MESH", + "help": "Enable this option to support sending Proxy Solicitation PDU.", + "id": "BLE_MESH_PROXY_SOLIC_PDU_TX", + "name": "BLE_MESH_PROXY_SOLIC_PDU_TX", + "range": null, + "title": "Support sending Proxy Solicitation PDU", + "type": "bool" + } + ], + "depends_on": "BLE_MESH", + "help": "This option enables support for Mesh GATT Proxy Client. The Proxy Client\ncan use the GATT bearer to send mesh messages to a node that supports the\nadvertising bearer.", + "id": "BLE_MESH_GATT_PROXY_CLIENT", + "name": "BLE_MESH_GATT_PROXY_CLIENT", + "range": null, + "title": "BLE Mesh GATT Proxy Client", + "type": "bool" + }, + { + "children": [], + "depends_on": "BLE_MESH", + "help": "Enable BLE Mesh net buffer pool tracking. This option is used to introduce another\nvariable in the bottom layer to record the usage of advertising buffers of BLE Mesh\ndevices. Recommend to enable this option as default.", + "id": "BLE_MESH_NET_BUF_POOL_USAGE", + "name": "BLE_MESH_NET_BUF_POOL_USAGE", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "BLE_MESH_SETTINGS && BLE_MESH", + "help": "This value defines in seconds how soon any pending changes are actually\nwritten into persistent storage (flash) after a change occurs.\nThe option allows nodes to delay a certain period of time to save proper\ninformation to flash. The default value is 0, which means information\nwill be stored immediately once there are updates.", + "id": "BLE_MESH_STORE_TIMEOUT", + "name": "BLE_MESH_STORE_TIMEOUT", + "range": null, + "title": "Delay (in seconds) before storing anything persistently", + "type": "int" + }, + { + "children": [], + "depends_on": "BLE_MESH_SETTINGS && BLE_MESH", + "help": "This value defines how often the local sequence number gets updated in\npersistent storage (i.e. flash). e.g. a value of 100 means that the\nsequence number will be stored to flash on every 100th increment.\nIf the node sends messages very frequently a higher value makes more\nsense, whereas if the node sends infrequently a value as low as 0\n(update storage for every increment) can make sense. When the stack\ngets initialized it will add sequence number to the last stored one,\nso that it starts off with a value that's guaranteed to be larger than\nthe last one used before power off.", + "id": "BLE_MESH_SEQ_STORE_RATE", + "name": "BLE_MESH_SEQ_STORE_RATE", + "range": null, + "title": "How often the sequence number gets updated in storage", + "type": "int" + }, + { + "children": [], + "depends_on": "BLE_MESH_SETTINGS && BLE_MESH", + "help": "This value defines in seconds how soon the RPL (Replay Protection List)\ngets written to persistent storage after a change occurs. If the node\nreceives messages frequently, then a large value is recommended. If the\nnode receives messages rarely, then the value can be as low as 0 (which\nmeans the RPL is written into the storage immediately).\nNote that if the node operates in a security-sensitive case, and there is\na risk of sudden power-off, then a value of 0 is strongly recommended.\nOtherwise, a power loss before RPL being written into the storage may\nintroduce message replay attacks and system security will be in a\nvulnerable state.", + "id": "BLE_MESH_RPL_STORE_TIMEOUT", + "name": "BLE_MESH_RPL_STORE_TIMEOUT", + "range": null, + "title": "Minimum frequency that the RPL gets updated in storage", + "type": "int" + }, + { + "children": [], + "depends_on": "BLE_MESH_NODE && BLE_MESH_SETTINGS && BLE_MESH", + "help": "This option is created to solve the issue of failure in recovering\nnode information after mesh stack updates. In the old version mesh\nstack, there is no key of \"mesh/role\" in nvs. In the new version\nmesh stack, key of \"mesh/role\" is added in nvs, recovering node\ninformation needs to check \"mesh/role\" key in nvs and implements\nselective recovery of mesh node information. Therefore, there may\nbe failure in recovering node information during node restarting\nafter OTA.\n\nThe new version mesh stack adds the option of \"mesh/role\" because\nwe have added the support of storing Provisioner information, while\nthe old version only supports storing node information.\n\nIf users are updating their nodes from old version to new version,\nwe recommend enabling this option, so that system could set the flag\nin advance before recovering node information and make sure the node\ninformation recovering could work as expected.", + "id": "BLE_MESH_SETTINGS_BACKWARD_COMPATIBILITY", + "name": "BLE_MESH_SETTINGS_BACKWARD_COMPATIBILITY", + "range": null, + "title": "A specific option for settings backward compatibility", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "BLE_MESH_SPECIFIC_PARTITION && BLE_MESH_SETTINGS && BLE_MESH", + "help": "This value defines the name of the specified NVS partition used by the\nmesh stack.", + "id": "BLE_MESH_PARTITION_NAME", + "name": "BLE_MESH_PARTITION_NAME", + "range": null, + "title": "Name of the NVS partition for BLE Mesh", + "type": "string" + } + ], + "depends_on": "BLE_MESH_SETTINGS && BLE_MESH", + "help": "When selected, the mesh stack will use a specified NVS partition instead of\ndefault NVS partition. Note that the specified partition must be registered\nwith NVS using nvs_flash_init_partition() API, and the partition must exists\nin the csv file.\nWhen Provisioner needs to store a large amount of nodes' information in the\nflash (e.g. more than 20), this option is recommended to be enabled.", + "id": "BLE_MESH_SPECIFIC_PARTITION", + "name": "BLE_MESH_SPECIFIC_PARTITION", + "range": null, + "title": "Use a specific NVS partition for BLE Mesh", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "BLE_MESH_USE_MULTIPLE_NAMESPACE && BLE_MESH_SETTINGS && BLE_MESH", + "help": "This option specifies the maximum NVS namespaces supported by Provisioner.", + "id": "BLE_MESH_MAX_NVS_NAMESPACE", + "name": "BLE_MESH_MAX_NVS_NAMESPACE", + "range": null, + "title": "Maximum number of NVS namespaces", + "type": "int" + } + ], + "depends_on": "BLE_MESH_PROVISIONER && BLE_MESH_SETTINGS && BLE_MESH", + "help": "When selected, Provisioner can use different NVS namespaces to store\ndifferent instances of mesh information.\nFor example, if in the first room, Provisioner uses NetKey A, AppKey\nA and provisions three devices, these information will be treated as\nmesh information instance A. When the Provisioner moves to the second\nroom, it uses NetKey B, AppKey B and provisions two devices, then the\ninformation will be treated as mesh information instance B.\nHere instance A and instance B will be stored in different namespaces.\nWith this option enabled, Provisioner needs to use specific functions\nto open the corresponding NVS namespace, restore the mesh information,\nrelease the mesh information or erase the mesh information.", + "id": "BLE_MESH_USE_MULTIPLE_NAMESPACE", + "name": "BLE_MESH_USE_MULTIPLE_NAMESPACE", + "range": null, + "title": "Support using multiple NVS namespaces by Provisioner", + "type": "bool" + } + ], + "depends_on": "BLE_MESH", + "help": "When selected, the BLE Mesh stack will take care of storing/restoring the BLE\nMesh configuration persistently in flash.\nIf the device is a BLE Mesh node, when this option is enabled, the configuration\nof the device will be stored persistently, including unicast address, NetKey,\nAppKey, etc.\nAnd if the device is a BLE Mesh Provisioner, the information of the device will\nbe stored persistently, including the information of provisioned nodes, NetKey,\nAppKey, etc.", + "id": "BLE_MESH_SETTINGS", + "name": "BLE_MESH_SETTINGS", + "range": null, + "title": "Store BLE Mesh configuration persistently", + "type": "bool" + }, + { + "children": [], + "depends_on": "BLE_MESH", + "help": "This option specifies how many subnets a Mesh network can have at the same time.\nIndeed, this value decides the number of the network keys which can be owned by a node.", + "id": "BLE_MESH_SUBNET_COUNT", + "name": "BLE_MESH_SUBNET_COUNT", + "range": null, + "title": "Maximum number of mesh subnets per network", + "type": "int" + }, + { + "children": [], + "depends_on": "BLE_MESH", + "help": "This option specifies how many application keys the device can store per network.\nIndeed, this value decides the number of the application keys which can be owned by a node.", + "id": "BLE_MESH_APP_KEY_COUNT", + "name": "BLE_MESH_APP_KEY_COUNT", + "range": null, + "title": "Maximum number of application keys per network", + "type": "int" + }, + { + "children": [], + "depends_on": "BLE_MESH", + "help": "This option specifies the maximum number of application keys to which each model\ncan be bound.", + "id": "BLE_MESH_MODEL_KEY_COUNT", + "name": "BLE_MESH_MODEL_KEY_COUNT", + "range": null, + "title": "Maximum number of application keys per model", + "type": "int" + }, + { + "children": [], + "depends_on": "BLE_MESH", + "help": "This option specifies the maximum number of addresses to which each model can\nbe subscribed.", + "id": "BLE_MESH_MODEL_GROUP_COUNT", + "name": "BLE_MESH_MODEL_GROUP_COUNT", + "range": null, + "title": "Maximum number of group address subscriptions per model", + "type": "int" + }, + { + "children": [], + "depends_on": "BLE_MESH", + "help": "This option specifies how many Label UUIDs can be stored.\nIndeed, this value decides the number of the Virtual Addresses can be supported by a node.", + "id": "BLE_MESH_LABEL_COUNT", + "name": "BLE_MESH_LABEL_COUNT", + "range": null, + "title": "Maximum number of Label UUIDs used for Virtual Addresses", + "type": "int" + }, + { + "children": [], + "depends_on": "BLE_MESH", + "help": "This option specifies the maximum capacity of the replay protection list.\nIt is similar to Network message cache size, but has a different purpose.\nThe replay protection list is used to prevent a node from replay attack,\nwhich will store the source address and sequence number of the received\nmesh messages.\nFor Provisioner, the replay protection list size should not be smaller than\nthe maximum number of nodes whose information can be stored. And the element\nnumber of each node should also be taken into consideration. For example, if\nProvisioner can provision up to 20 nodes and each node contains two elements,\nthen the replay protection list size of Provisioner should be at least 40.", + "id": "BLE_MESH_CRPL", + "name": "BLE_MESH_CRPL", + "range": null, + "title": "Maximum capacity of the replay protection list", + "type": "int" + }, + { + "children": [], + "depends_on": "BLE_MESH_EXPERIMENTAL && BLE_MESH", + "help": "There may be many expired messages in a complex mesh network that would be\nconsidered replayed messages.\nEnable this option will refuse to relay such messages, which could help to\nreduce invalid packets in the mesh network.\nHowever, it should be noted that enabling this option may result in packet\nloss in certain environments.\nTherefore, users need to decide whether to enable this option according to\nthe actual usage situation.", + "id": "BLE_MESH_NOT_RELAY_REPLAY_MSG", + "name": "BLE_MESH_NOT_RELAY_REPLAY_MSG", + "range": null, + "title": "Not relay replayed messages in a mesh network", + "type": "bool" + }, + { + "children": [], + "depends_on": "BLE_MESH", + "help": "Number of messages that are cached for the network. This helps prevent\nunnecessary decryption operations and unnecessary relays. This option\nis similar to Replay protection list, but has a different purpose.\nA node is not required to cache the entire Network PDU and may cache\nonly part of it for tracking, such as values for SRC/SEQ or others.", + "id": "BLE_MESH_MSG_CACHE_SIZE", + "name": "BLE_MESH_MSG_CACHE_SIZE", + "range": null, + "title": "Network message cache size", + "type": "int" + }, + { + "children": [], + "depends_on": "BLE_MESH", + "help": "Number of advertising buffers available. The transport layer reserves\nADV_BUF_COUNT - 3 buffers for outgoing segments. The maximum outgoing\nSDU size is 12 times this value (out of which 4 or 8 bytes are used\nfor the Transport Layer MIC). For example, 5 segments means the maximum\nSDU size is 60 bytes, which leaves 56 bytes for application layer data\nusing a 4-byte MIC, or 52 bytes using an 8-byte MIC.", + "id": "BLE_MESH_ADV_BUF_COUNT", + "name": "BLE_MESH_ADV_BUF_COUNT", + "range": null, + "title": "Number of advertising buffers", + "type": "int" + }, + { + "children": [], + "depends_on": "BLE_MESH", + "help": "When the IV Update state enters Normal operation or IV Update\nin Progress, we need to keep track of how many hours has passed\nin the state, since the specification requires us to remain in\nthe state at least for 96 hours (Update in Progress has an\nadditional upper limit of 144 hours).\n\nIn order to fulfill the above requirement, even if the node might\nbe powered off once in a while, we need to store persistently\nhow many hours the node has been in the state. This doesn't\nnecessarily need to happen every hour (thanks to the flexible\nduration range). The exact cadence will depend a lot on the\nways that the node will be used and what kind of power source it\nhas.\n\nSince there is no single optimal answer, this configuration\noption allows specifying a divider, i.e. how many intervals\nthe 96 hour minimum gets split into. After each interval the\nduration that the node has been in the current state gets\nstored to flash. E.g. the default value of 4 means that the\nstate is saved every 24 hours (96 / 4).", + "id": "BLE_MESH_IVU_DIVIDER", + "name": "BLE_MESH_IVU_DIVIDER", + "range": null, + "title": "Divider for IV Update state refresh timer", + "type": "int" + }, + { + "children": [], + "depends_on": "BLE_MESH", + "help": "According to Section 3.10.5 of Mesh Specification v1.0.1.\nIf a node in Normal Operation receives a Secure Network beacon with an IV index\nequal to the last known IV index+1 and the IV Update Flag set to 0, the node may\nupdate its IV without going to the IV Update in Progress state, or it may initiate\nan IV Index Recovery procedure (Section 3.10.6), or it may ignore the Secure\nNetwork beacon. The node makes the choice depending on the time since last IV\nupdate and the likelihood that the node has missed the Secure Network beacons\nwith the IV update Flag.\nWhen the above situation is encountered, this option can be used to decide whether\nto perform the IV index recovery procedure.", + "id": "BLE_MESH_IVU_RECOVERY_IVI", + "name": "BLE_MESH_IVU_RECOVERY_IVI", + "range": null, + "title": "Recovery the IV index when the latest whole IV update procedure is missed", + "type": "bool" + }, + { + "children": [], + "depends_on": "BLE_MESH_V11_SUPPORT && BLE_MESH", + "help": "Enable this option to use the enhanced segmentation and reassembly\nmechanism introduced in Bluetooth Mesh Protocol 1.1.", + "id": "BLE_MESH_SAR_ENHANCEMENT", + "name": "BLE_MESH_SAR_ENHANCEMENT", + "range": null, + "title": "Segmentation and reassembly enhancement", + "type": "bool" + }, + { + "children": [], + "depends_on": "BLE_MESH", + "help": "Maximum number of simultaneous outgoing multi-segment and/or reliable messages.\nThe default value is 1, which means the device can only send one segmented\nmessage at a time. And if another segmented message is going to be sent, it\nshould wait for the completion of the previous one.\nIf users are going to send multiple segmented messages at the same time, this\nvalue should be configured properly.", + "id": "BLE_MESH_TX_SEG_MSG_COUNT", + "name": "BLE_MESH_TX_SEG_MSG_COUNT", + "range": null, + "title": "Maximum number of simultaneous outgoing segmented messages", + "type": "int" + }, + { + "children": [], + "depends_on": "BLE_MESH", + "help": "Maximum number of simultaneous incoming multi-segment and/or reliable messages.\nThe default value is 1, which means the device can only receive one segmented\nmessage at a time. And if another segmented message is going to be received,\nit should wait for the completion of the previous one.\nIf users are going to receive multiple segmented messages at the same time, this\nvalue should be configured properly.", + "id": "BLE_MESH_RX_SEG_MSG_COUNT", + "name": "BLE_MESH_RX_SEG_MSG_COUNT", + "range": null, + "title": "Maximum number of simultaneous incoming segmented messages", + "type": "int" + }, + { + "children": [], + "depends_on": "BLE_MESH", + "help": "Maximum incoming Upper Transport Access PDU length. Leave this to the default\nvalue, unless you really need to optimize memory usage.", + "id": "BLE_MESH_RX_SDU_MAX", + "name": "BLE_MESH_RX_SDU_MAX", + "range": null, + "title": "Maximum incoming Upper Transport Access PDU length", + "type": "int" + }, + { + "children": [], + "depends_on": "BLE_MESH", + "help": "Maximum number of segments supported for outgoing messages.\nThis value should typically be fine-tuned based on what\nmodels the local node supports, i.e. what's the largest\nmessage payload that the node needs to be able to send.\nThis value affects memory and call stack consumption, which\nis why the default is lower than the maximum that the\nspecification would allow (32 segments).\n\nThe maximum outgoing SDU size is 12 times this number (out of\nwhich 4 or 8 bytes is used for the Transport Layer MIC). For\nexample, 5 segments means the maximum SDU size is 60 bytes,\nwhich leaves 56 bytes for application layer data using a\n4-byte MIC and 52 bytes using an 8-byte MIC.\n\nBe sure to specify a sufficient number of advertising buffers\nwhen setting this option to a higher value. There must be at\nleast three more advertising buffers (BLE_MESH_ADV_BUF_COUNT)\nas there are outgoing segments.", + "id": "BLE_MESH_TX_SEG_MAX", + "name": "BLE_MESH_TX_SEG_MAX", + "range": null, + "title": "Maximum number of segments in outgoing messages", + "type": "int" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "BLE_MESH_RELAY_ADV_BUF && BLE_MESH_RELAY && BLE_MESH", + "help": "Number of advertising buffers for relay packets available.", + "id": "BLE_MESH_RELAY_ADV_BUF_COUNT", + "name": "BLE_MESH_RELAY_ADV_BUF_COUNT", + "range": null, + "title": "Number of advertising buffers for relay packets", + "type": "int" + } + ], + "depends_on": "BLE_MESH_RELAY && BLE_MESH", + "help": "When selected, self-send packets will be put in a high-priority\nqueue and relay packets will be put in a low-priority queue.", + "id": "BLE_MESH_RELAY_ADV_BUF", + "name": "BLE_MESH_RELAY_ADV_BUF", + "range": null, + "title": "Use separate advertising buffers for relay packets", + "type": "bool" + } + ], + "depends_on": "BLE_MESH_NODE && BLE_MESH", + "help": "Support for acting as a Mesh Relay Node. Enabling this option will allow\na node to support the Relay feature, and the Relay feature can still\nbe enabled or disabled by proper configuration messages. Disabling this\noption will let a node not support the Relay feature.", + "id": "BLE_MESH_RELAY", + "name": "BLE_MESH_RELAY", + "range": null, + "title": "Relay support", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "BLE_MESH_LOW_POWER && BLE_MESH", + "help": "Perform the Friendship establishment using low power with the help of a\nreduced scan duty cycle. The downside of this is that the node may miss\nout on messages intended for it until it has successfully set up Friendship\nwith a Friend node.\nWhen this option is enabled, the node will stop scanning for a period of\ntime after a Friend Request or Friend Poll is sent, so as to reduce more\npower consumption.", + "id": "BLE_MESH_LPN_ESTABLISHMENT", + "name": "BLE_MESH_LPN_ESTABLISHMENT", + "range": null, + "title": "Perform Friendship establishment using low power", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "BLE_MESH_LPN_AUTO && BLE_MESH_LOW_POWER && BLE_MESH", + "help": "Time in seconds from the last received message, that the node waits out\nbefore starting to look for Friend nodes.", + "id": "BLE_MESH_LPN_AUTO_TIMEOUT", + "name": "BLE_MESH_LPN_AUTO_TIMEOUT", + "range": null, + "title": "Time from last received message before going to LPN mode", + "type": "int" + } + ], + "depends_on": "BLE_MESH_LOW_POWER && BLE_MESH", + "help": "Once provisioned, automatically enable LPN functionality and start looking\nfor Friend nodes. If this option is disabled LPN mode needs to be manually\nenabled by calling bt_mesh_lpn_set(true).\nWhen an unprovisioned device is provisioned successfully and becomes a node,\nenabling this option will trigger the node starts to send Friend Request at\na certain period until it finds a proper Friend node.", + "id": "BLE_MESH_LPN_AUTO", + "name": "BLE_MESH_LPN_AUTO", + "range": null, + "title": "Automatically start looking for Friend nodes once provisioned", + "type": "bool" + }, + { + "children": [], + "depends_on": "BLE_MESH_LOW_POWER && BLE_MESH", + "help": "Time in seconds between Friend Requests, if a previous Friend Request did\nnot yield any acceptable Friend Offers.", + "id": "BLE_MESH_LPN_RETRY_TIMEOUT", + "name": "BLE_MESH_LPN_RETRY_TIMEOUT", + "range": null, + "title": "Retry timeout for Friend requests", + "type": "int" + }, + { + "children": [], + "depends_on": "BLE_MESH_LOW_POWER && BLE_MESH", + "help": "The contribution of the RSSI, measured by the Friend node, used in Friend\nOffer Delay calculations. 0 = 1, 1 = 1.5, 2 = 2, 3 = 2.5.\nRSSIFactor, one of the parameters carried by Friend Request sent by Low Power\nnode, which is used to calculate the Friend Offer Delay.", + "id": "BLE_MESH_LPN_RSSI_FACTOR", + "name": "BLE_MESH_LPN_RSSI_FACTOR", + "range": null, + "title": "RSSIFactor, used in Friend Offer Delay calculation", + "type": "int" + }, + { + "children": [], + "depends_on": "BLE_MESH_LOW_POWER && BLE_MESH", + "help": "The contribution of the supported Receive Window used in Friend Offer\nDelay calculations. 0 = 1, 1 = 1.5, 2 = 2, 3 = 2.5.\nReceiveWindowFactor, one of the parameters carried by Friend Request sent by\nLow Power node, which is used to calculate the Friend Offer Delay.", + "id": "BLE_MESH_LPN_RECV_WIN_FACTOR", + "name": "BLE_MESH_LPN_RECV_WIN_FACTOR", + "range": null, + "title": "ReceiveWindowFactor, used in Friend Offer Delay calculation", + "type": "int" + }, + { + "children": [], + "depends_on": "BLE_MESH_LOW_POWER && BLE_MESH", + "help": "The MinQueueSizeLog field is defined as log_2(N), where N is the minimum\nnumber of maximum size Lower Transport PDUs that the Friend node can store\nin its Friend Queue. As an example, MinQueueSizeLog value 1 gives N = 2,\nand value 7 gives N = 128.", + "id": "BLE_MESH_LPN_MIN_QUEUE_SIZE", + "name": "BLE_MESH_LPN_MIN_QUEUE_SIZE", + "range": null, + "title": "Minimum size of the acceptable friend queue (MinQueueSizeLog)", + "type": "int" + }, + { + "children": [], + "depends_on": "BLE_MESH_LOW_POWER && BLE_MESH", + "help": "The ReceiveDelay is the time between the Low Power node sending a\nrequest and listening for a response. This delay allows the Friend\nnode time to prepare the response. The value is in units of milliseconds.", + "id": "BLE_MESH_LPN_RECV_DELAY", + "name": "BLE_MESH_LPN_RECV_DELAY", + "range": null, + "title": "Receive delay requested by the local node", + "type": "int" + }, + { + "children": [], + "depends_on": "BLE_MESH_LOW_POWER && BLE_MESH", + "help": "PollTimeout timer is used to measure time between two consecutive\nrequests sent by a Low Power node. If no requests are received\nthe Friend node before the PollTimeout timer expires, then the\nfriendship is considered terminated. The value is in units of 100\nmilliseconds, so e.g. a value of 300 means 30 seconds.\nThe smaller the value, the faster the Low Power node tries to get\nmessages from corresponding Friend node and vice versa.", + "id": "BLE_MESH_LPN_POLL_TIMEOUT", + "name": "BLE_MESH_LPN_POLL_TIMEOUT", + "range": null, + "title": "The value of the PollTimeout timer", + "type": "int" + }, + { + "children": [], + "depends_on": "BLE_MESH_LOW_POWER && BLE_MESH", + "help": "The initial value of the PollTimeout timer when Friendship is to be\nestablished for the first time. After this, the timeout gradually\ngrows toward the actual PollTimeout, doubling in value for each iteration.\nThe value is in units of 100 milliseconds, so e.g. a value of 300 means\n30 seconds.", + "id": "BLE_MESH_LPN_INIT_POLL_TIMEOUT", + "name": "BLE_MESH_LPN_INIT_POLL_TIMEOUT", + "range": null, + "title": "The starting value of the PollTimeout timer", + "type": "int" + }, + { + "children": [], + "depends_on": "BLE_MESH_LOW_POWER && BLE_MESH", + "help": "Latency (in milliseconds) is the time it takes to enable scanning. In\npractice, it means how much time in advance of the Receive Window, the\nrequest to enable scanning is made.", + "id": "BLE_MESH_LPN_SCAN_LATENCY", + "name": "BLE_MESH_LPN_SCAN_LATENCY", + "range": null, + "title": "Latency for enabling scanning", + "type": "int" + }, + { + "children": [], + "depends_on": "BLE_MESH_LOW_POWER && BLE_MESH", + "help": "Maximum number of groups to which the LPN can subscribe.", + "id": "BLE_MESH_LPN_GROUPS", + "name": "BLE_MESH_LPN_GROUPS", + "range": null, + "title": "Number of groups the LPN can subscribe to", + "type": "int" + }, + { + "children": [], + "depends_on": "BLE_MESH_LOW_POWER && BLE_MESH", + "help": "Automatically subscribe all nodes address when friendship\nestablished.", + "id": "BLE_MESH_LPN_SUB_ALL_NODES_ADDR", + "name": "BLE_MESH_LPN_SUB_ALL_NODES_ADDR", + "range": null, + "title": "Automatically subscribe all nodes address", + "type": "bool" + } + ], + "depends_on": "BLE_MESH_NODE && BLE_MESH", + "help": "Enable this option to operate as a Low Power Node. If low power consumption\nis required by a node, this option should be enabled. And once the node\nenters the mesh network, it will try to find a Friend node and establish a\nfriendship.", + "id": "BLE_MESH_LOW_POWER", + "name": "BLE_MESH_LOW_POWER", + "range": null, + "title": "Support for Low Power features", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "BLE_MESH_FRIEND && BLE_MESH", + "help": "Receive Window in milliseconds supported by the Friend node.", + "id": "BLE_MESH_FRIEND_RECV_WIN", + "name": "BLE_MESH_FRIEND_RECV_WIN", + "range": null, + "title": "Friend Receive Window", + "type": "int" + }, + { + "children": [], + "depends_on": "BLE_MESH_FRIEND && BLE_MESH", + "help": "Minimum number of buffers available to be stored for each local Friend Queue.\nThis option decides the size of each buffer which can be used by a Friend node\nto store messages for each Low Power node.", + "id": "BLE_MESH_FRIEND_QUEUE_SIZE", + "name": "BLE_MESH_FRIEND_QUEUE_SIZE", + "range": null, + "title": "Minimum number of buffers supported per Friend Queue", + "type": "int" + }, + { + "children": [], + "depends_on": "BLE_MESH_FRIEND && BLE_MESH", + "help": "Size of the Subscription List that can be supported by a Friend node for a\nLow Power node. And Low Power node can send Friend Subscription List Add or\nFriend Subscription List Remove messages to the Friend node to add or remove\nsubscription addresses.", + "id": "BLE_MESH_FRIEND_SUB_LIST_SIZE", + "name": "BLE_MESH_FRIEND_SUB_LIST_SIZE", + "range": null, + "title": "Friend Subscription List Size", + "type": "int" + }, + { + "children": [], + "depends_on": "BLE_MESH_FRIEND && BLE_MESH", + "help": "Number of Low Power Nodes with which a Friend can have Friendship simultaneously.\nA Friend node can have friendship with multiple Low Power nodes at the same time,\nwhile a Low Power node can only establish friendship with only one Friend node at\nthe same time.", + "id": "BLE_MESH_FRIEND_LPN_COUNT", + "name": "BLE_MESH_FRIEND_LPN_COUNT", + "range": null, + "title": "Number of supported LPN nodes", + "type": "int" + }, + { + "children": [], + "depends_on": "BLE_MESH_FRIEND && BLE_MESH", + "help": "Number of incomplete segment lists tracked for each Friends' LPN.\nIn other words, this determines from how many elements can segmented\nmessages destined for the Friend queue be received simultaneously.", + "id": "BLE_MESH_FRIEND_SEG_RX", + "name": "BLE_MESH_FRIEND_SEG_RX", + "range": null, + "title": "Number of incomplete segment lists per LPN", + "type": "int" + } + ], + "depends_on": "BLE_MESH", + "help": "Enable this option to be able to act as a Friend Node.", + "id": "BLE_MESH_FRIEND", + "name": "BLE_MESH_FRIEND", + "range": null, + "title": "Support for Friend feature", + "type": "bool" + }, + { + "children": [], + "depends_on": "BLE_MESH && BLE_MESH", + "help": "Select this to save the BLE Mesh related rodata code size. Enabling this option\nwill disable the output of BLE Mesh debug log.", + "id": "BLE_MESH_NO_LOG", + "name": "BLE_MESH_NO_LOG", + "range": null, + "title": "Disable BLE Mesh debug logs (minimize bin size)", + "type": "bool" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "BLE_MESH_TRACE_LEVEL_NONE", + "name": "BLE_MESH_TRACE_LEVEL_NONE", + "range": null, + "title": "NONE", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BLE_MESH_TRACE_LEVEL_ERROR", + "name": "BLE_MESH_TRACE_LEVEL_ERROR", + "range": null, + "title": "ERROR", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BLE_MESH_TRACE_LEVEL_WARNING", + "name": "BLE_MESH_TRACE_LEVEL_WARNING", + "range": null, + "title": "WARNING", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BLE_MESH_TRACE_LEVEL_INFO", + "name": "BLE_MESH_TRACE_LEVEL_INFO", + "range": null, + "title": "INFO", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BLE_MESH_TRACE_LEVEL_DEBUG", + "name": "BLE_MESH_TRACE_LEVEL_DEBUG", + "range": null, + "title": "DEBUG", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BLE_MESH_TRACE_LEVEL_VERBOSE", + "name": "BLE_MESH_TRACE_LEVEL_VERBOSE", + "range": null, + "title": "VERBOSE", + "type": "bool" + } + ], + "depends_on": "BLE_MESH && !BLE_MESH_NO_LOG && BLE_MESH && !BLE_MESH_NO_LOG && BLE_MESH", + "help": "Define BLE Mesh trace level for BLE Mesh stack.", + "id": "component-config-esp-ble-mesh-support-ble-mesh-stack-debug-log-level-ble_mesh_stack", + "name": "BLE_MESH_STACK_TRACE_LEVEL", + "title": "BLE_MESH_STACK", + "type": "choice" + }, + { + "children": [], + "depends_on": "BLE_MESH && BLE_MESH && !BLE_MESH_NO_LOG && BLE_MESH", + "help": null, + "id": "BLE_MESH_STACK_TRACE_LEVEL", + "name": "BLE_MESH_STACK_TRACE_LEVEL", + "range": null, + "title": null, + "type": "int" + } + ], + "depends_on": "BLE_MESH && !BLE_MESH_NO_LOG && BLE_MESH", + "id": "component-config-esp-ble-mesh-support-ble-mesh-stack-debug-log-level", + "title": "BLE Mesh STACK DEBUG LOG LEVEL", + "type": "menu" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "BLE_MESH_NET_BUF_TRACE_LEVEL_NONE", + "name": "BLE_MESH_NET_BUF_TRACE_LEVEL_NONE", + "range": null, + "title": "NONE", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BLE_MESH_NET_BUF_TRACE_LEVEL_ERROR", + "name": "BLE_MESH_NET_BUF_TRACE_LEVEL_ERROR", + "range": null, + "title": "ERROR", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BLE_MESH_NET_BUF_TRACE_LEVEL_WARNING", + "name": "BLE_MESH_NET_BUF_TRACE_LEVEL_WARNING", + "range": null, + "title": "WARNING", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BLE_MESH_NET_BUF_TRACE_LEVEL_INFO", + "name": "BLE_MESH_NET_BUF_TRACE_LEVEL_INFO", + "range": null, + "title": "INFO", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BLE_MESH_NET_BUF_TRACE_LEVEL_DEBUG", + "name": "BLE_MESH_NET_BUF_TRACE_LEVEL_DEBUG", + "range": null, + "title": "DEBUG", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "BLE_MESH_NET_BUF_TRACE_LEVEL_VERBOSE", + "name": "BLE_MESH_NET_BUF_TRACE_LEVEL_VERBOSE", + "range": null, + "title": "VERBOSE", + "type": "bool" + } + ], + "depends_on": "BLE_MESH && !BLE_MESH_NO_LOG && BLE_MESH && !BLE_MESH_NO_LOG && BLE_MESH", + "help": "Define BLE Mesh trace level for BLE Mesh net buffer.", + "id": "component-config-esp-ble-mesh-support-ble-mesh-net-buf-debug-log-level-ble_mesh_net_buf", + "name": "BLE_MESH_NET_BUF_TRACE_LEVEL", + "title": "BLE_MESH_NET_BUF", + "type": "choice" + }, + { + "children": [], + "depends_on": "BLE_MESH && BLE_MESH && !BLE_MESH_NO_LOG && BLE_MESH", + "help": null, + "id": "BLE_MESH_NET_BUF_TRACE_LEVEL", + "name": "BLE_MESH_NET_BUF_TRACE_LEVEL", + "range": null, + "title": null, + "type": "int" + } + ], + "depends_on": "BLE_MESH && !BLE_MESH_NO_LOG && BLE_MESH", + "id": "component-config-esp-ble-mesh-support-ble-mesh-net-buf-debug-log-level", + "title": "BLE Mesh NET BUF DEBUG LOG LEVEL", + "type": "menu" + }, + { + "children": [], + "depends_on": "BLE_MESH", + "help": "Timeout value used by the node to get response of the acknowledged\nmessage which is sent by the client model.\nThis value indicates the maximum time that a client model waits for\nthe response of the sent acknowledged messages. If a client model\nuses 0 as the timeout value when sending acknowledged messages, then\nthe default value will be used which is four seconds.", + "id": "BLE_MESH_CLIENT_MSG_TIMEOUT", + "name": "BLE_MESH_CLIENT_MSG_TIMEOUT", + "range": null, + "title": "Timeout(ms) for client message response", + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "BLE_MESH", + "help": "Enable support for Configuration Client model.", + "id": "BLE_MESH_CFG_CLI", + "name": "BLE_MESH_CFG_CLI", + "range": null, + "title": "Configuration Client model", + "type": "bool" + }, + { + "children": [], + "depends_on": "BLE_MESH", + "help": "Enable support for Health Client model.", + "id": "BLE_MESH_HEALTH_CLI", + "name": "BLE_MESH_HEALTH_CLI", + "range": null, + "title": "Health Client model", + "type": "bool" + }, + { + "children": [], + "depends_on": "BLE_MESH", + "help": "Enable support for Health Server model.", + "id": "BLE_MESH_HEALTH_SRV", + "name": "BLE_MESH_HEALTH_SRV", + "range": null, + "title": "Health Server model", + "type": "bool" + }, + { + "children": [], + "depends_on": "BLE_MESH_V11_SUPPORT && BLE_MESH", + "help": "Enable support for Bridge Configuration Client model.", + "id": "BLE_MESH_BRC_CLI", + "name": "BLE_MESH_BRC_CLI", + "range": null, + "title": "Bridge Configuration Client model", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "BLE_MESH_BRC_SRV && BLE_MESH_V11_SUPPORT && BLE_MESH", + "help": "Maximum number of Bridging Table entries that the Bridge Configuration Server can support.", + "id": "BLE_MESH_MAX_BRIDGING_TABLE_ENTRY_COUNT", + "name": "BLE_MESH_MAX_BRIDGING_TABLE_ENTRY_COUNT", + "range": null, + "title": "Maximum number of Bridging Table entries", + "type": "int" + }, + { + "children": [], + "depends_on": "BLE_MESH_BRC_SRV && BLE_MESH_V11_SUPPORT && BLE_MESH", + "help": "This option specifies the maximum capacity of the bridge replay\nprotection list. The bridge replay protection list is used to\nprevent a bridged subnet from replay attack, which will store the\nsource address and sequence number of the received bridge messages.", + "id": "BLE_MESH_BRIDGE_CRPL", + "name": "BLE_MESH_BRIDGE_CRPL", + "range": null, + "title": "Maximum capacity of bridge replay protection list", + "type": "int" + } + ], + "depends_on": "BLE_MESH_V11_SUPPORT && BLE_MESH", + "help": "Enable support for Bridge Configuration Server model.", + "id": "BLE_MESH_BRC_SRV", + "name": "BLE_MESH_BRC_SRV", + "range": null, + "title": "Bridge Configuration Server model", + "type": "bool" + }, + { + "children": [], + "depends_on": "BLE_MESH_V11_SUPPORT && BLE_MESH", + "help": "Enable support for Mesh Private Beacon Client model.", + "id": "BLE_MESH_PRB_CLI", + "name": "BLE_MESH_PRB_CLI", + "range": null, + "title": "Mesh Private Beacon Client model", + "type": "bool" + }, + { + "children": [], + "depends_on": "BLE_MESH_V11_SUPPORT && BLE_MESH", + "help": "Enable support for Mesh Private Beacon Server model.", + "id": "BLE_MESH_PRB_SRV", + "name": "BLE_MESH_PRB_SRV", + "range": null, + "title": "Mesh Private Beacon Server model", + "type": "bool" + }, + { + "children": [], + "depends_on": "BLE_MESH_V11_SUPPORT && BLE_MESH", + "help": "Enable support for On-Demand Private Proxy Client model.", + "id": "BLE_MESH_ODP_CLI", + "name": "BLE_MESH_ODP_CLI", + "range": null, + "title": "On-Demand Private Proxy Client model", + "type": "bool" + }, + { + "children": [], + "depends_on": "BLE_MESH_PROXY_SOLIC_PDU_RX && BLE_MESH_V11_SUPPORT && BLE_MESH", + "help": "Enable support for On-Demand Private Proxy Server model.", + "id": "BLE_MESH_ODP_SRV", + "name": "BLE_MESH_ODP_SRV", + "range": null, + "title": "On-Demand Private Proxy Server model", + "type": "bool" + }, + { + "children": [], + "depends_on": "BLE_MESH_V11_SUPPORT && BLE_MESH", + "help": "Enable support for Solicitation PDU RPL Configuration Client model.", + "id": "BLE_MESH_SRPL_CLI", + "name": "BLE_MESH_SRPL_CLI", + "range": null, + "title": "Solicitation PDU RPL Configuration Client model", + "type": "bool" + }, + { + "children": [], + "depends_on": "BLE_MESH_PROXY_SOLIC_PDU_RX && BLE_MESH_V11_SUPPORT && BLE_MESH", + "help": "Enable support for Solicitation PDU RPL Configuration Server model.\nNote:\nThis option depends on the functionality of receiving Solicitation\nPDU. If the device doesn't support receiving Solicitation PDU, then\nthere is no need to enable this server model.", + "id": "BLE_MESH_SRPL_SRV", + "name": "BLE_MESH_SRPL_SRV", + "range": null, + "title": "Solicitation PDU RPL Configuration Server model", + "type": "bool" + }, + { + "children": [], + "depends_on": "BLE_MESH_V11_SUPPORT && BLE_MESH", + "help": "Enable support for Opcodes Aggregator Client model.", + "id": "BLE_MESH_AGG_CLI", + "name": "BLE_MESH_AGG_CLI", + "range": null, + "title": "Opcodes Aggregator Client model", + "type": "bool" + }, + { + "children": [], + "depends_on": "BLE_MESH_V11_SUPPORT && BLE_MESH", + "help": "Enable support for Opcodes Aggregator Server model.", + "id": "BLE_MESH_AGG_SRV", + "name": "BLE_MESH_AGG_SRV", + "range": null, + "title": "Opcodes Aggregator Server model", + "type": "bool" + }, + { + "children": [], + "depends_on": "BLE_MESH_V11_SUPPORT && BLE_MESH", + "help": "Enable support for SAR Configuration Client model.", + "id": "BLE_MESH_SAR_CLI", + "name": "BLE_MESH_SAR_CLI", + "range": null, + "title": "SAR Configuration Client model", + "type": "bool" + }, + { + "children": [], + "depends_on": "BLE_MESH_V11_SUPPORT && BLE_MESH", + "help": "Enable support for SAR Configuration Server model.", + "id": "BLE_MESH_SAR_SRV", + "name": "BLE_MESH_SAR_SRV", + "range": null, + "title": "SAR Configuration Server model", + "type": "bool" + }, + { + "children": [], + "depends_on": "BLE_MESH_V11_SUPPORT && BLE_MESH", + "help": "Composition Data Page 1 contains information about the relationships\namong models.\nEach model either can be a root model or can extend other models.", + "id": "BLE_MESH_COMP_DATA_1", + "name": "BLE_MESH_COMP_DATA_1", + "range": null, + "title": "Support Composition Data Page 1", + "type": "bool" + }, + { + "children": [], + "depends_on": "BLE_MESH_V11_SUPPORT && BLE_MESH", + "help": "Composition Data Page 128 is used to indicate the structure of\nelements, features, and models of a node after the successful\nexecution of the Node Address Refresh procedure or the Node\nComposition Refresh procedure, or after the execution of the\nNode Removal procedure followed by the provisioning process.\nComposition Data Page 128 shall be present if the node supports\nthe Remote Provisioning Server model; otherwise it is optional.", + "id": "BLE_MESH_COMP_DATA_128", + "name": "BLE_MESH_COMP_DATA_128", + "range": null, + "title": "Support Composition Data Page 128", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "BLE_MESH_MODELS_METADATA_0 && BLE_MESH_V11_SUPPORT && BLE_MESH", + "help": "The Models Metadata state contains metadata of a node\u2019s models.\nThe Models Metadata state is composed of a number of pages of\ninformation.\nModels Metadata Page 128 contains metadata for the node\u2019s models\nafter the successful execution of the Node Address Refresh\nprocedure or the Node Composition Refresh procedure, or after\nthe execution of the Node Removal procedure followed by the\nprovisioning process.\nModels Metadata Page 128 shall be present if the node supports\nthe Remote Provisioning Server model and the node supports the\nLarge Composition Data Server model.", + "id": "BLE_MESH_MODELS_METADATA_128", + "name": "BLE_MESH_MODELS_METADATA_128", + "range": null, + "title": "Support Models Metadata Page 128", + "type": "bool" + } + ], + "depends_on": "BLE_MESH_V11_SUPPORT && BLE_MESH", + "help": "The Models Metadata state contains metadata of a node\u2019s models.\nThe Models Metadata state is composed of a number of pages of\ninformation.\nModels Metadata Page 0 shall be present if the node supports\nthe Large Composition Data Server model.", + "id": "BLE_MESH_MODELS_METADATA_0", + "name": "BLE_MESH_MODELS_METADATA_0", + "range": null, + "title": "Support Models Metadata Page 0", + "type": "bool" + }, + { + "children": [], + "depends_on": "BLE_MESH_V11_SUPPORT && BLE_MESH", + "help": "Enable support for Large Composition Data Client model.", + "id": "BLE_MESH_LCD_CLI", + "name": "BLE_MESH_LCD_CLI", + "range": null, + "title": "Large Composition Data Client model", + "type": "bool" + }, + { + "children": [], + "depends_on": "BLE_MESH_V11_SUPPORT && BLE_MESH", + "help": "Enable support for Large Composition Data Server model.", + "id": "BLE_MESH_LCD_SRV", + "name": "BLE_MESH_LCD_SRV", + "range": null, + "title": "Large Composition Data Server model", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "BLE_MESH_RPR_CLI && BLE_MESH_V11_SUPPORT && BLE_MESH", + "help": "This option specifies how many devices can be provisioned at the same time\nusing PB-REMOTE. For example, if the value is 2, it means a Provisioner can\nprovision two unprovisioned devices with PB-REMOTE at the same time.", + "id": "BLE_MESH_RPR_CLI_PROV_SAME_TIME", + "name": "BLE_MESH_RPR_CLI_PROV_SAME_TIME", + "range": null, + "title": "Maximum number of PB-Remote running at the same time by Provisioner", + "type": "int" + } + ], + "depends_on": "BLE_MESH_PROVISIONER && BLE_MESH_V11_SUPPORT && BLE_MESH", + "help": "Enable support for Remote Provisioning Client model", + "id": "BLE_MESH_RPR_CLI", + "name": "BLE_MESH_RPR_CLI", + "range": null, + "title": "Remote Provisioning Client model", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "BLE_MESH_RPR_SRV && BLE_MESH_V11_SUPPORT && BLE_MESH", + "help": "This option specifies how many device information can a Remote\nProvisioning Server store each time while scanning.", + "id": "BLE_MESH_RPR_SRV_MAX_SCANNED_ITEMS", + "name": "BLE_MESH_RPR_SRV_MAX_SCANNED_ITEMS", + "range": null, + "title": "Maximum number of device information can be scanned", + "type": "int" + }, + { + "children": [], + "depends_on": "BLE_MESH_RPR_SRV && BLE_MESH_V11_SUPPORT && BLE_MESH", + "help": "Enable this option to support Active Scan for remote provisioning.", + "id": "BLE_MESH_RPR_SRV_ACTIVE_SCAN", + "name": "BLE_MESH_RPR_SRV_ACTIVE_SCAN", + "range": null, + "title": "Support Active Scan for remote provisioning", + "type": "bool" + }, + { + "children": [], + "depends_on": "BLE_MESH_RPR_SRV && BLE_MESH_V11_SUPPORT && BLE_MESH", + "help": "This option specifies how many extended scan procedures can be\nstarted by the Remote Provisioning Server.", + "id": "BLE_MESH_RPR_SRV_MAX_EXT_SCAN", + "name": "BLE_MESH_RPR_SRV_MAX_EXT_SCAN", + "range": null, + "title": "Maximum number of extended scan procedures", + "type": "int" + } + ], + "depends_on": "BLE_MESH_NODE && BLE_MESH_V11_SUPPORT && BLE_MESH", + "help": "Enable support for Remote Provisioning Server model", + "id": "BLE_MESH_RPR_SRV", + "name": "BLE_MESH_RPR_SRV", + "range": null, + "title": "Remote Provisioning Server model", + "type": "bool" + }, + { + "children": [], + "depends_on": "BLE_MESH_V11_SUPPORT && BLE_MESH", + "help": "Enable support for Directed Forwarding Configuration Client model.", + "id": "BLE_MESH_DF_CLI", + "name": "BLE_MESH_DF_CLI", + "range": null, + "title": "Directed Forwarding Configuration Client model", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "BLE_MESH_DF_SRV && BLE_MESH_V11_SUPPORT && BLE_MESH", + "help": "Maximum number of Discovery Table entries supported by the node in a given subnet.", + "id": "BLE_MESH_MAX_DISC_TABLE_ENTRY_COUNT", + "name": "BLE_MESH_MAX_DISC_TABLE_ENTRY_COUNT", + "range": null, + "title": "Maximum number of discovery table entries in a given subnet", + "type": "int" + }, + { + "children": [], + "depends_on": "BLE_MESH_DF_SRV && BLE_MESH_V11_SUPPORT && BLE_MESH", + "help": "Maximum number of Forward Table entries supported by the node in a given subnet.", + "id": "BLE_MESH_MAX_FORWARD_TABLE_ENTRY_COUNT", + "name": "BLE_MESH_MAX_FORWARD_TABLE_ENTRY_COUNT", + "range": null, + "title": "Maximum number of forward table entries in a given subnet", + "type": "int" + }, + { + "children": [], + "depends_on": "BLE_MESH_DF_SRV && BLE_MESH_V11_SUPPORT && BLE_MESH", + "help": "Maximum size of dependent nodes list supported by each forward table entry.", + "id": "BLE_MESH_MAX_DEPS_NODES_PER_PATH", + "name": "BLE_MESH_MAX_DEPS_NODES_PER_PATH", + "range": null, + "title": "Maximum number of dependent nodes per path", + "type": "int" + }, + { + "children": [], + "depends_on": "BLE_MESH_DF_SRV && BLE_MESH_V11_SUPPORT && BLE_MESH", + "help": "The option only removes the Path Use timer; all other behavior of the\ndevice is not changed.\nIf Path Monitoring test mode is going to be used, this option should\nbe enabled.", + "id": "BLE_MESH_PATH_MONITOR_TEST", + "name": "BLE_MESH_PATH_MONITOR_TEST", + "range": null, + "title": "Enable Path Monitoring test mode", + "type": "bool" + }, + { + "children": [], + "depends_on": "BLE_MESH_GATT_PROXY_SERVER && BLE_MESH_DF_SRV && BLE_MESH_V11_SUPPORT && BLE_MESH", + "help": "Support Directed Proxy functionality.", + "id": "BLE_MESH_SUPPORT_DIRECTED_PROXY", + "name": "BLE_MESH_SUPPORT_DIRECTED_PROXY", + "range": null, + "title": "Enable Directed Proxy functionality", + "type": "bool" + } + ], + "depends_on": "BLE_MESH_V11_SUPPORT && BLE_MESH", + "help": "Enable support for Directed Forwarding Configuration Server model.", + "id": "BLE_MESH_DF_SRV", + "name": "BLE_MESH_DF_SRV", + "range": null, + "title": "Directed Forwarding Configuration Server model", + "type": "bool" + } + ], + "depends_on": "BLE_MESH", + "id": "component-config-esp-ble-mesh-support-support-for-ble-mesh-foundation-models", + "title": "Support for BLE Mesh Foundation models", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": "BLE_MESH", + "help": "Enable support for Generic OnOff Client model.", + "id": "BLE_MESH_GENERIC_ONOFF_CLI", + "name": "BLE_MESH_GENERIC_ONOFF_CLI", + "range": null, + "title": "Generic OnOff Client model", + "type": "bool" + }, + { + "children": [], + "depends_on": "BLE_MESH", + "help": "Enable support for Generic Level Client model.", + "id": "BLE_MESH_GENERIC_LEVEL_CLI", + "name": "BLE_MESH_GENERIC_LEVEL_CLI", + "range": null, + "title": "Generic Level Client model", + "type": "bool" + }, + { + "children": [], + "depends_on": "BLE_MESH", + "help": "Enable support for Generic Default Transition Time Client model.", + "id": "BLE_MESH_GENERIC_DEF_TRANS_TIME_CLI", + "name": "BLE_MESH_GENERIC_DEF_TRANS_TIME_CLI", + "range": null, + "title": "Generic Default Transition Time Client model", + "type": "bool" + }, + { + "children": [], + "depends_on": "BLE_MESH", + "help": "Enable support for Generic Power OnOff Client model.", + "id": "BLE_MESH_GENERIC_POWER_ONOFF_CLI", + "name": "BLE_MESH_GENERIC_POWER_ONOFF_CLI", + "range": null, + "title": "Generic Power OnOff Client model", + "type": "bool" + }, + { + "children": [], + "depends_on": "BLE_MESH", + "help": "Enable support for Generic Power Level Client model.", + "id": "BLE_MESH_GENERIC_POWER_LEVEL_CLI", + "name": "BLE_MESH_GENERIC_POWER_LEVEL_CLI", + "range": null, + "title": "Generic Power Level Client model", + "type": "bool" + }, + { + "children": [], + "depends_on": "BLE_MESH", + "help": "Enable support for Generic Battery Client model.", + "id": "BLE_MESH_GENERIC_BATTERY_CLI", + "name": "BLE_MESH_GENERIC_BATTERY_CLI", + "range": null, + "title": "Generic Battery Client model", + "type": "bool" + }, + { + "children": [], + "depends_on": "BLE_MESH", + "help": "Enable support for Generic Location Client model.", + "id": "BLE_MESH_GENERIC_LOCATION_CLI", + "name": "BLE_MESH_GENERIC_LOCATION_CLI", + "range": null, + "title": "Generic Location Client model", + "type": "bool" + }, + { + "children": [], + "depends_on": "BLE_MESH", + "help": "Enable support for Generic Property Client model.", + "id": "BLE_MESH_GENERIC_PROPERTY_CLI", + "name": "BLE_MESH_GENERIC_PROPERTY_CLI", + "range": null, + "title": "Generic Property Client model", + "type": "bool" + }, + { + "children": [], + "depends_on": "BLE_MESH", + "help": "Enable support for Sensor Client model.", + "id": "BLE_MESH_SENSOR_CLI", + "name": "BLE_MESH_SENSOR_CLI", + "range": null, + "title": "Sensor Client model", + "type": "bool" + }, + { + "children": [], + "depends_on": "BLE_MESH", + "help": "Enable support for Time Client model.", + "id": "BLE_MESH_TIME_CLI", + "name": "BLE_MESH_TIME_CLI", + "range": null, + "title": "Time Client model", + "type": "bool" + }, + { + "children": [], + "depends_on": "BLE_MESH", + "help": "Enable support for Scene Client model.", + "id": "BLE_MESH_SCENE_CLI", + "name": "BLE_MESH_SCENE_CLI", + "range": null, + "title": "Scene Client model", + "type": "bool" + }, + { + "children": [], + "depends_on": "BLE_MESH", + "help": "Enable support for Scheduler Client model.", + "id": "BLE_MESH_SCHEDULER_CLI", + "name": "BLE_MESH_SCHEDULER_CLI", + "range": null, + "title": "Scheduler Client model", + "type": "bool" + }, + { + "children": [], + "depends_on": "BLE_MESH", + "help": "Enable support for Light Lightness Client model.", + "id": "BLE_MESH_LIGHT_LIGHTNESS_CLI", + "name": "BLE_MESH_LIGHT_LIGHTNESS_CLI", + "range": null, + "title": "Light Lightness Client model", + "type": "bool" + }, + { + "children": [], + "depends_on": "BLE_MESH", + "help": "Enable support for Light CTL Client model.", + "id": "BLE_MESH_LIGHT_CTL_CLI", + "name": "BLE_MESH_LIGHT_CTL_CLI", + "range": null, + "title": "Light CTL Client model", + "type": "bool" + }, + { + "children": [], + "depends_on": "BLE_MESH", + "help": "Enable support for Light HSL Client model.", + "id": "BLE_MESH_LIGHT_HSL_CLI", + "name": "BLE_MESH_LIGHT_HSL_CLI", + "range": null, + "title": "Light HSL Client model", + "type": "bool" + }, + { + "children": [], + "depends_on": "BLE_MESH", + "help": "Enable support for Light XYL Client model.", + "id": "BLE_MESH_LIGHT_XYL_CLI", + "name": "BLE_MESH_LIGHT_XYL_CLI", + "range": null, + "title": "Light XYL Client model", + "type": "bool" + }, + { + "children": [], + "depends_on": "BLE_MESH", + "help": "Enable support for Light LC Client model.", + "id": "BLE_MESH_LIGHT_LC_CLI", + "name": "BLE_MESH_LIGHT_LC_CLI", + "range": null, + "title": "Light LC Client model", + "type": "bool" + }, + { + "children": [], + "depends_on": "BLE_MESH", + "help": "Enable support for Generic server models.", + "id": "BLE_MESH_GENERIC_SERVER", + "name": "BLE_MESH_GENERIC_SERVER", + "range": null, + "title": "Generic server models", + "type": "bool" + }, + { + "children": [], + "depends_on": "BLE_MESH", + "help": "Enable support for Sensor server models.", + "id": "BLE_MESH_SENSOR_SERVER", + "name": "BLE_MESH_SENSOR_SERVER", + "range": null, + "title": "Sensor server models", + "type": "bool" + }, + { + "children": [], + "depends_on": "BLE_MESH", + "help": "Enable support for Time and Scenes server models.", + "id": "BLE_MESH_TIME_SCENE_SERVER", + "name": "BLE_MESH_TIME_SCENE_SERVER", + "range": null, + "title": "Time and Scenes server models", + "type": "bool" + }, + { + "children": [], + "depends_on": "BLE_MESH", + "help": "Enable support for Lighting server models.", + "id": "BLE_MESH_LIGHTING_SERVER", + "name": "BLE_MESH_LIGHTING_SERVER", + "range": null, + "title": "Lighting server models", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "BLE_MESH_MBT_CLI && BLE_MESH", + "help": "Maximum number of BLOB Transfer Server models that can participating\nin the BLOB transfer with a BLOB Transfer Client model.", + "id": "BLE_MESH_MAX_BLOB_RECEIVERS", + "name": "BLE_MESH_MAX_BLOB_RECEIVERS", + "range": null, + "title": "Maximum number of simultaneous blob receivers", + "type": "int" + } + ], + "depends_on": "BLE_MESH_V11_SUPPORT && BLE_MESH", + "help": "Enable support for BLOB Transfer Client model.", + "id": "BLE_MESH_MBT_CLI", + "name": "BLE_MESH_MBT_CLI", + "range": null, + "title": "BLOB Transfer Client model", + "type": "bool" + }, + { + "children": [], + "depends_on": "BLE_MESH_V11_SUPPORT && BLE_MESH", + "help": "Enable support for BLOB Transfer Server model.", + "id": "BLE_MESH_MBT_SRV", + "name": "BLE_MESH_MBT_SRV", + "range": null, + "title": "BLOB Transfer Server model", + "type": "bool" + } + ], + "depends_on": "BLE_MESH", + "id": "component-config-esp-ble-mesh-support-support-for-ble-mesh-client-server-models", + "title": "Support for BLE Mesh Client/Server models", + "type": "menu" + }, + { + "children": [], + "depends_on": "BLE_MESH", + "help": "This option removes the 96 hour limit of the IV Update Procedure and\nlets the state to be changed at any time.\nIf IV Update test mode is going to be used, this option should be enabled.", + "id": "BLE_MESH_IV_UPDATE_TEST", + "name": "BLE_MESH_IV_UPDATE_TEST", + "range": null, + "title": "Test the IV Update Procedure", + "type": "bool" + }, + { + "children": [], + "depends_on": "BLE_MESH", + "help": "This option is used to decide whether discarding the old SeqAuth when\nreceiving a segmented message.", + "id": "BLE_MESH_DISCARD_OLD_SEQ_AUTH", + "name": "BLE_MESH_DISCARD_OLD_SEQ_AUTH", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "BLE_MESH", + "help": "This option adds extra self-tests which are run every time BLE Mesh\nnetworking is initialized.", + "id": "BLE_MESH_SELF_TEST", + "name": "BLE_MESH_SELF_TEST", + "range": null, + "title": "Perform BLE Mesh self-tests", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "BLE_MESH_BQB_TEST && BLE_MESH", + "help": "This option is used to enable the log of auto-pts test.", + "id": "BLE_MESH_BQB_TEST_LOG", + "name": "BLE_MESH_BQB_TEST_LOG", + "range": null, + "title": null, + "type": "bool" + } + ], + "depends_on": "BLE_MESH", + "help": "This option is used to enable some internal functions for auto-pts test.", + "id": "BLE_MESH_BQB_TEST", + "name": "BLE_MESH_BQB_TEST", + "range": null, + "title": "Enable BLE Mesh specific internal test", + "type": "bool" + }, + { + "children": [], + "depends_on": "BLE_MESH_SELF_TEST && BLE_MESH", + "help": "With this option enabled, an unprovisioned device can automatically\nenters mesh network using a specific test function without the pro-\nvisioning procedure. And on the Provisioner side, a test function\nneeds to be invoked to add the node information into the mesh stack.", + "id": "BLE_MESH_TEST_AUTO_ENTER_NETWORK", + "name": "BLE_MESH_TEST_AUTO_ENTER_NETWORK", + "range": null, + "title": "Unprovisioned device enters mesh network automatically", + "type": "bool" + }, + { + "children": [], + "depends_on": "BLE_MESH_SELF_TEST && BLE_MESH", + "help": "With this option enabled, users can use white list to filter mesh\nadvertising packets while scanning.", + "id": "BLE_MESH_TEST_USE_WHITE_LIST", + "name": "BLE_MESH_TEST_USE_WHITE_LIST", + "range": null, + "title": "Use white list to filter mesh advertising packets", + "type": "bool" + }, + { + "children": [], + "depends_on": "BLE_MESH", + "help": "Activate shell module that provides BLE Mesh commands to the console.", + "id": "BLE_MESH_SHELL", + "name": "BLE_MESH_SHELL", + "range": null, + "title": "Enable BLE Mesh shell", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "BLE_MESH_DEBUG && BLE_MESH", + "help": "Enable Network layer debug logs for the BLE Mesh functionality.", + "id": "BLE_MESH_DEBUG_NET", + "name": "BLE_MESH_DEBUG_NET", + "range": null, + "title": "Network layer debug", + "type": "bool" + }, + { + "children": [], + "depends_on": "BLE_MESH_DEBUG && BLE_MESH", + "help": "Enable Transport layer debug logs for the BLE Mesh functionality.", + "id": "BLE_MESH_DEBUG_TRANS", + "name": "BLE_MESH_DEBUG_TRANS", + "range": null, + "title": "Transport layer debug", + "type": "bool" + }, + { + "children": [], + "depends_on": "BLE_MESH_DEBUG && BLE_MESH", + "help": "Enable Beacon-related debug logs for the BLE Mesh functionality.", + "id": "BLE_MESH_DEBUG_BEACON", + "name": "BLE_MESH_DEBUG_BEACON", + "range": null, + "title": "Beacon debug", + "type": "bool" + }, + { + "children": [], + "depends_on": "BLE_MESH_DEBUG && BLE_MESH", + "help": "Enable cryptographic debug logs for the BLE Mesh functionality.", + "id": "BLE_MESH_DEBUG_CRYPTO", + "name": "BLE_MESH_DEBUG_CRYPTO", + "range": null, + "title": "Crypto debug", + "type": "bool" + }, + { + "children": [], + "depends_on": "BLE_MESH_DEBUG && BLE_MESH", + "help": "Enable Provisioning debug logs for the BLE Mesh functionality.", + "id": "BLE_MESH_DEBUG_PROV", + "name": "BLE_MESH_DEBUG_PROV", + "range": null, + "title": "Provisioning debug", + "type": "bool" + }, + { + "children": [], + "depends_on": "BLE_MESH_DEBUG && BLE_MESH", + "help": "Enable Access layer debug logs for the BLE Mesh functionality.", + "id": "BLE_MESH_DEBUG_ACCESS", + "name": "BLE_MESH_DEBUG_ACCESS", + "range": null, + "title": "Access layer debug", + "type": "bool" + }, + { + "children": [], + "depends_on": "BLE_MESH_DEBUG && BLE_MESH", + "help": "Enable Foundation Models debug logs for the BLE Mesh functionality.", + "id": "BLE_MESH_DEBUG_MODEL", + "name": "BLE_MESH_DEBUG_MODEL", + "range": null, + "title": "Foundation model debug", + "type": "bool" + }, + { + "children": [], + "depends_on": "BLE_MESH_DEBUG && BLE_MESH", + "help": "Enable advertising debug logs for the BLE Mesh functionality.", + "id": "BLE_MESH_DEBUG_ADV", + "name": "BLE_MESH_DEBUG_ADV", + "range": null, + "title": "Advertising debug", + "type": "bool" + }, + { + "children": [], + "depends_on": "BLE_MESH_DEBUG && BLE_MESH", + "help": "Enable Low Power debug logs for the BLE Mesh functionality.", + "id": "BLE_MESH_DEBUG_LOW_POWER", + "name": "BLE_MESH_DEBUG_LOW_POWER", + "range": null, + "title": "Low Power debug", + "type": "bool" + }, + { + "children": [], + "depends_on": "BLE_MESH_DEBUG && BLE_MESH", + "help": "Enable Friend debug logs for the BLE Mesh functionality.", + "id": "BLE_MESH_DEBUG_FRIEND", + "name": "BLE_MESH_DEBUG_FRIEND", + "range": null, + "title": "Friend debug", + "type": "bool" + }, + { + "children": [], + "depends_on": "BLE_MESH_PROXY && BLE_MESH_DEBUG && BLE_MESH", + "help": "Enable Proxy protocol debug logs for the BLE Mesh functionality.", + "id": "BLE_MESH_DEBUG_PROXY", + "name": "BLE_MESH_DEBUG_PROXY", + "range": null, + "title": "Proxy debug", + "type": "bool" + } + ], + "depends_on": "BLE_MESH", + "help": "Enable debug logs for the BLE Mesh functionality.", + "id": "BLE_MESH_DEBUG", + "name": "BLE_MESH_DEBUG", + "range": null, + "title": "Enable BLE Mesh debug logs", + "type": "bool" + } + ], + "depends_on": "BLE_MESH", + "id": "component-config-esp-ble-mesh-support-ble-mesh-specific-test-option", + "title": "BLE Mesh specific test option", + "type": "menu" + }, + { + "children": [], + "depends_on": "BLE_MESH", + "help": "Make BLE Mesh Experimental features visible.\nExperimental features list:\n- CONFIG_BLE_MESH_NOT_RELAY_REPLAY_MSG", + "id": "BLE_MESH_EXPERIMENTAL", + "name": "BLE_MESH_EXPERIMENTAL", + "range": null, + "title": "Make BLE Mesh experimental features visible", + "type": "bool" + } + ], + "depends_on": "BT_ENABLED", + "help": "This option enables ESP BLE Mesh support. The specific features that are\navailable may depend on other features that have been enabled in the\nstack, such as Bluetooth Support, Bluedroid Support & GATT support.", + "id": "BLE_MESH", + "is_menuconfig": true, + "name": "BLE_MESH", + "range": null, + "title": "ESP BLE Mesh Support", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": null, + "help": "Instead of listing the commands in the order of registration, the help command lists\nthe available commands in sorted order, if this option is enabled.", + "id": "CONSOLE_SORTED_HELP", + "name": "CONSOLE_SORTED_HELP", + "range": null, + "title": "Enable sorted help", + "type": "bool" + } + ], + "depends_on": null, + "id": "component-config-console-library", + "title": "Console Library", + "type": "menu" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "SOC_TWAI_SUPPORTED", + "help": "Place the TWAI ISR in to IRAM. This will allow the ISR to avoid\ncache misses, and also be able to run whilst the cache is disabled\n(such as when writing to SPI Flash).\nNote that if this option is enabled:\n- Users should also set the ESP_INTR_FLAG_IRAM in the driver\nconfiguration structure when installing the driver (see docs for\nspecifics).\n- Alert logging (i.e., setting of the TWAI_ALERT_AND_LOG flag)\nwill have no effect.", + "id": "TWAI_ISR_IN_IRAM", + "name": "TWAI_ISR_IN_IRAM", + "range": null, + "title": "Place TWAI ISR function into IRAM", + "type": "bool" + }, + { + "children": [], + "depends_on": "IDF_TARGET_ESP32 && SOC_TWAI_SUPPORTED", + "help": "When the bus-off condition is reached, the REC should be reset to 0 and frozen (via LOM) by the\ndriver's ISR. However on the ESP32, there is an edge case where the REC will increase before the\ndriver's ISR can respond in time (e.g., due to the rapid occurrence of bus errors), thus causing the\nREC to be non-zero after bus-off. A non-zero REC can prevent bus-off recovery as the bus-off recovery\ncondition is that both TEC and REC become 0. Enabling this option will add a workaround in the driver\nto forcibly reset REC to zero on reaching bus-off.", + "id": "TWAI_ERRATA_FIX_BUS_OFF_REC", + "name": "TWAI_ERRATA_FIX_BUS_OFF_REC", + "range": null, + "title": "Add SW workaround for REC change during bus-off", + "type": "bool" + }, + { + "children": [], + "depends_on": "IDF_TARGET_ESP32 && SOC_TWAI_SUPPORTED", + "help": "On the ESP32, when a transmit interrupt occurs, and interrupt register is read on the same APB clock\ncycle, the transmit interrupt could be lost. Enabling this option will add a workaround that checks the\ntransmit buffer status bit to recover any lost transmit interrupt.", + "id": "TWAI_ERRATA_FIX_TX_INTR_LOST", + "name": "TWAI_ERRATA_FIX_TX_INTR_LOST", + "range": null, + "title": "Add SW workaround for TX interrupt lost errata", + "type": "bool" + }, + { + "children": [], + "depends_on": "IDF_TARGET_ESP32 && SOC_TWAI_SUPPORTED", + "help": "On the ESP32, when receiving a data or remote frame, if a bus error occurs in the data or CRC field,\nthe data of the next received frame could be invalid. Enabling this option will add a workaround that\nwill reset the peripheral on detection of this errata condition. Note that if a frame is transmitted on\nthe bus whilst the reset is ongoing, the message will not be receive by the peripheral sent on the bus\nduring the reset, the message will be lost.", + "id": "TWAI_ERRATA_FIX_RX_FRAME_INVALID", + "name": "TWAI_ERRATA_FIX_RX_FRAME_INVALID", + "range": null, + "title": "Add SW workaround for invalid RX frame errata", + "type": "bool" + }, + { + "children": [], + "depends_on": "IDF_TARGET_ESP32 && SOC_TWAI_SUPPORTED", + "help": "On the ESP32, when the RX FIFO overruns and the RX message counter maxes out at 64 messages, the entire\nRX FIFO is no longer recoverable. Enabling this option will add a workaround that resets the peripheral\non detection of this errata condition. Note that if a frame is being sent on the bus during the reset\nbus during the reset, the message will be lost.", + "id": "TWAI_ERRATA_FIX_RX_FIFO_CORRUPT", + "name": "TWAI_ERRATA_FIX_RX_FIFO_CORRUPT", + "range": null, + "title": "Add SW workaround for RX FIFO corruption errata", + "type": "bool" + }, + { + "children": [], + "depends_on": "(IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32C3) && SOC_TWAI_SUPPORTED", + "help": "When in the listen only mode, the TWAI controller must not influence the TWAI bus (i.e., must not send\nany dominant bits). However, while in listen only mode on the ESP32/ESP32-S2/ESP32-S3/ESP32-C3, the\nTWAI controller will still transmit dominant bits when it detects an error (i.e., as part of an active\nerror frame). Enabling this option will add a workaround that forces the TWAI controller into an error\npassive state on initialization, thus preventing any dominant bits from being sent.", + "id": "TWAI_ERRATA_FIX_LISTEN_ONLY_DOM", + "name": "TWAI_ERRATA_FIX_LISTEN_ONLY_DOM", + "range": null, + "title": "Add SW workaround for listen only transmits dominant bit errata", + "type": "bool" + } + ], + "depends_on": "SOC_TWAI_SUPPORTED", + "id": "component-config-driver-configurations-twai-configuration", + "title": "TWAI Configuration", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": "SOC_DAC_SUPPORTED", + "help": "If this is set, the ADC2 driver will disable the output of the DAC corresponding to the specified\nchannel. This is the default value.\n\nFor testing, disable this option so that we can measure the output of DAC by internal ADC.", + "id": "ADC_DISABLE_DAC", + "name": "ADC_DISABLE_DAC", + "range": null, + "title": "Disable DAC when ADC2 is used on GPIO 25 and 26", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Whether to suppress the deprecation warnings when using legacy adc driver (driver/adc.h).\nIf you want to continue using the legacy driver, and don't want to see related deprecation warnings,\nyou can enable this option.", + "id": "ADC_SUPPRESS_DEPRECATE_WARN", + "name": "ADC_SUPPRESS_DEPRECATE_WARN", + "range": null, + "title": "Suppress legacy driver deprecated warning", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "This configuration option allows the user to bypass the conflict check mechanism with legacy code.", + "id": "ADC_SKIP_LEGACY_CONFLICT_CHECK", + "name": "ADC_SKIP_LEGACY_CONFLICT_CHECK", + "range": null, + "title": "Skip legacy conflict check", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "IDF_TARGET_ESP32", + "help": "Some ESP32s have Two Point calibration values burned into eFuse BLOCK3.\nThis option will allow the ADC calibration component to characterize the\nADC-Voltage curve using Two Point values if they are available.", + "id": "ADC_CAL_EFUSE_TP_ENABLE", + "name": "ADC_CAL_EFUSE_TP_ENABLE", + "range": null, + "title": "Use Two Point Values", + "type": "bool" + }, + { + "children": [], + "depends_on": "IDF_TARGET_ESP32", + "help": "Some ESP32s have Vref burned into eFuse BLOCK0. This option will allow\nthe ADC calibration component to characterize the ADC-Voltage curve using\neFuse Vref if it is available.", + "id": "ADC_CAL_EFUSE_VREF_ENABLE", + "name": "ADC_CAL_EFUSE_VREF_ENABLE", + "range": null, + "title": "Use eFuse Vref", + "type": "bool" + }, + { + "children": [], + "depends_on": "IDF_TARGET_ESP32", + "help": "This option will allow the ADC calibration component to use Lookup Tables\nto correct for non-linear behavior in 11db attenuation. Other attenuations\ndo not exhibit non-linear behavior hence will not be affected by this option.", + "id": "ADC_CAL_LUT_ENABLE", + "name": "ADC_CAL_LUT_ENABLE", + "range": null, + "title": "Use Lookup Tables", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Whether to suppress the deprecation warnings when using legacy adc calibration\ndriver (esp_adc_cal.h).\nIf you want to continue using the legacy driver, and don't want to see related\ndeprecation warnings, you can enable this option.", + "id": "ADC_CALI_SUPPRESS_DEPRECATE_WARN", + "name": "ADC_CALI_SUPPRESS_DEPRECATE_WARN", + "range": null, + "title": "Suppress legacy driver deprecated warning", + "type": "bool" + } + ], + "depends_on": null, + "id": "component-config-driver-configurations-legacy-adc-driver-configuration-legacy-adc-calibration-configuration", + "title": "Legacy ADC Calibration Configuration", + "type": "menu" + } + ], + "depends_on": null, + "id": "component-config-driver-configurations-legacy-adc-driver-configuration", + "title": "Legacy ADC Driver Configuration", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": "SOC_DAC_SUPPORTED", + "help": "Whether to suppress the deprecation warnings when using legacy dac driver (driver/dac.h).\nIf you want to continue using the legacy driver, and don't want to see related deprecation warnings,\nyou can enable this option.", + "id": "DAC_SUPPRESS_DEPRECATE_WARN", + "name": "DAC_SUPPRESS_DEPRECATE_WARN", + "range": null, + "title": "Suppress legacy driver deprecated warning", + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_DAC_SUPPORTED", + "help": "This configuration option allows the user to bypass the conflict check mechanism with legacy code.", + "id": "DAC_SKIP_LEGACY_CONFLICT_CHECK", + "name": "DAC_SKIP_LEGACY_CONFLICT_CHECK", + "range": null, + "title": "Skip legacy conflict check", + "type": "bool" + } + ], + "depends_on": "SOC_DAC_SUPPORTED", + "id": "component-config-driver-configurations-legacy-dac-driver-configurations", + "title": "Legacy DAC Driver Configurations", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": "SOC_MCPWM_SUPPORTED", + "help": "Whether to suppress the deprecation warnings when using legacy MCPWM driver (driver/mcpwm.h).\nIf you want to continue using the legacy driver, and don't want to see related deprecation warnings,\nyou can enable this option.", + "id": "MCPWM_SUPPRESS_DEPRECATE_WARN", + "name": "MCPWM_SUPPRESS_DEPRECATE_WARN", + "range": null, + "title": "Suppress legacy driver deprecated warning", + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_MCPWM_SUPPORTED", + "help": "This configuration option allows the user to bypass the conflict check mechanism with legacy code.", + "id": "MCPWM_SKIP_LEGACY_CONFLICT_CHECK", + "name": "MCPWM_SKIP_LEGACY_CONFLICT_CHECK", + "range": null, + "title": "Skip legacy conflict check", + "type": "bool" + } + ], + "depends_on": "SOC_MCPWM_SUPPORTED", + "id": "component-config-driver-configurations-legacy-mcpwm-driver-configurations", + "title": "Legacy MCPWM Driver Configurations", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": "SOC_GPTIMER_SUPPORTED", + "help": "Whether to suppress the deprecation warnings when using legacy timer group driver (driver/timer.h).\nIf you want to continue using the legacy driver, and don't want to see related deprecation warnings,\nyou can enable this option.", + "id": "GPTIMER_SUPPRESS_DEPRECATE_WARN", + "name": "GPTIMER_SUPPRESS_DEPRECATE_WARN", + "range": null, + "title": "Suppress legacy driver deprecated warning", + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_GPTIMER_SUPPORTED", + "help": "This configuration option allows the user to bypass the conflict check mechanism with legacy code.", + "id": "GPTIMER_SKIP_LEGACY_CONFLICT_CHECK", + "name": "GPTIMER_SKIP_LEGACY_CONFLICT_CHECK", + "range": null, + "title": "Skip legacy conflict check", + "type": "bool" + } + ], + "depends_on": "SOC_GPTIMER_SUPPORTED", + "id": "component-config-driver-configurations-legacy-timer-group-driver-configurations", + "title": "Legacy Timer Group Driver Configurations", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": "SOC_RMT_SUPPORTED", + "help": "Whether to suppress the deprecation warnings when using legacy rmt driver (driver/rmt.h).\nIf you want to continue using the legacy driver, and don't want to see related deprecation warnings,\nyou can enable this option.", + "id": "RMT_SUPPRESS_DEPRECATE_WARN", + "name": "RMT_SUPPRESS_DEPRECATE_WARN", + "range": null, + "title": "Suppress legacy driver deprecated warning", + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_RMT_SUPPORTED", + "help": "This configuration option allows the user to bypass the conflict check mechanism with legacy code.", + "id": "RMT_SKIP_LEGACY_CONFLICT_CHECK", + "name": "RMT_SKIP_LEGACY_CONFLICT_CHECK", + "range": null, + "title": "Skip legacy conflict check", + "type": "bool" + } + ], + "depends_on": "SOC_RMT_SUPPORTED", + "id": "component-config-driver-configurations-legacy-rmt-driver-configurations", + "title": "Legacy RMT Driver Configurations", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": "SOC_I2S_SUPPORTED", + "help": "Whether to suppress the deprecation warnings when using legacy i2s driver (driver/i2s.h).\nIf you want to continue using the legacy driver, and don't want to see related deprecation warnings,\nyou can enable this option.", + "id": "I2S_SUPPRESS_DEPRECATE_WARN", + "name": "I2S_SUPPRESS_DEPRECATE_WARN", + "range": null, + "title": "Suppress legacy driver deprecated warning", + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_I2S_SUPPORTED", + "help": "This configuration option allows the user to bypass the conflict check mechanism with legacy code.", + "id": "I2S_SKIP_LEGACY_CONFLICT_CHECK", + "name": "I2S_SKIP_LEGACY_CONFLICT_CHECK", + "range": null, + "title": "Skip legacy conflict check", + "type": "bool" + } + ], + "depends_on": "SOC_I2S_SUPPORTED", + "id": "component-config-driver-configurations-legacy-i2s-driver-configurations", + "title": "Legacy I2S Driver Configurations", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": "SOC_PCNT_SUPPORTED", + "help": "whether to suppress the deprecation warnings when using legacy PCNT driver (driver/pcnt.h).\nIf you want to continue using the legacy driver, and don't want to see related deprecation warnings,\nyou can enable this option.", + "id": "PCNT_SUPPRESS_DEPRECATE_WARN", + "name": "PCNT_SUPPRESS_DEPRECATE_WARN", + "range": null, + "title": "Suppress legacy driver deprecated warning", + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_PCNT_SUPPORTED", + "help": "This configuration option allows the user to bypass the conflict check mechanism with legacy code.", + "id": "PCNT_SKIP_LEGACY_CONFLICT_CHECK", + "name": "PCNT_SKIP_LEGACY_CONFLICT_CHECK", + "range": null, + "title": "Skip legacy conflict check", + "type": "bool" + } + ], + "depends_on": "SOC_PCNT_SUPPORTED", + "id": "component-config-driver-configurations-legacy-pcnt-driver-configurations", + "title": "Legacy PCNT Driver Configurations", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": "SOC_SDM_SUPPORTED", + "help": "whether to suppress the deprecation warnings when using legacy SDM driver (driver/sigmadelta.h).\nIf you want to continue using the legacy driver, and don't want to see related deprecation warnings,\nyou can enable this option.", + "id": "SDM_SUPPRESS_DEPRECATE_WARN", + "name": "SDM_SUPPRESS_DEPRECATE_WARN", + "range": null, + "title": "Suppress legacy driver deprecated warning", + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_SDM_SUPPORTED", + "help": "This configuration option allows the user to bypass the conflict check mechanism with legacy code.", + "id": "SDM_SKIP_LEGACY_CONFLICT_CHECK", + "name": "SDM_SKIP_LEGACY_CONFLICT_CHECK", + "range": null, + "title": "Skip legacy conflict check", + "type": "bool" + } + ], + "depends_on": "SOC_SDM_SUPPORTED", + "id": "component-config-driver-configurations-legacy-sdm-driver-configurations", + "title": "Legacy SDM Driver Configurations", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": "SOC_TEMP_SENSOR_SUPPORTED", + "help": "whether to suppress the deprecation warnings when using legacy temperature sensor driver\n(driver/temp_sensor.h). If you want to continue using the legacy driver,\nand don't want to see related deprecation warnings, you can enable this option.", + "id": "TEMP_SENSOR_SUPPRESS_DEPRECATE_WARN", + "name": "TEMP_SENSOR_SUPPRESS_DEPRECATE_WARN", + "range": null, + "title": "Suppress legacy driver deprecated warning", + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_TEMP_SENSOR_SUPPORTED", + "help": "This configuration option allows the user to bypass the conflict check mechanism with legacy code.", + "id": "TEMP_SENSOR_SKIP_LEGACY_CONFLICT_CHECK", + "name": "TEMP_SENSOR_SKIP_LEGACY_CONFLICT_CHECK", + "range": null, + "title": "Skip legacy conflict check", + "type": "bool" + } + ], + "depends_on": "SOC_TEMP_SENSOR_SUPPORTED", + "id": "component-config-driver-configurations-legacy-temperature-sensor-driver-configurations", + "title": "Legacy Temperature Sensor Driver Configurations", + "type": "menu" + } + ], + "depends_on": null, + "id": "component-config-driver-configurations", + "title": "Driver Configurations", + "type": "menu" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "EFUSE_CUSTOM_TABLE", + "help": "Name of the custom eFuse CSV filename. This path is evaluated\nrelative to the project root directory.", + "id": "EFUSE_CUSTOM_TABLE_FILENAME", + "name": "EFUSE_CUSTOM_TABLE_FILENAME", + "range": null, + "title": "Custom eFuse CSV file", + "type": "string" + } + ], + "depends_on": null, + "help": "Allows to generate a structure for eFuse from the CSV file.", + "id": "EFUSE_CUSTOM_TABLE", + "name": "EFUSE_CUSTOM_TABLE", + "range": null, + "title": "Use custom eFuse table", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "EFUSE_VIRTUAL && !IDF_TARGET_LINUX", + "help": "In addition to the \"Simulate eFuse operations in RAM\" option, this option just adds\na feature to keep eFuses after reboots in flash memory. To use this mode the partition_table\nshould have the `efuse` partition. partition.csv: \"efuse_em, data, efuse, , 0x2000,\"\n\nDuring startup, the eFuses are copied from flash or,\nin case if flash is empty, from real eFuse to RAM and then update flash.\nThis mode is useful when need to keep changes after reboot\n(testing secure_boot and flash_encryption).", + "id": "EFUSE_VIRTUAL_KEEP_IN_FLASH", + "name": "EFUSE_VIRTUAL_KEEP_IN_FLASH", + "range": null, + "title": "Keep eFuses in flash", + "type": "bool" + }, + { + "children": [], + "depends_on": "EFUSE_VIRTUAL", + "help": "If enabled, log efuse burns. This shows changes that would be made.", + "id": "EFUSE_VIRTUAL_LOG_ALL_WRITES", + "name": "EFUSE_VIRTUAL_LOG_ALL_WRITES", + "range": null, + "title": "Log all virtual writes", + "type": "bool" + } + ], + "depends_on": null, + "help": "If \"n\" - No virtual mode. All eFuse operations are real and use eFuse registers.\nIf \"y\" - The virtual mode is enabled and all eFuse operations (read and write) are redirected\nto RAM instead of eFuse registers, all permanent changes (via eFuse) are disabled.\nLog output will state changes that would be applied, but they will not be.\n\nIf it is \"y\", then SECURE_FLASH_ENCRYPTION_MODE_RELEASE cannot be used.\nBecause the EFUSE VIRT mode is for testing only.\n\nDuring startup, the eFuses are copied into RAM. This mode is useful for fast tests.", + "id": "EFUSE_VIRTUAL", + "name": "EFUSE_VIRTUAL", + "range": null, + "title": "Simulate eFuse operations in RAM", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "EFUSE_CODE_SCHEME_COMPAT_NONE", + "name": "EFUSE_CODE_SCHEME_COMPAT_NONE", + "range": null, + "title": "None Only", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "EFUSE_CODE_SCHEME_COMPAT_3_4", + "name": "EFUSE_CODE_SCHEME_COMPAT_3_4", + "range": null, + "title": "3/4 and None", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "EFUSE_CODE_SCHEME_COMPAT_REPEAT", + "name": "EFUSE_CODE_SCHEME_COMPAT_REPEAT", + "range": null, + "title": "Repeat, 3/4 and None (common table does not support it)", + "type": "bool" + } + ], + "depends_on": "IDF_TARGET_ESP32", + "help": "Selector eFuse code scheme.", + "id": "component-config-efuse-bit-manager-coding-scheme-compatibility", + "name": "EFUSE_CODE_SCHEME_SELECTOR", + "title": "Coding Scheme Compatibility", + "type": "choice" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "EFUSE_MAX_BLK_LEN", + "name": "EFUSE_MAX_BLK_LEN", + "range": null, + "title": null, + "type": "int" + } + ], + "depends_on": null, + "id": "component-config-efuse-bit-manager", + "title": "eFuse Bit Manager", + "type": "menu" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "ESP_TLS_USING_MBEDTLS", + "name": "ESP_TLS_USING_MBEDTLS", + "range": null, + "title": "mbedTLS", + "type": "bool" + }, + { + "children": [], + "depends_on": "TLS_STACK_WOLFSSL && ", + "help": null, + "id": "ESP_TLS_USING_WOLFSSL", + "name": "ESP_TLS_USING_WOLFSSL", + "range": null, + "title": "wolfSSL (License info in wolfSSL directory README)", + "type": "bool" + } + ], + "depends_on": null, + "help": "The ESP-TLS APIs support multiple backend TLS libraries. Currently mbedTLS and WolfSSL are\nsupported. Different TLS libraries may support different features and have different resource\nusage. Consult the ESP-TLS documentation in ESP-IDF Programming guide for more details.", + "id": "component-config-esp-tls-choose-ssl-tls-library-for-esp-tls-see-help-for-more-info-", + "name": "ESP_TLS_LIBRARY_CHOOSE", + "title": "Choose SSL/TLS library for ESP-TLS (See help for more Info)", + "type": "choice" + }, + { + "children": [], + "depends_on": "IDF_TARGET_ESP32 && ESP_TLS_USING_MBEDTLS", + "help": "Enable use of Secure Element for ESP-TLS, this enables internal support for\nATECC608A peripheral, which can be used for TLS connection.", + "id": "ESP_TLS_USE_SECURE_ELEMENT", + "name": "ESP_TLS_USE_SECURE_ELEMENT", + "range": null, + "title": "Use Secure Element (ATECC608A) with ESP-TLS", + "type": "bool" + }, + { + "children": [], + "depends_on": "ESP_TLS_USING_MBEDTLS && SOC_DIG_SIGN_SUPPORTED", + "help": "Enable use of the Digital Signature Peripheral for ESP-TLS.The DS peripheral\ncan only be used when it is appropriately configured for TLS.\nConsult the ESP-TLS documentation in ESP-IDF Programming Guide for more details.", + "id": "ESP_TLS_USE_DS_PERIPHERAL", + "name": "ESP_TLS_USE_DS_PERIPHERAL", + "range": null, + "title": "Use Digital Signature (DS) Peripheral with ESP-TLS", + "type": "bool" + }, + { + "children": [], + "depends_on": "ESP_TLS_USING_MBEDTLS && MBEDTLS_CLIENT_SSL_SESSION_TICKETS", + "help": "Enable session ticket support as specified in RFC5077.", + "id": "ESP_TLS_CLIENT_SESSION_TICKETS", + "name": "ESP_TLS_CLIENT_SESSION_TICKETS", + "range": null, + "title": "Enable client session tickets", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "ESP_TLS_SERVER_SESSION_TICKETS", + "help": "Sets the session ticket timeout used in the tls server.", + "id": "ESP_TLS_SERVER_SESSION_TICKET_TIMEOUT", + "name": "ESP_TLS_SERVER_SESSION_TICKET_TIMEOUT", + "range": null, + "title": "Server session ticket timeout in seconds", + "type": "int" + } + ], + "depends_on": "ESP_TLS_USING_MBEDTLS && MBEDTLS_SERVER_SSL_SESSION_TICKETS", + "help": "Enable session ticket support as specified in RFC5077", + "id": "ESP_TLS_SERVER_SESSION_TICKETS", + "name": "ESP_TLS_SERVER_SESSION_TICKETS", + "range": null, + "title": "Enable server session tickets", + "type": "bool" + }, + { + "children": [], + "depends_on": "ESP_TLS_USING_MBEDTLS", + "help": "Ability to configure and use a certificate selection callback during server handshake,\nto select a certificate to present to the client based on the TLS extensions supplied in\nthe client hello (alpn, sni, etc).", + "id": "ESP_TLS_SERVER_CERT_SELECT_HOOK", + "name": "ESP_TLS_SERVER_CERT_SELECT_HOOK", + "range": null, + "title": "Certificate selection hook", + "type": "bool" + }, + { + "children": [], + "depends_on": "ESP_TLS_USING_MBEDTLS", + "help": "When this option is enabled, the peer (here, the client) certificate is checked by the server,\nhowever the handshake continues even if verification failed. By default, the\npeer certificate is not checked and ignored by the server.\n\nmbedtls_ssl_get_verify_result() can be called after the handshake is complete to\nretrieve status of verification.", + "id": "ESP_TLS_SERVER_MIN_AUTH_MODE_OPTIONAL", + "name": "ESP_TLS_SERVER_MIN_AUTH_MODE_OPTIONAL", + "range": null, + "title": "ESP-TLS Server: Set minimum Certificate Verification mode to Optional", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Enable support for pre shared key ciphers, supported for both mbedTLS as well as\nwolfSSL TLS library.", + "id": "ESP_TLS_PSK_VERIFICATION", + "name": "ESP_TLS_PSK_VERIFICATION", + "range": null, + "title": "Enable PSK verification", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "ESP_TLS_INSECURE", + "help": "After enabling this option the esp-tls client will skip the server certificate verification\nby default. Note that this option will only modify the default behaviour of esp-tls client\nregarding server cert verification. The default behaviour should only be applicable when\nno other option regarding the server cert verification is opted in the esp-tls config\n(e.g. crt_bundle_attach, use_global_ca_store etc.).\nWARNING : Enabling this option comes with a potential risk of establishing a TLS connection\nwith a server which has a fake identity, provided that the server certificate\nis not provided either through API or other mechanism like ca_store etc.", + "id": "ESP_TLS_SKIP_SERVER_CERT_VERIFY", + "name": "ESP_TLS_SKIP_SERVER_CERT_VERIFY", + "range": null, + "title": "Skip server certificate verification by default (WARNING: ONLY FOR TESTING PURPOSE, READ HELP)", + "type": "bool" + } + ], + "depends_on": null, + "help": "You can enable some potentially insecure options. These options should only be used for testing pusposes.\nOnly enable these options if you are very sure.", + "id": "ESP_TLS_INSECURE", + "name": "ESP_TLS_INSECURE", + "range": null, + "title": "Allow potentially insecure options", + "type": "bool" + }, + { + "children": [], + "depends_on": "ESP_TLS_USING_WOLFSSL", + "help": "Enable detailed debug prints for wolfSSL SSL library.", + "id": "ESP_DEBUG_WOLFSSL", + "name": "ESP_DEBUG_WOLFSSL", + "range": null, + "title": "Enable debug logs for wolfSSL", + "type": "bool" + }, + { + "children": [], + "depends_on": "ESP_TLS_USING_WOLFSSL", + "help": "Enable a fuller set of OCSP checks: checking revocation status of intermediate certificates,\noptional fallbacks to CRLs, etc.", + "id": "ESP_TLS_OCSP_CHECKALL", + "name": "ESP_TLS_OCSP_CHECKALL", + "range": null, + "title": "Enabled full OCSP checks for ESP-TLS", + "type": "bool" + } + ], + "depends_on": null, + "id": "component-config-esp-tls", + "title": "ESP-TLS", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": null, + "help": "Place ISR version ADC oneshot mode read function into IRAM.", + "id": "ADC_ONESHOT_CTRL_FUNC_IN_IRAM", + "name": "ADC_ONESHOT_CTRL_FUNC_IN_IRAM", + "range": null, + "title": "Place ISR version ADC oneshot mode read function into IRAM", + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_ADC_DMA_SUPPORTED", + "help": "Ensure the ADC continuous mode ISR is IRAM-Safe. When enabled, the ISR handler\nwill be available when the cache is disabled.", + "id": "ADC_CONTINUOUS_ISR_IRAM_SAFE", + "name": "ADC_CONTINUOUS_ISR_IRAM_SAFE", + "range": null, + "title": "ADC continuous mode driver ISR IRAM-Safe", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "IDF_TARGET_ESP32", + "help": "Some ESP32s have Two Point calibration values burned into eFuse BLOCK3.\nThis option will allow the ADC calibration component to characterize the\nADC-Voltage curve using Two Point values if they are available.", + "id": "ADC_CALI_EFUSE_TP_ENABLE", + "name": "ADC_CALI_EFUSE_TP_ENABLE", + "range": null, + "title": "Use Two Point Values", + "type": "bool" + }, + { + "children": [], + "depends_on": "IDF_TARGET_ESP32", + "help": "Some ESP32s have Vref burned into eFuse BLOCK0. This option will allow\nthe ADC calibration component to characterize the ADC-Voltage curve using\neFuse Vref if it is available.", + "id": "ADC_CALI_EFUSE_VREF_ENABLE", + "name": "ADC_CALI_EFUSE_VREF_ENABLE", + "range": null, + "title": "Use eFuse Vref", + "type": "bool" + }, + { + "children": [], + "depends_on": "IDF_TARGET_ESP32", + "help": "This option will allow the ADC calibration component to use Lookup Tables\nto correct for non-linear behavior in 11db attenuation. Other attenuations\ndo not exhibit non-linear behavior hence will not be affected by this option.", + "id": "ADC_CALI_LUT_ENABLE", + "name": "ADC_CALI_LUT_ENABLE", + "range": null, + "title": "Use Lookup Tables", + "type": "bool" + } + ], + "depends_on": "IDF_TARGET_ESP32", + "id": "component-config-adc-and-adc-calibration-adc-calibration-configurations", + "title": "ADC Calibration Configurations", + "type": "menu" + }, + { + "children": [], + "depends_on": "SOC_DAC_SUPPORTED", + "help": "By default, this is set. The ADC oneshot driver will disable the output of the\ncorresponding DAC channels:\nESP32: IO25 and IO26\nESP32S2: IO17 and IO18\n\nDisable this option so as to measure the output of DAC by internal ADC, for test usage.", + "id": "ADC_DISABLE_DAC_OUTPUT", + "name": "ADC_DISABLE_DAC_OUTPUT", + "range": null, + "title": "Disable DAC when ADC2 is in use", + "type": "bool" + }, + { + "children": [], + "depends_on": "IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S3", + "help": "On ESP32C3 and ESP32S3, ADC2 Digital Controller is not stable. Therefore,\nADC2 continuous mode is not suggested on ESP32S3 and ESP32C3\n\nIf you stick to this, you can enable this option to force use ADC2 under above conditions.\nFor more details, you can search for errata on espressif website.", + "id": "ADC_CONTINUOUS_FORCE_USE_ADC2_ON_C3_S3", + "name": "ADC_CONTINUOUS_FORCE_USE_ADC2_ON_C3_S3", + "range": null, + "title": "Force use ADC2 continumous mode on ESP32S3 or ESP32C3", + "type": "bool" + }, + { + "children": [], + "depends_on": "IDF_TARGET_ESP32C3", + "help": "On ESP32C3, ADC2 Digital Controller is not stable. Therefore,\nADC2 oneshot mode is not suggested on ESP32C3\n\nIf you stick to this, you can enable this option to force use ADC2 under above conditions.\nFor more details, you can search for errata on espressif website.", + "id": "ADC_ONESHOT_FORCE_USE_ADC2_ON_C3", + "name": "ADC_ONESHOT_FORCE_USE_ADC2_ON_C3", + "range": null, + "title": "Force use ADC2 oneshot mode on ESP32C3", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "whether to enable the debug log message for ADC driver.\nNote that this option only controls the ADC driver log, will not affect other drivers.\n\nnote: This cannot be used in the ADC legacy driver.", + "id": "ADC_ENABLE_DEBUG_LOG", + "name": "ADC_ENABLE_DEBUG_LOG", + "range": null, + "title": "Enable ADC debug log", + "type": "bool" + } + ], + "depends_on": null, + "id": "component-config-adc-and-adc-calibration", + "title": "ADC and ADC Calibration", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": null, + "help": null, + "id": "ESP_COEX_ENABLED", + "name": "ESP_COEX_ENABLED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": "((ESP_WIFI_ENABLED && BT_ENABLED) || (ESP_WIFI_ENABLED && IEEE802154_ENABLED) || (IEEE802154_ENABLED && BT_ENABLED)) && ESP_COEX_ENABLED", + "help": "If enabled, WiFi & Bluetooth coexistence is controlled by software rather than hardware.\nRecommended for heavy traffic scenarios. Both coexistence configuration options are\nautomatically managed, no user intervention is required.\nIf only Bluetooth is used, it is recommended to disable this option to reduce binary file\nsize.", + "id": "ESP_COEX_SW_COEXIST_ENABLE", + "name": "ESP_COEX_SW_COEXIST_ENABLE", + "range": null, + "title": "Software controls WiFi/Bluetooth coexistence", + "type": "bool" + }, + { + "children": [], + "depends_on": "!(BT_ENABLED || NIMBLE_ENABLED) && !IDF_TARGET_ESP32 && ESP_COEX_ENABLED", + "help": "If enabled, HW External coexistence arbitration is managed by GPIO pins.\nIt can support three types of wired combinations so far which are 1-wired/2-wired/3-wired.\nUser can select GPIO pins in application code with configure interfaces.\n\nThis function depends on BT-off\nbecause currently we do not support external coex and internal coex simultaneously.", + "id": "ESP_COEX_EXTERNAL_COEXIST_ENABLE", + "name": "ESP_COEX_EXTERNAL_COEXIST_ENABLE", + "range": null, + "title": "External Coexistence", + "type": "bool" + }, + { + "children": [], + "depends_on": "ESP_COEX_SW_COEXIST_ENABLE && ESP_COEX_ENABLED", + "help": "If enabled, coexist power management will be enabled.", + "id": "ESP_COEX_POWER_MANAGEMENT", + "name": "ESP_COEX_POWER_MANAGEMENT", + "range": null, + "title": "Support power management under coexistence", + "type": "bool" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "ESP_COEX_GPIO_DEBUG_DIAG_GENERAL", + "name": "ESP_COEX_GPIO_DEBUG_DIAG_GENERAL", + "range": null, + "title": "General", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "ESP_COEX_GPIO_DEBUG_DIAG_WIFI", + "name": "ESP_COEX_GPIO_DEBUG_DIAG_WIFI", + "range": null, + "title": "Wi-Fi", + "type": "bool" + } + ], + "depends_on": "ESP_COEX_GPIO_DEBUG", + "help": "Select type of debugging diagram", + "id": "component-config-wireless-coexistence-gpio-debugging-for-coexistence-debugging-diagram", + "name": "ESP_COEX_GPIO_DEBUG_DIAG", + "title": "Debugging Diagram", + "type": "choice" + }, + { + "children": [], + "depends_on": "ESP_COEX_GPIO_DEBUG", + "help": null, + "id": "ESP_COEX_GPIO_DEBUG_IO_COUNT", + "name": "ESP_COEX_GPIO_DEBUG_IO_COUNT", + "range": null, + "title": "Max number of debugging GPIOs", + "type": "int" + }, + { + "children": [], + "depends_on": "ESP_COEX_GPIO_DEBUG_IO_COUNT > 0 && ESP_COEX_GPIO_DEBUG", + "help": null, + "id": "ESP_COEX_GPIO_DEBUG_IO_IDX0", + "name": "ESP_COEX_GPIO_DEBUG_IO_IDX0", + "range": null, + "title": "Actual IO num for Debug IO ID0", + "type": "int" + }, + { + "children": [], + "depends_on": "ESP_COEX_GPIO_DEBUG_IO_COUNT > 1 && ESP_COEX_GPIO_DEBUG", + "help": null, + "id": "ESP_COEX_GPIO_DEBUG_IO_IDX1", + "name": "ESP_COEX_GPIO_DEBUG_IO_IDX1", + "range": null, + "title": "Actual IO num for Debug IO ID1", + "type": "int" + }, + { + "children": [], + "depends_on": "ESP_COEX_GPIO_DEBUG_IO_COUNT > 2 && ESP_COEX_GPIO_DEBUG", + "help": null, + "id": "ESP_COEX_GPIO_DEBUG_IO_IDX2", + "name": "ESP_COEX_GPIO_DEBUG_IO_IDX2", + "range": null, + "title": "Actual IO num for Debug IO ID2", + "type": "int" + }, + { + "children": [], + "depends_on": "ESP_COEX_GPIO_DEBUG_IO_COUNT > 3 && ESP_COEX_GPIO_DEBUG", + "help": null, + "id": "ESP_COEX_GPIO_DEBUG_IO_IDX3", + "name": "ESP_COEX_GPIO_DEBUG_IO_IDX3", + "range": null, + "title": "Actual IO num for Debug IO ID3", + "type": "int" + }, + { + "children": [], + "depends_on": "ESP_COEX_GPIO_DEBUG_IO_COUNT > 4 && ESP_COEX_GPIO_DEBUG", + "help": null, + "id": "ESP_COEX_GPIO_DEBUG_IO_IDX4", + "name": "ESP_COEX_GPIO_DEBUG_IO_IDX4", + "range": null, + "title": "Actual IO num for Debug IO ID4", + "type": "int" + }, + { + "children": [], + "depends_on": "ESP_COEX_GPIO_DEBUG_IO_COUNT > 5 && ESP_COEX_GPIO_DEBUG", + "help": null, + "id": "ESP_COEX_GPIO_DEBUG_IO_IDX5", + "name": "ESP_COEX_GPIO_DEBUG_IO_IDX5", + "range": null, + "title": "Actual IO num for Debug IO ID5", + "type": "int" + }, + { + "children": [], + "depends_on": "ESP_COEX_GPIO_DEBUG_IO_COUNT > 6 && ESP_COEX_GPIO_DEBUG", + "help": null, + "id": "ESP_COEX_GPIO_DEBUG_IO_IDX6", + "name": "ESP_COEX_GPIO_DEBUG_IO_IDX6", + "range": null, + "title": "Actual IO num for Debug IO ID6", + "type": "int" + }, + { + "children": [], + "depends_on": "ESP_COEX_GPIO_DEBUG_IO_COUNT > 7 && ESP_COEX_GPIO_DEBUG", + "help": null, + "id": "ESP_COEX_GPIO_DEBUG_IO_IDX7", + "name": "ESP_COEX_GPIO_DEBUG_IO_IDX7", + "range": null, + "title": "Actual IO num for Debug IO ID7", + "type": "int" + }, + { + "children": [], + "depends_on": "ESP_COEX_GPIO_DEBUG_IO_COUNT > 8 && ESP_COEX_GPIO_DEBUG", + "help": null, + "id": "ESP_COEX_GPIO_DEBUG_IO_IDX8", + "name": "ESP_COEX_GPIO_DEBUG_IO_IDX8", + "range": null, + "title": "Actual IO num for Debug IO ID8", + "type": "int" + }, + { + "children": [], + "depends_on": "ESP_COEX_GPIO_DEBUG_IO_COUNT > 9 && ESP_COEX_GPIO_DEBUG", + "help": null, + "id": "ESP_COEX_GPIO_DEBUG_IO_IDX9", + "name": "ESP_COEX_GPIO_DEBUG_IO_IDX9", + "range": null, + "title": "Actual IO num for Debug IO ID9", + "type": "int" + }, + { + "children": [], + "depends_on": "ESP_COEX_GPIO_DEBUG_IO_COUNT > 10 && ESP_COEX_GPIO_DEBUG", + "help": null, + "id": "ESP_COEX_GPIO_DEBUG_IO_IDX10", + "name": "ESP_COEX_GPIO_DEBUG_IO_IDX10", + "range": null, + "title": "Actual IO num for Debug IO ID10", + "type": "int" + }, + { + "children": [], + "depends_on": "ESP_COEX_GPIO_DEBUG_IO_COUNT > 11 && ESP_COEX_GPIO_DEBUG", + "help": null, + "id": "ESP_COEX_GPIO_DEBUG_IO_IDX11", + "name": "ESP_COEX_GPIO_DEBUG_IO_IDX11", + "range": null, + "title": "Actual IO num for Debug IO ID11", + "type": "int" + } + ], + "depends_on": "!PM_SLP_DISABLE_GPIO && !PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP", + "help": "Support coexistence GPIO debugging", + "id": "ESP_COEX_GPIO_DEBUG", + "name": "ESP_COEX_GPIO_DEBUG", + "range": null, + "title": "GPIO debugging for coexistence", + "type": "bool" + } + ], + "depends_on": null, + "id": "component-config-wireless-coexistence", + "title": "Wireless Coexistence", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": null, + "help": "Functions esp_err_to_name() and esp_err_to_name_r() return string representations of error codes from a\npre-generated lookup table. This option can be used to turn off the use of the look-up table in order to\nsave memory but this comes at the price of sacrificing distinguishable (meaningful) output string\nrepresentations.", + "id": "ESP_ERR_TO_NAME_LOOKUP", + "name": "ESP_ERR_TO_NAME_LOOKUP", + "range": null, + "title": "Enable lookup of error code strings", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "ESP_ALLOW_BSS_SEG_EXTERNAL_MEMORY", + "name": "ESP_ALLOW_BSS_SEG_EXTERNAL_MEMORY", + "range": null, + "title": null, + "type": "bool" + } + ], + "depends_on": null, + "id": "component-config-common-esp-related", + "title": "Common ESP-related", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": "SOC_ANA_CMPR_SUPPORTED", + "help": "Ensure the Analog Comparator interrupt is IRAM-Safe by allowing the interrupt handler to be\nexecutable when the cache is disabled (e.g. SPI Flash write).", + "id": "ANA_CMPR_ISR_IRAM_SAFE", + "name": "ANA_CMPR_ISR_IRAM_SAFE", + "range": null, + "title": "Analog comparator ISR IRAM-Safe", + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_ANA_CMPR_SUPPORTED", + "help": "Place Analog Comparator control functions (like ana_cmpr_set_internal_reference) into IRAM,\nso that these functions can be IRAM-safe and able to be called in an IRAM interrupt context.\nEnabling this option can improve driver performance as well.", + "id": "ANA_CMPR_CTRL_FUNC_IN_IRAM", + "name": "ANA_CMPR_CTRL_FUNC_IN_IRAM", + "range": null, + "title": "Place Analog Comparator control functions into IRAM", + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_ANA_CMPR_SUPPORTED", + "help": "whether to enable the debug log message for Analog Comparator driver.\nNote that, this option only controls the Analog Comparator driver log, won't affect other drivers.", + "id": "ANA_CMPR_ENABLE_DEBUG_LOG", + "name": "ANA_CMPR_ENABLE_DEBUG_LOG", + "range": null, + "title": "Enable debug log", + "type": "bool" + } + ], + "depends_on": "SOC_ANA_CMPR_SUPPORTED", + "id": "component-config-esp-driver-analog-comparator-configurations", + "title": "ESP-Driver:Analog Comparator Configurations", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": "SOC_MIPI_CSI_SUPPORTED && (SOC_MIPI_CSI_SUPPORTED || SOC_LCDCAM_CAM_SUPPORTED)", + "help": "Ensure the CSI driver ISR is IRAM-Safe. When enabled, the ISR handler\nwill be available when the cache is disabled.", + "id": "CAM_CTLR_MIPI_CSI_ISR_IRAM_SAFE", + "name": "CAM_CTLR_MIPI_CSI_ISR_IRAM_SAFE", + "range": null, + "title": "CSI ISR IRAM-Safe", + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_MIPI_CSI_SUPPORTED || SOC_LCDCAM_CAM_SUPPORTED", + "help": "Ensure the ISP_DVP driver ISR is IRAM-Safe. When enabled, the ISR handler\nwill be available when the cache is disabled.", + "id": "CAM_CTLR_ISP_DVP_ISR_IRAM_SAFE", + "name": "CAM_CTLR_ISP_DVP_ISR_IRAM_SAFE", + "range": null, + "title": "ISP_DVP ISR IRAM-Safe", + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_LCDCAM_CAM_SUPPORTED && (SOC_MIPI_CSI_SUPPORTED || SOC_LCDCAM_CAM_SUPPORTED)", + "help": "Ensure the DVP driver ISR is IRAM-Safe. When enabled, the ISR handler\nwill be available when the cache is disabled.", + "id": "CAM_CTLR_DVP_CAM_ISR_IRAM_SAFE", + "name": "CAM_CTLR_DVP_CAM_ISR_IRAM_SAFE", + "range": null, + "title": "DVP ISR IRAM-Safe", + "type": "bool" + } + ], + "depends_on": "SOC_MIPI_CSI_SUPPORTED || SOC_LCDCAM_CAM_SUPPORTED", + "id": "component-config-esp-driver-camera-controller-configurations", + "title": "ESP-Driver:Camera Controller Configurations", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": "SOC_DAC_SUPPORTED", + "help": "Place DAC control functions (e.g. 'dac_oneshot_output_voltage') into IRAM,\nso that this function can be IRAM-safe and able to be called in the other IRAM interrupt context.\nEnabling this option can improve driver performance as well.", + "id": "DAC_CTRL_FUNC_IN_IRAM", + "name": "DAC_CTRL_FUNC_IN_IRAM", + "range": null, + "title": "Place DAC control functions into IRAM", + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_DAC_SUPPORTED", + "help": "Ensure the DAC interrupt is IRAM-Safe by allowing the interrupt handler to be\nexecutable when the cache is disabled (e.g. SPI Flash write).", + "id": "DAC_ISR_IRAM_SAFE", + "name": "DAC_ISR_IRAM_SAFE", + "range": null, + "title": "DAC ISR IRAM-Safe", + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_DAC_SUPPORTED", + "help": "whether to enable the debug log message for DAC driver.\nNote that, this option only controls the DAC driver log, won't affect other drivers.", + "id": "DAC_ENABLE_DEBUG_LOG", + "name": "DAC_ENABLE_DEBUG_LOG", + "range": null, + "title": "Enable debug log", + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_DAC_DMA_16BIT_ALIGN && SOC_DAC_SUPPORTED", + "help": "Whether to left shift the continuous data to align every bytes to 16 bits in the driver.\nOn ESP32, although the DAC resolution is only 8 bits,\nthe hardware requires 16 bits data in continuous mode.\nBy enabling this option, the driver will left shift 8 bits for the input data automatically.\nOnly disable this option when you decide to do this step by yourself.\nNote that the driver will allocate a new piece of memory to save the converted data.", + "id": "DAC_DMA_AUTO_16BIT_ALIGN", + "name": "DAC_DMA_AUTO_16BIT_ALIGN", + "range": null, + "title": "Align the continuous data to 16 bit automatically", + "type": "bool" + } + ], + "depends_on": "SOC_DAC_SUPPORTED", + "id": "component-config-esp-driver-dac-configurations", + "title": "ESP-Driver:DAC Configurations", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": "IDF_TARGET_ESP32", + "help": "This option is intended to fix the bug that ESP32 is not able to switch to configured\npullup/pulldown mode in sleep.\nIf this option is selected, chip will automatically emulate the behaviour of switching,\nand about 450B of source codes would be placed into IRAM.", + "id": "GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL", + "name": "GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL", + "range": null, + "title": "Support light sleep GPIO pullup/pulldown configuration for ESP32", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Place GPIO control functions (like intr_disable/set_level) into IRAM,\nso that these functions can be IRAM-safe and able to be called in the other IRAM interrupt context.", + "id": "GPIO_CTRL_FUNC_IN_IRAM", + "name": "GPIO_CTRL_FUNC_IN_IRAM", + "range": null, + "title": "Place GPIO control functions into IRAM", + "type": "bool" + } + ], + "depends_on": null, + "id": "component-config-esp-driver-gpio-configurations", + "title": "ESP-Driver:GPIO Configurations", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": "SOC_GPTIMER_SUPPORTED", + "help": "Place GPTimer ISR handler into IRAM for better performance and fewer cache misses.", + "id": "GPTIMER_ISR_HANDLER_IN_IRAM", + "name": "GPTIMER_ISR_HANDLER_IN_IRAM", + "range": null, + "title": "Place GPTimer ISR handler into IRAM", + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_GPTIMER_SUPPORTED", + "help": "Place GPTimer control functions (like start/stop) into IRAM,\nso that these functions can be IRAM-safe and able to be called in the other IRAM interrupt context.\nEnabling this option can improve driver performance as well.", + "id": "GPTIMER_CTRL_FUNC_IN_IRAM", + "name": "GPTIMER_CTRL_FUNC_IN_IRAM", + "range": null, + "title": "Place GPTimer control functions into IRAM", + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_GPTIMER_SUPPORTED", + "help": "Ensure the GPTimer interrupt is IRAM-Safe by allowing the interrupt handler to be\nexecutable when the cache is disabled (e.g. SPI Flash write).", + "id": "GPTIMER_ISR_IRAM_SAFE", + "name": "GPTIMER_ISR_IRAM_SAFE", + "range": null, + "title": "GPTimer ISR IRAM-Safe", + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_GPTIMER_SUPPORTED", + "help": "whether to enable the debug log message for GPTimer driver.\nNote that, this option only controls the GPTimer driver log, won't affect other drivers.", + "id": "GPTIMER_ENABLE_DEBUG_LOG", + "name": "GPTIMER_ENABLE_DEBUG_LOG", + "range": null, + "title": "Enable debug log", + "type": "bool" + } + ], + "depends_on": "SOC_GPTIMER_SUPPORTED", + "id": "component-config-esp-driver-gptimer-configurations", + "title": "ESP-Driver:GPTimer Configurations", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": "SOC_I2C_SUPPORTED", + "help": "Ensure the I2C interrupt is IRAM-Safe by allowing the interrupt handler to be\nexecutable when the cache is disabled (e.g. SPI Flash write).\nnote: This cannot be used in the I2C legacy driver.", + "id": "I2C_ISR_IRAM_SAFE", + "name": "I2C_ISR_IRAM_SAFE", + "range": null, + "title": "I2C ISR IRAM-Safe", + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_I2C_SUPPORTED", + "help": "whether to enable the debug log message for I2C driver.\nNote that this option only controls the I2C driver log, will not affect other drivers.\n\nnote: This cannot be used in the I2C legacy driver.", + "id": "I2C_ENABLE_DEBUG_LOG", + "name": "I2C_ENABLE_DEBUG_LOG", + "range": null, + "title": "Enable I2C debug log", + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_I2C_SUPPORTED", + "help": "I2C slave version 2 solves some existing known issues. Such as write/read workflow, stretch handling, etc.", + "id": "I2C_ENABLE_SLAVE_DRIVER_VERSION_2", + "name": "I2C_ENABLE_SLAVE_DRIVER_VERSION_2", + "range": null, + "title": "Enable I2C slave driver version 2", + "type": "bool" + } + ], + "depends_on": "SOC_I2C_SUPPORTED", + "id": "component-config-esp-driver-i2c-configurations", + "title": "ESP-Driver:I2C Configurations", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": "SOC_I2S_SUPPORTED", + "help": "Ensure the I2S interrupt is IRAM-Safe by allowing the interrupt handler to be\nexecutable when the cache is disabled (e.g. SPI Flash write).", + "id": "I2S_ISR_IRAM_SAFE", + "name": "I2S_ISR_IRAM_SAFE", + "range": null, + "title": "I2S ISR IRAM-Safe", + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_I2S_SUPPORTED", + "help": "whether to enable the debug log message for I2S driver.\nNote that, this option only controls the I2S driver log, will not affect other drivers.", + "id": "I2S_ENABLE_DEBUG_LOG", + "name": "I2S_ENABLE_DEBUG_LOG", + "range": null, + "title": "Enable I2S debug log", + "type": "bool" + } + ], + "depends_on": "SOC_I2S_SUPPORTED", + "id": "component-config-esp-driver-i2s-configurations", + "title": "ESP-Driver:I2S Configurations", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": "SOC_ISP_SUPPORTED", + "help": "Ensure the ISP driver ISR is IRAM-Safe. When enabled, the ISR handler\nwill be available when the cache is disabled.", + "id": "ISP_ISR_IRAM_SAFE", + "name": "ISP_ISR_IRAM_SAFE", + "range": null, + "title": "ISP driver ISR IRAM-Safe", + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_ISP_SUPPORTED", + "help": "Place ISP control functions into IRAM,\nso that these functions can be IRAM-safe and able to be called in the other IRAM interrupt context.\nEnabling this option can improve driver performance as well.\n\nFunction list:\n- `esp_isp_sharpen_configure`", + "id": "ISP_CTRL_FUNC_IN_IRAM", + "name": "ISP_CTRL_FUNC_IN_IRAM", + "range": null, + "title": "Place ISP control functions into IRAM", + "type": "bool" + } + ], + "depends_on": "SOC_ISP_SUPPORTED", + "id": "component-config-esp-driver-isp-configurations", + "title": "ESP-Driver:ISP Configurations", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": "SOC_JPEG_CODEC_SUPPORTED", + "help": "whether to enable the debug log message for JPEG driver.\nNote that, this option only controls the JPEG driver log, won't affect other drivers.\nPlease also note, enable this option will make jpeg codec process speed much slower.", + "id": "JPEG_ENABLE_DEBUG_LOG", + "name": "JPEG_ENABLE_DEBUG_LOG", + "range": null, + "title": "Enable debug log", + "type": "bool" + } + ], + "depends_on": "SOC_JPEG_CODEC_SUPPORTED", + "id": "component-config-esp-driver-jpeg-codec-configurations", + "title": "ESP-Driver:JPEG-Codec Configurations", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": null, + "help": "Place LEDC control functions (ledc_update_duty and ledc_stop) into IRAM,\nso that these functions can be IRAM-safe and able to be called in an IRAM context.\nEnabling this option can improve driver performance as well.", + "id": "LEDC_CTRL_FUNC_IN_IRAM", + "name": "LEDC_CTRL_FUNC_IN_IRAM", + "range": null, + "title": "Place LEDC control functions into IRAM", + "type": "bool" + } + ], + "depends_on": null, + "id": "component-config-esp-driver-ledc-configurations", + "title": "ESP-Driver:LEDC Configurations", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": "SOC_MCPWM_SUPPORTED", + "help": "This will ensure the MCPWM interrupt handle is IRAM-Safe, allow to avoid flash\ncache misses, and also be able to run whilst the cache is disabled.\n(e.g. SPI Flash write)", + "id": "MCPWM_ISR_IRAM_SAFE", + "name": "MCPWM_ISR_IRAM_SAFE", + "range": null, + "title": "Place MCPWM ISR function into IRAM", + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_MCPWM_SUPPORTED", + "help": "Place MCPWM control functions (like set_compare_value) into IRAM,\nso that these functions can be IRAM-safe and able to be called in the other IRAM interrupt context.\nEnabling this option can improve driver performance as well.", + "id": "MCPWM_CTRL_FUNC_IN_IRAM", + "name": "MCPWM_CTRL_FUNC_IN_IRAM", + "range": null, + "title": "Place MCPWM control functions into IRAM", + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_MCPWM_SUPPORTED", + "help": "whether to enable the debug log message for MCPWM driver.\nNote that, this option only controls the MCPWM driver log, won't affect other drivers.", + "id": "MCPWM_ENABLE_DEBUG_LOG", + "name": "MCPWM_ENABLE_DEBUG_LOG", + "range": null, + "title": "Enable debug log", + "type": "bool" + } + ], + "depends_on": "SOC_MCPWM_SUPPORTED", + "id": "component-config-esp-driver-mcpwm-configurations", + "title": "ESP-Driver:MCPWM Configurations", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": "SOC_PARLIO_SUPPORTED", + "help": "whether to enable the debug log message for parallel IO driver.\nNote that, this option only controls the parallel IO driver log, won't affect other drivers.", + "id": "PARLIO_ENABLE_DEBUG_LOG", + "name": "PARLIO_ENABLE_DEBUG_LOG", + "range": null, + "title": "Enable debug log", + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_PARLIO_SUPPORTED", + "help": "Ensure the Parallel IO interrupt is IRAM-Safe by allowing the interrupt handler to be\nexecutable when the cache is disabled (e.g. SPI Flash write).", + "id": "PARLIO_ISR_IRAM_SAFE", + "name": "PARLIO_ISR_IRAM_SAFE", + "range": null, + "title": "Parallel IO ISR IRAM-Safe", + "type": "bool" + } + ], + "depends_on": "SOC_PARLIO_SUPPORTED", + "id": "component-config-esp-driver-parallel-io-configurations", + "title": "ESP-Driver:Parallel IO Configurations", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": "SOC_PCNT_SUPPORTED", + "help": "Place PCNT control functions (like start/stop) into IRAM,\nso that these functions can be IRAM-safe and able to be called in the other IRAM interrupt context.\nEnabling this option can improve driver performance as well.", + "id": "PCNT_CTRL_FUNC_IN_IRAM", + "name": "PCNT_CTRL_FUNC_IN_IRAM", + "range": null, + "title": "Place PCNT control functions into IRAM", + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_PCNT_SUPPORTED", + "help": "Ensure the PCNT interrupt is IRAM-Safe by allowing the interrupt handler to be\nexecutable when the cache is disabled (e.g. SPI Flash write).", + "id": "PCNT_ISR_IRAM_SAFE", + "name": "PCNT_ISR_IRAM_SAFE", + "range": null, + "title": "PCNT ISR IRAM-Safe", + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_PCNT_SUPPORTED", + "help": "whether to enable the debug log message for PCNT driver.\nNote that, this option only controls the PCNT driver log, won't affect other drivers.", + "id": "PCNT_ENABLE_DEBUG_LOG", + "name": "PCNT_ENABLE_DEBUG_LOG", + "range": null, + "title": "Enable debug log", + "type": "bool" + } + ], + "depends_on": "SOC_PCNT_SUPPORTED", + "id": "component-config-esp-driver-pcnt-configurations", + "title": "ESP-Driver:PCNT Configurations", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": "SOC_RMT_SUPPORTED", + "help": "Ensure the RMT interrupt is IRAM-Safe by allowing the interrupt handler to be\nexecutable when the cache is disabled (e.g. SPI Flash write).", + "id": "RMT_ISR_IRAM_SAFE", + "name": "RMT_ISR_IRAM_SAFE", + "range": null, + "title": "RMT ISR IRAM-Safe", + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_RMT_SUPPORTED", + "help": "Place RMT receive function into IRAM,\nso that the receive function can be IRAM-safe and able to be called when the flash cache is disabled.\nEnabling this option can improve driver performance as well.", + "id": "RMT_RECV_FUNC_IN_IRAM", + "name": "RMT_RECV_FUNC_IN_IRAM", + "range": null, + "title": "Place RMT receive function into IRAM", + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_RMT_SUPPORTED", + "help": "whether to enable the debug log message for RMT driver.\nNote that, this option only controls the RMT driver log, won't affect other drivers.", + "id": "RMT_ENABLE_DEBUG_LOG", + "name": "RMT_ENABLE_DEBUG_LOG", + "range": null, + "title": "Enable debug log", + "type": "bool" + } + ], + "depends_on": "SOC_RMT_SUPPORTED", + "id": "component-config-esp-driver-rmt-configurations", + "title": "ESP-Driver:RMT Configurations", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": "SOC_SDM_SUPPORTED", + "help": "Place SDM control functions (like set_duty) into IRAM,\nso that these functions can be IRAM-safe and able to be called in the other IRAM interrupt context.\nEnabling this option can improve driver performance as well.", + "id": "SDM_CTRL_FUNC_IN_IRAM", + "name": "SDM_CTRL_FUNC_IN_IRAM", + "range": null, + "title": "Place SDM control functions into IRAM", + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_SDM_SUPPORTED", + "help": "whether to enable the debug log message for SDM driver.\nNote that, this option only controls the SDM driver log, won't affect other drivers.", + "id": "SDM_ENABLE_DEBUG_LOG", + "name": "SDM_ENABLE_DEBUG_LOG", + "range": null, + "title": "Enable debug log", + "type": "bool" + } + ], + "depends_on": "SOC_SDM_SUPPORTED", + "id": "component-config-esp-driver-sigma-delta-modulator-configurations", + "title": "ESP-Driver:Sigma Delta Modulator Configurations", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": "!FREERTOS_PLACE_FUNCTIONS_INTO_FLASH && SOC_GPSPI_SUPPORTED", + "help": "Normally only the ISR of SPI master is placed in the IRAM, so that it\ncan work without the flash when interrupt is triggered.\nFor other functions, there's some possibility that the flash cache\nmiss when running inside and out of SPI functions, which may increase\nthe interval of SPI transactions.\nEnable this to put ``queue_trans``, ``get_trans_result`` and\n``transmit`` functions into the IRAM to avoid possible cache miss.\n\nThis configuration won't be available if `CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH` is enabled.\n\nDuring unit test, this is enabled to measure the ideal case of api.", + "id": "SPI_MASTER_IN_IRAM", + "name": "SPI_MASTER_IN_IRAM", + "range": null, + "title": "Place transmitting functions of SPI master into IRAM", + "type": "bool" + }, + { + "children": [], + "depends_on": "!HEAP_PLACE_FUNCTION_INTO_FLASH && SOC_GPSPI_SUPPORTED", + "help": "Place the SPI master ISR in to IRAM to avoid possible cache miss.\n\nEnabling this configuration is possible only when HEAP_PLACE_FUNCTION_INTO_FLASH\nis disabled since the spi master uses can allocate transactions buffers into DMA\nmemory section using the heap component API that ipso facto has to be placed in IRAM.\n\nAlso you can forbid the ISR being disabled during flash writing\naccess, by add ESP_INTR_FLAG_IRAM when initializing the driver.", + "id": "SPI_MASTER_ISR_IN_IRAM", + "name": "SPI_MASTER_ISR_IN_IRAM", + "range": null, + "title": "Place SPI master ISR function into IRAM", + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_GPSPI_SUPPORTED", + "help": "Normally only the ISR of SPI slave is placed in the IRAM, so that it\ncan work without the flash when interrupt is triggered.\nFor other functions, there's some possibility that the flash cache\nmiss when running inside and out of SPI functions, which may increase\nthe interval of SPI transactions.\nEnable this to put ``queue_trans``, ``get_trans_result`` and\n``transmit`` functions into the IRAM to avoid possible cache miss.", + "id": "SPI_SLAVE_IN_IRAM", + "name": "SPI_SLAVE_IN_IRAM", + "range": null, + "title": "Place transmitting functions of SPI slave into IRAM", + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_GPSPI_SUPPORTED", + "help": "Place the SPI slave ISR in to IRAM to avoid possible cache miss.\n\nAlso you can forbid the ISR being disabled during flash writing\naccess, by add ESP_INTR_FLAG_IRAM when initializing the driver.", + "id": "SPI_SLAVE_ISR_IN_IRAM", + "name": "SPI_SLAVE_ISR_IN_IRAM", + "range": null, + "title": "Place SPI slave ISR function into IRAM", + "type": "bool" + } + ], + "depends_on": "SOC_GPSPI_SUPPORTED", + "id": "component-config-esp-driver-spi-configurations", + "title": "ESP-Driver:SPI Configurations", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": "SOC_TOUCH_SENSOR_SUPPORTED", + "help": "Place touch sensor oneshot scanning and continuous scanning functions into IRAM,\nso that these function can be IRAM-safe and able to be called when the flash cache is disabled.\nEnabling this option can improve driver performance as well.", + "id": "TOUCH_CTRL_FUNC_IN_IRAM", + "name": "TOUCH_CTRL_FUNC_IN_IRAM", + "range": null, + "title": "Place touch sensor control functions into IRAM", + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_TOUCH_SENSOR_SUPPORTED", + "help": "Ensure the touch sensor interrupt is IRAM-Safe by allowing the interrupt handler to be\nexecutable when the cache is disabled (e.g. SPI Flash write).", + "id": "TOUCH_ISR_IRAM_SAFE", + "name": "TOUCH_ISR_IRAM_SAFE", + "range": null, + "title": "Touch sensor ISR IRAM-Safe", + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_TOUCH_SENSOR_SUPPORTED", + "help": "Whether to enable the debug log message for touch driver.\nNote that, this option only controls the touch driver log, won't affect other drivers.", + "id": "TOUCH_ENABLE_DEBUG_LOG", + "name": "TOUCH_ENABLE_DEBUG_LOG", + "range": null, + "title": "Enable debug log", + "type": "bool" + } + ], + "depends_on": "SOC_TOUCH_SENSOR_SUPPORTED", + "id": "component-config-esp-driver-touch-sensor-configurations", + "title": "ESP-Driver:Touch Sensor Configurations", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": "SOC_TEMP_SENSOR_SUPPORTED", + "help": "whether to enable the debug log message for temperature sensor driver.\nNote that, this option only controls the temperature sensor driver log, won't affect other drivers.", + "id": "TEMP_SENSOR_ENABLE_DEBUG_LOG", + "name": "TEMP_SENSOR_ENABLE_DEBUG_LOG", + "range": null, + "title": "Enable debug log", + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_TEMPERATURE_SENSOR_INTR_SUPPORT && SOC_TEMP_SENSOR_SUPPORTED", + "help": "Ensure the Temperature Sensor interrupt is IRAM-Safe by allowing the interrupt handler to be\nexecutable when the cache is disabled (e.g. SPI Flash write).", + "id": "TEMP_SENSOR_ISR_IRAM_SAFE", + "name": "TEMP_SENSOR_ISR_IRAM_SAFE", + "range": null, + "title": "Temperature sensor ISR IRAM-Safe", + "type": "bool" + } + ], + "depends_on": "SOC_TEMP_SENSOR_SUPPORTED", + "id": "component-config-esp-driver-temperature-sensor-configurations", + "title": "ESP-Driver:Temperature Sensor Configurations", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": "!RINGBUF_PLACE_ISR_FUNCTIONS_INTO_FLASH", + "help": "If this option is not selected, UART interrupt will be disabled for a long time and\nmay cause data lost when doing spi flash operation.", + "id": "UART_ISR_IN_IRAM", + "name": "UART_ISR_IN_IRAM", + "range": null, + "title": "Place UART ISR function into IRAM", + "type": "bool" + } + ], + "depends_on": null, + "id": "component-config-esp-driver-uart-configurations", + "title": "ESP-Driver:UART Configurations", + "type": "menu" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "PM_ENABLE && ESP_CONSOLE_USB_SERIAL_JTAG_ENABLED && !SOC_USB_SERIAL_JTAG_SUPPORT_LIGHT_SLEEP && USJ_ENABLE_USB_SERIAL_JTAG && SOC_USB_SERIAL_JTAG_SUPPORTED", + "help": "If enabled, the chip will constantly monitor the connection status of the USB Serial/JTAG port. As long\nas the USB Serial/JTAG is connected, a ESP_PM_NO_LIGHT_SLEEP power management lock will be acquired to\nprevent the system from entering light sleep.\nThis option can be useful if serial monitoring is needed via USB Serial/JTAG while power management is\nenabled, as the USB Serial/JTAG cannot work under light sleep and after waking up from light sleep.\nNote. This option can only control the automatic Light-Sleep behavior. If esp_light_sleep_start() is\ncalled manually from the program, enabling this option will not prevent light sleep entry even if the\nUSB Serial/JTAG is in use.", + "id": "USJ_NO_AUTO_LS_ON_CONNECTION", + "name": "USJ_NO_AUTO_LS_ON_CONNECTION", + "range": null, + "title": "Don't enter the automatic light sleep when USB Serial/JTAG port is connected", + "type": "bool" + } + ], + "depends_on": "SOC_USB_SERIAL_JTAG_SUPPORTED", + "help": "The USB-Serial-JTAG module on ESP chips is turned on by default after power-on.\nIf your application does not need it and not rely on it to be used as system\nconsole or use the built-in JTAG for debugging, you can disable this option,\nthen the clock of this module will be disabled at startup, which will save\nsome power consumption.", + "id": "USJ_ENABLE_USB_SERIAL_JTAG", + "name": "USJ_ENABLE_USB_SERIAL_JTAG", + "range": null, + "title": "Enable USB-Serial-JTAG Module", + "type": "bool" + } + ], + "depends_on": "SOC_USB_SERIAL_JTAG_SUPPORTED", + "id": "component-config-esp-driver-usb-serial-jtag-configuration", + "title": "ESP-Driver:USB Serial/JTAG Configuration", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": null, + "help": null, + "id": "ETH_ENABLED", + "name": "ETH_ENABLED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "ETH_PHY_INTERFACE_RMII", + "name": "ETH_PHY_INTERFACE_RMII", + "range": null, + "title": "Reduced Media Independent Interface (RMII)", + "type": "bool" + } + ], + "depends_on": "ETH_USE_ESP32_EMAC", + "help": "Select the communication interface between MAC and PHY chip.", + "id": "component-config-ethernet-support-esp32-internal-emac-controller-phy-interface", + "name": "ETH_PHY_INTERFACE", + "title": "PHY interface", + "type": "choice" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": "MAC will get RMII clock from outside.\nNote that ESP32 only supports GPIO0 to input the RMII clock.", + "id": "ETH_RMII_CLK_INPUT", + "name": "ETH_RMII_CLK_INPUT", + "range": null, + "title": "Input RMII clock from external", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": "ESP32 can generate RMII clock by internal APLL.\nThis clock can be routed to the external PHY device.\nESP32 supports to route the RMII clock to GPIO0/16/17.", + "id": "ETH_RMII_CLK_OUTPUT", + "name": "ETH_RMII_CLK_OUTPUT", + "range": null, + "title": "Output RMII clock from internal", + "type": "bool" + } + ], + "depends_on": "IDF_TARGET_ESP32 && ETH_PHY_INTERFACE_RMII && ETH_USE_ESP32_EMAC", + "help": "Select external or internal RMII clock.", + "id": "component-config-ethernet-support-esp32-internal-emac-controller-rmii-clock-mode", + "name": "ETH_RMII_CLK_MODE", + "title": "RMII clock mode", + "type": "choice" + }, + { + "children": [], + "depends_on": "IDF_TARGET_ESP32 && ETH_RMII_CLK_INPUT && ETH_USE_ESP32_EMAC", + "help": "ESP32 only supports GPIO0 to input the RMII clock.", + "id": "ETH_RMII_CLK_IN_GPIO", + "name": "ETH_RMII_CLK_IN_GPIO", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": "IDF_TARGET_ESP32 && ETH_RMII_CLK_OUTPUT && ETH_USE_ESP32_EMAC", + "help": "GPIO0 can be set to output a pre-divided PLL clock. Enabling this option will configure\nGPIO0 to output a 50MHz clock. In fact this clock doesn't have directly relationship with\nEMAC peripheral. Sometimes this clock may not work well with your PHY chip.\nWARNING: If you want the Ethernet to work with WiFi, don\u2019t select ESP32 as RMII CLK output\nas it would result in clock instability!", + "id": "ETH_RMII_CLK_OUTPUT_GPIO0", + "name": "ETH_RMII_CLK_OUTPUT_GPIO0", + "range": null, + "title": "Output RMII clock from GPIO0 (Experimental!)", + "type": "bool" + }, + { + "children": [], + "depends_on": "IDF_TARGET_ESP32 && !ETH_RMII_CLK_OUTPUT_GPIO0 && ETH_RMII_CLK_OUTPUT && ETH_USE_ESP32_EMAC", + "help": "Set the GPIO number to output RMII Clock.\nWARNING: If you want the Ethernet to work with WiFi, don\u2019t select ESP32 as RMII CLK output\nas it would result in clock instability!", + "id": "ETH_RMII_CLK_OUT_GPIO", + "name": "ETH_RMII_CLK_OUT_GPIO", + "range": null, + "title": "RMII clock GPIO number", + "type": "int" + }, + { + "children": [], + "depends_on": "ETH_USE_ESP32_EMAC", + "help": "Set the size of each buffer used by Ethernet MAC DMA.\n!! Important !! Make sure it is 64B aligned for ESP32P4!", + "id": "ETH_DMA_BUFFER_SIZE", + "name": "ETH_DMA_BUFFER_SIZE", + "range": null, + "title": "Ethernet DMA buffer size (Byte)", + "type": "int" + }, + { + "children": [], + "depends_on": "ETH_USE_ESP32_EMAC", + "help": "Number of DMA receive buffers. Each buffer's size is ETH_DMA_BUFFER_SIZE.\nLarger number of buffers could increase throughput somehow.", + "id": "ETH_DMA_RX_BUFFER_NUM", + "name": "ETH_DMA_RX_BUFFER_NUM", + "range": null, + "title": "Amount of Ethernet DMA Rx buffers", + "type": "int" + }, + { + "children": [], + "depends_on": "ETH_USE_ESP32_EMAC", + "help": "Number of DMA transmit buffers. Each buffer's size is ETH_DMA_BUFFER_SIZE.\nLarger number of buffers could increase throughput somehow.", + "id": "ETH_DMA_TX_BUFFER_NUM", + "name": "ETH_DMA_TX_BUFFER_NUM", + "range": null, + "title": "Amount of Ethernet DMA Tx buffers", + "type": "int" + }, + { + "children": [], + "depends_on": "ETH_DMA_RX_BUFFER_NUM > 15 && ETH_USE_ESP32_EMAC", + "help": "Ethernet MAC engine on ESP32 doesn't feature a flow control logic.\nThe MAC driver can perform a software flow control if you enable this option.\nNote that, if the RX buffer number is small, enabling software flow control will\ncause obvious performance loss.", + "id": "ETH_SOFT_FLOW_CONTROL", + "name": "ETH_SOFT_FLOW_CONTROL", + "range": null, + "title": "Enable software flow control", + "type": "bool" + }, + { + "children": [], + "depends_on": "ETH_USE_ESP32_EMAC", + "help": "If enabled, functions related to RX/TX are placed into IRAM. It can improve Ethernet throughput.\nIf disabled, all functions are placed into FLASH.", + "id": "ETH_IRAM_OPTIMIZATION", + "name": "ETH_IRAM_OPTIMIZATION", + "range": null, + "title": "Enable IRAM optimization", + "type": "bool" + } + ], + "depends_on": "SOC_EMAC_SUPPORTED", + "help": "ESP32 integrates a 10/100M Ethernet MAC controller.", + "id": "ETH_USE_ESP32_EMAC", + "is_menuconfig": true, + "name": "ETH_USE_ESP32_EMAC", + "range": null, + "title": "Support ESP32 internal EMAC controller", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": "ETH_USE_SPI_ETHERNET", + "help": "DM9051 is a fast Ethernet controller with an SPI interface.\nIt's also integrated with a 10/100M PHY and MAC.\nSelect this to enable DM9051 driver.", + "id": "ETH_SPI_ETHERNET_DM9051", + "name": "ETH_SPI_ETHERNET_DM9051", + "range": null, + "title": "Use DM9051", + "type": "bool" + }, + { + "children": [], + "depends_on": "ETH_USE_SPI_ETHERNET", + "help": "W5500 is a HW TCP/IP embedded Ethernet controller.\nTCP/IP stack, 10/100 Ethernet MAC and PHY are embedded in a single chip.\nHowever the driver in ESP-IDF only enables the RAW MAC mode,\nmaking it compatible with the software TCP/IP stack.\nSay yes to enable W5500 driver.", + "id": "ETH_SPI_ETHERNET_W5500", + "name": "ETH_SPI_ETHERNET_W5500", + "range": null, + "title": "Use W5500 (MAC RAW)", + "type": "bool" + }, + { + "children": [], + "depends_on": "ETH_USE_SPI_ETHERNET", + "help": "The KSZ8851SNL is a single-chip Fast Ethernet controller consisting of\na 10/100 physical layer transceiver (PHY), a MAC, and a Serial Peripheral Interface (SPI).\nSelect this to enable KSZ8851SNL driver.", + "id": "ETH_SPI_ETHERNET_KSZ8851SNL", + "name": "ETH_SPI_ETHERNET_KSZ8851SNL", + "range": null, + "title": "Use KSZ8851SNL", + "type": "bool" + } + ], + "depends_on": null, + "help": "ESP-IDF can also support some SPI-Ethernet modules.", + "id": "ETH_USE_SPI_ETHERNET", + "is_menuconfig": true, + "name": "ETH_USE_SPI_ETHERNET", + "range": null, + "title": "Support SPI to Ethernet Module", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": "ETH_USE_OPENETH", + "help": "Number of DMA receive buffers, each buffer is 1600 bytes.", + "id": "ETH_OPENETH_DMA_RX_BUFFER_NUM", + "name": "ETH_OPENETH_DMA_RX_BUFFER_NUM", + "range": null, + "title": "Number of Ethernet DMA Rx buffers", + "type": "int" + }, + { + "children": [], + "depends_on": "ETH_USE_OPENETH", + "help": "Number of DMA transmit buffers, each buffer is 1600 bytes.", + "id": "ETH_OPENETH_DMA_TX_BUFFER_NUM", + "name": "ETH_OPENETH_DMA_TX_BUFFER_NUM", + "range": null, + "title": "Number of Ethernet DMA Tx buffers", + "type": "int" + } + ], + "depends_on": null, + "help": "OpenCores Ethernet MAC driver can be used when an ESP-IDF application\nis executed in QEMU. This driver is not supported when running on a\nreal chip.", + "id": "ETH_USE_OPENETH", + "is_menuconfig": true, + "name": "ETH_USE_OPENETH", + "range": null, + "title": "Support OpenCores Ethernet MAC (for use with QEMU)", + "type": "menu" + }, + { + "children": [], + "depends_on": "ETH_ENABLED", + "help": "Prevents multiple accesses when Ethernet interface is used as shared resource and multiple\nfunctionalities might try to access it at a time.", + "id": "ETH_TRANSMIT_MUTEX", + "name": "ETH_TRANSMIT_MUTEX", + "range": null, + "title": "Enable Transmit Mutex", + "type": "bool" + } + ], + "depends_on": null, + "id": "component-config-ethernet", + "title": "Ethernet", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": null, + "help": "Enables collections of statistics in the event loop library such as the number of events posted\nto/recieved by an event loop, number of callbacks involved, number of events dropped to to a full event\nloop queue, run time of event handlers, and number of times/run time of each event handler.", + "id": "ESP_EVENT_LOOP_PROFILING", + "name": "ESP_EVENT_LOOP_PROFILING", + "range": null, + "title": "Enable event loop profiling", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "ESP_EVENT_POST_FROM_ISR", + "help": "Enable posting events from interrupt handlers placed in IRAM. Enabling this option places API functions\nesp_event_post and esp_event_post_to in IRAM.", + "id": "ESP_EVENT_POST_FROM_IRAM_ISR", + "name": "ESP_EVENT_POST_FROM_IRAM_ISR", + "range": null, + "title": "Support posting events from ISRs placed in IRAM", + "type": "bool" + } + ], + "depends_on": null, + "help": "Enable posting events from interrupt handlers.", + "id": "ESP_EVENT_POST_FROM_ISR", + "name": "ESP_EVENT_POST_FROM_ISR", + "range": null, + "title": "Support posting events from ISRs", + "type": "bool" + } + ], + "depends_on": null, + "id": "component-config-event-loop-library", + "title": "Event Loop Library", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": null, + "help": null, + "id": "ESP_GDBSTUB_ENABLED", + "name": "ESP_GDBSTUB_ENABLED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Enable builtin GDBStub.\nThis allows to debug the target device using serial port:\n- Run 'idf.py monitor'.\n- Wait for the device to initialize.\n- Press Ctrl+C to interrupt the execution and enter GDB attached to your device for debugging.\nNOTE: all UART input will be handled by GDBStub.", + "id": "ESP_SYSTEM_GDBSTUB_RUNTIME", + "name": "ESP_SYSTEM_GDBSTUB_RUNTIME", + "range": null, + "title": "GDBStub at runtime", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "ESP_GDBSTUB_SUPPORT_TASKS", + "help": "Set the number of tasks which GDB Stub will support.", + "id": "ESP_GDBSTUB_MAX_TASKS", + "name": "ESP_GDBSTUB_MAX_TASKS", + "range": null, + "title": "Maximum number of tasks supported by GDB Stub", + "type": "int" + } + ], + "depends_on": "ESP_GDBSTUB_ENABLED", + "help": "If enabled, GDBStub can supply the list of FreeRTOS tasks to GDB.\nThread list can be queried from GDB using 'info threads' command.\nNote that if GDB task lists were corrupted, this feature may not work.\nIf GDBStub fails, try disabling this feature.", + "id": "ESP_GDBSTUB_SUPPORT_TASKS", + "name": "ESP_GDBSTUB_SUPPORT_TASKS", + "range": null, + "title": "Enable listing FreeRTOS tasks through GDB Stub", + "type": "bool" + } + ], + "depends_on": null, + "id": "component-config-gdb-stub", + "title": "GDB Stub", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": null, + "help": "This is the stack size for the BT HID task.\nDefault is 2048 bytes.", + "id": "ESPHID_TASK_SIZE_BT", + "name": "ESPHID_TASK_SIZE_BT", + "range": [ + 2048, + 10240 + ], + "title": "Task stack size for ESP HID BR/EDR", + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": "This is the stack size for the BLE HID task.\nDefault is 4096 bytes.", + "id": "ESPHID_TASK_SIZE_BLE", + "name": "ESPHID_TASK_SIZE_BLE", + "range": [ + 2048, + 10240 + ], + "title": "Task stack size for ESP HID BLE", + "type": "int" + } + ], + "depends_on": null, + "id": "component-config-esp-hid", + "title": "ESP HID", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": null, + "help": "This option will enable https protocol by linking esp-tls library and initializing SSL transport", + "id": "ESP_HTTP_CLIENT_ENABLE_HTTPS", + "name": "ESP_HTTP_CLIENT_ENABLE_HTTPS", + "range": null, + "title": "Enable https", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "This option will enable HTTP Basic Authentication. It is disabled by default as Basic\nauth uses unencrypted encoding, so it introduces a vulnerability when not using TLS", + "id": "ESP_HTTP_CLIENT_ENABLE_BASIC_AUTH", + "name": "ESP_HTTP_CLIENT_ENABLE_BASIC_AUTH", + "range": null, + "title": "Enable HTTP Basic Authentication", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "This option will enable HTTP Digest Authentication. It is enabled by default, but use of this\nconfiguration is not recommended as the password can be derived from the exchange, so it introduces\na vulnerability when not using TLS", + "id": "ESP_HTTP_CLIENT_ENABLE_DIGEST_AUTH", + "name": "ESP_HTTP_CLIENT_ENABLE_DIGEST_AUTH", + "range": null, + "title": "Enable HTTP Digest Authentication", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "This option will enable injection of a custom tcp_transport handle, so the http operation\nwill be performed on top of the user defined transport abstraction (if configured)", + "id": "ESP_HTTP_CLIENT_ENABLE_CUSTOM_TRANSPORT", + "name": "ESP_HTTP_CLIENT_ENABLE_CUSTOM_TRANSPORT", + "range": null, + "title": "Enable custom transport", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "This config option helps in setting the time in millisecond to wait for event to be posted to the\nsystem default event loop. Set it to -1 if you need to set timeout to portMAX_DELAY.", + "id": "ESP_HTTP_CLIENT_EVENT_POST_TIMEOUT", + "name": "ESP_HTTP_CLIENT_EVENT_POST_TIMEOUT", + "range": null, + "title": "Time in millisecond to wait for posting event", + "type": "int" + } + ], + "depends_on": null, + "id": "component-config-esp-http-client", + "title": "ESP HTTP client", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": null, + "help": "This sets the maximum supported size of headers section in HTTP request packet to be processed by the\nserver", + "id": "HTTPD_MAX_REQ_HDR_LEN", + "name": "HTTPD_MAX_REQ_HDR_LEN", + "range": null, + "title": "Max HTTP Request Header Length", + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": "This sets the maximum supported size of HTTP request URI to be processed by the server", + "id": "HTTPD_MAX_URI_LEN", + "name": "HTTPD_MAX_URI_LEN", + "range": null, + "title": "Max HTTP URI Length", + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": "Using TCP_NODEALY socket option ensures that HTTP error response reaches the client before the\nunderlying socket is closed. Please note that turning this off may cause multiple test failures", + "id": "HTTPD_ERR_RESP_NO_DELAY", + "name": "HTTPD_ERR_RESP_NO_DELAY", + "range": null, + "title": "Use TCP_NODELAY socket option when sending HTTP error responses", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "This sets the size of the temporary buffer used to receive and discard any remaining data that is\nreceived from the HTTP client in the request, but not processed as part of the server HTTP request\nhandler.\n\nIf the remaining data is larger than the available buffer size, the buffer will be filled in multiple\niterations. The buffer should be small enough to fit on the stack, but large enough to avoid excessive\niterations.", + "id": "HTTPD_PURGE_BUF_LEN", + "name": "HTTPD_PURGE_BUF_LEN", + "range": null, + "title": "Length of temporary buffer for purging data", + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": "Enabling this will log discarded binary HTTP request data at Debug level.\nFor large content data this may not be desirable as it will clutter the log.", + "id": "HTTPD_LOG_PURGE_DATA", + "name": "HTTPD_LOG_PURGE_DATA", + "range": null, + "title": "Log purged content data at Debug level", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "This sets the WebSocket server support.", + "id": "HTTPD_WS_SUPPORT", + "name": "HTTPD_WS_SUPPORT", + "range": null, + "title": "WebSocket server support", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "This makes httpd_queue_work() API to wait until a message space is available on UDP control socket.\nIt internally uses a counting semaphore with count set to `LWIP_UDP_RECVMBOX_SIZE` to achieve this.\nThis config will slightly change API behavior to block until message gets delivered on control socket.", + "id": "HTTPD_QUEUE_WORK_BLOCKING", + "name": "HTTPD_QUEUE_WORK_BLOCKING", + "range": null, + "title": "httpd_queue_work as blocking API", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "This config option helps in setting the time in millisecond to wait for event to be posted to the\nsystem default event loop. Set it to -1 if you need to set timeout to portMAX_DELAY.", + "id": "HTTPD_SERVER_EVENT_POST_TIMEOUT", + "name": "HTTPD_SERVER_EVENT_POST_TIMEOUT", + "range": null, + "title": "Time in millisecond to wait for posting event", + "type": "int" + } + ], + "depends_on": null, + "id": "component-config-http-server", + "title": "HTTP Server", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": null, + "help": "Exposes an additional callback whereby firmware data could be decrypted\nbefore being processed by OTA update component. This can help to integrate\nexternal encryption related format and removal of such encapsulation layer\nfrom firmware image.", + "id": "ESP_HTTPS_OTA_DECRYPT_CB", + "name": "ESP_HTTPS_OTA_DECRYPT_CB", + "range": null, + "title": "Provide decryption callback", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "It is highly recommended to keep HTTPS (along with server certificate validation) enabled.\nEnabling this option comes with potential risk of:\n- Non-encrypted communication channel with server\n- Accepting firmware upgrade image from server with fake identity", + "id": "ESP_HTTPS_OTA_ALLOW_HTTP", + "name": "ESP_HTTPS_OTA_ALLOW_HTTP", + "range": null, + "title": "Allow HTTP for OTA (WARNING: ONLY FOR TESTING PURPOSE, READ HELP)", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "This config option helps in setting the time in millisecond to wait for event to be posted to the\nsystem default event loop. Set it to -1 if you need to set timeout to portMAX_DELAY.", + "id": "ESP_HTTPS_OTA_EVENT_POST_TIMEOUT", + "name": "ESP_HTTPS_OTA_EVENT_POST_TIMEOUT", + "range": null, + "title": "Time in millisecond to wait for posting event", + "type": "int" + } + ], + "depends_on": null, + "id": "component-config-esp-https-ota", + "title": "ESP HTTPS OTA", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": "ESP_TLS_USING_MBEDTLS && MBEDTLS_TLS_SERVER", + "help": "Enable ESP HTTPS server component", + "id": "ESP_HTTPS_SERVER_ENABLE", + "name": "ESP_HTTPS_SERVER_ENABLE", + "range": null, + "title": "Enable ESP_HTTPS_SERVER component", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "This config option helps in setting the time in millisecond to wait for event to be posted to the\nsystem default event loop. Set it to -1 if you need to set timeout to portMAX_DELAY.", + "id": "ESP_HTTPS_SERVER_EVENT_POST_TIMEOUT", + "name": "ESP_HTTPS_SERVER_EVENT_POST_TIMEOUT", + "range": null, + "title": "Time in millisecond to wait for posting event", + "type": "int" + } + ], + "depends_on": null, + "id": "component-config-esp-https-server", + "title": "ESP HTTPS server", + "type": "menu" + }, + { + "children": [ + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "ESP32C3_REV_MIN_0", + "name": "ESP32C3_REV_MIN_0", + "range": null, + "title": "Rev v0.0 (ECO0)", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "ESP32C3_REV_MIN_1", + "name": "ESP32C3_REV_MIN_1", + "range": null, + "title": "Rev v0.1 (ECO1)", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "ESP32C3_REV_MIN_2", + "name": "ESP32C3_REV_MIN_2", + "range": null, + "title": "Rev v0.2 (ECO2)", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "ESP32C3_REV_MIN_3", + "name": "ESP32C3_REV_MIN_3", + "range": null, + "title": "Rev v0.3 (ECO3)", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "ESP32C3_REV_MIN_4", + "name": "ESP32C3_REV_MIN_4", + "range": null, + "title": "Rev v0.4 (ECO4)", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "ESP32C3_REV_MIN_101", + "name": "ESP32C3_REV_MIN_101", + "range": null, + "title": "Rev v1.1", + "type": "bool" + } + ], + "depends_on": null, + "help": "Required minimum chip revision. ESP-IDF will check for it and\nreject to boot if the chip revision fails the check.\nThis ensures the chip used will have some modifications (features, or bugfixes).\n\nThe complied binary will only support chips above this revision,\nthis will also help to reduce binary size.", + "id": "component-config-hardware-settings-chip-revision-minimum-supported-esp32-c3-revision", + "name": "ESP32C3_REV_MIN", + "title": "Minimum Supported ESP32-C3 Revision", + "type": "choice" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "ESP32C3_REV_MIN_FULL", + "name": "ESP32C3_REV_MIN_FULL", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "ESP_REV_MIN_FULL", + "name": "ESP_REV_MIN_FULL", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "ESP32C3_REV_MAX_FULL", + "name": "ESP32C3_REV_MAX_FULL", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "ESP_REV_MAX_FULL", + "name": "ESP_REV_MAX_FULL", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": "Required minimum eFuse Block revision. ESP-IDF will check it at the 2nd bootloader stage\nwhether the current image can work correctly for this eFuse Block revision.\nSo that to avoid running an incompatible image on a SoC that contains breaking change in the eFuse Block.\nIf you want to update this value to run the image that not compatible with the current eFuse Block revision,\nplease contact to Espressif's business team for details:\nhttps://www.espressif.com.cn/en/contact-us/sales-questions", + "id": "ESP_EFUSE_BLOCK_REV_MIN_FULL", + "name": "ESP_EFUSE_BLOCK_REV_MIN_FULL", + "range": null, + "title": "Minimum Supported ESP32-C3 eFuse Block Revision", + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "ESP_EFUSE_BLOCK_REV_MAX_FULL", + "name": "ESP_EFUSE_BLOCK_REV_MAX_FULL", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": "IDF_CI_BUILD", + "help": "For internal chip testing, a small number of new versions chips didn't\nupdate the version field in eFuse, you can enable this option to force the\nsoftware recognize the chip version based on the rev selected in menuconfig.", + "id": "ESP_REV_NEW_CHIP_TEST", + "name": "ESP_REV_NEW_CHIP_TEST", + "range": null, + "title": "Internal test mode", + "type": "bool" + } + ], + "depends_on": null, + "id": "component-config-hardware-settings-chip-revision", + "title": "Chip revision", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": null, + "help": null, + "id": "ESP_MAC_ADDR_UNIVERSE_WIFI_STA", + "name": "ESP_MAC_ADDR_UNIVERSE_WIFI_STA", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "ESP_MAC_ADDR_UNIVERSE_WIFI_AP", + "name": "ESP_MAC_ADDR_UNIVERSE_WIFI_AP", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "ESP_MAC_ADDR_UNIVERSE_BT", + "name": "ESP_MAC_ADDR_UNIVERSE_BT", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "ESP_MAC_ADDR_UNIVERSE_ETH", + "name": "ESP_MAC_ADDR_UNIVERSE_ETH", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "ESP_MAC_ADDR_UNIVERSE_IEEE802154", + "name": "ESP_MAC_ADDR_UNIVERSE_IEEE802154", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "ESP_MAC_UNIVERSAL_MAC_ADDRESSES_ONE", + "name": "ESP_MAC_UNIVERSAL_MAC_ADDRESSES_ONE", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "ESP_MAC_UNIVERSAL_MAC_ADDRESSES_TWO", + "name": "ESP_MAC_UNIVERSAL_MAC_ADDRESSES_TWO", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "ESP_MAC_UNIVERSAL_MAC_ADDRESSES_FOUR", + "name": "ESP_MAC_UNIVERSAL_MAC_ADDRESSES_FOUR", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "ESP_MAC_UNIVERSAL_MAC_ADDRESSES", + "name": "ESP_MAC_UNIVERSAL_MAC_ADDRESSES", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "ESP32C3_UNIVERSAL_MAC_ADDRESSES_TWO", + "name": "ESP32C3_UNIVERSAL_MAC_ADDRESSES_TWO", + "range": null, + "title": "Two", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "ESP32C3_UNIVERSAL_MAC_ADDRESSES_FOUR", + "name": "ESP32C3_UNIVERSAL_MAC_ADDRESSES_FOUR", + "range": null, + "title": "Four", + "type": "bool" + } + ], + "depends_on": null, + "help": "Configure the number of universally administered (by IEEE) MAC addresses.\n\nDuring initialization, MAC addresses for each network interface are generated or derived from a\nsingle base MAC address.\n\nIf the number of universal MAC addresses is four, all four interfaces (WiFi station, WiFi softap,\nBluetooth and Ethernet) receive a universally administered MAC address. These are generated\nsequentially by adding 0, 1, 2 and 3 (respectively) to the final octet of the base MAC address.\n\nIf the number of universal MAC addresses is two, only two interfaces (WiFi station and Bluetooth)\nreceive a universally administered MAC address. These are generated sequentially by adding 0\nand 1 (respectively) to the base MAC address. The remaining two interfaces (WiFi softap and Ethernet)\nreceive local MAC addresses. These are derived from the universal WiFi station and Bluetooth MAC\naddresses, respectively.\n\nWhen using the default (Espressif-assigned) base MAC address, either setting can be used. When using\na custom universal MAC address range, the correct setting will depend on the allocation of MAC\naddresses in this range (either 2 or 4 per device.)\n\nNote that ESP32-C3 has no integrated Ethernet MAC. Although it's possible to use the esp_read_mac()\nAPI to return a MAC for Ethernet, this can only be used with an external MAC peripheral.", + "id": "component-config-hardware-settings-mac-config-number-of-universally-administered-by-ieee-mac-address", + "name": "ESP32C3_UNIVERSAL_MAC_ADDRESSES", + "title": "Number of universally administered (by IEEE) MAC address", + "type": "choice" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "ESP32C3_UNIVERSAL_MAC_ADDRESSES", + "name": "ESP32C3_UNIVERSAL_MAC_ADDRESSES", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": "IDF_TARGET_ESP32", + "help": "If you have an invalid MAC CRC (ESP_ERR_INVALID_CRC) problem\nand you still want to use this chip, you can enable this option to bypass such an error.\nThis applies to both MAC_FACTORY and CUSTOM_MAC efuses.", + "id": "ESP_MAC_IGNORE_MAC_CRC_ERROR", + "name": "ESP_MAC_IGNORE_MAC_CRC_ERROR", + "range": null, + "title": "Ignore MAC CRC error (not recommended)", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "When this configuration is enabled, the user can invoke `esp_read_mac` to obtain the desired type of\nMAC using a custom MAC as the base MAC.", + "id": "ESP_MAC_USE_CUSTOM_MAC_AS_BASE_MAC", + "name": "ESP_MAC_USE_CUSTOM_MAC_AS_BASE_MAC", + "range": null, + "title": "Enable using custom mac as base mac", + "type": "bool" + } + ], + "depends_on": null, + "id": "component-config-hardware-settings-mac-config", + "title": "MAC Config", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": "(!SPIRAM || ESP_LDO_RESERVE_PSRAM) && !(IDF_TARGET_ESP32P4 && ESP32P4_REV_MIN_FULL < 100)", + "help": "If enabled, chip will try to power down flash as part of esp_light_sleep_start(), which costs\nmore time when chip wakes up. Can only be enabled if there is no SPIRAM configured.\n\nThis option will power down flash under a strict but relatively safe condition. Also, it is possible to\npower down flash under a relaxed condition by using esp_sleep_pd_config() to set ESP_PD_DOMAIN_VDDSDIO\nto ESP_PD_OPTION_OFF. It should be noted that there is a risk in powering down flash, you can refer\n`ESP-IDF Programming Guide/API Reference/System API/Sleep Modes/Power-down of Flash` for more details.", + "id": "ESP_SLEEP_POWER_DOWN_FLASH", + "name": "ESP_SLEEP_POWER_DOWN_FLASH", + "range": null, + "title": "Power down flash in light sleep when there is no SPIRAM or SPIRAM has independent power supply", + "type": "bool" + }, + { + "children": [], + "depends_on": "!APP_BUILD_TYPE_PURE_RAM_APP", + "help": "All IOs will be set to isolate(floating) state by default during sleep.\nSince the power supply of SPI Flash is not lost during lightsleep, if its CS pin is recognized as\nlow level(selected state) in the floating state, there will be a large current leakage, and the\ndata in Flash may be corrupted by random signals on other SPI pins.\nSelect this option will set the CS pin of Flash to PULL-UP state during sleep, but this will\nincrease the sleep current about 10 uA.\nIf you are developing with esp32xx modules, you must select this option, but if you are developing\nwith chips, you can also pull up the CS pin of SPI Flash in the external circuit to save power\nconsumption caused by internal pull-up during sleep.\n(!!! Don't deselect this option if you don't have external SPI Flash CS pin pullups.)", + "id": "ESP_SLEEP_FLASH_LEAKAGE_WORKAROUND", + "name": "ESP_SLEEP_FLASH_LEAKAGE_WORKAROUND", + "range": null, + "title": "Pull-up Flash CS pin in light sleep", + "type": "bool" + }, + { + "children": [], + "depends_on": "SPIRAM", + "help": "All IOs will be set to isolate(floating) state by default during sleep.\nSince the power supply of PSRAM is not lost during lightsleep, if its CS pin is recognized as\nlow level(selected state) in the floating state, there will be a large current leakage, and the\ndata in PSRAM may be corrupted by random signals on other SPI pins.\nSelect this option will set the CS pin of PSRAM to PULL-UP state during sleep, but this will\nincrease the sleep current about 10 uA.\nIf you are developing with esp32xx modules, you must select this option, but if you are developing\nwith chips, you can also pull up the CS pin of PSRAM in the external circuit to save power\nconsumption caused by internal pull-up during sleep.\n(!!! Don't deselect this option if you don't have external PSRAM CS pin pullups.)", + "id": "ESP_SLEEP_PSRAM_LEAKAGE_WORKAROUND", + "name": "ESP_SLEEP_PSRAM_LEAKAGE_WORKAROUND", + "range": null, + "title": "Pull-up PSRAM CS pin in light sleep", + "type": "bool" + }, + { + "children": [], + "depends_on": "ESP_SLEEP_PSRAM_LEAKAGE_WORKAROUND || ESP_SLEEP_FLASH_LEAKAGE_WORKAROUND", + "help": "To reduce leakage current, some types of SPI Flash/RAM only need to pull up the CS pin\nduring light sleep. But there are also some kinds of SPI Flash/RAM that need to pull up\nall pins. It depends on the SPI Flash/RAM chip used.", + "id": "ESP_SLEEP_MSPI_NEED_ALL_IO_PU", + "name": "ESP_SLEEP_MSPI_NEED_ALL_IO_PU", + "range": null, + "title": "Pull-up all SPI pins in light sleep", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "ESP_SLEEP_RTC_BUS_ISO_WORKAROUND", + "name": "ESP_SLEEP_RTC_BUS_ISO_WORKAROUND", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "esp32c2, esp32c3, esp32s3, esp32c5, esp32c6 and esp32h2 will reset at wake-up if GPIO is received\na small electrostatic pulse during light sleep, with specific condition\n\n- GPIO needs to be configured as input-mode only\n- The pin receives a small electrostatic pulse, and reset occurs when the pulse\n voltage is higher than 6 V\n\nFor GPIO set to input mode only, it is not a good practice to leave it open/floating,\nThe hardware design needs to controlled it with determined supply or ground voltage\nis necessary.\n\nThis option provides a software workaround for this issue. Configure to isolate all\nGPIO pins in sleep state.", + "id": "ESP_SLEEP_GPIO_RESET_WORKAROUND", + "name": "ESP_SLEEP_GPIO_RESET_WORKAROUND", + "range": null, + "title": "light sleep GPIO reset workaround", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "When the chip exits sleep, the CPU and the flash chip are powered on at the same time.\nCPU will run rom code (deepsleep) or ram code (lightsleep) first, and then load or execute\ncode from flash.\n\nSome flash chips need sufficient time to pass between power on and first read operation.\nBy default, without any extra delay, this time is approximately 900us, although\nsome flash chip types need more than that.\n\n(!!! Please adjust this value according to the Data Sheet of SPI Flash used in your project.)\nIn Flash Data Sheet, the parameters that define the Flash ready timing after power-up (minimum\ntime from Vcc(min) to CS activeare) usually named tVSL in ELECTRICAL CHARACTERISTICS chapter,\nand the configuration value here should be:\nESP_SLEEP_WAIT_FLASH_READY_EXTRA_DELAY = tVSL - 900\n\nFor esp32 and esp32s3, the default extra delay is set to 2000us. When optimizing startup time\nfor applications which require it, this value may be reduced.\n\nIf you are seeing \"flash read err, 1000\" message printed to the console after deep sleep reset\non esp32, or triggered RTC_WDT/LP_WDT after lightsleep wakeup, try increasing this value.\n(For esp32, the delay will be executed in both deep sleep and light sleep wake up flow.\nFor chips after esp32, the delay will be executed only in light sleep flow, the delay\ncontrolled by the EFUSE_FLASH_TPUW in ROM will be executed in deepsleep wake up flow.)", + "id": "ESP_SLEEP_WAIT_FLASH_READY_EXTRA_DELAY", + "name": "ESP_SLEEP_WAIT_FLASH_READY_EXTRA_DELAY", + "range": [ + 0, + 5000 + ], + "title": "Extra delay (in us) after flash powerdown sleep wakeup to wait flash ready", + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": "Enabling it will check the cache safety of the code before the flash power is ready after\nlight sleep wakeup, and check PM_SLP_IRAM_OPT related code cache safety. This option is\nonly for code quality inspection. Enabling it will increase the time overhead of entering\nand exiting sleep. It is not recommended to enable it in the release version.", + "id": "ESP_SLEEP_CACHE_SAFE_ASSERTION", + "name": "ESP_SLEEP_CACHE_SAFE_ASSERTION", + "range": null, + "title": "Check the cache safety of the sleep wakeup code in sleep process", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Enable esp sleep debug.", + "id": "ESP_SLEEP_DEBUG", + "name": "ESP_SLEEP_DEBUG", + "range": null, + "title": "esp sleep debug", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "When using rtc gpio wakeup source during deepsleep without external pull-up/downs, you may want to\nmake use of the internal ones.", + "id": "ESP_SLEEP_GPIO_ENABLE_INTERNAL_RESISTORS", + "name": "ESP_SLEEP_GPIO_ENABLE_INTERNAL_RESISTORS", + "range": null, + "title": "Allow to enable internal pull-up/downs for the Deep-Sleep wakeup IOs", + "type": "bool" + }, + { + "children": [], + "depends_on": "FREERTOS_USE_TICKLESS_IDLE", + "help": "If enabled, it allows user to register sleep event callbacks. It is primarily designed for internal\ndevelopers and customers can use PM_LIGHT_SLEEP_CALLBACKS as an alternative.\n\nNOTE: These callbacks are executed from the IDLE task context hence you cannot have any blocking calls\nin your callbacks.\n\nNOTE: Enabling these callbacks may change sleep duration calculations based on time spent in\ncallback and hence it is highly recommended to keep them as short as possible.", + "id": "ESP_SLEEP_EVENT_CALLBACKS", + "name": "ESP_SLEEP_EVENT_CALLBACKS", + "range": null, + "title": "Enable registration of sleep event callbacks", + "type": "bool" + } + ], + "depends_on": null, + "id": "component-config-hardware-settings-sleep-config", + "title": "Sleep Config", + "type": "menu" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "RTC_CLK_SRC_INT_RC", + "name": "RTC_CLK_SRC_INT_RC", + "range": null, + "title": "Internal 136 kHz RC oscillator", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "RTC_CLK_SRC_EXT_CRYS", + "name": "RTC_CLK_SRC_EXT_CRYS", + "range": null, + "title": "External 32 kHz crystal", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "RTC_CLK_SRC_EXT_OSC", + "name": "RTC_CLK_SRC_EXT_OSC", + "range": null, + "title": "External 32 kHz oscillator at 32K_XP pin", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "RTC_CLK_SRC_INT_8MD256", + "name": "RTC_CLK_SRC_INT_8MD256", + "range": null, + "title": "Internal 17.5 MHz oscillator, divided by 256", + "type": "bool" + } + ], + "depends_on": null, + "help": "Choose which clock is used as RTC clock source.", + "id": "component-config-hardware-settings-rtc-clock-config-rtc-clock-source", + "name": "RTC_CLK_SRC", + "title": "RTC clock source", + "type": "choice" + }, + { + "children": [], + "depends_on": null, + "help": "When the startup code initializes RTC_SLOW_CLK, it can perform\ncalibration by comparing the RTC_SLOW_CLK frequency with main XTAL\nfrequency. This option sets the number of RTC_SLOW_CLK cycles measured\nby the calibration routine. Higher numbers increase calibration\nprecision, which may be important for applications which spend a lot of\ntime in deep sleep. Lower numbers reduce startup time.\n\nWhen this option is set to 0, clock calibration will not be performed at\nstartup, and approximate clock frequencies will be assumed:\n\n- 150000 Hz if internal RC oscillator is used as clock source. For this use value 1024.\n- 32768 Hz if the 32k crystal oscillator is used. For this use value 3000 or more.\n In case more value will help improve the definition of the launch of the crystal.\n If the crystal could not start, it will be switched to internal RC.", + "id": "RTC_CLK_CAL_CYCLES", + "name": "RTC_CLK_CAL_CYCLES", + "range": [ + 0, + 32766 + ], + "title": "Number of cycles for RTC_SLOW_CLK calibration", + "type": "int" + } + ], + "depends_on": null, + "id": "component-config-hardware-settings-rtc-clock-config", + "title": "RTC Clock Config", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": null, + "help": "Place peripheral control functions (e.g. periph_module_reset) into IRAM,\nso that these functions can be IRAM-safe and able to be called in the other IRAM interrupt context.", + "id": "PERIPH_CTRL_FUNC_IN_IRAM", + "name": "PERIPH_CTRL_FUNC_IN_IRAM", + "range": null, + "title": "Place peripheral control functions into IRAM", + "type": "bool" + } + ], + "depends_on": null, + "id": "component-config-hardware-settings-peripheral-control", + "title": "Peripheral Control", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": "SOC_ETM_SUPPORTED", + "help": "whether to enable the debug log message for ETM core driver.\nNote that, this option only controls the ETM related driver log, won't affect other drivers.", + "id": "ETM_ENABLE_DEBUG_LOG", + "name": "ETM_ENABLE_DEBUG_LOG", + "range": null, + "title": "Enable debug log", + "type": "bool" + } + ], + "depends_on": "SOC_ETM_SUPPORTED", + "id": "component-config-hardware-settings-etm-configuration", + "title": "ETM Configuration", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": "SOC_GDMA_SUPPORTED", + "help": "Place GDMA control functions (like start/stop/append/reset) into IRAM,\nso that these functions can be IRAM-safe and able to be called in the other IRAM interrupt context.", + "id": "GDMA_CTRL_FUNC_IN_IRAM", + "name": "GDMA_CTRL_FUNC_IN_IRAM", + "range": null, + "title": "Place GDMA control functions in IRAM", + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_GDMA_SUPPORTED", + "help": "This will ensure the GDMA interrupt handler is IRAM-Safe, allow to avoid flash\ncache misses, and also be able to run whilst the cache is disabled.\n(e.g. SPI Flash write).", + "id": "GDMA_ISR_IRAM_SAFE", + "name": "GDMA_ISR_IRAM_SAFE", + "range": null, + "title": "GDMA ISR IRAM-Safe", + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_GDMA_SUPPORTED", + "help": "Whether to enable the debug log message for GDMA driver.\nNote that, this option only controls the GDMA driver log, won't affect other drivers.", + "id": "GDMA_ENABLE_DEBUG_LOG", + "name": "GDMA_ENABLE_DEBUG_LOG", + "range": null, + "title": "Enable debug log", + "type": "bool" + } + ], + "depends_on": "SOC_GDMA_SUPPORTED", + "id": "component-config-hardware-settings-gdma-configurations", + "title": "GDMA Configurations", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": "SOC_DW_GDMA_SUPPORTED", + "help": "Place DW_GDMA control functions (e.g. dw_gdma_channel_continue) into IRAM,\nso that these functions can be IRAM-safe and able to be called in the other IRAM interrupt context.", + "id": "DW_GDMA_CTRL_FUNC_IN_IRAM", + "name": "DW_GDMA_CTRL_FUNC_IN_IRAM", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_DW_GDMA_SUPPORTED", + "help": "Place DW_GDMA setter functions (e.g. dw_gdma_channel_set_block_markers) into IRAM,\nso that these functions can be IRAM-safe and able to be called in the other IRAM interrupt context.", + "id": "DW_GDMA_SETTER_FUNC_IN_IRAM", + "name": "DW_GDMA_SETTER_FUNC_IN_IRAM", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_DW_GDMA_SUPPORTED", + "help": "Place DW_GDMA getter functions (e.g. dw_gdma_link_list_get_item) into IRAM,\nso that these functions can be IRAM-safe and able to be called in the other IRAM interrupt context.", + "id": "DW_GDMA_GETTER_FUNC_IN_IRAM", + "name": "DW_GDMA_GETTER_FUNC_IN_IRAM", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_DW_GDMA_SUPPORTED", + "help": "This will ensure the DW_GDMA interrupt handler is IRAM-Safe, allow to avoid flash\ncache misses, and also be able to run whilst the cache is disabled.\n(e.g. SPI Flash write).", + "id": "DW_GDMA_ISR_IRAM_SAFE", + "name": "DW_GDMA_ISR_IRAM_SAFE", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_DW_GDMA_SUPPORTED", + "help": "This will ensure the DW_GDMA object is DRAM-Safe, allow to avoid external memory\ncache misses, and also be accessible whilst the cache is disabled.", + "id": "DW_GDMA_OBJ_DRAM_SAFE", + "name": "DW_GDMA_OBJ_DRAM_SAFE", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_DW_GDMA_SUPPORTED", + "help": "Whether to enable the debug log message for DW_GDMA driver.\nNote that, this option only controls the DW_GDMA driver log, won't affect other drivers.", + "id": "DW_GDMA_ENABLE_DEBUG_LOG", + "name": "DW_GDMA_ENABLE_DEBUG_LOG", + "range": null, + "title": "Enable debug log", + "type": "bool" + } + ], + "depends_on": "SOC_DW_GDMA_SUPPORTED", + "id": "component-config-hardware-settings-dw_gdma-configurations", + "title": "DW_GDMA Configurations", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": "SOC_DMA2D_SUPPORTED", + "help": "Place 2D-DMA all operation functions, including control functions (e.g. start/stop/append/reset) and setter\nfunctions (e.g. connect/strategy/callback registration) into IRAM, so that these functions can be IRAM-safe\nand able to be called in the other IRAM interrupt context. It also helps optimizing the performance.", + "id": "DMA2D_OPERATION_FUNC_IN_IRAM", + "name": "DMA2D_OPERATION_FUNC_IN_IRAM", + "range": null, + "title": "Place 2D-DMA operation functions into IRAM", + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_DMA2D_SUPPORTED", + "help": "This will ensure the 2D-DMA interrupt handler is IRAM-Safe, allow to avoid flash\ncache misses, and also be able to run whilst the cache is disabled.\n(e.g. SPI Flash write).", + "id": "DMA2D_ISR_IRAM_SAFE", + "name": "DMA2D_ISR_IRAM_SAFE", + "range": null, + "title": "2D-DMA ISR IRAM-Safe", + "type": "bool" + } + ], + "depends_on": "SOC_DMA2D_SUPPORTED", + "id": "component-config-hardware-settings-2d-dma-configurations", + "title": "2D-DMA Configurations", + "type": "menu" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "XTAL_FREQ_40", + "name": "XTAL_FREQ_40", + "range": null, + "title": "40 MHz", + "type": "bool" + } + ], + "depends_on": null, + "help": "This option selects the operating frequency of the XTAL (crystal) clock used to drive the ESP target.\nThe selected value MUST reflect the frequency of the given hardware.", + "id": "component-config-hardware-settings-main-xtal-config-main-xtal-frequency", + "name": "XTAL_FREQ", + "title": "Main XTAL frequency", + "type": "choice" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "XTAL_FREQ", + "name": "XTAL_FREQ", + "range": null, + "title": null, + "type": "int" + } + ], + "depends_on": null, + "id": "component-config-hardware-settings-main-xtal-config", + "title": "Main XTAL Config", + "type": "menu" + }, + { + "children": [], + "depends_on": null, + "help": "This option is only used for new chip bringup, when\nclock support isn't done yet. So with this option,\nwe use xtal on FPGA as the clock source.", + "id": "ESP_BRINGUP_BYPASS_CPU_CLK_SETTING", + "name": "ESP_BRINGUP_BYPASS_CPU_CLK_SETTING", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "This option is only used for new chip bringup, when\nRNG isn't done yet. So with this option, we use 0x5A\nto fill the random buffers", + "id": "ESP_BRINGUP_BYPASS_RANDOM_SETTING", + "name": "ESP_BRINGUP_BYPASS_RANDOM_SETTING", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "ESP_SPI_BUS_LOCK_ISR_FUNCS_IN_IRAM", + "name": "ESP_SPI_BUS_LOCK_ISR_FUNCS_IN_IRAM", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "ESP_SPI_BUS_LOCK_FUNCS_IN_IRAM", + "name": "ESP_SPI_BUS_LOCK_FUNCS_IN_IRAM", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Due to the poor low-temperature characteristics of\nRC32K (it cannot operate below -40 degrees Celsius),\nplease avoid using it whenever possible", + "id": "ESP_CLK_RC32K_NOT_TO_USE", + "name": "ESP_CLK_RC32K_NOT_TO_USE", + "range": null, + "title": null, + "type": "bool" + } + ], + "depends_on": null, + "id": "component-config-hardware-settings", + "title": "Hardware Settings", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": null, + "help": "whether to enable the debug log message for LCD driver.\nNote that, this option only controls the LCD driver log, won't affect other drivers.", + "id": "LCD_ENABLE_DEBUG_LOG", + "name": "LCD_ENABLE_DEBUG_LOG", + "range": null, + "title": "Enable debug log", + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_LCD_RGB_SUPPORTED", + "help": "Ensure the LCD interrupt is IRAM-Safe by allowing the interrupt handler to be\nexecutable when the cache is disabled (e.g. SPI Flash write).\nIf you want the LCD driver to keep flushing the screen even when cache ops disabled,\nyou can enable this option. Note, this will also increase the IRAM usage.", + "id": "LCD_RGB_ISR_IRAM_SAFE", + "name": "LCD_RGB_ISR_IRAM_SAFE", + "range": null, + "title": "RGB LCD ISR IRAM-Safe", + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_LCD_RGB_SUPPORTED", + "help": "Reset the GDMA channel every VBlank to stop permanent desyncs from happening.\nOnly need to enable it when in your application, the DMA can't deliver data\nas fast as the LCD consumes it.", + "id": "LCD_RGB_RESTART_IN_VSYNC", + "name": "LCD_RGB_RESTART_IN_VSYNC", + "range": null, + "title": "Always restart RGB LCD transmission in VSYNC", + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_MIPI_DSI_SUPPORTED", + "help": "Ensure the LCD interrupt is IRAM-Safe by allowing the interrupt handler to be\nexecutable when the cache is disabled (e.g. SPI Flash write).\nIf you want the LCD driver to keep flushing the screen even when cache ops disabled,\nyou can enable this option. Note, this will also increase the IRAM usage.", + "id": "LCD_DSI_ISR_IRAM_SAFE", + "name": "LCD_DSI_ISR_IRAM_SAFE", + "range": null, + "title": "DSI LCD ISR IRAM-Safe", + "type": "bool" + } + ], + "depends_on": null, + "id": "component-config-esp-driver-lcd-controller-configurations", + "title": "ESP-Driver:LCD Controller Configurations", + "type": "menu" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "ESP_MM_CACHE_MSYNC_C2M_CHUNKED_OPS", + "help": "Max len in bytes per C2M chunk, operations with size over the max len will be\nsliced into multiple chunks.", + "id": "ESP_MM_CACHE_MSYNC_C2M_CHUNKED_OPS_MAX_LEN", + "name": "ESP_MM_CACHE_MSYNC_C2M_CHUNKED_OPS_MAX_LEN", + "range": null, + "title": "Max len in bytes per C2M chunk", + "type": "hex" + } + ], + "depends_on": "SOC_CACHE_WRITEBACK_SUPPORTED", + "help": "`esp_cache_msync` C2M direction takes critical sections, which means during\nthe operation, the interrupts are disabled. Whereas Cache writebacks for\nlarge buffers could be especially time intensive, and might cause interrupts\nto be disabled for a significant amount of time.\n\nSometimes you want other ISRs to be responded during this C2M process.\nThis option is to slice one C2M operation into multiple chunks,\nwith CONFIG_ESP_MM_CACHE_MSYNC_C2M_CHUNKED_OPS_MAX_LEN max len. This will give you\na breath during the C2M process as sometimes the C2M process is quite long.\n\nNote if the buffer processed by the `esp_cache_msync` (C2M sliced) is interrupted by an ISR,\nand this ISR also accesses this buffer, this may lead to data coherence issue.", + "id": "ESP_MM_CACHE_MSYNC_C2M_CHUNKED_OPS", + "name": "ESP_MM_CACHE_MSYNC_C2M_CHUNKED_OPS", + "range": null, + "title": "Enable esp_cache_msync C2M chunked operation", + "type": "bool" + } + ], + "depends_on": null, + "id": "component-config-esp-mm-memory-management-configurations", + "title": "ESP-MM: Memory Management Configurations", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": null, + "help": "The value of 0 indicates the IP lost timer is disabled, otherwise the timer is enabled.\n\nThe IP address may be lost because of some reasons, e.g. when the station disconnects\nfrom soft-AP, or when DHCP IP renew fails etc. If the IP lost timer is enabled, it will\nbe started every time the IP is lost. Event SYSTEM_EVENT_STA_LOST_IP will be raised if\nthe timer expires. The IP lost timer is stopped if the station get the IP again before\nthe timer expires.", + "id": "ESP_NETIF_IP_LOST_TIMER_INTERVAL", + "name": "ESP_NETIF_IP_LOST_TIMER_INTERVAL", + "range": [ + 0, + 65535 + ], + "title": "IP Address lost timer interval (seconds)", + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": "No implementation of ESP-NETIF functions is provided.\nThis option is used for adding a custom TCP/IP stack and defining related\nesp_netif functionality", + "id": "ESP_NETIF_PROVIDE_CUSTOM_IMPLEMENTATION", + "name": "ESP_NETIF_PROVIDE_CUSTOM_IMPLEMENTATION", + "range": null, + "title": "Use only ESP-NETIF headers", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "LWIP_ENABLE && ", + "help": "lwIP is a small independent implementation of the TCP/IP protocol suite.", + "id": "ESP_NETIF_TCPIP_LWIP", + "name": "ESP_NETIF_TCPIP_LWIP", + "range": null, + "title": "LwIP", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": "Dummy implementation of esp-netif functionality which connects driver transmit\nto receive function. This option is for testing purpose only", + "id": "ESP_NETIF_LOOPBACK", + "name": "ESP_NETIF_LOOPBACK", + "range": null, + "title": "Loopback", + "type": "bool" + } + ], + "depends_on": "!ESP_NETIF_PROVIDE_CUSTOM_IMPLEMENTATION", + "help": "Choose the TCP/IP Stack to work, for example, LwIP, uIP, etc.", + "id": "component-config-esp-netif-adapter-tcp-ip-stack-library", + "name": "ESP_NETIF_USE_TCPIP_STACK_LIB", + "title": "TCP/IP Stack Library", + "type": "choice" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "ESP_NETIF_USES_TCPIP_WITH_BSD_API", + "name": "ESP_NETIF_USES_TCPIP_WITH_BSD_API", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Enable if esp_netif_transmit() and esp_netif_receive() should generate events. This can be useful\nto blink data traffic indication lights.", + "id": "ESP_NETIF_REPORT_DATA_TRAFFIC", + "name": "ESP_NETIF_REPORT_DATA_TRAFFIC", + "range": null, + "title": "Report data traffic via events", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Enable if esp_netif_receive() should return error code. This is useful to inform upper layers\nthat packet input to TCP/IP stack failed, so the upper layers could implement flow control.\nThis option is disabled by default due to backward compatibility and will be enabled in v6.0 (IDF-7194)", + "id": "ESP_NETIF_RECEIVE_REPORT_ERRORS", + "name": "ESP_NETIF_RECEIVE_REPORT_ERRORS", + "range": null, + "title": "Use esp_err_t to report errors from esp_netif_receive", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "ESP_NETIF_L2_TAP", + "help": "Maximum number of opened File descriptors (FD's) associated with ESP TAP device. ESP TAP FD's take up\na certain amount of memory, and allowing fewer FD's to be opened at the same time conserves memory.", + "id": "ESP_NETIF_L2_TAP_MAX_FDS", + "name": "ESP_NETIF_L2_TAP_MAX_FDS", + "range": null, + "title": "Maximum number of opened L2 TAP File descriptors", + "type": "int" + }, + { + "children": [], + "depends_on": "ESP_NETIF_L2_TAP", + "help": "Maximum number of frames queued in opened File descriptor. Once the queue is full, the newly arriving\nframes are dropped until the queue has enough room to accept incoming traffic (Tail Drop queue\nmanagement).", + "id": "ESP_NETIF_L2_TAP_RX_QUEUE_SIZE", + "name": "ESP_NETIF_L2_TAP_RX_QUEUE_SIZE", + "range": null, + "title": "Size of L2 TAP Rx queue", + "type": "int" + } + ], + "depends_on": null, + "help": "A user program can read/write link layer (L2) frames from/to ESP TAP device.\nThe ESP TAP device can be currently associated only with Ethernet physical interfaces.", + "id": "ESP_NETIF_L2_TAP", + "name": "ESP_NETIF_L2_TAP", + "range": null, + "title": "Enable netif L2 TAP support", + "type": "bool" + }, + { + "children": [], + "depends_on": "ESP_NETIF_TCPIP_LWIP", + "help": "Enable LwIP IEEE 802.1D bridge support in ESP-NETIF. Note that \"Number of clients store data in netif\"\n(LWIP_NUM_NETIF_CLIENT_DATA) option needs to be properly configured to be LwIP bridge available!", + "id": "ESP_NETIF_BRIDGE_EN", + "name": "ESP_NETIF_BRIDGE_EN", + "range": null, + "title": "Enable LwIP IEEE 802.1D bridge", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Enable this option to use the DNS server which belongs to the selected default network interface.\nThis feature collects DNS server and netif information from LWIP core modules.\nWhenever a new default netif is selected, global DNS servers in LWIP are updated with the netif\nrelated servers.", + "id": "ESP_NETIF_SET_DNS_PER_DEFAULT_NETIF", + "name": "ESP_NETIF_SET_DNS_PER_DEFAULT_NETIF", + "range": null, + "title": "Enable DNS server per interface", + "type": "bool" + } + ], + "depends_on": null, + "id": "component-config-esp-netif-adapter", + "title": "ESP NETIF Adapter", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": "IDF_TARGET_LINUX", + "help": "This option enables gathering host test statistics and SPI flash wear levelling simulation.", + "id": "ESP_PARTITION_ENABLE_STATS", + "name": "ESP_PARTITION_ENABLE_STATS", + "range": null, + "title": "Host test statistics enabled", + "type": "bool" + }, + { + "children": [], + "depends_on": "IDF_TARGET_LINUX", + "help": "This option controls whether the partition implementation checks\nif the flash is erased before writing to it.\nThis is necessary for SPIFFS, which expects to be able to write without erasing first.", + "id": "ESP_PARTITION_ERASE_CHECK", + "name": "ESP_PARTITION_ERASE_CHECK", + "range": null, + "title": "Check if flash is erased before writing", + "type": "bool" + } + ], + "depends_on": null, + "id": "component-config-partition-api-configuration", + "title": "Partition API Configuration", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": null, + "help": null, + "id": "ESP_PHY_ENABLED", + "name": "ESP_PHY_ENABLED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": "ESP_PHY_ENABLED", + "help": "If this option is enabled, NVS will be initialized and calibration data will be loaded from there.\nPHY calibration will be skipped on deep sleep wakeup. If calibration data is not found, full\ncalibration will be performed and stored in NVS. Normally, only partial calibration will be performed.\nIf this option is disabled, full calibration will be performed.\n\nIf it's easy that your board calibrate bad data, choose 'n'.\nTwo cases for example, you should choose 'n':\n1.If your board is easy to be booted up with antenna disconnected.\n2.Because of your board design, each time when you do calibration, the result are too unstable.\nIf unsure, choose 'y'.", + "id": "ESP_PHY_CALIBRATION_AND_DATA_STORAGE", + "name": "ESP_PHY_CALIBRATION_AND_DATA_STORAGE", + "range": null, + "title": "Store phy calibration data in NVS", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "ESP_PHY_INIT_DATA_IN_PARTITION && ESP_PHY_ENABLED", + "help": "If enabled, PHY init data will be restored to default if\nit cannot be verified successfully to avoid endless bootloops.\n\nIf unsure, choose 'n'.", + "id": "ESP_PHY_DEFAULT_INIT_IF_INVALID", + "name": "ESP_PHY_DEFAULT_INIT_IF_INVALID", + "range": null, + "title": "Reset default PHY init data if invalid", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "ESP_PHY_MULTIPLE_INIT_DATA_BIN && ESP_PHY_INIT_DATA_IN_PARTITION && ESP_PHY_ENABLED", + "help": "If enabled, multiple phy init data bin will embedded into app bin\nIf not enabled, multiple phy init data bin will still leave alone, and need to be flashed by users.", + "id": "ESP_PHY_MULTIPLE_INIT_DATA_BIN_EMBED", + "name": "ESP_PHY_MULTIPLE_INIT_DATA_BIN_EMBED", + "range": null, + "title": "Support embedded multiple phy init data bin to app bin", + "type": "bool" + }, + { + "children": [], + "depends_on": "ESP_PHY_MULTIPLE_INIT_DATA_BIN && ESP_PHY_INIT_DATA_IN_PARTITION && ESP_PHY_ENABLED", + "help": "If enabled, when an error occurs while the PHY init data is updated,\nthe program will terminate and restart.\nIf not enabled, the PHY init data will not be updated when an error occurs.", + "id": "ESP_PHY_INIT_DATA_ERROR", + "name": "ESP_PHY_INIT_DATA_ERROR", + "range": null, + "title": "Terminate operation when PHY init data error", + "type": "bool" + } + ], + "depends_on": "ESP_PHY_INIT_DATA_IN_PARTITION && ESP_PHY_INIT_DATA_IN_PARTITION && ESP_PHY_ENABLED", + "help": "If enabled, the corresponding PHY init data type can be automatically switched\naccording to the country code. China's PHY init data bin is used by default.\nCan be modified by country information in API esp_wifi_set_country().\nThe priority of switching the PHY init data type is:\n1. Country configured by API esp_wifi_set_country()\nand the parameter policy is WIFI_COUNTRY_POLICY_MANUAL.\n2. Country notified by the connected AP.\n3. Country configured by API esp_wifi_set_country()\nand the parameter policy is WIFI_COUNTRY_POLICY_AUTO.", + "id": "ESP_PHY_MULTIPLE_INIT_DATA_BIN", + "name": "ESP_PHY_MULTIPLE_INIT_DATA_BIN", + "range": null, + "title": "Support multiple PHY init data bin", + "type": "bool" + } + ], + "depends_on": "SOC_WIFI_SUPPORTED && ESP_PHY_ENABLED", + "help": "If enabled, PHY init data will be loaded from a partition.\nWhen using a custom partition table, make sure that PHY data\npartition is included (type: 'data', subtype: 'phy').\nWith default partition tables, this is done automatically.\nIf PHY init data is stored in a partition, it has to be flashed there,\notherwise runtime error will occur.\n\nIf this option is not enabled, PHY init data will be embedded\ninto the application binary.\n\nIf unsure, choose 'n'.", + "id": "ESP_PHY_INIT_DATA_IN_PARTITION", + "is_menuconfig": true, + "name": "ESP_PHY_INIT_DATA_IN_PARTITION", + "range": null, + "title": "Use a partition to store PHY init data", + "type": "menu" + }, + { + "children": [], + "depends_on": "ESP_PHY_ENABLED", + "help": "Set maximum transmit power for WiFi radio. Actual transmit power for high\ndata rates may be lower than this setting.", + "id": "ESP_PHY_MAX_WIFI_TX_POWER", + "name": "ESP_PHY_MAX_WIFI_TX_POWER", + "range": [ + 10, + 20 + ], + "title": "Max WiFi TX power (dBm)", + "type": "int" + }, + { + "children": [], + "depends_on": "ESP_PHY_ENABLED", + "help": null, + "id": "ESP_PHY_MAX_TX_POWER", + "name": "ESP_PHY_MAX_TX_POWER", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": "SOC_PM_SUPPORT_MAC_BB_PD && FREERTOS_USE_TICKLESS_IDLE && ESP_PHY_ENABLED", + "help": "If enabled, the MAC and baseband of Wi-Fi and Bluetooth will be powered\ndown when PHY is disabled. Enabling this setting reduces power consumption\nby a small amount but increases RAM use by approximately 4 KB(Wi-Fi only),\n2 KB(Bluetooth only) or 5.3 KB(Wi-Fi + Bluetooth).", + "id": "ESP_PHY_MAC_BB_PD", + "name": "ESP_PHY_MAC_BB_PD", + "range": null, + "title": "Power down MAC and baseband of Wi-Fi and Bluetooth when PHY is disabled", + "type": "bool" + }, + { + "children": [], + "depends_on": "ESP_BROWNOUT_DET && ESP_PHY_ENABLED", + "help": "When brownout reset occurs, reduce PHY TX power to keep the code running.", + "id": "ESP_PHY_REDUCE_TX_POWER", + "name": "ESP_PHY_REDUCE_TX_POWER", + "range": null, + "title": "Reduce PHY TX power when brownout reset", + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_WIFI_PHY_NEEDS_USB_WORKAROUND && ESP_PHY_ENABLED", + "help": "On some ESP targets, the USB PHY can interfere with WiFi thus lowering WiFi performance.\nAs a result, on those affected ESP targets, the ESP PHY library's initialization will automatically\ndisable the USB PHY to get best WiFi performance.\nThis option controls whether or not the ESP PHY library will keep the USB PHY enabled on\ninitialization.\n\nNote: This option can be disabled to increase WiFi performance. However, disabling this option will\nalso mean that the USB PHY cannot be used while WiFi is enabled.", + "id": "ESP_PHY_ENABLE_USB", + "name": "ESP_PHY_ENABLE_USB", + "range": null, + "title": "Keep the USB PHY enabled when initializing WiFi", + "type": "bool" + }, + { + "children": [], + "depends_on": "ESP_PHY_ENABLED", + "help": "If enabled, you can use RF certification test APIs.", + "id": "ESP_PHY_ENABLE_CERT_TEST", + "name": "ESP_PHY_ENABLE_CERT_TEST", + "range": null, + "title": "Enable RF certification test functions", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "ESP_PHY_RF_CAL_PARTIAL", + "name": "ESP_PHY_RF_CAL_PARTIAL", + "range": null, + "title": "Calibration partial", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "ESP_PHY_RF_CAL_NONE", + "name": "ESP_PHY_RF_CAL_NONE", + "range": null, + "title": "Calibration none", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "ESP_PHY_RF_CAL_FULL", + "name": "ESP_PHY_RF_CAL_FULL", + "range": null, + "title": "Calibration full", + "type": "bool" + } + ], + "depends_on": "ESP_PHY_ENABLED", + "help": "Select PHY calibration mode. During RF initialization, the partial calibration\nmethod is used by default for RF calibration. Full calibration takes about 100ms\nmore than partial calibration. If boot duration is not critical, it is suggested\nto use the full calibration method. No calibration method is only used when the\ndevice wakes up from deep sleep.", + "id": "component-config-phy-calibration-mode", + "name": "ESP_PHY_CALIBRATION_MODE", + "title": "Calibration mode", + "type": "choice" + }, + { + "children": [], + "depends_on": "ESP_PHY_ENABLED", + "help": null, + "id": "ESP_PHY_CALIBRATION_MODE", + "name": "ESP_PHY_CALIBRATION_MODE", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": "SOC_PHY_IMPROVE_RX_11B && ESP_PHY_ENABLED", + "help": "This is a workaround to improve Wi-Fi receive 11b pkts for some modules using AC-DC power supply with\nhigh interference, enable this option will sacrifice Wi-Fi OFDM receive performance.\nBut to guarantee 11b receive performance serves as a bottom line in this case.", + "id": "ESP_PHY_IMPROVE_RX_11B", + "name": "ESP_PHY_IMPROVE_RX_11B", + "range": null, + "title": "Improve Wi-Fi receive 11b pkts", + "type": "bool" + }, + { + "children": [], + "depends_on": "ESP_PHY_ENABLED", + "help": "If enabled, there will be some logs while pll tracking", + "id": "ESP_PHY_PLL_TRACK_DEBUG", + "name": "ESP_PHY_PLL_TRACK_DEBUG", + "range": null, + "title": "Enable pll track logging", + "type": "bool" + }, + { + "children": [], + "depends_on": "ESP_PHY_ENABLED", + "help": "Select to support record and query phy used time.", + "id": "ESP_PHY_RECORD_USED_TIME", + "name": "ESP_PHY_RECORD_USED_TIME", + "range": null, + "title": "Record PHY used time", + "type": "bool" + } + ], + "depends_on": null, + "id": "component-config-phy", + "title": "PHY", + "type": "menu" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "PM_ENABLE", + "help": "If enabled, startup code configures dynamic frequency scaling.\nMax CPU frequency is set to DEFAULT_CPU_FREQ_MHZ setting,\nmin frequency is set to XTAL frequency.\nIf disabled, DFS will not be active until the application\nconfigures it using esp_pm_configure function.", + "id": "PM_DFS_INIT_AUTO", + "name": "PM_DFS_INIT_AUTO", + "range": null, + "title": "Enable dynamic frequency scaling (DFS) at startup", + "type": "bool" + }, + { + "children": [], + "depends_on": "PM_ENABLE", + "help": "If enabled, esp_pm_* functions will keep track of the amount of time\neach of the power management locks has been held, and esp_pm_dump_locks\nfunction will print this information.\nThis feature can be used to analyze which locks are preventing the chip\nfrom going into a lower power state, and see what time the chip spends\nin each power saving mode. This feature does incur some run-time\noverhead, so should typically be disabled in production builds.", + "id": "PM_PROFILING", + "name": "PM_PROFILING", + "range": null, + "title": "Enable profiling counters for PM locks", + "type": "bool" + }, + { + "children": [], + "depends_on": "PM_ENABLE", + "help": "If enabled, some GPIOs will be used to signal events such as RTOS ticks,\nfrequency switching, entry/exit from idle state. Refer to pm_trace.c\nfile for the list of GPIOs.\nThis feature is intended to be used when analyzing/debugging behavior\nof power management implementation, and should be kept disabled in\napplications.", + "id": "PM_TRACE", + "name": "PM_TRACE", + "range": null, + "title": "Enable debug tracing of PM using GPIOs", + "type": "bool" + } + ], + "depends_on": "(!FREERTOS_SMP && SOC_PM_SUPPORTED) || __DOXYGEN__", + "help": "If enabled, application is compiled with support for power management.\nThis option has run-time overhead (increased interrupt latency,\nlonger time to enter idle state), and it also reduces accuracy of\nRTOS ticks and timers used for timekeeping.\nEnable this option if application uses power management APIs.", + "id": "PM_ENABLE", + "name": "PM_ENABLE", + "range": null, + "title": "Support for power management", + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_LIGHT_SLEEP_SUPPORTED", + "help": "If enabled, about 2.1KB of lightsleep related source code would be in IRAM and chip would sleep\nlonger for 310us at 160MHz CPU frequency most each time.\nThis feature is intended to be used when lower power consumption is needed\nwhile there is enough place in IRAM to place source code.", + "id": "PM_SLP_IRAM_OPT", + "name": "PM_SLP_IRAM_OPT", + "range": null, + "title": "Put lightsleep related codes in internal RAM", + "type": "bool" + }, + { + "children": [], + "depends_on": "FREERTOS_USE_TICKLESS_IDLE", + "help": "If enabled, about 180Bytes of RTOS_IDLE related source code would be in IRAM and chip would sleep\nlonger for 20us at 160MHz CPU frequency most each time.\nThis feature is intended to be used when lower power consumption is needed\nwhile there is enough place in IRAM to place source code.", + "id": "PM_RTOS_IDLE_OPT", + "name": "PM_RTOS_IDLE_OPT", + "range": null, + "title": "Put RTOS IDLE related codes in internal RAM", + "type": "bool" + }, + { + "children": [], + "depends_on": "FREERTOS_USE_TICKLESS_IDLE", + "help": "This feature is intended to disable all GPIO pins at automantic sleep to get a lower power mode.\nIf enabled, chips will disable all GPIO pins at automantic sleep to reduce about 200~300 uA current.\nIf you want to specifically use some pins normally as chip wakes when chip sleeps,\nyou can call 'gpio_sleep_sel_dis' to disable this feature on those pins.\nYou can also keep this feature on and call 'gpio_sleep_set_direction' and 'gpio_sleep_set_pull_mode'\nto have a different GPIO configuration at sleep.\nWarning: If you want to enable this option on ESP32, you should enable `GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL`\nat first, otherwise you will not be able to switch pullup/pulldown mode.", + "id": "PM_SLP_DISABLE_GPIO", + "name": "PM_SLP_DISABLE_GPIO", + "range": null, + "title": "Disable all GPIO when chip at sleep", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "PM_SLP_DEFAULT_PARAMS_OPT", + "name": "PM_SLP_DEFAULT_PARAMS_OPT", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": "PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP || (SOC_CPU_IN_TOP_DOMAIN && PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP)", + "help": "This option is invisible to users, and it is only used for ci testing,\nenabling it in the application will increase the sleep and wake-up time overhead", + "id": "PM_CHECK_SLEEP_RETENTION_FRAME", + "name": "PM_CHECK_SLEEP_RETENTION_FRAME", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": "PM_ENABLE", + "help": "The value of this option determines the calibration interval of the RTC_FAST/SLOW clock during sleep when\npower management is enabled. When it is configured as N, the RTC_FAST/SLOW clock will be calibrated\nevery N times of lightsleep.\nDecreasing this value will increase the time the chip is in the active state, thereby increasing the\naverage power consumption of the chip.\nIncreasing this value can reduce the average power consumption, but when the external environment changes\ndrastically and the chip RTC_FAST/SLOW oscillator frequency drifts, it may cause system instability.", + "id": "PM_LIGHTSLEEP_RTC_OSC_CAL_INTERVAL", + "name": "PM_LIGHTSLEEP_RTC_OSC_CAL_INTERVAL", + "range": null, + "title": "Calibrate the RTC_FAST/SLOW clock every N times of light sleep", + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "IDF_TARGET_ESP32S3 && PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP", + "help": "Cache tag memory and CPU both belong to the CPU power domain.\nESP chips supports saving and restoring Cache tag memory before and after sleep,\nthis feature supports accesses to the external memory that was cached before sleep still\nbe cached when the CPU wakes up from a powerdowned CPU lightsleep.\nThis option controls the restore method for Cache tag memory in lightsleep.\nIf this option is enabled, the I/D-cache tag memory will be backuped to the internal RAM\nbefore sleep and restored upon wakeup.\nDepending on the the cache configuration, if this option is enabled,\nit will consume up to 9 KB of internal RAM.\nIf this option is disabled, all cached data won't be kept after sleep,\nthe DCache will be writeback before sleep and invalid all cached data after sleep,\nall accesses to external memory(Flash/PSRAM) will be cache missed after waking up,\nresulting in performance degradation due to increased memory accesses latency.", + "id": "PM_RESTORE_CACHE_TAGMEM_AFTER_LIGHT_SLEEP", + "name": "PM_RESTORE_CACHE_TAGMEM_AFTER_LIGHT_SLEEP", + "range": null, + "title": "Restore I/D-cache tag memory after power down CPU light sleep", + "type": "bool" + } + ], + "depends_on": "SOC_PM_SUPPORT_CPU_PD", + "help": "If enabled, the CPU will be powered down in light sleep,\nESP chips supports saving and restoring CPU's running context before and after light sleep,\nthe feature provides applications with seamless CPU powerdowned lightsleep without user awareness.\nBut this will takes up some internal memory.\nOn esp32c3 soc, enabling this option will consume 1.68 KB of internal RAM\nand will reduce sleep current consumption by about 100 uA.\nOn esp32s3 soc, enabling this option will consume 8.58 KB of internal RAM\nand will reduce sleep current consumption by about 650 uA.", + "id": "PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP", + "name": "PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP", + "range": null, + "title": "Power down CPU in light sleep", + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_PM_SUPPORT_TOP_PD && SOC_PAU_SUPPORTED", + "help": "If enabled, digital peripherals will be powered down in light sleep, it will reduce sleep\ncurrent consumption by about 100 uA. Chip will save/restore register context at sleep/wake\ntime to keep the system running. Enabling this option will increase static RAM and heap usage,\nthe actual cost depends on the peripherals you have initialized. In order to save/restore the\ncontext of the necessary hardware for FreeRTOS to run, it will need at least 4.55 KB free heap\nat sleep time. Otherwise sleep will not power down the peripherals.\n\nNote1: Please use this option with caution, the current IDF does not support the retention of\nall peripherals. When the digital peripherals are powered off and a sleep and wake-up is completed,\nthe peripherals that have not saved the running context are equivalent to performing a reset.\n!!! Please confirm the peripherals used in your application and their sleep retention support status\nbefore enabling this option, peripherals sleep retention driver support status is tracked in\npower_management.rst\n\nNote2: When this option is enabled simultaneously with FREERTOS_USE_TICKLESS_IDLE, since the UART will\nbe powered down, the uart FIFO will be flushed before sleep to avoid data loss, however, this has the\npotential to block the sleep process and cause the wakeup time to be skipped, which will cause the tick\nof freertos to not be compensated correctly when returning from sleep and cause the system to crash.\nTo avoid this, you can increase FREERTOS_IDLE_TIME_BEFORE_SLEEP threshold in menuconfig.", + "id": "PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP", + "name": "PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP", + "range": null, + "title": "Power down Digital Peripheral in light sleep (EXPERIMENTAL)", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "PM_UPDATE_CCOMPARE_HLI_WORKAROUND", + "name": "PM_UPDATE_CCOMPARE_HLI_WORKAROUND", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": "FREERTOS_USE_TICKLESS_IDLE", + "help": "If enabled, it allows user to register entry and exit callbacks which are called before and after\nentering auto light sleep.\n\nNOTE: These callbacks are executed from the IDLE task context hence you cannot have any blocking calls\nin your callbacks.\n\nNOTE: Enabling these callbacks may change sleep duration calculations based on time spent in callback and\nhence it is highly recommended to keep them as short as possible", + "id": "PM_LIGHT_SLEEP_CALLBACKS", + "name": "PM_LIGHT_SLEEP_CALLBACKS", + "range": null, + "title": "Enable registration of pm light sleep callbacks", + "type": "bool" + } + ], + "depends_on": null, + "id": "component-config-power-management", + "title": "Power Management", + "type": "menu" + }, + { + "children": [], + "depends_on": "!APP_BUILD_TYPE_PURE_RAM_APP", + "id": "component-config-esp-psram", + "title": "ESP PSRAM", + "type": "menu" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "RINGBUF_PLACE_FUNCTIONS_INTO_FLASH", + "help": "Place ISR ringbuf functions (like xRingbufferSendFromISR/xRingbufferReceiveFromISR) into flash.\nThis frees up IRAM, but the functions can no longer be called when the cache is disabled\nor from an IRAM interrupt context.\n\nThis option is not compatible with ESP-IDF drivers which are configured to\nrun the ISR from an IRAM context, e.g. CONFIG_UART_ISR_IN_IRAM.", + "id": "RINGBUF_PLACE_ISR_FUNCTIONS_INTO_FLASH", + "name": "RINGBUF_PLACE_ISR_FUNCTIONS_INTO_FLASH", + "range": null, + "title": "Place ISR ringbuf functions into flash", + "type": "bool" + } + ], + "depends_on": null, + "help": "Place non-ISR ringbuf functions (like xRingbufferCreate/xRingbufferSend) into flash.\nThis frees up IRAM, but the functions can no longer be called when the cache is disabled.", + "id": "RINGBUF_PLACE_FUNCTIONS_INTO_FLASH", + "name": "RINGBUF_PLACE_FUNCTIONS_INTO_FLASH", + "range": null, + "title": "Place non-ISR ringbuf functions into flash", + "type": "bool" + } + ], + "depends_on": null, + "id": "component-config-esp-ringbuf", + "title": "ESP Ringbuf", + "type": "menu" + }, + { + "children": [ + { + "children": [ + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "ESP_CRYPTO_DPA_PROTECTION_LEVEL_LOW", + "name": "ESP_CRYPTO_DPA_PROTECTION_LEVEL_LOW", + "range": null, + "title": "Security level low", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "ESP_CRYPTO_DPA_PROTECTION_LEVEL_MEDIUM", + "name": "ESP_CRYPTO_DPA_PROTECTION_LEVEL_MEDIUM", + "range": null, + "title": "Security level medium", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "ESP_CRYPTO_DPA_PROTECTION_LEVEL_HIGH", + "name": "ESP_CRYPTO_DPA_PROTECTION_LEVEL_HIGH", + "range": null, + "title": "Security level high", + "type": "bool" + } + ], + "depends_on": "ESP_CRYPTO_DPA_PROTECTION_AT_STARTUP && SOC_CRYPTO_DPA_PROTECTION_SUPPORTED", + "help": "Configure the DPA protection security level", + "id": "component-config-esp-security-specific-crypto-dpa-protection-enable-crypto-dpa-protection-at-startup-dpa-protection-level", + "name": "ESP_CRYPTO_DPA_PROTECTION_LEVEL", + "title": "DPA protection level", + "type": "choice" + } + ], + "depends_on": "SOC_CRYPTO_DPA_PROTECTION_SUPPORTED", + "help": "This config controls the DPA (Differential Power Analysis) protection\nknob for the crypto peripherals. DPA protection dynamically adjusts\nclock frequency of the crypto peripheral. DPA protection helps to make it\ndifficult to perform SCA attacks on the crypto peripherals. However,\nthere is also associated performance impact based on the security level\nset. Please refer to the TRM for more details.", + "id": "ESP_CRYPTO_DPA_PROTECTION_AT_STARTUP", + "name": "ESP_CRYPTO_DPA_PROTECTION_AT_STARTUP", + "range": null, + "title": "Enable crypto DPA protection at startup", + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_CRYPTO_DPA_PROTECTION_SUPPORTED", + "help": null, + "id": "ESP_CRYPTO_DPA_PROTECTION_LEVEL", + "name": "ESP_CRYPTO_DPA_PROTECTION_LEVEL", + "range": null, + "title": null, + "type": "int" + } + ], + "depends_on": "SOC_CRYPTO_DPA_PROTECTION_SUPPORTED", + "id": "component-config-esp-security-specific-crypto-dpa-protection", + "title": "Crypto DPA Protection", + "type": "menu" + }, + { + "children": [], + "depends_on": "SOC_ECC_CONSTANT_TIME_POINT_MUL", + "help": "If enabled, the app startup code will burn the ECC_FORCE_CONST_TIME efuse bit to force the\nECC peripheral to always perform constant time point multiplication operations,\nirrespective of the ECC_MULT_SECURITY_MODE status bit that is present in the ECC_MULT_CONF_REG\nregister. By default, ESP-IDF configures the ECC peripheral to perform constant time point\nmultiplication operations, so enabling this config would provide security enhancement only in\nthe cases when trusted boot is not enabled and the attacker tries carrying out non-constant\ntime point multiplication operations by changing the default ESP-IDF configurations.\nPerforming constant time operations protect the ECC multiplication operations from timing attacks.", + "id": "ESP_CRYPTO_FORCE_ECC_CONSTANT_TIME_POINT_MUL", + "name": "ESP_CRYPTO_FORCE_ECC_CONSTANT_TIME_POINT_MUL", + "range": null, + "title": "Forcefully enable ECC constant time point multiplication operations", + "type": "bool" + } + ], + "depends_on": null, + "id": "component-config-esp-security-specific", + "title": "ESP Security Specific", + "type": "menu" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "IDF_ENV_FPGA && ", + "help": null, + "id": "ESP_DEFAULT_CPU_FREQ_MHZ_40", + "name": "ESP_DEFAULT_CPU_FREQ_MHZ_40", + "range": null, + "title": "40 MHz", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "ESP_DEFAULT_CPU_FREQ_MHZ_80", + "name": "ESP_DEFAULT_CPU_FREQ_MHZ_80", + "range": null, + "title": "80 MHz", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "ESP_DEFAULT_CPU_FREQ_MHZ_160", + "name": "ESP_DEFAULT_CPU_FREQ_MHZ_160", + "range": null, + "title": "160 MHz", + "type": "bool" + } + ], + "depends_on": null, + "help": "CPU frequency to be set on application startup.", + "id": "component-config-esp-system-settings-cpu-frequency", + "name": "ESP_DEFAULT_CPU_FREQ_MHZ", + "title": "CPU frequency", + "type": "choice" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "ESP_DEFAULT_CPU_FREQ_MHZ", + "name": "ESP_DEFAULT_CPU_FREQ_MHZ", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "!ESP_SYSTEM_GDBSTUB_RUNTIME && ", + "help": "Outputs the relevant registers over the serial port and halt the\nprocessor. Needs a manual reset to restart.", + "id": "ESP_SYSTEM_PANIC_PRINT_HALT", + "name": "ESP_SYSTEM_PANIC_PRINT_HALT", + "range": null, + "title": "Print registers and halt", + "type": "bool" + }, + { + "children": [], + "depends_on": "!ESP_SYSTEM_GDBSTUB_RUNTIME && ", + "help": "Outputs the relevant registers over the serial port and immediately\nreset the processor.", + "id": "ESP_SYSTEM_PANIC_PRINT_REBOOT", + "name": "ESP_SYSTEM_PANIC_PRINT_REBOOT", + "range": null, + "title": "Print registers and reboot", + "type": "bool" + }, + { + "children": [], + "depends_on": "!ESP_SYSTEM_GDBSTUB_RUNTIME && ", + "help": "Just resets the processor without outputting anything", + "id": "ESP_SYSTEM_PANIC_SILENT_REBOOT", + "name": "ESP_SYSTEM_PANIC_SILENT_REBOOT", + "range": null, + "title": "Silent reboot", + "type": "bool" + }, + { + "children": [], + "depends_on": "ESP_GDBSTUB_ENABLED && ", + "help": "Invoke gdbstub on the serial port, allowing for gdb to attach to it to do a postmortem\nof the crash.", + "id": "ESP_SYSTEM_PANIC_GDBSTUB", + "name": "ESP_SYSTEM_PANIC_GDBSTUB", + "range": null, + "title": "GDBStub on panic", + "type": "bool" + } + ], + "depends_on": null, + "help": "If FreeRTOS detects unexpected behaviour or an unhandled exception, the panic handler is\ninvoked. Configure the panic handler's action here.", + "id": "component-config-esp-system-settings-panic-handler-behaviour", + "name": "ESP_SYSTEM_PANIC", + "title": "Panic handler behaviour", + "type": "choice" + }, + { + "children": [], + "depends_on": "ESP_SYSTEM_PANIC_PRINT_REBOOT", + "help": "After the panic handler executes, you can specify a number of seconds to\nwait before the device reboots.", + "id": "ESP_SYSTEM_PANIC_REBOOT_DELAY_SECONDS", + "name": "ESP_SYSTEM_PANIC_REBOOT_DELAY_SECONDS", + "range": [ + 0, + 99 + ], + "title": "Panic reboot delay (Seconds)", + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": "Only initialize and use the main core.", + "id": "ESP_SYSTEM_SINGLE_CORE_MODE", + "name": "ESP_SYSTEM_SINGLE_CORE_MODE", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "ESP_SYSTEM_RTC_EXT_XTAL", + "name": "ESP_SYSTEM_RTC_EXT_XTAL", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "ESP_SYSTEM_RTC_EXT_OSC", + "name": "ESP_SYSTEM_RTC_EXT_OSC", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": "ESP_SYSTEM_RTC_EXT_XTAL", + "help": "To reduce the startup time of an external RTC crystal,\nwe bootstrap it with a 32kHz square wave for a fixed number of cycles.\nSetting 0 will disable bootstrapping (if disabled, the crystal may take\nlonger to start up or fail to oscillate under some conditions).\n\nIf this value is too high, a faulty crystal may initially start and then fail.\nIf this value is too low, an otherwise good crystal may not start.\n\nTo accurately determine if the crystal has started,\nset a larger \"Number of cycles for RTC_SLOW_CLK calibration\" (about 3000).", + "id": "ESP_SYSTEM_RTC_EXT_XTAL_BOOTSTRAP_CYCLES", + "name": "ESP_SYSTEM_RTC_EXT_XTAL_BOOTSTRAP_CYCLES", + "range": null, + "title": "Bootstrap cycles for external 32kHz crystal", + "type": "int" + }, + { + "children": [], + "depends_on": "SOC_RTC_FAST_MEM_SUPPORTED", + "help": null, + "id": "ESP_SYSTEM_RTC_FAST_MEM_AS_HEAP_DEPCHECK", + "name": "ESP_SYSTEM_RTC_FAST_MEM_AS_HEAP_DEPCHECK", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": "ESP_SYSTEM_RTC_FAST_MEM_AS_HEAP_DEPCHECK", + "help": "This config option allows to add RTC fast memory region to system heap with capability\nsimilar to that of DRAM region but without DMA. Speed wise RTC fast memory operates on\nAPB clock and hence does not have much performance impact.", + "id": "ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP", + "name": "ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP", + "range": null, + "title": "Enable RTC fast memory for dynamic allocations", + "type": "bool" + }, + { + "children": [], + "depends_on": "IDF_TARGET_ARCH_RISCV", + "help": "Generate DWARF information for each function of the project. These information will parsed and used to\nperform backtracing when panics occur. Activating this option will activate asynchronous frame unwinding\nand generation of both .eh_frame and .eh_frame_hdr sections, resulting in a bigger binary size (20% to\n100% larger). The main purpose of this option is to be able to have a backtrace parsed and printed by\nthe program itself, regardless of the serial monitor used.\nThis option shall NOT be used for production.", + "id": "ESP_SYSTEM_USE_EH_FRAME", + "name": "ESP_SYSTEM_USE_EH_FRAME", + "range": null, + "title": "Generate and use eh_frame for backtracing", + "type": "bool" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "IDF_TARGET_ARCH_RISCV && SOC_LP_CORE_SUPPORTED && ESP_SYSTEM_PMP_IDRAM_SPLIT", + "help": "If enabled, user can run code available in LP Core image.\n\nWarning: on ESP32-P4 this will also mark the memory area used for BOOTLOADER_RESERVE_RTC_MEM\nas executable. If you consider this a security risk then do not activate this option.", + "id": "ESP_SYSTEM_PMP_LP_CORE_RESERVE_MEM_EXECUTABLE", + "name": "ESP_SYSTEM_PMP_LP_CORE_RESERVE_MEM_EXECUTABLE", + "range": null, + "title": "Make LP core reserved memory executable from HP core", + "type": "bool" + } + ], + "depends_on": "SOC_CPU_IDRAM_SPLIT_USING_PMP", + "help": "If enabled, the CPU watches all the memory access and raises an exception in case\nof any memory violation. This feature automatically splits\nthe SRAM memory, using PMP, into data and instruction segments and sets Read/Execute permissions\nfor the instruction part (below given splitting address) and Read/Write permissions\nfor the data part (above the splitting address). The memory protection is effective\non all access through the IRAM0 and DRAM0 buses.", + "id": "ESP_SYSTEM_PMP_IDRAM_SPLIT", + "name": "ESP_SYSTEM_PMP_IDRAM_SPLIT", + "range": null, + "title": "Enable IRAM/DRAM split protection", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "ESP_SYSTEM_MEMPROT_FEATURE", + "help": "Once locked, memory protection settings cannot be changed anymore.\nThe lock is reset only on the chip startup.", + "id": "ESP_SYSTEM_MEMPROT_FEATURE_LOCK", + "name": "ESP_SYSTEM_MEMPROT_FEATURE_LOCK", + "range": null, + "title": "Lock memory protection settings", + "type": "bool" + } + ], + "depends_on": "SOC_MEMPROT_SUPPORTED", + "help": "If enabled, the permission control module watches all the memory access and fires the panic handler\nif a permission violation is detected. This feature automatically splits\nthe SRAM memory into data and instruction segments and sets Read/Execute permissions\nfor the instruction part (below given splitting address) and Read/Write permissions\nfor the data part (above the splitting address). The memory protection is effective\non all access through the IRAM0 and DRAM0 buses.", + "id": "ESP_SYSTEM_MEMPROT_FEATURE", + "name": "ESP_SYSTEM_MEMPROT_FEATURE", + "range": null, + "title": "Enable memory protection", + "type": "bool" + } + ], + "depends_on": null, + "id": "component-config-esp-system-settings-memory-protection", + "title": "Memory protection", + "type": "menu" + }, + { + "children": [], + "depends_on": null, + "help": "Config system event queue size in different application.", + "id": "ESP_SYSTEM_EVENT_QUEUE_SIZE", + "name": "ESP_SYSTEM_EVENT_QUEUE_SIZE", + "range": null, + "title": "System event queue size", + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": "Config system event task stack size in different application.", + "id": "ESP_SYSTEM_EVENT_TASK_STACK_SIZE", + "name": "ESP_SYSTEM_EVENT_TASK_STACK_SIZE", + "range": null, + "title": "Event loop task stack size", + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": "Configure the \"main task\" stack size. This is the stack of the task\nwhich calls app_main(). If app_main() returns then this task is deleted\nand its stack memory is freed.", + "id": "ESP_MAIN_TASK_STACK_SIZE", + "name": "ESP_MAIN_TASK_STACK_SIZE", + "range": null, + "title": "Main task stack size", + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "ESP_MAIN_TASK_AFFINITY_CPU0", + "name": "ESP_MAIN_TASK_AFFINITY_CPU0", + "range": null, + "title": "CPU0", + "type": "bool" + }, + { + "children": [], + "depends_on": "!FREERTOS_UNICORE && ", + "help": null, + "id": "ESP_MAIN_TASK_AFFINITY_CPU1", + "name": "ESP_MAIN_TASK_AFFINITY_CPU1", + "range": null, + "title": "CPU1", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "ESP_MAIN_TASK_AFFINITY_NO_AFFINITY", + "name": "ESP_MAIN_TASK_AFFINITY_NO_AFFINITY", + "range": null, + "title": "No affinity", + "type": "bool" + } + ], + "depends_on": null, + "help": "Configure the \"main task\" core affinity. This is the used core of the task\nwhich calls app_main(). If app_main() returns then this task is deleted.", + "id": "component-config-esp-system-settings-main-task-core-affinity", + "name": "ESP_MAIN_TASK_AFFINITY", + "title": "Main task core affinity", + "type": "choice" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "ESP_MAIN_TASK_AFFINITY", + "name": "ESP_MAIN_TASK_AFFINITY", + "range": null, + "title": null, + "type": "hex" + }, + { + "children": [], + "depends_on": null, + "help": "Minimal value of size, in bytes, accepted to execute a expression\nwith shared stack.", + "id": "ESP_MINIMAL_SHARED_STACK_SIZE", + "name": "ESP_MINIMAL_SHARED_STACK_SIZE", + "range": null, + "title": "Minimal allowed size for shared stack", + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "ESP_CONSOLE_UART_DEFAULT", + "name": "ESP_CONSOLE_UART_DEFAULT", + "range": null, + "title": "Default: UART0", + "type": "bool" + }, + { + "children": [], + "depends_on": "(IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3) && !TINY_USB && ", + "help": null, + "id": "ESP_CONSOLE_USB_CDC", + "name": "ESP_CONSOLE_USB_CDC", + "range": null, + "title": "USB CDC", + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_USB_SERIAL_JTAG_SUPPORTED && ", + "help": null, + "id": "ESP_CONSOLE_USB_SERIAL_JTAG", + "name": "ESP_CONSOLE_USB_SERIAL_JTAG", + "range": null, + "title": "USB Serial/JTAG Controller", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "ESP_CONSOLE_UART_CUSTOM", + "name": "ESP_CONSOLE_UART_CUSTOM", + "range": null, + "title": "Custom UART", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "ESP_CONSOLE_NONE", + "name": "ESP_CONSOLE_NONE", + "range": null, + "title": "None", + "type": "bool" + } + ], + "depends_on": null, + "help": "Select where to send console output (through stdout and stderr).\n\n- Default is to use UART0 on pre-defined GPIOs.\n- If \"Custom\" is selected, UART0 or UART1 can be chosen,\n and any pins can be selected.\n- If \"None\" is selected, there will be no console output on any UART, except\n for initial output from ROM bootloader. This ROM output can be suppressed by\n GPIO strapping or EFUSE, refer to chip datasheet for details.\n- On chips with USB OTG peripheral, \"USB CDC\" option redirects output to the\n CDC port. This option uses the CDC driver in the chip ROM.\n This option is incompatible with TinyUSB stack.\n- On chips with an USB serial/JTAG debug controller, selecting the option\n for that redirects output to the CDC/ACM (serial port emulation) component\n of that device.", + "id": "component-config-esp-system-settings-channel-for-console-output", + "name": "ESP_CONSOLE_UART", + "title": "Channel for console output", + "type": "choice" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "ESP_CONSOLE_SECONDARY_NONE", + "name": "ESP_CONSOLE_SECONDARY_NONE", + "range": null, + "title": "No secondary console", + "type": "bool" + }, + { + "children": [], + "depends_on": "!ESP_CONSOLE_USB_SERIAL_JTAG && ", + "help": "This option supports output through USB_SERIAL_JTAG port when the UART0 port is not connected.\nThe output currently only supports non-blocking mode without using the console.\nIf you want to output in blocking mode with REPL or input through USB_SERIAL_JTAG port,\nplease change the primary config to ESP_CONSOLE_USB_SERIAL_JTAG above.", + "id": "ESP_CONSOLE_SECONDARY_USB_SERIAL_JTAG", + "name": "ESP_CONSOLE_SECONDARY_USB_SERIAL_JTAG", + "range": null, + "title": "USB_SERIAL_JTAG PORT", + "type": "bool" + } + ], + "depends_on": "SOC_USB_SERIAL_JTAG_SUPPORTED", + "help": "This secondary option supports output through other specific port like USB_SERIAL_JTAG\nwhen UART0 port as a primary is selected but not connected. This secondary output currently only supports\nnon-blocking mode without using REPL. If you want to output in blocking mode with REPL or\ninput through this secondary port, please change the primary config to this port\nin `Channel for console output` menu.", + "id": "component-config-esp-system-settings-channel-for-console-secondary-output", + "name": "ESP_CONSOLE_SECONDARY", + "title": "Channel for console secondary output", + "type": "choice" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "ESP_CONSOLE_USB_SERIAL_JTAG_ENABLED", + "name": "ESP_CONSOLE_USB_SERIAL_JTAG_ENABLED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "ESP_CONSOLE_UART", + "name": "ESP_CONSOLE_UART", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "ESP_CONSOLE_UART_CUSTOM_NUM_0", + "name": "ESP_CONSOLE_UART_CUSTOM_NUM_0", + "range": null, + "title": "UART0", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "ESP_CONSOLE_UART_CUSTOM_NUM_1", + "name": "ESP_CONSOLE_UART_CUSTOM_NUM_1", + "range": null, + "title": "UART1", + "type": "bool" + } + ], + "depends_on": "ESP_CONSOLE_UART_CUSTOM", + "help": "This UART peripheral is used for console output from the ESP-IDF Bootloader and the app.\n\nIf the configuration is different in the Bootloader binary compared to the app binary, UART\nis reconfigured after the bootloader exits and the app starts.\n\nDue to an ESP32 ROM bug, UART2 is not supported for console output\nvia esp_rom_printf.", + "id": "component-config-esp-system-settings-uart-peripheral-to-use-for-console-output-0-1-", + "name": "ESP_CONSOLE_UART_NUM", + "title": "UART peripheral to use for console output (0-1)", + "type": "choice" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "ESP_CONSOLE_UART_NUM", + "name": "ESP_CONSOLE_UART_NUM", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "ESP_CONSOLE_ROM_SERIAL_PORT_NUM", + "name": "ESP_CONSOLE_ROM_SERIAL_PORT_NUM", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": "ESP_CONSOLE_UART_CUSTOM", + "help": "This GPIO is used for console UART TX output in the ESP-IDF Bootloader and the app (including\nboot log output and default standard output and standard error of the app). Value -1 means to\ncontinue using the default console UART TX pin.\n\nIf the configuration is different in the Bootloader binary compared to the app binary, UART\nis reconfigured after the bootloader exits and the app starts.", + "id": "ESP_CONSOLE_UART_TX_GPIO", + "name": "ESP_CONSOLE_UART_TX_GPIO", + "range": null, + "title": "UART TX on GPIO", + "type": "int" + }, + { + "children": [], + "depends_on": "ESP_CONSOLE_UART_CUSTOM", + "help": "This GPIO is used for console UART RX input in the ESP-IDF Bootloader and the app (including\ndefault standard input of the app). Value -1 means to continue using the default console UART\nRX pin.\n\nNote: The default ESP-IDF Bootloader configures this pin but doesn't read anything from the UART.\n\nIf the configuration is different in the Bootloader binary compared to the app binary, UART\nis reconfigured after the bootloader exits and the app starts.", + "id": "ESP_CONSOLE_UART_RX_GPIO", + "name": "ESP_CONSOLE_UART_RX_GPIO", + "range": null, + "title": "UART RX on GPIO", + "type": "int" + }, + { + "children": [], + "depends_on": "ESP_CONSOLE_UART", + "help": "This baud rate is used by both the ESP-IDF Bootloader and the app (including\nboot log output and default standard input/output/error of the app).\n\nThe app's maximum baud rate depends on the UART clock source. If Power Management is disabled,\nthe UART clock source is the APB clock and all baud rates in the available range will be sufficiently\naccurate. If Power Management is enabled, REF_TICK clock source is used so the baud rate is divided\nfrom 1MHz. Baud rates above 1Mbps are not possible and values between 500Kbps and 1Mbps may not be\naccurate.\n\nIf the configuration is different in the Bootloader binary compared to the app binary, UART\nis reconfigured after the bootloader exits and the app starts.", + "id": "ESP_CONSOLE_UART_BAUDRATE", + "name": "ESP_CONSOLE_UART_BAUDRATE", + "range": [ + 1200, + 4000000 + ], + "title": "UART console baud rate", + "type": "int" + }, + { + "children": [], + "depends_on": "ESP_CONSOLE_USB_CDC", + "help": "Set the size of USB CDC RX buffer. Increase the buffer size if your application\nis often receiving data over USB CDC.", + "id": "ESP_CONSOLE_USB_CDC_RX_BUF_SIZE", + "name": "ESP_CONSOLE_USB_CDC_RX_BUF_SIZE", + "range": null, + "title": "Size of USB CDC RX buffer", + "type": "int" + }, + { + "children": [], + "depends_on": "ESP_CONSOLE_USB_CDC", + "help": "If enabled, esp_rom_printf and ESP_EARLY_LOG output will also be sent over USB CDC.\nDisabling this option saves about 1kB or RAM.", + "id": "ESP_CONSOLE_USB_CDC_SUPPORT_ETS_PRINTF", + "name": "ESP_CONSOLE_USB_CDC_SUPPORT_ETS_PRINTF", + "range": null, + "title": "Enable esp_rom_printf / ESP_EARLY_LOG via USB CDC", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "ESP_INT_WDT", + "help": "The timeout of the watchdog, in milliseconds. Make this higher than the FreeRTOS tick rate.", + "id": "ESP_INT_WDT_TIMEOUT_MS", + "name": "ESP_INT_WDT_TIMEOUT_MS", + "range": [ + 10, + 10000 + ], + "title": "Interrupt watchdog timeout (ms)", + "type": "int" + }, + { + "children": [], + "depends_on": "ESP_INT_WDT && !FREERTOS_UNICORE", + "help": "Also detect if interrupts on CPU 1 are disabled for too long.", + "id": "ESP_INT_WDT_CHECK_CPU1", + "name": "ESP_INT_WDT_CHECK_CPU1", + "range": null, + "title": "Also watch CPU1 tick interrupt", + "type": "bool" + } + ], + "depends_on": null, + "help": "This watchdog timer can detect if the FreeRTOS tick interrupt has not been called for a certain time,\neither because a task turned off interrupts and did not turn them on for a long time, or because an\ninterrupt handler did not return. It will try to invoke the panic handler first and failing that\nreset the SoC.", + "id": "ESP_INT_WDT", + "name": "ESP_INT_WDT", + "range": null, + "title": "Interrupt watchdog", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "ESP_TASK_WDT_EN", + "help": null, + "id": "ESP_TASK_WDT_USE_ESP_TIMER", + "name": "ESP_TASK_WDT_USE_ESP_TIMER", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "ESP_TASK_WDT_INIT", + "help": "If this option is enabled, the Task Watchdog Timer will be configured to\ntrigger the panic handler when it times out. This can also be configured\nat run time (see Task Watchdog Timer API Reference)", + "id": "ESP_TASK_WDT_PANIC", + "name": "ESP_TASK_WDT_PANIC", + "range": null, + "title": "Invoke panic handler on Task Watchdog timeout", + "type": "bool" + }, + { + "children": [], + "depends_on": "ESP_TASK_WDT_INIT", + "help": "Timeout period configuration for the Task Watchdog Timer in seconds.\nThis is also configurable at run time (see Task Watchdog Timer API Reference)", + "id": "ESP_TASK_WDT_TIMEOUT_S", + "name": "ESP_TASK_WDT_TIMEOUT_S", + "range": [ + 1, + 60 + ], + "title": "Task Watchdog timeout period (seconds)", + "type": "int" + }, + { + "children": [], + "depends_on": "ESP_TASK_WDT_INIT", + "help": "If this option is enabled, the Task Watchdog Timer will watch the CPU0\nIdle Task. Having the Task Watchdog watch the Idle Task allows for detection\nof CPU starvation as the Idle Task not being called is usually a symptom of\nCPU starvation. Starvation of the Idle Task is detrimental as FreeRTOS household\ntasks depend on the Idle Task getting some runtime every now and then.", + "id": "ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0", + "name": "ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0", + "range": null, + "title": "Watch CPU0 Idle Task", + "type": "bool" + }, + { + "children": [], + "depends_on": "ESP_TASK_WDT_INIT && !FREERTOS_UNICORE", + "help": "If this option is enabled, the Task Watchdog Timer will wach the CPU1\nIdle Task.", + "id": "ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1", + "name": "ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1", + "range": null, + "title": "Watch CPU1 Idle Task", + "type": "bool" + } + ], + "depends_on": "ESP_TASK_WDT_EN", + "help": "Enabling this option will cause the Task Watchdog Timer to be initialized\nautomatically at startup.", + "id": "ESP_TASK_WDT_INIT", + "name": "ESP_TASK_WDT_INIT", + "range": null, + "title": "Initialize Task Watchdog Timer on startup", + "type": "bool" + } + ], + "depends_on": null, + "help": "The Task Watchdog Timer can be used to make sure individual tasks are still\nrunning. Enabling this option will enable the Task Watchdog Timer. It can be\neither initialized automatically at startup or initialized after startup\n(see Task Watchdog Timer API Reference)", + "id": "ESP_TASK_WDT_EN", + "name": "ESP_TASK_WDT_EN", + "range": null, + "title": "Enable Task Watchdog Timer", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "ESP_XT_WDT", + "help": "Timeout period configuration for the XTAL32K watchdog timer based on RTC_CLK.", + "id": "ESP_XT_WDT_TIMEOUT", + "name": "ESP_XT_WDT_TIMEOUT", + "range": null, + "title": "XTAL32K watchdog timeout period", + "type": "int" + }, + { + "children": [], + "depends_on": "ESP_XT_WDT", + "help": "Enable this to automatically switch to BACKUP32K_CLK as the source of RTC_SLOW_CLK when\nthe watchdog timer expires.", + "id": "ESP_XT_WDT_BACKUP_CLK_ENABLE", + "name": "ESP_XT_WDT_BACKUP_CLK_ENABLE", + "range": null, + "title": "Automatically switch to BACKUP32K_CLK when timer expires", + "type": "bool" + } + ], + "depends_on": "SOC_XT_WDT_SUPPORTED && (ESP_SYSTEM_RTC_EXT_OSC || ESP_SYSTEM_RTC_EXT_XTAL)", + "help": "This watchdog timer can detect oscillation failure of the XTAL32K_CLK. When such a failure\nis detected the hardware can be set up to automatically switch to BACKUP32K_CLK and generate\nan interrupt.", + "id": "ESP_XT_WDT", + "name": "ESP_XT_WDT", + "range": null, + "title": "Initialize XTAL32K watchdog timer on startup", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "If this option is disabled (default), the panic handler code is placed in flash not IRAM.\nThis means that if ESP-IDF crashes while flash cache is disabled, the panic handler will\nautomatically re-enable flash cache before running GDB Stub or Core Dump. This adds some minor\nrisk, if the flash cache status is also corrupted during the crash.\n\nIf this option is enabled, the panic handler code (including required UART functions) is placed\nin IRAM. This may be necessary to debug some complex issues with crashes while flash cache is\ndisabled (for example, when writing to SPI flash) or when flash cache is corrupted when an exception\nis triggered.", + "id": "ESP_PANIC_HANDLER_IRAM", + "name": "ESP_PANIC_HANDLER_IRAM", + "range": null, + "title": "Place panic handler code in IRAM", + "type": "bool" + }, + { + "children": [], + "depends_on": "!ESP32_TRAX && !ESP32S2_TRAX && !ESP32S3_TRAX", + "help": "Debug stubs are used by OpenOCD to execute pre-compiled onboard code\nwhich does some useful debugging stuff, e.g. GCOV data dump.", + "id": "ESP_DEBUG_STUBS_ENABLE", + "name": "ESP_DEBUG_STUBS_ENABLE", + "range": null, + "title": "OpenOCD debug stubs", + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_DEBUG_HAVE_OCD_STUB_BINS", + "help": "OpenOCD uses stub code to access flash during programming or when inserting and removing\nSW flash breakpoints.\nTo execute stub code, OpenOCD allocates memory on the target device, backs up the existing memory,\nloads the stub binary, runs the binary, and then restores the original memory.\nThis process can be time-consuming, especially when using USB serial JTAG.\nBy enabling this option, 8K of memory in RAM will be preallocated with the stub code,\neliminating the need to back up and restore the memory region.", + "id": "ESP_DEBUG_INCLUDE_OCD_STUB_BINS", + "name": "ESP_DEBUG_INCLUDE_OCD_STUB_BINS", + "range": null, + "title": "Preload OpenOCD stub binaries to speed up debugging. 8K memory will be reserved", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "The FreeRTOS panic and unhandled exception handers can detect a JTAG OCD debugger and\ninstead of panicking, have the debugger stop on the offending instruction.", + "id": "ESP_DEBUG_OCDAWARE", + "name": "ESP_DEBUG_OCDAWARE", + "range": null, + "title": "Make exception and panic handlers JTAG/OCD aware", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "IDF_TARGET_ESP32 && ", + "help": "Using level 5 interrupt for Interrupt Watchdog, IPC_ISR and other system checks.", + "id": "ESP_SYSTEM_CHECK_INT_LEVEL_5", + "name": "ESP_SYSTEM_CHECK_INT_LEVEL_5", + "range": null, + "title": "Level 5 interrupt", + "type": "bool" + }, + { + "children": [], + "depends_on": "!BTDM_CTRL_HLI && ", + "help": "Using level 4 interrupt for Interrupt Watchdog, IPC_ISR and other system checks.", + "id": "ESP_SYSTEM_CHECK_INT_LEVEL_4", + "name": "ESP_SYSTEM_CHECK_INT_LEVEL_4", + "range": null, + "title": "Level 4 interrupt", + "type": "bool" + } + ], + "depends_on": null, + "help": "Interrupt level to use for Interrupt Watchdog, IPC_ISR and other system checks.", + "id": "component-config-esp-system-settings-interrupt-level-to-use-for-interrupt-watchdog-and-other-system-checks", + "name": "ESP_SYSTEM_CHECK_INT_LEVEL", + "title": "Interrupt level to use for Interrupt Watchdog and other system checks", + "type": "choice" + }, + { + "children": [ + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "ESP_BROWNOUT_DET_LVL_SEL_7", + "name": "ESP_BROWNOUT_DET_LVL_SEL_7", + "range": null, + "title": "2.51V", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "ESP_BROWNOUT_DET_LVL_SEL_6", + "name": "ESP_BROWNOUT_DET_LVL_SEL_6", + "range": null, + "title": "2.64V", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "ESP_BROWNOUT_DET_LVL_SEL_5", + "name": "ESP_BROWNOUT_DET_LVL_SEL_5", + "range": null, + "title": "2.76V", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "ESP_BROWNOUT_DET_LVL_SEL_4", + "name": "ESP_BROWNOUT_DET_LVL_SEL_4", + "range": null, + "title": "2.92V", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "ESP_BROWNOUT_DET_LVL_SEL_3", + "name": "ESP_BROWNOUT_DET_LVL_SEL_3", + "range": null, + "title": "3.10V", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "ESP_BROWNOUT_DET_LVL_SEL_2", + "name": "ESP_BROWNOUT_DET_LVL_SEL_2", + "range": null, + "title": "3.27V", + "type": "bool" + } + ], + "depends_on": "ESP_BROWNOUT_DET", + "help": "The brownout detector will reset the chip when the supply voltage is approximately\nbelow this level. Note that there may be some variation of brownout voltage level\nbetween each chip.\n\n#The voltage levels here are estimates, more work needs to be done to figure out the exact voltages\n#of the brownout threshold levels.", + "id": "component-config-esp-system-settings-brownout-detector-hardware-brownout-detect-reset-brownout-voltage-level", + "name": "ESP_BROWNOUT_DET_LVL_SEL", + "title": "Brownout voltage level", + "type": "choice" + } + ], + "depends_on": "!IDF_ENV_FPGA", + "help": "The ESP32-C3 has a built-in brownout detector which can detect if the voltage is lower than\na specific value. If this happens, it will reset the chip in order to prevent unintended\nbehaviour.", + "id": "ESP_BROWNOUT_DET", + "name": "ESP_BROWNOUT_DET", + "range": null, + "title": "Hardware brownout detect & reset", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "ESP_BROWNOUT_DET_LVL", + "name": "ESP_BROWNOUT_DET_LVL", + "range": null, + "title": null, + "type": "int" + } + ], + "depends_on": null, + "id": "component-config-esp-system-settings-brownout-detector", + "title": "Brownout Detector", + "type": "menu" + }, + { + "children": [], + "depends_on": null, + "help": "This config allows to trigger an interrupt when brownout detected. Software restart will be done\nat the end of the default callback.\nTwo occasions need to restart the chip with interrupt so far.\n(1). For ESP32 version 1, brown-out reset function doesn't work (see ESP32 errata 3.4).\n So that we must restart from interrupt.\n(2). For special workflow, the chip needs do more things instead of restarting directly. This part\n needs to be done in callback function of interrupt.", + "id": "ESP_SYSTEM_BROWNOUT_INTR", + "name": "ESP_SYSTEM_BROWNOUT_INTR", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_ASSIST_DEBUG_SUPPORTED", + "help": "This config allows to trigger a panic interrupt when Stack Pointer register goes out of allocated stack\nmemory bounds.", + "id": "ESP_SYSTEM_HW_STACK_GUARD", + "name": "ESP_SYSTEM_HW_STACK_GUARD", + "range": null, + "title": "Hardware stack guard", + "type": "bool" + }, + { + "children": [], + "depends_on": "IDF_TARGET_ESP32C2 || IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32C6 || IDF_TARGET_ESP32H2", + "help": "This configuration helps to address an BBPLL inaccurate issue when boot from certain bootloader version,\nwhich may increase about the boot-up time by about 200 us. Disable this when your bootloader is built with\nESP-IDF version v5.2 and above.", + "id": "ESP_SYSTEM_BBPLL_RECALIB", + "name": "ESP_SYSTEM_BBPLL_RECALIB", + "range": null, + "title": "Re-calibration BBPLL at startup", + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_ASSIST_DEBUG_SUPPORTED", + "help": "This option will enable the PC recording function of assist_debug module. The PC value of the CPU will be\nrecorded to PC record register in assist_debug module in real time. When an exception occurs and the CPU\nis reset, this register will be kept, then we can use the recorded PC to debug the causes of the reset.", + "id": "ESP_SYSTEM_HW_PC_RECORD", + "name": "ESP_SYSTEM_HW_PC_RECORD", + "range": null, + "title": "Hardware PC recording", + "type": "bool" + } + ], + "depends_on": null, + "id": "component-config-esp-system-settings", + "title": "ESP System Settings", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": null, + "help": "Configure the IPC tasks stack size. An IPC task runs on each core (in dual core mode), and allows for\ncross-core function calls. See IPC documentation for more details. The default IPC stack size should be\nenough for most common simple use cases. However, users can increase/decrease the stack size to their\nneeds.", + "id": "ESP_IPC_TASK_STACK_SIZE", + "name": "ESP_IPC_TASK_STACK_SIZE", + "range": [ + 512, + 65536 + ], + "title": "Inter-Processor Call (IPC) task stack size", + "type": "int" + }, + { + "children": [], + "depends_on": "!FREERTOS_UNICORE", + "help": "If this option is not enabled then the IPC task will keep behavior same as prior to that of ESP-IDF v4.0,\nhence IPC task will run at (configMAX_PRIORITIES - 1) priority.", + "id": "ESP_IPC_USES_CALLERS_PRIORITY", + "name": "ESP_IPC_USES_CALLERS_PRIORITY", + "range": null, + "title": "IPC runs at caller's priority", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "The IPC ISR feature is similar to the IPC feature except that the callback function is executed in the\ncontext of a High Priority Interrupt. The IPC ISR feature is intended for low latency execution of simple\ncallbacks written in assembly on another CPU. Due to being run in a High Priority Interrupt, the assembly\ncallbacks must be written with particular restrictions (see \"IPC\" and \"High-Level Interrupt\" docs for more\ndetails).", + "id": "ESP_IPC_ISR_ENABLE", + "name": "ESP_IPC_ISR_ENABLE", + "range": null, + "title": null, + "type": "bool" + } + ], + "depends_on": null, + "id": "component-config-ipc-inter-processor-call-", + "title": "IPC (Inter-Processor Call)", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": null, + "help": "If enabled, esp_timer_dump will dump information such as number of times the timer was started,\nnumber of times the timer has triggered, and the total time it took for the callback to run.\nThis option has some effect on timer performance and the amount of memory used for timer\nstorage, and should only be used for debugging/testing purposes.", + "id": "ESP_TIMER_PROFILING", + "name": "ESP_TIMER_PROFILING", + "range": null, + "title": "Enable esp_timer profiling features", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "ESP_TIME_FUNCS_USE_RTC_TIMER", + "name": "ESP_TIME_FUNCS_USE_RTC_TIMER", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "ESP_TIME_FUNCS_USE_ESP_TIMER", + "name": "ESP_TIME_FUNCS_USE_ESP_TIMER", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "ESP_TIME_FUNCS_USE_NONE", + "name": "ESP_TIME_FUNCS_USE_NONE", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Configure the stack size of \"timer_task\" task. This task is used\nto dispatch callbacks of timers created using ets_timer and esp_timer\nAPIs. If you are seing stack overflow errors in timer task, increase\nthis value.\n\nNote that this is not the same as FreeRTOS timer task. To configure\nFreeRTOS timer task size, see \"FreeRTOS timer task stack size\" option\nin \"FreeRTOS\".", + "id": "ESP_TIMER_TASK_STACK_SIZE", + "name": "ESP_TIMER_TASK_STACK_SIZE", + "range": [ + 2048, + 65536 + ], + "title": "High-resolution timer task stack size", + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": "This sets the interrupt priority level for esp_timer ISR.\nA higher value reduces interrupt latency by minimizing the timer processing delay.", + "id": "ESP_TIMER_INTERRUPT_LEVEL", + "name": "ESP_TIMER_INTERRUPT_LEVEL", + "range": [ + 1, + 1 + ], + "title": "Interrupt level", + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": "This shows some hidden features of esp_timer.\nNote that they may break other features, use them with care.", + "id": "ESP_TIMER_SHOW_EXPERIMENTAL", + "name": "ESP_TIMER_SHOW_EXPERIMENTAL", + "range": null, + "title": "show esp_timer's experimental features", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "ESP_TIMER_TASK_AFFINITY", + "name": "ESP_TIMER_TASK_AFFINITY", + "range": null, + "title": null, + "type": "hex" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "ESP_TIMER_TASK_AFFINITY_CPU0", + "name": "ESP_TIMER_TASK_AFFINITY_CPU0", + "range": null, + "title": "CPU0", + "type": "bool" + }, + { + "children": [], + "depends_on": "!FREERTOS_UNICORE && ESP_TIMER_SHOW_EXPERIMENTAL && ", + "help": null, + "id": "ESP_TIMER_TASK_AFFINITY_CPU1", + "name": "ESP_TIMER_TASK_AFFINITY_CPU1", + "range": null, + "title": "CPU1", + "type": "bool" + }, + { + "children": [], + "depends_on": "!FREERTOS_UNICORE && ESP_TIMER_SHOW_EXPERIMENTAL && ", + "help": null, + "id": "ESP_TIMER_TASK_AFFINITY_NO_AFFINITY", + "name": "ESP_TIMER_TASK_AFFINITY_NO_AFFINITY", + "range": null, + "title": "No affinity", + "type": "bool" + } + ], + "depends_on": null, + "help": "The default settings: timer TASK on CPU0 and timer ISR on CPU0.\nOther settings may help in certain cases, but note that they may break\nother features, use them with care.\n- \"CPU0\": (default) esp_timer task is processed by CPU0.\n- \"CPU1\": esp_timer task is processed by CPU1.\n- \"No affinity\": esp_timer task can be processed by any CPU.", + "id": "component-config-esp-timer-high-resolution-timer--esp_timer-task-core-affinity", + "name": "ESP_TIMER_TASK_AFFINITY", + "title": "esp_timer task core affinity", + "type": "choice" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "ESP_TIMER_ISR_AFFINITY_CPU0", + "name": "ESP_TIMER_ISR_AFFINITY_CPU0", + "range": null, + "title": "CPU0", + "type": "bool" + }, + { + "children": [], + "depends_on": "!FREERTOS_UNICORE && ESP_TIMER_SHOW_EXPERIMENTAL && ", + "help": null, + "id": "ESP_TIMER_ISR_AFFINITY_CPU1", + "name": "ESP_TIMER_ISR_AFFINITY_CPU1", + "range": null, + "title": "CPU1", + "type": "bool" + }, + { + "children": [], + "depends_on": "!FREERTOS_UNICORE && ESP_TIMER_SHOW_EXPERIMENTAL && ", + "help": null, + "id": "ESP_TIMER_ISR_AFFINITY_NO_AFFINITY", + "name": "ESP_TIMER_ISR_AFFINITY_NO_AFFINITY", + "range": null, + "title": "No affinity", + "type": "bool" + } + ], + "depends_on": null, + "help": "The default settings: timer TASK on CPU0 and timer ISR on CPU0.\nOther settings may help in certain cases, but note that they may break\nother features, use them with care.\n- \"CPU0\": (default) timer interrupt is processed by CPU0.\n- \"CPU1\": timer interrupt is processed by CPU1.\n- \"No affinity\": timer interrupt can be processed by any CPU. It helps\nto reduce latency but there is a disadvantage it leads to the timer ISR\nrunning on every core. It increases the CPU time usage for timer ISRs\nby N on an N-core system.", + "id": "component-config-esp-timer-high-resolution-timer--timer-interrupt-core-affinity", + "name": "ESP_TIMER_ISR_AFFINITY", + "title": "timer interrupt core affinity", + "type": "choice" + }, + { + "children": [], + "depends_on": null, + "help": "Allows using ESP_TIMER_ISR dispatch method (ESP_TIMER_TASK dispatch method is also avalible).\n- ESP_TIMER_TASK - Timer callbacks are dispatched from a high-priority esp_timer task.\n- ESP_TIMER_ISR - Timer callbacks are dispatched directly from the timer interrupt handler.\nThe ISR dispatch can be used, in some cases, when a callback is very simple\nor need a lower-latency.", + "id": "ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD", + "name": "ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD", + "range": null, + "title": "Support ISR dispatch method", + "type": "bool" + }, + { + "children": [], + "depends_on": "IDF_TARGET_ESP32", + "help": null, + "id": "ESP_TIMER_IMPL_TG0_LAC", + "name": "ESP_TIMER_IMPL_TG0_LAC", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": "!IDF_TARGET_ESP32", + "help": null, + "id": "ESP_TIMER_IMPL_SYSTIMER", + "name": "ESP_TIMER_IMPL_SYSTIMER", + "range": null, + "title": null, + "type": "bool" + } + ], + "depends_on": null, + "id": "component-config-esp-timer-high-resolution-timer-", + "title": "ESP Timer (High Resolution Timer)", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": null, + "help": null, + "id": "ESP_WIFI_ENABLED", + "name": "ESP_WIFI_ENABLED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "ESP_HOST_WIFI_ENABLED", + "help": null, + "id": "ESP_WIFI_CONTROLLER_TARGET", + "name": "ESP_WIFI_CONTROLLER_TARGET", + "range": null, + "title": null, + "type": "string" + }, + { + "children": [], + "depends_on": "ESP_HOST_WIFI_ENABLED", + "help": null, + "id": "ESP_WIFI_TARGET_ESP32", + "name": "ESP_WIFI_TARGET_ESP32", + "range": null, + "title": null, + "type": "bool" + } + ], + "depends_on": "SOC_WIRELESS_HOST_SUPPORTED", + "help": null, + "id": "ESP_HOST_WIFI_ENABLED", + "name": "ESP_HOST_WIFI_ENABLED", + "range": null, + "title": "Host WiFi Enable", + "type": "bool" + }, + { + "children": [], + "depends_on": "ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED", + "help": "Set the number of WiFi static RX buffers. Each buffer takes approximately 1.6KB of RAM.\nThe static rx buffers are allocated when esp_wifi_init is called, they are not freed\nuntil esp_wifi_deinit is called.\n\nWiFi hardware use these buffers to receive all 802.11 frames.\nA higher number may allow higher throughput but increases memory use. If ESP_WIFI_AMPDU_RX_ENABLED\nis enabled, this value is recommended to set equal or bigger than ESP_WIFI_RX_BA_WIN in order to\nachieve better throughput and compatibility with both stations and APs.", + "id": "ESP_WIFI_STATIC_RX_BUFFER_NUM", + "name": "ESP_WIFI_STATIC_RX_BUFFER_NUM", + "range": [ + 2, + 25 + ], + "title": "Max number of WiFi static RX buffers", + "type": "int" + }, + { + "children": [], + "depends_on": "ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED", + "help": "Set the number of WiFi dynamic RX buffers, 0 means unlimited RX buffers will be allocated\n(provided sufficient free RAM). The size of each dynamic RX buffer depends on the size of\nthe received data frame.\n\nFor each received data frame, the WiFi driver makes a copy to an RX buffer and then delivers\nit to the high layer TCP/IP stack. The dynamic RX buffer is freed after the higher layer has\nsuccessfully received the data frame.\n\nFor some applications, WiFi data frames may be received faster than the application can\nprocess them. In these cases we may run out of memory if RX buffer number is unlimited (0).\n\nIf a dynamic RX buffer limit is set, it should be at least the number of static RX buffers.", + "id": "ESP_WIFI_DYNAMIC_RX_BUFFER_NUM", + "name": "ESP_WIFI_DYNAMIC_RX_BUFFER_NUM", + "range": [ + 0, + 128 + ], + "title": "Max number of WiFi dynamic RX buffers", + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "ESP_WIFI_STATIC_TX_BUFFER", + "name": "ESP_WIFI_STATIC_TX_BUFFER", + "range": null, + "title": "Static", + "type": "bool" + }, + { + "children": [], + "depends_on": "!(SPIRAM_TRY_ALLOCATE_WIFI_LWIP && !SPIRAM_IGNORE_NOTFOUND) && ", + "help": null, + "id": "ESP_WIFI_DYNAMIC_TX_BUFFER", + "name": "ESP_WIFI_DYNAMIC_TX_BUFFER", + "range": null, + "title": "Dynamic", + "type": "bool" + } + ], + "depends_on": "ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED", + "help": "Select type of WiFi TX buffers:\n\nIf \"Static\" is selected, WiFi TX buffers are allocated when WiFi is initialized and released\nwhen WiFi is de-initialized. The size of each static TX buffer is fixed to about 1.6KB.\n\nIf \"Dynamic\" is selected, each WiFi TX buffer is allocated as needed when a data frame is\ndelivered to the Wifi driver from the TCP/IP stack. The buffer is freed after the data frame\nhas been sent by the WiFi driver. The size of each dynamic TX buffer depends on the length\nof each data frame sent by the TCP/IP layer.\n\nIf PSRAM is enabled, \"Static\" should be selected to guarantee enough WiFi TX buffers.\nIf PSRAM is disabled, \"Dynamic\" should be selected to improve the utilization of RAM.", + "id": "component-config-wi-fi-type-of-wifi-tx-buffers", + "name": "ESP_WIFI_TX_BUFFER", + "title": "Type of WiFi TX buffers", + "type": "choice" + }, + { + "children": [], + "depends_on": "ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED", + "help": null, + "id": "ESP_WIFI_TX_BUFFER_TYPE", + "name": "ESP_WIFI_TX_BUFFER_TYPE", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": "ESP_WIFI_STATIC_TX_BUFFER && (ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED)", + "help": "Set the number of WiFi static TX buffers. Each buffer takes approximately 1.6KB of RAM.\nThe static RX buffers are allocated when esp_wifi_init() is called, they are not released\nuntil esp_wifi_deinit() is called.\n\nFor each transmitted data frame from the higher layer TCP/IP stack, the WiFi driver makes a\ncopy of it in a TX buffer. For some applications especially UDP applications, the upper\nlayer can deliver frames faster than WiFi layer can transmit. In these cases, we may run out\nof TX buffers.", + "id": "ESP_WIFI_STATIC_TX_BUFFER_NUM", + "name": "ESP_WIFI_STATIC_TX_BUFFER_NUM", + "range": null, + "title": "Max number of WiFi static TX buffers", + "type": "int" + }, + { + "children": [], + "depends_on": "SPIRAM_TRY_ALLOCATE_WIFI_LWIP && !SPIRAM_IGNORE_NOTFOUND && (ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED)", + "help": "Set the number of WiFi cache TX buffer number.\n\nFor each TX packet from uplayer, such as LWIP etc, WiFi driver needs to allocate a static TX\nbuffer and makes a copy of uplayer packet. If WiFi driver fails to allocate the static TX buffer,\nit caches the uplayer packets to a dedicated buffer queue, this option is used to configure the\nsize of the cached TX queue.", + "id": "ESP_WIFI_CACHE_TX_BUFFER_NUM", + "name": "ESP_WIFI_CACHE_TX_BUFFER_NUM", + "range": null, + "title": "Max number of WiFi cache TX buffers", + "type": "int" + }, + { + "children": [], + "depends_on": "ESP_WIFI_DYNAMIC_TX_BUFFER && (ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED)", + "help": "Set the number of WiFi dynamic TX buffers. The size of each dynamic TX buffer is not fixed,\nit depends on the size of each transmitted data frame.\n\nFor each transmitted frame from the higher layer TCP/IP stack, the WiFi driver makes a copy\nof it in a TX buffer. For some applications, especially UDP applications, the upper layer\ncan deliver frames faster than WiFi layer can transmit. In these cases, we may run out of TX\nbuffers.", + "id": "ESP_WIFI_DYNAMIC_TX_BUFFER_NUM", + "name": "ESP_WIFI_DYNAMIC_TX_BUFFER_NUM", + "range": [ + 1, + 128 + ], + "title": "Max number of WiFi dynamic TX buffers", + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "ESP_WIFI_STATIC_RX_MGMT_BUFFER", + "name": "ESP_WIFI_STATIC_RX_MGMT_BUFFER", + "range": null, + "title": "Static", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "ESP_WIFI_DYNAMIC_RX_MGMT_BUFFER", + "name": "ESP_WIFI_DYNAMIC_RX_MGMT_BUFFER", + "range": null, + "title": "Dynamic", + "type": "bool" + } + ], + "depends_on": "ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED", + "help": "Select type of WiFi RX MGMT buffers:\n\nIf \"Static\" is selected, WiFi RX MGMT buffers are allocated when WiFi is initialized and released\nwhen WiFi is de-initialized. The size of each static RX MGMT buffer is fixed to about 500 Bytes.\n\nIf \"Dynamic\" is selected, each WiFi RX MGMT buffer is allocated as needed when a MGMT data frame is\nreceived. The MGMT buffer is freed after the MGMT data frame has been processed by the WiFi driver.", + "id": "component-config-wi-fi-type-of-wifi-rx-mgmt-buffers", + "name": "ESP_WIFI_MGMT_RX_BUFFER", + "title": "Type of WiFi RX MGMT buffers", + "type": "choice" + }, + { + "children": [], + "depends_on": "ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED", + "help": null, + "id": "ESP_WIFI_DYNAMIC_RX_MGMT_BUF", + "name": "ESP_WIFI_DYNAMIC_RX_MGMT_BUF", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": "ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED", + "help": "Set the number of WiFi RX_MGMT buffers.\n\nFor Management buffers, the number of dynamic and static management buffers is the same.\nIn order to prevent memory fragmentation, the management buffer type should be set to static first.", + "id": "ESP_WIFI_RX_MGMT_BUF_NUM_DEF", + "name": "ESP_WIFI_RX_MGMT_BUF_NUM_DEF", + "range": [ + 1, + 10 + ], + "title": "Max number of WiFi RX MGMT buffers", + "type": "int" + }, + { + "children": [], + "depends_on": "SOC_WIFI_CSI_SUPPORT && (ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED)", + "help": "Select this option to enable CSI(Channel State Information) feature. CSI takes about\nCONFIG_ESP_WIFI_STATIC_RX_BUFFER_NUM KB of RAM. If CSI is not used, it is better to disable\nthis feature in order to save memory.", + "id": "ESP_WIFI_CSI_ENABLED", + "name": "ESP_WIFI_CSI_ENABLED", + "range": null, + "title": "WiFi CSI(Channel State Information)", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "ESP_WIFI_AMPDU_TX_ENABLED && (ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED)", + "help": "Set the size of WiFi Block Ack TX window. Generally a bigger value means higher throughput but\nmore memory. Most of time we should NOT change the default value unless special reason, e.g.\ntest the maximum UDP TX throughput with iperf etc. For iperf test in shieldbox, the recommended\nvalue is 9~12.", + "id": "ESP_WIFI_TX_BA_WIN", + "name": "ESP_WIFI_TX_BA_WIN", + "range": [ + 2, + 32 + ], + "title": "WiFi AMPDU TX BA window size", + "type": "int" + } + ], + "depends_on": "ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED", + "help": "Select this option to enable AMPDU TX feature", + "id": "ESP_WIFI_AMPDU_TX_ENABLED", + "name": "ESP_WIFI_AMPDU_TX_ENABLED", + "range": null, + "title": "WiFi AMPDU TX", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "ESP_WIFI_AMPDU_RX_ENABLED && (ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED)", + "help": "Set the size of WiFi Block Ack RX window. Generally a bigger value means higher throughput and better\ncompatibility but more memory. Most of time we should NOT change the default value unless special\nreason, e.g. test the maximum UDP RX throughput with iperf etc. For iperf test in shieldbox, the\nrecommended value is 9~12. If PSRAM is used and WiFi memory is preferred to allocate in PSRAM first,\nthe default and minimum value should be 16 to achieve better throughput and compatibility with both\nstations and APs.", + "id": "ESP_WIFI_RX_BA_WIN", + "name": "ESP_WIFI_RX_BA_WIN", + "range": [ + 2, + 32 + ], + "title": "WiFi AMPDU RX BA window size", + "type": "int" + } + ], + "depends_on": "ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED", + "help": "Select this option to enable AMPDU RX feature", + "id": "ESP_WIFI_AMPDU_RX_ENABLED", + "name": "ESP_WIFI_AMPDU_RX_ENABLED", + "range": null, + "title": "WiFi AMPDU RX", + "type": "bool" + }, + { + "children": [], + "depends_on": "ESP_WIFI_CACHE_TX_BUFFER_NUM >= 2 && (ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED)", + "help": "Select this option to enable AMSDU TX feature", + "id": "ESP_WIFI_AMSDU_TX_ENABLED", + "name": "ESP_WIFI_AMSDU_TX_ENABLED", + "range": null, + "title": "WiFi AMSDU TX", + "type": "bool" + }, + { + "children": [], + "depends_on": "ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED", + "help": "Select this option to enable WiFi NVS flash", + "id": "ESP_WIFI_NVS_ENABLED", + "name": "ESP_WIFI_NVS_ENABLED", + "range": null, + "title": "WiFi NVS flash", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "ESP_WIFI_TASK_PINNED_TO_CORE_0", + "name": "ESP_WIFI_TASK_PINNED_TO_CORE_0", + "range": null, + "title": "Core 0", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "ESP_WIFI_TASK_PINNED_TO_CORE_1", + "name": "ESP_WIFI_TASK_PINNED_TO_CORE_1", + "range": null, + "title": "Core 1", + "type": "bool" + } + ], + "depends_on": "!FREERTOS_UNICORE && (ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED)", + "help": "Pinned WiFi task to core 0 or core 1.", + "id": "component-config-wi-fi-wifi-task-core-id", + "name": "ESP_WIFI_TASK_CORE_ID", + "title": "WiFi Task Core ID", + "type": "choice" + }, + { + "children": [], + "depends_on": "ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED", + "help": "ESP-MESH utilizes beacon frames to detect and resolve root node conflicts (see documentation). However\nthe default length of a beacon frame can simultaneously hold only five root node identifier structures,\nmeaning that a root node conflict of up to five nodes can be detected at one time. In the occurrence of\nmore root nodes conflict involving more than five root nodes, the conflict resolution process will\ndetect five of the root nodes, resolve the conflict, and re-detect more root nodes. This process will\nrepeat until all root node conflicts are resolved. However this process can generally take a very long\ntime.\n\nTo counter this situation, the beacon frame length can be increased such that more root nodes can be\ndetected simultaneously. Each additional root node will require 36 bytes and should be added on top of\nthe default beacon frame length of\n752 bytes. For example, if you want to detect 10 root nodes simultaneously, you need to set the beacon\nframe length as\n932 (752+36*5).\n\nSetting a longer beacon length also assists with debugging as the conflicting root nodes can be\nidentified more quickly.", + "id": "ESP_WIFI_SOFTAP_BEACON_MAX_LEN", + "name": "ESP_WIFI_SOFTAP_BEACON_MAX_LEN", + "range": [ + 752, + 1256 + ], + "title": "Max length of WiFi SoftAP Beacon", + "type": "int" + }, + { + "children": [], + "depends_on": "ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED", + "help": "Set the maximum number of Wi-Fi management short buffers. These buffers are dynamically allocated,\nwith their size determined by the length of the management packet to be sent. When a management\npacket is less than 64 bytes, the Wi-Fi driver classifies it as a short management packet and\nassigns it to one of these buffers.", + "id": "ESP_WIFI_MGMT_SBUF_NUM", + "name": "ESP_WIFI_MGMT_SBUF_NUM", + "range": [ + 6, + 32 + ], + "title": "WiFi mgmt short buffer number", + "type": "int" + }, + { + "children": [], + "depends_on": "ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED", + "help": "Select this option to place frequently called Wi-Fi library functions in IRAM.\nWhen this option is disabled, more than 10Kbytes of IRAM memory will be saved\nbut Wi-Fi throughput will be reduced.", + "id": "ESP_WIFI_IRAM_OPT", + "name": "ESP_WIFI_IRAM_OPT", + "range": null, + "title": "WiFi IRAM speed optimization", + "type": "bool" + }, + { + "children": [], + "depends_on": "ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED", + "help": "Select this option to place additional frequently called Wi-Fi library functions\nin IRAM. When this option is disabled, more than 5Kbytes of IRAM memory will be saved\nbut Wi-Fi throughput will be reduced.", + "id": "ESP_WIFI_EXTRA_IRAM_OPT", + "name": "ESP_WIFI_EXTRA_IRAM_OPT", + "range": null, + "title": "WiFi EXTRA IRAM speed optimization", + "type": "bool" + }, + { + "children": [], + "depends_on": "ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED", + "help": "Select this option to place frequently called Wi-Fi library RX functions in IRAM.\nWhen this option is disabled, more than 17Kbytes of IRAM memory will be saved\nbut Wi-Fi performance will be reduced.", + "id": "ESP_WIFI_RX_IRAM_OPT", + "name": "ESP_WIFI_RX_IRAM_OPT", + "range": null, + "title": "WiFi RX IRAM speed optimization", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "ESP_WIFI_ENABLE_WPA3_SAE && (ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED)", + "help": "Select this option to enable SAE-PK", + "id": "ESP_WIFI_ENABLE_SAE_PK", + "name": "ESP_WIFI_ENABLE_SAE_PK", + "range": null, + "title": "Enable SAE-PK", + "type": "bool" + }, + { + "children": [], + "depends_on": "ESP_WIFI_ENABLE_WPA3_SAE && ESP_WIFI_SOFTAP_SUPPORT && (ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED)", + "help": "Select this option to enable SAE support in softAP mode.", + "id": "ESP_WIFI_SOFTAP_SAE_SUPPORT", + "name": "ESP_WIFI_SOFTAP_SAE_SUPPORT", + "range": null, + "title": "Enable WPA3 Personal(SAE) SoftAP", + "type": "bool" + } + ], + "depends_on": "ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED", + "help": "Select this option to allow the device to establish a WPA3-Personal connection with eligible AP's.\nPMF (Protected Management Frames) is a prerequisite feature for a WPA3 connection, it needs to be\nexplicitly configured before attempting connection. Please refer to the Wi-Fi Driver API Guide\nfor details.", + "id": "ESP_WIFI_ENABLE_WPA3_SAE", + "name": "ESP_WIFI_ENABLE_WPA3_SAE", + "range": null, + "title": "Enable WPA3-Personal", + "type": "bool" + }, + { + "children": [], + "depends_on": "ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED", + "help": "Select this option to allow the device to establish OWE connection with eligible AP's.\nPMF (Protected Management Frames) is a prerequisite feature for a WPA3 connection, it needs to be\nexplicitly configured before attempting connection. Please refer to the Wi-Fi Driver API Guide\nfor details.", + "id": "ESP_WIFI_ENABLE_WPA3_OWE_STA", + "name": "ESP_WIFI_ENABLE_WPA3_OWE_STA", + "range": null, + "title": "Enable OWE STA", + "type": "bool" + }, + { + "children": [], + "depends_on": "ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED", + "help": "Select this option to place called Wi-Fi library TBTT process and receive beacon functions in IRAM.\nSome functions can be put in IRAM either by ESP_WIFI_IRAM_OPT and ESP_WIFI_RX_IRAM_OPT, or this one.\nIf already enabled ESP_WIFI_IRAM_OPT, the other 7.3KB IRAM memory would be taken by this option.\nIf already enabled ESP_WIFI_RX_IRAM_OPT, the other 1.3KB IRAM memory would be taken by this option.\nIf neither of them are enabled, the other 7.4KB IRAM memory would be taken by this option.\nWi-Fi power-save mode average current would be reduced if this option is enabled.", + "id": "ESP_WIFI_SLP_IRAM_OPT", + "name": "ESP_WIFI_SLP_IRAM_OPT", + "range": null, + "title": "WiFi SLP IRAM speed optimization", + "type": "bool" + }, + { + "children": [], + "depends_on": "ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED", + "help": "Only for station in WIFI_PS_MIN_MODEM or WIFI_PS_MAX_MODEM. When the station enters the active state,\nit will work for at least ESP_WIFI_SLP_DEFAULT_MIN_ACTIVE_TIME. If a data packet is received or sent\nduring this period, the time will be refreshed. If the time is up, but the station still has packets\nto receive or send, the time will also be refreshed. unit: milliseconds.", + "id": "ESP_WIFI_SLP_DEFAULT_MIN_ACTIVE_TIME", + "name": "ESP_WIFI_SLP_DEFAULT_MIN_ACTIVE_TIME", + "range": [ + 8, + 60 + ], + "title": "Minimum active time", + "type": "int" + }, + { + "children": [], + "depends_on": "ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED", + "help": "Only for station in WIFI_PS_MIN_MODEM or WIFI_PS_MAX_MODEM. If no packet has been\nsent within ESP_WIFI_SLP_DEFAULT_MAX_ACTIVE_TIME, a null data packet will be sent\nto maintain the connection with the AP. unit: seconds.", + "id": "ESP_WIFI_SLP_DEFAULT_MAX_ACTIVE_TIME", + "name": "ESP_WIFI_SLP_DEFAULT_MAX_ACTIVE_TIME", + "range": [ + 10, + 60 + ], + "title": "Maximum keep alive time", + "type": "int" + }, + { + "children": [], + "depends_on": "ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED", + "help": "Only for station in WIFI_PS_MIN_MODEM or WIFI_PS_MAX_MODEM. When the station knows through the beacon\nthat AP will send broadcast packet, it will wait for ESP_WIFI_SLP_DEFAULT_WAIT_BROADCAST_DATA_TIME\nbefore entering the sleep process. If a broadcast packet is received with more data bits, the time\nwill refreshed. unit: milliseconds.", + "id": "ESP_WIFI_SLP_DEFAULT_WAIT_BROADCAST_DATA_TIME", + "name": "ESP_WIFI_SLP_DEFAULT_WAIT_BROADCAST_DATA_TIME", + "range": [ + 10, + 30 + ], + "title": "Minimum wait broadcast data time", + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "ESP_WIFI_FTM_ENABLE && (ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED)", + "help": null, + "id": "ESP_WIFI_FTM_INITIATOR_SUPPORT", + "name": "ESP_WIFI_FTM_INITIATOR_SUPPORT", + "range": null, + "title": "FTM Initiator support", + "type": "bool" + }, + { + "children": [], + "depends_on": "ESP_WIFI_FTM_ENABLE && (ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED)", + "help": null, + "id": "ESP_WIFI_FTM_RESPONDER_SUPPORT", + "name": "ESP_WIFI_FTM_RESPONDER_SUPPORT", + "range": null, + "title": "FTM Responder support", + "type": "bool" + } + ], + "depends_on": "SOC_WIFI_FTM_SUPPORT && (ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED)", + "help": "Enable feature Fine Timing Measurement for calculating WiFi Round-Trip-Time (RTT).", + "id": "ESP_WIFI_FTM_ENABLE", + "name": "ESP_WIFI_FTM_ENABLE", + "range": null, + "title": "WiFi FTM", + "type": "bool" + }, + { + "children": [], + "depends_on": "ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED", + "help": "Select this option to enable power_management for station when disconnected.\nChip will do modem-sleep when rf module is not in use any more.", + "id": "ESP_WIFI_STA_DISCONNECTED_PM_ENABLE", + "name": "ESP_WIFI_STA_DISCONNECTED_PM_ENABLE", + "range": null, + "title": "Power Management for station at disconnected", + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_WIFI_GCMP_SUPPORT && (ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED)", + "help": "Select this option to enable GCMP support. GCMP support is compulsory for WiFi Suite-B support.", + "id": "ESP_WIFI_GCMP_SUPPORT", + "name": "ESP_WIFI_GCMP_SUPPORT", + "range": null, + "title": "WiFi GCMP Support(GCMP128 and GCMP256)", + "type": "bool" + }, + { + "children": [], + "depends_on": "ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED", + "help": "Select this option to enable GMAC support. GMAC support is compulsory for WiFi 192 bit certification.", + "id": "ESP_WIFI_GMAC_SUPPORT", + "name": "ESP_WIFI_GMAC_SUPPORT", + "range": null, + "title": "WiFi GMAC Support(GMAC128 and GMAC256)", + "type": "bool" + }, + { + "children": [], + "depends_on": "ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED", + "help": "WiFi module can be compiled without SoftAP to save code size.", + "id": "ESP_WIFI_SOFTAP_SUPPORT", + "name": "ESP_WIFI_SOFTAP_SUPPORT", + "range": null, + "title": "WiFi SoftAP Support", + "type": "bool" + }, + { + "children": [], + "depends_on": "ESP_PHY_MAC_BB_PD && SOC_PM_SUPPORT_BEACON_WAKEUP && (ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED)", + "help": "The wifi modem automatically receives the beacon frame during light sleep.", + "id": "ESP_WIFI_ENHANCED_LIGHT_SLEEP", + "name": "ESP_WIFI_ENHANCED_LIGHT_SLEEP", + "range": null, + "title": "WiFi modem automatically receives the beacon", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "ESP_WIFI_SLP_BEACON_LOST_OPT && (ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED)", + "help": "Timeout time for close rf phy when beacon loss occurs, Unit: 1024 microsecond.", + "id": "ESP_WIFI_SLP_BEACON_LOST_TIMEOUT", + "name": "ESP_WIFI_SLP_BEACON_LOST_TIMEOUT", + "range": null, + "title": "Beacon loss timeout", + "type": "int" + }, + { + "children": [], + "depends_on": "ESP_WIFI_SLP_BEACON_LOST_OPT && (ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED)", + "help": "Maximum number of consecutive lost beacons allowed, WiFi keeps Rx state when\nthe number of consecutive beacons lost is greater than the given threshold.", + "id": "ESP_WIFI_SLP_BEACON_LOST_THRESHOLD", + "name": "ESP_WIFI_SLP_BEACON_LOST_THRESHOLD", + "range": null, + "title": "Maximum number of consecutive lost beacons allowed", + "type": "int" + }, + { + "children": [], + "depends_on": "ESP_WIFI_SLP_BEACON_LOST_OPT && SOC_WIFI_SUPPORT_VARIABLE_BEACON_WINDOW && (ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED)", + "help": "Delta early time for rf phy on, When the beacon is lost, the next rf phy on will\nbe earlier the time specified by the configuration item, Unit: 32 microsecond.", + "id": "ESP_WIFI_SLP_PHY_ON_DELTA_EARLY_TIME", + "name": "ESP_WIFI_SLP_PHY_ON_DELTA_EARLY_TIME", + "range": null, + "title": "Delta early time for RF PHY on", + "type": "int" + }, + { + "children": [], + "depends_on": "ESP_WIFI_SLP_BEACON_LOST_OPT && SOC_WIFI_SUPPORT_VARIABLE_BEACON_WINDOW && (ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED)", + "help": "Delta timeout time for rf phy off, When the beacon is lost, the next rf phy off will\nbe delayed for the time specified by the configuration item. Unit: 1024 microsecond.", + "id": "ESP_WIFI_SLP_PHY_OFF_DELTA_TIMEOUT_TIME", + "name": "ESP_WIFI_SLP_PHY_OFF_DELTA_TIMEOUT_TIME", + "range": null, + "title": "Delta timeout time for RF PHY off", + "type": "int" + } + ], + "depends_on": "ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED", + "help": "Enable wifi sleep optimization when beacon loss occurs and immediately enter\nsleep mode when the WiFi module detects beacon loss.", + "id": "ESP_WIFI_SLP_BEACON_LOST_OPT", + "name": "ESP_WIFI_SLP_BEACON_LOST_OPT", + "range": null, + "title": "Wifi sleep optimize when beacon lost", + "type": "bool" + }, + { + "children": [], + "depends_on": "ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED", + "help": "Maximum number of encrypted peers supported by espnow.\nThe number of hardware keys for encryption is fixed. And the espnow and SoftAP share the same\nhardware keys. So this configuration will affect the maximum connection number of SoftAP.\nMaximum espnow encrypted peers number + maximum number of connections of SoftAP = Max hardware\nkeys number. When using ESP mesh, this value should be set to a maximum of 6.", + "id": "ESP_WIFI_ESPNOW_MAX_ENCRYPT_NUM", + "name": "ESP_WIFI_ESPNOW_MAX_ENCRYPT_NUM", + "range": [ + 0, + 17 + ], + "title": "Maximum espnow encrypt peers number", + "type": "int" + }, + { + "children": [], + "depends_on": "SOC_WIFI_NAN_SUPPORT && (ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED)", + "help": "Enable WiFi Aware (NAN) feature.", + "id": "ESP_WIFI_NAN_ENABLE", + "name": "ESP_WIFI_NAN_ENABLE", + "range": null, + "title": "WiFi Aware", + "type": "bool" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "ESP_WIFI_MBEDTLS_TLS_CLIENT && IDF_EXPERIMENTAL_FEATURES && ESP_WIFI_MBEDTLS_CRYPTO && (ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED)", + "help": "Select this option to support EAP with TLS v1.3.\nThis configuration still supports compatibility with EAP-TLS v1.2.\nPlease note that enabling this configuration will cause every application which\nuses TLS go for TLS1.3 if server supports that. TLS1.3 is still in development in mbedtls\nand there may be interoperability issues with this. Please modify your application to set\nmax version as TLS1.2 if you want to enable TLS1.3 only for WiFi connection.", + "id": "ESP_WIFI_EAP_TLS1_3", + "name": "ESP_WIFI_EAP_TLS1_3", + "range": null, + "title": "Enable EAP-TLS v1.3 Support for WiFi Enterprise connection", + "type": "bool" + } + ], + "depends_on": "ESP_WIFI_ENTERPRISE_SUPPORT && ESP_WIFI_MBEDTLS_CRYPTO && (ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED)", + "help": "Select this option to use MbedTLS TLS client for WPA2 enterprise connection.\nPlease note that from MbedTLS-3.0 onwards, MbedTLS does not support SSL-3.0\nTLS-v1.0, TLS-v1.1 versions. In case your server is using one of these version,\nit is advisable to update your server.\nPlease disable this option for compatibility with older TLS versions.", + "id": "ESP_WIFI_MBEDTLS_TLS_CLIENT", + "name": "ESP_WIFI_MBEDTLS_TLS_CLIENT", + "range": null, + "title": "Use MbedTLS TLS client for WiFi Enterprise connection", + "type": "bool" + } + ], + "depends_on": "ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED", + "help": "Select this option to enable the use of MbedTLS crypto APIs.\nThe internal crypto support within the supplicant is limited\nand may not suffice for all new security features, including WPA3.\n\nIt is recommended to always keep this option enabled. Additionally,\nnote that MbedTLS can leverage hardware acceleration if available,\nresulting in significantly faster cryptographic operations.", + "id": "ESP_WIFI_MBEDTLS_CRYPTO", + "name": "ESP_WIFI_MBEDTLS_CRYPTO", + "range": null, + "title": "Use MbedTLS crypto APIs", + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_WIFI_WAPI_SUPPORT && (ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED)", + "help": "Select this option to enable WAPI-PSK\nwhich is a Chinese National Standard Encryption for Wireless LANs (GB 15629.11-2003).", + "id": "ESP_WIFI_WAPI_PSK", + "name": "ESP_WIFI_WAPI_PSK", + "range": null, + "title": "Enable WAPI PSK support", + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_WIFI_GCMP_SUPPORT && (ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED)", + "help": "Select this option to enable 192 bit NSA suite-B.\nThis is necessary to support WPA3 192 bit security.", + "id": "ESP_WIFI_SUITE_B_192", + "name": "ESP_WIFI_SUITE_B_192", + "range": null, + "title": "Enable NSA suite B support with 192 bit key", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "ESP_WIFI_11KV_SUPPORT && (ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED)", + "help": "Select this option to enable 802.11k APIs(RRM support).\nOnly APIs which are helpful for network assisted roaming\nare supported for now.\nEnable this option with RRM enabled in sta config\nto make device ready for network assisted roaming.\nRRM: Radio measurements enable STAs to understand the radio environment,\nit enables STAs to observe and gather data on radio link performance\nand on the radio environment. Current implementation adds beacon report,\nlink measurement, neighbor report.", + "id": "ESP_WIFI_RRM_SUPPORT", + "name": "ESP_WIFI_RRM_SUPPORT", + "range": null, + "title": "Enable 802.11k APIs Support", + "type": "bool" + }, + { + "children": [], + "depends_on": "ESP_WIFI_11KV_SUPPORT && (ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED)", + "help": "Select this option to enable 802.11v APIs(BTM support).\nOnly APIs which are helpful for network assisted roaming\nare supported for now.\nEnable this option with BTM enabled in sta config\nto make device ready for network assisted roaming.\nBTM: BSS transition management enables an AP to request a station to transition\nto a specific AP, or to indicate to a station a set of preferred APs.", + "id": "ESP_WIFI_WNM_SUPPORT", + "name": "ESP_WIFI_WNM_SUPPORT", + "range": null, + "title": "Enable 802.11v APIs Support", + "type": "bool" + } + ], + "depends_on": "ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED", + "help": "Select this option to enable 802.11k 802.11v APIs(RRM and BTM support).", + "id": "ESP_WIFI_11KV_SUPPORT", + "name": "ESP_WIFI_11KV_SUPPORT", + "range": null, + "title": "Enable 802.11k, 802.11v APIs Support", + "type": "bool" + }, + { + "children": [], + "depends_on": "ESP_WIFI_RRM_SUPPORT && (ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED)", + "help": "Keep scan results in cache, if not enabled, those\nwill be flushed immediately.", + "id": "ESP_WIFI_SCAN_CACHE", + "name": "ESP_WIFI_SCAN_CACHE", + "range": null, + "title": "Keep scan results in cache", + "type": "bool" + }, + { + "children": [], + "depends_on": "ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED", + "help": "Select this option to enable WiFi Multiband operation certification support.", + "id": "ESP_WIFI_MBO_SUPPORT", + "name": "ESP_WIFI_MBO_SUPPORT", + "range": null, + "title": "Enable Multi Band Operation Certification Support", + "type": "bool" + }, + { + "children": [ + { + "children": [ + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "ESP_WIFI_ROAMING_LOW_RSSI_ROAMING && ESP_WIFI_ENABLE_ROAMING_APP && (ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED)", + "help": "WiFi RSSI threshold to trigger roaming value in dBm (-99 to -1). Values under -30 dbm\nmight lead to a flood of low rssi events. This interferes with normal functioning and\nTX/Rx performance.", + "id": "ESP_WIFI_ROAMING_LOW_RSSI_THRESHOLD", + "name": "ESP_WIFI_ROAMING_LOW_RSSI_THRESHOLD", + "range": null, + "title": "WiFi RSSI threshold to trigger roaming", + "type": "int" + }, + { + "children": [], + "depends_on": "ESP_WIFI_ROAMING_LOW_RSSI_ROAMING && ESP_WIFI_ENABLE_ROAMING_APP && (ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED)", + "help": "Decide the offset by which to decrease the Low RSSI threshold set by ESP_WIFI_ROAMING_LOW_RSSI_THRESHOLD\nafter each failed attempt to roam. This allows for the station to keep scanning for better AP's after\nthe Low RSSI threshold is reached in a stepped manner, rather than only attempting to roam the first time\nthe current AP's RSSI breaches the set RSSI threshold.\nSetting 0 here may cause station to be flooded with low rssi events,\ntherefore that's not recommended to be kept.", + "id": "ESP_WIFI_ROAMING_LOW_RSSI_OFFSET", + "name": "ESP_WIFI_ROAMING_LOW_RSSI_OFFSET", + "range": null, + "title": "Offset by which to reset the RSSI Threshold after attempt to roam.", + "type": "int" + } + ], + "depends_on": "ESP_WIFI_ENABLE_ROAMING_APP && (ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED)", + "help": "Enable to use a RSSI threshold to trigger roaming.", + "id": "ESP_WIFI_ROAMING_LOW_RSSI_ROAMING", + "name": "ESP_WIFI_ROAMING_LOW_RSSI_ROAMING", + "range": null, + "title": "Use Low RSSI to trigger roaming.", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "ESP_WIFI_ROAMING_PERIODIC_SCAN_MONITOR && ESP_WIFI_ENABLE_ROAMING_APP && (ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED)", + "help": "Threshold at which the station will begin scanning to find an AP with better RSSI.", + "id": "ESP_WIFI_ROAMING_PERIODIC_SCAN_THRESHOLD", + "name": "ESP_WIFI_ROAMING_PERIODIC_SCAN_THRESHOLD", + "range": null, + "title": "Threshold at which to begin periodic scanning for a better AP.", + "type": "int" + }, + { + "children": [], + "depends_on": "ESP_WIFI_ROAMING_PERIODIC_SCAN_MONITOR && ESP_WIFI_ENABLE_ROAMING_APP && (ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED)", + "help": "Intervals at which station will periodically scan to check if better AP is available", + "id": "ESP_WIFI_ROAMING_SCAN_MONITOR_INTERVAL", + "name": "ESP_WIFI_ROAMING_SCAN_MONITOR_INTERVAL", + "range": null, + "title": "Time intervals (in seconds) at which station will initiate a scan", + "type": "int" + }, + { + "children": [], + "depends_on": "ESP_WIFI_ROAMING_PERIODIC_SCAN_MONITOR && ESP_WIFI_ENABLE_ROAMING_APP && (ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED)", + "help": "Minimum RSSI difference b/w current AP and a potential roaming candidate AP\nto trigger a roaming attempt.", + "id": "ESP_WIFI_ROAMING_SCAN_ROAM_RSSI_DIFF", + "name": "ESP_WIFI_ROAMING_SCAN_ROAM_RSSI_DIFF", + "range": null, + "title": "RSSI difference b/w current AP and candidate AP to initiate connection", + "type": "int" + } + ], + "depends_on": "ESP_WIFI_ENABLE_ROAMING_APP && (ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED)", + "help": "Conduct periodic scans periodically to check if a better AP is available.", + "id": "ESP_WIFI_ROAMING_PERIODIC_SCAN_MONITOR", + "name": "ESP_WIFI_ROAMING_PERIODIC_SCAN_MONITOR", + "range": null, + "title": "Conduct periodic scans to check if a better AP is available", + "type": "bool" + } + ], + "depends_on": "ESP_WIFI_ENABLE_ROAMING_APP && (ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED)", + "id": "component-config-wi-fi-advanced-support-for-wi-fi-roaming-experimental--configure-roaming-app-roaming-triggers", + "title": "Roaming triggers", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": "ESP_WIFI_ENABLE_ROAMING_APP && (ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED)", + "help": "Roaming between APs that do not support 802.11v.\nThis will allow station to roam even when connection is not BTM supported,\nby forcefully disconnecting from current AP and connecting to better AP.", + "id": "ESP_WIFI_ROAMING_LEGACY_ROAMING", + "name": "ESP_WIFI_ROAMING_LEGACY_ROAMING", + "range": null, + "title": "Support Legacy roaming approach", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "ESP_WIFI_ROAMING_NETWORK_ASSISTED_ROAM && ESP_WIFI_ROAMING_LEGACY_ROAMING && ESP_WIFI_ENABLE_ROAMING_APP && (ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED)", + "help": "Retry threshold after which the station should stop using Network Assisted\nroaming methods and start using legacy roaming instead.", + "id": "ESP_WIFI_NETWORK_ASSISTED_ROAMING_RETRY_COUNT", + "name": "ESP_WIFI_NETWORK_ASSISTED_ROAMING_RETRY_COUNT", + "range": null, + "title": "Retry count after which to switch to legacy roaming", + "type": "int" + } + ], + "depends_on": "ESP_WIFI_WNM_SUPPORT && ESP_WIFI_ENABLE_ROAMING_APP && (ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED)", + "help": "Roaming between APs using network assisted Roaming.\nThis involves BSS Transition Management mechanisms outlined in 802.11v.\nNote that this moves the responsibility to the AP's network, and hence isn't\nguaranteed to cause the station to attempt to roam each time.", + "id": "ESP_WIFI_ROAMING_NETWORK_ASSISTED_ROAM", + "name": "ESP_WIFI_ROAMING_NETWORK_ASSISTED_ROAM", + "range": null, + "title": "Support Network Assisted roaming using 802.11v", + "type": "bool" + } + ], + "depends_on": "ESP_WIFI_ENABLE_ROAMING_APP && (ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED)", + "id": "component-config-wi-fi-advanced-support-for-wi-fi-roaming-experimental--configure-roaming-app-roaming-methods", + "title": "Roaming Methods", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": "ESP_WIFI_ENABLE_ROAMING_APP && (ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED)", + "help": "Minimum duration of active scanning per channel in milliseconds.", + "id": "ESP_WIFI_ROAMING_SCAN_MIN_SCAN_TIME", + "name": "ESP_WIFI_ROAMING_SCAN_MIN_SCAN_TIME", + "range": null, + "title": "Minimum duration (in milliseconds) of station's per channel active scan", + "type": "int" + }, + { + "children": [], + "depends_on": "ESP_WIFI_ENABLE_ROAMING_APP && (ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED)", + "help": "Maximum duration of active scanning per channel in milliseconds.", + "id": "ESP_WIFI_ROAMING_SCAN_MAX_SCAN_TIME", + "name": "ESP_WIFI_ROAMING_SCAN_MAX_SCAN_TIME", + "range": null, + "title": "Maximum duration (in milliseconds) of station's per channel active scan time", + "type": "int" + }, + { + "children": [], + "depends_on": "ESP_WIFI_ENABLE_ROAMING_APP && (ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED)", + "help": "If connected, duration for which the station will return to it's home channel for Tx/Rx of\nframes stored in buffers between scanning on consecutive channels.", + "id": "ESP_WIFI_ROAMING_HOME_CHANNEL_DWELL_TIME", + "name": "ESP_WIFI_ROAMING_HOME_CHANNEL_DWELL_TIME", + "range": null, + "title": "Home channel dwell time scanning between consecutive channels", + "type": "int" + }, + { + "children": [], + "depends_on": "ESP_WIFI_ENABLE_ROAMING_APP && (ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED)", + "help": "Channels your wireless network operates on to allow for faster scanning.\nSpecify the channels(between 1-14) in a comma separated manner.", + "id": "ESP_WIFI_ROAMING_SCAN_CHAN_LIST", + "name": "ESP_WIFI_ROAMING_SCAN_CHAN_LIST", + "range": null, + "title": "Preferred channel list for scanning", + "type": "string" + }, + { + "children": [], + "depends_on": "ESP_WIFI_ENABLE_ROAMING_APP && (ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED)", + "help": "Duration for which the results from the most recent scans can be used\nby the roaming app for determining the roaming candidates.", + "id": "ESP_WIFI_ROAMING_SCAN_EXPIRY_WINDOW", + "name": "ESP_WIFI_ROAMING_SCAN_EXPIRY_WINDOW", + "range": null, + "title": "Scan results expiry window (in seconds)", + "type": "int" + }, + { + "children": [], + "depends_on": "ESP_WIFI_ENABLE_ROAMING_APP && (ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED)", + "help": "Max candidates that can be considered while scanning as a part of the\nnetwork at one time.", + "id": "ESP_WIFI_ROAMING_MAX_CANDIDATES", + "name": "ESP_WIFI_ROAMING_MAX_CANDIDATES", + "range": null, + "title": "Max Candidates in the network", + "type": "int" + } + ], + "depends_on": "ESP_WIFI_ENABLE_ROAMING_APP && (ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED)", + "id": "component-config-wi-fi-advanced-support-for-wi-fi-roaming-experimental--configure-roaming-app-scan-configuration", + "title": "Scan Configuration", + "type": "menu" + }, + { + "children": [], + "depends_on": "ESP_WIFI_ENABLE_ROAMING_APP && (ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED)", + "help": "Time to wait (in seconds) by station before registering for the RSSI event again\nor start continuous montoring to find better AP.", + "id": "ESP_WIFI_ROAMING_BACKOFF_TIME", + "name": "ESP_WIFI_ROAMING_BACKOFF_TIME", + "range": null, + "title": "Default time to wait between subsequent roaming attempts.", + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "ESP_WIFI_ROAMING_PERIODIC_RRM_MONITORING && ESP_WIFI_ENABLE_ROAMING_APP && (ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED)", + "help": "Enable this to send periodic neighbor report requests to the AP.\nThese neighbor report requests provide information about other APs in the same managed\nnetwork. This information is used for more intelligent roaming.", + "id": "ESP_WIFI_ROAMING_RRM_MONITOR_TIME", + "name": "ESP_WIFI_ROAMING_RRM_MONITOR_TIME", + "range": null, + "title": "Time interval (in seconds) between neighbor report requests to an AP", + "type": "int" + }, + { + "children": [], + "depends_on": "ESP_WIFI_ROAMING_PERIODIC_RRM_MONITORING && ESP_WIFI_ENABLE_ROAMING_APP && (ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED)", + "help": "The RSSI threshold beyond which we start sending periodic neighbor report requests.", + "id": "ESP_WIFI_ROAMING_RRM_MONITOR_THRESHOLD", + "name": "ESP_WIFI_ROAMING_RRM_MONITOR_THRESHOLD", + "range": null, + "title": "Threshold for sending periodic neighbor report requests", + "type": "int" + } + ], + "depends_on": "ESP_WIFI_RRM_SUPPORT && ESP_WIFI_ENABLE_ROAMING_APP && (ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED)", + "help": "This option will enable station to keep sending RRM neighbor list request to AP and\nupdate its internal list.", + "id": "ESP_WIFI_ROAMING_PERIODIC_RRM_MONITORING", + "name": "ESP_WIFI_ROAMING_PERIODIC_RRM_MONITORING", + "range": null, + "title": "Send periodic neighbor report request to AP for internal list updation", + "type": "bool" + } + ], + "depends_on": "ESP_WIFI_ENABLE_ROAMING_APP && (ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED)", + "id": "component-config-wi-fi-advanced-support-for-wi-fi-roaming-experimental--configure-roaming-app", + "title": "Configure roaming App", + "type": "menu" + } + ], + "depends_on": "IDF_EXPERIMENTAL_FEATURES && (ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED)", + "help": "Enable Espressif's roaming app to allow for efficient Wi-Fi roaming.\nThis includes configurable periodic environment scans, maintaining a cache of the\nbest APs, handling low rssi events etc.\n\nRisk Warning\nPlease note that this feature is still experimental and enabling this potentially can\nlead to unpredictable scanning, connection and roaming attempts.\nWe are still working on tuning and optimising this feature to ensure reliable and stable use.", + "id": "ESP_WIFI_ENABLE_ROAMING_APP", + "name": "ESP_WIFI_ENABLE_ROAMING_APP", + "range": null, + "title": "Advanced support for Wi-Fi Roaming (Experimental)", + "type": "bool" + }, + { + "children": [], + "depends_on": "ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED", + "help": "Select this option to enable WiFi Easy Connect Support.", + "id": "ESP_WIFI_DPP_SUPPORT", + "name": "ESP_WIFI_DPP_SUPPORT", + "range": null, + "title": "Enable DPP support", + "type": "bool" + }, + { + "children": [], + "depends_on": "ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED", + "help": "Select this option to enable WiFi Fast Transition Support.", + "id": "ESP_WIFI_11R_SUPPORT", + "name": "ESP_WIFI_11R_SUPPORT", + "range": null, + "title": "Enable 802.11R (Fast Transition) Support", + "type": "bool" + }, + { + "children": [], + "depends_on": "ESP_WIFI_SOFTAP_SUPPORT && (ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED)", + "help": "Select this option to enable WPS registrar support in softAP mode.", + "id": "ESP_WIFI_WPS_SOFTAP_REGISTRAR", + "name": "ESP_WIFI_WPS_SOFTAP_REGISTRAR", + "range": null, + "title": "Add WPS Registrar support in SoftAP mode", + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_WIFI_HE_SUPPORT && (ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED)", + "help": "Enable Wi-Fi transmission statistics. Total support 4 access category. Each access category\nwill use 346 bytes memory.", + "id": "ESP_WIFI_ENABLE_WIFI_TX_STATS", + "name": "ESP_WIFI_ENABLE_WIFI_TX_STATS", + "range": null, + "title": "Enable Wi-Fi transmission statistics", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "ESP_WIFI_ENABLE_WIFI_RX_STATS && (ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED)", + "help": "Enable Wi-Fi DL MU-MIMO and DL OFDMA reception statistics. Will use 10932 bytes memory.", + "id": "ESP_WIFI_ENABLE_WIFI_RX_MU_STATS", + "name": "ESP_WIFI_ENABLE_WIFI_RX_MU_STATS", + "range": null, + "title": "Enable Wi-Fi DL MU-MIMO and DL OFDMA reception statistics", + "type": "bool" + } + ], + "depends_on": "SOC_WIFI_HE_SUPPORT && (ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED)", + "help": "Enable Wi-Fi reception statistics. Total support 2 access category. Each access category\nwill use 190 bytes memory.", + "id": "ESP_WIFI_ENABLE_WIFI_RX_STATS", + "name": "ESP_WIFI_ENABLE_WIFI_RX_STATS", + "range": null, + "title": "Enable Wi-Fi reception statistics", + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_WIFI_HE_SUPPORT && (ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED)", + "help": "Set the maximum number of queue that can be aggregated by the STA in the A-MPDU carried in the\nHE TB PPDU.", + "id": "ESP_WIFI_TX_HETB_QUEUE_NUM", + "name": "ESP_WIFI_TX_HETB_QUEUE_NUM", + "range": null, + "title": "WiFi TX HE TB QUEUE number for STA HE TB PPDU transmission", + "type": "int" + }, + { + "children": [], + "depends_on": "SOC_WIFI_SUPPORT_5G && (ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED)", + "help": "Enable Wi-Fi dump HE-SIGB which is contained in DL HE MU PPDUs.", + "id": "ESP_WIFI_ENABLE_DUMP_HESIGB", + "name": "ESP_WIFI_ENABLE_DUMP_HESIGB", + "range": null, + "title": "Enable Wi-Fi dump HE-SIGB which is contained in DL HE MU PPDUs", + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_WIFI_SUPPORT_5G && (ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED)", + "help": "Enable Wi-Fi dump MU CFO.", + "id": "ESP_WIFI_ENABLE_DUMP_MU_CFO", + "name": "ESP_WIFI_ENABLE_DUMP_MU_CFO", + "range": null, + "title": "Enable Wi-Fi dump MU CFO", + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_WIFI_SUPPORT_5G && (ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED)", + "help": "Enable Wi-Fi dump NDPA frames.", + "id": "ESP_WIFI_ENABLE_DUMP_CTRL_NDPA", + "name": "ESP_WIFI_ENABLE_DUMP_CTRL_NDPA", + "range": null, + "title": "Enable Wi-Fi dump NDPA frames", + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_WIFI_SUPPORT_5G && (ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED)", + "help": "Enable Wi-Fi dump BFRP frames.", + "id": "ESP_WIFI_ENABLE_DUMP_CTRL_BFRP", + "name": "ESP_WIFI_ENABLE_DUMP_CTRL_BFRP", + "range": null, + "title": "Enable Wi-Fi dump BFRP frames", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED", + "help": "Select this option to enable validate each WPS attribute\nrigorously. Disabling this add the workarounds with various APs.\nEnabling this may cause inter operability issues with some APs.", + "id": "ESP_WIFI_WPS_STRICT", + "name": "ESP_WIFI_WPS_STRICT", + "range": null, + "title": "Strictly validate all WPS attributes", + "type": "bool" + }, + { + "children": [], + "depends_on": "ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED", + "help": "Select this option to get passphrase during WPS configuration.\nThis option fakes the virtual display capabilities to get the\nconfiguration in passphrase mode.\nNot recommended to be used since WPS credentials should not\nbe shared to other devices, making it in readable format increases\nthat risk, also passphrase requires pbkdf2 to convert in psk.", + "id": "ESP_WIFI_WPS_PASSPHRASE", + "name": "ESP_WIFI_WPS_PASSPHRASE", + "range": null, + "title": "Get WPA2 passphrase in WPS config", + "type": "bool" + } + ], + "depends_on": "ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED", + "id": "component-config-wi-fi-wps-configuration-options", + "title": "WPS Configuration Options", + "type": "menu" + }, + { + "children": [], + "depends_on": "ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED", + "help": "Select this option to print logging information from WPA supplicant,\nthis includes handshake information and key hex dumps depending\non the project logging level.\n\nEnabling this could increase the build size ~60kb\ndepending on the project logging level.", + "id": "ESP_WIFI_DEBUG_PRINT", + "name": "ESP_WIFI_DEBUG_PRINT", + "range": null, + "title": "Print debug messages from WPA Supplicant", + "type": "bool" + }, + { + "children": [], + "depends_on": "ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED", + "help": "Select this to enable unity test for DPP.", + "id": "ESP_WIFI_TESTING_OPTIONS", + "name": "ESP_WIFI_TESTING_OPTIONS", + "range": null, + "title": "Add DPP testing code", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "ESP_WIFI_ENTERPRISE_SUPPORT && (ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED)", + "help": "Select this configuration to free dynamic buffers during WiFi enterprise connection.\nThis will enable chip to reduce heap consumption during WiFi enterprise connection.", + "id": "ESP_WIFI_ENT_FREE_DYNAMIC_BUFFER", + "name": "ESP_WIFI_ENT_FREE_DYNAMIC_BUFFER", + "range": null, + "title": "Free dynamic buffers during WiFi enterprise connection", + "type": "bool" + } + ], + "depends_on": "ESP_WIFI_ENABLED || ESP_HOST_WIFI_ENABLED", + "help": "Select this to enable/disable enterprise connection support.\n\ndisabling this will reduce binary size.\ndisabling this will disable the use of any esp_wifi_sta_wpa2_ent_* (as APIs will be meaningless)\n\nNote that when using bigger certificates on low-power chips without crypto\nhardware acceleration, it is recommended to adjust the task watchdog timer (TWDT)\nif it is enabled. For precise information on timing requirements, you can check\nperformance numbers at https://github.com/espressif/mbedtls/wiki/Performance-Numbers.", + "id": "ESP_WIFI_ENTERPRISE_SUPPORT", + "name": "ESP_WIFI_ENTERPRISE_SUPPORT", + "range": null, + "title": "Enable enterprise option", + "type": "bool" + } + ], + "depends_on": null, + "id": "component-config-wi-fi", + "title": "Wi-Fi", + "type": "menu" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "ESP_COREDUMP_ENABLE_TO_FLASH", + "name": "ESP_COREDUMP_ENABLE_TO_FLASH", + "range": null, + "title": "Flash", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "ESP_COREDUMP_ENABLE_TO_UART", + "name": "ESP_COREDUMP_ENABLE_TO_UART", + "range": null, + "title": "UART", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "ESP_COREDUMP_ENABLE_TO_NONE", + "name": "ESP_COREDUMP_ENABLE_TO_NONE", + "range": null, + "title": "None", + "type": "bool" + } + ], + "depends_on": null, + "help": "Select place to store core dump: flash, uart or none (to disable core dumps generation).\n\nCore dumps to Flash are not available if PSRAM is used for task stacks.\n\nIf core dump is configured to be stored in flash and custom partition table is used add\ncorresponding entry to your CSV. For examples, please see predefined partition table CSV descriptions\nin the components/partition_table directory.", + "id": "component-config-core-dump-data-destination", + "name": "ESP_COREDUMP_TO_FLASH_OR_UART", + "title": "Data destination", + "type": "choice" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "ESP_COREDUMP_DATA_FORMAT_BIN", + "name": "ESP_COREDUMP_DATA_FORMAT_BIN", + "range": null, + "title": "Binary format", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "ESP_COREDUMP_DATA_FORMAT_ELF", + "name": "ESP_COREDUMP_DATA_FORMAT_ELF", + "range": null, + "title": "ELF format", + "type": "bool" + } + ], + "depends_on": "!ESP_COREDUMP_ENABLE_TO_NONE", + "help": "Select the data format for core dump.", + "id": "component-config-core-dump-core-dump-data-format", + "name": "ESP_COREDUMP_DATA_FORMAT", + "title": "Core dump data format", + "type": "choice" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "ESP_COREDUMP_CHECKSUM_CRC32", + "name": "ESP_COREDUMP_CHECKSUM_CRC32", + "range": null, + "title": "Use CRC32 for integrity verification", + "type": "bool" + }, + { + "children": [], + "depends_on": "ESP_COREDUMP_DATA_FORMAT_ELF && ", + "help": null, + "id": "ESP_COREDUMP_CHECKSUM_SHA256", + "name": "ESP_COREDUMP_CHECKSUM_SHA256", + "range": null, + "title": "Use SHA256 for integrity verification", + "type": "bool" + } + ], + "depends_on": "!ESP_COREDUMP_ENABLE_TO_NONE", + "help": "Select the integrity check for the core dump.", + "id": "component-config-core-dump-core-dump-data-integrity-check", + "name": "ESP_COREDUMP_CHECKSUM", + "title": "Core dump data integrity check", + "type": "choice" + }, + { + "children": [], + "depends_on": "ESP_COREDUMP_DATA_FORMAT_ELF", + "help": "Storing these sections can help with easier debugging and troubleshooting.\nHowever, additional storage space will be required in the core dump partition.\nAt least 128KB should be reserved, but the actual amount required may vary based\non the application's DRAM usage.\nNote that sections located in external RAM will not be stored.", + "id": "ESP_COREDUMP_CAPTURE_DRAM", + "name": "ESP_COREDUMP_CAPTURE_DRAM", + "range": null, + "title": "Include whole .bss and .data sections and heap data into core dump file", + "type": "bool" + }, + { + "children": [], + "depends_on": "ESP_COREDUMP_ENABLE_TO_FLASH", + "help": "When enabled, if any data are found on the flash core dump partition,\nthey will be checked by calculating their checksum.", + "id": "ESP_COREDUMP_CHECK_BOOT", + "name": "ESP_COREDUMP_CHECK_BOOT", + "range": null, + "title": "Check core dump data integrity on boot", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Enables/disable core dump module.", + "id": "ESP_COREDUMP_ENABLE", + "name": "ESP_COREDUMP_ENABLE", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": "ESP_COREDUMP_ENABLE", + "help": "Enable/disable coredump logs. Logs strings from espcoredump component are\nplaced in DRAM. Disabling these helps to save ~5KB of internal memory.", + "id": "ESP_COREDUMP_LOGS", + "name": "ESP_COREDUMP_LOGS", + "range": null, + "title": "Enable coredump logs for debugging", + "type": "bool" + }, + { + "children": [], + "depends_on": "ESP_COREDUMP_ENABLE", + "help": "Maximum number of tasks snapshots in core dump.", + "id": "ESP_COREDUMP_MAX_TASKS_NUM", + "name": "ESP_COREDUMP_MAX_TASKS_NUM", + "range": null, + "title": "Maximum number of tasks", + "type": "int" + }, + { + "children": [], + "depends_on": "ESP_COREDUMP_ENABLE_TO_UART", + "help": "Config delay (in ms) before printing core dump to UART.\nDelay can be interrupted by pressing Enter key.", + "id": "ESP_COREDUMP_UART_DELAY", + "name": "ESP_COREDUMP_UART_DELAY", + "range": null, + "title": "Delay before print to UART", + "type": "int" + }, + { + "children": [], + "depends_on": "ESP_COREDUMP_ENABLE_TO_FLASH", + "help": "Don't overwrite an existing core dump already present in flash.\nEnable this option to only keep the first of multiple core dumps.\n\nIf enabled, the core dump partition must be erased before the first\ncore dump can be written.", + "id": "ESP_COREDUMP_FLASH_NO_OVERWRITE", + "name": "ESP_COREDUMP_FLASH_NO_OVERWRITE", + "range": null, + "title": "Don't overwrite existing core dump", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Force the use of a custom DRAM stack for coredump when Task stacks can be in PSRAM.", + "id": "ESP_COREDUMP_USE_STACK_SIZE", + "name": "ESP_COREDUMP_USE_STACK_SIZE", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": "ESP_COREDUMP_ENABLE", + "help": "Size of the memory to be reserved for core dump stack. If 0 core dump process will run on\nthe stack of crashed task/ISR, otherwise special stack will be allocated.\nTo ensure that core dump itself will not overflow task/ISR stack set this to the value around 1300-1800\ndepending on the chosen checksum calculation method. SHA256 method needs more stack space than CRC32.\nNOTE: It eats DRAM.", + "id": "ESP_COREDUMP_STACK_SIZE", + "name": "ESP_COREDUMP_STACK_SIZE", + "range": null, + "title": "Reserved stack size", + "type": "int" + }, + { + "children": [], + "depends_on": "ESP_COREDUMP_DATA_FORMAT_ELF && ESP_COREDUMP_ENABLE_TO_FLASH && IDF_TARGET_ARCH_RISCV", + "help": "Size of the buffer that would be reserved for extracting backtrace info summary.\nThis buffer will contain the stack dump of the crashed task. This dump is useful in generating backtrace", + "id": "ESP_COREDUMP_SUMMARY_STACKDUMP_SIZE", + "name": "ESP_COREDUMP_SUMMARY_STACKDUMP_SIZE", + "range": null, + "title": "Size of the stack dump buffer", + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "ESP_COREDUMP_DECODE_INFO", + "name": "ESP_COREDUMP_DECODE_INFO", + "range": null, + "title": "Decode and show summary (info_corefile)", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "ESP_COREDUMP_DECODE_DISABLE", + "name": "ESP_COREDUMP_DECODE_DISABLE", + "range": null, + "title": "Don't decode", + "type": "bool" + } + ], + "depends_on": "ESP_COREDUMP_ENABLE_TO_UART", + "help": null, + "id": "component-config-core-dump-handling-of-uart-core-dumps-in-idf-monitor", + "name": "ESP_COREDUMP_DECODE", + "title": "Handling of UART core dumps in IDF Monitor", + "type": "choice" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "ESP_COREDUMP_DECODE", + "name": "ESP_COREDUMP_DECODE", + "range": null, + "title": null, + "type": "string" + } + ], + "depends_on": null, + "id": "component-config-core-dump", + "title": "Core dump", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": null, + "help": "Number of volumes (logical drives) to use.", + "id": "FATFS_VOLUME_COUNT", + "name": "FATFS_VOLUME_COUNT", + "range": [ + 1, + 10 + ], + "title": "Number of volumes", + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "FATFS_LFN_NONE", + "name": "FATFS_LFN_NONE", + "range": null, + "title": "No long filenames", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "FATFS_LFN_HEAP", + "name": "FATFS_LFN_HEAP", + "range": null, + "title": "Long filename buffer in heap", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "FATFS_LFN_STACK", + "name": "FATFS_LFN_STACK", + "range": null, + "title": "Long filename buffer on stack", + "type": "bool" + } + ], + "depends_on": null, + "help": "Support long filenames in FAT. Long filename data increases\nmemory usage. FATFS can be configured to store the buffer for\nlong filename data in stack or heap.", + "id": "component-config-fat-filesystem-support-long-filename-support", + "name": "FATFS_LONG_FILENAMES", + "title": "Long filename support", + "type": "choice" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "FATFS_SECTOR_512", + "name": "FATFS_SECTOR_512", + "range": null, + "title": "512", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "FATFS_SECTOR_4096", + "name": "FATFS_SECTOR_4096", + "range": null, + "title": "4096", + "type": "bool" + } + ], + "depends_on": null, + "help": "Specify the size of the sector in bytes for FATFS partition generator.", + "id": "component-config-fat-filesystem-support-sector-size", + "name": "FATFS_SECTOR_SIZE", + "title": "Sector size", + "type": "choice" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "FATFS_CODEPAGE_DYNAMIC", + "name": "FATFS_CODEPAGE_DYNAMIC", + "range": null, + "title": "Dynamic (all code pages supported)", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "FATFS_CODEPAGE_437", + "name": "FATFS_CODEPAGE_437", + "range": null, + "title": "US (CP437)", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "FATFS_CODEPAGE_720", + "name": "FATFS_CODEPAGE_720", + "range": null, + "title": "Arabic (CP720)", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "FATFS_CODEPAGE_737", + "name": "FATFS_CODEPAGE_737", + "range": null, + "title": "Greek (CP737)", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "FATFS_CODEPAGE_771", + "name": "FATFS_CODEPAGE_771", + "range": null, + "title": "KBL (CP771)", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "FATFS_CODEPAGE_775", + "name": "FATFS_CODEPAGE_775", + "range": null, + "title": "Baltic (CP775)", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "FATFS_CODEPAGE_850", + "name": "FATFS_CODEPAGE_850", + "range": null, + "title": "Latin 1 (CP850)", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "FATFS_CODEPAGE_852", + "name": "FATFS_CODEPAGE_852", + "range": null, + "title": "Latin 2 (CP852)", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "FATFS_CODEPAGE_855", + "name": "FATFS_CODEPAGE_855", + "range": null, + "title": "Cyrillic (CP855)", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "FATFS_CODEPAGE_857", + "name": "FATFS_CODEPAGE_857", + "range": null, + "title": "Turkish (CP857)", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "FATFS_CODEPAGE_860", + "name": "FATFS_CODEPAGE_860", + "range": null, + "title": "Portuguese (CP860)", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "FATFS_CODEPAGE_861", + "name": "FATFS_CODEPAGE_861", + "range": null, + "title": "Icelandic (CP861)", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "FATFS_CODEPAGE_862", + "name": "FATFS_CODEPAGE_862", + "range": null, + "title": "Hebrew (CP862)", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "FATFS_CODEPAGE_863", + "name": "FATFS_CODEPAGE_863", + "range": null, + "title": "Canadian French (CP863)", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "FATFS_CODEPAGE_864", + "name": "FATFS_CODEPAGE_864", + "range": null, + "title": "Arabic (CP864)", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "FATFS_CODEPAGE_865", + "name": "FATFS_CODEPAGE_865", + "range": null, + "title": "Nordic (CP865)", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "FATFS_CODEPAGE_866", + "name": "FATFS_CODEPAGE_866", + "range": null, + "title": "Russian (CP866)", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "FATFS_CODEPAGE_869", + "name": "FATFS_CODEPAGE_869", + "range": null, + "title": "Greek 2 (CP869)", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "FATFS_CODEPAGE_932", + "name": "FATFS_CODEPAGE_932", + "range": null, + "title": "Japanese (DBCS) (CP932)", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "FATFS_CODEPAGE_936", + "name": "FATFS_CODEPAGE_936", + "range": null, + "title": "Simplified Chinese (DBCS) (CP936)", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "FATFS_CODEPAGE_949", + "name": "FATFS_CODEPAGE_949", + "range": null, + "title": "Korean (DBCS) (CP949)", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "FATFS_CODEPAGE_950", + "name": "FATFS_CODEPAGE_950", + "range": null, + "title": "Traditional Chinese (DBCS) (CP950)", + "type": "bool" + } + ], + "depends_on": null, + "help": "OEM code page used for file name encodings.\n\nIf \"Dynamic\" is selected, code page can be chosen at runtime using\nf_setcp function. Note that choosing this option will increase\napplication size by ~480kB.", + "id": "component-config-fat-filesystem-support-oem-code-page", + "name": "FATFS_CHOOSE_CODEPAGE", + "title": "OEM Code Page", + "type": "choice" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "FATFS_CODEPAGE", + "name": "FATFS_CODEPAGE", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": "!FATFS_LFN_NONE", + "help": "Maximum long filename length. Can be reduced to save RAM.", + "id": "FATFS_MAX_LFN", + "name": "FATFS_MAX_LFN", + "range": null, + "title": "Max long filename length", + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "FATFS_API_ENCODING_ANSI_OEM", + "name": "FATFS_API_ENCODING_ANSI_OEM", + "range": null, + "title": "API uses ANSI/OEM encoding", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "FATFS_API_ENCODING_UTF_8", + "name": "FATFS_API_ENCODING_UTF_8", + "range": null, + "title": "API uses UTF-8 encoding", + "type": "bool" + } + ], + "depends_on": "!FATFS_LFN_NONE", + "help": "Choose encoding for character and string arguments/returns when using\nFATFS APIs. The encoding of arguments will usually depend on text\neditor settings.", + "id": "component-config-fat-filesystem-support-api-character-encoding", + "name": "FATFS_API_ENCODING", + "title": "API character encoding", + "type": "choice" + }, + { + "children": [], + "depends_on": null, + "help": "This option sets the FATFS configuration value _FS_LOCK.\nThe option _FS_LOCK switches file lock function to control duplicated file open\nand illegal operation to open objects.\n\n* 0: Disable file lock function. To avoid volume corruption, application\nshould avoid illegal open, remove and rename to the open objects.\n\n* >0: Enable file lock function. The value defines how many files/sub-directories\ncan be opened simultaneously under file lock control.\n\nNote that the file lock control is independent of re-entrancy.", + "id": "FATFS_FS_LOCK", + "name": "FATFS_FS_LOCK", + "range": [ + 0, + 65535 + ], + "title": "Number of simultaneously open files protected by lock function", + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": "This option sets FATFS configuration value _FS_TIMEOUT, scaled to milliseconds.\nSets the number of milliseconds FATFS will wait to acquire a mutex when\noperating on an open file. For example, if one task is performing a lengthy\noperation, another task will wait for the first task to release the lock,\nand time out after amount of time set by this option.", + "id": "FATFS_TIMEOUT_MS", + "name": "FATFS_TIMEOUT_MS", + "range": null, + "title": "Timeout for acquiring a file lock, ms", + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": "This option affects FATFS configuration value _FS_TINY.\n\nIf this option is set, _FS_TINY is 0, and each open file has its own cache,\nsize of the cache is equal to the _MAX_SS variable (512 or 4096 bytes).\nThis option uses more RAM if more than 1 file is open, but needs less reads\nand writes to the storage for some operations.\n\nIf this option is not set, _FS_TINY is 1, and single cache is used for\nall open files, size is also equal to _MAX_SS variable. This reduces the\namount of heap used when multiple files are open, but increases the number\nof read and write operations which FATFS needs to make.", + "id": "FATFS_PER_FILE_CACHE", + "name": "FATFS_PER_FILE_CACHE", + "range": null, + "title": "Use separate cache for each file", + "type": "bool" + }, + { + "children": [], + "depends_on": "SPIRAM_USE_CAPS_ALLOC || SPIRAM_USE_MALLOC", + "help": "When the option is enabled, internal buffers used by FATFS will be allocated\nfrom external RAM. If the allocation from external RAM fails, the buffer will\nbe allocated from the internal RAM.\nDisable this option if optimizing for performance. Enable this option if\noptimizing for internal memory size.", + "id": "FATFS_ALLOC_PREFER_EXTRAM", + "name": "FATFS_ALLOC_PREFER_EXTRAM", + "range": null, + "title": "Prefer external RAM when allocating FATFS buffers", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "The fast seek feature enables fast backward/long seek operations without\nFAT access by using an in-memory CLMT (cluster link map table).\nPlease note, fast-seek is only allowed for read-mode files, if a\nfile is opened in write-mode, the seek mechanism will automatically fallback\nto the default implementation.", + "id": "FATFS_USE_FASTSEEK", + "name": "FATFS_USE_FASTSEEK", + "range": null, + "title": "Enable fast seek algorithm when using lseek function through VFS FAT", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "FATFS_USE_STRFUNC_NONE", + "name": "FATFS_USE_STRFUNC_NONE", + "range": null, + "title": "0:Disable", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "FATFS_USE_STRFUNC_WITHOUT_CRLF_CONV", + "name": "FATFS_USE_STRFUNC_WITHOUT_CRLF_CONV", + "range": null, + "title": "1:Enable without LF-CRLF conversion", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "FATFS_USE_STRFUNC_WITH_CRLF_CONV", + "name": "FATFS_USE_STRFUNC_WITH_CRLF_CONV", + "range": null, + "title": "2:Enable with LF-CRLF conversion", + "type": "bool" + } + ], + "depends_on": null, + "help": "These are specialized alternatives to stdio functions for working\ndirectly with FATFS without VFS. Legacy code may need functions,\nbut for new development, it is advised to use stdio under VFS.\n\n0: Disable. FF_PRINT_LLI, FF_PRINT_FLOAT and FF_STRF_ENCODE have no effect.\n1: Enable without LF-CRLF conversion.\n2: Enable with LF-CRLF conversion.", + "id": "component-config-fat-filesystem-support-enable-string-functions-f_gets-f_putc-f_puts-and-f_printf-", + "name": "FATFS_USE_STRFUNC_CHOICE", + "title": "Enable string functions, f_gets(), f_putc(), f_puts() and f_printf()", + "type": "choice" + }, + { + "children": [], + "depends_on": "!FATFS_USE_STRFUNC_NONE", + "help": null, + "id": "FATFS_PRINT_LLI", + "name": "FATFS_PRINT_LLI", + "range": null, + "title": "Make fatfs f_printf() support long long argument", + "type": "bool" + }, + { + "children": [], + "depends_on": "!FATFS_USE_STRFUNC_NONE", + "help": null, + "id": "FATFS_PRINT_FLOAT", + "name": "FATFS_PRINT_FLOAT", + "range": null, + "title": "Make fatfs f_printf() support floating point argument", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "FATFS_STRF_ENCODE_ANSI", + "name": "FATFS_STRF_ENCODE_ANSI", + "range": null, + "title": "0:ANSI/OEM in current CP", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "FATFS_STRF_ENCODE_UTF16LE", + "name": "FATFS_STRF_ENCODE_UTF16LE", + "range": null, + "title": "1:Unicode in UTF-16LE", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "FATFS_STRF_ENCODE_UTF16BE", + "name": "FATFS_STRF_ENCODE_UTF16BE", + "range": null, + "title": "2:Unicode in UTF-16BE", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "FATFS_STRF_ENCODE_UTF8", + "name": "FATFS_STRF_ENCODE_UTF8", + "range": null, + "title": "3:Unicode in UTF-8", + "type": "bool" + } + ], + "depends_on": "!FATFS_LFN_NONE && !FATFS_USE_STRFUNC_NONE", + "help": "When FF_LFN_UNICODE >= 1 with LFN enabled, string functions convert the character\nencoding in it. FF_STRF_ENCODE selects assumption of character encoding ON THE FILE\nto be read/written via those functions.\n0: ANSI/OEM in current CP\n1: Unicode in UTF-16LE\n2: Unicode in UTF-16BE\n3: Unicode in UTF-8", + "id": "component-config-fat-filesystem-support-fatfs-string-functions-convert-character-encoding", + "name": "FATFS_STRF_ENCODE_CHOICE", + "title": "FatFS string functions: convert character encoding", + "type": "choice" + }, + { + "children": [], + "depends_on": "FATFS_USE_FASTSEEK", + "help": "If fast seek algorithm is enabled, this defines the size of\nCLMT buffer used by this algorithm in 32-bit word units.\nThis value should be chosen based on prior knowledge of\nmaximum elements of each file entry would store.", + "id": "FATFS_FAST_SEEK_BUFFER_SIZE", + "name": "FATFS_FAST_SEEK_BUFFER_SIZE", + "range": null, + "title": "Fast seek CLMT buffer size", + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": "If set to 0, the 'newlib' library's default size (BLKSIZ) is used (128 B).\nIf set to a non-zero value, the value is used as the block size.\nDefault file buffer size is set to this value\nand the buffer is allocated when first attempt of reading/writing to a file is made.\nIncreasing this value improves fread() speed, however the heap usage is increased as well.\n\nNOTE: The block size value is shared by all the filesystem functions\naccessing target media for given file descriptor!\nSee 'Improving I/O performance' section of 'Maximizing Execution Speed' documentation page\nfor more details.", + "id": "FATFS_VFS_FSTAT_BLKSIZE", + "name": "FATFS_VFS_FSTAT_BLKSIZE", + "range": null, + "title": "Default block size", + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": "Enables automatic calling of f_sync() to flush recent file changes after each call of vfs_fat_write(),\nvfs_fat_pwrite(), vfs_fat_link(), vfs_fat_truncate() and vfs_fat_ftruncate() functions.\nThis feature improves file-consistency and size reporting accuracy for the FatFS,\nat a price on decreased performance due to frequent disk operations", + "id": "FATFS_IMMEDIATE_FSYNC", + "name": "FATFS_IMMEDIATE_FSYNC", + "range": null, + "title": "Enable automatic f_sync", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Allows FATFS volume label to be specified using f_setlabel", + "id": "FATFS_USE_LABEL", + "name": "FATFS_USE_LABEL", + "range": null, + "title": "Use FATFS volume label", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "If enabled, the whole link operation (including file copying) is performed under lock.\nThis ensures that the link operation is atomic, but may cause performance for large files.\nIt may create less fragmented file copy.", + "id": "FATFS_LINK_LOCK", + "name": "FATFS_LINK_LOCK", + "range": null, + "title": "Perform the whole link operation under lock", + "type": "bool" + }, + { + "children": [], + "depends_on": "CONFIG_WL_SECTOR_SIZE_4096", + "help": "If enabled, the buffers used by FATFS will be allocated separately from the rest of the structure.\nThis option is useful when using multiple FATFS instances with different\nsector sizes, as the buffers will be allocated according to the sector size.\nIf disabled, the greatest sector size will be used for all FATFS instances.\n(In most cases, this would be the sector size of Wear Levelling library)\nThis might cause more memory to be used than necessary.", + "id": "FATFS_USE_DYN_BUFFERS", + "name": "FATFS_USE_DYN_BUFFERS", + "range": null, + "title": "Use dynamic buffers", + "type": "bool" + } + ], + "depends_on": null, + "id": "component-config-fat-filesystem-support", + "title": "FAT Filesystem support", + "type": "menu" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "!IDF_TARGET_ESP32P4", + "help": "Amazon has released an SMP version of the FreeRTOS Kernel which can be found via the following link:\nhttps://github.com/FreeRTOS/FreeRTOS-Kernel/tree/smp\n\nIDF has added an experimental port of this SMP kernel located in\ncomponents/freertos/FreeRTOS-Kernel-SMP. Enabling this option will cause IDF to use the Amazon SMP\nkernel. Note that THIS FEATURE IS UNDER ACTIVE DEVELOPMENT, users use this at their own risk.\n\nLeaving this option disabled will mean the IDF FreeRTOS kernel is used instead, which is located in:\ncomponents/freertos/FreeRTOS-Kernel. Both kernel versions are SMP capable, but differ in\ntheir implementation and features.", + "id": "FREERTOS_SMP", + "name": "FREERTOS_SMP", + "range": null, + "title": "Run the Amazon SMP FreeRTOS kernel instead (FEATURE UNDER DEVELOPMENT)", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "This version of FreeRTOS normally takes control of all cores of the CPU. Select this if you only want\nto start it on the first core. This is needed when e.g. another process needs complete control over the\nsecond core.", + "id": "FREERTOS_UNICORE", + "name": "FREERTOS_UNICORE", + "range": null, + "title": "Run FreeRTOS only on first core", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Sets the FreeRTOS tick interrupt frequency in Hz (see configTICK_RATE_HZ documentation for more\ndetails).", + "id": "FREERTOS_HZ", + "name": "FREERTOS_HZ", + "range": [ + 1, + 1000 + ], + "title": "configTICK_RATE_HZ", + "type": "int" + }, + { + "children": [], + "depends_on": "FREERTOS_UNICORE && !FREERTOS_SMP", + "help": "Enables port specific task selection method. This option can speed up the search of ready tasks\nwhen scheduling (see configUSE_PORT_OPTIMISED_TASK_SELECTION documentation for more details).", + "id": "FREERTOS_OPTIMIZED_SCHEDULER", + "name": "FREERTOS_OPTIMIZED_SCHEDULER", + "range": null, + "title": "configUSE_PORT_OPTIMISED_TASK_SELECTION", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": "Do not check for stack overflows (configCHECK_FOR_STACK_OVERFLOW = 0)", + "id": "FREERTOS_CHECK_STACKOVERFLOW_NONE", + "name": "FREERTOS_CHECK_STACKOVERFLOW_NONE", + "range": null, + "title": "No checking", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": "Check for stack overflows on each context switch by checking if the stack pointer is in a valid\nrange. Quick but does not detect stack overflows that happened between context switches\n(configCHECK_FOR_STACK_OVERFLOW = 1)", + "id": "FREERTOS_CHECK_STACKOVERFLOW_PTRVAL", + "name": "FREERTOS_CHECK_STACKOVERFLOW_PTRVAL", + "range": null, + "title": "Check by stack pointer value (Method 1)", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": "Places some magic bytes at the end of the stack area and on each context switch, check if these\nbytes are still intact. More thorough than just checking the pointer, but also slightly slower.\n(configCHECK_FOR_STACK_OVERFLOW = 2)", + "id": "FREERTOS_CHECK_STACKOVERFLOW_CANARY", + "name": "FREERTOS_CHECK_STACKOVERFLOW_CANARY", + "range": null, + "title": "Check using canary bytes (Method 2)", + "type": "bool" + } + ], + "depends_on": null, + "help": "Enables FreeRTOS to check for stack overflows (see configCHECK_FOR_STACK_OVERFLOW documentation for\nmore details).\n\nNote: If users do not provide their own ``vApplicationStackOverflowHook()`` function, a default\nfunction will be provided by ESP-IDF.", + "id": "component-config-freertos-kernel-configcheck_for_stack_overflow", + "name": "FREERTOS_CHECK_STACKOVERFLOW", + "title": "configCHECK_FOR_STACK_OVERFLOW", + "type": "choice" + }, + { + "children": [], + "depends_on": null, + "help": "Set the number of thread local storage pointers in each task (see\nconfigNUM_THREAD_LOCAL_STORAGE_POINTERS documentation for more details).\n\nNote: In ESP-IDF, this value must be at least 1. Index 0 is reserved for use by the pthreads API\nthread-local-storage. Other indexes can be used for any desired purpose.", + "id": "FREERTOS_THREAD_LOCAL_STORAGE_POINTERS", + "name": "FREERTOS_THREAD_LOCAL_STORAGE_POINTERS", + "range": [ + 1, + 256 + ], + "title": "configNUM_THREAD_LOCAL_STORAGE_POINTERS", + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": "Sets the idle task stack size in bytes (see configMINIMAL_STACK_SIZE documentation for more details).\n\nNote:\n\n- ESP-IDF specifies stack sizes in bytes instead of words.\n- The default size is enough for most use cases.\n- The stack size may need to be increased above the default if the app installs idle or thread local\n storage cleanup hooks that use a lot of stack memory.\n- Conversely, the stack size can be reduced to the minimum if non of the idle features are used.", + "id": "FREERTOS_IDLE_TASK_STACKSIZE", + "name": "FREERTOS_IDLE_TASK_STACKSIZE", + "range": [ + 768, + 32768 + ], + "title": "configMINIMAL_STACK_SIZE (Idle task stack size)", + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": "Enables the idle task application hook (see configUSE_IDLE_HOOK documentation for more details).\n\nNote:\n\n- The application must provide the hook function ``void vApplicationIdleHook( void );``\n- ``vApplicationIdleHook()`` is called from FreeRTOS idle task(s)\n- The FreeRTOS idle hook is NOT the same as the ESP-IDF Idle Hook, but both can be enabled\n simultaneously.", + "id": "FREERTOS_USE_IDLE_HOOK", + "name": "FREERTOS_USE_IDLE_HOOK", + "range": null, + "title": "configUSE_IDLE_HOOK", + "type": "bool" + }, + { + "children": [], + "depends_on": "FREERTOS_SMP", + "help": "Enables the minimal idle task application hook (see configUSE_IDLE_HOOK documentation for more\ndetails).\n\nNote:\n\n- The application must provide the hook function ``void vApplicationPassiveIdleHook( void );``\n- ``vApplicationPassiveIdleHook()`` is called from FreeRTOS minimal idle task(s)", + "id": "FREERTOS_USE_PASSIVE_IDLE_HOOK", + "name": "FREERTOS_USE_PASSIVE_IDLE_HOOK", + "range": null, + "title": "Use FreeRTOS minimal idle hook", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Enables the tick hook (see configUSE_TICK_HOOK documentation for more details).\n\nNote:\n\n- The application must provide the hook function ``void vApplicationTickHook( void );``\n- ``vApplicationTickHook()`` is called from FreeRTOS's tick handling function ``xTaskIncrementTick()``\n- The FreeRTOS tick hook is NOT the same as the ESP-IDF Tick Interrupt Hook, but both can be enabled\n simultaneously.", + "id": "FREERTOS_USE_TICK_HOOK", + "name": "FREERTOS_USE_TICK_HOOK", + "range": null, + "title": "configUSE_TICK_HOOK", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Sets the maximum number of characters for task names (see configMAX_TASK_NAME_LEN documentation for\nmore details).\n\nNote: For most uses, the default of 16 characters is sufficient.", + "id": "FREERTOS_MAX_TASK_NAME_LEN", + "name": "FREERTOS_MAX_TASK_NAME_LEN", + "range": [ + 1, + 256 + ], + "title": "configMAX_TASK_NAME_LEN", + "type": "int" + }, + { + "children": [], + "depends_on": "!IDF_TARGET_LINUX", + "help": "Enable backward compatibility with APIs prior to FreeRTOS v8.0.0. (see\nconfigENABLE_BACKWARD_COMPATIBILITY documentation for more details).", + "id": "FREERTOS_ENABLE_BACKWARD_COMPATIBILITY", + "name": "FREERTOS_ENABLE_BACKWARD_COMPATIBILITY", + "range": null, + "title": "configENABLE_BACKWARD_COMPATIBILITY", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "FREERTOS_USE_TIMERS", + "help": "Sets the timer task's name (see configTIMER_SERVICE_TASK_NAME documentation for more details).", + "id": "FREERTOS_TIMER_SERVICE_TASK_NAME", + "name": "FREERTOS_TIMER_SERVICE_TASK_NAME", + "range": null, + "title": "configTIMER_SERVICE_TASK_NAME", + "type": "string" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "FREERTOS_TIMER_TASK_AFFINITY_CPU0", + "name": "FREERTOS_TIMER_TASK_AFFINITY_CPU0", + "range": null, + "title": "CPU0", + "type": "bool" + }, + { + "children": [], + "depends_on": "!FREERTOS_UNICORE && ", + "help": null, + "id": "FREERTOS_TIMER_TASK_AFFINITY_CPU1", + "name": "FREERTOS_TIMER_TASK_AFFINITY_CPU1", + "range": null, + "title": "CPU1", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "FREERTOS_TIMER_TASK_NO_AFFINITY", + "name": "FREERTOS_TIMER_TASK_NO_AFFINITY", + "range": null, + "title": "No affinity", + "type": "bool" + } + ], + "depends_on": "FREERTOS_USE_TIMERS", + "help": "Sets the timer task's core affinity\n(see configTIMER_SERVICE_TASK_CORE_AFFINITY documentation for more details).", + "id": "component-config-freertos-kernel-configuse_timers-configtimer_service_task_core_affinity", + "name": "FREERTOS_TIMER_SERVICE_TASK_CORE_AFFINITY", + "title": "configTIMER_SERVICE_TASK_CORE_AFFINITY", + "type": "choice" + }, + { + "children": [], + "depends_on": "FREERTOS_USE_TIMERS", + "help": null, + "id": "FREERTOS_TIMER_SERVICE_TASK_CORE_AFFINITY", + "name": "FREERTOS_TIMER_SERVICE_TASK_CORE_AFFINITY", + "range": null, + "title": null, + "type": "hex" + }, + { + "children": [], + "depends_on": "FREERTOS_USE_TIMERS", + "help": "Sets the timer task's priority (see configTIMER_TASK_PRIORITY documentation for more details).", + "id": "FREERTOS_TIMER_TASK_PRIORITY", + "name": "FREERTOS_TIMER_TASK_PRIORITY", + "range": [ + 1, + 25 + ], + "title": "configTIMER_TASK_PRIORITY", + "type": "int" + }, + { + "children": [], + "depends_on": "FREERTOS_USE_TIMERS", + "help": "Set the timer task's stack size (see configTIMER_TASK_STACK_DEPTH documentation for more details).", + "id": "FREERTOS_TIMER_TASK_STACK_DEPTH", + "name": "FREERTOS_TIMER_TASK_STACK_DEPTH", + "range": [ + 1536, + 32768 + ], + "title": "configTIMER_TASK_STACK_DEPTH", + "type": "int" + }, + { + "children": [], + "depends_on": "FREERTOS_USE_TIMERS", + "help": "Set the timer task's command queue length (see configTIMER_QUEUE_LENGTH documentation for more\ndetails).", + "id": "FREERTOS_TIMER_QUEUE_LENGTH", + "name": "FREERTOS_TIMER_QUEUE_LENGTH", + "range": [ + 5, + 20 + ], + "title": "configTIMER_QUEUE_LENGTH", + "type": "int" + } + ], + "depends_on": null, + "help": "Enable FreeRTOS Software Timers. Normally the timer task will only get pulled into the build\nand created if any software timer related functions are used. This is achieved through IDF\ndefining a weak empty function for xTimerCreateTimerTask, which should take effect if timers.c\nis not pulled into the build.\n\nIn certain special cases (if you use configUSE_TRACE_FACILITY=y and event groups) the linker will\nstill pull in the xTimerCreateTimerTask from timers.c even if the function that utilized it gets\ndiscarded due to not being used.\n\nIn these cases you can use this option to force the timer task to be disabled.", + "id": "FREERTOS_USE_TIMERS", + "name": "FREERTOS_USE_TIMERS", + "range": null, + "title": "configUSE_TIMERS", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Set the size of the queue registry (see configQUEUE_REGISTRY_SIZE documentation for more details).\n\nNote: A value of 0 will disable queue registry functionality", + "id": "FREERTOS_QUEUE_REGISTRY_SIZE", + "name": "FREERTOS_QUEUE_REGISTRY_SIZE", + "range": [ + 0, + 20 + ], + "title": "configQUEUE_REGISTRY_SIZE", + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": "Set the size of the task notification array of each task. When increasing this value, keep in\nmind that this means additional memory for each and every task on the system.\nHowever, task notifications in general are more light weight compared to alternatives\nsuch as semaphores.", + "id": "FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES", + "name": "FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES", + "range": [ + 1, + 32 + ], + "title": "configTASK_NOTIFICATION_ARRAY_ENTRIES", + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "FREERTOS_USE_TRACE_FACILITY", + "help": "Set configUSE_TRACE_FACILITY and configUSE_STATS_FORMATTING_FUNCTIONS to 1 to include the\n``vTaskList()`` and ``vTaskGetRunTimeStats()`` functions in the build (see\nconfigUSE_STATS_FORMATTING_FUNCTIONS documentation for more details).", + "id": "FREERTOS_USE_STATS_FORMATTING_FUNCTIONS", + "name": "FREERTOS_USE_STATS_FORMATTING_FUNCTIONS", + "range": null, + "title": "configUSE_STATS_FORMATTING_FUNCTIONS", + "type": "bool" + } + ], + "depends_on": null, + "help": "Enables additional structure members and functions to assist with execution visualization and tracing\n(see configUSE_TRACE_FACILITY documentation for more details).", + "id": "FREERTOS_USE_TRACE_FACILITY", + "name": "FREERTOS_USE_TRACE_FACILITY", + "range": null, + "title": "configUSE_TRACE_FACILITY", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Enable list integrity checker\n(see configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES documentation for more details).", + "id": "FREERTOS_USE_LIST_DATA_INTEGRITY_CHECK_BYTES", + "name": "FREERTOS_USE_LIST_DATA_INTEGRITY_CHECK_BYTES", + "range": null, + "title": "configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES", + "type": "bool" + }, + { + "children": [], + "depends_on": "!FREERTOS_SMP && FREERTOS_USE_STATS_FORMATTING_FUNCTIONS", + "help": "If enabled, this will include an extra column when vTaskList is called to display the CoreID the task\nis pinned to (0,1) or -1 if not pinned.", + "id": "FREERTOS_VTASKLIST_INCLUDE_COREID", + "name": "FREERTOS_VTASKLIST_INCLUDE_COREID", + "range": null, + "title": "Enable display of xCoreID in vTaskList", + "type": "bool" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "", + "help": "configRUN_TIME_COUNTER_TYPE is set to uint32_t", + "id": "FREERTOS_RUN_TIME_COUNTER_TYPE_U32", + "name": "FREERTOS_RUN_TIME_COUNTER_TYPE_U32", + "range": null, + "title": "uint32_t", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": "configRUN_TIME_COUNTER_TYPE is set to uint64_t", + "id": "FREERTOS_RUN_TIME_COUNTER_TYPE_U64", + "name": "FREERTOS_RUN_TIME_COUNTER_TYPE_U64", + "range": null, + "title": "uint64_t", + "type": "bool" + } + ], + "depends_on": "FREERTOS_GENERATE_RUN_TIME_STATS && !FREERTOS_SMP", + "help": "Sets the data type used for the FreeRTOS run time stats. A larger data type can be used to reduce the\nfrequency of the counter overflowing.", + "id": "component-config-freertos-kernel-configgenerate_run_time_stats-configrun_time_counter_type", + "name": "FREERTOS_RUN_TIME_COUNTER_TYPE", + "title": "configRUN_TIME_COUNTER_TYPE", + "type": "choice" + } + ], + "depends_on": null, + "help": "Enables collection of run time statistics for each task (see configGENERATE_RUN_TIME_STATS\ndocumentation for more details).\n\nNote: The clock used for run time statistics can be configured in FREERTOS_RUN_TIME_STATS_CLK.", + "id": "FREERTOS_GENERATE_RUN_TIME_STATS", + "name": "FREERTOS_GENERATE_RUN_TIME_STATS", + "range": null, + "title": "configGENERATE_RUN_TIME_STATS", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "FREERTOS_USE_TICKLESS_IDLE", + "help": "FreeRTOS will enter light sleep mode if no tasks need to run for this number of ticks.\nYou can enable PM_PROFILING feature in esp_pm components and dump the sleep status with\nesp_pm_dump_locks, if the proportion of rejected sleeps is too high, please increase\nthis value to improve scheduling efficiency", + "id": "FREERTOS_IDLE_TIME_BEFORE_SLEEP", + "name": "FREERTOS_IDLE_TIME_BEFORE_SLEEP", + "range": null, + "title": "configEXPECTED_IDLE_TIME_BEFORE_SLEEP", + "type": "int" + } + ], + "depends_on": "PM_ENABLE", + "help": "If power management support is enabled, FreeRTOS will be able to put the system into light sleep mode\nwhen no tasks need to run for a number of ticks. This number can be set using\nFREERTOS_IDLE_TIME_BEFORE_SLEEP option. This feature is also known as \"automatic light sleep\".\n\nNote that timers created using esp_timer APIs may prevent the system from entering sleep mode, even\nwhen no tasks need to run. To skip unnecessary wake-up initialize a timer with the\n\"skip_unhandled_events\" option as true.\n\nIf disabled, automatic light sleep support will be disabled.", + "id": "FREERTOS_USE_TICKLESS_IDLE", + "name": "FREERTOS_USE_TICKLESS_IDLE", + "range": null, + "title": "configUSE_TICKLESS_IDLE", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Enables task tagging functionality and its associated API (see configUSE_APPLICATION_TASK_TAG\ndocumentation for more details).", + "id": "FREERTOS_USE_APPLICATION_TASK_TAG", + "name": "FREERTOS_USE_APPLICATION_TASK_TAG", + "range": null, + "title": "configUSE_APPLICATION_TASK_TAG", + "type": "bool" + } + ], + "depends_on": null, + "id": "component-config-freertos-kernel", + "title": "Kernel", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": "COMPILER_OPTIMIZATION_DEBUG || ESP_COREDUMP_ENABLE || ESP_SYSTEM_PANIC_GDBSTUB || ESP_SYSTEM_GDBSTUB_RUNTIME", + "help": "If enabled, all FreeRTOS task functions will be enclosed in a wrapper function. If a task function\nmistakenly returns (i.e. does not delete), the call flow will return to the wrapper function. The\nwrapper function will then log an error and abort the application. This option is also required for GDB\nbacktraces and C++ exceptions to work correctly inside top-level task functions.", + "id": "FREERTOS_TASK_FUNCTION_WRAPPER", + "name": "FREERTOS_TASK_FUNCTION_WRAPPER", + "range": null, + "title": "Wrap task functions", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "FreeRTOS can check if a stack has overflown its bounds by checking either the value of the stack\npointer or by checking the integrity of canary bytes. (See FREERTOS_CHECK_STACKOVERFLOW for more\ninformation.) These checks only happen on a context switch, and the situation that caused the stack\noverflow may already be long gone by then. This option will use the last debug memory watchpoint to\nallow breaking into the debugger (or panic'ing) as soon as any of the last 32 bytes on the stack of a\ntask are overwritten. The side effect is that using gdb, you effectively have one hardware watchpoint\nless because the last one is overwritten as soon as a task switch happens.\n\nAnother consequence is that due to alignment requirements of the watchpoint, the usable stack size\ndecreases by up to 60 bytes. This is because the watchpoint region has to be aligned to its size and\nthe size for the stack watchpoint in IDF is 32 bytes.\n\nThis check only triggers if the stack overflow writes within 32 bytes near the end of the stack, rather\nthan overshooting further, so it is worth combining this approach with one of the other stack overflow\ncheck methods.\n\nWhen this watchpoint is hit, gdb will stop with a SIGTRAP message. When no JTAG OCD is attached,\nesp-idf will panic on an unhandled debug exception.", + "id": "FREERTOS_WATCHPOINT_END_OF_STACK", + "name": "FREERTOS_WATCHPOINT_END_OF_STACK", + "range": null, + "title": "Enable stack overflow debug watchpoint", + "type": "bool" + }, + { + "children": [], + "depends_on": "FREERTOS_THREAD_LOCAL_STORAGE_POINTERS > 0", + "help": "ESP-IDF provides users with the ability to free TLSP memory by registering TLSP deletion callbacks.\nThese callbacks are automatically called by FreeRTOS when a task is deleted. When this option is turned\non, the memory reserved for TLSPs in the TCB is doubled to make space for storing the deletion\ncallbacks. If the user does not wish to use TLSP deletion callbacks then this option could be turned\noff to save space in the TCB memory.", + "id": "FREERTOS_TLSP_DELETION_CALLBACKS", + "name": "FREERTOS_TLSP_DELETION_CALLBACKS", + "range": null, + "title": "Enable thread local storage pointers deletion callbacks", + "type": "bool" + }, + { + "children": [], + "depends_on": "!FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP", + "help": "Enable this option to make FreeRTOS call a user provided hook function right before it deletes a task\n(i.e., frees/releases a dynamically/statically allocated task's memory). This is useful if users want\nto know when a task is actually deleted (in case the task's deletion is delegated to the IDLE task).\n\nIf this config option is enabled, users must define a ``void vTaskPreDeletionHook( void * pxTCB )``\nhook function in their application.", + "id": "FREERTOS_TASK_PRE_DELETION_HOOK", + "name": "FREERTOS_TASK_PRE_DELETION_HOOK", + "range": null, + "title": "Enable task pre-deletion hook", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "THIS OPTION IS DEPRECATED. Use FREERTOS_TASK_PRE_DELETION_HOOK instead.\n\nEnable this option to make FreeRTOS call the static task clean up hook when a task is deleted.\n\nNote: Users will need to provide a ``void vPortCleanUpTCB ( void *pxTCB )`` callback", + "id": "FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP", + "name": "FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP", + "range": null, + "title": "Enable static task clean up hook (DEPRECATED)", + "type": "bool" + }, + { + "children": [], + "depends_on": "!FREERTOS_SMP", + "help": "If enabled, assert that when a mutex semaphore is given, the task giving the semaphore is the task\nwhich is currently holding the mutex.", + "id": "FREERTOS_CHECK_MUTEX_GIVEN_BY_OWNER", + "name": "FREERTOS_CHECK_MUTEX_GIVEN_BY_OWNER", + "range": null, + "title": "Check that mutex semaphore is given by owner task", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "The interrupt handlers have their own stack. The size of the stack can be defined here. Each processor\nhas its own stack, so the total size occupied will be twice this.", + "id": "FREERTOS_ISR_STACKSIZE", + "name": "FREERTOS_ISR_STACKSIZE", + "range": [ + 1536, + 32768 + ], + "title": "ISR stack size", + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": "If this option is enabled, interrupt stack frame will be modified to point to the code of the\ninterrupted task as its return address. This helps the debugger (or the panic handler) show a backtrace\nfrom the interrupt to the task which was interrupted. This also works for nested interrupts: higher\nlevel interrupt stack can be traced back to the lower level interrupt. This option adds 4 instructions\nto the interrupt dispatching code.", + "id": "FREERTOS_INTERRUPT_BACKTRACE", + "name": "FREERTOS_INTERRUPT_BACKTRACE", + "range": null, + "title": "Enable backtrace from interrupt to task context", + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_CPU_HAS_FPU && (IDF_TARGET_ESP32 || IDF_TARGET_ESP32S3)", + "help": "When enabled, the usage of float type is allowed inside Level 1 ISRs. Note that usage of float types in\nhigher level interrupts is still not permitted.", + "id": "FREERTOS_FPU_IN_ISR", + "name": "FREERTOS_FPU_IN_ISR", + "range": null, + "title": "Use float in Level 1 ISR", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "FREERTOS_TICK_SUPPORT_CORETIMER", + "name": "FREERTOS_TICK_SUPPORT_CORETIMER", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "FREERTOS_TICK_SUPPORT_SYSTIMER", + "name": "FREERTOS_TICK_SUPPORT_SYSTIMER", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "FREERTOS_TICK_SUPPORT_CORETIMER && ", + "help": "Select this to use timer 0", + "id": "FREERTOS_CORETIMER_0", + "name": "FREERTOS_CORETIMER_0", + "range": null, + "title": "Timer 0 (int 6, level 1)", + "type": "bool" + }, + { + "children": [], + "depends_on": "FREERTOS_TICK_SUPPORT_CORETIMER && ", + "help": "Select this to use timer 1", + "id": "FREERTOS_CORETIMER_1", + "name": "FREERTOS_CORETIMER_1", + "range": null, + "title": "Timer 1 (int 15, level 3)", + "type": "bool" + }, + { + "children": [], + "depends_on": "FREERTOS_TICK_SUPPORT_SYSTIMER && ", + "help": "Select this to use systimer with the 1 interrupt priority.", + "id": "FREERTOS_CORETIMER_SYSTIMER_LVL1", + "name": "FREERTOS_CORETIMER_SYSTIMER_LVL1", + "range": null, + "title": "SYSTIMER 0 (level 1)", + "type": "bool" + }, + { + "children": [], + "depends_on": "FREERTOS_TICK_SUPPORT_SYSTIMER && ", + "help": "Select this to use systimer with the 3 interrupt priority.", + "id": "FREERTOS_CORETIMER_SYSTIMER_LVL3", + "name": "FREERTOS_CORETIMER_SYSTIMER_LVL3", + "range": null, + "title": "SYSTIMER 0 (level 3)", + "type": "bool" + } + ], + "depends_on": null, + "help": "FreeRTOS needs a timer with an associated interrupt to use as the main tick source to increase\ncounters, run timers and do pre-emptive multitasking with. There are multiple timers available to do\nthis, with different interrupt priorities.", + "id": "component-config-freertos-port-tick-timer-source-xtensa-only-", + "name": "FREERTOS_CORETIMER", + "title": "Tick timer source (Xtensa Only)", + "type": "choice" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "FREERTOS_SYSTICK_USES_SYSTIMER", + "name": "FREERTOS_SYSTICK_USES_SYSTIMER", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "FREERTOS_SYSTICK_USES_CCOUNT", + "name": "FREERTOS_SYSTICK_USES_CCOUNT", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": "ESP Timer will be used as the clock source for FreeRTOS run time stats. The ESP Timer runs at a\nfrequency of 1MHz regardless of Dynamic Frequency Scaling. Therefore the ESP Timer will overflow in\napproximately 4290 seconds.", + "id": "FREERTOS_RUN_TIME_STATS_USING_ESP_TIMER", + "name": "FREERTOS_RUN_TIME_STATS_USING_ESP_TIMER", + "range": null, + "title": "Use ESP TIMER for run time stats", + "type": "bool" + }, + { + "children": [], + "depends_on": "FREERTOS_SYSTICK_USES_CCOUNT && ", + "help": "CPU Clock will be used as the clock source for the generation of run time stats. The CPU Clock has\na frequency dependent on ESP_DEFAULT_CPU_FREQ_MHZ and Dynamic Frequency Scaling (DFS). Therefore\nthe CPU Clock frequency can fluctuate between 80 to 240MHz. Run time stats generated using the CPU\nClock represents the number of CPU cycles each task is allocated and DOES NOT reflect the amount of\ntime each task runs for (as CPU clock frequency can change). If the CPU clock consistently runs at\nthe maximum frequency of 240MHz, it will overflow in approximately 17 seconds.", + "id": "FREERTOS_RUN_TIME_STATS_USING_CPU_CLK", + "name": "FREERTOS_RUN_TIME_STATS_USING_CPU_CLK", + "range": null, + "title": "Use CPU Clock for run time stats", + "type": "bool" + } + ], + "depends_on": "FREERTOS_GENERATE_RUN_TIME_STATS", + "help": "Choose the clock source for FreeRTOS run time stats. Options are CPU0's CPU Clock or the ESP Timer.\nBoth clock sources are 32 bits. The CPU Clock can run at a higher frequency hence provide a finer\nresolution but will overflow much quicker. Note that run time stats are only valid until the clock\nsource overflows.", + "id": "component-config-freertos-port-choose-the-clock-source-for-run-time-stats", + "name": "FREERTOS_RUN_TIME_STATS_CLK", + "title": "Choose the clock source for run time stats", + "type": "choice" + }, + { + "children": [], + "depends_on": null, + "help": "When enabled the selected Non-ISR FreeRTOS functions will be placed into Flash memory instead of IRAM.\nThis saves up to 8KB of IRAM depending on which functions are used.", + "id": "FREERTOS_PLACE_FUNCTIONS_INTO_FLASH", + "name": "FREERTOS_PLACE_FUNCTIONS_INTO_FLASH", + "range": null, + "title": "Place FreeRTOS functions into Flash", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "If enabled, context of port*_CRITICAL calls (ISR or Non-ISR) would be checked to be in compliance with\nVanilla FreeRTOS. e.g Calling port*_CRITICAL from ISR context would cause assert failure", + "id": "FREERTOS_CHECK_PORT_CRITICAL_COMPLIANCE", + "name": "FREERTOS_CHECK_PORT_CRITICAL_COMPLIANCE", + "range": null, + "title": "Tests compliance with Vanilla FreeRTOS port*_CRITICAL calls", + "type": "bool" + } + ], + "depends_on": null, + "id": "component-config-freertos-port", + "title": "Port", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": "SPIRAM && FREERTOS_SUPPORT_STATIC_ALLOCATION", + "help": "Accessing memory in PSRAM has certain restrictions, so task stacks allocated by xTaskCreate\nare by default allocated from internal RAM.\n\nThis option allows for passing memory allocated from SPIRAM to be passed to xTaskCreateStatic.\nThis should only be used for tasks where the stack is never accessed while the cache is disabled.\n\nExtra notes for ESP32:\n\nBecause some bits of the ESP32 code environment cannot be recompiled with the cache workaround,\nnormally tasks cannot be safely run with their stack residing in external memory; for this reason\nxTaskCreate (and related task creation functions) always allocate stack in internal memory and\nxTaskCreateStatic will check if the memory passed to it is in internal memory.\nIf you have a task that needs a large amount of stack and does not call on ROM code in any way\n(no direct calls, but also no Bluetooth/WiFi), you can try enable this to\ncause xTaskCreateStatic to allow tasks stack in external memory.", + "id": "FREERTOS_TASK_CREATE_ALLOW_EXT_MEM", + "name": "FREERTOS_TASK_CREATE_ALLOW_EXT_MEM", + "range": null, + "title": "Allow external memory as an argument to xTaskCreateStatic (READ HELP)", + "type": "bool" + } + ], + "depends_on": null, + "id": "component-config-freertos-extra", + "title": "Extra", + "type": "menu" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "FREERTOS_PORT", + "name": "FREERTOS_PORT", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "FREERTOS_NO_AFFINITY", + "name": "FREERTOS_NO_AFFINITY", + "range": null, + "title": null, + "type": "hex" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "FREERTOS_SUPPORT_STATIC_ALLOCATION", + "name": "FREERTOS_SUPPORT_STATIC_ALLOCATION", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Hidden option, gets selected by CONFIG_ESP_DEBUG_OCDAWARE", + "id": "FREERTOS_DEBUG_OCDAWARE", + "name": "FREERTOS_DEBUG_OCDAWARE", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "FREERTOS_ENABLE_TASK_SNAPSHOT", + "name": "FREERTOS_ENABLE_TASK_SNAPSHOT", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": "!ESP_PANIC_HANDLER_IRAM", + "help": null, + "id": "FREERTOS_PLACE_SNAPSHOT_FUNS_INTO_FLASH", + "name": "FREERTOS_PLACE_SNAPSHOT_FUNS_INTO_FLASH", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "FREERTOS_NUMBER_OF_CORES", + "name": "FREERTOS_NUMBER_OF_CORES", + "range": [ + 1, + 2 + ], + "title": null, + "type": "int" + } + ], + "depends_on": null, + "id": "component-config-freertos", + "title": "FreeRTOS", + "type": "menu" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "HAL_ASSERTION_EQUALS_SYSTEM", + "name": "HAL_ASSERTION_EQUALS_SYSTEM", + "range": null, + "title": "Same as system assertion level", + "type": "bool" + }, + { + "children": [], + "depends_on": "COMPILER_OPTIMIZATION_ASSERTION_LEVEL >= 0 && ", + "help": null, + "id": "HAL_ASSERTION_DISABLE", + "name": "HAL_ASSERTION_DISABLE", + "range": null, + "title": "Disabled", + "type": "bool" + }, + { + "children": [], + "depends_on": "COMPILER_OPTIMIZATION_ASSERTION_LEVEL >= 1 && ", + "help": null, + "id": "HAL_ASSERTION_SILENT", + "name": "HAL_ASSERTION_SILENT", + "range": null, + "title": "Silent", + "type": "bool" + }, + { + "children": [], + "depends_on": "COMPILER_OPTIMIZATION_ASSERTION_LEVEL >= 2 && ", + "help": null, + "id": "HAL_ASSERTION_ENABLE", + "name": "HAL_ASSERTION_ENABLE", + "range": null, + "title": "Enabled", + "type": "bool" + } + ], + "depends_on": null, + "help": "Set the assert behavior / level for HAL component.\nHAL component assert level can be set separately,\nbut the level can't exceed the system assertion level.\ne.g. If the system assertion is disabled, then the HAL\nassertion can't be enabled either. If the system assertion\nis enable, then the HAL assertion can still be disabled\nby this Kconfig option.", + "id": "component-config-hardware-abstraction-layer-hal-and-low-level-ll--default-hal-assertion-level", + "name": "HAL_DEFAULT_ASSERTION_LEVEL", + "title": "Default HAL assertion level", + "type": "choice" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "HAL_DEFAULT_ASSERTION_LEVEL", + "name": "HAL_DEFAULT_ASSERTION_LEVEL", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "HAL_LOG_LEVEL_NONE", + "name": "HAL_LOG_LEVEL_NONE", + "range": null, + "title": "No output", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "HAL_LOG_LEVEL_ERROR", + "name": "HAL_LOG_LEVEL_ERROR", + "range": null, + "title": "Error", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "HAL_LOG_LEVEL_WARN", + "name": "HAL_LOG_LEVEL_WARN", + "range": null, + "title": "Warning", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "HAL_LOG_LEVEL_INFO", + "name": "HAL_LOG_LEVEL_INFO", + "range": null, + "title": "Info", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "HAL_LOG_LEVEL_DEBUG", + "name": "HAL_LOG_LEVEL_DEBUG", + "range": null, + "title": "Debug", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "HAL_LOG_LEVEL_VERBOSE", + "name": "HAL_LOG_LEVEL_VERBOSE", + "range": null, + "title": "Verbose", + "type": "bool" + } + ], + "depends_on": "!LOG_DEFAULT_LEVEL_NONE && !LOG_DEFAULT_LEVEL_ERROR && !LOG_DEFAULT_LEVEL_WARN && !LOG_DEFAULT_LEVEL_INFO && !LOG_DEFAULT_LEVEL_DEBUG && !LOG_DEFAULT_LEVEL_VERBOSE", + "help": "Specify how much output to see in HAL logs.", + "id": "component-config-hardware-abstraction-layer-hal-and-low-level-ll--hal-layer-log-verbosity", + "name": "HAL_LOG_LEVEL", + "title": "HAL layer log verbosity", + "type": "choice" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "HAL_LOG_LEVEL", + "name": "HAL_LOG_LEVEL", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": "ESP_ROM_HAS_HAL_SYSTIMER", + "help": "Enable this flag to use HAL functions from ROM instead of ESP-IDF.\n\nIf keeping this as \"n\" in your project, you will have less free IRAM.\nIf making this as \"y\" in your project, you will increase free IRAM,\nbut you will lose the possibility to debug this module, and some new\nfeatures will be added and bugs will be fixed in the IDF source\nbut cannot be synced to ROM.", + "id": "HAL_SYSTIMER_USE_ROM_IMPL", + "name": "HAL_SYSTIMER_USE_ROM_IMPL", + "range": null, + "title": "Use ROM implementation of SysTimer HAL driver", + "type": "bool" + }, + { + "children": [], + "depends_on": "ESP_ROM_HAS_HAL_WDT", + "help": "Enable this flag to use HAL functions from ROM instead of ESP-IDF.\n\nIf keeping this as \"n\" in your project, you will have less free IRAM.\nIf making this as \"y\" in your project, you will increase free IRAM,\nbut you will lose the possibility to debug this module, and some new\nfeatures will be added and bugs will be fixed in the IDF source\nbut cannot be synced to ROM.", + "id": "HAL_WDT_USE_ROM_IMPL", + "name": "HAL_WDT_USE_ROM_IMPL", + "range": null, + "title": "Use ROM implementation of WDT HAL driver", + "type": "bool" + }, + { + "children": [], + "depends_on": "SPI_MASTER_ISR_IN_IRAM", + "help": "Enable this option to place SPI master hal layer functions into IRAM.", + "id": "HAL_SPI_MASTER_FUNC_IN_IRAM", + "name": "HAL_SPI_MASTER_FUNC_IN_IRAM", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": "SPI_SLAVE_ISR_IN_IRAM", + "help": "Enable this option to place SPI slave hal layer functions into IRAM.", + "id": "HAL_SPI_SLAVE_FUNC_IN_IRAM", + "name": "HAL_SPI_SLAVE_FUNC_IN_IRAM", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": "IDF_TARGET_ESP32H2", + "help": "Enable this option to apply the countermeasure for ECDSA signature operation\nThis countermeasure masks the real ECDSA sign operation\nunder dummy sign operations to add randomness in the generated power signature.\nThis countermeasure is only necessary for ESP32-H2 < v1.2.", + "id": "HAL_ECDSA_GEN_SIG_CM", + "name": "HAL_ECDSA_GEN_SIG_CM", + "range": null, + "title": "Enable countermeasure for ECDSA signature generation", + "type": "bool" + } + ], + "depends_on": null, + "id": "component-config-hardware-abstraction-layer-hal-and-low-level-ll-", + "title": "Hardware Abstraction Layer (HAL) and Low Level (LL)", + "type": "menu" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "HEAP_POISONING_DISABLED", + "name": "HEAP_POISONING_DISABLED", + "range": null, + "title": "Basic (no poisoning)", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "HEAP_POISONING_LIGHT", + "name": "HEAP_POISONING_LIGHT", + "range": null, + "title": "Light impact", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "HEAP_POISONING_COMPREHENSIVE", + "name": "HEAP_POISONING_COMPREHENSIVE", + "range": null, + "title": "Comprehensive", + "type": "bool" + } + ], + "depends_on": null, + "help": "Enable heap poisoning features to detect heap corruption caused by out-of-bounds access to heap memory.\n\nSee the \"Heap Memory Debugging\" page of the IDF documentation\nfor a description of each level of heap corruption detection.", + "id": "component-config-heap-memory-debugging-heap-corruption-detection", + "name": "HEAP_CORRUPTION_DETECTION", + "title": "Heap corruption detection", + "type": "choice" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "HEAP_TRACING_OFF", + "name": "HEAP_TRACING_OFF", + "range": null, + "title": "Disabled", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "HEAP_TRACING_STANDALONE", + "name": "HEAP_TRACING_STANDALONE", + "range": null, + "title": "Standalone", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "HEAP_TRACING_TOHOST", + "name": "HEAP_TRACING_TOHOST", + "range": null, + "title": "Host-based", + "type": "bool" + } + ], + "depends_on": null, + "help": "Enables the heap tracing API defined in esp_heap_trace.h.\n\nThis function causes a moderate increase in IRAM code side and a minor increase in heap function\n(malloc/free/realloc) CPU overhead, even when the tracing feature is not used.\nSo it's best to keep it disabled unless tracing is being used.", + "id": "component-config-heap-memory-debugging-heap-tracing", + "name": "HEAP_TRACING_DEST", + "title": "Heap tracing", + "type": "choice" + }, + { + "children": [], + "depends_on": null, + "help": "Enables/disables heap tracing API.", + "id": "HEAP_TRACING", + "name": "HEAP_TRACING", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": "HEAP_TRACING", + "help": "Number of stack frames to save when tracing heap operation callers.\n\nMore stack frames uses more memory in the heap trace buffer (and slows down allocation), but\ncan provide useful information.", + "id": "HEAP_TRACING_STACK_DEPTH", + "name": "HEAP_TRACING_STACK_DEPTH", + "range": null, + "title": "Heap tracing stack depth", + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": "Enable the user to implement function hooks triggered for each successful allocation and free.", + "id": "HEAP_USE_HOOKS", + "name": "HEAP_USE_HOOKS", + "range": null, + "title": "Use allocation and free hooks", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Enables tracking the task responsible for each heap allocation.\n\nThis function depends on heap poisoning being enabled and adds four more bytes of overhead for each block\nallocated.", + "id": "HEAP_TASK_TRACKING", + "name": "HEAP_TASK_TRACKING", + "range": null, + "title": "Enable heap task tracking", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "HEAP_TRACE_HASH_MAP", + "help": "When enabled this configuration forces the hash map to be placed in external RAM.", + "id": "HEAP_TRACE_HASH_MAP_IN_EXT_RAM", + "name": "HEAP_TRACE_HASH_MAP_IN_EXT_RAM", + "range": null, + "title": "Place hash map in external RAM", + "type": "bool" + }, + { + "children": [], + "depends_on": "HEAP_TRACE_HASH_MAP", + "help": "Defines the number of entries in the heap trace hashmap. Each entry takes 8 bytes.\nThe bigger this number is, the better the performance. Recommended range: 200 - 2000.", + "id": "HEAP_TRACE_HASH_MAP_SIZE", + "name": "HEAP_TRACE_HASH_MAP_SIZE", + "range": null, + "title": "The number of entries in the hash map", + "type": "int" + } + ], + "depends_on": "HEAP_TRACING_STANDALONE", + "help": "Enable this flag to use a hash map to increase performance in handling\nheap trace records.\n\nHeap trace standalone supports storing records as a list, or a list + hash map.\n\nUsing only a list takes less memory, but calls to 'free' will get slower as the\nlist grows. This is particularly affected when using HEAP_TRACE_ALL mode.\n\nBy using a list + hash map, calls to 'free' remain fast, at the cost of\nadditional memory to store the hash map.", + "id": "HEAP_TRACE_HASH_MAP", + "name": "HEAP_TRACE_HASH_MAP", + "range": null, + "title": "Use hash map mechanism to access heap trace records", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "When enabled, if a memory allocation operation fails it will cause a system abort.", + "id": "HEAP_ABORT_WHEN_ALLOCATION_FAILS", + "name": "HEAP_ABORT_WHEN_ALLOCATION_FAILS", + "range": null, + "title": "Abort if memory allocation fails", + "type": "bool" + }, + { + "children": [], + "depends_on": "ESP_ROM_HAS_HEAP_TLSF", + "help": "Enable this flag to use heap functions from ROM instead of ESP-IDF.\n\nIf keeping this as \"n\" in your project, you will have less free IRAM.\nIf making this as \"y\" in your project, you will increase free IRAM,\nbut you will lose the possibility to debug this module, and some new\nfeatures will be added and bugs will be fixed in the IDF source\nbut cannot be synced to ROM.", + "id": "HEAP_TLSF_USE_ROM_IMPL", + "name": "HEAP_TLSF_USE_ROM_IMPL", + "range": null, + "title": "Use ROM implementation of heap tlsf library", + "type": "bool" + }, + { + "children": [], + "depends_on": "!HEAP_TLSF_USE_ROM_IMPL", + "help": "Enable this flag to save up RAM space by placing the heap component in the flash memory\n\nNote that it is only safe to enable this configuration if no functions from esp_heap_caps.h\nor esp_heap_trace.h are called from ISR.", + "id": "HEAP_PLACE_FUNCTION_INTO_FLASH", + "name": "HEAP_PLACE_FUNCTION_INTO_FLASH", + "range": null, + "title": "Force the entire heap component to be placed in flash memory", + "type": "bool" + } + ], + "depends_on": null, + "id": "component-config-heap-memory-debugging", + "title": "Heap memory debugging", + "type": "menu" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "IEEE802154_ENABLED", + "help": "The number of 802.15.4 receive buffers", + "id": "IEEE802154_RX_BUFFER_SIZE", + "name": "IEEE802154_RX_BUFFER_SIZE", + "range": null, + "title": "The number of 802.15.4 receive buffers", + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": "configure the CCA mode to Carrier sense only", + "id": "IEEE802154_CCA_CARRIER", + "name": "IEEE802154_CCA_CARRIER", + "range": null, + "title": "Carrier sense only", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": "configure the CCA mode to Energy above threshold", + "id": "IEEE802154_CCA_ED", + "name": "IEEE802154_CCA_ED", + "range": null, + "title": "Energy above threshold", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": "configure the CCA mode to Carrier sense OR energy above threshold", + "id": "IEEE802154_CCA_CARRIER_OR_ED", + "name": "IEEE802154_CCA_CARRIER_OR_ED", + "range": null, + "title": "Carrier sense OR energy above threshold", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": "configure the CCA mode to Carrier sense AND energy above threshold", + "id": "IEEE802154_CCA_CARRIER_AND_ED", + "name": "IEEE802154_CCA_CARRIER_AND_ED", + "range": null, + "title": "Carrier sense AND energy above threshold", + "type": "bool" + } + ], + "depends_on": "IEEE802154_ENABLED", + "help": "configure the CCA mode", + "id": "component-config-ieee-802-15-4-ieee802154-enable-clear-channel-assessment-cca-mode", + "name": "IEEE802154_CCA_MODE", + "title": "Clear Channel Assessment (CCA) mode", + "type": "choice" + }, + { + "children": [], + "depends_on": "IEEE802154_ENABLED", + "help": null, + "id": "IEEE802154_CCA_MODE", + "name": "IEEE802154_CCA_MODE", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": "IEEE802154_ENABLED", + "help": "set the CCA threshold, in dB", + "id": "IEEE802154_CCA_THRESHOLD", + "name": "IEEE802154_CCA_THRESHOLD", + "range": null, + "title": "CCA detection threshold", + "type": "int" + }, + { + "children": [], + "depends_on": "IEEE802154_ENABLED", + "help": "set the pending table size", + "id": "IEEE802154_PENDING_TABLE_SIZE", + "name": "IEEE802154_PENDING_TABLE_SIZE", + "range": null, + "title": "Pending table size", + "type": "int" + }, + { + "children": [], + "depends_on": "IEEE802154_ENABLED", + "help": "Enable IEEE802154 multi-pan", + "id": "IEEE802154_MULTI_PAN_ENABLE", + "name": "IEEE802154_MULTI_PAN_ENABLE", + "range": null, + "title": "Enable multi-pan feature for frame filter", + "type": "bool" + }, + { + "children": [], + "depends_on": "IEEE802154_ENABLED", + "help": "Enabling this option increases throughput by ~5% at the expense of ~2.1k\nIRAM code size increase.", + "id": "IEEE802154_TIMING_OPTIMIZATION", + "name": "IEEE802154_TIMING_OPTIMIZATION", + "range": null, + "title": "Enable throughput optimization", + "type": "bool" + }, + { + "children": [], + "depends_on": "PM_ENABLE && IEEE802154_ENABLED", + "help": "Enabling this option allows the IEEE802.15.4 module to be powered down during automatic light sleep,\nwhich reduces current consumption.", + "id": "IEEE802154_SLEEP_ENABLE", + "name": "IEEE802154_SLEEP_ENABLE", + "range": null, + "title": "Enable IEEE802154 light sleep", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "IEEE802154_DEBUG", + "help": "Enabling this option to count IEEE802154 rx buffer when allocating or freeing.", + "id": "IEEE802154_RX_BUFFER_STATISTIC", + "name": "IEEE802154_RX_BUFFER_STATISTIC", + "range": null, + "title": "Rx buffer statistic", + "type": "bool" + }, + { + "children": [], + "depends_on": "IEEE802154_DEBUG", + "help": "Enabling this option to print more information when assert.", + "id": "IEEE802154_ASSERT", + "name": "IEEE802154_ASSERT", + "range": null, + "title": "Enrich the assert information", + "type": "bool" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "IEEE802154_RECORD_EVENT", + "help": "set the record event table size", + "id": "IEEE802154_RECORD_EVENT_SIZE", + "name": "IEEE802154_RECORD_EVENT_SIZE", + "range": null, + "title": "Record event table size", + "type": "int" + } + ], + "depends_on": "IEEE802154_RECORD", + "help": "Enabling this option to record event, when assert, the recorded event will be printed.", + "id": "IEEE802154_RECORD_EVENT", + "name": "IEEE802154_RECORD_EVENT", + "range": null, + "title": "Enable record event information for debugging", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "IEEE802154_RECORD_STATE", + "help": "set the record state table size", + "id": "IEEE802154_RECORD_STATE_SIZE", + "name": "IEEE802154_RECORD_STATE_SIZE", + "range": null, + "title": "Record state table size", + "type": "int" + } + ], + "depends_on": "IEEE802154_RECORD", + "help": "Enabling this option to record state, when assert, the recorded state will be printed.", + "id": "IEEE802154_RECORD_STATE", + "name": "IEEE802154_RECORD_STATE", + "range": null, + "title": "Enable record state information for debugging", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "IEEE802154_RECORD_CMD", + "help": "set the record command table size", + "id": "IEEE802154_RECORD_CMD_SIZE", + "name": "IEEE802154_RECORD_CMD_SIZE", + "range": null, + "title": "Record command table size", + "type": "int" + } + ], + "depends_on": "IEEE802154_RECORD", + "help": "Enabling this option to record the command, when assert, the recorded\ncommand will be printed.", + "id": "IEEE802154_RECORD_CMD", + "name": "IEEE802154_RECORD_CMD", + "range": null, + "title": "Enable record command information for debugging", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "IEEE802154_RECORD_ABORT", + "help": "set the record abort table size", + "id": "IEEE802154_RECORD_ABORT_SIZE", + "name": "IEEE802154_RECORD_ABORT_SIZE", + "range": null, + "title": "Record abort table size", + "type": "int" + } + ], + "depends_on": "IEEE802154_RECORD", + "help": "Enabling this option to record the abort, when assert, the recorded\nabort will be printed.", + "id": "IEEE802154_RECORD_ABORT", + "name": "IEEE802154_RECORD_ABORT", + "range": null, + "title": "Enable record abort information for debugging", + "type": "bool" + } + ], + "depends_on": "IEEE802154_DEBUG", + "help": "Enabling this option to add some probe codes in the driver, and record these information.", + "id": "IEEE802154_RECORD", + "name": "IEEE802154_RECORD", + "range": null, + "title": "Record the information with IEEE802154 state and event", + "type": "bool" + }, + { + "children": [], + "depends_on": "IEEE802154_DEBUG", + "help": "Enabling this option to record the tx and rx", + "id": "IEEE802154_TXRX_STATISTIC", + "name": "IEEE802154_TXRX_STATISTIC", + "range": null, + "title": "Enable record tx/rx packets information for debugging", + "type": "bool" + } + ], + "depends_on": "IEEE802154_ENABLED", + "help": "Enabling this option allows different kinds of IEEE802154 debug output.\nAll IEEE802154 debug features increase the size of the final binary.", + "id": "IEEE802154_DEBUG", + "is_menuconfig": true, + "name": "IEEE802154_DEBUG", + "range": null, + "title": "Enable IEEE802154 Debug", + "type": "menu" + } + ], + "depends_on": null, + "help": null, + "id": "IEEE802154_ENABLED", + "name": "IEEE802154_ENABLED", + "range": null, + "title": "IEEE802154 Enable", + "type": "bool" + } + ], + "depends_on": null, + "id": "component-config-ieee-802-15-4", + "title": "IEEE 802.15.4", + "type": "menu" + }, + { + "children": [ + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "LOG_DEFAULT_LEVEL_NONE", + "name": "LOG_DEFAULT_LEVEL_NONE", + "range": null, + "title": "No output", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "LOG_DEFAULT_LEVEL_ERROR", + "name": "LOG_DEFAULT_LEVEL_ERROR", + "range": null, + "title": "Error", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "LOG_DEFAULT_LEVEL_WARN", + "name": "LOG_DEFAULT_LEVEL_WARN", + "range": null, + "title": "Warning", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "LOG_DEFAULT_LEVEL_INFO", + "name": "LOG_DEFAULT_LEVEL_INFO", + "range": null, + "title": "Info", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "LOG_DEFAULT_LEVEL_DEBUG", + "name": "LOG_DEFAULT_LEVEL_DEBUG", + "range": null, + "title": "Debug", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "LOG_DEFAULT_LEVEL_VERBOSE", + "name": "LOG_DEFAULT_LEVEL_VERBOSE", + "range": null, + "title": "Verbose", + "type": "bool" + } + ], + "depends_on": null, + "help": "Specify how much output to see in logs by default.\nYou can set lower verbosity level at runtime using\nesp_log_level_set() function if LOG_DYNAMIC_LEVEL_CONTROL\nis enabled.\n\nBy default, this setting limits which log statements\nare compiled into the program. For example, selecting\n\"Warning\" would mean that changing log level to \"Debug\"\nat runtime will not be possible. To allow increasing log\nlevel above the default at runtime, see the next option.", + "id": "component-config-log-log-level-default-log-verbosity", + "name": "LOG_DEFAULT_LEVEL", + "title": "Default log verbosity", + "type": "choice" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "LOG_DEFAULT_LEVEL", + "name": "LOG_DEFAULT_LEVEL", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "LOG_MAXIMUM_EQUALS_DEFAULT", + "name": "LOG_MAXIMUM_EQUALS_DEFAULT", + "range": null, + "title": "Same as default", + "type": "bool" + }, + { + "children": [], + "depends_on": "LOG_DEFAULT_LEVEL < 1 && ", + "help": null, + "id": "LOG_MAXIMUM_LEVEL_ERROR", + "name": "LOG_MAXIMUM_LEVEL_ERROR", + "range": null, + "title": "Error", + "type": "bool" + }, + { + "children": [], + "depends_on": "LOG_DEFAULT_LEVEL < 2 && ", + "help": null, + "id": "LOG_MAXIMUM_LEVEL_WARN", + "name": "LOG_MAXIMUM_LEVEL_WARN", + "range": null, + "title": "Warning", + "type": "bool" + }, + { + "children": [], + "depends_on": "LOG_DEFAULT_LEVEL < 3 && ", + "help": null, + "id": "LOG_MAXIMUM_LEVEL_INFO", + "name": "LOG_MAXIMUM_LEVEL_INFO", + "range": null, + "title": "Info", + "type": "bool" + }, + { + "children": [], + "depends_on": "LOG_DEFAULT_LEVEL < 4 && ", + "help": null, + "id": "LOG_MAXIMUM_LEVEL_DEBUG", + "name": "LOG_MAXIMUM_LEVEL_DEBUG", + "range": null, + "title": "Debug", + "type": "bool" + }, + { + "children": [], + "depends_on": "LOG_DEFAULT_LEVEL < 5 && ", + "help": null, + "id": "LOG_MAXIMUM_LEVEL_VERBOSE", + "name": "LOG_MAXIMUM_LEVEL_VERBOSE", + "range": null, + "title": "Verbose", + "type": "bool" + } + ], + "depends_on": null, + "help": "This config option sets the highest log verbosity that it's possible to select\nat runtime by calling esp_log_level_set(). This level may be higher than\nthe default verbosity level which is set when the app starts up.\n\nThis can be used enable debugging output only at a critical point, for a particular\ntag, or to minimize startup time but then enable more logs once the firmware has\nloaded.\n\nNote that increasing the maximum available log level will increase the firmware\nbinary size.\n\nThis option only applies to logging from the app, the bootloader log level is\nfixed at compile time to the separate \"Bootloader log verbosity\" setting.", + "id": "component-config-log-log-level-maximum-log-verbosity", + "name": "LOG_MAXIMUM_LEVEL", + "title": "Maximum log verbosity", + "type": "choice" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "LOG_MAXIMUM_LEVEL", + "name": "LOG_MAXIMUM_LEVEL", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": null, + "help": "Enables an additional global \"master\" log level check that occurs before a log tag cache\nlookup. This is useful if you want to compile in a lot of logs that are selectable at\nruntime, but avoid the performance hit during periods where you don't want log output.\n\nExamples include remote log forwarding, or disabling logs during a time-critical or\nCPU-intensive section and re-enabling them later. Results in larger program size\ndepending on number of logs compiled in.\n\nIf enabled, defaults to LOG_DEFAULT_LEVEL and can be set using\nesp_log_set_level_master(). This check takes precedence over ESP_LOG_LEVEL_LOCAL.", + "id": "LOG_MASTER_LEVEL", + "name": "LOG_MASTER_LEVEL", + "range": null, + "title": "Enable global master log level", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Enabling this option allows dynamic changes to the log level at runtime\n(using esp_log_level_set()), providing the ability to increase or decrease\nthe log level during program execution.\nIf disabled, the log level remains static once set at compile-time and calling\nesp_log_level_set() will have no effect.\nIf binary size is a critical consideration and dynamic log level changes are not needed,\nconsider disabling this option when LOG_TAG_LEVEL_IMPL_NONE=y to minimize program size.", + "id": "LOG_DYNAMIC_LEVEL_CONTROL", + "name": "LOG_DYNAMIC_LEVEL_CONTROL", + "range": null, + "title": "Enable dynamic log level changes at runtime", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": "This option disables the ability to set the log level per tag.\nThe ability to change the log level at runtime depends on LOG_DYNAMIC_LEVEL_CONTROL.\nIf LOG_DYNAMIC_LEVEL_CONTROL is disabled, then changing the log level at runtime\nusing `esp_log_level_set()` is not possible.\nThis implementation is suitable for highly constrained environments.", + "id": "LOG_TAG_LEVEL_IMPL_NONE", + "name": "LOG_TAG_LEVEL_IMPL_NONE", + "range": null, + "title": "None", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": "Select this option to use the linked list-only implementation (no cache) for log level retrieval.\nThis approach searches the linked list of all tags for the log level, which may be slower\nfor a large number of tags but may have lower memory requirements than the CACHE approach.\nThe linked list approach compares the whole strings of log tags for finding the log level.", + "id": "LOG_TAG_LEVEL_IMPL_LINKED_LIST", + "name": "LOG_TAG_LEVEL_IMPL_LINKED_LIST", + "range": null, + "title": "Linked List", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": "Select this option to use a hybrid mode: cache in combination with the linked list\nfor log tag level checks. This hybrid approach offers a balance between speed and memory usage.\n\nThe cache stores recently accessed log tags and their corresponding log levels, providing\nfaster lookups for frequently used tags. The cache approach compares the tag pointers, which is\nfaster than comparing the whole strings.\n\nFor less frequently used tags, the linked list is used to search for the log level, which may be\nslower for a large number of tags but has lower memory requirements compared to a full cache.\n\nThis hybrid approach aims to improve the efficiency of log level retrieval by combining the benefits\nof both cache and linked list implementations.", + "id": "LOG_TAG_LEVEL_IMPL_CACHE_AND_LINKED_LIST", + "name": "LOG_TAG_LEVEL_IMPL_CACHE_AND_LINKED_LIST", + "range": null, + "title": "Cache + Linked List", + "type": "bool" + } + ], + "depends_on": null, + "help": "Choose the per-tag log level implementation for the log library. This functionality is used\nto enable/disable logs for a particular tag at run time. Applicable only for\napplication logs (i.e., not bootloader logs).", + "id": "component-config-log-log-level-level-settings-method-of-tag-level-checks", + "name": "LOG_TAG_LEVEL_IMPL", + "title": "Method of tag level checks", + "type": "choice" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": "This option enables the use of a simple array-based cache implementation for storing and\nretrieving log tag levels. There is no additional code that reorders the cache for fast lookups.\nSuitable for projects where memory usage optimization is crucial and the simplicity of implementation\nis preferred.", + "id": "LOG_TAG_LEVEL_CACHE_ARRAY", + "name": "LOG_TAG_LEVEL_CACHE_ARRAY", + "range": null, + "title": "Array", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": "This option enables the use of a binary min-heap-based cache implementation for efficient\nstorage and retrieval of log tag levels. It does automatically optimizing cache for fast lookups.\nSuitable for projects where speed of lookup is critical and memory usage can accommodate\nthe overhead of maintaining a binary min-heap structure.", + "id": "LOG_TAG_LEVEL_CACHE_BINARY_MIN_HEAP", + "name": "LOG_TAG_LEVEL_CACHE_BINARY_MIN_HEAP", + "range": null, + "title": "Binary Min-Heap", + "type": "bool" + } + ], + "depends_on": "LOG_TAG_LEVEL_IMPL_CACHE_AND_LINKED_LIST", + "help": "The cache stores recently accessed log tags (address of tag) and their corresponding log levels,\nproviding faster lookups for frequently used tags. Cache size can be configured using the\nLOG_TAG_LEVEL_IMPL_CACHE_SIZE option. The cache approach compares the tag pointers, which is\nfaster than comparing the whole strings.", + "id": "component-config-log-log-level-level-settings-cache-implementation", + "name": "LOG_TAG_LEVEL_CACHE_IMPL", + "title": "Cache implementation", + "type": "choice" + }, + { + "children": [], + "depends_on": "LOG_TAG_LEVEL_CACHE_ARRAY || LOG_TAG_LEVEL_CACHE_BINARY_MIN_HEAP", + "help": "This option sets the size of the cache used for log tag entries. The cache stores recently accessed\nlog tags and their corresponding log levels, which helps improve the efficiency of log level retrieval.\nThe value must be a power of 2 minus 1 (e.g., 1, 3, 7, 15, 31, 63, 127, 255, ...)\nto ensure proper cache behavior. For LOG_TAG_LEVEL_CACHE_ARRAY option the value can be any,\nwithout restrictions.\n\nNote: A larger cache size can improve lookup performance for frequently used log tags but may consume\nmore memory. Conversely, a smaller cache size reduces memory usage but may lead to more frequent cache\nevictions for less frequently used log tags.", + "id": "LOG_TAG_LEVEL_IMPL_CACHE_SIZE", + "name": "LOG_TAG_LEVEL_IMPL_CACHE_SIZE", + "range": null, + "title": "Log Tag Cache Size", + "type": "int" + } + ], + "depends_on": null, + "id": "component-config-log-log-level-level-settings", + "title": "Level Settings", + "type": "menu" + } + ], + "depends_on": null, + "id": "component-config-log-log-level", + "title": "Log Level", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": null, + "help": "Enable ANSI terminal color codes.\nIn order to view these, your terminal program must support ANSI color codes.", + "id": "LOG_COLORS", + "name": "LOG_COLORS", + "range": null, + "title": "Color", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "NO_SYMBOL && ", + "help": null, + "id": "LOG_TIMESTAMP_SOURCE_NONE", + "name": "LOG_TIMESTAMP_SOURCE_NONE", + "range": null, + "title": "None", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "LOG_TIMESTAMP_SOURCE_RTOS", + "name": "LOG_TIMESTAMP_SOURCE_RTOS", + "range": null, + "title": "Milliseconds Since Boot", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "LOG_TIMESTAMP_SOURCE_SYSTEM", + "name": "LOG_TIMESTAMP_SOURCE_SYSTEM", + "range": null, + "title": "System Time (HH:MM:SS.sss)", + "type": "bool" + }, + { + "children": [], + "depends_on": "NO_SYMBOL && ", + "help": null, + "id": "LOG_TIMESTAMP_SOURCE_SYSTEM_FULL", + "name": "LOG_TIMESTAMP_SOURCE_SYSTEM_FULL", + "range": null, + "title": "System Time (YY-MM-DD HH:MM:SS.sss)", + "type": "bool" + } + ], + "depends_on": null, + "help": "Choose what sort of timestamp is displayed in the log output:\n\n- \"None\" - The log will only contain the actual log messages themselves\n without any time-related information. Avoiding timestamps can help conserve\n processing power and memory. It might useful when you\n perform log analysis or debugging, sometimes it's more straightforward\n to work with logs that lack timestamps, especially if the time of occurrence\n is not critical for understanding the issues.\n\n- \"Milliseconds since boot\" is calculated from the RTOS tick count multiplied\n by the tick period. This time will reset after a software reboot.\n e.g. (90000)\n\n- \"System time (HH:MM:SS.sss)\" is taken from POSIX time functions which use the chip's\n RTC and high resolution timers to maintain an accurate time. The system time is\n initialized to 0 on startup, it can be set with an SNTP sync, or with\n POSIX time functions. This time will not reset after a software reboot.\n e.g. (00:01:30.000)\n\n- \"System time (YY-MM-DD HH:MM:SS.sss)\" it is the same as the above,\n but also prints the date as well.\n\n- NOTE: Currently this will not get used in logging from binary blobs\n (i.e WiFi & Bluetooth libraries), these will always print\n milliseconds since boot.", + "id": "component-config-log-format-timestamp", + "name": "LOG_TIMESTAMP_SOURCE", + "title": "Timestamp", + "type": "choice" + } + ], + "depends_on": null, + "id": "component-config-log-format", + "title": "Format", + "type": "menu" + } + ], + "depends_on": null, + "id": "component-config-log", + "title": "Log", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": null, + "help": "Builds normally if selected. Excludes LwIP from build if unselected, even if it is a\ndependency of a component or application.\nSome applications can switch their IP stacks, e.g., when switching between chip\nand Linux targets (LwIP stack vs. Linux IP stack). Since the LwIP dependency cannot\neasily be excluded based on a Kconfig option, it has to be a dependency in all cases.\nThis switch allows the LwIP stack to be built selectively, even if it is a dependency.", + "id": "LWIP_ENABLE", + "name": "LWIP_ENABLE", + "range": null, + "title": "Enable LwIP stack", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "The default name this device will report to other devices on the network.\nCould be updated at runtime with esp_netif_set_hostname()", + "id": "LWIP_LOCAL_HOSTNAME", + "name": "LWIP_LOCAL_HOSTNAME", + "range": null, + "title": "Local netif hostname", + "type": "string" + }, + { + "children": [], + "depends_on": null, + "help": "If this feature is enabled, standard POSIX APIs: if_indextoname(), if_nametoindex()\ncould be used to convert network interface index to name\ninstead of IDF specific esp-netif APIs (such as esp_netif_get_netif_impl_name())", + "id": "LWIP_NETIF_API", + "name": "LWIP_NETIF_API", + "range": null, + "title": "Enable usage of standard POSIX APIs in LWIP", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "LWIP tcpip task priority. In case of high throughput, this parameter\ncould be changed up to (configMAX_PRIORITIES-1).", + "id": "LWIP_TCPIP_TASK_PRIO", + "name": "LWIP_TCPIP_TASK_PRIO", + "range": [ + 1, + 24 + ], + "title": "LWIP TCP/IP Task Priority", + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "LWIP_TCPIP_CORE_LOCKING", + "help": "when LWIP_TCPIP_CORE_LOCKING is enabled, this lets tcpip_input() grab the\nmutex for input packets as well, instead of allocating a message and passing\nit to tcpip_thread.", + "id": "LWIP_TCPIP_CORE_LOCKING_INPUT", + "name": "LWIP_TCPIP_CORE_LOCKING_INPUT", + "range": null, + "title": "Enable tcpip core locking input", + "type": "bool" + } + ], + "depends_on": null, + "help": "If Enable tcpip core locking,Creates a global mutex that is held\nduring TCPIP thread operations.Can be locked by client code to perform\nlwIP operations without changing into TCPIP thread using callbacks.\nSee LOCK_TCPIP_CORE() and UNLOCK_TCPIP_CORE().\n\nIf disable tcpip core locking,TCP IP will perform tasks through context switching", + "id": "LWIP_TCPIP_CORE_LOCKING", + "name": "LWIP_TCPIP_CORE_LOCKING", + "range": null, + "title": "Enable tcpip core locking", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Enable to check that the project does not violate lwip thread safety.\nIf enabled, all lwip functions that require thread awareness run an assertion\nto verify that the TCP/IP core functionality is either locked or accessed\nfrom the correct thread.", + "id": "LWIP_CHECK_THREAD_SAFETY", + "name": "LWIP_CHECK_THREAD_SAFETY", + "range": null, + "title": "Checks that lwip API runs in expected context", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "If this feature is enabled, standard API such as gethostbyname\nsupport .local addresses by sending one shot multicast mDNS\nquery", + "id": "LWIP_DNS_SUPPORT_MDNS_QUERIES", + "name": "LWIP_DNS_SUPPORT_MDNS_QUERIES", + "range": null, + "title": "Enable mDNS queries in resolving host name", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "If this feature is enabled, all traffic from layer2(WIFI Driver) will be\ncopied to a new buffer before sending it to layer3(LWIP stack), freeing\nthe layer2 buffer.\nPlease be notified that the total layer2 receiving buffer is fixed and\nESP32 currently supports 25 layer2 receiving buffer, when layer2 buffer\nruns out of memory, then the incoming packets will be dropped in hardware.\nThe layer3 buffer is allocated from the heap, so the total layer3 receiving\nbuffer depends on the available heap size, when heap runs out of memory,\nno copy will be sent to layer3 and packet will be dropped in layer2.\nPlease make sure you fully understand the impact of this feature before\nenabling it.", + "id": "LWIP_L2_TO_L3_COPY", + "name": "LWIP_L2_TO_L3_COPY", + "range": null, + "title": "Enable copy between Layer2 and Layer3 packets", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "If this feature is enabled, some functions relating to RX/TX in LWIP will be\nput into IRAM, it can improve UDP/TCP throughput by >10% for single core mode,\nit doesn't help too much for dual core mode. On the other hand, it needs about\n10KB IRAM for these optimizations.\n\nIf this feature is disabled, all lwip functions will be put into FLASH.", + "id": "LWIP_IRAM_OPTIMIZATION", + "name": "LWIP_IRAM_OPTIMIZATION", + "range": null, + "title": "Enable LWIP IRAM optimization", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "If this feature is enabled, some tcp part functions relating to RX/TX in LWIP will be\nput into IRAM, it can improve TCP throughput. On the other hand, it needs about 17KB\nIRAM for these optimizations.", + "id": "LWIP_EXTRA_IRAM_OPTIMIZATION", + "name": "LWIP_EXTRA_IRAM_OPTIMIZATION", + "range": null, + "title": "Enable LWIP IRAM optimization for TCP part", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "If this feature is enabled, IGMP and MLD6 timers will be activated only\nwhen joining groups or receiving QUERY packets.\n\nThis feature will reduce the power consumption for applications which do not\nuse IGMP and MLD6.", + "id": "LWIP_TIMERS_ONDEMAND", + "name": "LWIP_TIMERS_ONDEMAND", + "range": null, + "title": "Enable LWIP Timers on demand", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "LWIP_ND6", + "help": "This option is used to set the the router flag for the NA packets.\nWhen enabled, the router flag in NA packet will always set to 1,\notherwise, never set router flag for NA packets.", + "id": "LWIP_FORCE_ROUTER_FORWARDING", + "name": "LWIP_FORCE_ROUTER_FORWARDING", + "range": null, + "title": "LWIP Force Router Forwarding Enable/Disable", + "type": "bool" + } + ], + "depends_on": "LWIP_IPV6", + "help": "This option is used to disable the Network Discovery Protocol (NDP) if it is not required.\nPlease use this option with caution, as the NDP is essential for IPv6 functionality within a local network.", + "id": "LWIP_ND6", + "name": "LWIP_ND6", + "range": null, + "title": "LWIP NDP6 Enable/Disable", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "The practical maximum limit is\ndetermined by available heap memory at runtime.\n\nSockets take up a certain amount of memory, and allowing fewer\nsockets to be open at the same time conserves memory. Specify\nthe maximum amount of sockets here. The valid value is from 1\nto 253. If using value above 61, update CMakeLists defining\nFD_SETSIZE to the number of sockets used plus the\nexpected open files (minimum of +3 for stdout, stderr and stdin).", + "id": "LWIP_MAX_SOCKETS", + "name": "LWIP_MAX_SOCKETS", + "range": [ + 1, + 253 + ], + "title": "Max number of open sockets", + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": "This option is deprecated. Do not use this option, use VFS_SUPPORT_SELECT instead.", + "id": "LWIP_USE_ONLY_LWIP_SELECT", + "name": "LWIP_USE_ONLY_LWIP_SELECT", + "range": null, + "title": "Support LWIP socket select() only (DEPRECATED)", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Enabling this option allows SO_LINGER processing.\nl_onoff = 1,l_linger can set the timeout.\n\nIf l_linger=0, When a connection is closed, TCP will terminate the connection.\nThis means that TCP will discard any data packets stored in the socket send buffer\nand send an RST to the peer.\n\nIf l_linger!=0,Then closesocket() calls to block the process until\nthe remaining data packets has been sent or timed out.", + "id": "LWIP_SO_LINGER", + "name": "LWIP_SO_LINGER", + "range": null, + "title": "Enable SO_LINGER processing", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "LWIP_SO_REUSE", + "help": "Enabling this option means that any incoming broadcast or multicast\npacket will be copied to all of the local sockets that it matches\n(may be more than one if SO_REUSEADDR is set on the socket.)\n\nThis increases memory overhead as the packets need to be copied,\nhowever they are only copied per matching socket. You can safely\ndisable it if you don't plan to receive broadcast or multicast\ntraffic on more than one socket at a time.", + "id": "LWIP_SO_REUSE_RXTOALL", + "name": "LWIP_SO_REUSE_RXTOALL", + "range": null, + "title": "SO_REUSEADDR copies broadcast/multicast to all matches", + "type": "bool" + } + ], + "depends_on": null, + "help": "Enabling this option allows binding to a port which remains in\nTIME_WAIT.", + "id": "LWIP_SO_REUSE", + "name": "LWIP_SO_REUSE", + "range": null, + "title": "Enable SO_REUSEADDR option", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Enabling this option allows checking for available data on a netconn.", + "id": "LWIP_SO_RCVBUF", + "name": "LWIP_SO_RCVBUF", + "range": null, + "title": "Enable SO_RCVBUF option", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Enabling this option allows checking for the destination address\nof a received IPv4 Packet.", + "id": "LWIP_NETBUF_RECVINFO", + "name": "LWIP_NETBUF_RECVINFO", + "range": null, + "title": "Enable IP_PKTINFO option", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Set value for Time-To-Live used by transport layers.", + "id": "LWIP_IP_DEFAULT_TTL", + "name": "LWIP_IP_DEFAULT_TTL", + "range": [ + 1, + 255 + ], + "title": "The value for Time-To-Live used by transport layers", + "type": "int" + }, + { + "children": [], + "depends_on": "LWIP_IPV4", + "help": "Enabling this option allows fragmenting outgoing IP4 packets if their size\nexceeds MTU.", + "id": "LWIP_IP4_FRAG", + "name": "LWIP_IP4_FRAG", + "range": null, + "title": "Enable fragment outgoing IP4 packets", + "type": "bool" + }, + { + "children": [], + "depends_on": "LWIP_IPV6", + "help": "Enabling this option allows fragmenting outgoing IP6 packets if their size\nexceeds MTU.", + "id": "LWIP_IP6_FRAG", + "name": "LWIP_IP6_FRAG", + "range": null, + "title": "Enable fragment outgoing IP6 packets", + "type": "bool" + }, + { + "children": [], + "depends_on": "LWIP_IPV4", + "help": "Enabling this option allows reassemblying incoming fragmented IP4 packets.", + "id": "LWIP_IP4_REASSEMBLY", + "name": "LWIP_IP4_REASSEMBLY", + "range": null, + "title": "Enable reassembly incoming fragmented IP4 packets", + "type": "bool" + }, + { + "children": [], + "depends_on": "LWIP_IPV6", + "help": "Enabling this option allows reassemblying incoming fragmented IP6 packets.", + "id": "LWIP_IP6_REASSEMBLY", + "name": "LWIP_IP6_REASSEMBLY", + "range": null, + "title": "Enable reassembly incoming fragmented IP6 packets", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Set the maximum amount of pbufs waiting to be reassembled.", + "id": "LWIP_IP_REASS_MAX_PBUFS", + "name": "LWIP_IP_REASS_MAX_PBUFS", + "range": [ + 10, + 100 + ], + "title": "The maximum amount of pbufs waiting to be reassembled", + "type": "int" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "LWIP_IPV4_NAPT", + "help": "Enabling this option allows Port Forwarding or Port mapping.", + "id": "LWIP_IPV4_NAPT_PORTMAP", + "name": "LWIP_IPV4_NAPT_PORTMAP", + "range": null, + "title": "Enable NAT Port Mapping", + "type": "bool" + } + ], + "depends_on": "LWIP_IP_FORWARD", + "help": "Enabling this option allows Network Address and Port Translation.", + "id": "LWIP_IPV4_NAPT", + "name": "LWIP_IPV4_NAPT", + "range": null, + "title": "Enable NAT", + "type": "bool" + } + ], + "depends_on": null, + "help": "Enabling this option allows packets forwarding across multiple interfaces.", + "id": "LWIP_IP_FORWARD", + "name": "LWIP_IP_FORWARD", + "range": null, + "title": "Enable IP forwarding", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Enabling this option allows LWIP statistics", + "id": "LWIP_STATS", + "name": "LWIP_STATS", + "range": null, + "title": "Enable LWIP statistics", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "LWIP_ESP_GRATUITOUS_ARP", + "help": "Set the timer interval for gratuitous ARP. The default value is 60s", + "id": "LWIP_GARP_TMR_INTERVAL", + "name": "LWIP_GARP_TMR_INTERVAL", + "range": null, + "title": "GARP timer interval(seconds)", + "type": "int" + } + ], + "depends_on": "LWIP_IPV4", + "help": "Enable this option allows to send gratuitous ARP periodically.\n\nThis option solve the compatibility issues.If the ARP table of the AP is old, and the AP\ndoesn't send ARP request to update it's ARP table, this will lead to the STA sending IP packet fail.\nThus we send gratuitous ARP periodically to let AP update it's ARP table.", + "id": "LWIP_ESP_GRATUITOUS_ARP", + "name": "LWIP_ESP_GRATUITOUS_ARP", + "range": null, + "title": "Send gratuitous ARP periodically", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "LWIP_ESP_MLDV6_REPORT", + "help": "Set the timer interval for mldv6 report. The default value is 30s", + "id": "LWIP_MLDV6_TMR_INTERVAL", + "name": "LWIP_MLDV6_TMR_INTERVAL", + "range": null, + "title": "mldv6 report timer interval(seconds)", + "type": "int" + } + ], + "depends_on": "LWIP_IPV6", + "help": "Enable this option allows to send mldv6 report periodically.\n\nThis option solve the issue that failed to receive multicast data.\nSome routers fail to forward multicast packets.\nTo solve this problem, send multicast mdlv6 report to routers regularly.", + "id": "LWIP_ESP_MLDV6_REPORT", + "name": "LWIP_ESP_MLDV6_REPORT", + "range": null, + "title": "Send mldv6 report periodically", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Set TCPIP task receive mail box size. Generally bigger value means higher throughput\nbut more memory. The value should be bigger than UDP/TCP mail box size.", + "id": "LWIP_TCPIP_RECVMBOX_SIZE", + "name": "LWIP_TCPIP_RECVMBOX_SIZE", + "range": [ + 6, + 64 + ], + "title": "TCPIP task receive mail box size", + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "!LWIP_AUTOIP && ", + "help": null, + "id": "LWIP_DHCP_DOES_ARP_CHECK", + "name": "LWIP_DHCP_DOES_ARP_CHECK", + "range": null, + "title": "DHCP provides simple ARP check", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "LWIP_DHCP_DOES_ACD_CHECK", + "name": "LWIP_DHCP_DOES_ACD_CHECK", + "range": null, + "title": "DHCP provides Address Conflict Detection (ACD)", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "LWIP_DHCP_DOES_NOT_CHECK_OFFERED_IP", + "name": "LWIP_DHCP_DOES_NOT_CHECK_OFFERED_IP", + "range": null, + "title": "DHCP does not detect conflict on the offered IP", + "type": "bool" + } + ], + "depends_on": "LWIP_IPV4", + "help": "Choose the preferred way of DHCP client to check if the offered address\nis available:\n* Using Address Conflict Detection (ACD) module assures that the offered IP address\nis properly probed and announced before binding in DHCP. This conforms to RFC5227,\nbut takes several seconds.\n* Using ARP check, we only send two ARP requests to check for replies. This process\nlasts 1 - 2 seconds.\n* No conflict detection: We directly bind the offered address.", + "id": "component-config-lwip-choose-how-dhcp-validates-offered-ip", + "name": "LWIP_DHCP_CHECKS_OFFERED_ADDRESS", + "title": "Choose how DHCP validates offered IP", + "type": "choice" + }, + { + "children": [], + "depends_on": "LWIP_IPV4", + "help": "This option could be used to disable DHCP client identification with its MAC address.\n(Client id is used by DHCP servers to uniquely identify clients and are included\nin the DHCP packets as an option 61)\nSet this option to \"y\" in order to exclude option 61 from DHCP packets.", + "id": "LWIP_DHCP_DISABLE_CLIENT_ID", + "name": "LWIP_DHCP_DISABLE_CLIENT_ID", + "range": null, + "title": "DHCP: Disable Use of HW address as client identification", + "type": "bool" + }, + { + "children": [], + "depends_on": "LWIP_IPV4", + "help": "This option could be used to disable DHCP client vendor class identification.\nSet this option to \"y\" in order to exclude option 60 from DHCP packets.", + "id": "LWIP_DHCP_DISABLE_VENDOR_CLASS_ID", + "name": "LWIP_DHCP_DISABLE_VENDOR_CLASS_ID", + "range": null, + "title": "DHCP: Disable Use of vendor class identification", + "type": "bool" + }, + { + "children": [], + "depends_on": "LWIP_IPV4", + "help": "When this option is enabled, DHCP client tries to re-obtain last valid IP address obtained from DHCP\nserver. Last valid DHCP configuration is stored in nvs and restored after reset/power-up. If IP is still\navailable, there is no need for sending discovery message to DHCP server and save some time.", + "id": "LWIP_DHCP_RESTORE_LAST_IP", + "name": "LWIP_DHCP_RESTORE_LAST_IP", + "range": null, + "title": "DHCP: Restore last IP obtained from DHCP server", + "type": "bool" + }, + { + "children": [], + "depends_on": "LWIP_IPV4", + "help": "Set total length of outgoing DHCP option msg. Generally bigger value means it can carry more\noptions and values. If your code meets LWIP_ASSERT due to option value is too long.\nPlease increase the LWIP_DHCP_OPTIONS_LEN value.", + "id": "LWIP_DHCP_OPTIONS_LEN", + "name": "LWIP_DHCP_OPTIONS_LEN", + "range": [ + 68, + 255 + ], + "title": "DHCP total option length", + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": "Number of clients that may store data in client_data member array of struct netif.", + "id": "LWIP_NUM_NETIF_CLIENT_DATA", + "name": "LWIP_NUM_NETIF_CLIENT_DATA", + "range": [ + 0, + 256 + ], + "title": "Number of clients store data in netif", + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": "Set DHCP coarse interval in seconds.\nA higher value will be less precise but cost less power consumption.", + "id": "LWIP_DHCP_COARSE_TIMER_SECS", + "name": "LWIP_DHCP_COARSE_TIMER_SECS", + "range": [ + 1, + 10 + ], + "title": "DHCP coarse timer interval(s)", + "type": "int" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "LWIP_DHCPS", + "help": "The DHCP server is calculating lease time multiplying the sent\nand received times by this number of seconds per unit.\nThe default is 60, that equals one minute.", + "id": "LWIP_DHCPS_LEASE_UNIT", + "name": "LWIP_DHCPS_LEASE_UNIT", + "range": [ + 1, + 3600 + ], + "title": "Multiplier for lease time, in seconds", + "type": "int" + }, + { + "children": [], + "depends_on": "LWIP_DHCPS", + "help": "The maximum number of DHCP clients that are connected to the server.\nAfter this number is exceeded, DHCP server removes of the oldest device\nfrom it's address pool, without notification.", + "id": "LWIP_DHCPS_MAX_STATION_NUM", + "name": "LWIP_DHCPS_MAX_STATION_NUM", + "range": [ + 1, + 64 + ], + "title": "Maximum number of stations", + "type": "int" + }, + { + "children": [], + "depends_on": "LWIP_DHCPS", + "help": "Enabling this option allows DHCP server to support temporary static ARP entries\nfor DHCP Client. This will help the DHCP server to send the DHCP OFFER and DHCP ACK using IP unicast.", + "id": "LWIP_DHCPS_STATIC_ENTRIES", + "name": "LWIP_DHCPS_STATIC_ENTRIES", + "range": null, + "title": "Enable ARP static entries", + "type": "bool" + }, + { + "children": [], + "depends_on": "LWIP_DHCPS", + "help": "This allows the DNS option to be optional in the DHCP offers,\ndepending on the server's runtime configuration.\nWhen enabled, the DHCP server will always add the DNS option to DHCP responses.\nIf a DNS server is not explicitly configured, the server's IP address will be used\nas the fallback for the DNS option.\nWhen disabled, the DHCP server will only include the DNS option in responses\nif a DNS server has been explicitly configured.\nThis option will be removed in IDF v6.x", + "id": "LWIP_DHCPS_ADD_DNS", + "name": "LWIP_DHCPS_ADD_DNS", + "range": null, + "title": "Always add DNS option in DHCP responses", + "type": "bool" + } + ], + "depends_on": "LWIP_IPV4", + "help": "Enabling this option allows the device to run the DHCP server\n(to dynamically assign IPv4 addresses to clients).", + "id": "LWIP_DHCPS", + "name": "LWIP_DHCPS", + "range": null, + "title": "DHCPS: Enable IPv4 Dynamic Host Configuration Protocol Server (DHCPS)", + "type": "bool" + } + ], + "depends_on": null, + "id": "component-config-lwip-dhcp-server", + "title": "DHCP server", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": "LWIP_AUTOIP", + "help": "DHCP client will send this many probes before self-assigning a\nlink local address.\n\nFrom LWIP help: \"This can be set as low as 1 to get an AutoIP\naddress very quickly, but you should be prepared to handle a\nchanging IP address when DHCP overrides AutoIP.\" (In the case of\nESP-IDF, this means multiple SYSTEM_EVENT_STA_GOT_IP events.)", + "id": "LWIP_AUTOIP_TRIES", + "name": "LWIP_AUTOIP_TRIES", + "range": null, + "title": "DHCP Probes before self-assigning IPv4 LL address", + "type": "int" + }, + { + "children": [], + "depends_on": "LWIP_AUTOIP", + "help": "If the AUTOIP functionality detects this many IP conflicts while\nself-assigning an address, it will go into a rate limited mode.", + "id": "LWIP_AUTOIP_MAX_CONFLICTS", + "name": "LWIP_AUTOIP_MAX_CONFLICTS", + "range": null, + "title": "Max IP conflicts before rate limiting", + "type": "int" + }, + { + "children": [], + "depends_on": "LWIP_AUTOIP", + "help": "If rate limiting self-assignment requests, wait this long between\neach request.", + "id": "LWIP_AUTOIP_RATE_LIMIT_INTERVAL", + "name": "LWIP_AUTOIP_RATE_LIMIT_INTERVAL", + "range": null, + "title": "Rate limited interval (seconds)", + "type": "int" + } + ], + "depends_on": "LWIP_IPV4", + "help": "Enabling this option allows the device to self-assign an address\nin the 169.256/16 range if none is assigned statically or via DHCP.\n\nSee RFC 3927.", + "id": "LWIP_AUTOIP", + "is_menuconfig": true, + "name": "LWIP_AUTOIP", + "range": null, + "title": "Enable IPV4 Link-Local Addressing (AUTOIP)", + "type": "menu" + }, + { + "children": [], + "depends_on": null, + "help": "Enable IPv4 stack. If you want to use IPv6 only TCP/IP stack, disable this.", + "id": "LWIP_IPV4", + "name": "LWIP_IPV4", + "range": null, + "title": "Enable IPv4", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "LWIP_IPV6", + "help": "Enabling this option allows the devices to IPV6 stateless address autoconfiguration (SLAAC).\n\nSee RFC 4862.", + "id": "LWIP_IPV6_AUTOCONFIG", + "name": "LWIP_IPV6_AUTOCONFIG", + "range": null, + "title": "Enable IPV6 stateless address autoconfiguration (SLAAC)", + "type": "bool" + }, + { + "children": [], + "depends_on": "LWIP_IPV6", + "help": "The maximum number of IPv6 addresses on each interface. Any additional\naddresses will be discarded.", + "id": "LWIP_IPV6_NUM_ADDRESSES", + "name": "LWIP_IPV6_NUM_ADDRESSES", + "range": null, + "title": "Number of IPv6 addresses on each network interface", + "type": "int" + }, + { + "children": [], + "depends_on": "LWIP_IPV6", + "help": "Forwarding IPv6 packets between interfaces is only required when acting as\na router.", + "id": "LWIP_IPV6_FORWARD", + "name": "LWIP_IPV6_FORWARD", + "range": null, + "title": "Enable IPv6 forwarding between interfaces", + "type": "bool" + } + ], + "depends_on": null, + "help": "Enable IPv6 function. If not use IPv6 function, set this option to n.\nIf disabling LWIP_IPV6 then some other components (asio) will\nno longer be available.", + "id": "LWIP_IPV6", + "name": "LWIP_IPV6", + "range": null, + "title": "Enable IPv6", + "type": "bool" + }, + { + "children": [], + "depends_on": "LWIP_IPV6_AUTOCONFIG", + "help": "Use IPv6 Router Advertisement Recursive DNS Server Option (as per RFC 6106) to\ncopy a defined maximum number of DNS servers to the DNS module.\nSet this option to a number of desired DNS servers advertised in the RA protocol.\nThis feature is disabled when set to 0.", + "id": "LWIP_IPV6_RDNSS_MAX_DNS_SERVERS", + "name": "LWIP_IPV6_RDNSS_MAX_DNS_SERVERS", + "range": null, + "title": "Use IPv6 Router Advertisement Recursive DNS Server Option", + "type": "int" + }, + { + "children": [], + "depends_on": "LWIP_IPV6_AUTOCONFIG", + "help": "Enable DHCPv6 for IPv6 stateless address autoconfiguration.\nNote that the dhcpv6 client has to be started using dhcp6_enable_stateless(netif);\nNote that the stateful address autoconfiguration is not supported.", + "id": "LWIP_IPV6_DHCP6", + "name": "LWIP_IPV6_DHCP6", + "range": null, + "title": "Enable DHCPv6 stateless address autoconfiguration", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Enable callbacks when the network interface is up/down and addresses are changed.", + "id": "LWIP_NETIF_STATUS_CALLBACK", + "name": "LWIP_NETIF_STATUS_CALLBACK", + "range": null, + "title": "Enable status callback for network interfaces", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "LWIP_NETIF_LOOPBACK", + "help": "Configure the maximum number of packets which can be queued for\nloopback on a given interface. Reducing this number may cause packets\nto be dropped, but will avoid filling memory with queued packet data.", + "id": "LWIP_LOOPBACK_MAX_PBUFS", + "name": "LWIP_LOOPBACK_MAX_PBUFS", + "range": [ + 0, + 16 + ], + "title": "Max queued loopback packets per interface", + "type": "int" + } + ], + "depends_on": null, + "help": "Enabling this option means that if a packet is sent with a destination\naddress equal to the interface's own IP address, it will \"loop back\" and\nbe received by this interface.\nDisabling this option disables support of loopback interface in lwIP", + "id": "LWIP_NETIF_LOOPBACK", + "is_menuconfig": true, + "name": "LWIP_NETIF_LOOPBACK", + "range": null, + "title": "Support per-interface loopback", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": null, + "help": "The maximum number of simultaneously active TCP\nconnections. The practical maximum limit is\ndetermined by available heap memory at runtime.\n\nChanging this value by itself does not substantially\nchange the memory usage of LWIP, except for preventing\nnew TCP connections after the limit is reached.", + "id": "LWIP_MAX_ACTIVE_TCP", + "name": "LWIP_MAX_ACTIVE_TCP", + "range": [ + 1, + 1024 + ], + "title": "Maximum active TCP Connections", + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": "The maximum number of simultaneously listening TCP\nconnections. The practical maximum limit is\ndetermined by available heap memory at runtime.\n\nChanging this value by itself does not substantially\nchange the memory usage of LWIP, except for preventing\nnew listening TCP connections after the limit is reached.", + "id": "LWIP_MAX_LISTENING_TCP", + "name": "LWIP_MAX_LISTENING_TCP", + "range": [ + 1, + 1024 + ], + "title": "Maximum listening TCP Connections", + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": "Speed up the TCP retransmission interval. If disabled,\nit is recommended to change the number of SYN retransmissions to 6,\nand TCP initial rto time to 3000.", + "id": "LWIP_TCP_HIGH_SPEED_RETRANSMISSION", + "name": "LWIP_TCP_HIGH_SPEED_RETRANSMISSION", + "range": null, + "title": "TCP high speed retransmissions", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Set maximum number of retransmissions of data segments.", + "id": "LWIP_TCP_MAXRTX", + "name": "LWIP_TCP_MAXRTX", + "range": [ + 3, + 12 + ], + "title": "Maximum number of retransmissions of data segments", + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": "Set maximum number of retransmissions of SYN segments.", + "id": "LWIP_TCP_SYNMAXRTX", + "name": "LWIP_TCP_SYNMAXRTX", + "range": [ + 3, + 12 + ], + "title": "Maximum number of retransmissions of SYN segments", + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": "Set maximum segment size for TCP transmission.\n\nCan be set lower to save RAM, the default value 1460(ipv4)/1440(ipv6) will give best throughput.\nIPv4 TCP_MSS Range: 576 <= TCP_MSS <= 1460\nIPv6 TCP_MSS Range: 1220<= TCP_MSS <= 1440", + "id": "LWIP_TCP_MSS", + "name": "LWIP_TCP_MSS", + "range": [ + 536, + 1460 + ], + "title": "Maximum Segment Size (MSS)", + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": "Set TCP timer interval in milliseconds.\n\nCan be used to speed connections on bad networks.\nA lower value will redeliver unacked packets faster.", + "id": "LWIP_TCP_TMR_INTERVAL", + "name": "LWIP_TCP_TMR_INTERVAL", + "range": null, + "title": "TCP timer interval(ms)", + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": "Set maximum segment lifetime in milliseconds.", + "id": "LWIP_TCP_MSL", + "name": "LWIP_TCP_MSL", + "range": null, + "title": "Maximum segment lifetime (MSL)", + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": "Set maximum segment lifetime in milliseconds.", + "id": "LWIP_TCP_FIN_WAIT_TIMEOUT", + "name": "LWIP_TCP_FIN_WAIT_TIMEOUT", + "range": null, + "title": "Maximum FIN segment lifetime", + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": "Set default send buffer size for new TCP sockets.\n\nPer-socket send buffer size can be changed at runtime\nwith lwip_setsockopt(s, TCP_SNDBUF, ...).\n\nThis value must be at least 2x the MSS size, and the default\nis 4x the default MSS size.\n\nSetting a smaller default SNDBUF size can save some RAM, but\nwill decrease performance.", + "id": "LWIP_TCP_SND_BUF_DEFAULT", + "name": "LWIP_TCP_SND_BUF_DEFAULT", + "range": [ + 2440, + 65535 + ], + "title": "Default send buffer size", + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": "Set default TCP receive window size for new TCP sockets.\n\nPer-socket receive window size can be changed at runtime\nwith lwip_setsockopt(s, TCP_WINDOW, ...).\n\nSetting a smaller default receive window size can save some RAM,\nbut will significantly decrease performance.", + "id": "LWIP_TCP_WND_DEFAULT", + "name": "LWIP_TCP_WND_DEFAULT", + "range": [ + 2440, + 65535 + ], + "title": "Default receive window size", + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": "Set TCP receive mail box size. Generally bigger value means higher throughput\nbut more memory. The recommended value is: LWIP_TCP_WND_DEFAULT/TCP_MSS + 2, e.g. if\nLWIP_TCP_WND_DEFAULT=14360, TCP_MSS=1436, then the recommended receive mail box size is\n(14360/1436 + 2) = 12.\n\nTCP receive mail box is a per socket mail box, when the application receives packets\nfrom TCP socket, LWIP core firstly posts the packets to TCP receive mail box and the\napplication then fetches the packets from mail box. It means LWIP can caches maximum\nLWIP_TCP_RECCVMBOX_SIZE packets for each TCP socket, so the maximum possible cached TCP packets\nfor all TCP sockets is LWIP_TCP_RECCVMBOX_SIZE multiples the maximum TCP socket number. In other\nwords, the bigger LWIP_TCP_RECVMBOX_SIZE means more memory.\nOn the other hand, if the receive mail box is too small, the mail box may be full. If the\nmail box is full, the LWIP drops the packets. So generally we need to make sure the TCP\nreceive mail box is big enough to avoid packet drop between LWIP core and application.", + "id": "LWIP_TCP_RECVMBOX_SIZE", + "name": "LWIP_TCP_RECVMBOX_SIZE", + "range": [ + 6, + 64 + ], + "title": "Default TCP receive mail box size", + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": "Set TCP accept mail box size. Generally bigger value means supporting larger backlogs\nbut more memory. The recommended value is 6, but applications can set it to a lower value\nif listening servers are meant to have a smaller backlog.\n\nTCP accept mail box is a per socket mail box, when the application listens for connections\nwith a given listening TCP socket. If the mailbox is full, LWIP will send a RST packet and\nthe client will fail to connect.", + "id": "LWIP_TCP_ACCEPTMBOX_SIZE", + "name": "LWIP_TCP_ACCEPTMBOX_SIZE", + "range": [ + 1, + 64 + ], + "title": "Default TCP accept mail box size", + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "LWIP_TCP_QUEUE_OOSEQ", + "help": "The timeout value is TCP_OOSEQ_TIMEOUT * RTO.", + "id": "LWIP_TCP_OOSEQ_TIMEOUT", + "name": "LWIP_TCP_OOSEQ_TIMEOUT", + "range": [ + 1, + 30 + ], + "title": "Timeout for each pbuf queued in TCP OOSEQ, in RTOs.", + "type": "int" + }, + { + "children": [], + "depends_on": "LWIP_TCP_QUEUE_OOSEQ", + "help": "If LWIP_TCP_OOSEQ_MAX_PBUFS = 0, TCP will not control the number of OOSEQ pbufs.\n\nIn a poor network environment, many out-of-order tcp pbufs will be received.\nThese out-of-order pbufs will be cached in the TCP out-of-order queue which will\ncause Wi-Fi/Ethernet fail to release RX buffer in time.\nIt is possible that all RX buffers for MAC layer are used by OOSEQ.\n\nControl the number of out-of-order pbufs to ensure\nthat the MAC layer has enough RX buffer to receive packets.\n\nIn the Wi-Fi scenario, recommended OOSEQ PBUFS Range:\n0 <= TCP_OOSEQ_MAX_PBUFS <= CONFIG_ESP_WIFI_DYNAMIC_RX_BUFFER_NUM/(MAX_TCP_NUMBER + 1)\n\nIn the Ethernet scenario,recommended Ethernet OOSEQ PBUFS Range:\n0 <= TCP_OOSEQ_MAX_PBUFS <= CONFIG_ETH_DMA_RX_BUFFER_NUM/(MAX_TCP_NUMBER + 1)\n\nWithin the recommended value range, the larger the value, the better the performance.\n\nMAX_TCP_NUMBER represent Maximum number of TCP connections in Wi-Fi(STA+SoftAP) and Ethernet scenario.", + "id": "LWIP_TCP_OOSEQ_MAX_PBUFS", + "name": "LWIP_TCP_OOSEQ_MAX_PBUFS", + "range": [ + 0, + 12 + ], + "title": "The maximum number of pbufs queued on OOSEQ per pcb", + "type": "int" + }, + { + "children": [], + "depends_on": "LWIP_TCP_QUEUE_OOSEQ", + "help": "TCP will support sending selective acknowledgements (SACKs).", + "id": "LWIP_TCP_SACK_OUT", + "name": "LWIP_TCP_SACK_OUT", + "range": null, + "title": "Support sending selective acknowledgements", + "type": "bool" + } + ], + "depends_on": null, + "help": "Queue incoming out-of-order segments for later use.\n\nDisable this option to save some RAM during TCP sessions, at the expense\nof increased retransmissions if segments arrive out of order.", + "id": "LWIP_TCP_QUEUE_OOSEQ", + "name": "LWIP_TCP_QUEUE_OOSEQ", + "range": null, + "title": "Queue incoming out-of-order segments", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "LWIP_TCP_OVERSIZE_MSS", + "name": "LWIP_TCP_OVERSIZE_MSS", + "range": null, + "title": "MSS", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "LWIP_TCP_OVERSIZE_QUARTER_MSS", + "name": "LWIP_TCP_OVERSIZE_QUARTER_MSS", + "range": null, + "title": "25% MSS", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "LWIP_TCP_OVERSIZE_DISABLE", + "name": "LWIP_TCP_OVERSIZE_DISABLE", + "range": null, + "title": "Disabled", + "type": "bool" + } + ], + "depends_on": null, + "help": "Allows enabling \"oversize\" allocation of TCP transmission pbufs ahead of time,\nwhich can reduce the length of pbuf chains used for transmission.\n\nThis will not make a difference to sockets where Nagle's algorithm\nis disabled.\n\nDefault value of MSS is fine for most applications, 25% MSS may save\nsome RAM when only transmitting small amounts of data. Disabled will\nhave worst performance and fragmentation characteristics, but uses\nleast RAM overall.", + "id": "component-config-lwip-tcp-pre-allocate-transmit-pbuf-size", + "name": "LWIP_TCP_OVERSIZE", + "title": "Pre-allocate transmit PBUF size", + "type": "choice" + }, + { + "children": [ + { + "children": [], + "depends_on": "LWIP_WND_SCALE", + "help": "Enable this feature to support TCP window scaling.", + "id": "LWIP_TCP_RCV_SCALE", + "name": "LWIP_TCP_RCV_SCALE", + "range": null, + "title": "Set TCP receiving window scaling factor", + "type": "int" + } + ], + "depends_on": "SPIRAM_TRY_ALLOCATE_WIFI_LWIP && !SPIRAM_IGNORE_NOTFOUND", + "help": "Enable this feature to support TCP window scaling.", + "id": "LWIP_WND_SCALE", + "name": "LWIP_WND_SCALE", + "range": null, + "title": "Support TCP window scale", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Set default TCP rto time for a reasonable initial rto.\nIn bad network environment, recommend set value of rto time to 1500.", + "id": "LWIP_TCP_RTO_TIME", + "name": "LWIP_TCP_RTO_TIME", + "range": null, + "title": "Default TCP rto time", + "type": "int" + } + ], + "depends_on": null, + "id": "component-config-lwip-tcp", + "title": "TCP", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": null, + "help": "The maximum number of active UDP \"connections\" (ie\nUDP sockets sending/receiving data).\nThe practical maximum limit is determined by available\nheap memory at runtime.", + "id": "LWIP_MAX_UDP_PCBS", + "name": "LWIP_MAX_UDP_PCBS", + "range": [ + 1, + 1024 + ], + "title": "Maximum active UDP control blocks", + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": "Set UDP receive mail box size. The recommended value is 6.\n\nUDP receive mail box is a per socket mail box, when the application receives packets\nfrom UDP socket, LWIP core firstly posts the packets to UDP receive mail box and the\napplication then fetches the packets from mail box. It means LWIP can caches maximum\nUDP_RECCVMBOX_SIZE packets for each UDP socket, so the maximum possible cached UDP packets\nfor all UDP sockets is UDP_RECCVMBOX_SIZE multiples the maximum UDP socket number. In other\nwords, the bigger UDP_RECVMBOX_SIZE means more memory.\nOn the other hand, if the receive mail box is too small, the mail box may be full. If the\nmail box is full, the LWIP drops the packets. So generally we need to make sure the UDP\nreceive mail box is big enough to avoid packet drop between LWIP core and application.", + "id": "LWIP_UDP_RECVMBOX_SIZE", + "name": "LWIP_UDP_RECVMBOX_SIZE", + "range": [ + 6, + 64 + ], + "title": "Default UDP receive mail box size", + "type": "int" + } + ], + "depends_on": null, + "id": "component-config-lwip-udp", + "title": "UDP", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": null, + "help": "Enable checksum checking for received IP messages", + "id": "LWIP_CHECKSUM_CHECK_IP", + "name": "LWIP_CHECKSUM_CHECK_IP", + "range": null, + "title": "Enable LWIP IP checksums", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Enable checksum checking for received UDP messages", + "id": "LWIP_CHECKSUM_CHECK_UDP", + "name": "LWIP_CHECKSUM_CHECK_UDP", + "range": null, + "title": "Enable LWIP UDP checksums", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Enable checksum checking for received ICMP messages", + "id": "LWIP_CHECKSUM_CHECK_ICMP", + "name": "LWIP_CHECKSUM_CHECK_ICMP", + "range": null, + "title": "Enable LWIP ICMP checksums", + "type": "bool" + } + ], + "depends_on": null, + "id": "component-config-lwip-checksums", + "title": "Checksums", + "type": "menu" + }, + { + "children": [], + "depends_on": null, + "help": "Configure TCP/IP task stack size, used by LWIP to process multi-threaded TCP/IP operations.\nSetting this stack too small will result in stack overflow crashes.", + "id": "LWIP_TCPIP_TASK_STACK_SIZE", + "name": "LWIP_TCPIP_TASK_STACK_SIZE", + "range": [ + 2048, + 65536 + ], + "title": "TCP/IP Task Stack Size", + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "LWIP_TCPIP_TASK_AFFINITY_NO_AFFINITY", + "name": "LWIP_TCPIP_TASK_AFFINITY_NO_AFFINITY", + "range": null, + "title": "No affinity", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "LWIP_TCPIP_TASK_AFFINITY_CPU0", + "name": "LWIP_TCPIP_TASK_AFFINITY_CPU0", + "range": null, + "title": "CPU0", + "type": "bool" + }, + { + "children": [], + "depends_on": "!FREERTOS_UNICORE && ", + "help": null, + "id": "LWIP_TCPIP_TASK_AFFINITY_CPU1", + "name": "LWIP_TCPIP_TASK_AFFINITY_CPU1", + "range": null, + "title": "CPU1", + "type": "bool" + } + ], + "depends_on": null, + "help": "Allows setting LwIP tasks affinity, i.e. whether the task is pinned to\nCPU0, pinned to CPU1, or allowed to run on any CPU.\nCurrently this applies to \"TCP/IP\" task and \"Ping\" task.", + "id": "component-config-lwip-tcp-ip-task-affinity", + "name": "LWIP_TCPIP_TASK_AFFINITY", + "title": "TCP/IP task affinity", + "type": "choice" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "LWIP_TCPIP_TASK_AFFINITY", + "name": "LWIP_TCPIP_TASK_AFFINITY", + "range": null, + "title": null, + "type": "hex" + }, + { + "children": [], + "depends_on": "LWIP_IPV6", + "help": "Config max number of IPv6 packets to queue during MAC resolution.", + "id": "LWIP_IPV6_MEMP_NUM_ND6_QUEUE", + "name": "LWIP_IPV6_MEMP_NUM_ND6_QUEUE", + "range": [ + 3, + 20 + ], + "title": "Max number of IPv6 packets to queue during MAC resolution", + "type": "int" + }, + { + "children": [], + "depends_on": "LWIP_IPV6", + "help": "Config max number of entries in IPv6 neighbor cache", + "id": "LWIP_IPV6_ND6_NUM_NEIGHBORS", + "name": "LWIP_IPV6_ND6_NUM_NEIGHBORS", + "range": [ + 3, + 10 + ], + "title": "Max number of entries in IPv6 neighbor cache", + "type": "int" + }, + { + "children": [], + "depends_on": "LWIP_IPV6", + "help": "Maximum number of entries in IPv6 on-link prefixes cache", + "id": "LWIP_IPV6_ND6_NUM_PREFIXES", + "name": "LWIP_IPV6_ND6_NUM_PREFIXES", + "range": null, + "title": "Max number of entries in IPv6 on-link prefixes cache", + "type": "int" + }, + { + "children": [], + "depends_on": "LWIP_IPV6", + "help": "Maximum number of entries in IPv6 default routers cache", + "id": "LWIP_IPV6_ND6_NUM_ROUTERS", + "name": "LWIP_IPV6_ND6_NUM_ROUTERS", + "range": null, + "title": "Max number of entries in IPv6 default routers cache", + "type": "int" + }, + { + "children": [], + "depends_on": "LWIP_IPV6", + "help": "Maximum number of entries in IPv6 destinations cache", + "id": "LWIP_IPV6_ND6_NUM_DESTINATIONS", + "name": "LWIP_IPV6_ND6_NUM_DESTINATIONS", + "range": null, + "title": "Max number of entries in IPv6 destinations cache", + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "LWIP_PPP_SUPPORT && LWIP_IPV4", + "help": "Enable IPCP protocol in PPP negotiations, which assigns IPv4 addresses to the PPP client,\nas well as IPv4 DNS servers.\nYou can disable this if your modem supports IPv6 only.", + "id": "LWIP_PPP_ENABLE_IPV4", + "name": "LWIP_PPP_ENABLE_IPV4", + "range": null, + "title": "Enable IPV4 support for PPP connections (IPCP)", + "type": "bool" + }, + { + "children": [], + "depends_on": "LWIP_PPP_SUPPORT && LWIP_IPV6", + "help": "Enable IPV6 support in PPP for the local link between the DTE (processor) and DCE (modem).\nThere are some modems which do not support the IPV6 addressing in the local link.\nIf they are requested for IPV6CP negotiation, they may time out.\nThis would in turn fail the configuration for the whole link.\nIf your modem is not responding correctly to PPP Phase Network, try to disable IPV6 support.", + "id": "LWIP_PPP_ENABLE_IPV6", + "name": "LWIP_PPP_ENABLE_IPV6", + "range": null, + "title": "Enable IPV6 support for PPP connections (IPV6CP)", + "type": "bool" + }, + { + "children": [], + "depends_on": "LWIP_PPP_SUPPORT", + "help": "Enable to set a callback which is called on change of the internal PPP state machine.", + "id": "LWIP_PPP_NOTIFY_PHASE_SUPPORT", + "name": "LWIP_PPP_NOTIFY_PHASE_SUPPORT", + "range": null, + "title": "Enable Notify Phase Callback", + "type": "bool" + }, + { + "children": [], + "depends_on": "LWIP_PPP_SUPPORT", + "help": "Enable Password Authentication Protocol (PAP) support", + "id": "LWIP_PPP_PAP_SUPPORT", + "name": "LWIP_PPP_PAP_SUPPORT", + "range": null, + "title": "Enable PAP support", + "type": "bool" + }, + { + "children": [], + "depends_on": "LWIP_PPP_SUPPORT", + "help": "Enable Challenge Handshake Authentication Protocol (CHAP) support", + "id": "LWIP_PPP_CHAP_SUPPORT", + "name": "LWIP_PPP_CHAP_SUPPORT", + "range": null, + "title": "Enable CHAP support", + "type": "bool" + }, + { + "children": [], + "depends_on": "LWIP_PPP_SUPPORT", + "help": "Enable Microsoft version of the Challenge-Handshake Authentication Protocol (MSCHAP) support", + "id": "LWIP_PPP_MSCHAP_SUPPORT", + "name": "LWIP_PPP_MSCHAP_SUPPORT", + "range": null, + "title": "Enable MSCHAP support", + "type": "bool" + }, + { + "children": [], + "depends_on": "LWIP_PPP_SUPPORT", + "help": "Enable Microsoft Point-to-Point Encryption (MPPE) support", + "id": "LWIP_PPP_MPPE_SUPPORT", + "name": "LWIP_PPP_MPPE_SUPPORT", + "range": null, + "title": "Enable MPPE support", + "type": "bool" + }, + { + "children": [], + "depends_on": "LWIP_PPP_SUPPORT", + "help": "Enable to use PPP server", + "id": "LWIP_PPP_SERVER_SUPPORT", + "name": "LWIP_PPP_SERVER_SUPPORT", + "range": null, + "title": "Enable PPP server support", + "type": "bool" + }, + { + "children": [], + "depends_on": "LWIP_PPP_SUPPORT", + "help": "Enable support for VJ header compression.\nPlease disable this if you're using NAPT on PPP interface,\nsince the compressed IP header might not be correctly interpreted\nin NAT causing the compressed packet to be dropped.", + "id": "LWIP_PPP_VJ_HEADER_COMPRESSION", + "name": "LWIP_PPP_VJ_HEADER_COMPRESSION", + "range": null, + "title": "Enable VJ IP Header compression", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "LWIP_ENABLE_LCP_ECHO", + "help": "Interval in seconds between keepalive LCP echo requests, 0 to disable.", + "id": "LWIP_LCP_ECHOINTERVAL", + "name": "LWIP_LCP_ECHOINTERVAL", + "range": null, + "title": "Echo interval (s)", + "type": "int" + }, + { + "children": [], + "depends_on": "LWIP_ENABLE_LCP_ECHO", + "help": "Number of consecutive unanswered echo requests before failure is indicated.", + "id": "LWIP_LCP_MAXECHOFAILS", + "name": "LWIP_LCP_MAXECHOFAILS", + "range": null, + "title": "Maximum echo failures", + "type": "int" + } + ], + "depends_on": "LWIP_PPP_SUPPORT", + "help": "Enable LCP echo keepalive requests", + "id": "LWIP_ENABLE_LCP_ECHO", + "name": "LWIP_ENABLE_LCP_ECHO", + "range": null, + "title": "Enable LCP ECHO", + "type": "bool" + }, + { + "children": [], + "depends_on": "LWIP_PPP_SUPPORT", + "help": "Enable PPP debug log output", + "id": "LWIP_PPP_DEBUG_ON", + "name": "LWIP_PPP_DEBUG_ON", + "range": null, + "title": "Enable PPP debug log output", + "type": "bool" + }, + { + "children": [], + "depends_on": "LWIP_PPP_SUPPORT && !LWIP_PPP_MPPE_SUPPORT && !LWIP_PPP_MSCHAP_SUPPORT", + "help": "This option uses mbedTLS crypto functions (instead of internal PolarSSL\nimplementation) for PPP authentication modes (PAP, CHAP, etc.).\nYou can use this option to address symbol duplication issues, since\nthe internal functions are not namespaced (e.g. md5_init()).", + "id": "LWIP_USE_EXTERNAL_MBEDTLS", + "name": "LWIP_USE_EXTERNAL_MBEDTLS", + "range": null, + "title": "Use mbedTLS instead of internal polarSSL", + "type": "bool" + } + ], + "depends_on": null, + "help": "Enable PPP stack. Now only PPP over serial is possible.", + "id": "LWIP_PPP_SUPPORT", + "is_menuconfig": true, + "name": "LWIP_PPP_SUPPORT", + "range": null, + "title": "Enable PPP support", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": "LWIP_SLIP_SUPPORT", + "help": "Enable SLIP debug log output", + "id": "LWIP_SLIP_DEBUG_ON", + "name": "LWIP_SLIP_DEBUG_ON", + "range": null, + "title": "Enable SLIP debug log output", + "type": "bool" + } + ], + "depends_on": null, + "help": "Enable SLIP stack. Now only SLIP over serial is possible.\n\nSLIP over serial support is experimental and unsupported.", + "id": "LWIP_SLIP_SUPPORT", + "is_menuconfig": true, + "name": "LWIP_SLIP_SUPPORT", + "range": null, + "title": "Enable SLIP support (new/experimental)", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": null, + "help": "Enable ICMP module for check network stability", + "id": "LWIP_ICMP", + "name": "LWIP_ICMP", + "range": null, + "title": "ICMP: Enable ICMP", + "type": "bool" + }, + { + "children": [], + "depends_on": "LWIP_ICMP6 || LWIP_ICMP", + "help": null, + "id": "LWIP_MULTICAST_PING", + "name": "LWIP_MULTICAST_PING", + "range": null, + "title": "Respond to multicast pings", + "type": "bool" + }, + { + "children": [], + "depends_on": "LWIP_ICMP", + "help": null, + "id": "LWIP_BROADCAST_PING", + "name": "LWIP_BROADCAST_PING", + "range": null, + "title": "Respond to broadcast pings", + "type": "bool" + } + ], + "depends_on": null, + "id": "component-config-lwip-icmp", + "title": "ICMP", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": null, + "help": "The maximum number of simultaneously active LWIP\nRAW protocol control blocks. The practical maximum\nlimit is determined by available heap memory at runtime.", + "id": "LWIP_MAX_RAW_PCBS", + "name": "LWIP_MAX_RAW_PCBS", + "range": [ + 1, + 1024 + ], + "title": "Maximum LWIP RAW PCBs", + "type": "int" + } + ], + "depends_on": null, + "id": "component-config-lwip-lwip-raw-api", + "title": "LWIP RAW API", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": null, + "help": "Set maximum number of NTP servers used by LwIP SNTP module.\nFirst argument of sntp_setserver/sntp_setservername functions\nis limited to this value.", + "id": "LWIP_SNTP_MAX_SERVERS", + "name": "LWIP_SNTP_MAX_SERVERS", + "range": [ + 1, + 16 + ], + "title": "Maximum number of NTP servers", + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "LWIP_DHCP_GET_NTP_SRV", + "help": "Set maximum number of NTP servers acquired via DHCP-offer.\nShould be less or equal to \"Maximum number of NTP servers\", any extra servers would be just ignored.", + "id": "LWIP_DHCP_MAX_NTP_SERVERS", + "name": "LWIP_DHCP_MAX_NTP_SERVERS", + "range": null, + "title": "Maximum number of NTP servers acquired via DHCP", + "type": "int" + } + ], + "depends_on": null, + "help": "If enabled, LWIP will add 'NTP' to Parameter-Request Option sent via DHCP-request.\nDHCP server might reply with an NTP server address in option 42.\nSNTP callback for such replies should be set accordingly (see sntp_servermode_dhcp() func.)", + "id": "LWIP_DHCP_GET_NTP_SRV", + "name": "LWIP_DHCP_GET_NTP_SRV", + "range": null, + "title": "Request NTP servers from DHCP", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "This option allows you to set the time update period via SNTP.\nDefault is 1 hour. Must not be below 15 seconds by specification.\n(SNTPv4 RFC 4330 enforces a minimum update time of 15 seconds).", + "id": "LWIP_SNTP_UPDATE_DELAY", + "name": "LWIP_SNTP_UPDATE_DELAY", + "range": [ + 15000, + 4294967295 + ], + "title": "Request interval to update time (ms)", + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "LWIP_SNTP_STARTUP_DELAY", + "help": "RFC 4330 recommends a startup delay before sending the initial request.\nLWIP calculates this delay to a random number of milliseconds between 0 and this value.", + "id": "LWIP_SNTP_MAXIMUM_STARTUP_DELAY", + "name": "LWIP_SNTP_MAXIMUM_STARTUP_DELAY", + "range": [ + 100, + 300000 + ], + "title": "Maximum startup delay (ms)", + "type": "int" + } + ], + "depends_on": null, + "help": "It is recommended (RFC 4330) to delay the initial request after by a random timeout from 1 to 5 minutes\nto reduce potential load of NTP servers after simultaneous power-up of many devices.\nThis option disables this initial delay. Please use this option with care, it could improve\na single device responsiveness but might cause peaks on the network after reset.\nAnother option to address responsiveness of devices while using the initial random delay\nis to adjust LWIP_SNTP_MAXIMUM_STARTUP_DELAY.", + "id": "LWIP_SNTP_STARTUP_DELAY", + "name": "LWIP_SNTP_STARTUP_DELAY", + "range": null, + "title": "Enable SNTP startup delay", + "type": "bool" + } + ], + "depends_on": null, + "id": "component-config-lwip-sntp", + "title": "SNTP", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": null, + "help": "Maximum number of IP addresses that can be returned by DNS queries for a single host.", + "id": "LWIP_DNS_MAX_HOST_IP", + "name": "LWIP_DNS_MAX_HOST_IP", + "range": null, + "title": "Maximum number of IP addresses per host", + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": "Set maximum number of DNS servers.\nIf fallback DNS servers are supported,\nthe number of DNS servers needs to be greater than or equal to 3.", + "id": "LWIP_DNS_MAX_SERVERS", + "name": "LWIP_DNS_MAX_SERVERS", + "range": [ + 1, + 4 + ], + "title": "Maximum number of DNS servers", + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "LWIP_FALLBACK_DNS_SERVER_SUPPORT", + "help": "This option allows you to config dns fallback server address.", + "id": "LWIP_FALLBACK_DNS_SERVER_ADDRESS", + "name": "LWIP_FALLBACK_DNS_SERVER_ADDRESS", + "range": null, + "title": "DNS fallback server address", + "type": "string" + } + ], + "depends_on": "LWIP_DNS_MAX_SERVERS >= 3", + "help": "Enable this feature to support DNS fallback server.", + "id": "LWIP_FALLBACK_DNS_SERVER_SUPPORT", + "name": "LWIP_FALLBACK_DNS_SERVER_SUPPORT", + "range": null, + "title": "Enable DNS fallback server support", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "This option allows collecting DNS server settings per netif using\nconfigurable callback function.\nIt's typically used with CONFIG_ESP_NETIF_SET_DNS_PER_DEFAULT_NETIF\nwhich configures a callback to collect the DNS info on esp_netif layer.", + "id": "LWIP_DNS_SETSERVER_WITH_NETIF", + "name": "LWIP_DNS_SETSERVER_WITH_NETIF", + "range": null, + "title": "Enable DNS server settings with netif", + "type": "bool" + } + ], + "depends_on": null, + "id": "component-config-lwip-dns", + "title": "DNS", + "type": "menu" + }, + { + "children": [], + "depends_on": null, + "help": "Set maximum number of ports a bridge can consists of.", + "id": "LWIP_BRIDGEIF_MAX_PORTS", + "name": "LWIP_BRIDGEIF_MAX_PORTS", + "range": [ + 1, + 63 + ], + "title": "Maximum number of bridge ports", + "type": "int" + }, + { + "children": [], + "depends_on": "!COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE", + "help": "Enable this option keeps LWIP assertion checks enabled.\nIt is recommended to keep this option enabled.\n\nIf asserts are disabled for the entire project, they are also disabled\nfor LWIP and this option is ignored.", + "id": "LWIP_ESP_LWIP_ASSERT", + "name": "LWIP_ESP_LWIP_ASSERT", + "range": null, + "title": "Enable LWIP ASSERT checks", + "type": "bool" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "LWIP_HOOK_TCP_ISN_NONE", + "name": "LWIP_HOOK_TCP_ISN_NONE", + "range": null, + "title": "No hook declared", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "LWIP_HOOK_TCP_ISN_DEFAULT", + "name": "LWIP_HOOK_TCP_ISN_DEFAULT", + "range": null, + "title": "Default implementation", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "LWIP_HOOK_TCP_ISN_CUSTOM", + "name": "LWIP_HOOK_TCP_ISN_CUSTOM", + "range": null, + "title": "Custom implementation", + "type": "bool" + } + ], + "depends_on": null, + "help": "Enables to define a TCP ISN hook to randomize initial sequence\nnumber in TCP connection.\nThe default TCP ISN algorithm used in IDF (standardized in RFC 6528)\nproduces ISN by combining an MD5 of the new TCP id and a stable\nsecret with the current time.\nThis is because the lwIP implementation (`tcp_next_iss`) is not\nvery strong, as it does not take into consideration any platform\nspecific entropy source.\n\nSet to LWIP_HOOK_TCP_ISN_CUSTOM to provide custom implementation.\nSet to LWIP_HOOK_TCP_ISN_NONE to use lwIP implementation.", + "id": "component-config-lwip-hooks-tcp-isn-hook", + "name": "LWIP_HOOK_TCP_ISN", + "title": "TCP ISN Hook", + "type": "choice" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "LWIP_HOOK_IP6_ROUTE_NONE", + "name": "LWIP_HOOK_IP6_ROUTE_NONE", + "range": null, + "title": "No hook declared", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "LWIP_HOOK_IP6_ROUTE_DEFAULT", + "name": "LWIP_HOOK_IP6_ROUTE_DEFAULT", + "range": null, + "title": "Default (weak) implementation", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "LWIP_HOOK_IP6_ROUTE_CUSTOM", + "name": "LWIP_HOOK_IP6_ROUTE_CUSTOM", + "range": null, + "title": "Custom implementation", + "type": "bool" + } + ], + "depends_on": "LWIP_IPV6", + "help": "Enables custom IPv6 route hook.\nSetting this to \"default\" provides weak implementation\nstub that could be overwritten in application code.\nSetting this to \"custom\" provides hook's declaration\nonly and expects the application to implement it.", + "id": "component-config-lwip-hooks-ipv6-route-hook", + "name": "LWIP_HOOK_IP6_ROUTE", + "title": "IPv6 route Hook", + "type": "choice" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "LWIP_HOOK_ND6_GET_GW_NONE", + "name": "LWIP_HOOK_ND6_GET_GW_NONE", + "range": null, + "title": "No hook declared", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "LWIP_HOOK_ND6_GET_GW_DEFAULT", + "name": "LWIP_HOOK_ND6_GET_GW_DEFAULT", + "range": null, + "title": "Default (weak) implementation", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "LWIP_HOOK_ND6_GET_GW_CUSTOM", + "name": "LWIP_HOOK_ND6_GET_GW_CUSTOM", + "range": null, + "title": "Custom implementation", + "type": "bool" + } + ], + "depends_on": "LWIP_IPV6", + "help": "Enables custom IPv6 route hook.\nSetting this to \"default\" provides weak implementation\nstub that could be overwritten in application code.\nSetting this to \"custom\" provides hook's declaration\nonly and expects the application to implement it.", + "id": "component-config-lwip-hooks-ipv6-get-gateway-hook", + "name": "LWIP_HOOK_ND6_GET_GW", + "title": "IPv6 get gateway Hook", + "type": "choice" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "LWIP_HOOK_IP6_SELECT_SRC_ADDR_NONE", + "name": "LWIP_HOOK_IP6_SELECT_SRC_ADDR_NONE", + "range": null, + "title": "No hook declared", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "LWIP_HOOK_IP6_SELECT_SRC_ADDR_DEFAULT", + "name": "LWIP_HOOK_IP6_SELECT_SRC_ADDR_DEFAULT", + "range": null, + "title": "Default (weak) implementation", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "LWIP_HOOK_IP6_SELECT_SRC_ADDR_CUSTOM", + "name": "LWIP_HOOK_IP6_SELECT_SRC_ADDR_CUSTOM", + "range": null, + "title": "Custom implementation", + "type": "bool" + } + ], + "depends_on": "LWIP_IPV6", + "help": "Enables custom IPv6 source address selection.\nSetting this to \"default\" provides weak implementation\nstub that could be overwritten in application code.\nSetting this to \"custom\" provides hook's declaration\nonly and expects the application to implement it.", + "id": "component-config-lwip-hooks-ipv6-source-address-selection-hook", + "name": "LWIP_HOOK_IP6_SELECT_SRC_ADDR", + "title": "IPv6 source address selection Hook", + "type": "choice" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "LWIP_HOOK_NETCONN_EXT_RESOLVE_NONE", + "name": "LWIP_HOOK_NETCONN_EXT_RESOLVE_NONE", + "range": null, + "title": "No hook declared", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "LWIP_HOOK_NETCONN_EXT_RESOLVE_DEFAULT", + "name": "LWIP_HOOK_NETCONN_EXT_RESOLVE_DEFAULT", + "range": null, + "title": "Default (weak) implementation", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "LWIP_HOOK_NETCONN_EXT_RESOLVE_CUSTOM", + "name": "LWIP_HOOK_NETCONN_EXT_RESOLVE_CUSTOM", + "range": null, + "title": "Custom implementation", + "type": "bool" + } + ], + "depends_on": null, + "help": "Enables custom DNS resolve hook (without callback).\nSetting this to \"default\" provides weak implementation\nstub that could be overwritten in application code.\nSetting this to \"custom\" provides hook's declaration\nonly and expects the application to implement it.", + "id": "component-config-lwip-hooks-netconn-external-resolve-hook", + "name": "LWIP_HOOK_NETCONN_EXTERNAL_RESOLVE", + "title": "Netconn external resolve Hook", + "type": "choice" + }, + { + "children": [], + "depends_on": null, + "help": "This hidden option helps configure the DNS external resolve\nhook for external components like OpenThread. It ensures that\n`LWIP_HOOK_DNS_EXT_RESOLVE_CUSTOM` is selected without directly\nadding a dependency in the choice construct.", + "id": "LWIP_HOOK_DNS_EXTERNAL_RESOLVE_SELECT_CUSTOM", + "name": "LWIP_HOOK_DNS_EXTERNAL_RESOLVE_SELECT_CUSTOM", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "LWIP_HOOK_DNS_EXT_RESOLVE_NONE", + "name": "LWIP_HOOK_DNS_EXT_RESOLVE_NONE", + "range": null, + "title": "No hook declared", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "LWIP_HOOK_DNS_EXT_RESOLVE_CUSTOM", + "name": "LWIP_HOOK_DNS_EXT_RESOLVE_CUSTOM", + "range": null, + "title": "Custom implementation", + "type": "bool" + } + ], + "depends_on": null, + "help": "Enables custom DNS resolve hook (with callback).\nSetting this to \"custom\" provides hook's declaration\nonly and expects the application to implement it.", + "id": "component-config-lwip-hooks-dns-external-resolve-hook", + "name": "LWIP_HOOK_DNS_EXTERNAL_RESOLVE", + "title": "DNS external resolve Hook", + "type": "choice" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "LWIP_HOOK_IP6_INPUT_NONE", + "name": "LWIP_HOOK_IP6_INPUT_NONE", + "range": null, + "title": "No hook declared", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "LWIP_HOOK_IP6_INPUT_DEFAULT", + "name": "LWIP_HOOK_IP6_INPUT_DEFAULT", + "range": null, + "title": "Default (weak) implementation", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "LWIP_HOOK_IP6_INPUT_CUSTOM", + "name": "LWIP_HOOK_IP6_INPUT_CUSTOM", + "range": null, + "title": "Custom implementation", + "type": "bool" + } + ], + "depends_on": "LWIP_IPV6", + "help": "Enables custom IPv6 packet input.\nSetting this to \"default\" provides weak IDF implementation,\nwhich drops all incoming IPv6 traffic if the interface has no link local address.\n(this default implementation is \"weak\" and could be still overwritten\nin the application if some additional IPv6 input packet filtering is needed)\nSetting this to \"none\" removes this default filter and conforms to the lwIP\nimplementation (which accepts multicasts even if the interface has no link local address)\nSetting this to \"custom\" provides hook's declaration\nonly and expects the application to implement it.", + "id": "component-config-lwip-hooks-ipv6-packet-input", + "name": "LWIP_HOOK_IP6_INPUT", + "title": "IPv6 packet input", + "type": "choice" + } + ], + "depends_on": null, + "id": "component-config-lwip-hooks", + "title": "Hooks", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": "LWIP_DEBUG", + "help": "Enabling this option routes all enabled LWIP debugs through ESP_LOGD.", + "id": "LWIP_DEBUG_ESP_LOG", + "name": "LWIP_DEBUG_ESP_LOG", + "range": null, + "title": "Route LWIP debugs through ESP_LOG interface", + "type": "bool" + }, + { + "children": [], + "depends_on": "LWIP_DEBUG", + "help": null, + "id": "LWIP_NETIF_DEBUG", + "name": "LWIP_NETIF_DEBUG", + "range": null, + "title": "Enable netif debug messages", + "type": "bool" + }, + { + "children": [], + "depends_on": "LWIP_DEBUG", + "help": null, + "id": "LWIP_PBUF_DEBUG", + "name": "LWIP_PBUF_DEBUG", + "range": null, + "title": "Enable pbuf debug messages", + "type": "bool" + }, + { + "children": [], + "depends_on": "LWIP_DEBUG", + "help": null, + "id": "LWIP_ETHARP_DEBUG", + "name": "LWIP_ETHARP_DEBUG", + "range": null, + "title": "Enable etharp debug messages", + "type": "bool" + }, + { + "children": [], + "depends_on": "LWIP_DEBUG", + "help": null, + "id": "LWIP_API_LIB_DEBUG", + "name": "LWIP_API_LIB_DEBUG", + "range": null, + "title": "Enable api lib debug messages", + "type": "bool" + }, + { + "children": [], + "depends_on": "LWIP_DEBUG", + "help": null, + "id": "LWIP_SOCKETS_DEBUG", + "name": "LWIP_SOCKETS_DEBUG", + "range": null, + "title": "Enable socket debug messages", + "type": "bool" + }, + { + "children": [], + "depends_on": "LWIP_DEBUG", + "help": null, + "id": "LWIP_IP_DEBUG", + "name": "LWIP_IP_DEBUG", + "range": null, + "title": "Enable IP debug messages", + "type": "bool" + }, + { + "children": [], + "depends_on": "LWIP_DEBUG && LWIP_ICMP", + "help": null, + "id": "LWIP_ICMP_DEBUG", + "name": "LWIP_ICMP_DEBUG", + "range": null, + "title": "Enable ICMP debug messages", + "type": "bool" + }, + { + "children": [], + "depends_on": "LWIP_DEBUG", + "help": null, + "id": "LWIP_DHCP_STATE_DEBUG", + "name": "LWIP_DHCP_STATE_DEBUG", + "range": null, + "title": "Enable DHCP state tracking", + "type": "bool" + }, + { + "children": [], + "depends_on": "LWIP_DEBUG", + "help": null, + "id": "LWIP_DHCP_DEBUG", + "name": "LWIP_DHCP_DEBUG", + "range": null, + "title": "Enable DHCP debug messages", + "type": "bool" + }, + { + "children": [], + "depends_on": "LWIP_DEBUG", + "help": null, + "id": "LWIP_IP6_DEBUG", + "name": "LWIP_IP6_DEBUG", + "range": null, + "title": "Enable IP6 debug messages", + "type": "bool" + }, + { + "children": [], + "depends_on": "LWIP_DEBUG", + "help": null, + "id": "LWIP_ICMP6_DEBUG", + "name": "LWIP_ICMP6_DEBUG", + "range": null, + "title": "Enable ICMP6 debug messages", + "type": "bool" + }, + { + "children": [], + "depends_on": "LWIP_DEBUG", + "help": null, + "id": "LWIP_TCP_DEBUG", + "name": "LWIP_TCP_DEBUG", + "range": null, + "title": "Enable TCP debug messages", + "type": "bool" + }, + { + "children": [], + "depends_on": "LWIP_DEBUG", + "help": null, + "id": "LWIP_UDP_DEBUG", + "name": "LWIP_UDP_DEBUG", + "range": null, + "title": "Enable UDP debug messages", + "type": "bool" + }, + { + "children": [], + "depends_on": "LWIP_DEBUG", + "help": null, + "id": "LWIP_SNTP_DEBUG", + "name": "LWIP_SNTP_DEBUG", + "range": null, + "title": "Enable SNTP debug messages", + "type": "bool" + }, + { + "children": [], + "depends_on": "LWIP_DEBUG", + "help": null, + "id": "LWIP_DNS_DEBUG", + "name": "LWIP_DNS_DEBUG", + "range": null, + "title": "Enable DNS debug messages", + "type": "bool" + }, + { + "children": [], + "depends_on": "LWIP_DEBUG && LWIP_IPV4_NAPT", + "help": null, + "id": "LWIP_NAPT_DEBUG", + "name": "LWIP_NAPT_DEBUG", + "range": null, + "title": "Enable NAPT debug messages", + "type": "bool" + }, + { + "children": [], + "depends_on": "LWIP_DEBUG", + "help": null, + "id": "LWIP_BRIDGEIF_DEBUG", + "name": "LWIP_BRIDGEIF_DEBUG", + "range": null, + "title": "Enable bridge generic debug messages", + "type": "bool" + }, + { + "children": [], + "depends_on": "LWIP_DEBUG", + "help": null, + "id": "LWIP_BRIDGEIF_FDB_DEBUG", + "name": "LWIP_BRIDGEIF_FDB_DEBUG", + "range": null, + "title": "Enable bridge FDB debug messages", + "type": "bool" + }, + { + "children": [], + "depends_on": "LWIP_DEBUG", + "help": null, + "id": "LWIP_BRIDGEIF_FW_DEBUG", + "name": "LWIP_BRIDGEIF_FW_DEBUG", + "range": null, + "title": "Enable bridge forwarding debug messages", + "type": "bool" + } + ], + "depends_on": null, + "help": "Enabling this option allows different kinds of lwIP debug output.\n\nAll lwIP debug features increase the size of the final binary.", + "id": "LWIP_DEBUG", + "is_menuconfig": true, + "name": "LWIP_DEBUG", + "range": null, + "title": "Enable LWIP Debug", + "type": "menu" + } + ], + "depends_on": null, + "id": "component-config-lwip", + "title": "LWIP", + "type": "menu" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "MBEDTLS_INTERNAL_MEM_ALLOC", + "name": "MBEDTLS_INTERNAL_MEM_ALLOC", + "range": null, + "title": "Internal memory", + "type": "bool" + }, + { + "children": [], + "depends_on": "(SPIRAM_USE_CAPS_ALLOC || SPIRAM_USE_MALLOC) && ", + "help": null, + "id": "MBEDTLS_EXTERNAL_MEM_ALLOC", + "name": "MBEDTLS_EXTERNAL_MEM_ALLOC", + "range": null, + "title": "External SPIRAM", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "MBEDTLS_DEFAULT_MEM_ALLOC", + "name": "MBEDTLS_DEFAULT_MEM_ALLOC", + "range": null, + "title": "Default alloc mode", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "MBEDTLS_CUSTOM_MEM_ALLOC", + "name": "MBEDTLS_CUSTOM_MEM_ALLOC", + "range": null, + "title": "Custom alloc mode", + "type": "bool" + }, + { + "children": [], + "depends_on": "ESP32_IRAM_AS_8BIT_ACCESSIBLE_MEMORY && ", + "help": "Allows to use IRAM memory region as 8bit accessible region.\n\nTLS input and output buffers will be allocated in IRAM section which is 32bit aligned\nmemory. Every unaligned (8bit or 16bit) access will result in an exception\nand incur penalty of certain clock cycles per unaligned read/write.", + "id": "MBEDTLS_IRAM_8BIT_MEM_ALLOC", + "name": "MBEDTLS_IRAM_8BIT_MEM_ALLOC", + "range": null, + "title": "Internal IRAM", + "type": "bool" + } + ], + "depends_on": null, + "help": "Allocation strategy for mbedTLS, essentially provides ability to\nallocate all required dynamic allocations from,\n\n- Internal DRAM memory only\n- External SPIRAM memory only\n- Either internal or external memory based on default malloc()\n behavior in ESP-IDF\n- Custom allocation mode, by overwriting calloc()/free() using\n mbedtls_platform_set_calloc_free() function\n- Internal IRAM memory wherever applicable else internal DRAM\n\nRecommended mode here is always internal (*), since that is most preferred\nfrom security perspective. But if application requirement does not\nallow sufficient free internal memory then alternate mode can be\nselected.\n\n(*) In case of ESP32-S2/ESP32-S3, hardware allows encryption of external\nSPIRAM contents provided hardware flash encryption feature is enabled.\nIn that case, using external SPIRAM allocation strategy is also safe choice\nfrom security perspective.", + "id": "component-config-mbedtls-memory-allocation-strategy", + "name": "MBEDTLS_MEM_ALLOC_MODE", + "title": "Memory allocation strategy", + "type": "choice" + }, + { + "children": [], + "depends_on": "!MBEDTLS_ASYMMETRIC_CONTENT_LEN", + "help": "Maximum TLS message length (in bytes) supported by mbedTLS.\n\n16384 is the default and this value is required to comply\nfully with TLS standards.\n\nHowever you can set a lower value in order to save RAM. This\nis safe if the other end of the connection supports Maximum\nFragment Length Negotiation Extension (max_fragment_length,\nsee RFC6066) or you know for certain that it will never send a\nmessage longer than a certain number of bytes.\n\nIf the value is set too low, symptoms are a failed TLS\nhandshake or a return value of MBEDTLS_ERR_SSL_INVALID_RECORD\n(-0x7200).", + "id": "MBEDTLS_SSL_MAX_CONTENT_LEN", + "name": "MBEDTLS_SSL_MAX_CONTENT_LEN", + "range": null, + "title": "TLS maximum message content length", + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "MBEDTLS_ASYMMETRIC_CONTENT_LEN", + "help": "This defines maximum incoming fragment length, overriding default\nmaximum content length (MBEDTLS_SSL_MAX_CONTENT_LEN).", + "id": "MBEDTLS_SSL_IN_CONTENT_LEN", + "name": "MBEDTLS_SSL_IN_CONTENT_LEN", + "range": [ + 512, + 16384 + ], + "title": "TLS maximum incoming fragment length", + "type": "int" + }, + { + "children": [], + "depends_on": "MBEDTLS_ASYMMETRIC_CONTENT_LEN", + "help": "This defines maximum outgoing fragment length, overriding default\nmaximum content length (MBEDTLS_SSL_MAX_CONTENT_LEN).", + "id": "MBEDTLS_SSL_OUT_CONTENT_LEN", + "name": "MBEDTLS_SSL_OUT_CONTENT_LEN", + "range": [ + 512, + 16384 + ], + "title": "TLS maximum outgoing fragment length", + "type": "int" + } + ], + "depends_on": null, + "help": "If enabled, this option allows customizing TLS in/out fragment length\nin asymmetric way. Please note that enabling this with default values\nsaves 12KB of dynamic memory per TLS connection.", + "id": "MBEDTLS_ASYMMETRIC_CONTENT_LEN", + "name": "MBEDTLS_ASYMMETRIC_CONTENT_LEN", + "range": null, + "title": "Asymmetric in/out fragment length", + "type": "bool" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "MBEDTLS_DYNAMIC_FREE_CONFIG_DATA", + "help": "Free CA certificate after its usage in the handshake process.\nThis option will decrease the heap footprint for the TLS handshake, but may lead to a problem:\nIf the respective ssl object needs to perform the TLS handshake again,\nthe CA certificate should once again be registered to the ssl object.", + "id": "MBEDTLS_DYNAMIC_FREE_CA_CERT", + "name": "MBEDTLS_DYNAMIC_FREE_CA_CERT", + "range": null, + "title": "Free SSL CA certificate after its usage", + "type": "bool" + } + ], + "depends_on": "MBEDTLS_DYNAMIC_BUFFER", + "help": "Free private key and DHM data after its usage in handshake process.\n\nThe option will decrease heap cost when handshake, but also lead to problem:\n\nBecause all certificate, private key and DHM data are freed so users should register\ncertificate and private key to ssl config object again.", + "id": "MBEDTLS_DYNAMIC_FREE_CONFIG_DATA", + "name": "MBEDTLS_DYNAMIC_FREE_CONFIG_DATA", + "range": null, + "title": "Free private key and DHM data after its usage", + "type": "bool" + } + ], + "depends_on": "!IDF_TARGET_LINUX && !MBEDTLS_SSL_PROTO_DTLS && !MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH", + "help": "Using dynamic TX/RX buffer. After enabling this option, mbedTLS will\nallocate TX buffer when need to send data and then free it if all data\nis sent, allocate RX buffer when need to receive data and then free it\nwhen all data is used or read by upper layer.\n\nBy default, when SSL is initialized, mbedTLS also allocate TX and\nRX buffer with the default value of \"MBEDTLS_SSL_OUT_CONTENT_LEN\" or\n\"MBEDTLS_SSL_IN_CONTENT_LEN\", so to save more heap, users can set\nthe options to be an appropriate value.", + "id": "MBEDTLS_DYNAMIC_BUFFER", + "name": "MBEDTLS_DYNAMIC_BUFFER", + "range": null, + "title": "Using dynamic TX/RX buffer", + "type": "bool" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "MBEDTLS_DEBUG_LEVEL_WARN", + "name": "MBEDTLS_DEBUG_LEVEL_WARN", + "range": null, + "title": "Warning", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "MBEDTLS_DEBUG_LEVEL_INFO", + "name": "MBEDTLS_DEBUG_LEVEL_INFO", + "range": null, + "title": "Info", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "MBEDTLS_DEBUG_LEVEL_DEBUG", + "name": "MBEDTLS_DEBUG_LEVEL_DEBUG", + "range": null, + "title": "Debug", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "MBEDTLS_DEBUG_LEVEL_VERBOSE", + "name": "MBEDTLS_DEBUG_LEVEL_VERBOSE", + "range": null, + "title": "Verbose", + "type": "bool" + } + ], + "depends_on": "MBEDTLS_DEBUG", + "help": "Set mbedTLS debugging level", + "id": "component-config-mbedtls-enable-mbedtls-debugging-set-mbedtls-debugging-level", + "name": "MBEDTLS_DEBUG_LEVEL", + "title": "Set mbedTLS debugging level", + "type": "choice" + } + ], + "depends_on": null, + "help": "Enable mbedTLS debugging functions at compile time.\n\nIf this option is enabled, you can include\n\"mbedtls/esp_debug.h\" and call mbedtls_esp_enable_debug_log()\nat runtime in order to enable mbedTLS debug output via the ESP\nlog mechanism.", + "id": "MBEDTLS_DEBUG", + "name": "MBEDTLS_DEBUG", + "range": null, + "title": "Enable mbedTLS debugging", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "MBEDTLS_DEBUG_LEVEL", + "name": "MBEDTLS_DEBUG_LEVEL", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [ + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "MBEDTLS_SSL_PROTO_TLS1_3", + "help": null, + "id": "MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE", + "name": "MBEDTLS_SSL_TLS1_3_COMPATIBILITY_MODE", + "range": null, + "title": "TLS 1.3 middlebox compatibility mode", + "type": "bool" + }, + { + "children": [], + "depends_on": "MBEDTLS_SSL_PROTO_TLS1_3", + "help": null, + "id": "MBEDTLS_SSL_TLS1_3_KEXM_PSK", + "name": "MBEDTLS_SSL_TLS1_3_KEXM_PSK", + "range": null, + "title": "TLS 1.3 PSK key exchange mode", + "type": "bool" + }, + { + "children": [], + "depends_on": "MBEDTLS_SSL_PROTO_TLS1_3", + "help": null, + "id": "MBEDTLS_SSL_TLS1_3_KEXM_EPHEMERAL", + "name": "MBEDTLS_SSL_TLS1_3_KEXM_EPHEMERAL", + "range": null, + "title": "TLS 1.3 ephemeral key exchange mode", + "type": "bool" + }, + { + "children": [], + "depends_on": "MBEDTLS_SSL_PROTO_TLS1_3", + "help": null, + "id": "MBEDTLS_SSL_TLS1_3_KEXM_PSK_EPHEMERAL", + "name": "MBEDTLS_SSL_TLS1_3_KEXM_PSK_EPHEMERAL", + "range": null, + "title": "TLS 1.3 PSK ephemeral key exchange mode", + "type": "bool" + } + ], + "depends_on": "MBEDTLS_SSL_PROTO_TLS1_3", + "id": "component-config-mbedtls-mbedtls-v3-x-related-support-tls-1-3-protocol-tls-1-3-related-configurations", + "title": "TLS 1.3 related configurations", + "type": "menu" + } + ], + "depends_on": "MBEDTLS_TLS_ENABLED && MBEDTLS_SSL_KEEP_PEER_CERTIFICATE && !MBEDTLS_DYNAMIC_BUFFER", + "help": null, + "id": "MBEDTLS_SSL_PROTO_TLS1_3", + "name": "MBEDTLS_SSL_PROTO_TLS1_3", + "range": null, + "title": "Support TLS 1.3 protocol", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "This enables the SSL buffer to be resized automatically\nbased on the negotiated maximum fragment length in each direction.", + "id": "MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH", + "name": "MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH", + "range": null, + "title": "Variable SSL buffer length", + "type": "bool" + }, + { + "children": [], + "depends_on": "MBEDTLS_ECDH_C && MBEDTLS_ECP_RESTARTABLE", + "help": "Use the legacy ECDH context format.\nDefine this option only if you enable MBEDTLS_ECP_RESTARTABLE or if you\nwant to access ECDH context fields directly.", + "id": "MBEDTLS_ECDH_LEGACY_CONTEXT", + "name": "MBEDTLS_ECDH_LEGACY_CONTEXT", + "range": null, + "title": "Use a backward compatible ECDH context (Experimental)", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Enables users to configure the set of trusted certificates\nthrough a callback instead of a linked list.\n\nSee mbedTLS documentation for required API and more details.", + "id": "MBEDTLS_X509_TRUSTED_CERT_CALLBACK", + "name": "MBEDTLS_X509_TRUSTED_CERT_CALLBACK", + "range": null, + "title": "Enable trusted certificate callbacks", + "type": "bool" + }, + { + "children": [], + "depends_on": "MBEDTLS_GCM_C || MBEDTLS_CCM_C || MBEDTLS_CHACHAPOLY_C", + "help": "Enable serialization of the TLS context structures\nThis is a local optimization in handling a single, potentially long-lived connection.\n\nSee mbedTLS documentation for required API and more details.\nDisabling this option will save some code size.", + "id": "MBEDTLS_SSL_CONTEXT_SERIALIZATION", + "name": "MBEDTLS_SSL_CONTEXT_SERIALIZATION", + "range": null, + "title": "Enable serialization of the TLS context structures", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Keep the peer's certificate after completion of the handshake.\nDisabling this option will save about 4kB of heap and some code size.\n\nSee mbedTLS documentation for required API and more details.", + "id": "MBEDTLS_SSL_KEEP_PEER_CERTIFICATE", + "name": "MBEDTLS_SSL_KEEP_PEER_CERTIFICATE", + "range": null, + "title": "Keep peer certificate after handshake completion", + "type": "bool" + }, + { + "children": [], + "depends_on": "MBEDTLS_X509_CRL_PARSE_C", + "help": "Enable PKCS number 7 core for using PKCS number 7-formatted signatures.", + "id": "MBEDTLS_PKCS7_C", + "name": "MBEDTLS_PKCS7_C", + "range": null, + "title": "Enable PKCS number 7", + "type": "bool" + }, + { + "children": [], + "depends_on": "MBEDTLS_SSL_PROTO_TLS1_3 || MBEDTLS_SSL_DTLS_CONNECTION_ID", + "help": "Controls the use of record plaintext padding in TLS 1.3 and\nwhen using the Connection ID extension in DTLS 1.2.\n\nThe padding will always be chosen so that the length of the\npadded plaintext is a multiple of the value of this option.\n\nNotes:\n A value of 1 means that no padding will be used for outgoing records.\n On systems lacking division instructions, a power of two should be preferred.", + "id": "MBEDTLS_SSL_CID_PADDING_GRANULARITY", + "name": "MBEDTLS_SSL_CID_PADDING_GRANULARITY", + "range": null, + "title": "Record plaintext padding", + "type": "int" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "MBEDTLS_SSL_DTLS_CONNECTION_ID && MBEDTLS_SSL_PROTO_DTLS", + "help": "Maximum length of CIDs used for incoming DTLS messages", + "id": "MBEDTLS_SSL_CID_IN_LEN_MAX", + "name": "MBEDTLS_SSL_CID_IN_LEN_MAX", + "range": null, + "title": "Maximum length of CIDs used for incoming DTLS messages", + "type": "int" + }, + { + "children": [], + "depends_on": "MBEDTLS_SSL_DTLS_CONNECTION_ID && MBEDTLS_SSL_PROTO_DTLS", + "help": "Maximum length of CIDs used for outgoing DTLS messages", + "id": "MBEDTLS_SSL_CID_OUT_LEN_MAX", + "name": "MBEDTLS_SSL_CID_OUT_LEN_MAX", + "range": null, + "title": "Maximum length of CIDs used for outgoing DTLS messages", + "type": "int" + } + ], + "depends_on": "MBEDTLS_SSL_PROTO_DTLS", + "help": "Enable support for the DTLS Connection ID extension which allows to\nidentify DTLS connections across changes in the underlying transport.", + "id": "MBEDTLS_SSL_DTLS_CONNECTION_ID", + "name": "MBEDTLS_SSL_DTLS_CONNECTION_ID", + "range": null, + "title": "Support for the DTLS Connection ID extension", + "type": "bool" + }, + { + "children": [], + "depends_on": "MBEDTLS_SSL_PROTO_DTLS", + "help": "Enable support for negotiation of DTLS-SRTP (RFC 5764) through the use_srtp extension.\n\nSee mbedTLS documentation for required API and more details.\nDisabling this option will save some code size.", + "id": "MBEDTLS_SSL_DTLS_SRTP", + "name": "MBEDTLS_SSL_DTLS_SRTP", + "range": null, + "title": "Enable support for negotiation of DTLS-SRTP (RFC 5764)", + "type": "bool" + } + ], + "depends_on": "MBEDTLS_SSL_PROTO_DTLS", + "id": "component-config-mbedtls-mbedtls-v3-x-related-dtls-based-configurations", + "title": "DTLS-based configurations", + "type": "menu" + } + ], + "depends_on": null, + "id": "component-config-mbedtls-mbedtls-v3-x-related", + "title": "mbedTLS v3.x related", + "type": "menu" + }, + { + "children": [ + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_FULL", + "name": "MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_FULL", + "range": null, + "title": "Use the full default certificate bundle", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": "Use only the most common certificates from the default bundles, reducing the size with 50%,\nwhile still having around 99% coverage.", + "id": "MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_CMN", + "name": "MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_CMN", + "range": null, + "title": "Use only the most common certificates from the default bundles", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_NONE", + "name": "MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_NONE", + "range": null, + "title": "Do not use the default certificate bundle", + "type": "bool" + } + ], + "depends_on": "MBEDTLS_CERTIFICATE_BUNDLE", + "help": null, + "id": "component-config-mbedtls-certificate-bundle-enable-trusted-root-certificate-bundle-default-certificate-bundle-options", + "name": "MBEDTLS_DEFAULT_CERTIFICATE_BUNDLE", + "title": "Default certificate bundle options", + "type": "choice" + }, + { + "children": [ + { + "children": [], + "depends_on": "MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE", + "help": "Name of the custom certificate directory or file. This path is evaluated\nrelative to the project root directory.", + "id": "MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE_PATH", + "name": "MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE_PATH", + "range": null, + "title": "Custom certificate bundle path", + "type": "string" + } + ], + "depends_on": "MBEDTLS_CERTIFICATE_BUNDLE", + "help": null, + "id": "MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE", + "name": "MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE", + "range": null, + "title": "Add custom certificates to the default bundle", + "type": "bool" + }, + { + "children": [], + "depends_on": "MBEDTLS_CERTIFICATE_BUNDLE && !MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_NONE", + "help": "Include the deprecated list of root certificates in the bundle.\nThis list gets updated when a certificate is removed from the Mozilla's\nNSS root certificate store. This config can be enabled if you would like\nto ensure that none of the certificates that were deployed in the product\nare affected because of the update to bundle. In turn, enabling this\nconfig keeps expired, retracted certificates in the bundle and it may\npose a security risk.\n\n- Deprecated cert list may grow based based on sync with upstream bundle\n- Deprecated certs would be be removed in ESP-IDF (next) major release", + "id": "MBEDTLS_CERTIFICATE_BUNDLE_DEPRECATED_LIST", + "name": "MBEDTLS_CERTIFICATE_BUNDLE_DEPRECATED_LIST", + "range": null, + "title": "Add deprecated root certificates", + "type": "bool" + }, + { + "children": [], + "depends_on": "MBEDTLS_CERTIFICATE_BUNDLE", + "help": null, + "id": "MBEDTLS_CERTIFICATE_BUNDLE_MAX_CERTS", + "name": "MBEDTLS_CERTIFICATE_BUNDLE_MAX_CERTS", + "range": null, + "title": "Maximum no of certificates allowed in certificate bundle", + "type": "int" + } + ], + "depends_on": null, + "help": "Enable support for large number of default root certificates\n\nWhen enabled this option allows user to store default as well\nas customer specific root certificates in compressed format rather\nthan storing full certificate. For the root certificates the public key and the subject name\nwill be stored.", + "id": "MBEDTLS_CERTIFICATE_BUNDLE", + "name": "MBEDTLS_CERTIFICATE_BUNDLE", + "range": null, + "title": "Enable trusted root certificate bundle", + "type": "bool" + } + ], + "depends_on": null, + "id": "component-config-mbedtls-certificate-bundle", + "title": "Certificate Bundle", + "type": "menu" + }, + { + "children": [], + "depends_on": "MBEDTLS_ECP_C", + "help": "Enable \"non-blocking\" ECC operations that can return early and be resumed.", + "id": "MBEDTLS_ECP_RESTARTABLE", + "name": "MBEDTLS_ECP_RESTARTABLE", + "range": null, + "title": "Enable mbedTLS ecp restartable", + "type": "bool" + }, + { + "children": [], + "depends_on": "MBEDTLS_AES_C || MBEDTLS_DES_C", + "help": "Enable the CMAC (Cipher-based Message Authentication Code) mode for\nblock ciphers.", + "id": "MBEDTLS_CMAC_C", + "name": "MBEDTLS_CMAC_C", + "range": null, + "title": "Enable CMAC mode for block ciphers", + "type": "bool" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "MBEDTLS_AES_USE_INTERRUPT", + "help": "This config helps to set the interrupt priority level for the AES peripheral.\nValue 0 (default) means that there is no preference regarding the interrupt\npriority level and any level from 1 to 3 can be selected (based on the availability).\nNote: Higher value indicates high interrupt priority.", + "id": "MBEDTLS_AES_INTERRUPT_LEVEL", + "name": "MBEDTLS_AES_INTERRUPT_LEVEL", + "range": [ + 0, + 3 + ], + "title": "AES hardware interrupt level", + "type": "int" + } + ], + "depends_on": "!IDF_TARGET_ESP32 && MBEDTLS_HARDWARE_AES", + "help": "Use an interrupt to coordinate long AES operations.\n\nThis allows other code to run on the CPU while an AES operation is pending.\nOtherwise the CPU busy-waits.", + "id": "MBEDTLS_AES_USE_INTERRUPT", + "name": "MBEDTLS_AES_USE_INTERRUPT", + "range": null, + "title": "Use interrupt for long AES operations", + "type": "bool" + } + ], + "depends_on": "!SPIRAM_CACHE_WORKAROUND_STRATEGY_DUPLDST && SOC_AES_SUPPORTED", + "help": "Enable hardware accelerated AES encryption & decryption.\n\nNote that if the ESP32 CPU is running at 240MHz, hardware AES does not\noffer any speed boost over software AES.", + "id": "MBEDTLS_HARDWARE_AES", + "name": "MBEDTLS_HARDWARE_AES", + "range": null, + "title": "Enable hardware AES acceleration", + "type": "bool" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "MBEDTLS_AES_USE_PSEUDO_ROUND_FUNC_STRENGTH_LOW", + "name": "MBEDTLS_AES_USE_PSEUDO_ROUND_FUNC_STRENGTH_LOW", + "range": null, + "title": "Low", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "MBEDTLS_AES_USE_PSEUDO_ROUND_FUNC_STRENGTH_MEDIUM", + "name": "MBEDTLS_AES_USE_PSEUDO_ROUND_FUNC_STRENGTH_MEDIUM", + "range": null, + "title": "Medium", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "MBEDTLS_AES_USE_PSEUDO_ROUND_FUNC_STRENGTH_HIGH", + "name": "MBEDTLS_AES_USE_PSEUDO_ROUND_FUNC_STRENGTH_HIGH", + "range": null, + "title": "High", + "type": "bool" + } + ], + "depends_on": "MBEDTLS_AES_USE_PSEUDO_ROUND_FUNC", + "help": "The strength of the pseudo rounds functions can be configured to low, medium and high.\nYou can configure the strength of the pseudo rounds functions according to your use cases,\nfor example, increasing the strength would provide higher security but would slow down the\nhardware AES encryption/decryption operations.", + "id": "component-config-mbedtls-enable-aes-hardware-s-pseudo-round-function-strength-of-the-pseudo-rounds-function", + "name": "MBEDTLS_AES_USE_PSEUDO_ROUND_FUNC_STRENGTH", + "title": "Strength of the pseudo rounds function", + "type": "choice" + } + ], + "depends_on": "SOC_AES_SUPPORT_PSEUDO_ROUND_FUNCTION", + "help": "Enables the pseudo round function of the AES peripheral.\nEnabling this would impact the performance of the AES operations.\nFor more info regarding the performance impact, please checkout the pseudo round function section of the\nsecurity guide.", + "id": "MBEDTLS_AES_USE_PSEUDO_ROUND_FUNC", + "name": "MBEDTLS_AES_USE_PSEUDO_ROUND_FUNC", + "range": null, + "title": "Enable AES hardware's pseudo round function", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "MBEDTLS_AES_USE_PSEUDO_ROUND_FUNC_STRENGTH", + "name": "MBEDTLS_AES_USE_PSEUDO_ROUND_FUNC_STRENGTH", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": "SOC_AES_SUPPORT_GCM && MBEDTLS_HARDWARE_AES", + "help": "Enable partially hardware accelerated GCM. GHASH calculation is still done\nin software.\n\nIf MBEDTLS_HARDWARE_GCM is disabled and MBEDTLS_HARDWARE_AES is enabled then\nmbedTLS will still use the hardware accelerated AES block operation, but\non a single block at a time.", + "id": "MBEDTLS_HARDWARE_GCM", + "name": "MBEDTLS_HARDWARE_GCM", + "range": null, + "title": "Enable partially hardware accelerated GCM", + "type": "bool" + }, + { + "children": [], + "depends_on": "MBEDTLS_HARDWARE_AES", + "help": "Enable this config to support fallback to software definitions for a non-AES\ncipher GCM operation as we support hardware acceleration only for AES cipher.\nSome of the non-AES ciphers used in a GCM operation are DES, ARIA, CAMELLIA,\nCHACHA20, BLOWFISH.\n\nIf this config is disabled, performing a non-AES cipher GCM operation with\nthe config MBEDTLS_HARDWARE_AES enabled will result in calculation of an\nAES-GCM operation instead for the given input values and thus could lead\nto failure in certificate validation which would ultimately lead to a SSL\nhandshake failure.\n\nThis config being by-default enabled leads to an increase in binary size\nfootprint of ~2.5KB.\nIn case you are sure that your use case (for example, client and server\nconfigurations in case of a TLS handshake) would not involve any GCM\noperations using a non-AES cipher, you can safely disable this config,\nleading to reduction in binary size footprint.", + "id": "MBEDTLS_GCM_SUPPORT_NON_AES_CIPHER", + "name": "MBEDTLS_GCM_SUPPORT_NON_AES_CIPHER", + "range": null, + "title": "Enable support for non-AES ciphers in GCM operation", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "MBEDTLS_HARDWARE_MPI", + "help": "Fallback to software implementation for RSA key lengths\nlarger than SOC_RSA_MAX_BIT_LEN. If this is not active\nthen the ESP will be unable to process keys greater\nthan SOC_RSA_MAX_BIT_LEN.", + "id": "MBEDTLS_LARGE_KEY_SOFTWARE_MPI", + "name": "MBEDTLS_LARGE_KEY_SOFTWARE_MPI", + "range": null, + "title": "Fallback to software implementation for larger MPI values", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "MBEDTLS_MPI_USE_INTERRUPT", + "help": "This config helps to set the interrupt priority level for the MPI peripheral.\nValue 0 (default) means that there is no preference regarding the interrupt\npriority level and any level from 1 to 3 can be selected (based on the availability).\nNote: Higher value indicates high interrupt priority.", + "id": "MBEDTLS_MPI_INTERRUPT_LEVEL", + "name": "MBEDTLS_MPI_INTERRUPT_LEVEL", + "range": [ + 0, + 3 + ], + "title": "MPI hardware interrupt level", + "type": "int" + } + ], + "depends_on": "!IDF_TARGET_ESP32 && MBEDTLS_HARDWARE_MPI", + "help": "Use an interrupt to coordinate long MPI operations.\n\nThis allows other code to run on the CPU while an MPI operation is pending.\nOtherwise the CPU busy-waits.", + "id": "MBEDTLS_MPI_USE_INTERRUPT", + "name": "MBEDTLS_MPI_USE_INTERRUPT", + "range": null, + "title": "Use interrupt for MPI exp-mod operations", + "type": "bool" + } + ], + "depends_on": "!SPIRAM_CACHE_WORKAROUND_STRATEGY_DUPLDST && SOC_MPI_SUPPORTED", + "help": "Enable hardware accelerated multiple precision integer operations.\n\nHardware accelerated multiplication, modulo multiplication,\nand modular exponentiation for up to SOC_RSA_MAX_BIT_LEN bit results.\n\nThese operations are used by RSA.", + "id": "MBEDTLS_HARDWARE_MPI", + "name": "MBEDTLS_HARDWARE_MPI", + "range": null, + "title": "Enable hardware MPI (bignum) acceleration", + "type": "bool" + }, + { + "children": [], + "depends_on": "!SPIRAM_CACHE_WORKAROUND_STRATEGY_DUPLDST && SOC_SHA_SUPPORTED", + "help": "Enable hardware accelerated SHA1, SHA256, SHA384 & SHA512 in mbedTLS.\n\nDue to a hardware limitation, on the ESP32 hardware acceleration is only\nguaranteed if SHA digests are calculated one at a time. If more\nthan one SHA digest is calculated at the same time, one will\nbe calculated fully in hardware and the rest will be calculated\n(at least partially calculated) in software. This happens automatically.\n\nSHA hardware acceleration is faster than software in some situations but\nslower in others. You should benchmark to find the best setting for you.", + "id": "MBEDTLS_HARDWARE_SHA", + "name": "MBEDTLS_HARDWARE_SHA", + "range": null, + "title": "Enable hardware SHA acceleration", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "MBEDTLS_HARDWARE_ECC", + "help": "Fallback to software implementation of ECC point multiplication and point verification\nfor curves not supported in hardware.", + "id": "MBEDTLS_ECC_OTHER_CURVES_SOFT_FALLBACK", + "name": "MBEDTLS_ECC_OTHER_CURVES_SOFT_FALLBACK", + "range": null, + "title": "Fallback to software implementation for curves not supported in hardware", + "type": "bool" + } + ], + "depends_on": "SOC_ECC_SUPPORTED", + "help": "Enable hardware accelerated ECC point multiplication and point verification for points\non curve SECP192R1 and SECP256R1 in mbedTLS", + "id": "MBEDTLS_HARDWARE_ECC", + "name": "MBEDTLS_HARDWARE_ECC", + "range": null, + "title": "Enable hardware ECC acceleration", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Use ROM MD5 in mbedTLS.", + "id": "MBEDTLS_ROM_MD5", + "name": "MBEDTLS_ROM_MD5", + "range": null, + "title": "Use MD5 implementation in ROM", + "type": "bool" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "MBEDTLS_HARDWARE_ECDSA_SIGN && IDF_TARGET_ESP32H2", + "help": "The ECDSA peripheral before ESP32-H2 v1.2 does not offer constant time ECDSA sign operation.\nThis time can be observed through power profiling of the device,\nmaking the ECDSA private key vulnerable to side-channel timing attacks.\nThis countermeasure masks the real ECDSA sign operation\nunder dummy sign operations to add randomness in the generated power signature.\nIt is highly recommended to also enable Secure Boot for the device in addition to this countermeasure\nso that only trusted software can execute on the device.\nThis countermeasure can be safely disabled for ESP32-H2 v1.2 and above.", + "id": "MBEDTLS_HARDWARE_ECDSA_SIGN_MASKING_CM", + "name": "MBEDTLS_HARDWARE_ECDSA_SIGN_MASKING_CM", + "range": null, + "title": "Mask original ECDSA sign operation under dummy sign operations", + "type": "bool" + }, + { + "children": [], + "depends_on": "MBEDTLS_HARDWARE_ECDSA_SIGN && IDF_TARGET_ESP32H2", + "help": "This option adds a delay after the actual ECDSA signature operation\nso that the entire operation appears to be constant time for the software.\nThis fix helps in protecting the device only in case of remote timing attack on the ECDSA private key.\nFor e.g., When an interface is exposed by the device to perform ECDSA signature\nof an arbitrary message.\nThe signature time would appear to be constant to the external entity after enabling\nthis option.\nThis countermeasure can be safely disabled for ESP32-H2 v1.2 and above.", + "id": "MBEDTLS_HARDWARE_ECDSA_SIGN_CONSTANT_TIME_CM", + "name": "MBEDTLS_HARDWARE_ECDSA_SIGN_CONSTANT_TIME_CM", + "range": null, + "title": "Make ECDSA signature operation pseudo constant time for software", + "type": "bool" + } + ], + "depends_on": "MBEDTLS_HARDWARE_ECDSA_SIGN && IDF_TARGET_ESP32H2", + "id": "component-config-mbedtls-enable-ecdsa-signing-using-on-chip-ecdsa-peripheral-enable-software-countermeasure-for-ecdsa-signing-using-on-chip-ecdsa-peripheral", + "title": "Enable Software Countermeasure for ECDSA signing using on-chip ECDSA peripheral", + "type": "menu" + } + ], + "depends_on": "SOC_ECDSA_SUPPORTED", + "help": "Enable hardware accelerated ECDSA peripheral to sign data\non curve SECP192R1 and SECP256R1 in mbedTLS.\n\nNote that for signing, the private key has to be burnt in an efuse key block\nwith key purpose set to ECDSA_KEY.\nIf no key is burnt, it will report an error\n\nThe key should be burnt in little endian format. espefuse.py utility handles it internally\nbut care needs to be taken while burning using esp_efuse APIs", + "id": "MBEDTLS_HARDWARE_ECDSA_SIGN", + "name": "MBEDTLS_HARDWARE_ECDSA_SIGN", + "range": null, + "title": "Enable ECDSA signing using on-chip ECDSA peripheral", + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_ECDSA_SUPPORTED", + "help": "Enable hardware accelerated ECDSA peripheral to verify signature\non curve SECP192R1 and SECP256R1 in mbedTLS.", + "id": "MBEDTLS_HARDWARE_ECDSA_VERIFY", + "name": "MBEDTLS_HARDWARE_ECDSA_VERIFY", + "range": null, + "title": "Enable ECDSA signature verification using on-chip ECDSA peripheral", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "This option enables hardware acceleration for ECDSA sign function, only\nwhen using ATECC608A cryptoauth chip.", + "id": "MBEDTLS_ATCA_HW_ECDSA_SIGN", + "name": "MBEDTLS_ATCA_HW_ECDSA_SIGN", + "range": null, + "title": "Enable hardware ECDSA sign acceleration when using ATECC608A", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "This option enables hardware acceleration for ECDSA sign function, only\nwhen using ATECC608A cryptoauth chip.", + "id": "MBEDTLS_ATCA_HW_ECDSA_VERIFY", + "name": "MBEDTLS_ATCA_HW_ECDSA_VERIFY", + "range": null, + "title": "Enable hardware ECDSA verify acceleration when using ATECC608A", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "MBEDTLS_HAVE_TIME", + "help": "Enabling this config will provide users with a function\n\"mbedtls_platform_set_time()\" that allows to set an alternative\ntime function pointer.", + "id": "MBEDTLS_PLATFORM_TIME_ALT", + "name": "MBEDTLS_PLATFORM_TIME_ALT", + "range": null, + "title": "Enable mbedtls time support: platform-specific", + "type": "bool" + }, + { + "children": [], + "depends_on": "MBEDTLS_HAVE_TIME", + "help": "Enables X.509 certificate expiry checks in mbedTLS.\n\nIf this option is disabled (default) then X.509 certificate\n\"valid from\" and \"valid to\" timestamp fields are ignored.\n\nIf this option is enabled, these fields are compared with the\ncurrent system date and time. The time is retrieved using the\nstandard time() and gmtime() functions. If the certificate is not\nvalid for the current system time then verification will fail with\ncode MBEDTLS_X509_BADCERT_FUTURE or MBEDTLS_X509_BADCERT_EXPIRED.\n\nEnabling this option requires adding functionality in the firmware\nto set the system clock to a valid timestamp before using TLS. The\nrecommended way to do this is via ESP-IDF's SNTP functionality, but\nany method can be used.\n\nIn the case where only a small number of certificates are trusted by\nthe device, please carefully consider the tradeoffs of enabling this\noption. There may be undesired consequences, for example if all\ntrusted certificates expire while the device is offline and a TLS\nconnection is required to update. Or if an issue with the SNTP\nserver means that the system time is invalid for an extended period\nafter a reset.", + "id": "MBEDTLS_HAVE_TIME_DATE", + "name": "MBEDTLS_HAVE_TIME_DATE", + "range": null, + "title": "Enable mbedtls certificate expiry check", + "type": "bool" + } + ], + "depends_on": "!ESP_TIME_FUNCS_USE_NONE", + "help": "Enable use of time.h functions (time() and gmtime()) by mbedTLS.\n\nThis option doesn't require the system time to be correct, but enables\nfunctionality that requires relative timekeeping - for example periodic\nexpiry of TLS session tickets or session cache entries.\n\nDisabling this option will save some firmware size, particularly if\nthe rest of the firmware doesn't call any standard timekeeeping\nfunctions.", + "id": "MBEDTLS_HAVE_TIME", + "name": "MBEDTLS_HAVE_TIME", + "range": null, + "title": "Enable mbedtls time support", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Standard ECDSA is \"fragile\" in the sense that lack of entropy when signing\nmay result in a compromise of the long-term signing key.", + "id": "MBEDTLS_ECDSA_DETERMINISTIC", + "name": "MBEDTLS_ECDSA_DETERMINISTIC", + "range": null, + "title": "Enable deterministic ECDSA", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Enable MBEDTLS_SHA512_C adds support for SHA-384 and SHA-512.", + "id": "MBEDTLS_SHA512_C", + "name": "MBEDTLS_SHA512_C", + "range": null, + "title": "Enable the SHA-384 and SHA-512 cryptographic hash algorithms", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Enabling MBEDTLS_SHA3_C adds support for SHA3.\nEnabling this configuration option increases the flash footprint\nby almost 4KB.", + "id": "MBEDTLS_SHA3_C", + "name": "MBEDTLS_SHA3_C", + "range": null, + "title": "Enable the SHA3 cryptographic hash algorithm", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "MBEDTLS_TLS_SERVER_AND_CLIENT", + "name": "MBEDTLS_TLS_SERVER_AND_CLIENT", + "range": null, + "title": "Server & Client", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "MBEDTLS_TLS_SERVER_ONLY", + "name": "MBEDTLS_TLS_SERVER_ONLY", + "range": null, + "title": "Server", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "MBEDTLS_TLS_CLIENT_ONLY", + "name": "MBEDTLS_TLS_CLIENT_ONLY", + "range": null, + "title": "Client", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "MBEDTLS_TLS_DISABLED", + "name": "MBEDTLS_TLS_DISABLED", + "range": null, + "title": "None", + "type": "bool" + } + ], + "depends_on": null, + "help": "mbedTLS can be compiled with protocol support for the TLS\nserver, TLS client, or both server and client.\n\nReducing the number of TLS roles supported saves code size.", + "id": "component-config-mbedtls-tls-protocol-role", + "name": "MBEDTLS_TLS_MODE", + "title": "TLS Protocol Role", + "type": "choice" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "MBEDTLS_TLS_SERVER", + "name": "MBEDTLS_TLS_SERVER", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "MBEDTLS_TLS_CLIENT", + "name": "MBEDTLS_TLS_CLIENT", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "MBEDTLS_TLS_ENABLED", + "name": "MBEDTLS_TLS_ENABLED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "MBEDTLS_PSK_MODES && MBEDTLS_TLS_ENABLED", + "help": "Enable to support symmetric key PSK (pre-shared-key) TLS key exchange modes.", + "id": "MBEDTLS_KEY_EXCHANGE_PSK", + "name": "MBEDTLS_KEY_EXCHANGE_PSK", + "range": null, + "title": "Enable PSK based ciphersuite modes", + "type": "bool" + }, + { + "children": [], + "depends_on": "MBEDTLS_PSK_MODES && MBEDTLS_DHM_C && MBEDTLS_TLS_ENABLED", + "help": "Enable to support Diffie-Hellman PSK (pre-shared-key) TLS authentication modes.", + "id": "MBEDTLS_KEY_EXCHANGE_DHE_PSK", + "name": "MBEDTLS_KEY_EXCHANGE_DHE_PSK", + "range": null, + "title": "Enable DHE-PSK based ciphersuite modes", + "type": "bool" + }, + { + "children": [], + "depends_on": "MBEDTLS_PSK_MODES && MBEDTLS_ECDH_C && MBEDTLS_TLS_ENABLED", + "help": "Enable to support Elliptic-Curve-Diffie-Hellman PSK (pre-shared-key) TLS authentication modes.", + "id": "MBEDTLS_KEY_EXCHANGE_ECDHE_PSK", + "name": "MBEDTLS_KEY_EXCHANGE_ECDHE_PSK", + "range": null, + "title": "Enable ECDHE-PSK based ciphersuite modes", + "type": "bool" + }, + { + "children": [], + "depends_on": "MBEDTLS_PSK_MODES && MBEDTLS_TLS_ENABLED", + "help": "Enable to support RSA PSK (pre-shared-key) TLS authentication modes.", + "id": "MBEDTLS_KEY_EXCHANGE_RSA_PSK", + "name": "MBEDTLS_KEY_EXCHANGE_RSA_PSK", + "range": null, + "title": "Enable RSA-PSK based ciphersuite modes", + "type": "bool" + } + ], + "depends_on": "MBEDTLS_TLS_ENABLED", + "help": "Enable to show configuration for different types of pre-shared-key TLS authentatication methods.\n\nLeaving this options disabled will save code size if they are not used.", + "id": "MBEDTLS_PSK_MODES", + "name": "MBEDTLS_PSK_MODES", + "range": null, + "title": "Enable pre-shared-key ciphersuites", + "type": "bool" + }, + { + "children": [], + "depends_on": "MBEDTLS_TLS_ENABLED", + "help": "Enable to support ciphersuites with prefix TLS-RSA-WITH-", + "id": "MBEDTLS_KEY_EXCHANGE_RSA", + "name": "MBEDTLS_KEY_EXCHANGE_RSA", + "range": null, + "title": "Enable RSA-only based ciphersuite modes", + "type": "bool" + }, + { + "children": [], + "depends_on": "MBEDTLS_DHM_C && MBEDTLS_TLS_ENABLED", + "help": "Enable to support ciphersuites with prefix TLS-DHE-RSA-WITH-", + "id": "MBEDTLS_KEY_EXCHANGE_DHE_RSA", + "name": "MBEDTLS_KEY_EXCHANGE_DHE_RSA", + "range": null, + "title": "Enable DHE-RSA based ciphersuite modes", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE && MBEDTLS_ECDH_C && MBEDTLS_TLS_ENABLED", + "help": "Enable to support ciphersuites with prefix TLS-ECDHE-RSA-WITH-", + "id": "MBEDTLS_KEY_EXCHANGE_ECDHE_RSA", + "name": "MBEDTLS_KEY_EXCHANGE_ECDHE_RSA", + "range": null, + "title": "Enable ECDHE-RSA based ciphersuite modes", + "type": "bool" + }, + { + "children": [], + "depends_on": "MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE && MBEDTLS_ECDH_C && MBEDTLS_ECDSA_C && MBEDTLS_TLS_ENABLED", + "help": "Enable to support ciphersuites with prefix TLS-ECDHE-ECDSA-WITH-", + "id": "MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA", + "name": "MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA", + "range": null, + "title": "Enable ECDHE-ECDSA based ciphersuite modes", + "type": "bool" + }, + { + "children": [], + "depends_on": "MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE && MBEDTLS_ECDH_C && MBEDTLS_ECDSA_C && MBEDTLS_TLS_ENABLED", + "help": "Enable to support ciphersuites with prefix TLS-ECDH-ECDSA-WITH-", + "id": "MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA", + "name": "MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA", + "range": null, + "title": "Enable ECDH-ECDSA based ciphersuite modes", + "type": "bool" + }, + { + "children": [], + "depends_on": "MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE && MBEDTLS_ECDH_C && MBEDTLS_TLS_ENABLED", + "help": "Enable to support ciphersuites with prefix TLS-ECDH-RSA-WITH-", + "id": "MBEDTLS_KEY_EXCHANGE_ECDH_RSA", + "name": "MBEDTLS_KEY_EXCHANGE_ECDH_RSA", + "range": null, + "title": "Enable ECDH-RSA based ciphersuite modes", + "type": "bool" + } + ], + "depends_on": "MBEDTLS_ECP_C && MBEDTLS_TLS_ENABLED", + "help": "Enable to show Elliptic Curve based ciphersuite mode options.\n\nDisabling all Elliptic Curve ciphersuites saves code size and\ncan give slightly faster TLS handshakes, provided the server supports\nRSA-only ciphersuite modes.", + "id": "MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE", + "name": "MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE", + "range": null, + "title": "Support Elliptic Curve based ciphersuites", + "type": "bool" + }, + { + "children": [], + "depends_on": "MBEDTLS_ECJPAKE_C && MBEDTLS_ECP_DP_SECP256R1_ENABLED && MBEDTLS_TLS_ENABLED", + "help": "Enable to support ciphersuites with prefix TLS-ECJPAKE-WITH-", + "id": "MBEDTLS_KEY_EXCHANGE_ECJPAKE", + "name": "MBEDTLS_KEY_EXCHANGE_ECJPAKE", + "range": null, + "title": "Enable ECJPAKE based ciphersuite modes", + "type": "bool" + } + ], + "depends_on": "MBEDTLS_TLS_ENABLED", + "id": "component-config-mbedtls-tls-key-exchange-methods", + "title": "TLS Key Exchange Methods", + "type": "menu" + }, + { + "children": [], + "depends_on": "MBEDTLS_TLS_ENABLED && MBEDTLS_SSL_PROTO_TLS1_2", + "help": "The two main uses of renegotiation are (1) refresh keys on long-lived\nconnections and (2) client authentication after the initial handshake.\nIf you don't need renegotiation, disabling it will save code size and\nreduce the possibility of abuse/vulnerability.", + "id": "MBEDTLS_SSL_RENEGOTIATION", + "name": "MBEDTLS_SSL_RENEGOTIATION", + "range": null, + "title": "Support TLS renegotiation", + "type": "bool" + }, + { + "children": [], + "depends_on": "MBEDTLS_TLS_ENABLED", + "help": null, + "id": "MBEDTLS_SSL_PROTO_TLS1_2", + "name": "MBEDTLS_SSL_PROTO_TLS1_2", + "range": null, + "title": "Support TLS 1.2 protocol", + "type": "bool" + }, + { + "children": [], + "depends_on": "MBEDTLS_TLS_ENABLED", + "help": "Provisions for GM/T SSL 1.1 support", + "id": "MBEDTLS_SSL_PROTO_GMTSSL1_1", + "name": "MBEDTLS_SSL_PROTO_GMTSSL1_1", + "range": null, + "title": "Support GM/T SSL 1.1 protocol", + "type": "bool" + }, + { + "children": [], + "depends_on": "MBEDTLS_SSL_PROTO_TLS1_2", + "help": "Requires TLS 1.2 to be enabled for DTLS 1.2", + "id": "MBEDTLS_SSL_PROTO_DTLS", + "name": "MBEDTLS_SSL_PROTO_DTLS", + "range": null, + "title": "Support DTLS protocol (all versions)", + "type": "bool" + }, + { + "children": [], + "depends_on": "MBEDTLS_TLS_ENABLED", + "help": "Disabling this option will save some code size if it is not needed.", + "id": "MBEDTLS_SSL_ALPN", + "name": "MBEDTLS_SSL_ALPN", + "range": null, + "title": "Support ALPN (Application Layer Protocol Negotiation)", + "type": "bool" + }, + { + "children": [], + "depends_on": "MBEDTLS_TLS_ENABLED", + "help": "Client support for RFC 5077 session tickets. See mbedTLS documentation for more details.\nDisabling this option will save some code size.", + "id": "MBEDTLS_CLIENT_SSL_SESSION_TICKETS", + "name": "MBEDTLS_CLIENT_SSL_SESSION_TICKETS", + "range": null, + "title": "TLS: Client Support for RFC 5077 SSL session tickets", + "type": "bool" + }, + { + "children": [], + "depends_on": "MBEDTLS_TLS_ENABLED && (MBEDTLS_GCM_C || MBEDTLS_CCM_C || MBEDTLS_CHACHAPOLY_C)", + "help": "Server support for RFC 5077 session tickets. See mbedTLS documentation for more details.\nDisabling this option will save some code size.", + "id": "MBEDTLS_SERVER_SSL_SESSION_TICKETS", + "name": "MBEDTLS_SERVER_SSL_SESSION_TICKETS", + "range": null, + "title": "TLS: Server Support for RFC 5077 SSL session tickets", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": null, + "help": null, + "id": "MBEDTLS_AES_C", + "name": "MBEDTLS_AES_C", + "range": null, + "title": "AES block cipher", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "MBEDTLS_CAMELLIA_C", + "name": "MBEDTLS_CAMELLIA_C", + "range": null, + "title": "Camellia block cipher", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Enables the DES block cipher to support 3DES-based TLS ciphersuites.\n\n3DES is vulnerable to the Sweet32 attack and should only be enabled\nif absolutely necessary.", + "id": "MBEDTLS_DES_C", + "name": "MBEDTLS_DES_C", + "range": null, + "title": "DES block cipher (legacy, insecure)", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Enables the Blowfish block cipher (not used for TLS sessions.)\n\nThe Blowfish cipher is not used for mbedTLS TLS sessions but can be\nused for other purposes. Read up on the limitations of Blowfish (including\nSweet32) before enabling.", + "id": "MBEDTLS_BLOWFISH_C", + "name": "MBEDTLS_BLOWFISH_C", + "range": null, + "title": "Blowfish block cipher (read help)", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Enables the XTEA block cipher.", + "id": "MBEDTLS_XTEA_C", + "name": "MBEDTLS_XTEA_C", + "range": null, + "title": "XTEA block cipher", + "type": "bool" + }, + { + "children": [], + "depends_on": "MBEDTLS_AES_C || MBEDTLS_CAMELLIA_C", + "help": "Enable Counter with CBC-MAC (CCM) modes for AES and/or Camellia ciphers.\n\nDisabling this option saves some code size.", + "id": "MBEDTLS_CCM_C", + "name": "MBEDTLS_CCM_C", + "range": null, + "title": "CCM (Counter with CBC-MAC) block cipher modes", + "type": "bool" + }, + { + "children": [], + "depends_on": "MBEDTLS_AES_C || MBEDTLS_CAMELLIA_C", + "help": "Enable Galois/Counter Mode for AES and/or Camellia ciphers.\n\nThis option is generally faster than CCM.", + "id": "MBEDTLS_GCM_C", + "name": "MBEDTLS_GCM_C", + "range": null, + "title": "GCM (Galois/Counter) block cipher modes", + "type": "bool" + }, + { + "children": [], + "depends_on": "MBEDTLS_AES_C", + "help": "Enable NIST key wrapping and key wrapping padding.", + "id": "MBEDTLS_NIST_KW_C", + "name": "MBEDTLS_NIST_KW_C", + "range": null, + "title": "NIST key wrapping (KW) and KW padding (KWP)", + "type": "bool" + } + ], + "depends_on": null, + "id": "component-config-mbedtls-symmetric-ciphers", + "title": "Symmetric Ciphers", + "type": "menu" + }, + { + "children": [], + "depends_on": null, + "help": "Enable the RIPEMD-160 hash algorithm.", + "id": "MBEDTLS_RIPEMD160_C", + "name": "MBEDTLS_RIPEMD160_C", + "range": null, + "title": "Enable RIPEMD-160 hash algorithm", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": null, + "help": "Enable decoding/parsing of PEM formatted certificates.\n\nIf your certificates are all in the simpler DER format, disabling\nthis option will save some code size.", + "id": "MBEDTLS_PEM_PARSE_C", + "name": "MBEDTLS_PEM_PARSE_C", + "range": null, + "title": "Read & Parse PEM formatted certificates", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Enable writing of PEM formatted certificates.\n\nIf writing certificate data only in DER format, disabling this\noption will save some code size.", + "id": "MBEDTLS_PEM_WRITE_C", + "name": "MBEDTLS_PEM_WRITE_C", + "range": null, + "title": "Write PEM formatted certificates", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Support for parsing X.509 Certificate Revocation Lists.", + "id": "MBEDTLS_X509_CRL_PARSE_C", + "name": "MBEDTLS_X509_CRL_PARSE_C", + "range": null, + "title": "X.509 CRL parsing", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Support for parsing X.509 Certificate Signing Requests", + "id": "MBEDTLS_X509_CSR_PARSE_C", + "name": "MBEDTLS_X509_CSR_PARSE_C", + "range": null, + "title": "X.509 CSR parsing", + "type": "bool" + } + ], + "depends_on": null, + "id": "component-config-mbedtls-certificates", + "title": "Certificates", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": "MBEDTLS_ECP_C", + "help": "Enhance support for reading EC keys using variants of SEC1 not allowed by\nRFC 5915 and RFC 5480.", + "id": "MBEDTLS_PK_PARSE_EC_EXTENDED", + "name": "MBEDTLS_PK_PARSE_EC_EXTENDED", + "range": null, + "title": "Enhance support for reading EC keys", + "type": "bool" + }, + { + "children": [], + "depends_on": "MBEDTLS_ECP_C", + "help": "Enable the support for parsing public keys of type Short Weierstrass\n(MBEDTLS_ECP_DP_SECP_XXX and MBEDTLS_ECP_DP_BP_XXX) which are using the\ncompressed point format. This parsing is done through ECP module's functions.", + "id": "MBEDTLS_PK_PARSE_EC_COMPRESSED", + "name": "MBEDTLS_PK_PARSE_EC_COMPRESSED", + "range": null, + "title": "Enable the support for parsing public keys of type Short Weierstrass", + "type": "bool" + } + ], + "depends_on": null, + "help": null, + "id": "MBEDTLS_ECP_C", + "is_menuconfig": true, + "name": "MBEDTLS_ECP_C", + "range": null, + "title": "Elliptic Curve Ciphers", + "type": "menu" + }, + { + "children": [], + "depends_on": null, + "help": "Enable DHM. Needed to use DHE-xxx TLS ciphersuites.\n\nNote that the security of Diffie-Hellman key exchanges depends on\na suitable prime being used for the exchange. Please see detailed\nwarning text about this in file `mbedtls/dhm.h` file.", + "id": "MBEDTLS_DHM_C", + "name": "MBEDTLS_DHM_C", + "range": null, + "title": "Diffie-Hellman-Merkle key exchange (DHM)", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "MBEDTLS_ECDH_C", + "help": "Enable ECDSA. Needed to use ECDSA-xxx TLS ciphersuites.", + "id": "MBEDTLS_ECDSA_C", + "name": "MBEDTLS_ECDSA_C", + "range": null, + "title": "Elliptic Curve DSA", + "type": "bool" + } + ], + "depends_on": "MBEDTLS_ECP_C", + "help": "Enable ECDH. Needed to use ECDHE-xxx TLS ciphersuites.", + "id": "MBEDTLS_ECDH_C", + "name": "MBEDTLS_ECDH_C", + "range": null, + "title": "Elliptic Curve Diffie-Hellman (ECDH)", + "type": "bool" + }, + { + "children": [], + "depends_on": "MBEDTLS_ECP_C", + "help": "Enable ECJPAKE. Needed to use ECJPAKE-xxx TLS ciphersuites.", + "id": "MBEDTLS_ECJPAKE_C", + "name": "MBEDTLS_ECJPAKE_C", + "range": null, + "title": "Elliptic curve J-PAKE", + "type": "bool" + }, + { + "children": [], + "depends_on": "MBEDTLS_ECP_C", + "help": "Enable support for SECP192R1 Elliptic Curve.", + "id": "MBEDTLS_ECP_DP_SECP192R1_ENABLED", + "name": "MBEDTLS_ECP_DP_SECP192R1_ENABLED", + "range": null, + "title": "Enable SECP192R1 curve", + "type": "bool" + }, + { + "children": [], + "depends_on": "MBEDTLS_ECP_C", + "help": "Enable support for SECP224R1 Elliptic Curve.", + "id": "MBEDTLS_ECP_DP_SECP224R1_ENABLED", + "name": "MBEDTLS_ECP_DP_SECP224R1_ENABLED", + "range": null, + "title": "Enable SECP224R1 curve", + "type": "bool" + }, + { + "children": [], + "depends_on": "MBEDTLS_ECP_C", + "help": "Enable support for SECP256R1 Elliptic Curve.", + "id": "MBEDTLS_ECP_DP_SECP256R1_ENABLED", + "name": "MBEDTLS_ECP_DP_SECP256R1_ENABLED", + "range": null, + "title": "Enable SECP256R1 curve", + "type": "bool" + }, + { + "children": [], + "depends_on": "MBEDTLS_ECP_C", + "help": "Enable support for SECP384R1 Elliptic Curve.", + "id": "MBEDTLS_ECP_DP_SECP384R1_ENABLED", + "name": "MBEDTLS_ECP_DP_SECP384R1_ENABLED", + "range": null, + "title": "Enable SECP384R1 curve", + "type": "bool" + }, + { + "children": [], + "depends_on": "MBEDTLS_ECP_C", + "help": "Enable support for SECP521R1 Elliptic Curve.", + "id": "MBEDTLS_ECP_DP_SECP521R1_ENABLED", + "name": "MBEDTLS_ECP_DP_SECP521R1_ENABLED", + "range": null, + "title": "Enable SECP521R1 curve", + "type": "bool" + }, + { + "children": [], + "depends_on": "MBEDTLS_ECP_C", + "help": "Enable support for SECP192K1 Elliptic Curve.", + "id": "MBEDTLS_ECP_DP_SECP192K1_ENABLED", + "name": "MBEDTLS_ECP_DP_SECP192K1_ENABLED", + "range": null, + "title": "Enable SECP192K1 curve", + "type": "bool" + }, + { + "children": [], + "depends_on": "MBEDTLS_ECP_C", + "help": "Enable support for SECP224K1 Elliptic Curve.", + "id": "MBEDTLS_ECP_DP_SECP224K1_ENABLED", + "name": "MBEDTLS_ECP_DP_SECP224K1_ENABLED", + "range": null, + "title": "Enable SECP224K1 curve", + "type": "bool" + }, + { + "children": [], + "depends_on": "MBEDTLS_ECP_C", + "help": "Enable support for SECP256K1 Elliptic Curve.", + "id": "MBEDTLS_ECP_DP_SECP256K1_ENABLED", + "name": "MBEDTLS_ECP_DP_SECP256K1_ENABLED", + "range": null, + "title": "Enable SECP256K1 curve", + "type": "bool" + }, + { + "children": [], + "depends_on": "MBEDTLS_ECP_C", + "help": "support for DP Elliptic Curve.", + "id": "MBEDTLS_ECP_DP_BP256R1_ENABLED", + "name": "MBEDTLS_ECP_DP_BP256R1_ENABLED", + "range": null, + "title": "Enable BP256R1 curve", + "type": "bool" + }, + { + "children": [], + "depends_on": "MBEDTLS_ECP_C", + "help": "support for DP Elliptic Curve.", + "id": "MBEDTLS_ECP_DP_BP384R1_ENABLED", + "name": "MBEDTLS_ECP_DP_BP384R1_ENABLED", + "range": null, + "title": "Enable BP384R1 curve", + "type": "bool" + }, + { + "children": [], + "depends_on": "MBEDTLS_ECP_C", + "help": "support for DP Elliptic Curve.", + "id": "MBEDTLS_ECP_DP_BP512R1_ENABLED", + "name": "MBEDTLS_ECP_DP_BP512R1_ENABLED", + "range": null, + "title": "Enable BP512R1 curve", + "type": "bool" + }, + { + "children": [], + "depends_on": "MBEDTLS_ECP_C", + "help": "Enable support for CURVE25519 Elliptic Curve.", + "id": "MBEDTLS_ECP_DP_CURVE25519_ENABLED", + "name": "MBEDTLS_ECP_DP_CURVE25519_ENABLED", + "range": null, + "title": "Enable CURVE25519 curve", + "type": "bool" + }, + { + "children": [], + "depends_on": "MBEDTLS_ECP_C", + "help": "NIST 'modulo p' optimisations increase Elliptic Curve operation performance.\n\nDisabling this option saves some code size.", + "id": "MBEDTLS_ECP_NIST_OPTIM", + "name": "MBEDTLS_ECP_NIST_OPTIM", + "range": null, + "title": "NIST 'modulo p' optimisations", + "type": "bool" + }, + { + "children": [], + "depends_on": "MBEDTLS_ECP_C", + "help": "This configuration option enables optimizations to speedup (about 3 ~ 4 times) the ECP\nfixed point multiplication using pre-computed tables in the flash memory.\nEnabling this configuration option increases the flash footprint\n(about 29KB if all Elliptic Curve selected) in the application binary.\n\n# end of Elliptic Curve options", + "id": "MBEDTLS_ECP_FIXED_POINT_OPTIM", + "name": "MBEDTLS_ECP_FIXED_POINT_OPTIM", + "range": null, + "title": "Enable fixed-point multiplication optimisations", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Enable support for Poly1305 MAC algorithm.", + "id": "MBEDTLS_POLY1305_C", + "name": "MBEDTLS_POLY1305_C", + "range": null, + "title": "Poly1305 MAC algorithm", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "MBEDTLS_CHACHA20_C && MBEDTLS_POLY1305_C", + "help": "Enable support for ChaCha20-Poly1305 AEAD algorithm.", + "id": "MBEDTLS_CHACHAPOLY_C", + "name": "MBEDTLS_CHACHAPOLY_C", + "range": null, + "title": "ChaCha20-Poly1305 AEAD algorithm", + "type": "bool" + } + ], + "depends_on": null, + "help": "Enable support for Chacha20 stream cipher.", + "id": "MBEDTLS_CHACHA20_C", + "name": "MBEDTLS_CHACHA20_C", + "range": null, + "title": "Chacha20 stream cipher", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Enable support for the Hashed Message Authentication Code\n(HMAC)-based key derivation function (HKDF).", + "id": "MBEDTLS_HKDF_C", + "name": "MBEDTLS_HKDF_C", + "range": null, + "title": "HKDF algorithm (RFC 5869)", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "MBEDTLS_THREADING_C", + "help": "Enable threading alt to allow your own alternate threading implementation.", + "id": "MBEDTLS_THREADING_ALT", + "name": "MBEDTLS_THREADING_ALT", + "range": null, + "title": "Enable threading alternate implementation", + "type": "bool" + }, + { + "children": [], + "depends_on": "MBEDTLS_THREADING_C", + "help": "Enable the pthread wrapper layer for the threading layer.", + "id": "MBEDTLS_THREADING_PTHREAD", + "name": "MBEDTLS_THREADING_PTHREAD", + "range": null, + "title": "Enable threading pthread implementation", + "type": "bool" + } + ], + "depends_on": null, + "help": "If you do intend to use contexts between threads, you will need to enable\nthis layer to prevent race conditions.", + "id": "MBEDTLS_THREADING_C", + "name": "MBEDTLS_THREADING_C", + "range": null, + "title": "Enable the threading abstraction layer", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Enables mbedtls_strerror() for converting error codes to error strings.\nDisabling this config can save some code/rodata size as the error\nstring conversion implementation is replaced with an empty stub.", + "id": "MBEDTLS_ERROR_STRINGS", + "name": "MBEDTLS_ERROR_STRINGS", + "range": null, + "title": "Enable error code to error string conversion", + "type": "bool" + }, + { + "children": [], + "depends_on": "ESP_ROM_HAS_MBEDTLS_CRYPTO_LIB", + "help": "Enable this flag to use mbedtls crypto algorithm from ROM instead of ESP-IDF.\n\nThis configuration option saves flash footprint in the application binary.\nNote that the version of mbedtls crypto algorithm library in ROM(ECO1~ECO3) is v2.16.12,\nand the version of mbedtls crypto algorithm library in ROM(ECO4) is v3.6.0.\nWe have done the security analysis of the mbedtls revision in ROM (ECO1~ECO4)\nand ensured that affected symbols have been patched (removed). If in the future\nmbedtls revisions there are security issues that also affects the version in\nROM (ECO1~ECO4) then we shall patch the relevant symbols. This would increase\nthe flash footprint and hence care must be taken to keep some reserved space\nfor the application binary in flash layout.", + "id": "MBEDTLS_USE_CRYPTO_ROM_IMPL", + "name": "MBEDTLS_USE_CRYPTO_ROM_IMPL", + "range": null, + "title": "Use ROM implementation of the crypto algorithm", + "type": "bool" + }, + { + "children": [], + "depends_on": "(VFS_SUPPORT_IO && VFS_SUPPORT_DIR) || IDF_TARGET_LINUX", + "help": "This option enables functions in mbedTLS that use the filesystem.\nIt uses the default filesystem support for the target,\nwhich is added through vfs component for ESP32 based targets or by\nthe host system when the target is Linux.", + "id": "MBEDTLS_FS_IO", + "name": "MBEDTLS_FS_IO", + "range": null, + "title": "Enable functions that use the filesystem", + "type": "bool" + } + ], + "depends_on": null, + "id": "component-config-mbedtls", + "title": "mbedTLS", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": null, + "help": "If not, this library will use MQTT protocol 3.1", + "id": "MQTT_PROTOCOL_311", + "name": "MQTT_PROTOCOL_311", + "range": null, + "title": "Enable MQTT protocol 3.1.1", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "If not, this library will not support MQTT 5.0", + "id": "MQTT_PROTOCOL_5", + "name": "MQTT_PROTOCOL_5", + "range": null, + "title": "Enable MQTT protocol 5.0", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Enable MQTT transport over SSL with mbedtls", + "id": "MQTT_TRANSPORT_SSL", + "name": "MQTT_TRANSPORT_SSL", + "range": null, + "title": "Enable MQTT over SSL", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "MQTT_TRANSPORT_WEBSOCKET && MQTT_TRANSPORT_SSL", + "help": "Enable MQTT transport over Websocket Secure.", + "id": "MQTT_TRANSPORT_WEBSOCKET_SECURE", + "name": "MQTT_TRANSPORT_WEBSOCKET_SECURE", + "range": null, + "title": "Enable MQTT over Websocket Secure", + "type": "bool" + } + ], + "depends_on": "WS_TRANSPORT", + "help": "Enable MQTT transport over Websocket.", + "id": "MQTT_TRANSPORT_WEBSOCKET", + "name": "MQTT_TRANSPORT_WEBSOCKET", + "range": null, + "title": "Enable MQTT over Websocket", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Set this to true for the message id (2.3.1 Packet Identifier) to be generated\nas an incremental number rather then a random value (used by default)", + "id": "MQTT_MSG_ID_INCREMENTAL", + "name": "MQTT_MSG_ID_INCREMENTAL", + "range": null, + "title": "Use Incremental Message Id", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Set this to true to avoid publishing (enqueueing messages) if the client is disconnected.\nThe MQTT client tries to publish all messages by default, even in the disconnected state\n(where the qos1 and qos2 packets are stored in the internal outbox to be published later)\nThe MQTT_SKIP_PUBLISH_IF_DISCONNECTED option allows applications to override this behaviour\nand not enqueue publish packets in the disconnected state.", + "id": "MQTT_SKIP_PUBLISH_IF_DISCONNECTED", + "name": "MQTT_SKIP_PUBLISH_IF_DISCONNECTED", + "range": null, + "title": "Skip publish if disconnected", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Set this to true to post events for all messages which were deleted from the outbox\nbefore being correctly sent and confirmed.", + "id": "MQTT_REPORT_DELETED_MESSAGES", + "name": "MQTT_REPORT_DELETED_MESSAGES", + "range": null, + "title": "Report deleted messages", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "MQTT_USE_CUSTOM_CONFIG", + "help": "Default MQTT over TCP port", + "id": "MQTT_TCP_DEFAULT_PORT", + "name": "MQTT_TCP_DEFAULT_PORT", + "range": null, + "title": "Default MQTT over TCP port", + "type": "int" + }, + { + "children": [], + "depends_on": "MQTT_USE_CUSTOM_CONFIG && MQTT_TRANSPORT_SSL", + "help": "Default MQTT over SSL port", + "id": "MQTT_SSL_DEFAULT_PORT", + "name": "MQTT_SSL_DEFAULT_PORT", + "range": null, + "title": "Default MQTT over SSL port", + "type": "int" + }, + { + "children": [], + "depends_on": "MQTT_USE_CUSTOM_CONFIG && MQTT_TRANSPORT_WEBSOCKET", + "help": "Default MQTT over Websocket port", + "id": "MQTT_WS_DEFAULT_PORT", + "name": "MQTT_WS_DEFAULT_PORT", + "range": null, + "title": "Default MQTT over Websocket port", + "type": "int" + }, + { + "children": [], + "depends_on": "MQTT_USE_CUSTOM_CONFIG && MQTT_TRANSPORT_WEBSOCKET && MQTT_TRANSPORT_WEBSOCKET_SECURE", + "help": "Default MQTT over Websocket Secure port", + "id": "MQTT_WSS_DEFAULT_PORT", + "name": "MQTT_WSS_DEFAULT_PORT", + "range": null, + "title": "Default MQTT over Websocket Secure port", + "type": "int" + }, + { + "children": [], + "depends_on": "MQTT_USE_CUSTOM_CONFIG", + "help": "This buffer size using for both transmit and receive", + "id": "MQTT_BUFFER_SIZE", + "name": "MQTT_BUFFER_SIZE", + "range": null, + "title": "Default MQTT Buffer Size", + "type": "int" + }, + { + "children": [], + "depends_on": "MQTT_USE_CUSTOM_CONFIG", + "help": "MQTT task stack size", + "id": "MQTT_TASK_STACK_SIZE", + "name": "MQTT_TASK_STACK_SIZE", + "range": null, + "title": "MQTT task stack size", + "type": "int" + }, + { + "children": [], + "depends_on": "MQTT_USE_CUSTOM_CONFIG", + "help": "Default config employs API locks to protect internal structures. It is possible to disable\nthese locks if the user code doesn't access MQTT API from multiple concurrent tasks", + "id": "MQTT_DISABLE_API_LOCKS", + "name": "MQTT_DISABLE_API_LOCKS", + "range": null, + "title": "Disable API locks", + "type": "bool" + }, + { + "children": [], + "depends_on": "MQTT_USE_CUSTOM_CONFIG", + "help": "MQTT task priority. Higher number denotes higher priority.", + "id": "MQTT_TASK_PRIORITY", + "name": "MQTT_TASK_PRIORITY", + "range": null, + "title": "MQTT task priority", + "type": "int" + }, + { + "children": [], + "depends_on": "MQTT_USE_CUSTOM_CONFIG", + "help": "Timeout when polling underlying transport for read.", + "id": "MQTT_POLL_READ_TIMEOUT_MS", + "name": "MQTT_POLL_READ_TIMEOUT_MS", + "range": null, + "title": "MQTT transport poll read timeut", + "type": "int" + }, + { + "children": [], + "depends_on": "MQTT_USE_CUSTOM_CONFIG", + "help": "A value higher than 1 enables multiple queued events.", + "id": "MQTT_EVENT_QUEUE_SIZE", + "name": "MQTT_EVENT_QUEUE_SIZE", + "range": null, + "title": "Number of queued events.", + "type": "int" + } + ], + "depends_on": null, + "help": "Custom MQTT configurations.", + "id": "MQTT_USE_CUSTOM_CONFIG", + "name": "MQTT_USE_CUSTOM_CONFIG", + "range": null, + "title": "MQTT Using custom configurations", + "type": "bool" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "MQTT_USE_CORE_0", + "name": "MQTT_USE_CORE_0", + "range": null, + "title": "Core 0", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "MQTT_USE_CORE_1", + "name": "MQTT_USE_CORE_1", + "range": null, + "title": "Core 1", + "type": "bool" + } + ], + "depends_on": "MQTT_TASK_CORE_SELECTION_ENABLED", + "help": null, + "id": "component-config-esp-mqtt-configurations-enable-mqtt-task-core-selection-core-to-use-", + "name": "MQTT_TASK_CORE_SELECTION", + "title": "Core to use ?", + "type": "choice" + } + ], + "depends_on": null, + "help": "This will enable core selection", + "id": "MQTT_TASK_CORE_SELECTION_ENABLED", + "name": "MQTT_TASK_CORE_SELECTION_ENABLED", + "range": null, + "title": "Enable MQTT task core selection", + "type": "bool" + }, + { + "children": [], + "depends_on": "MQTT_USE_CUSTOM_CONFIG", + "help": "Set to true to use external memory for outbox data.", + "id": "MQTT_OUTBOX_DATA_ON_EXTERNAL_MEMORY", + "name": "MQTT_OUTBOX_DATA_ON_EXTERNAL_MEMORY", + "range": null, + "title": "Use external memory for outbox data", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Set to true if a specific implementation of message outbox is needed (e.g. persistent outbox in NVM or\nsimilar).\nNote: Implementation of the custom outbox must be added to the mqtt component. These CMake commands\ncould be used to append the custom implementation to lib-mqtt sources:\nidf_component_get_property(mqtt mqtt COMPONENT_LIB)\nset_property(TARGET ${mqtt} PROPERTY SOURCES ${PROJECT_DIR}/custom_outbox.c APPEND)", + "id": "MQTT_CUSTOM_OUTBOX", + "name": "MQTT_CUSTOM_OUTBOX", + "range": null, + "title": "Enable custom outbox implementation", + "type": "bool" + }, + { + "children": [], + "depends_on": "MQTT_USE_CUSTOM_CONFIG", + "help": "Messages which stays in the outbox longer than this value before being published will be discarded.", + "id": "MQTT_OUTBOX_EXPIRED_TIMEOUT_MS", + "name": "MQTT_OUTBOX_EXPIRED_TIMEOUT_MS", + "range": null, + "title": "Outbox message expired timeout[ms]", + "type": "int" + } + ], + "depends_on": null, + "id": "component-config-esp-mqtt-configurations", + "title": "ESP-MQTT Configurations", + "type": "menu" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "NEWLIB_STDOUT_LINE_ENDING_CRLF", + "name": "NEWLIB_STDOUT_LINE_ENDING_CRLF", + "range": null, + "title": "CRLF", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "NEWLIB_STDOUT_LINE_ENDING_LF", + "name": "NEWLIB_STDOUT_LINE_ENDING_LF", + "range": null, + "title": "LF", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "NEWLIB_STDOUT_LINE_ENDING_CR", + "name": "NEWLIB_STDOUT_LINE_ENDING_CR", + "range": null, + "title": "CR", + "type": "bool" + } + ], + "depends_on": null, + "help": "This option allows configuring the desired line endings sent to UART\nwhen a newline ('\\n', LF) appears on stdout.\nThree options are possible:\n\nCRLF: whenever LF is encountered, prepend it with CR\n\nLF: no modification is applied, stdout is sent as is\n\nCR: each occurrence of LF is replaced with CR\n\nThis option doesn't affect behavior of the UART driver (drivers/uart.h).", + "id": "component-config-newlib-line-ending-for-uart-output", + "name": "NEWLIB_STDOUT_LINE_ENDING", + "title": "Line ending for UART output", + "type": "choice" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "NEWLIB_STDIN_LINE_ENDING_CRLF", + "name": "NEWLIB_STDIN_LINE_ENDING_CRLF", + "range": null, + "title": "CRLF", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "NEWLIB_STDIN_LINE_ENDING_LF", + "name": "NEWLIB_STDIN_LINE_ENDING_LF", + "range": null, + "title": "LF", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "NEWLIB_STDIN_LINE_ENDING_CR", + "name": "NEWLIB_STDIN_LINE_ENDING_CR", + "range": null, + "title": "CR", + "type": "bool" + } + ], + "depends_on": null, + "help": "This option allows configuring which input sequence on UART produces\na newline ('\\n', LF) on stdin.\nThree options are possible:\n\nCRLF: CRLF is converted to LF\n\nLF: no modification is applied, input is sent to stdin as is\n\nCR: each occurrence of CR is replaced with LF\n\nThis option doesn't affect behavior of the UART driver (drivers/uart.h).", + "id": "component-config-newlib-line-ending-for-uart-input", + "name": "NEWLIB_STDIN_LINE_ENDING", + "title": "Line ending for UART input", + "type": "choice" + }, + { + "children": [], + "depends_on": null, + "help": "In most chips the ROM contains parts of newlib C library, including printf/scanf family\nof functions. These functions have been compiled with so-called \"nano\"\nformatting option. This option doesn't support 64-bit integer formats and C99\nfeatures, such as positional arguments.\n\nFor more details about \"nano\" formatting option, please see newlib readme file,\nsearch for '--enable-newlib-nano-formatted-io':\nhttps://sourceware.org/git/?p=newlib-cygwin.git;a=blob_plain;f=newlib/README;hb=HEAD\n\nIf this option is enabled and the ROM contains functions from newlib-nano, the build system\nwill use functions available in ROM, reducing the application binary size.\nFunctions available in ROM run faster than functions which run from flash. Functions available\nin ROM can also run when flash instruction cache is disabled.\n\nSome chips (e.g. ESP32-C6) has the full formatting versions of printf/scanf in ROM instead of\nthe nano versions and in this building with newlib nano might actually increase the size of\nthe binary. Which functions are present in ROM can be seen from ROM caps:\nESP_ROM_HAS_NEWLIB_NANO_FORMAT and ESP_ROM_HAS_NEWLIB_NORMAL_FORMAT.\n\nIf you need 64-bit integer formatting support or C99 features, keep this\noption disabled.", + "id": "NEWLIB_NANO_FORMAT", + "name": "NEWLIB_NANO_FORMAT", + "range": null, + "title": "Enable 'nano' formatting options for printf/scanf family", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "NEWLIB_TIME_SYSCALL_USE_RTC_HRT", + "name": "NEWLIB_TIME_SYSCALL_USE_RTC_HRT", + "range": null, + "title": "RTC and high-resolution timer", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "NEWLIB_TIME_SYSCALL_USE_RTC", + "name": "NEWLIB_TIME_SYSCALL_USE_RTC", + "range": null, + "title": "RTC", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "NEWLIB_TIME_SYSCALL_USE_HRT", + "name": "NEWLIB_TIME_SYSCALL_USE_HRT", + "range": null, + "title": "High-resolution timer", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "NEWLIB_TIME_SYSCALL_USE_NONE", + "name": "NEWLIB_TIME_SYSCALL_USE_NONE", + "range": null, + "title": "None", + "type": "bool" + } + ], + "depends_on": null, + "help": "This setting defines which hardware timers are used to\nimplement 'gettimeofday' and 'time' functions in C library.\n\n- If both high-resolution (systimer for all targets except ESP32)\n and RTC timers are used, timekeeping will continue in deep sleep.\n Time will be reported at 1 microsecond resolution.\n This is the default, and the recommended option.\n- If only high-resolution timer (systimer) is used, gettimeofday will\n provide time at microsecond resolution.\n Time will not be preserved when going into deep sleep mode.\n- If only RTC timer is used, timekeeping will continue in\n deep sleep, but time will be measured at 6.(6) microsecond\n resolution. Also the gettimeofday function itself may take\n longer to run.\n- If no timers are used, gettimeofday and time functions\n return -1 and set errno to ENOSYS; they are defined as weak,\n so they could be overridden.\n If you want to customize gettimeofday() and other time functions,\n please choose this option and refer to the 'time.c' source file\n for the exact prototypes of these functions.\n\n- When RTC is used for timekeeping, two RTC_STORE registers are\n used to keep time in deep sleep mode.", + "id": "component-config-newlib-timers-used-for-gettimeofday-function", + "name": "NEWLIB_TIME_SYSCALL", + "title": "Timers used for gettimeofday function", + "type": "choice" + } + ], + "depends_on": null, + "id": "component-config-newlib", + "title": "Newlib", + "type": "menu" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "STDATOMIC_S32C1I_SPIRAM_WORKAROUND", + "name": "STDATOMIC_S32C1I_SPIRAM_WORKAROUND", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "SECURE_FLASH_ENC_ENABLED || SOC_HMAC_SUPPORTED", + "help": "This option enables encryption for NVS. When enabled, XTS-AES is used to encrypt\nthe complete NVS data, except the page headers. It requires XTS encryption keys\nto be stored in an encrypted partition (enabling flash encryption is mandatory here)\nor to be derived from an HMAC key burnt in eFuse.", + "id": "NVS_ENCRYPTION", + "name": "NVS_ENCRYPTION", + "range": null, + "title": "Enable NVS encryption", + "type": "bool" + }, + { + "children": [], + "depends_on": "SECURE_FLASH_ENC_ENABLED", + "help": "Enabling this will ignore \"encrypted\" flag for NVS partitions. NVS encryption\nscheme is different than hardware flash encryption and hence it is not recommended\nto have \"encrypted\" flag for NVS partitions. This was not being checked in pre v4.3\nIDF. Hence, if you have any devices where this flag is kept enabled in partition\ntable then enabling this config will allow to have same behavior as pre v4.3 IDF.", + "id": "NVS_COMPATIBLE_PRE_V4_3_ENCRYPTION_FLAG", + "name": "NVS_COMPATIBLE_PRE_V4_3_ENCRYPTION_FLAG", + "range": null, + "title": "NVS partition encrypted flag compatible with ESP-IDF before v4.3", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "This option switches error checking type between assertions (y) or return codes (n).", + "id": "NVS_ASSERT_ERROR_CHECK", + "name": "NVS_ASSERT_ERROR_CHECK", + "range": null, + "title": "Use assertions for error checking", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Enabling this option will switch the nvs_set() family of functions to the legacy mode:\nwhen called repeatedly with the same key but different data type, the existing value\nin the NVS remains active and the new value is just stored, actually not accessible through\ncorresponding nvs_get() call for the key given. Use this option only when your application\nrelies on such NVS API behaviour.", + "id": "NVS_LEGACY_DUP_KEYS_COMPATIBILITY", + "name": "NVS_LEGACY_DUP_KEYS_COMPATIBILITY", + "range": null, + "title": "Enable legacy nvs_set function behavior when same key is reused with different data types", + "type": "bool" + }, + { + "children": [], + "depends_on": "SPIRAM && (SPIRAM_USE_CAPS_ALLOC || SPIRAM_USE_MALLOC)", + "help": "Enabling this option lets NVS library try to allocate page cache and key hash list in SPIRAM\ninstead of internal RAM. It can help applications using large nvs partitions or large number\nof keys to save heap space in internal RAM. SPIRAM heap allocation negatively impacts speed\nof NVS operations as the CPU accesses NVS cache via SPI instead of direct access to the internal RAM.", + "id": "NVS_ALLOCATE_CACHE_IN_SPIRAM", + "name": "NVS_ALLOCATE_CACHE_IN_SPIRAM", + "range": null, + "title": "Prefers allocation of in-memory cache structures in SPI connected PSRAM", + "type": "bool" + } + ], + "depends_on": null, + "id": "component-config-nvs", + "title": "NVS", + "type": "menu" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "SECURE_FLASH_ENC_ENABLED && ", + "help": "Protect the NVS Encryption Keys using Flash Encryption\nRequires a separate 'nvs_keys' partition (which will be encrypted by flash encryption)\nfor storing the NVS encryption keys", + "id": "NVS_SEC_KEY_PROTECT_USING_FLASH_ENC", + "name": "NVS_SEC_KEY_PROTECT_USING_FLASH_ENC", + "range": null, + "title": "Using Flash Encryption", + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_HMAC_SUPPORTED && ", + "help": "Derive and protect the NVS Encryption Keys using the HMAC peripheral\nRequires the specified eFuse block (NVS_SEC_HMAC_EFUSE_KEY_ID or the v2 API argument)\nto be empty or pre-written with a key with the purpose ESP_EFUSE_KEY_PURPOSE_HMAC_UP", + "id": "NVS_SEC_KEY_PROTECT_USING_HMAC", + "name": "NVS_SEC_KEY_PROTECT_USING_HMAC", + "range": null, + "title": "Using HMAC peripheral", + "type": "bool" + } + ], + "depends_on": "NVS_ENCRYPTION", + "help": "This choice defines the default NVS encryption keys protection scheme;\nwhich will be used for the default NVS partition.\nUsers can use the corresponding scheme registration APIs to register other\nschemes for the default as well as other NVS partitions.", + "id": "component-config-nvs-security-provider-nvs-encryption-key-protection-scheme", + "name": "NVS_SEC_KEY_PROTECTION_SCHEME", + "title": "NVS Encryption: Key Protection Scheme", + "type": "choice" + }, + { + "children": [], + "depends_on": "NVS_SEC_KEY_PROTECT_USING_HMAC", + "help": "eFuse block key ID storing the HMAC key for deriving the NVS encryption keys\n\nNote: The eFuse block key ID required by the HMAC scheme\n(CONFIG_NVS_SEC_KEY_PROTECT_USING_HMAC) is set using this config when the default\nNVS partition is initialized with nvs_flash_init(). The eFuse block key ID can\nalso be set at runtime by passing the appropriate value to the NVS security scheme\nregistration APIs.", + "id": "NVS_SEC_HMAC_EFUSE_KEY_ID", + "name": "NVS_SEC_HMAC_EFUSE_KEY_ID", + "range": null, + "title": "eFuse key ID storing the HMAC key", + "type": "int" + } + ], + "depends_on": null, + "id": "component-config-nvs-security-provider", + "title": "NVS Security Provider", + "type": "menu" + }, + { + "children": [ + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "OPENTHREAD_ENABLED", + "help": "The OpenThread package name.", + "id": "OPENTHREAD_PACKAGE_NAME", + "name": "OPENTHREAD_PACKAGE_NAME", + "range": null, + "title": "OpenThread package name", + "type": "string" + }, + { + "children": [], + "depends_on": "OPENTHREAD_ENABLED", + "help": "The OpenThread platform information.", + "id": "OPENTHREAD_PLATFORM_INFO", + "name": "OPENTHREAD_PLATFORM_INFO", + "range": null, + "title": "platform information", + "type": "string" + } + ], + "depends_on": "OPENTHREAD_ENABLED", + "id": "component-config-openthread-openthread-thread-version-message", + "title": "Thread Version Message", + "type": "menu" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "(ESP_CONSOLE_UART_DEFAULT || ESP_CONSOLE_UART_CUSTOM) && ", + "help": null, + "id": "OPENTHREAD_CONSOLE_TYPE_UART", + "name": "OPENTHREAD_CONSOLE_TYPE_UART", + "range": null, + "title": "OpenThread console type UART", + "type": "bool" + }, + { + "children": [], + "depends_on": "(ESP_CONSOLE_USB_SERIAL_JTAG || ESP_CONSOLE_SECONDARY_USB_SERIAL_JTAG) && ", + "help": null, + "id": "OPENTHREAD_CONSOLE_TYPE_USB_SERIAL_JTAG", + "name": "OPENTHREAD_CONSOLE_TYPE_USB_SERIAL_JTAG", + "range": null, + "title": "OpenThread console type USB Serial/JTAG Controller", + "type": "bool" + } + ], + "depends_on": "OPENTHREAD_ENABLED", + "help": "Select OpenThread console type", + "id": "component-config-openthread-openthread-thread-console-openthread-console-type", + "name": "OPENTHREAD_CONSOLE_TYPE", + "title": "OpenThread console type", + "type": "choice" + }, + { + "children": [], + "depends_on": "OPENTHREAD_ENABLED", + "help": "Select this option to enable Command-Line Interface in OpenThread.", + "id": "OPENTHREAD_CLI", + "name": "OPENTHREAD_CLI", + "range": null, + "title": "Enable Openthread Command-Line Interface", + "type": "bool" + } + ], + "depends_on": "OPENTHREAD_ENABLED", + "id": "component-config-openthread-openthread-thread-console", + "title": "Thread Console", + "type": "menu" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "OPENTHREAD_ENABLED", + "help": null, + "id": "OPENTHREAD_NETWORK_NAME", + "name": "OPENTHREAD_NETWORK_NAME", + "range": null, + "title": "OpenThread network name", + "type": "string" + }, + { + "children": [], + "depends_on": "OPENTHREAD_ENABLED", + "help": "A string in the format \"
/\", where `
` is an IPv6\naddress and `` is a prefix length. For example \"fd00:db8:a0:0::/64\"", + "id": "OPENTHREAD_MESH_LOCAL_PREFIX", + "name": "OPENTHREAD_MESH_LOCAL_PREFIX", + "range": null, + "title": "OpenThread mesh local prefix, format
/", + "type": "string" + }, + { + "children": [], + "depends_on": "OPENTHREAD_ENABLED", + "help": null, + "id": "OPENTHREAD_NETWORK_CHANNEL", + "name": "OPENTHREAD_NETWORK_CHANNEL", + "range": null, + "title": "OpenThread network channel", + "type": "int" + }, + { + "children": [], + "depends_on": "OPENTHREAD_ENABLED", + "help": null, + "id": "OPENTHREAD_NETWORK_PANID", + "name": "OPENTHREAD_NETWORK_PANID", + "range": null, + "title": "OpenThread network pan id", + "type": "hex" + }, + { + "children": [], + "depends_on": "OPENTHREAD_ENABLED", + "help": "The OpenThread network extended pan id in hex string format", + "id": "OPENTHREAD_NETWORK_EXTPANID", + "name": "OPENTHREAD_NETWORK_EXTPANID", + "range": null, + "title": "OpenThread extended pan id", + "type": "string" + }, + { + "children": [], + "depends_on": "OPENTHREAD_ENABLED", + "help": "The OpenThread network network key in hex string format", + "id": "OPENTHREAD_NETWORK_MASTERKEY", + "name": "OPENTHREAD_NETWORK_MASTERKEY", + "range": null, + "title": "OpenThread network key", + "type": "string" + }, + { + "children": [], + "depends_on": "OPENTHREAD_ENABLED", + "help": "The OpenThread pre-shared commissioner key in hex string format", + "id": "OPENTHREAD_NETWORK_PSKC", + "name": "OPENTHREAD_NETWORK_PSKC", + "range": null, + "title": "OpenThread pre-shared commissioner key", + "type": "string" + } + ], + "depends_on": "OPENTHREAD_ENABLED", + "id": "component-config-openthread-openthread-thread-core-features-thread-operational-dataset", + "title": "Thread Operational Dataset", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": "Select this to enable Full Thread Device which can act as router and leader in a Thread network.", + "id": "OPENTHREAD_FTD", + "name": "OPENTHREAD_FTD", + "range": null, + "title": "Full Thread Device", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": "Select this to enable Minimal Thread Device which can only act as end device in a Thread network.\nThis will reduce the code size of the OpenThread stack.", + "id": "OPENTHREAD_MTD", + "name": "OPENTHREAD_MTD", + "range": null, + "title": "Minimal Thread Device", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": "Select this to enable Radio Only Device which can only forward 15.4 packets to the host.\nThe OpenThread stack will be run on the host and OpenThread will have minimal footprint on the\nradio only device.", + "id": "OPENTHREAD_RADIO", + "name": "OPENTHREAD_RADIO", + "range": null, + "title": "Radio Only Device", + "type": "bool" + } + ], + "depends_on": "OPENTHREAD_ENABLED", + "help": "OpenThread can be configured to different device types (FTD, MTD, Radio)", + "id": "component-config-openthread-openthread-thread-core-features-thread-device-type", + "name": "OPENTHREAD_DEVICE_TYPE", + "title": "Thread device type", + "type": "choice" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "OPENTHREAD_RADIO_TREL && (EXAMPLE_CONNECT_WIFI || EXAMPLE_CONNECT_ETHERNET) && OPENTHREAD_ENABLED", + "help": "Configure the port number of TREL service.", + "id": "OPENTHREAD_TREL_PORT", + "name": "OPENTHREAD_TREL_PORT", + "range": null, + "title": "The port of openthread trel service", + "type": "int" + } + ], + "depends_on": "(EXAMPLE_CONNECT_WIFI || EXAMPLE_CONNECT_ETHERNET) && OPENTHREAD_ENABLED", + "help": "Select this option to enable Thread Radio Encapsulation Link.", + "id": "OPENTHREAD_RADIO_TREL", + "name": "OPENTHREAD_RADIO_TREL", + "range": null, + "title": "Enable Thread Radio Encapsulation Link (TREL)", + "type": "bool" + } + ], + "depends_on": "(EXAMPLE_CONNECT_WIFI || EXAMPLE_CONNECT_ETHERNET) && OPENTHREAD_ENABLED", + "id": "component-config-openthread-openthread-thread-core-features-thread-trel-radio-link", + "title": "Thread Trel Radio Link", + "type": "menu" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "", + "help": "Select this to use the native 15.4 radio.", + "id": "OPENTHREAD_RADIO_NATIVE", + "name": "OPENTHREAD_RADIO_NATIVE", + "range": null, + "title": "Native 15.4 radio", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": "Select this to connect to a Radio Co-Processor via UART.", + "id": "OPENTHREAD_RADIO_SPINEL_UART", + "name": "OPENTHREAD_RADIO_SPINEL_UART", + "range": null, + "title": "Connect via UART", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": "Select this to connect to a Radio Co-Processor via SPI.", + "id": "OPENTHREAD_RADIO_SPINEL_SPI", + "name": "OPENTHREAD_RADIO_SPINEL_SPI", + "range": null, + "title": "Connect via SPI", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": "Select this to disable the Thread radio based on 15.4 link.", + "id": "OPENTHREAD_RADIO_154_NONE", + "name": "OPENTHREAD_RADIO_154_NONE", + "range": null, + "title": "Disable the Thread radio based on 15.4 link", + "type": "bool" + } + ], + "depends_on": "OPENTHREAD_ENABLED", + "help": "Configure how OpenThread connects to the 15.4 radio", + "id": "component-config-openthread-openthread-thread-core-features-thread-15-4-radio-link-config-the-thread-radio-type-with-15-4-link", + "name": "OPENTHREAD_RADIO_TYPE", + "title": "Config the Thread radio type with 15.4 link", + "type": "choice" + } + ], + "depends_on": "OPENTHREAD_ENABLED", + "id": "component-config-openthread-openthread-thread-core-features-thread-15-4-radio-link", + "title": "Thread 15.4 Radio Link", + "type": "menu" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "", + "help": "Select this to enable UART connection to host.", + "id": "OPENTHREAD_RCP_UART", + "name": "OPENTHREAD_RCP_UART", + "range": null, + "title": "UART RCP", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": "Select this to enable SPI connection to host.", + "id": "OPENTHREAD_RCP_SPI", + "name": "OPENTHREAD_RCP_SPI", + "range": null, + "title": "SPI RCP", + "type": "bool" + } + ], + "depends_on": "OPENTHREAD_RADIO && OPENTHREAD_ENABLED", + "help": null, + "id": "component-config-openthread-openthread-thread-core-features-thread-radio-co-processor-feature-the-rcp-transport-type", + "name": "OPENTHREAD_RCP_TRANSPORT", + "title": "The RCP transport type", + "type": "choice" + }, + { + "children": [], + "depends_on": "OPENTHREAD_RADIO && OPENTHREAD_ENABLED", + "help": "Select this to enable OpenThread NCP vendor commands.", + "id": "OPENTHREAD_NCP_VENDOR_HOOK", + "name": "OPENTHREAD_NCP_VENDOR_HOOK", + "range": null, + "title": "Enable vendor command for RCP", + "type": "bool" + } + ], + "depends_on": "OPENTHREAD_RADIO && OPENTHREAD_ENABLED", + "id": "component-config-openthread-openthread-thread-core-features-thread-radio-co-processor-feature", + "title": "Thread Radio Co-Processor Feature", + "type": "menu" + }, + { + "children": [], + "depends_on": "OPENTHREAD_FTD && OPENTHREAD_ENABLED", + "help": "Select this option to enable border router features in OpenThread.", + "id": "OPENTHREAD_BORDER_ROUTER", + "name": "OPENTHREAD_BORDER_ROUTER", + "range": null, + "title": "Enable Border Router", + "type": "bool" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "OPENTHREAD_COMMISSIONER && OPENTHREAD_ENABLED", + "help": null, + "id": "OPENTHREAD_COMM_MAX_JOINER_ENTRIES", + "name": "OPENTHREAD_COMM_MAX_JOINER_ENTRIES", + "range": null, + "title": "The size of max commissioning joiner entries", + "type": "int" + } + ], + "depends_on": "OPENTHREAD_COMMISSIONER && OPENTHREAD_ENABLED", + "id": "component-config-openthread-openthread-thread-core-features-enable-commissioner-commissioner-configurations", + "title": "Commissioner Configurations", + "type": "menu" + } + ], + "depends_on": "OPENTHREAD_ENABLED", + "help": "Select this option to enable commissioner in OpenThread. This will enable the device to act as a\ncommissioner in the Thread network. A commissioner checks the pre-shared key from a joining device\nwith the Thread commissioning protocol and shares the network parameter with the joining device\nupon success.", + "id": "OPENTHREAD_COMMISSIONER", + "name": "OPENTHREAD_COMMISSIONER", + "range": null, + "title": "Enable Commissioner", + "type": "bool" + }, + { + "children": [], + "depends_on": "OPENTHREAD_ENABLED", + "help": "Select this option to enable Joiner in OpenThread. This allows a device to join the\nThread network with a pre-shared key using the Thread commissioning protocol.", + "id": "OPENTHREAD_JOINER", + "name": "OPENTHREAD_JOINER", + "range": null, + "title": "Enable Joiner", + "type": "bool" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "OPENTHREAD_SRP_CLIENT && OPENTHREAD_ENABLED", + "help": "Set the max buffer size of service entries in the SRP client service pool.", + "id": "OPENTHREAD_SRP_CLIENT_MAX_SERVICES", + "name": "OPENTHREAD_SRP_CLIENT_MAX_SERVICES", + "range": null, + "title": "Specifies number of service entries in the SRP client service pool", + "type": "int" + } + ], + "depends_on": "OPENTHREAD_SRP_CLIENT && OPENTHREAD_ENABLED", + "id": "component-config-openthread-openthread-thread-core-features-enable-srp-client-srp-client-configurations", + "title": "SRP Client Configurations", + "type": "menu" + } + ], + "depends_on": "OPENTHREAD_ENABLED", + "help": "Select this option to enable SRP Client in OpenThread.\nThis allows a device to register SRP services to SRP Server.", + "id": "OPENTHREAD_SRP_CLIENT", + "name": "OPENTHREAD_SRP_CLIENT", + "range": null, + "title": "Enable SRP Client", + "type": "bool" + }, + { + "children": [], + "depends_on": "OPENTHREAD_ENABLED", + "help": "Select this option to enable DNS Client in OpenThread.", + "id": "OPENTHREAD_DNS_CLIENT", + "name": "OPENTHREAD_DNS_CLIENT", + "range": null, + "title": "Enable DNS Client", + "type": "bool" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "OPENTHREAD_DNS64_CLIENT && OPENTHREAD_ENABLED", + "help": "Set the DNS server IPv4 address.", + "id": "OPENTHREAD_DNS_SERVER_ADDR", + "name": "OPENTHREAD_DNS_SERVER_ADDR", + "range": null, + "title": "DNS server address (IPv4)", + "type": "string" + } + ], + "depends_on": "OPENTHREAD_DNS64_CLIENT && OPENTHREAD_ENABLED", + "id": "component-config-openthread-openthread-thread-core-features-enable-dns64-client-dns64-client-configurations", + "title": "DNS64 Client Configurations", + "type": "menu" + } + ], + "depends_on": "LWIP_IPV4 && OPENTHREAD_ENABLED", + "help": "Select this option to acquire NAT64 address from dns servers.", + "id": "OPENTHREAD_DNS64_CLIENT", + "name": "OPENTHREAD_DNS64_CLIENT", + "range": null, + "title": "Enable DNS64 Client", + "type": "bool" + }, + { + "children": [], + "depends_on": "OPENTHREAD_ENABLED", + "help": "Select this option to enable link metrics feature", + "id": "OPENTHREAD_LINK_METRICS", + "name": "OPENTHREAD_LINK_METRICS", + "range": null, + "title": "Enable link metrics feature", + "type": "bool" + }, + { + "children": [], + "depends_on": "OPENTHREAD_ENABLED", + "help": "Select this option to enable mac filter feature", + "id": "OPENTHREAD_MACFILTER_ENABLE", + "name": "OPENTHREAD_MACFILTER_ENABLE", + "range": null, + "title": "Enable mac filter feature", + "type": "bool" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "OPENTHREAD_CSL_ENABLE && OPENTHREAD_ENABLED", + "help": "The current accuracy of the clock used for scheduling CSL operations", + "id": "OPENTHREAD_CSL_ACCURACY", + "name": "OPENTHREAD_CSL_ACCURACY", + "range": null, + "title": "The current CSL rx/tx scheduling drift, in units of \u00b1 ppm", + "type": "int" + }, + { + "children": [], + "depends_on": "OPENTHREAD_CSL_ENABLE && OPENTHREAD_ENABLED", + "help": "The fixed uncertainty of the Device for scheduling CSL Transmissions in units of 10 microseconds.", + "id": "OPENTHREAD_CSL_UNCERTAIN", + "name": "OPENTHREAD_CSL_UNCERTAIN", + "range": null, + "title": "The CSL Uncertainty in units of 10 us.", + "type": "int" + }, + { + "children": [], + "depends_on": "OPENTHREAD_CSL_ENABLE && OPENTHREAD_ENABLED", + "help": "Select this option to set rx on when sleep in CSL feature, only for debug", + "id": "OPENTHREAD_CSL_DEBUG_ENABLE", + "name": "OPENTHREAD_CSL_DEBUG_ENABLE", + "range": null, + "title": "Enable CSL debug", + "type": "bool" + } + ], + "depends_on": "OPENTHREAD_CSL_ENABLE && OPENTHREAD_ENABLED", + "id": "component-config-openthread-openthread-thread-core-features-enable-csl-feature-csl-configurations", + "title": "CSL Configurations", + "type": "menu" + } + ], + "depends_on": "OPENTHREAD_ENABLED", + "help": "Select this option to enable CSL feature", + "id": "OPENTHREAD_CSL_ENABLE", + "name": "OPENTHREAD_CSL_ENABLE", + "range": null, + "title": "Enable CSL feature", + "type": "bool" + }, + { + "children": [], + "depends_on": "OPENTHREAD_ENABLED", + "help": "Select this option to enable time synchronization feature, the devices in the same Thread network could\nsync to the same network time.", + "id": "OPENTHREAD_TIME_SYNC", + "name": "OPENTHREAD_TIME_SYNC", + "range": null, + "title": "Enable the time synchronization service feature", + "type": "bool" + }, + { + "children": [], + "depends_on": "(OPENTHREAD_FTD || OPENTHREAD_MTD) && OPENTHREAD_ENABLED", + "help": "Select this option to enable the radio statistics feature, you can use radio\ncommand to print some radio Statistics information.", + "id": "OPENTHREAD_RADIO_STATS_ENABLE", + "name": "OPENTHREAD_RADIO_STATS_ENABLE", + "range": null, + "title": "Enable Radio Statistics feature", + "type": "bool" + }, + { + "children": [], + "depends_on": "OPENTHREAD_ENABLED", + "help": "Select this option to enable OpenThread radio capability rx on when idle.\nDo not support this feature when SW coexistence is enabled.", + "id": "OPENTHREAD_RX_ON_WHEN_IDLE", + "name": "OPENTHREAD_RX_ON_WHEN_IDLE", + "range": null, + "title": "Enable OpenThread radio capability rx on when idle", + "type": "bool" + }, + { + "children": [], + "depends_on": "OPENTHREAD_ENABLED", + "help": "Select this option to enable Diag in OpenThread. This will enable diag mode and a series of diag\ncommands in the OpenThread command line. These commands allow users to manipulate low-level\nfeatures of the storage and 15.4 radio.", + "id": "OPENTHREAD_DIAG", + "name": "OPENTHREAD_DIAG", + "range": null, + "title": "Enable diag", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "(SPIRAM_USE_CAPS_ALLOC || SPIRAM_USE_MALLOC) && OPENTHREAD_ENABLED", + "help": "Select this option to allocate buffer from PSRAM for Thread", + "id": "OPENTHREAD_PLATFORM_MALLOC_CAP_SPIRAM", + "name": "OPENTHREAD_PLATFORM_MALLOC_CAP_SPIRAM", + "range": null, + "title": "Allocate memory from PSRAM", + "type": "bool" + }, + { + "children": [], + "depends_on": "(SPIRAM_USE_CAPS_ALLOC || SPIRAM_USE_MALLOC) && OPENTHREAD_ENABLED", + "help": "If enabled, the message pool is managed by platform defined logic.", + "id": "OPENTHREAD_PLATFORM_MSGPOOL_MANAGEMENT", + "name": "OPENTHREAD_PLATFORM_MSGPOOL_MANAGEMENT", + "range": null, + "title": "Allocate message pool buffer from PSRAM", + "type": "bool" + } + ], + "depends_on": "(SPIRAM_USE_CAPS_ALLOC || SPIRAM_USE_MALLOC) && OPENTHREAD_ENABLED", + "id": "component-config-openthread-openthread-thread-core-features-thread-memory-allocation", + "title": "Thread Memory Allocation", + "type": "menu" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "(OPENTHREAD_FTD || OPENTHREAD_MTD) && OPENTHREAD_ENABLED", + "help": null, + "id": "OPENTHREAD_ADDRESS_QUERY_TIMEOUT", + "name": "OPENTHREAD_ADDRESS_QUERY_TIMEOUT", + "range": null, + "title": "Timeout (in seconds) for a address notification response after sending an address query.", + "type": "int" + }, + { + "children": [], + "depends_on": "(OPENTHREAD_FTD || OPENTHREAD_MTD) && OPENTHREAD_ENABLED", + "help": null, + "id": "OPENTHREAD_ADDRESS_QUERY_RETRY_DELAY", + "name": "OPENTHREAD_ADDRESS_QUERY_RETRY_DELAY", + "range": null, + "title": "Initial retry delay for address query (in seconds).", + "type": "int" + }, + { + "children": [], + "depends_on": "(OPENTHREAD_FTD || OPENTHREAD_MTD) && OPENTHREAD_ENABLED", + "help": null, + "id": "OPENTHREAD_ADDRESS_QUERY_MAX_RETRY_DELAY", + "name": "OPENTHREAD_ADDRESS_QUERY_MAX_RETRY_DELAY", + "range": null, + "title": "Maximum retry delay for address query (in seconds).", + "type": "int" + } + ], + "depends_on": "OPENTHREAD_ENABLED", + "id": "component-config-openthread-openthread-thread-core-features-openthread-stack-parameters-thread-address-query-config", + "title": "Thread Address Query Config", + "type": "menu" + }, + { + "children": [], + "depends_on": "OPENTHREAD_ENABLED", + "help": null, + "id": "OPENTHREAD_PREFERRED_CHANNEL_MASK", + "name": "OPENTHREAD_PREFERRED_CHANNEL_MASK", + "range": null, + "title": "Preferred channel mask", + "type": "hex" + }, + { + "children": [], + "depends_on": "OPENTHREAD_ENABLED", + "help": null, + "id": "OPENTHREAD_SUPPORTED_CHANNEL_MASK", + "name": "OPENTHREAD_SUPPORTED_CHANNEL_MASK", + "range": null, + "title": "Supported channel mask", + "type": "hex" + }, + { + "children": [], + "depends_on": "OPENTHREAD_ENABLED", + "help": null, + "id": "OPENTHREAD_NUM_MESSAGE_BUFFERS", + "name": "OPENTHREAD_NUM_MESSAGE_BUFFERS", + "range": null, + "title": "The number of openthread message buffers", + "type": "int" + }, + { + "children": [], + "depends_on": "OPENTHREAD_ENABLED", + "help": "The device's XTAL accuracy, in ppm.", + "id": "OPENTHREAD_XTAL_ACCURACY", + "name": "OPENTHREAD_XTAL_ACCURACY", + "range": null, + "title": "The accuracy of the XTAL", + "type": "int" + }, + { + "children": [], + "depends_on": "OPENTHREAD_ENABLED", + "help": null, + "id": "OPENTHREAD_MLE_MAX_CHILDREN", + "name": "OPENTHREAD_MLE_MAX_CHILDREN", + "range": null, + "title": "The size of max MLE children entries", + "type": "int" + }, + { + "children": [], + "depends_on": "OPENTHREAD_ENABLED", + "help": null, + "id": "OPENTHREAD_TMF_ADDR_CACHE_ENTRIES", + "name": "OPENTHREAD_TMF_ADDR_CACHE_ENTRIES", + "range": null, + "title": "The size of max TMF address cache entries", + "type": "int" + }, + { + "children": [], + "depends_on": "OPENTHREAD_ENABLED", + "help": "Set the OpenThread UART buffer size.", + "id": "OPENTHREAD_UART_BUFFER_SIZE", + "name": "OPENTHREAD_UART_BUFFER_SIZE", + "range": null, + "title": "The uart received buffer size of openthread", + "type": "int" + }, + { + "children": [], + "depends_on": "OPENTHREAD_ENABLED", + "help": "The maximum number of backoffs the CSMA-CA algorithm will attempt before declaring a channel access\nfailure.", + "id": "OPENTHREAD_MAC_MAX_CSMA_BACKOFFS_DIRECT", + "name": "OPENTHREAD_MAC_MAX_CSMA_BACKOFFS_DIRECT", + "range": null, + "title": "Maximum backoffs times before declaring a channel access failure.", + "type": "int" + } + ], + "depends_on": "OPENTHREAD_ENABLED", + "id": "component-config-openthread-openthread-thread-core-features-openthread-stack-parameters", + "title": "OpenThread Stack Parameters", + "type": "menu" + } + ], + "depends_on": "OPENTHREAD_ENABLED", + "id": "component-config-openthread-openthread-thread-core-features", + "title": "Thread Core Features", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": "OPENTHREAD_ENABLED", + "help": "Select this option to enable dynamic log level control for OpenThread", + "id": "OPENTHREAD_LOG_LEVEL_DYNAMIC", + "name": "OPENTHREAD_LOG_LEVEL_DYNAMIC", + "range": null, + "title": "Enable dynamic log level control", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "OPENTHREAD_LOG_LEVEL_NONE", + "name": "OPENTHREAD_LOG_LEVEL_NONE", + "range": null, + "title": "No logs", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "OPENTHREAD_LOG_LEVEL_CRIT", + "name": "OPENTHREAD_LOG_LEVEL_CRIT", + "range": null, + "title": "Error logs", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "OPENTHREAD_LOG_LEVEL_WARN", + "name": "OPENTHREAD_LOG_LEVEL_WARN", + "range": null, + "title": "Warning logs", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "OPENTHREAD_LOG_LEVEL_NOTE", + "name": "OPENTHREAD_LOG_LEVEL_NOTE", + "range": null, + "title": "Notice logs", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "OPENTHREAD_LOG_LEVEL_INFO", + "name": "OPENTHREAD_LOG_LEVEL_INFO", + "range": null, + "title": "Info logs", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "OPENTHREAD_LOG_LEVEL_DEBG", + "name": "OPENTHREAD_LOG_LEVEL_DEBG", + "range": null, + "title": "Debug logs", + "type": "bool" + } + ], + "depends_on": "!OPENTHREAD_LOG_LEVEL_DYNAMIC && OPENTHREAD_ENABLED", + "help": "Select OpenThread log level.", + "id": "component-config-openthread-openthread-thread-log-openthread-log-verbosity", + "name": "OPENTHREAD_LOG_LEVEL", + "title": "OpenThread log verbosity", + "type": "choice" + }, + { + "children": [], + "depends_on": "!OPENTHREAD_LOG_LEVEL_DYNAMIC && OPENTHREAD_ENABLED", + "help": null, + "id": "OPENTHREAD_LOG_LEVEL", + "name": "OPENTHREAD_LOG_LEVEL", + "range": null, + "title": null, + "type": "int" + } + ], + "depends_on": "OPENTHREAD_ENABLED", + "id": "component-config-openthread-openthread-thread-log", + "title": "Thread Log", + "type": "menu" + }, + { + "children": [ + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "OPENTHREAD_HEADER_CUSTOM && OPENTHREAD_HEADER_CUSTOM && OPENTHREAD_ENABLED", + "help": "Please use relative paths with respect to the project folder.", + "id": "OPENTHREAD_CUSTOM_HEADER_PATH", + "name": "OPENTHREAD_CUSTOM_HEADER_PATH", + "range": null, + "title": "Path of custom header file", + "type": "string" + }, + { + "children": [], + "depends_on": "OPENTHREAD_HEADER_CUSTOM && OPENTHREAD_HEADER_CUSTOM && OPENTHREAD_ENABLED", + "help": "Name of custom header file.", + "id": "OPENTHREAD_CUSTOM_HEADER_FILE_NAME", + "name": "OPENTHREAD_CUSTOM_HEADER_FILE_NAME", + "range": null, + "title": "Name of custom header file", + "type": "string" + } + ], + "depends_on": "OPENTHREAD_HEADER_CUSTOM && OPENTHREAD_ENABLED", + "id": "component-config-openthread-openthread-thread-extensioned-features-use-a-header-file-defined-by-customer-openthread-custom-header-config", + "title": "OpenThread Custom Header Config", + "type": "menu" + } + ], + "depends_on": "OPENTHREAD_ENABLED", + "help": "This option allows users to tailor the values of openthread macros according to their requirements.\nThe openthread submodule contains numerous macros, each with a default value set. In the Kconfig of\nESP openthread, users can set specific openthread parameters, which will be applied for certain\nopenthread macros in the openthread-core-esp32x-xxx-config.h file. During compilation, the values\nspecified in openthread-core-esp32x-xxx-config.h will replace the default settings in the openthread\nsubmodule. However, Kconfig does not cover all openthread macros, particularly those typically\nusing default values. For such macros, users can enable the OPENTHREAD_HEADER_CUSTOM option in the\nKconfig and provide a custom header file. Macros defined in the custom header file will have the\nhighest priority.", + "id": "OPENTHREAD_HEADER_CUSTOM", + "name": "OPENTHREAD_HEADER_CUSTOM", + "range": null, + "title": "Use a header file defined by customer", + "type": "bool" + } + ], + "depends_on": "OPENTHREAD_ENABLED", + "id": "component-config-openthread-openthread-thread-extensioned-features", + "title": "Thread Extensioned Features", + "type": "menu" + } + ], + "depends_on": null, + "help": "Select this option to enable OpenThread and show the submenu with OpenThread configuration choices.", + "id": "OPENTHREAD_ENABLED", + "name": "OPENTHREAD_ENABLED", + "range": null, + "title": "OpenThread", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": null, + "help": "Select this option to enable the OpenThread Radio Spinel for external protocol stack, such as Zigbee.", + "id": "OPENTHREAD_SPINEL_ONLY", + "name": "OPENTHREAD_SPINEL_ONLY", + "range": null, + "title": "Enable OpenThread External Radio Spinel feature", + "type": "bool" + }, + { + "children": [], + "depends_on": "OPENTHREAD_ENABLED || OPENTHREAD_SPINEL_ONLY", + "help": null, + "id": "OPENTHREAD_SPINEL_RX_FRAME_BUFFER_SIZE", + "name": "OPENTHREAD_SPINEL_RX_FRAME_BUFFER_SIZE", + "range": null, + "title": "The size of openthread spinel rx frame buffer", + "type": "int" + }, + { + "children": [], + "depends_on": "OPENTHREAD_SPINEL_ONLY", + "help": "The maximum number of backoffs the CSMA-CA algorithm will attempt before declaring a channel access\nfailure.", + "id": "OPENTHREAD_SPINEL_MAC_MAX_CSMA_BACKOFFS_DIRECT", + "name": "OPENTHREAD_SPINEL_MAC_MAX_CSMA_BACKOFFS_DIRECT", + "range": null, + "title": "Maximum backoffs times before declaring a channel access failure.", + "type": "int" + } + ], + "depends_on": null, + "id": "component-config-openthread-openthread-spinel", + "title": "OpenThread Spinel", + "type": "menu" + } + ], + "depends_on": null, + "id": "component-config-openthread", + "title": "OpenThread", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": null, + "help": "Enable support of security version 0.\nDisabling this option saves some code size.\nConsult the Enabling protocomm security version section of the\nProtocomm documentation in ESP-IDF Programming guide for more details.", + "id": "ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_0", + "name": "ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_0", + "range": null, + "title": "Support protocomm security version 0 (no security)", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Enable support of security version 1.\nDisabling this option saves some code size.\nConsult the Enabling protocomm security version section of the\nProtocomm documentation in ESP-IDF Programming guide for more details.", + "id": "ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_1", + "name": "ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_1", + "range": null, + "title": "Support protocomm security version 1 (Curve25519 key exchange + AES-CTR encryption/decryption)", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Enable support of security version 2.\nDisabling this option saves some code size.\nConsult the Enabling protocomm security version section of the\nProtocomm documentation in ESP-IDF Programming guide for more details.", + "id": "ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_2", + "name": "ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_2", + "range": null, + "title": "Support protocomm security version 2 (SRP6a-based key exchange + AES-GCM encryption/decryption)", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Enable support of security patch version. This is a hidden config option\nkept for external components like \"network_provisioning\" to find out if\nprotocomm component support security patch version. This config option\nalso indicates availability of a new API `protocomm_get_sec_version`.\nPlease refer to Protocomm documentation in ESP-IDF Programming guide for\nmore details.", + "id": "ESP_PROTOCOMM_SUPPORT_SECURITY_PATCH_VERSION", + "name": "ESP_PROTOCOMM_SUPPORT_SECURITY_PATCH_VERSION", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_ENABLED", + "help": "Keep BT on after calling protocomm_ble_stop", + "id": "ESP_PROTOCOMM_KEEP_BLE_ON_AFTER_BLE_STOP", + "name": "ESP_PROTOCOMM_KEEP_BLE_ON_AFTER_BLE_STOP", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": "ESP_PROTOCOMM_KEEP_BLE_ON_AFTER_BLE_STOP", + "help": "Terminate connection after calling protocomm_ble_stop", + "id": "ESP_PROTOCOMM_DISCONNECT_AFTER_BLE_STOP", + "name": "ESP_PROTOCOMM_DISCONNECT_AFTER_BLE_STOP", + "range": null, + "title": null, + "type": "bool" + } + ], + "depends_on": null, + "id": "component-config-protocomm", + "title": "Protocomm", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": null, + "help": "Priority used to create new tasks with default pthread parameters.", + "id": "PTHREAD_TASK_PRIO_DEFAULT", + "name": "PTHREAD_TASK_PRIO_DEFAULT", + "range": [ + 0, + 255 + ], + "title": "Default task priority", + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": "Stack size used to create new tasks with default pthread parameters.", + "id": "PTHREAD_TASK_STACK_SIZE_DEFAULT", + "name": "PTHREAD_TASK_STACK_SIZE_DEFAULT", + "range": null, + "title": "Default task stack size", + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": "Minimum allowed pthread stack size set in attributes passed to pthread_create", + "id": "PTHREAD_STACK_MIN", + "name": "PTHREAD_STACK_MIN", + "range": null, + "title": "Minimum allowed pthread stack size", + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "PTHREAD_DEFAULT_CORE_NO_AFFINITY", + "name": "PTHREAD_DEFAULT_CORE_NO_AFFINITY", + "range": null, + "title": "No affinity", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "PTHREAD_DEFAULT_CORE_0", + "name": "PTHREAD_DEFAULT_CORE_0", + "range": null, + "title": "Core 0", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "PTHREAD_DEFAULT_CORE_1", + "name": "PTHREAD_DEFAULT_CORE_1", + "range": null, + "title": "Core 1", + "type": "bool" + } + ], + "depends_on": "!FREERTOS_UNICORE", + "help": "The default core to which pthreads are pinned.", + "id": "component-config-pthreads-default-pthread-core-affinity", + "name": "PTHREAD_TASK_CORE_DEFAULT", + "title": "Default pthread core affinity", + "type": "choice" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "PTHREAD_TASK_CORE_DEFAULT", + "name": "PTHREAD_TASK_CORE_DEFAULT", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": "The default name of pthreads.", + "id": "PTHREAD_TASK_NAME_DEFAULT", + "name": "PTHREAD_TASK_NAME_DEFAULT", + "range": null, + "title": "Default name of pthreads", + "type": "string" + } + ], + "depends_on": null, + "id": "component-config-pthreads", + "title": "PThreads", + "type": "menu" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "SOC_MMU_PAGE_SIZE_8KB_SUPPORTED", + "help": null, + "id": "MMU_PAGE_SIZE_8KB", + "name": "MMU_PAGE_SIZE_8KB", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "MMU_PAGE_SIZE_16KB", + "name": "MMU_PAGE_SIZE_16KB", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "MMU_PAGE_SIZE_32KB", + "name": "MMU_PAGE_SIZE_32KB", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "MMU_PAGE_SIZE_64KB", + "name": "MMU_PAGE_SIZE_64KB", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "MMU_PAGE_MODE", + "name": "MMU_PAGE_MODE", + "range": null, + "title": null, + "type": "string" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "MMU_PAGE_SIZE", + "name": "MMU_PAGE_SIZE", + "range": null, + "title": null, + "type": "hex" + } + ], + "depends_on": null, + "id": "component-config-soc-settings-mmu-config", + "title": "MMU Config", + "type": "menu" + } + ], + "depends_on": null, + "id": "component-config-soc-settings", + "title": "SoC Settings", + "type": "menu" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "!APP_BUILD_TYPE_PURE_RAM_APP", + "help": "When this option is selected, the patch will be enabled for XMC.\nFollow the recommended flow by XMC for better stability.\n\nDO NOT DISABLE UNLESS YOU KNOW WHAT YOU ARE DOING.", + "id": "SPI_FLASH_BROWNOUT_RESET_XMC", + "name": "SPI_FLASH_BROWNOUT_RESET_XMC", + "range": null, + "title": "Enable sending reset when brownout for XMC flash chips", + "type": "bool" + }, + { + "children": [], + "depends_on": "!APP_BUILD_TYPE_PURE_RAM_APP", + "help": "When brownout happens during flash erase/write operations,\nsend reset command to stop the flash operations to improve stability.", + "id": "SPI_FLASH_BROWNOUT_RESET", + "name": "SPI_FLASH_BROWNOUT_RESET", + "range": null, + "title": null, + "type": "bool" + } + ], + "depends_on": "!APP_BUILD_TYPE_PURE_RAM_APP", + "id": "component-config-main-flash-configuration-spi-flash-behavior-when-brownout", + "title": "SPI Flash behavior when brownout", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": "!APP_BUILD_TYPE_PURE_RAM_APP", + "help": "This is a helper config for HPM. Invisible for users.", + "id": "SPI_FLASH_UNDER_HIGH_FREQ", + "name": "SPI_FLASH_UNDER_HIGH_FREQ", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "SPI_FLASH_HPM_ENA", + "name": "SPI_FLASH_HPM_ENA", + "range": null, + "title": "Enable", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "SPI_FLASH_HPM_AUTO", + "name": "SPI_FLASH_HPM_AUTO", + "range": null, + "title": "Auto (Not recommended)", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "SPI_FLASH_HPM_DIS", + "name": "SPI_FLASH_HPM_DIS", + "range": null, + "title": "Disabled", + "type": "bool" + } + ], + "depends_on": "IDF_TARGET_ESP32S3 && !ESPTOOLPY_OCT_FLASH && !APP_BUILD_TYPE_PURE_RAM_APP", + "help": "Whether the High Performance Mode of Flash is enabled. As an optional feature, user needs to manually\nenable this option as a confirmation. To be back-compatible with earlier IDF version, this option is\nautomatically enabled with warning when Flash running > 80Mhz.", + "id": "component-config-main-flash-configuration-optional-and-experimental-features-read-docs-first--high-performance-mode-read-docs-first-80mhz-", + "name": "SPI_FLASH_HPM", + "title": "High Performance Mode (READ DOCS FIRST, > 80MHz)", + "type": "choice" + }, + { + "children": [], + "depends_on": "!APP_BUILD_TYPE_PURE_RAM_APP", + "help": "This option is invisible, and will be selected automatically\nwhen ``ESPTOOLPY_FLASHFREQ_120M`` is selected.", + "id": "SPI_FLASH_HPM_ON", + "name": "SPI_FLASH_HPM_ON", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "SPI_FLASH_HPM_DC_AUTO", + "name": "SPI_FLASH_HPM_DC_AUTO", + "range": null, + "title": "Auto (Enable when bootloader support enabled (BOOTLOADER_FLASH_DC_AWARE))", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "SPI_FLASH_HPM_DC_DISABLE", + "name": "SPI_FLASH_HPM_DC_DISABLE", + "range": null, + "title": "Disable (READ DOCS FIRST)", + "type": "bool" + } + ], + "depends_on": "SPI_FLASH_HPM_ON && !APP_BUILD_TYPE_PURE_RAM_APP", + "help": "This feature needs your bootloader to be compiled DC-aware (BOOTLOADER_FLASH_DC_AWARE=y). Otherwise the\nchip will not be able to boot after a reset.", + "id": "component-config-main-flash-configuration-optional-and-experimental-features-read-docs-first--support-hpm-using-dc-read-docs-first-", + "name": "SPI_FLASH_HPM_DC", + "title": "Support HPM using DC (READ DOCS FIRST)", + "type": "choice" + }, + { + "children": [], + "depends_on": "!APP_BUILD_TYPE_PURE_RAM_APP", + "help": "This is a helper config for HPM. Whether HPM-DC is enabled is also determined by bootloader.\nInvisible for users.", + "id": "SPI_FLASH_HPM_DC_ON", + "name": "SPI_FLASH_HPM_DC_ON", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_SPI_MEM_SUPPORT_AUTO_SUSPEND && !SPI_FLASH_ROM_IMPL && !APP_BUILD_TYPE_PURE_RAM_APP", + "help": "This option is disabled by default because it is supported only\nfor specific flash chips and for specific Espressif chips.\nTo evaluate if you can use this feature refer to\n`Optional Features for Flash` > `Auto Suspend & Resume` of the `ESP-IDF Programming Guide`.\n\nCAUTION: If you want to OTA to an app with this feature turned on, please make\nsure the bootloader has the support for it. (later than IDF v4.3)\n\nIf you are using an official Espressif module, please contact Espressif Business support\nto check if the module has the flash that support this feature installed.\nAlso refer to `Concurrency Constraints for Flash on SPI1` > `Flash Auto Suspend Feature`\nbefore enabling this option.", + "id": "SPI_FLASH_AUTO_SUSPEND", + "name": "SPI_FLASH_AUTO_SUSPEND", + "range": null, + "title": "Auto suspend long erase/write operations (READ DOCS FIRST)", + "type": "bool" + }, + { + "children": [], + "depends_on": "!APP_BUILD_TYPE_PURE_RAM_APP", + "help": "This config is used for setting Tsus parameter. Tsus means CS# high to next command after\nsuspend. You can refer to the chapter of AC CHARACTERISTICS of flash datasheet.", + "id": "SPI_FLASH_SUSPEND_TSUS_VAL_US", + "name": "SPI_FLASH_SUSPEND_TSUS_VAL_US", + "range": [ + 20, + 100 + ], + "title": "SPI flash tSUS value (refer to chapter AC CHARACTERISTICS)", + "type": "int" + }, + { + "children": [], + "depends_on": "!APP_BUILD_TYPE_PURE_RAM_APP", + "help": "XMC-C series is regarded as not qualified for the Suspend feature, since its specification\nhas a tRS >= 1ms restriction. We strongly do not suggest using it for the Suspend feature.\nHowever, if your product in field has enabled this feature, you may still enable this\nconfig option to keep the legacy behavior.\n\nFor new users, DO NOT enable this config.", + "id": "SPI_FLASH_FORCE_ENABLE_XMC_C_SUSPEND", + "name": "SPI_FLASH_FORCE_ENABLE_XMC_C_SUSPEND", + "range": null, + "title": "Enable XMC-C series flash chip suspend feature anyway", + "type": "bool" + }, + { + "children": [], + "depends_on": "SPI_FLASH_AUTO_SUSPEND && FREERTOS_UNICORE && IDF_EXPERIMENTAL_FEATURES && !APP_BUILD_TYPE_PURE_RAM_APP", + "help": "Enable this config will disable auto-resume from hardware. Thus the software will resume the chip\nafter any higher priority task/interrupt which suspend the chip. The benefit is that the suspend-resume\nwill not disturb the higher priority task and interrupt.\n\nThis currently is only valid on single core chip.", + "id": "SPI_FLASH_SOFTWARE_RESUME", + "name": "SPI_FLASH_SOFTWARE_RESUME", + "range": null, + "title": "Resume flash program/erase form suspend state by software control", + "type": "bool" + }, + { + "children": [], + "depends_on": "SPI_FLASH_AUTO_SUSPEND && FREERTOS_UNICORE && !APP_BUILD_TYPE_PURE_RAM_APP", + "help": "Disable freertos task scheduler when CONFIG_SPI_FLASH_AUTO_SUSPEND is enabled.\nThus only interrupt can trigger a suspend. When SPI_FLASH_AUTO_SUSPEND is enabled,\ndefault behavior is not disable the task scheduler, so both interrupt and high priority\ntask can suspend the erase/program operation. When this option is enabled, task\nscheduler is disabled, only interrupt can suspend erase/program operation.", + "id": "SPI_FLASH_DISABLE_SCHEDULER_IN_SUSPEND", + "name": "SPI_FLASH_DISABLE_SCHEDULER_IN_SUSPEND", + "range": null, + "title": "Disable task scheduler when suspend is enabled when SPI1 operation is ongoing", + "type": "bool" + }, + { + "children": [], + "depends_on": "SPI_FLASH_AUTO_SUSPEND && !APP_BUILD_TYPE_PURE_RAM_APP", + "help": "Majority flash supports to use flash register to judge if flash suspend status is\ndone or not. So enable this config, the behavior would use flash register WIP bit to judge\nwhether suspend is valid instead of waiting for a specific long time, which can save a\nlot of time and benefit for performance improvement.", + "id": "SPI_FLASH_AUTO_CHECK_SUSPEND_STATUS", + "name": "SPI_FLASH_AUTO_CHECK_SUSPEND_STATUS", + "range": null, + "title": "Check flash status automatically after flash suspend", + "type": "bool" + } + ], + "depends_on": "!APP_BUILD_TYPE_PURE_RAM_APP", + "id": "component-config-main-flash-configuration-optional-and-experimental-features-read-docs-first-", + "title": "Optional and Experimental Features (READ DOCS FIRST)", + "type": "menu" + } + ], + "depends_on": "!APP_BUILD_TYPE_PURE_RAM_APP", + "id": "component-config-main-flash-configuration", + "title": "Main Flash configuration", + "type": "menu" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "SPI_FLASH_VERIFY_WRITE && !APP_BUILD_TYPE_PURE_RAM_APP", + "help": "If this option is enabled, if SPI flash write verification fails then a log error line\nwill be written with the address, expected & actual values. This can be useful when\ndebugging hardware SPI flash problems.", + "id": "SPI_FLASH_LOG_FAILED_WRITE", + "name": "SPI_FLASH_LOG_FAILED_WRITE", + "range": null, + "title": "Log errors if verification fails", + "type": "bool" + }, + { + "children": [], + "depends_on": "SPI_FLASH_VERIFY_WRITE && !APP_BUILD_TYPE_PURE_RAM_APP", + "help": "If this option is enabled, any SPI flash write which tries to set zero bits in the flash to\nones will log a warning. Such writes will not result in the requested data appearing identically\nin flash once written, as SPI NOR flash can only set bits to one when an entire sector is erased.\nAfter erasing, individual bits can only be written from one to zero.\n\nNote that some software (such as SPIFFS) which is aware of SPI NOR flash may write one bits as an\noptimisation, relying on the data in flash becoming a bitwise AND of the new data and any existing data.\nSuch software will log spurious warnings if this option is enabled.", + "id": "SPI_FLASH_WARN_SETTING_ZERO_TO_ONE", + "name": "SPI_FLASH_WARN_SETTING_ZERO_TO_ONE", + "range": null, + "title": "Log warning if writing zero bits to ones", + "type": "bool" + } + ], + "depends_on": "!SPI_FLASH_ROM_IMPL && !APP_BUILD_TYPE_PURE_RAM_APP", + "help": "If this option is enabled, any time SPI flash is written then the data will be read\nback and verified. This can catch hardware problems with SPI flash, or flash which\nwas not erased before verification.", + "id": "SPI_FLASH_VERIFY_WRITE", + "name": "SPI_FLASH_VERIFY_WRITE", + "range": null, + "title": "Verify SPI flash writes", + "type": "bool" + }, + { + "children": [], + "depends_on": "!APP_BUILD_TYPE_PURE_RAM_APP", + "help": "This option enables the following APIs:\n\n- esp_flash_reset_counters\n- esp_flash_dump_counters\n- esp_flash_get_counters\n\nThese APIs may be used to collect performance data for spi_flash APIs\nand to help understand behaviour of libraries which use SPI flash.", + "id": "SPI_FLASH_ENABLE_COUNTERS", + "name": "SPI_FLASH_ENABLE_COUNTERS", + "range": null, + "title": "Enable operation counters", + "type": "bool" + }, + { + "children": [], + "depends_on": "!APP_BUILD_TYPE_PURE_RAM_APP", + "help": "Enable this flag to use patched versions of SPI flash ROM driver functions.\nThis option should be enabled, if any one of the following is true: (1) need to write\nto flash on ESP32-D2WD; (2) main SPI flash is connected to non-default pins; (3) main\nSPI flash chip is manufactured by ISSI.", + "id": "SPI_FLASH_ROM_DRIVER_PATCH", + "name": "SPI_FLASH_ROM_DRIVER_PATCH", + "range": null, + "title": "Enable SPI flash ROM driver patched functions", + "type": "bool" + }, + { + "children": [], + "depends_on": "ESP_ROM_HAS_SPI_FLASH && !APP_BUILD_TYPE_PURE_RAM_APP", + "help": "Enable this flag to use new SPI flash driver functions from ROM instead of ESP-IDF.\n\nIf keeping this as \"n\" in your project, you will have less free IRAM.\nBut you can use all of our flash features.\n\nIf making this as \"y\" in your project, you will increase free IRAM.\nBut you may miss out on some flash features and support for new flash chips.\n\nCurrently the ROM cannot support the following features:\n\n- SPI_FLASH_AUTO_SUSPEND (C3, S3)", + "id": "SPI_FLASH_ROM_IMPL", + "name": "SPI_FLASH_ROM_IMPL", + "range": null, + "title": "Use esp_flash implementation in ROM", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "SPI_FLASH_DANGEROUS_WRITE_ABORTS", + "name": "SPI_FLASH_DANGEROUS_WRITE_ABORTS", + "range": null, + "title": "Aborts", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "SPI_FLASH_DANGEROUS_WRITE_FAILS", + "name": "SPI_FLASH_DANGEROUS_WRITE_FAILS", + "range": null, + "title": "Fails", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "SPI_FLASH_DANGEROUS_WRITE_ALLOWED", + "name": "SPI_FLASH_DANGEROUS_WRITE_ALLOWED", + "range": null, + "title": "Allowed", + "type": "bool" + } + ], + "depends_on": "!APP_BUILD_TYPE_PURE_RAM_APP", + "help": "SPI flash APIs can optionally abort or return a failure code\nif erasing or writing addresses that fall at the beginning\nof flash (covering the bootloader and partition table) or that\noverlap the app partition that contains the running app.\n\nIt is not recommended to ever write to these regions from an IDF app,\nand this check prevents logic errors or corrupted firmware memory from\ndamaging these regions.\n\nNote that this feature *does not* check calls to the esp_rom_xxx SPI flash\nROM functions. These functions should not be called directly from IDF\napplications.", + "id": "component-config-spi-flash-driver-writing-to-dangerous-flash-regions", + "name": "SPI_FLASH_DANGEROUS_WRITE", + "title": "Writing to dangerous flash regions", + "type": "choice" + }, + { + "children": [], + "depends_on": "IDF_TARGET_ESP32 && !APP_BUILD_TYPE_PURE_RAM_APP", + "help": "Each SPI bus needs a lock for arbitration among devices. This allows multiple\ndevices on a same bus, but may reduce the speed of esp_flash driver access to the\nmain flash chip.\n\nIf you only need to use esp_flash driver to access the main flash chip, disable\nthis option, and the lock will be bypassed on SPI1 bus. Otherwise if extra devices\nare needed to attach to SPI1 bus, enable this option.", + "id": "SPI_FLASH_SHARE_SPI1_BUS", + "name": "SPI_FLASH_SHARE_SPI1_BUS", + "range": null, + "title": "Support other devices attached to SPI1 bus", + "type": "bool" + }, + { + "children": [], + "depends_on": "!APP_BUILD_TYPE_PURE_RAM_APP", + "help": "Some flash chips can have very high \"max\" erase times, especially for block erase (32KB or 64KB).\nThis option allows to bypass \"block erase\" and always do sector erase commands.\nThis will be much slower overall in most cases, but improves latency for other code to run.", + "id": "SPI_FLASH_BYPASS_BLOCK_ERASE", + "name": "SPI_FLASH_BYPASS_BLOCK_ERASE", + "range": null, + "title": "Bypass a block erase and always do sector erase", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "SPI_FLASH_YIELD_DURING_ERASE && !APP_BUILD_TYPE_PURE_RAM_APP", + "help": "If a duration of one erase command is large\nthen it will yield CPUs after finishing a current command.", + "id": "SPI_FLASH_ERASE_YIELD_DURATION_MS", + "name": "SPI_FLASH_ERASE_YIELD_DURATION_MS", + "range": null, + "title": "Duration of erasing to yield CPUs (ms)", + "type": "int" + }, + { + "children": [], + "depends_on": "SPI_FLASH_YIELD_DURING_ERASE && !APP_BUILD_TYPE_PURE_RAM_APP", + "help": "Defines how many ticks will be before returning to continue a erasing.", + "id": "SPI_FLASH_ERASE_YIELD_TICKS", + "name": "SPI_FLASH_ERASE_YIELD_TICKS", + "range": null, + "title": "CPU release time (tick) for an erase operation", + "type": "int" + } + ], + "depends_on": "!APP_BUILD_TYPE_PURE_RAM_APP", + "help": "This allows to yield the CPUs between erase commands.\nPrevents starvation of other tasks.\nPlease use this configuration together with ``SPI_FLASH_ERASE_YIELD_DURATION_MS`` and\n``SPI_FLASH_ERASE_YIELD_TICKS`` after carefully checking flash datasheet to avoid a\nwatchdog timeout.\nFor more information, please check `SPI Flash API` reference documentation\nunder section `OS Function`.", + "id": "SPI_FLASH_YIELD_DURING_ERASE", + "name": "SPI_FLASH_YIELD_DURING_ERASE", + "range": null, + "title": "Enables yield operation during flash erase", + "type": "bool" + }, + { + "children": [], + "depends_on": "!APP_BUILD_TYPE_PURE_RAM_APP", + "help": "Flash write is broken down in terms of multiple (smaller) write operations.\nThis configuration options helps to set individual write chunk size, smaller\nvalue here ensures that cache (and non-IRAM resident interrupts) remains\ndisabled for shorter duration.", + "id": "SPI_FLASH_WRITE_CHUNK_SIZE", + "name": "SPI_FLASH_WRITE_CHUNK_SIZE", + "range": [ + 256, + 8192 + ], + "title": "Flash write chunk size", + "type": "int" + }, + { + "children": [], + "depends_on": "!APP_BUILD_TYPE_PURE_RAM_APP", + "help": "SPI Flash driver uses the flash size configured in bootloader header by default.\nEnable this option to override flash size with latest ESPTOOLPY_FLASHSIZE value from\nthe app header if the size in the bootloader header is incorrect.", + "id": "SPI_FLASH_SIZE_OVERRIDE", + "name": "SPI_FLASH_SIZE_OVERRIDE", + "range": null, + "title": "Override flash size in bootloader header by ESPTOOLPY_FLASHSIZE", + "type": "bool" + }, + { + "children": [], + "depends_on": "!APP_BUILD_TYPE_PURE_RAM_APP", + "help": "This option is helpful if you are using a flash chip whose timeout is quite large or unpredictable.", + "id": "SPI_FLASH_CHECK_ERASE_TIMEOUT_DISABLED", + "name": "SPI_FLASH_CHECK_ERASE_TIMEOUT_DISABLED", + "range": null, + "title": "Flash timeout checkout disabled", + "type": "bool" + }, + { + "children": [], + "depends_on": "!APP_BUILD_TYPE_PURE_RAM_APP", + "help": "This option allows the chip driver list to be customized, instead of using the default list provided by\nESP-IDF.\n\nWhen this option is enabled, the default list is no longer compiled or linked. Instead, the\n`default_registered_chips` structure must be provided by the user.\n\nSee example: custom_chip_driver under examples/storage for more details.", + "id": "SPI_FLASH_OVERRIDE_CHIP_DRIVER_LIST", + "name": "SPI_FLASH_OVERRIDE_CHIP_DRIVER_LIST", + "range": null, + "title": "Override default chip driver list", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "!APP_BUILD_TYPE_PURE_RAM_APP", + "help": null, + "id": "SPI_FLASH_VENDOR_XMC_SUPPORTED", + "name": "SPI_FLASH_VENDOR_XMC_SUPPORTED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": "!APP_BUILD_TYPE_PURE_RAM_APP", + "help": null, + "id": "SPI_FLASH_VENDOR_GD_SUPPORTED", + "name": "SPI_FLASH_VENDOR_GD_SUPPORTED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": "!APP_BUILD_TYPE_PURE_RAM_APP", + "help": null, + "id": "SPI_FLASH_VENDOR_ISSI_SUPPORTED", + "name": "SPI_FLASH_VENDOR_ISSI_SUPPORTED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": "!APP_BUILD_TYPE_PURE_RAM_APP", + "help": null, + "id": "SPI_FLASH_VENDOR_MXIC_SUPPORTED", + "name": "SPI_FLASH_VENDOR_MXIC_SUPPORTED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": "!APP_BUILD_TYPE_PURE_RAM_APP", + "help": null, + "id": "SPI_FLASH_VENDOR_WINBOND_SUPPORTED", + "name": "SPI_FLASH_VENDOR_WINBOND_SUPPORTED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": "!APP_BUILD_TYPE_PURE_RAM_APP", + "help": null, + "id": "SPI_FLASH_VENDOR_BOYA_SUPPORTED", + "name": "SPI_FLASH_VENDOR_BOYA_SUPPORTED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": "!APP_BUILD_TYPE_PURE_RAM_APP", + "help": null, + "id": "SPI_FLASH_VENDOR_TH_SUPPORTED", + "name": "SPI_FLASH_VENDOR_TH_SUPPORTED", + "range": null, + "title": null, + "type": "bool" + }, + { + "children": [], + "depends_on": "!APP_BUILD_TYPE_PURE_RAM_APP", + "help": "Enable this to support auto detection of ISSI chips if chip vendor not directly\ngiven by ``chip_drv`` member of the chip struct. This adds support for variant\nchips, however will extend detecting time.", + "id": "SPI_FLASH_SUPPORT_ISSI_CHIP", + "name": "SPI_FLASH_SUPPORT_ISSI_CHIP", + "range": null, + "title": "ISSI", + "type": "bool" + }, + { + "children": [], + "depends_on": "!APP_BUILD_TYPE_PURE_RAM_APP", + "help": "Enable this to support auto detection of MXIC chips if chip vendor not directly\ngiven by ``chip_drv`` member of the chip struct. This adds support for variant\nchips, however will extend detecting time.", + "id": "SPI_FLASH_SUPPORT_MXIC_CHIP", + "name": "SPI_FLASH_SUPPORT_MXIC_CHIP", + "range": null, + "title": "MXIC", + "type": "bool" + }, + { + "children": [], + "depends_on": "!APP_BUILD_TYPE_PURE_RAM_APP", + "help": "Enable this to support auto detection of GD (GigaDevice) chips if chip vendor not\ndirectly given by ``chip_drv`` member of the chip struct. If you are using Wrover\nmodules, please don't disable this, otherwise your flash may not work in 4-bit\nmode.\n\nThis adds support for variant chips, however will extend detecting time and image\nsize. Note that the default chip driver supports the GD chips with product ID\n60H.", + "id": "SPI_FLASH_SUPPORT_GD_CHIP", + "name": "SPI_FLASH_SUPPORT_GD_CHIP", + "range": null, + "title": "GigaDevice", + "type": "bool" + }, + { + "children": [], + "depends_on": "!APP_BUILD_TYPE_PURE_RAM_APP", + "help": "Enable this to support auto detection of Winbond chips if chip vendor not directly\ngiven by ``chip_drv`` member of the chip struct. This adds support for variant\nchips, however will extend detecting time.", + "id": "SPI_FLASH_SUPPORT_WINBOND_CHIP", + "name": "SPI_FLASH_SUPPORT_WINBOND_CHIP", + "range": null, + "title": "Winbond", + "type": "bool" + }, + { + "children": [], + "depends_on": "!APP_BUILD_TYPE_PURE_RAM_APP", + "help": "Enable this to support auto detection of BOYA chips if chip vendor not directly\ngiven by ``chip_drv`` member of the chip struct. This adds support for variant\nchips, however will extend detecting time.", + "id": "SPI_FLASH_SUPPORT_BOYA_CHIP", + "name": "SPI_FLASH_SUPPORT_BOYA_CHIP", + "range": null, + "title": "BOYA", + "type": "bool" + }, + { + "children": [], + "depends_on": "!APP_BUILD_TYPE_PURE_RAM_APP", + "help": "Enable this to support auto detection of TH chips if chip vendor not directly\ngiven by ``chip_drv`` member of the chip struct. This adds support for variant\nchips, however will extend detecting time.", + "id": "SPI_FLASH_SUPPORT_TH_CHIP", + "name": "SPI_FLASH_SUPPORT_TH_CHIP", + "range": null, + "title": "TH", + "type": "bool" + }, + { + "children": [], + "depends_on": "IDF_TARGET_ESP32S3 && !APP_BUILD_TYPE_PURE_RAM_APP", + "help": "Enable this to support auto detection of Octal MXIC chips if chip vendor not directly\ngiven by ``chip_drv`` member of the chip struct. This adds support for variant\nchips, however will extend detecting time.", + "id": "SPI_FLASH_SUPPORT_MXIC_OPI_CHIP", + "name": "SPI_FLASH_SUPPORT_MXIC_OPI_CHIP", + "range": null, + "title": "mxic (opi)", + "type": "bool" + } + ], + "depends_on": "!APP_BUILD_TYPE_PURE_RAM_APP", + "id": "component-config-spi-flash-driver-auto-detect-flash-chips", + "title": "Auto-detect flash chips", + "type": "menu" + }, + { + "children": [], + "depends_on": "!APP_BUILD_TYPE_PURE_RAM_APP", + "help": "This option enables flash read/write operations to encrypted partition/s. This option\nis kept enabled irrespective of state of flash encryption feature. However, in case\napplication is not using flash encryption feature and is in need of some additional\nmemory from IRAM region (~1KB) then this config can be disabled.", + "id": "SPI_FLASH_ENABLE_ENCRYPTED_READ_WRITE", + "name": "SPI_FLASH_ENABLE_ENCRYPTED_READ_WRITE", + "range": null, + "title": "Enable encrypted partition read/write operations", + "type": "bool" + } + ], + "depends_on": "!APP_BUILD_TYPE_PURE_RAM_APP", + "id": "component-config-spi-flash-driver", + "title": "SPI Flash driver", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": null, + "help": "Define maximum number of partitions that can be mounted.", + "id": "SPIFFS_MAX_PARTITIONS", + "name": "SPIFFS_MAX_PARTITIONS", + "range": [ + 1, + 10 + ], + "title": "Maximum Number of Partitions", + "type": "int" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "SPIFFS_CACHE", + "help": "Enables memory write caching for file descriptors in hydrogen.", + "id": "SPIFFS_CACHE_WR", + "name": "SPIFFS_CACHE_WR", + "range": null, + "title": "Enable SPIFFS Write Caching", + "type": "bool" + }, + { + "children": [], + "depends_on": "SPIFFS_CACHE", + "help": "Enable/disable statistics on caching. Debug/test purpose only.", + "id": "SPIFFS_CACHE_STATS", + "name": "SPIFFS_CACHE_STATS", + "range": null, + "title": "Enable SPIFFS Cache Statistics", + "type": "bool" + } + ], + "depends_on": null, + "help": "Enables/disable memory read caching of nucleus file system\noperations.", + "id": "SPIFFS_CACHE", + "name": "SPIFFS_CACHE", + "range": null, + "title": "Enable SPIFFS Cache", + "type": "bool" + } + ], + "depends_on": null, + "id": "component-config-spiffs-configuration-spiffs-cache-configuration", + "title": "SPIFFS Cache Configuration", + "type": "menu" + }, + { + "children": [], + "depends_on": null, + "help": "Always check header of each accessed page to ensure consistent state.\nIf enabled it will increase number of reads from flash, especially\nif cache is disabled.", + "id": "SPIFFS_PAGE_CHECK", + "name": "SPIFFS_PAGE_CHECK", + "range": null, + "title": "Enable SPIFFS Page Check", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Define maximum number of GC runs to perform to reach desired free pages.", + "id": "SPIFFS_GC_MAX_RUNS", + "name": "SPIFFS_GC_MAX_RUNS", + "range": [ + 1, + 10000 + ], + "title": "Set Maximum GC Runs", + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": "Enable/disable statistics on gc. Debug/test purpose only.", + "id": "SPIFFS_GC_STATS", + "name": "SPIFFS_GC_STATS", + "range": null, + "title": "Enable SPIFFS GC Statistics", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Logical page size of SPIFFS partition, in bytes. Must be multiple\nof flash page size (which is usually 256 bytes).\nLarger page sizes reduce overhead when storing large files, and\nimprove filesystem performance when reading large files.\nSmaller page sizes reduce overhead when storing small (< page size)\nfiles.", + "id": "SPIFFS_PAGE_SIZE", + "name": "SPIFFS_PAGE_SIZE", + "range": [ + 256, + 1024 + ], + "title": "SPIFFS logical page size", + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": "Object name maximum length. Note that this length include the\nzero-termination character, meaning maximum string of characters\ncan at most be SPIFFS_OBJ_NAME_LEN - 1.\n\nSPIFFS_OBJ_NAME_LEN + SPIFFS_META_LENGTH should not exceed\nSPIFFS_PAGE_SIZE - 64.", + "id": "SPIFFS_OBJ_NAME_LEN", + "name": "SPIFFS_OBJ_NAME_LEN", + "range": [ + 1, + 256 + ], + "title": "Set SPIFFS Maximum Name Length", + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": "If this option is enabled, symbolic links are taken into account\nduring partition image creation.", + "id": "SPIFFS_FOLLOW_SYMLINKS", + "name": "SPIFFS_FOLLOW_SYMLINKS", + "range": null, + "title": "Enable symbolic links for image creation", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "SPIFFS_USE_MAGIC", + "help": "If this option is enabled, the magic will also be dependent\non the length of the filesystem. For example, a filesystem\nconfigured and formatted for 4 megabytes will not be accepted\nfor mounting with a configuration defining the filesystem as 2 megabytes.", + "id": "SPIFFS_USE_MAGIC_LENGTH", + "name": "SPIFFS_USE_MAGIC_LENGTH", + "range": null, + "title": "Enable SPIFFS Filesystem Length Magic", + "type": "bool" + } + ], + "depends_on": null, + "help": "Enable this to have an identifiable spiffs filesystem.\nThis will look for a magic in all sectors to determine if this\nis a valid spiffs system or not at mount time.", + "id": "SPIFFS_USE_MAGIC", + "name": "SPIFFS_USE_MAGIC", + "range": null, + "title": "Enable SPIFFS Filesystem Magic", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "This option sets the number of extra bytes stored in the file header.\nThese bytes can be used in an application-specific manner.\nSet this to at least 4 bytes to enable support for saving file\nmodification time.\n\nSPIFFS_OBJ_NAME_LEN + SPIFFS_META_LENGTH should not exceed\nSPIFFS_PAGE_SIZE - 64.", + "id": "SPIFFS_META_LENGTH", + "name": "SPIFFS_META_LENGTH", + "range": null, + "title": "Size of per-file metadata field", + "type": "int" + }, + { + "children": [], + "depends_on": "SPIFFS_META_LENGTH >= 4", + "help": "If enabled, then the first 4 bytes of per-file metadata will be used\nto store file modification time (mtime), accessible through\nstat/fstat functions.\nModification time is updated when the file is opened.", + "id": "SPIFFS_USE_MTIME", + "name": "SPIFFS_USE_MTIME", + "range": null, + "title": "Save file modification time", + "type": "bool" + }, + { + "children": [], + "depends_on": "SPIFFS_META_LENGTH >= 8", + "help": "If this option is not set, the time field is 32 bits (up to 2106 year),\notherwise it is 64 bits and make sure it matches SPIFFS_META_LENGTH.\nIf the chip already has the spiffs image with the time field = 32 bits\nthen this option cannot be applied in this case.\nErase it first before using this option.\nTo resolve the Y2K38 problem for the spiffs, use a toolchain with\n64-bit time_t support.", + "id": "SPIFFS_MTIME_WIDE_64_BITS", + "name": "SPIFFS_MTIME_WIDE_64_BITS", + "range": null, + "title": "The time field occupies 64 bits in the image instead of 32 bits", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": null, + "help": "Enabling this option will print general debug messages to the console.", + "id": "SPIFFS_DBG", + "name": "SPIFFS_DBG", + "range": null, + "title": "Enable general SPIFFS debug", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Enabling this option will print API debug messages to the console.", + "id": "SPIFFS_API_DBG", + "name": "SPIFFS_API_DBG", + "range": null, + "title": "Enable SPIFFS API debug", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Enabling this option will print GC debug messages to the console.", + "id": "SPIFFS_GC_DBG", + "name": "SPIFFS_GC_DBG", + "range": null, + "title": "Enable SPIFFS Garbage Cleaner debug", + "type": "bool" + }, + { + "children": [], + "depends_on": "SPIFFS_CACHE", + "help": "Enabling this option will print cache debug messages to the console.", + "id": "SPIFFS_CACHE_DBG", + "name": "SPIFFS_CACHE_DBG", + "range": null, + "title": "Enable SPIFFS Cache debug", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Enabling this option will print Filesystem Check debug messages\nto the console.", + "id": "SPIFFS_CHECK_DBG", + "name": "SPIFFS_CHECK_DBG", + "range": null, + "title": "Enable SPIFFS Filesystem Check debug", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Enable this option to enable SPIFFS_vis function in the API.", + "id": "SPIFFS_TEST_VISUALISATION", + "name": "SPIFFS_TEST_VISUALISATION", + "range": null, + "title": "Enable SPIFFS Filesystem Visualization", + "type": "bool" + } + ], + "depends_on": null, + "id": "component-config-spiffs-configuration-debug-configuration", + "title": "Debug Configuration", + "type": "menu" + } + ], + "depends_on": null, + "id": "component-config-spiffs-configuration", + "title": "SPIFFS Configuration", + "type": "menu" + }, + { + "children": [ + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "WS_TRANSPORT", + "help": "Size of the buffer used for constructing the HTTP Upgrade request during connect", + "id": "WS_BUFFER_SIZE", + "name": "WS_BUFFER_SIZE", + "range": null, + "title": "Websocket transport buffer size", + "type": "int" + }, + { + "children": [], + "depends_on": "WS_TRANSPORT", + "help": "If enable this option, websocket transport buffer will be freed after connection\nsucceed to save more heap.", + "id": "WS_DYNAMIC_BUFFER", + "name": "WS_DYNAMIC_BUFFER", + "range": null, + "title": "Using dynamic websocket transport buffer", + "type": "bool" + } + ], + "depends_on": null, + "help": "Enable support for creating websocket transport.", + "id": "WS_TRANSPORT", + "name": "WS_TRANSPORT", + "range": null, + "title": "Enable Websocket Transport", + "type": "bool" + } + ], + "depends_on": null, + "id": "component-config-tcp-transport-websocket", + "title": "Websocket", + "type": "menu" + } + ], + "depends_on": null, + "id": "component-config-tcp-transport", + "title": "TCP Transport", + "type": "menu" + }, + { + "children": [ + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "SOC_ULP_FSM_SUPPORTED && ", + "help": null, + "id": "ULP_COPROC_TYPE_FSM", + "name": "ULP_COPROC_TYPE_FSM", + "range": null, + "title": "ULP FSM (Finite State Machine)", + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_RISCV_COPROC_SUPPORTED && ", + "help": null, + "id": "ULP_COPROC_TYPE_RISCV", + "name": "ULP_COPROC_TYPE_RISCV", + "range": null, + "title": "ULP RISC-V", + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_LP_CORE_SUPPORTED && ", + "help": null, + "id": "ULP_COPROC_TYPE_LP_CORE", + "name": "ULP_COPROC_TYPE_LP_CORE", + "range": null, + "title": "LP core RISC-V", + "type": "bool" + } + ], + "depends_on": "ULP_COPROC_ENABLED && (SOC_ULP_SUPPORTED || SOC_RISCV_COPROC_SUPPORTED || SOC_LP_CORE_SUPPORTED)", + "help": "Choose the ULP Coprocessor type: ULP FSM (Finite State Machine) or ULP RISC-V.", + "id": "component-config-ultra-low-power-ulp-co-processor-enable-ultra-low-power-ulp-co-processor-ulp-co-processor-type", + "name": "ULP_COPROC_TYPE", + "title": "ULP Co-processor type", + "type": "choice" + }, + { + "children": [], + "depends_on": "ULP_COPROC_ENABLED && (SOC_ULP_SUPPORTED || SOC_RISCV_COPROC_SUPPORTED || SOC_LP_CORE_SUPPORTED)", + "help": "Bytes of memory to reserve for ULP Co-processor firmware & data.\nData is reserved at the beginning of RTC slow memory.", + "id": "ULP_COPROC_RESERVE_MEM", + "name": "ULP_COPROC_RESERVE_MEM", + "range": null, + "title": "RTC slow memory reserved for coprocessor", + "type": "int" + } + ], + "depends_on": "SOC_ULP_SUPPORTED || SOC_RISCV_COPROC_SUPPORTED || SOC_LP_CORE_SUPPORTED", + "help": "Enable this feature if you plan to use the ULP Co-processor.\nOnce this option is enabled, further ULP co-processor configuration will appear in the menu.", + "id": "ULP_COPROC_ENABLED", + "name": "ULP_COPROC_ENABLED", + "range": null, + "title": "Enable Ultra Low Power (ULP) Co-processor", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "ULP_COPROC_TYPE_RISCV && (SOC_ULP_SUPPORTED || SOC_RISCV_COPROC_SUPPORTED || SOC_LP_CORE_SUPPORTED)", + "help": "Turn on this setting to enabled interrupts on the ULP RISC-V core.", + "id": "ULP_RISCV_INTERRUPT_ENABLE", + "name": "ULP_RISCV_INTERRUPT_ENABLE", + "range": null, + "title": "Enable ULP RISC-V interrupts", + "type": "bool" + }, + { + "children": [], + "depends_on": "ULP_COPROC_TYPE_RISCV && (SOC_ULP_SUPPORTED || SOC_RISCV_COPROC_SUPPORTED || SOC_LP_CORE_SUPPORTED)", + "help": "The accuracy of the bitbanged UART driver is limited, it is not\nrecommend to increase the value above 19200.", + "id": "ULP_RISCV_UART_BAUDRATE", + "name": "ULP_RISCV_UART_BAUDRATE", + "range": null, + "title": "Baudrate used by the bitbanged ULP RISC-V UART driver", + "type": "int" + }, + { + "children": [], + "depends_on": "ULP_COPROC_TYPE_RISCV && (SOC_ULP_SUPPORTED || SOC_RISCV_COPROC_SUPPORTED || SOC_LP_CORE_SUPPORTED)", + "help": "Set the ULP RISC-V I2C read/write timeout. Set this value to -1\nif the ULP RISC-V I2C read and write APIs should wait forever.\nPlease note that the tick rate of the ULP co-processor would be\ndifferent than the OS tick rate of the main core and therefore\ncan have different timeout value depending on which core the API\nis invoked on.", + "id": "ULP_RISCV_I2C_RW_TIMEOUT", + "name": "ULP_RISCV_I2C_RW_TIMEOUT", + "range": null, + "title": "Set timeout for ULP RISC-V I2C transaction timeout in ticks.", + "type": "int" + } + ], + "depends_on": "ULP_COPROC_TYPE_RISCV && (SOC_ULP_SUPPORTED || SOC_RISCV_COPROC_SUPPORTED || SOC_LP_CORE_SUPPORTED)", + "id": "component-config-ultra-low-power-ulp-co-processor-ulp-risc-v-settings", + "title": "ULP RISC-V Settings", + "type": "menu" + }, + { + "children": [], + "depends_on": "ULP_COPROC_TYPE_LP_CORE && (SOC_ULP_SUPPORTED || SOC_RISCV_COPROC_SUPPORTED || SOC_LP_CORE_SUPPORTED)", + "help": "Size of the shared memory defined in ulp_lp_core_memory_shared.c.\nSize should be kept in-sync with the size of the struct defined there.", + "id": "ULP_SHARED_MEM", + "name": "ULP_SHARED_MEM", + "range": null, + "title": null, + "type": "hex" + }, + { + "children": [], + "depends_on": "ULP_COPROC_TYPE_LP_CORE && ESP_ROM_HAS_LP_ROM && (SOC_ULP_SUPPORTED || SOC_RISCV_COPROC_SUPPORTED || SOC_LP_CORE_SUPPORTED)", + "help": "Set this option to enable printf functionality from LP ROM. This option\ncan help reduce the LP core binary size by not linking printf functionality\nfrom RAM code.\nNote: For LP ROM prints to work properly, make sure that the LP core boots\nfrom the LP ROM.", + "id": "ULP_ROM_PRINT_ENABLE", + "name": "ULP_ROM_PRINT_ENABLE", + "range": null, + "title": "Enable print utilities from LP ROM", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "ULP_COPROC_TYPE_LP_CORE && SOC_ULP_LP_UART_SUPPORTED && (SOC_ULP_SUPPORTED || SOC_RISCV_COPROC_SUPPORTED || SOC_LP_CORE_SUPPORTED)", + "help": "Set this option to enable panic handler functionality. If this option is\nenabled then the LP Core will output a panic dump over LP UART,\nsimilar to what the main core does. Output depends on LP UART already being\ninitialized and configured.\nDisabling this option will reduce the LP core binary size by not\nlinking in panic handler functionality.", + "id": "ULP_PANIC_OUTPUT_ENABLE", + "name": "ULP_PANIC_OUTPUT_ENABLE", + "range": null, + "title": "Enable panic handler which outputs over LP UART", + "type": "bool" + }, + { + "children": [], + "depends_on": "ULP_COPROC_TYPE_LP_CORE && (SOC_ULP_SUPPORTED || SOC_RISCV_COPROC_SUPPORTED || SOC_LP_CORE_SUPPORTED)", + "help": "Set this option to route lp_core_printf to the console HP-UART.\nThis allows you to easily view print outputs from the LP core, without\nhaving to connect to the LP-UART. This option comes with the following\nlimitations:\n\n1. There is no mutual exclusion between the HP-Core and the LP-Core accessing\nthe HP-UART, which means that if both cores are logging heavily the output\nstrings might get mangled together.\n2. The HP-UART can only work while the HP-Core is running, which means that\nif the HP-Core is in deep sleep, the LP-Core will not be able to print to the\nconsole HP-UART.\n\nDue to these limitations it is only recommended to use this option for easy debugging.\nFor more serious use-cases you should use the LP-UART.", + "id": "ULP_HP_UART_CONSOLE_PRINT", + "name": "ULP_HP_UART_CONSOLE_PRINT", + "range": null, + "title": "Route lp_core_printf to the console HP-UART", + "type": "bool" + }, + { + "children": [], + "depends_on": "ULP_COPROC_TYPE_LP_CORE && (SOC_ULP_SUPPORTED || SOC_RISCV_COPROC_SUPPORTED || SOC_LP_CORE_SUPPORTED)", + "help": "Enable this feature to avoid resetting LP core in sleep mode when debugger is attached,\notherwise configured HW breakpoints and dcsr.ebreak* bits will be missed.\nThis is a workaround until it will be fixed in HW.", + "id": "ULP_NORESET_UNDER_DEBUG", + "name": "ULP_NORESET_UNDER_DEBUG", + "range": null, + "title": "Avoid resetting LP core when debugger is attached", + "type": "bool" + } + ], + "depends_on": "SOC_ULP_SUPPORTED || SOC_RISCV_COPROC_SUPPORTED || SOC_LP_CORE_SUPPORTED", + "id": "component-config-ultra-low-power-ulp-co-processor-ulp-debugging-options", + "title": "ULP Debugging Options", + "type": "menu" + } + ], + "depends_on": "SOC_ULP_SUPPORTED || SOC_RISCV_COPROC_SUPPORTED || SOC_LP_CORE_SUPPORTED", + "id": "component-config-ultra-low-power-ulp-co-processor", + "title": "Ultra Low Power (ULP) Co-processor", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": null, + "help": "If not set, assertions on float arguments will not be available.", + "id": "UNITY_ENABLE_FLOAT", + "name": "UNITY_ENABLE_FLOAT", + "range": null, + "title": "Support for float type", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "If not set, assertions on double arguments will not be available.", + "id": "UNITY_ENABLE_DOUBLE", + "name": "UNITY_ENABLE_DOUBLE", + "range": null, + "title": "Support for double type", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "If not set, assertions on 64-bit integer types will always fail.\nIf this feature is enabled, take care not to pass pointers (which are 32 bit)\nto UNITY_ASSERT_EQUAL, as that will cause pointer-to-int-cast warnings.", + "id": "UNITY_ENABLE_64BIT", + "name": "UNITY_ENABLE_64BIT", + "range": null, + "title": "Support for 64-bit integer types", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "If set, Unity will colorize test results using console escape sequences.", + "id": "UNITY_ENABLE_COLOR", + "name": "UNITY_ENABLE_COLOR", + "range": null, + "title": "Colorize test output", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "If set, then the following features will be available:\n\n- TEST_CASE macro which performs automatic registration of test functions\n- Functions to run registered test functions: unity_run_all_tests,\n unity_run_tests_with_filter, unity_run_single_test_by_name.\n- Interactive menu which lists test cases and allows choosing the tests to\n be run, available via unity_run_menu function.\n\nDisable if a different test registration mechanism is used.", + "id": "UNITY_ENABLE_IDF_TEST_RUNNER", + "name": "UNITY_ENABLE_IDF_TEST_RUNNER", + "range": null, + "title": "Include ESP-IDF test registration/running helpers", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "If set, unity_fixture.h header file and associated source files are part of\nthe build. These provide an optional set of macros and functions to\nimplement test groups.", + "id": "UNITY_ENABLE_FIXTURE", + "name": "UNITY_ENABLE_FIXTURE", + "range": null, + "title": "Include Unity test fixture", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "If set, the unity framework will print the backtrace information before\njumping back to the test menu. The jumping is usually occurs in assert\nfunctions such as TEST_ASSERT, TEST_FAIL etc.", + "id": "UNITY_ENABLE_BACKTRACE_ON_FAIL", + "name": "UNITY_ENABLE_BACKTRACE_ON_FAIL", + "range": null, + "title": "Print a backtrace when a unit test fails", + "type": "bool" + } + ], + "depends_on": null, + "id": "component-config-unity-unit-testing-library", + "title": "Unity unit testing library", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": "SOC_USB_OTG_SUPPORTED", + "help": "Each USB device attached is allocated a dedicated buffer for its OUT/IN transfers to/from the device's\ncontrol endpoint. The maximum size of that buffer is determined by this option. The limited size of the\ntransfer buffer have the following implications:\n- The maximum length of control transfers is limited\n- Device's with configuration descriptors larger than this limit cannot be supported", + "id": "USB_HOST_CONTROL_TRANSFER_MAX_SIZE", + "name": "USB_HOST_CONTROL_TRANSFER_MAX_SIZE", + "range": null, + "title": "Largest size (in bytes) of transfers to/from default endpoints", + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "USB_HOST_HW_BUFFER_BIAS_BALANCED", + "name": "USB_HOST_HW_BUFFER_BIAS_BALANCED", + "range": null, + "title": "Balanced", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "USB_HOST_HW_BUFFER_BIAS_IN", + "name": "USB_HOST_HW_BUFFER_BIAS_IN", + "range": null, + "title": "Bias IN", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "USB_HOST_HW_BUFFER_BIAS_PERIODIC_OUT", + "name": "USB_HOST_HW_BUFFER_BIAS_PERIODIC_OUT", + "range": null, + "title": "Periodic OUT", + "type": "bool" + } + ], + "depends_on": "SOC_USB_OTG_SUPPORTED", + "help": "The underlying hardware has size adjustable FIFOs to cache USB packets on reception (IN) or for\ntransmission (OUT). The size of these FIFOs will affect the largest MPS (maximum packet size) and the\nmaximum number of packets that can be cached at any one time. The hardware contains the following\nFIFOS: RX (for all IN packets), Non-periodic TX (for Bulk and Control OUT packets), and Periodic TX\n(for Interrupt and Isochronous OUT packets). This configuration option allows biasing the FIFO sizes\ntowards a particular use case, which may be necessary for devices that have endpoints with large MPS.\nThe MPS limits for each biasing are listed below:\n\nBalanced:\n- IN (all transfer types), 408 bytes\n- OUT non-periodic (Bulk/Control), 192 bytes (i.e., 3 x 64 byte packets)\n- OUT periodic (Interrupt/Isochronous), 192 bytes\n\nBias IN:\n- IN (all transfer types), 600 bytes\n- OUT non-periodic (Bulk/Control), 64 bytes (i.e., 1 x 64 byte packets)\n- OUT periodic (Interrupt/Isochronous), 128 bytes\n\nBias Periodic OUT:\n- IN (all transfer types), 128 bytes\n- OUT non-periodic (Bulk/Control), 64 bytes (i.e., 1 x 64 byte packets)\n- OUT periodic (Interrupt/Isochronous), 600 bytes", + "id": "component-config-usb-otg-hardware-fifo-size-biasing", + "name": "USB_HOST_HW_BUFFER_BIAS", + "title": "Hardware FIFO size biasing", + "type": "choice" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "SOC_USB_OTG_SUPPORTED", + "help": "On connection of a USB device, the USB 2.0 specification requires\na \"debounce interval with a minimum duration of 100ms\" to allow the connection to stabilize\n(see USB 2.0 chapter 7.1.7.3 for more details).\nDuring the debounce interval, no new connection/disconnection events are registered.\n\nThe default value is set to 250 ms to be safe.", + "id": "USB_HOST_DEBOUNCE_DELAY_MS", + "name": "USB_HOST_DEBOUNCE_DELAY_MS", + "range": null, + "title": "Debounce delay in ms", + "type": "int" + }, + { + "children": [], + "depends_on": "SOC_USB_OTG_SUPPORTED", + "help": "The reset signaling can be generated on any Hub or Host Controller port by request from\nthe USB System Software. The USB 2.0 specification requires that \"the reset signaling must\nbe driven for a minimum of 10ms\" (see USB 2.0 chapter 7.1.7.5 for more details).\nAfter the reset, the hub port will transition to the Enabled state (refer to Section 11.5).\n\nThe default value is set to 30 ms to be safe.", + "id": "USB_HOST_RESET_HOLD_MS", + "name": "USB_HOST_RESET_HOLD_MS", + "range": null, + "title": "Reset hold in ms", + "type": "int" + }, + { + "children": [], + "depends_on": "SOC_USB_OTG_SUPPORTED", + "help": "After a port stops driving the reset signal, the USB 2.0 specification requires that\nthe \"USB System Software guarantees a minimum of 10 ms for reset recovery\" before the\nattached device is expected to respond to data transfers (see USB 2.0 chapter 7.1.7.3 for\nmore details).\nThe device may ignore any data transfers during the recovery interval.\n\nThe default value is set to 30 ms to be safe.", + "id": "USB_HOST_RESET_RECOVERY_MS", + "name": "USB_HOST_RESET_RECOVERY_MS", + "range": null, + "title": "Reset recovery delay in ms", + "type": "int" + }, + { + "children": [], + "depends_on": "SOC_USB_OTG_SUPPORTED", + "help": "\"After successful completion of the Status stage, the device is allowed a SetAddress()\nrecovery interval of 2 ms. At the end of this interval, the device must be able to accept\nSetup packets addressed to the new address. Also, at the end of the recovery interval, the\ndevice must not respond to tokens sent to the old address (unless, of course, the old and new\naddress is the same).\" See USB 2.0 chapter 9.2.6.3 for more details.\n\nThe default value is set to 10 ms to be safe.", + "id": "USB_HOST_SET_ADDR_RECOVERY_MS", + "name": "USB_HOST_SET_ADDR_RECOVERY_MS", + "range": null, + "title": "SetAddress() recovery time in ms", + "type": "int" + } + ], + "depends_on": "SOC_USB_OTG_SUPPORTED", + "id": "component-config-usb-otg-hub-driver-configuration-root-port-configuration", + "title": "Root Port configuration", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": "USB_HOST_HUBS_SUPPORTED && SOC_USB_OTG_SUPPORTED", + "help": "Enables support for connecting multiple Hubs simultaneously.", + "id": "USB_HOST_HUB_MULTI_LEVEL", + "name": "USB_HOST_HUB_MULTI_LEVEL", + "range": null, + "title": "Support multiple Hubs", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "IDF_EXPERIMENTAL_FEATURES && USB_HOST_HUBS_SUPPORTED && SOC_USB_OTG_SUPPORTED", + "help": "Enables support of Low-speed devices, connected through the external Hub.", + "id": "USB_HOST_EXT_PORT_SUPPORT_LS", + "name": "USB_HOST_EXT_PORT_SUPPORT_LS", + "range": null, + "title": "Support LS", + "type": "bool" + }, + { + "children": [], + "depends_on": "IDF_EXPERIMENTAL_FEATURES && USB_HOST_HUBS_SUPPORTED && SOC_USB_OTG_SUPPORTED", + "help": "Amount of attempts to reset the device.\n\nThe default value is 1.", + "id": "USB_HOST_EXT_PORT_RESET_ATTEMPTS", + "name": "USB_HOST_EXT_PORT_RESET_ATTEMPTS", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": "USB_HOST_HUBS_SUPPORTED && SOC_USB_OTG_SUPPORTED", + "help": "After a port stops driving the reset signal, the USB 2.0 specification requires that\nthe \"USB System Software guarantees a minimum of 10 ms for reset recovery\" before the\nattached device is expected to respond to data transfers (see USB 2.0 chapter 7.1.7.3 for\nmore details).\nThe device may ignore any data transfers during the recovery interval.\n\nThe default value is set to 30 ms to be safe.", + "id": "USB_HOST_EXT_PORT_RESET_RECOVERY_DELAY_MS", + "name": "USB_HOST_EXT_PORT_RESET_RECOVERY_DELAY_MS", + "range": null, + "title": "Reset recovery delay in ms", + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "USB_HOST_EXT_PORT_CUSTOM_POWER_ON_DELAY_ENABLE && USB_HOST_HUBS_SUPPORTED && SOC_USB_OTG_SUPPORTED", + "help": "Custom value of delay from the time the power-on sequence begins on a port\nuntil power is good on that port.\nValue 0 is used for a hub with no power switches.\n\nThe default value is 100 ms.", + "id": "USB_HOST_EXT_PORT_CUSTOM_POWER_ON_DELAY_MS", + "name": "USB_HOST_EXT_PORT_CUSTOM_POWER_ON_DELAY_MS", + "range": null, + "title": "PwrOn2PwrGood delay in ms", + "type": "int" + } + ], + "depends_on": "USB_HOST_HUBS_SUPPORTED && SOC_USB_OTG_SUPPORTED", + "help": "Enables the possibility to configure custom time for the power-on sequence on a port\nuntil power is good on that port.\n\nWhen enabled, applies the custom PwrOn2PwrGood delay.\nWhen disabled, applies the PwrOn2PwrGood value from the Hub Descriptor.", + "id": "USB_HOST_EXT_PORT_CUSTOM_POWER_ON_DELAY_ENABLE", + "name": "USB_HOST_EXT_PORT_CUSTOM_POWER_ON_DELAY_ENABLE", + "range": null, + "title": "Custom bPwrOn2PwrGood value", + "type": "bool" + } + ], + "depends_on": "USB_HOST_HUBS_SUPPORTED && SOC_USB_OTG_SUPPORTED", + "id": "component-config-usb-otg-hub-driver-configuration-support-hubs-downstream-port-configuration", + "title": "Downstream Port configuration", + "type": "menu" + } + ], + "depends_on": "SOC_USB_OTG_SUPPORTED", + "help": "Enables support of external Hubs.", + "id": "USB_HOST_HUBS_SUPPORTED", + "name": "USB_HOST_HUBS_SUPPORTED", + "range": null, + "title": "Support Hubs", + "type": "bool" + } + ], + "depends_on": "SOC_USB_OTG_SUPPORTED", + "id": "component-config-usb-otg-hub-driver-configuration", + "title": "Hub Driver Configuration", + "type": "menu" + }, + { + "children": [], + "depends_on": "SOC_USB_OTG_SUPPORTED", + "help": "The enumeration filter callback is called before enumeration of each newly attached device.\nThis callback allows users to control whether a device should be enumerated, and what configuration\nnumber to use when enumerating a device.\n\nIf enabled, the enumeration filter callback can be set via 'usb_host_config_t' when calling\n'usb_host_install()'.", + "id": "USB_HOST_ENABLE_ENUM_FILTER_CALLBACK", + "name": "USB_HOST_ENABLE_ENUM_FILTER_CALLBACK", + "range": null, + "title": "Enable enumeration filter callback", + "type": "bool" + }, + { + "children": [], + "depends_on": "SOC_USB_OTG_SUPPORTED", + "help": null, + "id": "USB_OTG_SUPPORTED", + "name": "USB_OTG_SUPPORTED", + "range": null, + "title": null, + "type": "bool" + } + ], + "depends_on": "SOC_USB_OTG_SUPPORTED", + "id": "component-config-usb-otg", + "title": "USB-OTG", + "type": "menu" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "VFS_SUPPORT_IO", + "help": "If enabled, the following functions are provided by the VFS component.\n\nstat, link, unlink, rename, utime, access, truncate, rmdir, mkdir,\nopendir, closedir, readdir, readdir_r, seekdir, telldir, rewinddir\n\nFilesystem drivers can then be registered to handle these functions\nfor specific paths.\n\nDisabling this option can save memory when the support for these functions\nis not required.", + "id": "VFS_SUPPORT_DIR", + "name": "VFS_SUPPORT_DIR", + "range": null, + "title": "Provide directory related functions", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "VFS_SUPPORT_SELECT", + "help": "Select() related functions might produce an inconveniently lot of\ndebug outputs when one sets the default log level to DEBUG or higher.\nIt is possible to suppress these debug outputs by enabling this\noption.", + "id": "VFS_SUPPRESS_SELECT_DEBUG_OUTPUT", + "name": "VFS_SUPPRESS_SELECT_DEBUG_OUTPUT", + "range": null, + "title": "Suppress select() related debug outputs", + "type": "bool" + }, + { + "children": [], + "depends_on": "VFS_SUPPORT_SELECT", + "help": "If enabled, VFS driver select() callback function will be placed in IRAM.", + "id": "VFS_SELECT_IN_RAM", + "name": "VFS_SELECT_IN_RAM", + "range": null, + "title": "Make VFS driver select() callbacks IRAM-safe", + "type": "bool" + } + ], + "depends_on": "VFS_SUPPORT_IO && !LWIP_USE_ONLY_LWIP_SELECT", + "help": "If enabled, select function is provided by the VFS component, and can be used\non peripheral file descriptors (such as UART) and sockets at the same time.\n\nIf disabled, the default select implementation will be provided by LWIP for\nsockets only.\n\nDisabling this option can reduce code size if support for \"select\" on UART file\ndescriptors is not required.", + "id": "VFS_SUPPORT_SELECT", + "name": "VFS_SUPPORT_SELECT", + "range": null, + "title": "Provide select function", + "type": "bool" + }, + { + "children": [], + "depends_on": "VFS_SUPPORT_IO", + "help": "Disabling this option can save memory when the support for termios.h is not required.", + "id": "VFS_SUPPORT_TERMIOS", + "name": "VFS_SUPPORT_TERMIOS", + "range": null, + "title": "Provide termios.h functions", + "type": "bool" + }, + { + "children": [], + "depends_on": "VFS_SUPPORT_IO", + "help": "Define maximum number of virtual filesystems that can be registered.", + "id": "VFS_MAX_COUNT", + "name": "VFS_MAX_COUNT", + "range": [ + 1, + 20 + ], + "title": "Maximum Number of Virtual Filesystems", + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "VFS_SUPPORT_IO", + "help": "Define maximum number of host filesystem mount points.", + "id": "VFS_SEMIHOSTFS_MAX_MOUNT_POINTS", + "name": "VFS_SEMIHOSTFS_MAX_MOUNT_POINTS", + "range": null, + "title": "Host FS: Maximum number of the host filesystem mount points", + "type": "int" + } + ], + "depends_on": "VFS_SUPPORT_IO", + "id": "component-config-virtual-file-system-provide-basic-i-o-functions-host-file-system-i-o-semihosting-", + "title": "Host File System I/O (Semihosting)", + "type": "menu" + }, + { + "children": [], + "depends_on": "VFS_SUPPORT_IO", + "help": "If enabled, /dev/null VFS will be automatically initialized at startup.", + "id": "VFS_INITIALIZE_DEV_NULL", + "name": "VFS_INITIALIZE_DEV_NULL", + "range": null, + "title": "Initialize /dev/null VFS", + "type": "bool" + } + ], + "depends_on": null, + "help": "If enabled, the following functions are provided by the VFS component.\n\nopen, close, read, write, pread, pwrite, lseek, fstat, fsync, ioctl, fcntl\n\nFilesystem drivers can then be registered to handle these functions\nfor specific paths.\n\nDisabling this option can save memory when the support for these functions\nis not required.\n\nNote that the following functions can still be used with socket file descriptors\nwhen this option is disabled:\n\nclose, read, write, ioctl, fcntl.", + "id": "VFS_SUPPORT_IO", + "name": "VFS_SUPPORT_IO", + "range": null, + "title": "Provide basic I/O functions", + "type": "bool" + } + ], + "depends_on": null, + "id": "component-config-virtual-file-system", + "title": "Virtual file system", + "type": "menu" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "WL_SECTOR_SIZE_512", + "name": "WL_SECTOR_SIZE_512", + "range": null, + "title": "512", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "WL_SECTOR_SIZE_4096", + "name": "WL_SECTOR_SIZE_4096", + "range": null, + "title": "4096", + "type": "bool" + } + ], + "depends_on": null, + "help": "Sector size used by wear levelling library.\nYou can set default sector size or size that will\nfit to the flash device sector size.\n\nWith sector size set to 4096 bytes, wear levelling library is more\nefficient. However if FAT filesystem is used on top of wear levelling\nlibrary, it will need more temporary storage: 4096 bytes for each\nmounted filesystem and 4096 bytes for each opened file.\n\nWith sector size set to 512 bytes, wear levelling library will perform\nmore operations with flash memory, but less RAM will be used by FAT\nfilesystem library (512 bytes for the filesystem and 512 bytes for each\nfile opened).", + "id": "component-config-wear-levelling-wear-levelling-library-sector-size", + "name": "WL_SECTOR_SIZE", + "title": "Wear Levelling library sector size", + "type": "choice" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "WL_SECTOR_SIZE", + "name": "WL_SECTOR_SIZE", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "WL_SECTOR_MODE_PERF", + "name": "WL_SECTOR_MODE_PERF", + "range": null, + "title": "Performance", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "WL_SECTOR_MODE_SAFE", + "name": "WL_SECTOR_MODE_SAFE", + "range": null, + "title": "Safety", + "type": "bool" + } + ], + "depends_on": "WL_SECTOR_SIZE_512", + "help": "Specify the mode to store data into flash:\n\n- In Performance mode a data will be stored to the RAM and then\n stored back to the flash. Compared to the Safety mode, this operation is\n faster, but if power will be lost when erase sector operation is in\n progress, then the data from complete flash device sector will be lost.\n\n- In Safety mode data from complete flash device sector will be read from\n flash, modified, and then stored back to flash.\n Compared to the Performance mode, this operation is slower, but if\n power is lost during erase sector operation, then the data from full\n flash device sector will not be lost.", + "id": "component-config-wear-levelling-sector-store-mode", + "name": "WL_SECTOR_MODE", + "title": "Sector store mode", + "type": "choice" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "WL_SECTOR_MODE", + "name": "WL_SECTOR_MODE", + "range": null, + "title": null, + "type": "int" + } + ], + "depends_on": null, + "id": "component-config-wear-levelling", + "title": "Wear Levelling", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": null, + "help": "This sets the maximum number of entries of Wi-Fi scan results that will be kept by the provisioning manager", + "id": "WIFI_PROV_SCAN_MAX_ENTRIES", + "name": "WIFI_PROV_SCAN_MAX_ENTRIES", + "range": [ + 1, + 255 + ], + "title": "Max Wi-Fi Scan Result Entries", + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": "Time (in seconds) after which the Wi-Fi provisioning manager will auto-stop after connecting to\na Wi-Fi network successfully.", + "id": "WIFI_PROV_AUTOSTOP_TIMEOUT", + "name": "WIFI_PROV_AUTOSTOP_TIMEOUT", + "range": [ + 5, + 600 + ], + "title": "Provisioning auto-stop timeout", + "type": "int" + }, + { + "children": [], + "depends_on": "BT_ENABLED", + "help": "This option is applicable only when provisioning transport is BLE.", + "id": "WIFI_PROV_BLE_BONDING", + "name": "WIFI_PROV_BLE_BONDING", + "range": null, + "title": "Enable BLE bonding", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLED", + "help": "Used to enable Secure connection support when provisioning transport is BLE.", + "id": "WIFI_PROV_BLE_SEC_CONN", + "name": "WIFI_PROV_BLE_SEC_CONN", + "range": null, + "title": "Enable BLE Secure connection flag", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_ENABLED", + "help": "Used to enforce link encryption when attempting to read / write characteristic", + "id": "WIFI_PROV_BLE_FORCE_ENCRYPTION", + "name": "WIFI_PROV_BLE_FORCE_ENCRYPTION", + "range": null, + "title": "Force Link Encryption during characteristic Read / Write", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_ENABLED", + "help": "Used to enable support Notification in BLE descriptors of prov* characteristics", + "id": "WIFI_PROV_BLE_NOTIFY", + "name": "WIFI_PROV_BLE_NOTIFY", + "range": null, + "title": "Add support for Notification for provisioning BLE descriptors", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "WIFI_PROV_KEEP_BLE_ON_AFTER_PROV", + "help": null, + "id": "WIFI_PROV_DISCONNECT_AFTER_PROV", + "name": "WIFI_PROV_DISCONNECT_AFTER_PROV", + "range": null, + "title": "Terminate connection after provisioning is done", + "type": "bool" + } + ], + "depends_on": "BT_ENABLED", + "help": null, + "id": "WIFI_PROV_KEEP_BLE_ON_AFTER_PROV", + "name": "WIFI_PROV_KEEP_BLE_ON_AFTER_PROV", + "range": null, + "title": "Keep BT on after provisioning is done", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": "Scan will end after scanning the entire channel. This option is useful in Mesh WiFi Systems.", + "id": "WIFI_PROV_STA_ALL_CHANNEL_SCAN", + "name": "WIFI_PROV_STA_ALL_CHANNEL_SCAN", + "range": null, + "title": "All Channel Scan", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": "Scan will end after an AP matching with the SSID has been detected.", + "id": "WIFI_PROV_STA_FAST_SCAN", + "name": "WIFI_PROV_STA_FAST_SCAN", + "range": null, + "title": "Fast Scan", + "type": "bool" + } + ], + "depends_on": null, + "help": null, + "id": "component-config-wi-fi-provisioning-manager-wifi-provisioning-scan-method", + "name": "WIFI_PROV_STA_SCAN_METHOD", + "title": "Wifi Provisioning Scan Method", + "type": "choice" + } + ], + "depends_on": null, + "id": "component-config-wi-fi-provisioning-manager", + "title": "Wi-Fi Provisioning Manager", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": null, + "help": "By default only error logs are enabled.\nThis config option enables the capture of all log types (errors/warnings/events).", + "id": "APP_INSIGHTS_ENABLE_LOG_TYPE_ALL", + "name": "APP_INSIGHTS_ENABLE_LOG_TYPE_ALL", + "range": null, + "title": "Enable all diagnostics log type", + "type": "bool" + } + ], + "depends_on": null, + "id": "component-config-app-insights", + "title": "App Insights", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": null, + "help": null, + "id": "IO_GLITCH_FILTER_TIME_MS", + "name": "IO_GLITCH_FILTER_TIME_MS", + "range": [ + 10, + 100 + ], + "title": "IO glitch filter timer ms (10~100)", + "type": "int" + } + ], + "depends_on": null, + "id": "component-config-gpio-button", + "title": "GPIO Button", + "type": "menu" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "WS2812_LED_ENABLE", + "help": "Set the WS2812 RGB LED GPIO.", + "id": "WS2812_LED_GPIO", + "name": "WS2812_LED_GPIO", + "range": null, + "title": "WS2812 LED GPIO", + "type": "int" + } + ], + "depends_on": null, + "help": "Disable the WS2812 RGB LED.", + "id": "WS2812_LED_ENABLE", + "name": "WS2812_LED_ENABLE", + "range": null, + "title": "Enable RGB LED", + "type": "bool" + } + ], + "depends_on": null, + "id": "component-config-ws2812-rgb-led", + "title": "WS2812 RGB LED", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": null, + "help": "Select this option to enable MD5 hashsum check after flashing.", + "id": "SERIAL_FLASHER_MD5_ENABLED", + "name": "SERIAL_FLASHER_MD5_ENABLED", + "range": null, + "title": "Enable MD5 check", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "SERIAL_FLASHER_INTERFACE_UART", + "name": "SERIAL_FLASHER_INTERFACE_UART", + "range": null, + "title": "UART", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "SERIAL_FLASHER_INTERFACE_SPI", + "name": "SERIAL_FLASHER_INTERFACE_SPI", + "range": null, + "title": "SPI (Only supports downloading to RAM)", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "SERIAL_FLASHER_INTERFACE_USB", + "name": "SERIAL_FLASHER_INTERFACE_USB", + "range": null, + "title": "USB", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "SERIAL_FLASHER_INTERFACE_SDIO", + "name": "SERIAL_FLASHER_INTERFACE_SDIO", + "range": null, + "title": "SDIO (Experimental, Only supports downloading to RAM)", + "type": "bool" + } + ], + "depends_on": null, + "help": "esp-serial-flasher can work with UART and SPI interfaces.", + "id": "component-config-esp-serial-flasher-hardware-interface-to-use-for-firmware-download", + "name": "SERIAL_FLASHER_INTERFACE", + "title": "Hardware interface to use for firmware download", + "type": "choice" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SERIAL_FLASHER_RESET_HOLD_TIME_MS", + "name": "SERIAL_FLASHER_RESET_HOLD_TIME_MS", + "range": null, + "title": "Time for which the reset pin is asserted when doing a hard reset", + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SERIAL_FLASHER_BOOT_HOLD_TIME_MS", + "name": "SERIAL_FLASHER_BOOT_HOLD_TIME_MS", + "range": null, + "title": "Time for which the boot pin is asserted when doing a hard reset", + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SERIAL_FLASHER_DEBUG_TRACE", + "name": "SERIAL_FLASHER_DEBUG_TRACE", + "range": null, + "title": "Enable debug tracing output (only transfer data tracing is supported at the time)", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "SERIAL_FLASHER_WRITE_BLOCK_RETRIES", + "name": "SERIAL_FLASHER_WRITE_BLOCK_RETRIES", + "range": null, + "title": "Number of retries when writing blocks either to target flash or RAM", + "type": "int" + }, + { + "children": [], + "depends_on": "SERIAL_FLASHER_INTERFACE_UART", + "help": "Enable this option if there is an inverting connection between\nthe output of the serial-flasher and the reset pin of the ESP chip.", + "id": "SERIAL_FLASHER_RESET_INVERT", + "name": "SERIAL_FLASHER_RESET_INVERT", + "range": null, + "title": "Invert reset signal", + "type": "bool" + }, + { + "children": [], + "depends_on": "SERIAL_FLASHER_INTERFACE_UART", + "help": "Enable this option if there is an inverting connection between\nthe output of the serial-flasher and the boot pin of the ESP chip.", + "id": "SERIAL_FLASHER_BOOT_INVERT", + "name": "SERIAL_FLASHER_BOOT_INVERT", + "range": null, + "title": "Invert boot signal", + "type": "bool" + } + ], + "depends_on": null, + "id": "component-config-esp-serial-flasher", + "title": "ESP serial flasher", + "type": "menu" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "DIAG_DATA_STORE_RTC", + "name": "DIAG_DATA_STORE_RTC", + "range": null, + "title": "RTC memory", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": "Just a placeholder. This data store type is not supported as of now", + "id": "DIAG_DATA_STORE_FLASH", + "name": "DIAG_DATA_STORE_FLASH", + "range": null, + "title": "Flash", + "type": "bool" + } + ], + "depends_on": null, + "help": "This option configures the place to store diagnostics data: RTC memory or Flash.\n\nFlash store needs an additional patition table entry.\nNOTE: Diagnostics data partition must be encrypted if Flash Encryption is enabled.", + "id": "component-config-diagnostics-data-store-diagnostics-data-store-destination", + "name": "DIAG_DATA_STORE_RTC_OR_FLASH", + "title": "Diagnostics data store destination", + "type": "choice" + }, + { + "children": [], + "depends_on": null, + "help": "Enables debug prints for diagnostics data store", + "id": "DIAG_DATA_STORE_DBG_PRINTS", + "name": "DIAG_DATA_STORE_DBG_PRINTS", + "range": null, + "title": "Enable data store debug prints", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Data store has facility to post an event when buffer is filled to a configured level.\nThis option configures the reporting watermark for critical and non critical data.", + "id": "DIAG_DATA_STORE_REPORTING_WATERMARK_PERCENT", + "name": "DIAG_DATA_STORE_REPORTING_WATERMARK_PERCENT", + "range": [ + 50, + 90 + ], + "title": "Reporting watermark percentage", + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "DIAG_DATA_STORE_RTC", + "help": "RTC data store is divided into two parts to store critical and non-critical data.\nThis option configures the total size of data store.\nNOTE: On ESP32 devices, from esp-idf release v4.3 and onwards we can use all 8K RTC memory,\nso max range is specified as 7K. On releases before v4.3 we can only access maximum 4K RTC memory and\nRTC store uses few bytes for its operation so default for ESP32 is set to 3K.", + "id": "RTC_STORE_DATA_SIZE", + "name": "RTC_STORE_DATA_SIZE", + "range": [ + 512, + 7168 + ], + "title": "RTC store data size", + "type": "int" + }, + { + "children": [], + "depends_on": "DIAG_DATA_STORE_RTC", + "help": "This option configures the size of critical data buffer and remaining is used for\nnon critical data buffer.", + "id": "RTC_STORE_CRITICAL_DATA_SIZE", + "name": "RTC_STORE_CRITICAL_DATA_SIZE", + "range": [ + 512, + 6144 + ], + "title": "Maximum size of critical data store", + "type": "int" + } + ], + "depends_on": "DIAG_DATA_STORE_RTC", + "id": "component-config-diagnostics-data-store-rtc-store", + "title": "RTC Store", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": "DIAG_DATA_STORE_FLASH", + "help": "Diagnostics data is stored in this partition", + "id": "FLASH_STORE_PARTITION_LABEL", + "name": "FLASH_STORE_PARTITION_LABEL", + "range": null, + "title": "Diagnostics data partition name", + "type": "string" + } + ], + "depends_on": "DIAG_DATA_STORE_FLASH", + "id": "component-config-diagnostics-data-store-flash-store", + "title": "Flash Store", + "type": "menu" + } + ], + "depends_on": null, + "id": "component-config-diagnostics-data-store", + "title": "Diagnostics data store", + "type": "menu" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "DIAG_LOG_MSG_ARG_FORMAT_TLV", + "name": "DIAG_LOG_MSG_ARG_FORMAT_TLV", + "range": null, + "title": "Format arguments as TLV", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "DIAG_LOG_MSG_ARG_FORMAT_STRING", + "name": "DIAG_LOG_MSG_ARG_FORMAT_STRING", + "range": null, + "title": "Format arguments as string", + "type": "bool" + } + ], + "depends_on": null, + "help": "For error/warning/event logs, diagnostics module collects program counter, timestamp,\ntag, RO data pointer and log arguments. Log arguments are stored in statically allocated buffer.\nThis option configures how to format and store log arguments in buffer.\nLog arguments can be formatted as TLV or complete log string formatted using vsnprintf.\n\nIf \"TLV\" is selected, buffer contains arguments formatted as TLV.\nType - 1 byte for the type of argument, please check esp_diag_arg_type_t.\nLength - 1 byte for the size of argument, size is calculated using sizeof operator.\nValue - Size bytes for the value.\n\nIf \"STRING\" is selected, buffer contains the entire string formatted using vsnprintf.", + "id": "component-config-diagnostics-diagnostics-log-argument-format", + "name": "DIAG_LOG_MSG_ARG_FORMAT", + "title": "Diagnostics log argument format", + "type": "choice" + }, + { + "children": [], + "depends_on": null, + "help": "Log arguments are stored in a static allocated buffer.\nThis option configures the maximum size of buffer for storing log arguments.", + "id": "DIAG_LOG_MSG_ARG_MAX_SIZE", + "name": "DIAG_LOG_MSG_ARG_MAX_SIZE", + "range": [ + 32, + 255 + ], + "title": "Maximum size of diagnostics log argument buffer", + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": "Every Wi-Fi log printed on the console adds three diagnostics logs.\nFor some users, Wi-Fi logs may not be that useful.\nBy default, diagnostics drops Wi-Fi logs. Set this config option to \"n\" for recording Wi-Fi logs.", + "id": "DIAG_LOG_DROP_WIFI_LOGS", + "name": "DIAG_LOG_DROP_WIFI_LOGS", + "range": null, + "title": "Drop Wi-Fi logs", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "This option enables wrapping of esp_log_write and esp_log_writev APIs using `--wrap` gcc option.\nEnable this option when direct log access is required.\n\nNote: This option is automatically selected when ESP Insights is enabled.", + "id": "DIAG_ENABLE_WRAP_LOG_FUNCTIONS", + "name": "DIAG_ENABLE_WRAP_LOG_FUNCTIONS", + "range": null, + "title": "Enable wrapping of log functions", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "DIAG_ENABLE_METRICS", + "help": "This option configures the maximum number of metrics that can be registered.", + "id": "DIAG_METRICS_MAX_COUNT", + "name": "DIAG_METRICS_MAX_COUNT", + "range": null, + "title": "Maximum number of metrics", + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "DIAG_ENABLE_HEAP_METRICS", + "help": "This option configures the time interval in seconds at which heap metrics are collected.\nMinimum allowed value is 30 seconds and maximum is 24 hours (86400 seconds).", + "id": "DIAG_HEAP_POLLING_INTERVAL", + "name": "DIAG_HEAP_POLLING_INTERVAL", + "range": [ + 30, + 86400 + ], + "title": "Heap metrics polling interval in seconds", + "type": "int" + } + ], + "depends_on": "DIAG_ENABLE_METRICS", + "help": "Enables the heap memory metrics. This collects free memory, largest free block,\nand minimum free memory for heaps in internal as well as external memory.", + "id": "DIAG_ENABLE_HEAP_METRICS", + "name": "DIAG_ENABLE_HEAP_METRICS", + "range": null, + "title": "Enable Heap Metrics", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "DIAG_ENABLE_WIFI_METRICS", + "help": "This option configures the time interval in seconds at which Wi-Fi metrics are collected.\nMinimum allowed value is 30 seconds and maximum is 24 hours (86400 seconds).", + "id": "DIAG_WIFI_POLLING_INTERVAL", + "name": "DIAG_WIFI_POLLING_INTERVAL", + "range": [ + 30, + 86400 + ], + "title": "Wi-Fi metrics polling interval in seconds", + "type": "int" + } + ], + "depends_on": "DIAG_ENABLE_METRICS", + "help": "Enables Wi-Fi metrics and collects Wi-Fi RSSI and minumum ever Wi-Fi RSSI.", + "id": "DIAG_ENABLE_WIFI_METRICS", + "name": "DIAG_ENABLE_WIFI_METRICS", + "range": null, + "title": "Enable Wi-Fi Metrics", + "type": "bool" + } + ], + "depends_on": null, + "help": "Diagnostics module supports recording and reporting metrics to cloud.\nThis option enables the diagnostics metrics and related functionality.", + "id": "DIAG_ENABLE_METRICS", + "name": "DIAG_ENABLE_METRICS", + "range": null, + "title": "Enable diagnostics metrics", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "DIAG_ENABLE_VARIABLES", + "help": "This option configures the maximum number of variables that can be registered.", + "id": "DIAG_VARIABLES_MAX_COUNT", + "name": "DIAG_VARIABLES_MAX_COUNT", + "range": null, + "title": "Maximum number of variables", + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "DIAG_ENABLE_NETWORK_VARIABLES", + "help": "Enable more advanced network variables", + "id": "DIAG_MORE_NETWORK_VARS", + "name": "DIAG_MORE_NETWORK_VARS", + "range": null, + "title": "Enable More Advanced Network variables", + "type": "bool" + } + ], + "depends_on": "DIAG_ENABLE_VARIABLES", + "help": "Enables the Wi-Fi and IP address variables. Below variables are collected.\nFor Wi-Fi: SSID, BSSID, channel, auth mode, connection status, disconnection reason.\nFor IP: IPv4 address, netmask, and gateway of the device.", + "id": "DIAG_ENABLE_NETWORK_VARIABLES", + "name": "DIAG_ENABLE_NETWORK_VARIABLES", + "range": null, + "title": "Enable Network variables", + "type": "bool" + } + ], + "depends_on": null, + "help": "Variables are similar to metrics but they represent entities where their current value\nis much more important than over a period of time.\nThis option enables the diagnostics variables and related functionality", + "id": "DIAG_ENABLE_VARIABLES", + "name": "DIAG_ENABLE_VARIABLES", + "range": null, + "title": "Enable diagnostics variables", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Diagnostics component wraps the esp_log_write and esp_log_writev APIs using `--wrap` gcc option.\nThere can be scenario where another component also wants to wrap the logging functions.\nIn that case, enable this option and use the data ingestion APIs esp_diag_log_write and esp_diag_log_writev.", + "id": "DIAG_USE_EXTERNAL_LOG_WRAP", + "name": "DIAG_USE_EXTERNAL_LOG_WRAP", + "range": null, + "title": "Use external log wrapper", + "type": "bool" + } + ], + "depends_on": null, + "id": "component-config-diagnostics", + "title": "Diagnostics", + "type": "menu" + }, + { + "children": [ + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "ESP_INSIGHTS_DEBUG_ENABLED", + "help": "Print pretty format json data for cbor messages\nIf this option is not enabled, hexdump will be presented instead of json data", + "id": "ESP_INSIGHTS_DEBUG_PRINT_JSON", + "name": "ESP_INSIGHTS_DEBUG_PRINT_JSON", + "range": null, + "title": "Dump CBOR decoded data instead of hexdump", + "type": "bool" + } + ], + "depends_on": "ESP_INSIGHTS_ENABLED", + "help": null, + "id": "ESP_INSIGHTS_DEBUG_ENABLED", + "name": "ESP_INSIGHTS_DEBUG_ENABLED", + "range": null, + "title": "Enable Insights debug prints", + "type": "bool" + } + ], + "depends_on": null, + "help": "Enable ESP Insights functionality.\n\nThis automatically selects log wrapping (DIAG_ENABLE_WRAP_LOG_FUNCTIONS) which is\nrequired for ESP Insights to capture log messages.", + "id": "ESP_INSIGHTS_ENABLED", + "name": "ESP_INSIGHTS_ENABLED", + "range": null, + "title": "Enable ESP Insights", + "type": "bool" + }, + { + "children": [], + "depends_on": "(ESP_COREDUMP_ENABLE_TO_FLASH && ESP_COREDUMP_DATA_FORMAT_ELF) || (ESP32_ENABLE_COREDUMP_TO_FLASH && ESP32_COREDUMP_DATA_FORMAT_ELF)", + "help": "This option enables core dump summary functionality in insights.\nIn case of crash, insights sends the core dump summary to cloud on next boot.\nOnce the core dump summary is sent to cloud, it is erased from flash partition of the device.", + "id": "ESP_INSIGHTS_COREDUMP_ENABLE", + "name": "ESP_INSIGHTS_COREDUMP_ENABLE", + "range": null, + "title": "Enable core dump summary support", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "ESP_INSIGHTS_TRANSPORT_MQTT", + "name": "ESP_INSIGHTS_TRANSPORT_MQTT", + "range": null, + "title": "MQTT", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "ESP_INSIGHTS_TRANSPORT_HTTPS", + "name": "ESP_INSIGHTS_TRANSPORT_HTTPS", + "range": null, + "title": "HTTPS", + "type": "bool" + } + ], + "depends_on": null, + "help": "By default insights can send data to cloud using MQTT and HTTPS transports.\nThis option configures the default insights transport.\nInsights transport can be overridden using esp_insights_transport_register API.", + "id": "component-config-esp-insights-insights-default-transport", + "name": "ESP_INSIGHTS_TRANSPORT", + "title": "Insights default transport", + "type": "choice" + }, + { + "children": [], + "depends_on": "ESP_INSIGHTS_ENABLED && ESP_INSIGHTS_TRANSPORT_MQTT", + "help": "Enabling this option adds control of certain insights options remotely.\nWhen enabled, the available configurations, should be shown on the dashboard\nand controllable from there.\nPlease note, the feature is only available with RainMaker MQTT nodes for now.", + "id": "ESP_INSIGHTS_CMD_RESP_ENABLED", + "name": "ESP_INSIGHTS_CMD_RESP_ENABLED", + "range": null, + "title": "Enable command response module", + "type": "bool" + }, + { + "children": [], + "depends_on": "ESP_INSIGHTS_TRANSPORT_HTTPS", + "help": null, + "id": "ESP_INSIGHTS_TRANSPORT_HTTPS_HOST", + "name": "ESP_INSIGHTS_TRANSPORT_HTTPS_HOST", + "range": null, + "title": "Insights https host", + "type": "string" + }, + { + "children": [], + "depends_on": null, + "help": "Minimum interval between two consecutive cloud posts.\nThere is a dynamic logic to decide the next timeout when the insights data will be reported.\nIt depends on whether the data was sent or not during the previous timeout.\nIf the data was sent, the next timeout is doubled and if not, it is halved.", + "id": "ESP_INSIGHTS_CLOUD_POST_MIN_INTERVAL_SEC", + "name": "ESP_INSIGHTS_CLOUD_POST_MIN_INTERVAL_SEC", + "range": null, + "title": "Insights cloud post min interval (sec)", + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": "Maximum interval between two consecutive cloud posts.\nThere is a dynamic logic to decide the next timeout when the insights data will be reported.\nIt depends on whether the data was sent or not during the previous timeout.\nIf the data was sent, the next timeout is doubled and if not, it is halved.", + "id": "ESP_INSIGHTS_CLOUD_POST_MAX_INTERVAL_SEC", + "name": "ESP_INSIGHTS_CLOUD_POST_MAX_INTERVAL_SEC", + "range": null, + "title": "Insights cloud post max interval (sec)", + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": "For users already using older metadata, this provides an option to keep using the same.\nThis is important as the new metadata version (1.1), is not backwad compatible.", + "id": "ESP_INSIGHTS_META_VERSION_10", + "name": "ESP_INSIGHTS_META_VERSION_10", + "range": null, + "title": "Use older metadata format (1.0)", + "type": "bool" + } + ], + "depends_on": null, + "id": "component-config-esp-insights", + "title": "ESP Insights", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": null, + "help": "If enabled, the device will store the RCP image in its firmware and\ncompare the stored image version with the running RCP image upon boot. The RCP\nwill be automatically updated upon version mismatch.", + "id": "AUTO_UPDATE_RCP", + "name": "AUTO_UPDATE_RCP", + "range": null, + "title": "Update RCP automatically", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "If enabled, an ota image will be generated during building.", + "id": "CREATE_OTA_IMAGE_WITH_RCP_FW", + "name": "CREATE_OTA_IMAGE_WITH_RCP_FW", + "range": null, + "title": "Create the OTA image with rcp for border router", + "type": "bool" + }, + { + "children": [], + "depends_on": "AUTO_UPDATE_RCP || CREATE_OTA_IMAGE_WITH_RCP_FW", + "help": "The source folder containing the RCP firmware.", + "id": "RCP_SRC_DIR", + "name": "RCP_SRC_DIR", + "range": null, + "title": "Source folder containing the RCP firmware", + "type": "string" + }, + { + "children": [], + "depends_on": "AUTO_UPDATE_RCP", + "help": "The name of RCP storage partition.", + "id": "RCP_PARTITION_NAME", + "name": "RCP_PARTITION_NAME", + "range": null, + "title": "Name of RCP storage partition", + "type": "string" + } + ], + "depends_on": null, + "id": "component-config-openthread-rcp-update", + "title": "OpenThread RCP Update", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": "!IDF_TARGET_ESP32 && !IDF_TARGET_ESP32C2", + "help": "Enable the DS peripheral support. Not supported on esp32 and esp32c2.", + "id": "ESP_SECURE_CERT_DS_PERIPHERAL", + "name": "ESP_SECURE_CERT_DS_PERIPHERAL", + "range": null, + "title": "Enable DS peripheral support", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "This option enables support for the legacy formats along with\nthe current format in the esp_secure_cert component.\nThe current format is\ncust_flash_tlv\nThe legacy formats are as follows:\ncust_flash\nnvs", + "id": "ESP_SECURE_CERT_SUPPORT_LEGACY_FORMATS", + "name": "ESP_SECURE_CERT_SUPPORT_LEGACY_FORMATS", + "range": null, + "title": "Enable support for legacy formats", + "type": "bool" + } + ], + "depends_on": null, + "id": "component-config-esp-secure-cert-manager", + "title": "ESP Secure Cert Manager", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": null, + "help": "You can access parent node of parsed json", + "id": "JSMN_PARENT_LINKS", + "name": "JSMN_PARENT_LINKS", + "range": null, + "title": "Enable parent links", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "In strict mode primitives are: numbers and booleans", + "id": "JSMN_STRICT", + "name": "JSMN_STRICT", + "range": null, + "title": "Enable strict mode", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Declar JSMN API as static (instead of extern)", + "id": "JSMN_STATIC", + "name": "JSMN_STATIC", + "range": null, + "title": "Declare JSMN API as static", + "type": "bool" + } + ], + "depends_on": null, + "id": "component-config-jsmn", + "title": "jsmn", + "type": "menu" + }, + { + "children": [ + { + "children": [], + "depends_on": null, + "help": "Number of network interfaces to be served by the mDNS library.\nLowering this number helps to reduce some static RAM usage.", + "id": "MDNS_MAX_INTERFACES", + "name": "MDNS_MAX_INTERFACES", + "range": [ + 1, + 9 + ], + "title": "Max number of interfaces", + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": "Services take up a certain amount of memory, and allowing fewer\nservices to be open at the same time conserves memory. Specify\nthe maximum amount of services here.", + "id": "MDNS_MAX_SERVICES", + "name": "MDNS_MAX_SERVICES", + "range": null, + "title": "Max number of services", + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": "Allows setting mDNS task priority. Please do not set the task priority\nhigher than priorities of system tasks. Compile time warning/error\nwould be emitted if the chosen task priority were too high.", + "id": "MDNS_TASK_PRIORITY", + "name": "MDNS_TASK_PRIORITY", + "range": [ + 1, + 255 + ], + "title": "mDNS task priority", + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": "Allows setting the length of mDNS action queue.", + "id": "MDNS_ACTION_QUEUE_LEN", + "name": "MDNS_ACTION_QUEUE_LEN", + "range": [ + 8, + 64 + ], + "title": "Maximum actions pending to the server", + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": "Allows setting mDNS task stacksize.", + "id": "MDNS_TASK_STACK_SIZE", + "name": "MDNS_TASK_STACK_SIZE", + "range": null, + "title": "mDNS task stack size", + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "MDNS_TASK_AFFINITY_NO_AFFINITY", + "name": "MDNS_TASK_AFFINITY_NO_AFFINITY", + "range": null, + "title": "No affinity", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "MDNS_TASK_AFFINITY_CPU0", + "name": "MDNS_TASK_AFFINITY_CPU0", + "range": null, + "title": "CPU0", + "type": "bool" + }, + { + "children": [], + "depends_on": "!FREERTOS_UNICORE && ", + "help": null, + "id": "MDNS_TASK_AFFINITY_CPU1", + "name": "MDNS_TASK_AFFINITY_CPU1", + "range": null, + "title": "CPU1", + "type": "bool" + } + ], + "depends_on": null, + "help": "Allows setting mDNS tasks affinity, i.e. whether the task is pinned to\nCPU0, pinned to CPU1, or allowed to run on any CPU.", + "id": "component-config-mdns-mdns-task-affinity", + "name": "MDNS_TASK_AFFINITY", + "title": "mDNS task affinity", + "type": "choice" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "MDNS_TASK_AFFINITY", + "name": "MDNS_TASK_AFFINITY", + "range": null, + "title": null, + "type": "hex" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "(SPIRAM_USE_CAPS_ALLOC || SPIRAM_USE_MALLOC) && ", + "help": "mDNS task creates on the SPIRAM.\nThis option requires FreeRTOS component to allow creating\ntasks on the external memory.\nPlease read the documentation about FREERTOS_TASK_CREATE_ALLOW_EXT_MEM", + "id": "MDNS_TASK_CREATE_FROM_SPIRAM", + "name": "MDNS_TASK_CREATE_FROM_SPIRAM", + "range": null, + "title": "mDNS task creates on the SPIRAM (READ HELP)", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "MDNS_TASK_CREATE_FROM_INTERNAL", + "name": "MDNS_TASK_CREATE_FROM_INTERNAL", + "range": null, + "title": "mDNS task creates on the internal RAM", + "type": "bool" + } + ], + "depends_on": null, + "help": null, + "id": "component-config-mdns-mdns-memory-configuration-select-mdns-task-create-on-which-type-of-memory", + "name": "MDNS_TASK_MEMORY_ALLOC_FROM", + "title": "Select mDNS task create on which type of memory", + "type": "choice" + }, + { + "children": [ + { + "children": [], + "depends_on": "(SPIRAM_USE_CAPS_ALLOC || SPIRAM_USE_MALLOC) && ", + "help": null, + "id": "MDNS_MEMORY_ALLOC_SPIRAM", + "name": "MDNS_MEMORY_ALLOC_SPIRAM", + "range": null, + "title": "Allocate mDNS memory from SPIRAM", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "MDNS_MEMORY_ALLOC_INTERNAL", + "name": "MDNS_MEMORY_ALLOC_INTERNAL", + "range": null, + "title": "Allocate mDNS memory from internal RAM", + "type": "bool" + } + ], + "depends_on": null, + "help": null, + "id": "component-config-mdns-mdns-memory-configuration-select-mdns-memory-allocation-type", + "name": "MDNS_MEMORY_ALLOC_FROM", + "title": "Select mDNS memory allocation type", + "type": "choice" + }, + { + "children": [], + "depends_on": null, + "help": "Enable to implement custom memory functions for mDNS library.\nThis option is useful when the application wants to use custom\nmemory allocation functions for mDNS library.", + "id": "MDNS_MEMORY_CUSTOM_IMPL", + "name": "MDNS_MEMORY_CUSTOM_IMPL", + "range": null, + "title": "Implement custom memory functions", + "type": "bool" + } + ], + "depends_on": null, + "id": "component-config-mdns-mdns-memory-configuration", + "title": "MDNS Memory Configuration", + "type": "menu" + }, + { + "children": [], + "depends_on": null, + "help": "Configures timeout for adding a new mDNS service. Adding a service\nfails if could not be completed within this time.", + "id": "MDNS_SERVICE_ADD_TIMEOUT_MS", + "name": "MDNS_SERVICE_ADD_TIMEOUT_MS", + "range": [ + 10, + 30000 + ], + "title": "mDNS adding service timeout (ms)", + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": "Configures period of mDNS timer, which periodically transmits packets\nand schedules mDNS searches.", + "id": "MDNS_TIMER_PERIOD_MS", + "name": "MDNS_TIMER_PERIOD_MS", + "range": [ + 10, + 10000 + ], + "title": "mDNS timer period (ms)", + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": "Enables optional mDNS networking implementation using BSD sockets\nin UDP multicast mode.\nThis option creates a new thread to serve receiving packets (TODO).\nThis option uses additional N sockets, where N is number of interfaces.", + "id": "MDNS_NETWORKING_SOCKET", + "name": "MDNS_NETWORKING_SOCKET", + "range": null, + "title": "Use BSD sockets for mDNS networking", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Enable only if the querier and the responder share the same IP address.\nThis usually happens in test mode, where we may run multiple instances of\nresponders/queriers on the same interface.", + "id": "MDNS_SKIP_SUPPRESSING_OWN_QUERIES", + "name": "MDNS_SKIP_SUPPRESSING_OWN_QUERIES", + "range": null, + "title": "Skip suppressing our own packets", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Enable for the library to log received and sent mDNS packets to stdout.", + "id": "MDNS_ENABLE_DEBUG_PRINTS", + "name": "MDNS_ENABLE_DEBUG_PRINTS", + "range": null, + "title": "Enable debug prints of mDNS packets", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Enable for the console cli to be available on the device.", + "id": "MDNS_ENABLE_CONSOLE_CLI", + "name": "MDNS_ENABLE_CONSOLE_CLI", + "range": null, + "title": "Enable Command Line Interface on device console", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Enables support for IPv4 reverse lookup. If enabled, the mDNS library\nresponse to PTR queries of \"A.B.C.D.in-addr.arpa\" type.", + "id": "MDNS_RESPOND_REVERSE_QUERIES", + "name": "MDNS_RESPOND_REVERSE_QUERIES", + "range": null, + "title": "Enable responding to IPv4 reverse queries", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Enables adding multiple service instances under the same service type.", + "id": "MDNS_MULTIPLE_INSTANCE", + "name": "MDNS_MULTIPLE_INSTANCE", + "range": null, + "title": "Multiple instances under the same service type", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": null, + "help": "Set up mDNS for the default WiFi station.\nDisable this option if you do not need mDNS on default WiFi STA.", + "id": "MDNS_PREDEF_NETIF_STA", + "name": "MDNS_PREDEF_NETIF_STA", + "range": null, + "title": "Use predefined interface for WiFi Station", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Set up mDNS for the default WiFi Access Point.\nDisable this option if you do not need mDNS on default WiFi AP.", + "id": "MDNS_PREDEF_NETIF_AP", + "name": "MDNS_PREDEF_NETIF_AP", + "range": null, + "title": "Use predefined interface for WiFi Access Point", + "type": "bool" + }, + { + "children": [], + "depends_on": "ETH_ENABLED", + "help": "Set up mDNS for the default Ethernet interface.\nDisable this option if you do not need mDNS on default Ethernet.", + "id": "MDNS_PREDEF_NETIF_ETH", + "name": "MDNS_PREDEF_NETIF_ETH", + "range": null, + "title": "Use predefined interface for Ethernet", + "type": "bool" + } + ], + "depends_on": null, + "id": "component-config-mdns-mdns-predefined-interfaces", + "title": "MDNS Predefined interfaces", + "type": "menu" + } + ], + "depends_on": null, + "id": "component-config-mdns", + "title": "mDNS", + "type": "menu" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "(ESP_WIFI_ENABLED || ESP_WIFI_REMOTE_ENABLED) && ", + "help": null, + "id": "NETWORK_PROV_NETWORK_TYPE_WIFI", + "name": "NETWORK_PROV_NETWORK_TYPE_WIFI", + "range": null, + "title": "Network Type - Wi-Fi", + "type": "bool" + }, + { + "children": [], + "depends_on": "OPENTHREAD_ENABLED && ", + "help": null, + "id": "NETWORK_PROV_NETWORK_TYPE_THREAD", + "name": "NETWORK_PROV_NETWORK_TYPE_THREAD", + "range": null, + "title": "Network Type - Thread", + "type": "bool" + } + ], + "depends_on": null, + "help": null, + "id": "component-config-network-provisioning-manager-network-type", + "name": "NETWORK_PROV_NETWORK_TYPE", + "title": "Network Type", + "type": "choice" + }, + { + "children": [], + "depends_on": null, + "help": "This sets the maximum number of entries of network scan results that will be kept by the\nprovisioning manager", + "id": "NETWORK_PROV_SCAN_MAX_ENTRIES", + "name": "NETWORK_PROV_SCAN_MAX_ENTRIES", + "range": [ + 1, + 255 + ], + "title": "Max Network Scan Result Entries", + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": "Time (in seconds) after which the network provisioning manager will auto-stop after connecting to\na network successfully.", + "id": "NETWORK_PROV_AUTOSTOP_TIMEOUT", + "name": "NETWORK_PROV_AUTOSTOP_TIMEOUT", + "range": [ + 5, + 600 + ], + "title": "Provisioning auto-stop timeout", + "type": "int" + }, + { + "children": [], + "depends_on": "BT_ENABLED", + "help": "This option is applicable only when provisioning transport is BLE. Used to enable BLE bonding process\nwhere the information from the pairing process will be stored on the devices.", + "id": "NETWORK_PROV_BLE_BONDING", + "name": "NETWORK_PROV_BLE_BONDING", + "range": null, + "title": "Enable BLE bonding", + "type": "bool" + }, + { + "children": [], + "depends_on": "BT_NIMBLE_ENABLED", + "help": "Used to enable Secure connection support when provisioning transport is BLE.", + "id": "NETWORK_PROV_BLE_SEC_CONN", + "name": "NETWORK_PROV_BLE_SEC_CONN", + "range": null, + "title": "Enable BLE Secure connection flag", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Used to enforce link encryption when attempting to read / write characteristic", + "id": "NETWORK_PROV_BLE_FORCE_ENCRYPTION", + "name": "NETWORK_PROV_BLE_FORCE_ENCRYPTION", + "range": null, + "title": "Force Link Encryption during characteristic Read / Write", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "NETWORK_PROV_KEEP_BLE_ON_AFTER_PROV", + "help": null, + "id": "NETWORK_PROV_DISCONNECT_AFTER_PROV", + "name": "NETWORK_PROV_DISCONNECT_AFTER_PROV", + "range": null, + "title": "Terminate connection after provisioning is done", + "type": "bool" + } + ], + "depends_on": "BT_ENABLED", + "help": null, + "id": "NETWORK_PROV_KEEP_BLE_ON_AFTER_PROV", + "name": "NETWORK_PROV_KEEP_BLE_ON_AFTER_PROV", + "range": null, + "title": "Keep BT on after provisioning is done", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": "Scan will end after scanning the entire channel. This option is useful in Mesh WiFi Systems.", + "id": "NETWORK_PROV_WIFI_STA_ALL_CHANNEL_SCAN", + "name": "NETWORK_PROV_WIFI_STA_ALL_CHANNEL_SCAN", + "range": null, + "title": "All Channel Scan", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": "Scan will end after an AP matching with the SSID has been detected.", + "id": "NETWORK_PROV_WIFI_STA_FAST_SCAN", + "name": "NETWORK_PROV_WIFI_STA_FAST_SCAN", + "range": null, + "title": "Fast Scan", + "type": "bool" + } + ], + "depends_on": "NETWORK_PROV_NETWORK_TYPE_WIFI", + "help": null, + "id": "component-config-network-provisioning-manager-wifi-provisioning-scan-method", + "name": "NETWORK_PROV_WIFI_STA_SCAN_METHOD", + "title": "Wifi Provisioning Scan Method", + "type": "choice" + } + ], + "depends_on": null, + "id": "component-config-network-provisioning-manager", + "title": "Network Provisioning Manager", + "type": "menu" + }, + { + "children": [ + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "ESP_RMAKER_LIB_ESP_MQTT", + "name": "ESP_RMAKER_LIB_ESP_MQTT", + "range": null, + "title": "ESP-MQTT", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "ESP_RMAKER_LIB_AWS_IOT", + "name": "ESP_RMAKER_LIB_AWS_IOT", + "range": null, + "title": "AWS-IOT", + "type": "bool" + } + ], + "depends_on": null, + "help": "MQTT Library to be used", + "id": "component-config-esp-rainmaker-common-mqtt-library", + "name": "ESP_RMAKER_MQTT_GLUE_LIB", + "title": "MQTT Library", + "type": "choice" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "ESP_RMAKER_MQTT_GLUE_LIB", + "name": "ESP_RMAKER_MQTT_GLUE_LIB", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "", + "help": null, + "id": "ESP_RMAKER_MQTT_PORT_443", + "name": "ESP_RMAKER_MQTT_PORT_443", + "range": null, + "title": "443", + "type": "bool" + }, + { + "children": [], + "depends_on": "", + "help": null, + "id": "ESP_RMAKER_MQTT_PORT_8883", + "name": "ESP_RMAKER_MQTT_PORT_8883", + "range": null, + "title": "8883", + "type": "bool" + } + ], + "depends_on": null, + "help": "ESP RainMaker MQTT Broker can be connected to either on Port 8883 or port 443.\nPort 443 is recommended as it is generally not blocked by any firewalls,\nsince it is standard HTTPS port.", + "id": "component-config-esp-rainmaker-common-mqtt-port", + "name": "ESP_RMAKER_MQTT_PORT", + "title": "MQTT Port", + "type": "choice" + }, + { + "children": [], + "depends_on": null, + "help": null, + "id": "ESP_RMAKER_MQTT_PORT", + "name": "ESP_RMAKER_MQTT_PORT", + "range": null, + "title": null, + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": "Use persistent MQTT sessions. This improves reliability as QOS1 messages missed\nout due to some network issue are received after the MQTT reconnects. The broker\ncaches messages for a period of upto 1 hour. However, a side-effect of this is that\nmessages can be received at unexpected time. Enable this option only if it suits\nyour use case. Please read MQTT specs to understand more about persistent sessions\nand the cleanSession flag.", + "id": "ESP_RMAKER_MQTT_PERSISTENT_SESSION", + "name": "ESP_RMAKER_MQTT_PERSISTENT_SESSION", + "range": null, + "title": "Use Persisent MQTT sessions", + "type": "bool" + }, + { + "children": [ + { + "children": [], + "depends_on": "ESP_RMAKER_MQTT_SEND_USERNAME", + "help": "Approved AWS product name. Please get in touch with your Espressif/AWS representative for more info.", + "id": "ESP_RMAKER_MQTT_PRODUCT_NAME", + "name": "ESP_RMAKER_MQTT_PRODUCT_NAME", + "range": null, + "title": "Product Name", + "type": "string" + }, + { + "children": [], + "depends_on": "ESP_RMAKER_MQTT_SEND_USERNAME", + "help": "Approved AWS product version. Please get in touch with your Espressif/AWS representative for more info.", + "id": "ESP_RMAKER_MQTT_PRODUCT_VERSION", + "name": "ESP_RMAKER_MQTT_PRODUCT_VERSION", + "range": null, + "title": "Product Version", + "type": "string" + }, + { + "children": [], + "depends_on": "ESP_RMAKER_MQTT_SEND_USERNAME", + "help": "Product SKU. Please get in touch with your Espressif/AWS representative for more info.", + "id": "ESP_RMAKER_MQTT_PRODUCT_SKU", + "name": "ESP_RMAKER_MQTT_PRODUCT_SKU", + "range": null, + "title": "Product SKU", + "type": "string" + } + ], + "depends_on": null, + "help": "Send a Username during MQTT Connect. This is generally required only for tracking\nthe MQTT client types, platform, SDK, etc. in AWS.", + "id": "ESP_RMAKER_MQTT_SEND_USERNAME", + "name": "ESP_RMAKER_MQTT_SEND_USERNAME", + "range": null, + "title": "Send MQTT Username", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Use Certificate Bundle for server authentication. Enabling this is recommended to safeguard\nagainst any changes in the server certificates in future. This has an impact on the binary\nsize as well as heap requirement.", + "id": "ESP_RMAKER_MQTT_USE_CERT_BUNDLE", + "name": "ESP_RMAKER_MQTT_USE_CERT_BUNDLE", + "range": null, + "title": "Use Certificate Bundle", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "This value controls the maximum number of topics that the device can subscribe to.", + "id": "ESP_RMAKER_MAX_MQTT_SUBSCRIPTIONS", + "name": "ESP_RMAKER_MAX_MQTT_SUBSCRIPTIONS", + "range": null, + "title": "Maximum number of MQTT Subscriptions", + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": "MQTT Keep Alive Interval. Note that it can take upto 1.5x of keep alive interval for a device\nto be reported by offline by the MQTT Broker. Change this only if required.", + "id": "ESP_RMAKER_MQTT_KEEP_ALIVE_INTERVAL", + "name": "ESP_RMAKER_MQTT_KEEP_ALIVE_INTERVAL", + "range": [ + 30, + 1200 + ], + "title": "MQTT Keep Alive Internal", + "type": "int" + }, + { + "children": [ + { + "children": [], + "depends_on": "(ESP_WIFI_ENABLED || ESP32_WIFI_ENABLED || ESP_WIFI_REMOTE_ENABLED) && ", + "help": null, + "id": "ESP_RMAKER_NETWORK_OVER_WIFI", + "name": "ESP_RMAKER_NETWORK_OVER_WIFI", + "range": null, + "title": "ESP RainMaker over Wi-Fi", + "type": "bool" + }, + { + "children": [], + "depends_on": "OPENTHREAD_ENABLED && ", + "help": null, + "id": "ESP_RMAKER_NETWORK_OVER_THREAD", + "name": "ESP_RMAKER_NETWORK_OVER_THREAD", + "range": null, + "title": "ESP RainMaker over Thread", + "type": "bool" + } + ], + "depends_on": null, + "help": "Network protocol type over which the ESP RainMaker will run.", + "id": "component-config-esp-rainmaker-common-esp-rainmaker-network-type", + "name": "ESP_RMAKER_NETWORK_PROTOCOL_TYPE", + "title": "ESP RainMaker Network Type", + "type": "choice" + }, + { + "children": [], + "depends_on": null, + "help": "Stack size for the ESP RainMaker Work Queue Task.", + "id": "ESP_RMAKER_WORK_QUEUE_TASK_STACK", + "name": "ESP_RMAKER_WORK_QUEUE_TASK_STACK", + "range": null, + "title": "ESP RainMaker Work Queue Task stack", + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": "Priority for the ESP RainMaker Work Queue Task. Not recommended to be changed\nunless you really need it.", + "id": "ESP_RMAKER_WORK_QUEUE_TASK_PRIORITY", + "name": "ESP_RMAKER_WORK_QUEUE_TASK_PRIORITY", + "range": null, + "title": "ESP RainMaker Work Queue Task priority", + "type": "int" + }, + { + "children": [], + "depends_on": null, + "help": "Factory NVS Partition name which will have the MQTT connectivity credentials.", + "id": "ESP_RMAKER_FACTORY_PARTITION_NAME", + "name": "ESP_RMAKER_FACTORY_PARTITION_NAME", + "range": null, + "title": "ESP RainMaker Factory Partition Name", + "type": "string" + }, + { + "children": [], + "depends_on": null, + "help": "Namespace in the Factory NVS Partition name which will have the MQTT\nconnectivity credentials.", + "id": "ESP_RMAKER_FACTORY_NAMESPACE", + "name": "ESP_RMAKER_FACTORY_NAMESPACE", + "range": null, + "title": "ESP RainMaker Factory Namespace", + "type": "string" + }, + { + "children": [ + { + "children": [], + "depends_on": "ESP_RMAKER_ENCRYPT_FACTORY_PARTITION", + "help": "Label of the partition of subtype \"nvs_keys\" used for encrypting/decrypting Rainmaker factory partition.", + "id": "ESP_RMAKER_FACTORY_NVS_KEYS_PARTITION_NAME", + "name": "ESP_RMAKER_FACTORY_NVS_KEYS_PARTITION_NAME", + "range": null, + "title": "ESP Rainmaker Factory NVS keys partition label", + "type": "string" + } + ], + "depends_on": "NVS_ENCRYPTION", + "help": "Enable this option if the factory partition is pre-encrypted before flashing and the encryption keys\nare flashed in partition with subtype nvs_keys specified by CONFIG_ESP_RMAKER_FACTORY_NVS_KEYS_PARTITION_NAME.\nIf an unencrypted factory partition is flashed, the device would not be able to read its data and\nthe partition would be considered empty.\nIf nvs encryption keys are not flashed onto device, they would be auto-generated and any previous data\nin nvs/factory partition would become invalid.", + "id": "ESP_RMAKER_ENCRYPT_FACTORY_PARTITION", + "name": "ESP_RMAKER_ENCRYPT_FACTORY_PARTITION", + "range": null, + "title": "Encrypt Rainmaker Factory partition", + "type": "bool" + }, + { + "children": [], + "depends_on": null, + "help": "Default Timezone to use. Eg. \"Asia/Shanghai\", \"America/Los_Angeles\".\nCheck documentation for complete list of valid values. This value\nwill be used only if no timezone is set using the C APIs.", + "id": "ESP_RMAKER_DEF_TIMEZONE", + "name": "ESP_RMAKER_DEF_TIMEZONE", + "range": null, + "title": "Default Timezone", + "type": "string" + }, + { + "children": [], + "depends_on": null, + "help": "Default SNTP Server which is used for time synchronization.", + "id": "ESP_RMAKER_SNTP_SERVER_NAME", + "name": "ESP_RMAKER_SNTP_SERVER_NAME", + "range": null, + "title": "ESP RainMaker SNTP Server Name", + "type": "string" + }, + { + "children": [], + "depends_on": null, + "help": "Maximum number of commands supported by the command-response framework", + "id": "ESP_RMAKER_MAX_COMMANDS", + "name": "ESP_RMAKER_MAX_COMMANDS", + "range": null, + "title": "Maximum commands supported for command-response", + "type": "int" + } + ], + "depends_on": null, + "id": "component-config-esp-rainmaker-common", + "title": "ESP RainMaker Common", + "type": "menu" + } + ], + "depends_on": null, + "id": "component-config", + "title": "Component config", + "type": "menu" + }, + { + "children": [], + "depends_on": null, + "help": "By enabling this option, ESP-IDF experimental feature options will be visible.\n\nNote you should still enable a certain experimental feature option to use it, and you\nshould read the corresponding risk warning and known issue list carefully.\n\nCurrent experimental feature list:\n\n- CONFIG_ESPTOOLPY_FLASHFREQ_120M && CONFIG_ESPTOOLPY_FLASH_SAMPLE_MODE_DTR\n- CONFIG_SPIRAM_SPEED_120M && CONFIG_SPIRAM_MODE_OCT\n- CONFIG_BOOTLOADER_CACHE_32BIT_ADDR_QUAD_FLASH\n- CONFIG_ESP_WIFI_EAP_TLS1_3\n- CONFIG_ESP_WIFI_ENABLE_ROAMING_APP\n- CONFIG_USB_HOST_EXT_PORT_SUPPORT_LS\n- CONFIG_USB_HOST_EXT_PORT_RESET_ATTEMPTS", + "id": "IDF_EXPERIMENTAL_FEATURES", + "name": "IDF_EXPERIMENTAL_FEATURES", + "range": null, + "title": "Make experimental features visible", + "type": "bool" + } +] \ No newline at end of file diff --git a/RainMaker_Table-Lights/build/config/sdkconfig.cmake b/RainMaker_Table-Lights/build/config/sdkconfig.cmake new file mode 100644 index 000000000..5fa588e8e --- /dev/null +++ b/RainMaker_Table-Lights/build/config/sdkconfig.cmake @@ -0,0 +1,1790 @@ +# + # Automatically generated file. DO NOT EDIT. + # Espressif IoT Development Framework (ESP-IDF) Configuration cmake include file + # +set(CONFIG_SOC_ADC_SUPPORTED "y") +set(CONFIG_SOC_DEDICATED_GPIO_SUPPORTED "y") +set(CONFIG_SOC_UART_SUPPORTED "y") +set(CONFIG_SOC_GDMA_SUPPORTED "y") +set(CONFIG_SOC_AHB_GDMA_SUPPORTED "y") +set(CONFIG_SOC_GPTIMER_SUPPORTED "y") +set(CONFIG_SOC_TWAI_SUPPORTED "y") +set(CONFIG_SOC_BT_SUPPORTED "y") +set(CONFIG_SOC_ASYNC_MEMCPY_SUPPORTED "y") +set(CONFIG_SOC_USB_SERIAL_JTAG_SUPPORTED "y") +set(CONFIG_SOC_TEMP_SENSOR_SUPPORTED "y") +set(CONFIG_SOC_XT_WDT_SUPPORTED "y") +set(CONFIG_SOC_PHY_SUPPORTED "y") +set(CONFIG_SOC_WIFI_SUPPORTED "y") +set(CONFIG_SOC_SUPPORTS_SECURE_DL_MODE "y") +set(CONFIG_SOC_EFUSE_KEY_PURPOSE_FIELD "y") +set(CONFIG_SOC_EFUSE_HAS_EFUSE_RST_BUG "y") +set(CONFIG_SOC_EFUSE_SUPPORTED "y") +set(CONFIG_SOC_RTC_FAST_MEM_SUPPORTED "y") +set(CONFIG_SOC_RTC_MEM_SUPPORTED "y") +set(CONFIG_SOC_I2S_SUPPORTED "y") +set(CONFIG_SOC_RMT_SUPPORTED "y") +set(CONFIG_SOC_SDM_SUPPORTED "y") +set(CONFIG_SOC_GPSPI_SUPPORTED "y") +set(CONFIG_SOC_LEDC_SUPPORTED "y") +set(CONFIG_SOC_I2C_SUPPORTED "y") +set(CONFIG_SOC_SYSTIMER_SUPPORTED "y") +set(CONFIG_SOC_SUPPORT_COEXISTENCE "y") +set(CONFIG_SOC_AES_SUPPORTED "y") +set(CONFIG_SOC_MPI_SUPPORTED "y") +set(CONFIG_SOC_SHA_SUPPORTED "y") +set(CONFIG_SOC_HMAC_SUPPORTED "y") +set(CONFIG_SOC_DIG_SIGN_SUPPORTED "y") +set(CONFIG_SOC_FLASH_ENC_SUPPORTED "y") +set(CONFIG_SOC_SECURE_BOOT_SUPPORTED "y") +set(CONFIG_SOC_MEMPROT_SUPPORTED "y") +set(CONFIG_SOC_BOD_SUPPORTED "y") +set(CONFIG_SOC_CLK_TREE_SUPPORTED "y") +set(CONFIG_SOC_ASSIST_DEBUG_SUPPORTED "y") +set(CONFIG_SOC_WDT_SUPPORTED "y") +set(CONFIG_SOC_SPI_FLASH_SUPPORTED "y") +set(CONFIG_SOC_RNG_SUPPORTED "y") +set(CONFIG_SOC_LIGHT_SLEEP_SUPPORTED "y") +set(CONFIG_SOC_DEEP_SLEEP_SUPPORTED "y") +set(CONFIG_SOC_LP_PERIPH_SHARE_INTERRUPT "y") +set(CONFIG_SOC_PM_SUPPORTED "y") +set(CONFIG_SOC_XTAL_SUPPORT_40M "y") +set(CONFIG_SOC_AES_SUPPORT_DMA "y") +set(CONFIG_SOC_AES_GDMA "y") +set(CONFIG_SOC_AES_SUPPORT_AES_128 "y") +set(CONFIG_SOC_AES_SUPPORT_AES_256 "y") +set(CONFIG_SOC_ADC_DIG_CTRL_SUPPORTED "y") +set(CONFIG_SOC_ADC_ARBITER_SUPPORTED "y") +set(CONFIG_SOC_ADC_DIG_IIR_FILTER_SUPPORTED "y") +set(CONFIG_SOC_ADC_MONITOR_SUPPORTED "y") +set(CONFIG_SOC_ADC_DMA_SUPPORTED "y") +set(CONFIG_SOC_ADC_PERIPH_NUM "2") +set(CONFIG_SOC_ADC_MAX_CHANNEL_NUM "5") +set(CONFIG_SOC_ADC_ATTEN_NUM "4") +set(CONFIG_SOC_ADC_DIGI_CONTROLLER_NUM "1") +set(CONFIG_SOC_ADC_PATT_LEN_MAX "8") +set(CONFIG_SOC_ADC_DIGI_MIN_BITWIDTH "12") +set(CONFIG_SOC_ADC_DIGI_MAX_BITWIDTH "12") +set(CONFIG_SOC_ADC_DIGI_RESULT_BYTES "4") +set(CONFIG_SOC_ADC_DIGI_DATA_BYTES_PER_CONV "4") +set(CONFIG_SOC_ADC_DIGI_IIR_FILTER_NUM "2") +set(CONFIG_SOC_ADC_DIGI_MONITOR_NUM "2") +set(CONFIG_SOC_ADC_SAMPLE_FREQ_THRES_HIGH "83333") +set(CONFIG_SOC_ADC_SAMPLE_FREQ_THRES_LOW "611") +set(CONFIG_SOC_ADC_RTC_MIN_BITWIDTH "12") +set(CONFIG_SOC_ADC_RTC_MAX_BITWIDTH "12") +set(CONFIG_SOC_ADC_CALIBRATION_V1_SUPPORTED "y") +set(CONFIG_SOC_ADC_SELF_HW_CALI_SUPPORTED "y") +set(CONFIG_SOC_ADC_SHARED_POWER "y") +set(CONFIG_SOC_APB_BACKUP_DMA "y") +set(CONFIG_SOC_BROWNOUT_RESET_SUPPORTED "y") +set(CONFIG_SOC_SHARED_IDCACHE_SUPPORTED "y") +set(CONFIG_SOC_CACHE_MEMORY_IBANK_SIZE "0x4000") +set(CONFIG_SOC_CPU_CORES_NUM "1") +set(CONFIG_SOC_CPU_INTR_NUM "32") +set(CONFIG_SOC_CPU_HAS_FLEXIBLE_INTC "y") +set(CONFIG_SOC_CPU_HAS_CSR_PC "y") +set(CONFIG_SOC_CPU_BREAKPOINTS_NUM "8") +set(CONFIG_SOC_CPU_WATCHPOINTS_NUM "8") +set(CONFIG_SOC_CPU_WATCHPOINT_MAX_REGION_SIZE "0x80000000") +set(CONFIG_SOC_DS_SIGNATURE_MAX_BIT_LEN "3072") +set(CONFIG_SOC_DS_KEY_PARAM_MD_IV_LENGTH "16") +set(CONFIG_SOC_DS_KEY_CHECK_MAX_WAIT_US "1100") +set(CONFIG_SOC_AHB_GDMA_VERSION "1") +set(CONFIG_SOC_GDMA_NUM_GROUPS_MAX "1") +set(CONFIG_SOC_GDMA_PAIRS_PER_GROUP_MAX "3") +set(CONFIG_SOC_GPIO_PORT "1") +set(CONFIG_SOC_GPIO_PIN_COUNT "22") +set(CONFIG_SOC_GPIO_SUPPORT_PIN_GLITCH_FILTER "y") +set(CONFIG_SOC_GPIO_FILTER_CLK_SUPPORT_APB "y") +set(CONFIG_SOC_GPIO_SUPPORT_FORCE_HOLD "y") +set(CONFIG_SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP "y") +set(CONFIG_SOC_GPIO_IN_RANGE_MAX "21") +set(CONFIG_SOC_GPIO_OUT_RANGE_MAX "21") +set(CONFIG_SOC_GPIO_DEEP_SLEEP_WAKE_VALID_GPIO_MASK "0") +set(CONFIG_SOC_GPIO_DEEP_SLEEP_WAKE_SUPPORTED_PIN_CNT "6") +set(CONFIG_SOC_GPIO_VALID_DIGITAL_IO_PAD_MASK "0x3fffc0") +set(CONFIG_SOC_GPIO_CLOCKOUT_BY_GPIO_MATRIX "y") +set(CONFIG_SOC_GPIO_CLOCKOUT_CHANNEL_NUM "3") +set(CONFIG_SOC_GPIO_SUPPORT_HOLD_IO_IN_DSLP "y") +set(CONFIG_SOC_DEDIC_GPIO_OUT_CHANNELS_NUM "8") +set(CONFIG_SOC_DEDIC_GPIO_IN_CHANNELS_NUM "8") +set(CONFIG_SOC_DEDIC_PERIPH_ALWAYS_ENABLE "y") +set(CONFIG_SOC_I2C_NUM "1") +set(CONFIG_SOC_HP_I2C_NUM "1") +set(CONFIG_SOC_I2C_FIFO_LEN "32") +set(CONFIG_SOC_I2C_CMD_REG_NUM "8") +set(CONFIG_SOC_I2C_SUPPORT_SLAVE "y") +set(CONFIG_SOC_I2C_SUPPORT_HW_CLR_BUS "y") +set(CONFIG_SOC_I2C_SUPPORT_XTAL "y") +set(CONFIG_SOC_I2C_SUPPORT_RTC "y") +set(CONFIG_SOC_I2C_SUPPORT_10BIT_ADDR "y") +set(CONFIG_SOC_I2C_SLAVE_SUPPORT_BROADCAST "y") +set(CONFIG_SOC_I2C_SLAVE_CAN_GET_STRETCH_CAUSE "y") +set(CONFIG_SOC_I2C_SLAVE_SUPPORT_I2CRAM_ACCESS "y") +set(CONFIG_SOC_I2S_NUM "1") +set(CONFIG_SOC_I2S_HW_VERSION_2 "y") +set(CONFIG_SOC_I2S_SUPPORTS_XTAL "y") +set(CONFIG_SOC_I2S_SUPPORTS_PLL_F160M "y") +set(CONFIG_SOC_I2S_SUPPORTS_PCM "y") +set(CONFIG_SOC_I2S_SUPPORTS_PDM "y") +set(CONFIG_SOC_I2S_SUPPORTS_PDM_TX "y") +set(CONFIG_SOC_I2S_PDM_MAX_TX_LINES "2") +set(CONFIG_SOC_I2S_SUPPORTS_TDM "y") +set(CONFIG_SOC_LEDC_SUPPORT_APB_CLOCK "y") +set(CONFIG_SOC_LEDC_SUPPORT_XTAL_CLOCK "y") +set(CONFIG_SOC_LEDC_TIMER_NUM "4") +set(CONFIG_SOC_LEDC_CHANNEL_NUM "6") +set(CONFIG_SOC_LEDC_TIMER_BIT_WIDTH "14") +set(CONFIG_SOC_LEDC_SUPPORT_FADE_STOP "y") +set(CONFIG_SOC_MMU_LINEAR_ADDRESS_REGION_NUM "1") +set(CONFIG_SOC_MMU_PERIPH_NUM "1") +set(CONFIG_SOC_MPU_MIN_REGION_SIZE "0x20000000") +set(CONFIG_SOC_MPU_REGIONS_MAX_NUM "8") +set(CONFIG_SOC_RMT_GROUPS "1") +set(CONFIG_SOC_RMT_TX_CANDIDATES_PER_GROUP "2") +set(CONFIG_SOC_RMT_RX_CANDIDATES_PER_GROUP "2") +set(CONFIG_SOC_RMT_CHANNELS_PER_GROUP "4") +set(CONFIG_SOC_RMT_MEM_WORDS_PER_CHANNEL "48") +set(CONFIG_SOC_RMT_SUPPORT_RX_PINGPONG "y") +set(CONFIG_SOC_RMT_SUPPORT_RX_DEMODULATION "y") +set(CONFIG_SOC_RMT_SUPPORT_TX_ASYNC_STOP "y") +set(CONFIG_SOC_RMT_SUPPORT_TX_LOOP_COUNT "y") +set(CONFIG_SOC_RMT_SUPPORT_TX_SYNCHRO "y") +set(CONFIG_SOC_RMT_SUPPORT_TX_CARRIER_DATA_ONLY "y") +set(CONFIG_SOC_RMT_SUPPORT_XTAL "y") +set(CONFIG_SOC_RMT_SUPPORT_APB "y") +set(CONFIG_SOC_RMT_SUPPORT_RC_FAST "y") +set(CONFIG_SOC_RTC_CNTL_CPU_PD_DMA_BUS_WIDTH "128") +set(CONFIG_SOC_RTC_CNTL_CPU_PD_REG_FILE_NUM "108") +set(CONFIG_SOC_SLEEP_SYSTIMER_STALL_WORKAROUND "y") +set(CONFIG_SOC_SLEEP_TGWDT_STOP_WORKAROUND "y") +set(CONFIG_SOC_RTCIO_PIN_COUNT "0") +set(CONFIG_SOC_MPI_MEM_BLOCKS_NUM "4") +set(CONFIG_SOC_MPI_OPERATIONS_NUM "3") +set(CONFIG_SOC_RSA_MAX_BIT_LEN "3072") +set(CONFIG_SOC_SHA_DMA_MAX_BUFFER_SIZE "3968") +set(CONFIG_SOC_SHA_SUPPORT_DMA "y") +set(CONFIG_SOC_SHA_SUPPORT_RESUME "y") +set(CONFIG_SOC_SHA_GDMA "y") +set(CONFIG_SOC_SHA_SUPPORT_SHA1 "y") +set(CONFIG_SOC_SHA_SUPPORT_SHA224 "y") +set(CONFIG_SOC_SHA_SUPPORT_SHA256 "y") +set(CONFIG_SOC_SDM_GROUPS "1") +set(CONFIG_SOC_SDM_CHANNELS_PER_GROUP "4") +set(CONFIG_SOC_SDM_CLK_SUPPORT_APB "y") +set(CONFIG_SOC_SPI_PERIPH_NUM "2") +set(CONFIG_SOC_SPI_MAX_CS_NUM "6") +set(CONFIG_SOC_SPI_MAXIMUM_BUFFER_SIZE "64") +set(CONFIG_SOC_SPI_SUPPORT_DDRCLK "y") +set(CONFIG_SOC_SPI_SLAVE_SUPPORT_SEG_TRANS "y") +set(CONFIG_SOC_SPI_SUPPORT_CD_SIG "y") +set(CONFIG_SOC_SPI_SUPPORT_CONTINUOUS_TRANS "y") +set(CONFIG_SOC_SPI_SUPPORT_SLAVE_HD_VER2 "y") +set(CONFIG_SOC_SPI_SUPPORT_CLK_APB "y") +set(CONFIG_SOC_SPI_SUPPORT_CLK_XTAL "y") +set(CONFIG_SOC_SPI_PERIPH_SUPPORT_CONTROL_DUMMY_OUT "y") +set(CONFIG_SOC_SPI_SCT_SUPPORTED "y") +set(CONFIG_SOC_SPI_SCT_REG_NUM "14") +set(CONFIG_SOC_SPI_SCT_BUFFER_NUM_MAX "y") +set(CONFIG_SOC_SPI_SCT_CONF_BITLEN_MAX "0x3fffa") +set(CONFIG_SOC_MEMSPI_IS_INDEPENDENT "y") +set(CONFIG_SOC_SPI_MAX_PRE_DIVIDER "16") +set(CONFIG_SOC_SPI_MEM_SUPPORT_AUTO_WAIT_IDLE "y") +set(CONFIG_SOC_SPI_MEM_SUPPORT_AUTO_SUSPEND "y") +set(CONFIG_SOC_SPI_MEM_SUPPORT_AUTO_RESUME "y") +set(CONFIG_SOC_SPI_MEM_SUPPORT_IDLE_INTR "y") +set(CONFIG_SOC_SPI_MEM_SUPPORT_SW_SUSPEND "y") +set(CONFIG_SOC_SPI_MEM_SUPPORT_CHECK_SUS "y") +set(CONFIG_SOC_SPI_MEM_SUPPORT_CONFIG_GPIO_BY_EFUSE "y") +set(CONFIG_SOC_SPI_MEM_SUPPORT_WRAP "y") +set(CONFIG_SOC_MEMSPI_SRC_FREQ_80M_SUPPORTED "y") +set(CONFIG_SOC_MEMSPI_SRC_FREQ_40M_SUPPORTED "y") +set(CONFIG_SOC_MEMSPI_SRC_FREQ_26M_SUPPORTED "y") +set(CONFIG_SOC_MEMSPI_SRC_FREQ_20M_SUPPORTED "y") +set(CONFIG_SOC_SYSTIMER_COUNTER_NUM "2") +set(CONFIG_SOC_SYSTIMER_ALARM_NUM "3") +set(CONFIG_SOC_SYSTIMER_BIT_WIDTH_LO "32") +set(CONFIG_SOC_SYSTIMER_BIT_WIDTH_HI "20") +set(CONFIG_SOC_SYSTIMER_FIXED_DIVIDER "y") +set(CONFIG_SOC_SYSTIMER_INT_LEVEL "y") +set(CONFIG_SOC_SYSTIMER_ALARM_MISS_COMPENSATE "y") +set(CONFIG_SOC_TIMER_GROUPS "2") +set(CONFIG_SOC_TIMER_GROUP_TIMERS_PER_GROUP "1") +set(CONFIG_SOC_TIMER_GROUP_COUNTER_BIT_WIDTH "54") +set(CONFIG_SOC_TIMER_GROUP_SUPPORT_XTAL "y") +set(CONFIG_SOC_TIMER_GROUP_SUPPORT_APB "y") +set(CONFIG_SOC_TIMER_GROUP_TOTAL_TIMERS "2") +set(CONFIG_SOC_LP_TIMER_BIT_WIDTH_LO "32") +set(CONFIG_SOC_LP_TIMER_BIT_WIDTH_HI "16") +set(CONFIG_SOC_MWDT_SUPPORT_XTAL "y") +set(CONFIG_SOC_TWAI_CONTROLLER_NUM "1") +set(CONFIG_SOC_TWAI_CLK_SUPPORT_APB "y") +set(CONFIG_SOC_TWAI_BRP_MIN "2") +set(CONFIG_SOC_TWAI_BRP_MAX "16384") +set(CONFIG_SOC_TWAI_SUPPORTS_RX_STATUS "y") +set(CONFIG_SOC_EFUSE_DIS_DOWNLOAD_ICACHE "y") +set(CONFIG_SOC_EFUSE_DIS_PAD_JTAG "y") +set(CONFIG_SOC_EFUSE_DIS_USB_JTAG "y") +set(CONFIG_SOC_EFUSE_DIS_DIRECT_BOOT "y") +set(CONFIG_SOC_EFUSE_SOFT_DIS_JTAG "y") +set(CONFIG_SOC_EFUSE_DIS_ICACHE "y") +set(CONFIG_SOC_EFUSE_BLOCK9_KEY_PURPOSE_QUIRK "y") +set(CONFIG_SOC_SECURE_BOOT_V2_RSA "y") +set(CONFIG_SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS "3") +set(CONFIG_SOC_EFUSE_REVOKE_BOOT_KEY_DIGESTS "y") +set(CONFIG_SOC_SUPPORT_SECURE_BOOT_REVOKE_KEY "y") +set(CONFIG_SOC_FLASH_ENCRYPTED_XTS_AES_BLOCK_MAX "32") +set(CONFIG_SOC_FLASH_ENCRYPTION_XTS_AES "y") +set(CONFIG_SOC_FLASH_ENCRYPTION_XTS_AES_128 "y") +set(CONFIG_SOC_MEMPROT_CPU_PREFETCH_PAD_SIZE "16") +set(CONFIG_SOC_MEMPROT_MEM_ALIGN_SIZE "512") +set(CONFIG_SOC_UART_NUM "2") +set(CONFIG_SOC_UART_HP_NUM "2") +set(CONFIG_SOC_UART_FIFO_LEN "128") +set(CONFIG_SOC_UART_BITRATE_MAX "5000000") +set(CONFIG_SOC_UART_SUPPORT_APB_CLK "y") +set(CONFIG_SOC_UART_SUPPORT_RTC_CLK "y") +set(CONFIG_SOC_UART_SUPPORT_XTAL_CLK "y") +set(CONFIG_SOC_UART_SUPPORT_WAKEUP_INT "y") +set(CONFIG_SOC_UART_SUPPORT_FSM_TX_WAIT_SEND "y") +set(CONFIG_SOC_COEX_HW_PTI "y") +set(CONFIG_SOC_PHY_DIG_REGS_MEM_SIZE "21") +set(CONFIG_SOC_MAC_BB_PD_MEM_SIZE "192") +set(CONFIG_SOC_WIFI_LIGHT_SLEEP_CLK_WIDTH "12") +set(CONFIG_SOC_PM_SUPPORT_WIFI_WAKEUP "y") +set(CONFIG_SOC_PM_SUPPORT_BT_WAKEUP "y") +set(CONFIG_SOC_PM_SUPPORT_CPU_PD "y") +set(CONFIG_SOC_PM_SUPPORT_WIFI_PD "y") +set(CONFIG_SOC_PM_SUPPORT_BT_PD "y") +set(CONFIG_SOC_PM_SUPPORT_RC_FAST_PD "y") +set(CONFIG_SOC_PM_SUPPORT_VDDSDIO_PD "y") +set(CONFIG_SOC_PM_SUPPORT_MAC_BB_PD "y") +set(CONFIG_SOC_PM_CPU_RETENTION_BY_RTCCNTL "y") +set(CONFIG_SOC_PM_MODEM_RETENTION_BY_BACKUPDMA "y") +set(CONFIG_SOC_PM_MODEM_PD_BY_SW "y") +set(CONFIG_SOC_CLK_RC_FAST_D256_SUPPORTED "y") +set(CONFIG_SOC_RTC_SLOW_CLK_SUPPORT_RC_FAST_D256 "y") +set(CONFIG_SOC_CLK_RC_FAST_SUPPORT_CALIBRATION "y") +set(CONFIG_SOC_CLK_XTAL32K_SUPPORTED "y") +set(CONFIG_SOC_TEMPERATURE_SENSOR_SUPPORT_FAST_RC "y") +set(CONFIG_SOC_TEMPERATURE_SENSOR_SUPPORT_XTAL "y") +set(CONFIG_SOC_WIFI_HW_TSF "y") +set(CONFIG_SOC_WIFI_FTM_SUPPORT "y") +set(CONFIG_SOC_WIFI_GCMP_SUPPORT "y") +set(CONFIG_SOC_WIFI_WAPI_SUPPORT "y") +set(CONFIG_SOC_WIFI_CSI_SUPPORT "y") +set(CONFIG_SOC_WIFI_MESH_SUPPORT "y") +set(CONFIG_SOC_WIFI_SUPPORT_VARIABLE_BEACON_WINDOW "y") +set(CONFIG_SOC_WIFI_PHY_NEEDS_USB_WORKAROUND "y") +set(CONFIG_SOC_BLE_SUPPORTED "y") +set(CONFIG_SOC_BLE_MESH_SUPPORTED "y") +set(CONFIG_SOC_BLE_50_SUPPORTED "y") +set(CONFIG_SOC_BLE_DEVICE_PRIVACY_SUPPORTED "y") +set(CONFIG_SOC_BLUFI_SUPPORTED "y") +set(CONFIG_SOC_PHY_COMBO_MODULE "y") +set(CONFIG_IDF_CMAKE "y") +set(CONFIG_IDF_TOOLCHAIN "gcc") +set(CONFIG_IDF_TOOLCHAIN_GCC "y") +set(CONFIG_IDF_TARGET_ARCH_RISCV "y") +set(CONFIG_IDF_TARGET_ARCH "riscv") +set(CONFIG_IDF_TARGET "esp32c3") +set(CONFIG_IDF_INIT_VERSION "5.4.1") +set(CONFIG_IDF_TARGET_ESP32C3 "y") +set(CONFIG_IDF_FIRMWARE_CHIP_ID "0x5") +set(CONFIG_APP_BUILD_TYPE_APP_2NDBOOT "y") +set(CONFIG_APP_BUILD_TYPE_RAM "") +set(CONFIG_APP_BUILD_GENERATE_BINARIES "y") +set(CONFIG_APP_BUILD_BOOTLOADER "y") +set(CONFIG_APP_BUILD_USE_FLASH_SECTIONS "y") +set(CONFIG_APP_REPRODUCIBLE_BUILD "") +set(CONFIG_APP_NO_BLOBS "") +set(CONFIG_BOOTLOADER_COMPILE_TIME_DATE "y") +set(CONFIG_BOOTLOADER_PROJECT_VER "1") +set(CONFIG_BOOTLOADER_OFFSET_IN_FLASH "0x0") +set(CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE "y") +set(CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_DEBUG "") +set(CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_PERF "") +set(CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_NONE "") +set(CONFIG_BOOTLOADER_LOG_LEVEL_NONE "") +set(CONFIG_BOOTLOADER_LOG_LEVEL_ERROR "") +set(CONFIG_BOOTLOADER_LOG_LEVEL_WARN "") +set(CONFIG_BOOTLOADER_LOG_LEVEL_INFO "y") +set(CONFIG_BOOTLOADER_LOG_LEVEL_DEBUG "") +set(CONFIG_BOOTLOADER_LOG_LEVEL_VERBOSE "") +set(CONFIG_BOOTLOADER_LOG_LEVEL "3") +set(CONFIG_BOOTLOADER_LOG_COLORS "") +set(CONFIG_BOOTLOADER_LOG_TIMESTAMP_SOURCE_CPU_TICKS "y") +set(CONFIG_BOOTLOADER_FLASH_DC_AWARE "") +set(CONFIG_BOOTLOADER_FLASH_XMC_SUPPORT "y") +set(CONFIG_BOOTLOADER_FACTORY_RESET "") +set(CONFIG_BOOTLOADER_APP_TEST "") +set(CONFIG_BOOTLOADER_REGION_PROTECTION_ENABLE "y") +set(CONFIG_BOOTLOADER_WDT_ENABLE "y") +set(CONFIG_BOOTLOADER_WDT_DISABLE_IN_USER_CODE "") +set(CONFIG_BOOTLOADER_WDT_TIME_MS "9000") +set(CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE "y") +set(CONFIG_BOOTLOADER_APP_ANTI_ROLLBACK "") +set(CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP "") +set(CONFIG_BOOTLOADER_SKIP_VALIDATE_ON_POWER_ON "") +set(CONFIG_BOOTLOADER_SKIP_VALIDATE_ALWAYS "") +set(CONFIG_BOOTLOADER_RESERVE_RTC_SIZE "0x0") +set(CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC "") +set(CONFIG_SECURE_BOOT_V2_RSA_SUPPORTED "y") +set(CONFIG_SECURE_BOOT_V2_PREFERRED "y") +set(CONFIG_SECURE_SIGNED_APPS_NO_SECURE_BOOT "") +set(CONFIG_SECURE_BOOT "") +set(CONFIG_SECURE_FLASH_ENC_ENABLED "") +set(CONFIG_SECURE_ROM_DL_MODE_ENABLED "y") +set(CONFIG_APP_COMPILE_TIME_DATE "y") +set(CONFIG_APP_EXCLUDE_PROJECT_VER_VAR "") +set(CONFIG_APP_EXCLUDE_PROJECT_NAME_VAR "") +set(CONFIG_APP_PROJECT_VER_FROM_CONFIG "") +set(CONFIG_APP_RETRIEVE_LEN_ELF_SHA "9") +set(CONFIG_ESP_ROM_HAS_CRC_LE "y") +set(CONFIG_ESP_ROM_HAS_CRC_BE "y") +set(CONFIG_ESP_ROM_HAS_MZ_CRC32 "y") +set(CONFIG_ESP_ROM_HAS_JPEG_DECODE "y") +set(CONFIG_ESP_ROM_UART_CLK_IS_XTAL "y") +set(CONFIG_ESP_ROM_USB_SERIAL_DEVICE_NUM "3") +set(CONFIG_ESP_ROM_HAS_RETARGETABLE_LOCKING "y") +set(CONFIG_ESP_ROM_HAS_ERASE_0_REGION_BUG "y") +set(CONFIG_ESP_ROM_HAS_ENCRYPTED_WRITES_USING_LEGACY_DRV "y") +set(CONFIG_ESP_ROM_GET_CLK_FREQ "y") +set(CONFIG_ESP_ROM_NEEDS_SWSETUP_WORKAROUND "y") +set(CONFIG_ESP_ROM_HAS_LAYOUT_TABLE "y") +set(CONFIG_ESP_ROM_HAS_SPI_FLASH "y") +set(CONFIG_ESP_ROM_HAS_ETS_PRINTF_BUG "y") +set(CONFIG_ESP_ROM_HAS_NEWLIB "y") +set(CONFIG_ESP_ROM_HAS_NEWLIB_NANO_FORMAT "y") +set(CONFIG_ESP_ROM_HAS_NEWLIB_32BIT_TIME "y") +set(CONFIG_ESP_ROM_NEEDS_SET_CACHE_MMU_SIZE "y") +set(CONFIG_ESP_ROM_RAM_APP_NEEDS_MMU_INIT "y") +set(CONFIG_ESP_ROM_HAS_SW_FLOAT "y") +set(CONFIG_ESP_ROM_USB_OTG_NUM "-1") +set(CONFIG_ESP_ROM_HAS_VERSION "y") +set(CONFIG_ESP_ROM_SUPPORT_DEEP_SLEEP_WAKEUP_STUB "y") +set(CONFIG_BOOT_ROM_LOG_ALWAYS_ON "y") +set(CONFIG_BOOT_ROM_LOG_ALWAYS_OFF "") +set(CONFIG_BOOT_ROM_LOG_ON_GPIO_HIGH "") +set(CONFIG_BOOT_ROM_LOG_ON_GPIO_LOW "") +set(CONFIG_ESPTOOLPY_NO_STUB "") +set(CONFIG_ESPTOOLPY_FLASHMODE_QIO "") +set(CONFIG_ESPTOOLPY_FLASHMODE_QOUT "") +set(CONFIG_ESPTOOLPY_FLASHMODE_DIO "y") +set(CONFIG_ESPTOOLPY_FLASHMODE_DOUT "") +set(CONFIG_ESPTOOLPY_FLASH_SAMPLE_MODE_STR "y") +set(CONFIG_ESPTOOLPY_FLASHMODE "dio") +set(CONFIG_ESPTOOLPY_FLASHFREQ_80M "y") +set(CONFIG_ESPTOOLPY_FLASHFREQ_40M "") +set(CONFIG_ESPTOOLPY_FLASHFREQ_26M "") +set(CONFIG_ESPTOOLPY_FLASHFREQ_20M "") +set(CONFIG_ESPTOOLPY_FLASHFREQ "80m") +set(CONFIG_ESPTOOLPY_FLASHSIZE_1MB "") +set(CONFIG_ESPTOOLPY_FLASHSIZE_2MB "") +set(CONFIG_ESPTOOLPY_FLASHSIZE_4MB "y") +set(CONFIG_ESPTOOLPY_FLASHSIZE_8MB "") +set(CONFIG_ESPTOOLPY_FLASHSIZE_16MB "") +set(CONFIG_ESPTOOLPY_FLASHSIZE_32MB "") +set(CONFIG_ESPTOOLPY_FLASHSIZE_64MB "") +set(CONFIG_ESPTOOLPY_FLASHSIZE_128MB "") +set(CONFIG_ESPTOOLPY_FLASHSIZE "4MB") +set(CONFIG_ESPTOOLPY_HEADER_FLASHSIZE_UPDATE "") +set(CONFIG_ESPTOOLPY_BEFORE_RESET "y") +set(CONFIG_ESPTOOLPY_BEFORE_NORESET "") +set(CONFIG_ESPTOOLPY_BEFORE "default_reset") +set(CONFIG_ESPTOOLPY_AFTER_RESET "y") +set(CONFIG_ESPTOOLPY_AFTER_NORESET "") +set(CONFIG_ESPTOOLPY_AFTER "hard_reset") +set(CONFIG_ESPTOOLPY_MONITOR_BAUD "115200") +set(CONFIG_PARTITION_TABLE_SINGLE_APP "") +set(CONFIG_PARTITION_TABLE_SINGLE_APP_LARGE "") +set(CONFIG_PARTITION_TABLE_TWO_OTA "") +set(CONFIG_PARTITION_TABLE_TWO_OTA_LARGE "") +set(CONFIG_PARTITION_TABLE_CUSTOM "y") +set(CONFIG_PARTITION_TABLE_CUSTOM_FILENAME "partitions_4mb_optimised.csv") +set(CONFIG_PARTITION_TABLE_FILENAME "partitions_4mb_optimised.csv") +set(CONFIG_PARTITION_TABLE_OFFSET "0xc000") +set(CONFIG_PARTITION_TABLE_MD5 "y") +set(CONFIG_EXAMPLE_BOARD_BUTTON_GPIO "9") +set(CONFIG_APP_NETWORK_PROV_SHOW_QR "y") +set(CONFIG_APP_NETWORK_PROV_MAX_POP_MISMATCH "5") +set(CONFIG_APP_NETWORK_PROV_TRANSPORT_SOFTAP "") +set(CONFIG_APP_NETWORK_PROV_TRANSPORT_BLE "y") +set(CONFIG_APP_NETWORK_PROV_TRANSPORT "2") +set(CONFIG_APP_NETWORK_RESET_PROV_ON_FAILURE "y") +set(CONFIG_APP_NETWORK_PROV_MAX_RETRY_CNT "5") +set(CONFIG_APP_NETWORK_SHOW_DEMO_INTRO_TEXT "") +set(CONFIG_APP_NETWORK_PROV_TIMEOUT_PERIOD "30") +set(CONFIG_APP_NETWORK_PROV_NAME_PREFIX "PROV") +set(CONFIG_APP_WIFI_PROV_COMPAT "y") +set(CONFIG_ESP_RMAKER_NO_CLAIM "") +set(CONFIG_ESP_RMAKER_SELF_CLAIM "y") +set(CONFIG_ESP_RMAKER_ASSISTED_CLAIM "") +set(CONFIG_ESP_RMAKER_USE_NVS "y") +set(CONFIG_ESP_RMAKER_CLAIM_TYPE "1") +set(CONFIG_ESP_RMAKER_CLAIM_SERVICE_BASE_URL "https://esp-claiming.rainmaker.espressif.com") +set(CONFIG_ESP_RMAKER_READ_MQTT_HOST_FROM_CONFIG "") +set(CONFIG_ESP_RMAKER_READ_NODE_ID_FROM_CERT_CN "") +set(CONFIG_ESP_RMAKER_MQTT_HOST "a1p72mufdu6064-ats.iot.us-east-1.amazonaws.com") +set(CONFIG_ESP_RMAKER_MQTT_USE_BASIC_INGEST_TOPICS "y") +set(CONFIG_ESP_RMAKER_MQTT_ENABLE_BUDGETING "y") +set(CONFIG_ESP_RMAKER_MQTT_DEFAULT_BUDGET "100") +set(CONFIG_ESP_RMAKER_MQTT_MAX_BUDGET "1024") +set(CONFIG_ESP_RMAKER_MQTT_BUDGET_REVIVE_PERIOD "5") +set(CONFIG_ESP_RMAKER_MQTT_BUDGET_REVIVE_COUNT "1") +set(CONFIG_ESP_RMAKER_MAX_PARAM_DATA_SIZE "1024") +set(CONFIG_ESP_RMAKER_DISABLE_USER_MAPPING_PROV "") +set(CONFIG_ESP_RMAKER_USER_ID_CHECK "y") +set(CONFIG_RMAKER_NAME_PARAM_CB "") +set(CONFIG_ESP_RMAKER_LOCAL_CTRL_FEATURE_ENABLE "y") +set(CONFIG_ESP_RMAKER_LOCAL_CTRL_AUTO_ENABLE "y") +set(CONFIG_ESP_RMAKER_LOCAL_CTRL_HTTP_PORT "8080") +set(CONFIG_ESP_RMAKER_LOCAL_CTRL_STACK_SIZE "6144") +set(CONFIG_ESP_RMAKER_LOCAL_CTRL_SECURITY_0 "") +set(CONFIG_ESP_RMAKER_LOCAL_CTRL_SECURITY_1 "y") +set(CONFIG_ESP_RMAKER_LOCAL_CTRL_SECURITY "1") +set(CONFIG_ESP_RMAKER_CONSOLE_UART_NUM_0 "y") +set(CONFIG_ESP_RMAKER_CONSOLE_UART_NUM_1 "") +set(CONFIG_ESP_RMAKER_CONSOLE_UART_NUM "0") +set(CONFIG_ESP_RMAKER_USE_CERT_BUNDLE "y") +set(CONFIG_ESP_RMAKER_OTA_AUTOFETCH "y") +set(CONFIG_ESP_RMAKER_OTA_AUTOFETCH_PERIOD "0") +set(CONFIG_ESP_RMAKER_SKIP_COMMON_NAME_CHECK "") +set(CONFIG_ESP_RMAKER_SKIP_VERSION_CHECK "") +set(CONFIG_ESP_RMAKER_SKIP_SECURE_VERSION_CHECK "") +set(CONFIG_ESP_RMAKER_SKIP_PROJECT_NAME_CHECK "") +set(CONFIG_ESP_RMAKER_OTA_HTTP_RX_BUFFER_SIZE "1024") +set(CONFIG_ESP_RMAKER_OTA_ROLLBACK_WAIT_PERIOD "90") +set(CONFIG_ESP_RMAKER_OTA_DISABLE_AUTO_REBOOT "") +set(CONFIG_ESP_RMAKER_OTA_TIME_SUPPORT "y") +set(CONFIG_ESP_RMAKER_OTA_PROGRESS_SUPPORT "") +set(CONFIG_ESP_RMAKER_OTA_MAX_RETRIES "3") +set(CONFIG_ESP_RMAKER_OTA_RETRY_DELAY_MINUTES "5") +set(CONFIG_ESP_RMAKER_SCHEDULING_MAX_SCHEDULES "10") +set(CONFIG_ESP_RMAKER_SCENES_MAX_SCENES "10") +set(CONFIG_ESP_RMAKER_SCENES_DEACTIVATE_SUPPORT "") +set(CONFIG_ESP_RMAKER_CMD_RESP_ENABLE "y") +set(CONFIG_ESP_RMAKER_CMD_RESP_TEST_ENABLE "") +set(CONFIG_ESP_RMAKER_USING_NETWORK_PROV "y") +set(CONFIG_COMPILER_OPTIMIZATION_DEBUG "y") +set(CONFIG_COMPILER_OPTIMIZATION_SIZE "") +set(CONFIG_COMPILER_OPTIMIZATION_PERF "") +set(CONFIG_COMPILER_OPTIMIZATION_NONE "") +set(CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE "y") +set(CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT "") +set(CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE "") +set(CONFIG_COMPILER_ASSERT_NDEBUG_EVALUATE "y") +set(CONFIG_COMPILER_FLOAT_LIB_FROM_GCCLIB "y") +set(CONFIG_COMPILER_OPTIMIZATION_ASSERTION_LEVEL "2") +set(CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT "") +set(CONFIG_COMPILER_HIDE_PATHS_MACROS "y") +set(CONFIG_COMPILER_CXX_EXCEPTIONS "") +set(CONFIG_COMPILER_CXX_RTTI "") +set(CONFIG_COMPILER_STACK_CHECK_MODE_NONE "y") +set(CONFIG_COMPILER_STACK_CHECK_MODE_NORM "") +set(CONFIG_COMPILER_STACK_CHECK_MODE_STRONG "") +set(CONFIG_COMPILER_STACK_CHECK_MODE_ALL "") +set(CONFIG_COMPILER_NO_MERGE_CONSTANTS "") +set(CONFIG_COMPILER_WARN_WRITE_STRINGS "") +set(CONFIG_COMPILER_SAVE_RESTORE_LIBCALLS "") +set(CONFIG_COMPILER_DISABLE_DEFAULT_ERRORS "y") +set(CONFIG_COMPILER_DISABLE_GCC12_WARNINGS "") +set(CONFIG_COMPILER_DISABLE_GCC13_WARNINGS "") +set(CONFIG_COMPILER_DISABLE_GCC14_WARNINGS "") +set(CONFIG_COMPILER_DUMP_RTL_FILES "") +set(CONFIG_COMPILER_RT_LIB_GCCLIB "y") +set(CONFIG_COMPILER_RT_LIB_NAME "gcc") +set(CONFIG_COMPILER_ORPHAN_SECTIONS_WARNING "y") +set(CONFIG_COMPILER_ORPHAN_SECTIONS_PLACE "") +set(CONFIG_COMPILER_STATIC_ANALYZER "") +set(CONFIG_APPTRACE_DEST_JTAG "") +set(CONFIG_APPTRACE_DEST_NONE "y") +set(CONFIG_APPTRACE_DEST_UART1 "") +set(CONFIG_APPTRACE_DEST_USB_CDC "") +set(CONFIG_APPTRACE_DEST_UART_NONE "y") +set(CONFIG_APPTRACE_UART_TASK_PRIO "1") +set(CONFIG_APPTRACE_LOCK_ENABLE "y") +set(CONFIG_BT_ENABLED "y") +set(CONFIG_BT_BLUEDROID_ENABLED "") +set(CONFIG_BT_NIMBLE_ENABLED "y") +set(CONFIG_BT_CONTROLLER_ONLY "") +set(CONFIG_BT_CONTROLLER_ENABLED "y") +set(CONFIG_BT_CONTROLLER_DISABLED "") +set(CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_INTERNAL "y") +set(CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_DEFAULT "") +set(CONFIG_BT_NIMBLE_LOG_LEVEL_NONE "") +set(CONFIG_BT_NIMBLE_LOG_LEVEL_ERROR "") +set(CONFIG_BT_NIMBLE_LOG_LEVEL_WARNING "") +set(CONFIG_BT_NIMBLE_LOG_LEVEL_INFO "y") +set(CONFIG_BT_NIMBLE_LOG_LEVEL_DEBUG "") +set(CONFIG_BT_NIMBLE_LOG_LEVEL "1") +set(CONFIG_BT_NIMBLE_MAX_CONNECTIONS "3") +set(CONFIG_BT_NIMBLE_MAX_BONDS "3") +set(CONFIG_BT_NIMBLE_MAX_CCCDS "8") +set(CONFIG_BT_NIMBLE_L2CAP_COC_MAX_NUM "0") +set(CONFIG_BT_NIMBLE_PINNED_TO_CORE "0") +set(CONFIG_BT_NIMBLE_HOST_TASK_STACK_SIZE "4096") +set(CONFIG_BT_NIMBLE_ROLE_CENTRAL "y") +set(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL "y") +set(CONFIG_BT_NIMBLE_ROLE_BROADCASTER "y") +set(CONFIG_BT_NIMBLE_ROLE_OBSERVER "y") +set(CONFIG_BT_NIMBLE_NVS_PERSIST "") +set(CONFIG_BT_NIMBLE_SMP_ID_RESET "") +set(CONFIG_BT_NIMBLE_SECURITY_ENABLE "y") +set(CONFIG_BT_NIMBLE_SM_LEGACY "y") +set(CONFIG_BT_NIMBLE_SM_SC "y") +set(CONFIG_BT_NIMBLE_SM_SC_DEBUG_KEYS "") +set(CONFIG_BT_NIMBLE_LL_CFG_FEAT_LE_ENCRYPTION "y") +set(CONFIG_BT_NIMBLE_SM_LVL "0") +set(CONFIG_BT_NIMBLE_SM_SC_ONLY "0") +set(CONFIG_BT_NIMBLE_DEBUG "") +set(CONFIG_BT_NIMBLE_DYNAMIC_SERVICE "") +set(CONFIG_BT_NIMBLE_SVC_GAP_DEVICE_NAME "nimble") +set(CONFIG_BT_NIMBLE_GAP_DEVICE_NAME_MAX_LEN "31") +set(CONFIG_BT_NIMBLE_ATT_PREFERRED_MTU "256") +set(CONFIG_BT_NIMBLE_SVC_GAP_APPEARANCE "0x0") +set(CONFIG_BT_NIMBLE_MSYS_1_BLOCK_COUNT "12") +set(CONFIG_BT_NIMBLE_MSYS_1_BLOCK_SIZE "256") +set(CONFIG_BT_NIMBLE_MSYS_2_BLOCK_COUNT "24") +set(CONFIG_BT_NIMBLE_MSYS_2_BLOCK_SIZE "320") +set(CONFIG_BT_NIMBLE_TRANSPORT_ACL_FROM_LL_COUNT "24") +set(CONFIG_BT_NIMBLE_TRANSPORT_ACL_SIZE "255") +set(CONFIG_BT_NIMBLE_TRANSPORT_EVT_SIZE "70") +set(CONFIG_BT_NIMBLE_TRANSPORT_EVT_COUNT "30") +set(CONFIG_BT_NIMBLE_TRANSPORT_EVT_DISCARD_COUNT "8") +set(CONFIG_BT_NIMBLE_L2CAP_COC_SDU_BUFF_COUNT "1") +set(CONFIG_BT_NIMBLE_GATT_MAX_PROCS "4") +set(CONFIG_BT_NIMBLE_HS_FLOW_CTRL "") +set(CONFIG_BT_NIMBLE_RPA_TIMEOUT "900") +set(CONFIG_BT_NIMBLE_MESH "") +set(CONFIG_BT_NIMBLE_CRYPTO_STACK_MBEDTLS "y") +set(CONFIG_BT_NIMBLE_HS_STOP_TIMEOUT_MS "2000") +set(CONFIG_BT_NIMBLE_ENABLE_CONN_REATTEMPT "y") +set(CONFIG_BT_NIMBLE_MAX_CONN_REATTEMPT "3") +set(CONFIG_BT_NIMBLE_50_FEATURE_SUPPORT "y") +set(CONFIG_BT_NIMBLE_LL_CFG_FEAT_LE_2M_PHY "y") +set(CONFIG_BT_NIMBLE_LL_CFG_FEAT_LE_CODED_PHY "y") +set(CONFIG_BT_NIMBLE_EXT_ADV "") +set(CONFIG_BT_NIMBLE_EXT_SCAN "y") +set(CONFIG_BT_NIMBLE_ENABLE_PERIODIC_SYNC "y") +set(CONFIG_BT_NIMBLE_MAX_PERIODIC_SYNCS "0") +set(CONFIG_BT_NIMBLE_GATT_CACHING "") +set(CONFIG_BT_NIMBLE_WHITELIST_SIZE "12") +set(CONFIG_BT_NIMBLE_TEST_THROUGHPUT_TEST "") +set(CONFIG_BT_NIMBLE_BLUFI_ENABLE "") +set(CONFIG_BT_NIMBLE_USE_ESP_TIMER "y") +set(CONFIG_BT_NIMBLE_LEGACY_VHCI_ENABLE "y") +set(CONFIG_BT_NIMBLE_BLE_GATT_BLOB_TRANSFER "") +set(CONFIG_BT_NIMBLE_SVC_GAP_APPEAR_WRITE "") +set(CONFIG_BT_NIMBLE_SVC_GAP_APPEAR_WRITE_PERM "0") +set(CONFIG_BT_NIMBLE_SVC_GAP_APPEAR_WRITE_PERM_ENC "0") +set(CONFIG_BT_NIMBLE_SVC_GAP_APPEAR_WRITE_PERM_ATHN "0") +set(CONFIG_BT_NIMBLE_SVC_GAP_APPEAR_WRITE_PERM_ATHR "0") +set(CONFIG_BT_NIMBLE_SVC_GAP_CAR_CHAR_NOT_SUPP "y") +set(CONFIG_BT_NIMBLE_SVC_GAP_CAR_NOT_SUPP "") +set(CONFIG_BT_NIMBLE_SVC_GAP_CAR_SUPP "") +set(CONFIG_BT_NIMBLE_SVC_GAP_CENT_ADDR_RESOLUTION "-1") +set(CONFIG_BT_NIMBLE_SVC_GAP_NAME_WRITE "") +set(CONFIG_BT_NIMBLE_SVC_GAP_NAME_WRITE_PERM "0") +set(CONFIG_BT_NIMBLE_SVC_GAP_NAME_WRITE_PERM_ENC "0") +set(CONFIG_BT_NIMBLE_SVC_GAP_NAME_WRITE_PERM_AUTHEN "0") +set(CONFIG_BT_NIMBLE_SVC_GAP_NAME_WRITE_PERM_AUTHOR "0") +set(CONFIG_BT_NIMBLE_SVC_GAP_PPCP_MAX_CONN_INTERVAL "0") +set(CONFIG_BT_NIMBLE_SVC_GAP_PPCP_MIN_CONN_INTERVAL "0") +set(CONFIG_BT_NIMBLE_SVC_GAP_PPCP_SLAVE_LATENCY "0") +set(CONFIG_BT_NIMBLE_SVC_GAP_PPCP_SUPERVISION_TMO "0") +set(CONFIG_BT_NIMBLE_SVC_GAP_GATT_SECURITY_LEVEL "") +set(CONFIG_BT_NIMBLE_HID_SERVICE "") +set(CONFIG_BT_NIMBLE_SVC_BAS_BATTERY_LEVEL_NOTIFY "") +set(CONFIG_BT_NIMBLE_SVC_DIS_MANUFACTURER_NAME "") +set(CONFIG_BT_NIMBLE_SVC_DIS_SERIAL_NUMBER "") +set(CONFIG_BT_NIMBLE_SVC_DIS_HARDWARE_REVISION "") +set(CONFIG_BT_NIMBLE_SVC_DIS_FIRMWARE_REVISION "") +set(CONFIG_BT_NIMBLE_SVC_DIS_SOFTWARE_REVISION "") +set(CONFIG_BT_NIMBLE_SVC_DIS_SYSTEM_ID "") +set(CONFIG_BT_NIMBLE_SVC_DIS_PNP_ID "") +set(CONFIG_BT_NIMBLE_SVC_DIS_INCLUDED "") +set(CONFIG_BT_NIMBLE_VS_SUPPORT "") +set(CONFIG_BT_NIMBLE_ENC_ADV_DATA "") +set(CONFIG_BT_NIMBLE_HIGH_DUTY_ADV_ITVL "") +set(CONFIG_BT_NIMBLE_HOST_ALLOW_CONNECT_WITH_SCAN "") +set(CONFIG_BT_NIMBLE_HOST_QUEUE_CONG_CHECK "") +set(CONFIG_BT_NIMBLE_GATTC_PROC_PREEMPTION_PROTECT "") +set(CONFIG_UART_HW_FLOWCTRL_DISABLE "y") +set(CONFIG_UART_HW_FLOWCTRL_CTS_RTS "") +set(CONFIG_BT_NIMBLE_HCI_UART_FLOW_CTRL "0") +set(CONFIG_BT_NIMBLE_HCI_UART_RTS_PIN "19") +set(CONFIG_BT_NIMBLE_HCI_UART_CTS_PIN "23") +set(CONFIG_BT_NIMBLE_EATT_CHAN_NUM "0") +set(CONFIG_BT_NIMBLE_SUBRATE "") +set(CONFIG_BT_CTRL_MODE_EFF "1") +set(CONFIG_BT_CTRL_BLE_MAX_ACT "6") +set(CONFIG_BT_CTRL_BLE_MAX_ACT_EFF "6") +set(CONFIG_BT_CTRL_BLE_STATIC_ACL_TX_BUF_NB "0") +set(CONFIG_BT_CTRL_PINNED_TO_CORE "0") +set(CONFIG_BT_CTRL_HCI_MODE_VHCI "y") +set(CONFIG_BT_CTRL_HCI_MODE_UART_H4 "") +set(CONFIG_BT_CTRL_HCI_TL "1") +set(CONFIG_BT_CTRL_ADV_DUP_FILT_MAX "30") +set(CONFIG_BT_BLE_CCA_MODE_NONE "y") +set(CONFIG_BT_BLE_CCA_MODE_HW "") +set(CONFIG_BT_BLE_CCA_MODE_SW "") +set(CONFIG_BT_BLE_CCA_MODE "0") +set(CONFIG_BT_CTRL_HW_CCA_VAL "20") +set(CONFIG_BT_CTRL_HW_CCA_EFF "0") +set(CONFIG_BT_CTRL_CE_LENGTH_TYPE_ORIG "y") +set(CONFIG_BT_CTRL_CE_LENGTH_TYPE_CE "") +set(CONFIG_BT_CTRL_CE_LENGTH_TYPE_SD "") +set(CONFIG_BT_CTRL_CE_LENGTH_TYPE_EFF "0") +set(CONFIG_BT_CTRL_TX_ANTENNA_INDEX_0 "y") +set(CONFIG_BT_CTRL_TX_ANTENNA_INDEX_1 "") +set(CONFIG_BT_CTRL_TX_ANTENNA_INDEX_EFF "0") +set(CONFIG_BT_CTRL_RX_ANTENNA_INDEX_0 "y") +set(CONFIG_BT_CTRL_RX_ANTENNA_INDEX_1 "") +set(CONFIG_BT_CTRL_RX_ANTENNA_INDEX_EFF "0") +set(CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N24 "") +set(CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N21 "") +set(CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N18 "") +set(CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N15 "") +set(CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N12 "") +set(CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N9 "") +set(CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N6 "") +set(CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N3 "") +set(CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N0 "") +set(CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P3 "") +set(CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P6 "") +set(CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P9 "y") +set(CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P12 "") +set(CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P15 "") +set(CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P18 "") +set(CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P20 "") +set(CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_EFF "11") +set(CONFIG_BT_CTRL_BLE_ADV_REPORT_FLOW_CTRL_SUPP "y") +set(CONFIG_BT_CTRL_BLE_ADV_REPORT_FLOW_CTRL_NUM "100") +set(CONFIG_BT_CTRL_BLE_ADV_REPORT_DISCARD_THRSHOLD "20") +set(CONFIG_BT_CTRL_BLE_SCAN_DUPL "y") +set(CONFIG_BT_CTRL_SCAN_DUPL_TYPE_DEVICE "y") +set(CONFIG_BT_CTRL_SCAN_DUPL_TYPE_DATA "") +set(CONFIG_BT_CTRL_SCAN_DUPL_TYPE_DATA_DEVICE "") +set(CONFIG_BT_CTRL_SCAN_DUPL_TYPE "0") +set(CONFIG_BT_CTRL_SCAN_DUPL_CACHE_SIZE "100") +set(CONFIG_BT_CTRL_DUPL_SCAN_CACHE_REFRESH_PERIOD "0") +set(CONFIG_BT_CTRL_BLE_MESH_SCAN_DUPL_EN "") +set(CONFIG_BT_CTRL_COEX_PHY_CODED_TX_RX_TLIM_EN "") +set(CONFIG_BT_CTRL_COEX_PHY_CODED_TX_RX_TLIM_DIS "y") +set(CONFIG_BT_CTRL_COEX_PHY_CODED_TX_RX_TLIM_EFF "0") +set(CONFIG_BT_CTRL_MODEM_SLEEP "") +set(CONFIG_BT_CTRL_SLEEP_MODE_EFF "0") +set(CONFIG_BT_CTRL_SLEEP_CLOCK_EFF "0") +set(CONFIG_BT_CTRL_HCI_TL_EFF "1") +set(CONFIG_BT_CTRL_AGC_RECORRECT_EN "") +set(CONFIG_BT_CTRL_SCAN_BACKOFF_UPPERLIMITMAX "") +set(CONFIG_BT_BLE_ADV_DATA_LENGTH_ZERO_AUX "") +set(CONFIG_BT_CTRL_CHAN_ASS_EN "y") +set(CONFIG_BT_CTRL_LE_PING_EN "y") +set(CONFIG_BT_CTRL_BLE_LLCP_CONN_UPDATE "") +set(CONFIG_BT_CTRL_BLE_LLCP_CHAN_MAP_UPDATE "") +set(CONFIG_BT_CTRL_BLE_LLCP_PHY_UPDATE "") +set(CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY "") +set(CONFIG_BT_CTRL_CHECK_CONNECT_IND_ACCESS_ADDRESS "") +set(CONFIG_BT_ALARM_MAX_NUM "50") +set(CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED "") +set(CONFIG_BT_HCI_LOG_DEBUG_EN "") +set(CONFIG_BLE_MESH "") +set(CONFIG_CONSOLE_SORTED_HELP "") +set(CONFIG_TWAI_ISR_IN_IRAM "") +set(CONFIG_TWAI_ERRATA_FIX_LISTEN_ONLY_DOM "y") +set(CONFIG_ADC_SUPPRESS_DEPRECATE_WARN "") +set(CONFIG_ADC_SKIP_LEGACY_CONFLICT_CHECK "") +set(CONFIG_ADC_CALI_SUPPRESS_DEPRECATE_WARN "") +set(CONFIG_GPTIMER_SUPPRESS_DEPRECATE_WARN "") +set(CONFIG_GPTIMER_SKIP_LEGACY_CONFLICT_CHECK "") +set(CONFIG_RMT_SUPPRESS_DEPRECATE_WARN "") +set(CONFIG_RMT_SKIP_LEGACY_CONFLICT_CHECK "") +set(CONFIG_I2S_SUPPRESS_DEPRECATE_WARN "") +set(CONFIG_I2S_SKIP_LEGACY_CONFLICT_CHECK "") +set(CONFIG_SDM_SUPPRESS_DEPRECATE_WARN "") +set(CONFIG_SDM_SKIP_LEGACY_CONFLICT_CHECK "") +set(CONFIG_TEMP_SENSOR_SUPPRESS_DEPRECATE_WARN "") +set(CONFIG_TEMP_SENSOR_SKIP_LEGACY_CONFLICT_CHECK "") +set(CONFIG_EFUSE_CUSTOM_TABLE "") +set(CONFIG_EFUSE_VIRTUAL "") +set(CONFIG_EFUSE_MAX_BLK_LEN "256") +set(CONFIG_ESP_TLS_USING_MBEDTLS "y") +set(CONFIG_ESP_TLS_USE_DS_PERIPHERAL "y") +set(CONFIG_ESP_TLS_CLIENT_SESSION_TICKETS "") +set(CONFIG_ESP_TLS_SERVER_SESSION_TICKETS "") +set(CONFIG_ESP_TLS_SERVER_CERT_SELECT_HOOK "") +set(CONFIG_ESP_TLS_SERVER_MIN_AUTH_MODE_OPTIONAL "") +set(CONFIG_ESP_TLS_PSK_VERIFICATION "") +set(CONFIG_ESP_TLS_INSECURE "") +set(CONFIG_ADC_ONESHOT_CTRL_FUNC_IN_IRAM "") +set(CONFIG_ADC_CONTINUOUS_ISR_IRAM_SAFE "") +set(CONFIG_ADC_CONTINUOUS_FORCE_USE_ADC2_ON_C3_S3 "") +set(CONFIG_ADC_ONESHOT_FORCE_USE_ADC2_ON_C3 "") +set(CONFIG_ADC_ENABLE_DEBUG_LOG "") +set(CONFIG_ESP_COEX_ENABLED "y") +set(CONFIG_ESP_COEX_SW_COEXIST_ENABLE "y") +set(CONFIG_ESP_COEX_POWER_MANAGEMENT "") +set(CONFIG_ESP_COEX_GPIO_DEBUG "") +set(CONFIG_ESP_ERR_TO_NAME_LOOKUP "y") +set(CONFIG_GPIO_CTRL_FUNC_IN_IRAM "") +set(CONFIG_GPTIMER_ISR_HANDLER_IN_IRAM "y") +set(CONFIG_GPTIMER_CTRL_FUNC_IN_IRAM "") +set(CONFIG_GPTIMER_ISR_IRAM_SAFE "") +set(CONFIG_GPTIMER_ENABLE_DEBUG_LOG "") +set(CONFIG_I2C_ISR_IRAM_SAFE "") +set(CONFIG_I2C_ENABLE_DEBUG_LOG "") +set(CONFIG_I2C_ENABLE_SLAVE_DRIVER_VERSION_2 "") +set(CONFIG_I2S_ISR_IRAM_SAFE "") +set(CONFIG_I2S_ENABLE_DEBUG_LOG "") +set(CONFIG_LEDC_CTRL_FUNC_IN_IRAM "") +set(CONFIG_RMT_ISR_IRAM_SAFE "") +set(CONFIG_RMT_RECV_FUNC_IN_IRAM "") +set(CONFIG_RMT_ENABLE_DEBUG_LOG "") +set(CONFIG_SDM_CTRL_FUNC_IN_IRAM "") +set(CONFIG_SDM_ENABLE_DEBUG_LOG "") +set(CONFIG_SPI_MASTER_IN_IRAM "") +set(CONFIG_SPI_MASTER_ISR_IN_IRAM "y") +set(CONFIG_SPI_SLAVE_IN_IRAM "") +set(CONFIG_SPI_SLAVE_ISR_IN_IRAM "y") +set(CONFIG_TEMP_SENSOR_ENABLE_DEBUG_LOG "") +set(CONFIG_UART_ISR_IN_IRAM "") +set(CONFIG_USJ_ENABLE_USB_SERIAL_JTAG "y") +set(CONFIG_ETH_ENABLED "y") +set(CONFIG_ETH_USE_SPI_ETHERNET "y") +set(CONFIG_ETH_SPI_ETHERNET_DM9051 "") +set(CONFIG_ETH_SPI_ETHERNET_W5500 "") +set(CONFIG_ETH_SPI_ETHERNET_KSZ8851SNL "") +set(CONFIG_ETH_USE_OPENETH "") +set(CONFIG_ETH_TRANSMIT_MUTEX "") +set(CONFIG_ESP_EVENT_LOOP_PROFILING "") +set(CONFIG_ESP_EVENT_POST_FROM_ISR "y") +set(CONFIG_ESP_EVENT_POST_FROM_IRAM_ISR "y") +set(CONFIG_ESP_GDBSTUB_ENABLED "y") +set(CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME "") +set(CONFIG_ESP_GDBSTUB_SUPPORT_TASKS "y") +set(CONFIG_ESP_GDBSTUB_MAX_TASKS "32") +set(CONFIG_ESPHID_TASK_SIZE_BT "2048") +set(CONFIG_ESPHID_TASK_SIZE_BLE "4096") +set(CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS "y") +set(CONFIG_ESP_HTTP_CLIENT_ENABLE_BASIC_AUTH "") +set(CONFIG_ESP_HTTP_CLIENT_ENABLE_DIGEST_AUTH "") +set(CONFIG_ESP_HTTP_CLIENT_ENABLE_CUSTOM_TRANSPORT "") +set(CONFIG_ESP_HTTP_CLIENT_EVENT_POST_TIMEOUT "2000") +set(CONFIG_HTTPD_MAX_REQ_HDR_LEN "512") +set(CONFIG_HTTPD_MAX_URI_LEN "512") +set(CONFIG_HTTPD_ERR_RESP_NO_DELAY "y") +set(CONFIG_HTTPD_PURGE_BUF_LEN "32") +set(CONFIG_HTTPD_LOG_PURGE_DATA "") +set(CONFIG_HTTPD_WS_SUPPORT "") +set(CONFIG_HTTPD_QUEUE_WORK_BLOCKING "") +set(CONFIG_HTTPD_SERVER_EVENT_POST_TIMEOUT "2000") +set(CONFIG_ESP_HTTPS_OTA_DECRYPT_CB "") +set(CONFIG_ESP_HTTPS_OTA_ALLOW_HTTP "") +set(CONFIG_ESP_HTTPS_OTA_EVENT_POST_TIMEOUT "2000") +set(CONFIG_ESP_HTTPS_SERVER_ENABLE "y") +set(CONFIG_ESP_HTTPS_SERVER_EVENT_POST_TIMEOUT "2000") +set(CONFIG_ESP32C3_REV_MIN_0 "") +set(CONFIG_ESP32C3_REV_MIN_1 "") +set(CONFIG_ESP32C3_REV_MIN_2 "") +set(CONFIG_ESP32C3_REV_MIN_3 "y") +set(CONFIG_ESP32C3_REV_MIN_4 "") +set(CONFIG_ESP32C3_REV_MIN_101 "") +set(CONFIG_ESP32C3_REV_MIN_FULL "3") +set(CONFIG_ESP_REV_MIN_FULL "3") +set(CONFIG_ESP32C3_REV_MAX_FULL "199") +set(CONFIG_ESP_REV_MAX_FULL "199") +set(CONFIG_ESP_EFUSE_BLOCK_REV_MIN_FULL "0") +set(CONFIG_ESP_EFUSE_BLOCK_REV_MAX_FULL "199") +set(CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_STA "y") +set(CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_AP "y") +set(CONFIG_ESP_MAC_ADDR_UNIVERSE_BT "y") +set(CONFIG_ESP_MAC_ADDR_UNIVERSE_ETH "y") +set(CONFIG_ESP_MAC_UNIVERSAL_MAC_ADDRESSES_FOUR "y") +set(CONFIG_ESP_MAC_UNIVERSAL_MAC_ADDRESSES "4") +set(CONFIG_ESP32C3_UNIVERSAL_MAC_ADDRESSES_TWO "") +set(CONFIG_ESP32C3_UNIVERSAL_MAC_ADDRESSES_FOUR "y") +set(CONFIG_ESP32C3_UNIVERSAL_MAC_ADDRESSES "4") +set(CONFIG_ESP_MAC_USE_CUSTOM_MAC_AS_BASE_MAC "") +set(CONFIG_ESP_SLEEP_POWER_DOWN_FLASH "") +set(CONFIG_ESP_SLEEP_FLASH_LEAKAGE_WORKAROUND "y") +set(CONFIG_ESP_SLEEP_MSPI_NEED_ALL_IO_PU "") +set(CONFIG_ESP_SLEEP_GPIO_RESET_WORKAROUND "y") +set(CONFIG_ESP_SLEEP_WAIT_FLASH_READY_EXTRA_DELAY "0") +set(CONFIG_ESP_SLEEP_CACHE_SAFE_ASSERTION "") +set(CONFIG_ESP_SLEEP_DEBUG "") +set(CONFIG_ESP_SLEEP_GPIO_ENABLE_INTERNAL_RESISTORS "y") +set(CONFIG_RTC_CLK_SRC_INT_RC "y") +set(CONFIG_RTC_CLK_SRC_EXT_CRYS "") +set(CONFIG_RTC_CLK_SRC_EXT_OSC "") +set(CONFIG_RTC_CLK_SRC_INT_8MD256 "") +set(CONFIG_RTC_CLK_CAL_CYCLES "1024") +set(CONFIG_PERIPH_CTRL_FUNC_IN_IRAM "y") +set(CONFIG_GDMA_CTRL_FUNC_IN_IRAM "y") +set(CONFIG_GDMA_ISR_IRAM_SAFE "") +set(CONFIG_GDMA_ENABLE_DEBUG_LOG "") +set(CONFIG_XTAL_FREQ_40 "y") +set(CONFIG_XTAL_FREQ "40") +set(CONFIG_ESP_SPI_BUS_LOCK_ISR_FUNCS_IN_IRAM "y") +set(CONFIG_LCD_ENABLE_DEBUG_LOG "") +set(CONFIG_ESP_NETIF_IP_LOST_TIMER_INTERVAL "120") +set(CONFIG_ESP_NETIF_PROVIDE_CUSTOM_IMPLEMENTATION "") +set(CONFIG_ESP_NETIF_TCPIP_LWIP "y") +set(CONFIG_ESP_NETIF_LOOPBACK "") +set(CONFIG_ESP_NETIF_USES_TCPIP_WITH_BSD_API "y") +set(CONFIG_ESP_NETIF_REPORT_DATA_TRAFFIC "y") +set(CONFIG_ESP_NETIF_RECEIVE_REPORT_ERRORS "") +set(CONFIG_ESP_NETIF_L2_TAP "") +set(CONFIG_ESP_NETIF_BRIDGE_EN "") +set(CONFIG_ESP_NETIF_SET_DNS_PER_DEFAULT_NETIF "") +set(CONFIG_ESP_PHY_ENABLED "y") +set(CONFIG_ESP_PHY_CALIBRATION_AND_DATA_STORAGE "y") +set(CONFIG_ESP_PHY_INIT_DATA_IN_PARTITION "") +set(CONFIG_ESP_PHY_MAX_WIFI_TX_POWER "20") +set(CONFIG_ESP_PHY_MAX_TX_POWER "20") +set(CONFIG_ESP_PHY_REDUCE_TX_POWER "") +set(CONFIG_ESP_PHY_ENABLE_USB "y") +set(CONFIG_ESP_PHY_ENABLE_CERT_TEST "") +set(CONFIG_ESP_PHY_RF_CAL_PARTIAL "y") +set(CONFIG_ESP_PHY_RF_CAL_NONE "") +set(CONFIG_ESP_PHY_RF_CAL_FULL "") +set(CONFIG_ESP_PHY_CALIBRATION_MODE "0") +set(CONFIG_ESP_PHY_PLL_TRACK_DEBUG "") +set(CONFIG_ESP_PHY_RECORD_USED_TIME "") +set(CONFIG_PM_ENABLE "") +set(CONFIG_PM_SLP_IRAM_OPT "") +set(CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP "y") +set(CONFIG_RINGBUF_PLACE_FUNCTIONS_INTO_FLASH "") +set(CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_80 "") +set(CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_160 "y") +set(CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ "160") +set(CONFIG_ESP_SYSTEM_PANIC_PRINT_HALT "") +set(CONFIG_ESP_SYSTEM_PANIC_PRINT_REBOOT "y") +set(CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT "") +set(CONFIG_ESP_SYSTEM_PANIC_GDBSTUB "") +set(CONFIG_ESP_SYSTEM_PANIC_REBOOT_DELAY_SECONDS "0") +set(CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE "y") +set(CONFIG_ESP_SYSTEM_RTC_FAST_MEM_AS_HEAP_DEPCHECK "y") +set(CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP "y") +set(CONFIG_ESP_SYSTEM_USE_EH_FRAME "") +set(CONFIG_ESP_SYSTEM_MEMPROT_FEATURE "y") +set(CONFIG_ESP_SYSTEM_MEMPROT_FEATURE_LOCK "y") +set(CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE "32") +set(CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE "2304") +set(CONFIG_ESP_MAIN_TASK_STACK_SIZE "3584") +set(CONFIG_ESP_MAIN_TASK_AFFINITY_CPU0 "y") +set(CONFIG_ESP_MAIN_TASK_AFFINITY_NO_AFFINITY "") +set(CONFIG_ESP_MAIN_TASK_AFFINITY "0x0") +set(CONFIG_ESP_MINIMAL_SHARED_STACK_SIZE "2048") +set(CONFIG_ESP_CONSOLE_UART_DEFAULT "y") +set(CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG "") +set(CONFIG_ESP_CONSOLE_UART_CUSTOM "") +set(CONFIG_ESP_CONSOLE_NONE "") +set(CONFIG_ESP_CONSOLE_SECONDARY_NONE "") +set(CONFIG_ESP_CONSOLE_SECONDARY_USB_SERIAL_JTAG "y") +set(CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG_ENABLED "y") +set(CONFIG_ESP_CONSOLE_UART "y") +set(CONFIG_ESP_CONSOLE_UART_NUM "0") +set(CONFIG_ESP_CONSOLE_ROM_SERIAL_PORT_NUM "0") +set(CONFIG_ESP_CONSOLE_UART_BAUDRATE "115200") +set(CONFIG_ESP_INT_WDT "y") +set(CONFIG_ESP_INT_WDT_TIMEOUT_MS "300") +set(CONFIG_ESP_TASK_WDT_EN "y") +set(CONFIG_ESP_TASK_WDT_INIT "y") +set(CONFIG_ESP_TASK_WDT_PANIC "") +set(CONFIG_ESP_TASK_WDT_TIMEOUT_S "5") +set(CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0 "y") +set(CONFIG_ESP_PANIC_HANDLER_IRAM "") +set(CONFIG_ESP_DEBUG_STUBS_ENABLE "") +set(CONFIG_ESP_DEBUG_OCDAWARE "y") +set(CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL_4 "y") +set(CONFIG_ESP_BROWNOUT_DET "y") +set(CONFIG_ESP_BROWNOUT_DET_LVL_SEL_7 "y") +set(CONFIG_ESP_BROWNOUT_DET_LVL_SEL_6 "") +set(CONFIG_ESP_BROWNOUT_DET_LVL_SEL_5 "") +set(CONFIG_ESP_BROWNOUT_DET_LVL_SEL_4 "") +set(CONFIG_ESP_BROWNOUT_DET_LVL_SEL_3 "") +set(CONFIG_ESP_BROWNOUT_DET_LVL_SEL_2 "") +set(CONFIG_ESP_BROWNOUT_DET_LVL "7") +set(CONFIG_ESP_SYSTEM_BROWNOUT_INTR "y") +set(CONFIG_ESP_SYSTEM_HW_STACK_GUARD "y") +set(CONFIG_ESP_SYSTEM_HW_PC_RECORD "y") +set(CONFIG_ESP_IPC_TASK_STACK_SIZE "1024") +set(CONFIG_ESP_TIMER_PROFILING "") +set(CONFIG_ESP_TIME_FUNCS_USE_RTC_TIMER "y") +set(CONFIG_ESP_TIME_FUNCS_USE_ESP_TIMER "y") +set(CONFIG_ESP_TIMER_TASK_STACK_SIZE "3584") +set(CONFIG_ESP_TIMER_INTERRUPT_LEVEL "1") +set(CONFIG_ESP_TIMER_SHOW_EXPERIMENTAL "") +set(CONFIG_ESP_TIMER_TASK_AFFINITY "0x0") +set(CONFIG_ESP_TIMER_TASK_AFFINITY_CPU0 "y") +set(CONFIG_ESP_TIMER_ISR_AFFINITY_CPU0 "y") +set(CONFIG_ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD "") +set(CONFIG_ESP_TIMER_IMPL_SYSTIMER "y") +set(CONFIG_ESP_WIFI_ENABLED "y") +set(CONFIG_ESP_WIFI_STATIC_RX_BUFFER_NUM "10") +set(CONFIG_ESP_WIFI_DYNAMIC_RX_BUFFER_NUM "32") +set(CONFIG_ESP_WIFI_STATIC_TX_BUFFER "") +set(CONFIG_ESP_WIFI_DYNAMIC_TX_BUFFER "y") +set(CONFIG_ESP_WIFI_TX_BUFFER_TYPE "1") +set(CONFIG_ESP_WIFI_DYNAMIC_TX_BUFFER_NUM "32") +set(CONFIG_ESP_WIFI_STATIC_RX_MGMT_BUFFER "y") +set(CONFIG_ESP_WIFI_DYNAMIC_RX_MGMT_BUFFER "") +set(CONFIG_ESP_WIFI_DYNAMIC_RX_MGMT_BUF "0") +set(CONFIG_ESP_WIFI_RX_MGMT_BUF_NUM_DEF "5") +set(CONFIG_ESP_WIFI_CSI_ENABLED "") +set(CONFIG_ESP_WIFI_AMPDU_TX_ENABLED "y") +set(CONFIG_ESP_WIFI_TX_BA_WIN "6") +set(CONFIG_ESP_WIFI_AMPDU_RX_ENABLED "y") +set(CONFIG_ESP_WIFI_RX_BA_WIN "6") +set(CONFIG_ESP_WIFI_NVS_ENABLED "y") +set(CONFIG_ESP_WIFI_SOFTAP_BEACON_MAX_LEN "752") +set(CONFIG_ESP_WIFI_MGMT_SBUF_NUM "32") +set(CONFIG_ESP_WIFI_IRAM_OPT "y") +set(CONFIG_ESP_WIFI_EXTRA_IRAM_OPT "") +set(CONFIG_ESP_WIFI_RX_IRAM_OPT "y") +set(CONFIG_ESP_WIFI_ENABLE_WPA3_SAE "y") +set(CONFIG_ESP_WIFI_ENABLE_SAE_PK "y") +set(CONFIG_ESP_WIFI_SOFTAP_SAE_SUPPORT "y") +set(CONFIG_ESP_WIFI_ENABLE_WPA3_OWE_STA "y") +set(CONFIG_ESP_WIFI_SLP_IRAM_OPT "") +set(CONFIG_ESP_WIFI_SLP_DEFAULT_MIN_ACTIVE_TIME "50") +set(CONFIG_ESP_WIFI_SLP_DEFAULT_MAX_ACTIVE_TIME "10") +set(CONFIG_ESP_WIFI_SLP_DEFAULT_WAIT_BROADCAST_DATA_TIME "15") +set(CONFIG_ESP_WIFI_FTM_ENABLE "") +set(CONFIG_ESP_WIFI_STA_DISCONNECTED_PM_ENABLE "y") +set(CONFIG_ESP_WIFI_GCMP_SUPPORT "") +set(CONFIG_ESP_WIFI_GMAC_SUPPORT "y") +set(CONFIG_ESP_WIFI_SOFTAP_SUPPORT "y") +set(CONFIG_ESP_WIFI_SLP_BEACON_LOST_OPT "") +set(CONFIG_ESP_WIFI_ESPNOW_MAX_ENCRYPT_NUM "7") +set(CONFIG_ESP_WIFI_MBEDTLS_CRYPTO "y") +set(CONFIG_ESP_WIFI_MBEDTLS_TLS_CLIENT "y") +set(CONFIG_ESP_WIFI_WAPI_PSK "") +set(CONFIG_ESP_WIFI_SUITE_B_192 "") +set(CONFIG_ESP_WIFI_11KV_SUPPORT "") +set(CONFIG_ESP_WIFI_MBO_SUPPORT "") +set(CONFIG_ESP_WIFI_DPP_SUPPORT "") +set(CONFIG_ESP_WIFI_11R_SUPPORT "") +set(CONFIG_ESP_WIFI_WPS_SOFTAP_REGISTRAR "") +set(CONFIG_ESP_WIFI_WPS_STRICT "") +set(CONFIG_ESP_WIFI_WPS_PASSPHRASE "") +set(CONFIG_ESP_WIFI_DEBUG_PRINT "") +set(CONFIG_ESP_WIFI_TESTING_OPTIONS "") +set(CONFIG_ESP_WIFI_ENTERPRISE_SUPPORT "y") +set(CONFIG_ESP_WIFI_ENT_FREE_DYNAMIC_BUFFER "") +set(CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH "") +set(CONFIG_ESP_COREDUMP_ENABLE_TO_UART "") +set(CONFIG_ESP_COREDUMP_ENABLE_TO_NONE "y") +set(CONFIG_FATFS_VOLUME_COUNT "2") +set(CONFIG_FATFS_LFN_NONE "y") +set(CONFIG_FATFS_LFN_HEAP "") +set(CONFIG_FATFS_LFN_STACK "") +set(CONFIG_FATFS_SECTOR_512 "") +set(CONFIG_FATFS_SECTOR_4096 "y") +set(CONFIG_FATFS_CODEPAGE_DYNAMIC "") +set(CONFIG_FATFS_CODEPAGE_437 "y") +set(CONFIG_FATFS_CODEPAGE_720 "") +set(CONFIG_FATFS_CODEPAGE_737 "") +set(CONFIG_FATFS_CODEPAGE_771 "") +set(CONFIG_FATFS_CODEPAGE_775 "") +set(CONFIG_FATFS_CODEPAGE_850 "") +set(CONFIG_FATFS_CODEPAGE_852 "") +set(CONFIG_FATFS_CODEPAGE_855 "") +set(CONFIG_FATFS_CODEPAGE_857 "") +set(CONFIG_FATFS_CODEPAGE_860 "") +set(CONFIG_FATFS_CODEPAGE_861 "") +set(CONFIG_FATFS_CODEPAGE_862 "") +set(CONFIG_FATFS_CODEPAGE_863 "") +set(CONFIG_FATFS_CODEPAGE_864 "") +set(CONFIG_FATFS_CODEPAGE_865 "") +set(CONFIG_FATFS_CODEPAGE_866 "") +set(CONFIG_FATFS_CODEPAGE_869 "") +set(CONFIG_FATFS_CODEPAGE_932 "") +set(CONFIG_FATFS_CODEPAGE_936 "") +set(CONFIG_FATFS_CODEPAGE_949 "") +set(CONFIG_FATFS_CODEPAGE_950 "") +set(CONFIG_FATFS_CODEPAGE "437") +set(CONFIG_FATFS_FS_LOCK "0") +set(CONFIG_FATFS_TIMEOUT_MS "10000") +set(CONFIG_FATFS_PER_FILE_CACHE "y") +set(CONFIG_FATFS_USE_FASTSEEK "") +set(CONFIG_FATFS_USE_STRFUNC_NONE "y") +set(CONFIG_FATFS_USE_STRFUNC_WITHOUT_CRLF_CONV "") +set(CONFIG_FATFS_USE_STRFUNC_WITH_CRLF_CONV "") +set(CONFIG_FATFS_VFS_FSTAT_BLKSIZE "0") +set(CONFIG_FATFS_IMMEDIATE_FSYNC "") +set(CONFIG_FATFS_USE_LABEL "") +set(CONFIG_FATFS_LINK_LOCK "y") +set(CONFIG_FREERTOS_SMP "") +set(CONFIG_FREERTOS_UNICORE "y") +set(CONFIG_FREERTOS_HZ "100") +set(CONFIG_FREERTOS_OPTIMIZED_SCHEDULER "y") +set(CONFIG_FREERTOS_CHECK_STACKOVERFLOW_NONE "") +set(CONFIG_FREERTOS_CHECK_STACKOVERFLOW_PTRVAL "") +set(CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY "y") +set(CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS "1") +set(CONFIG_FREERTOS_IDLE_TASK_STACKSIZE "1536") +set(CONFIG_FREERTOS_USE_IDLE_HOOK "") +set(CONFIG_FREERTOS_USE_TICK_HOOK "") +set(CONFIG_FREERTOS_MAX_TASK_NAME_LEN "16") +set(CONFIG_FREERTOS_ENABLE_BACKWARD_COMPATIBILITY "") +set(CONFIG_FREERTOS_USE_TIMERS "y") +set(CONFIG_FREERTOS_TIMER_SERVICE_TASK_NAME "Tmr Svc") +set(CONFIG_FREERTOS_TIMER_TASK_AFFINITY_CPU0 "") +set(CONFIG_FREERTOS_TIMER_TASK_NO_AFFINITY "y") +set(CONFIG_FREERTOS_TIMER_SERVICE_TASK_CORE_AFFINITY "0x7fffffff") +set(CONFIG_FREERTOS_TIMER_TASK_PRIORITY "1") +set(CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH "3120") +set(CONFIG_FREERTOS_TIMER_QUEUE_LENGTH "10") +set(CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE "0") +set(CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES "1") +set(CONFIG_FREERTOS_USE_TRACE_FACILITY "") +set(CONFIG_FREERTOS_USE_LIST_DATA_INTEGRITY_CHECK_BYTES "") +set(CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS "") +set(CONFIG_FREERTOS_USE_APPLICATION_TASK_TAG "") +set(CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER "y") +set(CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK "") +set(CONFIG_FREERTOS_TLSP_DELETION_CALLBACKS "y") +set(CONFIG_FREERTOS_TASK_PRE_DELETION_HOOK "") +set(CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP "") +set(CONFIG_FREERTOS_CHECK_MUTEX_GIVEN_BY_OWNER "y") +set(CONFIG_FREERTOS_ISR_STACKSIZE "1536") +set(CONFIG_FREERTOS_INTERRUPT_BACKTRACE "y") +set(CONFIG_FREERTOS_TICK_SUPPORT_SYSTIMER "y") +set(CONFIG_FREERTOS_CORETIMER_SYSTIMER_LVL1 "y") +set(CONFIG_FREERTOS_CORETIMER_SYSTIMER_LVL3 "") +set(CONFIG_FREERTOS_SYSTICK_USES_SYSTIMER "y") +set(CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH "") +set(CONFIG_FREERTOS_CHECK_PORT_CRITICAL_COMPLIANCE "") +set(CONFIG_FREERTOS_PORT "y") +set(CONFIG_FREERTOS_NO_AFFINITY "0x7fffffff") +set(CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION "y") +set(CONFIG_FREERTOS_DEBUG_OCDAWARE "y") +set(CONFIG_FREERTOS_ENABLE_TASK_SNAPSHOT "y") +set(CONFIG_FREERTOS_PLACE_SNAPSHOT_FUNS_INTO_FLASH "y") +set(CONFIG_FREERTOS_NUMBER_OF_CORES "1") +set(CONFIG_HAL_ASSERTION_EQUALS_SYSTEM "y") +set(CONFIG_HAL_ASSERTION_DISABLE "") +set(CONFIG_HAL_ASSERTION_SILENT "") +set(CONFIG_HAL_ASSERTION_ENABLE "") +set(CONFIG_HAL_DEFAULT_ASSERTION_LEVEL "2") +set(CONFIG_HAL_SPI_MASTER_FUNC_IN_IRAM "y") +set(CONFIG_HAL_SPI_SLAVE_FUNC_IN_IRAM "y") +set(CONFIG_HEAP_POISONING_DISABLED "y") +set(CONFIG_HEAP_POISONING_LIGHT "") +set(CONFIG_HEAP_POISONING_COMPREHENSIVE "") +set(CONFIG_HEAP_TRACING_OFF "y") +set(CONFIG_HEAP_TRACING_STANDALONE "") +set(CONFIG_HEAP_TRACING_TOHOST "") +set(CONFIG_HEAP_USE_HOOKS "") +set(CONFIG_HEAP_TASK_TRACKING "") +set(CONFIG_HEAP_ABORT_WHEN_ALLOCATION_FAILS "") +set(CONFIG_HEAP_PLACE_FUNCTION_INTO_FLASH "") +set(CONFIG_LOG_DEFAULT_LEVEL_NONE "") +set(CONFIG_LOG_DEFAULT_LEVEL_ERROR "") +set(CONFIG_LOG_DEFAULT_LEVEL_WARN "") +set(CONFIG_LOG_DEFAULT_LEVEL_INFO "y") +set(CONFIG_LOG_DEFAULT_LEVEL_DEBUG "") +set(CONFIG_LOG_DEFAULT_LEVEL_VERBOSE "") +set(CONFIG_LOG_DEFAULT_LEVEL "3") +set(CONFIG_LOG_MAXIMUM_EQUALS_DEFAULT "y") +set(CONFIG_LOG_MAXIMUM_LEVEL_DEBUG "") +set(CONFIG_LOG_MAXIMUM_LEVEL_VERBOSE "") +set(CONFIG_LOG_MAXIMUM_LEVEL "3") +set(CONFIG_LOG_MASTER_LEVEL "") +set(CONFIG_LOG_DYNAMIC_LEVEL_CONTROL "y") +set(CONFIG_LOG_TAG_LEVEL_IMPL_NONE "") +set(CONFIG_LOG_TAG_LEVEL_IMPL_LINKED_LIST "") +set(CONFIG_LOG_TAG_LEVEL_IMPL_CACHE_AND_LINKED_LIST "y") +set(CONFIG_LOG_TAG_LEVEL_CACHE_ARRAY "") +set(CONFIG_LOG_TAG_LEVEL_CACHE_BINARY_MIN_HEAP "y") +set(CONFIG_LOG_TAG_LEVEL_IMPL_CACHE_SIZE "31") +set(CONFIG_LOG_COLORS "") +set(CONFIG_LOG_TIMESTAMP_SOURCE_RTOS "y") +set(CONFIG_LOG_TIMESTAMP_SOURCE_SYSTEM "") +set(CONFIG_LWIP_ENABLE "y") +set(CONFIG_LWIP_LOCAL_HOSTNAME "espressif") +set(CONFIG_LWIP_NETIF_API "") +set(CONFIG_LWIP_TCPIP_TASK_PRIO "18") +set(CONFIG_LWIP_TCPIP_CORE_LOCKING "") +set(CONFIG_LWIP_CHECK_THREAD_SAFETY "") +set(CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES "y") +set(CONFIG_LWIP_L2_TO_L3_COPY "") +set(CONFIG_LWIP_IRAM_OPTIMIZATION "") +set(CONFIG_LWIP_EXTRA_IRAM_OPTIMIZATION "") +set(CONFIG_LWIP_TIMERS_ONDEMAND "y") +set(CONFIG_LWIP_ND6 "y") +set(CONFIG_LWIP_FORCE_ROUTER_FORWARDING "") +set(CONFIG_LWIP_MAX_SOCKETS "10") +set(CONFIG_LWIP_USE_ONLY_LWIP_SELECT "") +set(CONFIG_LWIP_SO_LINGER "") +set(CONFIG_LWIP_SO_REUSE "y") +set(CONFIG_LWIP_SO_REUSE_RXTOALL "y") +set(CONFIG_LWIP_SO_RCVBUF "") +set(CONFIG_LWIP_NETBUF_RECVINFO "") +set(CONFIG_LWIP_IP_DEFAULT_TTL "64") +set(CONFIG_LWIP_IP4_FRAG "y") +set(CONFIG_LWIP_IP6_FRAG "y") +set(CONFIG_LWIP_IP4_REASSEMBLY "") +set(CONFIG_LWIP_IP6_REASSEMBLY "") +set(CONFIG_LWIP_IP_REASS_MAX_PBUFS "10") +set(CONFIG_LWIP_IP_FORWARD "") +set(CONFIG_LWIP_STATS "") +set(CONFIG_LWIP_ESP_GRATUITOUS_ARP "y") +set(CONFIG_LWIP_GARP_TMR_INTERVAL "60") +set(CONFIG_LWIP_ESP_MLDV6_REPORT "y") +set(CONFIG_LWIP_MLDV6_TMR_INTERVAL "40") +set(CONFIG_LWIP_TCPIP_RECVMBOX_SIZE "32") +set(CONFIG_LWIP_DHCP_DOES_ARP_CHECK "y") +set(CONFIG_LWIP_DHCP_DOES_ACD_CHECK "") +set(CONFIG_LWIP_DHCP_DOES_NOT_CHECK_OFFERED_IP "") +set(CONFIG_LWIP_DHCP_DISABLE_CLIENT_ID "") +set(CONFIG_LWIP_DHCP_DISABLE_VENDOR_CLASS_ID "y") +set(CONFIG_LWIP_DHCP_RESTORE_LAST_IP "") +set(CONFIG_LWIP_DHCP_OPTIONS_LEN "68") +set(CONFIG_LWIP_NUM_NETIF_CLIENT_DATA "0") +set(CONFIG_LWIP_DHCP_COARSE_TIMER_SECS "1") +set(CONFIG_LWIP_DHCPS "y") +set(CONFIG_LWIP_DHCPS_LEASE_UNIT "60") +set(CONFIG_LWIP_DHCPS_MAX_STATION_NUM "8") +set(CONFIG_LWIP_DHCPS_STATIC_ENTRIES "y") +set(CONFIG_LWIP_DHCPS_ADD_DNS "y") +set(CONFIG_LWIP_AUTOIP "") +set(CONFIG_LWIP_IPV4 "y") +set(CONFIG_LWIP_IPV6 "y") +set(CONFIG_LWIP_IPV6_AUTOCONFIG "") +set(CONFIG_LWIP_IPV6_NUM_ADDRESSES "3") +set(CONFIG_LWIP_IPV6_FORWARD "") +set(CONFIG_LWIP_NETIF_STATUS_CALLBACK "") +set(CONFIG_LWIP_NETIF_LOOPBACK "y") +set(CONFIG_LWIP_LOOPBACK_MAX_PBUFS "8") +set(CONFIG_LWIP_MAX_ACTIVE_TCP "16") +set(CONFIG_LWIP_MAX_LISTENING_TCP "16") +set(CONFIG_LWIP_TCP_HIGH_SPEED_RETRANSMISSION "y") +set(CONFIG_LWIP_TCP_MAXRTX "12") +set(CONFIG_LWIP_TCP_SYNMAXRTX "12") +set(CONFIG_LWIP_TCP_MSS "1440") +set(CONFIG_LWIP_TCP_TMR_INTERVAL "250") +set(CONFIG_LWIP_TCP_MSL "60000") +set(CONFIG_LWIP_TCP_FIN_WAIT_TIMEOUT "20000") +set(CONFIG_LWIP_TCP_SND_BUF_DEFAULT "5760") +set(CONFIG_LWIP_TCP_WND_DEFAULT "5760") +set(CONFIG_LWIP_TCP_RECVMBOX_SIZE "6") +set(CONFIG_LWIP_TCP_ACCEPTMBOX_SIZE "6") +set(CONFIG_LWIP_TCP_QUEUE_OOSEQ "y") +set(CONFIG_LWIP_TCP_OOSEQ_TIMEOUT "6") +set(CONFIG_LWIP_TCP_OOSEQ_MAX_PBUFS "4") +set(CONFIG_LWIP_TCP_SACK_OUT "") +set(CONFIG_LWIP_TCP_OVERSIZE_MSS "y") +set(CONFIG_LWIP_TCP_OVERSIZE_QUARTER_MSS "") +set(CONFIG_LWIP_TCP_OVERSIZE_DISABLE "") +set(CONFIG_LWIP_TCP_RTO_TIME "1500") +set(CONFIG_LWIP_MAX_UDP_PCBS "16") +set(CONFIG_LWIP_UDP_RECVMBOX_SIZE "6") +set(CONFIG_LWIP_CHECKSUM_CHECK_IP "") +set(CONFIG_LWIP_CHECKSUM_CHECK_UDP "") +set(CONFIG_LWIP_CHECKSUM_CHECK_ICMP "y") +set(CONFIG_LWIP_TCPIP_TASK_STACK_SIZE "3072") +set(CONFIG_LWIP_TCPIP_TASK_AFFINITY_NO_AFFINITY "y") +set(CONFIG_LWIP_TCPIP_TASK_AFFINITY_CPU0 "") +set(CONFIG_LWIP_TCPIP_TASK_AFFINITY "0x7fffffff") +set(CONFIG_LWIP_IPV6_MEMP_NUM_ND6_QUEUE "3") +set(CONFIG_LWIP_IPV6_ND6_NUM_NEIGHBORS "5") +set(CONFIG_LWIP_IPV6_ND6_NUM_PREFIXES "5") +set(CONFIG_LWIP_IPV6_ND6_NUM_ROUTERS "3") +set(CONFIG_LWIP_IPV6_ND6_NUM_DESTINATIONS "10") +set(CONFIG_LWIP_PPP_SUPPORT "") +set(CONFIG_LWIP_SLIP_SUPPORT "") +set(CONFIG_LWIP_ICMP "y") +set(CONFIG_LWIP_MULTICAST_PING "") +set(CONFIG_LWIP_BROADCAST_PING "") +set(CONFIG_LWIP_MAX_RAW_PCBS "16") +set(CONFIG_LWIP_SNTP_MAX_SERVERS "1") +set(CONFIG_LWIP_DHCP_GET_NTP_SRV "") +set(CONFIG_LWIP_SNTP_UPDATE_DELAY "3600000") +set(CONFIG_LWIP_SNTP_STARTUP_DELAY "y") +set(CONFIG_LWIP_SNTP_MAXIMUM_STARTUP_DELAY "5000") +set(CONFIG_LWIP_DNS_MAX_HOST_IP "1") +set(CONFIG_LWIP_DNS_MAX_SERVERS "3") +set(CONFIG_LWIP_FALLBACK_DNS_SERVER_SUPPORT "") +set(CONFIG_LWIP_DNS_SETSERVER_WITH_NETIF "") +set(CONFIG_LWIP_BRIDGEIF_MAX_PORTS "7") +set(CONFIG_LWIP_ESP_LWIP_ASSERT "y") +set(CONFIG_LWIP_HOOK_TCP_ISN_NONE "") +set(CONFIG_LWIP_HOOK_TCP_ISN_DEFAULT "y") +set(CONFIG_LWIP_HOOK_TCP_ISN_CUSTOM "") +set(CONFIG_LWIP_HOOK_IP6_ROUTE_NONE "y") +set(CONFIG_LWIP_HOOK_IP6_ROUTE_DEFAULT "") +set(CONFIG_LWIP_HOOK_IP6_ROUTE_CUSTOM "") +set(CONFIG_LWIP_HOOK_ND6_GET_GW_NONE "y") +set(CONFIG_LWIP_HOOK_ND6_GET_GW_DEFAULT "") +set(CONFIG_LWIP_HOOK_ND6_GET_GW_CUSTOM "") +set(CONFIG_LWIP_HOOK_IP6_SELECT_SRC_ADDR_NONE "y") +set(CONFIG_LWIP_HOOK_IP6_SELECT_SRC_ADDR_DEFAULT "") +set(CONFIG_LWIP_HOOK_IP6_SELECT_SRC_ADDR_CUSTOM "") +set(CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_NONE "y") +set(CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_DEFAULT "") +set(CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_CUSTOM "") +set(CONFIG_LWIP_HOOK_DNS_EXT_RESOLVE_NONE "y") +set(CONFIG_LWIP_HOOK_DNS_EXT_RESOLVE_CUSTOM "") +set(CONFIG_LWIP_HOOK_IP6_INPUT_NONE "") +set(CONFIG_LWIP_HOOK_IP6_INPUT_DEFAULT "y") +set(CONFIG_LWIP_HOOK_IP6_INPUT_CUSTOM "") +set(CONFIG_LWIP_DEBUG "") +set(CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC "y") +set(CONFIG_MBEDTLS_DEFAULT_MEM_ALLOC "") +set(CONFIG_MBEDTLS_CUSTOM_MEM_ALLOC "") +set(CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN "y") +set(CONFIG_MBEDTLS_SSL_IN_CONTENT_LEN "16384") +set(CONFIG_MBEDTLS_SSL_OUT_CONTENT_LEN "4096") +set(CONFIG_MBEDTLS_DYNAMIC_BUFFER "y") +set(CONFIG_MBEDTLS_DYNAMIC_FREE_CONFIG_DATA "y") +set(CONFIG_MBEDTLS_DYNAMIC_FREE_CA_CERT "y") +set(CONFIG_MBEDTLS_DEBUG "") +set(CONFIG_MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH "") +set(CONFIG_MBEDTLS_X509_TRUSTED_CERT_CALLBACK "") +set(CONFIG_MBEDTLS_SSL_CONTEXT_SERIALIZATION "") +set(CONFIG_MBEDTLS_SSL_KEEP_PEER_CERTIFICATE "y") +set(CONFIG_MBEDTLS_PKCS7_C "y") +set(CONFIG_MBEDTLS_CERTIFICATE_BUNDLE "y") +set(CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_FULL "") +set(CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_CMN "y") +set(CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_NONE "") +set(CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE "") +set(CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEPRECATED_LIST "") +set(CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_MAX_CERTS "200") +set(CONFIG_MBEDTLS_ECP_RESTARTABLE "") +set(CONFIG_MBEDTLS_CMAC_C "y") +set(CONFIG_MBEDTLS_HARDWARE_AES "y") +set(CONFIG_MBEDTLS_AES_USE_INTERRUPT "y") +set(CONFIG_MBEDTLS_AES_INTERRUPT_LEVEL "0") +set(CONFIG_MBEDTLS_GCM_SUPPORT_NON_AES_CIPHER "y") +set(CONFIG_MBEDTLS_HARDWARE_MPI "y") +set(CONFIG_MBEDTLS_LARGE_KEY_SOFTWARE_MPI "y") +set(CONFIG_MBEDTLS_MPI_USE_INTERRUPT "y") +set(CONFIG_MBEDTLS_MPI_INTERRUPT_LEVEL "0") +set(CONFIG_MBEDTLS_HARDWARE_SHA "y") +set(CONFIG_MBEDTLS_ROM_MD5 "y") +set(CONFIG_MBEDTLS_ATCA_HW_ECDSA_SIGN "") +set(CONFIG_MBEDTLS_ATCA_HW_ECDSA_VERIFY "") +set(CONFIG_MBEDTLS_HAVE_TIME "y") +set(CONFIG_MBEDTLS_PLATFORM_TIME_ALT "") +set(CONFIG_MBEDTLS_HAVE_TIME_DATE "") +set(CONFIG_MBEDTLS_ECDSA_DETERMINISTIC "y") +set(CONFIG_MBEDTLS_SHA512_C "y") +set(CONFIG_MBEDTLS_SHA3_C "") +set(CONFIG_MBEDTLS_TLS_SERVER_AND_CLIENT "y") +set(CONFIG_MBEDTLS_TLS_SERVER_ONLY "") +set(CONFIG_MBEDTLS_TLS_CLIENT_ONLY "") +set(CONFIG_MBEDTLS_TLS_DISABLED "") +set(CONFIG_MBEDTLS_TLS_SERVER "y") +set(CONFIG_MBEDTLS_TLS_CLIENT "y") +set(CONFIG_MBEDTLS_TLS_ENABLED "y") +set(CONFIG_MBEDTLS_PSK_MODES "") +set(CONFIG_MBEDTLS_KEY_EXCHANGE_RSA "y") +set(CONFIG_MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE "y") +set(CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_RSA "y") +set(CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA "y") +set(CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA "y") +set(CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_RSA "y") +set(CONFIG_MBEDTLS_SSL_RENEGOTIATION "y") +set(CONFIG_MBEDTLS_SSL_PROTO_TLS1_2 "y") +set(CONFIG_MBEDTLS_SSL_PROTO_GMTSSL1_1 "") +set(CONFIG_MBEDTLS_SSL_PROTO_DTLS "") +set(CONFIG_MBEDTLS_SSL_ALPN "y") +set(CONFIG_MBEDTLS_CLIENT_SSL_SESSION_TICKETS "y") +set(CONFIG_MBEDTLS_SERVER_SSL_SESSION_TICKETS "y") +set(CONFIG_MBEDTLS_AES_C "y") +set(CONFIG_MBEDTLS_CAMELLIA_C "") +set(CONFIG_MBEDTLS_DES_C "") +set(CONFIG_MBEDTLS_BLOWFISH_C "") +set(CONFIG_MBEDTLS_XTEA_C "") +set(CONFIG_MBEDTLS_CCM_C "y") +set(CONFIG_MBEDTLS_GCM_C "y") +set(CONFIG_MBEDTLS_NIST_KW_C "") +set(CONFIG_MBEDTLS_RIPEMD160_C "") +set(CONFIG_MBEDTLS_PEM_PARSE_C "y") +set(CONFIG_MBEDTLS_PEM_WRITE_C "y") +set(CONFIG_MBEDTLS_X509_CRL_PARSE_C "y") +set(CONFIG_MBEDTLS_X509_CSR_PARSE_C "y") +set(CONFIG_MBEDTLS_ECP_C "y") +set(CONFIG_MBEDTLS_PK_PARSE_EC_EXTENDED "y") +set(CONFIG_MBEDTLS_PK_PARSE_EC_COMPRESSED "y") +set(CONFIG_MBEDTLS_DHM_C "") +set(CONFIG_MBEDTLS_ECDH_C "y") +set(CONFIG_MBEDTLS_ECDSA_C "y") +set(CONFIG_MBEDTLS_ECJPAKE_C "") +set(CONFIG_MBEDTLS_ECP_DP_SECP192R1_ENABLED "y") +set(CONFIG_MBEDTLS_ECP_DP_SECP224R1_ENABLED "y") +set(CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED "y") +set(CONFIG_MBEDTLS_ECP_DP_SECP384R1_ENABLED "y") +set(CONFIG_MBEDTLS_ECP_DP_SECP521R1_ENABLED "y") +set(CONFIG_MBEDTLS_ECP_DP_SECP192K1_ENABLED "y") +set(CONFIG_MBEDTLS_ECP_DP_SECP224K1_ENABLED "y") +set(CONFIG_MBEDTLS_ECP_DP_SECP256K1_ENABLED "y") +set(CONFIG_MBEDTLS_ECP_DP_BP256R1_ENABLED "y") +set(CONFIG_MBEDTLS_ECP_DP_BP384R1_ENABLED "y") +set(CONFIG_MBEDTLS_ECP_DP_BP512R1_ENABLED "y") +set(CONFIG_MBEDTLS_ECP_DP_CURVE25519_ENABLED "y") +set(CONFIG_MBEDTLS_ECP_NIST_OPTIM "y") +set(CONFIG_MBEDTLS_ECP_FIXED_POINT_OPTIM "") +set(CONFIG_MBEDTLS_POLY1305_C "") +set(CONFIG_MBEDTLS_CHACHA20_C "") +set(CONFIG_MBEDTLS_HKDF_C "") +set(CONFIG_MBEDTLS_THREADING_C "") +set(CONFIG_MBEDTLS_ERROR_STRINGS "y") +set(CONFIG_MBEDTLS_FS_IO "y") +set(CONFIG_MQTT_PROTOCOL_311 "y") +set(CONFIG_MQTT_PROTOCOL_5 "") +set(CONFIG_MQTT_TRANSPORT_SSL "y") +set(CONFIG_MQTT_TRANSPORT_WEBSOCKET "y") +set(CONFIG_MQTT_TRANSPORT_WEBSOCKET_SECURE "y") +set(CONFIG_MQTT_MSG_ID_INCREMENTAL "") +set(CONFIG_MQTT_SKIP_PUBLISH_IF_DISCONNECTED "") +set(CONFIG_MQTT_REPORT_DELETED_MESSAGES "") +set(CONFIG_MQTT_USE_CUSTOM_CONFIG "") +set(CONFIG_MQTT_TASK_CORE_SELECTION_ENABLED "") +set(CONFIG_MQTT_CUSTOM_OUTBOX "") +set(CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF "y") +set(CONFIG_NEWLIB_STDOUT_LINE_ENDING_LF "") +set(CONFIG_NEWLIB_STDOUT_LINE_ENDING_CR "") +set(CONFIG_NEWLIB_STDIN_LINE_ENDING_CRLF "") +set(CONFIG_NEWLIB_STDIN_LINE_ENDING_LF "") +set(CONFIG_NEWLIB_STDIN_LINE_ENDING_CR "y") +set(CONFIG_NEWLIB_NANO_FORMAT "") +set(CONFIG_NEWLIB_TIME_SYSCALL_USE_RTC_HRT "y") +set(CONFIG_NEWLIB_TIME_SYSCALL_USE_RTC "") +set(CONFIG_NEWLIB_TIME_SYSCALL_USE_HRT "") +set(CONFIG_NEWLIB_TIME_SYSCALL_USE_NONE "") +set(CONFIG_NVS_ENCRYPTION "") +set(CONFIG_NVS_ASSERT_ERROR_CHECK "") +set(CONFIG_NVS_LEGACY_DUP_KEYS_COMPATIBILITY "") +set(CONFIG_OPENTHREAD_ENABLED "") +set(CONFIG_OPENTHREAD_SPINEL_ONLY "") +set(CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_0 "y") +set(CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_1 "y") +set(CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_2 "y") +set(CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_PATCH_VERSION "y") +set(CONFIG_PTHREAD_TASK_PRIO_DEFAULT "5") +set(CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT "3072") +set(CONFIG_PTHREAD_STACK_MIN "768") +set(CONFIG_PTHREAD_TASK_CORE_DEFAULT "-1") +set(CONFIG_PTHREAD_TASK_NAME_DEFAULT "pthread") +set(CONFIG_MMU_PAGE_SIZE_64KB "y") +set(CONFIG_MMU_PAGE_MODE "64KB") +set(CONFIG_MMU_PAGE_SIZE "0x10000") +set(CONFIG_SPI_FLASH_BROWNOUT_RESET_XMC "y") +set(CONFIG_SPI_FLASH_BROWNOUT_RESET "y") +set(CONFIG_SPI_FLASH_AUTO_SUSPEND "") +set(CONFIG_SPI_FLASH_SUSPEND_TSUS_VAL_US "50") +set(CONFIG_SPI_FLASH_FORCE_ENABLE_XMC_C_SUSPEND "") +set(CONFIG_SPI_FLASH_VERIFY_WRITE "") +set(CONFIG_SPI_FLASH_ENABLE_COUNTERS "") +set(CONFIG_SPI_FLASH_ROM_DRIVER_PATCH "y") +set(CONFIG_SPI_FLASH_ROM_IMPL "") +set(CONFIG_SPI_FLASH_DANGEROUS_WRITE_ABORTS "y") +set(CONFIG_SPI_FLASH_DANGEROUS_WRITE_FAILS "") +set(CONFIG_SPI_FLASH_DANGEROUS_WRITE_ALLOWED "") +set(CONFIG_SPI_FLASH_BYPASS_BLOCK_ERASE "") +set(CONFIG_SPI_FLASH_YIELD_DURING_ERASE "y") +set(CONFIG_SPI_FLASH_ERASE_YIELD_DURATION_MS "20") +set(CONFIG_SPI_FLASH_ERASE_YIELD_TICKS "1") +set(CONFIG_SPI_FLASH_WRITE_CHUNK_SIZE "8192") +set(CONFIG_SPI_FLASH_SIZE_OVERRIDE "") +set(CONFIG_SPI_FLASH_CHECK_ERASE_TIMEOUT_DISABLED "") +set(CONFIG_SPI_FLASH_OVERRIDE_CHIP_DRIVER_LIST "") +set(CONFIG_SPI_FLASH_VENDOR_XMC_SUPPORTED "y") +set(CONFIG_SPI_FLASH_VENDOR_GD_SUPPORTED "y") +set(CONFIG_SPI_FLASH_VENDOR_ISSI_SUPPORTED "y") +set(CONFIG_SPI_FLASH_VENDOR_MXIC_SUPPORTED "y") +set(CONFIG_SPI_FLASH_VENDOR_WINBOND_SUPPORTED "y") +set(CONFIG_SPI_FLASH_VENDOR_BOYA_SUPPORTED "y") +set(CONFIG_SPI_FLASH_VENDOR_TH_SUPPORTED "y") +set(CONFIG_SPI_FLASH_SUPPORT_ISSI_CHIP "y") +set(CONFIG_SPI_FLASH_SUPPORT_MXIC_CHIP "y") +set(CONFIG_SPI_FLASH_SUPPORT_GD_CHIP "y") +set(CONFIG_SPI_FLASH_SUPPORT_WINBOND_CHIP "y") +set(CONFIG_SPI_FLASH_SUPPORT_BOYA_CHIP "y") +set(CONFIG_SPI_FLASH_SUPPORT_TH_CHIP "y") +set(CONFIG_SPI_FLASH_ENABLE_ENCRYPTED_READ_WRITE "y") +set(CONFIG_SPIFFS_MAX_PARTITIONS "3") +set(CONFIG_SPIFFS_CACHE "y") +set(CONFIG_SPIFFS_CACHE_WR "y") +set(CONFIG_SPIFFS_CACHE_STATS "") +set(CONFIG_SPIFFS_PAGE_CHECK "y") +set(CONFIG_SPIFFS_GC_MAX_RUNS "10") +set(CONFIG_SPIFFS_GC_STATS "") +set(CONFIG_SPIFFS_PAGE_SIZE "256") +set(CONFIG_SPIFFS_OBJ_NAME_LEN "32") +set(CONFIG_SPIFFS_FOLLOW_SYMLINKS "") +set(CONFIG_SPIFFS_USE_MAGIC "y") +set(CONFIG_SPIFFS_USE_MAGIC_LENGTH "y") +set(CONFIG_SPIFFS_META_LENGTH "4") +set(CONFIG_SPIFFS_USE_MTIME "y") +set(CONFIG_SPIFFS_DBG "") +set(CONFIG_SPIFFS_API_DBG "") +set(CONFIG_SPIFFS_GC_DBG "") +set(CONFIG_SPIFFS_CACHE_DBG "") +set(CONFIG_SPIFFS_CHECK_DBG "") +set(CONFIG_SPIFFS_TEST_VISUALISATION "") +set(CONFIG_WS_TRANSPORT "y") +set(CONFIG_WS_BUFFER_SIZE "1024") +set(CONFIG_WS_DYNAMIC_BUFFER "") +set(CONFIG_UNITY_ENABLE_FLOAT "y") +set(CONFIG_UNITY_ENABLE_DOUBLE "y") +set(CONFIG_UNITY_ENABLE_64BIT "") +set(CONFIG_UNITY_ENABLE_COLOR "") +set(CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER "y") +set(CONFIG_UNITY_ENABLE_FIXTURE "") +set(CONFIG_UNITY_ENABLE_BACKTRACE_ON_FAIL "") +set(CONFIG_VFS_SUPPORT_IO "y") +set(CONFIG_VFS_SUPPORT_DIR "y") +set(CONFIG_VFS_SUPPORT_SELECT "y") +set(CONFIG_VFS_SUPPRESS_SELECT_DEBUG_OUTPUT "y") +set(CONFIG_VFS_SELECT_IN_RAM "") +set(CONFIG_VFS_SUPPORT_TERMIOS "y") +set(CONFIG_VFS_MAX_COUNT "8") +set(CONFIG_VFS_SEMIHOSTFS_MAX_MOUNT_POINTS "1") +set(CONFIG_VFS_INITIALIZE_DEV_NULL "y") +set(CONFIG_WL_SECTOR_SIZE_512 "") +set(CONFIG_WL_SECTOR_SIZE_4096 "y") +set(CONFIG_WL_SECTOR_SIZE "4096") +set(CONFIG_WIFI_PROV_SCAN_MAX_ENTRIES "16") +set(CONFIG_WIFI_PROV_AUTOSTOP_TIMEOUT "30") +set(CONFIG_WIFI_PROV_BLE_BONDING "") +set(CONFIG_WIFI_PROV_BLE_SEC_CONN "y") +set(CONFIG_WIFI_PROV_BLE_FORCE_ENCRYPTION "") +set(CONFIG_WIFI_PROV_BLE_NOTIFY "") +set(CONFIG_WIFI_PROV_KEEP_BLE_ON_AFTER_PROV "") +set(CONFIG_WIFI_PROV_STA_ALL_CHANNEL_SCAN "y") +set(CONFIG_WIFI_PROV_STA_FAST_SCAN "") +set(CONFIG_IO_GLITCH_FILTER_TIME_MS "50") +set(CONFIG_WS2812_LED_ENABLE "y") +set(CONFIG_WS2812_LED_GPIO "8") +set(CONFIG_SERIAL_FLASHER_MD5_ENABLED "y") +set(CONFIG_SERIAL_FLASHER_INTERFACE_UART "y") +set(CONFIG_SERIAL_FLASHER_INTERFACE_SPI "") +set(CONFIG_SERIAL_FLASHER_INTERFACE_USB "") +set(CONFIG_SERIAL_FLASHER_INTERFACE_SDIO "") +set(CONFIG_SERIAL_FLASHER_RESET_HOLD_TIME_MS "100") +set(CONFIG_SERIAL_FLASHER_BOOT_HOLD_TIME_MS "50") +set(CONFIG_SERIAL_FLASHER_DEBUG_TRACE "") +set(CONFIG_SERIAL_FLASHER_WRITE_BLOCK_RETRIES "3") +set(CONFIG_SERIAL_FLASHER_RESET_INVERT "") +set(CONFIG_SERIAL_FLASHER_BOOT_INVERT "") +set(CONFIG_DIAG_DATA_STORE_RTC "y") +set(CONFIG_DIAG_DATA_STORE_FLASH "") +set(CONFIG_DIAG_DATA_STORE_DBG_PRINTS "") +set(CONFIG_DIAG_DATA_STORE_REPORTING_WATERMARK_PERCENT "80") +set(CONFIG_RTC_STORE_DATA_SIZE "6144") +set(CONFIG_RTC_STORE_CRITICAL_DATA_SIZE "4096") +set(CONFIG_DIAG_LOG_MSG_ARG_FORMAT_TLV "y") +set(CONFIG_DIAG_LOG_MSG_ARG_FORMAT_STRING "") +set(CONFIG_DIAG_LOG_MSG_ARG_MAX_SIZE "64") +set(CONFIG_DIAG_LOG_DROP_WIFI_LOGS "y") +set(CONFIG_DIAG_ENABLE_WRAP_LOG_FUNCTIONS "") +set(CONFIG_DIAG_ENABLE_METRICS "y") +set(CONFIG_DIAG_METRICS_MAX_COUNT "20") +set(CONFIG_DIAG_ENABLE_HEAP_METRICS "y") +set(CONFIG_DIAG_HEAP_POLLING_INTERVAL "30") +set(CONFIG_DIAG_ENABLE_WIFI_METRICS "y") +set(CONFIG_DIAG_WIFI_POLLING_INTERVAL "30") +set(CONFIG_DIAG_ENABLE_VARIABLES "y") +set(CONFIG_DIAG_VARIABLES_MAX_COUNT "20") +set(CONFIG_DIAG_ENABLE_NETWORK_VARIABLES "y") +set(CONFIG_DIAG_MORE_NETWORK_VARS "") +set(CONFIG_DIAG_USE_EXTERNAL_LOG_WRAP "") +set(CONFIG_ESP_INSIGHTS_ENABLED "") +set(CONFIG_ESP_INSIGHTS_TRANSPORT_MQTT "y") +set(CONFIG_ESP_INSIGHTS_TRANSPORT_HTTPS "") +set(CONFIG_ESP_INSIGHTS_CLOUD_POST_MIN_INTERVAL_SEC "60") +set(CONFIG_ESP_INSIGHTS_CLOUD_POST_MAX_INTERVAL_SEC "240") +set(CONFIG_ESP_INSIGHTS_META_VERSION_10 "y") +set(CONFIG_AUTO_UPDATE_RCP "") +set(CONFIG_CREATE_OTA_IMAGE_WITH_RCP_FW "") +set(CONFIG_ESP_SECURE_CERT_DS_PERIPHERAL "y") +set(CONFIG_ESP_SECURE_CERT_SUPPORT_LEGACY_FORMATS "") +set(CONFIG_JSMN_PARENT_LINKS "") +set(CONFIG_JSMN_STRICT "") +set(CONFIG_JSMN_STATIC "") +set(CONFIG_MDNS_MAX_INTERFACES "3") +set(CONFIG_MDNS_MAX_SERVICES "10") +set(CONFIG_MDNS_TASK_PRIORITY "1") +set(CONFIG_MDNS_ACTION_QUEUE_LEN "16") +set(CONFIG_MDNS_TASK_STACK_SIZE "4096") +set(CONFIG_MDNS_TASK_AFFINITY_NO_AFFINITY "") +set(CONFIG_MDNS_TASK_AFFINITY_CPU0 "y") +set(CONFIG_MDNS_TASK_AFFINITY "0x0") +set(CONFIG_MDNS_TASK_CREATE_FROM_INTERNAL "y") +set(CONFIG_MDNS_MEMORY_ALLOC_INTERNAL "y") +set(CONFIG_MDNS_MEMORY_CUSTOM_IMPL "") +set(CONFIG_MDNS_SERVICE_ADD_TIMEOUT_MS "2000") +set(CONFIG_MDNS_TIMER_PERIOD_MS "100") +set(CONFIG_MDNS_NETWORKING_SOCKET "") +set(CONFIG_MDNS_SKIP_SUPPRESSING_OWN_QUERIES "") +set(CONFIG_MDNS_ENABLE_DEBUG_PRINTS "") +set(CONFIG_MDNS_ENABLE_CONSOLE_CLI "y") +set(CONFIG_MDNS_RESPOND_REVERSE_QUERIES "") +set(CONFIG_MDNS_MULTIPLE_INSTANCE "y") +set(CONFIG_MDNS_PREDEF_NETIF_STA "y") +set(CONFIG_MDNS_PREDEF_NETIF_AP "y") +set(CONFIG_MDNS_PREDEF_NETIF_ETH "y") +set(CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI "y") +set(CONFIG_NETWORK_PROV_SCAN_MAX_ENTRIES "16") +set(CONFIG_NETWORK_PROV_AUTOSTOP_TIMEOUT "30") +set(CONFIG_NETWORK_PROV_BLE_BONDING "") +set(CONFIG_NETWORK_PROV_BLE_SEC_CONN "y") +set(CONFIG_NETWORK_PROV_BLE_FORCE_ENCRYPTION "") +set(CONFIG_NETWORK_PROV_KEEP_BLE_ON_AFTER_PROV "") +set(CONFIG_NETWORK_PROV_WIFI_STA_ALL_CHANNEL_SCAN "y") +set(CONFIG_NETWORK_PROV_WIFI_STA_FAST_SCAN "") +set(CONFIG_ESP_RMAKER_LIB_ESP_MQTT "y") +set(CONFIG_ESP_RMAKER_LIB_AWS_IOT "") +set(CONFIG_ESP_RMAKER_MQTT_GLUE_LIB "1") +set(CONFIG_ESP_RMAKER_MQTT_PORT_443 "y") +set(CONFIG_ESP_RMAKER_MQTT_PORT_8883 "") +set(CONFIG_ESP_RMAKER_MQTT_PORT "1") +set(CONFIG_ESP_RMAKER_MQTT_PERSISTENT_SESSION "") +set(CONFIG_ESP_RMAKER_MQTT_SEND_USERNAME "y") +set(CONFIG_ESP_RMAKER_MQTT_PRODUCT_NAME "RMDev") +set(CONFIG_ESP_RMAKER_MQTT_PRODUCT_VERSION "1x0") +set(CONFIG_ESP_RMAKER_MQTT_PRODUCT_SKU "EX00") +set(CONFIG_ESP_RMAKER_MQTT_USE_CERT_BUNDLE "y") +set(CONFIG_ESP_RMAKER_MAX_MQTT_SUBSCRIPTIONS "10") +set(CONFIG_ESP_RMAKER_MQTT_KEEP_ALIVE_INTERVAL "120") +set(CONFIG_ESP_RMAKER_NETWORK_OVER_WIFI "y") +set(CONFIG_ESP_RMAKER_WORK_QUEUE_TASK_STACK "5120") +set(CONFIG_ESP_RMAKER_WORK_QUEUE_TASK_PRIORITY "5") +set(CONFIG_ESP_RMAKER_FACTORY_PARTITION_NAME "fctry") +set(CONFIG_ESP_RMAKER_FACTORY_NAMESPACE "rmaker_creds") +set(CONFIG_ESP_RMAKER_DEF_TIMEZONE "Asia/Shanghai") +set(CONFIG_ESP_RMAKER_SNTP_SERVER_NAME "pool.ntp.org") +set(CONFIG_ESP_RMAKER_MAX_COMMANDS "10") +set(CONFIG_IDF_EXPERIMENTAL_FEATURES "") +set(CONFIGS_LIST CONFIG_SOC_ADC_SUPPORTED;CONFIG_SOC_DEDICATED_GPIO_SUPPORTED;CONFIG_SOC_UART_SUPPORTED;CONFIG_SOC_GDMA_SUPPORTED;CONFIG_SOC_AHB_GDMA_SUPPORTED;CONFIG_SOC_GPTIMER_SUPPORTED;CONFIG_SOC_TWAI_SUPPORTED;CONFIG_SOC_BT_SUPPORTED;CONFIG_SOC_ASYNC_MEMCPY_SUPPORTED;CONFIG_SOC_USB_SERIAL_JTAG_SUPPORTED;CONFIG_SOC_TEMP_SENSOR_SUPPORTED;CONFIG_SOC_XT_WDT_SUPPORTED;CONFIG_SOC_PHY_SUPPORTED;CONFIG_SOC_WIFI_SUPPORTED;CONFIG_SOC_SUPPORTS_SECURE_DL_MODE;CONFIG_SOC_EFUSE_KEY_PURPOSE_FIELD;CONFIG_SOC_EFUSE_HAS_EFUSE_RST_BUG;CONFIG_SOC_EFUSE_SUPPORTED;CONFIG_SOC_RTC_FAST_MEM_SUPPORTED;CONFIG_SOC_RTC_MEM_SUPPORTED;CONFIG_SOC_I2S_SUPPORTED;CONFIG_SOC_RMT_SUPPORTED;CONFIG_SOC_SDM_SUPPORTED;CONFIG_SOC_GPSPI_SUPPORTED;CONFIG_SOC_LEDC_SUPPORTED;CONFIG_SOC_I2C_SUPPORTED;CONFIG_SOC_SYSTIMER_SUPPORTED;CONFIG_SOC_SUPPORT_COEXISTENCE;CONFIG_SOC_AES_SUPPORTED;CONFIG_SOC_MPI_SUPPORTED;CONFIG_SOC_SHA_SUPPORTED;CONFIG_SOC_HMAC_SUPPORTED;CONFIG_SOC_DIG_SIGN_SUPPORTED;CONFIG_SOC_FLASH_ENC_SUPPORTED;CONFIG_SOC_SECURE_BOOT_SUPPORTED;CONFIG_SOC_MEMPROT_SUPPORTED;CONFIG_SOC_BOD_SUPPORTED;CONFIG_SOC_CLK_TREE_SUPPORTED;CONFIG_SOC_ASSIST_DEBUG_SUPPORTED;CONFIG_SOC_WDT_SUPPORTED;CONFIG_SOC_SPI_FLASH_SUPPORTED;CONFIG_SOC_RNG_SUPPORTED;CONFIG_SOC_LIGHT_SLEEP_SUPPORTED;CONFIG_SOC_DEEP_SLEEP_SUPPORTED;CONFIG_SOC_LP_PERIPH_SHARE_INTERRUPT;CONFIG_SOC_PM_SUPPORTED;CONFIG_SOC_XTAL_SUPPORT_40M;CONFIG_SOC_AES_SUPPORT_DMA;CONFIG_SOC_AES_GDMA;CONFIG_SOC_AES_SUPPORT_AES_128;CONFIG_SOC_AES_SUPPORT_AES_256;CONFIG_SOC_ADC_DIG_CTRL_SUPPORTED;CONFIG_SOC_ADC_ARBITER_SUPPORTED;CONFIG_SOC_ADC_DIG_IIR_FILTER_SUPPORTED;CONFIG_SOC_ADC_MONITOR_SUPPORTED;CONFIG_SOC_ADC_DMA_SUPPORTED;CONFIG_SOC_ADC_PERIPH_NUM;CONFIG_SOC_ADC_MAX_CHANNEL_NUM;CONFIG_SOC_ADC_ATTEN_NUM;CONFIG_SOC_ADC_DIGI_CONTROLLER_NUM;CONFIG_SOC_ADC_PATT_LEN_MAX;CONFIG_SOC_ADC_DIGI_MIN_BITWIDTH;CONFIG_SOC_ADC_DIGI_MAX_BITWIDTH;CONFIG_SOC_ADC_DIGI_RESULT_BYTES;CONFIG_SOC_ADC_DIGI_DATA_BYTES_PER_CONV;CONFIG_SOC_ADC_DIGI_IIR_FILTER_NUM;CONFIG_SOC_ADC_DIGI_MONITOR_NUM;CONFIG_SOC_ADC_SAMPLE_FREQ_THRES_HIGH;CONFIG_SOC_ADC_SAMPLE_FREQ_THRES_LOW;CONFIG_SOC_ADC_RTC_MIN_BITWIDTH;CONFIG_SOC_ADC_RTC_MAX_BITWIDTH;CONFIG_SOC_ADC_CALIBRATION_V1_SUPPORTED;CONFIG_SOC_ADC_SELF_HW_CALI_SUPPORTED;CONFIG_SOC_ADC_SHARED_POWER;CONFIG_SOC_APB_BACKUP_DMA;CONFIG_SOC_BROWNOUT_RESET_SUPPORTED;CONFIG_SOC_SHARED_IDCACHE_SUPPORTED;CONFIG_SOC_CACHE_MEMORY_IBANK_SIZE;CONFIG_SOC_CPU_CORES_NUM;CONFIG_SOC_CPU_INTR_NUM;CONFIG_SOC_CPU_HAS_FLEXIBLE_INTC;CONFIG_SOC_CPU_HAS_CSR_PC;CONFIG_SOC_CPU_BREAKPOINTS_NUM;CONFIG_SOC_CPU_WATCHPOINTS_NUM;CONFIG_SOC_CPU_WATCHPOINT_MAX_REGION_SIZE;CONFIG_SOC_DS_SIGNATURE_MAX_BIT_LEN;CONFIG_SOC_DS_KEY_PARAM_MD_IV_LENGTH;CONFIG_SOC_DS_KEY_CHECK_MAX_WAIT_US;CONFIG_SOC_AHB_GDMA_VERSION;CONFIG_SOC_GDMA_NUM_GROUPS_MAX;CONFIG_SOC_GDMA_PAIRS_PER_GROUP_MAX;CONFIG_SOC_GPIO_PORT;CONFIG_SOC_GPIO_PIN_COUNT;CONFIG_SOC_GPIO_SUPPORT_PIN_GLITCH_FILTER;CONFIG_SOC_GPIO_FILTER_CLK_SUPPORT_APB;CONFIG_SOC_GPIO_SUPPORT_FORCE_HOLD;CONFIG_SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP;CONFIG_SOC_GPIO_IN_RANGE_MAX;CONFIG_SOC_GPIO_OUT_RANGE_MAX;CONFIG_SOC_GPIO_DEEP_SLEEP_WAKE_VALID_GPIO_MASK;CONFIG_SOC_GPIO_DEEP_SLEEP_WAKE_SUPPORTED_PIN_CNT;CONFIG_SOC_GPIO_VALID_DIGITAL_IO_PAD_MASK;CONFIG_SOC_GPIO_CLOCKOUT_BY_GPIO_MATRIX;CONFIG_SOC_GPIO_CLOCKOUT_CHANNEL_NUM;CONFIG_SOC_GPIO_SUPPORT_HOLD_IO_IN_DSLP;CONFIG_SOC_DEDIC_GPIO_OUT_CHANNELS_NUM;CONFIG_SOC_DEDIC_GPIO_IN_CHANNELS_NUM;CONFIG_SOC_DEDIC_PERIPH_ALWAYS_ENABLE;CONFIG_SOC_I2C_NUM;CONFIG_SOC_HP_I2C_NUM;CONFIG_SOC_I2C_FIFO_LEN;CONFIG_SOC_I2C_CMD_REG_NUM;CONFIG_SOC_I2C_SUPPORT_SLAVE;CONFIG_SOC_I2C_SUPPORT_HW_CLR_BUS;CONFIG_SOC_I2C_SUPPORT_XTAL;CONFIG_SOC_I2C_SUPPORT_RTC;CONFIG_SOC_I2C_SUPPORT_10BIT_ADDR;CONFIG_SOC_I2C_SLAVE_SUPPORT_BROADCAST;CONFIG_SOC_I2C_SLAVE_CAN_GET_STRETCH_CAUSE;CONFIG_SOC_I2C_SLAVE_SUPPORT_I2CRAM_ACCESS;CONFIG_SOC_I2S_NUM;CONFIG_SOC_I2S_HW_VERSION_2;CONFIG_SOC_I2S_SUPPORTS_XTAL;CONFIG_SOC_I2S_SUPPORTS_PLL_F160M;CONFIG_SOC_I2S_SUPPORTS_PCM;CONFIG_SOC_I2S_SUPPORTS_PDM;CONFIG_SOC_I2S_SUPPORTS_PDM_TX;CONFIG_SOC_I2S_PDM_MAX_TX_LINES;CONFIG_SOC_I2S_SUPPORTS_TDM;CONFIG_SOC_LEDC_SUPPORT_APB_CLOCK;CONFIG_SOC_LEDC_SUPPORT_XTAL_CLOCK;CONFIG_SOC_LEDC_TIMER_NUM;CONFIG_SOC_LEDC_CHANNEL_NUM;CONFIG_SOC_LEDC_TIMER_BIT_WIDTH;CONFIG_SOC_LEDC_SUPPORT_FADE_STOP;CONFIG_SOC_MMU_LINEAR_ADDRESS_REGION_NUM;CONFIG_SOC_MMU_PERIPH_NUM;CONFIG_SOC_MPU_MIN_REGION_SIZE;CONFIG_SOC_MPU_REGIONS_MAX_NUM;CONFIG_SOC_RMT_GROUPS;CONFIG_SOC_RMT_TX_CANDIDATES_PER_GROUP;CONFIG_SOC_RMT_RX_CANDIDATES_PER_GROUP;CONFIG_SOC_RMT_CHANNELS_PER_GROUP;CONFIG_SOC_RMT_MEM_WORDS_PER_CHANNEL;CONFIG_SOC_RMT_SUPPORT_RX_PINGPONG;CONFIG_SOC_RMT_SUPPORT_RX_DEMODULATION;CONFIG_SOC_RMT_SUPPORT_TX_ASYNC_STOP;CONFIG_SOC_RMT_SUPPORT_TX_LOOP_COUNT;CONFIG_SOC_RMT_SUPPORT_TX_SYNCHRO;CONFIG_SOC_RMT_SUPPORT_TX_CARRIER_DATA_ONLY;CONFIG_SOC_RMT_SUPPORT_XTAL;CONFIG_SOC_RMT_SUPPORT_APB;CONFIG_SOC_RMT_SUPPORT_RC_FAST;CONFIG_SOC_RTC_CNTL_CPU_PD_DMA_BUS_WIDTH;CONFIG_SOC_RTC_CNTL_CPU_PD_REG_FILE_NUM;CONFIG_SOC_SLEEP_SYSTIMER_STALL_WORKAROUND;CONFIG_SOC_SLEEP_TGWDT_STOP_WORKAROUND;CONFIG_SOC_RTCIO_PIN_COUNT;CONFIG_SOC_MPI_MEM_BLOCKS_NUM;CONFIG_SOC_MPI_OPERATIONS_NUM;CONFIG_SOC_RSA_MAX_BIT_LEN;CONFIG_SOC_SHA_DMA_MAX_BUFFER_SIZE;CONFIG_SOC_SHA_SUPPORT_DMA;CONFIG_SOC_SHA_SUPPORT_RESUME;CONFIG_SOC_SHA_GDMA;CONFIG_SOC_SHA_SUPPORT_SHA1;CONFIG_SOC_SHA_SUPPORT_SHA224;CONFIG_SOC_SHA_SUPPORT_SHA256;CONFIG_SOC_SDM_GROUPS;CONFIG_SOC_SDM_CHANNELS_PER_GROUP;CONFIG_SOC_SDM_CLK_SUPPORT_APB;CONFIG_SOC_SPI_PERIPH_NUM;CONFIG_SOC_SPI_MAX_CS_NUM;CONFIG_SOC_SPI_MAXIMUM_BUFFER_SIZE;CONFIG_SOC_SPI_SUPPORT_DDRCLK;CONFIG_SOC_SPI_SLAVE_SUPPORT_SEG_TRANS;CONFIG_SOC_SPI_SUPPORT_CD_SIG;CONFIG_SOC_SPI_SUPPORT_CONTINUOUS_TRANS;CONFIG_SOC_SPI_SUPPORT_SLAVE_HD_VER2;CONFIG_SOC_SPI_SUPPORT_CLK_APB;CONFIG_SOC_SPI_SUPPORT_CLK_XTAL;CONFIG_SOC_SPI_PERIPH_SUPPORT_CONTROL_DUMMY_OUT;CONFIG_SOC_SPI_SCT_SUPPORTED;CONFIG_SOC_SPI_SCT_REG_NUM;CONFIG_SOC_SPI_SCT_BUFFER_NUM_MAX;CONFIG_SOC_SPI_SCT_CONF_BITLEN_MAX;CONFIG_SOC_MEMSPI_IS_INDEPENDENT;CONFIG_SOC_SPI_MAX_PRE_DIVIDER;CONFIG_SOC_SPI_MEM_SUPPORT_AUTO_WAIT_IDLE;CONFIG_SOC_SPI_MEM_SUPPORT_AUTO_SUSPEND;CONFIG_SOC_SPI_MEM_SUPPORT_AUTO_RESUME;CONFIG_SOC_SPI_MEM_SUPPORT_IDLE_INTR;CONFIG_SOC_SPI_MEM_SUPPORT_SW_SUSPEND;CONFIG_SOC_SPI_MEM_SUPPORT_CHECK_SUS;CONFIG_SOC_SPI_MEM_SUPPORT_CONFIG_GPIO_BY_EFUSE;CONFIG_SOC_SPI_MEM_SUPPORT_WRAP;CONFIG_SOC_MEMSPI_SRC_FREQ_80M_SUPPORTED;CONFIG_SOC_MEMSPI_SRC_FREQ_40M_SUPPORTED;CONFIG_SOC_MEMSPI_SRC_FREQ_26M_SUPPORTED;CONFIG_SOC_MEMSPI_SRC_FREQ_20M_SUPPORTED;CONFIG_SOC_SYSTIMER_COUNTER_NUM;CONFIG_SOC_SYSTIMER_ALARM_NUM;CONFIG_SOC_SYSTIMER_BIT_WIDTH_LO;CONFIG_SOC_SYSTIMER_BIT_WIDTH_HI;CONFIG_SOC_SYSTIMER_FIXED_DIVIDER;CONFIG_SOC_SYSTIMER_INT_LEVEL;CONFIG_SOC_SYSTIMER_ALARM_MISS_COMPENSATE;CONFIG_SOC_TIMER_GROUPS;CONFIG_SOC_TIMER_GROUP_TIMERS_PER_GROUP;CONFIG_SOC_TIMER_GROUP_COUNTER_BIT_WIDTH;CONFIG_SOC_TIMER_GROUP_SUPPORT_XTAL;CONFIG_SOC_TIMER_GROUP_SUPPORT_APB;CONFIG_SOC_TIMER_GROUP_TOTAL_TIMERS;CONFIG_SOC_LP_TIMER_BIT_WIDTH_LO;CONFIG_SOC_LP_TIMER_BIT_WIDTH_HI;CONFIG_SOC_MWDT_SUPPORT_XTAL;CONFIG_SOC_TWAI_CONTROLLER_NUM;CONFIG_SOC_TWAI_CLK_SUPPORT_APB;CONFIG_SOC_TWAI_BRP_MIN;CONFIG_SOC_TWAI_BRP_MAX;CONFIG_SOC_TWAI_SUPPORTS_RX_STATUS;CONFIG_SOC_EFUSE_DIS_DOWNLOAD_ICACHE;CONFIG_SOC_EFUSE_DIS_PAD_JTAG;CONFIG_SOC_EFUSE_DIS_USB_JTAG;CONFIG_SOC_EFUSE_DIS_DIRECT_BOOT;CONFIG_SOC_EFUSE_SOFT_DIS_JTAG;CONFIG_SOC_EFUSE_DIS_ICACHE;CONFIG_SOC_EFUSE_BLOCK9_KEY_PURPOSE_QUIRK;CONFIG_SOC_SECURE_BOOT_V2_RSA;CONFIG_SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS;CONFIG_SOC_EFUSE_REVOKE_BOOT_KEY_DIGESTS;CONFIG_SOC_SUPPORT_SECURE_BOOT_REVOKE_KEY;CONFIG_SOC_FLASH_ENCRYPTED_XTS_AES_BLOCK_MAX;CONFIG_SOC_FLASH_ENCRYPTION_XTS_AES;CONFIG_SOC_FLASH_ENCRYPTION_XTS_AES_128;CONFIG_SOC_MEMPROT_CPU_PREFETCH_PAD_SIZE;CONFIG_SOC_MEMPROT_MEM_ALIGN_SIZE;CONFIG_SOC_UART_NUM;CONFIG_SOC_UART_HP_NUM;CONFIG_SOC_UART_FIFO_LEN;CONFIG_SOC_UART_BITRATE_MAX;CONFIG_SOC_UART_SUPPORT_APB_CLK;CONFIG_SOC_UART_SUPPORT_RTC_CLK;CONFIG_SOC_UART_SUPPORT_XTAL_CLK;CONFIG_SOC_UART_SUPPORT_WAKEUP_INT;CONFIG_SOC_UART_SUPPORT_FSM_TX_WAIT_SEND;CONFIG_SOC_COEX_HW_PTI;CONFIG_SOC_PHY_DIG_REGS_MEM_SIZE;CONFIG_SOC_MAC_BB_PD_MEM_SIZE;CONFIG_SOC_WIFI_LIGHT_SLEEP_CLK_WIDTH;CONFIG_SOC_PM_SUPPORT_WIFI_WAKEUP;CONFIG_SOC_PM_SUPPORT_BT_WAKEUP;CONFIG_SOC_PM_SUPPORT_CPU_PD;CONFIG_SOC_PM_SUPPORT_WIFI_PD;CONFIG_SOC_PM_SUPPORT_BT_PD;CONFIG_SOC_PM_SUPPORT_RC_FAST_PD;CONFIG_SOC_PM_SUPPORT_VDDSDIO_PD;CONFIG_SOC_PM_SUPPORT_MAC_BB_PD;CONFIG_SOC_PM_CPU_RETENTION_BY_RTCCNTL;CONFIG_SOC_PM_MODEM_RETENTION_BY_BACKUPDMA;CONFIG_SOC_PM_MODEM_PD_BY_SW;CONFIG_SOC_CLK_RC_FAST_D256_SUPPORTED;CONFIG_SOC_RTC_SLOW_CLK_SUPPORT_RC_FAST_D256;CONFIG_SOC_CLK_RC_FAST_SUPPORT_CALIBRATION;CONFIG_SOC_CLK_XTAL32K_SUPPORTED;CONFIG_SOC_TEMPERATURE_SENSOR_SUPPORT_FAST_RC;CONFIG_SOC_TEMPERATURE_SENSOR_SUPPORT_XTAL;CONFIG_SOC_WIFI_HW_TSF;CONFIG_SOC_WIFI_FTM_SUPPORT;CONFIG_SOC_WIFI_GCMP_SUPPORT;CONFIG_SOC_WIFI_WAPI_SUPPORT;CONFIG_SOC_WIFI_CSI_SUPPORT;CONFIG_SOC_WIFI_MESH_SUPPORT;CONFIG_SOC_WIFI_SUPPORT_VARIABLE_BEACON_WINDOW;CONFIG_SOC_WIFI_PHY_NEEDS_USB_WORKAROUND;CONFIG_SOC_BLE_SUPPORTED;CONFIG_SOC_BLE_MESH_SUPPORTED;CONFIG_SOC_BLE_50_SUPPORTED;CONFIG_SOC_BLE_DEVICE_PRIVACY_SUPPORTED;CONFIG_SOC_BLUFI_SUPPORTED;CONFIG_SOC_PHY_COMBO_MODULE;CONFIG_IDF_CMAKE;CONFIG_IDF_TOOLCHAIN;CONFIG_IDF_TOOLCHAIN_GCC;CONFIG_IDF_TARGET_ARCH_RISCV;CONFIG_IDF_TARGET_ARCH;CONFIG_IDF_TARGET;CONFIG_IDF_INIT_VERSION;CONFIG_IDF_TARGET_ESP32C3;CONFIG_IDF_FIRMWARE_CHIP_ID;CONFIG_APP_BUILD_TYPE_APP_2NDBOOT;CONFIG_APP_BUILD_TYPE_RAM;CONFIG_APP_BUILD_TYPE_ELF_RAM;CONFIG_APP_BUILD_GENERATE_BINARIES;CONFIG_APP_BUILD_BOOTLOADER;CONFIG_APP_BUILD_USE_FLASH_SECTIONS;CONFIG_APP_REPRODUCIBLE_BUILD;CONFIG_APP_NO_BLOBS;CONFIG_NO_BLOBS;CONFIG_BOOTLOADER_COMPILE_TIME_DATE;CONFIG_BOOTLOADER_PROJECT_VER;CONFIG_BOOTLOADER_OFFSET_IN_FLASH;CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE;CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_DEBUG;CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_PERF;CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_NONE;CONFIG_BOOTLOADER_LOG_LEVEL_NONE;CONFIG_LOG_BOOTLOADER_LEVEL_NONE;CONFIG_BOOTLOADER_LOG_LEVEL_ERROR;CONFIG_LOG_BOOTLOADER_LEVEL_ERROR;CONFIG_BOOTLOADER_LOG_LEVEL_WARN;CONFIG_LOG_BOOTLOADER_LEVEL_WARN;CONFIG_BOOTLOADER_LOG_LEVEL_INFO;CONFIG_LOG_BOOTLOADER_LEVEL_INFO;CONFIG_BOOTLOADER_LOG_LEVEL_DEBUG;CONFIG_LOG_BOOTLOADER_LEVEL_DEBUG;CONFIG_BOOTLOADER_LOG_LEVEL_VERBOSE;CONFIG_LOG_BOOTLOADER_LEVEL_VERBOSE;CONFIG_BOOTLOADER_LOG_LEVEL;CONFIG_LOG_BOOTLOADER_LEVEL;CONFIG_BOOTLOADER_LOG_COLORS;CONFIG_BOOTLOADER_LOG_TIMESTAMP_SOURCE_CPU_TICKS;CONFIG_BOOTLOADER_FLASH_DC_AWARE;CONFIG_BOOTLOADER_FLASH_XMC_SUPPORT;CONFIG_BOOTLOADER_FACTORY_RESET;CONFIG_BOOTLOADER_APP_TEST;CONFIG_BOOTLOADER_REGION_PROTECTION_ENABLE;CONFIG_BOOTLOADER_WDT_ENABLE;CONFIG_BOOTLOADER_WDT_DISABLE_IN_USER_CODE;CONFIG_BOOTLOADER_WDT_TIME_MS;CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE;CONFIG_APP_ROLLBACK_ENABLE;CONFIG_BOOTLOADER_APP_ANTI_ROLLBACK;CONFIG_APP_ANTI_ROLLBACK;CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP;CONFIG_BOOTLOADER_SKIP_VALIDATE_ON_POWER_ON;CONFIG_BOOTLOADER_SKIP_VALIDATE_ALWAYS;CONFIG_BOOTLOADER_RESERVE_RTC_SIZE;CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC;CONFIG_SECURE_BOOT_V2_RSA_SUPPORTED;CONFIG_SECURE_BOOT_V2_PREFERRED;CONFIG_SECURE_SIGNED_APPS_NO_SECURE_BOOT;CONFIG_SECURE_BOOT;CONFIG_SECURE_FLASH_ENC_ENABLED;CONFIG_FLASH_ENCRYPTION_ENABLED;CONFIG_SECURE_ROM_DL_MODE_ENABLED;CONFIG_APP_COMPILE_TIME_DATE;CONFIG_APP_EXCLUDE_PROJECT_VER_VAR;CONFIG_APP_EXCLUDE_PROJECT_NAME_VAR;CONFIG_APP_PROJECT_VER_FROM_CONFIG;CONFIG_APP_RETRIEVE_LEN_ELF_SHA;CONFIG_ESP_ROM_HAS_CRC_LE;CONFIG_ESP_ROM_HAS_CRC_BE;CONFIG_ESP_ROM_HAS_MZ_CRC32;CONFIG_ESP_ROM_HAS_JPEG_DECODE;CONFIG_ESP_ROM_UART_CLK_IS_XTAL;CONFIG_ESP_ROM_USB_SERIAL_DEVICE_NUM;CONFIG_ESP_ROM_HAS_RETARGETABLE_LOCKING;CONFIG_ESP_ROM_HAS_ERASE_0_REGION_BUG;CONFIG_ESP_ROM_HAS_ENCRYPTED_WRITES_USING_LEGACY_DRV;CONFIG_ESP_ROM_GET_CLK_FREQ;CONFIG_ESP_ROM_NEEDS_SWSETUP_WORKAROUND;CONFIG_ESP_ROM_HAS_LAYOUT_TABLE;CONFIG_ESP_ROM_HAS_SPI_FLASH;CONFIG_ESP_ROM_HAS_ETS_PRINTF_BUG;CONFIG_ESP_ROM_HAS_NEWLIB;CONFIG_ESP_ROM_HAS_NEWLIB_NANO_FORMAT;CONFIG_ESP_ROM_HAS_NEWLIB_32BIT_TIME;CONFIG_ESP_ROM_NEEDS_SET_CACHE_MMU_SIZE;CONFIG_ESP_ROM_RAM_APP_NEEDS_MMU_INIT;CONFIG_ESP_ROM_HAS_SW_FLOAT;CONFIG_ESP_ROM_USB_OTG_NUM;CONFIG_ESP_ROM_HAS_VERSION;CONFIG_ESP_ROM_SUPPORT_DEEP_SLEEP_WAKEUP_STUB;CONFIG_BOOT_ROM_LOG_ALWAYS_ON;CONFIG_BOOT_ROM_LOG_ALWAYS_OFF;CONFIG_BOOT_ROM_LOG_ON_GPIO_HIGH;CONFIG_BOOT_ROM_LOG_ON_GPIO_LOW;CONFIG_ESPTOOLPY_NO_STUB;CONFIG_ESPTOOLPY_FLASHMODE_QIO;CONFIG_FLASHMODE_QIO;CONFIG_ESPTOOLPY_FLASHMODE_QOUT;CONFIG_FLASHMODE_QOUT;CONFIG_ESPTOOLPY_FLASHMODE_DIO;CONFIG_FLASHMODE_DIO;CONFIG_ESPTOOLPY_FLASHMODE_DOUT;CONFIG_FLASHMODE_DOUT;CONFIG_ESPTOOLPY_FLASH_SAMPLE_MODE_STR;CONFIG_ESPTOOLPY_FLASHMODE;CONFIG_ESPTOOLPY_FLASHFREQ_80M;CONFIG_ESPTOOLPY_FLASHFREQ_40M;CONFIG_ESPTOOLPY_FLASHFREQ_26M;CONFIG_ESPTOOLPY_FLASHFREQ_20M;CONFIG_ESPTOOLPY_FLASHFREQ;CONFIG_ESPTOOLPY_FLASHSIZE_1MB;CONFIG_ESPTOOLPY_FLASHSIZE_2MB;CONFIG_ESPTOOLPY_FLASHSIZE_4MB;CONFIG_ESPTOOLPY_FLASHSIZE_8MB;CONFIG_ESPTOOLPY_FLASHSIZE_16MB;CONFIG_ESPTOOLPY_FLASHSIZE_32MB;CONFIG_ESPTOOLPY_FLASHSIZE_64MB;CONFIG_ESPTOOLPY_FLASHSIZE_128MB;CONFIG_ESPTOOLPY_FLASHSIZE;CONFIG_ESPTOOLPY_HEADER_FLASHSIZE_UPDATE;CONFIG_ESPTOOLPY_BEFORE_RESET;CONFIG_ESPTOOLPY_BEFORE_NORESET;CONFIG_ESPTOOLPY_BEFORE;CONFIG_ESPTOOLPY_AFTER_RESET;CONFIG_ESPTOOLPY_AFTER_NORESET;CONFIG_ESPTOOLPY_AFTER;CONFIG_ESPTOOLPY_MONITOR_BAUD;CONFIG_MONITOR_BAUD;CONFIG_PARTITION_TABLE_SINGLE_APP;CONFIG_PARTITION_TABLE_SINGLE_APP_LARGE;CONFIG_PARTITION_TABLE_TWO_OTA;CONFIG_PARTITION_TABLE_TWO_OTA_LARGE;CONFIG_PARTITION_TABLE_CUSTOM;CONFIG_PARTITION_TABLE_CUSTOM_FILENAME;CONFIG_PARTITION_TABLE_FILENAME;CONFIG_PARTITION_TABLE_OFFSET;CONFIG_PARTITION_TABLE_MD5;CONFIG_EXAMPLE_BOARD_BUTTON_GPIO;CONFIG_APP_NETWORK_PROV_SHOW_QR;CONFIG_APP_WIFI_PROV_SHOW_QR;CONFIG_APP_NETWORK_PROV_MAX_POP_MISMATCH;CONFIG_APP_WIFI_PROV_MAX_POP_MISMATCH;CONFIG_APP_NETWORK_PROV_TRANSPORT_SOFTAP;CONFIG_APP_WIFI_PROV_TRANSPORT_SOFTAP;CONFIG_APP_NETWORK_PROV_TRANSPORT_BLE;CONFIG_APP_WIFI_PROV_TRANSPORT_BLE;CONFIG_APP_NETWORK_PROV_TRANSPORT;CONFIG_APP_WIFI_PROV_TRANSPORT;CONFIG_APP_NETWORK_RESET_PROV_ON_FAILURE;CONFIG_APP_WIFI_RESET_PROV_ON_FAILURE;CONFIG_APP_NETWORK_PROV_MAX_RETRY_CNT;CONFIG_APP_NETWORK_SHOW_DEMO_INTRO_TEXT;CONFIG_APP_WIFI_SHOW_DEMO_INTRO_TEXT;CONFIG_APP_NETWORK_PROV_TIMEOUT_PERIOD;CONFIG_APP_WIFI_PROV_TIMEOUT_PERIOD;CONFIG_APP_NETWORK_PROV_NAME_PREFIX;CONFIG_APP_WIFI_PROV_NAME_PREFIX;CONFIG_APP_WIFI_PROV_COMPAT;CONFIG_ESP_RMAKER_NO_CLAIM;CONFIG_ESP_RMAKER_SELF_CLAIM;CONFIG_ESP_RMAKER_ASSISTED_CLAIM;CONFIG_ESP_RMAKER_USE_NVS;CONFIG_ESP_RMAKER_CLAIM_TYPE;CONFIG_ESP_RMAKER_CLAIM_SERVICE_BASE_URL;CONFIG_ESP_RMAKER_READ_MQTT_HOST_FROM_CONFIG;CONFIG_ESP_RMAKER_READ_NODE_ID_FROM_CERT_CN;CONFIG_ESP_RMAKER_MQTT_HOST;CONFIG_ESP_RMAKER_MQTT_USE_BASIC_INGEST_TOPICS;CONFIG_ESP_RMAKER_MQTT_ENABLE_BUDGETING;CONFIG_ESP_RMAKER_MQTT_DEFAULT_BUDGET;CONFIG_ESP_RMAKER_MQTT_MAX_BUDGET;CONFIG_ESP_RMAKER_MQTT_BUDGET_REVIVE_PERIOD;CONFIG_ESP_RMAKER_MQTT_BUDGET_REVIVE_COUNT;CONFIG_ESP_RMAKER_MAX_PARAM_DATA_SIZE;CONFIG_ESP_RMAKER_DISABLE_USER_MAPPING_PROV;CONFIG_ESP_RMAKER_USER_ID_CHECK;CONFIG_RMAKER_NAME_PARAM_CB;CONFIG_ESP_RMAKER_LOCAL_CTRL_FEATURE_ENABLE;CONFIG_ESP_RMAKER_LOCAL_CTRL_AUTO_ENABLE;CONFIG_ESP_RMAKER_LOCAL_CTRL_ENABLE;CONFIG_ESP_RMAKER_LOCAL_CTRL_HTTP_PORT;CONFIG_ESP_RMAKER_LOCAL_CTRL_STACK_SIZE;CONFIG_ESP_RMAKER_LOCAL_CTRL_SECURITY_0;CONFIG_ESP_RMAKER_LOCAL_CTRL_SECURITY_1;CONFIG_ESP_RMAKER_LOCAL_CTRL_SECURITY;CONFIG_ESP_RMAKER_CONSOLE_UART_NUM_0;CONFIG_ESP_RMAKER_CONSOLE_UART_NUM_1;CONFIG_ESP_RMAKER_CONSOLE_UART_NUM;CONFIG_ESP_RMAKER_USE_CERT_BUNDLE;CONFIG_ESP_RMAKER_OTA_AUTOFETCH;CONFIG_ESP_RMAKER_OTA_AUTOFETCH_PERIOD;CONFIG_ESP_RMAKER_SKIP_COMMON_NAME_CHECK;CONFIG_ESP_RMAKER_SKIP_VERSION_CHECK;CONFIG_ESP_RMAKER_SKIP_SECURE_VERSION_CHECK;CONFIG_ESP_RMAKER_SKIP_PROJECT_NAME_CHECK;CONFIG_ESP_RMAKER_OTA_HTTP_RX_BUFFER_SIZE;CONFIG_ESP_RMAKER_OTA_ROLLBACK_WAIT_PERIOD;CONFIG_ESP_RMAKER_OTA_DISABLE_AUTO_REBOOT;CONFIG_ESP_RMAKER_OTA_TIME_SUPPORT;CONFIG_ESP_RMAKER_OTA_PROGRESS_SUPPORT;CONFIG_ESP_RMAKER_OTA_MAX_RETRIES;CONFIG_ESP_RMAKER_OTA_RETRY_DELAY_MINUTES;CONFIG_ESP_RMAKER_SCHEDULING_MAX_SCHEDULES;CONFIG_ESP_RMAKER_SCENES_MAX_SCENES;CONFIG_ESP_RMAKER_SCENES_DEACTIVATE_SUPPORT;CONFIG_ESP_RMAKER_CMD_RESP_ENABLE;CONFIG_ESP_RMAKER_CMD_RESP_TEST_ENABLE;CONFIG_ESP_RMAKER_USING_NETWORK_PROV;CONFIG_COMPILER_OPTIMIZATION_DEBUG;CONFIG_OPTIMIZATION_LEVEL_DEBUG;CONFIG_COMPILER_OPTIMIZATION_LEVEL_DEBUG;CONFIG_COMPILER_OPTIMIZATION_DEFAULT;CONFIG_COMPILER_OPTIMIZATION_SIZE;CONFIG_OPTIMIZATION_LEVEL_RELEASE;CONFIG_COMPILER_OPTIMIZATION_LEVEL_RELEASE;CONFIG_COMPILER_OPTIMIZATION_PERF;CONFIG_COMPILER_OPTIMIZATION_NONE;CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE;CONFIG_OPTIMIZATION_ASSERTIONS_ENABLED;CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT;CONFIG_OPTIMIZATION_ASSERTIONS_SILENT;CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE;CONFIG_OPTIMIZATION_ASSERTIONS_DISABLED;CONFIG_COMPILER_ASSERT_NDEBUG_EVALUATE;CONFIG_COMPILER_FLOAT_LIB_FROM_GCCLIB;CONFIG_COMPILER_OPTIMIZATION_ASSERTION_LEVEL;CONFIG_OPTIMIZATION_ASSERTION_LEVEL;CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT;CONFIG_COMPILER_HIDE_PATHS_MACROS;CONFIG_COMPILER_CXX_EXCEPTIONS;CONFIG_CXX_EXCEPTIONS;CONFIG_COMPILER_CXX_RTTI;CONFIG_COMPILER_STACK_CHECK_MODE_NONE;CONFIG_STACK_CHECK_NONE;CONFIG_COMPILER_STACK_CHECK_MODE_NORM;CONFIG_STACK_CHECK_NORM;CONFIG_COMPILER_STACK_CHECK_MODE_STRONG;CONFIG_STACK_CHECK_STRONG;CONFIG_COMPILER_STACK_CHECK_MODE_ALL;CONFIG_STACK_CHECK_ALL;CONFIG_COMPILER_NO_MERGE_CONSTANTS;CONFIG_COMPILER_WARN_WRITE_STRINGS;CONFIG_WARN_WRITE_STRINGS;CONFIG_COMPILER_SAVE_RESTORE_LIBCALLS;CONFIG_COMPILER_DISABLE_DEFAULT_ERRORS;CONFIG_COMPILER_DISABLE_GCC12_WARNINGS;CONFIG_COMPILER_DISABLE_GCC13_WARNINGS;CONFIG_COMPILER_DISABLE_GCC14_WARNINGS;CONFIG_COMPILER_DUMP_RTL_FILES;CONFIG_COMPILER_RT_LIB_GCCLIB;CONFIG_COMPILER_RT_LIB_NAME;CONFIG_COMPILER_ORPHAN_SECTIONS_WARNING;CONFIG_COMPILER_ORPHAN_SECTIONS_PLACE;CONFIG_COMPILER_STATIC_ANALYZER;CONFIG_APPTRACE_DEST_JTAG;CONFIG_ESP32_APPTRACE_DEST_TRAX;CONFIG_APPTRACE_DEST_NONE;CONFIG_ESP32_APPTRACE_DEST_NONE;CONFIG_APPTRACE_DEST_UART1;CONFIG_APPTRACE_DEST_USB_CDC;CONFIG_APPTRACE_DEST_UART_NONE;CONFIG_APPTRACE_UART_TASK_PRIO;CONFIG_APPTRACE_LOCK_ENABLE;CONFIG_ESP32_APPTRACE_LOCK_ENABLE;CONFIG_BT_ENABLED;CONFIG_BT_BLUEDROID_ENABLED;CONFIG_BLUEDROID_ENABLED;CONFIG_BT_NIMBLE_ENABLED;CONFIG_NIMBLE_ENABLED;CONFIG_BT_CONTROLLER_ONLY;CONFIG_BT_CONTROLLER_ENABLED;CONFIG_BT_CONTROLLER_DISABLED;CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_INTERNAL;CONFIG_NIMBLE_MEM_ALLOC_MODE_INTERNAL;CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_DEFAULT;CONFIG_NIMBLE_MEM_ALLOC_MODE_DEFAULT;CONFIG_BT_NIMBLE_LOG_LEVEL_NONE;CONFIG_BT_NIMBLE_LOG_LEVEL_ERROR;CONFIG_BT_NIMBLE_LOG_LEVEL_WARNING;CONFIG_BT_NIMBLE_LOG_LEVEL_INFO;CONFIG_BT_NIMBLE_LOG_LEVEL_DEBUG;CONFIG_BT_NIMBLE_LOG_LEVEL;CONFIG_BT_NIMBLE_MAX_CONNECTIONS;CONFIG_NIMBLE_MAX_CONNECTIONS;CONFIG_BT_NIMBLE_MAX_BONDS;CONFIG_NIMBLE_MAX_BONDS;CONFIG_BT_NIMBLE_MAX_CCCDS;CONFIG_NIMBLE_MAX_CCCDS;CONFIG_BT_NIMBLE_L2CAP_COC_MAX_NUM;CONFIG_NIMBLE_L2CAP_COC_MAX_NUM;CONFIG_BT_NIMBLE_PINNED_TO_CORE;CONFIG_NIMBLE_PINNED_TO_CORE;CONFIG_BT_NIMBLE_HOST_TASK_STACK_SIZE;CONFIG_NIMBLE_TASK_STACK_SIZE;CONFIG_BT_NIMBLE_TASK_STACK_SIZE;CONFIG_BT_NIMBLE_ROLE_CENTRAL;CONFIG_NIMBLE_ROLE_CENTRAL;CONFIG_BT_NIMBLE_ROLE_PERIPHERAL;CONFIG_NIMBLE_ROLE_PERIPHERAL;CONFIG_BT_NIMBLE_ROLE_BROADCASTER;CONFIG_NIMBLE_ROLE_BROADCASTER;CONFIG_BT_NIMBLE_ROLE_OBSERVER;CONFIG_NIMBLE_ROLE_OBSERVER;CONFIG_BT_NIMBLE_NVS_PERSIST;CONFIG_NIMBLE_NVS_PERSIST;CONFIG_BT_NIMBLE_SMP_ID_RESET;CONFIG_BT_NIMBLE_SECURITY_ENABLE;CONFIG_BT_NIMBLE_SM_LEGACY;CONFIG_NIMBLE_SM_LEGACY;CONFIG_BT_NIMBLE_SM_SC;CONFIG_NIMBLE_SM_SC;CONFIG_BT_NIMBLE_SM_SC_DEBUG_KEYS;CONFIG_NIMBLE_SM_SC_DEBUG_KEYS;CONFIG_BT_NIMBLE_LL_CFG_FEAT_LE_ENCRYPTION;CONFIG_BT_NIMBLE_SM_LVL;CONFIG_BT_NIMBLE_SM_SC_LVL;CONFIG_BT_NIMBLE_SM_SC_ONLY;CONFIG_BT_NIMBLE_DEBUG;CONFIG_NIMBLE_DEBUG;CONFIG_BT_NIMBLE_DYNAMIC_SERVICE;CONFIG_BT_NIMBLE_SVC_GAP_DEVICE_NAME;CONFIG_NIMBLE_SVC_GAP_DEVICE_NAME;CONFIG_BT_NIMBLE_GAP_DEVICE_NAME_MAX_LEN;CONFIG_NIMBLE_GAP_DEVICE_NAME_MAX_LEN;CONFIG_BT_NIMBLE_ATT_PREFERRED_MTU;CONFIG_NIMBLE_ATT_PREFERRED_MTU;CONFIG_BT_NIMBLE_SVC_GAP_APPEARANCE;CONFIG_NIMBLE_SVC_GAP_APPEARANCE;CONFIG_BT_NIMBLE_MSYS_1_BLOCK_COUNT;CONFIG_BT_NIMBLE_MSYS1_BLOCK_COUNT;CONFIG_BT_NIMBLE_MSYS_1_BLOCK_SIZE;CONFIG_BT_NIMBLE_MSYS_2_BLOCK_COUNT;CONFIG_BT_NIMBLE_MSYS_2_BLOCK_SIZE;CONFIG_BT_NIMBLE_TRANSPORT_ACL_FROM_LL_COUNT;CONFIG_BT_NIMBLE_ACL_BUF_COUNT;CONFIG_BT_NIMBLE_TRANSPORT_ACL_SIZE;CONFIG_BT_NIMBLE_ACL_BUF_SIZE;CONFIG_BT_NIMBLE_TRANSPORT_EVT_SIZE;CONFIG_BT_NIMBLE_HCI_EVT_BUF_SIZE;CONFIG_BT_NIMBLE_TRANSPORT_EVT_COUNT;CONFIG_BT_NIMBLE_HCI_EVT_HI_BUF_COUNT;CONFIG_BT_NIMBLE_TRANSPORT_EVT_DISCARD_COUNT;CONFIG_BT_NIMBLE_HCI_EVT_LO_BUF_COUNT;CONFIG_BT_NIMBLE_L2CAP_COC_SDU_BUFF_COUNT;CONFIG_BT_NIMBLE_GATT_MAX_PROCS;CONFIG_BT_NIMBLE_HS_FLOW_CTRL;CONFIG_NIMBLE_HS_FLOW_CTRL;CONFIG_BT_NIMBLE_RPA_TIMEOUT;CONFIG_NIMBLE_RPA_TIMEOUT;CONFIG_BT_NIMBLE_MESH;CONFIG_NIMBLE_MESH;CONFIG_BT_NIMBLE_CRYPTO_STACK_MBEDTLS;CONFIG_NIMBLE_CRYPTO_STACK_MBEDTLS;CONFIG_BT_NIMBLE_HS_STOP_TIMEOUT_MS;CONFIG_BT_NIMBLE_ENABLE_CONN_REATTEMPT;CONFIG_BT_NIMBLE_MAX_CONN_REATTEMPT;CONFIG_BT_NIMBLE_50_FEATURE_SUPPORT;CONFIG_BT_NIMBLE_LL_CFG_FEAT_LE_2M_PHY;CONFIG_BT_NIMBLE_LL_CFG_FEAT_LE_CODED_PHY;CONFIG_BT_NIMBLE_EXT_ADV;CONFIG_BT_NIMBLE_EXT_SCAN;CONFIG_BT_NIMBLE_ENABLE_PERIODIC_SYNC;CONFIG_BT_NIMBLE_MAX_PERIODIC_SYNCS;CONFIG_BT_NIMBLE_GATT_CACHING;CONFIG_BT_NIMBLE_WHITELIST_SIZE;CONFIG_BT_NIMBLE_TEST_THROUGHPUT_TEST;CONFIG_BT_NIMBLE_BLUFI_ENABLE;CONFIG_BT_NIMBLE_USE_ESP_TIMER;CONFIG_BT_NIMBLE_LEGACY_VHCI_ENABLE;CONFIG_BT_NIMBLE_BLE_GATT_BLOB_TRANSFER;CONFIG_BT_NIMBLE_SVC_GAP_APPEAR_WRITE;CONFIG_BT_NIMBLE_SVC_GAP_APPEAR_WRITE_PERM;CONFIG_BT_NIMBLE_SVC_GAP_APPEAR_WRITE_PERM_ENC;CONFIG_BT_NIMBLE_SVC_GAP_APPEAR_WRITE_PERM_ATHN;CONFIG_BT_NIMBLE_SVC_GAP_APPEAR_WRITE_PERM_ATHR;CONFIG_BT_NIMBLE_SVC_GAP_CAR_CHAR_NOT_SUPP;CONFIG_BT_NIMBLE_SVC_GAP_CAR_NOT_SUPP;CONFIG_BT_NIMBLE_SVC_GAP_CAR_SUPP;CONFIG_BT_NIMBLE_SVC_GAP_CENT_ADDR_RESOLUTION;CONFIG_BT_NIMBLE_SVC_GAP_NAME_WRITE;CONFIG_BT_NIMBLE_SVC_GAP_NAME_WRITE_PERM;CONFIG_BT_NIMBLE_SVC_GAP_NAME_WRITE_PERM_ENC;CONFIG_BT_NIMBLE_SVC_GAP_NAME_WRITE_PERM_AUTHEN;CONFIG_BT_NIMBLE_SVC_GAP_NAME_WRITE_PERM_AUTHOR;CONFIG_BT_NIMBLE_SVC_GAP_PPCP_MAX_CONN_INTERVAL;CONFIG_BT_NIMBLE_SVC_GAP_PPCP_MIN_CONN_INTERVAL;CONFIG_BT_NIMBLE_SVC_GAP_PPCP_SLAVE_LATENCY;CONFIG_BT_NIMBLE_SVC_GAP_PPCP_SUPERVISION_TMO;CONFIG_BT_NIMBLE_SVC_GAP_GATT_SECURITY_LEVEL;CONFIG_BT_NIMBLE_HID_SERVICE;CONFIG_BT_NIMBLE_SVC_BAS_BATTERY_LEVEL_NOTIFY;CONFIG_BT_NIMBLE_SVC_DIS_MANUFACTURER_NAME;CONFIG_BT_NIMBLE_SVC_DIS_SERIAL_NUMBER;CONFIG_BT_NIMBLE_SVC_DIS_HARDWARE_REVISION;CONFIG_BT_NIMBLE_SVC_DIS_FIRMWARE_REVISION;CONFIG_BT_NIMBLE_SVC_DIS_SOFTWARE_REVISION;CONFIG_BT_NIMBLE_SVC_DIS_SYSTEM_ID;CONFIG_BT_NIMBLE_SVC_DIS_PNP_ID;CONFIG_BT_NIMBLE_SVC_DIS_INCLUDED;CONFIG_BT_NIMBLE_VS_SUPPORT;CONFIG_BT_NIMBLE_ENC_ADV_DATA;CONFIG_BT_NIMBLE_HIGH_DUTY_ADV_ITVL;CONFIG_BT_NIMBLE_HOST_ALLOW_CONNECT_WITH_SCAN;CONFIG_BT_NIMBLE_HOST_QUEUE_CONG_CHECK;CONFIG_BT_NIMBLE_GATTC_PROC_PREEMPTION_PROTECT;CONFIG_UART_HW_FLOWCTRL_DISABLE;CONFIG_UART_HW_FLOWCTRL_CTS_RTS;CONFIG_BT_NIMBLE_HCI_UART_FLOW_CTRL;CONFIG_BT_NIMBLE_HCI_UART_RTS_PIN;CONFIG_BT_NIMBLE_HCI_UART_CTS_PIN;CONFIG_BT_NIMBLE_EATT_CHAN_NUM;CONFIG_BT_NIMBLE_SUBRATE;CONFIG_BT_CTRL_MODE_EFF;CONFIG_BT_CTRL_BLE_MAX_ACT;CONFIG_BT_CTRL_BLE_MAX_ACT_EFF;CONFIG_BT_CTRL_BLE_STATIC_ACL_TX_BUF_NB;CONFIG_BT_CTRL_PINNED_TO_CORE;CONFIG_BT_CTRL_HCI_MODE_VHCI;CONFIG_BT_CTRL_HCI_MODE_UART_H4;CONFIG_BT_CTRL_HCI_TL;CONFIG_BT_CTRL_ADV_DUP_FILT_MAX;CONFIG_BT_BLE_CCA_MODE_NONE;CONFIG_BT_BLE_CCA_MODE_HW;CONFIG_BT_BLE_CCA_MODE_SW;CONFIG_BT_BLE_CCA_MODE;CONFIG_BT_CTRL_HW_CCA_VAL;CONFIG_BT_CTRL_HW_CCA_EFF;CONFIG_BT_CTRL_CE_LENGTH_TYPE_ORIG;CONFIG_BT_CTRL_CE_LENGTH_TYPE_CE;CONFIG_BT_CTRL_CE_LENGTH_TYPE_SD;CONFIG_BT_CTRL_CE_LENGTH_TYPE_EFF;CONFIG_BT_CTRL_TX_ANTENNA_INDEX_0;CONFIG_BT_CTRL_TX_ANTENNA_INDEX_1;CONFIG_BT_CTRL_TX_ANTENNA_INDEX_EFF;CONFIG_BT_CTRL_RX_ANTENNA_INDEX_0;CONFIG_BT_CTRL_RX_ANTENNA_INDEX_1;CONFIG_BT_CTRL_RX_ANTENNA_INDEX_EFF;CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N24;CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N21;CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N18;CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N15;CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N12;CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N9;CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N6;CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N3;CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N0;CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P3;CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P6;CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P9;CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P12;CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P15;CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P18;CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P20;CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_EFF;CONFIG_BT_CTRL_BLE_ADV_REPORT_FLOW_CTRL_SUPP;CONFIG_BT_CTRL_BLE_ADV_REPORT_FLOW_CTRL_NUM;CONFIG_BT_CTRL_BLE_ADV_REPORT_DISCARD_THRSHOLD;CONFIG_BT_CTRL_BLE_SCAN_DUPL;CONFIG_BT_CTRL_SCAN_DUPL_TYPE_DEVICE;CONFIG_BT_CTRL_SCAN_DUPL_TYPE_DATA;CONFIG_BT_CTRL_SCAN_DUPL_TYPE_DATA_DEVICE;CONFIG_BT_CTRL_SCAN_DUPL_TYPE;CONFIG_BT_CTRL_SCAN_DUPL_CACHE_SIZE;CONFIG_BT_CTRL_DUPL_SCAN_CACHE_REFRESH_PERIOD;CONFIG_BT_CTRL_BLE_MESH_SCAN_DUPL_EN;CONFIG_BT_CTRL_COEX_PHY_CODED_TX_RX_TLIM_EN;CONFIG_BT_NIMBLE_COEX_PHY_CODED_TX_RX_TLIM_EN;CONFIG_BT_CTRL_COEX_PHY_CODED_TX_RX_TLIM_DIS;CONFIG_BT_NIMBLE_COEX_PHY_CODED_TX_RX_TLIM_DIS;CONFIG_BT_CTRL_COEX_PHY_CODED_TX_RX_TLIM_EFF;CONFIG_BT_CTRL_MODEM_SLEEP;CONFIG_BT_CTRL_SLEEP_MODE_EFF;CONFIG_BT_CTRL_SLEEP_CLOCK_EFF;CONFIG_BT_CTRL_HCI_TL_EFF;CONFIG_BT_CTRL_AGC_RECORRECT_EN;CONFIG_BT_CTRL_SCAN_BACKOFF_UPPERLIMITMAX;CONFIG_BT_BLE_ADV_DATA_LENGTH_ZERO_AUX;CONFIG_BT_CTRL_CHAN_ASS_EN;CONFIG_BT_CTRL_LE_PING_EN;CONFIG_BT_CTRL_BLE_LLCP_CONN_UPDATE;CONFIG_BT_CTRL_BLE_LLCP_CHAN_MAP_UPDATE;CONFIG_BT_CTRL_BLE_LLCP_PHY_UPDATE;CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY;CONFIG_BT_CTRL_CHECK_CONNECT_IND_ACCESS_ADDRESS;CONFIG_BT_ALARM_MAX_NUM;CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED;CONFIG_BT_HCI_LOG_DEBUG_EN;CONFIG_BLE_MESH;CONFIG_CONSOLE_SORTED_HELP;CONFIG_TWAI_ISR_IN_IRAM;CONFIG_TWAI_ERRATA_FIX_LISTEN_ONLY_DOM;CONFIG_ADC_SUPPRESS_DEPRECATE_WARN;CONFIG_ADC_SKIP_LEGACY_CONFLICT_CHECK;CONFIG_ADC_CALI_SUPPRESS_DEPRECATE_WARN;CONFIG_GPTIMER_SUPPRESS_DEPRECATE_WARN;CONFIG_GPTIMER_SKIP_LEGACY_CONFLICT_CHECK;CONFIG_RMT_SUPPRESS_DEPRECATE_WARN;CONFIG_RMT_SKIP_LEGACY_CONFLICT_CHECK;CONFIG_I2S_SUPPRESS_DEPRECATE_WARN;CONFIG_I2S_SKIP_LEGACY_CONFLICT_CHECK;CONFIG_SDM_SUPPRESS_DEPRECATE_WARN;CONFIG_SDM_SKIP_LEGACY_CONFLICT_CHECK;CONFIG_TEMP_SENSOR_SUPPRESS_DEPRECATE_WARN;CONFIG_TEMP_SENSOR_SKIP_LEGACY_CONFLICT_CHECK;CONFIG_EFUSE_CUSTOM_TABLE;CONFIG_EFUSE_VIRTUAL;CONFIG_EFUSE_MAX_BLK_LEN;CONFIG_ESP_TLS_USING_MBEDTLS;CONFIG_ESP_TLS_USE_DS_PERIPHERAL;CONFIG_ESP_TLS_CLIENT_SESSION_TICKETS;CONFIG_ESP_TLS_SERVER_SESSION_TICKETS;CONFIG_ESP_TLS_SERVER_CERT_SELECT_HOOK;CONFIG_ESP_TLS_SERVER_MIN_AUTH_MODE_OPTIONAL;CONFIG_ESP_TLS_PSK_VERIFICATION;CONFIG_ESP_TLS_INSECURE;CONFIG_ADC_ONESHOT_CTRL_FUNC_IN_IRAM;CONFIG_ADC_CONTINUOUS_ISR_IRAM_SAFE;CONFIG_ADC_CONTINUOUS_FORCE_USE_ADC2_ON_C3_S3;CONFIG_ADC_ONESHOT_FORCE_USE_ADC2_ON_C3;CONFIG_ADC_ENABLE_DEBUG_LOG;CONFIG_ESP_COEX_ENABLED;CONFIG_ESP_COEX_SW_COEXIST_ENABLE;CONFIG_SW_COEXIST_ENABLE;CONFIG_ESP32_WIFI_SW_COEXIST_ENABLE;CONFIG_ESP_WIFI_SW_COEXIST_ENABLE;CONFIG_ESP_COEX_POWER_MANAGEMENT;CONFIG_ESP_COEX_GPIO_DEBUG;CONFIG_ESP_ERR_TO_NAME_LOOKUP;CONFIG_GPIO_CTRL_FUNC_IN_IRAM;CONFIG_GPTIMER_ISR_HANDLER_IN_IRAM;CONFIG_GPTIMER_CTRL_FUNC_IN_IRAM;CONFIG_GPTIMER_ISR_IRAM_SAFE;CONFIG_GPTIMER_ENABLE_DEBUG_LOG;CONFIG_I2C_ISR_IRAM_SAFE;CONFIG_I2C_ENABLE_DEBUG_LOG;CONFIG_I2C_ENABLE_SLAVE_DRIVER_VERSION_2;CONFIG_I2S_ISR_IRAM_SAFE;CONFIG_I2S_ENABLE_DEBUG_LOG;CONFIG_LEDC_CTRL_FUNC_IN_IRAM;CONFIG_RMT_ISR_IRAM_SAFE;CONFIG_RMT_RECV_FUNC_IN_IRAM;CONFIG_RMT_ENABLE_DEBUG_LOG;CONFIG_SDM_CTRL_FUNC_IN_IRAM;CONFIG_SDM_ENABLE_DEBUG_LOG;CONFIG_SPI_MASTER_IN_IRAM;CONFIG_SPI_MASTER_ISR_IN_IRAM;CONFIG_SPI_SLAVE_IN_IRAM;CONFIG_SPI_SLAVE_ISR_IN_IRAM;CONFIG_TEMP_SENSOR_ENABLE_DEBUG_LOG;CONFIG_UART_ISR_IN_IRAM;CONFIG_USJ_ENABLE_USB_SERIAL_JTAG;CONFIG_ETH_ENABLED;CONFIG_ETH_USE_SPI_ETHERNET;CONFIG_ETH_SPI_ETHERNET_DM9051;CONFIG_ETH_SPI_ETHERNET_W5500;CONFIG_ETH_SPI_ETHERNET_KSZ8851SNL;CONFIG_ETH_USE_OPENETH;CONFIG_ETH_TRANSMIT_MUTEX;CONFIG_ESP_EVENT_LOOP_PROFILING;CONFIG_EVENT_LOOP_PROFILING;CONFIG_ESP_EVENT_POST_FROM_ISR;CONFIG_POST_EVENTS_FROM_ISR;CONFIG_ESP_EVENT_POST_FROM_IRAM_ISR;CONFIG_POST_EVENTS_FROM_IRAM_ISR;CONFIG_ESP_GDBSTUB_ENABLED;CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME;CONFIG_ESP_GDBSTUB_SUPPORT_TASKS;CONFIG_GDBSTUB_SUPPORT_TASKS;CONFIG_ESP_GDBSTUB_MAX_TASKS;CONFIG_GDBSTUB_MAX_TASKS;CONFIG_ESPHID_TASK_SIZE_BT;CONFIG_ESPHID_TASK_SIZE_BLE;CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS;CONFIG_ESP_HTTP_CLIENT_ENABLE_BASIC_AUTH;CONFIG_ESP_HTTP_CLIENT_ENABLE_DIGEST_AUTH;CONFIG_ESP_HTTP_CLIENT_ENABLE_CUSTOM_TRANSPORT;CONFIG_ESP_HTTP_CLIENT_EVENT_POST_TIMEOUT;CONFIG_HTTPD_MAX_REQ_HDR_LEN;CONFIG_HTTPD_MAX_URI_LEN;CONFIG_HTTPD_ERR_RESP_NO_DELAY;CONFIG_HTTPD_PURGE_BUF_LEN;CONFIG_HTTPD_LOG_PURGE_DATA;CONFIG_HTTPD_WS_SUPPORT;CONFIG_HTTPD_QUEUE_WORK_BLOCKING;CONFIG_HTTPD_SERVER_EVENT_POST_TIMEOUT;CONFIG_ESP_HTTPS_OTA_DECRYPT_CB;CONFIG_ESP_HTTPS_OTA_ALLOW_HTTP;CONFIG_OTA_ALLOW_HTTP;CONFIG_ESP_HTTPS_OTA_EVENT_POST_TIMEOUT;CONFIG_ESP_HTTPS_SERVER_ENABLE;CONFIG_ESP_HTTPS_SERVER_EVENT_POST_TIMEOUT;CONFIG_ESP32C3_REV_MIN_0;CONFIG_ESP32C3_REV_MIN_1;CONFIG_ESP32C3_REV_MIN_2;CONFIG_ESP32C3_REV_MIN_3;CONFIG_ESP32C3_REV_MIN_4;CONFIG_ESP32C3_REV_MIN_101;CONFIG_ESP32C3_REV_MIN_FULL;CONFIG_ESP_REV_MIN_FULL;CONFIG_ESP32C3_REV_MAX_FULL;CONFIG_ESP_REV_MAX_FULL;CONFIG_ESP_EFUSE_BLOCK_REV_MIN_FULL;CONFIG_ESP_EFUSE_BLOCK_REV_MAX_FULL;CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_STA;CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_AP;CONFIG_ESP_MAC_ADDR_UNIVERSE_BT;CONFIG_ESP_MAC_ADDR_UNIVERSE_ETH;CONFIG_ESP_MAC_UNIVERSAL_MAC_ADDRESSES_FOUR;CONFIG_ESP_MAC_UNIVERSAL_MAC_ADDRESSES;CONFIG_ESP32C3_UNIVERSAL_MAC_ADDRESSES_TWO;CONFIG_ESP32C3_UNIVERSAL_MAC_ADDRESSES_FOUR;CONFIG_ESP32C3_UNIVERSAL_MAC_ADDRESSES;CONFIG_ESP_MAC_USE_CUSTOM_MAC_AS_BASE_MAC;CONFIG_ESP_SLEEP_POWER_DOWN_FLASH;CONFIG_ESP_SYSTEM_PD_FLASH;CONFIG_ESP_SLEEP_FLASH_LEAKAGE_WORKAROUND;CONFIG_ESP_SLEEP_MSPI_NEED_ALL_IO_PU;CONFIG_ESP_SLEEP_GPIO_RESET_WORKAROUND;CONFIG_ESP32C3_LIGHTSLEEP_GPIO_RESET_WORKAROUND;CONFIG_ESP_SLEEP_WAIT_FLASH_READY_EXTRA_DELAY;CONFIG_ESP_SLEEP_CACHE_SAFE_ASSERTION;CONFIG_ESP_SLEEP_DEBUG;CONFIG_ESP_SLEEP_GPIO_ENABLE_INTERNAL_RESISTORS;CONFIG_RTC_CLK_SRC_INT_RC;CONFIG_ESP32C3_RTC_CLK_SRC_INT_RC;CONFIG_RTC_CLK_SRC_EXT_CRYS;CONFIG_ESP32C3_RTC_CLK_SRC_EXT_CRYS;CONFIG_RTC_CLK_SRC_EXT_OSC;CONFIG_ESP32C3_RTC_CLK_SRC_EXT_OSC;CONFIG_RTC_CLK_SRC_INT_8MD256;CONFIG_ESP32C3_RTC_CLK_SRC_INT_8MD256;CONFIG_RTC_CLK_CAL_CYCLES;CONFIG_ESP32C3_RTC_CLK_CAL_CYCLES;CONFIG_PERIPH_CTRL_FUNC_IN_IRAM;CONFIG_GDMA_CTRL_FUNC_IN_IRAM;CONFIG_GDMA_ISR_IRAM_SAFE;CONFIG_GDMA_ENABLE_DEBUG_LOG;CONFIG_XTAL_FREQ_40;CONFIG_XTAL_FREQ;CONFIG_ESP_SPI_BUS_LOCK_ISR_FUNCS_IN_IRAM;CONFIG_LCD_ENABLE_DEBUG_LOG;CONFIG_ESP_NETIF_IP_LOST_TIMER_INTERVAL;CONFIG_ESP_NETIF_PROVIDE_CUSTOM_IMPLEMENTATION;CONFIG_ESP_NETIF_TCPIP_LWIP;CONFIG_ESP_NETIF_LOOPBACK;CONFIG_ESP_NETIF_USES_TCPIP_WITH_BSD_API;CONFIG_ESP_NETIF_REPORT_DATA_TRAFFIC;CONFIG_ESP_NETIF_RECEIVE_REPORT_ERRORS;CONFIG_ESP_NETIF_L2_TAP;CONFIG_ESP_NETIF_BRIDGE_EN;CONFIG_ESP_NETIF_SET_DNS_PER_DEFAULT_NETIF;CONFIG_ESP_PHY_ENABLED;CONFIG_ESP_PHY_CALIBRATION_AND_DATA_STORAGE;CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE;CONFIG_ESP_PHY_INIT_DATA_IN_PARTITION;CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION;CONFIG_ESP_PHY_MAX_WIFI_TX_POWER;CONFIG_ESP32_PHY_MAX_WIFI_TX_POWER;CONFIG_ESP_PHY_MAX_TX_POWER;CONFIG_ESP32_PHY_MAX_TX_POWER;CONFIG_ESP_PHY_REDUCE_TX_POWER;CONFIG_REDUCE_PHY_TX_POWER;CONFIG_ESP32_REDUCE_PHY_TX_POWER;CONFIG_ESP_PHY_ENABLE_USB;CONFIG_ESP_PHY_ENABLE_CERT_TEST;CONFIG_ESP_PHY_RF_CAL_PARTIAL;CONFIG_ESP_PHY_RF_CAL_NONE;CONFIG_ESP_PHY_RF_CAL_FULL;CONFIG_ESP_PHY_CALIBRATION_MODE;CONFIG_ESP_PHY_PLL_TRACK_DEBUG;CONFIG_ESP_PHY_RECORD_USED_TIME;CONFIG_PM_ENABLE;CONFIG_PM_SLP_IRAM_OPT;CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP;CONFIG_ESP_SYSTEM_PM_POWER_DOWN_CPU;CONFIG_RINGBUF_PLACE_FUNCTIONS_INTO_FLASH;CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_80;CONFIG_ESP32C3_DEFAULT_CPU_FREQ_80;CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_160;CONFIG_ESP32C3_DEFAULT_CPU_FREQ_160;CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ;CONFIG_ESP32C3_DEFAULT_CPU_FREQ_MHZ;CONFIG_ESP_SYSTEM_PANIC_PRINT_HALT;CONFIG_ESP_SYSTEM_PANIC_PRINT_REBOOT;CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT;CONFIG_ESP_SYSTEM_PANIC_GDBSTUB;CONFIG_ESP_SYSTEM_PANIC_REBOOT_DELAY_SECONDS;CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE;CONFIG_ESP_SYSTEM_RTC_FAST_MEM_AS_HEAP_DEPCHECK;CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP;CONFIG_ESP_SYSTEM_USE_EH_FRAME;CONFIG_ESP_SYSTEM_MEMPROT_FEATURE;CONFIG_ESP32C3_MEMPROT_FEATURE;CONFIG_ESP_SYSTEM_MEMPROT_FEATURE_LOCK;CONFIG_ESP32C3_MEMPROT_FEATURE_LOCK;CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE;CONFIG_SYSTEM_EVENT_QUEUE_SIZE;CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE;CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE;CONFIG_ESP_MAIN_TASK_STACK_SIZE;CONFIG_MAIN_TASK_STACK_SIZE;CONFIG_ESP_MAIN_TASK_AFFINITY_CPU0;CONFIG_ESP_MAIN_TASK_AFFINITY_NO_AFFINITY;CONFIG_ESP_MAIN_TASK_AFFINITY;CONFIG_ESP_MINIMAL_SHARED_STACK_SIZE;CONFIG_ESP_CONSOLE_UART_DEFAULT;CONFIG_CONSOLE_UART_DEFAULT;CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG;CONFIG_ESP_CONSOLE_UART_CUSTOM;CONFIG_CONSOLE_UART_CUSTOM;CONFIG_ESP_CONSOLE_NONE;CONFIG_CONSOLE_UART_NONE;CONFIG_ESP_CONSOLE_UART_NONE;CONFIG_ESP_CONSOLE_SECONDARY_NONE;CONFIG_ESP_CONSOLE_SECONDARY_USB_SERIAL_JTAG;CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG_ENABLED;CONFIG_ESP_CONSOLE_UART;CONFIG_CONSOLE_UART;CONFIG_ESP_CONSOLE_UART_NUM;CONFIG_CONSOLE_UART_NUM;CONFIG_ESP_CONSOLE_ROM_SERIAL_PORT_NUM;CONFIG_ESP_CONSOLE_UART_BAUDRATE;CONFIG_CONSOLE_UART_BAUDRATE;CONFIG_ESP_INT_WDT;CONFIG_INT_WDT;CONFIG_ESP_INT_WDT_TIMEOUT_MS;CONFIG_INT_WDT_TIMEOUT_MS;CONFIG_ESP_TASK_WDT_EN;CONFIG_ESP_TASK_WDT_INIT;CONFIG_TASK_WDT;CONFIG_ESP_TASK_WDT;CONFIG_ESP_TASK_WDT_PANIC;CONFIG_TASK_WDT_PANIC;CONFIG_ESP_TASK_WDT_TIMEOUT_S;CONFIG_TASK_WDT_TIMEOUT_S;CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0;CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU0;CONFIG_ESP_PANIC_HANDLER_IRAM;CONFIG_ESP_DEBUG_STUBS_ENABLE;CONFIG_ESP32_DEBUG_STUBS_ENABLE;CONFIG_ESP_DEBUG_OCDAWARE;CONFIG_ESP32C3_DEBUG_OCDAWARE;CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL_4;CONFIG_ESP_BROWNOUT_DET;CONFIG_BROWNOUT_DET;CONFIG_ESP32C3_BROWNOUT_DET;CONFIG_ESP_BROWNOUT_DET_LVL_SEL_7;CONFIG_BROWNOUT_DET_LVL_SEL_7;CONFIG_ESP32C3_BROWNOUT_DET_LVL_SEL_7;CONFIG_ESP_BROWNOUT_DET_LVL_SEL_6;CONFIG_BROWNOUT_DET_LVL_SEL_6;CONFIG_ESP32C3_BROWNOUT_DET_LVL_SEL_6;CONFIG_ESP_BROWNOUT_DET_LVL_SEL_5;CONFIG_BROWNOUT_DET_LVL_SEL_5;CONFIG_ESP32C3_BROWNOUT_DET_LVL_SEL_5;CONFIG_ESP_BROWNOUT_DET_LVL_SEL_4;CONFIG_BROWNOUT_DET_LVL_SEL_4;CONFIG_ESP32C3_BROWNOUT_DET_LVL_SEL_4;CONFIG_ESP_BROWNOUT_DET_LVL_SEL_3;CONFIG_BROWNOUT_DET_LVL_SEL_3;CONFIG_ESP32C3_BROWNOUT_DET_LVL_SEL_3;CONFIG_ESP_BROWNOUT_DET_LVL_SEL_2;CONFIG_BROWNOUT_DET_LVL_SEL_2;CONFIG_ESP32C3_BROWNOUT_DET_LVL_SEL_2;CONFIG_ESP_BROWNOUT_DET_LVL;CONFIG_BROWNOUT_DET_LVL;CONFIG_ESP32C3_BROWNOUT_DET_LVL;CONFIG_ESP_SYSTEM_BROWNOUT_INTR;CONFIG_ESP_SYSTEM_HW_STACK_GUARD;CONFIG_ESP_SYSTEM_HW_PC_RECORD;CONFIG_ESP_IPC_TASK_STACK_SIZE;CONFIG_IPC_TASK_STACK_SIZE;CONFIG_ESP_TIMER_PROFILING;CONFIG_ESP_TIME_FUNCS_USE_RTC_TIMER;CONFIG_ESP_TIME_FUNCS_USE_ESP_TIMER;CONFIG_ESP_TIMER_TASK_STACK_SIZE;CONFIG_TIMER_TASK_STACK_SIZE;CONFIG_ESP_TIMER_INTERRUPT_LEVEL;CONFIG_ESP_TIMER_SHOW_EXPERIMENTAL;CONFIG_ESP_TIMER_TASK_AFFINITY;CONFIG_ESP_TIMER_TASK_AFFINITY_CPU0;CONFIG_ESP_TIMER_ISR_AFFINITY_CPU0;CONFIG_ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD;CONFIG_ESP_TIMER_IMPL_SYSTIMER;CONFIG_ESP_WIFI_ENABLED;CONFIG_ESP32_WIFI_ENABLED;CONFIG_ESP_WIFI_STATIC_RX_BUFFER_NUM;CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM;CONFIG_ESP_WIFI_DYNAMIC_RX_BUFFER_NUM;CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM;CONFIG_ESP_WIFI_STATIC_TX_BUFFER;CONFIG_ESP32_WIFI_STATIC_TX_BUFFER;CONFIG_ESP_WIFI_DYNAMIC_TX_BUFFER;CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER;CONFIG_ESP_WIFI_TX_BUFFER_TYPE;CONFIG_ESP32_WIFI_TX_BUFFER_TYPE;CONFIG_ESP_WIFI_DYNAMIC_TX_BUFFER_NUM;CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM;CONFIG_ESP_WIFI_STATIC_RX_MGMT_BUFFER;CONFIG_ESP_WIFI_DYNAMIC_RX_MGMT_BUFFER;CONFIG_ESP_WIFI_DYNAMIC_RX_MGMT_BUF;CONFIG_ESP_WIFI_RX_MGMT_BUF_NUM_DEF;CONFIG_ESP_WIFI_CSI_ENABLED;CONFIG_ESP32_WIFI_CSI_ENABLED;CONFIG_ESP_WIFI_AMPDU_TX_ENABLED;CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED;CONFIG_ESP_WIFI_TX_BA_WIN;CONFIG_ESP32_WIFI_TX_BA_WIN;CONFIG_ESP_WIFI_AMPDU_RX_ENABLED;CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED;CONFIG_ESP_WIFI_RX_BA_WIN;CONFIG_ESP32_WIFI_RX_BA_WIN;CONFIG_ESP_WIFI_NVS_ENABLED;CONFIG_ESP32_WIFI_NVS_ENABLED;CONFIG_ESP_WIFI_SOFTAP_BEACON_MAX_LEN;CONFIG_ESP32_WIFI_SOFTAP_BEACON_MAX_LEN;CONFIG_ESP_WIFI_MGMT_SBUF_NUM;CONFIG_ESP32_WIFI_MGMT_SBUF_NUM;CONFIG_ESP_WIFI_IRAM_OPT;CONFIG_ESP32_WIFI_IRAM_OPT;CONFIG_ESP_WIFI_EXTRA_IRAM_OPT;CONFIG_ESP_WIFI_RX_IRAM_OPT;CONFIG_ESP32_WIFI_RX_IRAM_OPT;CONFIG_ESP_WIFI_ENABLE_WPA3_SAE;CONFIG_ESP32_WIFI_ENABLE_WPA3_SAE;CONFIG_ESP_WIFI_ENABLE_SAE_PK;CONFIG_ESP_WIFI_SOFTAP_SAE_SUPPORT;CONFIG_ESP_WIFI_ENABLE_WPA3_OWE_STA;CONFIG_ESP32_WIFI_ENABLE_WPA3_OWE_STA;CONFIG_ESP_WIFI_SLP_IRAM_OPT;CONFIG_ESP_WIFI_SLP_DEFAULT_MIN_ACTIVE_TIME;CONFIG_ESP_WIFI_SLP_DEFAULT_MAX_ACTIVE_TIME;CONFIG_ESP_WIFI_SLP_DEFAULT_WAIT_BROADCAST_DATA_TIME;CONFIG_ESP_WIFI_FTM_ENABLE;CONFIG_ESP_WIFI_STA_DISCONNECTED_PM_ENABLE;CONFIG_ESP_WIFI_GCMP_SUPPORT;CONFIG_ESP_WIFI_GMAC_SUPPORT;CONFIG_ESP_WIFI_SOFTAP_SUPPORT;CONFIG_ESP_WIFI_SLP_BEACON_LOST_OPT;CONFIG_ESP_WIFI_ESPNOW_MAX_ENCRYPT_NUM;CONFIG_ESP_WIFI_MBEDTLS_CRYPTO;CONFIG_WPA_MBEDTLS_CRYPTO;CONFIG_ESP_WIFI_MBEDTLS_TLS_CLIENT;CONFIG_WPA_MBEDTLS_TLS_CLIENT;CONFIG_ESP_WIFI_WAPI_PSK;CONFIG_WPA_WAPI_PSK;CONFIG_ESP_WIFI_SUITE_B_192;CONFIG_WPA_SUITE_B_192;CONFIG_ESP_WIFI_11KV_SUPPORT;CONFIG_WPA_11KV_SUPPORT;CONFIG_ESP_WIFI_MBO_SUPPORT;CONFIG_WPA_MBO_SUPPORT;CONFIG_ESP_WIFI_DPP_SUPPORT;CONFIG_WPA_DPP_SUPPORT;CONFIG_ESP_WIFI_11R_SUPPORT;CONFIG_WPA_11R_SUPPORT;CONFIG_ESP_WIFI_WPS_SOFTAP_REGISTRAR;CONFIG_WPA_WPS_SOFTAP_REGISTRAR;CONFIG_ESP_WIFI_WPS_STRICT;CONFIG_WPA_WPS_STRICT;CONFIG_ESP_WIFI_WPS_PASSPHRASE;CONFIG_ESP_WIFI_DEBUG_PRINT;CONFIG_WPA_DEBUG_PRINT;CONFIG_ESP_WIFI_TESTING_OPTIONS;CONFIG_WPA_TESTING_OPTIONS;CONFIG_ESP_WIFI_ENTERPRISE_SUPPORT;CONFIG_ESP_WIFI_ENT_FREE_DYNAMIC_BUFFER;CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH;CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH;CONFIG_ESP_COREDUMP_ENABLE_TO_UART;CONFIG_ESP32_ENABLE_COREDUMP_TO_UART;CONFIG_ESP_COREDUMP_ENABLE_TO_NONE;CONFIG_ESP32_ENABLE_COREDUMP_TO_NONE;CONFIG_FATFS_VOLUME_COUNT;CONFIG_FATFS_LFN_NONE;CONFIG_FATFS_LFN_HEAP;CONFIG_FATFS_LFN_STACK;CONFIG_FATFS_SECTOR_512;CONFIG_FATFS_SECTOR_4096;CONFIG_FATFS_CODEPAGE_DYNAMIC;CONFIG_FATFS_CODEPAGE_437;CONFIG_FATFS_CODEPAGE_720;CONFIG_FATFS_CODEPAGE_737;CONFIG_FATFS_CODEPAGE_771;CONFIG_FATFS_CODEPAGE_775;CONFIG_FATFS_CODEPAGE_850;CONFIG_FATFS_CODEPAGE_852;CONFIG_FATFS_CODEPAGE_855;CONFIG_FATFS_CODEPAGE_857;CONFIG_FATFS_CODEPAGE_860;CONFIG_FATFS_CODEPAGE_861;CONFIG_FATFS_CODEPAGE_862;CONFIG_FATFS_CODEPAGE_863;CONFIG_FATFS_CODEPAGE_864;CONFIG_FATFS_CODEPAGE_865;CONFIG_FATFS_CODEPAGE_866;CONFIG_FATFS_CODEPAGE_869;CONFIG_FATFS_CODEPAGE_932;CONFIG_FATFS_CODEPAGE_936;CONFIG_FATFS_CODEPAGE_949;CONFIG_FATFS_CODEPAGE_950;CONFIG_FATFS_CODEPAGE;CONFIG_FATFS_FS_LOCK;CONFIG_FATFS_TIMEOUT_MS;CONFIG_FATFS_PER_FILE_CACHE;CONFIG_FATFS_USE_FASTSEEK;CONFIG_FATFS_USE_STRFUNC_NONE;CONFIG_FATFS_USE_STRFUNC_WITHOUT_CRLF_CONV;CONFIG_FATFS_USE_STRFUNC_WITH_CRLF_CONV;CONFIG_FATFS_VFS_FSTAT_BLKSIZE;CONFIG_FATFS_IMMEDIATE_FSYNC;CONFIG_FATFS_USE_LABEL;CONFIG_FATFS_LINK_LOCK;CONFIG_FREERTOS_SMP;CONFIG_FREERTOS_UNICORE;CONFIG_FREERTOS_HZ;CONFIG_FREERTOS_OPTIMIZED_SCHEDULER;CONFIG_FREERTOS_CHECK_STACKOVERFLOW_NONE;CONFIG_FREERTOS_CHECK_STACKOVERFLOW_PTRVAL;CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY;CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS;CONFIG_FREERTOS_IDLE_TASK_STACKSIZE;CONFIG_FREERTOS_USE_IDLE_HOOK;CONFIG_FREERTOS_USE_TICK_HOOK;CONFIG_FREERTOS_MAX_TASK_NAME_LEN;CONFIG_FREERTOS_ENABLE_BACKWARD_COMPATIBILITY;CONFIG_FREERTOS_USE_TIMERS;CONFIG_FREERTOS_TIMER_SERVICE_TASK_NAME;CONFIG_FREERTOS_TIMER_TASK_AFFINITY_CPU0;CONFIG_FREERTOS_TIMER_TASK_NO_AFFINITY;CONFIG_FREERTOS_TIMER_SERVICE_TASK_CORE_AFFINITY;CONFIG_FREERTOS_TIMER_TASK_PRIORITY;CONFIG_TIMER_TASK_PRIORITY;CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH;CONFIG_TIMER_TASK_STACK_DEPTH;CONFIG_FREERTOS_TIMER_QUEUE_LENGTH;CONFIG_TIMER_QUEUE_LENGTH;CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE;CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES;CONFIG_FREERTOS_USE_TRACE_FACILITY;CONFIG_FREERTOS_USE_LIST_DATA_INTEGRITY_CHECK_BYTES;CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS;CONFIG_FREERTOS_USE_APPLICATION_TASK_TAG;CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER;CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK;CONFIG_FREERTOS_TLSP_DELETION_CALLBACKS;CONFIG_FREERTOS_TASK_PRE_DELETION_HOOK;CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP;CONFIG_ENABLE_STATIC_TASK_CLEAN_UP_HOOK;CONFIG_FREERTOS_CHECK_MUTEX_GIVEN_BY_OWNER;CONFIG_FREERTOS_ISR_STACKSIZE;CONFIG_FREERTOS_INTERRUPT_BACKTRACE;CONFIG_FREERTOS_TICK_SUPPORT_SYSTIMER;CONFIG_FREERTOS_CORETIMER_SYSTIMER_LVL1;CONFIG_FREERTOS_CORETIMER_SYSTIMER_LVL3;CONFIG_FREERTOS_SYSTICK_USES_SYSTIMER;CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH;CONFIG_FREERTOS_CHECK_PORT_CRITICAL_COMPLIANCE;CONFIG_FREERTOS_PORT;CONFIG_FREERTOS_NO_AFFINITY;CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION;CONFIG_FREERTOS_DEBUG_OCDAWARE;CONFIG_FREERTOS_ENABLE_TASK_SNAPSHOT;CONFIG_FREERTOS_PLACE_SNAPSHOT_FUNS_INTO_FLASH;CONFIG_FREERTOS_NUMBER_OF_CORES;CONFIG_HAL_ASSERTION_EQUALS_SYSTEM;CONFIG_HAL_ASSERTION_DISABLE;CONFIG_HAL_ASSERTION_SILENT;CONFIG_HAL_ASSERTION_SILIENT;CONFIG_HAL_ASSERTION_ENABLE;CONFIG_HAL_DEFAULT_ASSERTION_LEVEL;CONFIG_HAL_SPI_MASTER_FUNC_IN_IRAM;CONFIG_HAL_SPI_SLAVE_FUNC_IN_IRAM;CONFIG_HEAP_POISONING_DISABLED;CONFIG_HEAP_POISONING_LIGHT;CONFIG_HEAP_POISONING_COMPREHENSIVE;CONFIG_HEAP_TRACING_OFF;CONFIG_HEAP_TRACING_STANDALONE;CONFIG_HEAP_TRACING_TOHOST;CONFIG_HEAP_USE_HOOKS;CONFIG_HEAP_TASK_TRACKING;CONFIG_HEAP_ABORT_WHEN_ALLOCATION_FAILS;CONFIG_HEAP_PLACE_FUNCTION_INTO_FLASH;CONFIG_LOG_DEFAULT_LEVEL_NONE;CONFIG_LOG_DEFAULT_LEVEL_ERROR;CONFIG_LOG_DEFAULT_LEVEL_WARN;CONFIG_LOG_DEFAULT_LEVEL_INFO;CONFIG_LOG_DEFAULT_LEVEL_DEBUG;CONFIG_LOG_DEFAULT_LEVEL_VERBOSE;CONFIG_LOG_DEFAULT_LEVEL;CONFIG_LOG_MAXIMUM_EQUALS_DEFAULT;CONFIG_LOG_MAXIMUM_LEVEL_DEBUG;CONFIG_LOG_MAXIMUM_LEVEL_VERBOSE;CONFIG_LOG_MAXIMUM_LEVEL;CONFIG_LOG_MASTER_LEVEL;CONFIG_LOG_DYNAMIC_LEVEL_CONTROL;CONFIG_LOG_TAG_LEVEL_IMPL_NONE;CONFIG_LOG_TAG_LEVEL_IMPL_LINKED_LIST;CONFIG_LOG_TAG_LEVEL_IMPL_CACHE_AND_LINKED_LIST;CONFIG_LOG_TAG_LEVEL_CACHE_ARRAY;CONFIG_LOG_TAG_LEVEL_CACHE_BINARY_MIN_HEAP;CONFIG_LOG_TAG_LEVEL_IMPL_CACHE_SIZE;CONFIG_LOG_COLORS;CONFIG_LOG_TIMESTAMP_SOURCE_RTOS;CONFIG_LOG_TIMESTAMP_SOURCE_SYSTEM;CONFIG_LWIP_ENABLE;CONFIG_LWIP_LOCAL_HOSTNAME;CONFIG_LWIP_NETIF_API;CONFIG_LWIP_TCPIP_TASK_PRIO;CONFIG_LWIP_TCPIP_CORE_LOCKING;CONFIG_LWIP_CHECK_THREAD_SAFETY;CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES;CONFIG_LWIP_L2_TO_L3_COPY;CONFIG_L2_TO_L3_COPY;CONFIG_LWIP_IRAM_OPTIMIZATION;CONFIG_LWIP_EXTRA_IRAM_OPTIMIZATION;CONFIG_LWIP_TIMERS_ONDEMAND;CONFIG_LWIP_ND6;CONFIG_LWIP_FORCE_ROUTER_FORWARDING;CONFIG_LWIP_MAX_SOCKETS;CONFIG_LWIP_USE_ONLY_LWIP_SELECT;CONFIG_LWIP_SO_LINGER;CONFIG_LWIP_SO_REUSE;CONFIG_LWIP_SO_REUSE_RXTOALL;CONFIG_LWIP_SO_RCVBUF;CONFIG_LWIP_NETBUF_RECVINFO;CONFIG_LWIP_IP_DEFAULT_TTL;CONFIG_LWIP_IP4_FRAG;CONFIG_LWIP_IP6_FRAG;CONFIG_LWIP_IP4_REASSEMBLY;CONFIG_LWIP_IP6_REASSEMBLY;CONFIG_LWIP_IP_REASS_MAX_PBUFS;CONFIG_LWIP_IP_FORWARD;CONFIG_LWIP_STATS;CONFIG_LWIP_ESP_GRATUITOUS_ARP;CONFIG_ESP_GRATUITOUS_ARP;CONFIG_LWIP_GARP_TMR_INTERVAL;CONFIG_GARP_TMR_INTERVAL;CONFIG_LWIP_ESP_MLDV6_REPORT;CONFIG_LWIP_MLDV6_TMR_INTERVAL;CONFIG_LWIP_TCPIP_RECVMBOX_SIZE;CONFIG_TCPIP_RECVMBOX_SIZE;CONFIG_LWIP_DHCP_DOES_ARP_CHECK;CONFIG_LWIP_DHCP_DOES_ACD_CHECK;CONFIG_LWIP_DHCP_DOES_NOT_CHECK_OFFERED_IP;CONFIG_LWIP_DHCP_DISABLE_CLIENT_ID;CONFIG_LWIP_DHCP_DISABLE_VENDOR_CLASS_ID;CONFIG_LWIP_DHCP_RESTORE_LAST_IP;CONFIG_LWIP_DHCP_OPTIONS_LEN;CONFIG_LWIP_NUM_NETIF_CLIENT_DATA;CONFIG_LWIP_DHCP_COARSE_TIMER_SECS;CONFIG_LWIP_DHCPS;CONFIG_LWIP_DHCPS_LEASE_UNIT;CONFIG_LWIP_DHCPS_MAX_STATION_NUM;CONFIG_LWIP_DHCPS_STATIC_ENTRIES;CONFIG_LWIP_DHCPS_ADD_DNS;CONFIG_LWIP_AUTOIP;CONFIG_LWIP_IPV4;CONFIG_LWIP_IPV6;CONFIG_LWIP_IPV6_AUTOCONFIG;CONFIG_LWIP_IPV6_NUM_ADDRESSES;CONFIG_LWIP_IPV6_FORWARD;CONFIG_LWIP_NETIF_STATUS_CALLBACK;CONFIG_LWIP_NETIF_LOOPBACK;CONFIG_LWIP_LOOPBACK_MAX_PBUFS;CONFIG_LWIP_MAX_ACTIVE_TCP;CONFIG_LWIP_MAX_LISTENING_TCP;CONFIG_LWIP_TCP_HIGH_SPEED_RETRANSMISSION;CONFIG_LWIP_TCP_MAXRTX;CONFIG_TCP_MAXRTX;CONFIG_LWIP_TCP_SYNMAXRTX;CONFIG_TCP_SYNMAXRTX;CONFIG_LWIP_TCP_MSS;CONFIG_TCP_MSS;CONFIG_LWIP_TCP_TMR_INTERVAL;CONFIG_LWIP_TCP_MSL;CONFIG_TCP_MSL;CONFIG_LWIP_TCP_FIN_WAIT_TIMEOUT;CONFIG_LWIP_TCP_SND_BUF_DEFAULT;CONFIG_TCP_SND_BUF_DEFAULT;CONFIG_LWIP_TCP_WND_DEFAULT;CONFIG_TCP_WND_DEFAULT;CONFIG_LWIP_TCP_RECVMBOX_SIZE;CONFIG_TCP_RECVMBOX_SIZE;CONFIG_LWIP_TCP_ACCEPTMBOX_SIZE;CONFIG_LWIP_TCP_QUEUE_OOSEQ;CONFIG_TCP_QUEUE_OOSEQ;CONFIG_LWIP_TCP_OOSEQ_TIMEOUT;CONFIG_LWIP_TCP_OOSEQ_MAX_PBUFS;CONFIG_LWIP_TCP_SACK_OUT;CONFIG_LWIP_TCP_OVERSIZE_MSS;CONFIG_TCP_OVERSIZE_MSS;CONFIG_LWIP_TCP_OVERSIZE_QUARTER_MSS;CONFIG_TCP_OVERSIZE_QUARTER_MSS;CONFIG_LWIP_TCP_OVERSIZE_DISABLE;CONFIG_TCP_OVERSIZE_DISABLE;CONFIG_LWIP_TCP_RTO_TIME;CONFIG_LWIP_MAX_UDP_PCBS;CONFIG_LWIP_UDP_RECVMBOX_SIZE;CONFIG_UDP_RECVMBOX_SIZE;CONFIG_LWIP_CHECKSUM_CHECK_IP;CONFIG_LWIP_CHECKSUM_CHECK_UDP;CONFIG_LWIP_CHECKSUM_CHECK_ICMP;CONFIG_LWIP_TCPIP_TASK_STACK_SIZE;CONFIG_TCPIP_TASK_STACK_SIZE;CONFIG_LWIP_TCPIP_TASK_AFFINITY_NO_AFFINITY;CONFIG_TCPIP_TASK_AFFINITY_NO_AFFINITY;CONFIG_LWIP_TCPIP_TASK_AFFINITY_CPU0;CONFIG_TCPIP_TASK_AFFINITY_CPU0;CONFIG_LWIP_TCPIP_TASK_AFFINITY;CONFIG_TCPIP_TASK_AFFINITY;CONFIG_LWIP_IPV6_MEMP_NUM_ND6_QUEUE;CONFIG_LWIP_IPV6_ND6_NUM_NEIGHBORS;CONFIG_LWIP_IPV6_ND6_NUM_PREFIXES;CONFIG_LWIP_IPV6_ND6_NUM_ROUTERS;CONFIG_LWIP_IPV6_ND6_NUM_DESTINATIONS;CONFIG_LWIP_PPP_SUPPORT;CONFIG_PPP_SUPPORT;CONFIG_LWIP_SLIP_SUPPORT;CONFIG_LWIP_ICMP;CONFIG_LWIP_MULTICAST_PING;CONFIG_LWIP_BROADCAST_PING;CONFIG_LWIP_MAX_RAW_PCBS;CONFIG_LWIP_SNTP_MAX_SERVERS;CONFIG_LWIP_DHCP_GET_NTP_SRV;CONFIG_LWIP_SNTP_UPDATE_DELAY;CONFIG_LWIP_SNTP_STARTUP_DELAY;CONFIG_LWIP_SNTP_MAXIMUM_STARTUP_DELAY;CONFIG_LWIP_DNS_MAX_HOST_IP;CONFIG_LWIP_DNS_MAX_SERVERS;CONFIG_LWIP_FALLBACK_DNS_SERVER_SUPPORT;CONFIG_LWIP_DNS_SETSERVER_WITH_NETIF;CONFIG_LWIP_BRIDGEIF_MAX_PORTS;CONFIG_LWIP_ESP_LWIP_ASSERT;CONFIG_LWIP_HOOK_TCP_ISN_NONE;CONFIG_LWIP_HOOK_TCP_ISN_DEFAULT;CONFIG_LWIP_HOOK_TCP_ISN_CUSTOM;CONFIG_LWIP_HOOK_IP6_ROUTE_NONE;CONFIG_LWIP_HOOK_IP6_ROUTE_DEFAULT;CONFIG_LWIP_HOOK_IP6_ROUTE_CUSTOM;CONFIG_LWIP_HOOK_ND6_GET_GW_NONE;CONFIG_LWIP_HOOK_ND6_GET_GW_DEFAULT;CONFIG_LWIP_HOOK_ND6_GET_GW_CUSTOM;CONFIG_LWIP_HOOK_IP6_SELECT_SRC_ADDR_NONE;CONFIG_LWIP_HOOK_IP6_SELECT_SRC_ADDR_DEFAULT;CONFIG_LWIP_HOOK_IP6_SELECT_SRC_ADDR_CUSTOM;CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_NONE;CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_DEFAULT;CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_CUSTOM;CONFIG_LWIP_HOOK_DNS_EXT_RESOLVE_NONE;CONFIG_LWIP_HOOK_DNS_EXT_RESOLVE_CUSTOM;CONFIG_LWIP_HOOK_IP6_INPUT_NONE;CONFIG_LWIP_HOOK_IP6_INPUT_DEFAULT;CONFIG_LWIP_HOOK_IP6_INPUT_CUSTOM;CONFIG_LWIP_DEBUG;CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC;CONFIG_MBEDTLS_DEFAULT_MEM_ALLOC;CONFIG_MBEDTLS_CUSTOM_MEM_ALLOC;CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN;CONFIG_MBEDTLS_SSL_IN_CONTENT_LEN;CONFIG_MBEDTLS_SSL_OUT_CONTENT_LEN;CONFIG_MBEDTLS_DYNAMIC_BUFFER;CONFIG_MBEDTLS_DYNAMIC_FREE_CONFIG_DATA;CONFIG_MBEDTLS_DYNAMIC_FREE_CA_CERT;CONFIG_MBEDTLS_DEBUG;CONFIG_MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH;CONFIG_MBEDTLS_X509_TRUSTED_CERT_CALLBACK;CONFIG_MBEDTLS_SSL_CONTEXT_SERIALIZATION;CONFIG_MBEDTLS_SSL_KEEP_PEER_CERTIFICATE;CONFIG_MBEDTLS_PKCS7_C;CONFIG_MBEDTLS_CERTIFICATE_BUNDLE;CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_FULL;CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_CMN;CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_NONE;CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE;CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEPRECATED_LIST;CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_MAX_CERTS;CONFIG_MBEDTLS_ECP_RESTARTABLE;CONFIG_MBEDTLS_CMAC_C;CONFIG_MBEDTLS_HARDWARE_AES;CONFIG_MBEDTLS_AES_USE_INTERRUPT;CONFIG_MBEDTLS_AES_INTERRUPT_LEVEL;CONFIG_MBEDTLS_GCM_SUPPORT_NON_AES_CIPHER;CONFIG_MBEDTLS_HARDWARE_MPI;CONFIG_MBEDTLS_LARGE_KEY_SOFTWARE_MPI;CONFIG_MBEDTLS_MPI_USE_INTERRUPT;CONFIG_MBEDTLS_MPI_INTERRUPT_LEVEL;CONFIG_MBEDTLS_HARDWARE_SHA;CONFIG_MBEDTLS_ROM_MD5;CONFIG_MBEDTLS_ATCA_HW_ECDSA_SIGN;CONFIG_MBEDTLS_ATCA_HW_ECDSA_VERIFY;CONFIG_MBEDTLS_HAVE_TIME;CONFIG_MBEDTLS_PLATFORM_TIME_ALT;CONFIG_MBEDTLS_HAVE_TIME_DATE;CONFIG_MBEDTLS_ECDSA_DETERMINISTIC;CONFIG_MBEDTLS_SHA512_C;CONFIG_MBEDTLS_SHA3_C;CONFIG_MBEDTLS_TLS_SERVER_AND_CLIENT;CONFIG_MBEDTLS_TLS_SERVER_ONLY;CONFIG_MBEDTLS_TLS_CLIENT_ONLY;CONFIG_MBEDTLS_TLS_DISABLED;CONFIG_MBEDTLS_TLS_SERVER;CONFIG_MBEDTLS_TLS_CLIENT;CONFIG_MBEDTLS_TLS_ENABLED;CONFIG_MBEDTLS_PSK_MODES;CONFIG_MBEDTLS_KEY_EXCHANGE_RSA;CONFIG_MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE;CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_RSA;CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA;CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA;CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_RSA;CONFIG_MBEDTLS_SSL_RENEGOTIATION;CONFIG_MBEDTLS_SSL_PROTO_TLS1_2;CONFIG_MBEDTLS_SSL_PROTO_GMTSSL1_1;CONFIG_MBEDTLS_SSL_PROTO_DTLS;CONFIG_MBEDTLS_SSL_ALPN;CONFIG_MBEDTLS_CLIENT_SSL_SESSION_TICKETS;CONFIG_MBEDTLS_SERVER_SSL_SESSION_TICKETS;CONFIG_MBEDTLS_AES_C;CONFIG_MBEDTLS_CAMELLIA_C;CONFIG_MBEDTLS_DES_C;CONFIG_MBEDTLS_BLOWFISH_C;CONFIG_MBEDTLS_XTEA_C;CONFIG_MBEDTLS_CCM_C;CONFIG_MBEDTLS_GCM_C;CONFIG_MBEDTLS_NIST_KW_C;CONFIG_MBEDTLS_RIPEMD160_C;CONFIG_MBEDTLS_PEM_PARSE_C;CONFIG_MBEDTLS_PEM_WRITE_C;CONFIG_MBEDTLS_X509_CRL_PARSE_C;CONFIG_MBEDTLS_X509_CSR_PARSE_C;CONFIG_MBEDTLS_ECP_C;CONFIG_MBEDTLS_PK_PARSE_EC_EXTENDED;CONFIG_MBEDTLS_PK_PARSE_EC_COMPRESSED;CONFIG_MBEDTLS_DHM_C;CONFIG_MBEDTLS_ECDH_C;CONFIG_MBEDTLS_ECDSA_C;CONFIG_MBEDTLS_ECJPAKE_C;CONFIG_MBEDTLS_ECP_DP_SECP192R1_ENABLED;CONFIG_MBEDTLS_ECP_DP_SECP224R1_ENABLED;CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED;CONFIG_MBEDTLS_ECP_DP_SECP384R1_ENABLED;CONFIG_MBEDTLS_ECP_DP_SECP521R1_ENABLED;CONFIG_MBEDTLS_ECP_DP_SECP192K1_ENABLED;CONFIG_MBEDTLS_ECP_DP_SECP224K1_ENABLED;CONFIG_MBEDTLS_ECP_DP_SECP256K1_ENABLED;CONFIG_MBEDTLS_ECP_DP_BP256R1_ENABLED;CONFIG_MBEDTLS_ECP_DP_BP384R1_ENABLED;CONFIG_MBEDTLS_ECP_DP_BP512R1_ENABLED;CONFIG_MBEDTLS_ECP_DP_CURVE25519_ENABLED;CONFIG_MBEDTLS_ECP_NIST_OPTIM;CONFIG_MBEDTLS_ECP_FIXED_POINT_OPTIM;CONFIG_MBEDTLS_POLY1305_C;CONFIG_MBEDTLS_CHACHA20_C;CONFIG_MBEDTLS_HKDF_C;CONFIG_MBEDTLS_THREADING_C;CONFIG_MBEDTLS_ERROR_STRINGS;CONFIG_MBEDTLS_FS_IO;CONFIG_MQTT_PROTOCOL_311;CONFIG_MQTT_PROTOCOL_5;CONFIG_MQTT_TRANSPORT_SSL;CONFIG_MQTT_TRANSPORT_WEBSOCKET;CONFIG_MQTT_TRANSPORT_WEBSOCKET_SECURE;CONFIG_MQTT_MSG_ID_INCREMENTAL;CONFIG_MQTT_SKIP_PUBLISH_IF_DISCONNECTED;CONFIG_MQTT_REPORT_DELETED_MESSAGES;CONFIG_MQTT_USE_CUSTOM_CONFIG;CONFIG_MQTT_TASK_CORE_SELECTION_ENABLED;CONFIG_MQTT_CUSTOM_OUTBOX;CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF;CONFIG_NEWLIB_STDOUT_LINE_ENDING_LF;CONFIG_NEWLIB_STDOUT_LINE_ENDING_CR;CONFIG_NEWLIB_STDIN_LINE_ENDING_CRLF;CONFIG_NEWLIB_STDIN_LINE_ENDING_LF;CONFIG_NEWLIB_STDIN_LINE_ENDING_CR;CONFIG_NEWLIB_NANO_FORMAT;CONFIG_NEWLIB_TIME_SYSCALL_USE_RTC_HRT;CONFIG_ESP32C3_TIME_SYSCALL_USE_RTC_SYSTIMER;CONFIG_NEWLIB_TIME_SYSCALL_USE_RTC;CONFIG_ESP32C3_TIME_SYSCALL_USE_RTC;CONFIG_NEWLIB_TIME_SYSCALL_USE_HRT;CONFIG_ESP32C3_TIME_SYSCALL_USE_SYSTIMER;CONFIG_NEWLIB_TIME_SYSCALL_USE_NONE;CONFIG_ESP32C3_TIME_SYSCALL_USE_NONE;CONFIG_NVS_ENCRYPTION;CONFIG_NVS_ASSERT_ERROR_CHECK;CONFIG_NVS_LEGACY_DUP_KEYS_COMPATIBILITY;CONFIG_OPENTHREAD_ENABLED;CONFIG_OPENTHREAD_SPINEL_ONLY;CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_0;CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_1;CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_2;CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_PATCH_VERSION;CONFIG_PTHREAD_TASK_PRIO_DEFAULT;CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT;CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT;CONFIG_ESP32_PTHREAD_TASK_STACK_SIZE_DEFAULT;CONFIG_PTHREAD_STACK_MIN;CONFIG_ESP32_PTHREAD_STACK_MIN;CONFIG_PTHREAD_TASK_CORE_DEFAULT;CONFIG_ESP32_PTHREAD_TASK_CORE_DEFAULT;CONFIG_PTHREAD_TASK_NAME_DEFAULT;CONFIG_ESP32_PTHREAD_TASK_NAME_DEFAULT;CONFIG_MMU_PAGE_SIZE_64KB;CONFIG_MMU_PAGE_MODE;CONFIG_MMU_PAGE_SIZE;CONFIG_SPI_FLASH_BROWNOUT_RESET_XMC;CONFIG_SPI_FLASH_BROWNOUT_RESET;CONFIG_SPI_FLASH_AUTO_SUSPEND;CONFIG_SPI_FLASH_SUSPEND_TSUS_VAL_US;CONFIG_SPI_FLASH_FORCE_ENABLE_XMC_C_SUSPEND;CONFIG_SPI_FLASH_VERIFY_WRITE;CONFIG_SPI_FLASH_ENABLE_COUNTERS;CONFIG_SPI_FLASH_ROM_DRIVER_PATCH;CONFIG_SPI_FLASH_ROM_IMPL;CONFIG_SPI_FLASH_DANGEROUS_WRITE_ABORTS;CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ABORTS;CONFIG_SPI_FLASH_DANGEROUS_WRITE_FAILS;CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_FAILS;CONFIG_SPI_FLASH_DANGEROUS_WRITE_ALLOWED;CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ALLOWED;CONFIG_SPI_FLASH_BYPASS_BLOCK_ERASE;CONFIG_SPI_FLASH_YIELD_DURING_ERASE;CONFIG_SPI_FLASH_ERASE_YIELD_DURATION_MS;CONFIG_SPI_FLASH_ERASE_YIELD_TICKS;CONFIG_SPI_FLASH_WRITE_CHUNK_SIZE;CONFIG_SPI_FLASH_SIZE_OVERRIDE;CONFIG_SPI_FLASH_CHECK_ERASE_TIMEOUT_DISABLED;CONFIG_SPI_FLASH_OVERRIDE_CHIP_DRIVER_LIST;CONFIG_SPI_FLASH_VENDOR_XMC_SUPPORTED;CONFIG_SPI_FLASH_VENDOR_GD_SUPPORTED;CONFIG_SPI_FLASH_VENDOR_ISSI_SUPPORTED;CONFIG_SPI_FLASH_VENDOR_MXIC_SUPPORTED;CONFIG_SPI_FLASH_VENDOR_WINBOND_SUPPORTED;CONFIG_SPI_FLASH_VENDOR_BOYA_SUPPORTED;CONFIG_SPI_FLASH_VENDOR_TH_SUPPORTED;CONFIG_SPI_FLASH_SUPPORT_ISSI_CHIP;CONFIG_SPI_FLASH_SUPPORT_MXIC_CHIP;CONFIG_SPI_FLASH_SUPPORT_GD_CHIP;CONFIG_SPI_FLASH_SUPPORT_WINBOND_CHIP;CONFIG_SPI_FLASH_SUPPORT_BOYA_CHIP;CONFIG_SPI_FLASH_SUPPORT_TH_CHIP;CONFIG_SPI_FLASH_ENABLE_ENCRYPTED_READ_WRITE;CONFIG_SPIFFS_MAX_PARTITIONS;CONFIG_SPIFFS_CACHE;CONFIG_SPIFFS_CACHE_WR;CONFIG_SPIFFS_CACHE_STATS;CONFIG_SPIFFS_PAGE_CHECK;CONFIG_SPIFFS_GC_MAX_RUNS;CONFIG_SPIFFS_GC_STATS;CONFIG_SPIFFS_PAGE_SIZE;CONFIG_SPIFFS_OBJ_NAME_LEN;CONFIG_SPIFFS_FOLLOW_SYMLINKS;CONFIG_SPIFFS_USE_MAGIC;CONFIG_SPIFFS_USE_MAGIC_LENGTH;CONFIG_SPIFFS_META_LENGTH;CONFIG_SPIFFS_USE_MTIME;CONFIG_SPIFFS_DBG;CONFIG_SPIFFS_API_DBG;CONFIG_SPIFFS_GC_DBG;CONFIG_SPIFFS_CACHE_DBG;CONFIG_SPIFFS_CHECK_DBG;CONFIG_SPIFFS_TEST_VISUALISATION;CONFIG_WS_TRANSPORT;CONFIG_WS_BUFFER_SIZE;CONFIG_WS_DYNAMIC_BUFFER;CONFIG_UNITY_ENABLE_FLOAT;CONFIG_UNITY_ENABLE_DOUBLE;CONFIG_UNITY_ENABLE_64BIT;CONFIG_UNITY_ENABLE_COLOR;CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER;CONFIG_UNITY_ENABLE_FIXTURE;CONFIG_UNITY_ENABLE_BACKTRACE_ON_FAIL;CONFIG_VFS_SUPPORT_IO;CONFIG_VFS_SUPPORT_DIR;CONFIG_VFS_SUPPORT_SELECT;CONFIG_VFS_SUPPRESS_SELECT_DEBUG_OUTPUT;CONFIG_SUPPRESS_SELECT_DEBUG_OUTPUT;CONFIG_VFS_SELECT_IN_RAM;CONFIG_VFS_SUPPORT_TERMIOS;CONFIG_SUPPORT_TERMIOS;CONFIG_VFS_MAX_COUNT;CONFIG_VFS_SEMIHOSTFS_MAX_MOUNT_POINTS;CONFIG_SEMIHOSTFS_MAX_MOUNT_POINTS;CONFIG_VFS_INITIALIZE_DEV_NULL;CONFIG_WL_SECTOR_SIZE_512;CONFIG_WL_SECTOR_SIZE_4096;CONFIG_WL_SECTOR_SIZE;CONFIG_WIFI_PROV_SCAN_MAX_ENTRIES;CONFIG_WIFI_PROV_AUTOSTOP_TIMEOUT;CONFIG_WIFI_PROV_BLE_BONDING;CONFIG_WIFI_PROV_BLE_SEC_CONN;CONFIG_WIFI_PROV_BLE_FORCE_ENCRYPTION;CONFIG_WIFI_PROV_BLE_NOTIFY;CONFIG_WIFI_PROV_KEEP_BLE_ON_AFTER_PROV;CONFIG_WIFI_PROV_STA_ALL_CHANNEL_SCAN;CONFIG_WIFI_PROV_STA_FAST_SCAN;CONFIG_IO_GLITCH_FILTER_TIME_MS;CONFIG_WS2812_LED_ENABLE;CONFIG_WS2812_LED_GPIO;CONFIG_SERIAL_FLASHER_MD5_ENABLED;CONFIG_SERIAL_FLASHER_INTERFACE_UART;CONFIG_SERIAL_FLASHER_INTERFACE_SPI;CONFIG_SERIAL_FLASHER_INTERFACE_USB;CONFIG_SERIAL_FLASHER_INTERFACE_SDIO;CONFIG_SERIAL_FLASHER_RESET_HOLD_TIME_MS;CONFIG_SERIAL_FLASHER_BOOT_HOLD_TIME_MS;CONFIG_SERIAL_FLASHER_DEBUG_TRACE;CONFIG_SERIAL_FLASHER_WRITE_BLOCK_RETRIES;CONFIG_SERIAL_FLASHER_RESET_INVERT;CONFIG_SERIAL_FLASHER_BOOT_INVERT;CONFIG_DIAG_DATA_STORE_RTC;CONFIG_DIAG_DATA_STORE_FLASH;CONFIG_DIAG_DATA_STORE_DBG_PRINTS;CONFIG_DIAG_DATA_STORE_REPORTING_WATERMARK_PERCENT;CONFIG_RTC_STORE_DATA_SIZE;CONFIG_RTC_STORE_CRITICAL_DATA_SIZE;CONFIG_DIAG_LOG_MSG_ARG_FORMAT_TLV;CONFIG_DIAG_LOG_MSG_ARG_FORMAT_STRING;CONFIG_DIAG_LOG_MSG_ARG_MAX_SIZE;CONFIG_DIAG_LOG_DROP_WIFI_LOGS;CONFIG_DIAG_ENABLE_WRAP_LOG_FUNCTIONS;CONFIG_DIAG_ENABLE_METRICS;CONFIG_DIAG_METRICS_MAX_COUNT;CONFIG_DIAG_ENABLE_HEAP_METRICS;CONFIG_DIAG_HEAP_POLLING_INTERVAL;CONFIG_DIAG_ENABLE_WIFI_METRICS;CONFIG_DIAG_WIFI_POLLING_INTERVAL;CONFIG_DIAG_ENABLE_VARIABLES;CONFIG_DIAG_VARIABLES_MAX_COUNT;CONFIG_DIAG_ENABLE_NETWORK_VARIABLES;CONFIG_DIAG_MORE_NETWORK_VARS;CONFIG_DIAG_USE_EXTERNAL_LOG_WRAP;CONFIG_ESP_INSIGHTS_ENABLED;CONFIG_ESP_INSIGHTS_TRANSPORT_MQTT;CONFIG_ESP_INSIGHTS_TRANSPORT_HTTPS;CONFIG_ESP_INSIGHTS_CLOUD_POST_MIN_INTERVAL_SEC;CONFIG_ESP_INSIGHTS_CLOUD_POST_MAX_INTERVAL_SEC;CONFIG_ESP_INSIGHTS_META_VERSION_10;CONFIG_AUTO_UPDATE_RCP;CONFIG_CREATE_OTA_IMAGE_WITH_RCP_FW;CONFIG_ESP_SECURE_CERT_DS_PERIPHERAL;CONFIG_ESP_SECURE_CERT_SUPPORT_LEGACY_FORMATS;CONFIG_JSMN_PARENT_LINKS;CONFIG_JSMN_STRICT;CONFIG_JSMN_STATIC;CONFIG_MDNS_MAX_INTERFACES;CONFIG_MDNS_MAX_SERVICES;CONFIG_MDNS_TASK_PRIORITY;CONFIG_MDNS_ACTION_QUEUE_LEN;CONFIG_MDNS_TASK_STACK_SIZE;CONFIG_MDNS_TASK_AFFINITY_NO_AFFINITY;CONFIG_MDNS_TASK_AFFINITY_CPU0;CONFIG_MDNS_TASK_AFFINITY;CONFIG_MDNS_TASK_CREATE_FROM_INTERNAL;CONFIG_MDNS_MEMORY_ALLOC_INTERNAL;CONFIG_MDNS_MEMORY_CUSTOM_IMPL;CONFIG_MDNS_SERVICE_ADD_TIMEOUT_MS;CONFIG_MDNS_TIMER_PERIOD_MS;CONFIG_MDNS_NETWORKING_SOCKET;CONFIG_MDNS_SKIP_SUPPRESSING_OWN_QUERIES;CONFIG_MDNS_ENABLE_DEBUG_PRINTS;CONFIG_MDNS_ENABLE_CONSOLE_CLI;CONFIG_MDNS_RESPOND_REVERSE_QUERIES;CONFIG_MDNS_MULTIPLE_INSTANCE;CONFIG_MDNS_PREDEF_NETIF_STA;CONFIG_MDNS_PREDEF_NETIF_AP;CONFIG_MDNS_PREDEF_NETIF_ETH;CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI;CONFIG_NETWORK_PROV_SCAN_MAX_ENTRIES;CONFIG_NETWORK_PROV_AUTOSTOP_TIMEOUT;CONFIG_NETWORK_PROV_BLE_BONDING;CONFIG_NETWORK_PROV_BLE_SEC_CONN;CONFIG_NETWORK_PROV_BLE_FORCE_ENCRYPTION;CONFIG_NETWORK_PROV_KEEP_BLE_ON_AFTER_PROV;CONFIG_NETWORK_PROV_WIFI_STA_ALL_CHANNEL_SCAN;CONFIG_NETWORK_PROV_WIFI_STA_FAST_SCAN;CONFIG_ESP_RMAKER_LIB_ESP_MQTT;CONFIG_ESP_RMAKER_LIB_AWS_IOT;CONFIG_ESP_RMAKER_MQTT_GLUE_LIB;CONFIG_ESP_RMAKER_MQTT_PORT_443;CONFIG_ESP_RMAKER_MQTT_PORT_8883;CONFIG_ESP_RMAKER_MQTT_PORT;CONFIG_ESP_RMAKER_MQTT_PERSISTENT_SESSION;CONFIG_ESP_RMAKER_MQTT_SEND_USERNAME;CONFIG_ESP_RMAKER_MQTT_PRODUCT_NAME;CONFIG_ESP_RMAKER_MQTT_PRODUCT_VERSION;CONFIG_ESP_RMAKER_MQTT_PRODUCT_SKU;CONFIG_ESP_RMAKER_MQTT_USE_CERT_BUNDLE;CONFIG_ESP_RMAKER_MAX_MQTT_SUBSCRIPTIONS;CONFIG_ESP_RMAKER_MQTT_KEEP_ALIVE_INTERVAL;CONFIG_ESP_RMAKER_NETWORK_OVER_WIFI;CONFIG_ESP_RMAKER_WORK_QUEUE_TASK_STACK;CONFIG_ESP_RMAKER_WORK_QUEUE_TASK_PRIORITY;CONFIG_ESP_RMAKER_FACTORY_PARTITION_NAME;CONFIG_ESP_RMAKER_FACTORY_NAMESPACE;CONFIG_ESP_RMAKER_DEF_TIMEZONE;CONFIG_ESP_RMAKER_SNTP_SERVER_NAME;CONFIG_ESP_RMAKER_MAX_COMMANDS;CONFIG_IDF_EXPERIMENTAL_FEATURES) +# List of deprecated options for backward compatibility +set(CONFIG_APP_BUILD_TYPE_ELF_RAM "") +set(CONFIG_NO_BLOBS "") +set(CONFIG_LOG_BOOTLOADER_LEVEL_NONE "") +set(CONFIG_LOG_BOOTLOADER_LEVEL_ERROR "") +set(CONFIG_LOG_BOOTLOADER_LEVEL_WARN "") +set(CONFIG_LOG_BOOTLOADER_LEVEL_INFO "y") +set(CONFIG_LOG_BOOTLOADER_LEVEL_DEBUG "") +set(CONFIG_LOG_BOOTLOADER_LEVEL_VERBOSE "") +set(CONFIG_LOG_BOOTLOADER_LEVEL "3") +set(CONFIG_APP_ROLLBACK_ENABLE "y") +set(CONFIG_APP_ANTI_ROLLBACK "") +set(CONFIG_FLASH_ENCRYPTION_ENABLED "") +set(CONFIG_FLASHMODE_QIO "") +set(CONFIG_FLASHMODE_QOUT "") +set(CONFIG_FLASHMODE_DIO "y") +set(CONFIG_FLASHMODE_DOUT "") +set(CONFIG_MONITOR_BAUD "115200") +set(CONFIG_APP_WIFI_PROV_SHOW_QR "y") +set(CONFIG_APP_WIFI_PROV_MAX_POP_MISMATCH "5") +set(CONFIG_APP_WIFI_PROV_TRANSPORT_SOFTAP "") +set(CONFIG_APP_WIFI_PROV_TRANSPORT_BLE "y") +set(CONFIG_APP_WIFI_PROV_TRANSPORT "2") +set(CONFIG_APP_WIFI_RESET_PROV_ON_FAILURE "y") +set(CONFIG_APP_WIFI_SHOW_DEMO_INTRO_TEXT "") +set(CONFIG_APP_WIFI_PROV_TIMEOUT_PERIOD "30") +set(CONFIG_APP_WIFI_PROV_NAME_PREFIX "PROV") +set(CONFIG_ESP_RMAKER_LOCAL_CTRL_ENABLE "y") +set(CONFIG_OPTIMIZATION_LEVEL_DEBUG "y") +set(CONFIG_COMPILER_OPTIMIZATION_LEVEL_DEBUG "y") +set(CONFIG_COMPILER_OPTIMIZATION_DEFAULT "y") +set(CONFIG_OPTIMIZATION_LEVEL_RELEASE "") +set(CONFIG_COMPILER_OPTIMIZATION_LEVEL_RELEASE "") +set(CONFIG_OPTIMIZATION_ASSERTIONS_ENABLED "y") +set(CONFIG_OPTIMIZATION_ASSERTIONS_SILENT "") +set(CONFIG_OPTIMIZATION_ASSERTIONS_DISABLED "") +set(CONFIG_OPTIMIZATION_ASSERTION_LEVEL "2") +set(CONFIG_CXX_EXCEPTIONS "") +set(CONFIG_STACK_CHECK_NONE "y") +set(CONFIG_STACK_CHECK_NORM "") +set(CONFIG_STACK_CHECK_STRONG "") +set(CONFIG_STACK_CHECK_ALL "") +set(CONFIG_WARN_WRITE_STRINGS "") +set(CONFIG_ESP32_APPTRACE_DEST_TRAX "") +set(CONFIG_ESP32_APPTRACE_DEST_NONE "y") +set(CONFIG_ESP32_APPTRACE_LOCK_ENABLE "y") +set(CONFIG_BLUEDROID_ENABLED "") +set(CONFIG_NIMBLE_ENABLED "y") +set(CONFIG_NIMBLE_MEM_ALLOC_MODE_INTERNAL "y") +set(CONFIG_NIMBLE_MEM_ALLOC_MODE_DEFAULT "") +set(CONFIG_NIMBLE_MAX_CONNECTIONS "3") +set(CONFIG_NIMBLE_MAX_BONDS "3") +set(CONFIG_NIMBLE_MAX_CCCDS "8") +set(CONFIG_NIMBLE_L2CAP_COC_MAX_NUM "0") +set(CONFIG_NIMBLE_PINNED_TO_CORE "0") +set(CONFIG_NIMBLE_TASK_STACK_SIZE "4096") +set(CONFIG_BT_NIMBLE_TASK_STACK_SIZE "4096") +set(CONFIG_NIMBLE_ROLE_CENTRAL "y") +set(CONFIG_NIMBLE_ROLE_PERIPHERAL "y") +set(CONFIG_NIMBLE_ROLE_BROADCASTER "y") +set(CONFIG_NIMBLE_ROLE_OBSERVER "y") +set(CONFIG_NIMBLE_NVS_PERSIST "") +set(CONFIG_NIMBLE_SM_LEGACY "y") +set(CONFIG_NIMBLE_SM_SC "y") +set(CONFIG_NIMBLE_SM_SC_DEBUG_KEYS "") +set(CONFIG_BT_NIMBLE_SM_SC_LVL "0") +set(CONFIG_NIMBLE_DEBUG "") +set(CONFIG_NIMBLE_SVC_GAP_DEVICE_NAME "nimble") +set(CONFIG_NIMBLE_GAP_DEVICE_NAME_MAX_LEN "31") +set(CONFIG_NIMBLE_ATT_PREFERRED_MTU "256") +set(CONFIG_NIMBLE_SVC_GAP_APPEARANCE "0x0") +set(CONFIG_BT_NIMBLE_MSYS1_BLOCK_COUNT "12") +set(CONFIG_BT_NIMBLE_ACL_BUF_COUNT "24") +set(CONFIG_BT_NIMBLE_ACL_BUF_SIZE "255") +set(CONFIG_BT_NIMBLE_HCI_EVT_BUF_SIZE "70") +set(CONFIG_BT_NIMBLE_HCI_EVT_HI_BUF_COUNT "30") +set(CONFIG_BT_NIMBLE_HCI_EVT_LO_BUF_COUNT "8") +set(CONFIG_NIMBLE_HS_FLOW_CTRL "") +set(CONFIG_NIMBLE_RPA_TIMEOUT "900") +set(CONFIG_NIMBLE_MESH "") +set(CONFIG_NIMBLE_CRYPTO_STACK_MBEDTLS "y") +set(CONFIG_BT_NIMBLE_COEX_PHY_CODED_TX_RX_TLIM_EN "") +set(CONFIG_BT_NIMBLE_COEX_PHY_CODED_TX_RX_TLIM_DIS "y") +set(CONFIG_SW_COEXIST_ENABLE "y") +set(CONFIG_ESP32_WIFI_SW_COEXIST_ENABLE "y") +set(CONFIG_ESP_WIFI_SW_COEXIST_ENABLE "y") +set(CONFIG_EVENT_LOOP_PROFILING "") +set(CONFIG_POST_EVENTS_FROM_ISR "y") +set(CONFIG_POST_EVENTS_FROM_IRAM_ISR "y") +set(CONFIG_GDBSTUB_SUPPORT_TASKS "y") +set(CONFIG_GDBSTUB_MAX_TASKS "32") +set(CONFIG_OTA_ALLOW_HTTP "") +set(CONFIG_ESP_SYSTEM_PD_FLASH "") +set(CONFIG_ESP32C3_LIGHTSLEEP_GPIO_RESET_WORKAROUND "y") +set(CONFIG_ESP32C3_RTC_CLK_SRC_INT_RC "y") +set(CONFIG_ESP32C3_RTC_CLK_SRC_EXT_CRYS "") +set(CONFIG_ESP32C3_RTC_CLK_SRC_EXT_OSC "") +set(CONFIG_ESP32C3_RTC_CLK_SRC_INT_8MD256 "") +set(CONFIG_ESP32C3_RTC_CLK_CAL_CYCLES "1024") +set(CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE "y") +set(CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION "") +set(CONFIG_ESP32_PHY_MAX_WIFI_TX_POWER "20") +set(CONFIG_ESP32_PHY_MAX_TX_POWER "20") +set(CONFIG_REDUCE_PHY_TX_POWER "") +set(CONFIG_ESP32_REDUCE_PHY_TX_POWER "") +set(CONFIG_ESP_SYSTEM_PM_POWER_DOWN_CPU "y") +set(CONFIG_ESP32C3_DEFAULT_CPU_FREQ_80 "") +set(CONFIG_ESP32C3_DEFAULT_CPU_FREQ_160 "y") +set(CONFIG_ESP32C3_DEFAULT_CPU_FREQ_MHZ "160") +set(CONFIG_ESP32C3_MEMPROT_FEATURE "y") +set(CONFIG_ESP32C3_MEMPROT_FEATURE_LOCK "y") +set(CONFIG_SYSTEM_EVENT_QUEUE_SIZE "32") +set(CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE "2304") +set(CONFIG_MAIN_TASK_STACK_SIZE "3584") +set(CONFIG_CONSOLE_UART_DEFAULT "y") +set(CONFIG_CONSOLE_UART_CUSTOM "") +set(CONFIG_CONSOLE_UART_NONE "") +set(CONFIG_ESP_CONSOLE_UART_NONE "") +set(CONFIG_CONSOLE_UART "y") +set(CONFIG_CONSOLE_UART_NUM "0") +set(CONFIG_CONSOLE_UART_BAUDRATE "115200") +set(CONFIG_INT_WDT "y") +set(CONFIG_INT_WDT_TIMEOUT_MS "300") +set(CONFIG_TASK_WDT "y") +set(CONFIG_ESP_TASK_WDT "y") +set(CONFIG_TASK_WDT_PANIC "") +set(CONFIG_TASK_WDT_TIMEOUT_S "5") +set(CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU0 "y") +set(CONFIG_ESP32_DEBUG_STUBS_ENABLE "") +set(CONFIG_ESP32C3_DEBUG_OCDAWARE "y") +set(CONFIG_BROWNOUT_DET "y") +set(CONFIG_ESP32C3_BROWNOUT_DET "y") +set(CONFIG_BROWNOUT_DET_LVL_SEL_7 "y") +set(CONFIG_ESP32C3_BROWNOUT_DET_LVL_SEL_7 "y") +set(CONFIG_BROWNOUT_DET_LVL_SEL_6 "") +set(CONFIG_ESP32C3_BROWNOUT_DET_LVL_SEL_6 "") +set(CONFIG_BROWNOUT_DET_LVL_SEL_5 "") +set(CONFIG_ESP32C3_BROWNOUT_DET_LVL_SEL_5 "") +set(CONFIG_BROWNOUT_DET_LVL_SEL_4 "") +set(CONFIG_ESP32C3_BROWNOUT_DET_LVL_SEL_4 "") +set(CONFIG_BROWNOUT_DET_LVL_SEL_3 "") +set(CONFIG_ESP32C3_BROWNOUT_DET_LVL_SEL_3 "") +set(CONFIG_BROWNOUT_DET_LVL_SEL_2 "") +set(CONFIG_ESP32C3_BROWNOUT_DET_LVL_SEL_2 "") +set(CONFIG_BROWNOUT_DET_LVL "7") +set(CONFIG_ESP32C3_BROWNOUT_DET_LVL "7") +set(CONFIG_IPC_TASK_STACK_SIZE "1024") +set(CONFIG_TIMER_TASK_STACK_SIZE "3584") +set(CONFIG_ESP32_WIFI_ENABLED "y") +set(CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM "10") +set(CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM "32") +set(CONFIG_ESP32_WIFI_STATIC_TX_BUFFER "") +set(CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER "y") +set(CONFIG_ESP32_WIFI_TX_BUFFER_TYPE "1") +set(CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM "32") +set(CONFIG_ESP32_WIFI_CSI_ENABLED "") +set(CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED "y") +set(CONFIG_ESP32_WIFI_TX_BA_WIN "6") +set(CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED "y") +set(CONFIG_ESP32_WIFI_RX_BA_WIN "6") +set(CONFIG_ESP32_WIFI_NVS_ENABLED "y") +set(CONFIG_ESP32_WIFI_SOFTAP_BEACON_MAX_LEN "752") +set(CONFIG_ESP32_WIFI_MGMT_SBUF_NUM "32") +set(CONFIG_ESP32_WIFI_IRAM_OPT "y") +set(CONFIG_ESP32_WIFI_RX_IRAM_OPT "y") +set(CONFIG_ESP32_WIFI_ENABLE_WPA3_SAE "y") +set(CONFIG_ESP32_WIFI_ENABLE_WPA3_OWE_STA "y") +set(CONFIG_WPA_MBEDTLS_CRYPTO "y") +set(CONFIG_WPA_MBEDTLS_TLS_CLIENT "y") +set(CONFIG_WPA_WAPI_PSK "") +set(CONFIG_WPA_SUITE_B_192 "") +set(CONFIG_WPA_11KV_SUPPORT "") +set(CONFIG_WPA_MBO_SUPPORT "") +set(CONFIG_WPA_DPP_SUPPORT "") +set(CONFIG_WPA_11R_SUPPORT "") +set(CONFIG_WPA_WPS_SOFTAP_REGISTRAR "") +set(CONFIG_WPA_WPS_STRICT "") +set(CONFIG_WPA_DEBUG_PRINT "") +set(CONFIG_WPA_TESTING_OPTIONS "") +set(CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH "") +set(CONFIG_ESP32_ENABLE_COREDUMP_TO_UART "") +set(CONFIG_ESP32_ENABLE_COREDUMP_TO_NONE "y") +set(CONFIG_TIMER_TASK_PRIORITY "1") +set(CONFIG_TIMER_TASK_STACK_DEPTH "3120") +set(CONFIG_TIMER_QUEUE_LENGTH "10") +set(CONFIG_ENABLE_STATIC_TASK_CLEAN_UP_HOOK "") +set(CONFIG_HAL_ASSERTION_SILIENT "") +set(CONFIG_L2_TO_L3_COPY "") +set(CONFIG_ESP_GRATUITOUS_ARP "y") +set(CONFIG_GARP_TMR_INTERVAL "60") +set(CONFIG_TCPIP_RECVMBOX_SIZE "32") +set(CONFIG_TCP_MAXRTX "12") +set(CONFIG_TCP_SYNMAXRTX "12") +set(CONFIG_TCP_MSS "1440") +set(CONFIG_TCP_MSL "60000") +set(CONFIG_TCP_SND_BUF_DEFAULT "5760") +set(CONFIG_TCP_WND_DEFAULT "5760") +set(CONFIG_TCP_RECVMBOX_SIZE "6") +set(CONFIG_TCP_QUEUE_OOSEQ "y") +set(CONFIG_TCP_OVERSIZE_MSS "y") +set(CONFIG_TCP_OVERSIZE_QUARTER_MSS "") +set(CONFIG_TCP_OVERSIZE_DISABLE "") +set(CONFIG_UDP_RECVMBOX_SIZE "6") +set(CONFIG_TCPIP_TASK_STACK_SIZE "3072") +set(CONFIG_TCPIP_TASK_AFFINITY_NO_AFFINITY "y") +set(CONFIG_TCPIP_TASK_AFFINITY_CPU0 "") +set(CONFIG_TCPIP_TASK_AFFINITY "0x7fffffff") +set(CONFIG_PPP_SUPPORT "") +set(CONFIG_ESP32C3_TIME_SYSCALL_USE_RTC_SYSTIMER "y") +set(CONFIG_ESP32C3_TIME_SYSCALL_USE_RTC "") +set(CONFIG_ESP32C3_TIME_SYSCALL_USE_SYSTIMER "") +set(CONFIG_ESP32C3_TIME_SYSCALL_USE_NONE "") +set(CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT "5") +set(CONFIG_ESP32_PTHREAD_TASK_STACK_SIZE_DEFAULT "3072") +set(CONFIG_ESP32_PTHREAD_STACK_MIN "768") +set(CONFIG_ESP32_PTHREAD_TASK_CORE_DEFAULT "-1") +set(CONFIG_ESP32_PTHREAD_TASK_NAME_DEFAULT "pthread") +set(CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ABORTS "y") +set(CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_FAILS "") +set(CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ALLOWED "") +set(CONFIG_SUPPRESS_SELECT_DEBUG_OUTPUT "y") +set(CONFIG_SUPPORT_TERMIOS "y") +set(CONFIG_SEMIHOSTFS_MAX_MOUNT_POINTS "1") diff --git a/RainMaker_Table-Lights/build/config/sdkconfig.h b/RainMaker_Table-Lights/build/config/sdkconfig.h new file mode 100644 index 000000000..b73b4d354 --- /dev/null +++ b/RainMaker_Table-Lights/build/config/sdkconfig.h @@ -0,0 +1,1154 @@ +/* + * Automatically generated file. DO NOT EDIT. + * Espressif IoT Development Framework (ESP-IDF) 5.4.1 Configuration Header + */ +#pragma once +#define CONFIG_SOC_ADC_SUPPORTED 1 +#define CONFIG_SOC_DEDICATED_GPIO_SUPPORTED 1 +#define CONFIG_SOC_UART_SUPPORTED 1 +#define CONFIG_SOC_GDMA_SUPPORTED 1 +#define CONFIG_SOC_AHB_GDMA_SUPPORTED 1 +#define CONFIG_SOC_GPTIMER_SUPPORTED 1 +#define CONFIG_SOC_TWAI_SUPPORTED 1 +#define CONFIG_SOC_BT_SUPPORTED 1 +#define CONFIG_SOC_ASYNC_MEMCPY_SUPPORTED 1 +#define CONFIG_SOC_USB_SERIAL_JTAG_SUPPORTED 1 +#define CONFIG_SOC_TEMP_SENSOR_SUPPORTED 1 +#define CONFIG_SOC_XT_WDT_SUPPORTED 1 +#define CONFIG_SOC_PHY_SUPPORTED 1 +#define CONFIG_SOC_WIFI_SUPPORTED 1 +#define CONFIG_SOC_SUPPORTS_SECURE_DL_MODE 1 +#define CONFIG_SOC_EFUSE_KEY_PURPOSE_FIELD 1 +#define CONFIG_SOC_EFUSE_HAS_EFUSE_RST_BUG 1 +#define CONFIG_SOC_EFUSE_SUPPORTED 1 +#define CONFIG_SOC_RTC_FAST_MEM_SUPPORTED 1 +#define CONFIG_SOC_RTC_MEM_SUPPORTED 1 +#define CONFIG_SOC_I2S_SUPPORTED 1 +#define CONFIG_SOC_RMT_SUPPORTED 1 +#define CONFIG_SOC_SDM_SUPPORTED 1 +#define CONFIG_SOC_GPSPI_SUPPORTED 1 +#define CONFIG_SOC_LEDC_SUPPORTED 1 +#define CONFIG_SOC_I2C_SUPPORTED 1 +#define CONFIG_SOC_SYSTIMER_SUPPORTED 1 +#define CONFIG_SOC_SUPPORT_COEXISTENCE 1 +#define CONFIG_SOC_AES_SUPPORTED 1 +#define CONFIG_SOC_MPI_SUPPORTED 1 +#define CONFIG_SOC_SHA_SUPPORTED 1 +#define CONFIG_SOC_HMAC_SUPPORTED 1 +#define CONFIG_SOC_DIG_SIGN_SUPPORTED 1 +#define CONFIG_SOC_FLASH_ENC_SUPPORTED 1 +#define CONFIG_SOC_SECURE_BOOT_SUPPORTED 1 +#define CONFIG_SOC_MEMPROT_SUPPORTED 1 +#define CONFIG_SOC_BOD_SUPPORTED 1 +#define CONFIG_SOC_CLK_TREE_SUPPORTED 1 +#define CONFIG_SOC_ASSIST_DEBUG_SUPPORTED 1 +#define CONFIG_SOC_WDT_SUPPORTED 1 +#define CONFIG_SOC_SPI_FLASH_SUPPORTED 1 +#define CONFIG_SOC_RNG_SUPPORTED 1 +#define CONFIG_SOC_LIGHT_SLEEP_SUPPORTED 1 +#define CONFIG_SOC_DEEP_SLEEP_SUPPORTED 1 +#define CONFIG_SOC_LP_PERIPH_SHARE_INTERRUPT 1 +#define CONFIG_SOC_PM_SUPPORTED 1 +#define CONFIG_SOC_XTAL_SUPPORT_40M 1 +#define CONFIG_SOC_AES_SUPPORT_DMA 1 +#define CONFIG_SOC_AES_GDMA 1 +#define CONFIG_SOC_AES_SUPPORT_AES_128 1 +#define CONFIG_SOC_AES_SUPPORT_AES_256 1 +#define CONFIG_SOC_ADC_DIG_CTRL_SUPPORTED 1 +#define CONFIG_SOC_ADC_ARBITER_SUPPORTED 1 +#define CONFIG_SOC_ADC_DIG_IIR_FILTER_SUPPORTED 1 +#define CONFIG_SOC_ADC_MONITOR_SUPPORTED 1 +#define CONFIG_SOC_ADC_DMA_SUPPORTED 1 +#define CONFIG_SOC_ADC_PERIPH_NUM 2 +#define CONFIG_SOC_ADC_MAX_CHANNEL_NUM 5 +#define CONFIG_SOC_ADC_ATTEN_NUM 4 +#define CONFIG_SOC_ADC_DIGI_CONTROLLER_NUM 1 +#define CONFIG_SOC_ADC_PATT_LEN_MAX 8 +#define CONFIG_SOC_ADC_DIGI_MIN_BITWIDTH 12 +#define CONFIG_SOC_ADC_DIGI_MAX_BITWIDTH 12 +#define CONFIG_SOC_ADC_DIGI_RESULT_BYTES 4 +#define CONFIG_SOC_ADC_DIGI_DATA_BYTES_PER_CONV 4 +#define CONFIG_SOC_ADC_DIGI_IIR_FILTER_NUM 2 +#define CONFIG_SOC_ADC_DIGI_MONITOR_NUM 2 +#define CONFIG_SOC_ADC_SAMPLE_FREQ_THRES_HIGH 83333 +#define CONFIG_SOC_ADC_SAMPLE_FREQ_THRES_LOW 611 +#define CONFIG_SOC_ADC_RTC_MIN_BITWIDTH 12 +#define CONFIG_SOC_ADC_RTC_MAX_BITWIDTH 12 +#define CONFIG_SOC_ADC_CALIBRATION_V1_SUPPORTED 1 +#define CONFIG_SOC_ADC_SELF_HW_CALI_SUPPORTED 1 +#define CONFIG_SOC_ADC_SHARED_POWER 1 +#define CONFIG_SOC_APB_BACKUP_DMA 1 +#define CONFIG_SOC_BROWNOUT_RESET_SUPPORTED 1 +#define CONFIG_SOC_SHARED_IDCACHE_SUPPORTED 1 +#define CONFIG_SOC_CACHE_MEMORY_IBANK_SIZE 0x4000 +#define CONFIG_SOC_CPU_CORES_NUM 1 +#define CONFIG_SOC_CPU_INTR_NUM 32 +#define CONFIG_SOC_CPU_HAS_FLEXIBLE_INTC 1 +#define CONFIG_SOC_CPU_HAS_CSR_PC 1 +#define CONFIG_SOC_CPU_BREAKPOINTS_NUM 8 +#define CONFIG_SOC_CPU_WATCHPOINTS_NUM 8 +#define CONFIG_SOC_CPU_WATCHPOINT_MAX_REGION_SIZE 0x80000000 +#define CONFIG_SOC_DS_SIGNATURE_MAX_BIT_LEN 3072 +#define CONFIG_SOC_DS_KEY_PARAM_MD_IV_LENGTH 16 +#define CONFIG_SOC_DS_KEY_CHECK_MAX_WAIT_US 1100 +#define CONFIG_SOC_AHB_GDMA_VERSION 1 +#define CONFIG_SOC_GDMA_NUM_GROUPS_MAX 1 +#define CONFIG_SOC_GDMA_PAIRS_PER_GROUP_MAX 3 +#define CONFIG_SOC_GPIO_PORT 1 +#define CONFIG_SOC_GPIO_PIN_COUNT 22 +#define CONFIG_SOC_GPIO_SUPPORT_PIN_GLITCH_FILTER 1 +#define CONFIG_SOC_GPIO_FILTER_CLK_SUPPORT_APB 1 +#define CONFIG_SOC_GPIO_SUPPORT_FORCE_HOLD 1 +#define CONFIG_SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP 1 +#define CONFIG_SOC_GPIO_IN_RANGE_MAX 21 +#define CONFIG_SOC_GPIO_OUT_RANGE_MAX 21 +#define CONFIG_SOC_GPIO_DEEP_SLEEP_WAKE_VALID_GPIO_MASK 0 +#define CONFIG_SOC_GPIO_DEEP_SLEEP_WAKE_SUPPORTED_PIN_CNT 6 +#define CONFIG_SOC_GPIO_VALID_DIGITAL_IO_PAD_MASK 0x00000000003FFFC0 +#define CONFIG_SOC_GPIO_CLOCKOUT_BY_GPIO_MATRIX 1 +#define CONFIG_SOC_GPIO_CLOCKOUT_CHANNEL_NUM 3 +#define CONFIG_SOC_GPIO_SUPPORT_HOLD_IO_IN_DSLP 1 +#define CONFIG_SOC_DEDIC_GPIO_OUT_CHANNELS_NUM 8 +#define CONFIG_SOC_DEDIC_GPIO_IN_CHANNELS_NUM 8 +#define CONFIG_SOC_DEDIC_PERIPH_ALWAYS_ENABLE 1 +#define CONFIG_SOC_I2C_NUM 1 +#define CONFIG_SOC_HP_I2C_NUM 1 +#define CONFIG_SOC_I2C_FIFO_LEN 32 +#define CONFIG_SOC_I2C_CMD_REG_NUM 8 +#define CONFIG_SOC_I2C_SUPPORT_SLAVE 1 +#define CONFIG_SOC_I2C_SUPPORT_HW_CLR_BUS 1 +#define CONFIG_SOC_I2C_SUPPORT_XTAL 1 +#define CONFIG_SOC_I2C_SUPPORT_RTC 1 +#define CONFIG_SOC_I2C_SUPPORT_10BIT_ADDR 1 +#define CONFIG_SOC_I2C_SLAVE_SUPPORT_BROADCAST 1 +#define CONFIG_SOC_I2C_SLAVE_CAN_GET_STRETCH_CAUSE 1 +#define CONFIG_SOC_I2C_SLAVE_SUPPORT_I2CRAM_ACCESS 1 +#define CONFIG_SOC_I2S_NUM 1 +#define CONFIG_SOC_I2S_HW_VERSION_2 1 +#define CONFIG_SOC_I2S_SUPPORTS_XTAL 1 +#define CONFIG_SOC_I2S_SUPPORTS_PLL_F160M 1 +#define CONFIG_SOC_I2S_SUPPORTS_PCM 1 +#define CONFIG_SOC_I2S_SUPPORTS_PDM 1 +#define CONFIG_SOC_I2S_SUPPORTS_PDM_TX 1 +#define CONFIG_SOC_I2S_PDM_MAX_TX_LINES 2 +#define CONFIG_SOC_I2S_SUPPORTS_TDM 1 +#define CONFIG_SOC_LEDC_SUPPORT_APB_CLOCK 1 +#define CONFIG_SOC_LEDC_SUPPORT_XTAL_CLOCK 1 +#define CONFIG_SOC_LEDC_TIMER_NUM 4 +#define CONFIG_SOC_LEDC_CHANNEL_NUM 6 +#define CONFIG_SOC_LEDC_TIMER_BIT_WIDTH 14 +#define CONFIG_SOC_LEDC_SUPPORT_FADE_STOP 1 +#define CONFIG_SOC_MMU_LINEAR_ADDRESS_REGION_NUM 1 +#define CONFIG_SOC_MMU_PERIPH_NUM 1 +#define CONFIG_SOC_MPU_MIN_REGION_SIZE 0x20000000 +#define CONFIG_SOC_MPU_REGIONS_MAX_NUM 8 +#define CONFIG_SOC_RMT_GROUPS 1 +#define CONFIG_SOC_RMT_TX_CANDIDATES_PER_GROUP 2 +#define CONFIG_SOC_RMT_RX_CANDIDATES_PER_GROUP 2 +#define CONFIG_SOC_RMT_CHANNELS_PER_GROUP 4 +#define CONFIG_SOC_RMT_MEM_WORDS_PER_CHANNEL 48 +#define CONFIG_SOC_RMT_SUPPORT_RX_PINGPONG 1 +#define CONFIG_SOC_RMT_SUPPORT_RX_DEMODULATION 1 +#define CONFIG_SOC_RMT_SUPPORT_TX_ASYNC_STOP 1 +#define CONFIG_SOC_RMT_SUPPORT_TX_LOOP_COUNT 1 +#define CONFIG_SOC_RMT_SUPPORT_TX_SYNCHRO 1 +#define CONFIG_SOC_RMT_SUPPORT_TX_CARRIER_DATA_ONLY 1 +#define CONFIG_SOC_RMT_SUPPORT_XTAL 1 +#define CONFIG_SOC_RMT_SUPPORT_APB 1 +#define CONFIG_SOC_RMT_SUPPORT_RC_FAST 1 +#define CONFIG_SOC_RTC_CNTL_CPU_PD_DMA_BUS_WIDTH 128 +#define CONFIG_SOC_RTC_CNTL_CPU_PD_REG_FILE_NUM 108 +#define CONFIG_SOC_SLEEP_SYSTIMER_STALL_WORKAROUND 1 +#define CONFIG_SOC_SLEEP_TGWDT_STOP_WORKAROUND 1 +#define CONFIG_SOC_RTCIO_PIN_COUNT 0 +#define CONFIG_SOC_MPI_MEM_BLOCKS_NUM 4 +#define CONFIG_SOC_MPI_OPERATIONS_NUM 3 +#define CONFIG_SOC_RSA_MAX_BIT_LEN 3072 +#define CONFIG_SOC_SHA_DMA_MAX_BUFFER_SIZE 3968 +#define CONFIG_SOC_SHA_SUPPORT_DMA 1 +#define CONFIG_SOC_SHA_SUPPORT_RESUME 1 +#define CONFIG_SOC_SHA_GDMA 1 +#define CONFIG_SOC_SHA_SUPPORT_SHA1 1 +#define CONFIG_SOC_SHA_SUPPORT_SHA224 1 +#define CONFIG_SOC_SHA_SUPPORT_SHA256 1 +#define CONFIG_SOC_SDM_GROUPS 1 +#define CONFIG_SOC_SDM_CHANNELS_PER_GROUP 4 +#define CONFIG_SOC_SDM_CLK_SUPPORT_APB 1 +#define CONFIG_SOC_SPI_PERIPH_NUM 2 +#define CONFIG_SOC_SPI_MAX_CS_NUM 6 +#define CONFIG_SOC_SPI_MAXIMUM_BUFFER_SIZE 64 +#define CONFIG_SOC_SPI_SUPPORT_DDRCLK 1 +#define CONFIG_SOC_SPI_SLAVE_SUPPORT_SEG_TRANS 1 +#define CONFIG_SOC_SPI_SUPPORT_CD_SIG 1 +#define CONFIG_SOC_SPI_SUPPORT_CONTINUOUS_TRANS 1 +#define CONFIG_SOC_SPI_SUPPORT_SLAVE_HD_VER2 1 +#define CONFIG_SOC_SPI_SUPPORT_CLK_APB 1 +#define CONFIG_SOC_SPI_SUPPORT_CLK_XTAL 1 +#define CONFIG_SOC_SPI_PERIPH_SUPPORT_CONTROL_DUMMY_OUT 1 +#define CONFIG_SOC_SPI_SCT_SUPPORTED 1 +#define CONFIG_SOC_SPI_SCT_REG_NUM 14 +#define CONFIG_SOC_SPI_SCT_BUFFER_NUM_MAX 1 +#define CONFIG_SOC_SPI_SCT_CONF_BITLEN_MAX 0x3FFFA +#define CONFIG_SOC_MEMSPI_IS_INDEPENDENT 1 +#define CONFIG_SOC_SPI_MAX_PRE_DIVIDER 16 +#define CONFIG_SOC_SPI_MEM_SUPPORT_AUTO_WAIT_IDLE 1 +#define CONFIG_SOC_SPI_MEM_SUPPORT_AUTO_SUSPEND 1 +#define CONFIG_SOC_SPI_MEM_SUPPORT_AUTO_RESUME 1 +#define CONFIG_SOC_SPI_MEM_SUPPORT_IDLE_INTR 1 +#define CONFIG_SOC_SPI_MEM_SUPPORT_SW_SUSPEND 1 +#define CONFIG_SOC_SPI_MEM_SUPPORT_CHECK_SUS 1 +#define CONFIG_SOC_SPI_MEM_SUPPORT_CONFIG_GPIO_BY_EFUSE 1 +#define CONFIG_SOC_SPI_MEM_SUPPORT_WRAP 1 +#define CONFIG_SOC_MEMSPI_SRC_FREQ_80M_SUPPORTED 1 +#define CONFIG_SOC_MEMSPI_SRC_FREQ_40M_SUPPORTED 1 +#define CONFIG_SOC_MEMSPI_SRC_FREQ_26M_SUPPORTED 1 +#define CONFIG_SOC_MEMSPI_SRC_FREQ_20M_SUPPORTED 1 +#define CONFIG_SOC_SYSTIMER_COUNTER_NUM 2 +#define CONFIG_SOC_SYSTIMER_ALARM_NUM 3 +#define CONFIG_SOC_SYSTIMER_BIT_WIDTH_LO 32 +#define CONFIG_SOC_SYSTIMER_BIT_WIDTH_HI 20 +#define CONFIG_SOC_SYSTIMER_FIXED_DIVIDER 1 +#define CONFIG_SOC_SYSTIMER_INT_LEVEL 1 +#define CONFIG_SOC_SYSTIMER_ALARM_MISS_COMPENSATE 1 +#define CONFIG_SOC_TIMER_GROUPS 2 +#define CONFIG_SOC_TIMER_GROUP_TIMERS_PER_GROUP 1 +#define CONFIG_SOC_TIMER_GROUP_COUNTER_BIT_WIDTH 54 +#define CONFIG_SOC_TIMER_GROUP_SUPPORT_XTAL 1 +#define CONFIG_SOC_TIMER_GROUP_SUPPORT_APB 1 +#define CONFIG_SOC_TIMER_GROUP_TOTAL_TIMERS 2 +#define CONFIG_SOC_LP_TIMER_BIT_WIDTH_LO 32 +#define CONFIG_SOC_LP_TIMER_BIT_WIDTH_HI 16 +#define CONFIG_SOC_MWDT_SUPPORT_XTAL 1 +#define CONFIG_SOC_TWAI_CONTROLLER_NUM 1 +#define CONFIG_SOC_TWAI_CLK_SUPPORT_APB 1 +#define CONFIG_SOC_TWAI_BRP_MIN 2 +#define CONFIG_SOC_TWAI_BRP_MAX 16384 +#define CONFIG_SOC_TWAI_SUPPORTS_RX_STATUS 1 +#define CONFIG_SOC_EFUSE_DIS_DOWNLOAD_ICACHE 1 +#define CONFIG_SOC_EFUSE_DIS_PAD_JTAG 1 +#define CONFIG_SOC_EFUSE_DIS_USB_JTAG 1 +#define CONFIG_SOC_EFUSE_DIS_DIRECT_BOOT 1 +#define CONFIG_SOC_EFUSE_SOFT_DIS_JTAG 1 +#define CONFIG_SOC_EFUSE_DIS_ICACHE 1 +#define CONFIG_SOC_EFUSE_BLOCK9_KEY_PURPOSE_QUIRK 1 +#define CONFIG_SOC_SECURE_BOOT_V2_RSA 1 +#define CONFIG_SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS 3 +#define CONFIG_SOC_EFUSE_REVOKE_BOOT_KEY_DIGESTS 1 +#define CONFIG_SOC_SUPPORT_SECURE_BOOT_REVOKE_KEY 1 +#define CONFIG_SOC_FLASH_ENCRYPTED_XTS_AES_BLOCK_MAX 32 +#define CONFIG_SOC_FLASH_ENCRYPTION_XTS_AES 1 +#define CONFIG_SOC_FLASH_ENCRYPTION_XTS_AES_128 1 +#define CONFIG_SOC_MEMPROT_CPU_PREFETCH_PAD_SIZE 16 +#define CONFIG_SOC_MEMPROT_MEM_ALIGN_SIZE 512 +#define CONFIG_SOC_UART_NUM 2 +#define CONFIG_SOC_UART_HP_NUM 2 +#define CONFIG_SOC_UART_FIFO_LEN 128 +#define CONFIG_SOC_UART_BITRATE_MAX 5000000 +#define CONFIG_SOC_UART_SUPPORT_APB_CLK 1 +#define CONFIG_SOC_UART_SUPPORT_RTC_CLK 1 +#define CONFIG_SOC_UART_SUPPORT_XTAL_CLK 1 +#define CONFIG_SOC_UART_SUPPORT_WAKEUP_INT 1 +#define CONFIG_SOC_UART_SUPPORT_FSM_TX_WAIT_SEND 1 +#define CONFIG_SOC_COEX_HW_PTI 1 +#define CONFIG_SOC_PHY_DIG_REGS_MEM_SIZE 21 +#define CONFIG_SOC_MAC_BB_PD_MEM_SIZE 192 +#define CONFIG_SOC_WIFI_LIGHT_SLEEP_CLK_WIDTH 12 +#define CONFIG_SOC_PM_SUPPORT_WIFI_WAKEUP 1 +#define CONFIG_SOC_PM_SUPPORT_BT_WAKEUP 1 +#define CONFIG_SOC_PM_SUPPORT_CPU_PD 1 +#define CONFIG_SOC_PM_SUPPORT_WIFI_PD 1 +#define CONFIG_SOC_PM_SUPPORT_BT_PD 1 +#define CONFIG_SOC_PM_SUPPORT_RC_FAST_PD 1 +#define CONFIG_SOC_PM_SUPPORT_VDDSDIO_PD 1 +#define CONFIG_SOC_PM_SUPPORT_MAC_BB_PD 1 +#define CONFIG_SOC_PM_CPU_RETENTION_BY_RTCCNTL 1 +#define CONFIG_SOC_PM_MODEM_RETENTION_BY_BACKUPDMA 1 +#define CONFIG_SOC_PM_MODEM_PD_BY_SW 1 +#define CONFIG_SOC_CLK_RC_FAST_D256_SUPPORTED 1 +#define CONFIG_SOC_RTC_SLOW_CLK_SUPPORT_RC_FAST_D256 1 +#define CONFIG_SOC_CLK_RC_FAST_SUPPORT_CALIBRATION 1 +#define CONFIG_SOC_CLK_XTAL32K_SUPPORTED 1 +#define CONFIG_SOC_TEMPERATURE_SENSOR_SUPPORT_FAST_RC 1 +#define CONFIG_SOC_TEMPERATURE_SENSOR_SUPPORT_XTAL 1 +#define CONFIG_SOC_WIFI_HW_TSF 1 +#define CONFIG_SOC_WIFI_FTM_SUPPORT 1 +#define CONFIG_SOC_WIFI_GCMP_SUPPORT 1 +#define CONFIG_SOC_WIFI_WAPI_SUPPORT 1 +#define CONFIG_SOC_WIFI_CSI_SUPPORT 1 +#define CONFIG_SOC_WIFI_MESH_SUPPORT 1 +#define CONFIG_SOC_WIFI_SUPPORT_VARIABLE_BEACON_WINDOW 1 +#define CONFIG_SOC_WIFI_PHY_NEEDS_USB_WORKAROUND 1 +#define CONFIG_SOC_BLE_SUPPORTED 1 +#define CONFIG_SOC_BLE_MESH_SUPPORTED 1 +#define CONFIG_SOC_BLE_50_SUPPORTED 1 +#define CONFIG_SOC_BLE_DEVICE_PRIVACY_SUPPORTED 1 +#define CONFIG_SOC_BLUFI_SUPPORTED 1 +#define CONFIG_SOC_PHY_COMBO_MODULE 1 +#define CONFIG_IDF_CMAKE 1 +#define CONFIG_IDF_TOOLCHAIN "gcc" +#define CONFIG_IDF_TOOLCHAIN_GCC 1 +#define CONFIG_IDF_TARGET_ARCH_RISCV 1 +#define CONFIG_IDF_TARGET_ARCH "riscv" +#define CONFIG_IDF_TARGET "esp32c3" +#define CONFIG_IDF_INIT_VERSION "5.4.1" +#define CONFIG_IDF_TARGET_ESP32C3 1 +#define CONFIG_IDF_FIRMWARE_CHIP_ID 0x0005 +#define CONFIG_APP_BUILD_TYPE_APP_2NDBOOT 1 +#define CONFIG_APP_BUILD_GENERATE_BINARIES 1 +#define CONFIG_APP_BUILD_BOOTLOADER 1 +#define CONFIG_APP_BUILD_USE_FLASH_SECTIONS 1 +#define CONFIG_BOOTLOADER_COMPILE_TIME_DATE 1 +#define CONFIG_BOOTLOADER_PROJECT_VER 1 +#define CONFIG_BOOTLOADER_OFFSET_IN_FLASH 0x0 +#define CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE 1 +#define CONFIG_BOOTLOADER_LOG_LEVEL_INFO 1 +#define CONFIG_BOOTLOADER_LOG_LEVEL 3 +#define CONFIG_BOOTLOADER_LOG_TIMESTAMP_SOURCE_CPU_TICKS 1 +#define CONFIG_BOOTLOADER_FLASH_XMC_SUPPORT 1 +#define CONFIG_BOOTLOADER_REGION_PROTECTION_ENABLE 1 +#define CONFIG_BOOTLOADER_WDT_ENABLE 1 +#define CONFIG_BOOTLOADER_WDT_TIME_MS 9000 +#define CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE 1 +#define CONFIG_BOOTLOADER_RESERVE_RTC_SIZE 0x0 +#define CONFIG_SECURE_BOOT_V2_RSA_SUPPORTED 1 +#define CONFIG_SECURE_BOOT_V2_PREFERRED 1 +#define CONFIG_SECURE_ROM_DL_MODE_ENABLED 1 +#define CONFIG_APP_COMPILE_TIME_DATE 1 +#define CONFIG_APP_RETRIEVE_LEN_ELF_SHA 9 +#define CONFIG_ESP_ROM_HAS_CRC_LE 1 +#define CONFIG_ESP_ROM_HAS_CRC_BE 1 +#define CONFIG_ESP_ROM_HAS_MZ_CRC32 1 +#define CONFIG_ESP_ROM_HAS_JPEG_DECODE 1 +#define CONFIG_ESP_ROM_UART_CLK_IS_XTAL 1 +#define CONFIG_ESP_ROM_USB_SERIAL_DEVICE_NUM 3 +#define CONFIG_ESP_ROM_HAS_RETARGETABLE_LOCKING 1 +#define CONFIG_ESP_ROM_HAS_ERASE_0_REGION_BUG 1 +#define CONFIG_ESP_ROM_HAS_ENCRYPTED_WRITES_USING_LEGACY_DRV 1 +#define CONFIG_ESP_ROM_GET_CLK_FREQ 1 +#define CONFIG_ESP_ROM_NEEDS_SWSETUP_WORKAROUND 1 +#define CONFIG_ESP_ROM_HAS_LAYOUT_TABLE 1 +#define CONFIG_ESP_ROM_HAS_SPI_FLASH 1 +#define CONFIG_ESP_ROM_HAS_ETS_PRINTF_BUG 1 +#define CONFIG_ESP_ROM_HAS_NEWLIB 1 +#define CONFIG_ESP_ROM_HAS_NEWLIB_NANO_FORMAT 1 +#define CONFIG_ESP_ROM_HAS_NEWLIB_32BIT_TIME 1 +#define CONFIG_ESP_ROM_NEEDS_SET_CACHE_MMU_SIZE 1 +#define CONFIG_ESP_ROM_RAM_APP_NEEDS_MMU_INIT 1 +#define CONFIG_ESP_ROM_HAS_SW_FLOAT 1 +#define CONFIG_ESP_ROM_USB_OTG_NUM -1 +#define CONFIG_ESP_ROM_HAS_VERSION 1 +#define CONFIG_ESP_ROM_SUPPORT_DEEP_SLEEP_WAKEUP_STUB 1 +#define CONFIG_BOOT_ROM_LOG_ALWAYS_ON 1 +#define CONFIG_ESPTOOLPY_FLASHMODE_DIO 1 +#define CONFIG_ESPTOOLPY_FLASH_SAMPLE_MODE_STR 1 +#define CONFIG_ESPTOOLPY_FLASHMODE "dio" +#define CONFIG_ESPTOOLPY_FLASHFREQ_80M 1 +#define CONFIG_ESPTOOLPY_FLASHFREQ "80m" +#define CONFIG_ESPTOOLPY_FLASHSIZE_4MB 1 +#define CONFIG_ESPTOOLPY_FLASHSIZE "4MB" +#define CONFIG_ESPTOOLPY_BEFORE_RESET 1 +#define CONFIG_ESPTOOLPY_BEFORE "default_reset" +#define CONFIG_ESPTOOLPY_AFTER_RESET 1 +#define CONFIG_ESPTOOLPY_AFTER "hard_reset" +#define CONFIG_ESPTOOLPY_MONITOR_BAUD 115200 +#define CONFIG_PARTITION_TABLE_CUSTOM 1 +#define CONFIG_PARTITION_TABLE_CUSTOM_FILENAME "partitions_4mb_optimised.csv" +#define CONFIG_PARTITION_TABLE_FILENAME "partitions_4mb_optimised.csv" +#define CONFIG_PARTITION_TABLE_OFFSET 0xc000 +#define CONFIG_PARTITION_TABLE_MD5 1 +#define CONFIG_EXAMPLE_BOARD_BUTTON_GPIO 9 +#define CONFIG_APP_NETWORK_PROV_SHOW_QR 1 +#define CONFIG_APP_NETWORK_PROV_MAX_POP_MISMATCH 5 +#define CONFIG_APP_NETWORK_PROV_TRANSPORT_BLE 1 +#define CONFIG_APP_NETWORK_PROV_TRANSPORT 2 +#define CONFIG_APP_NETWORK_RESET_PROV_ON_FAILURE 1 +#define CONFIG_APP_NETWORK_PROV_MAX_RETRY_CNT 5 +#define CONFIG_APP_NETWORK_PROV_TIMEOUT_PERIOD 30 +#define CONFIG_APP_NETWORK_PROV_NAME_PREFIX "PROV" +#define CONFIG_APP_WIFI_PROV_COMPAT 1 +#define CONFIG_ESP_RMAKER_SELF_CLAIM 1 +#define CONFIG_ESP_RMAKER_USE_NVS 1 +#define CONFIG_ESP_RMAKER_CLAIM_TYPE 1 +#define CONFIG_ESP_RMAKER_CLAIM_SERVICE_BASE_URL "https://esp-claiming.rainmaker.espressif.com" +#define CONFIG_ESP_RMAKER_MQTT_HOST "a1p72mufdu6064-ats.iot.us-east-1.amazonaws.com" +#define CONFIG_ESP_RMAKER_MQTT_USE_BASIC_INGEST_TOPICS 1 +#define CONFIG_ESP_RMAKER_MQTT_ENABLE_BUDGETING 1 +#define CONFIG_ESP_RMAKER_MQTT_DEFAULT_BUDGET 100 +#define CONFIG_ESP_RMAKER_MQTT_MAX_BUDGET 1024 +#define CONFIG_ESP_RMAKER_MQTT_BUDGET_REVIVE_PERIOD 5 +#define CONFIG_ESP_RMAKER_MQTT_BUDGET_REVIVE_COUNT 1 +#define CONFIG_ESP_RMAKER_MAX_PARAM_DATA_SIZE 1024 +#define CONFIG_ESP_RMAKER_USER_ID_CHECK 1 +#define CONFIG_ESP_RMAKER_LOCAL_CTRL_FEATURE_ENABLE 1 +#define CONFIG_ESP_RMAKER_LOCAL_CTRL_AUTO_ENABLE 1 +#define CONFIG_ESP_RMAKER_LOCAL_CTRL_HTTP_PORT 8080 +#define CONFIG_ESP_RMAKER_LOCAL_CTRL_STACK_SIZE 6144 +#define CONFIG_ESP_RMAKER_LOCAL_CTRL_SECURITY_1 1 +#define CONFIG_ESP_RMAKER_LOCAL_CTRL_SECURITY 1 +#define CONFIG_ESP_RMAKER_CONSOLE_UART_NUM_0 1 +#define CONFIG_ESP_RMAKER_CONSOLE_UART_NUM 0 +#define CONFIG_ESP_RMAKER_USE_CERT_BUNDLE 1 +#define CONFIG_ESP_RMAKER_OTA_AUTOFETCH 1 +#define CONFIG_ESP_RMAKER_OTA_AUTOFETCH_PERIOD 0 +#define CONFIG_ESP_RMAKER_OTA_HTTP_RX_BUFFER_SIZE 1024 +#define CONFIG_ESP_RMAKER_OTA_ROLLBACK_WAIT_PERIOD 90 +#define CONFIG_ESP_RMAKER_OTA_TIME_SUPPORT 1 +#define CONFIG_ESP_RMAKER_OTA_MAX_RETRIES 3 +#define CONFIG_ESP_RMAKER_OTA_RETRY_DELAY_MINUTES 5 +#define CONFIG_ESP_RMAKER_SCHEDULING_MAX_SCHEDULES 10 +#define CONFIG_ESP_RMAKER_SCENES_MAX_SCENES 10 +#define CONFIG_ESP_RMAKER_CMD_RESP_ENABLE 1 +#define CONFIG_ESP_RMAKER_USING_NETWORK_PROV 1 +#define CONFIG_COMPILER_OPTIMIZATION_DEBUG 1 +#define CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE 1 +#define CONFIG_COMPILER_ASSERT_NDEBUG_EVALUATE 1 +#define CONFIG_COMPILER_FLOAT_LIB_FROM_GCCLIB 1 +#define CONFIG_COMPILER_OPTIMIZATION_ASSERTION_LEVEL 2 +#define CONFIG_COMPILER_HIDE_PATHS_MACROS 1 +#define CONFIG_COMPILER_STACK_CHECK_MODE_NONE 1 +#define CONFIG_COMPILER_DISABLE_DEFAULT_ERRORS 1 +#define CONFIG_COMPILER_RT_LIB_GCCLIB 1 +#define CONFIG_COMPILER_RT_LIB_NAME "gcc" +#define CONFIG_COMPILER_ORPHAN_SECTIONS_WARNING 1 +#define CONFIG_APPTRACE_DEST_NONE 1 +#define CONFIG_APPTRACE_DEST_UART_NONE 1 +#define CONFIG_APPTRACE_UART_TASK_PRIO 1 +#define CONFIG_APPTRACE_LOCK_ENABLE 1 +#define CONFIG_BT_ENABLED 1 +#define CONFIG_BT_NIMBLE_ENABLED 1 +#define CONFIG_BT_CONTROLLER_ENABLED 1 +#define CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_INTERNAL 1 +#define CONFIG_BT_NIMBLE_LOG_LEVEL_INFO 1 +#define CONFIG_BT_NIMBLE_LOG_LEVEL 1 +#define CONFIG_BT_NIMBLE_MAX_CONNECTIONS 3 +#define CONFIG_BT_NIMBLE_MAX_BONDS 3 +#define CONFIG_BT_NIMBLE_MAX_CCCDS 8 +#define CONFIG_BT_NIMBLE_L2CAP_COC_MAX_NUM 0 +#define CONFIG_BT_NIMBLE_PINNED_TO_CORE 0 +#define CONFIG_BT_NIMBLE_HOST_TASK_STACK_SIZE 4096 +#define CONFIG_BT_NIMBLE_ROLE_CENTRAL 1 +#define CONFIG_BT_NIMBLE_ROLE_PERIPHERAL 1 +#define CONFIG_BT_NIMBLE_ROLE_BROADCASTER 1 +#define CONFIG_BT_NIMBLE_ROLE_OBSERVER 1 +#define CONFIG_BT_NIMBLE_SECURITY_ENABLE 1 +#define CONFIG_BT_NIMBLE_SM_LEGACY 1 +#define CONFIG_BT_NIMBLE_SM_SC 1 +#define CONFIG_BT_NIMBLE_LL_CFG_FEAT_LE_ENCRYPTION 1 +#define CONFIG_BT_NIMBLE_SM_LVL 0 +#define CONFIG_BT_NIMBLE_SM_SC_ONLY 0 +#define CONFIG_BT_NIMBLE_SVC_GAP_DEVICE_NAME "nimble" +#define CONFIG_BT_NIMBLE_GAP_DEVICE_NAME_MAX_LEN 31 +#define CONFIG_BT_NIMBLE_ATT_PREFERRED_MTU 256 +#define CONFIG_BT_NIMBLE_SVC_GAP_APPEARANCE 0x0 +#define CONFIG_BT_NIMBLE_MSYS_1_BLOCK_COUNT 12 +#define CONFIG_BT_NIMBLE_MSYS_1_BLOCK_SIZE 256 +#define CONFIG_BT_NIMBLE_MSYS_2_BLOCK_COUNT 24 +#define CONFIG_BT_NIMBLE_MSYS_2_BLOCK_SIZE 320 +#define CONFIG_BT_NIMBLE_TRANSPORT_ACL_FROM_LL_COUNT 24 +#define CONFIG_BT_NIMBLE_TRANSPORT_ACL_SIZE 255 +#define CONFIG_BT_NIMBLE_TRANSPORT_EVT_SIZE 70 +#define CONFIG_BT_NIMBLE_TRANSPORT_EVT_COUNT 30 +#define CONFIG_BT_NIMBLE_TRANSPORT_EVT_DISCARD_COUNT 8 +#define CONFIG_BT_NIMBLE_L2CAP_COC_SDU_BUFF_COUNT 1 +#define CONFIG_BT_NIMBLE_GATT_MAX_PROCS 4 +#define CONFIG_BT_NIMBLE_RPA_TIMEOUT 900 +#define CONFIG_BT_NIMBLE_CRYPTO_STACK_MBEDTLS 1 +#define CONFIG_BT_NIMBLE_HS_STOP_TIMEOUT_MS 2000 +#define CONFIG_BT_NIMBLE_ENABLE_CONN_REATTEMPT 1 +#define CONFIG_BT_NIMBLE_MAX_CONN_REATTEMPT 3 +#define CONFIG_BT_NIMBLE_50_FEATURE_SUPPORT 1 +#define CONFIG_BT_NIMBLE_LL_CFG_FEAT_LE_2M_PHY 1 +#define CONFIG_BT_NIMBLE_LL_CFG_FEAT_LE_CODED_PHY 1 +#define CONFIG_BT_NIMBLE_EXT_SCAN 1 +#define CONFIG_BT_NIMBLE_ENABLE_PERIODIC_SYNC 1 +#define CONFIG_BT_NIMBLE_MAX_PERIODIC_SYNCS 0 +#define CONFIG_BT_NIMBLE_WHITELIST_SIZE 12 +#define CONFIG_BT_NIMBLE_USE_ESP_TIMER 1 +#define CONFIG_BT_NIMBLE_LEGACY_VHCI_ENABLE 1 +#define CONFIG_BT_NIMBLE_SVC_GAP_APPEAR_WRITE_PERM 0 +#define CONFIG_BT_NIMBLE_SVC_GAP_APPEAR_WRITE_PERM_ENC 0 +#define CONFIG_BT_NIMBLE_SVC_GAP_APPEAR_WRITE_PERM_ATHN 0 +#define CONFIG_BT_NIMBLE_SVC_GAP_APPEAR_WRITE_PERM_ATHR 0 +#define CONFIG_BT_NIMBLE_SVC_GAP_CAR_CHAR_NOT_SUPP 1 +#define CONFIG_BT_NIMBLE_SVC_GAP_CENT_ADDR_RESOLUTION -1 +#define CONFIG_BT_NIMBLE_SVC_GAP_NAME_WRITE_PERM 0 +#define CONFIG_BT_NIMBLE_SVC_GAP_NAME_WRITE_PERM_ENC 0 +#define CONFIG_BT_NIMBLE_SVC_GAP_NAME_WRITE_PERM_AUTHEN 0 +#define CONFIG_BT_NIMBLE_SVC_GAP_NAME_WRITE_PERM_AUTHOR 0 +#define CONFIG_BT_NIMBLE_SVC_GAP_PPCP_MAX_CONN_INTERVAL 0 +#define CONFIG_BT_NIMBLE_SVC_GAP_PPCP_MIN_CONN_INTERVAL 0 +#define CONFIG_BT_NIMBLE_SVC_GAP_PPCP_SLAVE_LATENCY 0 +#define CONFIG_BT_NIMBLE_SVC_GAP_PPCP_SUPERVISION_TMO 0 +#define CONFIG_UART_HW_FLOWCTRL_DISABLE 1 +#define CONFIG_BT_NIMBLE_HCI_UART_FLOW_CTRL 0 +#define CONFIG_BT_NIMBLE_HCI_UART_RTS_PIN 19 +#define CONFIG_BT_NIMBLE_HCI_UART_CTS_PIN 23 +#define CONFIG_BT_NIMBLE_EATT_CHAN_NUM 0 +#define CONFIG_BT_CTRL_MODE_EFF 1 +#define CONFIG_BT_CTRL_BLE_MAX_ACT 6 +#define CONFIG_BT_CTRL_BLE_MAX_ACT_EFF 6 +#define CONFIG_BT_CTRL_BLE_STATIC_ACL_TX_BUF_NB 0 +#define CONFIG_BT_CTRL_PINNED_TO_CORE 0 +#define CONFIG_BT_CTRL_HCI_MODE_VHCI 1 +#define CONFIG_BT_CTRL_HCI_TL 1 +#define CONFIG_BT_CTRL_ADV_DUP_FILT_MAX 30 +#define CONFIG_BT_BLE_CCA_MODE_NONE 1 +#define CONFIG_BT_BLE_CCA_MODE 0 +#define CONFIG_BT_CTRL_HW_CCA_VAL 20 +#define CONFIG_BT_CTRL_HW_CCA_EFF 0 +#define CONFIG_BT_CTRL_CE_LENGTH_TYPE_ORIG 1 +#define CONFIG_BT_CTRL_CE_LENGTH_TYPE_EFF 0 +#define CONFIG_BT_CTRL_TX_ANTENNA_INDEX_0 1 +#define CONFIG_BT_CTRL_TX_ANTENNA_INDEX_EFF 0 +#define CONFIG_BT_CTRL_RX_ANTENNA_INDEX_0 1 +#define CONFIG_BT_CTRL_RX_ANTENNA_INDEX_EFF 0 +#define CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P9 1 +#define CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_EFF 11 +#define CONFIG_BT_CTRL_BLE_ADV_REPORT_FLOW_CTRL_SUPP 1 +#define CONFIG_BT_CTRL_BLE_ADV_REPORT_FLOW_CTRL_NUM 100 +#define CONFIG_BT_CTRL_BLE_ADV_REPORT_DISCARD_THRSHOLD 20 +#define CONFIG_BT_CTRL_BLE_SCAN_DUPL 1 +#define CONFIG_BT_CTRL_SCAN_DUPL_TYPE_DEVICE 1 +#define CONFIG_BT_CTRL_SCAN_DUPL_TYPE 0 +#define CONFIG_BT_CTRL_SCAN_DUPL_CACHE_SIZE 100 +#define CONFIG_BT_CTRL_DUPL_SCAN_CACHE_REFRESH_PERIOD 0 +#define CONFIG_BT_CTRL_COEX_PHY_CODED_TX_RX_TLIM_DIS 1 +#define CONFIG_BT_CTRL_COEX_PHY_CODED_TX_RX_TLIM_EFF 0 +#define CONFIG_BT_CTRL_SLEEP_MODE_EFF 0 +#define CONFIG_BT_CTRL_SLEEP_CLOCK_EFF 0 +#define CONFIG_BT_CTRL_HCI_TL_EFF 1 +#define CONFIG_BT_CTRL_CHAN_ASS_EN 1 +#define CONFIG_BT_CTRL_LE_PING_EN 1 +#define CONFIG_BT_ALARM_MAX_NUM 50 +#define CONFIG_TWAI_ERRATA_FIX_LISTEN_ONLY_DOM 1 +#define CONFIG_EFUSE_MAX_BLK_LEN 256 +#define CONFIG_ESP_TLS_USING_MBEDTLS 1 +#define CONFIG_ESP_TLS_USE_DS_PERIPHERAL 1 +#define CONFIG_ESP_COEX_ENABLED 1 +#define CONFIG_ESP_COEX_SW_COEXIST_ENABLE 1 +#define CONFIG_ESP_ERR_TO_NAME_LOOKUP 1 +#define CONFIG_GPTIMER_ISR_HANDLER_IN_IRAM 1 +#define CONFIG_SPI_MASTER_ISR_IN_IRAM 1 +#define CONFIG_SPI_SLAVE_ISR_IN_IRAM 1 +#define CONFIG_USJ_ENABLE_USB_SERIAL_JTAG 1 +#define CONFIG_ETH_ENABLED 1 +#define CONFIG_ETH_USE_SPI_ETHERNET 1 +#define CONFIG_ESP_EVENT_POST_FROM_ISR 1 +#define CONFIG_ESP_EVENT_POST_FROM_IRAM_ISR 1 +#define CONFIG_ESP_GDBSTUB_ENABLED 1 +#define CONFIG_ESP_GDBSTUB_SUPPORT_TASKS 1 +#define CONFIG_ESP_GDBSTUB_MAX_TASKS 32 +#define CONFIG_ESPHID_TASK_SIZE_BT 2048 +#define CONFIG_ESPHID_TASK_SIZE_BLE 4096 +#define CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS 1 +#define CONFIG_ESP_HTTP_CLIENT_EVENT_POST_TIMEOUT 2000 +#define CONFIG_HTTPD_MAX_REQ_HDR_LEN 512 +#define CONFIG_HTTPD_MAX_URI_LEN 512 +#define CONFIG_HTTPD_ERR_RESP_NO_DELAY 1 +#define CONFIG_HTTPD_PURGE_BUF_LEN 32 +#define CONFIG_HTTPD_SERVER_EVENT_POST_TIMEOUT 2000 +#define CONFIG_ESP_HTTPS_OTA_EVENT_POST_TIMEOUT 2000 +#define CONFIG_ESP_HTTPS_SERVER_ENABLE 1 +#define CONFIG_ESP_HTTPS_SERVER_EVENT_POST_TIMEOUT 2000 +#define CONFIG_ESP32C3_REV_MIN_3 1 +#define CONFIG_ESP32C3_REV_MIN_FULL 3 +#define CONFIG_ESP_REV_MIN_FULL 3 +#define CONFIG_ESP32C3_REV_MAX_FULL 199 +#define CONFIG_ESP_REV_MAX_FULL 199 +#define CONFIG_ESP_EFUSE_BLOCK_REV_MIN_FULL 0 +#define CONFIG_ESP_EFUSE_BLOCK_REV_MAX_FULL 199 +#define CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_STA 1 +#define CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_AP 1 +#define CONFIG_ESP_MAC_ADDR_UNIVERSE_BT 1 +#define CONFIG_ESP_MAC_ADDR_UNIVERSE_ETH 1 +#define CONFIG_ESP_MAC_UNIVERSAL_MAC_ADDRESSES_FOUR 1 +#define CONFIG_ESP_MAC_UNIVERSAL_MAC_ADDRESSES 4 +#define CONFIG_ESP32C3_UNIVERSAL_MAC_ADDRESSES_FOUR 1 +#define CONFIG_ESP32C3_UNIVERSAL_MAC_ADDRESSES 4 +#define CONFIG_ESP_SLEEP_FLASH_LEAKAGE_WORKAROUND 1 +#define CONFIG_ESP_SLEEP_GPIO_RESET_WORKAROUND 1 +#define CONFIG_ESP_SLEEP_WAIT_FLASH_READY_EXTRA_DELAY 0 +#define CONFIG_ESP_SLEEP_GPIO_ENABLE_INTERNAL_RESISTORS 1 +#define CONFIG_RTC_CLK_SRC_INT_RC 1 +#define CONFIG_RTC_CLK_CAL_CYCLES 1024 +#define CONFIG_PERIPH_CTRL_FUNC_IN_IRAM 1 +#define CONFIG_GDMA_CTRL_FUNC_IN_IRAM 1 +#define CONFIG_XTAL_FREQ_40 1 +#define CONFIG_XTAL_FREQ 40 +#define CONFIG_ESP_SPI_BUS_LOCK_ISR_FUNCS_IN_IRAM 1 +#define CONFIG_ESP_NETIF_IP_LOST_TIMER_INTERVAL 120 +#define CONFIG_ESP_NETIF_TCPIP_LWIP 1 +#define CONFIG_ESP_NETIF_USES_TCPIP_WITH_BSD_API 1 +#define CONFIG_ESP_NETIF_REPORT_DATA_TRAFFIC 1 +#define CONFIG_ESP_PHY_ENABLED 1 +#define CONFIG_ESP_PHY_CALIBRATION_AND_DATA_STORAGE 1 +#define CONFIG_ESP_PHY_MAX_WIFI_TX_POWER 20 +#define CONFIG_ESP_PHY_MAX_TX_POWER 20 +#define CONFIG_ESP_PHY_ENABLE_USB 1 +#define CONFIG_ESP_PHY_RF_CAL_PARTIAL 1 +#define CONFIG_ESP_PHY_CALIBRATION_MODE 0 +#define CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP 1 +#define CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_160 1 +#define CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ 160 +#define CONFIG_ESP_SYSTEM_PANIC_PRINT_REBOOT 1 +#define CONFIG_ESP_SYSTEM_PANIC_REBOOT_DELAY_SECONDS 0 +#define CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE 1 +#define CONFIG_ESP_SYSTEM_RTC_FAST_MEM_AS_HEAP_DEPCHECK 1 +#define CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP 1 +#define CONFIG_ESP_SYSTEM_MEMPROT_FEATURE 1 +#define CONFIG_ESP_SYSTEM_MEMPROT_FEATURE_LOCK 1 +#define CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE 32 +#define CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE 2304 +#define CONFIG_ESP_MAIN_TASK_STACK_SIZE 3584 +#define CONFIG_ESP_MAIN_TASK_AFFINITY_CPU0 1 +#define CONFIG_ESP_MAIN_TASK_AFFINITY 0x0 +#define CONFIG_ESP_MINIMAL_SHARED_STACK_SIZE 2048 +#define CONFIG_ESP_CONSOLE_UART_DEFAULT 1 +#define CONFIG_ESP_CONSOLE_SECONDARY_USB_SERIAL_JTAG 1 +#define CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG_ENABLED 1 +#define CONFIG_ESP_CONSOLE_UART 1 +#define CONFIG_ESP_CONSOLE_UART_NUM 0 +#define CONFIG_ESP_CONSOLE_ROM_SERIAL_PORT_NUM 0 +#define CONFIG_ESP_CONSOLE_UART_BAUDRATE 115200 +#define CONFIG_ESP_INT_WDT 1 +#define CONFIG_ESP_INT_WDT_TIMEOUT_MS 300 +#define CONFIG_ESP_TASK_WDT_EN 1 +#define CONFIG_ESP_TASK_WDT_INIT 1 +#define CONFIG_ESP_TASK_WDT_TIMEOUT_S 5 +#define CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0 1 +#define CONFIG_ESP_DEBUG_OCDAWARE 1 +#define CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL_4 1 +#define CONFIG_ESP_BROWNOUT_DET 1 +#define CONFIG_ESP_BROWNOUT_DET_LVL_SEL_7 1 +#define CONFIG_ESP_BROWNOUT_DET_LVL 7 +#define CONFIG_ESP_SYSTEM_BROWNOUT_INTR 1 +#define CONFIG_ESP_SYSTEM_HW_STACK_GUARD 1 +#define CONFIG_ESP_SYSTEM_HW_PC_RECORD 1 +#define CONFIG_ESP_IPC_TASK_STACK_SIZE 1024 +#define CONFIG_ESP_TIME_FUNCS_USE_RTC_TIMER 1 +#define CONFIG_ESP_TIME_FUNCS_USE_ESP_TIMER 1 +#define CONFIG_ESP_TIMER_TASK_STACK_SIZE 3584 +#define CONFIG_ESP_TIMER_INTERRUPT_LEVEL 1 +#define CONFIG_ESP_TIMER_TASK_AFFINITY 0x0 +#define CONFIG_ESP_TIMER_TASK_AFFINITY_CPU0 1 +#define CONFIG_ESP_TIMER_ISR_AFFINITY_CPU0 1 +#define CONFIG_ESP_TIMER_IMPL_SYSTIMER 1 +#define CONFIG_ESP_WIFI_ENABLED 1 +#define CONFIG_ESP_WIFI_STATIC_RX_BUFFER_NUM 10 +#define CONFIG_ESP_WIFI_DYNAMIC_RX_BUFFER_NUM 32 +#define CONFIG_ESP_WIFI_DYNAMIC_TX_BUFFER 1 +#define CONFIG_ESP_WIFI_TX_BUFFER_TYPE 1 +#define CONFIG_ESP_WIFI_DYNAMIC_TX_BUFFER_NUM 32 +#define CONFIG_ESP_WIFI_STATIC_RX_MGMT_BUFFER 1 +#define CONFIG_ESP_WIFI_DYNAMIC_RX_MGMT_BUF 0 +#define CONFIG_ESP_WIFI_RX_MGMT_BUF_NUM_DEF 5 +#define CONFIG_ESP_WIFI_AMPDU_TX_ENABLED 1 +#define CONFIG_ESP_WIFI_TX_BA_WIN 6 +#define CONFIG_ESP_WIFI_AMPDU_RX_ENABLED 1 +#define CONFIG_ESP_WIFI_RX_BA_WIN 6 +#define CONFIG_ESP_WIFI_NVS_ENABLED 1 +#define CONFIG_ESP_WIFI_SOFTAP_BEACON_MAX_LEN 752 +#define CONFIG_ESP_WIFI_MGMT_SBUF_NUM 32 +#define CONFIG_ESP_WIFI_IRAM_OPT 1 +#define CONFIG_ESP_WIFI_RX_IRAM_OPT 1 +#define CONFIG_ESP_WIFI_ENABLE_WPA3_SAE 1 +#define CONFIG_ESP_WIFI_ENABLE_SAE_PK 1 +#define CONFIG_ESP_WIFI_SOFTAP_SAE_SUPPORT 1 +#define CONFIG_ESP_WIFI_ENABLE_WPA3_OWE_STA 1 +#define CONFIG_ESP_WIFI_SLP_DEFAULT_MIN_ACTIVE_TIME 50 +#define CONFIG_ESP_WIFI_SLP_DEFAULT_MAX_ACTIVE_TIME 10 +#define CONFIG_ESP_WIFI_SLP_DEFAULT_WAIT_BROADCAST_DATA_TIME 15 +#define CONFIG_ESP_WIFI_STA_DISCONNECTED_PM_ENABLE 1 +#define CONFIG_ESP_WIFI_GMAC_SUPPORT 1 +#define CONFIG_ESP_WIFI_SOFTAP_SUPPORT 1 +#define CONFIG_ESP_WIFI_ESPNOW_MAX_ENCRYPT_NUM 7 +#define CONFIG_ESP_WIFI_MBEDTLS_CRYPTO 1 +#define CONFIG_ESP_WIFI_MBEDTLS_TLS_CLIENT 1 +#define CONFIG_ESP_WIFI_ENTERPRISE_SUPPORT 1 +#define CONFIG_ESP_COREDUMP_ENABLE_TO_NONE 1 +#define CONFIG_FATFS_VOLUME_COUNT 2 +#define CONFIG_FATFS_LFN_NONE 1 +#define CONFIG_FATFS_SECTOR_4096 1 +#define CONFIG_FATFS_CODEPAGE_437 1 +#define CONFIG_FATFS_CODEPAGE 437 +#define CONFIG_FATFS_FS_LOCK 0 +#define CONFIG_FATFS_TIMEOUT_MS 10000 +#define CONFIG_FATFS_PER_FILE_CACHE 1 +#define CONFIG_FATFS_USE_STRFUNC_NONE 1 +#define CONFIG_FATFS_VFS_FSTAT_BLKSIZE 0 +#define CONFIG_FATFS_LINK_LOCK 1 +#define CONFIG_FREERTOS_UNICORE 1 +#define CONFIG_FREERTOS_HZ 100 +#define CONFIG_FREERTOS_OPTIMIZED_SCHEDULER 1 +#define CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY 1 +#define CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS 1 +#define CONFIG_FREERTOS_IDLE_TASK_STACKSIZE 1536 +#define CONFIG_FREERTOS_MAX_TASK_NAME_LEN 16 +#define CONFIG_FREERTOS_USE_TIMERS 1 +#define CONFIG_FREERTOS_TIMER_SERVICE_TASK_NAME "Tmr Svc" +#define CONFIG_FREERTOS_TIMER_TASK_NO_AFFINITY 1 +#define CONFIG_FREERTOS_TIMER_SERVICE_TASK_CORE_AFFINITY 0x7FFFFFFF +#define CONFIG_FREERTOS_TIMER_TASK_PRIORITY 1 +#define CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH 3120 +#define CONFIG_FREERTOS_TIMER_QUEUE_LENGTH 10 +#define CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE 0 +#define CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES 1 +#define CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER 1 +#define CONFIG_FREERTOS_TLSP_DELETION_CALLBACKS 1 +#define CONFIG_FREERTOS_CHECK_MUTEX_GIVEN_BY_OWNER 1 +#define CONFIG_FREERTOS_ISR_STACKSIZE 1536 +#define CONFIG_FREERTOS_INTERRUPT_BACKTRACE 1 +#define CONFIG_FREERTOS_TICK_SUPPORT_SYSTIMER 1 +#define CONFIG_FREERTOS_CORETIMER_SYSTIMER_LVL1 1 +#define CONFIG_FREERTOS_SYSTICK_USES_SYSTIMER 1 +#define CONFIG_FREERTOS_PORT 1 +#define CONFIG_FREERTOS_NO_AFFINITY 0x7FFFFFFF +#define CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION 1 +#define CONFIG_FREERTOS_DEBUG_OCDAWARE 1 +#define CONFIG_FREERTOS_ENABLE_TASK_SNAPSHOT 1 +#define CONFIG_FREERTOS_PLACE_SNAPSHOT_FUNS_INTO_FLASH 1 +#define CONFIG_FREERTOS_NUMBER_OF_CORES 1 +#define CONFIG_HAL_ASSERTION_EQUALS_SYSTEM 1 +#define CONFIG_HAL_DEFAULT_ASSERTION_LEVEL 2 +#define CONFIG_HAL_SPI_MASTER_FUNC_IN_IRAM 1 +#define CONFIG_HAL_SPI_SLAVE_FUNC_IN_IRAM 1 +#define CONFIG_HEAP_POISONING_DISABLED 1 +#define CONFIG_HEAP_TRACING_OFF 1 +#define CONFIG_LOG_DEFAULT_LEVEL_INFO 1 +#define CONFIG_LOG_DEFAULT_LEVEL 3 +#define CONFIG_LOG_MAXIMUM_EQUALS_DEFAULT 1 +#define CONFIG_LOG_MAXIMUM_LEVEL 3 +#define CONFIG_LOG_DYNAMIC_LEVEL_CONTROL 1 +#define CONFIG_LOG_TAG_LEVEL_IMPL_CACHE_AND_LINKED_LIST 1 +#define CONFIG_LOG_TAG_LEVEL_CACHE_BINARY_MIN_HEAP 1 +#define CONFIG_LOG_TAG_LEVEL_IMPL_CACHE_SIZE 31 +#define CONFIG_LOG_TIMESTAMP_SOURCE_RTOS 1 +#define CONFIG_LWIP_ENABLE 1 +#define CONFIG_LWIP_LOCAL_HOSTNAME "espressif" +#define CONFIG_LWIP_TCPIP_TASK_PRIO 18 +#define CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES 1 +#define CONFIG_LWIP_TIMERS_ONDEMAND 1 +#define CONFIG_LWIP_ND6 1 +#define CONFIG_LWIP_MAX_SOCKETS 10 +#define CONFIG_LWIP_SO_REUSE 1 +#define CONFIG_LWIP_SO_REUSE_RXTOALL 1 +#define CONFIG_LWIP_IP_DEFAULT_TTL 64 +#define CONFIG_LWIP_IP4_FRAG 1 +#define CONFIG_LWIP_IP6_FRAG 1 +#define CONFIG_LWIP_IP_REASS_MAX_PBUFS 10 +#define CONFIG_LWIP_ESP_GRATUITOUS_ARP 1 +#define CONFIG_LWIP_GARP_TMR_INTERVAL 60 +#define CONFIG_LWIP_ESP_MLDV6_REPORT 1 +#define CONFIG_LWIP_MLDV6_TMR_INTERVAL 40 +#define CONFIG_LWIP_TCPIP_RECVMBOX_SIZE 32 +#define CONFIG_LWIP_DHCP_DOES_ARP_CHECK 1 +#define CONFIG_LWIP_DHCP_DISABLE_VENDOR_CLASS_ID 1 +#define CONFIG_LWIP_DHCP_OPTIONS_LEN 68 +#define CONFIG_LWIP_NUM_NETIF_CLIENT_DATA 0 +#define CONFIG_LWIP_DHCP_COARSE_TIMER_SECS 1 +#define CONFIG_LWIP_DHCPS 1 +#define CONFIG_LWIP_DHCPS_LEASE_UNIT 60 +#define CONFIG_LWIP_DHCPS_MAX_STATION_NUM 8 +#define CONFIG_LWIP_DHCPS_STATIC_ENTRIES 1 +#define CONFIG_LWIP_DHCPS_ADD_DNS 1 +#define CONFIG_LWIP_IPV4 1 +#define CONFIG_LWIP_IPV6 1 +#define CONFIG_LWIP_IPV6_NUM_ADDRESSES 3 +#define CONFIG_LWIP_NETIF_LOOPBACK 1 +#define CONFIG_LWIP_LOOPBACK_MAX_PBUFS 8 +#define CONFIG_LWIP_MAX_ACTIVE_TCP 16 +#define CONFIG_LWIP_MAX_LISTENING_TCP 16 +#define CONFIG_LWIP_TCP_HIGH_SPEED_RETRANSMISSION 1 +#define CONFIG_LWIP_TCP_MAXRTX 12 +#define CONFIG_LWIP_TCP_SYNMAXRTX 12 +#define CONFIG_LWIP_TCP_MSS 1440 +#define CONFIG_LWIP_TCP_TMR_INTERVAL 250 +#define CONFIG_LWIP_TCP_MSL 60000 +#define CONFIG_LWIP_TCP_FIN_WAIT_TIMEOUT 20000 +#define CONFIG_LWIP_TCP_SND_BUF_DEFAULT 5760 +#define CONFIG_LWIP_TCP_WND_DEFAULT 5760 +#define CONFIG_LWIP_TCP_RECVMBOX_SIZE 6 +#define CONFIG_LWIP_TCP_ACCEPTMBOX_SIZE 6 +#define CONFIG_LWIP_TCP_QUEUE_OOSEQ 1 +#define CONFIG_LWIP_TCP_OOSEQ_TIMEOUT 6 +#define CONFIG_LWIP_TCP_OOSEQ_MAX_PBUFS 4 +#define CONFIG_LWIP_TCP_OVERSIZE_MSS 1 +#define CONFIG_LWIP_TCP_RTO_TIME 1500 +#define CONFIG_LWIP_MAX_UDP_PCBS 16 +#define CONFIG_LWIP_UDP_RECVMBOX_SIZE 6 +#define CONFIG_LWIP_CHECKSUM_CHECK_ICMP 1 +#define CONFIG_LWIP_TCPIP_TASK_STACK_SIZE 3072 +#define CONFIG_LWIP_TCPIP_TASK_AFFINITY_NO_AFFINITY 1 +#define CONFIG_LWIP_TCPIP_TASK_AFFINITY 0x7FFFFFFF +#define CONFIG_LWIP_IPV6_MEMP_NUM_ND6_QUEUE 3 +#define CONFIG_LWIP_IPV6_ND6_NUM_NEIGHBORS 5 +#define CONFIG_LWIP_IPV6_ND6_NUM_PREFIXES 5 +#define CONFIG_LWIP_IPV6_ND6_NUM_ROUTERS 3 +#define CONFIG_LWIP_IPV6_ND6_NUM_DESTINATIONS 10 +#define CONFIG_LWIP_ICMP 1 +#define CONFIG_LWIP_MAX_RAW_PCBS 16 +#define CONFIG_LWIP_SNTP_MAX_SERVERS 1 +#define CONFIG_LWIP_SNTP_UPDATE_DELAY 3600000 +#define CONFIG_LWIP_SNTP_STARTUP_DELAY 1 +#define CONFIG_LWIP_SNTP_MAXIMUM_STARTUP_DELAY 5000 +#define CONFIG_LWIP_DNS_MAX_HOST_IP 1 +#define CONFIG_LWIP_DNS_MAX_SERVERS 3 +#define CONFIG_LWIP_BRIDGEIF_MAX_PORTS 7 +#define CONFIG_LWIP_ESP_LWIP_ASSERT 1 +#define CONFIG_LWIP_HOOK_TCP_ISN_DEFAULT 1 +#define CONFIG_LWIP_HOOK_IP6_ROUTE_NONE 1 +#define CONFIG_LWIP_HOOK_ND6_GET_GW_NONE 1 +#define CONFIG_LWIP_HOOK_IP6_SELECT_SRC_ADDR_NONE 1 +#define CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_NONE 1 +#define CONFIG_LWIP_HOOK_DNS_EXT_RESOLVE_NONE 1 +#define CONFIG_LWIP_HOOK_IP6_INPUT_DEFAULT 1 +#define CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC 1 +#define CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN 1 +#define CONFIG_MBEDTLS_SSL_IN_CONTENT_LEN 16384 +#define CONFIG_MBEDTLS_SSL_OUT_CONTENT_LEN 4096 +#define CONFIG_MBEDTLS_DYNAMIC_BUFFER 1 +#define CONFIG_MBEDTLS_DYNAMIC_FREE_CONFIG_DATA 1 +#define CONFIG_MBEDTLS_DYNAMIC_FREE_CA_CERT 1 +#define CONFIG_MBEDTLS_SSL_KEEP_PEER_CERTIFICATE 1 +#define CONFIG_MBEDTLS_PKCS7_C 1 +#define CONFIG_MBEDTLS_CERTIFICATE_BUNDLE 1 +#define CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_CMN 1 +#define CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_MAX_CERTS 200 +#define CONFIG_MBEDTLS_CMAC_C 1 +#define CONFIG_MBEDTLS_HARDWARE_AES 1 +#define CONFIG_MBEDTLS_AES_USE_INTERRUPT 1 +#define CONFIG_MBEDTLS_AES_INTERRUPT_LEVEL 0 +#define CONFIG_MBEDTLS_GCM_SUPPORT_NON_AES_CIPHER 1 +#define CONFIG_MBEDTLS_HARDWARE_MPI 1 +#define CONFIG_MBEDTLS_LARGE_KEY_SOFTWARE_MPI 1 +#define CONFIG_MBEDTLS_MPI_USE_INTERRUPT 1 +#define CONFIG_MBEDTLS_MPI_INTERRUPT_LEVEL 0 +#define CONFIG_MBEDTLS_HARDWARE_SHA 1 +#define CONFIG_MBEDTLS_ROM_MD5 1 +#define CONFIG_MBEDTLS_HAVE_TIME 1 +#define CONFIG_MBEDTLS_ECDSA_DETERMINISTIC 1 +#define CONFIG_MBEDTLS_SHA512_C 1 +#define CONFIG_MBEDTLS_TLS_SERVER_AND_CLIENT 1 +#define CONFIG_MBEDTLS_TLS_SERVER 1 +#define CONFIG_MBEDTLS_TLS_CLIENT 1 +#define CONFIG_MBEDTLS_TLS_ENABLED 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_RSA 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_RSA 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_RSA 1 +#define CONFIG_MBEDTLS_SSL_RENEGOTIATION 1 +#define CONFIG_MBEDTLS_SSL_PROTO_TLS1_2 1 +#define CONFIG_MBEDTLS_SSL_ALPN 1 +#define CONFIG_MBEDTLS_CLIENT_SSL_SESSION_TICKETS 1 +#define CONFIG_MBEDTLS_SERVER_SSL_SESSION_TICKETS 1 +#define CONFIG_MBEDTLS_AES_C 1 +#define CONFIG_MBEDTLS_CCM_C 1 +#define CONFIG_MBEDTLS_GCM_C 1 +#define CONFIG_MBEDTLS_PEM_PARSE_C 1 +#define CONFIG_MBEDTLS_PEM_WRITE_C 1 +#define CONFIG_MBEDTLS_X509_CRL_PARSE_C 1 +#define CONFIG_MBEDTLS_X509_CSR_PARSE_C 1 +#define CONFIG_MBEDTLS_ECP_C 1 +#define CONFIG_MBEDTLS_PK_PARSE_EC_EXTENDED 1 +#define CONFIG_MBEDTLS_PK_PARSE_EC_COMPRESSED 1 +#define CONFIG_MBEDTLS_ECDH_C 1 +#define CONFIG_MBEDTLS_ECDSA_C 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP192R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP224R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP384R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP521R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP192K1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP224K1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP256K1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_BP256R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_BP384R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_BP512R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_CURVE25519_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_NIST_OPTIM 1 +#define CONFIG_MBEDTLS_ERROR_STRINGS 1 +#define CONFIG_MBEDTLS_FS_IO 1 +#define CONFIG_MQTT_PROTOCOL_311 1 +#define CONFIG_MQTT_TRANSPORT_SSL 1 +#define CONFIG_MQTT_TRANSPORT_WEBSOCKET 1 +#define CONFIG_MQTT_TRANSPORT_WEBSOCKET_SECURE 1 +#define CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF 1 +#define CONFIG_NEWLIB_STDIN_LINE_ENDING_CR 1 +#define CONFIG_NEWLIB_TIME_SYSCALL_USE_RTC_HRT 1 +#define CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_0 1 +#define CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_1 1 +#define CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_2 1 +#define CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_PATCH_VERSION 1 +#define CONFIG_PTHREAD_TASK_PRIO_DEFAULT 5 +#define CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT 3072 +#define CONFIG_PTHREAD_STACK_MIN 768 +#define CONFIG_PTHREAD_TASK_CORE_DEFAULT -1 +#define CONFIG_PTHREAD_TASK_NAME_DEFAULT "pthread" +#define CONFIG_MMU_PAGE_SIZE_64KB 1 +#define CONFIG_MMU_PAGE_MODE "64KB" +#define CONFIG_MMU_PAGE_SIZE 0x10000 +#define CONFIG_SPI_FLASH_BROWNOUT_RESET_XMC 1 +#define CONFIG_SPI_FLASH_BROWNOUT_RESET 1 +#define CONFIG_SPI_FLASH_SUSPEND_TSUS_VAL_US 50 +#define CONFIG_SPI_FLASH_ROM_DRIVER_PATCH 1 +#define CONFIG_SPI_FLASH_DANGEROUS_WRITE_ABORTS 1 +#define CONFIG_SPI_FLASH_YIELD_DURING_ERASE 1 +#define CONFIG_SPI_FLASH_ERASE_YIELD_DURATION_MS 20 +#define CONFIG_SPI_FLASH_ERASE_YIELD_TICKS 1 +#define CONFIG_SPI_FLASH_WRITE_CHUNK_SIZE 8192 +#define CONFIG_SPI_FLASH_VENDOR_XMC_SUPPORTED 1 +#define CONFIG_SPI_FLASH_VENDOR_GD_SUPPORTED 1 +#define CONFIG_SPI_FLASH_VENDOR_ISSI_SUPPORTED 1 +#define CONFIG_SPI_FLASH_VENDOR_MXIC_SUPPORTED 1 +#define CONFIG_SPI_FLASH_VENDOR_WINBOND_SUPPORTED 1 +#define CONFIG_SPI_FLASH_VENDOR_BOYA_SUPPORTED 1 +#define CONFIG_SPI_FLASH_VENDOR_TH_SUPPORTED 1 +#define CONFIG_SPI_FLASH_SUPPORT_ISSI_CHIP 1 +#define CONFIG_SPI_FLASH_SUPPORT_MXIC_CHIP 1 +#define CONFIG_SPI_FLASH_SUPPORT_GD_CHIP 1 +#define CONFIG_SPI_FLASH_SUPPORT_WINBOND_CHIP 1 +#define CONFIG_SPI_FLASH_SUPPORT_BOYA_CHIP 1 +#define CONFIG_SPI_FLASH_SUPPORT_TH_CHIP 1 +#define CONFIG_SPI_FLASH_ENABLE_ENCRYPTED_READ_WRITE 1 +#define CONFIG_SPIFFS_MAX_PARTITIONS 3 +#define CONFIG_SPIFFS_CACHE 1 +#define CONFIG_SPIFFS_CACHE_WR 1 +#define CONFIG_SPIFFS_PAGE_CHECK 1 +#define CONFIG_SPIFFS_GC_MAX_RUNS 10 +#define CONFIG_SPIFFS_PAGE_SIZE 256 +#define CONFIG_SPIFFS_OBJ_NAME_LEN 32 +#define CONFIG_SPIFFS_USE_MAGIC 1 +#define CONFIG_SPIFFS_USE_MAGIC_LENGTH 1 +#define CONFIG_SPIFFS_META_LENGTH 4 +#define CONFIG_SPIFFS_USE_MTIME 1 +#define CONFIG_WS_TRANSPORT 1 +#define CONFIG_WS_BUFFER_SIZE 1024 +#define CONFIG_UNITY_ENABLE_FLOAT 1 +#define CONFIG_UNITY_ENABLE_DOUBLE 1 +#define CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER 1 +#define CONFIG_VFS_SUPPORT_IO 1 +#define CONFIG_VFS_SUPPORT_DIR 1 +#define CONFIG_VFS_SUPPORT_SELECT 1 +#define CONFIG_VFS_SUPPRESS_SELECT_DEBUG_OUTPUT 1 +#define CONFIG_VFS_SUPPORT_TERMIOS 1 +#define CONFIG_VFS_MAX_COUNT 8 +#define CONFIG_VFS_SEMIHOSTFS_MAX_MOUNT_POINTS 1 +#define CONFIG_VFS_INITIALIZE_DEV_NULL 1 +#define CONFIG_WL_SECTOR_SIZE_4096 1 +#define CONFIG_WL_SECTOR_SIZE 4096 +#define CONFIG_WIFI_PROV_SCAN_MAX_ENTRIES 16 +#define CONFIG_WIFI_PROV_AUTOSTOP_TIMEOUT 30 +#define CONFIG_WIFI_PROV_BLE_SEC_CONN 1 +#define CONFIG_WIFI_PROV_STA_ALL_CHANNEL_SCAN 1 +#define CONFIG_IO_GLITCH_FILTER_TIME_MS 50 +#define CONFIG_WS2812_LED_ENABLE 1 +#define CONFIG_WS2812_LED_GPIO 8 +#define CONFIG_SERIAL_FLASHER_MD5_ENABLED 1 +#define CONFIG_SERIAL_FLASHER_INTERFACE_UART 1 +#define CONFIG_SERIAL_FLASHER_RESET_HOLD_TIME_MS 100 +#define CONFIG_SERIAL_FLASHER_BOOT_HOLD_TIME_MS 50 +#define CONFIG_SERIAL_FLASHER_WRITE_BLOCK_RETRIES 3 +#define CONFIG_DIAG_DATA_STORE_RTC 1 +#define CONFIG_DIAG_DATA_STORE_REPORTING_WATERMARK_PERCENT 80 +#define CONFIG_RTC_STORE_DATA_SIZE 6144 +#define CONFIG_RTC_STORE_CRITICAL_DATA_SIZE 4096 +#define CONFIG_DIAG_LOG_MSG_ARG_FORMAT_TLV 1 +#define CONFIG_DIAG_LOG_MSG_ARG_MAX_SIZE 64 +#define CONFIG_DIAG_LOG_DROP_WIFI_LOGS 1 +#define CONFIG_DIAG_ENABLE_METRICS 1 +#define CONFIG_DIAG_METRICS_MAX_COUNT 20 +#define CONFIG_DIAG_ENABLE_HEAP_METRICS 1 +#define CONFIG_DIAG_HEAP_POLLING_INTERVAL 30 +#define CONFIG_DIAG_ENABLE_WIFI_METRICS 1 +#define CONFIG_DIAG_WIFI_POLLING_INTERVAL 30 +#define CONFIG_DIAG_ENABLE_VARIABLES 1 +#define CONFIG_DIAG_VARIABLES_MAX_COUNT 20 +#define CONFIG_DIAG_ENABLE_NETWORK_VARIABLES 1 +#define CONFIG_ESP_INSIGHTS_TRANSPORT_MQTT 1 +#define CONFIG_ESP_INSIGHTS_CLOUD_POST_MIN_INTERVAL_SEC 60 +#define CONFIG_ESP_INSIGHTS_CLOUD_POST_MAX_INTERVAL_SEC 240 +#define CONFIG_ESP_INSIGHTS_META_VERSION_10 1 +#define CONFIG_ESP_SECURE_CERT_DS_PERIPHERAL 1 +#define CONFIG_MDNS_MAX_INTERFACES 3 +#define CONFIG_MDNS_MAX_SERVICES 10 +#define CONFIG_MDNS_TASK_PRIORITY 1 +#define CONFIG_MDNS_ACTION_QUEUE_LEN 16 +#define CONFIG_MDNS_TASK_STACK_SIZE 4096 +#define CONFIG_MDNS_TASK_AFFINITY_CPU0 1 +#define CONFIG_MDNS_TASK_AFFINITY 0x0 +#define CONFIG_MDNS_TASK_CREATE_FROM_INTERNAL 1 +#define CONFIG_MDNS_MEMORY_ALLOC_INTERNAL 1 +#define CONFIG_MDNS_SERVICE_ADD_TIMEOUT_MS 2000 +#define CONFIG_MDNS_TIMER_PERIOD_MS 100 +#define CONFIG_MDNS_ENABLE_CONSOLE_CLI 1 +#define CONFIG_MDNS_MULTIPLE_INSTANCE 1 +#define CONFIG_MDNS_PREDEF_NETIF_STA 1 +#define CONFIG_MDNS_PREDEF_NETIF_AP 1 +#define CONFIG_MDNS_PREDEF_NETIF_ETH 1 +#define CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI 1 +#define CONFIG_NETWORK_PROV_SCAN_MAX_ENTRIES 16 +#define CONFIG_NETWORK_PROV_AUTOSTOP_TIMEOUT 30 +#define CONFIG_NETWORK_PROV_BLE_SEC_CONN 1 +#define CONFIG_NETWORK_PROV_WIFI_STA_ALL_CHANNEL_SCAN 1 +#define CONFIG_ESP_RMAKER_LIB_ESP_MQTT 1 +#define CONFIG_ESP_RMAKER_MQTT_GLUE_LIB 1 +#define CONFIG_ESP_RMAKER_MQTT_PORT_443 1 +#define CONFIG_ESP_RMAKER_MQTT_PORT 1 +#define CONFIG_ESP_RMAKER_MQTT_SEND_USERNAME 1 +#define CONFIG_ESP_RMAKER_MQTT_PRODUCT_NAME "RMDev" +#define CONFIG_ESP_RMAKER_MQTT_PRODUCT_VERSION "1x0" +#define CONFIG_ESP_RMAKER_MQTT_PRODUCT_SKU "EX00" +#define CONFIG_ESP_RMAKER_MQTT_USE_CERT_BUNDLE 1 +#define CONFIG_ESP_RMAKER_MAX_MQTT_SUBSCRIPTIONS 10 +#define CONFIG_ESP_RMAKER_MQTT_KEEP_ALIVE_INTERVAL 120 +#define CONFIG_ESP_RMAKER_NETWORK_OVER_WIFI 1 +#define CONFIG_ESP_RMAKER_WORK_QUEUE_TASK_STACK 5120 +#define CONFIG_ESP_RMAKER_WORK_QUEUE_TASK_PRIORITY 5 +#define CONFIG_ESP_RMAKER_FACTORY_PARTITION_NAME "fctry" +#define CONFIG_ESP_RMAKER_FACTORY_NAMESPACE "rmaker_creds" +#define CONFIG_ESP_RMAKER_DEF_TIMEZONE "Asia/Shanghai" +#define CONFIG_ESP_RMAKER_SNTP_SERVER_NAME "pool.ntp.org" +#define CONFIG_ESP_RMAKER_MAX_COMMANDS 10 + +/* List of deprecated options */ +#define CONFIG_APP_ROLLBACK_ENABLE CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE +#define CONFIG_APP_WIFI_PROV_MAX_POP_MISMATCH CONFIG_APP_NETWORK_PROV_MAX_POP_MISMATCH +#define CONFIG_APP_WIFI_PROV_NAME_PREFIX CONFIG_APP_NETWORK_PROV_NAME_PREFIX +#define CONFIG_APP_WIFI_PROV_SHOW_QR CONFIG_APP_NETWORK_PROV_SHOW_QR +#define CONFIG_APP_WIFI_PROV_TIMEOUT_PERIOD CONFIG_APP_NETWORK_PROV_TIMEOUT_PERIOD +#define CONFIG_APP_WIFI_PROV_TRANSPORT CONFIG_APP_NETWORK_PROV_TRANSPORT +#define CONFIG_APP_WIFI_PROV_TRANSPORT_BLE CONFIG_APP_NETWORK_PROV_TRANSPORT_BLE +#define CONFIG_APP_WIFI_RESET_PROV_ON_FAILURE CONFIG_APP_NETWORK_RESET_PROV_ON_FAILURE +#define CONFIG_BROWNOUT_DET CONFIG_ESP_BROWNOUT_DET +#define CONFIG_BROWNOUT_DET_LVL CONFIG_ESP_BROWNOUT_DET_LVL +#define CONFIG_BROWNOUT_DET_LVL_SEL_7 CONFIG_ESP_BROWNOUT_DET_LVL_SEL_7 +#define CONFIG_BT_NIMBLE_ACL_BUF_COUNT CONFIG_BT_NIMBLE_TRANSPORT_ACL_FROM_LL_COUNT +#define CONFIG_BT_NIMBLE_ACL_BUF_SIZE CONFIG_BT_NIMBLE_TRANSPORT_ACL_SIZE +#define CONFIG_BT_NIMBLE_COEX_PHY_CODED_TX_RX_TLIM_DIS CONFIG_BT_CTRL_COEX_PHY_CODED_TX_RX_TLIM_DIS +#define CONFIG_BT_NIMBLE_HCI_EVT_BUF_SIZE CONFIG_BT_NIMBLE_TRANSPORT_EVT_SIZE +#define CONFIG_BT_NIMBLE_HCI_EVT_HI_BUF_COUNT CONFIG_BT_NIMBLE_TRANSPORT_EVT_COUNT +#define CONFIG_BT_NIMBLE_HCI_EVT_LO_BUF_COUNT CONFIG_BT_NIMBLE_TRANSPORT_EVT_DISCARD_COUNT +#define CONFIG_BT_NIMBLE_MSYS1_BLOCK_COUNT CONFIG_BT_NIMBLE_MSYS_1_BLOCK_COUNT +#define CONFIG_BT_NIMBLE_SM_SC_LVL CONFIG_BT_NIMBLE_SM_LVL +#define CONFIG_BT_NIMBLE_TASK_STACK_SIZE CONFIG_BT_NIMBLE_HOST_TASK_STACK_SIZE +#define CONFIG_COMPILER_OPTIMIZATION_DEFAULT CONFIG_COMPILER_OPTIMIZATION_DEBUG +#define CONFIG_COMPILER_OPTIMIZATION_LEVEL_DEBUG CONFIG_COMPILER_OPTIMIZATION_DEBUG +#define CONFIG_CONSOLE_UART CONFIG_ESP_CONSOLE_UART +#define CONFIG_CONSOLE_UART_BAUDRATE CONFIG_ESP_CONSOLE_UART_BAUDRATE +#define CONFIG_CONSOLE_UART_DEFAULT CONFIG_ESP_CONSOLE_UART_DEFAULT +#define CONFIG_CONSOLE_UART_NUM CONFIG_ESP_CONSOLE_UART_NUM +#define CONFIG_ESP32C3_BROWNOUT_DET CONFIG_ESP_BROWNOUT_DET +#define CONFIG_ESP32C3_BROWNOUT_DET_LVL CONFIG_ESP_BROWNOUT_DET_LVL +#define CONFIG_ESP32C3_BROWNOUT_DET_LVL_SEL_7 CONFIG_ESP_BROWNOUT_DET_LVL_SEL_7 +#define CONFIG_ESP32C3_DEBUG_OCDAWARE CONFIG_ESP_DEBUG_OCDAWARE +#define CONFIG_ESP32C3_DEFAULT_CPU_FREQ_160 CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_160 +#define CONFIG_ESP32C3_DEFAULT_CPU_FREQ_MHZ CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ +#define CONFIG_ESP32C3_LIGHTSLEEP_GPIO_RESET_WORKAROUND CONFIG_ESP_SLEEP_GPIO_RESET_WORKAROUND +#define CONFIG_ESP32C3_MEMPROT_FEATURE CONFIG_ESP_SYSTEM_MEMPROT_FEATURE +#define CONFIG_ESP32C3_MEMPROT_FEATURE_LOCK CONFIG_ESP_SYSTEM_MEMPROT_FEATURE_LOCK +#define CONFIG_ESP32C3_RTC_CLK_CAL_CYCLES CONFIG_RTC_CLK_CAL_CYCLES +#define CONFIG_ESP32C3_RTC_CLK_SRC_INT_RC CONFIG_RTC_CLK_SRC_INT_RC +#define CONFIG_ESP32C3_TIME_SYSCALL_USE_RTC_SYSTIMER CONFIG_NEWLIB_TIME_SYSCALL_USE_RTC_HRT +#define CONFIG_ESP32_APPTRACE_DEST_NONE CONFIG_APPTRACE_DEST_NONE +#define CONFIG_ESP32_APPTRACE_LOCK_ENABLE CONFIG_APPTRACE_LOCK_ENABLE +#define CONFIG_ESP32_ENABLE_COREDUMP_TO_NONE CONFIG_ESP_COREDUMP_ENABLE_TO_NONE +#define CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE CONFIG_ESP_PHY_CALIBRATION_AND_DATA_STORAGE +#define CONFIG_ESP32_PHY_MAX_TX_POWER CONFIG_ESP_PHY_MAX_TX_POWER +#define CONFIG_ESP32_PHY_MAX_WIFI_TX_POWER CONFIG_ESP_PHY_MAX_WIFI_TX_POWER +#define CONFIG_ESP32_PTHREAD_STACK_MIN CONFIG_PTHREAD_STACK_MIN +#define CONFIG_ESP32_PTHREAD_TASK_CORE_DEFAULT CONFIG_PTHREAD_TASK_CORE_DEFAULT +#define CONFIG_ESP32_PTHREAD_TASK_NAME_DEFAULT CONFIG_PTHREAD_TASK_NAME_DEFAULT +#define CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT CONFIG_PTHREAD_TASK_PRIO_DEFAULT +#define CONFIG_ESP32_PTHREAD_TASK_STACK_SIZE_DEFAULT CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT +#define CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED CONFIG_ESP_WIFI_AMPDU_RX_ENABLED +#define CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED CONFIG_ESP_WIFI_AMPDU_TX_ENABLED +#define CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM CONFIG_ESP_WIFI_DYNAMIC_RX_BUFFER_NUM +#define CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER CONFIG_ESP_WIFI_DYNAMIC_TX_BUFFER +#define CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM CONFIG_ESP_WIFI_DYNAMIC_TX_BUFFER_NUM +#define CONFIG_ESP32_WIFI_ENABLED CONFIG_ESP_WIFI_ENABLED +#define CONFIG_ESP32_WIFI_ENABLE_WPA3_OWE_STA CONFIG_ESP_WIFI_ENABLE_WPA3_OWE_STA +#define CONFIG_ESP32_WIFI_ENABLE_WPA3_SAE CONFIG_ESP_WIFI_ENABLE_WPA3_SAE +#define CONFIG_ESP32_WIFI_IRAM_OPT CONFIG_ESP_WIFI_IRAM_OPT +#define CONFIG_ESP32_WIFI_MGMT_SBUF_NUM CONFIG_ESP_WIFI_MGMT_SBUF_NUM +#define CONFIG_ESP32_WIFI_NVS_ENABLED CONFIG_ESP_WIFI_NVS_ENABLED +#define CONFIG_ESP32_WIFI_RX_BA_WIN CONFIG_ESP_WIFI_RX_BA_WIN +#define CONFIG_ESP32_WIFI_RX_IRAM_OPT CONFIG_ESP_WIFI_RX_IRAM_OPT +#define CONFIG_ESP32_WIFI_SOFTAP_BEACON_MAX_LEN CONFIG_ESP_WIFI_SOFTAP_BEACON_MAX_LEN +#define CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM CONFIG_ESP_WIFI_STATIC_RX_BUFFER_NUM +#define CONFIG_ESP32_WIFI_SW_COEXIST_ENABLE CONFIG_ESP_COEX_SW_COEXIST_ENABLE +#define CONFIG_ESP32_WIFI_TX_BA_WIN CONFIG_ESP_WIFI_TX_BA_WIN +#define CONFIG_ESP32_WIFI_TX_BUFFER_TYPE CONFIG_ESP_WIFI_TX_BUFFER_TYPE +#define CONFIG_ESP_GRATUITOUS_ARP CONFIG_LWIP_ESP_GRATUITOUS_ARP +#define CONFIG_ESP_RMAKER_LOCAL_CTRL_ENABLE CONFIG_ESP_RMAKER_LOCAL_CTRL_AUTO_ENABLE +#define CONFIG_ESP_SYSTEM_PM_POWER_DOWN_CPU CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP +#define CONFIG_ESP_TASK_WDT CONFIG_ESP_TASK_WDT_INIT +#define CONFIG_ESP_WIFI_SW_COEXIST_ENABLE CONFIG_ESP_COEX_SW_COEXIST_ENABLE +#define CONFIG_FLASHMODE_DIO CONFIG_ESPTOOLPY_FLASHMODE_DIO +#define CONFIG_GARP_TMR_INTERVAL CONFIG_LWIP_GARP_TMR_INTERVAL +#define CONFIG_GDBSTUB_MAX_TASKS CONFIG_ESP_GDBSTUB_MAX_TASKS +#define CONFIG_GDBSTUB_SUPPORT_TASKS CONFIG_ESP_GDBSTUB_SUPPORT_TASKS +#define CONFIG_INT_WDT CONFIG_ESP_INT_WDT +#define CONFIG_INT_WDT_TIMEOUT_MS CONFIG_ESP_INT_WDT_TIMEOUT_MS +#define CONFIG_IPC_TASK_STACK_SIZE CONFIG_ESP_IPC_TASK_STACK_SIZE +#define CONFIG_LOG_BOOTLOADER_LEVEL CONFIG_BOOTLOADER_LOG_LEVEL +#define CONFIG_LOG_BOOTLOADER_LEVEL_INFO CONFIG_BOOTLOADER_LOG_LEVEL_INFO +#define CONFIG_MAIN_TASK_STACK_SIZE CONFIG_ESP_MAIN_TASK_STACK_SIZE +#define CONFIG_MONITOR_BAUD CONFIG_ESPTOOLPY_MONITOR_BAUD +#define CONFIG_NIMBLE_ATT_PREFERRED_MTU CONFIG_BT_NIMBLE_ATT_PREFERRED_MTU +#define CONFIG_NIMBLE_CRYPTO_STACK_MBEDTLS CONFIG_BT_NIMBLE_CRYPTO_STACK_MBEDTLS +#define CONFIG_NIMBLE_ENABLED CONFIG_BT_NIMBLE_ENABLED +#define CONFIG_NIMBLE_GAP_DEVICE_NAME_MAX_LEN CONFIG_BT_NIMBLE_GAP_DEVICE_NAME_MAX_LEN +#define CONFIG_NIMBLE_L2CAP_COC_MAX_NUM CONFIG_BT_NIMBLE_L2CAP_COC_MAX_NUM +#define CONFIG_NIMBLE_MAX_BONDS CONFIG_BT_NIMBLE_MAX_BONDS +#define CONFIG_NIMBLE_MAX_CCCDS CONFIG_BT_NIMBLE_MAX_CCCDS +#define CONFIG_NIMBLE_MAX_CONNECTIONS CONFIG_BT_NIMBLE_MAX_CONNECTIONS +#define CONFIG_NIMBLE_MEM_ALLOC_MODE_INTERNAL CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_INTERNAL +#define CONFIG_NIMBLE_PINNED_TO_CORE CONFIG_BT_NIMBLE_PINNED_TO_CORE +#define CONFIG_NIMBLE_ROLE_BROADCASTER CONFIG_BT_NIMBLE_ROLE_BROADCASTER +#define CONFIG_NIMBLE_ROLE_CENTRAL CONFIG_BT_NIMBLE_ROLE_CENTRAL +#define CONFIG_NIMBLE_ROLE_OBSERVER CONFIG_BT_NIMBLE_ROLE_OBSERVER +#define CONFIG_NIMBLE_ROLE_PERIPHERAL CONFIG_BT_NIMBLE_ROLE_PERIPHERAL +#define CONFIG_NIMBLE_RPA_TIMEOUT CONFIG_BT_NIMBLE_RPA_TIMEOUT +#define CONFIG_NIMBLE_SM_LEGACY CONFIG_BT_NIMBLE_SM_LEGACY +#define CONFIG_NIMBLE_SM_SC CONFIG_BT_NIMBLE_SM_SC +#define CONFIG_NIMBLE_SVC_GAP_APPEARANCE CONFIG_BT_NIMBLE_SVC_GAP_APPEARANCE +#define CONFIG_NIMBLE_SVC_GAP_DEVICE_NAME CONFIG_BT_NIMBLE_SVC_GAP_DEVICE_NAME +#define CONFIG_NIMBLE_TASK_STACK_SIZE CONFIG_BT_NIMBLE_HOST_TASK_STACK_SIZE +#define CONFIG_OPTIMIZATION_ASSERTIONS_ENABLED CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE +#define CONFIG_OPTIMIZATION_ASSERTION_LEVEL CONFIG_COMPILER_OPTIMIZATION_ASSERTION_LEVEL +#define CONFIG_OPTIMIZATION_LEVEL_DEBUG CONFIG_COMPILER_OPTIMIZATION_DEBUG +#define CONFIG_POST_EVENTS_FROM_IRAM_ISR CONFIG_ESP_EVENT_POST_FROM_IRAM_ISR +#define CONFIG_POST_EVENTS_FROM_ISR CONFIG_ESP_EVENT_POST_FROM_ISR +#define CONFIG_SEMIHOSTFS_MAX_MOUNT_POINTS CONFIG_VFS_SEMIHOSTFS_MAX_MOUNT_POINTS +#define CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ABORTS CONFIG_SPI_FLASH_DANGEROUS_WRITE_ABORTS +#define CONFIG_STACK_CHECK_NONE CONFIG_COMPILER_STACK_CHECK_MODE_NONE +#define CONFIG_SUPPORT_TERMIOS CONFIG_VFS_SUPPORT_TERMIOS +#define CONFIG_SUPPRESS_SELECT_DEBUG_OUTPUT CONFIG_VFS_SUPPRESS_SELECT_DEBUG_OUTPUT +#define CONFIG_SW_COEXIST_ENABLE CONFIG_ESP_COEX_SW_COEXIST_ENABLE +#define CONFIG_SYSTEM_EVENT_QUEUE_SIZE CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE +#define CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE +#define CONFIG_TASK_WDT CONFIG_ESP_TASK_WDT_INIT +#define CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU0 CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0 +#define CONFIG_TASK_WDT_TIMEOUT_S CONFIG_ESP_TASK_WDT_TIMEOUT_S +#define CONFIG_TCPIP_RECVMBOX_SIZE CONFIG_LWIP_TCPIP_RECVMBOX_SIZE +#define CONFIG_TCPIP_TASK_AFFINITY CONFIG_LWIP_TCPIP_TASK_AFFINITY +#define CONFIG_TCPIP_TASK_AFFINITY_NO_AFFINITY CONFIG_LWIP_TCPIP_TASK_AFFINITY_NO_AFFINITY +#define CONFIG_TCPIP_TASK_STACK_SIZE CONFIG_LWIP_TCPIP_TASK_STACK_SIZE +#define CONFIG_TCP_MAXRTX CONFIG_LWIP_TCP_MAXRTX +#define CONFIG_TCP_MSL CONFIG_LWIP_TCP_MSL +#define CONFIG_TCP_MSS CONFIG_LWIP_TCP_MSS +#define CONFIG_TCP_OVERSIZE_MSS CONFIG_LWIP_TCP_OVERSIZE_MSS +#define CONFIG_TCP_QUEUE_OOSEQ CONFIG_LWIP_TCP_QUEUE_OOSEQ +#define CONFIG_TCP_RECVMBOX_SIZE CONFIG_LWIP_TCP_RECVMBOX_SIZE +#define CONFIG_TCP_SND_BUF_DEFAULT CONFIG_LWIP_TCP_SND_BUF_DEFAULT +#define CONFIG_TCP_SYNMAXRTX CONFIG_LWIP_TCP_SYNMAXRTX +#define CONFIG_TCP_WND_DEFAULT CONFIG_LWIP_TCP_WND_DEFAULT +#define CONFIG_TIMER_QUEUE_LENGTH CONFIG_FREERTOS_TIMER_QUEUE_LENGTH +#define CONFIG_TIMER_TASK_PRIORITY CONFIG_FREERTOS_TIMER_TASK_PRIORITY +#define CONFIG_TIMER_TASK_STACK_DEPTH CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH +#define CONFIG_TIMER_TASK_STACK_SIZE CONFIG_ESP_TIMER_TASK_STACK_SIZE +#define CONFIG_UDP_RECVMBOX_SIZE CONFIG_LWIP_UDP_RECVMBOX_SIZE +#define CONFIG_WPA_MBEDTLS_CRYPTO CONFIG_ESP_WIFI_MBEDTLS_CRYPTO +#define CONFIG_WPA_MBEDTLS_TLS_CLIENT CONFIG_ESP_WIFI_MBEDTLS_TLS_CLIENT diff --git a/RainMaker_Table-Lights/build/config/sdkconfig.json b/RainMaker_Table-Lights/build/config/sdkconfig.json new file mode 100644 index 000000000..ec494398c --- /dev/null +++ b/RainMaker_Table-Lights/build/config/sdkconfig.json @@ -0,0 +1,1564 @@ +{ + "ADC_CALI_SUPPRESS_DEPRECATE_WARN": false, + "ADC_CONTINUOUS_FORCE_USE_ADC2_ON_C3_S3": false, + "ADC_CONTINUOUS_ISR_IRAM_SAFE": false, + "ADC_ENABLE_DEBUG_LOG": false, + "ADC_ONESHOT_CTRL_FUNC_IN_IRAM": false, + "ADC_ONESHOT_FORCE_USE_ADC2_ON_C3": false, + "ADC_SKIP_LEGACY_CONFLICT_CHECK": false, + "ADC_SUPPRESS_DEPRECATE_WARN": false, + "APPTRACE_DEST_JTAG": false, + "APPTRACE_DEST_NONE": true, + "APPTRACE_DEST_UART1": false, + "APPTRACE_DEST_UART_NONE": true, + "APPTRACE_DEST_USB_CDC": false, + "APPTRACE_LOCK_ENABLE": true, + "APPTRACE_UART_TASK_PRIO": 1, + "APP_BUILD_BOOTLOADER": true, + "APP_BUILD_GENERATE_BINARIES": true, + "APP_BUILD_TYPE_APP_2NDBOOT": true, + "APP_BUILD_TYPE_RAM": false, + "APP_BUILD_USE_FLASH_SECTIONS": true, + "APP_COMPILE_TIME_DATE": true, + "APP_EXCLUDE_PROJECT_NAME_VAR": false, + "APP_EXCLUDE_PROJECT_VER_VAR": false, + "APP_NETWORK_PROV_MAX_POP_MISMATCH": 5, + "APP_NETWORK_PROV_MAX_RETRY_CNT": 5, + "APP_NETWORK_PROV_NAME_PREFIX": "PROV", + "APP_NETWORK_PROV_SHOW_QR": true, + "APP_NETWORK_PROV_TIMEOUT_PERIOD": 30, + "APP_NETWORK_PROV_TRANSPORT": 2, + "APP_NETWORK_PROV_TRANSPORT_BLE": true, + "APP_NETWORK_PROV_TRANSPORT_SOFTAP": false, + "APP_NETWORK_RESET_PROV_ON_FAILURE": true, + "APP_NETWORK_SHOW_DEMO_INTRO_TEXT": false, + "APP_NO_BLOBS": false, + "APP_PROJECT_VER_FROM_CONFIG": false, + "APP_REPRODUCIBLE_BUILD": false, + "APP_RETRIEVE_LEN_ELF_SHA": 9, + "APP_WIFI_PROV_COMPAT": true, + "AUTO_UPDATE_RCP": false, + "BLE_MESH": false, + "BOOTLOADER_APP_ANTI_ROLLBACK": false, + "BOOTLOADER_APP_ROLLBACK_ENABLE": true, + "BOOTLOADER_APP_TEST": false, + "BOOTLOADER_COMPILER_OPTIMIZATION_DEBUG": false, + "BOOTLOADER_COMPILER_OPTIMIZATION_NONE": false, + "BOOTLOADER_COMPILER_OPTIMIZATION_PERF": false, + "BOOTLOADER_COMPILER_OPTIMIZATION_SIZE": true, + "BOOTLOADER_COMPILE_TIME_DATE": true, + "BOOTLOADER_CUSTOM_RESERVE_RTC": false, + "BOOTLOADER_FACTORY_RESET": false, + "BOOTLOADER_FLASH_DC_AWARE": false, + "BOOTLOADER_FLASH_XMC_SUPPORT": true, + "BOOTLOADER_LOG_COLORS": false, + "BOOTLOADER_LOG_LEVEL": 3, + "BOOTLOADER_LOG_LEVEL_DEBUG": false, + "BOOTLOADER_LOG_LEVEL_ERROR": false, + "BOOTLOADER_LOG_LEVEL_INFO": true, + "BOOTLOADER_LOG_LEVEL_NONE": false, + "BOOTLOADER_LOG_LEVEL_VERBOSE": false, + "BOOTLOADER_LOG_LEVEL_WARN": false, + "BOOTLOADER_LOG_TIMESTAMP_SOURCE_CPU_TICKS": true, + "BOOTLOADER_OFFSET_IN_FLASH": 0, + "BOOTLOADER_PROJECT_VER": 1, + "BOOTLOADER_REGION_PROTECTION_ENABLE": true, + "BOOTLOADER_RESERVE_RTC_SIZE": 0, + "BOOTLOADER_SKIP_VALIDATE_ALWAYS": false, + "BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP": false, + "BOOTLOADER_SKIP_VALIDATE_ON_POWER_ON": false, + "BOOTLOADER_WDT_DISABLE_IN_USER_CODE": false, + "BOOTLOADER_WDT_ENABLE": true, + "BOOTLOADER_WDT_TIME_MS": 9000, + "BOOT_ROM_LOG_ALWAYS_OFF": false, + "BOOT_ROM_LOG_ALWAYS_ON": true, + "BOOT_ROM_LOG_ON_GPIO_HIGH": false, + "BOOT_ROM_LOG_ON_GPIO_LOW": false, + "BT_ALARM_MAX_NUM": 50, + "BT_BLE_ADV_DATA_LENGTH_ZERO_AUX": false, + "BT_BLE_CCA_MODE": 0, + "BT_BLE_CCA_MODE_HW": false, + "BT_BLE_CCA_MODE_NONE": true, + "BT_BLE_CCA_MODE_SW": false, + "BT_BLE_LOG_SPI_OUT_ENABLED": false, + "BT_BLUEDROID_ENABLED": false, + "BT_CONTROLLER_DISABLED": false, + "BT_CONTROLLER_ENABLED": true, + "BT_CONTROLLER_ONLY": false, + "BT_CTRL_ADV_DUP_FILT_MAX": 30, + "BT_CTRL_AGC_RECORRECT_EN": false, + "BT_CTRL_BLE_ADV_REPORT_DISCARD_THRSHOLD": 20, + "BT_CTRL_BLE_ADV_REPORT_FLOW_CTRL_NUM": 100, + "BT_CTRL_BLE_ADV_REPORT_FLOW_CTRL_SUPP": true, + "BT_CTRL_BLE_LLCP_CHAN_MAP_UPDATE": false, + "BT_CTRL_BLE_LLCP_CONN_UPDATE": false, + "BT_CTRL_BLE_LLCP_PHY_UPDATE": false, + "BT_CTRL_BLE_MAX_ACT": 6, + "BT_CTRL_BLE_MAX_ACT_EFF": 6, + "BT_CTRL_BLE_MESH_SCAN_DUPL_EN": false, + "BT_CTRL_BLE_SCAN_DUPL": true, + "BT_CTRL_BLE_STATIC_ACL_TX_BUF_NB": 0, + "BT_CTRL_CE_LENGTH_TYPE_CE": false, + "BT_CTRL_CE_LENGTH_TYPE_EFF": 0, + "BT_CTRL_CE_LENGTH_TYPE_ORIG": true, + "BT_CTRL_CE_LENGTH_TYPE_SD": false, + "BT_CTRL_CHAN_ASS_EN": true, + "BT_CTRL_CHECK_CONNECT_IND_ACCESS_ADDRESS": false, + "BT_CTRL_COEX_PHY_CODED_TX_RX_TLIM_DIS": true, + "BT_CTRL_COEX_PHY_CODED_TX_RX_TLIM_EFF": 0, + "BT_CTRL_COEX_PHY_CODED_TX_RX_TLIM_EN": false, + "BT_CTRL_DFT_TX_POWER_LEVEL_EFF": 11, + "BT_CTRL_DFT_TX_POWER_LEVEL_N0": false, + "BT_CTRL_DFT_TX_POWER_LEVEL_N12": false, + "BT_CTRL_DFT_TX_POWER_LEVEL_N15": false, + "BT_CTRL_DFT_TX_POWER_LEVEL_N18": false, + "BT_CTRL_DFT_TX_POWER_LEVEL_N21": false, + "BT_CTRL_DFT_TX_POWER_LEVEL_N24": false, + "BT_CTRL_DFT_TX_POWER_LEVEL_N3": false, + "BT_CTRL_DFT_TX_POWER_LEVEL_N6": false, + "BT_CTRL_DFT_TX_POWER_LEVEL_N9": false, + "BT_CTRL_DFT_TX_POWER_LEVEL_P12": false, + "BT_CTRL_DFT_TX_POWER_LEVEL_P15": false, + "BT_CTRL_DFT_TX_POWER_LEVEL_P18": false, + "BT_CTRL_DFT_TX_POWER_LEVEL_P20": false, + "BT_CTRL_DFT_TX_POWER_LEVEL_P3": false, + "BT_CTRL_DFT_TX_POWER_LEVEL_P6": false, + "BT_CTRL_DFT_TX_POWER_LEVEL_P9": true, + "BT_CTRL_DUPL_SCAN_CACHE_REFRESH_PERIOD": 0, + "BT_CTRL_HCI_MODE_UART_H4": false, + "BT_CTRL_HCI_MODE_VHCI": true, + "BT_CTRL_HCI_TL": 1, + "BT_CTRL_HCI_TL_EFF": 1, + "BT_CTRL_HW_CCA_EFF": 0, + "BT_CTRL_HW_CCA_VAL": 20, + "BT_CTRL_LE_PING_EN": true, + "BT_CTRL_MODEM_SLEEP": false, + "BT_CTRL_MODE_EFF": 1, + "BT_CTRL_PINNED_TO_CORE": 0, + "BT_CTRL_RUN_IN_FLASH_ONLY": false, + "BT_CTRL_RX_ANTENNA_INDEX_0": true, + "BT_CTRL_RX_ANTENNA_INDEX_1": false, + "BT_CTRL_RX_ANTENNA_INDEX_EFF": 0, + "BT_CTRL_SCAN_BACKOFF_UPPERLIMITMAX": false, + "BT_CTRL_SCAN_DUPL_CACHE_SIZE": 100, + "BT_CTRL_SCAN_DUPL_TYPE": 0, + "BT_CTRL_SCAN_DUPL_TYPE_DATA": false, + "BT_CTRL_SCAN_DUPL_TYPE_DATA_DEVICE": false, + "BT_CTRL_SCAN_DUPL_TYPE_DEVICE": true, + "BT_CTRL_SLEEP_CLOCK_EFF": 0, + "BT_CTRL_SLEEP_MODE_EFF": 0, + "BT_CTRL_TX_ANTENNA_INDEX_0": true, + "BT_CTRL_TX_ANTENNA_INDEX_1": false, + "BT_CTRL_TX_ANTENNA_INDEX_EFF": 0, + "BT_ENABLED": true, + "BT_HCI_LOG_DEBUG_EN": false, + "BT_NIMBLE_50_FEATURE_SUPPORT": true, + "BT_NIMBLE_ATT_PREFERRED_MTU": 256, + "BT_NIMBLE_BLE_GATT_BLOB_TRANSFER": false, + "BT_NIMBLE_BLUFI_ENABLE": false, + "BT_NIMBLE_CRYPTO_STACK_MBEDTLS": true, + "BT_NIMBLE_DEBUG": false, + "BT_NIMBLE_DYNAMIC_SERVICE": false, + "BT_NIMBLE_EATT_CHAN_NUM": 0, + "BT_NIMBLE_ENABLED": true, + "BT_NIMBLE_ENABLE_CONN_REATTEMPT": true, + "BT_NIMBLE_ENABLE_PERIODIC_SYNC": true, + "BT_NIMBLE_ENC_ADV_DATA": false, + "BT_NIMBLE_EXT_ADV": false, + "BT_NIMBLE_EXT_SCAN": true, + "BT_NIMBLE_GAP_DEVICE_NAME_MAX_LEN": 31, + "BT_NIMBLE_GATTC_PROC_PREEMPTION_PROTECT": false, + "BT_NIMBLE_GATT_CACHING": false, + "BT_NIMBLE_GATT_MAX_PROCS": 4, + "BT_NIMBLE_HCI_UART_CTS_PIN": 23, + "BT_NIMBLE_HCI_UART_FLOW_CTRL": 0, + "BT_NIMBLE_HCI_UART_RTS_PIN": 19, + "BT_NIMBLE_HID_SERVICE": false, + "BT_NIMBLE_HIGH_DUTY_ADV_ITVL": false, + "BT_NIMBLE_HOST_ALLOW_CONNECT_WITH_SCAN": false, + "BT_NIMBLE_HOST_QUEUE_CONG_CHECK": false, + "BT_NIMBLE_HOST_TASK_STACK_SIZE": 4096, + "BT_NIMBLE_HS_FLOW_CTRL": false, + "BT_NIMBLE_HS_STOP_TIMEOUT_MS": 2000, + "BT_NIMBLE_L2CAP_COC_MAX_NUM": 0, + "BT_NIMBLE_L2CAP_COC_SDU_BUFF_COUNT": 1, + "BT_NIMBLE_LEGACY_VHCI_ENABLE": true, + "BT_NIMBLE_LL_CFG_FEAT_LE_2M_PHY": true, + "BT_NIMBLE_LL_CFG_FEAT_LE_CODED_PHY": true, + "BT_NIMBLE_LL_CFG_FEAT_LE_ENCRYPTION": true, + "BT_NIMBLE_LOG_LEVEL": 1, + "BT_NIMBLE_LOG_LEVEL_DEBUG": false, + "BT_NIMBLE_LOG_LEVEL_ERROR": false, + "BT_NIMBLE_LOG_LEVEL_INFO": true, + "BT_NIMBLE_LOG_LEVEL_NONE": false, + "BT_NIMBLE_LOG_LEVEL_WARNING": false, + "BT_NIMBLE_MAX_BONDS": 3, + "BT_NIMBLE_MAX_CCCDS": 8, + "BT_NIMBLE_MAX_CONNECTIONS": 3, + "BT_NIMBLE_MAX_CONN_REATTEMPT": 3, + "BT_NIMBLE_MAX_PERIODIC_SYNCS": 0, + "BT_NIMBLE_MEM_ALLOC_MODE_DEFAULT": false, + "BT_NIMBLE_MEM_ALLOC_MODE_INTERNAL": true, + "BT_NIMBLE_MESH": false, + "BT_NIMBLE_MSYS_1_BLOCK_COUNT": 12, + "BT_NIMBLE_MSYS_1_BLOCK_SIZE": 256, + "BT_NIMBLE_MSYS_2_BLOCK_COUNT": 24, + "BT_NIMBLE_MSYS_2_BLOCK_SIZE": 320, + "BT_NIMBLE_NVS_PERSIST": false, + "BT_NIMBLE_PINNED_TO_CORE": 0, + "BT_NIMBLE_ROLE_BROADCASTER": true, + "BT_NIMBLE_ROLE_CENTRAL": true, + "BT_NIMBLE_ROLE_OBSERVER": true, + "BT_NIMBLE_ROLE_PERIPHERAL": true, + "BT_NIMBLE_RPA_TIMEOUT": 900, + "BT_NIMBLE_SECURITY_ENABLE": true, + "BT_NIMBLE_SMP_ID_RESET": false, + "BT_NIMBLE_SM_LEGACY": true, + "BT_NIMBLE_SM_LVL": 0, + "BT_NIMBLE_SM_SC": true, + "BT_NIMBLE_SM_SC_DEBUG_KEYS": false, + "BT_NIMBLE_SM_SC_ONLY": 0, + "BT_NIMBLE_SUBRATE": false, + "BT_NIMBLE_SVC_BAS_BATTERY_LEVEL_NOTIFY": false, + "BT_NIMBLE_SVC_DIS_FIRMWARE_REVISION": false, + "BT_NIMBLE_SVC_DIS_HARDWARE_REVISION": false, + "BT_NIMBLE_SVC_DIS_INCLUDED": false, + "BT_NIMBLE_SVC_DIS_MANUFACTURER_NAME": false, + "BT_NIMBLE_SVC_DIS_PNP_ID": false, + "BT_NIMBLE_SVC_DIS_SERIAL_NUMBER": false, + "BT_NIMBLE_SVC_DIS_SOFTWARE_REVISION": false, + "BT_NIMBLE_SVC_DIS_SYSTEM_ID": false, + "BT_NIMBLE_SVC_GAP_APPEARANCE": 0, + "BT_NIMBLE_SVC_GAP_APPEAR_WRITE": false, + "BT_NIMBLE_SVC_GAP_APPEAR_WRITE_PERM": 0, + "BT_NIMBLE_SVC_GAP_APPEAR_WRITE_PERM_ATHN": 0, + "BT_NIMBLE_SVC_GAP_APPEAR_WRITE_PERM_ATHR": 0, + "BT_NIMBLE_SVC_GAP_APPEAR_WRITE_PERM_ENC": 0, + "BT_NIMBLE_SVC_GAP_CAR_CHAR_NOT_SUPP": true, + "BT_NIMBLE_SVC_GAP_CAR_NOT_SUPP": false, + "BT_NIMBLE_SVC_GAP_CAR_SUPP": false, + "BT_NIMBLE_SVC_GAP_CENT_ADDR_RESOLUTION": -1, + "BT_NIMBLE_SVC_GAP_DEVICE_NAME": "nimble", + "BT_NIMBLE_SVC_GAP_GATT_SECURITY_LEVEL": false, + "BT_NIMBLE_SVC_GAP_NAME_WRITE": false, + "BT_NIMBLE_SVC_GAP_NAME_WRITE_PERM": 0, + "BT_NIMBLE_SVC_GAP_NAME_WRITE_PERM_AUTHEN": 0, + "BT_NIMBLE_SVC_GAP_NAME_WRITE_PERM_AUTHOR": 0, + "BT_NIMBLE_SVC_GAP_NAME_WRITE_PERM_ENC": 0, + "BT_NIMBLE_SVC_GAP_PPCP_MAX_CONN_INTERVAL": 0, + "BT_NIMBLE_SVC_GAP_PPCP_MIN_CONN_INTERVAL": 0, + "BT_NIMBLE_SVC_GAP_PPCP_SLAVE_LATENCY": 0, + "BT_NIMBLE_SVC_GAP_PPCP_SUPERVISION_TMO": 0, + "BT_NIMBLE_TEST_THROUGHPUT_TEST": false, + "BT_NIMBLE_TRANSPORT_ACL_FROM_LL_COUNT": 24, + "BT_NIMBLE_TRANSPORT_ACL_SIZE": 255, + "BT_NIMBLE_TRANSPORT_EVT_COUNT": 30, + "BT_NIMBLE_TRANSPORT_EVT_DISCARD_COUNT": 8, + "BT_NIMBLE_TRANSPORT_EVT_SIZE": 70, + "BT_NIMBLE_USE_ESP_TIMER": true, + "BT_NIMBLE_VS_SUPPORT": false, + "BT_NIMBLE_WHITELIST_SIZE": 12, + "COMPILER_ASSERT_NDEBUG_EVALUATE": true, + "COMPILER_CXX_EXCEPTIONS": false, + "COMPILER_CXX_RTTI": false, + "COMPILER_DISABLE_DEFAULT_ERRORS": true, + "COMPILER_DISABLE_GCC12_WARNINGS": false, + "COMPILER_DISABLE_GCC13_WARNINGS": false, + "COMPILER_DISABLE_GCC14_WARNINGS": false, + "COMPILER_DUMP_RTL_FILES": false, + "COMPILER_FLOAT_LIB_FROM_GCCLIB": true, + "COMPILER_HIDE_PATHS_MACROS": true, + "COMPILER_NO_MERGE_CONSTANTS": false, + "COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE": false, + "COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE": true, + "COMPILER_OPTIMIZATION_ASSERTIONS_SILENT": false, + "COMPILER_OPTIMIZATION_ASSERTION_LEVEL": 2, + "COMPILER_OPTIMIZATION_CHECKS_SILENT": false, + "COMPILER_OPTIMIZATION_DEBUG": true, + "COMPILER_OPTIMIZATION_NONE": false, + "COMPILER_OPTIMIZATION_PERF": false, + "COMPILER_OPTIMIZATION_SIZE": false, + "COMPILER_ORPHAN_SECTIONS_PLACE": false, + "COMPILER_ORPHAN_SECTIONS_WARNING": true, + "COMPILER_RT_LIB_GCCLIB": true, + "COMPILER_RT_LIB_NAME": "gcc", + "COMPILER_SAVE_RESTORE_LIBCALLS": false, + "COMPILER_STACK_CHECK_MODE_ALL": false, + "COMPILER_STACK_CHECK_MODE_NONE": true, + "COMPILER_STACK_CHECK_MODE_NORM": false, + "COMPILER_STACK_CHECK_MODE_STRONG": false, + "COMPILER_STATIC_ANALYZER": false, + "COMPILER_WARN_WRITE_STRINGS": false, + "CONSOLE_SORTED_HELP": false, + "CREATE_OTA_IMAGE_WITH_RCP_FW": false, + "DIAG_DATA_STORE_DBG_PRINTS": false, + "DIAG_DATA_STORE_FLASH": false, + "DIAG_DATA_STORE_REPORTING_WATERMARK_PERCENT": 80, + "DIAG_DATA_STORE_RTC": true, + "DIAG_ENABLE_HEAP_METRICS": true, + "DIAG_ENABLE_METRICS": true, + "DIAG_ENABLE_NETWORK_VARIABLES": true, + "DIAG_ENABLE_VARIABLES": true, + "DIAG_ENABLE_WIFI_METRICS": true, + "DIAG_ENABLE_WRAP_LOG_FUNCTIONS": false, + "DIAG_HEAP_POLLING_INTERVAL": 30, + "DIAG_LOG_DROP_WIFI_LOGS": true, + "DIAG_LOG_MSG_ARG_FORMAT_STRING": false, + "DIAG_LOG_MSG_ARG_FORMAT_TLV": true, + "DIAG_LOG_MSG_ARG_MAX_SIZE": 64, + "DIAG_METRICS_MAX_COUNT": 20, + "DIAG_MORE_NETWORK_VARS": false, + "DIAG_USE_EXTERNAL_LOG_WRAP": false, + "DIAG_VARIABLES_MAX_COUNT": 20, + "DIAG_WIFI_POLLING_INTERVAL": 30, + "EFUSE_CUSTOM_TABLE": false, + "EFUSE_MAX_BLK_LEN": 256, + "EFUSE_VIRTUAL": false, + "ESP32C3_REV_MAX_FULL": 199, + "ESP32C3_REV_MIN_0": false, + "ESP32C3_REV_MIN_1": false, + "ESP32C3_REV_MIN_101": false, + "ESP32C3_REV_MIN_2": false, + "ESP32C3_REV_MIN_3": true, + "ESP32C3_REV_MIN_4": false, + "ESP32C3_REV_MIN_FULL": 3, + "ESP32C3_UNIVERSAL_MAC_ADDRESSES": 4, + "ESP32C3_UNIVERSAL_MAC_ADDRESSES_FOUR": true, + "ESP32C3_UNIVERSAL_MAC_ADDRESSES_TWO": false, + "ESPHID_TASK_SIZE_BLE": 4096, + "ESPHID_TASK_SIZE_BT": 2048, + "ESPTOOLPY_AFTER": "hard_reset", + "ESPTOOLPY_AFTER_NORESET": false, + "ESPTOOLPY_AFTER_RESET": true, + "ESPTOOLPY_BEFORE": "default_reset", + "ESPTOOLPY_BEFORE_NORESET": false, + "ESPTOOLPY_BEFORE_RESET": true, + "ESPTOOLPY_FLASHFREQ": "80m", + "ESPTOOLPY_FLASHFREQ_20M": false, + "ESPTOOLPY_FLASHFREQ_26M": false, + "ESPTOOLPY_FLASHFREQ_40M": false, + "ESPTOOLPY_FLASHFREQ_80M": true, + "ESPTOOLPY_FLASHMODE": "dio", + "ESPTOOLPY_FLASHMODE_DIO": true, + "ESPTOOLPY_FLASHMODE_DOUT": false, + "ESPTOOLPY_FLASHMODE_QIO": false, + "ESPTOOLPY_FLASHMODE_QOUT": false, + "ESPTOOLPY_FLASHSIZE": "4MB", + "ESPTOOLPY_FLASHSIZE_128MB": false, + "ESPTOOLPY_FLASHSIZE_16MB": false, + "ESPTOOLPY_FLASHSIZE_1MB": false, + "ESPTOOLPY_FLASHSIZE_2MB": false, + "ESPTOOLPY_FLASHSIZE_32MB": false, + "ESPTOOLPY_FLASHSIZE_4MB": true, + "ESPTOOLPY_FLASHSIZE_64MB": false, + "ESPTOOLPY_FLASHSIZE_8MB": false, + "ESPTOOLPY_FLASH_SAMPLE_MODE_STR": true, + "ESPTOOLPY_HEADER_FLASHSIZE_UPDATE": false, + "ESPTOOLPY_MONITOR_BAUD": 115200, + "ESPTOOLPY_NO_STUB": false, + "ESP_BROWNOUT_DET": true, + "ESP_BROWNOUT_DET_LVL": 7, + "ESP_BROWNOUT_DET_LVL_SEL_2": false, + "ESP_BROWNOUT_DET_LVL_SEL_3": false, + "ESP_BROWNOUT_DET_LVL_SEL_4": false, + "ESP_BROWNOUT_DET_LVL_SEL_5": false, + "ESP_BROWNOUT_DET_LVL_SEL_6": false, + "ESP_BROWNOUT_DET_LVL_SEL_7": true, + "ESP_COEX_ENABLED": true, + "ESP_COEX_GPIO_DEBUG": false, + "ESP_COEX_POWER_MANAGEMENT": false, + "ESP_COEX_SW_COEXIST_ENABLE": true, + "ESP_CONSOLE_NONE": false, + "ESP_CONSOLE_ROM_SERIAL_PORT_NUM": 0, + "ESP_CONSOLE_SECONDARY_NONE": false, + "ESP_CONSOLE_SECONDARY_USB_SERIAL_JTAG": true, + "ESP_CONSOLE_UART": true, + "ESP_CONSOLE_UART_BAUDRATE": 115200, + "ESP_CONSOLE_UART_CUSTOM": false, + "ESP_CONSOLE_UART_DEFAULT": true, + "ESP_CONSOLE_UART_NUM": 0, + "ESP_CONSOLE_USB_SERIAL_JTAG": false, + "ESP_CONSOLE_USB_SERIAL_JTAG_ENABLED": true, + "ESP_COREDUMP_ENABLE_TO_FLASH": false, + "ESP_COREDUMP_ENABLE_TO_NONE": true, + "ESP_COREDUMP_ENABLE_TO_UART": false, + "ESP_DEBUG_OCDAWARE": true, + "ESP_DEBUG_STUBS_ENABLE": false, + "ESP_DEFAULT_CPU_FREQ_MHZ": 160, + "ESP_DEFAULT_CPU_FREQ_MHZ_160": true, + "ESP_DEFAULT_CPU_FREQ_MHZ_80": false, + "ESP_EFUSE_BLOCK_REV_MAX_FULL": 199, + "ESP_EFUSE_BLOCK_REV_MIN_FULL": 0, + "ESP_ERR_TO_NAME_LOOKUP": true, + "ESP_EVENT_LOOP_PROFILING": false, + "ESP_EVENT_POST_FROM_IRAM_ISR": true, + "ESP_EVENT_POST_FROM_ISR": true, + "ESP_GDBSTUB_ENABLED": true, + "ESP_GDBSTUB_MAX_TASKS": 32, + "ESP_GDBSTUB_SUPPORT_TASKS": true, + "ESP_HTTPS_OTA_ALLOW_HTTP": false, + "ESP_HTTPS_OTA_DECRYPT_CB": false, + "ESP_HTTPS_OTA_EVENT_POST_TIMEOUT": 2000, + "ESP_HTTPS_SERVER_ENABLE": true, + "ESP_HTTPS_SERVER_EVENT_POST_TIMEOUT": 2000, + "ESP_HTTP_CLIENT_ENABLE_BASIC_AUTH": false, + "ESP_HTTP_CLIENT_ENABLE_CUSTOM_TRANSPORT": false, + "ESP_HTTP_CLIENT_ENABLE_DIGEST_AUTH": false, + "ESP_HTTP_CLIENT_ENABLE_HTTPS": true, + "ESP_HTTP_CLIENT_EVENT_POST_TIMEOUT": 2000, + "ESP_INSIGHTS_CLOUD_POST_MAX_INTERVAL_SEC": 240, + "ESP_INSIGHTS_CLOUD_POST_MIN_INTERVAL_SEC": 60, + "ESP_INSIGHTS_ENABLED": false, + "ESP_INSIGHTS_META_VERSION_10": true, + "ESP_INSIGHTS_TRANSPORT_HTTPS": false, + "ESP_INSIGHTS_TRANSPORT_MQTT": true, + "ESP_INT_WDT": true, + "ESP_INT_WDT_TIMEOUT_MS": 300, + "ESP_IPC_TASK_STACK_SIZE": 1024, + "ESP_MAC_ADDR_UNIVERSE_BT": true, + "ESP_MAC_ADDR_UNIVERSE_ETH": true, + "ESP_MAC_ADDR_UNIVERSE_WIFI_AP": true, + "ESP_MAC_ADDR_UNIVERSE_WIFI_STA": true, + "ESP_MAC_UNIVERSAL_MAC_ADDRESSES": 4, + "ESP_MAC_UNIVERSAL_MAC_ADDRESSES_FOUR": true, + "ESP_MAC_USE_CUSTOM_MAC_AS_BASE_MAC": false, + "ESP_MAIN_TASK_AFFINITY": 0, + "ESP_MAIN_TASK_AFFINITY_CPU0": true, + "ESP_MAIN_TASK_AFFINITY_NO_AFFINITY": false, + "ESP_MAIN_TASK_STACK_SIZE": 3584, + "ESP_MINIMAL_SHARED_STACK_SIZE": 2048, + "ESP_NETIF_BRIDGE_EN": false, + "ESP_NETIF_IP_LOST_TIMER_INTERVAL": 120, + "ESP_NETIF_L2_TAP": false, + "ESP_NETIF_LOOPBACK": false, + "ESP_NETIF_PROVIDE_CUSTOM_IMPLEMENTATION": false, + "ESP_NETIF_RECEIVE_REPORT_ERRORS": false, + "ESP_NETIF_REPORT_DATA_TRAFFIC": true, + "ESP_NETIF_SET_DNS_PER_DEFAULT_NETIF": false, + "ESP_NETIF_TCPIP_LWIP": true, + "ESP_NETIF_USES_TCPIP_WITH_BSD_API": true, + "ESP_PANIC_HANDLER_IRAM": false, + "ESP_PHY_CALIBRATION_AND_DATA_STORAGE": true, + "ESP_PHY_CALIBRATION_MODE": 0, + "ESP_PHY_ENABLED": true, + "ESP_PHY_ENABLE_CERT_TEST": false, + "ESP_PHY_ENABLE_USB": true, + "ESP_PHY_INIT_DATA_IN_PARTITION": false, + "ESP_PHY_MAX_TX_POWER": 20, + "ESP_PHY_MAX_WIFI_TX_POWER": 20, + "ESP_PHY_PLL_TRACK_DEBUG": false, + "ESP_PHY_RECORD_USED_TIME": false, + "ESP_PHY_REDUCE_TX_POWER": false, + "ESP_PHY_RF_CAL_FULL": false, + "ESP_PHY_RF_CAL_NONE": false, + "ESP_PHY_RF_CAL_PARTIAL": true, + "ESP_PROTOCOMM_SUPPORT_SECURITY_PATCH_VERSION": true, + "ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_0": true, + "ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_1": true, + "ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_2": true, + "ESP_REV_MAX_FULL": 199, + "ESP_REV_MIN_FULL": 3, + "ESP_RMAKER_ASSISTED_CLAIM": false, + "ESP_RMAKER_CLAIM_SERVICE_BASE_URL": "https://esp-claiming.rainmaker.espressif.com", + "ESP_RMAKER_CLAIM_TYPE": 1, + "ESP_RMAKER_CMD_RESP_ENABLE": true, + "ESP_RMAKER_CMD_RESP_TEST_ENABLE": false, + "ESP_RMAKER_CONSOLE_UART_NUM": 0, + "ESP_RMAKER_CONSOLE_UART_NUM_0": true, + "ESP_RMAKER_CONSOLE_UART_NUM_1": false, + "ESP_RMAKER_DEF_TIMEZONE": "Asia/Shanghai", + "ESP_RMAKER_DISABLE_USER_MAPPING_PROV": false, + "ESP_RMAKER_FACTORY_NAMESPACE": "rmaker_creds", + "ESP_RMAKER_FACTORY_PARTITION_NAME": "fctry", + "ESP_RMAKER_LIB_AWS_IOT": false, + "ESP_RMAKER_LIB_ESP_MQTT": true, + "ESP_RMAKER_LOCAL_CTRL_AUTO_ENABLE": true, + "ESP_RMAKER_LOCAL_CTRL_FEATURE_ENABLE": true, + "ESP_RMAKER_LOCAL_CTRL_HTTP_PORT": 8080, + "ESP_RMAKER_LOCAL_CTRL_SECURITY": 1, + "ESP_RMAKER_LOCAL_CTRL_SECURITY_0": false, + "ESP_RMAKER_LOCAL_CTRL_SECURITY_1": true, + "ESP_RMAKER_LOCAL_CTRL_STACK_SIZE": 6144, + "ESP_RMAKER_MAX_COMMANDS": 10, + "ESP_RMAKER_MAX_MQTT_SUBSCRIPTIONS": 10, + "ESP_RMAKER_MAX_PARAM_DATA_SIZE": 1024, + "ESP_RMAKER_MQTT_BUDGET_REVIVE_COUNT": 1, + "ESP_RMAKER_MQTT_BUDGET_REVIVE_PERIOD": 5, + "ESP_RMAKER_MQTT_DEFAULT_BUDGET": 100, + "ESP_RMAKER_MQTT_ENABLE_BUDGETING": true, + "ESP_RMAKER_MQTT_GLUE_LIB": 1, + "ESP_RMAKER_MQTT_HOST": "a1p72mufdu6064-ats.iot.us-east-1.amazonaws.com", + "ESP_RMAKER_MQTT_KEEP_ALIVE_INTERVAL": 120, + "ESP_RMAKER_MQTT_MAX_BUDGET": 1024, + "ESP_RMAKER_MQTT_PERSISTENT_SESSION": false, + "ESP_RMAKER_MQTT_PORT": 1, + "ESP_RMAKER_MQTT_PORT_443": true, + "ESP_RMAKER_MQTT_PORT_8883": false, + "ESP_RMAKER_MQTT_PRODUCT_NAME": "RMDev", + "ESP_RMAKER_MQTT_PRODUCT_SKU": "EX00", + "ESP_RMAKER_MQTT_PRODUCT_VERSION": "1x0", + "ESP_RMAKER_MQTT_SEND_USERNAME": true, + "ESP_RMAKER_MQTT_USE_BASIC_INGEST_TOPICS": true, + "ESP_RMAKER_MQTT_USE_CERT_BUNDLE": true, + "ESP_RMAKER_NETWORK_OVER_WIFI": true, + "ESP_RMAKER_NO_CLAIM": false, + "ESP_RMAKER_OTA_AUTOFETCH": true, + "ESP_RMAKER_OTA_AUTOFETCH_PERIOD": 0, + "ESP_RMAKER_OTA_DISABLE_AUTO_REBOOT": false, + "ESP_RMAKER_OTA_HTTP_RX_BUFFER_SIZE": 1024, + "ESP_RMAKER_OTA_MAX_RETRIES": 3, + "ESP_RMAKER_OTA_PROGRESS_SUPPORT": false, + "ESP_RMAKER_OTA_RETRY_DELAY_MINUTES": 5, + "ESP_RMAKER_OTA_ROLLBACK_WAIT_PERIOD": 90, + "ESP_RMAKER_OTA_TIME_SUPPORT": true, + "ESP_RMAKER_READ_MQTT_HOST_FROM_CONFIG": false, + "ESP_RMAKER_READ_NODE_ID_FROM_CERT_CN": false, + "ESP_RMAKER_SCENES_DEACTIVATE_SUPPORT": false, + "ESP_RMAKER_SCENES_MAX_SCENES": 10, + "ESP_RMAKER_SCHEDULING_MAX_SCHEDULES": 10, + "ESP_RMAKER_SELF_CLAIM": true, + "ESP_RMAKER_SKIP_COMMON_NAME_CHECK": false, + "ESP_RMAKER_SKIP_PROJECT_NAME_CHECK": false, + "ESP_RMAKER_SKIP_SECURE_VERSION_CHECK": false, + "ESP_RMAKER_SKIP_VERSION_CHECK": false, + "ESP_RMAKER_SNTP_SERVER_NAME": "pool.ntp.org", + "ESP_RMAKER_USER_ID_CHECK": true, + "ESP_RMAKER_USE_CERT_BUNDLE": true, + "ESP_RMAKER_USE_NVS": true, + "ESP_RMAKER_USING_NETWORK_PROV": true, + "ESP_RMAKER_WORK_QUEUE_TASK_PRIORITY": 5, + "ESP_RMAKER_WORK_QUEUE_TASK_STACK": 5120, + "ESP_ROM_GET_CLK_FREQ": true, + "ESP_ROM_HAS_CRC_BE": true, + "ESP_ROM_HAS_CRC_LE": true, + "ESP_ROM_HAS_ENCRYPTED_WRITES_USING_LEGACY_DRV": true, + "ESP_ROM_HAS_ERASE_0_REGION_BUG": true, + "ESP_ROM_HAS_ETS_PRINTF_BUG": true, + "ESP_ROM_HAS_JPEG_DECODE": true, + "ESP_ROM_HAS_LAYOUT_TABLE": true, + "ESP_ROM_HAS_MZ_CRC32": true, + "ESP_ROM_HAS_NEWLIB": true, + "ESP_ROM_HAS_NEWLIB_32BIT_TIME": true, + "ESP_ROM_HAS_NEWLIB_NANO_FORMAT": true, + "ESP_ROM_HAS_RETARGETABLE_LOCKING": true, + "ESP_ROM_HAS_SPI_FLASH": true, + "ESP_ROM_HAS_SW_FLOAT": true, + "ESP_ROM_HAS_VERSION": true, + "ESP_ROM_NEEDS_SET_CACHE_MMU_SIZE": true, + "ESP_ROM_NEEDS_SWSETUP_WORKAROUND": true, + "ESP_ROM_RAM_APP_NEEDS_MMU_INIT": true, + "ESP_ROM_SUPPORT_DEEP_SLEEP_WAKEUP_STUB": true, + "ESP_ROM_UART_CLK_IS_XTAL": true, + "ESP_ROM_USB_OTG_NUM": -1, + "ESP_ROM_USB_SERIAL_DEVICE_NUM": 3, + "ESP_SECURE_CERT_DS_PERIPHERAL": true, + "ESP_SECURE_CERT_SUPPORT_LEGACY_FORMATS": false, + "ESP_SLEEP_CACHE_SAFE_ASSERTION": false, + "ESP_SLEEP_DEBUG": false, + "ESP_SLEEP_FLASH_LEAKAGE_WORKAROUND": true, + "ESP_SLEEP_GPIO_ENABLE_INTERNAL_RESISTORS": true, + "ESP_SLEEP_GPIO_RESET_WORKAROUND": true, + "ESP_SLEEP_MSPI_NEED_ALL_IO_PU": false, + "ESP_SLEEP_POWER_DOWN_FLASH": false, + "ESP_SLEEP_WAIT_FLASH_READY_EXTRA_DELAY": 0, + "ESP_SPI_BUS_LOCK_ISR_FUNCS_IN_IRAM": true, + "ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP": true, + "ESP_SYSTEM_BROWNOUT_INTR": true, + "ESP_SYSTEM_CHECK_INT_LEVEL_4": true, + "ESP_SYSTEM_EVENT_QUEUE_SIZE": 32, + "ESP_SYSTEM_EVENT_TASK_STACK_SIZE": 2304, + "ESP_SYSTEM_GDBSTUB_RUNTIME": false, + "ESP_SYSTEM_HW_PC_RECORD": true, + "ESP_SYSTEM_HW_STACK_GUARD": true, + "ESP_SYSTEM_MEMPROT_FEATURE": true, + "ESP_SYSTEM_MEMPROT_FEATURE_LOCK": true, + "ESP_SYSTEM_PANIC_GDBSTUB": false, + "ESP_SYSTEM_PANIC_PRINT_HALT": false, + "ESP_SYSTEM_PANIC_PRINT_REBOOT": true, + "ESP_SYSTEM_PANIC_REBOOT_DELAY_SECONDS": 0, + "ESP_SYSTEM_PANIC_SILENT_REBOOT": false, + "ESP_SYSTEM_RTC_FAST_MEM_AS_HEAP_DEPCHECK": true, + "ESP_SYSTEM_SINGLE_CORE_MODE": true, + "ESP_SYSTEM_USE_EH_FRAME": false, + "ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0": true, + "ESP_TASK_WDT_EN": true, + "ESP_TASK_WDT_INIT": true, + "ESP_TASK_WDT_PANIC": false, + "ESP_TASK_WDT_TIMEOUT_S": 5, + "ESP_TIMER_IMPL_SYSTIMER": true, + "ESP_TIMER_INTERRUPT_LEVEL": 1, + "ESP_TIMER_ISR_AFFINITY_CPU0": true, + "ESP_TIMER_PROFILING": false, + "ESP_TIMER_SHOW_EXPERIMENTAL": false, + "ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD": false, + "ESP_TIMER_TASK_AFFINITY": 0, + "ESP_TIMER_TASK_AFFINITY_CPU0": true, + "ESP_TIMER_TASK_STACK_SIZE": 3584, + "ESP_TIME_FUNCS_USE_ESP_TIMER": true, + "ESP_TIME_FUNCS_USE_RTC_TIMER": true, + "ESP_TLS_CLIENT_SESSION_TICKETS": false, + "ESP_TLS_INSECURE": false, + "ESP_TLS_PSK_VERIFICATION": false, + "ESP_TLS_SERVER_CERT_SELECT_HOOK": false, + "ESP_TLS_SERVER_MIN_AUTH_MODE_OPTIONAL": false, + "ESP_TLS_SERVER_SESSION_TICKETS": false, + "ESP_TLS_USE_DS_PERIPHERAL": true, + "ESP_TLS_USING_MBEDTLS": true, + "ESP_WIFI_11KV_SUPPORT": false, + "ESP_WIFI_11R_SUPPORT": false, + "ESP_WIFI_AMPDU_RX_ENABLED": true, + "ESP_WIFI_AMPDU_TX_ENABLED": true, + "ESP_WIFI_CSI_ENABLED": false, + "ESP_WIFI_DEBUG_PRINT": false, + "ESP_WIFI_DPP_SUPPORT": false, + "ESP_WIFI_DYNAMIC_RX_BUFFER_NUM": 32, + "ESP_WIFI_DYNAMIC_RX_MGMT_BUF": 0, + "ESP_WIFI_DYNAMIC_RX_MGMT_BUFFER": false, + "ESP_WIFI_DYNAMIC_TX_BUFFER": true, + "ESP_WIFI_DYNAMIC_TX_BUFFER_NUM": 32, + "ESP_WIFI_ENABLED": true, + "ESP_WIFI_ENABLE_SAE_PK": true, + "ESP_WIFI_ENABLE_WPA3_OWE_STA": true, + "ESP_WIFI_ENABLE_WPA3_SAE": true, + "ESP_WIFI_ENTERPRISE_SUPPORT": true, + "ESP_WIFI_ENT_FREE_DYNAMIC_BUFFER": false, + "ESP_WIFI_ESPNOW_MAX_ENCRYPT_NUM": 7, + "ESP_WIFI_EXTRA_IRAM_OPT": false, + "ESP_WIFI_FTM_ENABLE": false, + "ESP_WIFI_GCMP_SUPPORT": false, + "ESP_WIFI_GMAC_SUPPORT": true, + "ESP_WIFI_IRAM_OPT": true, + "ESP_WIFI_MBEDTLS_CRYPTO": true, + "ESP_WIFI_MBEDTLS_TLS_CLIENT": true, + "ESP_WIFI_MBO_SUPPORT": false, + "ESP_WIFI_MGMT_SBUF_NUM": 32, + "ESP_WIFI_NVS_ENABLED": true, + "ESP_WIFI_RX_BA_WIN": 6, + "ESP_WIFI_RX_IRAM_OPT": true, + "ESP_WIFI_RX_MGMT_BUF_NUM_DEF": 5, + "ESP_WIFI_SLP_BEACON_LOST_OPT": false, + "ESP_WIFI_SLP_DEFAULT_MAX_ACTIVE_TIME": 10, + "ESP_WIFI_SLP_DEFAULT_MIN_ACTIVE_TIME": 50, + "ESP_WIFI_SLP_DEFAULT_WAIT_BROADCAST_DATA_TIME": 15, + "ESP_WIFI_SLP_IRAM_OPT": false, + "ESP_WIFI_SOFTAP_BEACON_MAX_LEN": 752, + "ESP_WIFI_SOFTAP_SAE_SUPPORT": true, + "ESP_WIFI_SOFTAP_SUPPORT": true, + "ESP_WIFI_STATIC_RX_BUFFER_NUM": 10, + "ESP_WIFI_STATIC_RX_MGMT_BUFFER": true, + "ESP_WIFI_STATIC_TX_BUFFER": false, + "ESP_WIFI_STA_DISCONNECTED_PM_ENABLE": true, + "ESP_WIFI_SUITE_B_192": false, + "ESP_WIFI_TESTING_OPTIONS": false, + "ESP_WIFI_TX_BA_WIN": 6, + "ESP_WIFI_TX_BUFFER_TYPE": 1, + "ESP_WIFI_WAPI_PSK": false, + "ESP_WIFI_WPS_PASSPHRASE": false, + "ESP_WIFI_WPS_SOFTAP_REGISTRAR": false, + "ESP_WIFI_WPS_STRICT": false, + "ETH_ENABLED": true, + "ETH_SPI_ETHERNET_DM9051": false, + "ETH_SPI_ETHERNET_KSZ8851SNL": false, + "ETH_SPI_ETHERNET_W5500": false, + "ETH_TRANSMIT_MUTEX": false, + "ETH_USE_OPENETH": false, + "ETH_USE_SPI_ETHERNET": true, + "EXAMPLE_BOARD_BUTTON_GPIO": 9, + "FATFS_CODEPAGE": 437, + "FATFS_CODEPAGE_437": true, + "FATFS_CODEPAGE_720": false, + "FATFS_CODEPAGE_737": false, + "FATFS_CODEPAGE_771": false, + "FATFS_CODEPAGE_775": false, + "FATFS_CODEPAGE_850": false, + "FATFS_CODEPAGE_852": false, + "FATFS_CODEPAGE_855": false, + "FATFS_CODEPAGE_857": false, + "FATFS_CODEPAGE_860": false, + "FATFS_CODEPAGE_861": false, + "FATFS_CODEPAGE_862": false, + "FATFS_CODEPAGE_863": false, + "FATFS_CODEPAGE_864": false, + "FATFS_CODEPAGE_865": false, + "FATFS_CODEPAGE_866": false, + "FATFS_CODEPAGE_869": false, + "FATFS_CODEPAGE_932": false, + "FATFS_CODEPAGE_936": false, + "FATFS_CODEPAGE_949": false, + "FATFS_CODEPAGE_950": false, + "FATFS_CODEPAGE_DYNAMIC": false, + "FATFS_FS_LOCK": 0, + "FATFS_IMMEDIATE_FSYNC": false, + "FATFS_LFN_HEAP": false, + "FATFS_LFN_NONE": true, + "FATFS_LFN_STACK": false, + "FATFS_LINK_LOCK": true, + "FATFS_PER_FILE_CACHE": true, + "FATFS_SECTOR_4096": true, + "FATFS_SECTOR_512": false, + "FATFS_TIMEOUT_MS": 10000, + "FATFS_USE_FASTSEEK": false, + "FATFS_USE_LABEL": false, + "FATFS_USE_STRFUNC_NONE": true, + "FATFS_USE_STRFUNC_WITHOUT_CRLF_CONV": false, + "FATFS_USE_STRFUNC_WITH_CRLF_CONV": false, + "FATFS_VFS_FSTAT_BLKSIZE": 0, + "FATFS_VOLUME_COUNT": 2, + "FREERTOS_CHECK_MUTEX_GIVEN_BY_OWNER": true, + "FREERTOS_CHECK_PORT_CRITICAL_COMPLIANCE": false, + "FREERTOS_CHECK_STACKOVERFLOW_CANARY": true, + "FREERTOS_CHECK_STACKOVERFLOW_NONE": false, + "FREERTOS_CHECK_STACKOVERFLOW_PTRVAL": false, + "FREERTOS_CORETIMER_SYSTIMER_LVL1": true, + "FREERTOS_CORETIMER_SYSTIMER_LVL3": false, + "FREERTOS_DEBUG_OCDAWARE": true, + "FREERTOS_ENABLE_BACKWARD_COMPATIBILITY": false, + "FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP": false, + "FREERTOS_ENABLE_TASK_SNAPSHOT": true, + "FREERTOS_GENERATE_RUN_TIME_STATS": false, + "FREERTOS_HZ": 100, + "FREERTOS_IDLE_TASK_STACKSIZE": 1536, + "FREERTOS_INTERRUPT_BACKTRACE": true, + "FREERTOS_ISR_STACKSIZE": 1536, + "FREERTOS_MAX_TASK_NAME_LEN": 16, + "FREERTOS_NO_AFFINITY": 2147483647, + "FREERTOS_NUMBER_OF_CORES": 1, + "FREERTOS_OPTIMIZED_SCHEDULER": true, + "FREERTOS_PLACE_FUNCTIONS_INTO_FLASH": false, + "FREERTOS_PLACE_SNAPSHOT_FUNS_INTO_FLASH": true, + "FREERTOS_PORT": true, + "FREERTOS_QUEUE_REGISTRY_SIZE": 0, + "FREERTOS_SMP": false, + "FREERTOS_SUPPORT_STATIC_ALLOCATION": true, + "FREERTOS_SYSTICK_USES_SYSTIMER": true, + "FREERTOS_TASK_FUNCTION_WRAPPER": true, + "FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES": 1, + "FREERTOS_TASK_PRE_DELETION_HOOK": false, + "FREERTOS_THREAD_LOCAL_STORAGE_POINTERS": 1, + "FREERTOS_TICK_SUPPORT_SYSTIMER": true, + "FREERTOS_TIMER_QUEUE_LENGTH": 10, + "FREERTOS_TIMER_SERVICE_TASK_CORE_AFFINITY": 2147483647, + "FREERTOS_TIMER_SERVICE_TASK_NAME": "Tmr Svc", + "FREERTOS_TIMER_TASK_AFFINITY_CPU0": false, + "FREERTOS_TIMER_TASK_NO_AFFINITY": true, + "FREERTOS_TIMER_TASK_PRIORITY": 1, + "FREERTOS_TIMER_TASK_STACK_DEPTH": 3120, + "FREERTOS_TLSP_DELETION_CALLBACKS": true, + "FREERTOS_UNICORE": true, + "FREERTOS_USE_APPLICATION_TASK_TAG": false, + "FREERTOS_USE_IDLE_HOOK": false, + "FREERTOS_USE_LIST_DATA_INTEGRITY_CHECK_BYTES": false, + "FREERTOS_USE_TICK_HOOK": false, + "FREERTOS_USE_TIMERS": true, + "FREERTOS_USE_TRACE_FACILITY": false, + "FREERTOS_WATCHPOINT_END_OF_STACK": false, + "GDMA_CTRL_FUNC_IN_IRAM": true, + "GDMA_ENABLE_DEBUG_LOG": false, + "GDMA_ISR_IRAM_SAFE": false, + "GPIO_CTRL_FUNC_IN_IRAM": false, + "GPTIMER_CTRL_FUNC_IN_IRAM": false, + "GPTIMER_ENABLE_DEBUG_LOG": false, + "GPTIMER_ISR_HANDLER_IN_IRAM": true, + "GPTIMER_ISR_IRAM_SAFE": false, + "GPTIMER_SKIP_LEGACY_CONFLICT_CHECK": false, + "GPTIMER_SUPPRESS_DEPRECATE_WARN": false, + "HAL_ASSERTION_DISABLE": false, + "HAL_ASSERTION_ENABLE": false, + "HAL_ASSERTION_EQUALS_SYSTEM": true, + "HAL_ASSERTION_SILENT": false, + "HAL_DEFAULT_ASSERTION_LEVEL": 2, + "HAL_SPI_MASTER_FUNC_IN_IRAM": true, + "HAL_SPI_SLAVE_FUNC_IN_IRAM": true, + "HEAP_ABORT_WHEN_ALLOCATION_FAILS": false, + "HEAP_PLACE_FUNCTION_INTO_FLASH": false, + "HEAP_POISONING_COMPREHENSIVE": false, + "HEAP_POISONING_DISABLED": true, + "HEAP_POISONING_LIGHT": false, + "HEAP_TASK_TRACKING": false, + "HEAP_TRACING_OFF": true, + "HEAP_TRACING_STANDALONE": false, + "HEAP_TRACING_TOHOST": false, + "HEAP_USE_HOOKS": false, + "HTTPD_ERR_RESP_NO_DELAY": true, + "HTTPD_LOG_PURGE_DATA": false, + "HTTPD_MAX_REQ_HDR_LEN": 512, + "HTTPD_MAX_URI_LEN": 512, + "HTTPD_PURGE_BUF_LEN": 32, + "HTTPD_QUEUE_WORK_BLOCKING": false, + "HTTPD_SERVER_EVENT_POST_TIMEOUT": 2000, + "HTTPD_WS_SUPPORT": false, + "I2C_ENABLE_DEBUG_LOG": false, + "I2C_ENABLE_SLAVE_DRIVER_VERSION_2": false, + "I2C_ISR_IRAM_SAFE": false, + "I2S_ENABLE_DEBUG_LOG": false, + "I2S_ISR_IRAM_SAFE": false, + "I2S_SKIP_LEGACY_CONFLICT_CHECK": false, + "I2S_SUPPRESS_DEPRECATE_WARN": false, + "IDF_CMAKE": true, + "IDF_EXPERIMENTAL_FEATURES": false, + "IDF_FIRMWARE_CHIP_ID": 5, + "IDF_INIT_VERSION": "5.4.1", + "IDF_TARGET": "esp32c3", + "IDF_TARGET_ARCH": "riscv", + "IDF_TARGET_ARCH_RISCV": true, + "IDF_TARGET_ESP32C3": true, + "IDF_TOOLCHAIN": "gcc", + "IDF_TOOLCHAIN_GCC": true, + "IO_GLITCH_FILTER_TIME_MS": 50, + "JSMN_PARENT_LINKS": false, + "JSMN_STATIC": false, + "JSMN_STRICT": false, + "LCD_ENABLE_DEBUG_LOG": false, + "LEDC_CTRL_FUNC_IN_IRAM": false, + "LOG_COLORS": false, + "LOG_DEFAULT_LEVEL": 3, + "LOG_DEFAULT_LEVEL_DEBUG": false, + "LOG_DEFAULT_LEVEL_ERROR": false, + "LOG_DEFAULT_LEVEL_INFO": true, + "LOG_DEFAULT_LEVEL_NONE": false, + "LOG_DEFAULT_LEVEL_VERBOSE": false, + "LOG_DEFAULT_LEVEL_WARN": false, + "LOG_DYNAMIC_LEVEL_CONTROL": true, + "LOG_MASTER_LEVEL": false, + "LOG_MAXIMUM_EQUALS_DEFAULT": true, + "LOG_MAXIMUM_LEVEL": 3, + "LOG_MAXIMUM_LEVEL_DEBUG": false, + "LOG_MAXIMUM_LEVEL_VERBOSE": false, + "LOG_TAG_LEVEL_CACHE_ARRAY": false, + "LOG_TAG_LEVEL_CACHE_BINARY_MIN_HEAP": true, + "LOG_TAG_LEVEL_IMPL_CACHE_AND_LINKED_LIST": true, + "LOG_TAG_LEVEL_IMPL_CACHE_SIZE": 31, + "LOG_TAG_LEVEL_IMPL_LINKED_LIST": false, + "LOG_TAG_LEVEL_IMPL_NONE": false, + "LOG_TIMESTAMP_SOURCE_RTOS": true, + "LOG_TIMESTAMP_SOURCE_SYSTEM": false, + "LWIP_AUTOIP": false, + "LWIP_BRIDGEIF_MAX_PORTS": 7, + "LWIP_BROADCAST_PING": false, + "LWIP_CHECKSUM_CHECK_ICMP": true, + "LWIP_CHECKSUM_CHECK_IP": false, + "LWIP_CHECKSUM_CHECK_UDP": false, + "LWIP_CHECK_THREAD_SAFETY": false, + "LWIP_DEBUG": false, + "LWIP_DHCPS": true, + "LWIP_DHCPS_ADD_DNS": true, + "LWIP_DHCPS_LEASE_UNIT": 60, + "LWIP_DHCPS_MAX_STATION_NUM": 8, + "LWIP_DHCPS_STATIC_ENTRIES": true, + "LWIP_DHCP_COARSE_TIMER_SECS": 1, + "LWIP_DHCP_DISABLE_CLIENT_ID": false, + "LWIP_DHCP_DISABLE_VENDOR_CLASS_ID": true, + "LWIP_DHCP_DOES_ACD_CHECK": false, + "LWIP_DHCP_DOES_ARP_CHECK": true, + "LWIP_DHCP_DOES_NOT_CHECK_OFFERED_IP": false, + "LWIP_DHCP_GET_NTP_SRV": false, + "LWIP_DHCP_OPTIONS_LEN": 68, + "LWIP_DHCP_RESTORE_LAST_IP": false, + "LWIP_DNS_MAX_HOST_IP": 1, + "LWIP_DNS_MAX_SERVERS": 3, + "LWIP_DNS_SETSERVER_WITH_NETIF": false, + "LWIP_DNS_SUPPORT_MDNS_QUERIES": true, + "LWIP_ENABLE": true, + "LWIP_ESP_GRATUITOUS_ARP": true, + "LWIP_ESP_LWIP_ASSERT": true, + "LWIP_ESP_MLDV6_REPORT": true, + "LWIP_EXTRA_IRAM_OPTIMIZATION": false, + "LWIP_FALLBACK_DNS_SERVER_SUPPORT": false, + "LWIP_FORCE_ROUTER_FORWARDING": false, + "LWIP_GARP_TMR_INTERVAL": 60, + "LWIP_HOOK_DNS_EXT_RESOLVE_CUSTOM": false, + "LWIP_HOOK_DNS_EXT_RESOLVE_NONE": true, + "LWIP_HOOK_IP6_INPUT_CUSTOM": false, + "LWIP_HOOK_IP6_INPUT_DEFAULT": true, + "LWIP_HOOK_IP6_INPUT_NONE": false, + "LWIP_HOOK_IP6_ROUTE_CUSTOM": false, + "LWIP_HOOK_IP6_ROUTE_DEFAULT": false, + "LWIP_HOOK_IP6_ROUTE_NONE": true, + "LWIP_HOOK_IP6_SELECT_SRC_ADDR_CUSTOM": false, + "LWIP_HOOK_IP6_SELECT_SRC_ADDR_DEFAULT": false, + "LWIP_HOOK_IP6_SELECT_SRC_ADDR_NONE": true, + "LWIP_HOOK_ND6_GET_GW_CUSTOM": false, + "LWIP_HOOK_ND6_GET_GW_DEFAULT": false, + "LWIP_HOOK_ND6_GET_GW_NONE": true, + "LWIP_HOOK_NETCONN_EXT_RESOLVE_CUSTOM": false, + "LWIP_HOOK_NETCONN_EXT_RESOLVE_DEFAULT": false, + "LWIP_HOOK_NETCONN_EXT_RESOLVE_NONE": true, + "LWIP_HOOK_TCP_ISN_CUSTOM": false, + "LWIP_HOOK_TCP_ISN_DEFAULT": true, + "LWIP_HOOK_TCP_ISN_NONE": false, + "LWIP_ICMP": true, + "LWIP_IP4_FRAG": true, + "LWIP_IP4_REASSEMBLY": false, + "LWIP_IP6_FRAG": true, + "LWIP_IP6_REASSEMBLY": false, + "LWIP_IPV4": true, + "LWIP_IPV6": true, + "LWIP_IPV6_AUTOCONFIG": false, + "LWIP_IPV6_FORWARD": false, + "LWIP_IPV6_MEMP_NUM_ND6_QUEUE": 3, + "LWIP_IPV6_ND6_NUM_DESTINATIONS": 10, + "LWIP_IPV6_ND6_NUM_NEIGHBORS": 5, + "LWIP_IPV6_ND6_NUM_PREFIXES": 5, + "LWIP_IPV6_ND6_NUM_ROUTERS": 3, + "LWIP_IPV6_NUM_ADDRESSES": 3, + "LWIP_IP_DEFAULT_TTL": 64, + "LWIP_IP_FORWARD": false, + "LWIP_IP_REASS_MAX_PBUFS": 10, + "LWIP_IRAM_OPTIMIZATION": false, + "LWIP_L2_TO_L3_COPY": false, + "LWIP_LOCAL_HOSTNAME": "espressif", + "LWIP_LOOPBACK_MAX_PBUFS": 8, + "LWIP_MAX_ACTIVE_TCP": 16, + "LWIP_MAX_LISTENING_TCP": 16, + "LWIP_MAX_RAW_PCBS": 16, + "LWIP_MAX_SOCKETS": 10, + "LWIP_MAX_UDP_PCBS": 16, + "LWIP_MLDV6_TMR_INTERVAL": 40, + "LWIP_MULTICAST_PING": false, + "LWIP_ND6": true, + "LWIP_NETBUF_RECVINFO": false, + "LWIP_NETIF_API": false, + "LWIP_NETIF_LOOPBACK": true, + "LWIP_NETIF_STATUS_CALLBACK": false, + "LWIP_NUM_NETIF_CLIENT_DATA": 0, + "LWIP_PPP_SUPPORT": false, + "LWIP_SLIP_SUPPORT": false, + "LWIP_SNTP_MAXIMUM_STARTUP_DELAY": 5000, + "LWIP_SNTP_MAX_SERVERS": 1, + "LWIP_SNTP_STARTUP_DELAY": true, + "LWIP_SNTP_UPDATE_DELAY": 3600000, + "LWIP_SO_LINGER": false, + "LWIP_SO_RCVBUF": false, + "LWIP_SO_REUSE": true, + "LWIP_SO_REUSE_RXTOALL": true, + "LWIP_STATS": false, + "LWIP_TCPIP_CORE_LOCKING": false, + "LWIP_TCPIP_RECVMBOX_SIZE": 32, + "LWIP_TCPIP_TASK_AFFINITY": 2147483647, + "LWIP_TCPIP_TASK_AFFINITY_CPU0": false, + "LWIP_TCPIP_TASK_AFFINITY_NO_AFFINITY": true, + "LWIP_TCPIP_TASK_PRIO": 18, + "LWIP_TCPIP_TASK_STACK_SIZE": 3072, + "LWIP_TCP_ACCEPTMBOX_SIZE": 6, + "LWIP_TCP_FIN_WAIT_TIMEOUT": 20000, + "LWIP_TCP_HIGH_SPEED_RETRANSMISSION": true, + "LWIP_TCP_MAXRTX": 12, + "LWIP_TCP_MSL": 60000, + "LWIP_TCP_MSS": 1440, + "LWIP_TCP_OOSEQ_MAX_PBUFS": 4, + "LWIP_TCP_OOSEQ_TIMEOUT": 6, + "LWIP_TCP_OVERSIZE_DISABLE": false, + "LWIP_TCP_OVERSIZE_MSS": true, + "LWIP_TCP_OVERSIZE_QUARTER_MSS": false, + "LWIP_TCP_QUEUE_OOSEQ": true, + "LWIP_TCP_RECVMBOX_SIZE": 6, + "LWIP_TCP_RTO_TIME": 1500, + "LWIP_TCP_SACK_OUT": false, + "LWIP_TCP_SND_BUF_DEFAULT": 5760, + "LWIP_TCP_SYNMAXRTX": 12, + "LWIP_TCP_TMR_INTERVAL": 250, + "LWIP_TCP_WND_DEFAULT": 5760, + "LWIP_TIMERS_ONDEMAND": true, + "LWIP_UDP_RECVMBOX_SIZE": 6, + "LWIP_USE_ONLY_LWIP_SELECT": false, + "MBEDTLS_AES_C": true, + "MBEDTLS_AES_INTERRUPT_LEVEL": 0, + "MBEDTLS_AES_USE_INTERRUPT": true, + "MBEDTLS_ASYMMETRIC_CONTENT_LEN": true, + "MBEDTLS_ATCA_HW_ECDSA_SIGN": false, + "MBEDTLS_ATCA_HW_ECDSA_VERIFY": false, + "MBEDTLS_BLOWFISH_C": false, + "MBEDTLS_CAMELLIA_C": false, + "MBEDTLS_CCM_C": true, + "MBEDTLS_CERTIFICATE_BUNDLE": true, + "MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_CMN": true, + "MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_FULL": false, + "MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_NONE": false, + "MBEDTLS_CERTIFICATE_BUNDLE_DEPRECATED_LIST": false, + "MBEDTLS_CERTIFICATE_BUNDLE_MAX_CERTS": 200, + "MBEDTLS_CHACHA20_C": false, + "MBEDTLS_CLIENT_SSL_SESSION_TICKETS": true, + "MBEDTLS_CMAC_C": true, + "MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE": false, + "MBEDTLS_CUSTOM_MEM_ALLOC": false, + "MBEDTLS_DEBUG": false, + "MBEDTLS_DEFAULT_MEM_ALLOC": false, + "MBEDTLS_DES_C": false, + "MBEDTLS_DHM_C": false, + "MBEDTLS_DYNAMIC_BUFFER": true, + "MBEDTLS_DYNAMIC_FREE_CA_CERT": true, + "MBEDTLS_DYNAMIC_FREE_CONFIG_DATA": true, + "MBEDTLS_ECDH_C": true, + "MBEDTLS_ECDSA_C": true, + "MBEDTLS_ECDSA_DETERMINISTIC": true, + "MBEDTLS_ECJPAKE_C": false, + "MBEDTLS_ECP_C": true, + "MBEDTLS_ECP_DP_BP256R1_ENABLED": true, + "MBEDTLS_ECP_DP_BP384R1_ENABLED": true, + "MBEDTLS_ECP_DP_BP512R1_ENABLED": true, + "MBEDTLS_ECP_DP_CURVE25519_ENABLED": true, + "MBEDTLS_ECP_DP_SECP192K1_ENABLED": true, + "MBEDTLS_ECP_DP_SECP192R1_ENABLED": true, + "MBEDTLS_ECP_DP_SECP224K1_ENABLED": true, + "MBEDTLS_ECP_DP_SECP224R1_ENABLED": true, + "MBEDTLS_ECP_DP_SECP256K1_ENABLED": true, + "MBEDTLS_ECP_DP_SECP256R1_ENABLED": true, + "MBEDTLS_ECP_DP_SECP384R1_ENABLED": true, + "MBEDTLS_ECP_DP_SECP521R1_ENABLED": true, + "MBEDTLS_ECP_FIXED_POINT_OPTIM": false, + "MBEDTLS_ECP_NIST_OPTIM": true, + "MBEDTLS_ECP_RESTARTABLE": false, + "MBEDTLS_ERROR_STRINGS": true, + "MBEDTLS_FS_IO": true, + "MBEDTLS_GCM_C": true, + "MBEDTLS_GCM_SUPPORT_NON_AES_CIPHER": true, + "MBEDTLS_HARDWARE_AES": true, + "MBEDTLS_HARDWARE_MPI": true, + "MBEDTLS_HARDWARE_SHA": true, + "MBEDTLS_HAVE_TIME": true, + "MBEDTLS_HAVE_TIME_DATE": false, + "MBEDTLS_HKDF_C": false, + "MBEDTLS_INTERNAL_MEM_ALLOC": true, + "MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA": true, + "MBEDTLS_KEY_EXCHANGE_ECDHE_RSA": true, + "MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA": true, + "MBEDTLS_KEY_EXCHANGE_ECDH_RSA": true, + "MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE": true, + "MBEDTLS_KEY_EXCHANGE_RSA": true, + "MBEDTLS_LARGE_KEY_SOFTWARE_MPI": true, + "MBEDTLS_MPI_INTERRUPT_LEVEL": 0, + "MBEDTLS_MPI_USE_INTERRUPT": true, + "MBEDTLS_NIST_KW_C": false, + "MBEDTLS_PEM_PARSE_C": true, + "MBEDTLS_PEM_WRITE_C": true, + "MBEDTLS_PKCS7_C": true, + "MBEDTLS_PK_PARSE_EC_COMPRESSED": true, + "MBEDTLS_PK_PARSE_EC_EXTENDED": true, + "MBEDTLS_PLATFORM_TIME_ALT": false, + "MBEDTLS_POLY1305_C": false, + "MBEDTLS_PSK_MODES": false, + "MBEDTLS_RIPEMD160_C": false, + "MBEDTLS_ROM_MD5": true, + "MBEDTLS_SERVER_SSL_SESSION_TICKETS": true, + "MBEDTLS_SHA3_C": false, + "MBEDTLS_SHA512_C": true, + "MBEDTLS_SSL_ALPN": true, + "MBEDTLS_SSL_CONTEXT_SERIALIZATION": false, + "MBEDTLS_SSL_IN_CONTENT_LEN": 16384, + "MBEDTLS_SSL_KEEP_PEER_CERTIFICATE": true, + "MBEDTLS_SSL_OUT_CONTENT_LEN": 4096, + "MBEDTLS_SSL_PROTO_DTLS": false, + "MBEDTLS_SSL_PROTO_GMTSSL1_1": false, + "MBEDTLS_SSL_PROTO_TLS1_2": true, + "MBEDTLS_SSL_RENEGOTIATION": true, + "MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH": false, + "MBEDTLS_THREADING_C": false, + "MBEDTLS_TLS_CLIENT": true, + "MBEDTLS_TLS_CLIENT_ONLY": false, + "MBEDTLS_TLS_DISABLED": false, + "MBEDTLS_TLS_ENABLED": true, + "MBEDTLS_TLS_SERVER": true, + "MBEDTLS_TLS_SERVER_AND_CLIENT": true, + "MBEDTLS_TLS_SERVER_ONLY": false, + "MBEDTLS_X509_CRL_PARSE_C": true, + "MBEDTLS_X509_CSR_PARSE_C": true, + "MBEDTLS_X509_TRUSTED_CERT_CALLBACK": false, + "MBEDTLS_XTEA_C": false, + "MDNS_ACTION_QUEUE_LEN": 16, + "MDNS_ENABLE_CONSOLE_CLI": true, + "MDNS_ENABLE_DEBUG_PRINTS": false, + "MDNS_MAX_INTERFACES": 3, + "MDNS_MAX_SERVICES": 10, + "MDNS_MEMORY_ALLOC_INTERNAL": true, + "MDNS_MEMORY_CUSTOM_IMPL": false, + "MDNS_MULTIPLE_INSTANCE": true, + "MDNS_NETWORKING_SOCKET": false, + "MDNS_PREDEF_NETIF_AP": true, + "MDNS_PREDEF_NETIF_ETH": true, + "MDNS_PREDEF_NETIF_STA": true, + "MDNS_RESPOND_REVERSE_QUERIES": false, + "MDNS_SERVICE_ADD_TIMEOUT_MS": 2000, + "MDNS_SKIP_SUPPRESSING_OWN_QUERIES": false, + "MDNS_TASK_AFFINITY": 0, + "MDNS_TASK_AFFINITY_CPU0": true, + "MDNS_TASK_AFFINITY_NO_AFFINITY": false, + "MDNS_TASK_CREATE_FROM_INTERNAL": true, + "MDNS_TASK_PRIORITY": 1, + "MDNS_TASK_STACK_SIZE": 4096, + "MDNS_TIMER_PERIOD_MS": 100, + "MMU_PAGE_MODE": "64KB", + "MMU_PAGE_SIZE": 65536, + "MMU_PAGE_SIZE_64KB": true, + "MQTT_CUSTOM_OUTBOX": false, + "MQTT_MSG_ID_INCREMENTAL": false, + "MQTT_PROTOCOL_311": true, + "MQTT_PROTOCOL_5": false, + "MQTT_REPORT_DELETED_MESSAGES": false, + "MQTT_SKIP_PUBLISH_IF_DISCONNECTED": false, + "MQTT_TASK_CORE_SELECTION_ENABLED": false, + "MQTT_TRANSPORT_SSL": true, + "MQTT_TRANSPORT_WEBSOCKET": true, + "MQTT_TRANSPORT_WEBSOCKET_SECURE": true, + "MQTT_USE_CUSTOM_CONFIG": false, + "NETWORK_PROV_AUTOSTOP_TIMEOUT": 30, + "NETWORK_PROV_BLE_BONDING": false, + "NETWORK_PROV_BLE_FORCE_ENCRYPTION": false, + "NETWORK_PROV_BLE_SEC_CONN": true, + "NETWORK_PROV_KEEP_BLE_ON_AFTER_PROV": false, + "NETWORK_PROV_NETWORK_TYPE_WIFI": true, + "NETWORK_PROV_SCAN_MAX_ENTRIES": 16, + "NETWORK_PROV_WIFI_STA_ALL_CHANNEL_SCAN": true, + "NETWORK_PROV_WIFI_STA_FAST_SCAN": false, + "NEWLIB_NANO_FORMAT": false, + "NEWLIB_STDIN_LINE_ENDING_CR": true, + "NEWLIB_STDIN_LINE_ENDING_CRLF": false, + "NEWLIB_STDIN_LINE_ENDING_LF": false, + "NEWLIB_STDOUT_LINE_ENDING_CR": false, + "NEWLIB_STDOUT_LINE_ENDING_CRLF": true, + "NEWLIB_STDOUT_LINE_ENDING_LF": false, + "NEWLIB_TIME_SYSCALL_USE_HRT": false, + "NEWLIB_TIME_SYSCALL_USE_NONE": false, + "NEWLIB_TIME_SYSCALL_USE_RTC": false, + "NEWLIB_TIME_SYSCALL_USE_RTC_HRT": true, + "NVS_ASSERT_ERROR_CHECK": false, + "NVS_ENCRYPTION": false, + "NVS_LEGACY_DUP_KEYS_COMPATIBILITY": false, + "OPENTHREAD_ENABLED": false, + "OPENTHREAD_SPINEL_ONLY": false, + "PARTITION_TABLE_CUSTOM": true, + "PARTITION_TABLE_CUSTOM_FILENAME": "partitions_4mb_optimised.csv", + "PARTITION_TABLE_FILENAME": "partitions_4mb_optimised.csv", + "PARTITION_TABLE_MD5": true, + "PARTITION_TABLE_OFFSET": 49152, + "PARTITION_TABLE_SINGLE_APP": false, + "PARTITION_TABLE_SINGLE_APP_LARGE": false, + "PARTITION_TABLE_TWO_OTA": false, + "PARTITION_TABLE_TWO_OTA_LARGE": false, + "PERIPH_CTRL_FUNC_IN_IRAM": true, + "PM_ENABLE": false, + "PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP": true, + "PM_SLP_IRAM_OPT": false, + "PTHREAD_STACK_MIN": 768, + "PTHREAD_TASK_CORE_DEFAULT": -1, + "PTHREAD_TASK_NAME_DEFAULT": "pthread", + "PTHREAD_TASK_PRIO_DEFAULT": 5, + "PTHREAD_TASK_STACK_SIZE_DEFAULT": 3072, + "RINGBUF_PLACE_FUNCTIONS_INTO_FLASH": false, + "RMAKER_NAME_PARAM_CB": false, + "RMT_ENABLE_DEBUG_LOG": false, + "RMT_ISR_IRAM_SAFE": false, + "RMT_RECV_FUNC_IN_IRAM": false, + "RMT_SKIP_LEGACY_CONFLICT_CHECK": false, + "RMT_SUPPRESS_DEPRECATE_WARN": false, + "RTC_CLK_CAL_CYCLES": 1024, + "RTC_CLK_SRC_EXT_CRYS": false, + "RTC_CLK_SRC_EXT_OSC": false, + "RTC_CLK_SRC_INT_8MD256": false, + "RTC_CLK_SRC_INT_RC": true, + "RTC_STORE_CRITICAL_DATA_SIZE": 4096, + "RTC_STORE_DATA_SIZE": 6144, + "SDM_CTRL_FUNC_IN_IRAM": false, + "SDM_ENABLE_DEBUG_LOG": false, + "SDM_SKIP_LEGACY_CONFLICT_CHECK": false, + "SDM_SUPPRESS_DEPRECATE_WARN": false, + "SECURE_BOOT": false, + "SECURE_BOOT_V2_PREFERRED": true, + "SECURE_BOOT_V2_RSA_SUPPORTED": true, + "SECURE_FLASH_ENC_ENABLED": false, + "SECURE_ROM_DL_MODE_ENABLED": true, + "SECURE_SIGNED_APPS_NO_SECURE_BOOT": false, + "SERIAL_FLASHER_BOOT_HOLD_TIME_MS": 50, + "SERIAL_FLASHER_BOOT_INVERT": false, + "SERIAL_FLASHER_DEBUG_TRACE": false, + "SERIAL_FLASHER_INTERFACE_SDIO": false, + "SERIAL_FLASHER_INTERFACE_SPI": false, + "SERIAL_FLASHER_INTERFACE_UART": true, + "SERIAL_FLASHER_INTERFACE_USB": false, + "SERIAL_FLASHER_MD5_ENABLED": true, + "SERIAL_FLASHER_RESET_HOLD_TIME_MS": 100, + "SERIAL_FLASHER_RESET_INVERT": false, + "SERIAL_FLASHER_WRITE_BLOCK_RETRIES": 3, + "SOC_ADC_ARBITER_SUPPORTED": true, + "SOC_ADC_ATTEN_NUM": 4, + "SOC_ADC_CALIBRATION_V1_SUPPORTED": true, + "SOC_ADC_DIGI_CONTROLLER_NUM": 1, + "SOC_ADC_DIGI_DATA_BYTES_PER_CONV": 4, + "SOC_ADC_DIGI_IIR_FILTER_NUM": 2, + "SOC_ADC_DIGI_MAX_BITWIDTH": 12, + "SOC_ADC_DIGI_MIN_BITWIDTH": 12, + "SOC_ADC_DIGI_MONITOR_NUM": 2, + "SOC_ADC_DIGI_RESULT_BYTES": 4, + "SOC_ADC_DIG_CTRL_SUPPORTED": true, + "SOC_ADC_DIG_IIR_FILTER_SUPPORTED": true, + "SOC_ADC_DMA_SUPPORTED": true, + "SOC_ADC_MAX_CHANNEL_NUM": 5, + "SOC_ADC_MONITOR_SUPPORTED": true, + "SOC_ADC_PATT_LEN_MAX": 8, + "SOC_ADC_PERIPH_NUM": 2, + "SOC_ADC_RTC_MAX_BITWIDTH": 12, + "SOC_ADC_RTC_MIN_BITWIDTH": 12, + "SOC_ADC_SAMPLE_FREQ_THRES_HIGH": 83333, + "SOC_ADC_SAMPLE_FREQ_THRES_LOW": 611, + "SOC_ADC_SELF_HW_CALI_SUPPORTED": true, + "SOC_ADC_SHARED_POWER": true, + "SOC_ADC_SUPPORTED": true, + "SOC_AES_GDMA": true, + "SOC_AES_SUPPORTED": true, + "SOC_AES_SUPPORT_AES_128": true, + "SOC_AES_SUPPORT_AES_256": true, + "SOC_AES_SUPPORT_DMA": true, + "SOC_AHB_GDMA_SUPPORTED": true, + "SOC_AHB_GDMA_VERSION": 1, + "SOC_APB_BACKUP_DMA": true, + "SOC_ASSIST_DEBUG_SUPPORTED": true, + "SOC_ASYNC_MEMCPY_SUPPORTED": true, + "SOC_BLE_50_SUPPORTED": true, + "SOC_BLE_DEVICE_PRIVACY_SUPPORTED": true, + "SOC_BLE_MESH_SUPPORTED": true, + "SOC_BLE_SUPPORTED": true, + "SOC_BLUFI_SUPPORTED": true, + "SOC_BOD_SUPPORTED": true, + "SOC_BROWNOUT_RESET_SUPPORTED": true, + "SOC_BT_SUPPORTED": true, + "SOC_CACHE_MEMORY_IBANK_SIZE": 16384, + "SOC_CLK_RC_FAST_D256_SUPPORTED": true, + "SOC_CLK_RC_FAST_SUPPORT_CALIBRATION": true, + "SOC_CLK_TREE_SUPPORTED": true, + "SOC_CLK_XTAL32K_SUPPORTED": true, + "SOC_COEX_HW_PTI": true, + "SOC_CPU_BREAKPOINTS_NUM": 8, + "SOC_CPU_CORES_NUM": 1, + "SOC_CPU_HAS_CSR_PC": true, + "SOC_CPU_HAS_FLEXIBLE_INTC": true, + "SOC_CPU_INTR_NUM": 32, + "SOC_CPU_WATCHPOINTS_NUM": 8, + "SOC_CPU_WATCHPOINT_MAX_REGION_SIZE": 2147483648, + "SOC_DEDICATED_GPIO_SUPPORTED": true, + "SOC_DEDIC_GPIO_IN_CHANNELS_NUM": 8, + "SOC_DEDIC_GPIO_OUT_CHANNELS_NUM": 8, + "SOC_DEDIC_PERIPH_ALWAYS_ENABLE": true, + "SOC_DEEP_SLEEP_SUPPORTED": true, + "SOC_DIG_SIGN_SUPPORTED": true, + "SOC_DS_KEY_CHECK_MAX_WAIT_US": 1100, + "SOC_DS_KEY_PARAM_MD_IV_LENGTH": 16, + "SOC_DS_SIGNATURE_MAX_BIT_LEN": 3072, + "SOC_EFUSE_BLOCK9_KEY_PURPOSE_QUIRK": true, + "SOC_EFUSE_DIS_DIRECT_BOOT": true, + "SOC_EFUSE_DIS_DOWNLOAD_ICACHE": true, + "SOC_EFUSE_DIS_ICACHE": true, + "SOC_EFUSE_DIS_PAD_JTAG": true, + "SOC_EFUSE_DIS_USB_JTAG": true, + "SOC_EFUSE_HAS_EFUSE_RST_BUG": true, + "SOC_EFUSE_KEY_PURPOSE_FIELD": true, + "SOC_EFUSE_REVOKE_BOOT_KEY_DIGESTS": true, + "SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS": 3, + "SOC_EFUSE_SOFT_DIS_JTAG": true, + "SOC_EFUSE_SUPPORTED": true, + "SOC_FLASH_ENCRYPTED_XTS_AES_BLOCK_MAX": 32, + "SOC_FLASH_ENCRYPTION_XTS_AES": true, + "SOC_FLASH_ENCRYPTION_XTS_AES_128": true, + "SOC_FLASH_ENC_SUPPORTED": true, + "SOC_GDMA_NUM_GROUPS_MAX": 1, + "SOC_GDMA_PAIRS_PER_GROUP_MAX": 3, + "SOC_GDMA_SUPPORTED": true, + "SOC_GPIO_CLOCKOUT_BY_GPIO_MATRIX": true, + "SOC_GPIO_CLOCKOUT_CHANNEL_NUM": 3, + "SOC_GPIO_DEEP_SLEEP_WAKE_SUPPORTED_PIN_CNT": 6, + "SOC_GPIO_DEEP_SLEEP_WAKE_VALID_GPIO_MASK": 0, + "SOC_GPIO_FILTER_CLK_SUPPORT_APB": true, + "SOC_GPIO_IN_RANGE_MAX": 21, + "SOC_GPIO_OUT_RANGE_MAX": 21, + "SOC_GPIO_PIN_COUNT": 22, + "SOC_GPIO_PORT": 1, + "SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP": true, + "SOC_GPIO_SUPPORT_FORCE_HOLD": true, + "SOC_GPIO_SUPPORT_HOLD_IO_IN_DSLP": true, + "SOC_GPIO_SUPPORT_PIN_GLITCH_FILTER": true, + "SOC_GPIO_VALID_DIGITAL_IO_PAD_MASK": 4194240, + "SOC_GPSPI_SUPPORTED": true, + "SOC_GPTIMER_SUPPORTED": true, + "SOC_HMAC_SUPPORTED": true, + "SOC_HP_I2C_NUM": 1, + "SOC_I2C_CMD_REG_NUM": 8, + "SOC_I2C_FIFO_LEN": 32, + "SOC_I2C_NUM": 1, + "SOC_I2C_SLAVE_CAN_GET_STRETCH_CAUSE": true, + "SOC_I2C_SLAVE_SUPPORT_BROADCAST": true, + "SOC_I2C_SLAVE_SUPPORT_I2CRAM_ACCESS": true, + "SOC_I2C_SUPPORTED": true, + "SOC_I2C_SUPPORT_10BIT_ADDR": true, + "SOC_I2C_SUPPORT_HW_CLR_BUS": true, + "SOC_I2C_SUPPORT_RTC": true, + "SOC_I2C_SUPPORT_SLAVE": true, + "SOC_I2C_SUPPORT_XTAL": true, + "SOC_I2S_HW_VERSION_2": true, + "SOC_I2S_NUM": 1, + "SOC_I2S_PDM_MAX_TX_LINES": 2, + "SOC_I2S_SUPPORTED": true, + "SOC_I2S_SUPPORTS_PCM": true, + "SOC_I2S_SUPPORTS_PDM": true, + "SOC_I2S_SUPPORTS_PDM_TX": true, + "SOC_I2S_SUPPORTS_PLL_F160M": true, + "SOC_I2S_SUPPORTS_TDM": true, + "SOC_I2S_SUPPORTS_XTAL": true, + "SOC_LEDC_CHANNEL_NUM": 6, + "SOC_LEDC_SUPPORTED": true, + "SOC_LEDC_SUPPORT_APB_CLOCK": true, + "SOC_LEDC_SUPPORT_FADE_STOP": true, + "SOC_LEDC_SUPPORT_XTAL_CLOCK": true, + "SOC_LEDC_TIMER_BIT_WIDTH": 14, + "SOC_LEDC_TIMER_NUM": 4, + "SOC_LIGHT_SLEEP_SUPPORTED": true, + "SOC_LP_PERIPH_SHARE_INTERRUPT": true, + "SOC_LP_TIMER_BIT_WIDTH_HI": 16, + "SOC_LP_TIMER_BIT_WIDTH_LO": 32, + "SOC_MAC_BB_PD_MEM_SIZE": 192, + "SOC_MEMPROT_CPU_PREFETCH_PAD_SIZE": 16, + "SOC_MEMPROT_MEM_ALIGN_SIZE": 512, + "SOC_MEMPROT_SUPPORTED": true, + "SOC_MEMSPI_IS_INDEPENDENT": true, + "SOC_MEMSPI_SRC_FREQ_20M_SUPPORTED": true, + "SOC_MEMSPI_SRC_FREQ_26M_SUPPORTED": true, + "SOC_MEMSPI_SRC_FREQ_40M_SUPPORTED": true, + "SOC_MEMSPI_SRC_FREQ_80M_SUPPORTED": true, + "SOC_MMU_LINEAR_ADDRESS_REGION_NUM": 1, + "SOC_MMU_PERIPH_NUM": 1, + "SOC_MPI_MEM_BLOCKS_NUM": 4, + "SOC_MPI_OPERATIONS_NUM": 3, + "SOC_MPI_SUPPORTED": true, + "SOC_MPU_MIN_REGION_SIZE": 536870912, + "SOC_MPU_REGIONS_MAX_NUM": 8, + "SOC_MWDT_SUPPORT_XTAL": true, + "SOC_PHY_COMBO_MODULE": true, + "SOC_PHY_DIG_REGS_MEM_SIZE": 21, + "SOC_PHY_SUPPORTED": true, + "SOC_PM_CPU_RETENTION_BY_RTCCNTL": true, + "SOC_PM_MODEM_PD_BY_SW": true, + "SOC_PM_MODEM_RETENTION_BY_BACKUPDMA": true, + "SOC_PM_SUPPORTED": true, + "SOC_PM_SUPPORT_BT_PD": true, + "SOC_PM_SUPPORT_BT_WAKEUP": true, + "SOC_PM_SUPPORT_CPU_PD": true, + "SOC_PM_SUPPORT_MAC_BB_PD": true, + "SOC_PM_SUPPORT_RC_FAST_PD": true, + "SOC_PM_SUPPORT_VDDSDIO_PD": true, + "SOC_PM_SUPPORT_WIFI_PD": true, + "SOC_PM_SUPPORT_WIFI_WAKEUP": true, + "SOC_RMT_CHANNELS_PER_GROUP": 4, + "SOC_RMT_GROUPS": 1, + "SOC_RMT_MEM_WORDS_PER_CHANNEL": 48, + "SOC_RMT_RX_CANDIDATES_PER_GROUP": 2, + "SOC_RMT_SUPPORTED": true, + "SOC_RMT_SUPPORT_APB": true, + "SOC_RMT_SUPPORT_RC_FAST": true, + "SOC_RMT_SUPPORT_RX_DEMODULATION": true, + "SOC_RMT_SUPPORT_RX_PINGPONG": true, + "SOC_RMT_SUPPORT_TX_ASYNC_STOP": true, + "SOC_RMT_SUPPORT_TX_CARRIER_DATA_ONLY": true, + "SOC_RMT_SUPPORT_TX_LOOP_COUNT": true, + "SOC_RMT_SUPPORT_TX_SYNCHRO": true, + "SOC_RMT_SUPPORT_XTAL": true, + "SOC_RMT_TX_CANDIDATES_PER_GROUP": 2, + "SOC_RNG_SUPPORTED": true, + "SOC_RSA_MAX_BIT_LEN": 3072, + "SOC_RTCIO_PIN_COUNT": 0, + "SOC_RTC_CNTL_CPU_PD_DMA_BUS_WIDTH": 128, + "SOC_RTC_CNTL_CPU_PD_REG_FILE_NUM": 108, + "SOC_RTC_FAST_MEM_SUPPORTED": true, + "SOC_RTC_MEM_SUPPORTED": true, + "SOC_RTC_SLOW_CLK_SUPPORT_RC_FAST_D256": true, + "SOC_SDM_CHANNELS_PER_GROUP": 4, + "SOC_SDM_CLK_SUPPORT_APB": true, + "SOC_SDM_GROUPS": 1, + "SOC_SDM_SUPPORTED": true, + "SOC_SECURE_BOOT_SUPPORTED": true, + "SOC_SECURE_BOOT_V2_RSA": true, + "SOC_SHARED_IDCACHE_SUPPORTED": true, + "SOC_SHA_DMA_MAX_BUFFER_SIZE": 3968, + "SOC_SHA_GDMA": true, + "SOC_SHA_SUPPORTED": true, + "SOC_SHA_SUPPORT_DMA": true, + "SOC_SHA_SUPPORT_RESUME": true, + "SOC_SHA_SUPPORT_SHA1": true, + "SOC_SHA_SUPPORT_SHA224": true, + "SOC_SHA_SUPPORT_SHA256": true, + "SOC_SLEEP_SYSTIMER_STALL_WORKAROUND": true, + "SOC_SLEEP_TGWDT_STOP_WORKAROUND": true, + "SOC_SPI_FLASH_SUPPORTED": true, + "SOC_SPI_MAXIMUM_BUFFER_SIZE": 64, + "SOC_SPI_MAX_CS_NUM": 6, + "SOC_SPI_MAX_PRE_DIVIDER": 16, + "SOC_SPI_MEM_SUPPORT_AUTO_RESUME": true, + "SOC_SPI_MEM_SUPPORT_AUTO_SUSPEND": true, + "SOC_SPI_MEM_SUPPORT_AUTO_WAIT_IDLE": true, + "SOC_SPI_MEM_SUPPORT_CHECK_SUS": true, + "SOC_SPI_MEM_SUPPORT_CONFIG_GPIO_BY_EFUSE": true, + "SOC_SPI_MEM_SUPPORT_IDLE_INTR": true, + "SOC_SPI_MEM_SUPPORT_SW_SUSPEND": true, + "SOC_SPI_MEM_SUPPORT_WRAP": true, + "SOC_SPI_PERIPH_NUM": 2, + "SOC_SPI_PERIPH_SUPPORT_CONTROL_DUMMY_OUT": true, + "SOC_SPI_SCT_BUFFER_NUM_MAX": true, + "SOC_SPI_SCT_CONF_BITLEN_MAX": 262138, + "SOC_SPI_SCT_REG_NUM": 14, + "SOC_SPI_SCT_SUPPORTED": true, + "SOC_SPI_SLAVE_SUPPORT_SEG_TRANS": true, + "SOC_SPI_SUPPORT_CD_SIG": true, + "SOC_SPI_SUPPORT_CLK_APB": true, + "SOC_SPI_SUPPORT_CLK_XTAL": true, + "SOC_SPI_SUPPORT_CONTINUOUS_TRANS": true, + "SOC_SPI_SUPPORT_DDRCLK": true, + "SOC_SPI_SUPPORT_SLAVE_HD_VER2": true, + "SOC_SUPPORTS_SECURE_DL_MODE": true, + "SOC_SUPPORT_COEXISTENCE": true, + "SOC_SUPPORT_SECURE_BOOT_REVOKE_KEY": true, + "SOC_SYSTIMER_ALARM_MISS_COMPENSATE": true, + "SOC_SYSTIMER_ALARM_NUM": 3, + "SOC_SYSTIMER_BIT_WIDTH_HI": 20, + "SOC_SYSTIMER_BIT_WIDTH_LO": 32, + "SOC_SYSTIMER_COUNTER_NUM": 2, + "SOC_SYSTIMER_FIXED_DIVIDER": true, + "SOC_SYSTIMER_INT_LEVEL": true, + "SOC_SYSTIMER_SUPPORTED": true, + "SOC_TEMPERATURE_SENSOR_SUPPORT_FAST_RC": true, + "SOC_TEMPERATURE_SENSOR_SUPPORT_XTAL": true, + "SOC_TEMP_SENSOR_SUPPORTED": true, + "SOC_TIMER_GROUPS": 2, + "SOC_TIMER_GROUP_COUNTER_BIT_WIDTH": 54, + "SOC_TIMER_GROUP_SUPPORT_APB": true, + "SOC_TIMER_GROUP_SUPPORT_XTAL": true, + "SOC_TIMER_GROUP_TIMERS_PER_GROUP": 1, + "SOC_TIMER_GROUP_TOTAL_TIMERS": 2, + "SOC_TWAI_BRP_MAX": 16384, + "SOC_TWAI_BRP_MIN": 2, + "SOC_TWAI_CLK_SUPPORT_APB": true, + "SOC_TWAI_CONTROLLER_NUM": 1, + "SOC_TWAI_SUPPORTED": true, + "SOC_TWAI_SUPPORTS_RX_STATUS": true, + "SOC_UART_BITRATE_MAX": 5000000, + "SOC_UART_FIFO_LEN": 128, + "SOC_UART_HP_NUM": 2, + "SOC_UART_NUM": 2, + "SOC_UART_SUPPORTED": true, + "SOC_UART_SUPPORT_APB_CLK": true, + "SOC_UART_SUPPORT_FSM_TX_WAIT_SEND": true, + "SOC_UART_SUPPORT_RTC_CLK": true, + "SOC_UART_SUPPORT_WAKEUP_INT": true, + "SOC_UART_SUPPORT_XTAL_CLK": true, + "SOC_USB_SERIAL_JTAG_SUPPORTED": true, + "SOC_WDT_SUPPORTED": true, + "SOC_WIFI_CSI_SUPPORT": true, + "SOC_WIFI_FTM_SUPPORT": true, + "SOC_WIFI_GCMP_SUPPORT": true, + "SOC_WIFI_HW_TSF": true, + "SOC_WIFI_LIGHT_SLEEP_CLK_WIDTH": 12, + "SOC_WIFI_MESH_SUPPORT": true, + "SOC_WIFI_PHY_NEEDS_USB_WORKAROUND": true, + "SOC_WIFI_SUPPORTED": true, + "SOC_WIFI_SUPPORT_VARIABLE_BEACON_WINDOW": true, + "SOC_WIFI_WAPI_SUPPORT": true, + "SOC_XTAL_SUPPORT_40M": true, + "SOC_XT_WDT_SUPPORTED": true, + "SPIFFS_API_DBG": false, + "SPIFFS_CACHE": true, + "SPIFFS_CACHE_DBG": false, + "SPIFFS_CACHE_STATS": false, + "SPIFFS_CACHE_WR": true, + "SPIFFS_CHECK_DBG": false, + "SPIFFS_DBG": false, + "SPIFFS_FOLLOW_SYMLINKS": false, + "SPIFFS_GC_DBG": false, + "SPIFFS_GC_MAX_RUNS": 10, + "SPIFFS_GC_STATS": false, + "SPIFFS_MAX_PARTITIONS": 3, + "SPIFFS_META_LENGTH": 4, + "SPIFFS_OBJ_NAME_LEN": 32, + "SPIFFS_PAGE_CHECK": true, + "SPIFFS_PAGE_SIZE": 256, + "SPIFFS_TEST_VISUALISATION": false, + "SPIFFS_USE_MAGIC": true, + "SPIFFS_USE_MAGIC_LENGTH": true, + "SPIFFS_USE_MTIME": true, + "SPI_FLASH_AUTO_SUSPEND": false, + "SPI_FLASH_BROWNOUT_RESET": true, + "SPI_FLASH_BROWNOUT_RESET_XMC": true, + "SPI_FLASH_BYPASS_BLOCK_ERASE": false, + "SPI_FLASH_CHECK_ERASE_TIMEOUT_DISABLED": false, + "SPI_FLASH_DANGEROUS_WRITE_ABORTS": true, + "SPI_FLASH_DANGEROUS_WRITE_ALLOWED": false, + "SPI_FLASH_DANGEROUS_WRITE_FAILS": false, + "SPI_FLASH_ENABLE_COUNTERS": false, + "SPI_FLASH_ENABLE_ENCRYPTED_READ_WRITE": true, + "SPI_FLASH_ERASE_YIELD_DURATION_MS": 20, + "SPI_FLASH_ERASE_YIELD_TICKS": 1, + "SPI_FLASH_FORCE_ENABLE_XMC_C_SUSPEND": false, + "SPI_FLASH_OVERRIDE_CHIP_DRIVER_LIST": false, + "SPI_FLASH_ROM_DRIVER_PATCH": true, + "SPI_FLASH_ROM_IMPL": false, + "SPI_FLASH_SIZE_OVERRIDE": false, + "SPI_FLASH_SUPPORT_BOYA_CHIP": true, + "SPI_FLASH_SUPPORT_GD_CHIP": true, + "SPI_FLASH_SUPPORT_ISSI_CHIP": true, + "SPI_FLASH_SUPPORT_MXIC_CHIP": true, + "SPI_FLASH_SUPPORT_TH_CHIP": true, + "SPI_FLASH_SUPPORT_WINBOND_CHIP": true, + "SPI_FLASH_SUSPEND_TSUS_VAL_US": 50, + "SPI_FLASH_VENDOR_BOYA_SUPPORTED": true, + "SPI_FLASH_VENDOR_GD_SUPPORTED": true, + "SPI_FLASH_VENDOR_ISSI_SUPPORTED": true, + "SPI_FLASH_VENDOR_MXIC_SUPPORTED": true, + "SPI_FLASH_VENDOR_TH_SUPPORTED": true, + "SPI_FLASH_VENDOR_WINBOND_SUPPORTED": true, + "SPI_FLASH_VENDOR_XMC_SUPPORTED": true, + "SPI_FLASH_VERIFY_WRITE": false, + "SPI_FLASH_WRITE_CHUNK_SIZE": 8192, + "SPI_FLASH_YIELD_DURING_ERASE": true, + "SPI_MASTER_IN_IRAM": false, + "SPI_MASTER_ISR_IN_IRAM": true, + "SPI_SLAVE_IN_IRAM": false, + "SPI_SLAVE_ISR_IN_IRAM": true, + "TEMP_SENSOR_ENABLE_DEBUG_LOG": false, + "TEMP_SENSOR_SKIP_LEGACY_CONFLICT_CHECK": false, + "TEMP_SENSOR_SUPPRESS_DEPRECATE_WARN": false, + "TWAI_ERRATA_FIX_LISTEN_ONLY_DOM": true, + "TWAI_ISR_IN_IRAM": false, + "UART_HW_FLOWCTRL_CTS_RTS": false, + "UART_HW_FLOWCTRL_DISABLE": true, + "UART_ISR_IN_IRAM": false, + "UNITY_ENABLE_64BIT": false, + "UNITY_ENABLE_BACKTRACE_ON_FAIL": false, + "UNITY_ENABLE_COLOR": false, + "UNITY_ENABLE_DOUBLE": true, + "UNITY_ENABLE_FIXTURE": false, + "UNITY_ENABLE_FLOAT": true, + "UNITY_ENABLE_IDF_TEST_RUNNER": true, + "USJ_ENABLE_USB_SERIAL_JTAG": true, + "VFS_INITIALIZE_DEV_NULL": true, + "VFS_MAX_COUNT": 8, + "VFS_SELECT_IN_RAM": false, + "VFS_SEMIHOSTFS_MAX_MOUNT_POINTS": 1, + "VFS_SUPPORT_DIR": true, + "VFS_SUPPORT_IO": true, + "VFS_SUPPORT_SELECT": true, + "VFS_SUPPORT_TERMIOS": true, + "VFS_SUPPRESS_SELECT_DEBUG_OUTPUT": true, + "WIFI_PROV_AUTOSTOP_TIMEOUT": 30, + "WIFI_PROV_BLE_BONDING": false, + "WIFI_PROV_BLE_FORCE_ENCRYPTION": false, + "WIFI_PROV_BLE_NOTIFY": false, + "WIFI_PROV_BLE_SEC_CONN": true, + "WIFI_PROV_KEEP_BLE_ON_AFTER_PROV": false, + "WIFI_PROV_SCAN_MAX_ENTRIES": 16, + "WIFI_PROV_STA_ALL_CHANNEL_SCAN": true, + "WIFI_PROV_STA_FAST_SCAN": false, + "WL_SECTOR_SIZE": 4096, + "WL_SECTOR_SIZE_4096": true, + "WL_SECTOR_SIZE_512": false, + "WS2812_LED_ENABLE": true, + "WS2812_LED_GPIO": 8, + "WS_BUFFER_SIZE": 1024, + "WS_DYNAMIC_BUFFER": false, + "WS_TRANSPORT": true, + "XTAL_FREQ": 40, + "XTAL_FREQ_40": true +} \ No newline at end of file diff --git a/RainMaker_Table-Lights/build/gdbinit/prefix_map b/RainMaker_Table-Lights/build/gdbinit/prefix_map new file mode 100644 index 000000000..c7842ec17 --- /dev/null +++ b/RainMaker_Table-Lights/build/gdbinit/prefix_map @@ -0,0 +1 @@ +# There is no prefix map defined for the project. diff --git a/RainMaker_Table-Lights/build/kconfigs.in b/RainMaker_Table-Lights/build/kconfigs.in new file mode 100644 index 000000000..63a7ee9b2 --- /dev/null +++ b/RainMaker_Table-Lights/build/kconfigs.in @@ -0,0 +1,89 @@ +source "/home/alex/esp/v5.4.1/esp-idf/components/app_trace/Kconfig" +source "/home/alex/esp/v5.4.1/esp-idf/components/bt/Kconfig" +source "/home/alex/esp/v5.4.1/esp-idf/components/console/Kconfig" +source "/home/alex/esp/v5.4.1/esp-idf/components/driver/Kconfig" +source "/home/alex/esp/v5.4.1/esp-idf/components/efuse/Kconfig" +source "/home/alex/esp/v5.4.1/esp-idf/components/esp-tls/Kconfig" +source "/home/alex/esp/v5.4.1/esp-idf/components/esp_adc/Kconfig" +source "/home/alex/esp/v5.4.1/esp-idf/components/esp_coex/Kconfig" +source "/home/alex/esp/v5.4.1/esp-idf/components/esp_common/Kconfig" +source "/home/alex/esp/v5.4.1/esp-idf/components/esp_driver_ana_cmpr/Kconfig" +source "/home/alex/esp/v5.4.1/esp-idf/components/esp_driver_cam/Kconfig" +source "/home/alex/esp/v5.4.1/esp-idf/components/esp_driver_dac/Kconfig" +source "/home/alex/esp/v5.4.1/esp-idf/components/esp_driver_gpio/Kconfig" +source "/home/alex/esp/v5.4.1/esp-idf/components/esp_driver_gptimer/Kconfig" +source "/home/alex/esp/v5.4.1/esp-idf/components/esp_driver_i2c/Kconfig" +source "/home/alex/esp/v5.4.1/esp-idf/components/esp_driver_i2s/Kconfig" +source "/home/alex/esp/v5.4.1/esp-idf/components/esp_driver_isp/Kconfig" +source "/home/alex/esp/v5.4.1/esp-idf/components/esp_driver_jpeg/Kconfig" +source "/home/alex/esp/v5.4.1/esp-idf/components/esp_driver_ledc/Kconfig" +source "/home/alex/esp/v5.4.1/esp-idf/components/esp_driver_mcpwm/Kconfig" +source "/home/alex/esp/v5.4.1/esp-idf/components/esp_driver_parlio/Kconfig" +source "/home/alex/esp/v5.4.1/esp-idf/components/esp_driver_pcnt/Kconfig" +source "/home/alex/esp/v5.4.1/esp-idf/components/esp_driver_rmt/Kconfig" +source "/home/alex/esp/v5.4.1/esp-idf/components/esp_driver_sdm/Kconfig" +source "/home/alex/esp/v5.4.1/esp-idf/components/esp_driver_spi/Kconfig" +source "/home/alex/esp/v5.4.1/esp-idf/components/esp_driver_touch_sens/Kconfig" +source "/home/alex/esp/v5.4.1/esp-idf/components/esp_driver_tsens/Kconfig" +source "/home/alex/esp/v5.4.1/esp-idf/components/esp_driver_uart/Kconfig" +source "/home/alex/esp/v5.4.1/esp-idf/components/esp_driver_usb_serial_jtag/Kconfig" +source "/home/alex/esp/v5.4.1/esp-idf/components/esp_eth/Kconfig" +source "/home/alex/esp/v5.4.1/esp-idf/components/esp_event/Kconfig" +source "/home/alex/esp/v5.4.1/esp-idf/components/esp_gdbstub/Kconfig" +source "/home/alex/esp/v5.4.1/esp-idf/components/esp_hid/Kconfig" +source "/home/alex/esp/v5.4.1/esp-idf/components/esp_http_client/Kconfig" +source "/home/alex/esp/v5.4.1/esp-idf/components/esp_http_server/Kconfig" +source "/home/alex/esp/v5.4.1/esp-idf/components/esp_https_ota/Kconfig" +source "/home/alex/esp/v5.4.1/esp-idf/components/esp_https_server/Kconfig" +source "/home/alex/esp/v5.4.1/esp-idf/components/esp_hw_support/Kconfig" +source "/home/alex/esp/v5.4.1/esp-idf/components/esp_lcd/Kconfig" +source "/home/alex/esp/v5.4.1/esp-idf/components/esp_mm/Kconfig" +source "/home/alex/esp/v5.4.1/esp-idf/components/esp_netif/Kconfig" +source "/home/alex/esp/v5.4.1/esp-idf/components/esp_partition/Kconfig" +source "/home/alex/esp/v5.4.1/esp-idf/components/esp_phy/Kconfig" +source "/home/alex/esp/v5.4.1/esp-idf/components/esp_pm/Kconfig" +source "/home/alex/esp/v5.4.1/esp-idf/components/esp_psram/Kconfig" +source "/home/alex/esp/v5.4.1/esp-idf/components/esp_ringbuf/Kconfig" +source "/home/alex/esp/v5.4.1/esp-idf/components/esp_security/Kconfig" +source "/home/alex/esp/v5.4.1/esp-idf/components/esp_system/Kconfig" +source "/home/alex/esp/v5.4.1/esp-idf/components/esp_timer/Kconfig" +source "/home/alex/esp/v5.4.1/esp-idf/components/esp_wifi/Kconfig" +source "/home/alex/esp/v5.4.1/esp-idf/components/espcoredump/Kconfig" +source "/home/alex/esp/v5.4.1/esp-idf/components/fatfs/Kconfig" +source "/home/alex/esp/v5.4.1/esp-idf/components/freertos/Kconfig" +source "/home/alex/esp/v5.4.1/esp-idf/components/hal/Kconfig" +source "/home/alex/esp/v5.4.1/esp-idf/components/heap/Kconfig" +source "/home/alex/esp/v5.4.1/esp-idf/components/ieee802154/Kconfig" +source "/home/alex/esp/v5.4.1/esp-idf/components/log/Kconfig" +source "/home/alex/esp/v5.4.1/esp-idf/components/lwip/Kconfig" +source "/home/alex/esp/v5.4.1/esp-idf/components/mbedtls/Kconfig" +source "/home/alex/esp/v5.4.1/esp-idf/components/mqtt/esp-mqtt/Kconfig" +source "/home/alex/esp/v5.4.1/esp-idf/components/newlib/Kconfig" +source "/home/alex/esp/v5.4.1/esp-idf/components/nvs_flash/Kconfig" +source "/home/alex/esp/v5.4.1/esp-idf/components/nvs_sec_provider/Kconfig" +source "/home/alex/esp/v5.4.1/esp-idf/components/openthread/Kconfig" +source "/home/alex/esp/v5.4.1/esp-idf/components/protocomm/Kconfig" +source "/home/alex/esp/v5.4.1/esp-idf/components/pthread/Kconfig" +source "/home/alex/esp/v5.4.1/esp-idf/components/soc/Kconfig" +source "/home/alex/esp/v5.4.1/esp-idf/components/spi_flash/Kconfig" +source "/home/alex/esp/v5.4.1/esp-idf/components/spiffs/Kconfig" +source "/home/alex/esp/v5.4.1/esp-idf/components/tcp_transport/Kconfig" +source "/home/alex/esp/v5.4.1/esp-idf/components/ulp/Kconfig" +source "/home/alex/esp/v5.4.1/esp-idf/components/unity/Kconfig" +source "/home/alex/esp/v5.4.1/esp-idf/components/usb/Kconfig" +source "/home/alex/esp/v5.4.1/esp-idf/components/vfs/Kconfig" +source "/home/alex/esp/v5.4.1/esp-idf/components/wear_levelling/Kconfig" +source "/home/alex/esp/v5.4.1/esp-idf/components/wifi_provisioning/Kconfig" +source "/home/alex/.espressif/esp-rainmaker/examples/common/app_insights/Kconfig" +source "/home/alex/.espressif/esp-rainmaker/examples/common/gpio_button/Kconfig" +source "/home/alex/.espressif/esp-rainmaker/examples/common/ws2812_led/Kconfig" +source "/home/alex/github/ESP-Nodes/RainMaker_Table-Lights/managed_components/espressif__esp-serial-flasher/Kconfig" +source "/home/alex/github/ESP-Nodes/RainMaker_Table-Lights/managed_components/espressif__esp_diag_data_store/Kconfig" +source "/home/alex/github/ESP-Nodes/RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/Kconfig" +source "/home/alex/github/ESP-Nodes/RainMaker_Table-Lights/managed_components/espressif__esp_insights/Kconfig" +source "/home/alex/github/ESP-Nodes/RainMaker_Table-Lights/managed_components/espressif__esp_rcp_update/Kconfig" +source "/home/alex/github/ESP-Nodes/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/Kconfig" +source "/home/alex/github/ESP-Nodes/RainMaker_Table-Lights/managed_components/espressif__jsmn/Kconfig" +source "/home/alex/github/ESP-Nodes/RainMaker_Table-Lights/managed_components/espressif__mdns/Kconfig" +source "/home/alex/github/ESP-Nodes/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/Kconfig" +source "/home/alex/github/ESP-Nodes/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/Kconfig" \ No newline at end of file diff --git a/RainMaker_Table-Lights/build/kconfigs_projbuild.in b/RainMaker_Table-Lights/build/kconfigs_projbuild.in new file mode 100644 index 000000000..fada0bfdb --- /dev/null +++ b/RainMaker_Table-Lights/build/kconfigs_projbuild.in @@ -0,0 +1,8 @@ +source "/home/alex/esp/v5.4.1/esp-idf/components/bootloader/Kconfig.projbuild" +source "/home/alex/esp/v5.4.1/esp-idf/components/esp_app_format/Kconfig.projbuild" +source "/home/alex/esp/v5.4.1/esp-idf/components/esp_rom/Kconfig.projbuild" +source "/home/alex/esp/v5.4.1/esp-idf/components/esptool_py/Kconfig.projbuild" +source "/home/alex/esp/v5.4.1/esp-idf/components/partition_table/Kconfig.projbuild" +source "/home/alex/github/ESP-Nodes/RainMaker_Table-Lights/main/Kconfig.projbuild" +source "/home/alex/.espressif/esp-rainmaker/examples/common/app_network/Kconfig.projbuild" +source "/home/alex/.espressif/esp-rainmaker/components/esp_rainmaker/Kconfig.projbuild" \ No newline at end of file diff --git a/RainMaker_Table-Lights/build/local_components_list.temp.yml b/RainMaker_Table-Lights/build/local_components_list.temp.yml deleted file mode 100644 index aa62d5cb5..000000000 --- a/RainMaker_Table-Lights/build/local_components_list.temp.yml +++ /dev/null @@ -1,225 +0,0 @@ -components: - - name: "app_trace" - path: "/home/alex/esp/v5.4.1/esp-idf/components/app_trace" - - name: "app_update" - path: "/home/alex/esp/v5.4.1/esp-idf/components/app_update" - - name: "bootloader" - path: "/home/alex/esp/v5.4.1/esp-idf/components/bootloader" - - name: "bootloader_support" - path: "/home/alex/esp/v5.4.1/esp-idf/components/bootloader_support" - - name: "bt" - path: "/home/alex/esp/v5.4.1/esp-idf/components/bt" - - name: "cmock" - path: "/home/alex/esp/v5.4.1/esp-idf/components/cmock" - - name: "console" - path: "/home/alex/esp/v5.4.1/esp-idf/components/console" - - name: "cxx" - path: "/home/alex/esp/v5.4.1/esp-idf/components/cxx" - - name: "driver" - path: "/home/alex/esp/v5.4.1/esp-idf/components/driver" - - name: "efuse" - path: "/home/alex/esp/v5.4.1/esp-idf/components/efuse" - - name: "esp-tls" - path: "/home/alex/esp/v5.4.1/esp-idf/components/esp-tls" - - name: "esp_adc" - path: "/home/alex/esp/v5.4.1/esp-idf/components/esp_adc" - - name: "esp_app_format" - path: "/home/alex/esp/v5.4.1/esp-idf/components/esp_app_format" - - name: "esp_bootloader_format" - path: "/home/alex/esp/v5.4.1/esp-idf/components/esp_bootloader_format" - - name: "esp_coex" - path: "/home/alex/esp/v5.4.1/esp-idf/components/esp_coex" - - name: "esp_common" - path: "/home/alex/esp/v5.4.1/esp-idf/components/esp_common" - - name: "esp_driver_ana_cmpr" - path: "/home/alex/esp/v5.4.1/esp-idf/components/esp_driver_ana_cmpr" - - name: "esp_driver_cam" - path: "/home/alex/esp/v5.4.1/esp-idf/components/esp_driver_cam" - - name: "esp_driver_dac" - path: "/home/alex/esp/v5.4.1/esp-idf/components/esp_driver_dac" - - name: "esp_driver_gpio" - path: "/home/alex/esp/v5.4.1/esp-idf/components/esp_driver_gpio" - - name: "esp_driver_gptimer" - path: "/home/alex/esp/v5.4.1/esp-idf/components/esp_driver_gptimer" - - name: "esp_driver_i2c" - path: "/home/alex/esp/v5.4.1/esp-idf/components/esp_driver_i2c" - - name: "esp_driver_i2s" - path: "/home/alex/esp/v5.4.1/esp-idf/components/esp_driver_i2s" - - name: "esp_driver_isp" - path: "/home/alex/esp/v5.4.1/esp-idf/components/esp_driver_isp" - - name: "esp_driver_jpeg" - path: "/home/alex/esp/v5.4.1/esp-idf/components/esp_driver_jpeg" - - name: "esp_driver_ledc" - path: "/home/alex/esp/v5.4.1/esp-idf/components/esp_driver_ledc" - - name: "esp_driver_mcpwm" - path: "/home/alex/esp/v5.4.1/esp-idf/components/esp_driver_mcpwm" - - name: "esp_driver_parlio" - path: "/home/alex/esp/v5.4.1/esp-idf/components/esp_driver_parlio" - - name: "esp_driver_pcnt" - path: "/home/alex/esp/v5.4.1/esp-idf/components/esp_driver_pcnt" - - name: "esp_driver_ppa" - path: "/home/alex/esp/v5.4.1/esp-idf/components/esp_driver_ppa" - - name: "esp_driver_rmt" - path: "/home/alex/esp/v5.4.1/esp-idf/components/esp_driver_rmt" - - name: "esp_driver_sdio" - path: "/home/alex/esp/v5.4.1/esp-idf/components/esp_driver_sdio" - - name: "esp_driver_sdm" - path: "/home/alex/esp/v5.4.1/esp-idf/components/esp_driver_sdm" - - name: "esp_driver_sdmmc" - path: "/home/alex/esp/v5.4.1/esp-idf/components/esp_driver_sdmmc" - - name: "esp_driver_sdspi" - path: "/home/alex/esp/v5.4.1/esp-idf/components/esp_driver_sdspi" - - name: "esp_driver_spi" - path: "/home/alex/esp/v5.4.1/esp-idf/components/esp_driver_spi" - - name: "esp_driver_touch_sens" - path: "/home/alex/esp/v5.4.1/esp-idf/components/esp_driver_touch_sens" - - name: "esp_driver_tsens" - path: "/home/alex/esp/v5.4.1/esp-idf/components/esp_driver_tsens" - - name: "esp_driver_uart" - path: "/home/alex/esp/v5.4.1/esp-idf/components/esp_driver_uart" - - name: "esp_driver_usb_serial_jtag" - path: "/home/alex/esp/v5.4.1/esp-idf/components/esp_driver_usb_serial_jtag" - - name: "esp_eth" - path: "/home/alex/esp/v5.4.1/esp-idf/components/esp_eth" - - name: "esp_event" - path: "/home/alex/esp/v5.4.1/esp-idf/components/esp_event" - - name: "esp_gdbstub" - path: "/home/alex/esp/v5.4.1/esp-idf/components/esp_gdbstub" - - name: "esp_hid" - path: "/home/alex/esp/v5.4.1/esp-idf/components/esp_hid" - - name: "esp_http_client" - path: "/home/alex/esp/v5.4.1/esp-idf/components/esp_http_client" - - name: "esp_http_server" - path: "/home/alex/esp/v5.4.1/esp-idf/components/esp_http_server" - - name: "esp_https_ota" - path: "/home/alex/esp/v5.4.1/esp-idf/components/esp_https_ota" - - name: "esp_https_server" - path: "/home/alex/esp/v5.4.1/esp-idf/components/esp_https_server" - - name: "esp_hw_support" - path: "/home/alex/esp/v5.4.1/esp-idf/components/esp_hw_support" - - name: "esp_lcd" - path: "/home/alex/esp/v5.4.1/esp-idf/components/esp_lcd" - - name: "esp_local_ctrl" - path: "/home/alex/esp/v5.4.1/esp-idf/components/esp_local_ctrl" - - name: "esp_mm" - path: "/home/alex/esp/v5.4.1/esp-idf/components/esp_mm" - - name: "esp_netif" - path: "/home/alex/esp/v5.4.1/esp-idf/components/esp_netif" - - name: "esp_netif_stack" - path: "/home/alex/esp/v5.4.1/esp-idf/components/esp_netif_stack" - - name: "esp_partition" - path: "/home/alex/esp/v5.4.1/esp-idf/components/esp_partition" - - name: "esp_phy" - path: "/home/alex/esp/v5.4.1/esp-idf/components/esp_phy" - - name: "esp_pm" - path: "/home/alex/esp/v5.4.1/esp-idf/components/esp_pm" - - name: "esp_psram" - path: "/home/alex/esp/v5.4.1/esp-idf/components/esp_psram" - - name: "esp_ringbuf" - path: "/home/alex/esp/v5.4.1/esp-idf/components/esp_ringbuf" - - name: "esp_rom" - path: "/home/alex/esp/v5.4.1/esp-idf/components/esp_rom" - - name: "esp_security" - path: "/home/alex/esp/v5.4.1/esp-idf/components/esp_security" - - name: "esp_system" - path: "/home/alex/esp/v5.4.1/esp-idf/components/esp_system" - - name: "esp_timer" - path: "/home/alex/esp/v5.4.1/esp-idf/components/esp_timer" - - name: "esp_vfs_console" - path: "/home/alex/esp/v5.4.1/esp-idf/components/esp_vfs_console" - - name: "esp_wifi" - path: "/home/alex/esp/v5.4.1/esp-idf/components/esp_wifi" - - name: "espcoredump" - path: "/home/alex/esp/v5.4.1/esp-idf/components/espcoredump" - - name: "esptool_py" - path: "/home/alex/esp/v5.4.1/esp-idf/components/esptool_py" - - name: "fatfs" - path: "/home/alex/esp/v5.4.1/esp-idf/components/fatfs" - - name: "freertos" - path: "/home/alex/esp/v5.4.1/esp-idf/components/freertos" - - name: "hal" - path: "/home/alex/esp/v5.4.1/esp-idf/components/hal" - - name: "heap" - path: "/home/alex/esp/v5.4.1/esp-idf/components/heap" - - name: "http_parser" - path: "/home/alex/esp/v5.4.1/esp-idf/components/http_parser" - - name: "idf_test" - path: "/home/alex/esp/v5.4.1/esp-idf/components/idf_test" - - name: "ieee802154" - path: "/home/alex/esp/v5.4.1/esp-idf/components/ieee802154" - - name: "json" - path: "/home/alex/esp/v5.4.1/esp-idf/components/json" - - name: "linux" - path: "/home/alex/esp/v5.4.1/esp-idf/components/linux" - - name: "log" - path: "/home/alex/esp/v5.4.1/esp-idf/components/log" - - name: "lwip" - path: "/home/alex/esp/v5.4.1/esp-idf/components/lwip" - - name: "mbedtls" - path: "/home/alex/esp/v5.4.1/esp-idf/components/mbedtls" - - name: "mqtt" - path: "/home/alex/esp/v5.4.1/esp-idf/components/mqtt" - - name: "newlib" - path: "/home/alex/esp/v5.4.1/esp-idf/components/newlib" - - name: "nvs_flash" - path: "/home/alex/esp/v5.4.1/esp-idf/components/nvs_flash" - - name: "nvs_sec_provider" - path: "/home/alex/esp/v5.4.1/esp-idf/components/nvs_sec_provider" - - name: "openthread" - path: "/home/alex/esp/v5.4.1/esp-idf/components/openthread" - - name: "partition_table" - path: "/home/alex/esp/v5.4.1/esp-idf/components/partition_table" - - name: "perfmon" - path: "/home/alex/esp/v5.4.1/esp-idf/components/perfmon" - - name: "protobuf-c" - path: "/home/alex/esp/v5.4.1/esp-idf/components/protobuf-c" - - name: "protocomm" - path: "/home/alex/esp/v5.4.1/esp-idf/components/protocomm" - - name: "pthread" - path: "/home/alex/esp/v5.4.1/esp-idf/components/pthread" - - name: "riscv" - path: "/home/alex/esp/v5.4.1/esp-idf/components/riscv" - - name: "rt" - path: "/home/alex/esp/v5.4.1/esp-idf/components/rt" - - name: "sdmmc" - path: "/home/alex/esp/v5.4.1/esp-idf/components/sdmmc" - - name: "soc" - path: "/home/alex/esp/v5.4.1/esp-idf/components/soc" - - name: "spi_flash" - path: "/home/alex/esp/v5.4.1/esp-idf/components/spi_flash" - - name: "spiffs" - path: "/home/alex/esp/v5.4.1/esp-idf/components/spiffs" - - name: "tcp_transport" - path: "/home/alex/esp/v5.4.1/esp-idf/components/tcp_transport" - - name: "touch_element" - path: "/home/alex/esp/v5.4.1/esp-idf/components/touch_element" - - name: "ulp" - path: "/home/alex/esp/v5.4.1/esp-idf/components/ulp" - - name: "unity" - path: "/home/alex/esp/v5.4.1/esp-idf/components/unity" - - name: "usb" - path: "/home/alex/esp/v5.4.1/esp-idf/components/usb" - - name: "vfs" - path: "/home/alex/esp/v5.4.1/esp-idf/components/vfs" - - name: "wear_levelling" - path: "/home/alex/esp/v5.4.1/esp-idf/components/wear_levelling" - - name: "wifi_provisioning" - path: "/home/alex/esp/v5.4.1/esp-idf/components/wifi_provisioning" - - name: "wpa_supplicant" - path: "/home/alex/esp/v5.4.1/esp-idf/components/wpa_supplicant" - - name: "xtensa" - path: "/home/alex/esp/v5.4.1/esp-idf/components/xtensa" - - name: "main" - path: "/home/alex/github/ESP-Nodes/RainMaker_Table-Lights/main" - - name: "app_insights" - path: "/home/alex/.espressif/esp-rainmaker/examples/common/app_insights" - - name: "app_network" - path: "/home/alex/.espressif/esp-rainmaker/examples/common/app_network" - - name: "app_reset" - path: "/home/alex/.espressif/esp-rainmaker/examples/common/app_reset" - - name: "gpio_button" - path: "/home/alex/.espressif/esp-rainmaker/examples/common/gpio_button" - - name: "ledc_driver" - path: "/home/alex/.espressif/esp-rainmaker/examples/common/ledc_driver" - - name: "ws2812_led" - path: "/home/alex/.espressif/esp-rainmaker/examples/common/ws2812_led" diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/.component_hash b/RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/.component_hash new file mode 100644 index 000000000..6c9ad798c --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/.component_hash @@ -0,0 +1 @@ +b6ae5ae71264612d3742ef91e3f44092ae98060feecddd70e04f26bdc172cded \ No newline at end of file diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/CHECKSUMS.json b/RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/CHECKSUMS.json new file mode 100644 index 000000000..3c211c805 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/CHECKSUMS.json @@ -0,0 +1 @@ +{"version": "1.0", "algorithm": "sha256", "created_at": "2025-05-30T12:44:52.431051+00:00", "files": [{"path": "CMakeLists.txt", "size": 1796, "hash": "8a508fb5023a0899df0da80a887008bf5e76e5ff2424f12ba10bcb5ed574d666"}, {"path": "Kconfig", "size": 5692, "hash": "c1f95ec2df707d3b7b9bbe8ababd1ed7505ac7d58b370ad2863c60873b672f12"}, {"path": "LICENSE", "size": 11358, "hash": "cfc7749b96f63bd31c3c42b5c471bf756814053e847c10f3eb003417bc523d30"}, {"path": "README.md", "size": 327, "hash": "8fed44792908fbe8876d0fc31ebbb4fea047da693f656343ae4afa62e2ff8abc"}, {"path": "idf_component.yml", "size": 557, "hash": "20ec0f5b6f6041118b24f05d1d91f801fd17624640fd26c84451fcb14556daea"}, {"path": "include/esp_diagnostics.h", "size": 12531, "hash": "6863c63f8018608857bb1a374c35a24d69b8d25c7f576142f9c4c566d9087d24"}, {"path": "include/esp_diagnostics_metrics.h", "size": 9383, "hash": "63923d3f95654dc87eb325ca4b0cc38aa0af21b60f5f846cff3c8a7f44d33e38"}, {"path": "include/esp_diagnostics_network_variables.h", "size": 798, "hash": "9df14b8dee1a265932162a2ffa374cb5f342ad4b68702b031aa2dffcad19f61e"}, {"path": "include/esp_diagnostics_system_metrics.h", "size": 3153, "hash": "e807dd4c3292af2961073e31f11f245a811777696471d37a8698202f9f106c20"}, {"path": "include/esp_diagnostics_variables.h", "size": 10260, "hash": "6989111538e4fc272785661eb4474ffaa713be9f94b678a851da21d357b7434e"}, {"path": "src/esp_diagnostics_heap_metrics.c", "size": 9956, "hash": "ad56f049c25c557851e6c2c5c1b9c31e2f19d8be5749b229fa1379666069f6cd"}, {"path": "src/esp_diagnostics_internal.h", "size": 696, "hash": "6d0e13d39bd2517ec7f79ab9add4c963bc13c04a1854525fd119374a5c370e40"}, {"path": "src/esp_diagnostics_log_hook.c", "size": 17422, "hash": "d3a9d79c96e8d4019d53eb3f83e7140cb8eed8185ed1351369fdb776e223e6d7"}, {"path": "src/esp_diagnostics_metrics.c", "size": 11033, "hash": "4f4670042323c6475deeb965f38141e172f3ae395c0c4ed18c4fe8f7b54a5f97"}, {"path": "src/esp_diagnostics_network_variables.c", "size": 14862, "hash": "fac3f922554ab0ac01e43b2131e5847d55e3a493769a0de6bb0e7e7b38d3226f"}, {"path": "src/esp_diagnostics_utils.c", "size": 15990, "hash": "dab3d80d4f93c70315fadd48934c631f3b0ff0bbc3a4388cb078ba9bb9552bf0"}, {"path": "src/esp_diagnostics_variables.c", "size": 11063, "hash": "5a56a467e267490a1fc3cddbcdfdf25dc4c9b72e4502586427dc646212eba516"}, {"path": "src/esp_diagnostics_wifi_metrics.c", "size": 8173, "hash": "98c21faccdb27e7bbfc92c5783f4d430d3754d290159a6da03de69ca1f10728f"}]} \ No newline at end of file diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/CMakeLists.txt b/RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/CMakeLists.txt new file mode 100644 index 000000000..9d9b2c875 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/CMakeLists.txt @@ -0,0 +1,52 @@ +set(srcs "src/esp_diagnostics_log_hook.c" + "src/esp_diagnostics_utils.c") + +if(CONFIG_DIAG_ENABLE_METRICS) + list(APPEND srcs "src/esp_diagnostics_metrics.c") + if(CONFIG_DIAG_ENABLE_HEAP_METRICS) + list(APPEND srcs "src/esp_diagnostics_heap_metrics.c") + endif() + if(CONFIG_DIAG_ENABLE_WIFI_METRICS) + list(APPEND srcs "src/esp_diagnostics_wifi_metrics.c") + endif() +endif() + +if(CONFIG_DIAG_ENABLE_VARIABLES) + list(APPEND srcs "src/esp_diagnostics_variables.c") + if(CONFIG_DIAG_ENABLE_NETWORK_VARIABLES) + list(APPEND srcs "src/esp_diagnostics_network_variables.c") + endif() +endif() + +set(priv_req freertos app_update rmaker_common) + +# esp_hw_support component was introduced in v4.3 +if("${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}" VERSION_GREATER "4.2") + list(APPEND priv_req esp_hw_support) +endif() + +# from IDF version 5.0, we need to explicitly specify requirements +if("${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}" VERSION_GREATER_EQUAL "5.0") + list(APPEND priv_req esp_wifi esp_event) +endif() + +idf_component_register(SRCS "${srcs}" + INCLUDE_DIRS "include" + PRIV_REQUIRES ${priv_req}) + +# Only wrap the log functions if ESP-INSIGHTS is enabled +if(CONFIG_DIAG_ENABLE_WRAP_LOG_FUNCTIONS) + # If log level is set to NONE or if logging APIs are externally wrapped then skip + # wrapping logging APIs here + if ((NOT CONFIG_LOG_DEFAULT_LEVEL_NONE) AND (NOT CONFIG_DIAG_USE_EXTERNAL_LOG_WRAP)) + list(APPEND WRAP_FUNCTIONS esp_log_write esp_log_writev) + endif() + + if(CONFIG_LIB_BUILDER_COMPILE) + list(APPEND WRAP_FUNCTIONS log_printf) + endif() + + foreach(func ${WRAP_FUNCTIONS}) + target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=${func}") + endforeach() +endif() diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/Kconfig b/RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/Kconfig new file mode 100644 index 000000000..faa7efefe --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/Kconfig @@ -0,0 +1,134 @@ +menu "Diagnostics" + choice DIAG_LOG_MSG_ARG_FORMAT + prompt "Diagnostics log argument format" + default DIAG_LOG_MSG_ARG_FORMAT_TLV + help + For error/warning/event logs, diagnostics module collects program counter, timestamp, + tag, RO data pointer and log arguments. Log arguments are stored in statically allocated buffer. + This option configures how to format and store log arguments in buffer. + Log arguments can be formatted as TLV or complete log string formatted using vsnprintf. + + If "TLV" is selected, buffer contains arguments formatted as TLV. + Type - 1 byte for the type of argument, please check esp_diag_arg_type_t. + Length - 1 byte for the size of argument, size is calculated using sizeof operator. + Value - Size bytes for the value. + + If "STRING" is selected, buffer contains the entire string formatted using vsnprintf. + + config DIAG_LOG_MSG_ARG_FORMAT_TLV + bool "Format arguments as TLV" + config DIAG_LOG_MSG_ARG_FORMAT_STRING + bool "Format arguments as string" + endchoice + + config DIAG_LOG_MSG_ARG_MAX_SIZE + int "Maximum size of diagnostics log argument buffer" + range 32 255 + default 64 + help + Log arguments are stored in a static allocated buffer. + This option configures the maximum size of buffer for storing log arguments. + + config DIAG_LOG_DROP_WIFI_LOGS + bool "Drop Wi-Fi logs" + default y + help + Every Wi-Fi log printed on the console adds three diagnostics logs. + For some users, Wi-Fi logs may not be that useful. + By default, diagnostics drops Wi-Fi logs. Set this config option to "n" for recording Wi-Fi logs. + + config DIAG_ENABLE_WRAP_LOG_FUNCTIONS + bool "Enable wrapping of log functions" + default n + help + This option enables wrapping of esp_log_write and esp_log_writev APIs using `--wrap` gcc option. + Enable this option when direct log access is required. + + Note: This option is automatically selected when ESP Insights is enabled. + + config DIAG_ENABLE_METRICS + bool "Enable diagnostics metrics" + default y + help + Diagnostics module supports recording and reporting metrics to cloud. + This option enables the diagnostics metrics and related functionality. + + config DIAG_METRICS_MAX_COUNT + depends on DIAG_ENABLE_METRICS + int "Maximum number of metrics" + default 20 + help + This option configures the maximum number of metrics that can be registered. + + config DIAG_ENABLE_HEAP_METRICS + depends on DIAG_ENABLE_METRICS + bool "Enable Heap Metrics" + default y + help + Enables the heap memory metrics. This collects free memory, largest free block, + and minimum free memory for heaps in internal as well as external memory. + + config DIAG_HEAP_POLLING_INTERVAL + depends on DIAG_ENABLE_HEAP_METRICS + int "Heap metrics polling interval in seconds" + range 30 86400 + default 30 + help + This option configures the time interval in seconds at which heap metrics are collected. + Minimum allowed value is 30 seconds and maximum is 24 hours (86400 seconds). + + config DIAG_ENABLE_WIFI_METRICS + depends on DIAG_ENABLE_METRICS + bool "Enable Wi-Fi Metrics" + default y + help + Enables Wi-Fi metrics and collects Wi-Fi RSSI and minumum ever Wi-Fi RSSI. + + config DIAG_WIFI_POLLING_INTERVAL + depends on DIAG_ENABLE_WIFI_METRICS + int "Wi-Fi metrics polling interval in seconds" + range 30 86400 + default 30 + help + This option configures the time interval in seconds at which Wi-Fi metrics are collected. + Minimum allowed value is 30 seconds and maximum is 24 hours (86400 seconds). + + config DIAG_ENABLE_VARIABLES + bool "Enable diagnostics variables" + default y + help + Variables are similar to metrics but they represent entities where their current value + is much more important than over a period of time. + This option enables the diagnostics variables and related functionality + + config DIAG_VARIABLES_MAX_COUNT + depends on DIAG_ENABLE_VARIABLES + int "Maximum number of variables" + default 20 + help + This option configures the maximum number of variables that can be registered. + + config DIAG_ENABLE_NETWORK_VARIABLES + depends on DIAG_ENABLE_VARIABLES + bool "Enable Network variables" + default y + help + Enables the Wi-Fi and IP address variables. Below variables are collected. + For Wi-Fi: SSID, BSSID, channel, auth mode, connection status, disconnection reason. + For IP: IPv4 address, netmask, and gateway of the device. + + config DIAG_MORE_NETWORK_VARS + depends on DIAG_ENABLE_NETWORK_VARIABLES + bool "Enable More Advanced Network variables" + default n + help + Enable more advanced network variables + + config DIAG_USE_EXTERNAL_LOG_WRAP + bool "Use external log wrapper" + default n + help + Diagnostics component wraps the esp_log_write and esp_log_writev APIs using `--wrap` gcc option. + There can be scenario where another component also wants to wrap the logging functions. + In that case, enable this option and use the data ingestion APIs esp_diag_log_write and esp_diag_log_writev. +endmenu diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/LICENSE b/RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/README.md b/RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/README.md new file mode 100644 index 000000000..3cc5eee08 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/README.md @@ -0,0 +1,5 @@ +# ESP Diagnostics Component + +[![Component Registry](https://components.espressif.com/components/espressif/esp_diagnostics/badge.svg)](https://components.espressif.com/components/espressif/esp_diagnostics) + +This component provides the diagnostics functionality used by [ESP Insights](https://github.com/espressif/esp-insights). diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/idf_component.yml b/RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/idf_component.yml new file mode 100644 index 000000000..8596c0e33 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/idf_component.yml @@ -0,0 +1,14 @@ +dependencies: + espressif/rmaker_common: + version: ~1.4.0 + idf: + version: '>=4.1' +description: Diagnostics component used in ESP Insights, which is a remote diagnostics + solution to monitor the health of ESP devices in the field. +issues: https://github.com/espressif/esp-insights/issues +repository: git://github.com/espressif/esp-insights.git +repository_info: + commit_sha: b043f72425dadf58095847125404426bc2d4cba8 + path: components/esp_diagnostics +url: https://github.com/espressif/esp-insights/tree/main/components/esp_diagnostics +version: 1.2.3 diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/include/esp_diagnostics.h b/RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/include/esp_diagnostics.h new file mode 100644 index 000000000..6887ea0ca --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/include/esp_diagnostics.h @@ -0,0 +1,339 @@ +/* + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Callback to write log to diagnostics storage + */ +typedef esp_err_t (*esp_diag_log_write_cb_t)(void *data, size_t len, void *priv_data); + +/** + * @brief Diagnostics log configurations + */ +typedef struct { + esp_diag_log_write_cb_t write_cb; /*!< Callback function to write diagnostics data */ + void *cb_arg; /*!< User data to pass in callback function */ +} esp_diag_log_config_t; + +/** + * @brief Supported log types in diagnostics + */ +typedef enum { + ESP_DIAG_LOG_TYPE_ERROR = 1 << 0, /*!< Diagnostics log type error */ + ESP_DIAG_LOG_TYPE_WARNING = 1 << 1, /*!< Diagnostics log type warning */ + ESP_DIAG_LOG_TYPE_EVENT = 1 << 2, /*!< Diagnostics log type event */ +} esp_diag_log_type_t; + +/** + * @brief Log argument data types + */ +typedef enum { + ARG_TYPE_CHAR, /*!< Argument type (char) */ + ARG_TYPE_SHORT, /*!< Argument type (short) */ + ARG_TYPE_INT, /*!< Argument type (int) */ + ARG_TYPE_L, /*!< Argument type (long) */ + ARG_TYPE_LL, /*!< Argument type (long long) */ + ARG_TYPE_INTMAX, /*!< Argument type (intmax_t) */ + ARG_TYPE_PTRDIFF, /*!< Argument type (ptrdiff_t) */ + ARG_TYPE_UCHAR, /*!< Argument type (unsigned char) */ + ARG_TYPE_USHORT, /*!< Argument type (unsigned short) */ + ARG_TYPE_UINT, /*!< Argument type (unsigned int) */ + ARG_TYPE_UL, /*!< Argument type (unsigned long) */ + ARG_TYPE_ULL, /*!< Argument type (unsigned long long) */ + ARG_TYPE_UINTMAX, /*!< Argument type (uintmax_t) */ + ARG_TYPE_SIZE, /*!< Argument type (size_t) */ + ARG_TYPE_DOUBLE, /*!< Argument type (double) */ + ARG_TYPE_LDOUBLE, /*!< Argument type (long double) */ + ARG_TYPE_STR, /*!< Argument type (char *) */ + ARG_TYPE_INVALID, /*!< Argument type invalid */ +} esp_diag_arg_type_t; + +/** + * @brief Log argument data value + */ +typedef union { + char c; /*!< Value of type signed char */ + short s; /*!< Value of type signed short */ + int i; /*!< Value of type signed integer */ + long l; /*!< Value of type signed long */ + long long ll; /*!< Value of type signed long long */ + intmax_t imx; /*!< Value of type intmax_t */ + ptrdiff_t ptrdiff; /*!< Value of type ptrdiff_t */ + unsigned char uc; /*!< Value of type unsigned char */ + unsigned short us; /*!< Value of type unsigned short */ + unsigned int u; /*!< Value of type unsigned integer */ + unsigned long ul; /*!< Value of type unsigned long */ + unsigned long long ull; /*!< Value of type unsigned long long */ + uintmax_t umx; /*!< Value of type uintmax_t */ + size_t sz; /*!< Value of type size_t */ + double d; /*!< Value of type double */ + long double ld; /*!< Value of type long double */ + char *str; /*!< value of type string */ +} esp_diag_arg_value_t; + +/** + * @brief Diagnostics data point type + */ +typedef enum { + ESP_DIAG_DATA_PT_METRICS, /*!< Data point of type metrics */ + ESP_DIAG_DATA_PT_VARIABLE, /*!< Data point of type variable */ +} esp_diag_data_pt_type_t; + +/** + * @brief Diagnostics data types + */ +typedef enum { + ESP_DIAG_DATA_TYPE_BOOL, /*!< Data type boolean */ + ESP_DIAG_DATA_TYPE_INT, /*!< Data type integer */ + ESP_DIAG_DATA_TYPE_UINT, /*!< Data type unsigned integer */ + ESP_DIAG_DATA_TYPE_FLOAT, /*!< Data type float */ + ESP_DIAG_DATA_TYPE_STR, /*!< Data type string */ + ESP_DIAG_DATA_TYPE_IPv4, /*!< Data type IPv4 address */ + ESP_DIAG_DATA_TYPE_MAC, /*!< Data type MAC address */ + ESP_DIAG_DATA_TYPE_NULL, /*!< No type */ + ESP_DIAG_DATA_TYPE_MAX, /*!< Max type */ +} esp_diag_data_type_t; + +/** + * @brief Diagnostics log data structure + */ +typedef struct { + esp_diag_log_type_t type; /*!< Type of diagnostics log */ + uint32_t pc; /*!< Program Counter */ + uint64_t timestamp; /*!< If NTP sync enabled then POSIX time, + otherwise relative time since bootup in microseconds */ + char tag[16]; /*!< Tag of log message */ + void *msg_ptr; /*!< Address of err/warn/event message in rodata */ + uint8_t msg_args[CONFIG_DIAG_LOG_MSG_ARG_MAX_SIZE]; /*!< Arguments of log message */ + uint8_t msg_args_len; /*!< Length of argument */ + char task_name[CONFIG_FREERTOS_MAX_TASK_NAME_LEN]; /*!< Task name */ +} esp_diag_log_data_t; + +/** + * @brief Device information structure + */ +#define DIAG_HEX_SHA_SIZE 16 /* Length of ELF SHA as HEX string*/ +#define DIAG_SHA_SIZE (DIAG_HEX_SHA_SIZE / 2) /* Length of ELF SHA as raw bytes*/ +typedef struct { + uint32_t chip_model; /*!< Chip model */ + uint32_t chip_rev; /*!< Chip revision */ + uint32_t reset_reason; /*!< Reset reason */ + char app_version[32]; /*!< Application version */ + char project_name[32]; /*!< Project name */ + char app_elf_sha256[DIAG_HEX_SHA_SIZE + 1]; /*!< SHA256 of application elf */ +} esp_diag_device_info_t; + +/** + * @brief Task backtrace structure + */ +typedef struct { + uint32_t bt[16]; /*!< Backtrace (array of PC) */ + uint32_t depth; /*!< Number of backtrace entries */ + bool corrupted; /*!< Status flag for backtrace is corrupt or not */ +} esp_diag_task_bt_t; + +/** + * @brief Task information structure + */ +typedef struct { + char name[CONFIG_FREERTOS_MAX_TASK_NAME_LEN]; /*!< Task name */ + uint32_t state; /*!< Task state */ + uint32_t high_watermark; /*!< Task high watermark */ +#ifndef CONFIG_IDF_TARGET_ARCH_RISCV + esp_diag_task_bt_t bt_info; /*!< Backtrace of the task */ +#endif /* !CONFIG_IDF_TARGET_ARCH_RISCV */ +} esp_diag_task_info_t; + +/** + * @brief Structure for diagnostics data point + */ +typedef struct { + uint16_t type; /*!< Metrics or Variable */ + uint16_t data_type; /*!< Data type */ +#ifndef CONFIG_ESP_INSIGHTS_META_VERSION_10 + char tag[16]; /*!< TAG */ +#endif + char key[16]; /*!< Key */ + uint64_t ts; /*!< Timestamp */ + union { + bool b; /*!< Value for boolean data type */ + int32_t i; /*!< Value for integer data type */ + uint32_t u; /*!< Value for unsigned integer data type */ + float f; /*!< Value for float data type */ + uint32_t ipv4; /*!< Value for the IPv4 address */ + uint8_t mac[6]; /*!< Value for the MAC address */ + } value; +} esp_diag_data_pt_t; + +/** + * @brief Structure for string data type diagnostics data point + */ +typedef struct { + uint16_t type; /*!< Metrics or Variable */ + uint16_t data_type; /*!< Data type */ +#ifndef CONFIG_ESP_INSIGHTS_META_VERSION_10 + char tag[16]; /*!< TAG */ +#endif + char key[16]; /*!< Key */ + uint64_t ts; /*!< Timestamp */ + union { + char str[32]; /*!< Value for string data type */ + } value; +} esp_diag_str_data_pt_t; + +/** + * @brief Initialize diagnostics log hook + * + * @param[in] config Pointer to a config structure of type \ref esp_diag_log_config_t + * + * @return ESP_OK if successful, appropriate error code otherwise. + */ +esp_err_t esp_diag_log_hook_init(esp_diag_log_config_t *config); + +/** + * @brief Enable the diagnostics log hook for provided log type + * + * @param[in] type Log type to enable, can be the bitwise OR of types from \ref esp_diag_log_type_t + */ +void esp_diag_log_hook_enable(uint32_t type); + +/** + * @brief Disable the diagnostics log hook for provided log type + * + * @param[in] type Log type to disable, can be the bitwise OR of types from \ref esp_diag_log_type_t + * + */ +void esp_diag_log_hook_disable(uint32_t type); + +/** + * @brief Add diagnostics event + * + * @param[in] tag The tag of message + * @param[in] format Message format + * @param[in] ... Variable arguments + * + * @return ESP_OK if successful, appropriate error code otherwise. + * + * @note This function is not intended to be used directly, Instead, use macro \ref ESP_DIAG_EVENT + */ +esp_err_t esp_diag_log_event(const char *tag, const char *format, ...) __attribute__ ((format (printf, 2, 3))); + +/** + * @brief Macro to add the custom event + * + * @param[in] tag tag of the event + * @param[in] format format of the event + * @param[in] ... Variable arguments + */ +#define ESP_DIAG_EVENT(tag, format, ...) \ +{ \ + esp_diag_log_event(tag, "EV (%" PRIu32 ") %s: " format, esp_log_timestamp(), tag, ##__VA_ARGS__); \ + ESP_LOGI(tag, format, ##__VA_ARGS__); \ +} + +/** + * @brief Get the device information for diagnostics + * + * @param[out] device_info Pointer to device_info structure of type \ref esp_diag_device_info_t + * + * @return ESP_OK on success + * @return ESP_ERR_INVALID_ARG if device_info is NULL + */ +esp_err_t esp_diag_device_info_get(esp_diag_device_info_t *device_info); + +/** + * @brief Get the timestamp + * + * This function returns POSIX time if NTP sync is enabled + * otherwise returns time since bootup in microseconds + * + * @return timestamp + */ +uint64_t esp_diag_timestamp_get(void); + +/** + * @brief Get backtrace and some more details of all tasks in system + * + * @note On device backtrace parsing not available on RISC-V boards (ESP32C3) + * + * @param[out] tasks Array to store task info + * @param[in] size Size of array, If size is less than the number of tasks in system, + * then info of size tasks is filled in array + * + * @return Number of task info filled in array + * + * @note Allocate enough memory to store all tasks, + * Use uxTaskGetNumberOfTasks() to get number of tasks in system + */ +uint32_t esp_diag_task_snapshot_get(esp_diag_task_info_t *tasks, size_t size); + +/** + * @brief Dump backtrace and some more details of all tasks + * in system to console using \ref ESP_DIAG_EVENT + */ +void esp_diag_task_snapshot_dump(void); + +/** + * @brief Get CRC of diagnostics metadata + * + * @return crc + */ +uint32_t esp_diag_meta_crc_get(void); + +/** + * @brief Get CRC of diagnostics data structures' size + * + * @return crc + */ +uint32_t esp_diag_data_size_get_crc(void); + + +/** + * @brief Convenience API for ingesting log data into diagnostics when esp_log_writev() is externally wrapped. + * This API should be called from __wrap_esp_log_writev(). \see CONFIG_DIAG_USE_EXTERNAL_LOG_WRAP. + * + * @param[in] level Log level + * @param[in] tag Tag of the log + * @param[in] format Format of the log + * @param[in] v Variable argument list + * + * @note The Diagnostics component wraps the esp_log_write() and esp_log_writev() APIs using the `--wrap` GCC option + * to collect logs. If another component intends to wrap the logging APIs, enable the configuration option + * CONFIG_DIAG_USE_EXTERNAL_LOG_WRAP. This will prevent the Diagnostics component from wrapping the logging APIs. + * To enable log diagnostics in such case, call the esp_diag_log_writev() and esp_diag_log_write() APIs within + * their respective externally wrapped APIs. + * + * @note Avoid calling this API explicitly unless there is an use case as the one described above. + */ +void esp_diag_log_writev(esp_log_level_t level, const char *tag, const char *format, va_list v); + +/** + * @brief Convenience API for ingesting log data into diagnostics when esp_log_write() is externally wrapped. + * This API should be called from __wrap_esp_log_write(). \see CONFIG_DIAG_USE_EXTERNAL_LOG_WRAP. + * + * @param[in] level Log level + * @param[in] tag Tag of the log + * @param[in] format Format of the log + * @param[in] v variable argument list + * + * @note Please see notes from \see esp_diag_log_writev() + */ +void esp_diag_log_write(esp_log_level_t level, const char *tag, const char *format, va_list v); + +#ifdef __cplusplus +} +#endif diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/include/esp_diagnostics_metrics.h b/RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/include/esp_diagnostics_metrics.h new file mode 100644 index 000000000..2144d162a --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/include/esp_diagnostics_metrics.h @@ -0,0 +1,309 @@ +/* + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once +#include +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +#if CONFIG_DIAG_ENABLE_METRICS +/** + * @brief Callback to write metrics data + * + * @param[in] tag Tag for metrics + * @param[in] data Metrics data + * @param[in] len Length of metrics data + * @param[in] cb_arg User data to pass in write callback + */ +typedef esp_err_t (*esp_diag_metrics_write_cb_t)(const char *tag, void *data, size_t len, void *cb_arg); + +/** + * @brief Diagnostics metrics config structure + */ +typedef struct { + esp_diag_metrics_write_cb_t write_cb; /*!< Callback function to write diagnostics data */ + void *cb_arg; /*!< User data to pass in callback function */ +} esp_diag_metrics_config_t; + +/** + * @brief Structure for diagnostics metrics metadata + */ +typedef struct { + const char *tag; /*!< Tag of metrics */ + const char *key; /*!< Unique key for the metrics */ + const char *label; /*!< Label for the metrics */ + const char *path; /*!< Hierarchical path for the key, must be separated by '.' for more than one level, + eg: "wifi", "heap.internal", "heap.external" */ + const char *unit; /*!< Data unit, can be NULL */ + esp_diag_data_type_t type; /*!< Data type of metrics */ +} esp_diag_metrics_meta_t; + +/** + * @brief Initialize the diagnostics metrics + * + * @param[in] config Pointer to a config structure of type \ref esp_diag_metrics_config_t + * + * @return ESP_OK if successful, appropriate error code otherwise. + */ +esp_err_t esp_diag_metrics_init(esp_diag_metrics_config_t *config); + +/** + * @brief Deinitialize the diagnostics metrics + * + * @return ESP_OK if successful, appropriate error code otherwise. + */ +esp_err_t esp_diag_metrics_deinit(void); + +/** + * @brief Register a metrics + * + * @param[in] tag Tag of metrics + * @param[in] key Unique key for the metrics + * @param[in] label Label for the metrics + * @param[in] path Hierarchical path for key, must be separated by '.' for more than one level + * @param[in] type Data type of metrics + * + * @return ESP_OK if successful, appropriate error code otherwise. + */ +esp_err_t esp_diag_metrics_register(const char *tag, + const char *key, + const char *label, + const char *path, + esp_diag_data_type_t type); + +/** + * @brief Unregister all previously registered metrics + * + * @return ESP_OK if successful, qppropriate error code otherwise. + */ +esp_err_t esp_diag_metrics_unregister_all(void); + +/** + * @brief Get metadata for all metrics + * + * @param[out] len Length of the metrics meta data array + * + * @return array Array of metrics meta data + */ +const esp_diag_metrics_meta_t *esp_diag_metrics_meta_get_all(uint32_t *len); + +/** + * @brief Print metadata for all metrics + */ +void esp_diag_metrics_meta_print_all(void); + +#ifndef CONFIG_ESP_INSIGHTS_META_VERSION_10 + +/** + * @brief Unregister a diagnostics metrics + * + * @param[in] tag Tag of the metrics + * @param[in] key Key for the metrics + * + * @return ESP_OK if successful, appropriate error code otherwise. + */ +esp_err_t esp_diag_metrics_unregister(const char *tag, const char *key); + +/** + * @brief Specify unit of the data for the particular key + * + * @param[in] tag Tag of the metrics + * @param[in] key Key for which the unit to be specified + * @param[in] unit Unit string of the data + * + * @return ESP_OK if successful, appropriate error code othewise. + * + * @note this API if used, should be called after \ref esp_diag_metrics_register + * API with the same `key` to take effect + */ +esp_err_t esp_diag_metrics_add_unit(const char *tag, const char *key, const char *unit); + +/** + * @brief Add metrics to storage + * + * @param[in] data_type Data type of metrics \ref esp_diag_data_type_t + * @param[in] tag Tag of metrics + * @param[in] key Key of metrics + * @param[in] val Value of metrics + * @param[in] val_sz Size of val + * @param[in] ts Timestamp in microseconds, this should be the value at the time of data gathering + * + * @return ESP_OK if successful, appropriate error code otherwise. + * + * @note \ref esp_diag_timestamp_get() API can be used to get timestamp in mircoseconds. + */ +esp_err_t esp_diag_metrics_report(esp_diag_data_type_t data_type, + const char *tag, const char *key, const void *val, + size_t val_sz, uint64_t ts); + +/** + * @brief Add the metrics of data type boolean + * + * @param[in] tag Tag of metrics + * @param[in] key Key of the metrics + * @param[in] b Value of the metrics + * + * @return ESP_OK if successful, appropriate error code otherwise. + */ +esp_err_t esp_diag_metrics_report_bool(const char *tag, const char *key, bool b); + +/** + * @brief Add the metrics of data type integer + * + * @param[in] tag Tag of metrics + * @param[in] key Key of the metrics + * @param[in] i Value of the metrics + * + * @return ESP_OK if successful, appropriate error code otherwise. + */ +esp_err_t esp_diag_metrics_report_int(const char *tag, const char *key, int32_t i); + +/** + * @brief Add the metrics of data type unsigned integer + * + * @param[in] tag Tag of metrics + * @param[in] key Key of the metrics + * @param[in] u Value of the metrics + * + * @return ESP_OK if successful, appropriate error code otherwise. + */ +esp_err_t esp_diag_metrics_report_uint(const char *tag, const char *key, uint32_t u); + +/** + * @brief Add the metrics of data type float + * + * @param[in] tag Tag of metrics + * @param[in] key Key of the metrics + * @param[in] f Value of the metrics + * + * @return ESP_OK if successful, appropriate error code otherwise. + */ +esp_err_t esp_diag_metrics_report_float(const char *tag, const char *key, float f); + +/** + * @brief Add the IPv4 address metrics + * + * @param[in] tag Tag of metrics + * @param[in] key Key of the metrics + * @param[in] ip IPv4 address + * + * @return ESP_OK if successful, appropriate error code otherwise. + */ +esp_err_t esp_diag_metrics_report_ipv4(const char *tag, const char *key, uint32_t ip); + +/** + * @brief Add the MAC address metrics + * + * @param[in] tag Tag of metrics + * @param[in] key Key of the metrics + * @param[in] mac Array of length 6 i.e 6 octets of mac address + * + * @return ESP_OK if successful, appropriate error code otherwise. + */ +esp_err_t esp_diag_metrics_report_mac(const char *tag, const char *key, uint8_t *mac); + +/** + * @brief Add the metrics of data type string + * + * @param[in] tag Tag of metrics + * @param[in] key Key of the metrics + * @param[in] str Value of the metrics + * + * @return ESP_OK if successful, appropriate error code otherwise. + */ +esp_err_t esp_diag_metrics_report_str(const char *tag, const char *key, const char *str); + +#else /** APIs for older version of metadata for compatibility */ + +/** + * @brief Unregister a diagnostics metrics + * + * Legacy version of metrics_unregister without `tag` parameter + */ +esp_err_t esp_diag_metrics_unregister(const char *key); + +/** + * @brief Specify unit of the data for the particular key + * + * @param[in] key Key for which the unit to be specified + * @param[in] unit Unit string of the data + * + * @return ESP_OK if successful, appropriate error code othewise. + * + * @note this API if used, should be called after \ref esp_diag_metrics_register + * API with the same `key` to take effect + */ +esp_err_t esp_diag_metrics_add_unit(const char *key, const char *unit); + +/** + * @brief Add the metrics of data type `data_type` + * + * @note Same as \ref esp_diag_metrics_report but with legacy format + */ +esp_err_t esp_diag_metrics_add(esp_diag_data_type_t data_type, const char *key, + const void *val, size_t val_sz, uint64_t ts); + +/** + * @brief Add the metrics of data type bool + * + * @note Same as \ref esp_diag_metrics_report_bool but with legacy format + */ +esp_err_t esp_diag_metrics_add_bool(const char *key, bool b); + +/** + * @brief Add the metrics of data type integer + * + * @note Same as \ref esp_diag_metrics_report_int but with legacy format + */ +esp_err_t esp_diag_metrics_add_int(const char *key, int32_t i); + +/** + * @brief Add the metrics of data type unsigned integer + * + * @note Same as \ref esp_diag_metrics_report_uint but with legacy format + */ +esp_err_t esp_diag_metrics_add_uint(const char *key, uint32_t u); + +/** + * @brief Add the metrics of data type float + * + * @note Same as \ref esp_diag_metrics_report_float but with legacy format + */ +esp_err_t esp_diag_metrics_add_float(const char *key, float f); + +/** + * @brief Add the IPv4 address metrics + * + * @note Same as \ref esp_diag_metrics_report_ipv4 but with legacy format + */ +esp_err_t esp_diag_metrics_add_ipv4(const char *key, uint32_t ip); + +/** + * @brief Add the MAC address metrics + * + * @note Same as \ref esp_diag_metrics_report_mac but with legacy format + */ +esp_err_t esp_diag_metrics_add_mac(const char *key, uint8_t *mac); + +/** + * @brief Add the metrics of data type string + * + * @note Same as \ref esp_diag_metrics_report_str but with legacy format + */ +esp_err_t esp_diag_metrics_add_str(const char *key, const char *str); + +#endif + +#endif /* CONFIG_DIAG_ENABLE_METRICS */ + +#ifdef __cplusplus +} +#endif diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/include/esp_diagnostics_network_variables.h b/RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/include/esp_diagnostics_network_variables.h new file mode 100644 index 000000000..f6faf0bee --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/include/esp_diagnostics_network_variables.h @@ -0,0 +1,34 @@ +/* + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#ifdef __cplusplus +extern "C" +{ +#endif + +#if CONFIG_DIAG_ENABLE_NETWORK_VARIABLES +/** + * @brief Initialize the network variables + * + * Below listed Wi-Fi and IP parameters are collected and reported to cloud on change. + * Wi-Fi connection status, BSSID, SSID, channel, authentication mode, + * Wi-Fi disconnection reason, IP address, netmask, and gateway. + * + * @return ESP_OK if successful, appropriate error code otherwise. + */ +esp_err_t esp_diag_network_variables_init(void); + +/** + * @brief Deinitialize the network variables + */ +esp_err_t esp_diag_network_variables_deinit(void); +#endif /* CONFIG_DIAG_ENABLE_NETWORK_VARIABLES */ + +#ifdef __cplusplus +} +#endif diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/include/esp_diagnostics_system_metrics.h b/RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/include/esp_diagnostics_system_metrics.h new file mode 100644 index 000000000..8d496f3e8 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/include/esp_diagnostics_system_metrics.h @@ -0,0 +1,104 @@ +/* + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#ifdef __cplusplus +extern "C" +{ +#endif + +#if CONFIG_DIAG_ENABLE_HEAP_METRICS + +/** + * @brief Initialize the heap metrics + * + * Free heap, largest free block, and all time minimum free heap values are collected periodically. + * Parameters are collected for RAM in internal memory and external memory (if device has PSRAM). + * + * The periodic interval is configurable through CONFIG_DIAG_HEAP_POLLING_INTERVAL Kconfig option. + * Default is 30 seconds and can be changed with esp_diag_heap_metrics_reset_interval() at runtime. + * Valid range is from 30 seconds to 24 hours (86400 seconds). + * + * @return ESP_OK if successful, appropriate error code otherwise. + */ +esp_err_t esp_diag_heap_metrics_init(void); + +/** + * @brief Deinitialize the heap metrics + * + * @return ESP_OK if successful, appropriate error code otherwise. + */ +esp_err_t esp_diag_heap_metrics_deinit(void); + +/** + * @brief Reset the periodic interval + * + * By default, heap metrics are collected based on CONFIG_DIAG_HEAP_POLLING_INTERVAL Kconfig option. + * This function can be used to change the interval at runtime. + * If the interval is set to 0, heap metrics collection is disabled. + * + * @param[in] period Period interval in seconds + */ +void esp_diag_heap_metrics_reset_interval(uint32_t period); + +/** + * @brief Dumps the heap metrics and prints them to the console. + * + * This API collects and reports metrics value at any give point in time. + * + * @return ESP_OK if successful, appropriate error code otherwise. + */ +esp_err_t esp_diag_heap_metrics_dump(void); + +#endif /* CONFIG_DIAG_ENABLE_HEAP_METRICS */ + +#if CONFIG_DIAG_ENABLE_WIFI_METRICS + +/** + * @brief Initialize the wifi metrics + * + * Wi-Fi RSSI and minimum ever Wi-Fi RSSI values are collected periodically. + * The periodic interval is configurable through CONFIG_DIAG_WIFI_POLLING_INTERVAL Kconfig option. + * Default is 30 seconds and can be changed with esp_diag_wifi_metrics_reset_interval() at runtime. + * Valid range is from 30 seconds to 24 hours (86400 seconds). + * + * @return ESP_OK if successful, appropriate error code otherwise. + */ +esp_err_t esp_diag_wifi_metrics_init(void); + +/** + * @brief Deinitialize the wifi metrics + * + * @return ESP_OK if successful, appropriate error code otherwise. + */ +esp_err_t esp_diag_wifi_metrics_deinit(void); + +/** + * @brief Dumps the wifi metrics and prints them to the console. + * + * This API can be used to collect wifi metrics at any given point in time. + * + * @return ESP_OK if successful, appropriate error code otherwise. + */ +esp_err_t esp_diag_wifi_metrics_dump(void); + +/** + * @brief Reset the periodic interval + * + * By default, wifi metrics are collected based on CONFIG_DIAG_WIFI_POLLING_INTERVAL Kconfig option. + * This function can be used to change the interval at runtime. + * If the interval is set to 0, wifi metrics collection is disabled. + * + * @param[in] period Period interval in seconds + */ +void esp_diag_wifi_metrics_reset_interval(uint32_t period); + +#endif /* CONFIG_DIAG_ENABLE_WIFI_METRICS */ + +#ifdef __cplusplus +} +#endif diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/include/esp_diagnostics_variables.h b/RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/include/esp_diagnostics_variables.h new file mode 100644 index 000000000..2c12c4381 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/include/esp_diagnostics_variables.h @@ -0,0 +1,336 @@ +/* + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +#if CONFIG_DIAG_ENABLE_VARIABLES + +/** + * @brief Callback to write variable's data + * + * @param[in] tag Tag for variable + * @param[in] data Data for variable + * @param[in] len Length of variable + * @param[in] cb_arg User data to pass in write callback + */ +typedef esp_err_t (*esp_diag_variable_write_cb_t)(const char *tag, void *data, size_t len, void *cb_arg); + +/** + * @brief Diagnostics variable config structure + */ +typedef struct { + esp_diag_variable_write_cb_t write_cb; /*!< Callback function to write diagnostics data */ + void *cb_arg; /*!< User data to pass in callback function */ +} esp_diag_variable_config_t; + +/** + * @brief Structure for diagnostics variable metadata + */ +typedef struct { + const char *tag; /*!< Tag of variable */ + const char *key; /*!< Unique key for the variable */ + const char *label; /*!< Label for the variable */ + const char *path; /*!< Hierarchical path for the key, must be separated by '.' for more than one level, + eg: "wifi", "heap.internal", "heap.external" */ + const char *unit; /*!< Data unit, can be NULL */ + esp_diag_data_type_t type; /*!< Data type of variables */ +} esp_diag_variable_meta_t; + +/** + * @brief Initialize the diagnostics variable + * + * @param[in] config Pointer to a config structure of type \ref esp_diag_variable_config_t + * + * @return ESP_OK if successful, appropriate error code otherwise. + */ +esp_err_t esp_diag_variable_init(esp_diag_variable_config_t *config); + +/** + * @brief Deinitialize the diagnostics variables + * + * @return ESP_OK if successful, appropriate error code otherwise. + */ +esp_err_t esp_diag_variables_deinit(void); + +/** + * @brief Register a diagnostics variable + * + * @param[in] tag Tag of variable + * @param[in] key Unique key for the variable + * @param[in] label Label for the variable + * @param[in] path Hierarchical path for key, must be separated by '.' for more than one level + * @param[in] type Data type of variable + * + * @return ESP_OK if successful, appropriate error code otherwise. + */ +esp_err_t esp_diag_variable_register(const char *tag, + const char *key, + const char *label, + const char *path, + esp_diag_data_type_t type); + +/** + * @brief Unregister all previously registered variables + * + * @return ESP_OK if successful, qppropriate error code otherwise. + */ +esp_err_t esp_diag_variable_unregister_all(void); + +/** + * @brief Get metadata for all variables + * + * @param[out] len Length of the variables meta data array + * + * @return array Array of variables meta data + */ +const esp_diag_variable_meta_t *esp_diag_variable_meta_get_all(uint32_t *len); + +/** + * @brief Print metadata for all variables + */ +void esp_diag_variable_meta_print_all(void); + +#ifndef CONFIG_ESP_INSIGHTS_META_VERSION_10 + +/** + * @brief Unregister a diagnostics variable + * + * @param[in] tag Tag of variable + * @param[in] key Key for the variable + * + * @return ESP_OK if successful, appropriate error code otherwise. + */ +esp_err_t esp_diag_variable_unregister(const char *tag, const char *key); + +/** + * @brief Specify unit of the data for the particular key + * + * @param[in] tag Tag of variable + * @param[in] key Key for which the unit to be specified + * @param[in] unit Unit string of the data + * + * @return ESP_OK if successful, appropriate error code othewise. + * + * @note this API if used, should be called after \ref esp_diag_variable_register + * API with the same `key` to take effect + */ +esp_err_t esp_diag_variable_add_unit(const char *tag, const char *key, const char *unit); + +/** + * @brief Add variable to storage + * + * @param[in] data_type Data type of variable \ref esp_diag_data_type_t + * @param[in] key Key of variable + * @param[in] val Value of variable + * @param[in] val_sz Size of val + * @param[in] ts Timestamp in microseconds, this should be the value at the time of data gathering + * + * @return ESP_OK if successful, appropriate error code otherwise. + * + * @note \ref esp_diag_timestamp_get() API can be used to get timestamp in mircoseconds. + */ +esp_err_t esp_diag_variable_report(esp_diag_data_type_t data_type, + const char *tag, const char *key, const void *val, + size_t val_sz, uint64_t ts); + +/** + * @brief Add the variable of data type boolean + * + * @param[in] key Key of the variable + * @param[in] b Value of the variable + * + * @return ESP_OK if successful, appropriate error code otherwise. + */ +esp_err_t esp_diag_variable_report_bool(const char *tag, const char *key, bool b); + +/** + * @brief Add the variable of data type integer + * + * @param[in] key Key of the variable + * @param[in] i Value of the variable + * + * @return ESP_OK if successful, appropriate error code otherwise. + */ +esp_err_t esp_diag_variable_report_int(const char *tag, const char *key, int32_t i); + +/** + * @brief Add the variable of data type unsigned integer + * + * @param[in] key Key of the variable + * @param[in] u Value of the variable + * + * @return ESP_OK if successful, appropriate error code otherwise. + */ +esp_err_t esp_diag_variable_report_uint(const char *tag, const char *key, uint32_t u); + +/** + * @brief Add the variable of data type float + * + * @param[in] key Key of the variable + * @param[in] f Value of the variable + * + * @return ESP_OK if successful, appropriate error code otherwise. + */ +esp_err_t esp_diag_variable_report_float(const char *tag, const char *key, float f); + +/** + * @brief Add the IPv4 address variable + * + * @param[in] key Key of the variable + * @param[in] ip IPv4 address + * + * @return ESP_OK if successful, appropriate error code otherwise. + */ +esp_err_t esp_diag_variable_report_ipv4(const char *tag, const char *key, uint32_t ip); + +/** + * @brief Add the MAC address variable + * + * @param[in] key Key of the variable + * @param[in] mac Array of length 6 i.e 6 octets of mac address + * + * @return ESP_OK if successful, appropriate error code otherwise. + */ +esp_err_t esp_diag_variable_report_mac(const char *tag, const char *key, uint8_t *mac); + +/** + * @brief Add the variable of data type string + * + * @param[in] key Key of the variable + * @param[in] str Value of the variable + * + * @return ESP_OK if successful, appropriate error code otherwise. + */ +esp_err_t esp_diag_variable_report_str(const char *tag, const char *key, const char *str); + +#else /** APIs for older version of metadata for compatibility */ + +/** + * @brief Unregister a diagnostics variable + * + * @param[in] key Key for the variable + * + * @return ESP_OK if successful, appropriate error code otherwise. + */ +esp_err_t esp_diag_variable_unregister(const char *key); + +/** + * @brief Specify unit of the data for the particular key + * + * @param[in] key Key for which the unit to be specified + * @param[in] unit Unit string of the data + * + * @return ESP_OK if successful, appropriate error code othewise. + * + * @note this API if used, should be called after \ref esp_diag_variable_register + * API with the same `key` to take effect + */ +esp_err_t esp_diag_variable_add_unit(const char *key, const char *unit); + +/** + * @brief Add variable to storage + * + * @param[in] data_type Data type of variable \ref esp_diag_data_type_t + * @param[in] tag Tag of variable + * @param[in] key Key of variable + * @param[in] val Value of variable + * @param[in] val_sz Size of val + * @param[in] ts Timestamp in microseconds, this should be the value at the time of data gathering + * + * @return ESP_OK if successful, appropriate error code otherwise. + * + * @note \ref esp_diag_timestamp_get() API can be used to get timestamp in mircoseconds. + */ +esp_err_t esp_diag_variable_add(esp_diag_data_type_t data_type, + const char *key, const void *val, + size_t val_sz, uint64_t ts); + +/** + * @brief Add the variable of data type boolean + * + * @param[in] key Key of the variable + * @param[in] b Value of the variable + * + * @return ESP_OK if successful, appropriate error code otherwise. + */ +esp_err_t esp_diag_variable_add_bool(const char *key, bool b); + +/** + * @brief Add the variable of data type integer + * + * @param[in] key Key of the variable + * @param[in] i Value of the variable + * + * @return ESP_OK if successful, appropriate error code otherwise. + */ +esp_err_t esp_diag_variable_add_int(const char *key, int32_t i); + +/** + * @brief Add the variable of data type unsigned integer + * + * @param[in] key Key of the variable + * @param[in] u Value of the variable + * + * @return ESP_OK if successful, appropriate error code otherwise. + */ +esp_err_t esp_diag_variable_add_uint(const char *key, uint32_t u); + +/** + * @brief Add the variable of data type float + * + * @param[in] key Key of the variable + * @param[in] f Value of the variable + * + * @return ESP_OK if successful, appropriate error code otherwise. + */ +esp_err_t esp_diag_variable_add_float(const char *key, float f); + +/** + * @brief Add the IPv4 address variable + * + * @param[in] key Key of the variable + * @param[in] ip IPv4 address + * + * @return ESP_OK if successful, appropriate error code otherwise. + */ +esp_err_t esp_diag_variable_add_ipv4(const char *key, uint32_t ip); + +/** + * @brief Add the MAC address variable + * + * @param[in] key Key of the variable + * @param[in] mac Array of length 6 i.e 6 octets of mac address + * + * @return ESP_OK if successful, appropriate error code otherwise. + */ +esp_err_t esp_diag_variable_add_mac(const char *key, uint8_t *mac); + +/** + * @brief Add the variable of data type string + * + * @param[in] key Key of the variable + * @param[in] str Value of the variable + * + * @return ESP_OK if successful, appropriate error code otherwise. + */ +esp_err_t esp_diag_variable_add_str(const char *key, const char *str); + +#endif + +#endif /* CONFIG_DIAG_ENABLE_VARIABLES */ + +#ifdef __cplusplus +} +#endif diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/src/esp_diagnostics_heap_metrics.c b/RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/src/esp_diagnostics_heap_metrics.c new file mode 100644 index 000000000..20d3e4354 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/src/esp_diagnostics_heap_metrics.c @@ -0,0 +1,239 @@ +/* + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include "sdkconfig.h" + +#include +#include +#include +#include "esp_diagnostics_internal.h" + +#define LOG_TAG "heap_metrics" +#define METRICS_TAG "heap" +#define METRICS_UNIT "bytes" + +#define KEY_ALLOC_FAIL "alloc_fail" +#define KEY_FREE "free" +#define KEY_MIN_FREE "min_free_ever" +#define KEY_LFB "lfb" +#ifdef CONFIG_ESP32_SPIRAM_SUPPORT +#define KEY_EXT_FREE "ext_free" +#define KEY_EXT_LFB "ext_lfb" +#define KEY_EXT_MIN_FREE "ext_min_free_ever" +#endif /* CONFIG_ESP32_SPIRAM_SUPPORT */ + +#define PATH_HEAP_INTERNAL "heap.internal" +#define PATH_HEAP_EXTERNAL "heap.external" + +/* Use configurable polling interval with default fallback */ +#ifdef CONFIG_DIAG_HEAP_POLLING_INTERVAL +#define DEFAULT_POLLING_INTERVAL CONFIG_DIAG_HEAP_POLLING_INTERVAL +#else +#define DEFAULT_POLLING_INTERVAL 30 /* 30 seconds */ +#endif + +typedef struct { + bool init; + TimerHandle_t handle; +} heap_diag_priv_data_t; + +static heap_diag_priv_data_t s_priv_data; + +esp_err_t esp_diag_heap_metrics_dump(void) +{ + if (!s_priv_data.init) { + ESP_LOGW(LOG_TAG, "Heap metrics not initialized"); + return ESP_ERR_INVALID_STATE; + } + uint32_t free = heap_caps_get_free_size(MALLOC_CAP_INTERNAL); + uint32_t lfb = heap_caps_get_largest_free_block(MALLOC_CAP_INTERNAL); + uint32_t min_free_ever = heap_caps_get_minimum_free_size(MALLOC_CAP_INTERNAL); +#ifndef CONFIG_ESP_INSIGHTS_META_VERSION_10 + RET_ON_ERR_WITH_LOG(esp_diag_metrics_report_uint(METRICS_TAG, KEY_FREE, free), ESP_LOG_WARN, LOG_TAG, + "Failed to add heap metric key:" KEY_FREE); + RET_ON_ERR_WITH_LOG(esp_diag_metrics_report_uint(METRICS_TAG, KEY_LFB, lfb), ESP_LOG_WARN, LOG_TAG, + "Failed to add heap metric key:" KEY_LFB); + RET_ON_ERR_WITH_LOG(esp_diag_metrics_report_uint(METRICS_TAG, KEY_MIN_FREE, min_free_ever), ESP_LOG_WARN, LOG_TAG, + "Failed to add heap metric key:" KEY_MIN_FREE); + + ESP_LOGI(LOG_TAG, KEY_FREE ":0x%" PRIx32 " " KEY_LFB ":0x%" PRIx32 " " KEY_MIN_FREE ":0x%" PRIx32, free, lfb, min_free_ever); +#ifdef CONFIG_ESP32_SPIRAM_SUPPORT + free = heap_caps_get_free_size(MALLOC_CAP_SPIRAM); + lfb = heap_caps_get_largest_free_block(MALLOC_CAP_SPIRAM); + min_free_ever = heap_caps_get_minimum_free_size(MALLOC_CAP_SPIRAM); + + RET_ON_ERR_WITH_LOG(esp_diag_metrics_report_uint(METRICS_TAG, KEY_EXT_FREE, free), ESP_LOG_WARN, LOG_TAG, + "Failed to add heap metric key:" KEY_EXT_FREE); + RET_ON_ERR_WITH_LOG(esp_diag_metrics_report_uint(METRICS_TAG, KEY_EXT_LFB, lfb), ESP_LOG_WARN, LOG_TAG, + "Failed to add heap metric key:" KEY_EXT_LFB); + RET_ON_ERR_WITH_LOG(esp_diag_metrics_report_uint(METRICS_TAG, KEY_EXT_MIN_FREE, min_free_ever), ESP_LOG_WARN, LOG_TAG, + "Failed to add heap metric key:" KEY_EXT_MIN_FREE); + + ESP_LOGI(LOG_TAG, KEY_EXT_FREE ":0x%" PRIx32 " " KEY_EXT_LFB ":0x%" PRIx32 " " KEY_EXT_MIN_FREE ":0x%" PRIx32, free, lfb, min_free_ever); +#endif /* CONFIG_ESP32_SPIRAM_SUPPORT */ +#else + RET_ON_ERR_WITH_LOG(esp_diag_metrics_add_uint(KEY_FREE, free), ESP_LOG_WARN, LOG_TAG, + "Failed to add heap metric key:" KEY_FREE); + RET_ON_ERR_WITH_LOG(esp_diag_metrics_add_uint(KEY_LFB, lfb), ESP_LOG_WARN, LOG_TAG, + "Failed to add heap metric key:" KEY_LFB); + RET_ON_ERR_WITH_LOG(esp_diag_metrics_add_uint(KEY_MIN_FREE, min_free_ever), ESP_LOG_WARN, LOG_TAG, + "Failed to add heap metric key:" KEY_MIN_FREE); + + ESP_LOGI(LOG_TAG, KEY_FREE ":0x%"PRIx32" " KEY_LFB ":0x%"PRIx32" " KEY_MIN_FREE ":0x%"PRIx32, free, lfb, min_free_ever); +#ifdef CONFIG_ESP32_SPIRAM_SUPPORT + free = heap_caps_get_free_size(MALLOC_CAP_SPIRAM); + lfb = heap_caps_get_largest_free_block(MALLOC_CAP_SPIRAM); + min_free_ever = heap_caps_get_minimum_free_size(MALLOC_CAP_SPIRAM); + + RET_ON_ERR_WITH_LOG(esp_diag_metrics_add_uint(KEY_EXT_FREE, free), ESP_LOG_WARN, LOG_TAG, + "Failed to add heap metric key:" KEY_EXT_FREE); + RET_ON_ERR_WITH_LOG(esp_diag_metrics_add_uint(KEY_EXT_LFB, lfb), ESP_LOG_WARN, LOG_TAG, + "Failed to add heap metric key:" KEY_EXT_LFB); + RET_ON_ERR_WITH_LOG(esp_diag_metrics_add_uint(KEY_EXT_MIN_FREE, min_free_ever), ESP_LOG_WARN, LOG_TAG, + "Failed to add heap metric key:" KEY_EXT_MIN_FREE); + + ESP_LOGI(LOG_TAG, KEY_EXT_FREE ":0x%"PRIx32" " KEY_EXT_LFB ":0x%"PRIx32" " KEY_EXT_MIN_FREE ":0x%"PRIx32, free, lfb, min_free_ever); +#endif /* CONFIG_ESP32_SPIRAM_SUPPORT */ +#endif + return ESP_OK; +} + +static void heap_metrics_dump_cb(void *arg) +{ + esp_diag_heap_metrics_dump(); +} + +static void heap_timer_cb(TimerHandle_t handle) +{ + esp_rmaker_work_queue_add_task(heap_metrics_dump_cb, NULL); +} + +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0) +static void alloc_failed_hook(size_t size, uint32_t caps, const char *func) +{ + esp_diag_heap_metrics_dump(); +#ifndef CONFIG_ESP_INSIGHTS_META_VERSION_10 + esp_diag_metrics_report_uint(METRICS_TAG, KEY_ALLOC_FAIL, size); +#else + esp_diag_metrics_add_uint(KEY_ALLOC_FAIL, size); +#endif + + ESP_DIAG_EVENT(METRICS_TAG, KEY_ALLOC_FAIL " size:0x%x func:%s", size, func); +} +#endif + +esp_err_t esp_diag_heap_metrics_init(void) +{ + if (s_priv_data.init) { + return ESP_ERR_INVALID_STATE; + } +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0) + esp_err_t err = heap_caps_register_failed_alloc_callback(alloc_failed_hook); + if (err != ESP_OK) { + return err; + } + esp_diag_metrics_register(METRICS_TAG, KEY_ALLOC_FAIL, "Malloc fail", METRICS_TAG, ESP_DIAG_DATA_TYPE_UINT); +#ifndef CONFIG_ESP_INSIGHTS_META_VERSION_10 + esp_diag_metrics_add_unit(METRICS_TAG, KEY_ALLOC_FAIL, METRICS_UNIT); +#else + esp_diag_metrics_add_unit(KEY_ALLOC_FAIL, METRICS_UNIT); +#endif +#endif + +#ifdef CONFIG_ESP32_SPIRAM_SUPPORT + esp_diag_metrics_register(METRICS_TAG, KEY_EXT_FREE, "External free heap", PATH_HEAP_EXTERNAL, ESP_DIAG_DATA_TYPE_UINT); + esp_diag_metrics_register(METRICS_TAG, KEY_EXT_LFB, "External largest free block", PATH_HEAP_EXTERNAL, ESP_DIAG_DATA_TYPE_UINT); + esp_diag_metrics_register(METRICS_TAG, KEY_EXT_MIN_FREE, "External minimum free size", PATH_HEAP_EXTERNAL, ESP_DIAG_DATA_TYPE_UINT); +#ifndef CONFIG_ESP_INSIGHTS_META_VERSION_10 + esp_diag_metrics_add_unit(METRICS_TAG, KEY_EXT_FREE, METRICS_UNIT); + esp_diag_metrics_add_unit(METRICS_TAG, KEY_EXT_LFB, METRICS_UNIT); + esp_diag_metrics_add_unit(METRICS_TAG, KEY_EXT_MIN_FREE, METRICS_UNIT); +#else + esp_diag_metrics_add_unit(KEY_EXT_FREE, METRICS_UNIT); + esp_diag_metrics_add_unit(KEY_EXT_LFB, METRICS_UNIT); + esp_diag_metrics_add_unit(KEY_EXT_MIN_FREE, METRICS_UNIT); +#endif +#endif /* CONFIG_ESP32_SPIRAM_SUPPORT */ + + esp_diag_metrics_register(METRICS_TAG, KEY_FREE, "Free heap", PATH_HEAP_INTERNAL, ESP_DIAG_DATA_TYPE_UINT); + esp_diag_metrics_register(METRICS_TAG, KEY_LFB, "Largest free block", PATH_HEAP_INTERNAL, ESP_DIAG_DATA_TYPE_UINT); + esp_diag_metrics_register(METRICS_TAG, KEY_MIN_FREE, "Minimum free size", PATH_HEAP_INTERNAL, ESP_DIAG_DATA_TYPE_UINT); +#ifndef CONFIG_ESP_INSIGHTS_META_VERSION_10 + esp_diag_metrics_add_unit(METRICS_TAG, KEY_FREE, METRICS_UNIT); + esp_diag_metrics_add_unit(METRICS_TAG, KEY_LFB, METRICS_UNIT); + esp_diag_metrics_add_unit(METRICS_TAG, KEY_MIN_FREE, METRICS_UNIT); +#else + esp_diag_metrics_add_unit(KEY_FREE, METRICS_UNIT); + esp_diag_metrics_add_unit(KEY_LFB, METRICS_UNIT); + esp_diag_metrics_add_unit(KEY_MIN_FREE, METRICS_UNIT); +#endif + s_priv_data.handle = xTimerCreate("heap_metrics", SEC2TICKS(DEFAULT_POLLING_INTERVAL), + pdTRUE, NULL, heap_timer_cb); + if (s_priv_data.handle) { + xTimerStart(s_priv_data.handle, 0); + } + s_priv_data.init = true; + + // Dump metrics for the first time + esp_diag_heap_metrics_dump(); + + return ESP_OK; +} + +esp_err_t esp_diag_heap_metrics_deinit(void) +{ + if (!s_priv_data.init) { + return ESP_ERR_INVALID_STATE; + } + /* Try to delete timer with 10 ticks wait time */ + if (xTimerDelete(s_priv_data.handle, 10) == pdFALSE) { + ESP_LOGW(LOG_TAG, "Failed to delete heap metric timer"); + } +#ifdef CONFIG_ESP_INSIGHTS_META_VERSION_10 +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0) + esp_diag_metrics_unregister(KEY_ALLOC_FAIL); +#endif +#ifdef CONFIG_ESP32_SPIRAM_SUPPORT + esp_diag_metrics_unregister(KEY_EXT_FREE); + esp_diag_metrics_unregister(KEY_EXT_LFB); + esp_diag_metrics_unregister(KEY_EXT_MIN_FREE); +#endif + esp_diag_metrics_unregister(KEY_FREE); + esp_diag_metrics_unregister(KEY_LFB); + esp_diag_metrics_unregister(KEY_MIN_FREE); +#else +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0) + esp_diag_metrics_unregister(METRICS_TAG, KEY_ALLOC_FAIL); +#endif +#ifdef CONFIG_ESP32_SPIRAM_SUPPORT + esp_diag_metrics_unregister(METRICS_TAG, KEY_EXT_FREE); + esp_diag_metrics_unregister(METRICS_TAG, KEY_EXT_LFB); + esp_diag_metrics_unregister(METRICS_TAG, KEY_EXT_MIN_FREE); +#endif + esp_diag_metrics_unregister(METRICS_TAG, KEY_FREE); + esp_diag_metrics_unregister(METRICS_TAG, KEY_LFB); + esp_diag_metrics_unregister(METRICS_TAG, KEY_MIN_FREE); +#endif + memset(&s_priv_data, 0, sizeof(s_priv_data)); + return ESP_OK; +} + +void esp_diag_heap_metrics_reset_interval(uint32_t period) +{ + if (!s_priv_data.init) { + return; + } + if (period == 0) { + xTimerStop(s_priv_data.handle, 0); + return; + } + xTimerChangePeriod(s_priv_data.handle, SEC2TICKS(period), 0); +} diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/src/esp_diagnostics_internal.h b/RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/src/esp_diagnostics_internal.h new file mode 100644 index 000000000..2bfbd7ba2 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/src/esp_diagnostics_internal.h @@ -0,0 +1,25 @@ +/* + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#define RET_ON_ERR_WITH_LOG(x, level, tag, format, ...) { \ + esp_err_t ret = (x); \ + if (ret != ESP_OK) { \ + ESP_LOG_LEVEL(level, tag, "%s", format, ##__VA_ARGS__); \ + return ret; \ + } \ +} + +#define SEC2TICKS(s) ((s * 1000) / portTICK_PERIOD_MS) + +#ifdef __cplusplus +} +#endif diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/src/esp_diagnostics_log_hook.c b/RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/src/esp_diagnostics_log_hook.c new file mode 100644 index 000000000..f03c4ba31 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/src/esp_diagnostics_log_hook.c @@ -0,0 +1,481 @@ +/* + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "stdio.h" +#include "string.h" +#include "esp_log.h" +#include "esp_diagnostics.h" +#include "soc/soc_memory_layout.h" +#include "esp_idf_version.h" +#include +#include + +/* Onwards esp-idf v5.0 esp_cpu_process_stack_pc() is moved to + * components/xtensa/include/esp_cpu_utils.h + */ +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0) + #if CONFIG_IDF_TARGET_ARCH_XTENSA + #include "esp_cpu_utils.h" + #else /* CONFIG_IDF_TARGET_ARCH_RISCV */ + #define esp_cpu_process_stack_pc(x) (x) // dummy definition to avoid compilation error + #endif +#else // For esp-idf version <= v4.4 + #include "soc/cpu.h" +#endif + +#define IS_LOG_TYPE_ENABLED(type) (s_priv_data.init && (type & s_priv_data.enabled_log_type)) + +typedef struct { + uint32_t enabled_log_type; + esp_diag_log_config_t config; + bool init; +} log_hook_priv_data_t; + +static log_hook_priv_data_t s_priv_data; + +#ifdef CONFIG_DIAG_LOG_MSG_ARG_FORMAT_TLV +typedef enum { + MOD_NONE, /* none */ + MOD_hh, /* char */ + MOD_h, /* short */ + MOD_l, /* long, NOTE: in case of double, this can be ignored */ + MOD_ll, /* long long */ + MOD_j, /* intmax_t or uintmax_t */ + MOD_t, /* ptrdiff_t */ + MOD_z, /* size_t */ + MOD_L, /* long double, NOTE: only for double */ +} modifiers_t; + +static esp_err_t append_arg(uint8_t *args, uint8_t *out_size, uint8_t max_len, + uint8_t type, uint8_t len, void *value) +{ + if ((*out_size + 2 + len) > max_len) { + return ESP_ERR_NO_MEM; + } + + args += *out_size; + *args++ = type; + *args++ = len; + memcpy(args, value, len); + *out_size += (len + 2); + return ESP_OK; +} + +static void get_tlv_from_ap(esp_diag_log_data_t *log, const char *format, va_list ap) +{ + const char *p = NULL; + uint8_t len, out_size = 0; + uint8_t arg_max_len = sizeof(log->msg_args); + esp_err_t err = ESP_OK; + esp_diag_arg_value_t arg_val; + modifiers_t mf; + + /* there can be flags, field width digits, precision digits, modifiers, specifiers + * modifier tells the size of the field eg: hh, h, l, ll + * specifier tells whether it is signed, unsigned, double, string, pointer, etc. + * Following parsing is done by considering printf manual (man 3 printf) + */ + for (p = format; *p; p++) { + if (*p == '%') { + p++; + } else { + continue; + } + /* skip zero or more flags */ + while (*p == '#' || *p == '0' || *p == '-' || *p == ' ' || *p == '+' || *p == '\'') { + p++; + } + /* skip the field width digits */ + while (*p >= '0' && *p <= '9') { + p++; + } + /* skip precision bytes, period(.) followed by digits */ + if (*p == '.') { + p++; + while (*p >= '0' && *p <= '9') { + p++; + } + } + /* An optional length modifier, that specifies the size of the argument */ + len = 0; + mf = MOD_NONE; + while (*p) { + bool _default = false; + switch (*p) { + case 'h': + if (mf == MOD_h) { + mf = MOD_hh; + len = sizeof(char); + } else { + mf = MOD_h; + len = sizeof(short); + } + break; + case 'l': + if (mf == MOD_l) { + mf = MOD_ll; + len = sizeof(long long); + } else { + mf = MOD_l; + len = sizeof(long); + } + break; + case 'j': + mf = MOD_j; + len = sizeof(intmax_t); + break; + case 't': + mf = MOD_t; + len = sizeof(ptrdiff_t); + break; + case 'z': + mf = MOD_z; + len = sizeof(size_t); + break; + case 'L': + mf = MOD_L; + len = sizeof(long double); + break; + default: + _default = true; + break; + } + if (_default) { + break; + } + p++; + } + /* specifier, character that specifies the type of conversion to be applied */ + memset(&arg_val, 0, sizeof(arg_val)); + switch (*p) { + case 'D': /* equivalent to ld */ + arg_val.l = va_arg(ap, long); + err = append_arg(log->msg_args, &out_size, arg_max_len, ARG_TYPE_L, sizeof(long), &arg_val.l); + break; + case 'd': + case 'i': + switch (mf) { + case MOD_NONE: /* none, no modifier found */ + case MOD_z: /* singed integer of size size_t */ + arg_val.i = va_arg(ap, int); + err = append_arg(log->msg_args, &out_size, arg_max_len, ARG_TYPE_INT, sizeof(int), &arg_val.i); + break; + case MOD_hh: /* char */ + arg_val.c = va_arg(ap, int); /* char is promoted to int */ + err = append_arg(log->msg_args, &out_size, arg_max_len, ARG_TYPE_CHAR, len, &arg_val.c); + break; + case MOD_h: /* short */ + arg_val.s = va_arg(ap, int); /* short is promoted to int */ + err = append_arg(log->msg_args, &out_size, arg_max_len, ARG_TYPE_SHORT, len, &arg_val.s); + break; + case MOD_l: /* long */ + arg_val.l = va_arg(ap, long); + err = append_arg(log->msg_args, &out_size, arg_max_len, ARG_TYPE_L, len, &arg_val.l); + break; + break; + case MOD_ll: /* long long */ + arg_val.ll = va_arg(ap, long long); + err = append_arg(log->msg_args, &out_size, arg_max_len, ARG_TYPE_LL, len, &arg_val.ll); + break; + case MOD_j: + /* intmax_t */ + arg_val.imx = va_arg(ap, intmax_t); + err = append_arg(log->msg_args, &out_size, arg_max_len, ARG_TYPE_INTMAX, len, &arg_val.imx); + break; + case MOD_t: + /* ptrdiff_t */ + arg_val.ptrdiff = va_arg(ap, ptrdiff_t); + err = append_arg(log->msg_args, &out_size, arg_max_len, ARG_TYPE_PTRDIFF, len, &arg_val.ptrdiff); + break; + default: + break; + } + break; + case 'O': /* equivalent to lo */ + case 'U': /* equivalent to lu */ + arg_val.ul = va_arg(ap, unsigned long); + err = append_arg(log->msg_args, &out_size, arg_max_len, ARG_TYPE_ULL, sizeof(unsigned long), &arg_val.ul); + break; + case 'o': + case 'u': + case 'x': + case 'X': + case 'p': + switch (mf) { + case MOD_NONE: /* none, no modifier found */ + case MOD_t: /* unsigned type of size ptrdiff_t */ + len = sizeof(unsigned int); + arg_val.u = va_arg(ap, unsigned int); + err = append_arg(log->msg_args, &out_size, arg_max_len, ARG_TYPE_UINT, len, &arg_val.u); + break; + case MOD_hh: /* unsinged char */ + arg_val.uc = va_arg(ap, unsigned int); + err = append_arg(log->msg_args, &out_size, arg_max_len, ARG_TYPE_UCHAR, len, &arg_val.uc); + break; + case MOD_h: /* unsigned short */ + arg_val.us = va_arg(ap, unsigned int); + err = append_arg(log->msg_args, &out_size, arg_max_len, ARG_TYPE_USHORT, len, &arg_val.us); + break; + case MOD_l: /* unsigned long */ + arg_val.ul = va_arg(ap, unsigned long); + err = append_arg(log->msg_args, &out_size, arg_max_len, ARG_TYPE_UL, len, &arg_val.ul); + break; + case MOD_ll: /* unsigned long long */ + arg_val.ull = va_arg(ap, unsigned long long); + err = append_arg(log->msg_args, &out_size, arg_max_len, ARG_TYPE_ULL, len, &arg_val.ull); + break; + case MOD_j: /* uintmax_t */ + arg_val.umx = va_arg(ap, uintmax_t); + err = append_arg(log->msg_args, &out_size, arg_max_len, ARG_TYPE_UINTMAX, len, &arg_val.umx); + break; + case MOD_z: /* size_t */ + arg_val.sz = va_arg(ap, size_t); + err = append_arg(log->msg_args, &out_size, arg_max_len, ARG_TYPE_SIZE, len, &arg_val.sz); + break; + default: + break; + } + break; + case 'a': + case 'A': + case 'e': + case 'E': + case 'f': + case 'F': + case 'g': + case 'G': + switch (mf) { + case MOD_NONE: /* double */ + case MOD_l: /* double */ + len = sizeof(double); + arg_val.d = va_arg(ap, double); + err = append_arg(log->msg_args, &out_size, arg_max_len, ARG_TYPE_DOUBLE, len, &arg_val.d); + break; + case MOD_L: /* long double */ + arg_val.ld = va_arg(ap, long double); + err = append_arg(log->msg_args, &out_size, arg_max_len, ARG_TYPE_LDOUBLE, len, &arg_val.ld); + break; + default: + break; + } + break; + case 'c': /* char */ + arg_val.c = va_arg(ap, int); + err = append_arg(log->msg_args, &out_size, arg_max_len, ARG_TYPE_CHAR, sizeof(char), &arg_val.c); + break; + case 's': /* array of chars */ + arg_val.str = va_arg(ap, char *); + if (arg_val.str) { + len = strlen(arg_val.str); + } else { + len = 0; + } + err = append_arg(log->msg_args, &out_size, arg_max_len, ARG_TYPE_STR, len, arg_val.str); + break; + case 'n': /* %n outputs the number of bytes printed till that point, so will skip it */ + va_arg(ap, int); + break; + default: + /* since we do not know the size or type of argument so, consuming the unsupported format specifier as integer. */ + va_arg(ap, int); + break; + } + if (err != ESP_OK) { + break; + } + } + log->msg_args_len = out_size; +} +#endif /* CONFIG_DIAG_LOG_MSG_ARG_FORMAT_TLV */ + +static esp_err_t write_data(void *data, size_t len) +{ + if (s_priv_data.config.write_cb) { + return s_priv_data.config.write_cb(data, len, s_priv_data.config.cb_arg); + } + return ESP_FAIL; +} + +static esp_err_t diag_log_add(esp_diag_log_type_t type, uint32_t pc, const char *tag, const char *format, va_list args) +{ + esp_diag_log_data_t log; + va_list ap; + char *task_name = NULL; + + if (!IS_LOG_TYPE_ENABLED(type)) { + return ESP_ERR_NOT_FOUND; + } + + memset(&log, 0, sizeof(log)); + log.type = type; + log.pc = pc; + va_copy(ap, args); + log.timestamp = esp_diag_timestamp_get(); + strlcpy(log.tag, tag, sizeof(log.tag)); + log.msg_ptr = (void *)format; + log.msg_args_len = sizeof(log.msg_args); +#ifdef CONFIG_DIAG_LOG_MSG_ARG_FORMAT_TLV + get_tlv_from_ap(&log, format, ap); +#else + vsnprintf((char *)log.msg_args, log.msg_args_len, format, ap); + log.msg_args_len = strlen((char *)log.msg_args); +#endif + va_end(ap); +#if ESP_IDF_VERSION_MAJOR == 4 && ESP_IDF_VERSION_MINOR < 3 + task_name = pcTaskGetTaskName(NULL); +#else + task_name = pcTaskGetName(NULL); +#endif + if (task_name) { + strlcpy(log.task_name, task_name, sizeof(log.task_name)); + } + return write_data(&log, sizeof(log)); +} + +/** + * If error logs are enabled via menuconfig, irrespective of if error logs are disabled + * using `esp_log_level_set()`, error logs are still reported to Insights cloud + */ +static esp_err_t esp_diag_log_error(uint32_t pc, const char *tag, const char *format, va_list args) +{ + return diag_log_add(ESP_DIAG_LOG_TYPE_ERROR, pc, tag, format, args); +} + +/** + * If warning logs are enabled via menuconfig, irrespective of if warning logs are disabled + * using `esp_log_level_set()`, warning logs are still reported to Insights cloud + */ +static esp_err_t esp_diag_log_warning(uint32_t pc, const char *tag, const char *format, va_list args) +{ + return diag_log_add(ESP_DIAG_LOG_TYPE_WARNING, pc, tag, format, args); +} + +/** + * Events are reported irrespective of device logging level. + */ +esp_err_t esp_diag_log_event(const char *tag, const char *format, ...) +{ + esp_err_t err; + va_list args; + uint32_t pc = esp_cpu_process_stack_pc((uint32_t)__builtin_return_address(0)); + va_start(args, format); + err = diag_log_add(ESP_DIAG_LOG_TYPE_EVENT, pc, tag, format, args); + va_end(args); + return err; +} + +void esp_diag_log_hook_enable(uint32_t type) +{ + s_priv_data.enabled_log_type |= type; +} + +void esp_diag_log_hook_disable(uint32_t type) +{ + s_priv_data.enabled_log_type &= (~type); +} + +static void esp_diag_log(esp_log_level_t level, uint32_t pc, const char *tag, const char *format, va_list list) +{ + if (level == ESP_LOG_ERROR) { + esp_diag_log_error(pc, tag, format, list); + } else if (level == ESP_LOG_WARN) { + esp_diag_log_warning(pc, tag, format, list); + } +} + +esp_err_t esp_diag_log_hook_init(esp_diag_log_config_t *config) +{ + if (!config && !config->write_cb) { + return ESP_ERR_INVALID_ARG; + } + if (s_priv_data.init) { + return ESP_FAIL; + } + memcpy(&s_priv_data.config, config, sizeof(esp_diag_log_config_t)); + s_priv_data.init = true; + return ESP_OK; +} + +#ifdef CONFIG_LIB_BUILDER_COMPILE +extern int log_printfv(const char *format, va_list arg); + +void __real_log_printf(const char *format, ...); + +void __wrap_log_printf(const char *format, ...) +{ + va_list list; + va_start(list, format); + uint32_t pc = 0; + pc = esp_cpu_process_stack_pc((uint32_t)__builtin_return_address(0)); + if (strlen(format) > 7 && format[6] == 'E') { + esp_diag_log(ESP_LOG_ERROR, pc, "arduino-esp32", format, list); + } else if (strlen(format) > 7 && format[6] == 'W') { + esp_diag_log(ESP_LOG_WARN, pc, "arduino-esp32", format, list); + } + log_printfv(format, list); + va_end(list); +} +#endif + +void esp_diag_log_writev(esp_log_level_t level, + const char *tag, + const char *format, + va_list args) +{ +#ifndef CONFIG_DIAG_LOG_DROP_WIFI_LOGS + /* Only collect logs with "wifi" tag */ + if (strcmp(tag, "wifi") == 0) { + uint32_t pc = 0; + pc = esp_cpu_process_stack_pc((uint32_t)__builtin_return_address(0)); + esp_diag_log(level, pc, tag, format, args); + } +#endif /* !CONFIG_DIAG_LOG_DROP_WIFI_LOGS */ +} + +void esp_diag_log_write(esp_log_level_t level, + const char *tag, + const char *format, + va_list list) +{ +#ifndef BOOTLOADER_BUILD + /* Logs with "wifi" tag, will be collected in esp_log_writev() */ + if (strcmp(tag, "wifi") != 0) { + uint32_t pc = 0; + pc = esp_cpu_process_stack_pc((uint32_t)__builtin_return_address(0)); + esp_diag_log(level, pc, tag, format, list); + } +#endif +} + +#if !CONFIG_DIAG_USE_EXTERNAL_LOG_WRAP +/* Wrapping esp_log_write() and esp_log_writev() reduces the + * changes required in esp_log module to support diagnostics + */ +void __real_esp_log_writev(esp_log_level_t level, + const char *tag, + const char *format, + va_list args); + +void __wrap_esp_log_writev(esp_log_level_t level, + const char *tag, + const char *format, + va_list args) +{ + esp_diag_log_write(level, tag, format, args); + __real_esp_log_writev(level, tag, format, args); +} + +void __wrap_esp_log_write(esp_log_level_t level, + const char *tag, + const char *format, ...) +{ + va_list list; + va_start(list, format); + esp_diag_log_writev(level, tag, format, list); + esp_log_writev(level, tag, format, list); + va_end(list); +} +#endif // CONFIG_DIAG_USE_EXTERNAL_LOG_WRAP diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/src/esp_diagnostics_metrics.c b/RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/src/esp_diagnostics_metrics.c new file mode 100644 index 000000000..1d2cb1296 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/src/esp_diagnostics_metrics.c @@ -0,0 +1,350 @@ +/* + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include + +#define TAG "DIAG_METRICS" +#define DIAG_METRICS_MAX_COUNT CONFIG_DIAG_METRICS_MAX_COUNT + +/* Max supported string lenth */ +#define MAX_STR_LEN (sizeof(((esp_diag_str_data_pt_t *)0)->value.str) - 1) +#define MAX_METRICS_WRITE_SZ sizeof(esp_diag_data_pt_t) +#define MAX_STR_METRICS_WRITE_SZ sizeof(esp_diag_str_data_pt_t) + +typedef struct { + size_t metrics_count; + esp_diag_metrics_meta_t metrics[DIAG_METRICS_MAX_COUNT]; + esp_diag_metrics_config_t config; + bool init; +} metrics_priv_data_t; + +static metrics_priv_data_t s_priv_data; + +static esp_diag_metrics_meta_t *esp_diag_metrics_meta_get(const char *tag, const char *key) +{ + uint32_t i; + if (!tag || !key) { + return NULL; + } + for (i = 0; i < s_priv_data.metrics_count; i++) { + if (s_priv_data.metrics[i].tag && s_priv_data.metrics[i].key && + (strcmp(s_priv_data.metrics[i].tag, tag) == 0) && + (strcmp(s_priv_data.metrics[i].key, key) == 0)) { + return &s_priv_data.metrics[i]; + } + } + return NULL; +} + +#ifdef CONFIG_ESP_INSIGHTS_META_VERSION_10 +/* Checks only by key for registered metric. Use this for meta version < 1.1 */ +static esp_diag_metrics_meta_t *esp_diag_metrics_meta_get_by_key(const char *key) +{ + uint32_t i; + if (!key) { + return NULL; + } + for (i = 0; i < s_priv_data.metrics_count; i++) { + if (s_priv_data.metrics[i].key && + (strcmp(s_priv_data.metrics[i].key, key) == 0)) { + return &s_priv_data.metrics[i]; + } + } + return NULL; +} +#endif + +static bool tag_key_present(const char *tag, const char *key) +{ + return (esp_diag_metrics_meta_get(tag, key) != NULL); +} + +esp_err_t esp_diag_metrics_register(const char *tag, const char *key, + const char *label, const char *path, + esp_diag_data_type_t type) +{ + if (!tag || !key || !label || !path) { + ESP_LOGE(TAG, "Failed to register metrics, tag, key, lable, or path is NULL"); + return ESP_ERR_INVALID_ARG; + } + if (!s_priv_data.init) { + return ESP_ERR_INVALID_STATE; + } + if (s_priv_data.metrics_count >= DIAG_METRICS_MAX_COUNT) { + ESP_LOGE(TAG, "No space left for more metrics"); + return ESP_ERR_NO_MEM; + } + if (tag_key_present(tag, key)) { + ESP_LOGE(TAG, "Metrics tag: %s key:%s exists", tag, key); + return ESP_FAIL; + } + s_priv_data.metrics[s_priv_data.metrics_count].tag = tag; + s_priv_data.metrics[s_priv_data.metrics_count].key = key; + s_priv_data.metrics[s_priv_data.metrics_count].label = label; + s_priv_data.metrics[s_priv_data.metrics_count].unit = NULL; + s_priv_data.metrics[s_priv_data.metrics_count].path = path; + s_priv_data.metrics[s_priv_data.metrics_count].type = type; + s_priv_data.metrics_count++; + return ESP_OK; +} + +#ifdef CONFIG_ESP_INSIGHTS_META_VERSION_10 +esp_err_t esp_diag_metrics_add_unit(const char *key, const char *unit) +#else +esp_err_t esp_diag_metrics_add_unit(const char *tag, const char *key, const char *unit) +#endif +{ +#ifndef CONFIG_ESP_INSIGHTS_META_VERSION_10 + if (!tag) { + return ESP_ERR_INVALID_ARG; + } +#endif + if (!key) { + return ESP_ERR_INVALID_ARG; + } + if (!s_priv_data.init) { + return ESP_ERR_INVALID_STATE; + } + +#ifdef CONFIG_ESP_INSIGHTS_META_VERSION_10 + esp_diag_metrics_meta_t *metrics = esp_diag_metrics_meta_get_by_key(key); + if (!metrics) { + ESP_LOGI(TAG, "metrics with (key %s) not found", key); + return ESP_ERR_NOT_FOUND; + } +#else + esp_diag_metrics_meta_t *metrics = esp_diag_metrics_meta_get(tag, key); + if (!metrics) { + ESP_LOGI(TAG, "metrics with (tag %s, key %s) not found", tag, key); + return ESP_ERR_NOT_FOUND; + } +#endif + metrics->unit = unit; + return ESP_OK; +} + +#ifdef CONFIG_ESP_INSIGHTS_META_VERSION_10 +esp_err_t esp_diag_metrics_unregister(const char *key) +#else +esp_err_t esp_diag_metrics_unregister(const char *tag, const char *key) +#endif +{ + int i; +#ifndef CONFIG_ESP_INSIGHTS_META_VERSION_10 + if (!tag) { + return ESP_ERR_INVALID_ARG; + } +#endif + if (!key) { + return ESP_ERR_INVALID_ARG; + } + for (i = 0; i < s_priv_data.metrics_count; i++) { + if (s_priv_data.metrics[i].key && +#ifndef CONFIG_ESP_INSIGHTS_META_VERSION_10 + (strcmp(s_priv_data.metrics[i].tag, tag) == 0) && +#endif + (strcmp(s_priv_data.metrics[i].key, key) == 0)) { + break; + } + } + if (i < s_priv_data.metrics_count) { + s_priv_data.metrics[i] = s_priv_data.metrics[s_priv_data.metrics_count - 1]; + memset(&s_priv_data.metrics[s_priv_data.metrics_count - 1], 0, sizeof(esp_diag_metrics_meta_t)); + s_priv_data.metrics_count--; + return ESP_OK; + } + return ESP_ERR_NOT_FOUND; +} + +esp_err_t esp_diag_metrics_unregister_all(void) +{ + if (!s_priv_data.init) { + return ESP_ERR_INVALID_STATE; + } + memset(&s_priv_data.metrics, 0, sizeof(s_priv_data.metrics)); + s_priv_data.metrics_count = 0; + return ESP_OK; +} + +const esp_diag_metrics_meta_t *esp_diag_metrics_meta_get_all(uint32_t *len) +{ + if (!s_priv_data.init) { + *len = 0; + return NULL; + } + *len = s_priv_data.metrics_count; + return &s_priv_data.metrics[0]; +} + +void esp_diag_metrics_meta_print_all(void) +{ + uint32_t len; + uint32_t i; + const esp_diag_metrics_meta_t *meta = esp_diag_metrics_meta_get_all(&len); + if (meta) { + ESP_LOGI(TAG, "Tag\tKey\tLabel\tPath\tData type\n"); + for (i = 0; i < len; i++) { + ESP_LOGI(TAG, "%s\t%s\t%s\t%s\t%d\n", meta[i].tag, meta[i].key, meta[i].label, meta[i].path, meta[i].type); + } + } +} + +esp_err_t esp_diag_metrics_init(esp_diag_metrics_config_t *config) +{ + if (!config || !config->write_cb) { + return ESP_ERR_INVALID_ARG; + } + if (s_priv_data.init) { + return ESP_ERR_INVALID_STATE; + } + memcpy(&s_priv_data.config, config, sizeof(s_priv_data.config)); + s_priv_data.init = true; + return ESP_OK; +} + +esp_err_t esp_diag_metrics_deinit(void) +{ + if (!s_priv_data.init) { + return ESP_ERR_INVALID_STATE; + } + memset(&s_priv_data, 0, sizeof(s_priv_data)); + return ESP_OK; +} + +#ifdef CONFIG_ESP_INSIGHTS_META_VERSION_10 +esp_err_t esp_diag_metrics_add(esp_diag_data_type_t data_type, +#else +esp_err_t esp_diag_metrics_report(esp_diag_data_type_t data_type, const char *tag, +#endif + const char *key, const void *val, + size_t val_sz, uint64_t ts) +{ +#ifndef CONFIG_ESP_INSIGHTS_META_VERSION_10 + if (!tag) { + return ESP_ERR_INVALID_ARG; + } +#endif + if (!key || !val) { + return ESP_ERR_INVALID_ARG; + } + if (!s_priv_data.init) { + return ESP_ERR_INVALID_STATE; + } + +#ifdef CONFIG_ESP_INSIGHTS_META_VERSION_10 + const esp_diag_metrics_meta_t *metrics = esp_diag_metrics_meta_get_by_key(key); + if (!metrics) { + ESP_LOGI(TAG, "metrics with (key %s) not registered", key); + return ESP_ERR_NOT_FOUND; + } +#else + const esp_diag_metrics_meta_t *metrics = esp_diag_metrics_meta_get(tag, key); + if (!metrics) { + ESP_LOGI(TAG, "metrics with (tag %s, key %s) not registered", tag, key); + return ESP_ERR_NOT_FOUND; + } +#endif + if (metrics->type != data_type) { + return ESP_ERR_INVALID_ARG; + } + size_t write_sz = MAX_METRICS_WRITE_SZ; + if (metrics->type == ESP_DIAG_DATA_TYPE_STR) { + write_sz = MAX_STR_METRICS_WRITE_SZ; + } + + esp_diag_str_data_pt_t data; + memset(&data, 0, sizeof(data)); + data.type = ESP_DIAG_DATA_PT_METRICS; + data.data_type = data_type; +#ifndef CONFIG_ESP_INSIGHTS_META_VERSION_10 + strlcpy(data.tag, tag, sizeof(data.tag)); +#endif + strlcpy(data.key, key, sizeof(data.key)); + data.ts = ts; + memcpy(&data.value, val, val_sz); + + if (s_priv_data.config.write_cb) { + return s_priv_data.config.write_cb(metrics->tag, &data, write_sz, s_priv_data.config.cb_arg); + } + return ESP_OK; +} + +#ifdef CONFIG_ESP_INSIGHTS_META_VERSION_10 +esp_err_t esp_diag_metrics_add_bool(const char *key, bool b) +{ + return esp_diag_metrics_add(ESP_DIAG_DATA_TYPE_BOOL, key, &b, sizeof(b), esp_diag_timestamp_get()); +} + +esp_err_t esp_diag_metrics_add_int(const char *key, int32_t i) +{ + return esp_diag_metrics_add(ESP_DIAG_DATA_TYPE_INT, key, &i, sizeof(i), esp_diag_timestamp_get()); +} + +esp_err_t esp_diag_metrics_add_uint(const char *key, uint32_t u) +{ + return esp_diag_metrics_add(ESP_DIAG_DATA_TYPE_UINT, key, &u, sizeof(u), esp_diag_timestamp_get()); +} + +esp_err_t esp_diag_metrics_add_float(const char *key, float f) +{ + return esp_diag_metrics_add(ESP_DIAG_DATA_TYPE_FLOAT, key, &f, sizeof(f), esp_diag_timestamp_get()); +} + +esp_err_t esp_diag_metrics_add_ipv4(const char *key, uint32_t ip) +{ + return esp_diag_metrics_add(ESP_DIAG_DATA_TYPE_IPv4, key, &ip, sizeof(ip), esp_diag_timestamp_get()); +} + +esp_err_t esp_diag_metrics_add_mac(const char *key, uint8_t *mac) +{ + return esp_diag_metrics_add(ESP_DIAG_DATA_TYPE_MAC, key, mac, 6, esp_diag_timestamp_get()); +} + +esp_err_t esp_diag_metrics_add_str(const char *key, const char *str) +{ + return esp_diag_metrics_add(ESP_DIAG_DATA_TYPE_STR, key, str, strlen(str), esp_diag_timestamp_get()); +} +#else +esp_err_t esp_diag_metrics_report_bool(const char *tag, const char *key, bool b) +{ + return esp_diag_metrics_report(ESP_DIAG_DATA_TYPE_BOOL, tag, key, &b, sizeof(b), esp_diag_timestamp_get()); +} + +esp_err_t esp_diag_metrics_report_int(const char *tag, const char *key, int32_t i) +{ + return esp_diag_metrics_report(ESP_DIAG_DATA_TYPE_INT, tag, key, &i, sizeof(i), esp_diag_timestamp_get()); +} + +esp_err_t esp_diag_metrics_report_uint(const char *tag, const char *key, uint32_t u) +{ + return esp_diag_metrics_report(ESP_DIAG_DATA_TYPE_UINT, tag, key, &u, sizeof(u), esp_diag_timestamp_get()); +} + +esp_err_t esp_diag_metrics_report_float(const char *tag, const char *key, float f) +{ + return esp_diag_metrics_report(ESP_DIAG_DATA_TYPE_FLOAT, tag, key, &f, sizeof(f), esp_diag_timestamp_get()); +} + +esp_err_t esp_diag_metrics_report_ipv4(const char *tag, const char *key, uint32_t ip) +{ + return esp_diag_metrics_report(ESP_DIAG_DATA_TYPE_IPv4, tag, key, &ip, sizeof(ip), esp_diag_timestamp_get()); +} + +esp_err_t esp_diag_metrics_report_mac(const char *tag, const char *key, uint8_t *mac) +{ + return esp_diag_metrics_report(ESP_DIAG_DATA_TYPE_MAC, tag, key, mac, 6, esp_diag_timestamp_get()); +} + +esp_err_t esp_diag_metrics_report_str(const char *tag, const char *key, const char *str) +{ + return esp_diag_metrics_report(ESP_DIAG_DATA_TYPE_STR, tag, key, str, strlen(str), esp_diag_timestamp_get()); +} +#endif diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/src/esp_diagnostics_network_variables.c b/RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/src/esp_diagnostics_network_variables.c new file mode 100644 index 000000000..d0e873136 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/src/esp_diagnostics_network_variables.c @@ -0,0 +1,353 @@ +/* + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include + +#define TAG_IP "ip" +#define TAG_WIFI "wifi" + +/* Wifi keys */ +#define KEY_SSID "ssid" +#define KEY_BSSID "bssid" +#define KEY_CHANNEL "channel" +#define KEY_AUTHMODE "auth" +#define KEY_REASON "reason" +#define KEY_DISC_CNT "disconn_cnt" + +/* Optional WiFi var keys */ +#define KEY_PROTOCOL "protocol" +#define KEY_BANDWIDTH "bandwidth" +#define KEY_PROTOCOL_AP "protocol_ap" +#define KEY_BANDWIDTH_AP "bandwidth_ap" +#define KEY_POWER_SAVE "power_save" +#define KEY_SECOND_CH "second_ch" + +/* IP keys */ +#define KEY_IPv4 "ipv4" +#define KEY_NETMASK "netmask" +#define KEY_GATEWAY "gw" + +#define PATH_WIFI_STATION "Wi-Fi.Station" +#define PATH_IP_STATION "IP.Station" +#define PATH_WIFI_AP "Wi-Fi.AP" + +typedef struct { + wifi_event_sta_connected_t prev_sta_data; + bool wifi_connected; + int32_t disconn_cnt; + bool init; +} priv_data_t; + +static priv_data_t s_priv_data; + +static bool bssid_matched(uint8_t *bssid1, uint8_t *bssid2) +{ + uint8_t i; + for (i = 0; i < 6; i++) { + if (bssid1[i] != bssid2[i]) { + return false; + } + } + return true; +} + +#if CONFIG_DIAG_MORE_NETWORK_VARS +static void diag_add_more_wifi_vars() +{ + uint8_t wifi_protocol = 0; + wifi_bandwidth_t wifi_bw = WIFI_BW_HT20; + wifi_ps_type_t wifi_ps_type = WIFI_PS_NONE; + esp_wifi_get_protocol(WIFI_IF_STA, &wifi_protocol); + esp_wifi_get_bandwidth(WIFI_IF_STA, &wifi_bw); + esp_wifi_get_ps(&wifi_ps_type); + +#ifdef CONFIG_ESP_INSIGHTS_META_VERSION_10 + esp_diag_variable_add_uint(KEY_PROTOCOL, wifi_protocol); + esp_diag_variable_add_uint(KEY_BANDWIDTH, wifi_bw); + esp_diag_variable_add_uint(KEY_POWER_SAVE, wifi_ps_type); + if (wifi_bw == WIFI_BW_HT40) { + // not very useful for now, but will be useful for 5GHz band + uint8_t primary_ch = 0; + wifi_second_chan_t secondary_ch = WIFI_SECOND_CHAN_NONE; + esp_wifi_get_channel(&primary_ch, &secondary_ch); + esp_diag_variable_add_uint(KEY_SECOND_CH, secondary_ch); + } + esp_wifi_get_protocol(WIFI_IF_AP, &wifi_protocol); + esp_wifi_get_bandwidth(WIFI_IF_AP, &wifi_bw); + esp_diag_variable_add_uint(KEY_PROTOCOL_AP, wifi_protocol); + esp_diag_variable_add_uint(KEY_BANDWIDTH_AP, wifi_bw); +#else + esp_diag_variable_report_uint(TAG_WIFI, KEY_PROTOCOL, wifi_protocol); + esp_diag_variable_report_uint(TAG_WIFI, KEY_BANDWIDTH, wifi_bw); + esp_diag_variable_report_uint(TAG_WIFI, KEY_POWER_SAVE, wifi_ps_type); + if (wifi_bw == WIFI_BW_HT40) { + // not very useful for now, but will be useful for 5GHz band + uint8_t primary_ch = 0; + wifi_second_chan_t secondary_ch = WIFI_SECOND_CHAN_NONE; + esp_wifi_get_channel(&primary_ch, &secondary_ch); + esp_diag_variable_report_uint(TAG_WIFI, KEY_SECOND_CH, secondary_ch); + } + esp_wifi_get_protocol(WIFI_IF_AP, &wifi_protocol); + esp_wifi_get_bandwidth(WIFI_IF_AP, &wifi_bw); + esp_diag_variable_report_uint(TAG_WIFI, KEY_PROTOCOL_AP, wifi_protocol); + esp_diag_variable_report_uint(TAG_WIFI, KEY_BANDWIDTH_AP, wifi_bw); +#endif +} +#endif + +static void diag_register_wifi_vars() +{ + esp_diag_variable_register(TAG_WIFI, KEY_SSID, "SSID", PATH_WIFI_STATION, ESP_DIAG_DATA_TYPE_STR); + esp_diag_variable_register(TAG_WIFI, KEY_BSSID, "BSSID", PATH_WIFI_STATION, ESP_DIAG_DATA_TYPE_MAC); + esp_diag_variable_register(TAG_WIFI, KEY_CHANNEL, "Channel", PATH_WIFI_STATION, ESP_DIAG_DATA_TYPE_INT); + esp_diag_variable_register(TAG_WIFI, KEY_AUTHMODE, "Auth Mode", PATH_WIFI_STATION, ESP_DIAG_DATA_TYPE_UINT); + esp_diag_variable_register(TAG_WIFI, KEY_DISC_CNT, "Disconnect count since last reboot", PATH_WIFI_STATION, ESP_DIAG_DATA_TYPE_INT); + esp_diag_variable_register(TAG_WIFI, KEY_REASON, "Last Wi-Fi disconnect reason", PATH_WIFI_STATION, ESP_DIAG_DATA_TYPE_INT); +} + +#if CONFIG_DIAG_MORE_NETWORK_VARS +static void diag_register_more_wifi_vars() +{ + esp_diag_variable_register(TAG_WIFI, KEY_PROTOCOL, "Protocol", PATH_WIFI_STATION, ESP_DIAG_DATA_TYPE_UINT); + esp_diag_variable_register(TAG_WIFI, KEY_BANDWIDTH, "Bandwidth", PATH_WIFI_STATION, ESP_DIAG_DATA_TYPE_UINT); + esp_diag_variable_register(TAG_WIFI, KEY_POWER_SAVE, "Power Save", PATH_WIFI_STATION, ESP_DIAG_DATA_TYPE_UINT); + esp_diag_variable_register(TAG_WIFI, KEY_SECOND_CH, "Secondary Channel", PATH_WIFI_STATION, ESP_DIAG_DATA_TYPE_UINT); + + esp_diag_variable_register(TAG_WIFI, KEY_PROTOCOL_AP, "Protocol", PATH_WIFI_AP, ESP_DIAG_DATA_TYPE_UINT); + esp_diag_variable_register(TAG_WIFI, KEY_BANDWIDTH_AP, "Bandwidth", PATH_WIFI_AP, ESP_DIAG_DATA_TYPE_UINT); +} +#endif + +static void evt_handler(void *arg, esp_event_base_t evt_base, int32_t evt_id, void *evt_data) +{ + if (evt_base == WIFI_EVENT) { + switch (evt_id) { + case WIFI_EVENT_STA_CONNECTED: + { + s_priv_data.wifi_connected = true; + wifi_event_sta_connected_t *data = evt_data; +#ifdef CONFIG_ESP_INSIGHTS_META_VERSION_10 + if (strncmp((char *)s_priv_data.prev_sta_data.ssid, (char *)data->ssid, data->ssid_len) != 0) { + esp_diag_variable_add_str(KEY_SSID, (char *)data->ssid); + } + if (!bssid_matched(s_priv_data.prev_sta_data.bssid, data->bssid)) { + esp_diag_variable_add_mac(KEY_BSSID, data->bssid); + } + if (s_priv_data.prev_sta_data.channel != data->channel) { + esp_diag_variable_add_int(KEY_CHANNEL, data->channel); + } + if (s_priv_data.prev_sta_data.authmode != data->authmode) { + esp_diag_variable_add_uint(KEY_AUTHMODE, data->authmode); + } +#else + if (strncmp((char *)s_priv_data.prev_sta_data.ssid, (char *)data->ssid, data->ssid_len) != 0) { + esp_diag_variable_report_str(TAG_WIFI, KEY_SSID, (char *)data->ssid); + } + if (!bssid_matched(s_priv_data.prev_sta_data.bssid, data->bssid)) { + esp_diag_variable_report_mac(TAG_WIFI, KEY_BSSID, data->bssid); + } + if (s_priv_data.prev_sta_data.channel != data->channel) { + esp_diag_variable_report_int(TAG_WIFI, KEY_CHANNEL, data->channel); + } + if (s_priv_data.prev_sta_data.authmode != data->authmode) { + esp_diag_variable_report_uint(TAG_WIFI, KEY_AUTHMODE, data->authmode); + } +#endif + memcpy(&s_priv_data.prev_sta_data, data, sizeof(s_priv_data.prev_sta_data)); + break; + } + case WIFI_EVENT_STA_DISCONNECTED: + { + if (s_priv_data.wifi_connected) { + s_priv_data.wifi_connected = false; + wifi_event_sta_disconnected_t *data = evt_data; + s_priv_data.disconn_cnt++; +#ifdef CONFIG_ESP_INSIGHTS_META_VERSION_10 + esp_diag_variable_add_int(KEY_REASON, data->reason); + esp_diag_variable_add_int(KEY_DISC_CNT, s_priv_data.disconn_cnt); +#else + esp_diag_variable_report_int(TAG_WIFI, KEY_REASON, data->reason); + esp_diag_variable_report_int(TAG_WIFI, KEY_DISC_CNT, s_priv_data.disconn_cnt); +#endif + } + break; + } + case WIFI_EVENT_STA_AUTHMODE_CHANGE: + { + wifi_event_sta_authmode_change_t *data = evt_data; +#ifdef CONFIG_ESP_INSIGHTS_META_VERSION_10 + esp_diag_variable_add_uint(KEY_AUTHMODE, data->new_mode); +#else + esp_diag_variable_report_uint(TAG_WIFI, KEY_AUTHMODE, data->new_mode); +#endif + s_priv_data.prev_sta_data.authmode = data->new_mode; + break; + } + default: + break; + } + } else if (evt_base == IP_EVENT) { + switch(evt_id) { + case IP_EVENT_STA_GOT_IP: + { + ip_event_got_ip_t *data = evt_data; +#ifdef CONFIG_ESP_INSIGHTS_META_VERSION_10 + esp_diag_variable_add_ipv4(KEY_IPv4, data->ip_info.ip.addr); + esp_diag_variable_add_ipv4(KEY_NETMASK, data->ip_info.netmask.addr); + esp_diag_variable_add_ipv4(KEY_GATEWAY, data->ip_info.gw.addr); +#else + esp_diag_variable_report_ipv4(TAG_IP, KEY_IPv4, data->ip_info.ip.addr); + esp_diag_variable_report_ipv4(TAG_IP, KEY_NETMASK, data->ip_info.netmask.addr); + esp_diag_variable_report_ipv4(TAG_IP, KEY_GATEWAY, data->ip_info.gw.addr); +#endif +#if CONFIG_DIAG_MORE_NETWORK_VARS + diag_add_more_wifi_vars(); +#endif + break; + } + case IP_EVENT_STA_LOST_IP: + { + uint32_t ip = 0x0; +#ifdef CONFIG_ESP_INSIGHTS_META_VERSION_10 + esp_diag_variable_add_ipv4(KEY_IPv4, ip); +#else + esp_diag_variable_report_ipv4(TAG_IP, KEY_IPv4, ip); +#endif + break; + } + default: + break; + } + } +} + +esp_err_t esp_diag_network_variables_init(void) +{ + wifi_ap_record_t ap_info; + esp_netif_ip_info_t ip_info; + + if (s_priv_data.init) { + return ESP_ERR_INVALID_STATE; + } + /* Register the event handler for wifi events */ + esp_err_t err = esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, evt_handler, NULL); + if (err != ESP_OK) { + return err; + } + /* Register the event handler for ip events */ + err = esp_event_handler_register(IP_EVENT, ESP_EVENT_ANY_ID, evt_handler, NULL); + if (err != ESP_OK) { + return err; + } + + /* wifi variables */ + diag_register_wifi_vars(); +#if CONFIG_DIAG_MORE_NETWORK_VARS + diag_register_more_wifi_vars(); +#endif + + /* IP address variables */ + esp_diag_variable_register(TAG_IP, KEY_IPv4, "IPv4", PATH_IP_STATION, ESP_DIAG_DATA_TYPE_IPv4); + esp_diag_variable_register(TAG_IP, KEY_NETMASK, "Netmask", PATH_IP_STATION, ESP_DIAG_DATA_TYPE_IPv4); + esp_diag_variable_register(TAG_IP, KEY_GATEWAY, "Gateway", PATH_IP_STATION, ESP_DIAG_DATA_TYPE_IPv4); + + memset(&s_priv_data.prev_sta_data, 0, sizeof(s_priv_data.prev_sta_data)); + /* If wifi is not connected then wifi details are recorded in event handler */ + if (esp_wifi_sta_get_ap_info(&ap_info) == ESP_OK) { + /* If wifi is connected then record the wifi details */ + memcpy(s_priv_data.prev_sta_data.ssid, ap_info.ssid, sizeof(s_priv_data.prev_sta_data.ssid)); + memcpy(s_priv_data.prev_sta_data.bssid, ap_info.bssid, sizeof(s_priv_data.prev_sta_data.bssid)); + s_priv_data.prev_sta_data.channel = ap_info.primary; + s_priv_data.prev_sta_data.authmode = ap_info.authmode; + s_priv_data.wifi_connected = true; +#ifdef CONFIG_ESP_INSIGHTS_META_VERSION_10 + esp_diag_variable_add_str(KEY_SSID, (char *)ap_info.ssid); + esp_diag_variable_add_mac(KEY_BSSID, ap_info.bssid); + esp_diag_variable_add_int(KEY_CHANNEL, ap_info.primary); + esp_diag_variable_add_uint(KEY_AUTHMODE, ap_info.authmode); +#else + esp_diag_variable_report_str(TAG_WIFI, KEY_SSID, (char *)ap_info.ssid); + esp_diag_variable_report_mac(TAG_WIFI, KEY_BSSID, ap_info.bssid); + esp_diag_variable_report_int(TAG_WIFI, KEY_CHANNEL, ap_info.primary); + esp_diag_variable_report_uint(TAG_WIFI, KEY_AUTHMODE, ap_info.authmode); +#endif + } + + memset(&ip_info, 0, sizeof(ip_info)); + /* If wifi interface is up and running then record the details */ + if (esp_netif_is_netif_up(esp_netif_get_handle_from_ifkey("WIFI_STA_DEF")) + && esp_netif_get_ip_info(esp_netif_get_handle_from_ifkey("WIFI_STA_DEF"), &ip_info) == ESP_OK) { +#ifdef CONFIG_ESP_INSIGHTS_META_VERSION_10 + esp_diag_variable_add_ipv4(KEY_IPv4, ip_info.ip.addr); + esp_diag_variable_add_ipv4(KEY_NETMASK, ip_info.netmask.addr); + esp_diag_variable_add_ipv4(KEY_GATEWAY, ip_info.gw.addr); +#else + esp_diag_variable_report_ipv4(TAG_IP, KEY_IPv4, ip_info.ip.addr); + esp_diag_variable_report_ipv4(TAG_IP, KEY_NETMASK, ip_info.netmask.addr); + esp_diag_variable_report_ipv4(TAG_IP, KEY_GATEWAY, ip_info.gw.addr); +#endif + } +#ifdef CONFIG_ESP_INSIGHTS_META_VERSION_10 + esp_diag_variable_add_int(KEY_DISC_CNT, s_priv_data.disconn_cnt); +#else + esp_diag_variable_report_int(TAG_WIFI, KEY_DISC_CNT, s_priv_data.disconn_cnt); +#endif + s_priv_data.init = true; + return ESP_OK; +} + +esp_err_t esp_diag_network_variables_deinit(void) +{ + if (!s_priv_data.init) { + return ESP_ERR_INVALID_STATE; + } + esp_event_handler_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, evt_handler); + esp_event_handler_unregister(IP_EVENT, ESP_EVENT_ANY_ID, evt_handler); + +#ifdef CONFIG_ESP_INSIGHTS_META_VERSION_10 + esp_diag_variable_unregister(KEY_SSID); + esp_diag_variable_unregister(KEY_BSSID); + esp_diag_variable_unregister(KEY_CHANNEL); + esp_diag_variable_unregister(KEY_AUTHMODE); + esp_diag_variable_unregister(KEY_REASON); + esp_diag_variable_unregister(KEY_DISC_CNT); + esp_diag_variable_unregister(KEY_IPv4); + esp_diag_variable_unregister(KEY_NETMASK); + esp_diag_variable_unregister(KEY_GATEWAY); +#if CONFIG_DIAG_MORE_NETWORK_VARS + esp_diag_variable_unregister(KEY_PROTOCOL); + esp_diag_variable_unregister(KEY_BANDWIDTH); + esp_diag_variable_unregister(KEY_POWER_SAVE); + esp_diag_variable_unregister(KEY_SECOND_CH); + esp_diag_variable_unregister(KEY_PROTOCOL_AP); + esp_diag_variable_unregister(KEY_BANDWIDTH_AP); +#endif +#else + esp_diag_variable_unregister(TAG_WIFI, KEY_SSID); + esp_diag_variable_unregister(TAG_WIFI, KEY_BSSID); + esp_diag_variable_unregister(TAG_WIFI, KEY_CHANNEL); + esp_diag_variable_unregister(TAG_WIFI, KEY_AUTHMODE); + esp_diag_variable_unregister(TAG_WIFI, KEY_REASON); + esp_diag_variable_unregister(TAG_WIFI, KEY_DISC_CNT); + esp_diag_variable_unregister(TAG_IP, KEY_IPv4); + esp_diag_variable_unregister(TAG_IP, KEY_NETMASK); + esp_diag_variable_unregister(TAG_IP, KEY_GATEWAY); +#if CONFIG_DIAG_MORE_NETWORK_VARS + esp_diag_variable_unregister(TAG_WIFI, KEY_PROTOCOL); + esp_diag_variable_unregister(TAG_WIFI, KEY_BANDWIDTH); + esp_diag_variable_unregister(TAG_WIFI, KEY_POWER_SAVE); + esp_diag_variable_unregister(TAG_WIFI, KEY_SECOND_CH); + esp_diag_variable_unregister(TAG_WIFI, KEY_PROTOCOL_AP); + esp_diag_variable_unregister(TAG_WIFI, KEY_BANDWIDTH_AP); +#endif +#endif + memset(&s_priv_data, 0, sizeof(s_priv_data)); + return ESP_OK; +} diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/src/esp_diagnostics_utils.c b/RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/src/esp_diagnostics_utils.c new file mode 100644 index 000000000..f872b4bac --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/src/esp_diagnostics_utils.c @@ -0,0 +1,359 @@ +/* + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "esp_partition.h" +#include "esp_idf_version.h" +#include "esp_diagnostics.h" +#include "esp_log.h" +#include "sys/time.h" +#include "esp_system.h" +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "soc/soc_memory_layout.h" +#include "esp_debug_helpers.h" +#include "esp_diagnostics_metrics.h" +#include "esp_diagnostics_variables.h" + +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0) +#include "esp_chip_info.h" +#else +#include "esp_ota_ops.h" +#endif + +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 3, 0) +#include +#define ESP_CRC32_LE(crc, buf, len) esp_rom_crc32_le(crc, buf, len) +#define TASK_GET_NAME(handle) pcTaskGetName(handle) +#else +#include +#define ESP_CRC32_LE(crc, buf, len) esp_crc32_le(crc, buf, len) +#define TASK_GET_NAME(handle) pcTaskGetTaskName(handle) +#endif + +#define TASK_SNAP_TAG "task_snap" +#define TASK_INFO_FMT "task:%s state:%" PRIu32 " high_watermark:%" PRIu32 " " +#define BT_FMT "bt:" +#define BT_DEPTH_FMT_1 "0x%" PRIx32 " " +#define BT_DEPTH_FMT_2 "0x%" PRIx32 " 0x%" PRIx32 " " +#define BT_DEPTH_FMT_3 "0x%" PRIx32 " 0x%" PRIx32 " 0x%" PRIx32 " " +#define BT_DEPTH_FMT_4 "0x%" PRIx32 " 0x%" PRIx32 " 0x%" PRIx32 " 0x%" PRIx32 " " +#define BT_DEPTH_FMT_8 BT_DEPTH_FMT_4 BT_DEPTH_FMT_4 +#define BT_DEPTH_FMT_16 BT_DEPTH_FMT_8 BT_DEPTH_FMT_8 + +/* From esp-idf v4.4 onwards + * - portENTER_CRITICAL_NESTED() and portEXIT_CRITICAL_NESTED() macros are deprecated + * - freertos/task_snapshot.h has been removed from freertos/task.h + */ +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 4, 0) +#include "freertos/task_snapshot.h" +#define DISABLE_INTERRUPTS portSET_INTERRUPT_MASK_FROM_ISR +#define ENABLE_INTERRUPTS portCLEAR_INTERRUPT_MASK_FROM_ISR +#else +#define DISABLE_INTERRUPTS portENTER_CRITICAL_NESTED +#define ENABLE_INTERRUPTS portEXIT_CRITICAL_NESTED +#endif + +/* ESP-IDF v5.0 changed some existing APIs and moved some to other header files + */ + +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0) +#include +#if CONFIG_IDF_TARGET_ARCH_XTENSA +#include +#endif +#endif + +esp_err_t esp_diag_device_info_get(esp_diag_device_info_t *device_info) +{ + esp_chip_info_t chip; + const esp_app_desc_t *app_desc; + + if (!device_info) { + return ESP_ERR_INVALID_ARG; + } + + esp_chip_info(&chip); + device_info->chip_model = chip.model; + device_info->chip_rev = chip.revision; + device_info->reset_reason = esp_reset_reason(); +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0) + app_desc = esp_app_get_description(); + const uint8_t* src = app_desc->app_elf_sha256; + memcpy((uint8_t *)device_info->app_elf_sha256, src, DIAG_SHA_SIZE); +#else + app_desc = esp_ota_get_app_description(); + esp_ota_get_app_elf_sha256(device_info->app_elf_sha256, sizeof(device_info->app_elf_sha256)); +#endif + strlcpy(device_info->app_version, app_desc->version, sizeof(device_info->app_version)); + strlcpy(device_info->project_name, app_desc->project_name, sizeof(device_info->project_name)); + return ESP_OK; +} + +uint64_t esp_diag_timestamp_get(void) +{ + struct timeval tv_now; + if (gettimeofday(&tv_now, NULL) == 0) { + return ((uint64_t)tv_now.tv_sec * 1000000L + (uint64_t)tv_now.tv_usec); + } else { + /* esp_log_timestamp returns timestamp in milliseconds */ + return ((uint64_t)esp_log_timestamp() * 1000); + } +} + +#ifndef CONFIG_IDF_TARGET_ARCH_RISCV +static void diag_task_get_bt(esp_diag_task_bt_t *bt_info, XtExcFrame *stack) +{ + esp_backtrace_frame_t frame = { + .pc = stack->pc, + .sp = stack->a1, + .next_pc = stack->a0, + }; + uint32_t i = 0; + uint32_t max_depth = sizeof(bt_info->bt) / sizeof(bt_info->bt[0]); + bool corrupted = !(esp_stack_ptr_is_sane(frame.sp) && + esp_ptr_executable((void *)esp_cpu_process_stack_pc(frame.pc))); + + bt_info->bt[i++] = esp_cpu_process_stack_pc(frame.pc); + while (max_depth-- > 0 && frame.next_pc && !corrupted) { + if (!esp_backtrace_get_next_frame(&frame)) { + corrupted = true; + } + if (corrupted == false) { + bt_info->bt[i++] = esp_cpu_process_stack_pc(frame.pc); + } + } + bt_info->depth = i; + bt_info->corrupted = corrupted; +} +#endif /* !CONFIG_IDF_TARGET_ARCH_RISCV */ + +uint32_t esp_diag_task_snapshot_get(esp_diag_task_info_t *tasks, size_t size) +{ + if (!tasks || !size) { + return 0; + } + unsigned irq_state = DISABLE_INTERRUPTS(); +#if !CONFIG_FREERTOS_UNICORE + int other_cpu = xPortGetCoreID() ? 0 : 1; + esp_cpu_stall(other_cpu); +#endif + + uint32_t i = 0; + uint32_t task_count = uxTaskGetNumberOfTasks(); + TaskSnapshot_t *snapshots = calloc(task_count, sizeof(TaskSnapshot_t)); + if (!snapshots) { + return 0; + } + size_t tcb_size; /* unused */ + uint32_t count = uxTaskGetSnapshotAll(snapshots, task_count, &tcb_size); + if (count == 0) { + free(snapshots); + return 0; + } + for (i = 0; i < count; i++) { + TaskHandle_t handle = (TaskHandle_t)snapshots[i].pxTCB; + char *name = TASK_GET_NAME(handle); + if (name && *name) { + strlcpy(tasks[i].name, name, sizeof(tasks[i].name)); + } + tasks[i].state = eTaskGetState(handle); + tasks[i].high_watermark = uxTaskGetStackHighWaterMark(handle); +#ifndef CONFIG_IDF_TARGET_ARCH_RISCV + diag_task_get_bt(&tasks[i].bt_info, (XtExcFrame *)snapshots[i].pxTopOfStack); +#endif /* !CONFIG_IDF_TARGET_ARCH_RISCV */ + } + free(snapshots); + +#if !CONFIG_FREERTOS_UNICORE + esp_cpu_unstall(other_cpu); +#endif + ENABLE_INTERRUPTS(irq_state); + return i; +} + +#if CONFIG_IDF_TARGET_ARCH_RISCV +static void print_task_info(esp_diag_task_info_t *task) +{ + ESP_DIAG_EVENT(TASK_SNAP_TAG, TASK_INFO_FMT, task->name, task->state, task->high_watermark); +} +#else +static void print_task_info(esp_diag_task_info_t *task) +{ + switch(task->bt_info.depth) { + case 1: + ESP_DIAG_EVENT(TASK_SNAP_TAG, TASK_INFO_FMT BT_FMT BT_DEPTH_FMT_1, + task->name, task->state, task->high_watermark, + task->bt_info.bt[0]); + break; + case 2: + ESP_DIAG_EVENT(TASK_SNAP_TAG, TASK_INFO_FMT BT_FMT BT_DEPTH_FMT_2, + task->name, task->state, task->high_watermark, + task->bt_info.bt[0], task->bt_info.bt[1]); + break; + case 3: + ESP_DIAG_EVENT(TASK_SNAP_TAG, TASK_INFO_FMT BT_FMT BT_DEPTH_FMT_3, + task->name, task->state, task->high_watermark, + task->bt_info.bt[0], task->bt_info.bt[1], task->bt_info.bt[2]); + break; + case 4: + ESP_DIAG_EVENT(TASK_SNAP_TAG, TASK_INFO_FMT BT_FMT BT_DEPTH_FMT_4, + task->name, task->state, task->high_watermark, + task->bt_info.bt[0], task->bt_info.bt[1], task->bt_info.bt[2], task->bt_info.bt[3]); + break; + case 5: + ESP_DIAG_EVENT(TASK_SNAP_TAG, TASK_INFO_FMT BT_FMT BT_DEPTH_FMT_4 BT_DEPTH_FMT_1, + task->name, task->state, task->high_watermark, + task->bt_info.bt[0], task->bt_info.bt[1], task->bt_info.bt[2], task->bt_info.bt[3], + task->bt_info.bt[4]); + break; + case 6: + ESP_DIAG_EVENT(TASK_SNAP_TAG, TASK_INFO_FMT BT_FMT BT_DEPTH_FMT_4 BT_DEPTH_FMT_2, + task->name, task->state, task->high_watermark, + task->bt_info.bt[0], task->bt_info.bt[1], task->bt_info.bt[2], task->bt_info.bt[3], + task->bt_info.bt[4], task->bt_info.bt[5]); + break; + case 7: + ESP_DIAG_EVENT(TASK_SNAP_TAG, TASK_INFO_FMT BT_FMT BT_DEPTH_FMT_4 BT_DEPTH_FMT_3, + task->name, task->state, task->high_watermark, + task->bt_info.bt[0], task->bt_info.bt[1], task->bt_info.bt[2], task->bt_info.bt[3], + task->bt_info.bt[4], task->bt_info.bt[5], task->bt_info.bt[6]); + break; + case 8: + ESP_DIAG_EVENT(TASK_SNAP_TAG, TASK_INFO_FMT BT_FMT BT_DEPTH_FMT_8, + task->name, task->state, task->high_watermark, + task->bt_info.bt[0], task->bt_info.bt[1], task->bt_info.bt[2], task->bt_info.bt[3], + task->bt_info.bt[4], task->bt_info.bt[5], task->bt_info.bt[6], task->bt_info.bt[7]); + break; + case 9: + ESP_DIAG_EVENT(TASK_SNAP_TAG, TASK_INFO_FMT BT_FMT BT_DEPTH_FMT_8 BT_DEPTH_FMT_1, + task->name, task->state, task->high_watermark, + task->bt_info.bt[0], task->bt_info.bt[1], task->bt_info.bt[2], task->bt_info.bt[3], + task->bt_info.bt[4], task->bt_info.bt[5], task->bt_info.bt[6], task->bt_info.bt[7], + task->bt_info.bt[8]); + break; + case 10: + ESP_DIAG_EVENT(TASK_SNAP_TAG, TASK_INFO_FMT BT_FMT BT_DEPTH_FMT_8 BT_DEPTH_FMT_2, + task->name, task->state, task->high_watermark, + task->bt_info.bt[0], task->bt_info.bt[1], task->bt_info.bt[2], task->bt_info.bt[3], + task->bt_info.bt[4], task->bt_info.bt[5], task->bt_info.bt[6], task->bt_info.bt[7], + task->bt_info.bt[8], task->bt_info.bt[9]); + break; + case 11: + ESP_DIAG_EVENT(TASK_SNAP_TAG, TASK_INFO_FMT BT_FMT BT_DEPTH_FMT_8 BT_DEPTH_FMT_3, + task->name, task->state, task->high_watermark, + task->bt_info.bt[0], task->bt_info.bt[1], task->bt_info.bt[2], task->bt_info.bt[3], + task->bt_info.bt[4], task->bt_info.bt[5], task->bt_info.bt[6], task->bt_info.bt[7], + task->bt_info.bt[8], task->bt_info.bt[9], task->bt_info.bt[10]); + break; + case 12: + ESP_DIAG_EVENT(TASK_SNAP_TAG, TASK_INFO_FMT BT_FMT BT_DEPTH_FMT_8 BT_DEPTH_FMT_4, + task->name, task->state, task->high_watermark, + task->bt_info.bt[0], task->bt_info.bt[1], task->bt_info.bt[2], task->bt_info.bt[3], + task->bt_info.bt[4], task->bt_info.bt[5], task->bt_info.bt[6], task->bt_info.bt[7], + task->bt_info.bt[8], task->bt_info.bt[9], task->bt_info.bt[10], task->bt_info.bt[11]); + break; + case 13: + ESP_DIAG_EVENT(TASK_SNAP_TAG, TASK_INFO_FMT BT_FMT BT_DEPTH_FMT_8 BT_DEPTH_FMT_4 BT_DEPTH_FMT_1, + task->name, task->state, task->high_watermark, + task->bt_info.bt[0], task->bt_info.bt[1], task->bt_info.bt[2], task->bt_info.bt[3], + task->bt_info.bt[4], task->bt_info.bt[5], task->bt_info.bt[6], task->bt_info.bt[7], + task->bt_info.bt[8], task->bt_info.bt[9], task->bt_info.bt[10], task->bt_info.bt[11], + task->bt_info.bt[12]); + break; + case 14: + ESP_DIAG_EVENT(TASK_SNAP_TAG, TASK_INFO_FMT BT_FMT BT_DEPTH_FMT_8 BT_DEPTH_FMT_4 BT_DEPTH_FMT_2, + task->name, task->state, task->high_watermark, + task->bt_info.bt[0], task->bt_info.bt[1], task->bt_info.bt[2], task->bt_info.bt[3], + task->bt_info.bt[4], task->bt_info.bt[5], task->bt_info.bt[6], task->bt_info.bt[7], + task->bt_info.bt[8], task->bt_info.bt[9], task->bt_info.bt[10], task->bt_info.bt[11], + task->bt_info.bt[12], task->bt_info.bt[13]); + break; + case 15: + ESP_DIAG_EVENT(TASK_SNAP_TAG, TASK_INFO_FMT BT_FMT BT_DEPTH_FMT_8 BT_DEPTH_FMT_4 BT_DEPTH_FMT_3, + task->name, task->state, task->high_watermark, + task->bt_info.bt[0], task->bt_info.bt[1], task->bt_info.bt[2], task->bt_info.bt[3], + task->bt_info.bt[4], task->bt_info.bt[5], task->bt_info.bt[6], task->bt_info.bt[7], + task->bt_info.bt[8], task->bt_info.bt[9], task->bt_info.bt[10], task->bt_info.bt[11], + task->bt_info.bt[12], task->bt_info.bt[13], task->bt_info.bt[14]); + break; + case 16: + ESP_DIAG_EVENT(TASK_SNAP_TAG, TASK_INFO_FMT BT_FMT BT_DEPTH_FMT_16, + task->name, task->state, task->high_watermark, + task->bt_info.bt[0], task->bt_info.bt[1], task->bt_info.bt[2], task->bt_info.bt[3], + task->bt_info.bt[4], task->bt_info.bt[5], task->bt_info.bt[6], task->bt_info.bt[7], + task->bt_info.bt[8], task->bt_info.bt[9], task->bt_info.bt[10], task->bt_info.bt[11], + task->bt_info.bt[12], task->bt_info.bt[13], task->bt_info.bt[14], task->bt_info.bt[15]); + break; + } +} +#endif /* CONFIG_IDF_TARGET_ARCH_RISCV */ + +void esp_diag_task_snapshot_dump(void) +{ + int i; + size_t task_count = uxTaskGetNumberOfTasks(); + esp_diag_task_info_t *tasks = calloc(1, sizeof(esp_diag_task_info_t) * task_count); + if (!tasks) { + return; + } + uint32_t count = esp_diag_task_snapshot_get(tasks, task_count); + for (i = 0; i < count; i++) { + print_task_info(&tasks[i]); + } + free(tasks); +} + +uint32_t esp_diag_data_size_get_crc(void) +{ + size_t diag_data_size = sizeof(esp_diag_data_pt_t) + sizeof(esp_diag_str_data_pt_t) + sizeof(esp_diag_log_data_t); + uint32_t crc = 0; + crc = esp_crc32_le(crc, (const unsigned char *)&diag_data_size, sizeof(diag_data_size)); + return crc; +} + +uint32_t esp_diag_meta_crc_get(void) +{ + uint32_t crc = 0; + const esp_app_desc_t *app_desc; +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0) + app_desc = esp_app_get_description(); +#else + app_desc = esp_ota_get_app_description(); +#endif + crc = ESP_CRC32_LE(crc, (const uint8_t *) app_desc->app_elf_sha256, sizeof(app_desc->app_elf_sha256)); +#if CONFIG_DIAG_ENABLE_METRICS + uint32_t metrics_len = 0; + const esp_diag_metrics_meta_t *metrics = esp_diag_metrics_meta_get_all(&metrics_len); + if (metrics) { + uint32_t i; + for (i = 0; i < metrics_len; i++) { + crc = ESP_CRC32_LE(crc, (const uint8_t *)metrics[i].tag, strlen(metrics[i].tag)); + crc = ESP_CRC32_LE(crc, (const uint8_t *)metrics[i].key, strlen(metrics[i].key)); + crc = ESP_CRC32_LE(crc, (const uint8_t *)metrics[i].label, strlen(metrics[i].label)); + crc = ESP_CRC32_LE(crc, (const uint8_t *)metrics[i].path, strlen(metrics[i].path)); + crc = ESP_CRC32_LE(crc, (const uint8_t *)&metrics[i].type, sizeof(metrics[i].type)); + } + } +#endif /* CONFIG_DIAG_ENABLE_METRICS */ + +#if CONFIG_DIAG_ENABLE_VARIABLES + uint32_t variables_len = 0; + const esp_diag_variable_meta_t *variables = esp_diag_variable_meta_get_all(&variables_len); + if (variables) { + uint32_t i; + for (i = 0; i < variables_len; i++) { + crc = ESP_CRC32_LE(crc, (const uint8_t *)variables[i].tag, strlen(variables[i].tag)); + crc = ESP_CRC32_LE(crc, (const uint8_t *)variables[i].key, strlen(variables[i].key)); + crc = ESP_CRC32_LE(crc, (const uint8_t *)variables[i].label, strlen(variables[i].label)); + crc = ESP_CRC32_LE(crc, (const uint8_t *)variables[i].path, strlen(variables[i].path)); + crc = ESP_CRC32_LE(crc, (const uint8_t *)&variables[i].type, sizeof(variables[i].type)); + } + } +#endif /* CONFIG_DIAG_ENABLE_VARIABLES */ + return crc; +} diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/src/esp_diagnostics_variables.c b/RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/src/esp_diagnostics_variables.c new file mode 100644 index 000000000..e110cff31 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/src/esp_diagnostics_variables.c @@ -0,0 +1,344 @@ +/* + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include + +#define TAG "DIAG_VARIABLES" +#define DIAG_VARIABLES_MAX_COUNT CONFIG_DIAG_VARIABLES_MAX_COUNT + +/* Max supported string lenth */ +#define MAX_STR_LEN (sizeof(((esp_diag_str_data_pt_t *)0)->value.str) - 1) +#define MAX_VARIABLES_WRITE_SZ sizeof(esp_diag_data_pt_t) +#define MAX_STR_VARIABLES_WRITE_SZ sizeof(esp_diag_str_data_pt_t) + +typedef struct { + size_t variables_count; + esp_diag_variable_meta_t variables[DIAG_VARIABLES_MAX_COUNT]; + esp_diag_variable_config_t config; + bool init; +} variables_priv_data_t; + +static variables_priv_data_t s_priv_data; + +static esp_diag_variable_meta_t *esp_diag_variable_meta_get(const char *tag, const char *key) +{ + uint32_t i; + if (!tag || !key) { + return NULL; + } + for (i = 0; i < s_priv_data.variables_count; i++) { + if (s_priv_data.variables[i].key && + (strcmp(s_priv_data.variables[i].tag, tag) == 0) && + (strcmp(s_priv_data.variables[i].key, key) == 0)) { + return &s_priv_data.variables[i]; + } + } + return NULL; +} + +#ifdef CONFIG_ESP_INSIGHTS_META_VERSION_10 +/* Checks only by key for registered variable. Use this for meta version < 1.1 */ +static esp_diag_variable_meta_t *esp_diag_variable_meta_get_by_key(const char *key) +{ + uint32_t i; + if (!key) { + return NULL; + } + for (i = 0; i < s_priv_data.variables_count; i++) { + if (s_priv_data.variables[i].key && + (strcmp(s_priv_data.variables[i].key, key) == 0)) { + return &s_priv_data.variables[i]; + } + } + return NULL; +} +#endif + +static bool tag_key_present(const char *tag, const char *key) +{ + return (esp_diag_variable_meta_get(tag, key) != NULL); +} + +esp_err_t esp_diag_variable_register(const char *tag, const char *key, + const char *label, const char *path, + esp_diag_data_type_t type) +{ + if (!tag || !key || !label || !path) { + ESP_LOGE(TAG, "Failed to register variable, tag, key, lable, or path is NULL"); + return ESP_ERR_INVALID_ARG; + } + if (!s_priv_data.init) { + return ESP_ERR_INVALID_STATE; + } + if (s_priv_data.variables_count >= DIAG_VARIABLES_MAX_COUNT) { + ESP_LOGE(TAG, "No space left for more variable"); + return ESP_ERR_NO_MEM; + } + if (tag_key_present(tag, key)) { + ESP_LOGE(TAG, "Param-val tag:%s, key:%s exists", tag, key); + return ESP_FAIL; + } + s_priv_data.variables[s_priv_data.variables_count].tag = tag; + s_priv_data.variables[s_priv_data.variables_count].key = key; + s_priv_data.variables[s_priv_data.variables_count].label = label; + s_priv_data.variables[s_priv_data.variables_count].unit = NULL; + s_priv_data.variables[s_priv_data.variables_count].path = path; + s_priv_data.variables[s_priv_data.variables_count].type = type; + s_priv_data.variables_count++; + return ESP_OK; +} + +#ifdef CONFIG_ESP_INSIGHTS_META_VERSION_10 +esp_err_t esp_diag_variable_add_unit(const char *key, const char *unit) +#else +esp_err_t esp_diag_variable_add_unit(const char *tag, const char *key, const char *unit) +#endif +{ + if (!key) { + return ESP_ERR_INVALID_ARG; + } + if (!s_priv_data.init) { + return ESP_ERR_INVALID_STATE; + } +#ifdef CONFIG_ESP_INSIGHTS_META_VERSION_10 + esp_diag_variable_meta_t *variable = esp_diag_variable_meta_get_by_key(key); + if (!variable) { + ESP_LOGI(TAG, "var with (key %s) not found", key); + return ESP_ERR_NOT_FOUND; + } +#else + esp_diag_variable_meta_t *variable = esp_diag_variable_meta_get(tag, key); + if (!variable) { + ESP_LOGI(TAG, "var with (tag %s, key %s) not found", tag, key); + return ESP_ERR_NOT_FOUND; + } +#endif + variable->unit = unit; + return ESP_OK; +} + +#ifdef CONFIG_ESP_INSIGHTS_META_VERSION_10 +esp_err_t esp_diag_variable_unregister(const char *key) +#else +esp_err_t esp_diag_variable_unregister(const char *tag, const char *key) +#endif +{ + int i; +#ifndef CONFIG_ESP_INSIGHTS_META_VERSION_10 + if (!tag) { + return ESP_ERR_INVALID_ARG; + } +#endif + if (!key) { + return ESP_ERR_INVALID_ARG; + } + for (i = 0; i < s_priv_data.variables_count; i++) { + if (s_priv_data.variables[i].key && +#ifndef CONFIG_ESP_INSIGHTS_META_VERSION_10 + (strcmp(s_priv_data.variables[i].tag, tag) == 0) && +#endif + (strcmp(s_priv_data.variables[i].key, key) == 0)) { + break; + } + } + if (i < s_priv_data.variables_count) { + s_priv_data.variables[i] = s_priv_data.variables[s_priv_data.variables_count - 1]; + memset(&s_priv_data.variables[s_priv_data.variables_count - 1], 0, sizeof(esp_diag_variable_meta_t)); + s_priv_data.variables_count--; + return ESP_OK; + } + return ESP_ERR_NOT_FOUND; +} + +esp_err_t esp_diag_variable_unregister_all(void) +{ + if (!s_priv_data.init) { + return ESP_ERR_INVALID_STATE; + } + memset(&s_priv_data.variables, 0, sizeof(s_priv_data.variables)); + s_priv_data.variables_count = 0; + return ESP_OK; +} + +const esp_diag_variable_meta_t *esp_diag_variable_meta_get_all(uint32_t *len) +{ + if (!s_priv_data.init) { + *len = 0; + return NULL; + } + *len = s_priv_data.variables_count; + return &s_priv_data.variables[0]; +} + +void esp_diag_variable_meta_print_all(void) +{ + uint32_t len; + uint32_t i; + const esp_diag_variable_meta_t *meta = esp_diag_variable_meta_get_all(&len); + if (meta) { + ESP_LOGI(TAG, "Tag\tKey\tLabel\tPath\tData type\n"); + for (i = 0; i < len; i++) { + ESP_LOGI(TAG, "%s\t%s\t%s\t%s\t%d\n", meta[i].tag, meta[i].key, meta[i].label, meta[i].path, meta[i].type); + } + } +} + +esp_err_t esp_diag_variable_init(esp_diag_variable_config_t *config) +{ + if (!config || !config->write_cb) { + return ESP_ERR_INVALID_ARG; + } + if (s_priv_data.init) { + return ESP_ERR_INVALID_STATE; + } + memcpy(&s_priv_data.config, config, sizeof(s_priv_data.config)); + s_priv_data.init = true; + return ESP_OK; +} + +esp_err_t esp_diag_variables_deinit(void) +{ + if (!s_priv_data.init) { + return ESP_ERR_INVALID_STATE; + } + memset(&s_priv_data, 0, sizeof(s_priv_data)); + return ESP_OK; +} + +#ifdef CONFIG_ESP_INSIGHTS_META_VERSION_10 +esp_err_t esp_diag_variable_add(esp_diag_data_type_t data_type, +#else +esp_err_t esp_diag_variable_report(esp_diag_data_type_t data_type, const char *tag, +#endif + const char *key, const void *val, + size_t val_sz, uint64_t ts) +{ +#ifndef CONFIG_ESP_INSIGHTS_META_VERSION_10 + if (!tag) { + return ESP_ERR_INVALID_ARG; + } +#endif + if (!key || !val) { + return ESP_ERR_INVALID_ARG; + } + if (!s_priv_data.init) { + return ESP_ERR_INVALID_STATE; + } + +#ifdef CONFIG_ESP_INSIGHTS_META_VERSION_10 + const esp_diag_variable_meta_t *variable = esp_diag_variable_meta_get_by_key(key); + if (!variable) { + ESP_LOGI(TAG, "var with (key %s) not registered", key); + return ESP_ERR_NOT_FOUND; + } +#else + const esp_diag_variable_meta_t *variable = esp_diag_variable_meta_get(tag, key); + if (!variable) { + ESP_LOGI(TAG, "var with (tag %s, key %s) not registered", tag, key); + return ESP_ERR_NOT_FOUND; + } +#endif + if (variable->type != data_type) { + return ESP_ERR_INVALID_ARG; + } + size_t write_sz = MAX_VARIABLES_WRITE_SZ; + if (variable->type == ESP_DIAG_DATA_TYPE_STR) { + write_sz = MAX_STR_VARIABLES_WRITE_SZ; + } + + esp_diag_str_data_pt_t data; + memset(&data, 0, sizeof(data)); + data.type = ESP_DIAG_DATA_PT_VARIABLE; + data.data_type = data_type; +#ifndef CONFIG_ESP_INSIGHTS_META_VERSION_10 + strlcpy(data.tag, tag, sizeof(data.tag)); +#endif + strlcpy(data.key, key, sizeof(data.key)); + data.ts = ts; + memcpy(&data.value, val, val_sz); + + if (s_priv_data.config.write_cb) { + return s_priv_data.config.write_cb(variable->tag, &data, write_sz, s_priv_data.config.cb_arg); + } + return ESP_OK; +} + +#ifdef CONFIG_ESP_INSIGHTS_META_VERSION_10 +esp_err_t esp_diag_variable_add_bool(const char *key, bool b) +{ + return esp_diag_variable_add(ESP_DIAG_DATA_TYPE_BOOL, key, &b, sizeof(b), esp_diag_timestamp_get()); +} + +esp_err_t esp_diag_variable_add_int(const char *key, int32_t i) +{ + return esp_diag_variable_add(ESP_DIAG_DATA_TYPE_INT, key, &i, sizeof(i), esp_diag_timestamp_get()); +} + +esp_err_t esp_diag_variable_add_uint(const char *key, uint32_t u) +{ + return esp_diag_variable_add(ESP_DIAG_DATA_TYPE_UINT, key, &u, sizeof(u), esp_diag_timestamp_get()); +} + +esp_err_t esp_diag_variable_add_float(const char *key, float f) +{ + return esp_diag_variable_add(ESP_DIAG_DATA_TYPE_FLOAT, key, &f, sizeof(f), esp_diag_timestamp_get()); +} + +esp_err_t esp_diag_variable_add_ipv4(const char *key, uint32_t ip) +{ + return esp_diag_variable_add(ESP_DIAG_DATA_TYPE_IPv4, key, &ip, sizeof(ip), esp_diag_timestamp_get()); +} + +esp_err_t esp_diag_variable_add_mac(const char *key, uint8_t *mac) +{ + return esp_diag_variable_add(ESP_DIAG_DATA_TYPE_MAC, key, mac, 6, esp_diag_timestamp_get()); +} + +esp_err_t esp_diag_variable_add_str(const char *key, const char *str) +{ + return esp_diag_variable_add(ESP_DIAG_DATA_TYPE_STR, key, str, strlen(str), esp_diag_timestamp_get()); +} +#else +esp_err_t esp_diag_variable_report_bool(const char *tag, const char *key, bool b) +{ + return esp_diag_variable_report(ESP_DIAG_DATA_TYPE_BOOL, tag, key, &b, sizeof(b), esp_diag_timestamp_get()); +} + +esp_err_t esp_diag_variable_report_int(const char *tag, const char *key, int32_t i) +{ + return esp_diag_variable_report(ESP_DIAG_DATA_TYPE_INT, tag, key, &i, sizeof(i), esp_diag_timestamp_get()); +} + +esp_err_t esp_diag_variable_report_uint(const char *tag, const char *key, uint32_t u) +{ + return esp_diag_variable_report(ESP_DIAG_DATA_TYPE_UINT, tag, key, &u, sizeof(u), esp_diag_timestamp_get()); +} + +esp_err_t esp_diag_variable_report_float(const char *tag, const char *key, float f) +{ + return esp_diag_variable_report(ESP_DIAG_DATA_TYPE_FLOAT, tag, key, &f, sizeof(f), esp_diag_timestamp_get()); +} + +esp_err_t esp_diag_variable_report_ipv4(const char *tag, const char *key, uint32_t ip) +{ + return esp_diag_variable_report(ESP_DIAG_DATA_TYPE_IPv4, tag, key, &ip, sizeof(ip), esp_diag_timestamp_get()); +} + +esp_err_t esp_diag_variable_report_mac(const char *tag, const char *key, uint8_t *mac) +{ + return esp_diag_variable_report(ESP_DIAG_DATA_TYPE_MAC, tag, key, mac, 6, esp_diag_timestamp_get()); +} + +esp_err_t esp_diag_variable_report_str(const char *tag, const char *key, const char *str) +{ + return esp_diag_variable_report(ESP_DIAG_DATA_TYPE_STR, tag, key, str, strlen(str), esp_diag_timestamp_get()); +} +#endif diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/src/esp_diagnostics_wifi_metrics.c b/RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/src/esp_diagnostics_wifi_metrics.c new file mode 100644 index 000000000..1b1164088 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_diagnostics/src/esp_diagnostics_wifi_metrics.c @@ -0,0 +1,244 @@ +/* + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include "sdkconfig.h" + +#include +#include +#include "esp_diagnostics_internal.h" + +#define LOG_TAG "wifi_metrics" +#define METRICS_TAG "wifi" +#define METRICS_UNIT "dB" +#define KEY_RSSI "rssi" +#define KEY_MIN_RSSI "min_rssi_ever" +#define KEY_STATUS "conn_status" + +#define PATH_WIFI_STATION "Wi-Fi.Station" + +/* Use configurable polling interval with default fallback */ +#ifdef CONFIG_DIAG_WIFI_POLLING_INTERVAL +#define DEFAULT_POLLING_INTERVAL CONFIG_DIAG_WIFI_POLLING_INTERVAL +#else +#define DEFAULT_POLLING_INTERVAL 30 /* 30 seconds */ +#endif + +/* start reporting minimum ever rssi when rssi reaches -50 dbm */ +#define WIFI_RSSI_THRESHOLD -50 + +typedef struct { + bool init; + bool wifi_connected; + bool status_sent; + uint32_t period; + TimerHandle_t handle; + int32_t prev_rssi; + int32_t min_rssi; +} wifi_diag_priv_data_t; + +static wifi_diag_priv_data_t s_priv_data; + +static void update_min_rssi(int32_t rssi) +{ + if (rssi < s_priv_data.min_rssi) { + s_priv_data.min_rssi = rssi; +#ifndef CONFIG_ESP_INSIGHTS_META_VERSION_10 + esp_diag_metrics_report_int(METRICS_TAG, KEY_MIN_RSSI, rssi); +#else + esp_diag_metrics_add_int(KEY_MIN_RSSI, rssi); +#endif + ESP_LOGI(LOG_TAG, "Wi-Fi RSSI crossed threshold %" PRIi32, rssi); +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 3, 0) + esp_wifi_set_rssi_threshold(rssi); +#endif + } +} + +static void wifi_evt_handler(void *arg, esp_event_base_t evt_base, int32_t evt_id, void *evt_data) +{ + switch (evt_id) { +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 3, 0) + case WIFI_EVENT_STA_BSS_RSSI_LOW: + { + wifi_event_bss_rssi_low_t *data = evt_data; + update_min_rssi(data->rssi); + } + break; +#endif /* ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 3, 0) */ + case WIFI_EVENT_STA_CONNECTED: + { + s_priv_data.wifi_connected = true; + s_priv_data.status_sent = false; +#ifndef CONFIG_ESP_INSIGHTS_META_VERSION_10 + if (esp_diag_metrics_report_bool(METRICS_TAG, KEY_STATUS, 1) == ESP_OK) { + s_priv_data.status_sent = true; + } +#else + if (esp_diag_metrics_add_bool(KEY_STATUS, 1) == ESP_OK) { + s_priv_data.status_sent = true; + } +#endif + + break; + } + case WIFI_EVENT_STA_DISCONNECTED: + { + if (s_priv_data.wifi_connected) { + s_priv_data.wifi_connected = false; + s_priv_data.status_sent = false; +#ifndef CONFIG_ESP_INSIGHTS_META_VERSION_10 + if (esp_diag_metrics_report_bool(METRICS_TAG, KEY_STATUS, 0) == ESP_OK) { + s_priv_data.status_sent = true; + } +#else + if (esp_diag_metrics_add_bool(KEY_STATUS, 0) == ESP_OK) { + s_priv_data.status_sent = true; + } +#endif + } + break; + } + default: + break; + } +} + +/* This function returns 1 on failure otherwise valid RSSI */ +static int32_t get_rssi(void) +{ + wifi_ap_record_t ap_info; + if (esp_wifi_sta_get_ap_info(&ap_info) == ESP_OK) { + return ap_info.rssi; + } + return 1; +} + +esp_err_t esp_diag_wifi_metrics_dump(void) +{ + if (!s_priv_data.init) { + ESP_LOGW(LOG_TAG, "Wi-Fi metrics not initialized"); + return ESP_ERR_INVALID_STATE; + } + int32_t rssi = get_rssi(); + if (rssi != 1) { + update_min_rssi(rssi); +#ifndef CONFIG_ESP_INSIGHTS_META_VERSION_10 + RET_ON_ERR_WITH_LOG(esp_diag_metrics_report_int(METRICS_TAG, KEY_RSSI, rssi), ESP_LOG_WARN, LOG_TAG, + "Failed to add Wi-Fi metrics key:" KEY_RSSI); + RET_ON_ERR_WITH_LOG(esp_diag_metrics_report_int(METRICS_TAG, KEY_MIN_RSSI, s_priv_data.min_rssi), ESP_LOG_WARN, LOG_TAG, + "Failed to add Wi-Fi metrics key:" KEY_MIN_RSSI); +#else + RET_ON_ERR_WITH_LOG(esp_diag_metrics_add_int(KEY_RSSI, rssi), ESP_LOG_WARN, LOG_TAG, + "Failed to add Wi-Fi metrics key:" KEY_RSSI); + RET_ON_ERR_WITH_LOG(esp_diag_metrics_add_int(KEY_MIN_RSSI, s_priv_data.min_rssi), ESP_LOG_WARN, LOG_TAG, + "Failed to add Wi-Fi metrics key:" KEY_MIN_RSSI); +#endif + s_priv_data.prev_rssi = rssi; + ESP_LOGI(LOG_TAG, "%s:%" PRIi32 " %s:%" PRIi32, KEY_RSSI, rssi, KEY_MIN_RSSI, s_priv_data.min_rssi); + } + if (!s_priv_data.status_sent) { + // if for some reason we were not able to add the status, try again +#ifndef CONFIG_ESP_INSIGHTS_META_VERSION_10 + if (esp_diag_metrics_report_bool(METRICS_TAG, KEY_STATUS, s_priv_data.wifi_connected) == ESP_OK) { + s_priv_data.status_sent = true; + } +#else + if (esp_diag_metrics_add_bool(KEY_STATUS, s_priv_data.wifi_connected) == ESP_OK) { + s_priv_data.status_sent = true; + } +#endif + } + return ESP_OK; +} + +static void wifi_metrics_dump_cb(void *arg) +{ + esp_diag_wifi_metrics_dump(); +} + +static void wifi_timer_cb(TimerHandle_t handle) +{ + esp_rmaker_work_queue_add_task(wifi_metrics_dump_cb, NULL); +} + +esp_err_t esp_diag_wifi_metrics_init(void) +{ + if (s_priv_data.init) { + return ESP_ERR_INVALID_STATE; + } + /* Register the event handler for wifi events */ + esp_err_t err = esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, wifi_evt_handler, NULL); + if (err != ESP_OK) { + return err; + } +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 3, 0) + err = esp_wifi_set_rssi_threshold(WIFI_RSSI_THRESHOLD); + if (err != ESP_OK) { + ESP_LOGW(LOG_TAG, "Failed to set rssi threshold value"); + } +#endif + esp_diag_metrics_register(METRICS_TAG, KEY_RSSI, "Wi-Fi RSSI", PATH_WIFI_STATION, ESP_DIAG_DATA_TYPE_INT); + esp_diag_metrics_register(METRICS_TAG, KEY_MIN_RSSI, "Minimum ever Wi-Fi RSSI", PATH_WIFI_STATION, ESP_DIAG_DATA_TYPE_INT); + esp_diag_metrics_register(METRICS_TAG, KEY_STATUS, "Wi-Fi connect status", PATH_WIFI_STATION, ESP_DIAG_DATA_TYPE_BOOL); +#ifndef CONFIG_ESP_INSIGHTS_META_VERSION_10 + esp_diag_metrics_add_unit(METRICS_TAG, KEY_RSSI, METRICS_UNIT); + esp_diag_metrics_add_unit(METRICS_TAG, KEY_MIN_RSSI, METRICS_UNIT); +#else + esp_diag_metrics_add_unit(KEY_RSSI, METRICS_UNIT); + esp_diag_metrics_add_unit(KEY_MIN_RSSI, METRICS_UNIT); +#endif + s_priv_data.min_rssi = WIFI_RSSI_THRESHOLD; + s_priv_data.handle = xTimerCreate("wifi_metrics", SEC2TICKS(DEFAULT_POLLING_INTERVAL), + pdTRUE, NULL, wifi_timer_cb); + if (s_priv_data.handle) { + xTimerStart(s_priv_data.handle, 0); + } + s_priv_data.init = true; + /* Record RSSI at start */ + esp_diag_wifi_metrics_dump(); + return ESP_OK; +} + +esp_err_t esp_diag_wifi_metrics_deinit(void) +{ + if (!s_priv_data.init) { + return ESP_ERR_INVALID_STATE; + } + esp_event_handler_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, wifi_evt_handler); + /* Try to delete timer with 10 ticks wait time */ + if (xTimerDelete(s_priv_data.handle, 10) == pdFALSE) { + ESP_LOGW(LOG_TAG, "Failed to delete heap metric timer"); + } +#ifdef CONFIG_ESP_INSIGHTS_META_VERSION_10 + esp_diag_metrics_unregister(KEY_RSSI); + esp_diag_metrics_unregister(KEY_MIN_RSSI); + esp_diag_metrics_unregister(KEY_STATUS); +#else + esp_diag_metrics_unregister(METRICS_TAG, KEY_RSSI); + esp_diag_metrics_unregister(METRICS_TAG, KEY_MIN_RSSI); + esp_diag_metrics_unregister(METRICS_TAG, KEY_STATUS); +#endif + memset(&s_priv_data, 0, sizeof(s_priv_data)); + return ESP_OK; +} + +void esp_diag_wifi_metrics_reset_interval(uint32_t period) +{ + if (!s_priv_data.init) { + return; + } + if (period == 0) { + xTimerStop(s_priv_data.handle, 0); + return; + } + xTimerChangePeriod(s_priv_data.handle, SEC2TICKS(period), 0); +} diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_insights/.component_hash b/RainMaker_Table-Lights/managed_components/espressif__esp_insights/.component_hash new file mode 100644 index 000000000..57aac83b9 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_insights/.component_hash @@ -0,0 +1 @@ +b9e0863e821a4a18d5805a969a0240e1c82c59aff13b9350568fe7892cef84b3 \ No newline at end of file diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_insights/CHECKSUMS.json b/RainMaker_Table-Lights/managed_components/espressif__esp_insights/CHECKSUMS.json new file mode 100644 index 000000000..9fedc443d --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_insights/CHECKSUMS.json @@ -0,0 +1 @@ +{"version": "1.0", "algorithm": "sha256", "created_at": "2025-06-26T15:05:04.008787+00:00", "files": [{"path": "CMakeLists.txt", "size": 1851, "hash": "1ae6ac81e7c6a7f35e1feebf2d938fcfd340ea2abce645c5b7565e43cf5c4a75"}, {"path": "Kconfig", "size": 3892, "hash": "7ea93a5bb99bf5ba3ab74d04f2d14516e639d87532a2ff24e0fd707d215aff6d"}, {"path": "LICENSE", "size": 11358, "hash": "cfc7749b96f63bd31c3c42b5c471bf756814053e847c10f3eb003417bc523d30"}, {"path": "README.md", "size": 408, "hash": "d8860ff0dc69d4c4b6c6eff20b35af58f9b43892113fa2af674fee15724c76d3"}, {"path": "idf_component.yml", "size": 719, "hash": "9fd63245ac3e8c9de1908d897fda6453efd61900c8cc6e555495a7bdfa9a2555"}, {"path": "project_include.cmake", "size": 1404, "hash": "dfb677a3a19b8dcf26e05ad56dd8e7fed0c4e30cb95fde23d92e35f1fe8fc20f"}, {"path": "include/esp_insights.h", "size": 7444, "hash": "269463d4b55bb848fb149bce1db8136b9ba661ff9d357417ab5c3061ce27946c"}, {"path": "scripts/gen_tar_dir.cmake", "size": 3638, "hash": "e89a8b65c7f642de4249f3cd0eb01d1e95b2fe6fbbfe6f1237a8248d1f06388e"}, {"path": "scripts/get_projbuild_gitconfig.py", "size": 3560, "hash": "372daadca20c2a66062ca5f77db61f4b30674efc3de0d62c2e5c6b5accf95cc2"}, {"path": "server_certs/https_server.crt", "size": 1188, "hash": "2c43952ee9e000ff2acc4e2ed0897c0a72ad5fa72c3d934e81741cbd54f05bd1"}, {"path": "server_certs/mqtt_server.crt", "size": 1188, "hash": "2c43952ee9e000ff2acc4e2ed0897c0a72ad5fa72c3d934e81741cbd54f05bd1"}, {"path": "src/esp_insights.c", "size": 37414, "hash": "2856e052d79f0ecce4d707f57e98630cee97217e3bc8d6de3778686ea6b6aee4"}, {"path": "src/esp_insights_cbor_decoder.c", "size": 11588, "hash": "1c314643c4c7b2d622bb2ac84766317cb139db9736e9720903eea0babf5d447e"}, {"path": "src/esp_insights_cbor_decoder.h", "size": 1560, "hash": "19dde3ba304804214a41402a155e0aac8e41de2d54c0048bc37bd6d40d00a97d"}, {"path": "src/esp_insights_cbor_encoder.c", "size": 35326, "hash": "4e8c622b17a8674996d953ea19fe2cebe93b19d5dfe131274aca964ef9a5b18a"}, {"path": "src/esp_insights_cbor_encoder.h", "size": 3505, "hash": "3cda3f143edaefbc2587acf649041e8f8189a21ae2a7ef09e631bfdad4bc1dce"}, {"path": "src/esp_insights_client_data.c", "size": 3443, "hash": "6aca785110facc9aabb6feb56f04b55f761391100159251db9eeb525a7cae1bd"}, {"path": "src/esp_insights_client_data.h", "size": 554, "hash": "d95f6505138c97f6f6ac5f42ce4c02b1b19a364680900161cb8855035d59349d"}, {"path": "src/esp_insights_cmd_resp.c", "size": 25392, "hash": "e5488c0cfc617c666c9ec79b6dc8c22858fda981a6e1bcd4df730ff60e2c7c8a"}, {"path": "src/esp_insights_encoder.c", "size": 7545, "hash": "5bf287595b8b19361516070cf762c3a6c890cfbbac1a7df56bebbaaf6aa75b96"}, {"path": "src/esp_insights_encoder.h", "size": 1293, "hash": "e46706af88b8e68c3a93123a8121832aa41c2208ec2a4ead2bab263c68c04953"}, {"path": "src/esp_insights_internal.h", "size": 1792, "hash": "f945b09dac01c9d17ea130f57057fb1769f3b1f3c7acee8783c2a239bc5de461"}, {"path": "src/esp_insights_transport.c", "size": 2513, "hash": "ac07c1e809f21fca536246a726be2325b633f9ff92a047a638bb66bba88c4dbd"}, {"path": "src/transport/esp_insights_https.c", "size": 5381, "hash": "1a31930945b755ee8fa291ab5ad41c93f2846b0b1463ad0f2d61d6d861b164ee"}, {"path": "src/transport/esp_insights_mqtt.c", "size": 6564, "hash": "fc7841df7fd00cbc0dc7bcb1b658468b41d08028d814eee57709a3eb64c18616"}]} \ No newline at end of file diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_insights/CMakeLists.txt b/RainMaker_Table-Lights/managed_components/espressif__esp_insights/CMakeLists.txt new file mode 100644 index 000000000..8f0f38a96 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_insights/CMakeLists.txt @@ -0,0 +1,47 @@ +# ESP Insights +set(srcs "src/esp_insights.c" + "src/esp_insights_transport.c" + "src/esp_insights_client_data.c" + "src/esp_insights_encoder.c" + "src/esp_insights_cmd_resp.c" + "src/esp_insights_cbor_decoder.c" + "src/esp_insights_cbor_encoder.c") + +set(priv_req cbor rmaker_common esptool_py espcoredump esp_diag_data_store nvs_flash) + +# esp_timer component was introduced in v4.2 +if("${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}" VERSION_GREATER "4.1") + list(APPEND priv_req esp_timer) +endif() + +# esp_hw_support component was introduced in v4.3 +if("${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}" VERSION_GREATER "4.2") + list(APPEND priv_req esp_hw_support) +endif() + +# from IDF version 5.0, we need to explicitly specify requirements +if("${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}" VERSION_GREATER_EQUAL "5.0") + list(APPEND priv_req esp_wifi) +endif() + +set(pub_req esp_diagnostics) + +idf_component_register(SRCS ${srcs} + INCLUDE_DIRS "include" + PRIV_INCLUDE_DIRS "src" + REQUIRES ${pub_req} + PRIV_REQUIRES ${priv_req}) + +if(CONFIG_ESP_INSIGHTS_TRANSPORT_MQTT) + target_add_binary_data(${COMPONENT_TARGET} "server_certs/mqtt_server.crt" TEXT) + target_sources(${COMPONENT_LIB} PRIVATE "src/transport/esp_insights_mqtt.c") +else() + target_add_binary_data(${COMPONENT_TARGET} "server_certs/https_server.crt" TEXT) + idf_component_get_property(http_client_lib esp_http_client COMPONENT_LIB) + target_link_libraries(${COMPONENT_LIB} PRIVATE ${http_client_lib}) + target_sources(${COMPONENT_LIB} PRIVATE "src/transport/esp_insights_https.c") +endif() + +# Added just to automatically trigger re-runs of CMake +git_describe(ESP_INSIGHTS_VERSION ${COMPONENT_DIR}) +message("ESP Insights Project commit: " ${ESP_INSIGHTS_VERSION}) diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_insights/Kconfig b/RainMaker_Table-Lights/managed_components/espressif__esp_insights/Kconfig new file mode 100644 index 000000000..460bf67de --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_insights/Kconfig @@ -0,0 +1,90 @@ +menu "ESP Insights" + + config ESP_INSIGHTS_ENABLED + bool "Enable ESP Insights" + default n + select DIAG_ENABLE_WRAP_LOG_FUNCTIONS + help + Enable ESP Insights functionality. + + This automatically selects log wrapping (DIAG_ENABLE_WRAP_LOG_FUNCTIONS) which is + required for ESP Insights to capture log messages. + + config ESP_INSIGHTS_DEBUG_ENABLED + depends on ESP_INSIGHTS_ENABLED + bool "Enable Insights debug prints" + default n + + config ESP_INSIGHTS_DEBUG_PRINT_JSON + depends on ESP_INSIGHTS_DEBUG_ENABLED + bool "Dump CBOR decoded data instead of hexdump" + default y + help + Print pretty format json data for cbor messages + If this option is not enabled, hexdump will be presented instead of json data + + config ESP_INSIGHTS_COREDUMP_ENABLE + bool "Enable core dump summary support" + default y + depends on (ESP_COREDUMP_ENABLE_TO_FLASH && ESP_COREDUMP_DATA_FORMAT_ELF) || (ESP32_ENABLE_COREDUMP_TO_FLASH && ESP32_COREDUMP_DATA_FORMAT_ELF) + help + This option enables core dump summary functionality in insights. + In case of crash, insights sends the core dump summary to cloud on next boot. + Once the core dump summary is sent to cloud, it is erased from flash partition of the device. + + choice ESP_INSIGHTS_TRANSPORT + prompt "Insights default transport" + default ESP_INSIGHTS_TRANSPORT_HTTPS + help + By default insights can send data to cloud using MQTT and HTTPS transports. + This option configures the default insights transport. + Insights transport can be overridden using esp_insights_transport_register API. + + config ESP_INSIGHTS_TRANSPORT_MQTT + bool "MQTT" + + config ESP_INSIGHTS_TRANSPORT_HTTPS + bool "HTTPS" + + endchoice + + config ESP_INSIGHTS_CMD_RESP_ENABLED + depends on (ESP_INSIGHTS_ENABLED && ESP_INSIGHTS_TRANSPORT_MQTT) + bool "Enable command response module" + default n + help + Enabling this option adds control of certain insights options remotely. + When enabled, the available configurations, should be shown on the dashboard + and controllable from there. + Please note, the feature is only available with RainMaker MQTT nodes for now. + + config ESP_INSIGHTS_TRANSPORT_HTTPS_HOST + depends on ESP_INSIGHTS_TRANSPORT_HTTPS + string "Insights https host" + default "https://client.insights.espressif.com" + + config ESP_INSIGHTS_CLOUD_POST_MIN_INTERVAL_SEC + int "Insights cloud post min interval (sec)" + default 60 + help + Minimum interval between two consecutive cloud posts. + There is a dynamic logic to decide the next timeout when the insights data will be reported. + It depends on whether the data was sent or not during the previous timeout. + If the data was sent, the next timeout is doubled and if not, it is halved. + + config ESP_INSIGHTS_CLOUD_POST_MAX_INTERVAL_SEC + int "Insights cloud post max interval (sec)" + default 240 + help + Maximum interval between two consecutive cloud posts. + There is a dynamic logic to decide the next timeout when the insights data will be reported. + It depends on whether the data was sent or not during the previous timeout. + If the data was sent, the next timeout is doubled and if not, it is halved. + + config ESP_INSIGHTS_META_VERSION_10 + bool "Use older metadata format (1.0)" + default y + help + For users already using older metadata, this provides an option to keep using the same. + This is important as the new metadata version (1.1), is not backwad compatible. +endmenu diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_insights/LICENSE b/RainMaker_Table-Lights/managed_components/espressif__esp_insights/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_insights/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_insights/README.md b/RainMaker_Table-Lights/managed_components/espressif__esp_insights/README.md new file mode 100644 index 000000000..dfa74dde0 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_insights/README.md @@ -0,0 +1,6 @@ +# ESP Insights Agent Component + +[![Component Registry](https://components.espressif.com/components/espressif/esp_insights/badge.svg)](https://components.espressif.com/components/espressif/esp_insights) + +This is the main firmware agent for ESP Insights, which will then pull in other required comoponents. Please check the [ESP Insights documentation](https://github.com/espressif/esp-insights) for details. + diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_insights/idf_component.yml b/RainMaker_Table-Lights/managed_components/espressif__esp_insights/idf_component.yml new file mode 100644 index 000000000..5f1ad24fa --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_insights/idf_component.yml @@ -0,0 +1,22 @@ +dependencies: + espressif/cbor: + rules: + - if: idf_version >=5.0 + version: ~0.6 + espressif/esp_diag_data_store: + version: 1.0.2 + espressif/esp_diagnostics: + version: '>=1.2.3' + espressif/rmaker_common: + version: ~1.4.0 + idf: + version: '>=4.1' +description: Firmware agent for ESP Insights, which is a remote diagnostics solution + to monitor the health of ESP devices in the field. +issues: https://github.com/espressif/esp-insights/issues +repository: git://github.com/espressif/esp-insights.git +repository_info: + commit_sha: de283a76dddc7bff94a774582452dcb419dd7d56 + path: components/esp_insights +url: https://github.com/espressif/esp-insights/tree/main/components/esp_insights +version: 1.2.7 diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_insights/include/esp_insights.h b/RainMaker_Table-Lights/managed_components/espressif__esp_insights/include/esp_insights.h new file mode 100644 index 000000000..af834e685 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_insights/include/esp_insights.h @@ -0,0 +1,253 @@ +/* + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** @cond **/ +/** + * @brief Insights event base + */ +ESP_EVENT_DECLARE_BASE(INSIGHTS_EVENT); +/** @endcond **/ + +/** + * @brief ESP Insights configuration + */ +typedef struct { + /** Log types to enable, bitwise OR the values from \ref esp_diag_log_type_t */ + uint32_t log_type; + /** Node id for insights. If NULL then insights agent uses MAC address as node id */ + const char *node_id; + /** Authentication key, valid only for https transport */ + const char *auth_key; + /** Try to allocate large buffers in External RAM */ + bool alloc_ext_ram; +} esp_insights_config_t; + +/** + * @brief Insights events + * + * Transport layer emits events using default event loop, every transport + * event has event data of type \ref esp_insights_transport_event_data_t; + */ +typedef enum { + /** Asynchronous data send succeded. Event data contains the msg_id of the data. */ + INSIGHTS_EVENT_TRANSPORT_SEND_SUCCESS, + /** Asynchronous data send failed. Event data contains the msg_id of the data. */ + INSIGHTS_EVENT_TRANSPORT_SEND_FAILED, + /** Data received. Event data contains received data and data_len. */ + INSIGHTS_EVENT_TRANSPORT_RECV, +} esp_insights_event_t; + +/** + * @brief Insights transport event data + */ +typedef struct { + uint8_t *data; /*!< Data associated with the event */ + size_t data_len; /*!< Length of the data for the event */ + int msg_id; /*!< Message id */ +} esp_insights_transport_event_data_t; + +/** + * @brief Insights transport init callback prototype + * + * @param[in] userdata User data + * + * @return ESP_OK on success, appropriate error code otherwise. + */ +typedef esp_err_t(*esp_insights_transport_init_t)(void *userdata); + +/** + * @brief Insights transport deinit callback prototype + */ +typedef void(*esp_insights_transport_deinit_t)(void); + +/** + * @brief Insights transport connect callback prototype + * + * @return ESP_OK on success, appropriate error code otherwise. + */ +typedef esp_err_t(*esp_insights_transport_connect_t)(void); + +/** + * @brief Insights transport disconnect callback prototype + */ +typedef void(*esp_insights_transport_disconnect_t)(void); + +/** + * @brief Insights transport data send callback prototype + * + * @param[in] data Data to send + * @param[in] len Length of data + * + * @return msg_id Message_id of the sent data. + * On failure, -1 + * On success, 0 if data send happens synchronously. + * On success, message-id(positive integer) if data send happened asynchronously. + * + * @note If data send happened asynchronously then appropriate events in \ref esp_insights_event_t must be emitted. + */ +typedef int(*esp_insights_transport_data_send_t)(void *data, size_t len); + +/** + * @brief Insights transport configurations + */ +typedef struct { + /** Insights transport callback functions */ + struct { + /** Transport init function */ + esp_insights_transport_init_t init; + /** Transport deinit function */ + esp_insights_transport_deinit_t deinit; + /** Transport connect function */ + esp_insights_transport_connect_t connect; + /** Transport disconnect function */ + esp_insights_transport_disconnect_t disconnect; + /** Function to send data */ + esp_insights_transport_data_send_t data_send; + } callbacks; + /** User data */ + void *userdata; +} esp_insights_transport_config_t; + +/** + * @brief Initialize ESP Insights. + * + * This initializes ESP Insights with the transport (HTTPS/MQTT) as per the sdkconfig. + * To override the transport configuration, please use esp_insights_transport_register() + * and esp_insights_enable(). + * + * @param[in] config Configuration for ESP Insights. + * + * @return ESP_OK on success, appropriate error code otherwise + */ +esp_err_t esp_insights_init(esp_insights_config_t *config); + +/** + * @brief Deinitialize ESP Insights. + * + * Disconnects the registered transport and disables ESP Insights + */ +void esp_insights_deinit(void); + +/** + * @brief Register insights transport. + * + * This function should be used only when default transport needs to be overridden. + * + * @note Call esp_insights_enable() + * after registering your own transport to enable Insights. + * + * @param[in] config Configurations of type \ref esp_insights_transport_config_t + * + * @return ESP_OK on success, appropriate error code otherwise + */ +esp_err_t esp_insights_transport_register(esp_insights_transport_config_t *config); + +/** + * @brief Unregister insights transport. + * + * @note This API does not disable Insights. + * Call esp_insights_disable() to turn off Insights. + */ +void esp_insights_transport_unregister(void); + +/** + * @brief Read insights data from buffers and send it to the cloud. + * + * Call to this function is asynchronous, it may take some time to send the data. + * + * @return ESP_OK on success, appropriate error code otherwise + */ +esp_err_t esp_insights_send_data(void); + +/** + * @brief Enable ESP Insights except transport. + * + * This API is used in conjunction with esp_insights_transport_register() + * to start Insights with custom transport. + * + * @param[in] config Configuration for ESP Insights. + * + * @return ESP_OK on success, appropriate error code otherwise + */ +esp_err_t esp_insights_enable(esp_insights_config_t *config); + +/** + * @brief Disable ESP Insights. + * + * This API does not unregister the transport. + * + * @note Call esp_insights_transport_unregister() to remove the transport. + */ +void esp_insights_disable(void); + +/** + * @brief Returns pointer to the NULL terminated Node ID string. + * + * @return Pointer to a NULL terminated Node ID string. + */ +const char *esp_insights_get_node_id(void); + +/** + * @brief Check if insights reporting is enabled + * + * @return true reporting is on + * @return false reporting is off + */ +bool esp_insights_is_reporting_enabled(void); + +/** + * @brief Turn on the Insights reporting + * + * @return esp_err_t ESP_OK on success, apt error otherwise + */ +esp_err_t esp_insights_reporting_enable(); + +/** + * @brief Turn off the Insights repoting + * + * @return esp_err_t ESP_OK on success, apt error otherwise + * @note meta message if changed and the boot message will still be + * sent as this information is critical for Insights working with the + * cloud. You may disable insight completely using esp_insights_disable + */ +esp_err_t esp_insights_reporting_disable(); + +/** + * @brief Encode and parse the command directly using esp-insight's parser + * + * This tests only if the parser is working as expected. + */ +esp_err_t esp_insights_test_cmd_handler(); + +/** + * @brief Enable esp-insights command-response module + * + * This API registers esp-insights command parser which when data is received, + * parses it to filter out insights specific data, modifies configs accordingly, + * and prepares and gives response data to the module + * + * The \ref esp_insights_init takes care of initializing command response and + * enabling the same. In cases where, only esp_insights_enable is called, e.g., + * ESP Rainmaker's app_insights module, user needs to call this API, before or + * after \ref esp_insights_enable + */ +esp_err_t esp_insights_cmd_resp_enable(void); + +#ifdef __cplusplus +} +#endif diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_insights/project_include.cmake b/RainMaker_Table-Lights/managed_components/espressif__esp_insights/project_include.cmake new file mode 100644 index 000000000..28f5cb14b --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_insights/project_include.cmake @@ -0,0 +1,29 @@ +idf_build_get_property(python PYTHON) +idf_build_get_property(idf_path IDF_PATH) +idf_build_get_property(build_dir BUILD_DIR) + +set(PROJ_BUILD_CONFIG_FILE project_build_config.json) +set(ARCHIVE_NAME ${CMAKE_PROJECT_NAME}-v${PROJECT_VER}) + +if(CONFIG_ESP_INSIGHTS_ENABLED) +# This will create the archive tar +add_custom_command( + TARGET app + POST_BUILD + COMMAND ${python} ${CMAKE_CURRENT_LIST_DIR}/scripts/get_projbuild_gitconfig.py ${PROJECT_DIR} ${CMAKE_PROJECT_NAME} ${PROJECT_VER} ${build_dir}/${PROJ_BUILD_CONFIG_FILE} ${idf_path} ${_CMAKE_TOOLCHAIN_PREFIX} + COMMAND ${CMAKE_COMMAND} + -D BUILD_DIR=${build_dir} + -D PROJECT_DIR=${PROJECT_DIR} + -D PROJECT_NAME=${CMAKE_PROJECT_NAME} + -D PROJECT_VER=${PROJECT_VER} + -D ARCHIVE_DIR=${ARCHIVE_NAME} + -D PROJ_CONFIG_FILE=${PROJ_BUILD_CONFIG_FILE} + -D PARTITION_CSV_FILE=${CONFIG_PARTITION_TABLE_CUSTOM_FILENAME} + -P ${CMAKE_CURRENT_LIST_DIR}/scripts/gen_tar_dir.cmake + COMMAND ${CMAKE_COMMAND} -E echo "===================== Generating insights firmware package build/${ARCHIVE_NAME}.zip ======================" + COMMAND ${CMAKE_COMMAND} -E tar cfv ${ARCHIVE_NAME}.zip ${ARCHIVE_NAME} --format=zip + COMMAND ${CMAKE_COMMAND} -E remove_directory ${ARCHIVE_NAME} + COMMAND ${CMAKE_COMMAND} -E remove ${PROJ_BUILD_CONFIG_FILE} + VERBATIM +) +endif() diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_insights/scripts/gen_tar_dir.cmake b/RainMaker_Table-Lights/managed_components/espressif__esp_insights/scripts/gen_tar_dir.cmake new file mode 100644 index 000000000..238d94451 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_insights/scripts/gen_tar_dir.cmake @@ -0,0 +1,94 @@ +# A CMake script to create tar package for ESP Insights +# It is created for the esp_rainmaker component + +cmake_minimum_required(VERSION 3.5) + +# Set file paths +# Set app elf file path +set(elf_file_path ${BUILD_DIR}/${PROJECT_NAME}.elf) +# Set app binary file path +set(bin_file_path ${BUILD_DIR}/${PROJECT_NAME}.bin) +# Set app map file path +set(map_file_path ${BUILD_DIR}/${PROJECT_NAME}.map) +# Set project git config json file path +set(proj_config_file_path ${BUILD_DIR}/${PROJ_CONFIG_FILE}) +# Set sdkconfig file path +set(sdkconfig_file_path ${PROJECT_DIR}/sdkconfig) +# Set partition table binary file path +set(partition_bin_file_path ${BUILD_DIR}/partition_table/partition-table.bin) +# Set partition table csv file path +set(partition_csv_file_path ${PROJECT_DIR}/${PARTITION_CSV_FILE}) +# Set bootloader binary file path +set(bootloader_bin_file_path ${BUILD_DIR}/bootloader/bootloader.bin) +# Set ota data initial binary file path +set(ota_data_bin_file_path ${BUILD_DIR}/ota_data_initial.bin) +# Set flash args file path +set(flash_args_file_path ${BUILD_DIR}/flash_args) +# Set project build config file path +set(proj_desc_file_path ${BUILD_DIR}/project_description.json) +# Set custom project build config file path +set(custom_proj_desc_file_path ${BUILD_DIR}/project_description_custom.json) + +# Create archive directory +file(MAKE_DIRECTORY ${BUILD_DIR}/${ARCHIVE_DIR}) +# Copy project git config file generated to archive directory +file(COPY ${proj_config_file_path} DESTINATION ${BUILD_DIR}/${ARCHIVE_DIR}) + +# Copy elf file to archive directory +if(EXISTS ${elf_file_path}) + file(COPY ${elf_file_path} DESTINATION ${BUILD_DIR}/${ARCHIVE_DIR}) +endif() + +# Copy bin file to archive directory +if(EXISTS ${bin_file_path}) + file(COPY ${bin_file_path} DESTINATION ${BUILD_DIR}/${ARCHIVE_DIR}) +endif() + +# Copy map file to archive directory +if(EXISTS ${map_file_path}) + file(COPY ${map_file_path} DESTINATION ${BUILD_DIR}/${ARCHIVE_DIR}) +endif() + +# Copy sdkconfig file to archive directory +if(EXISTS ${sdkconfig_file_path}) + file(COPY ${sdkconfig_file_path} DESTINATION ${BUILD_DIR}/${ARCHIVE_DIR}) +endif() + +# Copy partition csv file to archive directory +if(EXISTS ${partition_csv_file_path}) + file(COPY ${partition_csv_file_path} DESTINATION ${BUILD_DIR}/${ARCHIVE_DIR}) +endif() + +# Copy partition bin file to archive directory +if(EXISTS ${partition_bin_file_path}) + # Create partition_table sub-dir in archive directory + file(MAKE_DIRECTORY ${BUILD_DIR}/${ARCHIVE_DIR}/partition_table) + file(COPY ${partition_bin_file_path} DESTINATION ${BUILD_DIR}/${ARCHIVE_DIR}/partition_table) +endif() + +# Copy bootloader bin file to archive directory +if(EXISTS ${bootloader_bin_file_path}) + # Create bootloader sub-dir in archive directory + file(MAKE_DIRECTORY ${BUILD_DIR}/${ARCHIVE_DIR}/bootloader) + file(COPY ${bootloader_bin_file_path} DESTINATION ${BUILD_DIR}/${ARCHIVE_DIR}/bootloader) +endif() + +# Copy ota_data_initial bin file to archive directory +if(EXISTS ${ota_data_bin_file_path}) + file(COPY ${ota_data_bin_file_path} DESTINATION ${BUILD_DIR}/${ARCHIVE_DIR}) +endif() + +# Copy flash args file to archive directory +if(EXISTS ${flash_args_file_path}) + file(COPY ${flash_args_file_path} DESTINATION ${BUILD_DIR}/${ARCHIVE_DIR}) +endif() + +# Copy project description json file to archive directory +if (EXISTS ${proj_desc_file_path}) + file(COPY ${proj_desc_file_path} DESTINATION ${BUILD_DIR}/${ARCHIVE_DIR}/) +endif() + +# Copy custom project description json file to archive directory +if (EXISTS ${custom_proj_desc_file_path}) + file(COPY ${custom_proj_desc_file_path} DESTINATION ${BUILD_DIR}/${ARCHIVE_DIR}/) +endif() diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_insights/scripts/get_projbuild_gitconfig.py b/RainMaker_Table-Lights/managed_components/espressif__esp_insights/scripts/get_projbuild_gitconfig.py new file mode 100644 index 000000000..146dcf97c --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_insights/scripts/get_projbuild_gitconfig.py @@ -0,0 +1,120 @@ +# This file is expected to be present in ${COMPONENT_DIR} +# accessed from components/esp_insights/CMakeLists.txt +# Used in: +# 1. Project ESP Insights build package tar file + +#from __future__ import unicode_literals +import os +import sys +import json +import subprocess +from builtins import range, str +from io import open + +# Input project directory from CMakeLists.txt +PROJ_DIR=sys.argv[1] +# Input project name +PROJ_NAME=sys.argv[2] +# Input project version +PROJ_VER=sys.argv[3] +# Input custom config filename from CMakeLists.txt +FILENAME=sys.argv[4] +# Input IDF_PATH from CMakeLists.txt +IDF_PATH=sys.argv[5] +# Toolchain Prefix +TOOLCHAIN_PREFIX=sys.argv[6] + +NEWLINE = "\n" + +CONFIG = {} + +# Set Config + +# Set current directory i.e Set ${COMPONENT_DIR} as current directory +CURR_DIR = os.getcwd() + +def _change_dir(dirname): + # Change directory + os.chdir(dirname) + + +def _set_submodule_cfg(submodules, repo_name): + # Set config for submodules + CFG_TITLE = "submodules" + NAME_STR = "name" + VERSION_STR = "version" + CONFIG[repo_name][CFG_TITLE] = [] + + if submodules: + # Get the submodule name and version + submodules_list = submodules.strip().split(NEWLINE) + for i in range(0, len(submodules_list), 2): + name = submodules_list[i].split('\'')[1] + version = submodules_list[i+1] + submodule_json = { NAME_STR: name, VERSION_STR: version } + CONFIG[repo_name][CFG_TITLE].append(submodule_json) + + +def run_cmd(command, get_basename=False): + try: + resp = subprocess.check_output(command, shell=True).strip().decode('utf-8') + if get_basename: + resp = os.path.basename(resp) + return resp + except subprocess.CalledProcessError: + raise Exception("ERROR: Please check command : {}".format(command)) + +def set_cfg(config_name): + # Set config for ESP-IDF Repo + if config_name == "esp-idf": + # Get repo name (for IDF repo) + REPO_CMD='git rev-parse --show-toplevel' + repo_name = run_cmd(REPO_CMD, get_basename=True) + CONFIG[repo_name] = {} + + # Get commit HEAD + GITHEAD_STR = "HEAD" + HEAD='git describe --always --tags --dirty' + head_ver = run_cmd(HEAD) + CONFIG[repo_name][GITHEAD_STR] = head_ver + + # Get submodule latest refs + SUBMODULE = 'git submodule foreach git describe --always --tags --dirty' + submodules = run_cmd(SUBMODULE) + _set_submodule_cfg(submodules, repo_name) + elif config_name == "toolchain": + # Get toolchain version + TOOLCHAIN_STR = "toolchain" + TOOLCHAIN = TOOLCHAIN_PREFIX + 'gcc --version' + toolchain = run_cmd(TOOLCHAIN) + CONFIG[TOOLCHAIN_STR] = toolchain.strip().split(NEWLINE)[0] + +# Set project details - name and version +def set_project_details(): + # Set project name and version + CONFIG['project'] = {} + CONFIG['project']['name'] = PROJ_NAME + CONFIG['project']['version'] = PROJ_VER + +try: + with open(FILENAME, "w+", encoding="utf-8") as output_file: + # ESP-IDF REPO CONFIG + # Change to ESP-IDF Directory + _change_dir(IDF_PATH) + set_cfg("esp-idf") + + # Change back to ${COMPONENT_DIR} + _change_dir(CURR_DIR) + + # Set project name and version + set_project_details() + + # GET TOOLCHAIN VERSION + set_cfg("toolchain") + + output_file.write(str(json.dumps(CONFIG, indent=4, sort_keys=True))) + +except Exception as e: + # Remove config file created if error occurs + os.system("rm " + FILENAME) + sys.exit(e) \ No newline at end of file diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_insights/server_certs/https_server.crt b/RainMaker_Table-Lights/managed_components/espressif__esp_insights/server_certs/https_server.crt new file mode 100644 index 000000000..a6f3e92af --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_insights/server_certs/https_server.crt @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF +ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6 +b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL +MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv +b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj +ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM +9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw +IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6 +VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L +93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm +jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA +A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI +U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs +N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv +o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU +5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy +rqXRfboQnoZsG4q5WTP468SQvvG5 +-----END CERTIFICATE----- diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_insights/server_certs/mqtt_server.crt b/RainMaker_Table-Lights/managed_components/espressif__esp_insights/server_certs/mqtt_server.crt new file mode 100644 index 000000000..a6f3e92af --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_insights/server_certs/mqtt_server.crt @@ -0,0 +1,20 @@ +-----BEGIN CERTIFICATE----- +MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF +ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6 +b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL +MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv +b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj +ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM +9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw +IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6 +VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L +93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm +jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC +AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA +A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI +U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs +N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv +o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU +5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy +rqXRfboQnoZsG4q5WTP468SQvvG5 +-----END CERTIFICATE----- diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_insights/src/esp_insights.c b/RainMaker_Table-Lights/managed_components/espressif__esp_insights/src/esp_insights.c new file mode 100644 index 000000000..c1243e5e1 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_insights/src/esp_insights.c @@ -0,0 +1,1076 @@ +/* + * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "esp_insights_client_data.h" +#include "esp_insights_encoder.h" +#include "esp_insights_cbor_decoder.h" + +#ifdef CONFIG_ESP_INSIGHTS_CMD_RESP_ENABLED +#define INSIGHTS_CMD_RESP 1 +#endif + +#include +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0) +#include +#endif + +#define INSIGHTS_DEBUG_ENABLED CONFIG_ESP_INSIGHTS_DEBUG_ENABLED + +#if CONFIG_ESP_INSIGHTS_CLOUD_POST_MIN_INTERVAL_SEC > CONFIG_ESP_INSIGHTS_CLOUD_POST_MAX_INTERVAL_SEC +#error "CONFIG_ESP_INSIGHTS_CLOUD_POST_MIN_INTERVAL_SEC must be less than or equal to CONFIG_ESP_INSIGHTS_CLOUD_POST_MAX_INTERVAL_SEC" +#endif + +#define CLOUD_REPORTING_PERIOD_MIN_SEC CONFIG_ESP_INSIGHTS_CLOUD_POST_MIN_INTERVAL_SEC +#define CLOUD_REPORTING_PERIOD_MAX_SEC CONFIG_ESP_INSIGHTS_CLOUD_POST_MAX_INTERVAL_SEC +#define CLOUD_REPORTING_TIMEOUT_TICKS ((30 * 1000) / portTICK_PERIOD_MS) + +#ifdef CONFIG_DIAG_DATA_STORE_RTC +#if CONFIG_RTC_STORE_DATA_SIZE > (1024 * 4) +#define INSIGHTS_DATA_MAX_SIZE (CONFIG_RTC_STORE_DATA_SIZE - 1024) +#else +#define INSIGHTS_DATA_MAX_SIZE CONFIG_RTC_STORE_DATA_SIZE +#endif +#else +/* TODO: Hardcoding it to 6K but needs to think about clearer way to define this */ +#define INSIGHTS_DATA_MAX_SIZE (1024 * 6) +#endif + +#define INSIGHTS_READ_BUF_SIZE (1024) // read this much data from data store in one go + +#define SEND_INSIGHTS_META (CONFIG_DIAG_ENABLE_METRICS || CONFIG_DIAG_ENABLE_VARIABLES) + +/* TAG for reporting generic miscellaneous insights. Different from ESP_LOGx tag */ +#define TAG_DIAG "diag" +#define KEY_LOG_WR_FAIL "log_wr_fail" + +#define DIAG_DATA_STORE_CRC_KEY "rtc_buf_sha" +#define INSIGHTS_NVS_NAMESPACE "storage" + +ESP_EVENT_DEFINE_BASE(INSIGHTS_EVENT); + +#ifdef CONFIG_ESP_INSIGHTS_ENABLED + +static const char *TAG = "esp_insights"; /* tag for ESP_LOGx */ + +typedef struct esp_insights_entry { + esp_rmaker_work_fn_t work_fn; + TimerHandle_t timer; + uint32_t min_seconds; + uint32_t max_seconds; + uint32_t cur_seconds; + void *priv_data; +} esp_insights_entry_t; + +typedef struct { + uint8_t *scratch_buf; + uint8_t *read_buf; // buffer to hold data read from RTC buf + int data_msg_id; + uint32_t data_msg_len; + SemaphoreHandle_t data_lock; + char app_sha256[DIAG_HEX_SHA_SIZE + 1]; + bool data_sent; +#if SEND_INSIGHTS_META +#if INSIGHTS_CMD_RESP + bool conf_meta_msg_pending; + uint32_t conf_meta_msg_id; +#endif + bool meta_msg_pending; + uint32_t meta_msg_id; + uint32_t meta_crc; +#endif /* SEND_INSIGHTS_META */ + bool data_send_inprogress; + uint32_t log_write_fail_cnt; /* Count of failed log write */ + TimerHandle_t data_send_timer; /* timer to reset data_send_inprogress flag on timeout */ + char *node_id; + int boot_msg_id; /* To track whether first message is sent or not, -1:failed, 0:success, >0:inprogress */ +#if INSIGHTS_CMD_RESP + int conf_msg_id; +#endif + bool init_done; /* insights init done */ + bool enabled; /* insights enable is done */ +} esp_insights_data_t; + +static esp_insights_data_t s_insights_data; +static esp_insights_entry_t *s_periodic_insights_entry; + +extern esp_err_t esp_insights_cmd_resp_init(void); + +static void esp_insights_first_call(void *priv_data) +{ + if (!priv_data) { + return; + } + esp_insights_entry_t *entry = (esp_insights_entry_t *)priv_data; + esp_rmaker_work_queue_add_task(entry->work_fn, entry->priv_data); + /* Start timer here so that the function is called periodically */ + ESP_LOGI(TAG, "Scheduling Insights timer for %" PRIu32 " seconds.", entry->cur_seconds); + xTimerStart(entry->timer, 0); +} + +/* Returns true if wifi is connected and insights is enabled, false otherwise */ +static bool is_insights_active(void) +{ + wifi_ap_record_t ap_info; + bool wifi_connected = esp_wifi_sta_get_ap_info(&ap_info) == ESP_OK; + return wifi_connected && s_insights_data.enabled; +} + +/* Returns true if wifi is connected, false otherwise */ +static bool is_wifi_connected(void) +{ + wifi_ap_record_t ap_info; + bool wifi_connected = esp_wifi_sta_get_ap_info(&ap_info) == ESP_OK; + return wifi_connected; +} + +/* This executes in the context of timer task. + * + * There is a dynamic logic to decide the next instance when the insights + * data will be reported. Depending on whether data was sent or not during + * the previous timeout, we double or halve the time period. + * This ensures that data generally gets reported quick enough, + * but if there's very frequent data being generated, it wont result + * into too frquent publishes. + * The period will keep changing between CLOUD_REPORTING_PERIOD_MIN_SEC and + * CLOUD_REPORTING_PERIOD_MAX_SEC + */ +static void esp_insights_common_cb(TimerHandle_t handle) +{ + esp_insights_entry_t *entry = (esp_insights_entry_t *)pvTimerGetTimerID(handle); + /* Check if any data was sent during the previous time out */ + xSemaphoreTake(s_insights_data.data_lock, portMAX_DELAY); + bool l_data_sent = s_insights_data.data_sent; + s_insights_data.data_sent = false; + xSemaphoreGive(s_insights_data.data_lock); + + if (entry) { + if (is_insights_active() == true) { + esp_rmaker_work_queue_add_task(entry->work_fn, entry->priv_data); + } + /* If data was sent during previous timer interval, double the period */ + if (l_data_sent) { + entry->cur_seconds <<= 1; /* Double the period */ + if (entry->cur_seconds > entry->max_seconds) { + entry->cur_seconds = entry->max_seconds; + } + } else { + /* If no data was sent during previous timer interval, halve the period */ + entry->cur_seconds >>= 1; /* Halve the period */ + if (entry->cur_seconds < entry->min_seconds) { + entry->cur_seconds = entry->min_seconds; + } + } + xTimerChangePeriod(handle, (entry->cur_seconds * 1000)/ portTICK_PERIOD_MS, 100); + xTimerStart(handle, 0); + } +} + +static esp_err_t esp_insights_unregister_periodic_handler(void) +{ + if (s_periodic_insights_entry) { + if (s_periodic_insights_entry->timer) { + ESP_LOGI(TAG, "Stopping the periodic timer"); + if (xTimerIsTimerActive(s_periodic_insights_entry->timer) == pdTRUE) { + xTimerStop(s_periodic_insights_entry->timer, portMAX_DELAY); + } + ESP_LOGI(TAG, "Deleting the periodic timer"); + xTimerDelete(s_periodic_insights_entry->timer, portMAX_DELAY); + s_periodic_insights_entry->timer = NULL; + } + + free(s_periodic_insights_entry); + s_periodic_insights_entry = NULL; + } + + return ESP_OK; +} + +static esp_err_t esp_insights_register_periodic_handler(esp_rmaker_work_fn_t work_fn, + uint32_t min_seconds, uint32_t max_seconds, + void *priv_data) +{ + if (s_periodic_insights_entry) { + ESP_LOGI(TAG, "s_periodic_insights_entry already registered"); + return ESP_OK; + } + + if (!work_fn || (min_seconds == 0) || (max_seconds == 0)) { + ESP_LOGI(TAG, "invalid params register_periodic_handler"); + return ESP_ERR_INVALID_ARG; + } + + s_periodic_insights_entry = calloc (1, sizeof(esp_insights_entry_t)); + if (!s_periodic_insights_entry) { + ESP_LOGI(TAG, "allocation failed, line %d", __LINE__); + return ESP_ERR_NO_MEM; + } + s_periodic_insights_entry->work_fn = work_fn; + s_periodic_insights_entry->priv_data = priv_data; + s_periodic_insights_entry->min_seconds = min_seconds; + s_periodic_insights_entry->max_seconds = max_seconds; + s_periodic_insights_entry->cur_seconds = min_seconds; + s_periodic_insights_entry->timer = xTimerCreate("test", (s_periodic_insights_entry->cur_seconds * 1000)/ portTICK_PERIOD_MS, + pdFALSE, (void *)s_periodic_insights_entry, esp_insights_common_cb); + if (!s_periodic_insights_entry->timer) { + ESP_LOGI(TAG, "timer creation failed, line %d", __LINE__); + free(s_periodic_insights_entry); + return ESP_FAIL; + } + /* Rainmaker work queue execution start after MQTT connection is established, + * esp_insights_first_call() will be executed after MQTT connection is established. + * It add the work_fn to the queue and start the periodic timer. + */ + esp_err_t ret = esp_rmaker_work_queue_add_task(esp_insights_first_call, s_periodic_insights_entry); + if (ret != ESP_OK) { + ESP_LOGI(TAG, "failed to enqueue insights_first_call, line %d", __LINE__); + } + return ret; +} + +static void data_send_timeout_cb(TimerHandle_t handle) +{ + xSemaphoreTake(s_insights_data.data_lock, portMAX_DELAY); + s_insights_data.data_send_inprogress = false; + if (s_insights_data.boot_msg_id > 0) { + s_insights_data.boot_msg_id = -1; + } +#if INSIGHTS_CMD_RESP + if (s_insights_data.conf_msg_id > 0) { + s_insights_data.conf_msg_id = -1; + } +#endif + xSemaphoreGive(s_insights_data.data_lock); +} + +/* This executes in the context of default event loop task */ +static void insights_event_handler(void* arg, esp_event_base_t event_base, + int32_t event_id, void* event_data) +{ + esp_insights_transport_event_data_t *data = event_data; + if (event_base != INSIGHTS_EVENT) { + return; + } + switch(event_id) { + case INSIGHTS_EVENT_TRANSPORT_SEND_SUCCESS: + if (data && data->msg_id) { + xSemaphoreTake(s_insights_data.data_lock, portMAX_DELAY); + if (data->msg_id == s_insights_data.data_msg_id) { +#if INSIGHTS_DEBUG_ENABLED + ESP_LOGI(TAG, "Data message send success, msg_id:%d.", data ? data->msg_id : 0); +#endif + esp_diag_data_store_critical_release(s_insights_data.data_msg_len); + s_insights_data.data_sent = true; + s_insights_data.data_send_inprogress = false; + if (xTimerIsTimerActive(s_insights_data.data_send_timer) == pdTRUE) { + xTimerStop(s_insights_data.data_send_timer, portMAX_DELAY); + } +#if SEND_INSIGHTS_META + } else if (s_insights_data.meta_msg_pending && data->msg_id == s_insights_data.meta_msg_id) { +#if INSIGHTS_DEBUG_ENABLED + ESP_LOGI(TAG, "Meta message send success, msg_id:%d.", data ? data->msg_id : 0); +#endif + esp_insights_meta_nvs_crc_set(s_insights_data.meta_crc); + s_insights_data.meta_msg_pending = false; + s_insights_data.data_sent = true; +#endif /* SEND_INSIGHTS_META */ + } else if (s_insights_data.boot_msg_id > 0 && s_insights_data.boot_msg_id == data->msg_id) { +#if INSIGHTS_DEBUG_ENABLED + ESP_LOGI(TAG, "Boot message send success, msg_id:%d.", data ? data->msg_id : 0); +#endif +#if CONFIG_ESP_INSIGHTS_COREDUMP_ENABLE + esp_core_dump_image_erase(); +#endif // CONFIG_ESP_INSIGHTS_COREDUMP_ENABLE + s_insights_data.boot_msg_id = 0; + } +#if INSIGHTS_CMD_RESP + else if (s_insights_data.conf_msg_id > 0 && s_insights_data.conf_msg_id == data->msg_id) { +#if INSIGHTS_DEBUG_ENABLED + ESP_LOGI(TAG, "Conf message send success, msg_id:%d.", data ? data->msg_id : 0); +#endif + s_insights_data.conf_msg_id = 0; + } +#endif + + xSemaphoreGive(s_insights_data.data_lock); + } + break; + case INSIGHTS_EVENT_TRANSPORT_SEND_FAILED: + xSemaphoreTake(s_insights_data.data_lock, portMAX_DELAY); + if (xTimerIsTimerActive(s_insights_data.data_send_timer) == pdTRUE) { + xTimerStop(s_insights_data.data_send_timer, portMAX_DELAY); + } + s_insights_data.data_send_inprogress = false; + if (s_insights_data.boot_msg_id > 0 && data->msg_id == s_insights_data.boot_msg_id) { + s_insights_data.boot_msg_id = -1; + } +#if INSIGHTS_CMD_RESP + else if (s_insights_data.conf_msg_id > 0 && data->msg_id == s_insights_data.conf_msg_id) { + s_insights_data.conf_msg_id = -1; + } +#endif + xSemaphoreGive(s_insights_data.data_lock); + break; + default: + break; + } +} + +#if INSIGHTS_DEBUG_ENABLED +#ifndef CONFIG_ESP_INSIGHTS_DEBUG_PRINT_JSON +static void hex_dump(uint8_t *data, uint32_t len) +{ + int index; + for (index = 0; index < len; index++) { + if ((index % 16) == 0) { + printf("\n"); + } + printf("0x%02x ", s_insights_data.scratch_buf[index]); + } + printf("\n"); +} +#endif + +static void insights_dbg_dump(uint8_t *data, uint32_t len) +{ +#if CONFIG_ESP_INSIGHTS_DEBUG_PRINT_JSON + esp_insights_cbor_decode_dump((const uint8_t *) (s_insights_data.scratch_buf + 3), len - 3); +#else + hex_dump(data, len); +#endif +} +#endif /* INSIGHTS_DEBUG_ENABLED */ + +static void send_boottime_data(void) +{ + uint16_t len = 0; + esp_insights_encode_data_begin(s_insights_data.scratch_buf, INSIGHTS_DATA_MAX_SIZE); + esp_insights_encode_boottime_data(); + len = esp_insights_encode_data_end(s_insights_data.scratch_buf); + if (len == 0) { + ESP_LOGE(TAG, "No boottime data to send"); + s_insights_data.boot_msg_id = 0; // mark it sent + } +#if INSIGHTS_DEBUG_ENABLED + ESP_LOGI(TAG, "Sending boottime data of length: %d", len); + insights_dbg_dump(s_insights_data.scratch_buf, len); +#endif + int msg_id = esp_insights_transport_data_send(s_insights_data.scratch_buf, len); + s_insights_data.boot_msg_id = msg_id; + if (msg_id > 0) { + return; + } else if (msg_id == 0) { +#if CONFIG_ESP_INSIGHTS_COREDUMP_ENABLE + esp_core_dump_image_erase(); +#endif // CONFIG_ESP_INSIGHTS_COREDUMP_ENABLE + } else { +#if INSIGHTS_DEBUG_ENABLED + ESP_LOGI(TAG, "boottime_data message send failed"); +#endif + } +} + +#if INSIGHTS_CMD_RESP +static void send_insights_conf_meta(void); +static void send_insights_config(void) +{ + send_insights_conf_meta(); +} +#endif + +#if SEND_INSIGHTS_META +/* Returns true if ESP Insights metadata CRC is changed */ +static bool insights_meta_changed(void) +{ + uint32_t nvs_crc; + uint32_t meta_crc = esp_diag_meta_crc_get(); + esp_err_t err = esp_insights_meta_nvs_crc_get(&nvs_crc); + if (err == ESP_OK && nvs_crc == meta_crc) { + /* crc found and matched, no need to send insights meta */ + return false; + } + ESP_LOGI(TAG, "Insights metadata changed"); + s_insights_data.meta_crc = meta_crc; + return true; +} + +static void send_insights_meta(void) +{ + uint16_t len = 0; + + memset(s_insights_data.scratch_buf, 0, INSIGHTS_DATA_MAX_SIZE); + len = esp_insights_encode_meta(s_insights_data.scratch_buf, INSIGHTS_DATA_MAX_SIZE, s_insights_data.app_sha256); + if (len == 0) { +#if INSIGHTS_DEBUG_ENABLED + ESP_LOGI(TAG, "No metadata to send"); +#endif + return; + } +#if INSIGHTS_DEBUG_ENABLED + ESP_LOGI(TAG, "Insights meta data length %d", len); + insights_dbg_dump(s_insights_data.scratch_buf, len); +#endif + int msg_id = esp_insights_transport_data_send(s_insights_data.scratch_buf, len); + if (msg_id > 0) { + xSemaphoreTake(s_insights_data.data_lock, portMAX_DELAY); + s_insights_data.meta_msg_pending = true; + s_insights_data.meta_msg_id = msg_id; + xSemaphoreGive(s_insights_data.data_lock); + } else if (msg_id == 0) { + esp_insights_meta_nvs_crc_set(s_insights_data.meta_crc); + } else { +#if INSIGHTS_DEBUG_ENABLED + ESP_LOGI(TAG, "meta message send failed"); +#endif + } +} +#endif /* SEND_INSIGHTS_META */ + +#if INSIGHTS_CMD_RESP +static void send_insights_conf_meta(void) +{ + uint16_t len = 0; + + memset(s_insights_data.scratch_buf, 0, INSIGHTS_DATA_MAX_SIZE); + len = esp_insights_encode_conf_meta(s_insights_data.scratch_buf, INSIGHTS_DATA_MAX_SIZE, s_insights_data.app_sha256); + if (len == 0) { +#if INSIGHTS_DEBUG_ENABLED + ESP_LOGI(TAG, "No conf metadata to send"); +#endif + return; + } +#if INSIGHTS_DEBUG_ENABLED + ESP_LOGI(TAG, "Insights conf meta data length %d", len); + insights_dbg_dump(s_insights_data.scratch_buf, len); +#endif + int msg_id = esp_insights_transport_data_send(s_insights_data.scratch_buf, len); + if (msg_id > 0) { + xSemaphoreTake(s_insights_data.data_lock, portMAX_DELAY); + s_insights_data.conf_meta_msg_pending = true; + s_insights_data.conf_meta_msg_id = msg_id; + xSemaphoreGive(s_insights_data.data_lock); + } else if (msg_id == 0) { /* sent successfully */ + s_insights_data.conf_meta_msg_pending = false; + } +} +#endif + +/* Consider 100 bytes are published and received on cloud but RMAKER_MQTT_EVENT_PUBLISHED + * event is not received for 100 bytes. In a mean time 50 bytes are added to the buffer. + * When the next time timer expires then old 100 bytes plus new 50 bytes will be published + * and if RMAKER_MQTT_EVENT_PUBLISHED event is recieve for the new message then 150 bytes + * will be removed from the buffers. + * + * In short, there is the possibility of data duplication, so cloud should be able to handle it. + */ + +/* This encodes and sends insights data */ +static void send_insights_data(void) +{ + uint16_t len = 0; + size_t critical_data_size = 0; + size_t non_critical_data_size = 0; + size_t critical_consumed = 0; + size_t non_critical_consumed = 0; + + memset(s_insights_data.scratch_buf, 0, INSIGHTS_DATA_MAX_SIZE); + +#if CONFIG_DIAG_ENABLE_VARIABLES + static uint32_t prev_log_write_fail_cnt = 0; + if (s_insights_data.log_write_fail_cnt > prev_log_write_fail_cnt) { + prev_log_write_fail_cnt = s_insights_data.log_write_fail_cnt; +#ifdef CONFIG_ESP_INSIGHTS_META_VERSION_10 + esp_diag_variable_add_uint(KEY_LOG_WR_FAIL, prev_log_write_fail_cnt); +#else + esp_diag_variable_report_uint(TAG_DIAG, KEY_LOG_WR_FAIL, prev_log_write_fail_cnt); +#endif + } +#endif /* CONFIG_DIAG_ENABLE_VARIABLES */ + + esp_insights_encode_data_begin(s_insights_data.scratch_buf, INSIGHTS_DATA_MAX_SIZE); + + critical_data_size = esp_diag_data_store_critical_read(s_insights_data.read_buf, INSIGHTS_READ_BUF_SIZE); + if (critical_data_size > 0) { + critical_consumed = esp_insights_encode_critical_data(s_insights_data.read_buf, critical_data_size); + } + + non_critical_data_size = esp_diag_data_store_non_critical_read(s_insights_data.read_buf, INSIGHTS_READ_BUF_SIZE); + if (non_critical_data_size > 0) { + non_critical_consumed = esp_insights_encode_non_critical_data(s_insights_data.read_buf, non_critical_data_size); + esp_diag_data_store_non_critical_release(non_critical_consumed); + } + len = esp_insights_encode_data_end(s_insights_data.scratch_buf); + if (!critical_consumed && !non_critical_consumed) { + len = 0; // just ignore the encoded data + } + + if (len == 0) { +#if INSIGHTS_DEBUG_ENABLED + ESP_LOGI(TAG, "No data to send"); +#endif + goto data_send_end; + } +#if INSIGHTS_DEBUG_ENABLED + ESP_LOGI(TAG, "Sending data of length: %d", len); + insights_dbg_dump(s_insights_data.scratch_buf, len); +#endif + int msg_id = esp_insights_transport_data_send(s_insights_data.scratch_buf, len); + if (msg_id > 0) { + xSemaphoreTake(s_insights_data.data_lock, portMAX_DELAY); + s_insights_data.data_msg_len = critical_consumed; + s_insights_data.data_msg_id = msg_id; + xTimerReset(s_insights_data.data_send_timer, portMAX_DELAY); + xSemaphoreGive(s_insights_data.data_lock); + return; + } else if (msg_id == 0) { + esp_diag_data_store_critical_release(critical_consumed); + s_insights_data.data_sent = true; + } else { +#if INSIGHTS_DEBUG_ENABLED + ESP_LOGI(TAG, "insights_data message send failed"); +#endif + } +data_send_end: + xSemaphoreTake(s_insights_data.data_lock, portMAX_DELAY); + s_insights_data.data_send_inprogress = false; + xSemaphoreGive(s_insights_data.data_lock); +} + +#if INSIGHTS_CMD_RESP +static void __insights_report_config_update(void *priv_data) +{ + send_insights_config(); +} +#endif + +static void insights_periodic_handler(void *priv_data) +{ + xSemaphoreTake(s_insights_data.data_lock, portMAX_DELAY); + /* Return if wifi is disconnected */ + if (is_insights_active() == false) { + s_insights_data.data_send_inprogress = false; + xSemaphoreGive(s_insights_data.data_lock); + return; + } + if (s_insights_data.data_send_inprogress) { + xSemaphoreGive(s_insights_data.data_lock); + return; + } + s_insights_data.data_send_inprogress = true; + xSemaphoreGive(s_insights_data.data_lock); +#if SEND_INSIGHTS_META + if (insights_meta_changed()) { + send_insights_meta(); +#if INSIGHTS_CMD_RESP + send_insights_conf_meta(); +#endif + } +#endif /* SEND_INSIGHTS_META */ + +#if INSIGHTS_CMD_RESP + xSemaphoreTake(s_insights_data.data_lock, portMAX_DELAY); + if (s_insights_data.conf_msg_id == -1) { + xSemaphoreGive(s_insights_data.data_lock); + send_insights_config(); + } else { + xSemaphoreGive(s_insights_data.data_lock); + } +#endif + xSemaphoreTake(s_insights_data.data_lock, portMAX_DELAY); + if (s_insights_data.boot_msg_id == -1) { + xSemaphoreGive(s_insights_data.data_lock); + send_boottime_data(); + } else { + xSemaphoreGive(s_insights_data.data_lock); + } + send_insights_data(); +} + +esp_err_t esp_insights_send_data(void) +{ + if (is_wifi_connected() == true) { + ESP_LOGI(TAG, "Sending data to cloud"); + return esp_rmaker_work_queue_add_task(insights_periodic_handler, NULL); + } + ESP_LOGW(TAG, "Wi-Fi not in connected state"); + return ESP_FAIL; +} + +#if INSIGHTS_CMD_RESP +void esp_insights_report_config_update(void) +{ + s_insights_data.conf_msg_id = -1; + if (is_wifi_connected() == true) { + /* if wifi is connected, immediately send the report */ + /* if not, this will be reported from periodic handler */ + esp_rmaker_work_queue_add_task(__insights_report_config_update, NULL); + } +} +#else +void esp_insights_report_config_update(void) +{ + ESP_LOGI(TAG, "Not reporting config when cmd_resp is not enabled"); +} +#endif + +static void data_store_event_handler(void* arg, esp_event_base_t event_base, + int32_t event_id, void* event_data) +{ + if (event_base != ESP_DIAG_DATA_STORE_EVENT) { + return; + } + switch(event_id) { + case ESP_DIAG_DATA_STORE_EVENT_CRITICAL_DATA_LOW_MEM: + case ESP_DIAG_DATA_STORE_EVENT_NON_CRITICAL_DATA_LOW_MEM: + { +#if INSIGHTS_DEBUG_ENABLED + ESP_LOGI(TAG, "ESP_DIAG_DATA_STORE_EVENT_%sCRITICAL_DATA_LOW_MEM", + event_id == ESP_DIAG_DATA_STORE_EVENT_CRITICAL_DATA_LOW_MEM ? "" : "NON_"); +#endif + if (is_insights_active() == true) { + esp_rmaker_work_queue_add_task(insights_periodic_handler, NULL); + } + break; + } + + case ESP_DIAG_DATA_STORE_EVENT_CRITICAL_DATA_WRITE_FAIL: + s_insights_data.log_write_fail_cnt++; +#if INSIGHTS_DEBUG_ENABLED + ESP_LOGI(TAG, "Log write fail count: %" PRIu32, s_insights_data.log_write_fail_cnt); +#endif + break; + + case ESP_DIAG_DATA_STORE_EVENT_NON_CRITICAL_DATA_WRITE_FAIL: +#if INSIGHTS_DEBUG_ENABLED + ESP_LOGI(TAG, "Non critical data write failed"); +#endif + break; + + default: + break; + } +} + +static esp_err_t log_write_cb(void *data, size_t len, void *priv_data) +{ + esp_err_t ret_val = esp_diag_data_store_critical_write(data, len); +#if INSIGHTS_DEBUG_ENABLED + if (ret_val != ESP_OK) { + ESP_LOGI(TAG, "esp_diag_data_store_critical_write failed len %d, err 0x%04x", len, ret_val); + } +#endif + return ret_val; +} + +#if CONFIG_DIAG_ENABLE_METRICS +static esp_err_t metrics_write_cb(const char *group, void *data, size_t len, void *cb_arg) +{ + esp_err_t ret_val = esp_diag_data_store_non_critical_write(group, data, len); +#if INSIGHTS_DEBUG_ENABLED + if (ret_val != ESP_OK) { + ESP_LOGI(TAG, "esp_diag_data_store_non_critical_write failed group %s, len %d, err 0x%04x", group, len, ret_val); + } +#endif + return ret_val; +} + +static void metrics_init(void) +{ + /* Initialize and enable metrics */ + esp_diag_metrics_config_t metrics_config = { + .write_cb = metrics_write_cb, + .cb_arg = NULL, + }; + esp_err_t ret = esp_diag_metrics_init(&metrics_config); + if (ret == ESP_OK) { +#if CONFIG_DIAG_ENABLE_HEAP_METRICS + ret = esp_diag_heap_metrics_init(); + if (ret != ESP_OK) { + ESP_LOGW(TAG, "Failed to initialize heap metrics"); + } +#endif /* CONFIG_DIAG_ENABLE_HEAP_METRICS */ +#if CONFIG_DIAG_ENABLE_WIFI_METRICS + ret = esp_diag_wifi_metrics_init(); + if (ret != ESP_OK) { + ESP_LOGW(TAG, "Failed to initialize wifi metrics"); + } +#endif /* CONFIG_DIAG_ENABLE_WIFI_METRICS */ + return; + } + ESP_LOGE(TAG, "Failed to initialize metrics."); +} + +static void metrics_deinit(void) +{ +#if CONFIG_DIAG_ENABLE_HEAP_METRICS + esp_diag_heap_metrics_deinit(); +#endif +#if CONFIG_DIAG_ENABLE_WIFI_METRICS + esp_diag_wifi_metrics_deinit(); +#endif + esp_diag_metrics_deinit(); +} +#endif /* CONFIG_DIAG_ENABLE_METRICS */ + +#if CONFIG_DIAG_ENABLE_VARIABLES +static esp_err_t variables_write_cb(const char *group, void *data, size_t len, void *cb_arg) +{ + return esp_diag_data_store_non_critical_write(group, data, len); +} + +static void variables_init(void) +{ + /* Initialize and enable variables */ + esp_diag_variable_config_t variable_config = { + .write_cb = variables_write_cb, + .cb_arg = NULL, + }; + esp_err_t ret = esp_diag_variable_init(&variable_config); + if (ret == ESP_OK) { +#if CONFIG_DIAG_ENABLE_NETWORK_VARIABLES + ret = esp_diag_network_variables_init(); + if (ret != ESP_OK) { + ESP_LOGW(TAG, "Failed to initialize network variables"); + } +#endif /* CONFIG_DIAG_ENABLE_NETWORK_VARIABLES */ + esp_diag_variable_register(TAG_DIAG, KEY_LOG_WR_FAIL, "Log write fail count", "Diagnostics.Log", ESP_DIAG_DATA_TYPE_UINT); + return; + } + ESP_LOGE(TAG, "Failed to initialize param-values."); +} + +static void variables_deinit(void) +{ +#if CONFIG_DIAG_ENABLE_NETWORK_VARIABLES + esp_diag_network_variables_deinit(); +#endif + esp_diag_variables_deinit(); +} +#endif /* CONFIG_DIAG_ENABLE_VARIABLES */ + +void esp_insights_disable(void) +{ + s_insights_data.enabled = false; + + esp_insights_unregister_periodic_handler(); +#ifdef CONFIG_DIAG_ENABLE_VARIABLES + variables_deinit(); +#endif +#ifdef CONFIG_DIAG_ENABLE_METRICS + metrics_deinit(); +#endif + esp_diag_log_hook_disable(ESP_DIAG_LOG_TYPE_ERROR | ESP_DIAG_LOG_TYPE_WARNING | ESP_DIAG_LOG_TYPE_EVENT); + esp_diag_data_store_deinit(); + esp_event_handler_unregister(INSIGHTS_EVENT, ESP_EVENT_ANY_ID, insights_event_handler); + esp_event_handler_unregister(ESP_DIAG_DATA_STORE_EVENT, ESP_EVENT_ANY_ID, data_store_event_handler); + if (s_insights_data.data_lock) { + vSemaphoreDelete(s_insights_data.data_lock); + s_insights_data.data_lock = NULL; + } + if (s_insights_data.scratch_buf) { + free(s_insights_data.scratch_buf); + s_insights_data.scratch_buf = NULL; + } + if (s_insights_data.data_send_timer) { + xTimerDelete(s_insights_data.data_send_timer, portMAX_DELAY); + s_insights_data.data_send_timer = NULL; + } + if (s_insights_data.node_id) { + free(s_insights_data.node_id); + s_insights_data.node_id = NULL; + } +} + +void esp_insights_deinit(void) +{ + esp_insights_transport_disconnect(); + esp_insights_disable(); + esp_insights_transport_unregister(); + esp_rmaker_work_queue_deinit(); + s_insights_data.init_done = false; +} + +/* Use the node id provided by user, if it is NULL and transport is set to MQTT then + * try to find node id in factory partition. If not found in factory partition or in case + * of HTTPS transport generate one using mac address + */ +static esp_err_t esp_insights_set_node_id(const char *node_id) +{ + if (node_id) { + s_insights_data.node_id = strdup(node_id); + if (!s_insights_data.node_id) { + return ESP_ERR_NO_MEM; + } + return ESP_OK; + } +#ifdef CONFIG_ESP_INSIGHTS_TRANSPORT_MQTT + if (esp_rmaker_factory_init() == ESP_OK) { + s_insights_data.node_id = esp_rmaker_factory_get("node_id"); + } +#endif + if (!s_insights_data.node_id) { + uint8_t eth_mac[6]; + if (esp_read_mac(eth_mac, ESP_MAC_WIFI_STA) != ESP_OK) { + ESP_LOGE(TAG, "Could not fetch MAC address."); + return ESP_FAIL; + } + s_insights_data.node_id = calloc(1, 13); /* 12 bytes for mac + 1 for NULL terminatation */ + if (!s_insights_data.node_id) { + return ESP_ERR_NO_MEM; + } + snprintf(s_insights_data.node_id, 13, "%02X%02X%02X%02X%02X%02X", + eth_mac[0], eth_mac[1], eth_mac[2], eth_mac[3], eth_mac[4], eth_mac[5]); + } + return ESP_OK; +} + +const char *esp_insights_get_node_id(void) +{ + return s_insights_data.node_id; +} + +static esp_err_t esp_insights_read_diag_data_store_crc_from_nvs(uint32_t *crc) +{ + if (!crc) { + return ESP_ERR_INVALID_ARG; + } + nvs_handle_t handle; + esp_err_t err = nvs_open(INSIGHTS_NVS_NAMESPACE, NVS_READONLY, &handle); + if (err != ESP_OK) { + return err; + } + err = nvs_get_u32(handle, DIAG_DATA_STORE_CRC_KEY, crc); + nvs_close(handle); + return err; +} + +static esp_err_t esp_insights_set_rtc_crc_in_nvs(uint32_t crc) +{ + if (!crc) { + return ESP_ERR_INVALID_ARG; + } + nvs_handle_t handle; + esp_err_t err = nvs_open(INSIGHTS_NVS_NAMESPACE, NVS_READWRITE, &handle); + if (err != ESP_OK) { + return err; + } +err = nvs_set_u32(handle, DIAG_DATA_STORE_CRC_KEY, crc); + nvs_commit(handle); + nvs_close(handle); + return err; +} + +esp_err_t esp_insights_enable(esp_insights_config_t *config) +{ + esp_err_t err = ESP_OK; + if (!config) { + return ESP_ERR_INVALID_ARG; + } + if (s_insights_data.data_lock) { + ESP_LOGW(TAG, "Insights already enabled"); + return ESP_OK; + } + s_insights_data.data_lock = xSemaphoreCreateMutex(); + if (!s_insights_data.data_lock) { + ESP_LOGE(TAG, "Failed to create data lock."); + return ESP_ERR_NO_MEM; + } + err = s_insights_data.node_id ? ESP_OK : esp_insights_set_node_id(config->node_id); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to set node id"); + goto enable_err; + } + if (config->alloc_ext_ram) { + s_insights_data.scratch_buf = MEM_ALLOC_EXTRAM(INSIGHTS_DATA_MAX_SIZE); + s_insights_data.read_buf = MEM_ALLOC_EXTRAM(INSIGHTS_READ_BUF_SIZE); + } else { + s_insights_data.scratch_buf = malloc(INSIGHTS_DATA_MAX_SIZE); + s_insights_data.read_buf = malloc(INSIGHTS_READ_BUF_SIZE); + } + if (!s_insights_data.scratch_buf) { + ESP_LOGE(TAG, "Failed to allocate memory for scratch buffer."); + err = ESP_ERR_NO_MEM; + goto enable_err; + } + if (!s_insights_data.read_buf) { + ESP_LOGE(TAG, "Failed to allocate memory for read_buf"); + free(s_insights_data.scratch_buf); + err = ESP_ERR_NO_MEM; + goto enable_err; + } + + /* Get sha256 */ + esp_diag_device_info_t device_info; + memset(&device_info, 0, sizeof(device_info)); + err = esp_diag_device_info_get(&device_info); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to get device info"); + goto enable_err; + } + memcpy((uint8_t *) s_insights_data.app_sha256, (uint8_t *) device_info.app_elf_sha256, sizeof(s_insights_data.app_sha256)); + err = esp_event_handler_register(INSIGHTS_EVENT, ESP_EVENT_ANY_ID, insights_event_handler, NULL); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to register event handler for INSIGHTS_EVENTS"); + goto enable_err; + } + /* Register event handler for data store events */ + err = esp_event_handler_register(ESP_DIAG_DATA_STORE_EVENT, ESP_EVENT_ANY_ID, data_store_event_handler, NULL); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to register event handler for DIAG_DATA_STORE_EVENT"); + goto enable_err; + } + err = esp_diag_data_store_init(); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to initialise RTC store."); + goto enable_err; + } + uint32_t new_crc, previous_crc; + new_crc = esp_diag_data_store_get_crc(); + new_crc = esp_crc32_le(esp_diag_data_size_get_crc(), (const unsigned char *)&new_crc, sizeof(new_crc)); + err = esp_insights_read_diag_data_store_crc_from_nvs(&previous_crc); + if ((err != ESP_OK) || (new_crc != previous_crc)) { + ESP_LOGI(TAG, "RTC Store configuration changed. Discarding previous data from RTC buffers"); + esp_diag_data_discard_data(); + err = esp_insights_set_rtc_crc_in_nvs(new_crc); + if (err != ESP_OK) { + ESP_LOGI(TAG, "Failed to set RTC Store CRC in nvs."); + } + } + esp_diag_log_config_t log_config = { + .write_cb = log_write_cb, + .cb_arg = NULL, + }; + err = esp_diag_log_hook_init(&log_config); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to initialise Log hook."); + goto enable_err; + } + esp_diag_log_hook_enable(config->log_type); + +#if CONFIG_DIAG_ENABLE_METRICS + metrics_init(); +#endif /* CONFIG_DIAG_ENABLE_METRICS */ +#if CONFIG_DIAG_ENABLE_VARIABLES + variables_init(); +#endif /* CONFIG_DIAG_ENABLE_VARIABLES */ + + s_insights_data.boot_msg_id = -1; +#if INSIGHTS_CMD_RESP + s_insights_data.conf_msg_id = -1; +#endif + s_insights_data.data_send_timer = xTimerCreate("data_send_timer", CLOUD_REPORTING_TIMEOUT_TICKS, + pdFALSE, NULL, data_send_timeout_cb); + if (!s_insights_data.data_send_timer) { + ESP_LOGE(TAG, "Failed to create data_send_timer."); + err = ESP_ERR_NO_MEM; + goto enable_err; + } + + err = esp_insights_register_periodic_handler(insights_periodic_handler, + CLOUD_REPORTING_PERIOD_MIN_SEC, CLOUD_REPORTING_PERIOD_MAX_SEC, NULL); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to register insights_periodic_handler."); + goto enable_err; + } + + s_insights_data.enabled = true; + + ESP_LOGI(TAG, "========================================="); + ESP_LOGI(TAG, "Insights enabled for Node ID %s", s_insights_data.node_id); + ESP_LOGI(TAG, "========================================="); + s_insights_data.init_done = true; + return ESP_OK; +enable_err: + esp_insights_disable(); + return err; +} + +esp_err_t esp_insights_init(esp_insights_config_t *config) +{ + esp_err_t err; + if (s_insights_data.data_lock) { + ESP_LOGW(TAG, "ESP Insights already initialized"); + return ESP_OK; + } + if (!config) { + return ESP_ERR_INVALID_ARG; + } + /* set node id */ + err = esp_insights_set_node_id(config->node_id); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to set node id"); + return err; + } +#ifdef CONFIG_ESP_INSIGHTS_TRANSPORT_MQTT + err = esp_insights_transport_register(&g_default_insights_transport_mqtt); +#else + g_default_insights_transport_https.userdata = (void *)config->auth_key; + err = esp_insights_transport_register(&g_default_insights_transport_https); +#endif + if (err != ESP_OK && err != ESP_ERR_INVALID_STATE) { + ESP_LOGE(TAG, "Failed to register transport"); + goto init_err; + } + err = esp_rmaker_work_queue_init(); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to initialise Work Queue."); + goto init_err; + } + err = esp_insights_enable(config); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to enable ESP Insights."); + goto init_err; + } + err = esp_insights_transport_connect(); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to connect to transport."); + goto init_err; + } + err = esp_rmaker_work_queue_start(); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to start Work Queue."); + goto init_err; + } + + s_insights_data.init_done = true; + + err = esp_insights_cmd_resp_init() || esp_insights_cmd_resp_enable(); + if (err != ESP_OK) { /* device can keep working neverthless */ + ESP_LOGE(TAG, "Failed to enable insights_cmd_resp"); + } + return ESP_OK; +init_err: + if (s_insights_data.node_id) { + free(s_insights_data.node_id); + s_insights_data.node_id = NULL; + } + esp_insights_deinit(); + return err; +} + +#endif /* CONFIG_ESP_INSIGHTS_ENABLED */ diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_insights/src/esp_insights_cbor_decoder.c b/RainMaker_Table-Lights/managed_components/espressif__esp_insights/src/esp_insights_cbor_decoder.c new file mode 100644 index 000000000..3981da052 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_insights/src/esp_insights_cbor_decoder.c @@ -0,0 +1,382 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include + +#include +#include "esp_insights_cbor_decoder.h" + +static const char *TAG = "insight_cbor_dec"; + +#define CBOR_CHECK(a, str, goto_tag, ret_value, ...) \ + do { \ + if ((a) != CborNoError) { \ + ESP_LOGE(TAG, "%s(%d): " str, __FUNCTION__, __LINE__, ##__VA_ARGS__); \ + ret = ret_value; \ + goto goto_tag; \ + } \ + } while (0) + +static void dumpbytes(const uint8_t *buf, size_t len) +{ + while (len--) { + printf("%02X ", *buf++); + } +} + +static void indent(int nestingLevel) +{ + printf("%*s", 2 * nestingLevel, ""); +} + +// extremely light implementation of stack needed for cbor dump +typedef struct cbor_dump_value { + CborValue *it; // current iterator + int nesting_level; + CborType parent_type; + int cnt; // count of elements already processed +} cbor_dump_value_t; + +typedef struct cbor_dump_node cbor_dump_node_t; +typedef struct cbor_dump_node { + cbor_dump_value_t *data; + cbor_dump_node_t *next; +} cbor_dump_node_t; + +static cbor_dump_node_t *dump_list_head = NULL; + +static cbor_dump_value_t* cbor_dump_list_get_head() +{ + cbor_dump_value_t *value = NULL; + if (dump_list_head) { + cbor_dump_node_t *head = dump_list_head; + dump_list_head = head->next; + value = head->data; + free(head); + } + return value; +} + +static void cbor_dump_list_insert_at_head(cbor_dump_value_t* data) +{ + cbor_dump_node_t *node = MEM_ALLOC_EXTRAM(sizeof(cbor_dump_node_t)); + node->data = data; + node->next = dump_list_head; + dump_list_head = node; +} + +/** + * Decode CBOR data manually + */ +static CborError insights_dump_cbor_buffer(cbor_dump_value_t *value) +{ + if (!value) { + return ESP_FAIL; + } + while (1) { + CborError ret = CborNoError; + int cnt = value->cnt; + CborValue *it = value->it; + int nestingLevel = value->nesting_level; + CborType parent_type = value->parent_type; + + while (!cbor_value_at_end(it)) { + CborType type = cbor_value_get_type(it); + cnt++; + + if ((cnt % 2 == 0) || (parent_type == CborArrayType)) { + if (cnt) { + puts(","); + } else { + puts(""); + } + indent(nestingLevel); + } else { + printf(" : "); + } + + if (type == CborArrayType || type == CborMapType) { + // push current node + cbor_dump_value_t *value = MEM_ALLOC_EXTRAM(sizeof(cbor_dump_value_t)); + value->cnt = cnt; + value->it = it; + value->nesting_level = nestingLevel; + value->parent_type = parent_type; + cbor_dump_list_insert_at_head(value); + + CborValue *recursed = MEM_ALLOC_EXTRAM(sizeof(CborValue)); + if (false == cbor_value_is_container(it)) { + goto err; + } + ret = cbor_value_enter_container(it, recursed); + CBOR_CHECK(ret, "enter container failed", err, ret); + + cnt = -1; + nestingLevel += 1; + parent_type = type; + it = recursed; + if (type == CborArrayType) { + printf("["); + } else { + printf("{"); + } + continue; + } + + switch (type) { + case CborArrayType: + case CborMapType: + continue; + case CborIntegerType: { + int64_t val; + ret = cbor_value_get_int64(it, &val); + CBOR_CHECK(ret, "parse int64 failed", err, ret); + printf("%lld", (long long)val); + break; + } + case CborByteStringType: { + uint8_t *buf; + size_t n; + ret = cbor_value_dup_byte_string(it, &buf, &n, it); + CBOR_CHECK(ret, "parse byte string failed", err, ret); + dumpbytes(buf, n); + free(buf); + continue; + } + case CborTextStringType: { + char *buf; + size_t n; + ret = cbor_value_dup_text_string(it, &buf, &n, it); + CBOR_CHECK(ret, "parse text string failed", err, ret); + printf("\"%s\"", buf); + free(buf); + continue; + } + case CborTagType: { + CborTag tag; + ret = cbor_value_get_tag(it, &tag); + CBOR_CHECK(ret, "parse tag failed", err, ret); + printf("Tag(%lld)\n", (long long)tag); + break; + } + case CborSimpleType: { + uint8_t type; + ret = cbor_value_get_simple_type(it, &type); + CBOR_CHECK(ret, "parse simple type failed", err, ret); + printf("simple(%u)\n", type); + break; + } + case CborNullType: + printf("null"); + break; + case CborUndefinedType: + printf("undefined"); + break; + case CborBooleanType: { + bool val; + ret = cbor_value_get_boolean(it, &val); + CBOR_CHECK(ret, "parse boolean type failed", err, ret); + printf(val ? "true" : "false"); + break; + } + case CborHalfFloatType: { + uint16_t val; + ret = cbor_value_get_half_float(it, &val); + CBOR_CHECK(ret, "parse half float type failed", err, ret); + printf("__f16(%04x)", val); + break; + } + case CborFloatType: { + float val; + ret = cbor_value_get_float(it, &val); + CBOR_CHECK(ret, "parse float type failed", err, ret); + printf("%g", val); + break; + } + case CborDoubleType: { + double val; + ret = cbor_value_get_double(it, &val); + CBOR_CHECK(ret, "parse double float type failed", err, ret); + printf("%g", val); + break; + } + case CborInvalidType: { + ret = CborErrorUnknownType; + CBOR_CHECK(ret, "unknown cbor type", err, ret); + break; + } + } + ret = cbor_value_advance_fixed(it); + CBOR_CHECK(ret, "fix value failed", err, ret); + } + + printf("\n"); + cbor_dump_value_t *data = cbor_dump_list_get_head(); + if (data) { + free(value); // free current + value = data; + CborType type = cbor_value_get_type(value->it); + if (type == CborArrayType || type == CborMapType) { + ret = cbor_value_leave_container(value->it, it); + free(it); + CBOR_CHECK(ret, "leave container failed", err, ret); + indent(value->nesting_level); + if (type == CborArrayType) { + printf("]"); + } else { + printf("}"); + } + } + continue; + } + ret = CborNoError; +err: + // done + printf("\n"); + if (value) { + free(value->it); + free(value); + value = NULL; + } + + // final cleanup + value = cbor_dump_list_get_head(); + while (value) { + free(value->it); + free(value); + value = cbor_dump_list_get_head(); + } + dump_list_head = NULL; + + return ret; + } +} + +esp_err_t esp_insights_cbor_decode_dump(const uint8_t *buffer, int len) +{ + if (!buffer || len <= 0) { + return ESP_ERR_INVALID_ARG; + } + CborParser root_parser; + CborValue *it = MEM_ALLOC_EXTRAM(sizeof(CborValue)); + + // Initialize the cbor parser and the value iterator + cbor_parser_init(buffer, len, 0, &root_parser, it); + + cbor_dump_value_t *value = MEM_ALLOC_EXTRAM(sizeof(cbor_dump_value_t)); + value->cnt = -1; + value->it = it; + value->nesting_level = 0; + value->parent_type = CborMapType; + + if (insights_dump_cbor_buffer(value) != CborNoError) { + ESP_LOGI(TAG, "cbor dump failed"); + } + + return ESP_OK; +} + +bool esp_insights_cbor_decoder_at_end(cbor_parse_ctx_t *ctx) +{ + return cbor_value_at_end(&ctx->it[ctx->curr_itr]); +} + +esp_err_t esp_insights_cbor_decoder_advance(cbor_parse_ctx_t *ctx) +{ + if (CborNoError == cbor_value_advance(&ctx->it[ctx->curr_itr])) { + return ESP_OK; + } + return ESP_FAIL; +} + +CborType esp_insights_cbor_decode_get_value_type(cbor_parse_ctx_t *ctx) +{ + return cbor_value_get_type(&ctx->it[ctx->curr_itr]); +} + +char *esp_insights_cbor_decoder_get_string(CborValue *val) +{ + CborError ret = CborNoError; + char *buf = NULL; + size_t n; + if (cbor_value_get_type(val) != CborTextStringType) { + return NULL; + } + ret = cbor_value_dup_text_string(val, &buf, &n, val); + if (ret == CborNoError) { + return (char *) buf; + } + return NULL; +} + +esp_err_t esp_insights_cbor_decoder_enter_container(cbor_parse_ctx_t *ctx) +{ + CborError ret = CborNoError; + int curr_itr = ctx->curr_itr; + if (curr_itr >= INS_CBOR_MAX_DEPTH) { + ESP_LOGE(TAG, "Cannot parse depth more than %d", INS_CBOR_MAX_DEPTH); + return ESP_FAIL; + } + ret = cbor_value_enter_container(&ctx->it[curr_itr], &ctx->it[curr_itr + 1]); + if (ret != CborNoError) { + ESP_LOGE(TAG, "error entering container"); + return ESP_FAIL; + } + if (esp_insights_cbor_decoder_at_end(ctx)) { + return ESP_FAIL; + } + ctx->curr_itr++; + + return ESP_OK; +} + +esp_err_t esp_insights_cbor_decoder_exit_container(cbor_parse_ctx_t *ctx) +{ + CborError ret = CborNoError; + if (ctx->curr_itr <= 0) { + ESP_LOGE(TAG, "cannot exit, already at top"); + return ESP_FAIL; + } + ctx->curr_itr--; + int curr_itr = ctx->curr_itr; + ret = cbor_value_leave_container(&ctx->it[curr_itr], &ctx->it[curr_itr + 1]); + if (ret != CborNoError) { + ESP_LOGE(TAG, "error leaving container"); + return ESP_FAIL; + } + return ESP_OK; +} + +esp_err_t esp_insights_cbor_decoder_done(cbor_parse_ctx_t *ctx) +{ + if (ctx) { + free(ctx); + } + return ESP_OK; +} + +cbor_parse_ctx_t *esp_insights_cbor_decoder_start(const uint8_t *buffer, int len) +{ + if (!buffer || len == 0) { + return NULL; + } + cbor_parse_ctx_t *ctx = calloc(1, sizeof(cbor_parse_ctx_t)); + if (!ctx) { + ESP_LOGE(TAG, "failed to allocate cbor ctx"); + return NULL; + } + CborParser root_parser = ctx->root_parser; + CborValue *it = &ctx->it[0]; + if (cbor_parser_init(buffer, len, 0, &root_parser, it) != CborNoError) { + ESP_LOGE(TAG, "Error initializing cbor parser"); + return NULL; + } + return ctx; +} diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_insights/src/esp_insights_cbor_decoder.h b/RainMaker_Table-Lights/managed_components/espressif__esp_insights/src/esp_insights_cbor_decoder.h new file mode 100644 index 000000000..cbeb6af0f --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_insights/src/esp_insights_cbor_decoder.h @@ -0,0 +1,49 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +/** + * @file esp_insights_cbor_decoder.h + * @brief this file contains useful abstractions on cbor + * + * @note please keep this file as utility, avoid taking insights decisions here + */ + +#include + +#include + +#define INS_CBOR_MAX_DEPTH 12 // depth to which we can traverse + +typedef struct cbor_parse_ctx { + CborParser root_parser; + CborValue it[INS_CBOR_MAX_DEPTH + 1]; + int curr_itr; +} cbor_parse_ctx_t; + +cbor_parse_ctx_t *esp_insights_cbor_decoder_start(const uint8_t *buffer, int len); +esp_err_t esp_insights_cbor_decoder_enter_and_check_value(cbor_parse_ctx_t *ctx, const char *val); +bool esp_insights_cbor_decoder_at_end(cbor_parse_ctx_t *ctx); + +esp_err_t esp_insights_cbor_decoder_advance(cbor_parse_ctx_t *ctx); +CborType esp_insights_cbor_decode_get_value_type(cbor_parse_ctx_t *ctx); +char *esp_insights_cbor_decoder_get_string(CborValue *val); + +esp_err_t esp_insights_cbor_decoder_enter_container(cbor_parse_ctx_t *ctx); +esp_err_t esp_insights_cbor_decoder_exit_container(cbor_parse_ctx_t *ctx); + +/* Do cleanups if any */ +esp_err_t esp_insights_cbor_decoder_done(cbor_parse_ctx_t *ctx); + +/** + * @brief decodes a cbor message and prints into json format + * + * @param buffer buffer to decode and print + * @param len length of the buffer to decode + * @return esp_err_t ESP_OK on success, apt error otherwise + */ +esp_err_t esp_insights_cbor_decode_dump(const uint8_t *buffer, int len); diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_insights/src/esp_insights_cbor_encoder.c b/RainMaker_Table-Lights/managed_components/espressif__esp_insights/src/esp_insights_cbor_encoder.c new file mode 100644 index 000000000..ff1b601a8 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_insights/src/esp_insights_cbor_encoder.c @@ -0,0 +1,947 @@ +/* + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#include +#include +#if CONFIG_ESP_INSIGHTS_COREDUMP_ENABLE +#include +#endif /* CONFIG_ESP_INSIGHTS_COREDUMP_ENABLE */ + +#include +#include +#include +#include +#include "esp_insights_cbor_encoder.h" + +#define TAG "cbor_encoder" + +#define METRICS_PATH_VALUE "M" +#define VARIABLES_PATH_VALUE "P" + +static CborEncoder s_encoder, s_result_map, s_diag_map, s_diag_data_map, s_diag_conf_map; +static CborEncoder s_meta_encoder, s_meta_result_map, s_diag_meta_map, s_diag_meta_data_map; + +#define CBOR_ENC_MAX_CBS 10 +static struct cbor_encoder_data { + insights_cbor_encoder_cb_t cb[CBOR_ENC_MAX_CBS]; + int cb_cnt; +} s_priv_data; + +static inline void _cbor_encode_meta_hdr(CborEncoder *hdr_map, const rtc_store_meta_header_t *hdr); + +esp_err_t esp_insights_cbor_encoder_register_meta_cb(insights_cbor_encoder_cb_t cb) +{ + if (s_priv_data.cb_cnt == CBOR_ENC_MAX_CBS) { + return ESP_ERR_NO_MEM; + } + ESP_LOGV(TAG, "Registering callback %p", cb); + s_priv_data.cb[s_priv_data.cb_cnt++] = cb; + return ESP_OK; +} + +void esp_insights_cbor_encode_diag_begin(void *data, size_t data_size, const char *version) +{ + cbor_encoder_init(&s_encoder, data, data_size, 0); + cbor_encoder_create_map(&s_encoder, &s_result_map, 1); + cbor_encode_text_stringz(&s_result_map, "diag"); + cbor_encoder_create_map(&s_result_map, &s_diag_map, CborIndefiniteLength); + + cbor_encode_text_stringz(&s_diag_map, "ver"); + cbor_encode_text_stringz(&s_diag_map, version); + + cbor_encode_text_stringz(&s_diag_map, "ts"); + cbor_encode_uint(&s_diag_map, esp_diag_timestamp_get()); + + // cbor_encode_text_stringz(&s_diag_map, "sha256"); + // cbor_encode_text_stringz(&s_diag_map, sha256); + + // encode meta_data + const rtc_store_meta_header_t *hdr = rtc_store_get_meta_record_current(); + _cbor_encode_meta_hdr(&s_diag_map, hdr); +} + +size_t esp_insights_cbor_encode_diag_end(void *data) +{ + cbor_encoder_close_container(&s_result_map, &s_diag_map); + cbor_encoder_close_container(&s_encoder, &s_result_map); + return cbor_encoder_get_buffer_size(&s_encoder, data); +} + +void esp_insights_cbor_encode_diag_data_begin(void) +{ + cbor_encode_text_stringz(&s_diag_map, "data"); + cbor_encoder_create_map(&s_diag_map, &s_diag_data_map, CborIndefiniteLength); +} + +void esp_insights_cbor_encode_diag_conf_data_begin(void) +{ + cbor_encode_text_stringz(&s_diag_data_map, "configs"); + cbor_encoder_create_array(&s_diag_data_map, &s_diag_conf_map, CborIndefiniteLength); +} + +void esp_insights_cbor_encode_diag_data_end(void) +{ + cbor_encoder_close_container(&s_diag_map, &s_diag_data_map); +} + +void esp_insights_cbor_encode_diag_conf_data_end(void) +{ + cbor_encoder_close_container(&s_diag_data_map, &s_diag_conf_map); +} + +#if CONFIG_ESP_INSIGHTS_COREDUMP_ENABLE +void esp_insights_cbor_encode_diag_crash(esp_core_dump_summary_t *summary) +{ + uint32_t i = 0; + CborEncoder crash_map, val_list, bt_list; + + cbor_encode_text_stringz(&s_diag_data_map, "crash"); + cbor_encoder_create_map(&s_diag_data_map, &crash_map, CborIndefiniteLength); + cbor_encode_text_stringz(&crash_map, "ver"); + cbor_encode_uint(&crash_map, summary->core_dump_version); + cbor_encode_text_stringz(&crash_map, "sha256"); + cbor_encode_text_stringz(&crash_map, (char *)summary->app_elf_sha256); + cbor_encode_text_stringz(&crash_map, "task"); + cbor_encode_text_stringz(&crash_map, summary->exc_task); + + cbor_encode_text_stringz(&crash_map, "exc_val"); + cbor_encoder_create_array(&crash_map, &val_list, CborIndefiniteLength); + cbor_encode_uint(&val_list, summary->exc_pc); +#if CONFIG_IDF_TARGET_ARCH_RISCV + cbor_encode_uint(&val_list, summary->ex_info.mcause); + cbor_encode_uint(&val_list, summary->ex_info.mtval); + + cbor_encoder_close_container(&crash_map, &val_list); + + cbor_encode_text_stringz(&crash_map, "stackdump"); + cbor_encoder_create_array(&crash_map, &bt_list, CborIndefiniteLength); + + // Interpret stackdump as an array of uint32_t + uint32_t *s_dump =(uint32_t *)&summary->exc_bt_info.stackdump[0]; + + for (i = 0; i < (summary->exc_bt_info.dump_size / 4); i++) { + cbor_encode_uint(&bt_list, s_dump[i]); + } + cbor_encoder_close_container(&crash_map, &bt_list); + + // stackdump is treated as an array of uint32_t hence converting no. of bytes to no. of words + cbor_encode_text_stringz(&crash_map, "dump_size"); + cbor_encode_uint(&crash_map, summary->exc_bt_info.dump_size / 4); + + CborEncoder reg_list; + cbor_encode_text_stringz(&crash_map, "mstatus"); + cbor_encode_uint(&crash_map, summary->ex_info.mstatus); + cbor_encode_text_stringz(&crash_map, "mtvec"); + cbor_encode_uint(&crash_map, summary->ex_info.mtvec); + cbor_encode_text_stringz(&crash_map, "ra"); + cbor_encode_uint(&crash_map, summary->ex_info.ra); + cbor_encode_text_stringz(&crash_map, "sp"); + cbor_encode_uint(&crash_map, summary->ex_info.sp); + cbor_encode_text_stringz(&crash_map, "a_reg"); + cbor_encoder_create_array(&crash_map, ®_list, CborIndefiniteLength); + for (i = 0; i < 8; i++) { + cbor_encode_uint(®_list, summary->ex_info.exc_a[i]); + } + cbor_encoder_close_container(&crash_map, ®_list); +#else /* IDF_TARGET_ARCH_XTENSA */ + cbor_encode_uint(&val_list, summary->ex_info.exc_cause); + cbor_encode_uint(&val_list, summary->ex_info.exc_vaddr); + + cbor_encoder_close_container(&crash_map, &val_list); + cbor_encode_text_stringz(&crash_map, "bt"); + cbor_encoder_create_array(&crash_map, &bt_list, CborIndefiniteLength); + for (i = 0; i < summary->exc_bt_info.depth; i++) { + cbor_encode_uint(&bt_list, summary->exc_bt_info.bt[i]); + } + cbor_encoder_close_container(&crash_map, &bt_list); + + cbor_encode_text_stringz(&crash_map, "bt_corrupt"); + cbor_encode_boolean(&crash_map, summary->exc_bt_info.corrupted); + + CborEncoder epcx_list, reg_list; + cbor_encode_text_stringz(&crash_map, "a_reg"); + cbor_encoder_create_array(&crash_map, ®_list, CborIndefiniteLength); + for (i = 0; i < 16; i++) { + cbor_encode_uint(®_list, summary->ex_info.exc_a[i]); + } + cbor_encoder_close_container(&crash_map, ®_list); + + cbor_encode_text_stringz(&crash_map, "epcx"); + cbor_encoder_create_array(&crash_map, &epcx_list, CborIndefiniteLength); + for (i = 0; i < EPCx_REGISTER_COUNT; i++) { + if (summary->ex_info.epcx_reg_bits & (1 << i)) { + cbor_encode_uint(&epcx_list, summary->ex_info.epcx[i]); + } + } + cbor_encoder_close_container(&crash_map, &epcx_list); +#endif /* CONFIG_IDF_TARGET_ARCH_RISCV */ + cbor_encoder_close_container(&s_diag_data_map, &crash_map); +} +#endif /* CONFIG_ESP_INSIGHTS_COREDUMP_ENABLE */ + +// use a scratch_pad to memcpy data before access +// this avoids `potential` unaligned memory accesses as +// data pointer we receive is not guaranteed to be word aligned +static union encode_scratch_buf { +#if (CONFIG_DIAG_ENABLE_METRICS || CONFIG_DIAG_ENABLE_VARIABLES) + esp_diag_str_data_pt_t str_data_pt; + esp_diag_data_pt_t data_pt; +#endif + esp_diag_log_data_t log_data_pt; + char sha_sum[DIAG_HEX_SHA_SIZE + 1]; +} enc_scratch_buf; + +static inline uint8_t to_hex_digit(unsigned val) +{ + return (val < 10) ? ('0' + val) : ('a' + val - 10); +} + +void bytes_to_hex(uint8_t *src, uint8_t *dst, int in_len) +{ + for (int i = 0; i < in_len; i++) { + dst[2 * i] = to_hex_digit(src[i] >> 4); + dst[2 * i + 1] = to_hex_digit(src[i] & 0xf); + } + dst[2 * in_len] = 0; +} + +static inline void _cbor_encode_meta_hdr(CborEncoder *hdr_map, const rtc_store_meta_header_t *hdr) +{ + cbor_encode_text_stringz(hdr_map, "sha256"); + bytes_to_hex((uint8_t *) hdr->sha_sum, (uint8_t *) enc_scratch_buf.sha_sum, DIAG_SHA_SIZE); // expand uint8 packed data to hex + cbor_encode_text_stringz(hdr_map, enc_scratch_buf.sha_sum); + cbor_encode_text_stringz(hdr_map, "gen_id"); + cbor_encode_uint(hdr_map, hdr->gen_id); + cbor_encode_text_stringz(hdr_map, "boot_cnt"); + cbor_encode_uint(hdr_map, hdr->boot_cnt); +} + +void esp_insights_cbor_encode_diag_boot_info(esp_diag_device_info_t *device_info) +{ + CborEncoder boot_map; + cbor_encode_text_stringz(&s_diag_data_map, "boot"); + cbor_encoder_create_map(&s_diag_data_map, &boot_map, CborIndefiniteLength); + + /* xTaskGetTickCount() API returns count of ticks since start of scheduler + * For boot timestamp, we subtract the ticks since boot to get closest timestamp to bootup + */ + cbor_encode_text_stringz(&boot_map, "ts"); + cbor_encode_uint(&boot_map, esp_diag_timestamp_get() - (uint64_t)(pdTICKS_TO_MS(xTaskGetTickCount()) * 1000)); + + cbor_encode_text_stringz(&boot_map, "chip"); + cbor_encode_uint(&boot_map, device_info->chip_model); + cbor_encode_text_stringz(&boot_map, "chip_rev"); + cbor_encode_uint(&boot_map, device_info->chip_rev); + cbor_encode_text_stringz(&boot_map, "reason"); + cbor_encode_uint(&boot_map, device_info->reset_reason); + cbor_encode_text_stringz(&boot_map, "proj"); + cbor_encode_text_stringz(&boot_map, device_info->project_name); + cbor_encode_text_stringz(&boot_map, "app_ver"); + cbor_encode_text_stringz(&boot_map, device_info->app_version); + + cbor_encoder_close_container(&s_diag_data_map, &boot_map); +} + +void esp_insights_cbor_encode_meta_c_hdr(const rtc_store_meta_header_t *hdr) +{ + CborEncoder hdr_map; + cbor_encode_text_stringz(&s_diag_data_map, "meta_c"); + cbor_encoder_create_map(&s_diag_data_map, &hdr_map, CborIndefiniteLength); + + CborEncoder map_list; + cbor_encode_text_stringz(&hdr_map, "maps_to"); + cbor_encoder_create_array(&hdr_map, &map_list, CborIndefiniteLength); + cbor_encode_text_stringz(&map_list, "traces"); + cbor_encoder_close_container(&hdr_map, &map_list); + + _cbor_encode_meta_hdr(&hdr_map, hdr); + cbor_encoder_close_container(&s_diag_data_map, &hdr_map); +} + +void esp_insights_cbor_encode_meta_nc_hdr(const rtc_store_meta_header_t *hdr) +{ + CborEncoder hdr_map; + cbor_encode_text_stringz(&s_diag_data_map, "meta_nc"); + cbor_encoder_create_map(&s_diag_data_map, &hdr_map, CborIndefiniteLength); + + CborEncoder map_list; + cbor_encode_text_stringz(&hdr_map, "maps_to"); + cbor_encoder_create_array(&hdr_map, &map_list, CborIndefiniteLength); + cbor_encode_text_stringz(&map_list, "metrics"); + cbor_encode_text_stringz(&map_list, "params"); + cbor_encoder_close_container(&hdr_map, &map_list); + + _cbor_encode_meta_hdr(&hdr_map, hdr); + cbor_encoder_close_container(&s_diag_data_map, &hdr_map); +} + +static void encode_msg_args(CborEncoder *element, uint8_t *args, uint8_t args_len) +{ +#ifdef CONFIG_DIAG_LOG_MSG_ARG_FORMAT_TLV + uint8_t type, len, i = 0; + CborEncoder arg_list; + esp_diag_arg_value_t arg_val; + + cbor_encoder_create_array(element, &arg_list, CborIndefiniteLength); + if (!args || !args_len) { + cbor_encoder_close_container(element, &arg_list); + return; + } + while (i < args_len) { + memset(&arg_val, 0, sizeof(arg_val)); + type = args[i++]; + len = args[i++]; + switch(type) { + case ARG_TYPE_CHAR: + case ARG_TYPE_UCHAR: + { + cbor_encode_simple_value(&arg_list, args[i]); + break; + } + case ARG_TYPE_SHORT: + { + memcpy(&arg_val.s, args + i, len); + if (arg_val.s < 0) { + cbor_encode_negative_int(&arg_list, -arg_val.s); + } else { + cbor_encode_int(&arg_list, arg_val.s); + } + break; + } + case ARG_TYPE_INT: + { + memcpy(&arg_val.i, args + i, len); + if (arg_val.i < 0) { + cbor_encode_negative_int(&arg_list, -arg_val.i); + } else { + cbor_encode_int(&arg_list, arg_val.i); + } + break; + } + case ARG_TYPE_L: + { + memcpy(&arg_val.l, args + i, len); + if (arg_val.l < 0) { + cbor_encode_negative_int(&arg_list, -arg_val.l); + } else { + cbor_encode_int(&arg_list, arg_val.l); + } + break; + } + case ARG_TYPE_LL: + { + memcpy(&arg_val.ll, args + i, len); + if (arg_val.ll < 0) { + cbor_encode_negative_int(&arg_list, -arg_val.ll); + } else { + cbor_encode_int(&arg_list, arg_val.ll); + } + break; + } + case ARG_TYPE_PTRDIFF: + { + memcpy(&arg_val.ptrdiff, args + i, len); + if (arg_val.ptrdiff < 0) { + cbor_encode_negative_int(&arg_list, -arg_val.ptrdiff); + } else { + cbor_encode_int(&arg_list, arg_val.ptrdiff); + } + break; + } + case ARG_TYPE_INTMAX: + { + memcpy(&arg_val.imx, args + i, len); + if (arg_val.imx < 0) { + cbor_encode_negative_int(&arg_list, -arg_val.imx); + } else { + cbor_encode_int(&arg_list, arg_val.imx); + } + break; + } + case ARG_TYPE_USHORT: + { + memcpy(&arg_val.us, args + i, len); + cbor_encode_uint(&arg_list, arg_val.us); + break; + } + case ARG_TYPE_UINT: + { + memcpy(&arg_val.u, args + i, len); + cbor_encode_uint(&arg_list, arg_val.u); + break; + } + case ARG_TYPE_UL: + { + memcpy(&arg_val.ul, args + i, len); + cbor_encode_uint(&arg_list, arg_val.ul); + break; + } + case ARG_TYPE_ULL: + { + memcpy(&arg_val.ull, args + i, len); + cbor_encode_uint(&arg_list, arg_val.ull); + break; + } + case ARG_TYPE_SIZE: + { + memcpy(&arg_val.sz, args + i, len); + cbor_encode_uint(&arg_list, arg_val.sz); + break; + } + case ARG_TYPE_UINTMAX: + { + memcpy(&arg_val.umx, args + i, len); + cbor_encode_uint(&arg_list, arg_val.umx); + break; + } + case ARG_TYPE_DOUBLE: + { + memcpy(&arg_val.d, args + i, len); + cbor_encode_double(&arg_list, arg_val.d); + break; + } + case ARG_TYPE_LDOUBLE: + { + memcpy(&arg_val.ld, args + i, len); + cbor_encode_double(&arg_list, arg_val.ld); + break; + } + case ARG_TYPE_STR: + cbor_encode_text_string(&arg_list, (char *)(args + i), len); + break; + } + i += len; + } + cbor_encoder_close_container(element, &arg_list); +#else + cbor_encode_text_stringz(element, (char *)args); +#endif /* CONFIG_DIAG_LOG_MSG_ARG_FORMAT_TLV */ +} + +static void encode_log_element(CborEncoder *list, esp_diag_log_data_t *data) +{ + CborEncoder element; + esp_diag_log_data_t *log = &enc_scratch_buf.log_data_pt; + // copy at aligned address to avoid potential alignment issue + memcpy(log, data, sizeof(esp_diag_log_data_t)); + + cbor_encoder_create_map(list, &element, CborIndefiniteLength); + cbor_encode_text_stringz(&element, "ts"); + cbor_encode_uint(&element, log->timestamp); + cbor_encode_text_stringz(&element, "tag"); + cbor_encode_text_stringz(&element, log->tag); + cbor_encode_text_stringz(&element, "pc"); + cbor_encode_uint(&element, log->pc); + cbor_encode_text_stringz(&element, "ro"); + cbor_encode_uint(&element, (uint32_t)log->msg_ptr); + cbor_encode_text_stringz(&element, "av"); + encode_msg_args(&element, log->msg_args, log->msg_args_len); + if (strlen(log->task_name) > 0) { + cbor_encode_text_stringz(&element, "task"); + cbor_encode_text_stringz(&element, log->task_name); + } + cbor_encoder_close_container(list, &element); +} + +static size_t encode_log_list(CborEncoder *map, esp_diag_log_type_t type, + const char *key, const uint8_t *data, size_t size) +{ + int i = 0, len = 0; + CborEncoder list; + esp_diag_log_data_t *log = NULL; + cbor_encode_text_stringz(map, key); + cbor_encoder_create_array(map, &list, CborIndefiniteLength); + uint8_t meta_idx = data[0]; + while (size > sizeof (esp_diag_log_data_t)) { + if (data[i] != meta_idx) { +#if INSIGHTS_DEBUG_ENABLED + printf("%s: skip data for next iteration meta: %d, data[i]: %d, itr: %d\n", + "insights_cbor_enocoder", meta_idx, data[i], i); +#endif + break; // do not encode for next meta info + } + i += 1; // skip meta byte + size -= 1; + if (data[i] == type) { + log = (esp_diag_log_data_t *)&data[i]; + encode_log_element(&list, log); + } + len = sizeof(esp_diag_log_data_t); + i += len; + size -= len ; + } + cbor_encoder_close_container(map, &list); + return i; +} + +/* The TinyCBOR library does not support DOM (Document Object Model)-like API. + * So, we need to traverse through the entire data to encode every type of log. + */ +size_t esp_insights_cbor_encode_diag_logs(const uint8_t *data, size_t size) +{ + CborEncoder log_map; + cbor_encode_text_stringz(&s_diag_data_map, "traces"); + cbor_encoder_create_map(&s_diag_data_map, &log_map, CborIndefiniteLength); + size_t consumed = 0, consumed_max = 0; + consumed_max = encode_log_list(&log_map, ESP_DIAG_LOG_TYPE_ERROR, "errors", data, size); + consumed = encode_log_list(&log_map, ESP_DIAG_LOG_TYPE_WARNING, "warnings", data, size); + if (consumed > consumed_max) { + consumed_max = consumed; + } + consumed = encode_log_list(&log_map, ESP_DIAG_LOG_TYPE_EVENT, "events", data, size); + if (consumed > consumed_max) { + consumed_max = consumed; + } + cbor_encoder_close_container(&s_diag_data_map, &log_map); + return consumed_max; +} + +#if (CONFIG_DIAG_ENABLE_METRICS || CONFIG_DIAG_ENABLE_VARIABLES) +// {"n":, "v": , "t": } +static void encode_str_data_pt(CborEncoder *array, const uint8_t *data) +{ + CborEncoder map; + cbor_encoder_create_map(array, &map, CborIndefiniteLength); + esp_diag_str_data_pt_t *m_data = &enc_scratch_buf.str_data_pt; + // copy at aligned address to avoid potential alignment issue + memcpy(m_data, data, sizeof(esp_diag_str_data_pt_t)); + cbor_encode_text_stringz(&map, "n"); +#ifndef CONFIG_ESP_INSIGHTS_META_VERSION_10 + char temp_path_key[10] = {0}; + snprintf(temp_path_key, sizeof(temp_path_key), "%s", ((m_data->type & 0xffff)==ESP_DIAG_DATA_PT_METRICS)?METRICS_PATH_VALUE:VARIABLES_PATH_VALUE); + CborEncoder key_arr; + cbor_encoder_create_array(&map, &key_arr, CborIndefiniteLength); + cbor_encode_text_stringz(&key_arr, temp_path_key); + cbor_encode_text_stringz(&key_arr, m_data->tag); + cbor_encode_text_stringz(&key_arr, m_data->key); + cbor_encoder_close_container(&map, &key_arr); +#else + cbor_encode_text_stringz(&map, m_data->key); +#endif + cbor_encode_text_stringz(&map, "v"); + cbor_encode_text_stringz(&map, m_data->value.str); + cbor_encode_text_stringz(&map, "t"); + cbor_encode_uint(&map, m_data->ts); + + cbor_encoder_close_container(array, &map); +} + +static void encode_data_pt(CborEncoder *array, const uint8_t *data) +{ + CborEncoder map; + cbor_encoder_create_map(array, &map, CborIndefiniteLength); + esp_diag_data_pt_t *m_data = &enc_scratch_buf.data_pt; + // copy at aligned address to avoid potential alignment issue + memcpy(m_data, data, sizeof(esp_diag_data_pt_t)); + cbor_encode_text_stringz(&map, "n"); +#ifndef CONFIG_ESP_INSIGHTS_META_VERSION_10 + char temp_path_key[10] = {0}; + snprintf(temp_path_key, sizeof(temp_path_key), "%s", ((m_data->type & 0xffff)==ESP_DIAG_DATA_PT_METRICS)?METRICS_PATH_VALUE:VARIABLES_PATH_VALUE); + CborEncoder key_arr; + cbor_encoder_create_array(&map, &key_arr, CborIndefiniteLength); + cbor_encode_text_stringz(&key_arr, temp_path_key); + cbor_encode_text_stringz(&key_arr, m_data->tag); + cbor_encode_text_stringz(&key_arr, m_data->key); + cbor_encoder_close_container(&map, &key_arr); +#else + cbor_encode_text_stringz(&map, m_data->key); +#endif + cbor_encode_text_stringz(&map, "v"); + switch (m_data->data_type) { + case ESP_DIAG_DATA_TYPE_BOOL: + cbor_encode_boolean(&map, m_data->value.b); + break; + case ESP_DIAG_DATA_TYPE_INT: + if (m_data->value.i < 0) { + cbor_encode_negative_int(&map, -(m_data->value.i)); + } else { + cbor_encode_int(&map, m_data->value.i); + } + break; + case ESP_DIAG_DATA_TYPE_UINT: + cbor_encode_uint(&map, m_data->value.u); + break; + case ESP_DIAG_DATA_TYPE_FLOAT: + cbor_encode_float(&map, m_data->value.f); + break; + case ESP_DIAG_DATA_TYPE_IPv4: + cbor_encode_byte_string(&map, (uint8_t *)&m_data->value.ipv4, sizeof(m_data->value.ipv4)); + break; + case ESP_DIAG_DATA_TYPE_MAC: + cbor_encode_byte_string(&map, &m_data->value.mac[0], sizeof(m_data->value.mac)); + break; + default: + break; + } + cbor_encode_text_stringz(&map, "t"); + cbor_encode_uint(&map, m_data->ts); + + cbor_encoder_close_container(array, &map); +} + +static size_t encode_data_points(const uint8_t *data, size_t size, const char *key, uint16_t type) +{ + assert(key); + size_t i = 0; + CborEncoder array; + /* FIXME */ + rtc_store_non_critical_data_hdr_t header; + esp_diag_data_type_t data_type; + + if (!data || (size <= sizeof(header))) { + printf("%s: Invalid arg! data %p, size %d. line %d\n", + "insights_cbor_enocoder", data, size, __LINE__); + return 0; + } + cbor_encode_text_stringz(&s_diag_data_map, key); + cbor_encoder_create_array(&s_diag_data_map, &array, CborIndefiniteLength); + + uint8_t meta_idx = data[0]; + while (size > sizeof(header)) { // if remaining + if (data[i] != meta_idx) { +#if INSIGHTS_DEBUG_ENABLED + printf("%s: skip data for next iteration meta: %d, data[i]: %d, itr: %d\n", + "insights_cbor_enocoder", meta_idx, data[i], i); +#endif + break; // do not encode for next meta info + } + i += 1; // skip meta_idx byte + size -= 1; + + memcpy(&header, data + i, sizeof(header)); + if (sizeof(header) + header.len > size) { +#if INSIGHTS_DEBUG_ENABLED + // partial record + printf("%s: partial record, needed %d, size %d\n", + "insights_cbor_enocoder", sizeof(header) + header.len, size); +#endif + i -= 1; + size += 1; + break; + } + + if (!header.len) { +#if INSIGHTS_DEBUG_ENABLED + // invalid record + printf("%s: invalid record, header.len %d\n", "insights_cbor_enocoder", header.len); + + ESP_LOG_BUFFER_HEX_LEVEL("cbor_enc", data, size, ESP_LOG_INFO); +#endif + i -= 1; + size += 1; + break; + } + uint32_t type_int; + memcpy(&type_int, &data[i + sizeof(header)], 4); // copy, (b'cos alignment!) + if ((type_int & 0xffff) == type) { + data_type = (type_int >> 16) & 0xffff; + if (data_type == ESP_DIAG_DATA_TYPE_STR && header.len == sizeof(esp_diag_str_data_pt_t)) { + encode_str_data_pt(&array, data + i + sizeof(header)); + } else if (header.len == sizeof(esp_diag_data_pt_t)) { + encode_data_pt(&array, data + i + sizeof(header)); + } + } + size -= (sizeof(header) + header.len); + i += (sizeof(header) + header.len); + } + cbor_encoder_close_container(&s_diag_data_map, &array); + return i; +} +#endif /* (CONFIG_DIAG_ENABLE_METRICS || CONFIG_DIAG_ENABLE_VARIABLES) */ + +#if CONFIG_DIAG_ENABLE_METRICS +size_t esp_insights_cbor_encode_diag_metrics(const uint8_t *data, size_t size) +{ + return encode_data_points(data, size, "metrics", ESP_DIAG_DATA_PT_METRICS); +} +#endif /* CONFIG_DIAG_ENABLE_METRICS */ + +#if CONFIG_DIAG_ENABLE_VARIABLES +size_t esp_insights_cbor_encode_diag_variables(const uint8_t *data, size_t size) +{ + return encode_data_points(data, size, "params", ESP_DIAG_DATA_PT_VARIABLE); +} +#endif /* CONFIG_DIAG_ENABLE_VARIABLES */ + +/* Below are the helpers to encode esp insights meta data */ + +void esp_insights_cbor_encode_meta_begin(void *data, size_t data_size, const char *version, const char *sha256) +{ + cbor_encoder_init(&s_meta_encoder, data, data_size, 0); + cbor_encoder_create_map(&s_meta_encoder, &s_meta_result_map, 1); + cbor_encode_text_stringz(&s_meta_result_map, "diagmeta"); + cbor_encoder_create_map(&s_meta_result_map, &s_diag_meta_map, CborIndefiniteLength); + + cbor_encode_text_stringz(&s_diag_meta_map, "ver"); + cbor_encode_text_stringz(&s_diag_meta_map, version); + + cbor_encode_text_stringz(&s_diag_meta_map, "ts"); + cbor_encode_uint(&s_diag_meta_map, esp_diag_timestamp_get()); + cbor_encode_text_stringz(&s_diag_meta_map, "sha256"); + cbor_encode_text_stringz(&s_diag_meta_map, sha256); +} + +size_t esp_insights_cbor_encode_meta_end(void *data) +{ + cbor_encoder_close_container(&s_meta_result_map, &s_diag_meta_map); + cbor_encoder_close_container(&s_meta_encoder, &s_meta_result_map); + return cbor_encoder_get_buffer_size(&s_meta_encoder, data); +} + +void esp_insights_cbor_encode_meta_data_begin(void) +{ + cbor_encode_text_stringz(&s_diag_meta_map, "data"); + cbor_encoder_create_map(&s_diag_meta_map, &s_diag_meta_data_map, CborIndefiniteLength); +} + +void esp_insights_cbor_encode_meta_data_end(void) +{ + cbor_encoder_close_container(&s_diag_meta_map, &s_diag_meta_data_map); +} + +void esp_insights_cbor_encode_conf_meta_data_begin(void) +{ + cbor_encode_text_stringz(&s_diag_meta_map, "data"); + cbor_encoder_create_map(&s_diag_meta_map, &s_diag_meta_data_map, CborIndefiniteLength); +#ifdef NEW_META_STRUCT + for (int i = 0; i < s_priv_data.cb_cnt; i++) { + if (s_priv_data.cb[i]) { + s_priv_data.cb[i] (&s_diag_meta_data_map, INSIGHTS_MSG_TYPE_META); + } + } +#endif +} + +/** Vikram: remove? */ +void esp_insights_cbor_encode_conf_meta_data_end(void) +{ + cbor_encoder_close_container(&s_diag_meta_map, &s_diag_meta_data_map); +} + +#if CONFIG_DIAG_ENABLE_METRICS +static void encode_metrics_meta_element(CborEncoder *map, const esp_diag_metrics_meta_t *metrics) +{ + CborEncoder id_map; +#ifdef NEW_META_STRUCT + CborEncoder m_map; +#endif + cbor_encode_text_stringz(map, metrics->key); +#ifdef NEW_META_STRUCT + cbor_encoder_create_map(map, &m_map, CborIndefiniteLength); + cbor_encode_text_stringz(&m_map, "m"); // a metrics meta entry + cbor_encoder_create_map(&m_map, &id_map, CborIndefiniteLength); +#else + cbor_encoder_create_map(map, &id_map, CborIndefiniteLength); +#endif +#ifndef TAG_IS_OUTER_KEY + cbor_encode_text_stringz(&id_map, "tag"); + cbor_encode_text_stringz(&id_map, metrics->tag); +#endif + cbor_encode_text_stringz(&id_map, "label"); + cbor_encode_text_stringz(&id_map, metrics->label); + cbor_encode_text_stringz(&id_map, "path"); + cbor_encode_text_stringz(&id_map, metrics->path); + cbor_encode_text_stringz(&id_map, "data_type"); + cbor_encode_uint(&id_map, metrics->type); + if (metrics->unit) { + cbor_encode_text_stringz(&id_map, "unit"); + cbor_encode_text_stringz(&id_map, metrics->unit); + } +#ifdef NEW_META_STRUCT + cbor_encoder_close_container(&m_map, &id_map); // close metrics + cbor_encoder_close_container(map, &m_map); +#else + cbor_encoder_close_container(map, &id_map); +#endif +} + +void esp_insights_cbor_encode_meta_metrics(const esp_diag_metrics_meta_t *metrics, uint32_t metrics_len) +{ + if (!metrics || !metrics_len) { + return; + } + CborEncoder map; +#ifdef NEW_META_STRUCT + CborEncoder metrics_map; + cbor_encode_text_stringz(&s_diag_meta_data_map, METRICS_PATH_VALUE); + cbor_encoder_create_map(&s_diag_meta_data_map, &metrics_map, CborIndefiniteLength); + // d: decendants map + cbor_encode_text_stringz(&metrics_map, "d"); + cbor_encoder_create_map(&metrics_map, &map, CborIndefiniteLength); + // d: descendants map + // enabled config for data +#else + cbor_encode_text_stringz(&s_diag_meta_data_map, "metrics"); + cbor_encoder_create_map(&s_diag_meta_data_map, &map, CborIndefiniteLength); +#endif +#ifndef TAG_IS_OUTER_KEY + for (int i = 0; i < metrics_len; i++) { + encode_metrics_meta_element(&map, (metrics + i)); + } +#else + for (int i = 0; i < metrics_len; i++) { + const esp_diag_metrics_meta_t *metrics_i = metrics + i; + // check if this group was already encoded + bool encoded = false; + for (int j = 0; j < i; j++) { + const esp_diag_metrics_meta_t *metrics_j = metrics + j; + // ESP_LOGI(TAG, "Comparing tags %s %s", metrics_i->tag, metrics_j->tag); + if (metrics_j->tag == metrics_i->tag) { + encoded = true; + break; + } + } + if (encoded == false) { + // encode all the metrices with the group + ESP_LOGD(TAG, "Encoding new tag %s", metrics_i->tag); + CborEncoder tag_map; + cbor_encode_text_stringz(&map, metrics_i->tag); +#ifdef NEW_META_STRUCT + CborEncoder tag_d_map; + cbor_encoder_create_map(&map, &tag_d_map, CborIndefiniteLength); + cbor_encode_text_stringz(&tag_d_map, "d"); + cbor_encoder_create_map(&tag_d_map, &tag_map, CborIndefiniteLength); +#else + cbor_encoder_create_map(&map, &tag_map, CborIndefiniteLength); +#endif + for (int j = i; j < metrics_len; j++) { + const esp_diag_metrics_meta_t *metrics_j = metrics + j; + if (metrics_j->tag == metrics_i->tag) { + ESP_LOGD(TAG, "Encoding key %s", metrics_j->key); + encode_metrics_meta_element(&tag_map, metrics_j); + } + } +#ifdef NEW_META_STRUCT + cbor_encoder_close_container(&tag_d_map, &tag_map); + cbor_encoder_close_container(&map, &tag_d_map); +#else + cbor_encoder_close_container(&map, &tag_map); +#endif + } + } +#endif +#ifdef NEW_META_STRUCT + // close d: decendants + cbor_encoder_close_container(&metrics_map, &map); + cbor_encoder_close_container(&s_diag_meta_data_map, &metrics_map); +#else + cbor_encoder_close_container(&s_diag_meta_data_map, &map); +#endif +} +#endif /* CONFIG_DIAG_ENABLE_METRICS */ + +#if CONFIG_DIAG_ENABLE_VARIABLES +static void encode_variable_meta_element(CborEncoder *map, const esp_diag_variable_meta_t *variable) +{ + CborEncoder id_map; +#ifdef NEW_META_STRUCT + CborEncoder m_map; +#endif + cbor_encode_text_stringz(map, variable->key); +#ifdef NEW_META_STRUCT + cbor_encoder_create_map(map, &m_map, CborIndefiniteLength); + cbor_encode_text_stringz(&m_map, "p"); // a variable meta entry + cbor_encoder_create_map(&m_map, &id_map, CborIndefiniteLength); +#else + cbor_encoder_create_map(map, &id_map, CborIndefiniteLength); +#endif +#ifndef TAG_IS_OUTER_KEY + cbor_encode_text_stringz(&id_map, "tag"); + cbor_encode_text_stringz(&id_map, variable->tag); +#endif + cbor_encode_text_stringz(&id_map, "label"); + cbor_encode_text_stringz(&id_map, variable->label); + cbor_encode_text_stringz(&id_map, "path"); + cbor_encode_text_stringz(&id_map, variable->path); + cbor_encode_text_stringz(&id_map, "data_type"); + cbor_encode_uint(&id_map, variable->type); + if (variable->unit) { + cbor_encode_text_stringz(&id_map, "unit"); + cbor_encode_text_stringz(&id_map, variable->unit); + } +#ifdef NEW_META_STRUCT + cbor_encoder_close_container(&m_map, &id_map); // close variable entry + cbor_encoder_close_container(map, &m_map); +#else + cbor_encoder_close_container(map, &id_map); +#endif +} + +void esp_insights_cbor_encode_meta_variables(const esp_diag_variable_meta_t *variables, uint32_t variables_len) +{ + if (!variables || !variables_len) { + return; + } + + CborEncoder map; +#ifdef NEW_META_STRUCT + CborEncoder variables_map; + cbor_encode_text_stringz(&s_diag_meta_data_map, VARIABLES_PATH_VALUE); + cbor_encoder_create_map(&s_diag_meta_data_map, &variables_map, CborIndefiniteLength); + // d: decendants map + cbor_encode_text_stringz(&variables_map, "d"); + cbor_encoder_create_map(&variables_map, &map, CborIndefiniteLength); +#else + cbor_encode_text_stringz(&s_diag_meta_data_map, "params"); + cbor_encoder_create_map(&s_diag_meta_data_map, &map, CborIndefiniteLength); +#endif +#ifndef TAG_IS_OUTER_KEY + for (int i = 0; i < variables_len; i++) { + encode_variable_meta_element(&map, (variables + i)); + } +#else + for (int i = 0; i < variables_len; i++) { + const esp_diag_variable_meta_t *variables_i = variables + i; + // check if this group was already encoded + bool encoded = false; + for (int j = 0; j < i; j++) { + const esp_diag_variable_meta_t *variables_j = variables + j; + if (variables_j->tag == variables_i->tag) { + encoded = true; + break; + } + } + if (encoded == false) { + CborEncoder tag_map; + // encode all the metrices with the group + cbor_encode_text_stringz(&map, variables_i->tag); +#ifdef NEW_META_STRUCT + CborEncoder tag_d_map; + cbor_encoder_create_map(&map, &tag_d_map, CborIndefiniteLength); + cbor_encode_text_stringz(&tag_d_map, "d"); + cbor_encoder_create_map(&tag_d_map, &tag_map, CborIndefiniteLength); +#else + cbor_encoder_create_map(&map, &tag_map, CborIndefiniteLength); +#endif + for (int j = i; j < variables_len; j++) { + const esp_diag_variable_meta_t *variables_j = variables + j; + if (variables_j->tag == variables_i->tag) { + encode_variable_meta_element(&tag_map, variables_j); + } + } +#ifdef NEW_META_STRUCT + cbor_encoder_close_container(&tag_d_map, &tag_map); + cbor_encoder_close_container(&map, &tag_d_map); +#else + cbor_encoder_close_container(&map, &tag_map); +#endif + } + } +#endif +#ifdef NEW_META_STRUCT + // close d: decendants + cbor_encoder_close_container(&variables_map, &map); + cbor_encoder_close_container(&s_diag_meta_data_map, &variables_map); +#else + cbor_encoder_close_container(&s_diag_meta_data_map, &map); +#endif +} +#endif /* CONFIG_DIAG_ENABLE_VARIABLES */ diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_insights/src/esp_insights_cbor_encoder.h b/RainMaker_Table-Lights/managed_components/espressif__esp_insights/src/esp_insights_cbor_encoder.h new file mode 100644 index 000000000..ec158ea01 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_insights/src/esp_insights_cbor_encoder.h @@ -0,0 +1,92 @@ +/* + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include +#include +#if CONFIG_ESP_INSIGHTS_COREDUMP_ENABLE +#include +#endif /* CONFIG_ESP_INSIGHTS_COREDUMP_ENABLE */ +#include + +// make tag/group as a outer key and actual keys from it are contained within +#ifndef CONFIG_ESP_INSIGHTS_META_VERSION_10 +#define TAG_IS_OUTER_KEY 1 +#define NEW_META_STRUCT 1 +#endif + +typedef enum { + INSIGHTS_MSG_TYPE_META, + INSIGHTS_MSG_TYPE_DATA +} insights_msg_type_t; + +/** + * @brief cbor encoder callback + * + * @param map parent map to which new data will be encoded + * @param type information type to be collected + */ +typedef void (*insights_cbor_encoder_cb_t) (CborEncoder *map, insights_msg_type_t type); + +/** + * @brief register a meta collection callback + * + * @param cb callback of type \ref insights_cbor_encoder_cb_t + * + * @return ESP_OK on success, appropriate error otherwise + */ +esp_err_t esp_insights_cbor_encoder_register_meta_cb(insights_cbor_encoder_cb_t cb); + +void esp_insights_cbor_encode_diag_begin(void *data, size_t data_size, const char *version); +void esp_insights_cbor_encode_diag_data_begin(void); +void esp_insights_cbor_encode_diag_boot_info(esp_diag_device_info_t *device_info); + +/** + * @brief encode master header + * + * @param hdr meta header which contains data regarding message it follows + * @param type rtc_store type (viz., "critical", "non_critical") + */ +void esp_insights_cbor_encode_meta_c_hdr(const rtc_store_meta_header_t *hdr); +void esp_insights_cbor_encode_meta_nc_hdr(const rtc_store_meta_header_t *hdr); + +#if CONFIG_ESP_INSIGHTS_COREDUMP_ENABLE +void esp_insights_cbor_encode_diag_crash(esp_core_dump_summary_t *summary); +#endif /* CONFIG_ESP_INSIGHTS_COREDUMP_ENABLE */ +size_t esp_insights_cbor_encode_diag_logs(const uint8_t *data, size_t size); +size_t esp_insights_cbor_encode_diag_metrics(const uint8_t *data, size_t size); +size_t esp_insights_cbor_encode_diag_variables(const uint8_t *data, size_t size); +void esp_insights_cbor_encode_diag_data_end(void); +size_t esp_insights_cbor_encode_diag_end(void *data); + +/* For encoding diag meta data */ +void esp_insights_cbor_encode_meta_begin(void *data, size_t data_size, const char *version, const char *sha256); +void esp_insights_cbor_encode_meta_data_begin(void); +#if CONFIG_DIAG_ENABLE_METRICS +void esp_insights_cbor_encode_meta_metrics(const esp_diag_metrics_meta_t *metrics, uint32_t metrics_len); +#endif /* CONFIG_DIAG_ENABLE_METRICS */ +#if CONFIG_DIAG_ENABLE_VARIABLES +void esp_insights_cbor_encode_meta_variables(const esp_diag_variable_meta_t *variables, uint32_t variables_len); +#endif /* CONFIG_DIAG_ENABLE_VARIABLES */ +void esp_insights_cbor_encode_meta_data_end(void); +size_t esp_insights_cbor_encode_meta_end(void *data); + + +/* For encoding conf data */ +void esp_insights_cbor_encode_conf_meta_begin(void *data, size_t data_size, const char *version, const char *sha256); +void esp_insights_cbor_encode_conf_meta_data_begin(void); +void esp_insights_cbor_encode_conf_meta_data_end(void); +size_t esp_insights_cbor_encode_conf_meta_end(void *data); + +void esp_insights_cbor_encode_diag_conf_data_begin(void); +void esp_insights_cbor_encode_diag_conf_data_end(void); +void esp_insights_cbor_encode_diag_conf_data(void); + +/* For converting 8 bytes sha256 to hex form */ +void bytes_to_hex(uint8_t *src, uint8_t *dst, int in_len); + diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_insights/src/esp_insights_client_data.c b/RainMaker_Table-Lights/managed_components/espressif__esp_insights/src/esp_insights_client_data.c new file mode 100644 index 000000000..e3f1200ed --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_insights/src/esp_insights_client_data.c @@ -0,0 +1,118 @@ +/* + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include + +#define INSIGHTS_CLIENT_CERT_NVS_KEY "client_cert" +#define INSIGHTS_CLIENT_KEY_NVS_KEY "client_key" +#define INSIGHTS_MQTT_HOST_NVS_KEY "mqtt_host" +#define INSIGHTS_NODE_ID "node_id" +#define INSIGHTS_META_CRC_NVS_KEY "i_meta_crc" +#define INSIGHTS_NVS_NAMESPACE "nvs" + +extern uint8_t mqtt_server_root_ca_pem_start[] asm("_binary_mqtt_server_crt_start"); +extern uint8_t mqtt_server_root_ca_pem_end[] asm("_binary_mqtt_server_crt_end"); + +static char *esp_insights_get_mqtt_host(void) +{ + return esp_rmaker_factory_get(INSIGHTS_MQTT_HOST_NVS_KEY); +} + +static char *esp_insights_get_client_cert(void) +{ + return esp_rmaker_factory_get(INSIGHTS_CLIENT_CERT_NVS_KEY); +} + +static char *esp_insights_get_client_key(void) +{ + return esp_rmaker_factory_get(INSIGHTS_CLIENT_KEY_NVS_KEY); +} + +esp_rmaker_mqtt_conn_params_t *esp_insights_get_mqtt_conn_params(void) +{ + esp_rmaker_mqtt_conn_params_t *mqtt_conn_params = calloc(1, sizeof(esp_rmaker_mqtt_conn_params_t)); + if ((mqtt_conn_params->client_key = esp_insights_get_client_key()) == NULL) { + goto init_err; + } + if ((mqtt_conn_params->client_cert = esp_insights_get_client_cert()) == NULL) { + goto init_err; + } + if ((mqtt_conn_params->mqtt_host = esp_insights_get_mqtt_host()) == NULL) { + goto init_err; + } + mqtt_conn_params->server_cert = (char *)mqtt_server_root_ca_pem_start; + mqtt_conn_params->client_id = esp_rmaker_factory_get(INSIGHTS_NODE_ID); + return mqtt_conn_params; +init_err: + if (mqtt_conn_params->mqtt_host) { + free(mqtt_conn_params->mqtt_host); + } + if (mqtt_conn_params->client_cert) { + free(mqtt_conn_params->client_cert); + } + if (mqtt_conn_params->client_key) { + free(mqtt_conn_params->client_key); + } + free(mqtt_conn_params); + return NULL; +} + +void esp_insights_clean_mqtt_conn_params(esp_rmaker_mqtt_conn_params_t *mqtt_conn_params) +{ + if (mqtt_conn_params) { + if (mqtt_conn_params->mqtt_host) { + free(mqtt_conn_params->mqtt_host); + } + if (mqtt_conn_params->client_cert) { + free(mqtt_conn_params->client_cert); + } + if (mqtt_conn_params->client_key) { + free(mqtt_conn_params->client_key); + } + } +} + +esp_err_t esp_insights_meta_nvs_crc_get(uint32_t *crc) +{ + if (!crc) { + return ESP_ERR_INVALID_ARG; + } + nvs_handle_t handle; + esp_err_t err = nvs_open(INSIGHTS_NVS_NAMESPACE, NVS_READONLY, &handle); + if (err != ESP_OK) { + return err; + } + err = nvs_get_u32(handle, INSIGHTS_META_CRC_NVS_KEY, crc); + if (err != ESP_OK) { + nvs_close(handle); + return err; + } + nvs_close(handle); + return err; +} + +esp_err_t esp_insights_meta_nvs_crc_set(uint32_t crc) +{ + nvs_handle_t handle; + esp_err_t err = nvs_open(INSIGHTS_NVS_NAMESPACE, NVS_READWRITE, &handle); + if (err != ESP_OK) { + return err; + } + err = nvs_set_u32(handle, INSIGHTS_META_CRC_NVS_KEY, crc); + if (err != ESP_OK) { + nvs_close(handle); + return err; + } + nvs_commit(handle); + nvs_close(handle); + return err; +} diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_insights/src/esp_insights_client_data.h b/RainMaker_Table-Lights/managed_components/espressif__esp_insights/src/esp_insights_client_data.h new file mode 100644 index 000000000..236265790 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_insights/src/esp_insights_client_data.h @@ -0,0 +1,23 @@ +/* + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif +esp_rmaker_mqtt_conn_params_t *esp_insights_get_mqtt_conn_params(void); +void esp_insights_clean_mqtt_conn_params(esp_rmaker_mqtt_conn_params_t *mqtt_conn_params); +esp_err_t esp_insights_meta_nvs_crc_get(uint32_t *crc); +esp_err_t esp_insights_meta_nvs_crc_set(uint32_t crc); +#ifdef __cplusplus +} +#endif diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_insights/src/esp_insights_cmd_resp.c b/RainMaker_Table-Lights/managed_components/espressif__esp_insights/src/esp_insights_cmd_resp.c new file mode 100644 index 000000000..e0ff1139d --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_insights/src/esp_insights_cmd_resp.c @@ -0,0 +1,676 @@ +/* + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file esp_insights_cmd_resp.c + * @brief this file contains glue between received data parsing for insights config, + * which eventually calls the commands it has registered to + */ + +#include +#include + +static const char *TAG = "insights_cmd_resp"; + +#ifdef CONFIG_ESP_INSIGHTS_CMD_RESP_ENABLED +#include + +#include /* for nodeID */ +#include +#include + +#include "esp_insights_internal.h" +#include "esp_insights_cbor_decoder.h" +#include "esp_insights_cbor_encoder.h" + +#define INS_CONF_STR "config" +#define RMAKER_CFG_TOPIC_SUFFIX "config" +#define TO_NODE_TOPIC_SUFFIX "to-node" +#define FROM_NODE_TOPIC_SUFFIX "from-node" + +/** This is a common command identifier for Insights and then Insights internally has its own commands and their handlers. + */ +#define INSIGHTS_CONF_CMD 0x101 + +/* depth is dictated by cmd_depth */ +#define MAX_CMD_DEPTH 10 +#define CMD_STORE_SIZE 10 +#define SCRATCH_BUF_SIZE (1 * 1024) + +typedef esp_err_t (*esp_insights_cmd_cb_t)(const void *data, size_t data_len, const void *priv); + +typedef struct { + const char *cmd[MAX_CMD_DEPTH]; /* complete path of the command */ + int depth; + esp_insights_cmd_cb_t cb; /* callback function */ + void *prv_data; /* pointer to the private data */ +} generic_cmd_t; + +typedef struct { + generic_cmd_t cmd_store[CMD_STORE_SIZE]; + int cmd_cnt; /* total registered commands */ + uint8_t *scratch_buf; + bool enabled; + bool init_done; +} insights_cmd_resp_data_t; + +static insights_cmd_resp_data_t s_cmd_resp_data; +static bool reboot_report_pending = false; + +static esp_err_t reboot_cmd_handler(const void *data, size_t data_len, const void *prv_data) +{ + reboot_report_pending = true; + ESP_LOGI(TAG, "rebooting in 5 seconds..."); + esp_rmaker_reboot(5); + return ESP_OK; +} + +static void __collect_reboot_meta(CborEncoder *map) +{ + cbor_encode_text_stringz(map, "reboot"); /* name of the config */ + CborEncoder conf_map, conf_data_map; + cbor_encoder_create_map(map, &conf_map, CborIndefiniteLength); + cbor_encode_text_stringz(&conf_map, "c"); /* denotes this to be config */ + cbor_encoder_create_map(&conf_map, &conf_data_map, CborIndefiniteLength); + cbor_encode_text_stringz(&conf_data_map, "type"); + cbor_encode_uint(&conf_data_map, ESP_DIAG_DATA_TYPE_NULL); /* data_type */ + cbor_encoder_close_container(&conf_map, &conf_data_map); + cbor_encoder_close_container(map, &conf_map); +} + +static void __collect_reboot_data(CborEncoder *map) +{ + CborEncoder conf_map, key_arr; + cbor_encoder_create_map(map, &conf_map, CborIndefiniteLength); + cbor_encode_text_stringz(&conf_map, "n"); + cbor_encoder_create_array(&conf_map, &key_arr, CborIndefiniteLength); + cbor_encode_text_stringz(&key_arr, "reboot"); + cbor_encoder_close_container(&conf_map, &key_arr); + cbor_encode_text_stringz(&conf_map, "t"); + cbor_encode_uint(&conf_map, esp_diag_timestamp_get()); + cbor_encoder_close_container(map, &conf_map); +} + +static void esp_insights_cbor_reboot_msg_cb(CborEncoder *map, insights_msg_type_t type) +{ + if (type == INSIGHTS_MSG_TYPE_META) { + __collect_reboot_meta(map); + } else if (reboot_report_pending) { + __collect_reboot_data(map); + reboot_report_pending = false; + } +} + +esp_err_t esp_insights_cmd_resp_register_cmd(esp_insights_cmd_cb_t cb, void *prv_data, int cmd_depth, ...) +{ + int idx = s_cmd_resp_data.cmd_cnt; + + va_list valist; + va_start(valist, cmd_depth); + for (int i = 0; i < cmd_depth; i++) { + s_cmd_resp_data.cmd_store[idx].cmd[i] = va_arg(valist, char *); + } + /* clean memory reserved for valist */ + va_end(valist); + + s_cmd_resp_data.cmd_store[idx].depth = cmd_depth; + s_cmd_resp_data.cmd_store[idx].prv_data = prv_data; + s_cmd_resp_data.cmd_store[idx].cb = cb; + s_cmd_resp_data.cmd_cnt += 1; + + return ESP_OK; +} + +static esp_err_t insights_cmd_resp_search_execute_cmd_store(char **cmd_tree, int cmd_depth) +{ + for(int i = 0; i< s_cmd_resp_data.cmd_cnt; i++) { + if (cmd_depth == s_cmd_resp_data.cmd_store[i].depth) { + bool match_found = true; + /* the command depth matches, now go for whole path */ + for (int j = 0; j < cmd_depth; j++) { + if (strcmp(cmd_tree[j], s_cmd_resp_data.cmd_store[i].cmd[j]) != 0) { + match_found = false; + break; /* break at first mismatch */ + } + } + if (match_found) { + ESP_LOGI(TAG, "match found in cmd_store... Executing the callback"); + s_cmd_resp_data.cmd_store[i].cb(NULL, 0, s_cmd_resp_data.cmd_store[i].prv_data); + return ESP_OK; + } + } + } + return ESP_ERR_NOT_FOUND; +} + +static void insights_cmd_parser_clear_cmd_tree(char *cmd_tree[]) +{ + for (int i = 0; i < MAX_CMD_DEPTH; i++) { + if (cmd_tree[i]) { + free(cmd_tree[i]); + cmd_tree[i] = NULL; + } else { + return; + } + } +} + +static void insights_cmd_parser_add_cmd_to_tree(char * cmd_tree[], char *cmd, int pos) +{ + ESP_LOGV(TAG, "Adding %s to command path\n", cmd); + /* free depth already consumed */ + for (int i = pos; i < MAX_CMD_DEPTH; i++) { + if (cmd_tree[i]) { + free(cmd_tree[i]); + cmd_tree[i] = NULL; + } else { + break; + } + } + + /* insert at the position */ + cmd_tree[pos] = cmd; +} + +static void insights_cmd_parser_print_cmd_tree(const char *cmd_tree[], int depth) +{ + if (depth <= 0) { + ESP_LOGI(TAG, "No command found to be printed"); + return; + } + printf("The command is: "); + for (int i = 0; i < depth - 1; i++) { + if (cmd_tree[i]) { + printf("%s > ", cmd_tree[i]); + } else { + printf("\ncouldn't find complete depth\n"); + return; + } + } + if (cmd_tree[depth - 1]) { + printf("%s\n", cmd_tree[depth - 1]); + } else { + printf("\ncouldn't find complete depth\n"); + } +} + +#define MAX_BUFFER_SIZE 100 + +/* extract top level fields from CBOR and check for sanity */ +esp_err_t check_top_fields_from_cbor(const uint8_t *cbor_data, size_t cbor_data_len) +{ + CborParser parser; + CborValue map, value; + CborError err; + + /* Initialize the parser */ + cbor_parser_init(cbor_data, cbor_data_len, 0, &parser, &map); + + /* Parse the top-level map */ + if (!cbor_value_is_map(&map)) { + ESP_LOGE(TAG, "Invalid CBOR format: top-level map expected"); + return ESP_FAIL; + } + + if (CborNoError != cbor_value_enter_container(&map, &value)) { + ESP_LOGE(TAG, "Error entering the container"); + return ESP_FAIL; + } + + /* Iterate through the map and extract the desired fields */ + while (!cbor_value_at_end(&value)) { + CborValue map_key; + + /* Check the map key and extract the corresponding field */ + if (cbor_value_is_text_string(&value)) { + char buffer[MAX_BUFFER_SIZE]; + size_t buffer_size = sizeof(buffer); + err = cbor_value_copy_text_string(&value, buffer, &buffer_size, &map_key); + if (err != CborNoError) { + ESP_LOGE(TAG, "CBOR value copy text string failed: %d", err); + return ESP_FAIL; + } + + buffer_size = sizeof(buffer); + if (strcmp(buffer, "ver") == 0) { + if (cbor_value_is_text_string(&map_key)) { + err = cbor_value_copy_text_string(&map_key, buffer, &buffer_size, &map_key); + if (err != CborNoError) { + ESP_LOGE(TAG, "CBOR value copy text string failed: %d", err); + return ESP_FAIL; + } + ESP_LOGI(TAG, "ver: %s", buffer); + } else { + ESP_LOGE(TAG, "Invalid CBOR format: text string expected as ver key"); + } + } else if (strcmp(buffer, "ts") == 0) { + CborType _type = cbor_value_get_type(&map_key); + ESP_LOGI(TAG, "ts is of type %d", _type); + } else if (strcmp(buffer, "sha256") == 0) { + if (cbor_value_is_text_string(&map_key)) { + err = cbor_value_copy_text_string(&map_key, buffer, &buffer_size, &map_key); + if (err != CborNoError) { + ESP_LOGE(TAG, "CBOR value copy text string failed: %d", err); + return ESP_FAIL; + } + ESP_LOGI(TAG, "sha256: %s", buffer); + } else { + ESP_LOGE(TAG, "Invalid CBOR format: text string expected as sha256 key"); + } + } else if (strcmp(buffer, INS_CONF_STR) == 0) { + /* Nothing to do here */ + } + + /* skip this string now */ + err = cbor_value_advance(&value); + if (err != CborNoError) { + ESP_LOGE(TAG, "CBOR value advance failed: %d", err); + return ESP_FAIL; + } + } + + /* advance the value */ + CborType _type = cbor_value_get_type(&value); + ESP_LOGI(TAG, "Skipping type %d", _type); + err = cbor_value_advance(&value); + if (err != CborNoError) { + ESP_LOGE(TAG, "CBOR value advance failed: %d", err); + return ESP_FAIL; + } + } + return ESP_OK; +} + +/** + * @brief Get next config entry from data + * + */ +static esp_err_t esp_insights_cmd_resp_parse_one_entry(cbor_parse_ctx_t *ctx) +{ + char *tmp_str = NULL; + int cmd_depth = 0; + bool cmd_value_b; + esp_err_t ret = ESP_OK; + char *cmd_tree[MAX_CMD_DEPTH] = {0, }; + + /* parse till we are at the end */ + while (!esp_insights_cbor_decoder_at_end(ctx)) { + CborType type = esp_insights_cbor_decode_get_value_type(ctx); + CborValue *it = &ctx->it[ctx->curr_itr]; + switch (type) + { + case CborTextStringType: + tmp_str = esp_insights_cbor_decoder_get_string(it); + if (!tmp_str) { + return ESP_FAIL; + } + ESP_LOGI(TAG, "found \"%s\"", tmp_str); + if (strcmp(tmp_str, "n") == 0) { + CborType _type = esp_insights_cbor_decode_get_value_type(ctx); + if (_type == CborArrayType) { + if (esp_insights_cbor_decoder_enter_container(ctx) == ESP_OK) { + while(!esp_insights_cbor_decoder_at_end(ctx)) { + char *buffer = esp_insights_cbor_decoder_get_string(&ctx->it[ctx->curr_itr]); + if (!buffer) { + ESP_LOGE(TAG, "Invalid entry"); + break; + } + insights_cmd_parser_add_cmd_to_tree(cmd_tree, buffer, cmd_depth); + ++cmd_depth; + } + + insights_cmd_parser_print_cmd_tree((const char **) cmd_tree, cmd_depth); + esp_insights_cbor_decoder_exit_container(ctx); + } + } else { + ESP_LOGE(TAG, "A config name must be of array type"); + } + } else if (strcmp(tmp_str, "v") == 0) { + /* decide the type of the value first and then fetch it (bool for now) */ + esp_diag_data_type_t type = ESP_DIAG_DATA_TYPE_BOOL; + /* get the value in val */ + switch (type) + { + case ESP_DIAG_DATA_TYPE_BOOL: + cbor_value_get_boolean(it, &cmd_value_b); + break; + default: + break; + } + cbor_value_advance_fixed(it); + } else { + esp_insights_cbor_decoder_advance(ctx); + } + + if (tmp_str) { + free(tmp_str); + tmp_str = NULL; + } + break; + + default: + esp_insights_cbor_decoder_advance(ctx); + break; + } + } + + insights_cmd_resp_search_execute_cmd_store(cmd_tree, cmd_depth); + insights_cmd_parser_clear_cmd_tree(cmd_tree); + + return ret; +} + +static esp_err_t esp_insights_cmd_resp_parse_execute(cbor_parse_ctx_t *ctx) +{ + esp_insights_cbor_decoder_enter_container(ctx); + int cmd_cnt = 0; + /* iterate till we are done with current container */ + while (!esp_insights_cbor_decoder_at_end(ctx)) { + esp_insights_cbor_decoder_enter_container(ctx); + esp_insights_cmd_resp_parse_one_entry(ctx); + esp_insights_cbor_decoder_exit_container(ctx); + cmd_cnt++; + } + if (cmd_cnt) { + esp_insights_report_config_update(); + } + esp_insights_cbor_decoder_exit_container(ctx); + ESP_LOGI(TAG, "parsed and executed %d commands", cmd_cnt); + return ESP_OK; +} + +static esp_err_t esp_insights_cmd_resp_iterate_to_cmds_array(cbor_parse_ctx_t *ctx) +{ + /* layer one */ + if (esp_insights_cbor_decoder_at_end(ctx)) { + ESP_LOGW(TAG, "invalid cmd_resp payload"); + return ESP_FAIL; + } + + if (esp_insights_cbor_decode_get_value_type(ctx) != CborMapType) { + ESP_LOGE(TAG, "invalid cmd_resp payload. line (%d)", __LINE__); + return ESP_FAIL; + } + + if (esp_insights_cbor_decoder_enter_container(ctx) == ESP_OK) { + while(!esp_insights_cbor_decoder_at_end(ctx)) { + char *buffer = esp_insights_cbor_decoder_get_string(&ctx->it[ctx->curr_itr]); + + if (!buffer) { + ESP_LOGE(TAG, "Parsing problem..."); + return ESP_FAIL; + } + + if (strcmp(buffer, INS_CONF_STR) == 0) { + free(buffer); + buffer = NULL; + ESP_LOGI(TAG, "Found commands array:"); + return ESP_OK; + } else { + ESP_LOGI(TAG, "skipping token %s", buffer); + } + free(buffer); + buffer = NULL; + /* skip the value and find next for INS_CONF_STR */ + esp_insights_cbor_decoder_advance(ctx); + } + ESP_LOGI(TAG, "failed to find a `config` array!"); + return ESP_FAIL; + } + + ESP_LOGI(TAG, "invalid payload type"); + return ESP_FAIL; +} + +static char resp_data[100]; /* FIXME: assumed that the response size is < 100 bytes */ +/** This is a common handler registered with the lower layer command response framework. + * It parses the received CBOR payload aqnd redirects to appropriate internal insights command callback. */ +static esp_err_t esp_insights_cmd_handler(const void *in_data, size_t in_len, void **out_data, + size_t *out_len, esp_rmaker_cmd_ctx_t *ctx, void *priv) +{ + esp_err_t ret = ESP_FAIL; + if (in_data == NULL || in_len == 0) { + ESP_LOGE(TAG, "No data received"); + return ESP_FAIL; + } + +#if CONFIG_ESP_INSIGHTS_DEBUG_ENABLED + ESP_LOG_BUFFER_HEX_LEVEL(TAG, in_data, in_len, ESP_LOG_INFO); + ESP_LOGI(TAG, "Received command, len %d: ", in_len); + esp_insights_cbor_decode_dump((uint8_t *) in_data, in_len); +#endif + + if (ESP_FAIL == check_top_fields_from_cbor(in_data, in_len)) { + snprintf(resp_data, sizeof(resp_data), "{\"status\":\"payload error\"}"); + goto out; + } + cbor_parse_ctx_t *cbor_ctx = esp_insights_cbor_decoder_start(in_data, in_len); + if (cbor_ctx) { + ret = esp_insights_cmd_resp_iterate_to_cmds_array(cbor_ctx); + if (ret == ESP_OK) { + esp_insights_cmd_resp_parse_execute(cbor_ctx); /* it is okay if this is empty */ + snprintf(resp_data, sizeof(resp_data), "{\"status\":\"success\"}"); + } else { + snprintf(resp_data, sizeof(resp_data), "{\"status\":\"payload error\"}"); + } + esp_insights_cbor_decoder_done(cbor_ctx); + } else { + snprintf(resp_data, sizeof(resp_data), "{\"status\":\"internal error\"}"); + } +out: + *out_data = resp_data; + *out_len = strlen(resp_data); + return ret; +} + +const uint8_t test_buf0[] = { + 0xA1, 0x68, 0x64, 0x69, 0x61, 0x67, 0x6D, 0x65, 0x74, 0x61, 0xA4, 0x63, 0x76, 0x65, 0x72, 0x63, + 0x31, 0x2E, 0x31, 0x62, 0x74, 0x73, 0x1B, 0x00, 0x05, 0xFB, 0x53, 0xF9, 0x42, 0x0C, 0x39, 0x66, + 0x73, 0x68, 0x61, 0x32, 0x35, 0x36, 0x70, 0x39, 0x61, 0x65, 0x38, 0x30, 0x36, 0x36, 0x61, 0x30, + 0x37, 0x65, 0x38, 0x37, 0x38, 0x66, 0x64, 0x64, 0x64, 0x61, 0x74, 0x61, 0xA1, 0x61, 0x64, 0xA2, + 0x67, 0x65, 0x6E, 0x61, 0x62, 0x6C, 0x65, 0x64, 0xA1, 0x61, 0x63, 0xA2, 0x64, 0x74, 0x79, 0x70, + 0x65, 0x00, 0x61, 0x76, 0xF5, 0x67, 0x6D, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0xA1, 0x61, 0x64, + 0xA2, 0x67, 0x65, 0x6E, 0x61, 0x62, 0x6C, 0x65, 0x64, 0xA1, 0x61, 0x63, 0xA2, 0x64, 0x74, 0x79, + 0x70, 0x65, 0x00, 0x61, 0x76, 0xF5, 0x64, 0x68, 0x65, 0x61, 0x70, 0xA1, 0x61, 0x64, 0xA2, 0x67, + 0x65, 0x6E, 0x61, 0x62, 0x6C, 0x65, 0x64, 0xA1, 0x61, 0x63, 0xA2, 0x64, 0x74, 0x79, 0x70, 0x65, + 0x00, 0x61, 0x76, 0xF5, 0x6A, 0x61, 0x6C, 0x6C, 0x6F, 0x63, 0x5F, 0x66, 0x61, 0x69, 0x6C, 0xA1, + 0x61, 0x64, 0xA1, 0x67, 0x65, 0x6E, 0x61, 0x62, 0x6C, 0x65, 0x64, 0xA1, 0x61, 0x63, 0xA2, 0x64, + 0x74, 0x79, 0x70, 0x65, 0x00, 0x61, 0x76, 0xF5 +}; + +/** Test vector 2 */ +const uint8_t test_buf1[] = { + 0xA1, 0x68, 0x64, 0x69, 0x61, 0x67, 0x6D, 0x65, 0x74, 0x61, 0xA4, 0x63, 0x76, 0x65, 0x72, 0x63, + 0x31, 0x2E, 0x31, 0x62, 0x74, 0x73, 0x1B, 0x00, 0x05, 0xFB, 0x53, 0xF9, 0x42, 0x0C, 0x39, 0x66, + 0x73, 0x68, 0x61, 0x32, 0x35, 0x36, 0x70, 0x39, 0x61, 0x65, 0x38, 0x30, 0x36, 0x36, 0x61, 0x30, + 0x37, 0x65, 0x38, 0x37, 0x38, 0x66, 0x64, 0x64, 0x64, 0x61, 0x74, 0x61, 0xA1, 0x61, 0x64, 0xA3, + 0x67, 0x65, 0x6E, 0x61, 0x62, 0x6C, 0x65, 0x64, 0xA1, 0x61, 0x63, 0xA2, 0x64, 0x74, 0x79, 0x70, + 0x65, 0x00, 0x61, 0x76, 0xF5, 0x67, 0x6D, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0xA1, 0x61, 0x64, + 0xA2, 0x67, 0x65, 0x6E, 0x61, 0x62, 0x6C, 0x65, 0x64, 0xA1, 0x61, 0x63, 0xA2, 0x64, 0x74, 0x79, + 0x70, 0x65, 0x00, 0x61, 0x76, 0xF5, 0x64, 0x68, 0x65, 0x61, 0x70, 0xA1, 0x61, 0x64, 0xA3, 0x67, + 0x65, 0x6E, 0x61, 0x62, 0x6C, 0x65, 0x64, 0xA1, 0x61, 0x63, 0xA2, 0x64, 0x74, 0x79, 0x70, 0x65, + 0x00, 0x61, 0x76, 0xF5, 0x6A, 0x61, 0x6C, 0x6C, 0x6F, 0x63, 0x5F, 0x66, 0x61, 0x69, 0x6C, 0xA1, + 0x61, 0x64, 0xA1, 0x67, 0x65, 0x6E, 0x61, 0x62, 0x6C, 0x65, 0x64, 0xA1, 0x61, 0x63, 0xA2, 0x64, + 0x74, 0x79, 0x70, 0x65, 0x00, 0x61, 0x76, 0xF5, 0x64, 0x66, 0x72, 0x65, 0x65, 0xA1, 0x61, 0x64, + 0xA1, 0x67, 0x65, 0x6E, 0x61, 0x62, 0x6C, 0x65, 0x64, 0xA1, 0x61, 0x63, 0xA2, 0x64, 0x74, 0x79, + 0x70, 0x65, 0x00, 0x61, 0x76, 0xF5, 0x66, 0x70, 0x61, 0x72, 0x61, 0x6D, 0x73, 0xA1, 0x61, 0x64, + 0xA2, 0x67, 0x65, 0x6E, 0x61, 0x62, 0x6C, 0x65, 0x64, 0xA1, 0x61, 0x63, 0xA2, 0x64, 0x74, 0x79, + 0x70, 0x65, 0x00, 0x61, 0x76, 0xF5, 0x64, 0x77, 0x69, 0x66, 0x69, 0xA1, 0x61, 0x64, 0xA1, 0x67, + 0x65, 0x6E, 0x61, 0x62, 0x6C, 0x65, 0x64, 0xA1, 0x61, 0x63, 0xA2, 0x64, 0x74, 0x79, 0x70, 0x65, + 0x00, 0x61, 0x76, 0xF5 +}; + +/* test vec 2 */ +const uint8_t test_buf2[] = { + 0xA4, 0x63, 0x76, 0x65, 0x72, 0x63, 0x32, 0x2E, 0x30, 0x62, 0x74, 0x73, + 0x1B, 0x00, 0x05, 0xC5, 0x85, 0x48, 0x4E, 0xCF, 0x80, 0x66, 0x73, 0x68, + 0x61, 0x32, 0x35, 0x36, 0x70, 0x37, 0x63, 0x32, 0x65, 0x64, 0x62, 0x31, + 0x39, 0x34, 0x39, 0x36, 0x33, 0x39, 0x61, 0x37, 0x33, 0x66, 0x63, 0x6F, + 0x6E, 0x66, 0x69, 0x67, 0x82, 0xA2, 0x61, 0x6E, 0x83, 0x64, 0x68, 0x65, + 0x61, 0x70, 0x6A, 0x61, 0x6C, 0x6C, 0x6F, 0x63, 0x5F, 0x66, 0x61, 0x69, + 0x6C, 0x66, 0x65, 0x6E, 0x61, 0x62, 0x6C, 0x65, 0x61, 0x76, 0xF5, 0xA2, + 0x61, 0x6E, 0x82, 0x64, 0x77, 0x69, 0x66, 0x69, 0x66, 0x65, 0x6E, 0x61, + 0x62, 0x6C, 0x65, 0x61, 0x76, 0xF5, +}; + +esp_err_t esp_insights_test_cmd_handler() +{ + int encoded_sz = sizeof (test_buf2); + const uint8_t *test_buffer = test_buf2; + ESP_LOGI(TAG, "Performing commands decode on test_data0"); + void *resp_data = NULL; + size_t resp_len = 0; + esp_err_t ret = esp_insights_cmd_handler(test_buffer, encoded_sz, &resp_data, &resp_len, NULL, NULL); + ESP_LOGI(TAG, "response: %s", (char *) resp_data); + + ESP_LOGI(TAG, "Performing commands decode on test_data1"); + encoded_sz = sizeof (test_buf1); + test_buffer = test_buf1; + resp_data = NULL; + resp_len = 0; + ret = esp_insights_cmd_handler(test_buffer, encoded_sz, &resp_data, &resp_len, NULL, NULL); + ESP_LOGI(TAG, "response: %s", (char *) resp_data); + return ret; +} + +static void esp_insights_cmd_callback(const char *topic, void *payload, size_t payload_len, void *priv_data) +{ + void *output = NULL; + size_t output_len = 0; + /* Any command data received is directly sent to the command response framework and on success, + * the response (if any) is sent back to the MQTT Broker. + */ + if (esp_rmaker_cmd_response_handler(payload, payload_len, &output, &output_len) == ESP_OK) { + if (output) { + char publish_topic[100]; + snprintf(publish_topic, sizeof(publish_topic), "node/%s/%s", esp_insights_get_node_id(), FROM_NODE_TOPIC_SUFFIX); + if (esp_insights_mqtt_publish(publish_topic, output, output_len, RMAKER_MQTT_QOS1, NULL) != ESP_OK) { + ESP_LOGE(TAG, "Failed to publish reponse."); + } + free(output); + } else { + ESP_LOGE(TAG, "No output generated by command-response handler."); + } + } +} + +const char notify_cmd_resp_str[] = + "{\ + \"node_id\": \"%s\",\ + \"config_version\": \"2019-09-11\",\ + \"attributes\": [\ + {\ + \"name\": \"cmd-resp\",\ + \"value\": \"1\"\ + }\ + ],\ + }"; + +esp_err_t esp_insights_cmd_resp_init(void) +{ + esp_err_t err = ESP_FAIL; + if (s_cmd_resp_data.init_done) { + ESP_LOGI(TAG, "already initialized. Skipped"); + return ESP_OK; + } + + s_cmd_resp_data.scratch_buf = MEM_ALLOC_EXTRAM(SCRATCH_BUF_SIZE); + if (!s_cmd_resp_data.scratch_buf) { + ESP_LOGE(TAG, "Failed to allocate memory for scratch buffer."); + err = ESP_ERR_NO_MEM; + goto init_err; + } + + const int topic_size = 100; + char *mqtt_topic = (char *) s_cmd_resp_data.scratch_buf; + const char *node_id = esp_insights_get_node_id(); + if (!node_id) { + ESP_LOGE(TAG, "node_id not found. Bailing out..."); + goto init_err; + } + snprintf(mqtt_topic, topic_size, "node/%s/%s", node_id, TO_NODE_TOPIC_SUFFIX); + err = esp_insights_mqtt_subscribe(mqtt_topic, esp_insights_cmd_callback, RMAKER_MQTT_QOS1, NULL); + if(err != ESP_OK) { + ESP_LOGE(TAG, "Failed to subscribe to %s. Error %d", mqtt_topic, err); + goto init_err; + } + + /* Notify rmaker about our command response capability */ + char *publish_data = mqtt_topic + topic_size; + sprintf(publish_data, notify_cmd_resp_str, esp_insights_get_node_id()); + snprintf(mqtt_topic, topic_size, "node/%s/%s", esp_insights_get_node_id(), RMAKER_CFG_TOPIC_SUFFIX); + if (esp_insights_mqtt_publish(mqtt_topic, publish_data, strlen(publish_data), RMAKER_MQTT_QOS1, NULL) != ESP_OK) { + ESP_LOGE(TAG, "Failed to publish cmd-resp attrib"); + } + + s_cmd_resp_data.init_done = true; + ESP_LOGI(TAG, "Command-Response Module initialized"); + return ESP_OK; + +init_err: + if (s_cmd_resp_data.scratch_buf) { + free(s_cmd_resp_data.scratch_buf); + s_cmd_resp_data.scratch_buf = NULL; + } + return err; +} + +esp_err_t esp_insights_cmd_resp_enable(void) +{ + esp_err_t err = ESP_FAIL; + + if (s_cmd_resp_data.enabled == true) { + ESP_LOGI(TAG, "already enabled. Skipped"); + return ESP_OK; + } + + if (!s_cmd_resp_data.scratch_buf) { + s_cmd_resp_data.scratch_buf = MEM_ALLOC_EXTRAM(SCRATCH_BUF_SIZE); + } + if (!s_cmd_resp_data.scratch_buf) { + ESP_LOGE(TAG, "Failed to allocate memory for scratch buffer."); + err = ESP_ERR_NO_MEM; + goto enable_err; + } + + esp_insights_cbor_encoder_register_meta_cb(&esp_insights_cbor_reboot_msg_cb); + /* register `reboot` command to our commands store */ + esp_insights_cmd_resp_register_cmd(reboot_cmd_handler, NULL, 1, "reboot"); + + ESP_LOGI(TAG, "Enabling Command-Response Module."); + + /* Register our config parsing command to cmd_resp module */ + err = esp_rmaker_cmd_register(INSIGHTS_CONF_CMD, ESP_RMAKER_USER_ROLE_SUPER_ADMIN, + esp_insights_cmd_handler, false, NULL); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to register INSIGHTS_CONF_CMD"); + goto enable_err; + } + + s_cmd_resp_data.enabled = true; + return ESP_OK; + +enable_err: + if (s_cmd_resp_data.scratch_buf) { + free(s_cmd_resp_data.scratch_buf); + s_cmd_resp_data.scratch_buf = NULL; + } + s_cmd_resp_data.init_done = false; + return err; +} + +#else /* CONFIG_ESP_INSIGHTS_CMD_RESP_ENABLED */ +esp_err_t esp_insights_cmd_resp_init(void) +{ + return ESP_FAIL; +} + +esp_err_t esp_insights_cmd_resp_enable(void) { + ESP_LOGE(TAG, "Please enable CONFIG_ESP_INSIGHTS_CMD_RESP_ENABLED=y, line %d", __LINE__); + return ESP_FAIL; +} + +#endif /* CONFIG_ESP_INSIGHTS_CMD_RESP_ENABLED */ diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_insights/src/esp_insights_encoder.c b/RainMaker_Table-Lights/managed_components/espressif__esp_insights/src/esp_insights_encoder.c new file mode 100644 index 000000000..5d967d350 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_insights/src/esp_insights_encoder.c @@ -0,0 +1,217 @@ +/* + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#include "esp_insights_cbor_encoder.h" + +#if CONFIG_ESP_INSIGHTS_META_VERSION_10 +#define INSIGHTS_VERSION_MAJOR "1" +#else +#define INSIGHTS_VERSION_MAJOR "2" +#endif +#define INSIGHTS_VERSION_MINOR "0" +#define INSIGHTS_VERSION INSIGHTS_VERSION_MAJOR \ + "." INSIGHTS_VERSION_MINOR + +#if CONFIG_ESP_INSIGHTS_META_VERSION_10 +#define INSIGHTS_META_VERSION_MAJOR "1" +#else +#define INSIGHTS_META_VERSION_MAJOR "2" +#endif +#define INSIGHTS_META_VERSION_MINOR "0" + +#define INSIGHTS_META_VERSION INSIGHTS_META_VERSION_MAJOR \ + "." INSIGHTS_META_VERSION_MINOR + +#define INSIGHTS_DATA_TYPE 0x02 +#define INSIGHTS_META_DATA_TYPE 0x03 +#define INSIGHTS_CONF_DATA_TYPE 0x12 +#define TLV_OFFSET 3 + +static void esp_insights_encode_meta_data(void) +{ +#if CONFIG_DIAG_ENABLE_METRICS + uint32_t metrics_len = 0; + const esp_diag_metrics_meta_t *metrics = esp_diag_metrics_meta_get_all(&metrics_len); + if (!metrics) { + return; + } + esp_insights_cbor_encode_meta_metrics((const esp_diag_metrics_meta_t *)metrics, metrics_len); +#endif /* CONFIG_DIAG_ENABLE_METRICS */ + +#if CONFIG_DIAG_ENABLE_VARIABLES + uint32_t variables_len = 0; + const esp_diag_variable_meta_t *variables = esp_diag_variable_meta_get_all(&variables_len); + if (!variables) { + return; + } + esp_insights_cbor_encode_meta_variables((const esp_diag_variable_meta_t *)variables, variables_len); +#endif /* CONFIG_DIAG_ENABLE_VARIABLES */ +} + +size_t esp_insights_encode_meta(uint8_t *out_data, size_t out_data_size, char *sha256) +{ + if (!out_data || !out_data_size) { + return 0; + } + char sha[DIAG_HEX_SHA_SIZE + 1]; + bytes_to_hex((uint8_t *) sha256,(uint8_t *) sha, DIAG_SHA_SIZE); + esp_insights_cbor_encode_meta_begin(out_data + TLV_OFFSET, + out_data_size - TLV_OFFSET, + INSIGHTS_META_VERSION, sha); + esp_insights_cbor_encode_meta_data_begin(); + esp_insights_encode_meta_data(); + esp_insights_cbor_encode_meta_data_end(); + uint16_t len = esp_insights_cbor_encode_meta_end(out_data + TLV_OFFSET); + + out_data[0] = INSIGHTS_META_DATA_TYPE; /* Data type inidcation diagnostics meta - 1 byte */ + memcpy(&out_data[1], &len, sizeof(len)); /* Data length - 2 bytes */ + len += TLV_OFFSET; + return len; +} + +esp_err_t esp_insights_encode_data_begin(void *out_data, size_t out_data_size) +{ + if (!out_data || !out_data_size) { + return ESP_ERR_INVALID_ARG; + } + esp_insights_cbor_encode_diag_begin(out_data + TLV_OFFSET, out_data_size - TLV_OFFSET, INSIGHTS_VERSION); + esp_insights_cbor_encode_diag_data_begin(); + return ESP_OK; +} + +size_t esp_insights_encode_conf_meta(uint8_t *out_data, size_t out_data_size, char *sha256) +{ + if (!out_data || !out_data_size) { + return 0; + } + char sha[DIAG_HEX_SHA_SIZE + 1]; + bytes_to_hex((uint8_t *) sha256,(uint8_t *) sha, DIAG_SHA_SIZE); + esp_insights_cbor_encode_meta_begin(out_data + TLV_OFFSET, + out_data_size - TLV_OFFSET, + INSIGHTS_META_VERSION, sha); + esp_insights_cbor_encode_conf_meta_data_begin(); + /* TODO: Implement and collect diagnostics specific conf meta */ + // esp_insights_encode_conf_meta_data(); + esp_insights_cbor_encode_conf_meta_data_end(); + + uint16_t len = esp_insights_cbor_encode_meta_end(out_data + TLV_OFFSET); + + out_data[0] = INSIGHTS_META_DATA_TYPE; /* Data type inidcation diagnostics meta - 1 byte */ + memcpy(&out_data[1], &len, sizeof(len)); /* Data length - 2 bytes */ + len += TLV_OFFSET; + return len; +} + +void esp_insights_encode_boottime_data(void) +{ + /* encode device info */ + esp_diag_device_info_t device_info; + memset(&device_info, 0, sizeof(device_info)); + esp_diag_device_info_get(&device_info); + esp_insights_cbor_encode_diag_boot_info(&device_info); + + /* encode core dump summary */ +#if CONFIG_ESP_INSIGHTS_COREDUMP_ENABLE + const char *TAG = "Insights"; + esp_err_t err = esp_core_dump_image_check(); + if (err == ESP_OK) { + esp_core_dump_summary_t *summary = malloc(sizeof(esp_core_dump_summary_t)); + if (summary) { + memset(summary, 0, sizeof(esp_core_dump_summary_t)); + if (esp_core_dump_get_summary(summary) == ESP_OK) { + esp_insights_cbor_encode_diag_crash(summary); + } + free(summary); + } + } else if (err == ESP_ERR_INVALID_CRC) { + ESP_LOGE(TAG, "Core dump stored in flash is corrupted"); + } +#endif /* CONFIG_ESP_INSIGHTS_COREDUMP_ENABLE */ +} + +void esp_insights_encode_conf_data() +{ + /* collect the configs */ + esp_insights_cbor_encode_diag_conf_data_begin(); + esp_insights_cbor_encode_diag_conf_data(); + esp_insights_cbor_encode_diag_conf_data_end(); +} + + +size_t esp_insights_encode_conf_end(uint8_t *out_data) +{ + if (!out_data) { + return 0; + } + esp_insights_cbor_encode_diag_data_end(); + uint16_t len = esp_insights_cbor_encode_diag_end(out_data + TLV_OFFSET); + + out_data[0] = INSIGHTS_CONF_DATA_TYPE; /* Data type indicating diagnostics - 1 byte */ + memcpy(&out_data[1], &len, sizeof(len)); /* Data length - 2 bytes */ + len += TLV_OFFSET; + return len; +} + +size_t esp_insights_encode_critical_data(const void *data, size_t data_size) +{ + size_t consumed = 0; + if (data) { + consumed = esp_insights_cbor_encode_diag_logs(data, data_size); + if (consumed) { + uint8_t meta_idx = ((uint8_t *) data)[0]; + const rtc_store_meta_header_t *hdr = rtc_store_get_meta_record_by_index(meta_idx); + if (hdr) { + esp_insights_cbor_encode_meta_c_hdr(hdr); + } + } + } + return consumed; +} + +size_t esp_insights_encode_non_critical_data(const void *data, size_t data_size) +{ + size_t consumed_max = 0; + if (data) { +#if CONFIG_DIAG_ENABLE_METRICS + consumed_max = esp_insights_cbor_encode_diag_metrics(data, data_size); +#endif /* CONFIG_DIAG_ENABLE_METRICS */ +#if CONFIG_DIAG_ENABLE_VARIABLES + size_t consumed = esp_insights_cbor_encode_diag_variables(data, data_size); + if (consumed > consumed_max) { + consumed_max = consumed; + } +#endif /* CONFIG_DIAG_ENABLE_VARIABLES */ +#if CONFIG_DIAG_ENABLE_METRICS || CONFIG_DIAG_ENABLE_VARIABLES + if (consumed_max) { + uint8_t meta_idx = ((uint8_t *) data)[0]; + const rtc_store_meta_header_t *hdr = rtc_store_get_meta_record_by_index(meta_idx); + if (hdr) { + esp_insights_cbor_encode_meta_nc_hdr(hdr); + } + } +#endif + } + return consumed_max; +} + +size_t esp_insights_encode_data_end(uint8_t *out_data) +{ + if (!out_data) { + return 0; + } + esp_insights_cbor_encode_diag_data_end(); + uint16_t len = esp_insights_cbor_encode_diag_end(out_data + TLV_OFFSET); + + out_data[0] = INSIGHTS_DATA_TYPE; /* Data type indicating diagnostics - 1 byte */ + memcpy(&out_data[1], &len, sizeof(len)); /* Data length - 2 bytes */ + len += TLV_OFFSET; + return len; +} diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_insights/src/esp_insights_encoder.h b/RainMaker_Table-Lights/managed_components/espressif__esp_insights/src/esp_insights_encoder.h new file mode 100644 index 000000000..1f12cfe4f --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_insights/src/esp_insights_encoder.h @@ -0,0 +1,42 @@ +/* + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#if CONFIG_ESP_INSIGHTS_COREDUMP_ENABLE +#include +#endif + +size_t esp_insights_encode_meta(uint8_t *out_data, size_t out_data_size, char *sha256); +size_t esp_insights_encode_conf_meta(uint8_t *out_data, size_t out_data_size, char *sha256); +esp_err_t esp_insights_encode_data_begin(uint8_t *out_data, size_t out_data_size); +void esp_insights_encode_boottime_data(void); + +/** + * @brief encode critical data + * + * @param critical_data pointer to critical data + * @param critical_data_size size of critical data + * @return size_t length of data consumed + */ +size_t esp_insights_encode_critical_data(const void *critical_data, size_t critical_data_size); + +/** + * @brief encode non_critical data + * + * @param critical_data pointer to non_critical data + * @param critical_data_size size of non_critical data + * @return size_t length of data consumed + */ +size_t esp_insights_encode_non_critical_data(const void *non_critical_data, size_t non_critical_data_size); + +/** + * @brief finish encoding message + * + * @param out_data encoded data pointer + * @return size_t size of the data encoded + */ +size_t esp_insights_encode_data_end(uint8_t *out_data); diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_insights/src/esp_insights_internal.h b/RainMaker_Table-Lights/managed_components/espressif__esp_insights/src/esp_insights_internal.h new file mode 100644 index 000000000..7f1023245 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_insights/src/esp_insights_internal.h @@ -0,0 +1,63 @@ +/* + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include + +#ifdef CONFIG_ESP_INSIGHTS_TRANSPORT_MQTT +#include + +/* Default configurations for rmaker mqtt glue lib */ +extern esp_insights_transport_config_t g_default_insights_transport_mqtt; + +/* other functions for more granularity */ +esp_err_t esp_insights_mqtt_publish(const char *topic, void *data, size_t data_len, uint8_t qos, int *msg_id); +esp_err_t esp_insights_mqtt_subscribe(const char *topic, esp_rmaker_mqtt_subscribe_cb_t cb, uint8_t qos, void *priv_data); +#else +/* Default configurations for https */ +extern esp_insights_transport_config_t g_default_insights_transport_https; +#endif + +/** + * @brief Perform transport connect + * + * @return ESP_OK on success, otherwise appropriate error code + */ +esp_err_t esp_insights_transport_connect(void); + +/** + * @brief Perform transport disconnect + */ +void esp_insights_transport_disconnect(void); + +/** + * @brief Send data using the transport + * + * @paran[in] data Data to send + * @param[in] len Length of data + * + * @return msg_id Message_id of the sent data. + * On failure, -1 + * On success, 0 if data send happens synchronously. + * On success, message-id(positive integer) if data send happened asynchronously. + */ +int esp_insights_transport_data_send(void *data, size_t len); + +/** + * @brief Send update to the cloud about new state + */ +void esp_insights_report_config_update(void); + +/** + * @brief Get node id + * + * For MQTT transports if node id is present in factory partition then it is returned, + * otherwise mac address string is returned. + * + * @return node_id + */ +const char *esp_insights_get_node_id(void); diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_insights/src/esp_insights_transport.c b/RainMaker_Table-Lights/managed_components/espressif__esp_insights/src/esp_insights_transport.c new file mode 100644 index 000000000..4e0abe0a1 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_insights/src/esp_insights_transport.c @@ -0,0 +1,88 @@ +/* + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +static const char *TAG = "insights_transport"; + +typedef struct { + bool init; + esp_insights_transport_config_t config; +} priv_data_t; + +static priv_data_t s_priv_data; + +#define CHECK_TRANSPORT_INIT(ret) do { \ + if (!s_priv_data.init) { \ + ESP_LOGE(TAG, "Transport callbacks not registered"); \ + return ret; \ + } \ +} while (0) + +esp_err_t esp_insights_transport_register(esp_insights_transport_config_t *config) +{ + if (s_priv_data.init) { + ESP_LOGW(TAG, "Already initialized"); + return ESP_ERR_INVALID_STATE; + } + /* We at least need data_send callback */ + if (!(config && config->callbacks.data_send)) { + ESP_LOGE(TAG, "Failed to init transport, Please set at least data_send callback"); + return ESP_ERR_INVALID_ARG; + } + memcpy(&s_priv_data.config, config, sizeof(s_priv_data.config)); + s_priv_data.init = true; + + /* Call transport init */ + if (s_priv_data.config.callbacks.init) { + s_priv_data.config.callbacks.init(config->userdata); + } + return ESP_OK; +} + +void esp_insights_transport_unregister(void) +{ + if (!s_priv_data.init) { + ESP_LOGE(TAG, "Not initialized"); + return; + } + /* Call transport deinit */ + if (s_priv_data.config.callbacks.deinit) { + s_priv_data.config.callbacks.deinit(); + } + memset(&s_priv_data, 0, sizeof(s_priv_data)); +} + +esp_err_t esp_insights_transport_connect(void) +{ + CHECK_TRANSPORT_INIT(ESP_ERR_INVALID_STATE); + if (s_priv_data.config.callbacks.connect) { + return s_priv_data.config.callbacks.connect(); + } + ESP_LOGW(TAG, "connect callback not set"); + return ESP_OK; +} + +void esp_insights_transport_disconnect(void) +{ + CHECK_TRANSPORT_INIT(); + if (s_priv_data.config.callbacks.disconnect) { + return s_priv_data.config.callbacks.disconnect(); + } + ESP_LOGW(TAG, "disconnect callback not set"); +} + +int esp_insights_transport_data_send(void *data, size_t len) +{ + CHECK_TRANSPORT_INIT(-1); + if (s_priv_data.config.callbacks.data_send) { + return s_priv_data.config.callbacks.data_send(data, len); + } + ESP_LOGW(TAG, "data send callback not set"); + return -1; +} diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_insights/src/transport/esp_insights_https.c b/RainMaker_Table-Lights/managed_components/espressif__esp_insights/src/transport/esp_insights_https.c new file mode 100644 index 000000000..81f9e1e9e --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_insights/src/transport/esp_insights_https.c @@ -0,0 +1,158 @@ +// Copyright 2021 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. + +#include +#include +#include +#include +#include +#include +#include + +typedef struct { + const char *auth_key; + const char *node_id; + const char *url; +} https_data_t; + +static https_data_t s_https_data; + +static const char *TAG = "tport_https"; +#define HTTPS_URL_PATH "prod/node/data" + +extern const uint8_t insights_https_server_crt_start[] asm("_binary_https_server_crt_start"); +extern const uint8_t insights_https_server_crt_end[] asm("_binary_https_server_crt_end"); + +static esp_err_t esp_insights_https_init(void *userdata) +{ + if (sizeof(CONFIG_ESP_INSIGHTS_TRANSPORT_HTTPS_HOST) <= 1) { + ESP_LOGE(TAG, "Insights HTTPS host is missing"); + return ESP_ERR_INVALID_ARG; + } + s_https_data.url = CONFIG_ESP_INSIGHTS_TRANSPORT_HTTPS_HOST "/" HTTPS_URL_PATH; + /* In default https transport, auth_key is sent as userdata */ + s_https_data.auth_key = (const char *)userdata; + s_https_data.node_id = esp_insights_get_node_id(); + return ESP_OK; +} + +static void esp_insights_https_deinit(void) +{ + memset(&s_https_data, 0, sizeof(s_https_data)); +} + +static esp_err_t http_event_handle(esp_http_client_event_t *evt) +{ + switch(evt->event_id) { + case HTTP_EVENT_ERROR: + ESP_LOGD(TAG, "HTTP_EVENT_ERROR"); + break; + case HTTP_EVENT_ON_CONNECTED: + ESP_LOGD(TAG, "HTTP_EVENT_ON_CONNECTED"); + break; + case HTTP_EVENT_HEADER_SENT: + ESP_LOGD(TAG, "HTTP_EVENT_HEADER_SENT"); + break; + case HTTP_EVENT_ON_HEADER: + ESP_LOGD(TAG, "HTTP_EVENT_ON_HEADER %s:%s", evt->header_key, evt->header_value); + break; + case HTTP_EVENT_ON_DATA: + ESP_LOGD(TAG, "HTTP_EVENT_ON_DATA, len=%d", evt->data_len); + if (!esp_http_client_is_chunked_response(evt->client)) { + ESP_LOGD(TAG, "%.*s\n", evt->data_len, (char*)evt->data); + } + break; + case HTTP_EVENT_ON_FINISH: + ESP_LOGD(TAG, "HTTP_EVENT_ON_FINISH"); + break; + case HTTP_EVENT_DISCONNECTED: + ESP_LOGD(TAG, "HTTP_EVENT_DISCONNECTED"); + break; + default: + break; + } + return ESP_OK; +} + +static int esp_insights_https_data_send(void *data, size_t len) +{ + if (!data) { + return ESP_ERR_INVALID_ARG; + } + if (!s_https_data.auth_key) { + ESP_LOGE(TAG, "Transport not initialized"); + return ESP_ERR_INVALID_STATE; + } + + int msg_id = -1; + char url[256]; + memset(url, 0, sizeof(url)); + snprintf(url, sizeof(url), "%s?node_id=%s", s_https_data.url, s_https_data.node_id); + + esp_http_client_config_t client_config = { + .url = url, + .method = HTTP_METHOD_POST, + .transport_type = HTTP_TRANSPORT_OVER_SSL, + .buffer_size_tx = 1024, + .event_handler = http_event_handle, + .cert_pem = (const char *)insights_https_server_crt_start, + }; + esp_http_client_handle_t client = esp_http_client_init(&client_config); + if (!client) { + ESP_LOGE(TAG, "Failed to initialize esp_http_client"); + return msg_id; + } + esp_err_t err = esp_http_client_set_header(client, "Authorization", s_https_data.auth_key); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to set Authorization header err:0x%x", err); + goto cleanup; + } + err = esp_http_client_set_header(client, "Content-type", "application/octet-stream"); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to set content type err:0x%x", err); + goto cleanup; + } + err = esp_http_client_set_post_field(client, data, len); + if (err != ESP_OK) { + ESP_LOGE(TAG, "esp_http_client_set_post_field failed err:0x%x", err); + goto cleanup; + } + err = esp_http_client_perform(client); + if (err != ESP_OK) { + ESP_LOGE(TAG, "esp_http_client_perform failed err:0x%x", err); + } else { + int status = esp_http_client_get_status_code(client); + if (status == HttpStatus_Ok) { + msg_id = 0; + } else { + ESP_LOGE(TAG, "API response status = %d", status); + } + } + if (msg_id == 0) { + esp_event_post(INSIGHTS_EVENT, INSIGHTS_EVENT_TRANSPORT_SEND_SUCCESS, NULL, 0, portMAX_DELAY); + } else { + esp_event_post(INSIGHTS_EVENT, INSIGHTS_EVENT_TRANSPORT_SEND_FAILED, NULL, 0, portMAX_DELAY); + } +cleanup: + esp_http_client_cleanup(client); + return msg_id; +} + +esp_insights_transport_config_t g_default_insights_transport_https = { + .callbacks = { + .init = esp_insights_https_init, + .deinit = esp_insights_https_deinit, + .data_send = esp_insights_https_data_send, + } +}; diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_insights/src/transport/esp_insights_mqtt.c b/RainMaker_Table-Lights/managed_components/espressif__esp_insights/src/transport/esp_insights_mqtt.c new file mode 100644 index 000000000..6c78622f7 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_insights/src/transport/esp_insights_mqtt.c @@ -0,0 +1,201 @@ +// Copyright 2021 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. + +#include +#include +#include +#include +#include +#include +#include +#include + +static const char *TAG = "tport_mqtt"; + +#define INSIGHTS_TOPIC_SUFFIX "diagnostics/from-node" + +typedef struct { + const char *node_id; + esp_rmaker_mqtt_config_t mqtt_config; + esp_rmaker_mqtt_conn_params_t *conn_params; + bool connected; +} mqtt_data_t; + +static mqtt_data_t s_mqtt_data; + +static esp_rmaker_mqtt_conn_params_t *get_mqtt_conn_params(void) +{ + if (s_mqtt_data.mqtt_config.get_conn_params) { + return s_mqtt_data.mqtt_config.get_conn_params(); + } else { + return esp_insights_get_mqtt_conn_params(); + } +} + +static void clean_mqtt_conn_params(void) +{ + if (s_mqtt_data.conn_params) { + esp_insights_clean_mqtt_conn_params(s_mqtt_data.conn_params); + free(s_mqtt_data.conn_params); + s_mqtt_data.conn_params = NULL; + } +} + +static void rmaker_common_event_handler(void* arg, esp_event_base_t event_base, + int32_t event_id, void* event_data) +{ + if (event_base != RMAKER_COMMON_EVENT) { + return; + } + esp_insights_transport_event_data_t data; + switch(event_id) { + case RMAKER_MQTT_EVENT_DISCONNECTED: + s_mqtt_data.connected = false; + break; + case RMAKER_MQTT_EVENT_CONNECTED: + s_mqtt_data.connected = true; + break; + case RMAKER_MQTT_EVENT_PUBLISHED: + memset(&data, 0, sizeof(data)); + data.msg_id = *(int *)event_data; + esp_event_post(INSIGHTS_EVENT, INSIGHTS_EVENT_TRANSPORT_SEND_SUCCESS, &data, sizeof(data), portMAX_DELAY); + break; +#ifdef CONFIG_MQTT_REPORT_DELETED_MESSAGES + case RMAKER_MQTT_EVENT_MSG_DELETED: + memset(&data, 0, sizeof(data)); + data.msg_id = *(int *)event_data; + esp_event_post(INSIGHTS_EVENT, INSIGHTS_EVENT_TRANSPORT_SEND_FAILED, &data, sizeof(data), portMAX_DELAY); + break; +#endif /* CONFIG_MQTT_REPORT_DELETED_MESSAGES */ + default: + break; + } +} + +static esp_err_t esp_insights_mqtt_init(void *userdata) +{ + if (!s_mqtt_data.mqtt_config.setup_done) { + esp_rmaker_mqtt_glue_setup(&s_mqtt_data.mqtt_config); + } + esp_err_t err = esp_event_handler_register(RMAKER_COMMON_EVENT, ESP_EVENT_ANY_ID, rmaker_common_event_handler, NULL); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to register event handler for RMAKER_COMMON_EVENT"); + return err; + } + err = esp_rmaker_factory_init(); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to initialize factory partition"); + return err; + } + s_mqtt_data.conn_params = get_mqtt_conn_params(); + if (!s_mqtt_data.conn_params) { + ESP_LOGE(TAG, "Failed to get MQTT connection parameters."); + err = ESP_FAIL; + goto init_err; + } + s_mqtt_data.node_id = esp_insights_get_node_id(); + if (!s_mqtt_data.node_id) { + ESP_LOGE(TAG, "Failed to get node id"); + err = ESP_FAIL; + goto init_err; + } + if (!s_mqtt_data.mqtt_config.init) { + ESP_LOGW(TAG, "esp_insights_mqtt_init not registered"); + return ESP_OK; + } + err = s_mqtt_data.mqtt_config.init(s_mqtt_data.conn_params); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to initialize MQTT connection"); + goto init_err; + } + return ESP_OK; +init_err: + clean_mqtt_conn_params(); + esp_event_handler_unregister(RMAKER_COMMON_EVENT, ESP_EVENT_ANY_ID, rmaker_common_event_handler); + return err; +} + +static void esp_insights_mqtt_deinit(void) +{ + if (s_mqtt_data.mqtt_config.deinit) { + s_mqtt_data.mqtt_config.deinit(); + } + if (s_mqtt_data.node_id) { + s_mqtt_data.node_id = NULL; + } + clean_mqtt_conn_params(); + esp_event_handler_unregister(RMAKER_COMMON_EVENT, ESP_EVENT_ANY_ID, rmaker_common_event_handler); +} + +static esp_err_t esp_insights_mqtt_connect(void) +{ + if (s_mqtt_data.mqtt_config.connect) { + return s_mqtt_data.mqtt_config.connect(); + } + ESP_LOGW(TAG, "esp_insights_mqtt_connect not registered"); + return ESP_ERR_NOT_FOUND; +} + +static void esp_insights_mqtt_disconnect(void) +{ + if (s_mqtt_data.mqtt_config.disconnect) { + s_mqtt_data.mqtt_config.disconnect(); + } else { + ESP_LOGW(TAG, "esp_insights_mqtt_disconnect not registered"); + } +} + +esp_err_t esp_insights_mqtt_publish(const char *topic, void *data, size_t data_len, uint8_t qos, int *msg_id) +{ + if (s_mqtt_data.mqtt_config.publish) { + return s_mqtt_data.mqtt_config.publish(topic, data, data_len, qos, msg_id); + } + ESP_LOGW(TAG, "esp_insights_mqtt_publish not registered"); + return ESP_ERR_NOT_FOUND; +} + +esp_err_t esp_insights_mqtt_subscribe(const char *topic, esp_rmaker_mqtt_subscribe_cb_t cb, uint8_t qos, void *priv_data) +{ + if (s_mqtt_data.mqtt_config.subscribe) { + ESP_LOGI(TAG, "subscribing to %s", topic); + return s_mqtt_data.mqtt_config.subscribe(topic, cb, qos, priv_data); + } + ESP_LOGW(TAG, "esp_insights_mqtt_subscribe not registered"); + return ESP_OK; +} + +static int esp_insights_mqtt_data_send(void *data, size_t len) +{ + char topic[128]; + int msg_id = -1; + if (!data) { + return 0; + } + if (!s_mqtt_data.node_id) { + return -1; + } + snprintf(topic, sizeof(topic), "node/%s/%s", s_mqtt_data.node_id, INSIGHTS_TOPIC_SUFFIX); + esp_insights_mqtt_publish(topic, data, len, 1, &msg_id); + return msg_id; +} + +esp_insights_transport_config_t g_default_insights_transport_mqtt = { + .callbacks = { + .init = esp_insights_mqtt_init, + .deinit = esp_insights_mqtt_deinit, + .connect = esp_insights_mqtt_connect, + .disconnect = esp_insights_mqtt_disconnect, + .data_send = esp_insights_mqtt_data_send, + } +}; diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_rcp_update/.component_hash b/RainMaker_Table-Lights/managed_components/espressif__esp_rcp_update/.component_hash new file mode 100644 index 000000000..41d5bbd6b --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_rcp_update/.component_hash @@ -0,0 +1 @@ +0629efd75df671b132cc3b3d66e37267d12da63ea734f820280431e4d805ab0b \ No newline at end of file diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_rcp_update/CHECKSUMS.json b/RainMaker_Table-Lights/managed_components/espressif__esp_rcp_update/CHECKSUMS.json new file mode 100644 index 000000000..9fc00fcda --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_rcp_update/CHECKSUMS.json @@ -0,0 +1 @@ +{"version": "1.0", "algorithm": "sha256", "created_at": "2025-05-21T16:59:20.876878+00:00", "files": [{"path": "CMakeLists.txt", "size": 1173, "hash": "4c0898e4897412abc6833081d94158c57c980882f03845427548e59e0d545c5f"}, {"path": "LICENSE", "size": 11358, "hash": "cfc7749b96f63bd31c3c42b5c471bf756814053e847c10f3eb003417bc523d30"}, {"path": "idf_component.yml", "size": 443, "hash": "992e11cd00c0046d8b9d94eed38a2a8d84fc128d71ece31a30923c9e679d197c"}, {"path": "Kconfig", "size": 1066, "hash": "0952686c100f7c8ba7d7b4f7854fc1d9a98b924c86178694bb33415d53e0f714"}, {"path": "create_ota_image.py", "size": 3591, "hash": "4e9eb7bbd13fe10daad30f33ff009665e0a83dd8b1c94813d5be0a77437ab691"}, {"path": "include/esp_rcp_update.h", "size": 4118, "hash": "6754270d95281b64fb089e076249baaa3e6ee40b66bb1aa9275d3ef60c5507b5"}, {"path": "include/esp_rcp_ota.h", "size": 2904, "hash": "5197cf63da01d833b6884b6b2b097f9f33907d40db16c71f1c7fe8ff8c8b63b5"}, {"path": "include/esp_rcp_firmware.h", "size": 735, "hash": "976bea2dfccb706f8c425b57ff490fbe900610d914eccd8b67ef23517e224a75"}, {"path": "src/esp_rcp_update.c", "size": 11289, "hash": "b0acc1f10cad3c743deea316fe3982c21cbc79e7ddec99a553722c1aab073ee3"}, {"path": "src/esp_rcp_ota.c", "size": 11292, "hash": "17da7bdcb4d793d2d5eea3cc22c860dec47d0c9a83d0fbe14757927bba2fd292"}]} \ No newline at end of file diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_rcp_update/CMakeLists.txt b/RainMaker_Table-Lights/managed_components/espressif__esp_rcp_update/CMakeLists.txt new file mode 100644 index 000000000..0777cf0ad --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_rcp_update/CMakeLists.txt @@ -0,0 +1,28 @@ +idf_component_register(SRC_DIRS src + INCLUDE_DIRS include + REQUIRES driver esp-serial-flasher nvs_flash) + +idf_build_get_property(python PYTHON) +if(CONFIG_AUTO_UPDATE_RCP) +add_custom_target(rcp_image_generation ALL + COMMAND ${python} ${CMAKE_CURRENT_SOURCE_DIR}/create_ota_image.py + --rcp-build-dir ${CONFIG_RCP_SRC_DIR} + --target-file ${CMAKE_CURRENT_BINARY_DIR}/spiffs_image/ot_rcp_0/rcp_image + ) + +spiffs_create_partition_image(${CONFIG_RCP_PARTITION_NAME} ${CMAKE_CURRENT_BINARY_DIR}/spiffs_image FLASH_IN_PROJECT + DEPENDS rcp_image_generation) +endif() + +if(CONFIG_CREATE_OTA_IMAGE_WITH_RCP_FW) + add_custom_command(OUTPUT ${build_dir}/ota_with_rcp_image + COMMAND ${python} ${CMAKE_CURRENT_SOURCE_DIR}/create_ota_image.py + --rcp-build-dir ${CONFIG_RCP_SRC_DIR} + --target-file ${build_dir}/ota_with_rcp_image + --br-firmware "${build_dir}/${elf_name}.bin" + DEPENDS "${build_dir}/.bin_timestamp" + ) + + add_custom_target(gen_ota_image ALL DEPENDS ${build_dir}/ota_with_rcp_image) + add_dependencies(gen_ota_image gen_project_binary) +endif() diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_rcp_update/Kconfig b/RainMaker_Table-Lights/managed_components/espressif__esp_rcp_update/Kconfig new file mode 100644 index 000000000..68f6224a7 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_rcp_update/Kconfig @@ -0,0 +1,31 @@ +menu "OpenThread RCP Update" + + config AUTO_UPDATE_RCP + bool 'Update RCP automatically' + default n + help + If enabled, the device will store the RCP image in its firmware and + compare the stored image version with the running RCP image upon boot. The RCP + will be automatically updated upon version mismatch. + + config CREATE_OTA_IMAGE_WITH_RCP_FW + bool 'Create the OTA image with rcp for border router' + default n + help + If enabled, an ota image will be generated during building. + + config RCP_SRC_DIR + depends on AUTO_UPDATE_RCP || CREATE_OTA_IMAGE_WITH_RCP_FW + string "Source folder containing the RCP firmware" + default "$ENV{IDF_PATH}/examples/openthread/ot_rcp/build" + help + The source folder containing the RCP firmware. + + config RCP_PARTITION_NAME + depends on AUTO_UPDATE_RCP + string "Name of RCP storage partition" + default "rcp_fw" + help + The name of RCP storage partition. + +endmenu diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_rcp_update/LICENSE b/RainMaker_Table-Lights/managed_components/espressif__esp_rcp_update/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_rcp_update/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_rcp_update/create_ota_image.py b/RainMaker_Table-Lights/managed_components/espressif__esp_rcp_update/create_ota_image.py new file mode 100644 index 000000000..cc6d1110d --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_rcp_update/create_ota_image.py @@ -0,0 +1,94 @@ +#!/usr/bin/env python3 + +import os +import sys +import argparse +import pathlib +import shutil +import struct + +FILETAG_RCP_VERSION = 0 +FILETAG_RCP_FLASH_ARGS = 1 +FILETAG_RCP_BOOTLOADER = 2 +FILETAG_RCP_PARTITION_TABLE = 3 +FILETAG_RCP_FIRMWARE = 4 +FILETAG_BR_OTA_IMAGE = 5 +FILETAG_IMAGE_HEADER = 0xff + +HEADER_ENTRY_SIZE = 3 * 4 +RCP_IMAGE_HEADER_SIZE = HEADER_ENTRY_SIZE * 6 +RCP_FLASH_ARGS_SIZE = 2 * 4 * 3 + + +def append_subfile_header(fout, tag, size, offset): + fout.write(struct.pack(' 0: + fout.write(data) + data = fin.read(buf_size) + + +def append_flash_args(fout, flash_args_path): + with open(flash_args_path, 'r') as f: + # skip first line + next(f) + partition_info_list = [l.split() for l in f] + for offset, partition_file in partition_info_list: + offset = int(offset, 0) + if partition_file.find('bootloader') >= 0: + fout.write(struct.pack('= 0: + fout.write(struct.pack('=5.0' +description: Espressif RCP Update Component for Thread Border Router and Zigbee Gateway +repository: git://github.com/espressif/esp-thread-br.git +repository_info: + commit_sha: a5ed23e1a1abc8973c5f5c629de4cde44aef5b7c + path: components/esp_rcp_update +url: https://github.com/espressif/esp-thread-br/tree/main/components/esp_rcp_update +version: 1.4.0 diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_rcp_update/include/esp_rcp_firmware.h b/RainMaker_Table-Lights/managed_components/espressif__esp_rcp_update/include/esp_rcp_firmware.h new file mode 100644 index 000000000..441d74c6c --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_rcp_update/include/esp_rcp_firmware.h @@ -0,0 +1,38 @@ +/* + * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define MAX_SUBFILE_INFO 7 + +typedef enum { + FILETAG_RCP_VERSION = 0, + FILETAG_RCP_FLASH_ARGS = 1, + FILETAG_RCP_BOOTLOADER = 2, + FILETAG_RCP_PARTITION_TABLE = 3, + FILETAG_RCP_FIRMWARE = 4, + FILETAG_HOST_FIRMWARE = 5, + FILETAG_IMAGE_HEADER = 0xff, +} esp_rcp_filetag_t; + +struct esp_rcp_subfile_info { + uint32_t tag; + uint32_t size; + uint32_t offset; +} __attribute__((packed)); + +typedef struct esp_rcp_subfile_info esp_rcp_subfile_info_t; + +#define ESP_RCP_IMAGE_FILENAME "rcp_image" + +#ifdef __cplusplus +} +#endif diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_rcp_update/include/esp_rcp_ota.h b/RainMaker_Table-Lights/managed_components/espressif__esp_rcp_update/include/esp_rcp_ota.h new file mode 100644 index 000000000..0c484d4a4 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_rcp_update/include/esp_rcp_ota.h @@ -0,0 +1,100 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + ESP_RCP_OTA_STATE_READ_HEADER = 0, /* State of reading image header */ + ESP_RCP_OTA_STATE_DOWNLOAD_RCP_FW, /* State of writing RCP firmware */ + ESP_RCP_OTA_STATE_FINISHED, /* State of finishing RCP firmwares writing */ + ESP_RCP_OTA_STATE_INVALID, /* Invalid state */ +} esp_rcp_ota_state_t; + +/* RCP OTA handle */ +typedef uint32_t esp_rcp_ota_handle_t; + +/** + * @brief Initialize a handle of RCP OTA + * + * @param[out] out_handle On success, returns a handle which should be used for subsequent esp_rcp_ota_receive() + * and esp_rcp_ota_end() calls. + * + * @return ESP_OK on success. + * @return error in case of failure. + */ +esp_err_t esp_rcp_ota_begin(esp_rcp_ota_handle_t *out_handle); + +/** + * @brief Get state of RCP OTA + * + * @param[in] handle Handle of RCP OTA + * + * @return state of RCP OTA + */ +esp_rcp_ota_state_t esp_rcp_ota_get_state(esp_rcp_ota_handle_t handle); + +/** + * @brief Get subfile size from the parsed RCP image header + * + * This function must be called after the RCP OTA handle finishes the state of ESP_RCP_OTA_STATE_READ_HEADER + * + * @param[in] handle Handle of RCP OTA + * @param[in] filetag Tag of the subfile + * + * @return size of the subfile in the RCP image + */ +uint32_t esp_rcp_ota_get_subfile_size(esp_rcp_ota_handle_t handle, esp_rcp_filetag_t filetag); + +/** + * @brief Receive RCP OTA data + * + * This function should be called multiple times as data is received during the OTA operation. + * Data should be read sequentially from the image file generated by esp_rcp_update/create_ota_image.py. + * + * @param[in] handle Handle of RCP OTA + * @param[in] data Data buffer received + * @param[in] size Size of data buffer in bytes. + * @param[out] received_size Received size from the data buffer. + * + * @return ESP_OK on success. + * @return error in case of failure. + */ +esp_err_t esp_rcp_ota_receive(esp_rcp_ota_handle_t handle, const void *data, size_t size, size_t *received_size); + +/** + * @brief Finish RCP OTA update, validate and apply newly updated image. + * + * @note After calling esp_rcp_ota_end(), the handle is no longer valid and any memory associated with + * it is freed (regardless of result). + * + * @param[in] handle Handle of RCP OTA + * + * @return ESP_OK on success. + * @return error in case of failure. + */ +esp_err_t esp_rcp_ota_end(esp_rcp_ota_handle_t handle); + +/** + * @brief Abort RCP OTA update, free the handle and memory associated with it. + * + * @param[in] handle Handle of RCP OTA + * + * @return ESP_OK on success. + * @return error in case of failure. + */ +esp_err_t esp_rcp_ota_abort(esp_rcp_ota_handle_t handle); + +#ifdef __cplusplus +} +#endif diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_rcp_update/include/esp_rcp_update.h b/RainMaker_Table-Lights/managed_components/espressif__esp_rcp_update/include/esp_rcp_update.h new file mode 100644 index 000000000..6fb8254af --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_rcp_update/include/esp_rcp_update.h @@ -0,0 +1,156 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "esp_loader.h" +#include "nvs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define RCP_FIRMWARE_DIR_SIZE 20 +#define RCP_FILENAME_MAX_SIZE 100 +#define RCP_URL_MAX_SIZE 100 + +typedef enum { + RCP_TYPE_INVALID = 0, /* Invalid type */ + RCP_TYPE_UART = 1, /* Connected via UART */ + RCP_TYPE_MAX = 2, /* Max type */ +} esp_rcp_type_t; + +/* For compatibility, will be removed in the next major update. */ +#define RCP_TYPE_ESP32H2_UART \ + _Pragma("GCC warning \"'RCP_TYPE_ESP32H2_UART' enum is deprecated, use 'RCP_TYPE_UART' instead\"") RCP_TYPE_UART + +/** + * @brief The RCP update config for OpenThread. + * + */ +typedef struct { + esp_rcp_type_t rcp_type; /*!< RCP type */ + int uart_rx_pin; /*!< UART rx pin */ + int uart_tx_pin; /*!< UART tx pin */ + int uart_port; /*!< UART port */ + int uart_baudrate; /*!< UART baudrate */ + int reset_pin; /*!< RESET pin */ + int boot_pin; /*!< Boot mode select pin */ + uint32_t update_baudrate; /*!< Baudrate when flashing the firmware */ + char firmware_dir[RCP_FIRMWARE_DIR_SIZE]; /*!< The directory storing the RCP firmware */ + target_chip_t target_chip; /*!< The target chip type */ +} esp_rcp_update_config_t; + +/** + * @brief This function initializes the RCP update process + * + * @param[in] update_config The RCP update specific config + * + * @return + * - ESP_OK + * - ESP_FAIL + * - ESP_ERR_INVALID_ARG If the RCP type is not supported. + * + */ +esp_err_t esp_rcp_update_init(const esp_rcp_update_config_t *update_config); + +/** + * @brief This function triggers an RCP firmware update. + * + * @return + * - ESP_OK + * - ESP_FAIL + * - ESP_ERR_INVALID_STASTE If the RCP update is not initialized. + * - ESP_ERR_NOT_FOUND RCP firmware not found in storage. + * + */ +esp_err_t esp_rcp_update(void); + +/** + * @brief This function acquires the RCP image base directory. + * + * @note The real RCP image directory should be suffixed the update sequence. + * + */ +const char *esp_rcp_get_firmware_dir(void); + +/** + * @brief This function retrieves the update image sequence. + * + * The current update image sequence will be used to update the RCP. + * + */ +int8_t esp_rcp_get_update_seq(void); + +/** + * @brief This function retrieves the next update image sequence. + * + * The next update image sequence will be used for the downloaded image. + * + */ +int8_t esp_rcp_get_next_update_seq(void); + +/** + * @brief This function resets the RCP. + * + */ +void esp_rcp_reset(void); + +/** + * @brief This function marks the downloaded image as valid. + * + * The image in the next update image sequence will then be used for RCP update. + * + * @return + * - ESP_OK + * - ESP_ERR_INVALID_STASTE If the RCP update is not initialized. + * + */ +esp_err_t esp_rcp_submit_new_image(void); + +/** + * @brief This function marks previously downloaded image as valid. + * + * @return + * - ESP_OK + * - ESP_ERR_INVALID_STASTE If the RCP update is not initialized. + * + */ +esp_err_t esp_rcp_mark_image_verified(bool verified); + +/** + * @brief This function marks previously downloaded image as unusable. + * + * @return + * - ESP_OK + * - ESP_ERR_INVALID_STASTE If the RCP update is not initialized. + * + */ +esp_err_t esp_rcp_mark_image_unusable(void); + +/** + * @brief This function loads the RCP version in the current update image. + * + * @param[out] version_str The RCP version string output. + * @param[in] size Size of version_str. + * + * @return + * - ESP_OK + * - ESP_ERR_INVALID_STASTE If the RCP update is not initialized. + * - ESP_ERR_NOT_FOUND RCP version not found in update image. + * + */ +esp_err_t esp_rcp_load_version_in_storage(char *version_str, size_t size); + +/** + * @brief This function deinitializes the RCP update process. + * + */ +void esp_rcp_update_deinit(void); + +#ifdef __cplusplus +} +#endif diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_rcp_update/src/esp_rcp_ota.c b/RainMaker_Table-Lights/managed_components/espressif__esp_rcp_update/src/esp_rcp_ota.c new file mode 100644 index 000000000..75b88db18 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_rcp_update/src/esp_rcp_ota.c @@ -0,0 +1,291 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define IMAGE_HEADER_MAX_LEN sizeof(esp_rcp_subfile_info_t) * MAX_SUBFILE_INFO +#define OTA_MAX_WRITE_SIZE 16 + +typedef struct rcp_ota_entry_ { + esp_rcp_ota_handle_t handle; + esp_rcp_ota_state_t state; + uint32_t header_size; + uint32_t header_read; + uint8_t image_header_buffer[IMAGE_HEADER_MAX_LEN]; + uint32_t rcp_firmware_size; + uint32_t rcp_firmware_downloaded; + FILE *rcp_fp; + LIST_ENTRY(rcp_ota_entry_) entries; +} rcp_ota_entry_t; + +static LIST_HEAD(rcp_ota_entries_head, + rcp_ota_entry_) s_rcp_ota_entries_head = LIST_HEAD_INITIALIZER(s_rcp_ota_entries_head); + +static esp_rcp_ota_handle_t s_ota_last_handle = 0; + +const static char *TAG = "esp_rcp_ota"; + +esp_err_t esp_rcp_ota_begin(esp_rcp_ota_handle_t *out_handle) +{ + rcp_ota_entry_t *new_entry = NULL; + ESP_RETURN_ON_FALSE(out_handle, ESP_ERR_INVALID_ARG, TAG, "out_handle cannot be NULL"); + + new_entry = (rcp_ota_entry_t *)calloc(1, sizeof(rcp_ota_entry_t)); + ESP_RETURN_ON_FALSE(new_entry, ESP_ERR_NO_MEM, TAG, "Failed to allocate memory for RCP OTA handle"); + LIST_INSERT_HEAD(&s_rcp_ota_entries_head, new_entry, entries); + + new_entry->state = ESP_RCP_OTA_STATE_READ_HEADER; + new_entry->header_size = 0; + new_entry->header_read = 0; + new_entry->rcp_firmware_size = 0; + new_entry->rcp_firmware_downloaded = 0; + new_entry->rcp_fp = NULL; + memset(new_entry->image_header_buffer, 0, sizeof(new_entry->image_header_buffer)); + new_entry->handle = ++s_ota_last_handle; + *out_handle = new_entry->handle; + return ESP_OK; +} + +static rcp_ota_entry_t *find_esp_rcp_ota_entry(esp_rcp_ota_handle_t handle) +{ + rcp_ota_entry_t *ret = NULL; + for (ret = LIST_FIRST(&s_rcp_ota_entries_head); ret != NULL; ret = LIST_NEXT(ret, entries)) { + if (ret->handle == handle) { + return ret; + } + } + return NULL; +} + +esp_rcp_ota_state_t esp_rcp_ota_get_state(esp_rcp_ota_handle_t handle) +{ + rcp_ota_entry_t *entry = find_esp_rcp_ota_entry(handle); + return entry ? entry->state : ESP_RCP_OTA_STATE_INVALID; +} + +uint32_t esp_rcp_ota_get_subfile_size(esp_rcp_ota_handle_t handle, esp_rcp_filetag_t tag) +{ + rcp_ota_entry_t *entry = find_esp_rcp_ota_entry(handle); + if (!entry || entry->header_size % sizeof(esp_rcp_subfile_info_t) != 0) { + return 0; + } + size_t subfile_info_num = entry->header_size / sizeof(esp_rcp_subfile_info_t); + for (size_t i = 0; i < subfile_info_num; ++i) { + esp_rcp_subfile_info_t *subfile_info = + (esp_rcp_subfile_info_t *)(&entry->image_header_buffer[i * sizeof(esp_rcp_subfile_info_t)]); + if (subfile_info->tag == tag) { + return subfile_info->size; + } + } + return 0; +} + +static void parse_image_header(rcp_ota_entry_t *entry) +{ + size_t subfile_info_num = entry->header_size / sizeof(esp_rcp_subfile_info_t); + for (size_t i = 0; i < subfile_info_num; ++i) { + esp_rcp_subfile_info_t *subfile_info = + (esp_rcp_subfile_info_t *)(&entry->image_header_buffer[i * sizeof(esp_rcp_subfile_info_t)]); + if (subfile_info->tag == FILETAG_IMAGE_HEADER || subfile_info->tag == FILETAG_RCP_VERSION || + subfile_info->tag == FILETAG_RCP_BOOTLOADER || subfile_info->tag == FILETAG_RCP_FLASH_ARGS || + subfile_info->tag == FILETAG_RCP_PARTITION_TABLE || subfile_info->tag == FILETAG_RCP_FIRMWARE) { + entry->rcp_firmware_size += subfile_info->size; + } + } +} + +static int write_file_for_length(FILE *fp, const void *buf, size_t size) +{ + static const int k_max_retry = 5; + int retry_count = 0; + int offset = 0; + const uint8_t *data = (const uint8_t *)buf; + while (offset < size) { + int ret = + fwrite(data + offset, 1, ((size - offset) < OTA_MAX_WRITE_SIZE ? (size - offset) : OTA_MAX_WRITE_SIZE), fp); + if (ret < 0) { + return ret; + } + if (ret == 0) { + retry_count++; + } else { + offset += ret; + retry_count = 0; + } + if (retry_count > k_max_retry) { + return -1; + } + } + return size; +} + +static esp_err_t receive_header(const uint8_t *data, size_t size, rcp_ota_entry_t *entry, size_t *consumed_size) +{ + if (entry->header_size == 0) { + if (entry->header_read < sizeof(esp_rcp_subfile_info_t)) { + size_t copy_size = size > sizeof(esp_rcp_subfile_info_t) - entry->header_read + ? sizeof(esp_rcp_subfile_info_t) - entry->header_read + : size; + memcpy(entry->image_header_buffer + entry->header_read, data, copy_size); + data = data + copy_size; + size -= copy_size; + entry->header_read += copy_size; + *consumed_size += copy_size; + } + if (entry->header_read >= sizeof(esp_rcp_subfile_info_t)) { + esp_rcp_subfile_info_t *subfile_info = (esp_rcp_subfile_info_t *)(entry->image_header_buffer); + if (subfile_info->tag != FILETAG_IMAGE_HEADER || subfile_info->offset != 0 || + subfile_info->size % sizeof(esp_rcp_subfile_info_t) != 0) { + ESP_LOGE(TAG, "Invalid image header"); + return ESP_ERR_INVALID_ARG; + } else { + entry->header_size = subfile_info->size; + } + } + } + + if (entry->header_size > 0 && entry->header_read < entry->header_size) { + size_t copy_size = + size > entry->header_size - entry->header_read ? entry->header_size - entry->header_read : size; + memcpy(entry->image_header_buffer + entry->header_read, data, copy_size); + data += copy_size; + size -= copy_size; + entry->header_read += copy_size; + *consumed_size += copy_size; + } + if (entry->header_size > 0 && entry->header_read >= entry->header_size) { + parse_image_header(entry); + if (entry->rcp_firmware_size > 0) { + entry->state = ESP_RCP_OTA_STATE_DOWNLOAD_RCP_FW; + } else { + entry->state = ESP_RCP_OTA_STATE_FINISHED; + } + } + return ESP_OK; +} + +static esp_err_t receive_rcp_fw(const uint8_t *data, size_t size, rcp_ota_entry_t *entry, size_t *consumed_size) +{ + if (entry->rcp_firmware_size == 0 || entry->rcp_firmware_size <= entry->rcp_firmware_downloaded) { + return ESP_ERR_INVALID_STATE; + } + if (!entry->rcp_fp) { + const char *rcp_firmware_dir = esp_rcp_get_firmware_dir(); + int8_t rcp_update_seq = esp_rcp_get_next_update_seq(); + char rcp_target_path[RCP_FILENAME_MAX_SIZE]; + sprintf(rcp_target_path, "%s_%d/" ESP_RCP_IMAGE_FILENAME, rcp_firmware_dir, rcp_update_seq); + entry->rcp_fp = fopen(rcp_target_path, "w"); + if (!entry->rcp_fp) { + ESP_LOGE(TAG, "Fail to open %s, will delete it and create a new one", rcp_target_path); + remove(rcp_target_path); + entry->rcp_fp = fopen(rcp_target_path, "w"); + } + ESP_RETURN_ON_FALSE(entry->rcp_fp, ESP_FAIL, TAG, "Fail to open %s", rcp_target_path); + ESP_LOGI(TAG, "Start downloading the rcp firmware"); + } + if (entry->rcp_firmware_downloaded == 0) { + ESP_RETURN_ON_FALSE(write_file_for_length(entry->rcp_fp, entry->image_header_buffer, entry->header_size) == + entry->header_size, + ESP_FAIL, TAG, "Failed to write data"); + entry->rcp_firmware_downloaded += entry->header_size; + ESP_LOGD(TAG, "RCP firmware download %ld/%ld", entry->rcp_firmware_downloaded, entry->rcp_firmware_size); + } + if (entry->rcp_firmware_downloaded < entry->rcp_firmware_size && + entry->rcp_firmware_downloaded >= entry->header_size) { + size_t copy_size = size > entry->rcp_firmware_size - entry->rcp_firmware_downloaded + ? entry->rcp_firmware_size - entry->rcp_firmware_downloaded + : size; + ESP_RETURN_ON_FALSE(write_file_for_length(entry->rcp_fp, data, copy_size) == copy_size, ESP_FAIL, TAG, + "Failed to write data"); + entry->rcp_firmware_downloaded += copy_size; + *consumed_size += copy_size; + ESP_LOGD(TAG, "RCP firmware download %ld/%ld", entry->rcp_firmware_downloaded, entry->rcp_firmware_size); + } + if (entry->rcp_firmware_downloaded >= entry->rcp_firmware_size) { + if (entry->rcp_fp != NULL) { + fclose(entry->rcp_fp); + entry->rcp_fp = NULL; + } + entry->state = ESP_RCP_OTA_STATE_FINISHED; + } + return ESP_OK; +} + +esp_err_t esp_rcp_ota_receive(esp_rcp_ota_handle_t handle, const void *data, size_t size, size_t *received_size) +{ + rcp_ota_entry_t *entry = find_esp_rcp_ota_entry(handle); + ESP_RETURN_ON_FALSE(entry, ESP_ERR_NOT_FOUND, TAG, "Invalid rcp_ota handle"); + ESP_RETURN_ON_FALSE(data && size != 0, ESP_ERR_INVALID_ARG, TAG, "Invalid data received"); + const uint8_t *cur_data = data; + *received_size = 0; + + while (size > 0) { + size_t consumed_size = 0; + switch (entry->state) { + case ESP_RCP_OTA_STATE_READ_HEADER: { + ESP_RETURN_ON_ERROR(receive_header(cur_data, size, entry, &consumed_size), TAG, "Failed to receive header"); + break; + } + case ESP_RCP_OTA_STATE_DOWNLOAD_RCP_FW: { + ESP_RETURN_ON_ERROR(receive_rcp_fw(cur_data, size, entry, &consumed_size), TAG, "Failed to receive rcp_fw"); + break; + } + case ESP_RCP_OTA_STATE_FINISHED: + break; + default: + ESP_LOGE(TAG, "Invalid state of Border Router OTA"); + return ESP_ERR_INVALID_STATE; + break; + } + cur_data += consumed_size; + size -= consumed_size; + *received_size = cur_data - (const uint8_t *)data; + if (entry->state == ESP_RCP_OTA_STATE_FINISHED) { + break; + } + } + return ESP_OK; +} + +esp_err_t esp_rcp_ota_end(esp_rcp_ota_handle_t handle) +{ + esp_err_t ret = ESP_OK; + rcp_ota_entry_t *entry = find_esp_rcp_ota_entry(handle); + ESP_RETURN_ON_FALSE(entry, ESP_ERR_NOT_FOUND, TAG, "Invalid rcp_ota handle"); + ESP_GOTO_ON_FALSE(entry->state == ESP_RCP_OTA_STATE_FINISHED, ESP_ERR_INVALID_STATE, cleanup, TAG, "Invalid State"); + // TODO: esp_rcp_submit_new_image() is not a thread-safe function, we need to make it thread-safe. + ESP_GOTO_ON_ERROR(esp_rcp_submit_new_image(), cleanup, TAG, "Failed to submit RCP image"); +cleanup: + if (entry->rcp_fp != NULL) { + fclose(entry->rcp_fp); + } + LIST_REMOVE(entry, entries); + free(entry); + return ret; +} + +esp_err_t esp_rcp_ota_abort(esp_rcp_ota_handle_t handle) +{ + rcp_ota_entry_t *entry = find_esp_rcp_ota_entry(handle); + ESP_RETURN_ON_FALSE(entry, ESP_ERR_NOT_FOUND, TAG, "Invalid rcp_ota handle"); + + if (entry->rcp_fp != NULL) { + fclose(entry->rcp_fp); + } + LIST_REMOVE(entry, entries); + free(entry); + return ESP_OK; +} diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_rcp_update/src/esp_rcp_update.c b/RainMaker_Table-Lights/managed_components/espressif__esp_rcp_update/src/esp_rcp_update.c new file mode 100644 index 000000000..f042a3da9 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_rcp_update/src/esp_rcp_update.c @@ -0,0 +1,343 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "esp_rcp_update.h" + +#include +#include +#include + +#include "esp32_port.h" +#include "esp_check.h" +#include "esp_err.h" +#include "esp_loader.h" +#include "esp_log.h" +#include "esp_rcp_firmware.h" +#include "nvs.h" +#include "nvs_flash.h" +#include "driver/gpio.h" +#include "driver/uart.h" + +#define RCP_UPDATE_MAX_RETRY 3 +#define RCP_VERIFIED_FLAG (1 << 5) +#define RCP_SEQ_KEY "rcp_seq" +#define TAG "RCP_UPDATE" + +typedef struct esp_rcp_update_handle { + nvs_handle_t nvs_handle; + int8_t update_seq; + bool verified; + esp_rcp_update_config_t update_config; +} esp_rcp_update_handle; + +struct rcp_flash_arg_t { + uint32_t tag; + uint32_t offset; +} __attribute__((packed)); + +typedef struct rcp_flash_arg_t rcp_flash_arg_t; + +static esp_rcp_update_handle s_handle; + +static esp_loader_error_t connect_to_target(target_chip_t target_chip, uint32_t higher_baudrate) +{ + esp_loader_connect_args_t connect_config = ESP_LOADER_CONNECT_DEFAULT(); + + esp_loader_error_t err = esp_loader_connect(&connect_config); + if (err != ESP_LOADER_SUCCESS) { + return err; + } + if (esp_loader_get_target() != target_chip) { + return ESP_LOADER_ERROR_UNSUPPORTED_CHIP; + } + + if (higher_baudrate) { + ESP_RETURN_ON_ERROR(esp_loader_change_transmission_rate(higher_baudrate), TAG, + "Failed to change bootloader baudrate"); + ESP_RETURN_ON_ERROR(loader_port_change_transmission_rate(higher_baudrate), TAG, + "Failed to change local port baudrate"); + } + return ESP_LOADER_SUCCESS; +} + +static esp_err_t seek_to_subfile(FILE *fp, esp_rcp_filetag_t tag, esp_rcp_subfile_info_t *found_info) +{ + if (fseek(fp, 0, SEEK_SET) != 0) { + return ESP_FAIL; + } + esp_rcp_subfile_info_t subfile_info; + if (fread(&subfile_info, 1, sizeof(subfile_info), fp) != sizeof(subfile_info)) { + return ESP_FAIL; + } + if (subfile_info.tag != FILETAG_IMAGE_HEADER || subfile_info.size % sizeof(subfile_info) != 0) { + return ESP_FAIL; + } + + int num_subfiles = subfile_info.size / sizeof(subfile_info); + for (int i = 1; i < num_subfiles; i++) { + if (fread(&subfile_info, 1, sizeof(subfile_info), fp) != sizeof(subfile_info)) { + return ESP_FAIL; + } + if (subfile_info.tag == tag) { + *found_info = subfile_info; + return fseek(fp, subfile_info.offset, SEEK_SET) == 0 ? ESP_OK : ESP_FAIL; + } + } + return ESP_ERR_NOT_FOUND; +} + +esp_err_t esp_rcp_load_version_in_storage(char *version_str, size_t size) +{ + char fullpath[RCP_FILENAME_MAX_SIZE]; + int8_t update_seq = esp_rcp_get_update_seq(); + + sprintf(fullpath, "%s_%d/" ESP_RCP_IMAGE_FILENAME, s_handle.update_config.firmware_dir, update_seq); + FILE *fp = fopen(fullpath, "r"); + if (fp == NULL) { + return ESP_ERR_NOT_FOUND; + } + esp_rcp_subfile_info_t version_info; + ESP_RETURN_ON_ERROR(seek_to_subfile(fp, FILETAG_RCP_VERSION, &version_info), TAG, "Failed to find version subfile"); + memset(version_str, 0, size); + int read_size = size < version_info.size ? size : version_info.size; + fread(version_str, 1, read_size, fp); + fclose(fp); + return ESP_OK; +} + +static esp_loader_error_t flash_binary(FILE *firmware, size_t size, size_t address) +{ + esp_loader_error_t err; + static uint8_t payload[1024]; + + ESP_LOGI(TAG, "Erasing flash (this may take a while)..."); + err = esp_loader_flash_start(address, size, sizeof(payload)); + if (err != ESP_LOADER_SUCCESS) { + ESP_LOGE(TAG, "Erasing flash failed with error %d.", err); + return err; + } + ESP_LOGI(TAG, "Start programming"); + + size_t binary_size = size; + size_t written = 0; + + ESP_LOGI(TAG, "binary_size %u", binary_size); + while (size > 0) { + size_t to_read = size < sizeof(payload) ? size : sizeof(payload); + fread(payload, 1, to_read, firmware); + + err = esp_loader_flash_write(payload, to_read); + if (err != ESP_LOADER_SUCCESS) { + ESP_LOGE(TAG, "Packet could not be written! Error %d.", err); + return err; + } + + size -= to_read; + written += to_read; + ESP_LOGI(TAG, "left size %u, written %u", size, written); + + int progress = (int)(((float)written / binary_size) * 100); + ESP_LOGI(TAG, "Progress: %d %%", progress); + fflush(stdout); + }; + + ESP_LOGI(TAG, "Finished programming"); + + err = esp_loader_flash_verify(); + if (err != ESP_LOADER_SUCCESS) { + ESP_LOGE(TAG, "MD5 does not match. err: %d", err); + return err; + } + ESP_LOGI(TAG, "Flash verified"); + + return ESP_LOADER_SUCCESS; +} + +static void load_rcp_update_seq(esp_rcp_update_handle *handle) +{ + int8_t seq = 0; + bool verified; + esp_err_t err = nvs_get_i8(handle->nvs_handle, RCP_SEQ_KEY, &seq); + + if (err != ESP_OK) { + seq = 0; + verified = 1; + } else { + verified = (seq & RCP_VERIFIED_FLAG); + seq = (seq & ~RCP_VERIFIED_FLAG); + } + handle->update_seq = seq; + handle->verified = verified; +} + +const char *esp_rcp_get_firmware_dir(void) +{ + return s_handle.update_config.firmware_dir; +} + +int8_t esp_rcp_get_update_seq(void) +{ + return s_handle.verified ? (s_handle.update_seq) : (1 - s_handle.update_seq); +} + +int8_t esp_rcp_get_next_update_seq(void) +{ + return 1 - esp_rcp_get_update_seq(); +} + +esp_err_t esp_rcp_submit_new_image() +{ + ESP_RETURN_ON_FALSE(s_handle.update_config.rcp_type != RCP_TYPE_INVALID, ESP_ERR_INVALID_STATE, TAG, + "RCP update not initialized"); + s_handle.update_seq = esp_rcp_get_next_update_seq(); + s_handle.verified = true; + + int8_t new_seq = s_handle.update_seq | RCP_VERIFIED_FLAG; + esp_err_t error = nvs_set_i8(s_handle.nvs_handle, RCP_SEQ_KEY, new_seq); + if (error == ESP_OK) { + return nvs_commit(s_handle.nvs_handle); + } else { + return error; + } +} + +esp_err_t esp_rcp_update_init(const esp_rcp_update_config_t *update_config) +{ + ESP_RETURN_ON_ERROR(nvs_open("storage", NVS_READWRITE, &s_handle.nvs_handle), "TAG", "Failed to open nvs"); + ESP_RETURN_ON_FALSE(update_config->rcp_type > RCP_TYPE_INVALID && update_config->rcp_type < RCP_TYPE_MAX, + ESP_ERR_INVALID_ARG, TAG, "Unsupported RCP type"); + + s_handle.update_config = *update_config; + load_rcp_update_seq(&s_handle); + ESP_LOGI(TAG, "RCP: using update sequence %d", s_handle.update_seq); + return ESP_OK; +} + +#if CONFIG_OPENTHREAD_RADIO_SPINEL_SPI +static esp_err_t esp_rcp_boot_pin_mux(void) +{ + gpio_config_t io_conf; + memset(&io_conf, 0, sizeof(io_conf)); + io_conf.intr_type = GPIO_INTR_NEGEDGE; + io_conf.pin_bit_mask = (1ULL << s_handle.update_config.boot_pin); + io_conf.mode = GPIO_MODE_INPUT; + io_conf.pull_up_en = GPIO_PULLUP_ENABLE; + ESP_RETURN_ON_ERROR(gpio_config(&io_conf), TAG, "Failed to config GPIO[%d]", s_handle.update_config.boot_pin); + return ESP_OK; +} +#endif + +esp_err_t esp_rcp_update(void) +{ + ESP_RETURN_ON_FALSE(s_handle.update_config.rcp_type != RCP_TYPE_INVALID, ESP_ERR_INVALID_STATE, TAG, + "RCP update not initialized"); + + loader_esp32_config_t loader_config = { + .baud_rate = s_handle.update_config.uart_baudrate, + .uart_port = s_handle.update_config.uart_port, + .uart_rx_pin = s_handle.update_config.uart_rx_pin, + .uart_tx_pin = s_handle.update_config.uart_tx_pin, + .reset_trigger_pin = s_handle.update_config.reset_pin, + .gpio0_trigger_pin = s_handle.update_config.boot_pin, + }; + ESP_RETURN_ON_ERROR(loader_port_esp32_init(&loader_config), TAG, "Failed to initialize UART port"); + ESP_RETURN_ON_ERROR(connect_to_target(s_handle.update_config.target_chip, s_handle.update_config.update_baudrate), + TAG, "Failed to connect to RCP"); + + char fullpath[RCP_FILENAME_MAX_SIZE]; + int update_seq = esp_rcp_get_update_seq(); + sprintf(fullpath, "%s_%d/" ESP_RCP_IMAGE_FILENAME, s_handle.update_config.firmware_dir, update_seq); + FILE *fp = fopen(fullpath, "r"); + ESP_RETURN_ON_FALSE(fp != NULL, ESP_ERR_NOT_FOUND, TAG, "Cannot find rcp image"); + esp_rcp_subfile_info_t subfile; + seek_to_subfile(fp, FILETAG_RCP_FLASH_ARGS, &subfile); + int num_flash_binaries = subfile.size / sizeof(rcp_flash_arg_t); + + for (int i = 0; i < num_flash_binaries; i++) { + rcp_flash_arg_t flash_args; + fread(&flash_args, 1, sizeof(flash_args), fp); + int num_retry = 0; + long current = ftell(fp); + if (seek_to_subfile(fp, flash_args.tag, &subfile) != ESP_OK) { + ESP_LOGE(TAG, "Failed to seek to subfile with tag %lu", flash_args.tag); + abort(); + } + while (flash_binary(fp, subfile.size, flash_args.offset) != ESP_LOADER_SUCCESS) { + ESP_LOGW(TAG, "Failed to flash %s, retrying...", fullpath); + num_retry++; + if (num_retry > RCP_UPDATE_MAX_RETRY) { + ESP_LOGE(TAG, "Failed to update RCP, abort and reboot"); + abort(); + } + seek_to_subfile(fp, flash_args.tag, &subfile); + } + fseek(fp, current, SEEK_SET); + } + fclose(fp); + esp_loader_reset_target(); + loader_port_esp32_deinit(); + +#if CONFIG_OPENTHREAD_RADIO_SPINEL_SPI + ESP_RETURN_ON_ERROR(esp_rcp_boot_pin_mux(), TAG, "Failed to multiplex boot pin"); +#endif + return ESP_OK; +} + +void esp_rcp_update_deinit(void) +{ + nvs_close(s_handle.nvs_handle); +} + +esp_err_t esp_rcp_mark_image_verified(bool verified) +{ + ESP_RETURN_ON_FALSE(s_handle.update_config.rcp_type != RCP_TYPE_INVALID, ESP_ERR_INVALID_STATE, TAG, + "RCP update not initialized"); + int8_t val; + if (!verified) { + val = esp_rcp_get_update_seq(); + } else { + val = esp_rcp_get_update_seq() | RCP_VERIFIED_FLAG; + } + s_handle.verified = verified; + s_handle.update_seq = (val & ~RCP_VERIFIED_FLAG); + esp_err_t error = nvs_set_i8(s_handle.nvs_handle, RCP_SEQ_KEY, val); + if (error == ESP_OK) { + return nvs_commit(s_handle.nvs_handle); + } else { + return error; + } +} + +esp_err_t esp_rcp_mark_image_unusable(void) +{ + ESP_RETURN_ON_FALSE(s_handle.update_config.rcp_type != RCP_TYPE_INVALID, ESP_ERR_INVALID_STATE, TAG, + "RCP update not initialized"); + + s_handle.verified = 0; + int8_t val = s_handle.update_seq & ~RCP_VERIFIED_FLAG; + esp_err_t error = nvs_set_i8(s_handle.nvs_handle, RCP_SEQ_KEY, val); + if (error == ESP_OK) { + return nvs_commit(s_handle.nvs_handle); + } else { + return error; + } +} + +void esp_rcp_reset(void) +{ + gpio_config_t io_conf = {}; + uint8_t reset_pin = s_handle.update_config.reset_pin; + io_conf.pin_bit_mask = ((1ULL << reset_pin)); + io_conf.mode = GPIO_MODE_OUTPUT; + io_conf.pull_up_en = GPIO_PULLUP_DISABLE; + io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE; + io_conf.intr_type = GPIO_INTR_DISABLE; + gpio_config(&io_conf); + gpio_set_level(reset_pin, 0); + vTaskDelay(pdMS_TO_TICKS(150)); + gpio_set_level(reset_pin, 1); + vTaskDelay(pdMS_TO_TICKS(850)); +} diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_schedule/.component_hash b/RainMaker_Table-Lights/managed_components/espressif__esp_schedule/.component_hash new file mode 100644 index 000000000..5eaaeba2e --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_schedule/.component_hash @@ -0,0 +1 @@ +e202a9c688f7f1ab601efb91d682e4bcfaebc508dcceee1a1e0a0d2d1ca75a26 \ No newline at end of file diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_schedule/CHECKSUMS.json b/RainMaker_Table-Lights/managed_components/espressif__esp_schedule/CHECKSUMS.json new file mode 100644 index 000000000..55f8548c0 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_schedule/CHECKSUMS.json @@ -0,0 +1 @@ +{"version": "1.0", "algorithm": "sha256", "created_at": "2025-05-21T17:01:57.285779+00:00", "files": [{"path": "CMakeLists.txt", "size": 385, "hash": "b17de1af3a50ce7620daf4e6bffbc68fc7d3c59d865226e2f6583008e3c2c524"}, {"path": "LICENSE", "size": 11357, "hash": "c71d239df91726fc519c6eb72d318ec65820627232b2f796219e87dcf35d0ab4"}, {"path": "idf_component.yml", "size": 425, "hash": "a668bdef108230d23c87160ad253336784d0b2d1100cf9998b7db675b89286b6"}, {"path": "component.mk", "size": 95, "hash": "c20dd1fca41afe18163119c0f27ae2dcdd1276cc75b69d1440f4c76c1dc1ef09"}, {"path": "README.md", "size": 1707, "hash": "5b0d31601429dc46cde78716affe25c40ef05fdf0a50afa347051445871f61f6"}, {"path": "include/esp_schedule.h", "size": 8387, "hash": "4328488dea993ec634725f12eab95a3d0b32fb4798de34415a2228bc7260df37"}, {"path": "src/esp_schedule_nvs.c", "size": 10106, "hash": "5dca7ad66b84fc2b3a7bf434586ba1832029e987b899f02c91c191929eacbb57"}, {"path": "src/esp_schedule_internal.h", "size": 844, "hash": "55af8d787a7d4fca912a2f815c55bdca92f9afa1b14b41c3b032c0cd9db3f58f"}, {"path": "src/esp_schedule.c", "size": 24094, "hash": "81afd23f2e74a1e6e7329eac63dab44b7868cc119b2e0729fe1829af9e665c0e"}]} \ No newline at end of file diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_schedule/CMakeLists.txt b/RainMaker_Table-Lights/managed_components/espressif__esp_schedule/CMakeLists.txt new file mode 100644 index 000000000..02eb95250 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_schedule/CMakeLists.txt @@ -0,0 +1,10 @@ +set(component_srcs "src/esp_schedule.c" + "src/esp_schedule_nvs.c") + +idf_component_register(SRCS "${component_srcs}" + INCLUDE_DIRS "include" + PRIV_INCLUDE_DIRS "src" + PRIV_REQUIRES "rmaker_common" + REQUIRES "nvs_flash") + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-function") diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_schedule/LICENSE b/RainMaker_Table-Lights/managed_components/espressif__esp_schedule/LICENSE new file mode 100644 index 000000000..261eeb9e9 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_schedule/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_schedule/README.md b/RainMaker_Table-Lights/managed_components/espressif__esp_schedule/README.md new file mode 100644 index 000000000..3646ec001 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_schedule/README.md @@ -0,0 +1,50 @@ +# ESP Scheduling + +[![Component Registry](https://components.espressif.com/components/espressif/esp_schedule/badge.svg)](https://components.espressif.com/components/espressif/esp_schedule) + +This component is used internally by ESP RainMaker to implement schedules. + +> Note: By default, the time is w.r.t. UTC. If the timezone has been set, then the time is w.r.t. the specified timezone. + +## Test code: + +``` +#include + +void app_schedule_trigger_cb(esp_schedule_handle_t handle, void *priv_data) +{ + printf("priv_data: %.*s\n", (char *)priv_data); +} + +static char *priv_data_global = "from app"; + +void app_schedule_set() +{ + esp_schedule_config_t schedule_config = { + .name = "test", + .trigger.type = ESP_SCHEDULE_TYPE_DAYS_OF_WEEK, + .trigger.hours = 13, + .trigger.minutes = 30, + .trigger.day.repeat_days = ESP_SCHEDULE_DAY_MONDAY | ESP_SCHEDULE_DAY_THURSDAY, + .trigger_cb = app_schedule_trigger_cb, + .priv_data = priv_data_global, + }; + esp_schedule_create(&schedule_config); +} + +void app_schedule_init() +{ + uint8_t schedule_count; + esp_schedule_handle_t *schedule_list = esp_schedule_init(true, NULL, &schedule_count); + if (schedule_count > 0 && schedule_list != NULL) { + ESP_LOGI(TAG, "Found %d schedule(s) in NVS.", schedule_count); + for (size_t i = 0; i < schedule_count; i++) { + esp_schedule_config_t schedule_config; + esp_schedule_get(schedule_list[i], &schedule_config); + schedule_config.trigger_cb = app_schedule_trigger_cb; + schedule_config.priv_data = priv_data_global; + esp_schedule_edit(schedule_list[i], &schedule_config); + } + } +} +``` diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_schedule/component.mk b/RainMaker_Table-Lights/managed_components/espressif__esp_schedule/component.mk new file mode 100644 index 000000000..49844ec88 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_schedule/component.mk @@ -0,0 +1,5 @@ +COMPONENT_ADD_INCLUDEDIRS := include + +COMPONENT_SRCDIRS := src + +CFLAGS += -Wno-unused-function diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_schedule/idf_component.yml b/RainMaker_Table-Lights/managed_components/espressif__esp_schedule/idf_component.yml new file mode 100644 index 000000000..ed63a81d7 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_schedule/idf_component.yml @@ -0,0 +1,11 @@ +dependencies: + espressif/rmaker_common: + version: ~1.4.2 +description: ESP Schedules, used in RainMaker +issues: https://github.com/espressif/esp-rainmaker/issues +repository: git://github.com/espressif/esp-rainmaker.git +repository_info: + commit_sha: 2f7f487bc0fa835fb9ac9ce108c76a667e9d2f42 + path: components/esp_schedule +url: https://github.com/espressif/esp-rainmaker/tree/master/components/esp_schedule +version: 1.2.0 diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_schedule/include/esp_schedule.h b/RainMaker_Table-Lights/managed_components/espressif__esp_schedule/include/esp_schedule.h new file mode 100644 index 000000000..4c75ebf41 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_schedule/include/esp_schedule.h @@ -0,0 +1,236 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +/** Schedule Handle */ +typedef void *esp_schedule_handle_t; + +/** Maximum length of the schedule name allowed. This value cannot be more than 16 as it is used for NVS key. */ +#define MAX_SCHEDULE_NAME_LEN 16 + +/** Callback for schedule trigger + * + * This callback is called when the schedule is triggered. + * + * @param[in] handle Schedule handle. + * @param[in] priv_data Pointer to the private data passed while creating/editing the schedule. + */ +typedef void (*esp_schedule_trigger_cb_t)(esp_schedule_handle_t handle, void *priv_data); + +/** Callback for schedule timestamp + * + * This callback is called when the next trigger timestamp of the schedule is changed. This might be useful to check if + * one time schedules have already passed while the device was powered off. + * + * @param[in] handle Schedule handle. + * @param[in] next_timestamp timestamp at which the schedule will trigger next. + * @param[in] priv_data Pointer to the user data passed while creating/editing the schedule. + */ +typedef void (*esp_schedule_timestamp_cb_t)(esp_schedule_handle_t handle, uint32_t next_timestamp, void *priv_data); + +/** Schedule type */ +typedef enum esp_schedule_type { + ESP_SCHEDULE_TYPE_INVALID = 0, + ESP_SCHEDULE_TYPE_DAYS_OF_WEEK, + ESP_SCHEDULE_TYPE_DATE, + ESP_SCHEDULE_TYPE_RELATIVE, +} esp_schedule_type_t; + +/** Schedule days. Used for ESP_SCHEDULE_TYPE_DAYS_OF_WEEK. */ +typedef enum esp_schedule_days { + ESP_SCHEDULE_DAY_ONCE = 0, + ESP_SCHEDULE_DAY_EVERYDAY = 0b1111111, + ESP_SCHEDULE_DAY_MONDAY = 1 << 0, + ESP_SCHEDULE_DAY_TUESDAY = 1 << 1, + ESP_SCHEDULE_DAY_WEDNESDAY = 1 << 2, + ESP_SCHEDULE_DAY_THURSDAY = 1 << 3, + ESP_SCHEDULE_DAY_FRIDAY = 1 << 4, + ESP_SCHEDULE_DAY_SATURDAY = 1 << 5, + ESP_SCHEDULE_DAY_SUNDAY = 1 << 6, +} esp_schedule_days_t; + +/** Schedule months. Used for ESP_SCHEDULE_TYPE_DATE. */ +typedef enum esp_schedule_months { + ESP_SCHEDULE_MONTH_ONCE = 0, + ESP_SCHEDULE_MONTH_ALL = 0b1111111, + ESP_SCHEDULE_MONTH_JANUARY = 1 << 0, + ESP_SCHEDULE_MONTH_FEBRUARY = 1 << 1, + ESP_SCHEDULE_MONTH_MARCH = 1 << 2, + ESP_SCHEDULE_MONTH_APRIL = 1 << 3, + ESP_SCHEDULE_MONTH_MAY = 1 << 4, + ESP_SCHEDULE_MONTH_JUNE = 1 << 5, + ESP_SCHEDULE_MONTH_JULY = 1 << 6, + ESP_SCHEDULE_MONTH_AUGUST = 1 << 7, + ESP_SCHEDULE_MONTH_SEPTEMBER = 1 << 8, + ESP_SCHEDULE_MONTH_OCTOBER = 1 << 9, + ESP_SCHEDULE_MONTH_NOVEMBER = 1 << 10, + ESP_SCHEDULE_MONTH_DECEMBER = 1 << 11, +} esp_schedule_months_t; + +/** Trigger details of the schedule */ +typedef struct esp_schedule_trigger { + /** Type of schedule */ + esp_schedule_type_t type; + /** Hours in 24 hour format. Accepted values: 0-23 */ + uint8_t hours; + /** Minutes in the given hour. Accepted values: 0-59. */ + uint8_t minutes; + /** For type ESP_SCHEDULE_TYPE_DAYS_OF_WEEK */ + struct { + /** 'OR' list of esp_schedule_days_t */ + uint8_t repeat_days; + } day; + /** For type ESP_SCHEDULE_TYPE_DATE */ + struct { + /** Day of the month. Accepted values: 1-31. */ + uint8_t day; + /* 'OR' list of esp_schedule_months_t */ + uint16_t repeat_months; + /** Year */ + uint16_t year; + /** If the schedule is to be repeated every year. */ + bool repeat_every_year; + } date; + /** For type ESP_SCHEDULE_TYPE_SECONDS */ + int relative_seconds; + /** Used for passing the next schedule timestamp for + * ESP_SCHEDULE_TYPE_RELATIVE */ + time_t next_scheduled_time_utc; +} esp_schedule_trigger_t; + +/** Schedule Validity + * Start and end time within which the schedule will be applicable. + */ +typedef struct esp_schedule_validity { + /* Start time as UTC timestamp */ + time_t start_time; + /* End time as UTC timestamp */ + time_t end_time; +} esp_schedule_validity_t; + +/** Schedule config */ +typedef struct esp_schedule_config { + /** Name of the schedule. This is like a primary key for the schedule. This is required. +1 for NULL termination. */ + char name[MAX_SCHEDULE_NAME_LEN + 1]; + /** Trigger details */ + esp_schedule_trigger_t trigger; + /** Trigger callback */ + esp_schedule_trigger_cb_t trigger_cb; + /** Timestamp callback */ + esp_schedule_timestamp_cb_t timestamp_cb; + /** Private data associated with the schedule. This will be passed to callbacks. */ + void *priv_data; + /** Validity of schedules. */ + esp_schedule_validity_t validity; +} esp_schedule_config_t; + +/** Initialize ESP Schedule + * + * This initializes ESP Schedule. This must be called first before calling any of the other APIs. + * This API also gets all the schedules from NVS (if it has been enabled). + * + * Note: After calling this API, the pointers to the callbacks should be updated for all the schedules by calling + * esp_schedule_get() followed by esp_schedule_edit() with the correct callbacks. + * + * @param[in] enable_nvs If NVS is to be enabled or not. + * @param[in] nvs_partition (Optional) The NVS partition to be used. If NULL is passed, the default partition is used. + * @param[out] schedule_count Number of active schedules found in NVS. + * + * @return Array of schedule handles if any schedules have been found. + * @return NULL if no schedule is found in NVS (or if NVS is not enabled). + */ +esp_schedule_handle_t *esp_schedule_init(bool enable_nvs, char *nvs_partition, uint8_t *schedule_count); + +/** Create Schedule + * + * This API can be used to create a new schedule. The schedule still needs to be enabled using + * esp_schedule_enable(). + * + * @param[in] schedule_config Configuration of the schedule to be created. + * + * @return Schedule handle if successfully created. + * @return NULL in case of error. + */ +esp_schedule_handle_t esp_schedule_create(esp_schedule_config_t *schedule_config); + +/** Remove Schedule + * + * This API can be used to remove an existing schedule. + * + * @param[in] handle Schedule handle for the schedule to be removed. + * + * @return ESP_OK on success. + * @return error in case of failure. + */ +esp_err_t esp_schedule_delete(esp_schedule_handle_t handle); + +/** Edit Schedule + * + * This API can be used to edit an existing schedule. + * The schedule name should be same as when the schedule was created. The complete config must be provided + * or the previously stored config might be over-written. + * + * Note: If a schedule is edited when it is on-going, the new changes will not be reflected. + * You will need to disable the schedule, edit it, and then enable it again. + * + * @param[in] handle Schedule handle for the schedule to be edited. + * @param[in] schedule_config Configuration of the schedule to be edited. + * + * @return ESP_OK on success. + * @return error in case of failure. + */ +esp_err_t esp_schedule_edit(esp_schedule_handle_t handle, esp_schedule_config_t *schedule_config); + +/** Enable Schedule + * + * This API can be used to enable an existing schedule. + * It can be used to enable a schedule after it has been created using esp_schedule_create() + * or if the schedule has been disabled using esp_schedule_disable(). + * + * @param[in] handle Schedule handle for the schedule to be enabled. + * + * @return ESP_OK on success. + * @return error in case of failure. + */ +esp_err_t esp_schedule_enable(esp_schedule_handle_t handle); + +/** Disable Schedule + * + * This API can be used to disable an on-going schedule. + * It does not remove the schedule, just stops it. The schedule can be enabled again using + * esp_schedule_enable(). + * + * @param[in] handle Schedule handle for the schedule to be disabled. + * + * @return ESP_OK on success. + * @return error in case of failure. + */ +esp_err_t esp_schedule_disable(esp_schedule_handle_t handle); + +/** Get Schedule + * + * This API can be used to get details of an existing schedule. + * The schedule_config is populated with the schedule details. + * + * @param[in] handle Schedule handle. + * @param[out] schedule_config Details of the schedule whose handle is passed. + * + * @return ESP_OK on success. + * @return error in case of failure. + */ +esp_err_t esp_schedule_get(esp_schedule_handle_t handle, esp_schedule_config_t *schedule_config); + +#ifdef __cplusplus +} +#endif diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_schedule/src/esp_schedule.c b/RainMaker_Table-Lights/managed_components/espressif__esp_schedule/src/esp_schedule.c new file mode 100644 index 000000000..017ecb3f0 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_schedule/src/esp_schedule.c @@ -0,0 +1,600 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include +#include +#include +#include "esp_schedule_internal.h" + +static const char *TAG = "esp_schedule"; + +#define SECONDS_TILL_2020 ((2020 - 1970) * 365 * 24 * 3600) +#define SECONDS_IN_DAY (60 * 60 * 24) + +static bool init_done = false; + +static int esp_schedule_get_no_of_days(esp_schedule_trigger_t *trigger, struct tm *current_time, struct tm *schedule_time) +{ + /* for day, monday = 0, sunday = 6. */ + int next_day = 0; + /* struct tm has tm_wday with sunday as 0. Whereas we have monday as 0. Converting struct tm to our format */ + int today = ((current_time->tm_wday + 7 - 1) % 7); + + esp_schedule_days_t today_bit = 1 << today; + uint8_t repeat_days = trigger->day.repeat_days; + int current_seconds = (current_time->tm_hour * 60 + current_time->tm_min) * 60 + current_time->tm_sec; + int schedule_seconds = (schedule_time->tm_hour * 60 + schedule_time->tm_min) * 60; + + /* Handling for one time schedule */ + if (repeat_days == ESP_SCHEDULE_DAY_ONCE) { + if (schedule_seconds > current_seconds) { + /* The schedule is today and is yet to go off */ + return 0; + } else { + /* The schedule is tomorrow */ + return 1; + } + } + + /* Handling for repeating schedules */ + /* Check if it is today */ + if ((repeat_days & today_bit)) { + if (schedule_seconds > current_seconds) { + /* The schedule is today and is yet to go off. */ + return 0; + } + } + /* Check if it is this week or next week */ + if ((repeat_days & (today_bit ^ 0xFF)) > today_bit) { + /* Next schedule is yet to come in this week */ + next_day = ffs(repeat_days & (0xFF << (today + 1))) - 1; + return (next_day - today); + } else { + /* First scheduled day of the next week */ + next_day = ffs(repeat_days) - 1; + if (next_day == today) { + /* Same day, next week */ + return 7; + } + return (7 - today + next_day); + } + + ESP_LOGE(TAG, "No of days could not be found. This should not happen."); + return 0; +} + +static uint8_t esp_schedule_get_next_month(esp_schedule_trigger_t *trigger, struct tm *current_time, struct tm *schedule_time) +{ + int current_seconds = (current_time->tm_hour * 60 + current_time->tm_min) * 60 + current_time->tm_sec; + int schedule_seconds = (schedule_time->tm_hour * 60 + schedule_time->tm_min) * 60; + /* +1 is because struct tm has months starting from 0, whereas we have them starting from 1 */ + uint8_t current_month = current_time->tm_mon + 1; + /* -1 because month_bit starts from 0b1. So for January, it should be 1 << 0. And current_month starts from 1. */ + uint16_t current_month_bit = 1 << (current_month - 1); + uint8_t next_schedule_month = 0; + uint16_t repeat_months = trigger->date.repeat_months; + + /* Check if month is not specified */ + if (repeat_months == ESP_SCHEDULE_MONTH_ONCE) { + if (trigger->date.day == current_time->tm_mday) { + /* The schedule day is same. Check if time has already passed */ + if (schedule_seconds > current_seconds) { + /* The schedule is today and is yet to go off */ + return current_month; + } else { + /* Today's time has passed */ + return (current_month + 1); + } + } else if (trigger->date.day > current_time->tm_mday) { + /* The day is yet to come in this month */ + return current_month; + } else { + /* The day has passed in the current month */ + return (current_month + 1); + } + } + + /* Check if schedule is not this year itself, it is in future. */ + if (trigger->date.year > (current_time->tm_year + 1900)) { + /* Find first schedule month of next year */ + next_schedule_month = ffs(repeat_months); + /* Year will be handled by the caller. So no need to add any additional months */ + return next_schedule_month; + } + + /* Check if schedule is this month and is yet to come */ + if (current_month_bit & repeat_months) { + if (trigger->date.day == current_time->tm_mday) { + /* The schedule day is same. Check if time has already passed */ + if (schedule_seconds > current_seconds) { + /* The schedule is today and is yet to go off */ + return current_month; + } + } + if (trigger->date.day > current_time->tm_mday) { + /* The day is yet to come in this month */ + return current_month; + } + } + + /* Check if schedule is this year */ + if ((repeat_months & (current_month_bit ^ 0xFFFF)) > current_month_bit) { + /* Next schedule month is yet to come in this year */ + next_schedule_month = ffs(repeat_months & (0xFFFF << (current_month))); + return next_schedule_month; + } + + /* Check if schedule is for this year and does not repeat */ + if (!trigger->date.repeat_every_year) { + if (trigger->date.year <= (current_time->tm_year + 1900)) { + ESP_LOGE(TAG, "Schedule does not repeat next year, but get_next_month has been called."); + return 0; + } + } + + /* Schedule is not this year */ + /* Find first schedule month of next year */ + next_schedule_month = ffs(repeat_months); + /* +12 because the schedule is next year */ + return (next_schedule_month + 12); +} + +static uint16_t esp_schedule_get_next_year(esp_schedule_trigger_t *trigger, struct tm *current_time, struct tm *schedule_time) +{ + uint16_t current_year = current_time->tm_year + 1900; + uint16_t schedule_year = trigger->date.year; + if (schedule_year > current_year) { + return schedule_year; + } + /* If the schedule is set to repeat_every_year, we return the current year */ + /* If the schedule has already passed in this year, we still return current year, as the additional months will be handled in get_next_month */ + return current_year; +} + +static uint32_t esp_schedule_get_next_schedule_time_diff(const char *schedule_name, esp_schedule_trigger_t *trigger) +{ + struct tm current_time, schedule_time; + time_t now; + char time_str[64]; + int32_t time_diff; + + /* Get current time */ + time(&now); + /* Handling ESP_SCHEDULE_TYPE_RELATIVE first since it doesn't require any + * computation based on days, hours, minutes, etc. + */ + if (trigger->type == ESP_SCHEDULE_TYPE_RELATIVE) { + /* If next scheduled time is already set, just compute the difference + * between current time and next scheduled time and return that diff. + */ + time_t target; + if (trigger->next_scheduled_time_utc > 0) { + target = (time_t)trigger->next_scheduled_time_utc; + time_diff = difftime(target, now); + } else { + target = now + (time_t)trigger->relative_seconds; + time_diff = trigger->relative_seconds; + } + localtime_r(&target, &schedule_time); + trigger->next_scheduled_time_utc = mktime(&schedule_time); + /* Print schedule time */ + memset(time_str, 0, sizeof(time_str)); + strftime(time_str, sizeof(time_str), "%c %z[%Z]", &schedule_time); + ESP_LOGI(TAG, "Schedule %s will be active on: %s. DST: %s", schedule_name, time_str, schedule_time.tm_isdst ? "Yes" : "No"); + return time_diff; + } + localtime_r(&now, ¤t_time); + + /* Get schedule time */ + localtime_r(&now, &schedule_time); + schedule_time.tm_sec = 0; + schedule_time.tm_min = trigger->minutes; + schedule_time.tm_hour = trigger->hours; + mktime(&schedule_time); + + /* Adjust schedule day */ + if (trigger->type == ESP_SCHEDULE_TYPE_DAYS_OF_WEEK) { + int no_of_days = 0; + no_of_days = esp_schedule_get_no_of_days(trigger, ¤t_time, &schedule_time); + schedule_time.tm_sec += no_of_days * SECONDS_IN_DAY; + } + if (trigger->type == ESP_SCHEDULE_TYPE_DATE) { + schedule_time.tm_mday = trigger->date.day; + schedule_time.tm_mon = esp_schedule_get_next_month(trigger, ¤t_time, &schedule_time) - 1; + schedule_time.tm_year = esp_schedule_get_next_year(trigger, ¤t_time, &schedule_time) - 1900; + if (schedule_time.tm_mon < 0) { + ESP_LOGE(TAG, "Invalid month found: %d. Setting it to next month.", schedule_time.tm_mon); + schedule_time.tm_mon = current_time.tm_mon + 1; + } + if (schedule_time.tm_mon >= 12) { + schedule_time.tm_year += schedule_time.tm_mon / 12; + schedule_time.tm_mon = schedule_time.tm_mon % 12; + } + } + mktime(&schedule_time); + + /* Adjust time according to DST */ + time_t dst_adjust = 0; + if (!current_time.tm_isdst && schedule_time.tm_isdst) { + dst_adjust = -3600; + } else if (current_time.tm_isdst && !schedule_time.tm_isdst ) { + dst_adjust = 3600; + } + ESP_LOGD(TAG, "DST adjust seconds: %lld", (long long) dst_adjust); + schedule_time.tm_sec += dst_adjust; + mktime(&schedule_time); + + /* Print schedule time */ + memset(time_str, 0, sizeof(time_str)); + strftime(time_str, sizeof(time_str), "%c %z[%Z]", &schedule_time); + ESP_LOGI(TAG, "Schedule %s will be active on: %s. DST: %s", schedule_name, time_str, schedule_time.tm_isdst ? "Yes" : "No"); + + /* Calculate difference */ + time_diff = difftime((mktime(&schedule_time)), mktime(¤t_time)); + + /* For one time schedules to check for expiry after a reboot. If NVS is enabled, this should be stored in NVS. */ + trigger->next_scheduled_time_utc = mktime(&schedule_time); + + return time_diff; +} + +static bool esp_schedule_is_expired(esp_schedule_trigger_t *trigger) +{ + time_t current_timestamp = 0; + struct tm current_time = {0}; + time(¤t_timestamp); + localtime_r(¤t_timestamp, ¤t_time); + + if (trigger->type == ESP_SCHEDULE_TYPE_RELATIVE) { + if (trigger->next_scheduled_time_utc > 0 && trigger->next_scheduled_time_utc <= current_timestamp) { + /* Relative seconds based schedule has expired */ + return true; + } else if (trigger->next_scheduled_time_utc == 0) { + /* Schedule has been disabled , so it is as good as expired. */ + return true; + } + } else if (trigger->type == ESP_SCHEDULE_TYPE_DAYS_OF_WEEK) { + if (trigger->day.repeat_days == ESP_SCHEDULE_DAY_ONCE) { + if (trigger->next_scheduled_time_utc > 0 && trigger->next_scheduled_time_utc <= current_timestamp) { + /* One time schedule has expired */ + return true; + } else if (trigger->next_scheduled_time_utc == 0) { + /* Schedule has been disabled , so it is as good as expired. */ + return true; + } + } + } else if (trigger->type == ESP_SCHEDULE_TYPE_DATE) { + if (trigger->date.repeat_months == 0) { + if (trigger->next_scheduled_time_utc > 0 && trigger->next_scheduled_time_utc <= current_timestamp) { + /* One time schedule has expired */ + return true; + } else { + return false; + } + } + if (trigger->date.repeat_every_year == true) { + return false; + } + + struct tm schedule_time = {0}; + localtime_r(¤t_timestamp, &schedule_time); + schedule_time.tm_sec = 0; + schedule_time.tm_min = trigger->minutes; + schedule_time.tm_hour = trigger->hours; + schedule_time.tm_mday = trigger->date.day; + /* For expiry, just check the last month of the repeat_months. */ + /* '-1' because struct tm has months starting from 0 and we have months starting from 1. */ + schedule_time.tm_mon = fls(trigger->date.repeat_months) - 1; + /* '-1900' because struct tm has number of years after 1900 */ + schedule_time.tm_year = trigger->date.year - 1900; + time_t schedule_timestamp = mktime(&schedule_time); + + if (schedule_timestamp < current_timestamp) { + return true; + } + } else { + /* Invalid type. Mark as expired */ + return true; + } + return false; +} + +static void esp_schedule_stop_timer(esp_schedule_t *schedule) +{ + xTimerStop(schedule->timer, portMAX_DELAY); +} + +static void esp_schedule_start_timer(esp_schedule_t *schedule) +{ + time_t current_time = 0; + time(¤t_time); + if (current_time < SECONDS_TILL_2020) { + ESP_LOGE(TAG, "Time is not updated"); + return; + } + + schedule->next_scheduled_time_diff = esp_schedule_get_next_schedule_time_diff(schedule->name, &schedule->trigger); + ESP_LOGI(TAG, "Starting a timer for %"PRIu32" seconds for schedule %s", schedule->next_scheduled_time_diff, schedule->name); + + if (schedule->timestamp_cb) { + schedule->timestamp_cb((esp_schedule_handle_t)schedule, schedule->trigger.next_scheduled_time_utc, schedule->priv_data); + } + + xTimerStop(schedule->timer, portMAX_DELAY); + xTimerChangePeriod(schedule->timer, (schedule->next_scheduled_time_diff * 1000) / portTICK_PERIOD_MS, portMAX_DELAY); +} + +static void esp_schedule_common_timer_cb(TimerHandle_t timer) +{ + void *priv_data = pvTimerGetTimerID(timer); + if (priv_data == NULL) { + return; + } + esp_schedule_t *schedule = (esp_schedule_t *)priv_data; + time_t now; + time(&now); + struct tm validity_time; + char time_str[64] = {0}; + if (schedule->validity.start_time != 0) { + if (now < schedule->validity.start_time) { + memset(time_str, 0, sizeof(time_str)); + localtime_r(&schedule->validity.start_time, &validity_time); + strftime(time_str, sizeof(time_str), "%c %z[%Z]", &validity_time); + ESP_LOGW(TAG, "Schedule %s skipped. It will be active only after: %s. DST: %s.", schedule->name, time_str, validity_time.tm_isdst ? "Yes" : "No"); + /* TODO: Start the timer such that the next time it triggeres, it will be within the valid window. + * Currently, it will just keep triggering and then get skipped if not in valid range. + */ + goto restart_schedule; + } + } + if (schedule->validity.end_time != 0) { + if (now > schedule->validity.end_time) { + localtime_r(&schedule->validity.end_time, &validity_time); + strftime(time_str, sizeof(time_str), "%c %z[%Z]", &validity_time); + ESP_LOGW(TAG, "Schedule %s skipped. It can't be active after: %s. DST: %s.", schedule->name, time_str, validity_time.tm_isdst ? "Yes" : "No"); + /* Return from here will ensure that the timer does not start again for this schedule */ + return; + } + } + ESP_LOGI(TAG, "Schedule %s triggered", schedule->name); + if (schedule->trigger_cb) { + schedule->trigger_cb((esp_schedule_handle_t)schedule, schedule->priv_data); + } + +restart_schedule: + + if (esp_schedule_is_expired(&schedule->trigger)) { + /* Not deleting the schedule here. Just not starting it again. */ + return; + } + esp_schedule_start_timer(schedule); +} + +static void esp_schedule_delete_timer(esp_schedule_t *schedule) +{ + xTimerDelete(schedule->timer, portMAX_DELAY); +} + +static void esp_schedule_create_timer(esp_schedule_t *schedule) +{ + if (esp_schedule_nvs_is_enabled()) { + /* This is just used for calculating next_scheduled_time_utc for ESP_SCHEDULE_DAY_ONCE (in case of ESP_SCHEDULE_TYPE_DAYS_OF_WEEK) or for ESP_SCHEDULE_MONTH_ONCE (in case of ESP_SCHEDULE_TYPE_DATE), and only used when NVS is enabled. And if NVS is enabled, time will already be synced and the time will be correctly calculated. */ + schedule->next_scheduled_time_diff = esp_schedule_get_next_schedule_time_diff(schedule->name, &schedule->trigger); + } + + /* Temporarily setting the timer for 1 (anything greater than 0) tick. This will get changed when xTimerChangePeriod() is called. */ + schedule->timer = xTimerCreate("schedule", 1, pdFALSE, (void *)schedule, esp_schedule_common_timer_cb); +} + +esp_err_t esp_schedule_get(esp_schedule_handle_t handle, esp_schedule_config_t *schedule_config) +{ + if (schedule_config == NULL) { + return ESP_ERR_INVALID_ARG; + } + if (handle == NULL) { + return ESP_ERR_INVALID_ARG; + } + esp_schedule_t *schedule = (esp_schedule_t *)handle; + + strcpy(schedule_config->name, schedule->name); + schedule_config->trigger.type = schedule->trigger.type; + schedule_config->trigger.hours = schedule->trigger.hours; + schedule_config->trigger.minutes = schedule->trigger.minutes; + if (schedule->trigger.type == ESP_SCHEDULE_TYPE_DAYS_OF_WEEK) { + schedule_config->trigger.day.repeat_days = schedule->trigger.day.repeat_days; + } else if (schedule->trigger.type == ESP_SCHEDULE_TYPE_DATE) { + schedule_config->trigger.date.day = schedule->trigger.date.day; + schedule_config->trigger.date.repeat_months = schedule->trigger.date.repeat_months; + schedule_config->trigger.date.year = schedule->trigger.date.year; + schedule_config->trigger.date.repeat_every_year = schedule->trigger.date.repeat_every_year; + } + + schedule_config->trigger_cb = schedule->trigger_cb; + schedule_config->timestamp_cb = schedule->timestamp_cb; + schedule_config->priv_data = schedule->priv_data; + schedule_config->validity = schedule->validity; + return ESP_OK; +} + +esp_err_t esp_schedule_enable(esp_schedule_handle_t handle) +{ + if (handle == NULL) { + return ESP_ERR_INVALID_ARG; + } + esp_schedule_t *schedule = (esp_schedule_t *)handle; + esp_schedule_start_timer(schedule); + return ESP_OK; +} + +esp_err_t esp_schedule_disable(esp_schedule_handle_t handle) +{ + if (handle == NULL) { + return ESP_ERR_INVALID_ARG; + } + esp_schedule_t *schedule = (esp_schedule_t *)handle; + esp_schedule_stop_timer(schedule); + /* Disabling a schedule should also reset the next_scheduled_time. + * It would be re-computed after enabling. + */ + schedule->trigger.next_scheduled_time_utc = 0; + return ESP_OK; +} + +static esp_err_t esp_schedule_set(esp_schedule_t *schedule, esp_schedule_config_t *schedule_config) +{ + /* Setting everything apart from name. */ + schedule->trigger.type = schedule_config->trigger.type; + if (schedule->trigger.type == ESP_SCHEDULE_TYPE_RELATIVE) { + schedule->trigger.relative_seconds = schedule_config->trigger.relative_seconds; + schedule->trigger.next_scheduled_time_utc = schedule_config->trigger.next_scheduled_time_utc; + } else { + schedule->trigger.hours = schedule_config->trigger.hours; + schedule->trigger.minutes = schedule_config->trigger.minutes; + + if (schedule->trigger.type == ESP_SCHEDULE_TYPE_DAYS_OF_WEEK) { + schedule->trigger.day.repeat_days = schedule_config->trigger.day.repeat_days; + } else if (schedule->trigger.type == ESP_SCHEDULE_TYPE_DATE) { + schedule->trigger.date.day = schedule_config->trigger.date.day; + schedule->trigger.date.repeat_months = schedule_config->trigger.date.repeat_months; + schedule->trigger.date.year = schedule_config->trigger.date.year; + schedule->trigger.date.repeat_every_year = schedule_config->trigger.date.repeat_every_year; + } + } + + schedule->trigger_cb = schedule_config->trigger_cb; + schedule->timestamp_cb = schedule_config->timestamp_cb; + schedule->priv_data = schedule_config->priv_data; + schedule->validity = schedule_config->validity; + esp_schedule_nvs_add(schedule); + return ESP_OK; +} + +esp_err_t esp_schedule_edit(esp_schedule_handle_t handle, esp_schedule_config_t *schedule_config) +{ + if (handle == NULL || schedule_config == NULL) { + return ESP_ERR_INVALID_ARG; + } + esp_schedule_t *schedule = (esp_schedule_t *)handle; + if (strncmp(schedule->name, schedule_config->name, sizeof(schedule->name)) != 0) { + ESP_LOGE(TAG, "Schedule name mismatch. Expected: %s, Passed: %s", schedule->name, schedule_config->name); + return ESP_FAIL; + } + + /* Editing a schedule with relative time should also reset it. */ + if (schedule->trigger.type == ESP_SCHEDULE_TYPE_RELATIVE) { + schedule->trigger.next_scheduled_time_utc = 0; + } + esp_schedule_set(schedule, schedule_config); + ESP_LOGD(TAG, "Schedule %s edited", schedule->name); + return ESP_OK; +} + +esp_err_t esp_schedule_delete(esp_schedule_handle_t handle) +{ + if (handle == NULL) { + return ESP_ERR_INVALID_ARG; + } + esp_schedule_t *schedule = (esp_schedule_t *)handle; + ESP_LOGI(TAG, "Deleting schedule %s", schedule->name); + if (schedule->timer) { + esp_schedule_stop_timer(schedule); + esp_schedule_delete_timer(schedule); + } + esp_schedule_nvs_remove(schedule); + free(schedule); + return ESP_OK; +} + +esp_schedule_handle_t esp_schedule_create(esp_schedule_config_t *schedule_config) +{ + if (schedule_config == NULL) { + return NULL; + } + if (strlen(schedule_config->name) <= 0) { + ESP_LOGE(TAG, "Set schedule failed. Please enter a unique valid name for the schedule."); + return NULL; + } + + if (schedule_config->trigger.type == ESP_SCHEDULE_TYPE_INVALID) { + ESP_LOGE(TAG, "Schedule type is invalid."); + return NULL; + } + + esp_schedule_t *schedule = (esp_schedule_t *)MEM_CALLOC_EXTRAM(1, sizeof(esp_schedule_t)); + if (schedule == NULL) { + ESP_LOGE(TAG, "Could not allocate handle"); + return NULL; + } + strlcpy(schedule->name, schedule_config->name, sizeof(schedule->name)); + + esp_schedule_set(schedule, schedule_config); + + esp_schedule_create_timer(schedule); + ESP_LOGD(TAG, "Schedule %s created", schedule->name); + return (esp_schedule_handle_t)schedule; +} + +esp_schedule_handle_t *esp_schedule_init(bool enable_nvs, char *nvs_partition, uint8_t *schedule_count) +{ +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 1, 0) + if (!esp_sntp_enabled()) { + ESP_LOGI(TAG, "Initializing SNTP"); + esp_sntp_setoperatingmode(SNTP_OPMODE_POLL); + esp_sntp_setservername(0, "pool.ntp.org"); + esp_sntp_init(); + } +#else + if (!sntp_enabled()) { + ESP_LOGI(TAG, "Initializing SNTP"); + sntp_setoperatingmode(SNTP_OPMODE_POLL); + sntp_setservername(0, "pool.ntp.org"); + sntp_init(); + } +#endif + + if (!enable_nvs) { + return NULL; + } + + /* Wait for time to be updated here */ + + + /* Below this is initialising schedules from NVS */ + esp_schedule_nvs_init(nvs_partition); + + /* Get handle list from NVS */ + esp_schedule_handle_t *handle_list = NULL; + *schedule_count = 0; + handle_list = esp_schedule_nvs_get_all(schedule_count); + if (handle_list == NULL) { + ESP_LOGI(TAG, "No schedules found in NVS"); + return NULL; + } + ESP_LOGI(TAG, "Schedules found in NVS: %"PRIu8, *schedule_count); + /* Start/Delete the schedules */ + esp_schedule_t *schedule = NULL; + for (size_t handle_count = 0; handle_count < *schedule_count; handle_count++) { + schedule = (esp_schedule_t *)handle_list[handle_count]; + schedule->trigger_cb = NULL; + schedule->timer = NULL; + /* Check for ONCE and expired schedules and delete them. */ + if (esp_schedule_is_expired(&schedule->trigger)) { + /* This schedule has already expired. */ + ESP_LOGI(TAG, "Schedule %s does not repeat and has already expired. Deleting it.", schedule->name); + esp_schedule_delete((esp_schedule_handle_t)schedule); + /* Removing the schedule from the list */ + handle_list[handle_count] = handle_list[*schedule_count - 1]; + (*schedule_count)--; + handle_count--; + continue; + } + esp_schedule_create_timer(schedule); + esp_schedule_start_timer(schedule); + } + init_done = true; + return handle_list; +} diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_schedule/src/esp_schedule_internal.h b/RainMaker_Table-Lights/managed_components/espressif__esp_schedule/src/esp_schedule_internal.h new file mode 100644 index 000000000..64c3f8a06 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_schedule/src/esp_schedule_internal.h @@ -0,0 +1,28 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include +#include + +typedef struct esp_schedule { + char name[MAX_SCHEDULE_NAME_LEN + 1]; + esp_schedule_trigger_t trigger; + uint32_t next_scheduled_time_diff; + TimerHandle_t timer; + esp_schedule_trigger_cb_t trigger_cb; + esp_schedule_timestamp_cb_t timestamp_cb; + void *priv_data; + esp_schedule_validity_t validity; +} esp_schedule_t; + +esp_err_t esp_schedule_nvs_add(esp_schedule_t *schedule); +esp_err_t esp_schedule_nvs_remove(esp_schedule_t *schedule); +esp_schedule_handle_t *esp_schedule_nvs_get_all(uint8_t *schedule_count); +bool esp_schedule_nvs_is_enabled(void); +esp_err_t esp_schedule_nvs_init(char *nvs_partition); diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_schedule/src/esp_schedule_nvs.c b/RainMaker_Table-Lights/managed_components/espressif__esp_schedule/src/esp_schedule_nvs.c new file mode 100644 index 000000000..acff4051c --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_schedule/src/esp_schedule_nvs.c @@ -0,0 +1,296 @@ +// Copyright 2020 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. + +#include +#include +#include +#include +#include "esp_schedule_internal.h" + +static const char *TAG = "esp_schedule_nvs"; + +#define ESP_SCHEDULE_NVS_NAMESPACE "schd" +#define ESP_SCHEDULE_COUNT_KEY "schd_count" + +static char *esp_schedule_nvs_partition = NULL; +static bool nvs_enabled = false; + +esp_err_t esp_schedule_nvs_add(esp_schedule_t *schedule) +{ + if (!nvs_enabled) { + ESP_LOGD(TAG, "NVS not enabled. Not adding to NVS."); + return ESP_ERR_INVALID_STATE; + } + nvs_handle_t nvs_handle; + esp_err_t err = nvs_open_from_partition(esp_schedule_nvs_partition, ESP_SCHEDULE_NVS_NAMESPACE, NVS_READWRITE, &nvs_handle); + if (err != ESP_OK) { + ESP_LOGE(TAG, "NVS open failed with error %d", err); + return err; + } + + /* Check if this is new schedule or editing an existing schedule */ + size_t buf_size; + bool editing_schedule = true; + err = nvs_get_blob(nvs_handle, schedule->name, NULL, &buf_size); + if (err != ESP_OK) { + if (err == ESP_ERR_NVS_NOT_FOUND) { + editing_schedule = false; + } else { + ESP_LOGE(TAG, "NVS get failed with error %d", err); + nvs_close(nvs_handle); + return err; + } + } else { + ESP_LOGI(TAG, "Updating the existing schedule %s", schedule->name); + } + + err = nvs_set_blob(nvs_handle, schedule->name, schedule, sizeof(esp_schedule_t)); + if (err != ESP_OK) { + ESP_LOGE(TAG, "NVS set failed with error %d", err); + nvs_close(nvs_handle); + return err; + } + if (editing_schedule == false) { + uint8_t schedule_count; + err = nvs_get_u8(nvs_handle, ESP_SCHEDULE_COUNT_KEY, &schedule_count); + if (err != ESP_OK) { + if (err == ESP_ERR_NVS_NOT_FOUND) { + schedule_count = 0; + } else { + ESP_LOGE(TAG, "NVS get failed with error %d", err); + nvs_close(nvs_handle); + return err; + } + } + schedule_count++; + err = nvs_set_u8(nvs_handle, ESP_SCHEDULE_COUNT_KEY, schedule_count); + if (err != ESP_OK) { + ESP_LOGE(TAG, "NVS set failed for schedule count with error %d", err); + nvs_close(nvs_handle); + return err; + } + } + nvs_commit(nvs_handle); + nvs_close(nvs_handle); + ESP_LOGI(TAG, "Schedule %s added in NVS", schedule->name); + return ESP_OK; +} + +esp_err_t esp_schedule_nvs_remove_all(void) +{ + if (!nvs_enabled) { + ESP_LOGD(TAG, "NVS not enabled. Not removing from NVS."); + return ESP_ERR_INVALID_STATE; + } + nvs_handle_t nvs_handle; + esp_err_t err = nvs_open_from_partition(esp_schedule_nvs_partition, ESP_SCHEDULE_NVS_NAMESPACE, NVS_READWRITE, &nvs_handle); + if (err != ESP_OK) { + ESP_LOGE(TAG, "NVS open failed with error %d", err); + return err; + } + err = nvs_erase_all(nvs_handle); + if (err != ESP_OK) { + ESP_LOGE(TAG, "NVS erase all keys failed with error %d", err); + nvs_close(nvs_handle); + return err; + } + nvs_commit(nvs_handle); + nvs_close(nvs_handle); + ESP_LOGI(TAG, "All schedules removed from NVS"); + return ESP_OK; +} + +esp_err_t esp_schedule_nvs_remove(esp_schedule_t *schedule) +{ + if (!nvs_enabled) { + ESP_LOGD(TAG, "NVS not enabled. Not removing from NVS."); + return ESP_ERR_INVALID_STATE; + } + nvs_handle_t nvs_handle; + esp_err_t err = nvs_open_from_partition(esp_schedule_nvs_partition, ESP_SCHEDULE_NVS_NAMESPACE, NVS_READWRITE, &nvs_handle); + if (err != ESP_OK) { + ESP_LOGE(TAG, "NVS open failed with error %d", err); + return err; + } + err = nvs_erase_key(nvs_handle, schedule->name); + if (err != ESP_OK) { + ESP_LOGE(TAG, "NVS erase key failed with error %d", err); + nvs_close(nvs_handle); + return err; + } + uint8_t schedule_count; + err = nvs_get_u8(nvs_handle, ESP_SCHEDULE_COUNT_KEY, &schedule_count); + if (err != ESP_OK) { + ESP_LOGE(TAG, "NVS get failed for schedule count with error %d", err); + nvs_close(nvs_handle); + return err; + } + schedule_count--; + err = nvs_set_u8(nvs_handle, ESP_SCHEDULE_COUNT_KEY, schedule_count); + if (err != ESP_OK) { + ESP_LOGE(TAG, "NVS set failed for schedule count with error %d", err); + nvs_close(nvs_handle); + return err; + } + nvs_commit(nvs_handle); + nvs_close(nvs_handle); + ESP_LOGI(TAG, "Schedule %s removed from NVS", schedule->name); + return ESP_OK; +} + +static uint8_t esp_schedule_nvs_get_count(void) +{ + if (!nvs_enabled) { + ESP_LOGD(TAG, "NVS not enabled. Not getting count from NVS."); + return 0; + } + nvs_handle_t nvs_handle; + esp_err_t err = nvs_open_from_partition(esp_schedule_nvs_partition, ESP_SCHEDULE_NVS_NAMESPACE, NVS_READONLY, &nvs_handle); + if (err != ESP_OK) { + ESP_LOGE(TAG, "NVS open failed with error %d", err); + return 0; + } + uint8_t schedule_count; + err = nvs_get_u8(nvs_handle, ESP_SCHEDULE_COUNT_KEY, &schedule_count); + if (err != ESP_OK) { + ESP_LOGE(TAG, "NVS get failed for schedule count with error %d", err); + nvs_close(nvs_handle); + return 0; + } + nvs_close(nvs_handle); + ESP_LOGI(TAG, "Schedules in NVS: %d", schedule_count); + return schedule_count; +} + +static esp_schedule_handle_t esp_schedule_nvs_get(char *nvs_key) +{ + if (!nvs_enabled) { + ESP_LOGD(TAG, "NVS not enabled. Not getting from NVS."); + return NULL; + } + size_t buf_size; + nvs_handle_t nvs_handle; + esp_err_t err = nvs_open_from_partition(esp_schedule_nvs_partition, ESP_SCHEDULE_NVS_NAMESPACE, NVS_READONLY, &nvs_handle); + if (err != ESP_OK) { + ESP_LOGE(TAG, "NVS open failed with error %d", err); + return NULL; + } + err = nvs_get_blob(nvs_handle, nvs_key, NULL, &buf_size); + if (err != ESP_OK) { + ESP_LOGE(TAG, "NVS get failed with error %d", err); + nvs_close(nvs_handle); + return NULL; + } + esp_schedule_t *schedule = (esp_schedule_t *)malloc(buf_size); + if (schedule == NULL) { + ESP_LOGE(TAG, "Could not allocate handle"); + nvs_close(nvs_handle); + return NULL; + } + err = nvs_get_blob(nvs_handle, nvs_key, schedule, &buf_size); + if (err != ESP_OK) { + ESP_LOGE(TAG, "NVS get failed with error %d", err); + nvs_close(nvs_handle); + free(schedule); + return NULL; + } + nvs_close(nvs_handle); + ESP_LOGI(TAG, "Schedule %s found in NVS", schedule->name); + return (esp_schedule_handle_t) schedule; +} + +esp_schedule_handle_t *esp_schedule_nvs_get_all(uint8_t *schedule_count) +{ + if (!nvs_enabled) { + ESP_LOGD(TAG, "NVS not enabled. Not Initialising NVS."); + return NULL; + } + + *schedule_count = esp_schedule_nvs_get_count(); + if (*schedule_count == 0) { + ESP_LOGI(TAG, "No Entries found in NVS"); + return NULL; + } + esp_schedule_handle_t *handle_list = (esp_schedule_handle_t *)malloc(sizeof(esp_schedule_handle_t) * (*schedule_count)); + if (handle_list == NULL) { + ESP_LOGE(TAG, "Could not allocate schedule list"); + *schedule_count = 0; + return NULL; + } + int handle_count = 0; + + nvs_entry_info_t nvs_entry; +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0) + nvs_iterator_t nvs_iterator = NULL; + esp_err_t err = nvs_entry_find(esp_schedule_nvs_partition, ESP_SCHEDULE_NVS_NAMESPACE, NVS_TYPE_BLOB, &nvs_iterator); + if (err != ESP_OK) { + ESP_LOGE(TAG, "No entry found in NVS"); + return NULL;; + } + while (err == ESP_OK) { + nvs_entry_info(nvs_iterator, &nvs_entry); + ESP_LOGI(TAG, "Found schedule in NVS with key: %s", nvs_entry.key); + handle_list[handle_count] = esp_schedule_nvs_get(nvs_entry.key); + if (handle_list[handle_count] != NULL) { + /* Increase count only if nvs_get was successful */ + handle_count++; + } + err = nvs_entry_next(&nvs_iterator); + } + nvs_release_iterator(nvs_iterator); +#else + nvs_iterator_t nvs_iterator = nvs_entry_find(esp_schedule_nvs_partition, ESP_SCHEDULE_NVS_NAMESPACE, NVS_TYPE_BLOB); + if (nvs_iterator == NULL) { + ESP_LOGE(TAG, "No entry found in NVS"); + return NULL;; + } + while (nvs_iterator != NULL) { + nvs_entry_info(nvs_iterator, &nvs_entry); + ESP_LOGI(TAG, "Found schedule in NVS with key: %s", nvs_entry.key); + handle_list[handle_count] = esp_schedule_nvs_get(nvs_entry.key); + if (handle_list[handle_count] != NULL) { + /* Increase count only if nvs_get was successful */ + handle_count++; + } + nvs_iterator = nvs_entry_next(nvs_iterator); + } +#endif + *schedule_count = handle_count; + ESP_LOGI(TAG, "Found %d schedules in NVS", *schedule_count); + return handle_list; +} + +bool esp_schedule_nvs_is_enabled(void) +{ + return nvs_enabled; +} + +esp_err_t esp_schedule_nvs_init(char *nvs_partition) +{ + if (nvs_enabled) { + ESP_LOGI(TAG, "NVS already enabled"); + return ESP_OK; + } + if (nvs_partition) { + esp_schedule_nvs_partition = strndup(nvs_partition, strlen(nvs_partition)); + } else { + esp_schedule_nvs_partition = strndup("nvs", strlen("nvs")); + } + if (esp_schedule_nvs_partition == NULL) { + ESP_LOGE(TAG, "Could not allocate nvs_partition"); + return ESP_ERR_NO_MEM; + } + nvs_enabled = true; + return ESP_OK; +} diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/.component_hash b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/.component_hash new file mode 100644 index 000000000..994c9c747 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/.component_hash @@ -0,0 +1 @@ +5d9175b416f751ba6a7cb35bdf092f0af85658ce06c4a592c7c541d8017ebeb9 \ No newline at end of file diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/.gitignore b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/.gitignore new file mode 100644 index 000000000..232c93032 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/.gitignore @@ -0,0 +1,2 @@ +*.pyc +tools/esp_secure_cert_data/* diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/.pre-commit-config.yaml b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/.pre-commit-config.yaml new file mode 100644 index 000000000..3e7d1c5ec --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/.pre-commit-config.yaml @@ -0,0 +1,16 @@ +# Contains the pre-commit hooks for the repository +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v3.3.0 + hooks: + - id: trailing-whitespace + exclude: '.+\.(md|rst)' + - id: end-of-file-fixer + - id: check-executables-have-shebangs + - id: mixed-line-ending + args: ['-f=lf'] + - repo: https://gitlab.com/pycqa/flake8 + rev: 3.8.4 + hooks: + - id: flake8 + args: ['--config=.flake8', '--tee', '--benchmark'] diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/CHECKSUMS.json b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/CHECKSUMS.json new file mode 100644 index 000000000..805edd402 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/CHECKSUMS.json @@ -0,0 +1 @@ +{"version": "1.0", "algorithm": "sha256", "created_at": "2025-05-21T16:24:13.335465+00:00", "files": [{"path": "CMakeLists.txt", "size": 603, "hash": "3ffefa168d1145010382b75cba9c1fd29465a8d7256d1ada0eed72c362a918bc"}, {"path": "LICENSE", "size": 11358, "hash": "cfc7749b96f63bd31c3c42b5c471bf756814053e847c10f3eb003417bc523d30"}, {"path": "Changelog.md", "size": 4187, "hash": "0cb134316ef63f48aa1e8d3f54ca2b7b8343c7fa2ef992f174b00e76a6f96f58"}, {"path": ".pre-commit-config.yaml", "size": 480, "hash": "0fcfd97be8acd28d18b5e3a27adca7458bc44a31a9d3010e78bec3bfd6189c6c"}, {"path": "idf_component.yml", "size": 293, "hash": "67b9d6193a49dae423d4661ab806f6c7f7057d4cc63256056a3c3e817c783cfb"}, {"path": "Kconfig", "size": 742, "hash": "d0f282a9a6c4f1915596548791b255359ca1870a00eaba9d529e53f56748f075"}, {"path": "README.md", "size": 4479, "hash": "20c459891a3acb469b486e2ce309b352ce2868f41afcf927160f43eb1bf8c634"}, {"path": ".gitignore", "size": 35, "hash": "01cdabe6ba0e7b7768187f66f3194ff2112b4fe915b47833e9ff27e65965370b"}, {"path": "private_include/esp_secure_cert_tlv_private.h", "size": 7978, "hash": "7f289093c4e2cd82ab2e93f8d29c5a51e08f61c5893699a3f7f16f2898ab44cb"}, {"path": "private_include/esp_secure_cert_config.h", "size": 4782, "hash": "5aaf2266422cc4237d477bf5eccb6b1b02135f9edb06d6465c6d1242a1ea9009"}, {"path": "tools/LICENSE", "size": 11358, "hash": "cfc7749b96f63bd31c3c42b5c471bf756814053e847c10f3eb003417bc523d30"}, {"path": "tools/requirements.txt", "size": 21, "hash": "15aaae898623362aaf0c62963976e57741b65214f28dab1fadbfdb770d624600"}, {"path": "tools/__init__.py", "size": 0, "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"}, {"path": "tools/MANIFEST.in", "size": 25, "hash": "784e45a1e4db56d48aa446db42d51ac551698415350ae30c414ef713312d51a2"}, {"path": "tools/README.md", "size": 5482, "hash": "cc1fa36053355f204f0c922320920b7d9309463e5e8a5b2a35c574220852b2da"}, {"path": "tools/configure_esp_secure_cert.py", "size": 15301, "hash": "3c286c83e820f5b5e9587e69a45b5acdf125c0e5d8bed06eacb59cd8759299c3"}, {"path": "tools/setup.py", "size": 3014, "hash": "03e6726c428edcee0acc0b77189987910bb6324b7dc44b2e56f7d56344b249df"}, {"path": "ci/build_test.sh", "size": 2503, "hash": "08d425e6500c3ee5e2e9297501fee6cd927ece226776f4e0746db216cef55ace"}, {"path": "include/esp_secure_cert_tlv_read.h", "size": 4931, "hash": "fd1a271b22b661d5a0224eaa17eeab521c28775593ca1b1f04cd8e21f659e121"}, {"path": "include/esp_secure_cert_crypto.h", "size": 1502, "hash": "e978283ae6c051c427b1bb897dd3da3ece0a4eced5b42440b3a7b1eb5f2ed0dc"}, {"path": "include/esp_secure_cert_tlv_config.h", "size": 2308, "hash": "0d7ab8ac30c41753afdf6f690e8cad609664c7d8301d6ff26ee2da5faae17de1"}, {"path": "include/esp_secure_cert_read.h", "size": 9644, "hash": "ec885c2238a961421a4457614ba59036a03a7518e7604bc6762d3f617a0ecf83"}, {"path": "docs/format.md", "size": 5499, "hash": "370961191b5c36d01cf569ea030dcfb74d79bc7bbe0ae07219456fd625004a7d"}, {"path": "examples/pytest.ini", "size": 337, "hash": "a2cc9429b3e63c0b36acb8d7fa76675d01e0d4e48d4ed11754c8fb224dedad94"}, {"path": "srcs/esp_secure_cert_tlv_read.c", "size": 32685, "hash": "b958b38548f499006bb2fa955dff0b8abf76ae504c5f4943c86cd8e48c2e3305"}, {"path": "srcs/esp_secure_cert_crypto.c", "size": 2835, "hash": "05c6c5cbc8f2b2a2c8b8d818d811a916b75dcaa878c45b39600d5185ed4d2bda"}, {"path": "srcs/esp_secure_cert_read.c", "size": 24175, "hash": "11e4ca50261a4763f3d536c984d3fff1abfed1ae497772e06201c69602db7b77"}, {"path": "examples/esp_secure_cert_app/sdkconfig.ci.tlv", "size": 25, "hash": "9938190ed1d01faebc0b6a1d26ef7ba5fb5186f2bb5c78c403d85f79d9565ccf"}, {"path": "examples/esp_secure_cert_app/CMakeLists.txt", "size": 243, "hash": "324717189a89f4f001f43cf90150bedac7823eb2df09ff533448ec32b73fd04e"}, {"path": "examples/esp_secure_cert_app/sdkconfig.ci.legacy", "size": 73, "hash": "afa473d11e93ab5c1686a542f7b031bb8d6cd1a77a51f02940540b62859533ce"}, {"path": "examples/esp_secure_cert_app/README.md", "size": 2666, "hash": "c30354334441aac8d5e1a8969f89a347171e8604e91e62e58ec9eb9e9cbe3f9f"}, {"path": "examples/esp_secure_cert_app/partitions.csv", "size": 284, "hash": "088c19ab6a8b55e62fcbd53f9350d8b660ba1b59b6d61a96aa7818b9639ed71e"}, {"path": "examples/esp_secure_cert_app/test_esp_secure_cert.py", "size": 767, "hash": "96668c02f4ea5cfcb074d0a199dd1f26a79673ff3c4a04344c474742c9aac53c"}, {"path": "examples/esp_secure_cert_app/sdkconfig.defaults", "size": 125, "hash": "de1e751c0d47fbdca7f835cf29b683c5b4711a1528634841ffe351fd0e721921"}, {"path": "examples/esp_secure_cert_app/qemu_test/make-qemu-img.sh", "size": 734, "hash": "ce4fefecf336a494e089385790ccd858c3ed8e56ca1afed1c2ee825a11faf601"}, {"path": "examples/esp_secure_cert_app/qemu_test/requirements.txt", "size": 57, "hash": "1df6ecd64bf38e53738a46b0c87f69a487f231b5caf3f9552e2f625781dab28b"}, {"path": "examples/esp_secure_cert_app/qemu_test/README.md", "size": 1348, "hash": "bb264a77edbe1be494e90d7b503b3a3ce95d45da4237f651b445df578e941a9a"}, {"path": "examples/esp_secure_cert_app/qemu_test/build_qemu_images.sh", "size": 2521, "hash": "9c9d9ed6bc7d286ed444831fb3d8536b5ce755e7ca34d9bd56356851d3c29d5b"}, {"path": "examples/esp_secure_cert_app/main/CMakeLists.txt", "size": 68, "hash": "5f89331a1df250c42e250296a2062ff0366ff32f2fdd5e527fdc98313f0958d7"}, {"path": "examples/esp_secure_cert_app/main/idf_component.yml", "size": 230, "hash": "c509d2920d49649e0e0f31f1b649e5e7b9907b54239dcbc9e1ef649b6d895570"}, {"path": "examples/esp_secure_cert_app/main/app_main.c", "size": 8777, "hash": "b70ba98d54b69e8cc5e50ba992cf73ce321c0a50f8038f1367bff2a937bbc857"}, {"path": "examples/esp_secure_cert_app/qemu_test/cust_flash_legacy/partition-table.bin", "size": 3072, "hash": "9c01b9db0230e9637331d7800481177f5beb0626aeb60dd36ac625eb8b0f714c"}, {"path": "examples/esp_secure_cert_app/qemu_test/cust_flash_legacy/cust_flash_legacy.bin", "size": 24576, "hash": "f88ee14b4f99f12ccf6c9caa24a79a246f0a37aa915858c69e3aa67609890644"}, {"path": "examples/esp_secure_cert_app/qemu_test/cust_flash/partition-table.bin", "size": 3072, "hash": "61a0ad0011af31b8d3589d85d965a3074da41ddc966d4de8e662730196b922f1"}, {"path": "examples/esp_secure_cert_app/qemu_test/cust_flash/cust_flash.bin", "size": 24576, "hash": "852759453c560691b3331724197e9dfba08eb6b7eb2853cf9c3a5a6166b50366"}, {"path": "examples/esp_secure_cert_app/qemu_test/cust_flash_tlv/partition-table.bin", "size": 3072, "hash": "27d7e6495348affbeb58cfc3e17808a9a45569a39257d24520d96a98db0393da"}, {"path": "examples/esp_secure_cert_app/qemu_test/cust_flash_tlv/cust_flash_tlv.bin", "size": 8192, "hash": "aacba3774662c9c13309f9b7a7f0a6ebf6a80cb91aabf97a19db243f8edbe9d3"}, {"path": "examples/esp_secure_cert_app/qemu_test/nvs/partition-table.bin", "size": 3072, "hash": "f7f021e6b6b8d9be364c994706585ccf566c7fb5e82a45554fc29f79711951d1"}, {"path": "examples/esp_secure_cert_app/qemu_test/nvs/nvs.bin", "size": 12288, "hash": "b2c8eb81f30f6b4f980b6c7005eaac41268a7451e1f688597961cb847c3bfacd"}, {"path": "examples/esp_secure_cert_app/qemu_test/nvs_legacy/partition-table.bin", "size": 3072, "hash": "b70cb53c59aa6febf75e01fd411838688135958207b839a6ff52737d777c9301"}, {"path": "examples/esp_secure_cert_app/qemu_test/nvs_legacy/nvs_legacy.bin", "size": 12288, "hash": "6d5a7de9aaeb30e71eea8f7e77dd2338347aab38c8fc8180d3828cb161c477fd"}, {"path": "docs/_static/tlv_format.png", "size": 49394, "hash": "78ee1c07959ed8ad0c610872443ae69714c6999ed846d8bf4cf0f82fbff5314c"}, {"path": "tools/esp_secure_cert/custflash_format.py", "size": 7606, "hash": "b3c79715a4b09e303b97c67a0a0b1a79de80ef222e52a9f28b1e121b3e66df5a"}, {"path": "tools/esp_secure_cert/esp_secure_cert_helper.py", "size": 4516, "hash": "cac0e8e4fbb1811dd2d6b08840876bc0c2784cfacff753c0919ed5d1ba6d696f"}, {"path": "tools/esp_secure_cert/__init__.py", "size": 0, "hash": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"}, {"path": "tools/esp_secure_cert/configure_ds.py", "size": 6830, "hash": "f868994365d916592da48f8666e3c2665559e8a071f332ca053969279d6089b0"}, {"path": "tools/esp_secure_cert/tlv_format.py", "size": 14908, "hash": "9988aaa466d430076851f4d7e110af135f3523dd7b669cd872b91eb924c89017"}, {"path": "tools/esp_secure_cert/efuse_helper.py", "size": 9214, "hash": "8121b681c7e9e18b0cf2814ed3efe77e4271d4352e6ee74d3cc68d1ae9800bbd"}, {"path": "tools/esp_secure_cert/nvs_format.py", "size": 3105, "hash": "1e6b7737d6a7691bdadc02765dfb3419d33030f24f6bec30ec7e53415734746e"}]} \ No newline at end of file diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/CMakeLists.txt b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/CMakeLists.txt new file mode 100644 index 000000000..d0d062748 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/CMakeLists.txt @@ -0,0 +1,17 @@ +set(srcs "srcs/esp_secure_cert_tlv_read.c" "srcs/esp_secure_cert_crypto.c") + +if(CONFIG_ESP_SECURE_CERT_SUPPORT_LEGACY_FORMATS) + list(APPEND srcs "srcs/esp_secure_cert_read.c") +endif() + +set(priv reqs "") +idf_build_get_property(build_components BUILD_COMPONENTS) +if(esp_partition IN_LIST build_components) + list(APPEND priv_reqs esp_partition) +endif() + +idf_component_register(SRCS ${srcs} + INCLUDE_DIRS "include" + PRIV_INCLUDE_DIRS "private_include" + REQUIRES spi_flash mbedtls nvs_flash efuse + PRIV_REQUIRES ${priv_reqs}) diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/Changelog.md b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/Changelog.md new file mode 100644 index 000000000..528707ff5 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/Changelog.md @@ -0,0 +1,88 @@ +# This file contains the list of changes across different versions + +## v2.5.0 +* Assigned 2 project specific entries for Matter project in the list of TLV entries + +## v2.4.1 +* Added a new API `esp_secure_cert_get_tlv_info` for obtaining TLV information +* Added `esp_secure_cert_free_tlv_info` API for freeing TLV information. +* Added `esp_secure_cert_iterate_to_next_tlv` API for iterating the TLV entries +* Updated the API documentation for available `esp_secure_cert_get_*` APIs + +## v2.4.0 (yanked) +* Added support for multiple entries of the same type by adding a new field called subtype. +* Fixed API for obtaining CA cert for the legacy flash formats (9b091ee) + +### Yank explanation +This version was later yanked due to following reason. + +* The API `esp_secure_cert_tlv_get_addr` which was made public in this version has incorrect documentation and the respective free API was not present. +* The changes in this version also modifiy the behaviour of existing APIs to obtain the TLV entry of latest subtype. While no current users shall be affected, this may cause inconsistency in the available API usage going forward. + +Please note that the yanked version does not affect any of existing users. The yanking is done due to future API usage considerations and to avoid any possible inconsistencies. + +## v2.3.1 +* Make esp_secure_cert_get_key_type API available for DS peripheral case as well. + +## v2.3.0 +* Added support to obtain the priv key type +* Added support for getting the efuse key id for priv key + +## v2.2.0 +* tools: Support DER encoded private keys when creating secure cert partition on host +### Breaking changes in v2.2.0 +* Updated the order of arguments for esp_pbkdf2_hmac_sha256 API to match it with corresponding mbedTLS API + +## v2.1.0 +* Added support for HMAC based ECDSA key derivation with PBKDF2-HMAC-SHA256 +* Fixed build failure when example is setup through component manager + +## v2.0.8 +* Fix for supporting IDF v4.3 + +## v2.0.7 +* Updated documentation regarding TLV format +* Fixed priv_key free API when HMAC based encryption scheme is enabled. + +## v2.0.6 +* Added HMAC based encryption scheme to protect private key data +* Added support for private key validation in the esp_secure_cert_app +* Added support of configurable esp_secure_cert partition offset in for configure_esp_secure_cert.py utility + +## v2.0.5 +* Fixed targets in Kconfig to reflect DS Peripheral compatibility + +## v2.0.4 +* Add implementation of `esp_secure_cert_free_*` APIs for TLV configuration. + +## v2.0.3 +* Added C linkage so that C++ code can find the definitions for secure cert APIs. +* Minor documentation fixes. + +## v2.0.2 +* Updated reference to the new esp_partition component (IDFv5.0) + +## v2.0.1 +* Added fixes for build failures with `-Wstrict-prototypes` CFLAG. +* Added fix for build failure with toolchain change in IDFv4.x and IDFv5.x + +## v2.0.0 +* Added esp-secure-cert-tool to PyPi. +* Restructure esp-secure-cert-tool +### Breaking changes in v2.0.0 +* Added the support for TLV format for storing data in esp_secure_cert partition. +* Make the TLV `cust_flash_tlv` as the default flash format. +* Marked all the supported flash formats before TLV as legacy: `cust_flash`, `nvs`. +* esp_secure_cert_app: Updated the partition table for the example + +## v1.0.3 +* esp_secure_cert API now Dynamically identify the type of partitionand access the data accordingly +* esp_secure_cert_app: Enable support for target esp32 +* Added tests based on qemu +* Added priv_key functionality to the configure_esp_secure_cert.py script. +### Breaking changes in v1.0.3 +* Removed all the configuration options related to selecting the type of `esp_secure_cert` partition +* Remove `esp_secure_cert_get_*_addr` API, the contents can now be obtained through `esp_secure_cert_get_*` API. +* Remove APIs to obain the contents of the DS contexts e.g. efuse key id, ciphertext, iv etc. The contents can be accesed from inside the DS context which can be obtained through respective API. +* Breaking change in the `esp_secure_cert_get_*` API: +The API now accepts `char **buffer` instead of `char *buffer`. It will allocate the required memory dynamically and directly if necessary and provide the respective pointer. diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/Kconfig b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/Kconfig new file mode 100644 index 000000000..20b392c3b --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/Kconfig @@ -0,0 +1,22 @@ +menu "ESP Secure Cert Manager" + + config ESP_SECURE_CERT_DS_PERIPHERAL + bool "Enable DS peripheral support" + default y + depends on !IDF_TARGET_ESP32 && !IDF_TARGET_ESP32C2 + help + Enable the DS peripheral support. Not supported on esp32 and esp32c2. + + config ESP_SECURE_CERT_SUPPORT_LEGACY_FORMATS + bool "Enable support for legacy formats" + default n + help + This option enables support for the legacy formats along with + the current format in the esp_secure_cert component. + The current format is + cust_flash_tlv + The legacy formats are as follows: + cust_flash + nvs + +endmenu # ESP Secure Cert Manager diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/LICENSE b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/README.md b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/README.md new file mode 100644 index 000000000..841601ed9 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/README.md @@ -0,0 +1,51 @@ +# ESP Secure Certificate Manager + +The *esp_secure_cert_mgr* provides a simplified interface to access the PKI credentials of a device pre-provisioned with the +Espressif Provisioning Service. It provides the set of APIs that are required to access the contents of +the `esp_secure_cert` partition. +A demo example has also been provided with the `esp_secure_cert_mgr`, more details can be found out +in the [example README](https://github.com/espressif/esp_secure_cert_mgr/blob/main/examples/esp_secure_cert_app/README.md) + +## Usage Guidelines + +### 1) Include `esp_secure_cert_mgr` in your project +There are two ways to include `esp_secure_cert_mgr` in your project: + +i) Add `esp_secure_cert_mgr` to your project with help of IDF component manager: +* The component is hosted at https://components.espressif.com/component/espressif/esp_secure_cert_mgr. Please use the same link to obtain the latest available version of the component along with the instructions on how to add it to your project. +* Additional details about using a component through IDF component manager can be found [here](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/tools/idf-component-manager.html#using-with-a-project) + +ii) Add `esp_secure_cert_mgr` as an extra component in your project. + +* Download `esp_secure_cert_mgr` with: +``` + git clone https://github.com/espressif/esp_secure_cert_mgr.git +``` +* Include `esp_secure_cert_mgr` in `ESP-IDF` with setting `EXTRA_COMPONENT_DIRS` in CMakeLists.txt/Makefile of your project.For reference see [Optional Project Variables](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/build-system.html#optional-project-variables) + +### 2) Use the public API provided by `esp_secure_cert_mgr` in your project +* The file [esp_secure_cert_read.h](https://github.com/espressif/esp_secure_cert_mgr/blob/main/include/esp_secure_cert_read.h) contains the public APIs provided by the `esp_secure_cert_mgr`. Please include the file in your project to make use of the available APIs. The file also contains more details about the available APIs. + +## What is Pre-Provisioning? + +With the Espressif Pre-Provisioning Service, the ESP modules are pre-provisioned with an encrypted RSA private key and respective X509 public certificate before they are shipped out to you. The PKI credentials can then be registered with the cloud service to establish a secure TLS channel for communication. With the pre-provisioning taking place in the factory, it provides a hassle-free PKI infrastructure to the Makers. You may use this repository to set up your test modules to validate that your firmware works with the pre-provisioned modules that you ordered through Espressif's pre-provisioning service. + +## ESP Secure Cert Partition + +When a device is pre-provisioned that means the PKI credentials are generated for the device. The PKI credentials are then stored in a partition named +*esp_secure_cert*. + +The `esp_secure_cert` partition can be generated on host with help of [configure_esp_secure_cert.py](https://github.com/espressif/esp_secure_cert_mgr/blob/main/tools/configure_esp_secure_cert.py) utility, more details about the utility can be found in the [tools/README](https://github.com/espressif/esp_secure_cert_mgr/tree/main/tools#readme). + +For esp devices that support DS peripheral, the pre-provisioning is done by leveraging the security benefit of the DS peripheral. In that case, all of the data which is present in the *esp_secure_cert* partition is completely secure. + +When the device is pre-provisioned with help of the DS peripheral then by default the partition primarily contains the following data: +1) Device certificate: It is the public key/ certificate for the device's private key. It is used in TLS authentication. +2) CA certificate: This is the certificate of the CA which is used to sign the device cert. +3) Ciphertext: This is the encrypted private key of the device. The ciphertext is encrypted using the DS peripheral, thus it is completely safe to store on the flash. + +As listed above, the data only contains the public certificates and the encrypted private key and hence it is completely secure in itself. There is no need to further encrypt this data with any additional security algorithm. + +### Partition Format + +The *esp_secure_cert* partition uses TLV format by default. Please take a look at the [format document](https://github.com/espressif/esp_secure_cert_mgr/tree/main/docs/format.md) for more details. diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/ci/build_test.sh b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/ci/build_test.sh new file mode 100644 index 000000000..7f02264eb --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/ci/build_test.sh @@ -0,0 +1,90 @@ +#!/bin/bash +ESP_SECURE_CERT_APP=$PWD/../examples/esp_secure_cert_app + +# This option causes the script to fail if any command fails in the main body of the script +# Note: this does not apply to the internal functions +# We need to check the exit status of each command individually +set -e + +clean() { + rm -r sdkconfig 2>&1 + rm -r build 2>&1 +} + +idf_path_verify() { + if [[ -z "$IDF_PATH" ]]; then + echo "IDF_PATH not set. Please set IDF_PATH " + exit 1 + else + echo '--------####--------' + echo 'IDF_PATH & Branch' + echo $IDF_PATH;(cd $IDF_PATH;git branch --show-current) + echo '--------####--------' + fi +} + +# Build the default config with ds support enabled +# $1 = IDF_TARGET +build_ds_config() { + idf_target=$1 + cd $ESP_SECURE_CERT_APP + clean + idf.py set-target $idf_target || exit $? + idf.py build || exit $? + clean +} + +# Build the firmware with the config option for legacy flash formats enabled +# $1 = IDF_TARGET +build_ds_config_legacy_flash_format() { + idf_target=$1 + cd $ESP_SECURE_CERT_APP + clean + echo "CONFIG_ESP_SECURE_CERT_SUPPORT_LEGACY_FORMATS=y" >> sdkconfig.defaults + idf.py set-target $idf_target || exit $? + idf.py build || exit $? + clean +} + +# Build the firmware with ds support disabled +build_no_ds_config() { + idf_target=$1 + if [[ $idf_target == "esp32" ]]; then + echo "No ds config is same as default config for esp32" + echo "Exiting" + exit 0 + fi + cd $ESP_SECURE_CERT_APP + clean + echo "CONFIG_ESP_SECURE_CERT_DS_PERIPHERAL=n" >> sdkconfig.defaults + idf.py set-target $idf_target || exit $? + idf.py build || exit $? + clean +} + +# $1 = IDF_TARGET +# $2 = CI_PARALLEL_COUNT +# This function assigns tests based on the parallel count value +assign_test() { + idf_target=$1 + ci_parallel_count=$2 + if [[ $ci_parallel_count == "1" ]]; then + echo "Building the default config" + build_ds_config $idf_target || exit 1 + fi + if [[ $ci_parallel_count == "2" ]]; then + echo "Building the legacy flash format config" + build_ds_config_legacy_flash_format $idf_target || exit 1 + fi + if [[ $ci_parallel_count == "3" ]]; then + echo "Building with ds support disabled" + build_no_ds_config $idf_target || exit 1 + fi +} + +IDF_TARGET=$1 +CI_PARALLEL_COUNT=$2 +echo "Building for target "$IDF_TARGET +echo "CI Parallel count: "$CI_PARALLEL_COUNT +idf_path_verify || exit 1 +assign_test $IDF_TARGET $CI_PARALLEL_COUNT diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/docs/_static/tlv_format.png b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/docs/_static/tlv_format.png new file mode 100644 index 0000000000000000000000000000000000000000..3dd0b15c9662418b4dbce9a1a2181bbc273511c8 GIT binary patch literal 49394 zcmZU51yogC7cD6lknS$&?vM_VZln>A?(R-$B&EB%K}x!ti-a`N4bt!qe(`_rJ;%6% zQ)};Y_St)_HRqbg&x-PrNC@}{5D*YZQt!o;At0clAs`@oK(Bx!rKD*Sz>bc&n3$rJ zm>8*|gRP0Vl`#YaO`LPAjEtxfW^i&0>a2)3INv}1RY36a8-&ypDUh%S)840Cr`)AAHc65H*PhGj}d-BrAP24WT|X^V(fd)uaGY4(x7#d@8Fe|M=x_)^nw@=ouCl1z0ES!LSVPK0P7Z<& z*aksBhMGgb09%m24SO6%uT&s^O#|C(CDKYt3Zv$=1-A$<5mC#RP)ijStwgHg+-~b+fjz zapZFoApdg(AF%y$n3jhz@i8;Iy1FvCvNPE_m@>2S^71mXuraf-F#=aGI=b698MrapI8yx8$Up6f z8#@{~nA+B>zPX5x-zyJQaPh&Up|Mg_!`1fN056Jv-hMAR#h56sM z0aN~$qkM|yZpK!c;^x-C@Bn=Xa&WTp|GEDEJM+ID|6{4~KT9r7j{jQz=gj|Wspe?x zAZBX~bm=7czc=%@@qbVLZOG63^5p*+iNA*V&rx8U1rhj}|9xkI2wC5foFE{CA*94b zRNWvCGhn?`2QUUgAw-^<-}aF;!-cLXlWN$x(!&&KWH)0m_vu2xxXxqK66ZIIO>V%Z zK0i^lZEicbwt$9o*?M-47mho;R|S|H>)x^}c_qe%p`t>G3WGq9WTY@beyE@zKQYqz z?b`qQ=trnro?$qVf3E^ey6AvoTES8X@PAwWX(nugChNcZAjmRM*oGMv744gs*8lA) zJkRUZfA?X^$w|ZW)Kcas2b74Kt5-EZ;vv zWEBP6R3jHT+2O=gp5)%s*%t@6Y9w#<=gSYysly)ZtC#NfY2=?4f> ziO~8Jsc0F&P&{>!YKih0qBWJ&mtMQW-CeVDuCtB4y#6SHnfXvf<_C?_7vNrU*jizjuspCR@yyvw)!G)W{Z_51ob<-+!tFM zi|p03TAgSUnRHW+SK0~I7Jt+j-L9C=6c*_F+y*C(wK^X-w3MoqP3K9*fWRZLh}fr( z6B%y@22hCk*Vt@V+SZLoNJs?r>P({6HCtUz~7xLlX z9!pDJdh7GRb4_HG%55v(pQOX|#`d3)J&c2JP>T?kh1$Q^J=osfK3PwIooaGE06&ed z3(KKVn6{i;>`dG)j(%nL-t3P$xZj&8f-q(`86BKYF#Pq_QBDT0ehw{^?& zY(qkDHBS;npHt#kyWPWi6`fN0hAyJWHt-da7a|VRq37wE$SNfCtD9T_&atC1hTIP6 zg-hLUE{yX(8!SKgdFEAo8v1fe{MKa@=USZP`QbugmFTUDT?TMRw{(_dC!49t7Tzbz zEjxh^$YcWBm`TYz*Yoia$>PUlOBE#4_= z5Y?GZjH^##(kkCny^;L)tw#FEsx2+}c~>3xhoJ?ga$3GiY4m=$VLe*y%);lgGW+d9 zDU-yZGm<4FWIofeICL;yRi|7`RHTrV>6%FSr77iCh%hS=yUFVU`Ha+<91hX!wy$6K zoc9$Yuo*!r%b(FH4Jp}u9&QT5(G%XQKv5IRC16dn^hG)xNx!+yV+HTAJX?^D_bvF-~n3&q;7$WV!Uj@DSw72Xav88z~FAo=H*4BEk zIyyvX19Ly$iwy-y@|1@Z!Vs@`Oo0vd=j9BM3ZHIzKV#$x?w3PvD(aaVEEf*b{)U?P**YRbL1XAP$=3XVuk3f$^l%7LYAP_9J_kk zrE5s-_1%?a08Uehxv`r?&mOEa#;4o!?MuKVDsS|Dc8{PnkR@Z*YfD)>1cnII4d0-e zxqJ!%gzp{4J8qusH9i<*hH9PeudvvHAVS+n*m2%!gzi)XW8`Zv%wumoFQNZh?{tlk zWw#8IPY`7%1@P-<9m+hncgH`!-D-FSUcm2XGcEe{L@D3gu>H2za~HW#e|~NE zZ-iWX_5ZAS;7oU>U%CBj&tDFb|6B$vq92q%7&vnHkw5d#ih2psozk`0HO=LACYr_ygx)TEJmQ${6wGJ=law#$C zU`q10w0qYq^_odhzqFd**Z#!f>;RA3#4#C~2=&rCC*(qZ1)IL_P<`Lb0A{KD`qbrQKef>AGcx0e+QW&eOuAK>eP|L0a(0rH%a4u3~lU9KO znAb!Yg9%kk5>jhc=T`%t5fk`jfEZ-)t&{q2OE4NC$$b5U5ZQwJSVnFCH^{ETvC4k7 zcx(+~$9@$_8|4)b$ufrAB2td#1sJxebru822j0Ep19{LCKhdE?Nzc)ES{;#pcD8-h zce~?Nfy0kR+#2f_jwC`PXih5X9M{V^;65SnYroq;qW6zF_`sGv;}ZJ`oK88}Y+Vs; z_2+@`fpOg;Ea_9@yr77cb$2|&@ zcAW)nyff5W_lE@T#LC4u#`Lkb9+P!DRj<|FDQJoFW)LVfiXshquVLPu_u2B@ZI{i@ zmiMp(%waB33o^fUCKm8{XH((x>o;ACOVP|u<#_|_2-i%kQm0BCgYyoq1$aKt3m-av4T#t;X;F~FHVbE4Di z6xjdN+Pf(x9cZd0jY@X`z=G^_{;PRk6k;CFWwJ{Qr@Cbj? zOux0y%n~%e2^yw+4CE0_NFK$J&;!oAKUSSdp5W!iwxt%ADG%0Yat155PvJdb`AvPSuAFx$4ek4N~t zPyRBTOe=noY?CVhCx7m&A=Bg`PYwqs^tS)Ibtj&yR5bARtI2@%wK)0l{f9p}>UT1~ zs~Ao8qRqYiOLG;)WuBUn+K9S^!cujHcV*a-m##$Ptf=LQLCU+a)hV3^3R#``H)k7@ zyF(Gh;@d7>D44~1B|N(AE}=z*5tw!xeANL-3`xn?w#(<*o?ppg=t(SX1r;6(Yv~gh z4HfYlEdPv^%gcoRW<((X%x+d2BnIY#dJ18U*w*dv#$4dn6phqg93=- zRknBq-@D7NOm3^$q1|-U*yE!@2_eBw;Rk`bT41tGNaVmF=++Ws|4`>iy@*aK`?|dvkQ<+?H zCCOu^Q>S1^7gDE{Qt{Ouv&5UXV1&%91x zZ+NvyPA@+GW%&s~*6@Tp>euY+uf`eBqnB*o`=B?ofOQqT{ZaWxmLOqGuvRaWOH^D}k3 z*fz#QwL(uptKJaN)BP>Zc;8k08+l>+oo7+N+vExc7M=0(%x{fm#&KEk7Go+u6Ya0q zk|$3jQMNDm48y*-?igXr?X$vMkKl^65n4hUf<_ctS6~Q9bwEEhuOph033ywYLlK!B zxv$*sz7XH@=Z)e`-=+Ny8Mp|P6g=F80@EbZ81RSV&-t&kKMT7a3l_@aDXU!WJ{_Uk zuC^DYHIXRpCk)XTK+UYI{JJCG2^JQoTx)kl=WVI1EgQIa7Fw!oWy<*DtU&%J5)dm3 zZg?`0xKp%Zcd8*XcWgCAeffu)a@q*bIB&7HhvSA66;!eDdGH z#Gi$lG~6hKBAEaI^500*CHOKQvo@*P{~H5RfV_!yG;RdxzcC=|B?e5`$Lsxx0e>}1 zItrNM{up{Q3WwgB)L? zAg@D9&VQp|Jb=%B^V&>X{>MCs7clQ3Y*|+Pw{KLa-!C!vo{)R5;Xmfx>43RGw2lqU z|HcFI{tbXly`$4EwfiXYcoX?2ET6r0GaE0BIK2P@BQ?! z{jEOYowv959^mU&E4lTQ zJAn=?R--x=3+CdAr74V_d&7*!3PW^9&p{eUC*@qEWzo1%CBC{+bq`=^8EBX z4I+$B%10r2YAEGL5V=k3bW(}M>T;LiQl6GgG~X*dQePcu&MvTje<>!x=ecgXNvBTo zY`+0Tbh}BIJiod#5syRb_~bD=(yi?(rjP7>(6HKlmb)3uMv1m@t67?~er<_V~V(s?xjzrf9u}x-S~S=0v-;(tT3HRZ(C) zN$TcDuT4&Z-_!RfBqc$P#M7&$^BtQBj52&$Tmyl`Lhkag=O*lx7IQVMP3D^(D&e0# zmzUB9k7A%k{C%%bWNSJ+I6!oQ{29H37?7kE8RyiTR~0xsNv=FIMJn`54lp7GF0mwwg8%%@bWZ z_ap^|%%r&zlBLg#gjB$lIL$>b&zlg1)Z~6X(C>JVe2Iou!T5?t{odwVLBSj*=Z1He zdx%K*tZA8@H=$|%Y(Z>p;NwTC)CPv=%(k$RYzAE6)5Gd&bEpH{JH;kVUqLlBO-b*} zj(o|OEPKu6yf2oneBQ^U>V4Hj0_JEh;rOw`PM|5~>6y(3vcS1?=-QctCpeKyb$8m6 zUoP!vD5<@Vz6pP^E82&UNvCz(cycEvZ)Xz7fLW7(iBhw+HL;h}4({(l>`t^w9D))yo zUOy~{ofV;5;^q&b#6~wQr@X1(+$gfRe{s2zh<4+@1U`j z1=im!>EGF8HT-PZb}r_Cz$;3q@DI@Q=a}3!R$^(2ztO3~6|~hAat}49RR%JR+>rcy1>j@B92He&mZUXX8v~r*CkS%HoWtztVa@6P4AP;Da~okML_mKG5ejDtprB z_5_i>`()Mk4UPJh_Uru0qy3p&O|eAI3x#e0S@_J0Yg*`Hx47leHE>2~0;eNi_hl{B zMY2^c;M*r5uCcu=e)u(FD%e*n6r+fIeo2(B3xxN6L4u(-TGDGxKQ<~xv(5?F45RO_ z*73SC;rAJFS!{^fT%XS^m2a7hr-X!KjaU54Y+B@5%T~|pz!dP{Fsa_@f*0ep`zL){ z3PC?w%qP+JJ>8|HU)E$REWpFKn=D~ZHV3ygZ0XS8s8wi0>PX|{wsMZ(^%H>mEU+R} zh78?HlzvKI{@CHo;5{kAbv@(_sa$QF$O_C2b~sn%!ZeJjaopS3Ca8BA!rlK-irjD@ z7;dL8&~$V5G%&NTkl8_cGQvGqcbOx-9X?%oHM4t>%sg9tMfxP0dQi1)U>y3XR7()% zk5_#E4nn=cN38HdC5C7vQH!$#%?e6>fvq~A*87?@vr@0YhWl!7C8+SBad@(Dz|Tds zLfJkXof2VtBqNbZUVnUM^4oP*_I{#F@wr?J112&`L!%P&J#t1akT9Dq-sk}noJx(Y zQFU+RBZ=h^KyOSGIqr<+W0pVT;pE`&>$Stl85fYNkK)!#XcAJ#?0?@;yopklHkI3# zboOBwQLnL*9ulx$Oj}xLy`Vu-naGhFdUoG8^!uG$u_96szMW@7w12@#Bkg)DfS`y> z{SIkQ9BUZ6kfbc((+C}A4WCewQ5h*FYjuFJ%U#e)kZA~}+Aug+hI_YHf5qt{9p^EY zi87H{B`mQU$Tn-C`eEm^lVr_l?YnQvi;JY=f_^b93JWTo0pAVHka}r7w%vGpO%cwEc<-U}aY`xx7i3<#bHl9e$j3yQuNUn}{ zX_zNo{AT{D2@dwU^Z6-HQXy06Xy3Tl6OP;F#J9%C{&wVpty0bduN%oSAyJ-XQ+7dF zQ(b}k`7W`SO?TLFLS7ib&-Uk(7`dx?MNJoR`-F)5b zn#l#=kbGIuW>q$^WSHtFzOH_s&R}z8`ho2QZ-~Lhmb4s$!C4b zO?L>XgT+G7zH_2&{@p5fZ}xO4qOVQfIO?w7V$Rc#j9J#!QinS(!pcG27k(obCngdg zfjU!hd+~|#bfGZ84lb1DVL9b|zVQ1L_A%s8>_B4EVp>dXz9u@2ve31SIn5U`Z|R;( z26=4e)B(G(+41jrMJ+;#_+)nlplT??(s?oiR$sL&!Rz}-Weu{G;mfzl@Uiclir(2bLq2OxIF$6@J&*)j;whNfsX&k>39IL*D5Tf=w%re z`{NveBiexHkMTqac-blYiGR?clU8jrR&^@dS*8NZg zXQj1@<~jN-iD6f6{SKc72tDrYggQA2Mw?$pAI!UuX-K@FB3g6ruNB{-tNUzMe|^2Y zT~O*#r5+ZZYV*EMyFyK3GV(|F`XETs~Bl#OV24VLIu&3I5(csgC^R+g2kG8RS&}hkEf`p6F>>PBl zEUcx(awH*CX2>!!xsK)XJQCf;2%l&yq3G4up?KYhjP?&XZ=7P}k!UrigNFSL>K#b& zy0Ina3%xbn17KxshaAE-x-4g?q8~nIsPkRp4ShGnCNmBcaXkp_@yJhj^1(@-EC z+%yy<&NL3p;SZ$@Jz~!9ZF*v0>c6+47NR6f>LXn6S#tz9l5N2q2OHUIX4}HV3tt1% z=oirET%J6uaC9j|`?8ZYLSy>p46j^Vc%(U-7be zaT`S8CqS1|h@T#ykO(`qYdE6xADf~L7nS&>ias*>xa3A$o;9{v>Kc*iAs)Z-D(7acwIBMxRXkggiF zJ3RF)RF&W4?oNZ^=En{m`!uG(qqEAroyX_(U9*M;6d7z{{&VsNA72~v z^$Chk$gRRLc)C>_XGytN8kP5mbsu=Ly_vW>+EIS571#O?SY$x;gR7uYq&w{ce_@RQcZm_m)AXTWRA~T zPuY4RXeuiwN&8~oWs>_R45ajtg`_#Y<61~ljPJFW8&?NkeLY2oM+d-ZV2}*LUvOF2 z49%~n@2vfT*JV@8_)(M16Ia1AMEyQz0ohQ+PzzI}!GMy#)-ifvZ+&eAM;eVGqX?M+ z0fUma`7yyGE)9UMah?y`dw&r1x-^94(P^!-e~%neg9%#I2_?ur55@7K{g~ni!9N!D zrV*XG{;QzLSDBf03BCxG+MJTa1f|7jL27J@%L z?~NVTt*C`yuamgmr}mE-r2C{s5qi~)C_B$Q_9DKiv2uO00^!Z|zZB^Py$P`$wojJQ zjTX}BX$e_l1M!gg3-c|r;OPXnyi}4$GocZKuHeI86ADH+vcMHYCtyK|P?D<5iBM8) z|3wY>sr*9PpGlP>ok1YP4tZYAj9EX0*opHM@;;YD7$*gN4|o^@h33Lg_eY0<>qtCk1nF0h;gwuHz4^uubT-Yh7i@ zhI=wFz9f;TbRYxUa;!+nGimFg?a@|<%tde`*>;fdN0{CXTwJmiroX5GND%4l>o(=H z@Dfa3nutZ#^!KAu?1^~B0Ma9T(4wz%nsc$3s}EW5n|dDuCy9U5w^FUOU8N0!GO@QD zR*PjJd<QwG3`2|3$nCxaP@WK1WXD@50=W>Yz=CiL6nLBFl(#z`=L zs3E>Xhf08>$~?GM>~oMX`_2M3s{>TbpT3r! zBHkO&hCzZ3h{~g5k+hL(scQ;Sf+%M1x(tkd;p-_rTn5Z~>d6c!MGaHJ^G2QVxvt~m zoGH6!nab{t(Qf~eyI)Y0(~bcZ;p}v`n9Y>JtLi3Sy`y*A+h;^Jt001NjqrSZyp)>S zs+N=UxHw%qx5O*lY#CKs@BVEybwX|l*>Sj^0dK~^?_jp%i^H-+{679BI=ujo85J!3b%aTKTS#oiSE`JsPmvr`O?A}%$o8MaSV|5Z05}jiR?)cX> z7ivyh)iFaHCL(>Q5Au~gKHIRc-Q z%r8IAabVM=#i(la#tzSzR=t*c@ZMy43r`l0SeU<_DB!zCHI5r-WF(@V;3JSawG?`P z>wGdzwbV&bHt{X#xS<+=RXG6k~p0Wg;QL83c zi-Su@u0k0(4Qq=6obMU>O10`1LMtD$CtnJ^l&fqe%>H7brq^;oqwx*ZT@E?cU|LkI ziM%8bj@?L-hGcK|m230i-P_j#@B$mCkhFt({3*h#!jbYji*o!Hr&7>>z|Leff(h*PfA}1!{!Cpg$Rmd}W#F59!IW zP#}$&^t`JG@#6M2LR)T+ArYDa$n*3Aye!D9B4&7%w$n-`B@X7k7#zt8`^eISrn`Et zV}L55p~?N`{w{J-Y|n8ncf>-VxFl9Wi+5oW+5hw| z^ELcSjUp&>_Ad?|GK~~s8^NBKQwpeRog6QFrUPt-yxjhWbu0E1sPPQ;c=gCco*w_t zMCD@XZ2cJ(zKJ^FsWb+UB`K^#nl*FtDI7+@S_gX)fgVl2i#T#$7uIn4=iZ35CM@O* z9ob&Y$9c~8=W?XxQ&5XVyv%S3<;6cWH4tPP1&fJ>>0^V)C`I~b=m|(=rzZ_JAQ5i+9&rLS=?P{+|H0^e7Vb*<*3)VXaPO-z))B`FqvR9|Ix){^m> zP1}IRQk$6G$o)xUI?#)^76rOo#n6($bOkH$-#$96PdkTa=8OAvRQ_HRGq!X>uv?ji z=c(*szw?BLiu+KuszMte{^JBFJD1KLi5O8a7izl_r?xSkyHJocHbB8q^v2KD?rUf( z&^OsHk>Rfy@O9*?zia%h@KQb?={b3Vk#rr;xliW4K;%wicg|kNU1vN+{BiT40z1!Y zM7~p1ON;ufZ&5jTI1GzD#3j7xhK=J|X0h4Y7i$}+Y(V;d#-N@CR4+%_MIr~}`~W9- zcXML>&}#3J;h-obg=OhVu}KmtV!7}nO`&J}Y_O_eE^3nI->!9j{b}8yg2z!d%|vMW zOl4)ZEl{!;LM&1a7fP?g1Ec&ms=QgdG@1MU==R6CWa-}`FE@-^WOrnI{^|1%83n|X z*f;iGJvDiGd%+v0uf$oj9~|akZjECe?4wh64HM1h%NNK!1GUStXx)=aVPppO96un< zeN1G~ZJ^M%1RJCv>>nhL{01r;K}H&KH4-7O%%zIq5TAAu$LG+(w6}rmmeKvLE z$G_VR&74FwLCA;w3+ni z(Pq_jePkVPNx!?> zYzmqU3<`Jy72M(y2rcWiej}FOpICC!KFkHiyG%6nHJ6;GuED7GjPpl;vMvJTn>;FR02?^G5< z3g!P|;lAnAsQ0oQPNqhD;iHG6EaQD5Fnr{1nNlFZE=r;6BTY9L_5SdYuf-?A zU$s_4Z-22PQ)qk0Eiw)PO&UDS>jQ3U9eZ_pjnjQ$He$Nc=B+R&tx|5sG`E^s&fi0a zo4&)<(fM@q(07nP{lNrzKJcVNK_O;x!1viWc*^Kd$3gvCa#UKS)@}hCe{Che!^Nf- zm`VqMJh5w4@VKVqu^}Vt%hiz9SOd>BqK7R$%u!dnq5$u@xh;N!{CKe?Q9#I4BvBVK zd4u-zMUNm|)80F_J@^~iT3H4Bks6)##l!Uyen@jGMKF#y#bHbsD6~;axU%PdX6>p{ zR&lsqG2*l9Rj6U_c$#0Je~7sM#mgLRtll9@rWaAS(DC2?L z4!Ldjv(THrK@Sj(1PqYfLDb9=Gf<<_T=xd*?_^}BGYUder|Ug?fF5=EHRd3o z167&G6fj@w@+ULr({MJh-sk?rH!m^#J@!+aNThh%Wv$@~NKmK7g}UfLj8MFnOt!K% z`x8J7V~gbXU%1}|1Ztxk&IJr7j8;v<_$XP%&MT*xaL&av-Ytg=bh$i;p(EgZDn;mx z+GbkhYl99|aO~JgJa9RyZz*_Q0u@J}eg<)wV`>SQZFz_bTmLm49%U zL#9uL5ZqazHR7J$xk;BqFP)W`iwRIoycAuMcS@oc=k zY`fNN+}ijA5Csc#miylt0N6c>xZU+?By{;3hY39yrcOOv#P%h8d&>mP2i0IkQSBSZ z&QHHtNp6J@6SE5o0nYBXmzPTyM5lF}R%=3cT?E9yG zWx|||qe4Neh}{HqGpot0lLO+7elVN{X?^l<#T2N3PlKDo5obi`*qh8u59=Z;OMw37 zG(ov`)FLWscn?8DUdyWmOKGo#^oBeLaBd|6I-$m@3GZS-U)N%kH999Zt2>G~uV)h8 zU7qM0Gv3{tQ5YNp# z6nUa#qCRzYPa#QDZ0!Lhq@RFZ_|-NOSiE4mOwx1~9j*66Tkg|pH+~`ShQZj+9!Z53 z;+1f0z`q34Dw3|po?TykgF(yz&<6Ii?TLWf7l16aHA5`9AB8V>(}J)mvchY|HBkV# z!=7u=l|3X20g`C~e0nRu`#C;#x%2eo%O}q2$33{$)^6MPgr8Ym@q0X^cOEQ?NSSt? z@Dt`C7iQN4tGT5O@3nhRur>l)H13rjCjX6^*T&Gh|)<$ zet5XCZ}!?x@OkulydxqR(e9-n#U2RbF66or5A#+pm4;LQaVnvvA;%0W$?^!}{(doiKjc^>WQ%FE$dbU67fy{UmlhY4K4-5u<2;m0YdIDXdo?+FT5(v)s|BRZbR z&mDcn+l*T<-90t%(mHO-+$>sBU*6=HPGs7%N+!NTew<~9c6Dt+DsLUr8^D)jltFBK z^x(+Dw`m9MU7^z$Lk%xHG5W|;WC?l~BCc@LSQa`tUEL8a*4Q9axi435qiR0^lA%$R zN;9MPom>y2ir{J!B@DZn-U@jMi>aYNB8O}a!&dOLD{KPs&dc*~xp#_vw$;o+8RHKm<=^H_hcuHjp*{Ka>7rTNNF8t1tX z)6#lxUT|Z;>5RPPR@w0?k65Udh>)=Ot9BP|a!P54l@6~zOAqw-a?~W9wE+mIG6mwF zffbdy_p;dl3$FAHyWzE^#!R8qxbqg{1{!LFQ7^%aojbY4Q+0>bv#8`LWpK$VKyQ}l z7th_q7~AoIPOJyNs4dZ?-fb+po??ElI~|(Y0m=ztnRG*G^oYLZ>+{Uu`7Vnv=DCv2 zieC+JH@O2i#J$R%I>IYK!Zhe9Y{m%fp4ZXYEH4V*<)1%?1_nak#SmBcfclX7-fGTc z78b=*$#*dyh8E__#s#GXhB6g$)G(cG?a4g&`u67RU2YCW7gKy*m`!L{$pFdx6?$~nXa6qpYb6Yv+Kcd(j=e|_WO!G1toUP`Ht#cz#Safu zUxU2KVzLYx)8CN^EF%1=tfoi`U)Q{nU9NZ<7ful8RrHNpiq)&ApZ)!yBA7+P3VtI$ z+b4|-rlEoup&swAKM0w0C<1bBH#s9Wnut5o@2UN<<(9KeS7T2*u3QFCLK3(&gzMEI zC5LQt4~FC$&!k`>Lkpa7Y$hR>9DUQut#FO`Fk0213;!?iyq#IDTntH;*uD`MWzUs< zl*lT5c8cGXal&3g#BH$GOfz%7dc$-Z=T!*a7i59{QwN*}(9gzSAH-_3=43DoC%OZ1 z$Jt^Z^nI7RH}8js=0tpK#5Sp1KCbt=(lG4p;xKq3X+4cn+DA5|xY?*|p!WGEpRM7O z>tfRGatmZF(PAhl^@x^fzQyQ`83E7gj7RZq;it!!&bt-`?a@2TRPS#%Leo1HTK!SY>l?7E9K6txxU;6x<8GwOb^%4*bDO@vC`F8kY0x(Xf$(te>T;q z6r@9Z!|%shD1s&P++?rd_R&&CW3&ND0)riYZ??Yd=^ONCq%WV!Wj`pmD<{eN$kUra zgWvU51+l@x?>jnDV%VmL*wZb>7Saxo(sZE876fK-TGr(38hnKiE!%@7b6L|cdZ2(B zfv!LKz>iUQx!L=9dtw3hd$&QN1h0T(5Yzt83i!E7y?4I!3*2I)Z5`BOP6MSg|9;bh zstUD!6>Js}ZuIexymbTj$Hmgj6`-puQ`99GWc6^;>h#h{aRvlDLOhL!nNdC~r(`Xx zZDnV#HS#{c$I@uR!w=wTe+-c;5?eBXlUYEC68xb}uzn?ghc5p##!O}|^%s@#qJmn3 zVd0E&_C``=7^+U7!%CmiI`ZWKQ z0J^Q_eNmq+$G#8!oBLD;b@9T;vyrcYNQnytSp6MQMG-X7c|MT^SG-?)k!_{NCH(yX z69p7VGS3*3btM{5jl>$isZf#gZ8%=>9d(WkQDwFR3lsRJH)jitWzL0tzy$~V2nm~p zpw-U9V7y+&J7fZ?Nb?NT{I=%|YHH=ZM^B3{;B)QFiUCmU7SK6+;%1rH*vY~pieRT% zTzQrb()>CJQIvJ7?1GuFUAA?L$n$0_$Ope-gW)viPN*{Qf{GZ0s`5Ij3v7kve+Zbg zJlbm-Y>zsWSYtxx0RRWI=^M(wA2AGKqj=>-77dDy;)z_eFXD1uP}*2kc&gwBqyjr@ zKi-R#CIgyBhhiMY{%jW{c-T7>_GdVKdYr{2gS?&6w((@Kf`z=dJGjl+-~R}!8$NFL zODh6;o%9b{DtbyNWc^(w_K$uCgx@h1YP&`G%KQ!o2`c-lIGh!F?U$>)+Dc@e#`o@# zB+w9?W`2vAFI5^53cja*Em2>hjF0At-cqCOL^w`s)o@VQcsC(G^NJ3uLK?+=KXQ-t zXTu4P@yM6xq_H!WxrB7~moLW9P-*v&0YBu6x!qCq`b=n_?NQZcKh>}oIrl}P&bNCR)8dBEAD{7Y(q+Ezbgbjnn8?AiO^|Bv zVM@rMM#CusDBuXw*1%h=7FxqC=QQB6V1;2*2Zs5uZCT1{HLD}Mx{L<2whR7ud(tUT zq5VC8H6uUn=>R-_r>7a5Df7eFS3eFovU*5Lh4^1Y0x1j5oK%~I4BInxIBrvbgxqo5 zav29K-U|dN&%-L2S&lP;MDdMSa6;$NY0ZV%)|&imr>P@yYc$LIBtfJ8EF!l!3XS`G zJo<-*2_|R zvWCB6|*i3on3S zHYk{LoTABmdWTIixZPwG-Bz@3avJpP4LhF0Evz;zoH^W+0S(2YZ(J4f(gPXIzl zib=m4u#iF{@2x9|XgUXRRt|P(Rm<&c)YA-5SbvnrGo* z&(9)LEv?w?I(`dy7-A0#isfu2SP$d@6S-wi!~bnZHkXqF~dg@EE??8u8mODu=h=HFT$lI z*Y_HcGZ1(D-Z@xEQ`ku?`PxBOsFtVM5b7@W$n|n8kOUgIISCZWO(tZcB?-oIs1RPy z>z%tDwbdf2&bTIPLFTq@@&t&5*E!j#@hIUDwEokD@D4_uz9-ysWf^t#kL3(es5GsB zEK16;280UUd6VuHfEYHoN4;_t6ii6vju#UBq~O4aDb!C4E4;JPm=osAJ{x*>fC zmX{wtGXUBe1zQW>UIRJlbQ(bgGNX2UFcg(EZp_`4SwEO*8G<*ZhKaQpow0Ovw!DKF zlXNhzOj`~4{6`x~Fr&AYkVJq&&}l`ma&gTHs}jg>~f~@P&yI{0{#x-WG(m zGj~;{8O_~(R#V6$qJmq0sURsH+{4`LKS)SLOwBglUJq~4`&rB(J+~*n^ z4~^-uB|Y(I_lo|k!~{?zAd>u2N^8_s{oD?dM9EXLtDoZXsDG$2`*&^1Q?p1WzWWmn zVZznv*pln3P;BerhU@GS$U^IN(twnR5%rUg1@)?DUi`s_1z=G@ugge46se$_AbA>O zK60a1&EK8#N+qWs3X#b0SrdJX!egk^8fM#I^}C8{vktw-IY)NExboZPkUcX2im?(X zb0oCdSJ=X`x@j1f*Cn;2mect@So`d5_5E4IZ5F z0{+yd8rU1~QK)K;I`=d<8=tN$qphWuhW^;Pr$iQSx*8Vu45bE}rPy%U*73@~Jd@Lw z==vTIoR-VNC7n;*)CKN@C|eJe^v^yTeAlfvq}NVa5bZFbCVMpcgbhTJi`|jBmyg?M z;p;7w12c72$C(d(nfZBsO)^0X^2f9k8(ql$TN=LZ`0oy zsBN2DaXGvV%%!Fk31fz*j!9o&SFWmz($pMG?_}~s7c=PQ9MmA9wWWS)ULj@Jm^1hX{b6hga7%z04|f>%BmQpPo4l6 z$h{)Zgy@Q%==A4J9kekaSj;i^C(8BwU1+V1v^$_na@#gaXC5Td`YQl{t{_`T4kwI@201#=(IHJ7(7^zDC;V0Ey)*PFR0>ZMVQa zw3#W7z7bV>4MnskNkC86D6)_L3+|kAa34plfdN(4 zy18e04@cv906SQsA1G@lTB|$;OV+APg>YEwFbCkU!Vr&F^K=ir;mJK|D!8-TXelYr zsY%4bLSVTwWCBx(ihUoFdR`E5OJDh!s(7@&3hvWt&3eK=4rUF(5h9E$e|){S#L`5f zw;KQJ&S=bCbJGlo@}>6pB4b?_g;0M-6QwARN`Ok- zU0r>@s^<@TC(GvCYp*%y7-P5FcHL8NhymrBJCZ*qDBm9=s6RH4g&>Fd?7yIZ#-gUj zb=4plL4gEYMBV5L-6AYH;Lyf|X31t?1_4*@^h%FXYFHU8KjYR`+&xXdP9M1|<7N3V z`}-E=j2B{yjepAI5FPi5=>xcv0?@)FVCB+;UsEgEv0%nbQ24>Ni%pfO(cxHyp?_M) zDNNiY`GoUcEvh_VF{)ZDP?_(={f9r}3-{J{0|u#Mfk(PXgV>6!vbLD@$i!%z?4FS5 ze=EbkGHf{>`_!);L`Akfiyj+Dfg$P8Duv|O+?&aNT>lusr%L;@$FL|CpZ<>46YaNOsFdOb$w;ZvhP8f391x^@33L#WY`x-DCjX9w%6YX`#!M-?lKuW9C*8 zI6#vESgo{RBPIoA-)cyYgoVLQon|Tn2!P{BW;=y24kt1WXIy?#uF;qmWO+mzGDKAE$o zaM>nI!ph>WCiTi`4+>T;L&<*Dv)r(@vUKOhuEWiIi^mM3F82!E-$Qk=UEuJ|@R~B8 z(FNhBe$PMe-hq52vh7dNn3ea+Jmzpu=PN`4@MlS4a+-7i#9!Dxx43s0kz)rCQ3+2u zz`hWVZURMM4#kj+jxz4}_jtg8lvdR%b23k6{Ujm69+dYS#W9WVZ4!31I~dAmQS#3E z$ikg`ybzMuWO%E`w|Svofyw%wDHP#X@<6~2hruU&#JLbyfEJW7z^r10Yzr}fx0J`~ z`o0Ssmk}2wslw^^QZnqB*$q54!_P`si9|Kf*A@F{DmD zYGiQ8;O>mBj6(;6e2fM_KsNble9K7+U5y_aWSrWFDQ=q_@$-eKRqth;F50Nfk{bIsm%spS}@_vUmm0_CRAgCd)H4BZ8!l?g;LY|4|{!%Sn zi6&Rx87IZ+qV#`WTHFYF(hk^xHP-UA{L=skGANT14|2{lI+LLP2gm$_Kho-t@w6VE{d zpHhQFtyM4qO6_A!9xeg$P50hVfq|K7OlKJbwPXFe15=r4G3gX~AP({Qj6t!S+yzhA zN&unLS)f3s2Z`{u3}qAfDCILe`Y_IL!k2rG5!zPsSw_=oX9yrf3i{A`C&l(V{})_C z%3HiDwcl63@z#Kwh`gqP17lFcD&8v+AqSPvIQ>v4T*erHPe*I!I0%0iL#hc**KZ(N zvSiRK|IQo-6e=K;UkakISxuSaV>bBZbh0IwV_)el-yQ=jsDdZnbDhnSmJ(ZD%Mnbd z;~aVRZ^8W86l-PP1ojn6JVDQEyQQ{n#k-Kpx@u1E0faZJhCaDe>YiKEJGiob<~!_6Os4!k-Ly*Bgtii=i!>HSGN23#yC?57XbJKs^)R}()HnC+|fHp zw5_r#)#&pr8TK(}Yb^;wJ}(iAF|R14EE@?r#d-n64{KaxCkLzOV|asOhzGhpvEX+T z#m;60GF6FFKzzdY)9<}XYlpjLky_}(x6vuD^JGREfKL>uThDm)c%$&+>!ZX-fpk zJ9O<}QZ$>qLrjhqQg#AM2RQ+nPzQeB^EZDoQHw-B(&zHVwDpX`3=@jRU1I1LGz6{o zVN3@Y%jfBg+M;l!s69nmMf_Zu9DkBMFD|EqleA-=R z9GmcrUVwcN7}=f>BU=4%c_(GM48m||^#UISxW0GlK_3Rp>uGZX3E3@{cg%nClrFtn z@V0>j%|w22(HJTV4i}DR`}rCNZPU*8n`g+GH-;*4Hl!8q9dR#Npv15tdlSr&27y5C zQkMM#@I$l!Znzfbl|*Z+JvC5(#xH{`jf+0~fb{eT`5Hd#g4>u1t^X+siM$qtBmvst zv9ViBjVOu!t8##Ta2Ai>>zkwfEA;nedtVRCwjbB#sS;^vxH)f+X^W2+0pdKz!GM3C z|F@G|%*!!;%lXX(1@MLxrb&SA1uv5RC{R4Gn@Oo3FUjY2SUgbeB|h!{IAV!^yn``; zjkog5Z8VaNCIcGJOrcjH!2k`!s8cHQ{cIJ8@F9@r+=!kBPYdOg*y?d)`Q(z*D-Z=2XK|`A z1VjcC)D~Kt9pnB(rM#GpW>fa7TC zft;`z$*^Gu@%}SsgId%)1R_y9*iU_M(#q(>N;Y)q7X8FKprpd1%xg45RXACUulXq= z1afl7iLeQwvX(}tB8JuxgMO8v7@H=X9h<$$aGEU;ot5h7U(D;)6y-jE-$X`lG~j-_ zizyf5_&IhSW-|5+jX4!}R76bRvg2Y|VtHMmKYpotiYak&#Yb z6oYPcSaG(T%HZC!zy+_^q$Q`f`BRAn1UdOqRgQ)y%-gW<36qolNH3;!5&zdEQB#Ey zc{>@Ma4}2jq)hxZeY>aVN>x)TAD3I$nt(zLzzk*q@HCrXv0`qV-Id6oFD2RlCvdv4 ziC5#pN+)W)3+TNPP+CmI>s#m$9PIk&?HXUTuznv3&{Qu;NT;H2IY6K#Ki>F|2fybg zM-ySALi@})%E9sA2D5JfUjJu-R&|y{7uWtg|Fe`j>{J$TvYuDiTSNAnH7ZShfusJ) z7#WiZ6b`>lh0E%m?5Hl@wrV8h*0waVZQIAK1=WYi?~i+m>l*#)<`O#{T~S(%_UP>-j%WY`SU>N%$+XD#@2#+778U0 zzrD)Up$2+vg8ljZ;dZkYueTp$XrS=^jU(nRog!I5e84?;VsHat(Td^^|q>*1buk zG=1`wy@3OI>nRu;I)z+W47p7%yoofG{r!1)CqO5ah<6ZOjUv_c(^I$Sz zNl)`w`4|0V(%g^=6$Sdg80z^9yaUp*K?g(cYLR-^E0)n+_YGx;lTps6W8UIOEcj7O?ou znu0$DTboy|B++VC}Iwa2GH{Q=c14pg)Qf!eB~ zGtqzW^U%I;(A1?HdV|+LiVyT#W1?#ni+x|y=vW1x1!zK<_S3q0oB?P+At4y8iw5Zr z0UR031uXv4Pu0o*d@qgZ#~F643xRMe6vA|JWUGjP=fcCkDf9ut5akxg2iJ!p;d^8( z5O^RjUiJyfcPeBg?r&YQjjG8z5;co^LZpH8k|CD4v&!p;+8qhXO_wc%kiS7>&9oIx zpGZK%BZ#53ECGzYA@g}_Vb4V7;&i^|@+)t7?o+&HJa5-mE;xILG#&H=?t3pAKjZrI zo1<_RgG#z&Sq`Xb8xJq=V1tRs!|w)_JSUwg>Ap&~p6TILPSosY-3U zTf~yFht^Vg6Y?7T_w9S#8odvevK_m6{H9@F_>RtSMN0QuKgE6N(A=ai0?ODC)U;Tlh_f1Qr&LXIco-fx`sXH6r|34|ND#c=_Gj* z>_AksPY_H<2ze=M*GP=yP1mUcPp)irw_1=FMtQ(-Uz5fss7rKAng0`=Ehj~wl&X0i zfVzKg<91L|Ew4mAq9z!!ud*>_o>57QU@bJVytUM0Hsv`d-5QLuf1sS3qGM z%ta3*`>=IIu-sRf`tcl zYj0(=hEzg%8z{uI9uV|NJRwJ+n zjTaj2?iBhv3cVr+NoApN9 zz~DC!7+9&{y7NlQxCSRk&BL;$OO`H63^j!?^|xpPK;vU}eFZ!&ho43J5B{ej+k<;2 zKJF0aW%9KFu!_;q>28@}8rRrce0_`yLh)JFim^8KTf=xv`;MO$gwzQ2WP}qsh>cOB zxo^A_IXu~-4*?V)=4#}H-R9j44W7&`4UrtX$L_azUoa(ka%9N@v6lfHQ|K|IGMny} z?j6d?0D%8ulnvti4{BbtT^S_Si*I6x?Uj7fI_en?=>OEsDN?|_1{&=LXf(Ei&thN&zmc=SQ{eq{IH$_fv22P2R5?aGE$62(Chv(IS{~ z1fa%F7E8Ft5aGo6IA|V*`vvtcYyAs7mtd)tbh(KYk9E9Y40Z!$f|>VnY$D%|Rfn0` zxk~byC?}Bi*EhX9T15JJ8PfHxI>+hkQD2x&w<=2Xamg!OFfV3sE>pGJnixmuEC|2@ znQJqv8+lMlDj!^}?HmHt+nbydxe=u$iIKt^g#Qr z&ikvfXj}+-7_q24R_Faw5dMiL4_ofwnT)+9aPG`m;$%L6f1F9&abd!0milyLr@6?jQKR`}y15zAY^-&aX>gNygpN4z#sdx!! zqI$uGCVl)p?$Rf7WJb+D#&w(p)^Mw%Bmhusa659j#DGc+2WAd0C-`q-GRuWl(?Hxe zzwdt=_YJ?H7=;D5qcg+p6TlAWSj?1M?_q_GCd($E(alAsPRlO}E2%#jr1J%Y%G3X%)Z=pZZ^ zn$qTT0yR`owaynp8udfXM4=~EsRy;=A8T94YV2kCOKSlcm;kPhBb0>CU>m~h17VbL zY5Fy-*<^2tf4(8;ddt?`f8H)8AS_{sGRl;n&6xAk6CfvZft2namZqV^^_h(*Kn;hu zlVXthPddq4;LR&Ut$iJUs0rrd6^cXzA~u9GKEaa~IcJ%oFM4LvI3Y{RnaXm+fBk7B zhf3j%Olvj-fG=~jA3|+i_)CIw4Nd#*%`3BE)J?h@>a7iuk{i2OD07?7IxibJy?owP zPH~XX^gj8$3hzCVT2AhPr4ZM17Ju(I2q9QX)XxVsY{QbRR1>Vpea5~70BrxH;`^B`dA7r(t-R*H^dLqW>J^HgHBY0#d1|H14@F_qwlmgt#0f{zcm7R-yjSoQsT0IkWps|frQ-z zc>L#6B0Ywlc$QGmYH%FMoz5d(l46PN}nJW%UaJ z`JYXfcyd7=*q;zgRnv=RPvlqLd&Fu9trJ8G;ZoG}8f3~m0g^$&tHo{ZYQ8?y;xI5B zk#C^q+QFVSK>TjskCJM?vL4Mk6qgv6fq)5@5tBdtQSgC?dIP|+3MqM-%kj~{q>yuo zujn}hzi`!yWbIG2tO{ROvc=5EuJT7a(j`l&-_=&cod1>4@8XhhSAX)T=xi`~I5v3A zV)Mwr`=iRNt^HsP7ev|e?5!r%$+whch=Dc3!uifn5=6PdHFB?R_v{6ffc5}Ino9qZ zfU^sP5pE9Q^`~?Sb|(jD1=voPI`=1jsSp zngrxx#_5|e1E=(E?HdQq%o{ycbDzs~bA{gV+Z|jJ$Z5!f1W{41?#ve`0amx5XxIHtyVQou=-@ zXoPAxmt{Z%YF&mkTh_h!rZ&FEY25^FU8(hV9Uo8icWN6UrS zqx#rfo>APXo(HJg41$*8@e*NTON{+?1Y3R!aaVy$W#Us+-kbpxVHjVKnbW5{lb|vMGmdPc!}sLGnG#+UO~Uc%zGeh4hVXkH6zK z*<0HuG$-r7>N$fR`k9~b-0>sE){t`>MQFX>01G!j#CKVsqhcXESFr`bwK3~ z`hi+OZ%y2Ewfrv->f1A5rOQV@1k&|V=WqN+h6~oT#)_8S45#Zu+mhCQ6q3A!-Y7=6 zjIFmX{IG|yhKIT`5jm~KWwj=h`S^QT9s#!FCOTVUYU0gRrD%FELFg8cU&t5!%|oR) z{5AALe%gDa!ij)~PK{rx@(?$^nTC=q*_~LKH7cW{X;-ye&u#ENr`;o<5Sn?pYLa+7V;(&7W;Z&u~ez{UTtoBkto^6?cH_Kv0C z{XGOMSKNlErB0J{8sC#t*S&ov75_|L0@d+cRi50pb;~G<3I&z}Hj5Eh<0gxzkyyB= z6^Wof8_#QW@a9!&?+#}U!s{dB<0m0ErFEQ@7Iz__*pUaTY&IEW%=bN}+3K34C-_4W zlkt#9g~3ah&DN+~nGPSj`Y0KmI2WMB@Sh=py$2w_5I9P%ZrK=PX*PAt#zPVn(fUqz zotQSGsqvCKGBSWPGsB(uOf0jyy6j*0IUo}!NCw2S0FBGuXoj#hSDMO%2UaLnDA(`JWyE<;es<^x81qdvLX(+-n$WGy8r6q@ckaFTbnt}z-GmuFp2 zR1wsi%G3!yfpMkcJJ0t~Gc-w3^R}QJrWz$0aVb#e8sirF-|J0;`-;PDBt&|F(rLRX z?vW*tN{y_=Ymj!dTuq-cnNU>9`Br7wnI(QD@vwOiG@nC4USI37mYVd!(*$(!Wd{!B~bddDV|33moW4ee5 zxA*H`9e+;*I%ebLnc)0aA9IMnEX|E+vdRBD7a)Ua0<^twc`Cm1_fUY5f8homi0YJz z@YH`zu|4-yJ8-g#IOQ)=;a}YY`A~=6PcB6NoeMx-1bi?{1}V%=_Pj2Jo#aI7rLZMd^W^{y?{@aAHuO=MI zB6k0`2@wE}`tP6bgc|>CLZJJ=EZVTp%m1ot11rNO444ob3x4m9m;SXge@_5>?f)+W zbtPCkIFJHJ-06#smcIe{a_?nOT$#>9P15Y{a#LN01#$fcK>deGV47Z+ZxT?U!&r0s zmU6ptq`4?(_Mm6ZX?9|!b-W4$RX6x6*lCF8XE(>j;oN8))PUo3Kyk3(TV909L^FDF zMU~BHYlhFp+AB3ne)g>E#>beNcl=h?c7Z{sy>^i|_5wP2^bfgw|^LaiG8?69b&dt1#oLKF|-*c2%5-+@7 zC!x=H?sp4JW2BdlJF*5{oIweMAT} z%1tG5#3j-{%?H|j-+}SCjxmd)76Hy9iEXiAxVX6LoGi6`0NErE7K7r`qJt$s&DVlo zawy{Gqm0bUZsxqe9Myx0h3~(#uA-<@#9NtNdB%9~T(AhQU34%frO1Z7_yDWGOGyLq zDX1OLQz&qMxCR6Xm&Q$*v=%rW9x3d1=VN;jk_2jsW-|a=_Dc$_>a|cBohvCde}g%m z4L$>CSUhX)R4*LQAJjj89n_(WR#y1LM#%iBpQ4CRNpuh|CW4HXGRvseH#U~y$tXKR zT$n9J>HeuLZRh&&`0nX(v|-l%gtx70$5pq@b;dSzhx247ch@@Hgn7>}v zqOqk29+Ox6t6UoO1JYsCjJAe2^|I%66urdt_j$vk`x=|9!0u$u(b#8qsKN9I#{ncw zkMQFZ3x$pbDjnrti;JFK29@C+ugjgJ&i5!Kfp@7fCoLH2z;=_1Gc!oj8& zvm#|BpiVr4sIMo)wB(_8nfRbphdd`RF4FY`2M^tMh+mBiiH}Fn;qYFhP_=}P7%D8b z276|3>CRS~2Xc&>q^0TVxBt|O;Zii?c8Aizpa#=n>3ZZt@{-N!t)4=mFs1taih_yl zk^MxYdeY{^4(xkz7%#o9p9A59LWTgVlF4p&ydAb*EH%*-V%45@0TVuf$>{yC5YF?n zn0`n*r*Rsw^Tigc9)o$w>}1fzP9jKs-+Cy4IB&^u7P{lPoazI8%zy!2qAFRin>A_Wb?n zH%YF2h^&J5h=-(Od|Z?7kmP3FYD9VS>0z2PX-iEAh2FtO1sfYiFS|Nom+cOYsY=c> z85zm9Whgvno_}p4Pj#2(HNF6)8T1Xqorgc)#JeNn@{tf9x5>>EKWT-XG0iv8|K{FD z$L~I^Jz6x}IZlbBG!Vt){{D%>GTy82>dY7~W?Hv25*9=)ep2cla+-Lt|9$@IKz6>? zAj$1^54J&gUIvF({d{YbTIbG6^!NjvN~6;qKCiX!8QD!sRUHqXb)wmG^4^cx!7=_A zT<$ulUzt4!2i`jvOgCEWbfZr#=X>ydch!W*4+SY~CX6$a(Qlf;^Ih%@uljzrv#**n zu_xvtBsIKOKO2BLUx*Z0$G6z{hBTQoh5+`Kdov6%hwnh7u$@fBIVWZFV_#2*`hUAdcVIpn#wn2 zT<&=U*$k4bxuL3fju?vUs47&u0hUG|(7SJ{YXT)_Fy>h&IZyb)Y% z9YOe-w&-#dG}lKr>~iPaP-_jhH+z8S>~PI2THd*6Z`*e4ZF=nA%lrM@!Q9_0n4s$k ze*L)FJUqDV#KX3DXjS)XW>*kR=z8c1ILSpqLWo-DyRut{qZLx*U1YBjEY`YtSh)v; z24$O_LBP+>lUsS>V)YFC<8M8lEZa7yxm)HD(q*t66pMiSg(pzU1-pZk^f2P0~F8u`i@Q7 zyVfQ#@t^RRBxx(B`(_-?pw3dWmFs$Tw<@m}@ih|Y%Y#`t-~$b$57$S`6#@dX2}~mQ zHz$@n;p8axjYqI@1UheQ3+1H-*W3eZF<+c-2wKl~M(|rW^)WY49HIhiS{|xkx*B;y+|X&`>nj}4bm9HozfI4eYm}+T{9E4ya*a+$6qK> zS7jFI`qd516^HgwTR&wEv^Ry`Kvx)FfjCq`hH>5BiKk%MlluImcGTl^zV{;sm9@Pv zon@*cpCf6O5#diiAsblSF}!_wh*NsCo>9JZ0UW6Ka9&wj_q%@J2gExegqWHQ5h?Lf zt%jPPd3M4jF&J^p4HpT^QGYn3-w{q>o3O6a@XSV zbITNEW-gLsQoXY*IAu`l68ci-g7O=&(59yw>aE2}x%&eu-V_^8r=VMGp~7$})8x~O zpO30ftP2Fe=o3TRgv@b8rz@h+V&6&YgKX*GEJZ`pJvyR3;&iue>4O5+bQ2j7KEB&| zE6&4Cyq0!Wt$G++=rmnPZl=gEoNiz05vU+x(&&;F@ON=v^*%zmB=hmB+h)Fcw=TdK}CK5RALH^K`U| zt)!{aMsGRN*dWxDQ`odH&Ct9SSoc3#_9Q!34TEn8V=E9hPLN6^T?d`AwV!Uo$Qh8f zFzTw^6P4`G>CJ4es<`L3pRygYI5AR3mr-EzJ@r1$c+?B(BrxhqqEVZ8_cX0p;YlHH ze-_<)0*||tW#-%iKD#u&jdUlZxk{s68P665d@`xMP(W>-2~>@`#Es(IbIK|tiojJG zLcB1OL4}&K#8r1dlT@t;3(tyh+Mh8WFqxXjDbxDwkcAR>r7?qu^xG#9jD@{pod2Wx zdT(pWRyeVPy-`b6Y;Kn5M=xvdcwMapUGCO{$7U9Rrx3%K_Q~8ee?iW8sqbajY zEd8#OsdX(117^%02bGk^;xB?P@#Yj)kDtzh3FWF4)7qyB6qTW$P|$RQrBqF}D_c&!uN4rtAsoI%(uo{Ofqzj;{3X(kAOQiRrhc^L6PV z>SWc%)8OaQ9kxU!CqLU<5L+4!oz9(IP~3rH+?%38#kd_4eC!2*jJT{x9d`?_J=Xch z#8{@28daGvqaBBx=D0qjqxj>Qce~%<`JOW>dVQQZ`ihfh9I)Y z$+^!6YuDJYCa`V7Oj>;FPX9cSbulv0DyCV5VEzja?t~#do&@i=^SQ!*N$qvs+zaRtg=JyvUC?rcNd{)GT4IEFx_*m zs_acvIPkbq#a183Z)6)>Zv`e@KYn^kpTb&}Pia6F$~Mc(mCJE761U2BlzYTg_VBj! zjCqV_@}0~K+EF!r>S_E^DeiHv9H!ZIgVc!#Ml=<%Hn&||tK${hO)aol#y4l$N*Npl z&mQ#hO&rx?qt@=V^wt(#1|pfaFBcYk*7P<#rN$;xa&~OX@NX#V*wo}HROMt!AQbYp z?5D;54RwM(O0Dh0uZOTW6$gS_u^qwZ`XHjYrB1Z4*OyXd4@-bp=O)@W2C60u7c5e% z{vdgeMW=-y8AI8U78%>Jyc#$e2c{@R`4+zCheM#qrPl}EYYZ2XPtE9)slRKzcqhDe zz*?}5tOUN1gcVlmiv)?WEXbOq)~}vHpv!6!J>@OCJ^p0T*_?gqIVg|B>SO$NL*^96 zU4*RXfT2iO}6kcFVZ%X0IF73`0Y;1ifW3|eFK56LUcF#h?$dShyye-kiY3Ort zUx{qi-OyI!N=X3=xHId=7C7m1Riz^9dof_ zVR#|C(jU$E%iK7+T>WgNFm}4qJfATwHuum+6GCU*Z0emrlhnsfi`%pA=Y|~e9I5cU z$5LPKWtUGC-F(XC()2M7} zyUBF#*_JiqyVn-QvB3`Oh zV-O+%UO*5EQ(njw3g@p*{9l`SIlY=pE~lgUUmk$->M5I@dNcnFh#(d4lwL&>2Ks;O zh};LP@n*eMJnKIb3?K*A_)H0F81A3>bu$9<VJm!f70rO50niX_J?hw}8Z zm2u%e=0)ZJwjwWTrmyk;Y&(yH0_(d-j=BHx6)zz2`&dt8@bjPdVmm(YKmVt(zn1O) z$(kiR_Mi1a&OSsGTbhJwuJ+VbKZ)N?9C1I2&(yI%NuTU#E_jeO>v?duMatgTIX~rc zpWDft2Cedm&tArVgb_xKXEjr~EUeeL7UA#~Z)gPHz>+TfYVm}JxzwUpD2h22L5uyA zTz$CAky;gB=#0&vO@aoSW14)1qYk7-oSu4Z-=-L@$krX)1pUJAuQr*Kjl^;!_liaV z$`p=+4wu&SD#{PgX%bQYJz)rh124LF1=aDY|7h%@afEfb zW^6Zr*!ljh$Hsa280BEXg^;&&8Tgns!|Y}GGcOUM@ye2Mj?m=(-?!2{R!mFxnvSuN ztvTpv zf&CDksHzgFiXj3UBw|?_-U&GtGel2|fr1BzoZt?{M={o1u6BLQ?X+}#sqr~akJ))A zsAPNAxV=T8{@bt9^ILyo=B+LYJFPlLreuf}^fS%IYAex7V9aUFDoYV0naI0x*5w)vLri zF3uBlOKok$XNnWLhMX^wH#OW+7Ild)(A&tx!pH&#)#+&?EK(8&FpY7--elUWdb~hn z@rKi=R}C~!d7KV8Uvoy1n$4WrlrA}&mv83I);0*nwlxSm-yeK)T0GcK`R?pK8{hYk z>T-{WH-~|EFe^Pnqn-oQVYcI#cjhBWZDUVuj%{t4z7{D@&YaJ1Tkf4be?Y7{9l4vR zb#999YmycLc?m&v>TyP0LregZiMW)vd>p9@o4p`BbCG)>4wfctDb>ziXcS^Eq1`Q^ zkNCCYX=pLwK?z*Nk!XrNGV0G4>}z4kd-}`-3G5)q96GEi-dY;0O&W+V*Z$2-8@9G~ z05T>PzxI2aL&<&*&jNWKVnp26;Fx62%DyGM6Y2w23&OS+2Q?M<$JBv+$E2B|G5#lt zkg^uKuQUGqr@qo|`k~1&#Kyx%XRVc=mwV5F@30S$7ojE+yIm}k-RMrF=KniE%cJhvQQ!Q`%ndajPxT$3ezERzv^!~{mHod47$|F5Nnb8(*q1S23T zF1>L|p<^egPN{g`c{v8JD6I@e+2CNC9HWhw;*_^!e?oi@R>7=%5j7K$v$ZhN;|OK& z<_*u4gs`Ae>Jv?a@o*QD$?%suqlen+QT@W+v`DiXAl+-Uwf39IV^D3r!q&BL+dm@W z4Gf9QS~YTLyOmIr==r%fDEHpy_$#d+h-fWn1ijl)i8)aJ;}0VL1J==Nh~8!*s3Se)LHK3Ld!`hib9?b)T=>#SdPrqW5*q^H1p3irAkANRVYPZZ)Z=rI4d^aPA z#Xv;}t76C$%9-KGF}z7ja~TCoeBUDXjI^syol*3>8?BTU@7*4*8Uqe7C{+|HO|F!K zYEz6JTb^X-4=&(7{DMZE^5YMCrc7#m;39eufy0P8oUfF^Ht*s*e_qdxv+uZo74cpF z^oS~cWL9T4(8*-eKf>hpsOTaa9mM^n!2JlFR!7nT(#VY#du6KCA?O1o zo#Q1Y0TM5xdJ>*;aMR}1;P_6OCmk>=*I|Mn4Ek8NyYrqU2O?_z+cj`X?Z#>}s_07B zbtL{rf)pqoG0I+v0Tg`%}N1;m7zMilq}-BywevwlO`2Q{*;d@{+BD$>Rf6MO2179z2o*Ej_@g;O&Rog_smh z!sR%c-a!|S35=7xFw;oP;36O}=^zeApFK{gTP2Vi(L#%3nAli2T5$c*%(atn%d^5# z?_ha6A*GYd&rTOMOReYtouR7hepUa)`FxAhLR(UW=VF+7qQ-0%4X$r1H(|m~$L&m{ z;jnTjTfhqpMFN-4Z7yJcqbEpeD3;b}dpO~Ih`tSYT|E(Za$?Yosp>e3Fd6nEuS9d& zeq|2ERtd&r7Nu+4%{*lrP6pgXAyXJ8f!#8-+H96i9~)x{#!!B3kFS3oIPFO_G)DN; zHyShEYI5;5i@kHS{P+kiv5i9W*HJAY!v`PUC-%V#^X?rY`!*oP(3+FB0&{UMW4W=H zw9%nrq<>X<;x9L`sP8g^2nY{z(KY4~3rFPOfK6HqGV2G8T` zw08Qz;giR%xSsF|s=+Hd?&ZV{0D3j2X7zI@cvY_>EeL&$&7tgOXhsdd!Kgmtya(XxxP zWJ4~W?4>liMK<<9Q!(J(|J|xq&p@c{izU@eT=(hSPSNWgWSUIR%cc zUSO$H+x=>Ky`G^8@Bw0{Aaq)+3Ou;QI!pGx@9cAh*FI24iI<|GIFziWQw*6O^a!ll zZa3giad=XQt^j8P)~zz$Jk9+&L1LC>mtSeKYf&v*9EEuNGi#WAbvAIACL0NO&0)R% z2&Q3%6PU?~WSzPRaP;Ea_HvVkd3ZufH0xsTuMV)~)(^_s=m7hM&8w7Xu$oMg>7l_m zm8}&B)lhS}r8lyxmTFDpep3f{aw^?9F8FSv2G}*u zfp!L+cT&g!a8io^GS?)h)!Gj;4r7he+)vPb`)J_nPS^9s{ysZnX{*Csw$SvXJdvk# zMELo~4zN9#%wK(Py5M~Yd5RdUymo758f=ZLme~;IDvjX$vizdDqdOU41eT=#invV# z2{d*&Cd<8{4hWoz*$;=A$5=Y#m*J?@E3*?e@D~m9P49eR)Tb$#WDog z-GW(J%(pO7-+D!HeST=!IiQde@{t|x^9upPXONr}p4a48oW8B~FBE?TJ*Q~`)#bJh z_g348LJMj_%8WeDzc*maao0PvD)jx*afufmMX-IT3d2hT4K;j>k@PK}AMYyN?ra)1 z0;vyk159kX^q}#SLi(7tKIn*<#rH9S`Xf$r=&M(KokWs^?GhyreDbDb`g27e^E7b0 zkV8FRQr05nsBd2$ZD~p}W$T>6o>a{vEMRi2KS3ekN^hcV5W6U`^Inb%d0(?KR1k^O8E^K8`f5k@Q^4Nxa?E8e(zW@d`63iWZNfCmdOI)$JmrSgV2Q zaM~_+^8+1D!f3lxU?~3#_U_V8Hv)uekgz>VbLFlbxX-tqCzP(;^bim@5|7mcF6!@X zRA)++;&^84%f#keD z_PFmwV$3yBAp*nZucWcOE6nR=6tV_lQrDZ=TAz;JKTR#Elo4209i6nju$c#1W%*`w zaADPToeBuL5--gua3@O;;69(-%V05;t%{2ZHhK`-raqD$@E%U&1PQ+owCX1;_gPd8 zeY`+9!UvvdI^+}p=*22XKtNc$;(nuD6})e%R`qox^g>*pmuobg8OB8_i)zt z%hq|N&slLCT+QjI;YNC!j&pYq;88gar5LYs%mav!%d?C)Yy|vf`-Y+)*S>mhqqbg1mNx z9c&{hOULMuG26aS%bOJfr`$dRY>gi(=(+OKZ&;gsM;U=ieYrtj=sK0oBHQ~;#@GxO z*QI*v+_gT^M%i!f(d2p^sRG!IF>r+>lyqg{O0_iDgbTmQJJrJ zxT+d8rbeLy^E0UHB^jGxQ5m)?KReJ&8qB*Kl$PrN9b82>A{^QXfhAWQbCtBThurA4 zOrPk&DbduVsI`cWT4mku(HgUtv0xZl#M&-l(Jc?}i#Pxo5tHkN(@KZ!q?*3aC$mh= zm#eP@vyUnrE^f+T;7FRbL6*ITv!GUMIms~1KFKm}vbnWZnYdO)-34t$87`I*Abt)y zOt`tsx{(@c{E(wwa(;ib(6ptC>v-@RN-Um!m?wR;Qu}V5n{2hB^Ugsa@w9ZgX=|lI zNCq7MUK!=S0?k4erlO=wqoZ`5EF)8z-Y-<+JgA2475L}4Y?><6=zPG;%KWIC8~=DK zd|`x15ZHzC7I+P33=9sQN0y{2089XBLRa2Hflta6+e1W1uM? z*Ica4soo|?4nu?y@~)01_;oe)K`hgQ}&hk+2~7@)C=dlx5s8L5_kICyF4qF>f#hI z>|yka#>32SekQYP*~P{LSvX9=?@DhA%@LJbF>VXZR^Wm1UYI7&e z@JrdXLe9SOM24oW`tA9!6;Ka7Nq=5*SauItAKtlDKx7;UK%HA|*`Fjvm#x?`kt~)WvRdXLpMxA<9 z^j4BdW7#M^m&Y*PTi@n}Lj>o?1hE{WD3yH^8mc2r$8Z~r*r*$R54mGJKKWA1Wu0Ec zBm#PR7YV#cE3980i8dunScEdz+SCA&?_xbbE{(+bi7b}2Y&HD!UWNx>_ABBh<^o%Y z&RIIH{?S5>(e3HFPRE2jcK2QY3Ngec^S#mO1QF7%n~)Trm-GPAzGZ(O*$U|uAn)U% zs!JBecNb`KQNNWUmt)moYqanCcAGX|;F-tf^YpkraTrp>NvWG+<%8g0_q1@nh#6R~qiG8$ zR$x@hJtSpvQtJGu*@n+YvU%LnWk_z&E6sGZr<(leo1y;GQnx>5<_TFQNA8R>Z`mIBna;a`ppN~FO6rQ!k2E-C>CNKw ze>o%e{HV2r$Z#xnFDS#z&N0^%L%7tqY#3Ua2&m;Uirny`2YPRFM0_ z&A>Ko5(tR-;dTlGU=1}x{#SMH84lO?hW~0&q7$7#B!pTF(kI2_EvRx&O6;7Liz zJUg1wn0HIgN+5(^$^2PR0{06&d{TeSmgy#~+7jb}x$eWfSCc-P$y8mpd+X-^!+g`2S3{m>ove%T zAYLpl46^sDaoUlrZjz{cK{FM|BxzxvCI!mpJF5a+?@`F$Ad4%pSd{u7KJ3{PWm-8D zXcfaT+oTqFyfqLM^%B#_TH9m!=_liGz15ERx3}kCQS6Ja3!PO|mIBjHw%@fsW!I4r z7I@cbx*vku)vj53q4jngx%ab3XD;db^5n%FRCJb&AS@sXV+g=>np() z`I;^m`HrwFQ?!GLpN{=x!9&2jlf9BQMCLwhOk7i_=&KOhito;`W#Xo-Dj}2Q zgypa2c+}Z`6XJC*(MOXZutiFYweV*~6v`Y&kPfO$oehIgVws)OJ~i=M-$_2Epm3%A zTV`A=koozp8fmNUZ?~H_1Hb#koxgHdxy5lWK0+s6SE1<7Vq34NiDA)XkpLJaD$-Dx zn;~5?J9JIUki}w6Tb!(H+`S5s{&^JI{RDSM#ASS()H1 zk$Fso9ngJB`pyHIc6YLn>dV?$8rA(Q>TQ>gjKV)z=O!)AV(~LF86D}HY&x)G5c3Gj zs_NIu@ad(qZykaX0gC?VS*I;0^Y1RTaCns~s_&kA^Zv!k@z1T(>IN2!JgzERPz)*E zlRX(H6KHcnu{7Iw+-&n&0NKj7m(t32hGX-s$&itmlhPi$wAJMuLATKd%d*C5V{%Hx z56OSDE46C$EQTY9r&wketEP3_P#b8lP`%IlAJW6V%^iDFwJ(IM`|q9~e5Rw^E^m$L zb!4f{&x)}KTbe6>QAH7HZ4=7w#q7E&gY5GOi44Qw(IrOvX&aq5zI*S}K!6kk1J%jX zV6l<5zwWnenW<-du5%JrJiNmBxI!4q(XyAi9~G5PcjB@0Ab5!{+rr@eV>_dsUKNgR zW6l2hrAPc2VitoGJ44sTIj?IV3dL@n&V?(zMOAku_2@}gGEfrT3&QGdPY1Y)kYcya zht99itL2Sg*EqS?{Kq`2QjV>>h68%pPX(Li81TVG`;nH8`(3xU*1o^z$$MjHwUc2| zpuUgEpYc8nU1Mh}^$w{rUo%@JPL!5FNKejl=P_p7sN+YW5$ zIPK}vCO_}%?qBzRZl|x};mmgLiwH=AWd9MByoUhCb?fTy{KtFQ>H&j6kg-RfZ2li6 z6)F$^U12BethA;*&u*9-S@PT{z}%jAA+9|9?q}@Y z4QL8+3#KDB3Th;%~^3xJ#95NrnbxDfp3%h)KC!JS2R zu{bN7|NhDrs0?t@a9#$^SIPCI^~=p!MPZ z*sMAmfY~hW5)b^hsTT!6@&gcB|FEt+PB<_ss12bp|7qG51Q0p`X2-jKfj{7nxd&K! zf4q17Z&MJ^6ubbX{&#O5y^Yys3K1D3-a z8yS50|9NzUs%*x!4laO5%OC;GB4Lrzb6M?Up!DPg-=Sn9qkDHMp(sekAf$Y-HYjl8 z*axy@PcRYnA_YyA^1lw~;lcvrTGJnqx{)1e4}m|lcr%l;NWGPb(#_X=G>2^ceep9v z8PJa`0dcBFfCm20(iJFiAL~_>)4XhaBOtX9H$?%}RK!6)ssO>Wo^eV790jd?M;!w} zRe$V?r27fzBP;_X*8iT+f*u!eoQ(C8!`1#9edbUTpRJW3)ba2-%1EKhf5h0NNpdgAU!wuMA$KhpiG9laGFkn*ov0`mxO9;y7i z{F?lp{HgpOWzU4iJY`H9={`fKW^A?&Ia-d_NiEy* zVEOuQFi?o#&?9dacV%;3Y-C7k&yGhnT(=JYiXyPM(HN_&?wB|NRg99otq5nO+78 zIV~&Td?g9QB_R93>VM@tvwwpO4hH4^FxSaW+%}=ETnwX0+|o|RngYqbJL~jZ2Hk_E zQe#vkV(1?&iXaCN1c6A9k7jR@fPhLQ?I%ENeR88ckLGLHlC9;&%EsZ`x}E1OrO9TC zLrly2p+8NWi$ySmJ$-+&;F(gU&#okO{Pe{gPU^~O08T6y6_>? zMcUE#D8f3^TlMA@0i=wGxrCAx=cVq)YXcctQ=cBb>_xKrrtN`(2qXY~;M7W0pKtM9L6FNOJbmysZVHf}qgdrkQvvY= z&^BYtwiC%tZVhggHELfRZE(EyJO2_+EKowqB&I1OXNv5G+=G6@dtVUxjxq)jN-k$O zF(bEt$2RA9BPuU{R9gmwoJ3LkiDV|PB>q<;S3fXp?TCz3IqVscXD7Cn182@f#DUY+BsDpKb{3PKuw6N$Xc%nz_9n)NX(((v8ZKYmra zfB-LgxsDL2e$y54bRb<4v0?THkkEslB=RzR2PAisLCQMlpUe3_ikm7z&J$&?r1MO5 z2aga$$YktT01AMEuNJ511WcL9RuW}TZ0B2=AG2!C`CUS)2BXF2=wXNb;)u&)0-ii_ zGejjIxn^5`_MOPv->I92`<<`Qxss^YDForO)3~CqXRKyM#(5@yQlCL2gMjuPygHC! zpCf-RIr_pWPLklMqA1vWiR|ov51>`?RR9Mk4lVf^FMRQocb>x->&tF%Mb z-A7ZC2MD17t#rf!3ZOerfx>%z{Eq3+xg}KFxrEbP(}(H(-zU>foUu1j{Jw2Xv7u@U zkaDOy&gJ}nzl&#Gw(STe8YoHicBn%}9^ys;viacC{!~#Vp1wYJ0 zeLy_yo|5Cn)$hx_{3g8$_!6Qf=8}Nq6es=gWR8lgGo_6};$Urp9Iz7xzdt-N81j-cN^ zm_W;>8%ouS_4^deLT|$;nY}0!tD7+$#OSvbQCn03I$?AU(2~v4N0&-d@@=*>S-)bA zO;;1kXrjxT4xZQmXpNIU!O87=@yl{CZxs+gY*;?t>80@2bNbjr-FuK73KBARY}^rZ zC6gCiIHMq2F^aJ)4*yD@5-1 zS#A$G9x+J{gEIgze-Vmznup{vahWiA+0sk76-e^eEsc95aFzmWsy#2{;2UoVG?+q3 zQX#tI{hDBvFxC}kg-qc~W(&nZ%<+#qxq{gA|z1KYCw%iE}!BLMa9HK zsj>BhGLueB=Ig!|TaEG(dfrdY7JHKxx#!PJ)Bw>ay^>yfyhWu!jV2TzawO!kpCpr2rkX7Pqlj&eH%LlCE-3TBY=U@y zKzc9PvXoNr2sVnV?%C6q$mwrekn1kq#%p%G(m}p z_4qd7L@s5u?9dLs%TK<#C19aZX8>Wr|Wz!p$uDev*lc z$=4Ksg{RdIgNQx$yXewv6L}3a(;io4{Q;o&UFnBB%gW6zXv@AV1u)}4t}vFL1YHeE z?5^f>^blGBESRsA4BJr#OQNsipU5#|S{Z2W#qk-7x%Pe0NTT&^dvdb<>(wEVhhX}W zAZCQ;F}Gg92SbnFy4fox2|%(*u{0^Jpt}Er9^X3M8P1Kn=A4WbTE zTUHW#60b`$Tn8i{P4^T{eFPHcFS8twYr{eBL&VSV;+Nuwn;Sy90@@y5^I|69qe;Bd zX(ilJUu@&Co;?$gu%bzNU!6m0GN!?ms~RnI`piLR*WGo(&^qMYTyDCSKI&k(heKli z_`X^-LxAKSB|cnRlgQG`^w0cV_&H>S|a@4G^RBE%MNhk>I4KrV6Am=Gn{Ro7&w6r4qPrX1! zjka+&c3N5+OT&VRD>fMisbl%jD~Idv5P>>2AtH*+z=Tq)AVrZ)k~Bvk(ePs|gu=YR zbuESvP7nuMS8nEA4Gm4!FIEk1e{U>7lJXwnm4%)uFlqSawl@dnH3f!;6g$aMjwwq! zf>FTCtH53~&Hh3^&w%}X(tS7lil6$L3ou;)M`f2p24xD8O9L{aXopV2PO_L=b#A2+ zFLZPy_)Y9l`MgbaTH;L|ma5IEXg;sXHt;R{$`CT@&1R}&DC00SS%Gj*^n3&PDv*=y z2f)Ypsaj@mZI-0hehr4TIa9p#R|sE1OKZ{&>QixhqicIBK34&4!my@$?oDE?`hC;Y zajA-$=(%tq-PoFjfw5xNN~YQx$h1D@o8#UZ;erQPdAo#oJ!)}VG&bo@0!JqGgVzv0 zvtFGvo8WQ=NR{1gzgOA97ldimW{QY5wgj&kMZiLMl5m|H<{Kfx`wi(Nwp5n^qIo8B z5LlG8-^Db{m2c)M8GY;+QQB+0Jh|WWK<4@gu!adg|L(bERa@gQZ1Q=7NZ@3MdQ!yk z9u0qkf%}hw3IzAXk3V0VG16`}PA5*YMPFi`VxCF-z!}E_>?+=yjvjm*6k40zx;cYsNB3SF^whNIv<$F`BLwqaVHfJa!aTVb4#f*N%j zm}s?jZZ~OSG@dF3!{6}`TY%h=$Eeh56@49uR4=B~{Ea?FL}QzN1c+k_0X?W*a7Gy# z6d)KjH;8w(#|pO##EkN22nQ4EF9qT`2c}WNw$S*Yneh`80(hLTF$HEDnvb(@^NpGx zjDFP-&lCuwU8c@_=0)RN1%KMvPlO*EuAfFxZA^p$1n`9bHD&<{ZKYTpuNd~Lh30_d z5IRm&Q%81EzWxf4GR}ZP-q-Pb&WOB`SZ%dwZw74N-{)&TNyTT(#Fo%IiLzzFrD7sr zrF}MhrSzZY2P?vBqQOL+4-6Vpnzi>oz}Z5f-R}5<<)DW#)E$(I8fjw5OtJ&n2CKCGCC3xOVJH$p$8=Z0hs+jT ztj%Png3zi{QZLnKob)Jsavor}zeivwuVi{t44o(&=1$I}2%a3gF2YhmKP=Y<*Ej(j z%x9;EagA^fMmAHQ8hTYalPeo8TzN>d=8npfQkTsG(U)=XZd2kE9ljF>-o5$-!}llx z`i{0sqG19go}W5h=38cgPEMI%%=5)_?ATmmse+I444N5I=YQt)cey= z*h~!b+Ke#k%5I{B9q`S3kaS(MBfs<=DT7GI`_D`ww}$jECOR1x6_RwH(|_mvnmG9` z){Pc<)2Z&gH@lQ^i&j2~KjXerW|NUmg?euRyg^G1H!uM4Qym$@vdmMe62P(S-Areg z_H}Z3tdP9$_j=*vi&wtbPrPc)FU98_;sS9mwyqnh=ZuRs&VLz^t^XWy75<#m3j>=v ztB6V#oNfaFJw+l@pJ4WEpL#4s=yA*0mFwiO*p6EYPr#kD7BpO%XI%xPXv{#5`egQt zkx^{x7FnUgghi3~XXv0D6F*F@5v1#zoZ|6#iVpHdP-U9c?E|#dML?~)hZ2%8pN00qz6x3ilD6{!-it+bNZ_?MfVZ@Wn^~fi5kXw|T-!nK+ z5_en0{z!;Foe-SfqDMw~d|2;$f1bC9^v>t&p#WyCaJb^|lQ2LNPJ-E$$ zof&?V0U_@*Y3vrN0J*FBZ*TIx`C5kjqLu z%F}XH^k+UFt!6j5e4$8C!e{J%o3wciMIc;8uf~7PZYa%aGAZtMSc2B{|1m zo8RYt=?j%cQuIo8!P7Y4!EHgb&Ci|9b994rvEJC+DN*}M5T-K2Tlwy82jyK{a^;z` zp?XF-Nk>MCm@{@+84N?`QN>RI6mXkj{N&D~#>&Bu~)PNkl z9Zj_`?Azjs5I1h)x=RRDdC!rs(m)Y(IknXBX!_j1 zwkv`aJu|UX-;RA6n2-!(?EnW?${A!i)copj9=@LxKe?Y1PvU0^cfGx)$cq4vwvZrE zyR`#b@1o`i&Jn&Mq9ou_XUD)-)eT>QnilDE%ek8<%nAgIphOEW#G&*>=l~BzjDDVi zK{SK#1Ytdwn-?EMiHX*u^*R&NL8l=hE8<>6=^FNWIxx+Rjak}lon8^8Ur{=gL?7HP zbkvhB>57;hv!G{ZX4NGi=rDAq&+v51SICrdf8xcU{LYAp7S-s~x&=!k*BnLNWs0!f z)#-d%3g48}W5_Zhh2S5rzGXDnx@A}7a|E}}Q9i~)fwHe@GzH!YyZ=@~I5e^ry)4-v z?Wlp>exZMR+$~RjTIl#>YF3lxR#EuVny8|udenuU>`k)+62;MaSgCfDdXeb*r(Xi? zUR1{_y&yw@H$U*_-{zZuF>!tE;RragMk}*wS?nfukqb6Yt13wpyW_+wsWEGY1LXj!*5iyGP`Z2p(2M$x}T+Y*SS`z1>~ezux-m?0Yw%mR1m?Yl??(XaR1@KBW zG~d@Q0qik&cDhYFCkD0UL=UOdB#57{`x8Jm=Kp!0;?0b*7c(Gv(4Jfw#xAuhg+^=3 z9}6{k;qEn!c2e#*16d`u?}F8DhDr*Gd8*!(V%RMU=+fcg7CqA%N(BcKCx=!{GJfPT z7_)-sE4|srOk(gBgTpU9u~kJE&X9p%=oI<)TcF3ww!hzpSTS76NI1ux+q4O^Zj+cZ ztLruBq{?);`@&$%Iz>f{U(<|h7>g*=UkKCB_v=${HD!lZ~OTbwoeXWJ=Y`mLyMIVi{*G`eBa3 zpN`^Ynl-^6UntmAjR(>AIX+7}Mr9g}5#0|ty2LavD|Kgw&&EnEVvTro@72z6#))cJ zNv8qz<&h%oz3P9Tz({HUO^j`Z_J>6sd$gD82Q$I)zxM_F0-zA&u-u7e%0IG)qtZ6I z6t)_BMqcP#cQc5VPv+8GmRaZPR*jM>t3K z-F=C!i(b7WbD!I4@80*FM;opU(7)6St#B@ra{LW|E#c1>?Q34o-$)Qfc?RofXJhlU z+-Ld8roBJw091LlMIX96W@w3ys^1}BDv73lboZ)IV!IV^xo+go*LTu?I^zXS);NML zZqkwTc{aLZEkW5A;-jS6>Z9N5{=GH5y8+g%eiX~~Q zxb11S50q45Z0FNr3E?c!EitXsjZ)d9VXYp`@SNj5dt2rAs3)ovG8+EHNw7ss_GjdP zd}jXL2l?nN%5|JF%FdY>$eC1RQZxvRaaI0>N#sR=v5e>nR^bHWIsmcp)X z#K9<1VE01*lI7VEP4~yKz4BBv470%>1-@Bbr_N%!Nb;h~$JfK(F4lc^an&GK!bTt3 zoxLHHrGr=U?Dt61v~kLXy>6}C{KV(@7s^Rsx z6+!bbO1tg1Bdkkig|ZV#R$Gjr0}kt*S#fo znW97;@aHeU)Q-Ta?&Y{hk+nCHW_bU!2=Ip506<_>(xI+vera!fDqmmHMp77m9USB+joZ<<~Q)a`yYE0T|H^z2K1M7g^FSeJk5 zt8x)x-k;7Ugez`db>EohA z1hNR9MKNj;kcf{jojD|nzAL-U?^J#yI2U)@vhp*gf;e-NC{b9@M&W538kV~m0JcVUIFh0J$bGMZ1TqZMK} zG*wpmtp#gEP83)cWi8AZKDC zWM{S0j))waPvr$qXperdt!B66hFzP)x#PJlD~i9;<0 z`dzH)x;yU>s7G|%i1;CVf~Zq>X12Kua55Bkm>SxJ&5V&TMyS?K&7VWY@2W)52X21K z^kYGioNPqVzo!oJ>3B+C-unBytMJ<2Ao*NfzS&PzccFnC;h9l0@ho3E!!B`{YzQ!) zHRGs}S3gl;2{vvGqth+7Da{Ta-FkhaEgnZCsmjX{AH@!BzNNmlhy`061@DyLB2CKv z;IpV<9c2fY2RMHS0l|d@Gs%ymsK~L+B8Z!SE-r3Ia7P^9f zIOlD38*O7xUa43d*AKhWfHdR8E`=LBXT;8-RHWAi^cg7?W$+EV@@K~NTd&`uVQq2A z^_A#w&Wa}`0jiHw8eDYa!>s}rJcM7O2~WRjRV#;69o(=xpJfT38TsKH9(o>HIR~G; z=F=Dr9qBUqPmzP0Y)a8g;xU94#PVBXxA>=)Q)#N69!ylo%?t<nxcJhS0gCfK+6fa;3PrRwCjmWfD73By+&YM0efPdlX1+Ukockgxm+elxQ2E(YjfhPPCJ*zoL8rjnB05DXkWv_Xy-(?Q`Rn<5H?(b#=T4%ru67 zJ9yGE>6O*kE}*b$UN?ulF4E&3ouga==h#UmX7@7f8wc7VvS5bNee`uA!4FZ|i_y5Y z*T<8uf!$#*0g(Ka8xJD$5SThu&c1MXC5JMwQ)7ttWHtt%;TQLwI4; zhkg{(7Hu>SV=DbFcDPh;w;Vt(s^pI~g?ZuXibr3_HpoN1K(J0e0Wwh~{#;dq^lb)O+I-&_}7}M-&4Z zP-E?XQQj%QQyBuzRRC8%!i5vd{(jLv|W3 zZHts*sInP}Z;)!ju+lX7S`{dW?bVG5e_Mwd zfXWYeQOQU1!|Z*+Rh1VuoR2gEnf?Y~AjxY#!~yCmjz-{-|Mxtqws^p0#szZx=b6H$ zssJ2id_>y+Z7c&g#bAqQ)&ETaZ#-!lfGaL;A>n_K57^Q6|N6tOST`MB@n=Drim`y7 N$12*&Wr}9+{}0+h%RvAD literal 0 HcmV?d00001 diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/docs/format.md b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/docs/format.md new file mode 100644 index 000000000..908b3e466 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/docs/format.md @@ -0,0 +1,75 @@ +# `esp_secure_cert` partition format + +## TLV format + +The `esp_secure_cert` partition uses TLV format by default. TLV format has been decided based on its simplicity and efficiency. We use customized headers specifically designed for the `esp_secure_cert` partition. The `esp_secure_cert` partition is supposed to be a READ-only partition which can contain the data which is bound to the device and is not usually updated e.g. Device private key, Device certificate, CA certificate. Currently `esp_secure_cert_mgr` component does not support modification of the `esp_secure_cert` partition. + +The TLV format used in the esp_secure_cert partition is as follows: + +![](_static/tlv_format.png) + +* TLV header: It contains the information regarding the data such as the type of the data and the length of the data. For more details about the TLV, please take a look at [tlv_config.h](https://github.com/espressif/esp_secure_cert_mgr/tree/main/private_include/esp_secure_cert_tlv_config.h). + + * i) TLV flags field - flags byte that identifies different characteristics for the TLV + * ii) TLV type: Currently the TLV format supports only a list of pre-defined types. The latest list for pre-defined types can be found at [tlv_config.h](https://github.com/espressif/esp_secure_cert_mgr/tree/main/private_include/esp_secure_cert_tlv_config.h). Additional custom types are also provided in order to allow storing custom data in TLV format. The custom data types can be typecasted to appropriate types after reading the TLV. + * iii) TLV length - the length of the data field in the TLV. +* TLV footer: It contains the crc32 of the data and header field. +* TLV format Padding - In TLV format a padding is added automatically between the end offset of data and TLV footer. The padding is added in order to make the data field a multiple of 16 bytes which is the minimum alignment required for flash encrypted writes. + + +### Partition table entry + +* For TLV format the `partitions.csv` file for the project should contain the following line which enables it to identify the `esp_secure_cert` partition: + +``` +# Name, Type, SubType, Offset, Size, Flags +esp_secure_cert, 0x3F, , 0xD000, 0x2000, encrypted +``` + +Please note that, TLV format uses compact data representation and hence partition size is kept as 8KiB. + +> Note: The TLV read API expects that a padding of appropriate size is added to data to make it size as a multiple of 16 bytes, the partition generation utility i.e. [configure_esp_secure_cert.py](https://github.com/espressif/esp_secure_cert_mgr/blob/main/tools/configure_esp_secure_cert.py) takes care of this internally while generating the partition. + +When flash encryption is enabled for the device it is imporatant to encrypt the `esp_secure_cert` partition as well. Adding the encrypted flag in the partition table as done above can ensure that this is done. When flash encryption is not enabled this flag shall be ignored. + +## TLV storage algorithms + +The `esp_secure_cert_mgr` component also supports following algorithms for TLV. In this case the TLV data is not stored directly but is stored by using one of the following algorithms. The information about the algorithms is a part of the TLV itself. + +- HMAC based AES-GCM encryption: + In this case the first key stored on the device with purpose `HMAC_UP` is used to derive an AES key and the salt. + This key is used to encrypt the TLV contents. + This algorithm is suitable where the platform encryption is not enabled. + +- HMAC based ECDSA key derivation: + In this case the ECDSA key is derived using following two values + - Salt: This is the salt stored in a different tlv with type `ESP_SECURE_CERT_HMAC_ECDSA_KEY_SALT` + - HMAC key: This is the first key stored on the device with purpose `HMAC_UP`. + Both of these entities are used as input for the pbkdf2 algorithm to generate the ECDSA key. + +Please ensure that appropriate TLV flags are enabled to take care of the underlying security configuration for the given TLV entry. On top of these security configuration, if platform flash encryption is enabled then the secure cert partition contents shall be stored in an encrypted manner on the external flash storage + +## Legacy formats for `esp_secure_cert` partition + +`esp_secure_cert` partition also supports two legacy flash formats. +The support for these can be enabled through following menuconfig option: +* `Component config > ESP Secure Cert Manager -> Enable support for legacy formats` + +1) *cust_flash*: In this case, the partition is a custom flash partition. The data is directly stored over the flash. +* In this case the `partitions.csv` file for the project should contain the following line which enables it to identify the `esp_secure_cert` partition. + +``` +# Name, Type, SubType, Offset, Size, Flags +esp_secure_cert, 0x3F, , 0xD000, 0x6000, encrypted +``` +When flash encryption is enabled the behaviour is same as mentioned above for the TLV format. + +2) *nvs partition*: In this case, the partition is of the `nvs` type. The `nvs_flash` abstraction layer from the ESP-IDF is used to store and then retreive the contents of the `esp_secure_cert` partition. + +* In this case the `partitions.csv` file for the project should contain the following line which enables it to identify the `esp_secure_cert` partition. + +``` +# Name, Type, SubType, Offset, Size, Flags +esp_secure_cert, data, nvs, 0xD000, 0x6000, +``` +Currently the nvs encryption option is not supported for the `esp_secure_cert` partition. diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/CMakeLists.txt b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/CMakeLists.txt new file mode 100644 index 000000000..e1f086cea --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/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(esp_secure_cert_app) diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/README.md b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/README.md new file mode 100644 index 000000000..cf6e7877d --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/README.md @@ -0,0 +1,61 @@ +# ESP Secure Certificate Application + +The sample app demonstrates the use of APIs from *esp_secure_cert_mgr* to retrieve the contents of the *esp_secure_cert* partition. The example can also be used to verify the validity of the contents from the *esp_secure_cert* partition. + +## Requirements +* The device must be pre-provisioned and have an *esp_secure_cert* partition. + +## How to use the example +Before project configuration and build, be sure to set the correct chip target using `idf.py set-target `. +### Configure the project + +* The *esp_secure_cert* partition needs to be generated and flashed first with help of [configure_esp_secure_cert.py](https://github.com/espressif/esp_secure_cert_mgr/blob/main/tools/configure_esp_secure_cert.py) script. See [tools/README.md](https://github.com/espressif/esp_secure_cert_mgr/blob/main/tools/README.md) for more details. + +* Please ensure that appropriate type of esp_secure_cert partition has been set in your projects `partitions.csv` file. Please refer the "esp_secure_cert partition" section in the [component README](https://github.com/espressif/esp_secure_cert_mgr#readme) for more details. + +### Build and Flash + +Build the project and flash it to the board, then run the monitor tool to view the serial output: + +``` +idf.py -p PORT flash monitor +``` + +(Replace PORT with the name of the serial port to use.) + +(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 +``` +I (331) sample_app: Device Cert: +Length: 1233 +-----BEGIN CERTIFICATE----- +. +. +-----END CERTIFICATE----- + +I (441) sample_app: CA Cert: +Length: 1285 +-----BEGIN CERTIFICATE----- +. +. +-----END CERTIFICATE----- + +I (561) sample_app: Successfuly obtained ciphertext, ciphertext length is 1200 +I (571) sample_app: Successfuly obtained initialization vector, iv length is 16 +I (571) sample_app: RSA length is 2048 +I (581) sample_app: Efuse key id 1 +I (581) sample_app: Successfully obtained the ds context +I (831) sample_app: Ciphertext validated succcessfully +``` + +## Additional configurations for `pre_prov` partition +Few of the modules which were pre-provisioned initially had the name of the pre-provisioning partition as `pre_prov`. For the modules which have pre-provisioning partition of name `esp_secure_cert` this part can be ignored. + +* For modules with `pre_prov` partition of type *cust_flash*, please update the line refering to `esp_secure_cert` partition in the partitions.csv with following: +``` +pre_prov, 0x3F, , 0xD000, 0x6000, +``` +* No change is necessary for `pre_prov` partition of type *nvs*. diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/main/CMakeLists.txt b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/main/CMakeLists.txt new file mode 100644 index 000000000..4af813af0 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/main/CMakeLists.txt @@ -0,0 +1,4 @@ +idf_component_register( + SRC_DIRS "." + INCLUDE_DIRS "." + ) diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/main/app_main.c b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/main/app_main.c new file mode 100644 index 000000000..86c0bc87b --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/main/app_main.c @@ -0,0 +1,259 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* ESP Secure Cert App + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ +#include +#include +#include "esp_log.h" +#include "esp_secure_cert_read.h" +#include "esp_secure_cert_tlv_read.h" + +#include "mbedtls/ssl.h" +#include "mbedtls/pk.h" +#include "mbedtls/x509.h" +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/error.h" +#include "esp_idf_version.h" + +#define TAG "esp_secure_cert_app" + + +#ifdef CONFIG_ESP_SECURE_CERT_DS_PERIPHERAL +static esp_err_t test_ciphertext_validity(esp_ds_data_ctx_t *ds_data, unsigned char *dev_cert, size_t dev_cert_len) +{ + mbedtls_x509_crt crt; + mbedtls_x509_crt_init(&crt); + unsigned char *sig = NULL; + + if (ds_data == NULL || dev_cert == NULL) { + return ESP_ERR_INVALID_ARG; + } + + int ret = mbedtls_x509_crt_parse(&crt, dev_cert, dev_cert_len); + if (ret < 0) { + ESP_LOGE(TAG, "Parsing of device certificate failed, returned %02X", ret); + goto exit; + } + + esp_err_t esp_ret = esp_ds_init_data_ctx(ds_data); + if (esp_ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to initialze the DS context"); + return esp_ret; + } + + const size_t sig_len = 256; + uint32_t hash[8] = {[0 ... 7] = 0xAABBCCDD}; + + sig = (unsigned char *) calloc(1, 1000 * sizeof(char)); + if (sig == NULL) { + ESP_LOGE(TAG, "Failed to allocate memory for signature"); + goto exit; + } + +#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0) + ret = esp_ds_rsa_sign(NULL, NULL, NULL, 0, MBEDTLS_MD_SHA256, 0, (const unsigned char *) hash, sig); +#else + ret = esp_ds_rsa_sign(NULL, NULL, NULL, MBEDTLS_MD_SHA256, 0, (const unsigned char *) hash, sig); +#endif + if (ret != 0) { + ESP_LOGE(TAG, "Failed to sign the data with rsa key, returned %02X", ret); + goto exit; + } + esp_ds_release_ds_lock(); + + ret = mbedtls_pk_verify(&crt.pk, MBEDTLS_MD_SHA256, (const unsigned char *) hash, 0, sig, sig_len); + if (ret != 0) { + printf("\nFailed to verify the data\n"); + goto exit; + } + free(sig); + return ESP_OK; +exit: + free(sig); + mbedtls_x509_crt_free(&crt); + printf("\nFailed to verify the ciphertext\n"); + esp_ds_release_ds_lock(); + return ESP_FAIL; +} +#else +static esp_err_t test_priv_key_validity(unsigned char* priv_key, size_t priv_key_len, unsigned char *dev_cert, size_t dev_cert_len) +{ + static const char *pers = "Hello"; + mbedtls_x509_crt crt; + mbedtls_entropy_context entropy; + mbedtls_ctr_drbg_context ctr_drbg; + mbedtls_pk_context pk; + unsigned char *sig = NULL; + + mbedtls_ctr_drbg_init(&ctr_drbg); + mbedtls_x509_crt_init(&crt); + mbedtls_entropy_init(&entropy); + mbedtls_pk_init(&pk); + esp_err_t esp_ret = ESP_FAIL; + if (priv_key == NULL || dev_cert == NULL) { + return ESP_ERR_INVALID_ARG; + } + + int ret = mbedtls_x509_crt_parse(&crt, dev_cert, dev_cert_len); + if (ret != 0) { + ESP_LOGE(TAG, "Parsing of device certificate failed, returned %02X", ret); + esp_ret = ESP_FAIL; + goto exit; + } else { + ESP_LOGI(TAG, "Successfully parsed the certificate"); + } + ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy, (const unsigned char *) pers, strlen(pers)); + if (ret != 0) { + ESP_LOGE(TAG, "mbedtls_ctr_drbg_seed returned -0x%04x", -ret ); + esp_ret = ESP_FAIL; + goto exit; + } + +#if (MBEDTLS_VERSION_NUMBER < 0x03000000) + ret = mbedtls_pk_parse_key(&pk, (const uint8_t *)priv_key, priv_key_len, NULL, 0); +#else + ret = mbedtls_pk_parse_key(&pk, (const uint8_t *)priv_key, priv_key_len, NULL, 0, mbedtls_ctr_drbg_random, &ctr_drbg); +#endif + if (ret != 0) { + ESP_LOGE(TAG, "Failed to parse the key"); + esp_ret = ESP_FAIL; + goto exit; + } else { + ESP_LOGI(TAG, "Successfully parsed the key"); + } + + static uint32_t hash[8] = {[0 ... 7] = 0xAABBCCDD}; +#define SIG_SIZE 1024 + sig = (unsigned char*)calloc(1, SIG_SIZE * sizeof(char)); + if (sig == NULL) { + ESP_LOGE(TAG, "Failed to allocate memory"); + esp_ret = ESP_FAIL; + goto exit; + } + size_t sig_len = 0; +#if (MBEDTLS_VERSION_NUMBER < 0x03000000) + ret = mbedtls_pk_sign(&pk, MBEDTLS_MD_SHA256, (const unsigned char *) hash, 0, sig, &sig_len, mbedtls_ctr_drbg_random, &ctr_drbg); +#else + ret = mbedtls_pk_sign(&pk, MBEDTLS_MD_SHA256, (const unsigned char *) hash, 0, sig, SIG_SIZE, &sig_len, mbedtls_ctr_drbg_random, &ctr_drbg); +#endif + if (ret != 0) { + ESP_LOGE(TAG, "Failed to sign the data"); + esp_ret = ESP_FAIL; + goto exit; + } else { + ESP_LOGI(TAG, "Successfully signed the data"); + } + + ret = mbedtls_pk_verify(&crt.pk, MBEDTLS_MD_SHA256, (const unsigned char *) hash, 0, sig, sig_len); + if (ret != 0) { + ESP_LOGE(TAG, "Failed to verify the signed data"); + esp_ret = ESP_FAIL; + goto exit; + } + esp_ret = ESP_OK; +exit: + free(sig); + mbedtls_pk_free(&pk); + mbedtls_entropy_free(&entropy); + mbedtls_ctr_drbg_free(&ctr_drbg); + mbedtls_x509_crt_free(&crt); + return esp_ret; +} +#endif + +void app_main() +{ + uint32_t len = 0; + char *addr = NULL; + esp_err_t esp_ret = ESP_FAIL; + + esp_ret = esp_secure_cert_get_device_cert(&addr, &len); + if (esp_ret == ESP_OK) { + ESP_LOGI(TAG, "Device Cert: \nLength: %"PRIu32"\n%s", len, (char *)addr); + } else { + ESP_LOGE(TAG, "Failed to obtain flash address of device cert"); + } + + esp_ret = esp_secure_cert_get_ca_cert(&addr, &len); + if (esp_ret == ESP_OK) { + ESP_LOGI(TAG, "CA Cert: \nLength: %"PRIu32"\n%s", len, (char *)addr); + ESP_LOG_BUFFER_HEX_LEVEL(TAG, addr, len, ESP_LOG_DEBUG); + } else { + ESP_LOGE(TAG, "Failed to obtain flash address of ca_cert"); + } + +#ifndef CONFIG_ESP_SECURE_CERT_DS_PERIPHERAL + esp_ret = esp_secure_cert_get_priv_key(&addr, &len); + if (esp_ret == ESP_OK) { + ESP_LOGI(TAG, "PEM KEY: \nLength: %"PRIu32"\n%s", len, (char *)addr); + } else { + ESP_LOGE(TAG, "Failed to obtain flash address of private_key"); + } + uint32_t dev_cert_len = 0; + char *dev_cert_addr = NULL; + esp_ret = esp_secure_cert_get_device_cert(&dev_cert_addr, &dev_cert_len); + if (esp_ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to obtain the dev cert flash address"); + } + + esp_ret = test_priv_key_validity((unsigned char *)addr, len, (unsigned char *)dev_cert_addr, dev_cert_len); + if (esp_ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to validate the private key and device certificate"); + } +#else + esp_ds_data_ctx_t *ds_data = NULL; + ds_data = esp_secure_cert_get_ds_ctx(); + if (ds_data != NULL) { + ESP_LOGI(TAG, "Successfully obtained the ds context"); + ESP_LOG_BUFFER_HEX_LEVEL(TAG, ds_data->esp_ds_data->c, ESP_DS_C_LEN, ESP_LOG_DEBUG); + ESP_LOG_BUFFER_HEX_LEVEL(TAG, ds_data->esp_ds_data->iv, ESP_DS_IV_LEN, ESP_LOG_DEBUG); + ESP_LOGI(TAG, "The value of rsa length is %d", ds_data->rsa_length_bits); + ESP_LOGI(TAG, "The value of efuse key id is %d", ds_data->efuse_key_id); + } else { + ESP_LOGE(TAG, "Failed to obtain the ds context"); + } + + /* Read the dev_cert addr again */ + esp_ret = esp_secure_cert_get_device_cert(&addr, &len); + if (esp_ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to obtain the dev cert flash address"); + } + + esp_ret = test_ciphertext_validity(ds_data, (unsigned char *)addr, len); + if (esp_ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to validate ciphertext"); + } else { + ESP_LOGI(TAG, "Ciphertext validated succcessfully"); + } +#endif + if (esp_ret == ESP_OK) { + ESP_LOGI(TAG, "Successfully obtained and verified the contents of esp_secure_cert partition"); + } else { + ESP_LOGE(TAG, "Failed to obtain and verify the contents of the esp_secure_cert partition"); + } +#ifndef CONFIG_ESP_SECURE_CERT_SUPPORT_LEGACY_FORMATS + esp_secure_cert_tlv_config_t tlv_config = {}; + tlv_config.type = ESP_SECURE_CERT_DEV_CERT_TLV; + tlv_config.subtype = ESP_SECURE_CERT_SUBTYPE_0; + esp_secure_cert_tlv_info_t tlv_info = {}; + esp_ret = esp_secure_cert_get_tlv_info(&tlv_config, &tlv_info); + if (esp_ret == ESP_OK) { + ESP_LOGI(TAG, "Device Cert: \nLength: %"PRIu32"\n%s", tlv_info.length, tlv_info.data); + } + + ESP_LOGI(TAG, "Printing a list of TLV entries"); + esp_secure_cert_list_tlv_entries(); +#endif + +} diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/main/idf_component.yml b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/main/idf_component.yml new file mode 100644 index 000000000..f6db2dbf5 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/main/idf_component.yml @@ -0,0 +1,6 @@ +version: "1.0.0" +description: ESP Secure Cert Manager Example +dependencies: + espressif/esp_secure_cert_mgr: + version: '^2.0.8' + override_path: '../../../' # three levels up, pointing the directory with the component itself diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/partitions.csv b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/partitions.csv new file mode 100644 index 000000000..3141de45c --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/partitions.csv @@ -0,0 +1,4 @@ +# Name, Type, SubType, Offset, Size, Flags +# Note: if you change the phy_init or app partition offset, make sure to change the offset in Kconfig.projbuild +esp_secure_cert, 0x3F, , 0xD000, 0x2000, encrypted +factory, app, factory, 0x20000, 1M, diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/qemu_test/README.md b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/qemu_test/README.md new file mode 100644 index 000000000..96dc07a31 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/qemu_test/README.md @@ -0,0 +1,40 @@ +# ESP Secure cert partition tests + +This folder contains the test setup for testing the different flash formats supported by esp_secure_cert partition. The tests are based on the QEMU emulater. + +## Requirements + +* **QEMU emulator**: + + The test is based on qemu and needs the qemu emulator support. + + * For Linux Distributions, the executables to be downloaded from [qemu/releases](https://github.com/espressif/qemu/releases) + + * For macOS you need to build the binaries for specific release locally on machine. see [Compiling Qemu](https://github.com/espressif/esp-toolchain-docs/blob/main/qemu/esp32/README.md#compiling-qemu) for more details. + +* **Pytest**: + Install the pytest environment by executing following command + + ```pip install -r requirements.txt``` + +## Testing +The script [`build_qemu_images.sh`](./build_qemu_images.sh) can be used to generate the respective qemu images. These images are then provided to pytest framework for execution. + + +### Test the TLV support on esp32 +The TLV support can be tested with following commands: + +* ```./build_qemu_images.sh tlv``` + +* ``` cd ..``` + +* ``pytest --target esp32`` + +### Test the legacy flash format support on esp32 +The TLV support can be tested with following commands: + +* ```./build_qemu_images.sh legacy``` + +* ``` cd ..``` + +* ``pytest --target esp32`` diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/qemu_test/build_qemu_images.sh b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/qemu_test/build_qemu_images.sh new file mode 100644 index 000000000..bb18d31dd --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/qemu_test/build_qemu_images.sh @@ -0,0 +1,82 @@ +#!/bin/bash +ESP_SECURE_CERT_APP=$PWD/../ + +if [ -z "$1" ]; then + echo "Usage: build_qemu_image.sh image_type + image type can be tlv, legacy_format" + exit 1 +fi + +image_type=$1 + +# This option causes the script to fail if any command fails in the main body of the script +# Note: this does not apply to the internal functions +# We need to check the exit status of each command individually +set -e + +save_defaults() { + cp sdkconfig.defaults sdkconfig_defaults_clean +} + +restore_defaults() { + mv sdkconfig_defaults_clean sdkconfig.defaults +} + +clean() { + rm -rf sdkconfig 2>&1 + rm -rf build 2>&1 +} + +idf_path_verify() { + if [[ -z "$IDF_PATH" ]]; then + echo "IDF_PATH not set. Please set IDF_PATH " + exit 1 + else + echo '--------####--------' + echo 'IDF_PATH & Branch' + echo $IDF_PATH;(cd $IDF_PATH;git branch --show-current) + echo '--------####--------' + fi +} + +build_tlv_image() { + cd $ESP_SECURE_CERT_APP + save_defaults + clean + cat sdkconfig.ci.tlv >> sdkconfig.defaults + idf.py build + cd qemu_test + rm -rf qemu_test_images + mkdir qemu_test_images + ./make-qemu-img.sh cust_flash_tlv/cust_flash_tlv.bin cust_flash_tlv/partition-table.bin ../ esp_secure_cert_app qemu_test_images/cust_flash_tlv_qemu.img + cd $ESP_SECURE_CERT_APP + restore_defaults +} + +build_legacy_format_images() { + cd $ESP_SECURE_CERT_APP + save_defaults + clean + cat sdkconfig.ci.legacy >> sdkconfig.defaults + idf.py build + cd qemu_test + rm -rf qemu_test_images + mkdir qemu_test_images + ./make-qemu-img.sh cust_flash/cust_flash.bin cust_flash/partition-table.bin ../ esp_secure_cert_app qemu_test_images/cust_flash_qemu.img + ./make-qemu-img.sh cust_flash_legacy/cust_flash_legacy.bin cust_flash_legacy/partition-table.bin ../ esp_secure_cert_app qemu_test_images/cust_flash_legacy_qemu.img + ./make-qemu-img.sh nvs/nvs.bin nvs/partition-table.bin ../ esp_secure_cert_app qemu_test_images/nvs_qemu.img + ./make-qemu-img.sh nvs_legacy/nvs_legacy.bin nvs/partition-table.bin ../ esp_secure_cert_app qemu_test_images/nvs_legacy_qemu.img + ./make-qemu-img.sh nvs_legacy/nvs_legacy.bin nvs_legacy/partition-table.bin ../ esp_secure_cert_app qemu_test_images/nvs_legacy_qemu_new_part_name.img + cd $ESP_SECURE_CERT_APP + restore_defaults +} + +if [ $1 == "tlv" ]; then + # Build the TLV format image + build_tlv_image +fi + +if [ $1 == "legacy_format" ]; then + # Build the TLV format image + build_legacy_format_images +fi diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/qemu_test/cust_flash/cust_flash.bin b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/qemu_test/cust_flash/cust_flash.bin new file mode 100644 index 0000000000000000000000000000000000000000..4db3ecee01f708fd9861d4fdecb59450bf292e1f GIT binary patch literal 24576 zcmeI%%MP(eH`*jATK)GMb=vp@ax%a<>|`sE-0`janTevkh7C%^momoJM$ z{9=#(&*L{=51JFC$9D{8SQ0NWz~a6|5k-=ihGiJwrwpSr%2nbHbDWf;1s-%-bXoBh zt}{jhec%BLOvL~*oBFJy>nsam8wtDzCUFm1p$U(*q*Y6d?x&jCR9BmE(^DH`ov&9U}>efCJQ<_=bzsXG?WuNB*=p0S!fK5|Q17ByVH_U!c z1NE&mkK%BgL!A|A%c(?X7t0351uIA z$ml6K{*0+s#D}Q}u?7cYD{3M65w9_2cYb%Mjtre&#CfqwUJ_4~M6;fCYQ|a^cmb)+ zz%!%{6~&oV?W@(^pLgy}CS)Jqg2(NU3s>Q@wPa(-=y@g;!JC0DzR~z>?1(Xkc+Fr| zftEV?kTT>eF>ma(B4Ms;LoAZe?$Npwh#+##1=yxDz*^SK`# zTmrWSlSiSh$Ue~X$UmvmIWWUZEdZr$F05u!xp_s7*2Xj+j*A%_GCgL+&r;gkEez4?d()BW9>yOxDLEWZI$%bB8 zxunKb_&AhjX+D6}T*D_#EIes>q>Cet8brcEsS20%vW z^x@E;Q2^#xHp`g`4ZaQ9)B5e7X+00T8}|MFz>;Q_(zef zV#wDi{m0e#V&-OF{JM$Qa%@jozVy#?7U)k_PxpJmKyPkigD{P)wYPLE!+EsyYK~6p zoH=2cS%w@fmRRKGk-S`4Lsdl1CW)#UyG;5-K3)0iR(Z&x<3zx?k1G(KXBOP(^to@G za#hoH8emVLa5^LL-18u1_wBU;l3fCRnbN4P=qL&p#P~d0m20_ac)!l_Q3Y?1MT=Wi z+l^z>t{*%+RucSS9s|3#@u0e}sCKN*7+M+y%oqRnN`M2Q02F`%Pyh-*0Vn_kpa2wr z0zYnnfBF75Oz@p%NX}mW|4!!o?|T4T3nUr<`CD!GEUkIHJnVC7;HZZ`#O>{#>-#Gg zsU}-)fn?A)DL02+y=#Q*3&^=+D8b7#4wJ02+HKtF!0xqVx}Hq)1LVM8@f*v{`l=p3 zuam4XoF7d6JWo#_m#;mIxK%@WI6k40M-BgUOtK!!exBr0Q8A)@&o^=1-*z-ljFz;>3$LFfW3qBReYdssinLn9R@x1oc zB{|}w*}i);vL!*Ak%Z+{+fI{cNV!L>h40fdob52al`;43iDv>7(mJZeI1lE%JX9lA z7Fdlc5f&cQy2=oxr+T)Sg9OmvbtmzbTk{e#UhhQ?3Y2!$Rn2d@v{xVY0nLuhstiiS z2b3bv!F(T)IU9m~RDQ*z_*geF;|!N`9Mx}Ebmg?bOkd}N=h(u-6uJZZiLP&j zblm>aBWSkT1gDBiHqh)SR*}ZJaT-RsJ?|9{V)NIiNT%l%H0sPHiC$Z=J|BmfsQJ)~ zX%PV(xMZfRRE4{0&Wqtn`NW6sI20>Sda}o4GFwV7wAw#7(K{TKM9Dcuw5GW-?#$_c z)WV$Qse{WS!=B5U&=@k!8>79LcP=;=!Xxw!eX8AbL%xU`wlt_ysI~aIx?xz5!d}7$ z;U%3pCiOXR4W0|<1Db8N?m3-ICOb8CerFrblX=^%7eh|9r?Yw}p}M|ZG>+IJlRfFV zR<3i%pahAj-ZC-ZKw-KT_*Ot!yp{9I>ry)49AbNG<<1JNP^xT@KMFTKdq^L#?n9Rr zd39-0$4PcBs=eRyq;bYsx9q|e6F-fWLu(zD`pl!?xH~4;-)4NNk_CBm@w@b^ul{4@)Dp+o>>wyz)h+u_#f$oOQWYC#x zxR8nCQB6NI!RAKeoF+0=r?X(yvK%f9OBnBQYs2$!A6J7HM! zJeFFu;C>ulT4ha8)dfPf2zdS)0;>osYhQ~eh1SahvUhya*QsTdZa9#95SHbnI4Z9& znC4*{f!BgPGHP;&(vL3;kr)%YmsF29l=$PFm~V)D!Y6ezF!~e)xP5&aPU?udy!UmO zW!?_lF;ZOBNc5W~3>3e22Hh$DoLnxeoqF$o&B#(E!;J`AkWtfkNUHpl$CDH?;BKEd zwAfpk)nJX;ZOJpUlq>1#ldHjoQ61_l24oYV6ehbyjlf^BM54&?IKC7ixa;I}J~;Tv zwLObpKW(gb^oyy7QJ2K!M8>DHSqJWET97MHGVqTnZ@L=UA=-}=u8K?<<-u#N(^yp6 z+w8nG?ZoC~@Zov1!5Fput4{s_}P*@4HH7 zUsYU2YjQs9F9&pa#+MT9WD6gV!fHL7NH2?*hJxYWBQ4geVxt&wA=!W_TG|xT)#aNz ztGrcVZeDf_(tqt<{b0I*9jqVsb_3oW6o3Ly017|>C;$bZ02F`%Pyh-*0Vn_kpa2wr z0#E=7KmjNK1)u;FfC5ke3P1rU00p1`6o3Ly017|>C;$bZ02F`%Pyh-*0Vn_kpa2wr b0#E=7KmjNK1)u;FfC5ke3P6D$rNG|-C)^oz literal 0 HcmV?d00001 diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/qemu_test/cust_flash/partition-table.bin b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/qemu_test/cust_flash/partition-table.bin new file mode 100644 index 0000000000000000000000000000000000000000..e1d23a77243aec4437e3190a4e08d60d84bd5e81 GIT binary patch literal 3072 zcmZ1#V9&;Ifq{V`fq@~lxFEhbHMz7XH9k4Ds01j;z_2O+L^1)f07F`0a!GzsB}f1c zUcdg20+RUbP1d;NyuLoC&dOJ?+Z07|lrtIvqaiRF0;3@?8UmvsFd71*Aut*OqaiS$ GApihw@we{) literal 0 HcmV?d00001 diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/qemu_test/cust_flash_legacy/cust_flash_legacy.bin b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/qemu_test/cust_flash_legacy/cust_flash_legacy.bin new file mode 100644 index 0000000000000000000000000000000000000000..2bf0c3720575b0f77a052045eabac9c9dc726016 GIT binary patch literal 24576 zcmeI%JMXi~nE>#Av{4GmEmqp@6zNc8Y{1w>is6ni=6>zK7%=y%xqOQKBCGWI5cxEz zQtXEJO>~qfC(@~pW-2rqd4``Ep5b}E{`uYg{|NQzH?RVcA%?Z-u2Zl2&iI*5)ao>9pMUt3?Wfd!O>X zPqBXNo4K6R6+j5!XmbddXVDRyEoNv|xAv8o(#-1qO>P1y`#c{&=V)37Y?^W!__k8L zVfJepsBfhqFBamc4HqBE>tGeL;Di*m1p$NC9pr|s0^^-6u-JbJs= ztxK>nHdKf)OMo-D{XH2ysK1@Z3H8>bsQ47hBc#SE$^SeWJWa#`N&Wly@l6aydn)R$xGuFbu z3rKASo*{LpD9)^EU#<53ymN0dA^Z3iJZ^_vxC)=GB^ygd&oikA-VAi{jmBqVM~ped zYX-9lwA9Imyjg7q%p3qe^$Y-Y{|7kW@-I@gj1AQ=sv|oCNn5Q=qC;}z4!Qi|&F(Xt z&;97&61X*(JPLJ1_JN*9{z;wAff-(E0Vr*AVKtM=%`0-u?(%JWGKN66E}g8m;2ED} zHpA~m>J1YoKG-de2;L%UU30VqI~=`38&Hq8A@cdGBKhnp=ydszZ+nd$9TTKu>e01F zMpjJ{=bIi=I_-FxredG2*~g$$y<^MJ)_RkYd_hl6 z)UfT(Cv|;jD>00ACDKxONj|AQn49{#rs&-@5ue#Qb==NaIc zHuTEMB{iuN(I3|6zjyPyh=2 zY=Q4DlYbxoX)|Z&%PigYh$@9Eg-(7zD4-DNwG&K*xYB@|?;Cgj*7q%B)0x7UHnHpn z02!gvheLx#0hnXiEN3b-_&#V4>$ks$^*r!y*pKG}OPW=dTa{dyRj2Wg{m`%}|J?a+ zXZxwikZ()+m)ZDY=4M~~c8J(=Y!6w!^!IBP=ucKp_j|%XZ*F6QFpaIXw{$GSd9?Iu zj!x^GIboSuh8!)HSmfrByj)pBRYcAviK-d9O!`DVUHR))dB~#UM8LR@D-fP%7ToCc zxgVTzRnv7EU{9cMIwSGi^B`sS?X?1uT>^fY(x|TJC<++F_&i&cYq@E7zs~Ye1#gf= zi(6IOjbqcUA3Qu(68vEv1G~5Jpt`WAcC5}AS{en67e9L^z=2Qz3P1rU00p1`6o3Ly z017~XU$($MeE%CJ_(3xyXV3rtAankYH2|&!5)FX-J-2(7*1TRG_Bl0h)WaX*_IA(p z{gsPUlP$MEGH9HXn?tYOHA40UBq0*Pce)s-Zj_pHRsois@BGsnVOPj}q}otB3GC%I#e)V*^WE zwezoWtq$jO<4?I&@#~A*f57mJq`6>Ex_@u%`J!T&_crC@bJgMnpNizQo{iqjpUkOv zUi<2j9P!a?-#r@HlAz5E(wY>ea^_D*>bEPpa#~=fuk*okY~f)F-GTi? z*SA7CZvW{KG+S+gQ^h44Xm%8@;pudP_0kHbvV zeCWlrh=2}UGE-Kn!d*4z#c-v3;=^|wij^ll*<&)9Eu|M)?H`=z9ga$(>5qgI{)o!{WU&IYt8q_J&T6|sIFf2%6 zPvL{`lFl5H`W(0h&xP{=%{E*2oK7Z_otiqovkm9TyzSPDA*b5YSv{0cUEeMmM{JSF zp7dNR*EwWRg2YsBnHX@OFkK6LE1)di%K7DWDIIVQvAwi%XN6WMRW`^Ug&Uteq>otl zp-YRrx-_ZdBs&+?UhjF*IOD8ac43Q&pT^3ewGK;t=239m9TV*DE5208f;>9%hFzM} z>POtF=sqL5wLov=BFX_EFWAf91ZvEl2X>0vrDfmB8Tc9%EVtM7zzH`*u);k-cf)2f z=u9?T$i(rerXQMMbE9!i6Pc>hS+HtZ4i|pS^kGwe)ib*9v_4iJ?sm1y5aBN@8&T)Lp0 zFsykVORZXPKMpUgvL>kN0wG%jJbw*=RfLtb@5Pfs>*WF2D?aJ#)Urx997sM0%W_g2 zl~)){^RSJ;Yr!5FH917-#}|f3j0xRKsz)43{P9lAH$*<+le!rgeTo9yzP=47bwpj> z>pILbZwKxeDXwZH`b`rCir*`P?v#H{E|=9#z1P2HWT}$jMuaWMsA)VTRes9jNeUTo zw@(~e>?O@=u*U4RC;$bZ02F`%Pyh-*0Vn_kpa2wr0#E=7KmjNK1)u;FfC5ke3P1rU00p1`6o3Ly d017|>C;$bZ02F`%Pyh-*0Vn_kpujIu;IASK8Fc^v literal 0 HcmV?d00001 diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/qemu_test/cust_flash_legacy/partition-table.bin b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/qemu_test/cust_flash_legacy/partition-table.bin new file mode 100644 index 0000000000000000000000000000000000000000..adf0db09eef9c3f20e50c5d1337c57f4c14b4815 GIT binary patch literal 3072 zcmZ1#V9&;Ifq{V`fq|i*C^f#ID8CHIgM(E8ASM$K3oxW5CYR(FRl?;!jMuOKqkyNY zHeG+VE%;yuCh}sc)h6Qo6_m>GgY5jcpWfJSqo3Gl%v_y!ImNGTNcYwnFmB~ z9hNwq)@c0Ay3(bw<*D5iuCpGjBg0ot`+bi6HFt0gXK55JP>9C?)NzQu;NKZTvzGf+ zi6b4X70SvGN!6a}l*Q4sMX_bcnbgmfS_AX-OjD-jt?Zou50EuF^7fvimyp;ID4e}W z!~TJu)zdu^{T9rZKW_wvti5GT4;w!NKWwjhTo{;52cVoQ!blb;q>i0wi~)D@yIu#L z(8J_YM5YjMQ#%R^R~&Rk@%db;6&>wia4E6bJ`=zo;fMFKgcd@@Yqilf6Sp{{U1ZH` zaeKy{zh*odC%p&fphjKNV+`}M`HZ7LzFvg`JR&>^347V@3Nlbeq14Kaoe~XlVjk%| z@gX7z;?P2*Ig;l>N&-;t6lpLC>h7gv0I*K7@6z5>VlbE1ezYkpJ~EVdP=a~o6NSNR z^K87!e!$4&V16eg2)zf*>>GF}k1ik;JL)rWP&eA%IUYkD97VZ*qz5SD>kDv{`MGs- zrBwKen@Tkv!0OgE*u7N~GK`wrKh&eB7Z9nJvfiq<>-TJ6%B5+$=M2rKb+_bbw#K@O zox5ac?f?VvHrSjzBoa#UOLpRU`B->biPM*qgu z6Afcv=%hrJJ4PzbwSu0{(s-H1akmH~I}e*N@6cB7Vk0d%dSED+Oz9#BXxK>&c7Yo| z0jgjp+c93%5qP9D3!8B3i1LCTEl87V%i|y-xK|k=TMfM`EZ~Pgh}Y!WKHGv_1`a5* z7AvvPphoiUFG{4@I6R}^!wQI<_K*}2aO;kDqB0*4ql_g}j&l!_CJj%JuTlg6=frzh zzx^%ni=3R!{&!)2{P^)Ve^va`Z~oKoAOADIU*l!&7Ogez|Hf~MHCh!Y1yc5MGNTs}5}t_HuAnh>Ek@B-lYnN#p5q=&G9MMJA#) z>N?W$1qke)bv#|xSoWHvRm$5;bTH-Et# zz{5609;s-6qlf$S`8?jWC8Ai<7n058iW;00nk<)toETq4WdZ6A9T!I`H*%?ZHUOF- z-c%+92AzvL!J6e1*z)nk&yUUlX)`rnIj{FRZ+FJ02*llY$;T0l1f4K1I_iL4O;uQ* zF!4ru7S#Tv-&$(=V{Z3j6uwd{y@1;*(p}VB{^7(ckIT*4i{~?gJfy8p+M{f?PUnMP z7e6k+Kq>@#(L%DY%E1?OmGV{dKANs0hHxO)({PC2YS?m zC=}vOx7l^}#77~62P`Im#C3Egplj*$3O8p%GcoW?d!IVFPz+RsscSx5mG{b>j)_Oh zvH3Z)eY;r6tQ$z-0xu=E2Gl9B*)t;Ms-{yb&I(T_CGApl8clUaE>`u3bXui4>BIRv4Fl+Nt)qcZ3GH{8N7a{lES5KmM2BfBxei{_>Y$@caF3JJe66E%{&j`zM79f8F8S zXh}3hDZk9-=jp(vzW2CBB)jfjt-bFB9S*i|)HUcrmw1}=f@vXy1RFUQK!9d6Gq+;H zM}GZQlNw93I;#mn`#CG@_|w(ooRyJs{O)zdp|>bf(}FA2t9{JWTn-Mr|D5 zy{beS2k?C^!NFmDD3A?4&bMF9f8qjAds*Cz3Um71=t2*z-_ zPqJgkOKtmVZARfD4e?2a(m-vzJ}PV!k<<1OUh5kgqiC#H52)8qw?3;i!O?K2OK4z? zwAz|HtVDwr@O>)5%NINUwu%-DeKi?Wgc#VuLCs5dWfADzU{tdpjCN0W#m4H9RoS&# z1wxT0kFla%U?f`-OIZ|64PUS==30skA>!3pTZ#crm_-H!y$y|6-RiT4pXY{q`mP*l z>Gf(H9LK!i63ON0*Bix7(HT>v+(+^7$3$R5z`mfcvcEdC&`Gs|65-_J(MqRe`I)dYy<}7HdO3-$`(R{_UwyR$r&48FUlpXIt%? z35MmAc=kTj#@FT9KjLQtawsr!i9ZbK7h&P+zyr-KsyEN)a~kDP_3c0Xxv5PgJj!)y zZ)edNn|FrRfN=j#-@70HjL)Ij5UiUs&#%Df_C77e-oY_1_isG0t)s+)6mCXvLVPh= ziPICCVZv?1Xb#AefH$~GDOv0aOiERCmX87ts%WrWw`5*|t3-#g%9AaFv4ib{!QjN; zKdOTNeZ@Ki6#J%4&(4LMi`8-cg-Ey=!GzlSquIS#Br{2Umx!4*ny3Duv-U1~W<#OJ z&Vat+vjEjRAL=4wsuP$OkvbhwM4oNfyTvWcNWh-(B)g>4_IpEpm@%E{34s{lQ|&XU4L+3x-j*t5SJR;+$0S?RE|Nfh5>dYNyblUF66 zhqYM_XK$V)jbTibcH;nZuHN`io*E*K6F}5FW`sZZ{w&C4d64e3gmE|;lL zwk-`1#k9*)=hctOEp1p;-9zdp87s;4NF%3@!@M_zB2@wpSUkw8AMwwvOl1zw*P2xc zwFOG!gvWlN~w9u|aY(62h zT#cfa?ilEyyutzRMS&twQu5E;`h)B9kFJ{^&%gdx@8^HZ@AxM0P2iirH-T>g-vqu1 bd=vO4@J-;Gz&C+!0^bC_349ay|0D1pwemYr literal 0 HcmV?d00001 diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/qemu_test/cust_flash_tlv/partition-table.bin b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/qemu_test/cust_flash_tlv/partition-table.bin new file mode 100644 index 0000000000000000000000000000000000000000..ebd80f17e9b2d1cce532656c205c5cc9ff73dd82 GIT binary patch literal 3072 zcmZ1#V9&;Ifq{WRfq@~lxFEhbHMz7XH9k4Ds01j;z_2O+L^1)f07F`0a!GzsB}f1c zUcdg20!|+IdH2h literal 0 HcmV?d00001 diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/qemu_test/make-qemu-img.sh b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/qemu_test/make-qemu-img.sh new file mode 100644 index 000000000..d751a188f --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/qemu_test/make-qemu-img.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash +set -e +arg_esp_secucertimg=$1 +arg_partition_table=$2 +arg_projpath="$3" +arg_projname="$4" +arg_flashimg=$5 + +if [ -z "$1" -o -z "$2" -o -z "$3" ]; then + echo "Usage: make-qemu-img.sh esp_secure_cert_partition partition_table path_to_build_dir project_name image_name" + exit 1 +fi + +dd if=/dev/zero bs=1024 count=4096 of=${arg_flashimg} +dd if=${arg_projpath}/build/bootloader/bootloader.bin bs=1 seek=$((0x1000)) of=${arg_flashimg} conv=notrunc +dd if=${arg_esp_secucertimg} bs=1 seek=$((0xD000)) of=${arg_flashimg} conv=notrunc +dd if=${arg_partition_table} bs=1 seek=$((0xC000)) of=${arg_flashimg} conv=notrunc +dd if=${arg_projpath}/build/${arg_projname}.bin bs=1 seek=$((0x20000)) of=${arg_flashimg} conv=notrunc diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/qemu_test/nvs/nvs.bin b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/qemu_test/nvs/nvs.bin new file mode 100644 index 0000000000000000000000000000000000000000..aed22893791f75d9818c538241ae8e00c5e182dc GIT binary patch literal 12288 zcmeH~JMZl3RmS%g5``rSiuC6c6v&Evx5q__*Vpm*HolI>&5>_odwiW4-%FJA^b{0y zv{cYir9q_NGw>Zy#2@c{q7Y7wA|$GaS&c_a@4R0A`F)+v(fX{Pkdk$Q!R6JX zs7jfgQ4Uxy2?)T^Z7>V@Rq!oK5J2idVPK$&XmC1527;@sx?nB(9pHulHdE^Moc<*@ zo9=IOvv?OR9gs4>JP`u(eDr01OL@!MvJdi*l}VL0*rWJEQ#*LyvUow2hj2+#xHMO^f8IWYdZZ zyyxW!r8Gf~!+5ihYtf)HKe2vJ4O}7?9Wz~Bk%@b73-C201)qK{u^P}mDw5-5YuO~w z478l3K@991OjT~AXJ46_80jYf@I!n(Bq4Re@>6&NdbA$KZENhv5s#vs_d`p9HA|rC zg_DP?w8U3OaAA=Lvk1VCodIC(Z$JdD<&lTxpiyZ-^XqegY*ln!^Tbw;Ecwwa9Z1WP z>BEB4N7%AS8IklOaUe}8MUa;o&39kKvicDOnoj5T+(CNrnzFnJ&+x1AS4ERNEXC*2 z!{d7a!!PlP=XrF)b4x$lrO?`5p`z%@9G+?c7VWIc9`=^pXm~xwn z^ZjaS@W(xAbmRlaB}r25QwLhSoarXBO_8ZyUXFbt4O`K=^gPe; z>o^nk=~&gy*elQ#5 z3_^oUw2e~W(7zr6D(K1i)K!@(Bdpv3URAL>waW%^_ZdV_J7vDxERbssG20G_`U9@|I83$D!%03=lj9QV6 zI%%zW_kj}HSIfNfkR2r^gxxHFS3}>>e6FR4pXU!rg@m3np$G+V^QO@nkMHn>!`4zU?V1Y5b1eF@*EV@ zXO9sOZM~M+=1!B-sEI*btWQ^uS1};3^qJfyiYDPvB%<;aW#SFwItKwD{?N9y-`F+> z1kWHg?L`$a>t^xFd7QTBn+Px5BQ+jWeZzeyO7UrB5%44rg5S(>bF_E&msJ0Dc^M`~ za`urbMW*6UEN?y7>%}`su7Byp_NLAuy+JCY9oFU)*Xzp(YwLXTHF!#y-nPmj;DReN zKTwb&MWwN@wI<$$Cm(8a^Va%gT+A~887S$W0|C|R*f_o%Gak5S-`cHOVEJ=M#LOiS z$!uR+-BFWlB}nTLF2-3a(WQmNiqLs#2w@c|n-~D#E*nV~a(@SKUBa0# zx;IK`in?GHM{dHB-Q?6Koo-NZKIUto9Abx_gECNtMF?J}Ve?~Gjuw*2&dChA`V~`s zohxhiypaD3ulW2e{qgU={O72DmeY4twthbyeERg)fBNz9ul`?1zvBBmCw=;s+Tf2yW`qlgKy~t?1bB5h_UDyof45l%4HSCg3_*4OIW=Aldi9#kK9-Avj zGas?_ybx(TnwW5IDDZ4h3)WJ#G!v_=Ml~N|E@7mezEtjzVh1B-9*cZSCd9e77!+A- zn8YomWVbBS4IWu&#o@fkdU^o$F232yG%_BYD6Bd=x^S5QB%4-QHOA>Wr6h z%%}WG^>#)wU6_t#8weZXl~c(Z@nB)5Bng4aIEHky@thOglRbqU42>F7E)q^A4|J0c zg#^py9o88*8_&StH3a|F(K?l)#}R=J7AokkiBRr$A{fZEHquYTKFdcB(FEFSc;vUAk9 zA%IsLeNHvMB(7h{{@054GXOP=qN;{;f6dM`HKHZldE5-of!RkTm&Vor!VnmQNQ1Lf zs5hVrSlo9!ZLL(&VoU`&D_HShyd<42Au^)x#*bfT-L7?H7w>}ws>Hk6t=*@SE`3CH zf=`7-X03L^#8k*DNL6-EJk8?F?rr(8Y*zLRjdUN3^e6;Y-y5({;i29&=;PIT zw8V1k4^U{vu|n7gTRlAaHp8Cov_dm2UrW}DSwdabSa_?~E@i#kCp_q=E=y$chDzK` zA)s!(r%`WXsYP=q9zp#S9FKe^j{FFZ&&BqvdF6ReM4dSd=VhB7+_fn|KsDltX{Z~d zU9H|25fGY)Y{g9oC$WiKZ<{$>=w~yp`2MvJ!oD<>#r=d)eb!;U`C1;geV|mY+6LLQ zeU&N;+e-%ejA17tn>N~qnLMv9$_$9;B~97gZEV(W*vY^#JJ!tlr5jF1(M}4r;hmum zV;zNb(8}adSQuQ=VRIe#$-T@4^u!$wO8zp!Ma|h_Op$WR5``rSis{cOD3CSs-HwYXwy$w~i?4Cq9QhX8@imF>C7S8!DJbX= z9Tl`x(;)Z?G<*j%;=%93FbrpoMo3g6vI-|!+1XnDdH?@w`IjFbA3xgT-}le&$IpK9 z_kZ`-zccp#e);k-|INQ7{WJTne|FQ?y}rhmUv2i~+iyPLKmOZ)PNMIU>^Xe?_Vx0Q zfAI0~^I!bf`pMVeL|HMu;YHh3B!vgA_?d-tMd3Sv=fO4Sd5b@-XnodCNXfdu;PUEG zRHe+$CG&r3j1Hn~RU9cAY4sb&Nn<;gBPXC&l zP50NiS-gvu4oDebo(O??KKio1r93BC?p}$b%z|}2sa>cPQ(^#16BF^VYYV{%Rw|sk8C*KVxL1rCZ}Pk3VMT8eSbI( zi=G5=xmF{jJvZmld*t-+Rxi(=Sz5h3E<3AJF&gnH^Un?4>8Hy*n8l*RL)eSpsJ4mV za?7LGBOuP-m>jG+a@|gdU|!9!MLAcwAg{;Gozeb@p+`D(+D1)1?vRzsrbY5pvT4Ny z-t+Q=Qko#gVZ2$$wP?_ppIASq1}+hcj+w5m$izLk1^610f=@q}SPf_&70Ge3wQLe- z23pS2AO?00rYbkmv#-odjPw%#_#wU?l8`!K`6;{sJz5Xrwl#L-h)2=R`=KSlnk7*6 z!pXx`TH>oCxUk5BSp?vR&Hym?Cm;gX^2kGT(5SSa`SrO#wko==d15O^mi%az4y0wt z^kKp2BW&5Ej7a*CIFP24BFIaP=DROqS^WqCO{a5v?jXH*Ob48nD*4u+V$l{ZmOGOu0?P z`F=Gud7O2l{bw`>5I`V@KbVbj z2BASF+D0jG=wA;374+nM>Z(kY5mxR1a)&IsZbR#*KZQQUDH_6W3-(9fcaV>dFW-Lq z@n?VfM}LuK)BiAlf7|s>V%hY$+3(Q*eBV_Sb-VtBbw4t>ddyIF`#& zJ>fGq8-l3mp!!e!bA`@39=YsxqH?+6bD+}!>bssG20G_`F4{f9jDsod!fqD8@&F(ePME>h1uE#2Jttf<;q;(&5tEy;Xd;vWJWOHw z%;iO)W9^v8ZucO_TGPbyQeUun`kHi1a)oc@7Hd zv&RUCwqDC@bEnB^)Wjez)~Bn-s~C`1`b=&UMU(I-5>fezGVum-or3@nzi->xuWXwG zf@ct$_M(cIb+dToJWgBmO@tTjks1%GzTrL;rTDb62zZhQ!EffcIoiAXOR9gnybKc~ zIr~VJB2)1vmbV`4_2Qi**T3{)dsF9--XN9H4r_CY>-FV?wROJv8a$;;Z(C&%aKV+C zA1FwXqS9E{S`+WWlMl7Id24+#F6Nnl43zZGfq?3DY#d*X84ujEZ|znsu>3hBV&)Qv zWVWxZ?x;z&5~TGA7vrpz=+Z)BMd&;=gs_T~O$-2VmyM(gxxWLrF5y_8q?U*(#$$m= z-5aGeMO`q9BR65mZgT3APB*AHAM>?P4zWYeK^Z8+A_T9~u=%koM+-@1=VS(5{feo+ z&Xu)$UdaE2SA6-F{`l8l{6o|~%jvr+TmNf7`13#f`1mLPPo&@Q2ipPPoNdM5=Ywxl z@%rl-LF}zvL_q!Yeta)78tfScJ7jAx>diHOJM3ewC+ zY&|bT8jmI>oEr)}8`OfeR4vWKDyvb=hnPzksi!ZMJEYjbNSVhX-;xP&?kxsI78@pU zODWkc%XEWB7FuyQZ?c{qK)s7^wla;3M`w9W(nb-{b>l}O%Hz!-gtN^F5Rfl3ktedF z)uR+C1nh)GW%T@Q8L9GG!pV}v4gt{9{9^X*y-2uNk7N2K@o+aviJKu2@GN{^z9j+_;PC~N4s3&)_ zXJF=?MbzwCjvnh-j^l#qngD&pz`a5v*wOagnUW+hXyV8I7R(oTBue#m5i+dkJNK20 zZRt*jtxlX75hOmItW#DZJXji){ zVNRW^nlPUJ+#fZ4I~CU^3dWNlXa!dFX}pOCh&vvMTfZs5>Ccas863ggrh-AgjQdcE zuJbA|Ol?dEdr`Ie^281pCn#huTFUWZ_Yw_%`b`TSF-#W=<<phKn8%r&kJMjqWr{H+xGjZfccziClXU!|mdm`%0VK^__^x&>d2?DASPfSDIAnj`P z#)yE>L}V*&LO6*{&@5lxa|X_det__rtPa# zS=e4O&}R%g5!tlSKFs8Kbx~$OL@#N|?rvkVe#1@%j@hwh)-T;~I*N8us15H7eHiN~ zq=Qx_kHW&>k`9~exKHk7E}$pwa8UA>5iV-Z7Gsi}3pk1}skISC(r`!-9~f<_$v9rE zSyM73I`gGl>krYJc%>3}*%mn0YuEN=iwT=h&qsJX>A%sjez4vAz=ZqTGw<(H=9hc1 zU-qW^L+}58b^Oc2@6)}!Ykd=V6L=GN6L=GN6L=GN6L=GN6L=GN6L=GN6L=GN6L=GN g6L=GN6L=GN6L=GN6L=GN6L=GN6L=H&|4QIL0G)KeRsaA1 literal 0 HcmV?d00001 diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/qemu_test/nvs_legacy/partition-table.bin b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/qemu_test/nvs_legacy/partition-table.bin new file mode 100644 index 0000000000000000000000000000000000000000..f50b435b802966abcfa6e43a6de44219a1cc9a16 GIT binary patch literal 3072 zcmZ1#z{tdKfq{V`fq|i*C^f#ID8CHIgM(E8ASM$K3oxW5CYR(FRl?;!jMuOKqk!j6 zot6vT^$D_KF`F=5&@l)_a+EU~0;3@?8UmvsFd71*Aut*OqaiRF0;3@?pdkPNoQ<^Y literal 0 HcmV?d00001 diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/qemu_test/requirements.txt b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/qemu_test/requirements.txt new file mode 100644 index 000000000..2bc4dd470 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/qemu_test/requirements.txt @@ -0,0 +1,3 @@ +pytest_embedded +pytest_embedded_idf +pytest_embedded_qemu diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/sdkconfig.ci.legacy b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/sdkconfig.ci.legacy new file mode 100644 index 000000000..7cb75391a --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/sdkconfig.ci.legacy @@ -0,0 +1,2 @@ +CONFIG_ESP_TASK_WDT_EN=n +CONFIG_ESP_SECURE_CERT_SUPPORT_LEGACY_FORMATS=y diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/sdkconfig.ci.tlv b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/sdkconfig.ci.tlv new file mode 100644 index 000000000..e4bfc208a --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/sdkconfig.ci.tlv @@ -0,0 +1 @@ +CONFIG_ESP_TASK_WDT_EN=n diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/sdkconfig.defaults b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/sdkconfig.defaults new file mode 100644 index 000000000..f15366026 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/sdkconfig.defaults @@ -0,0 +1,3 @@ +CONFIG_PARTITION_TABLE_CUSTOM=y +CONFIG_PARTITION_TABLE_OFFSET=0xc000 +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/test_esp_secure_cert.py b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/test_esp_secure_cert.py new file mode 100644 index 000000000..4b860150e --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/esp_secure_cert_app/test_esp_secure_cert.py @@ -0,0 +1,24 @@ +import pytest +import os + +qemu_images = [] +qemu_images_path = 'qemu_test/qemu_test_images' + +# Use os.walk to traverse the directory and its subdirectories +for root, dirs, files in os.walk(qemu_images_path): + for file in files: + if file.endswith('.img'): + file_path = os.path.join(root, file) + qemu_images.append(file_path) + +# Print the list of image filenames +print('The list entries are ------------') +for image in qemu_images: + print(image) + + +@pytest.mark.parametrize('qemu_image_path', qemu_images, indirect=True) +@pytest.mark.parametrize('skip_regenerate_image', ['y'], indirect=True) +def test_esp_secure_cert(dut): + dut.expect('Successfully obtained and verified the ' + 'contents of esp_secure_cert partition') diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/pytest.ini b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/pytest.ini new file mode 100644 index 000000000..7f71b9ae4 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/examples/pytest.ini @@ -0,0 +1,13 @@ +[pytest] +addopts = --embedded-services idf,qemu -s + +# log related +log_cli = True +log_cli_level = INFO +log_cli_format = %(asctime)s %(levelname)s %(message)s +log_cli_date_format = %Y-%m-%d %H:%M:%S + +log_file = test.log +log_file_level = INFO +log_file_format = %(asctime)s %(levelname)s %(message)s +log_file_date_format = %Y-%m-%d %H:%M:%S diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/idf_component.yml b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/idf_component.yml new file mode 100644 index 000000000..8c35f70a8 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/idf_component.yml @@ -0,0 +1,10 @@ +dependencies: + idf: + version: '>=4.3' +description: ESP Secure Cert Manager +repository: git://github.com/espressif/esp_secure_cert_mgr.git +repository_info: + commit_sha: 48c7dfe46c8beff161248eeb2a7d3ac94cca1949 + path: . +url: https://github.com/espressif/esp_secure_cert_mgr +version: 2.5.0 diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/include/esp_secure_cert_crypto.h b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/include/esp_secure_cert_crypto.h new file mode 100644 index 000000000..5a41556eb --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/include/esp_secure_cert_crypto.h @@ -0,0 +1,28 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once +#include "esp_err.h" +#include "soc/soc_caps.h" + +#ifdef SOC_HMAC_SUPPORTED +#include "esp_hmac.h" +/* + * @info + * PBKDF2_hmac- password based key derivation function based on HMAC. + * The API acts as a password based key derivation function by using the hardware HMAC peripheral present on the SoC. The hmac key shall be used from the efuse key block provided as the hmac_key_id. The API makes use of the hardware HMAC peripheral and hardware SHA peripheral present on the SoC. The SHA operation is limited to SHA256. + * @input + * hmac_key_id The efuse_key_id in which the HMAC key has already been burned. + * This key should be read and write protected for its protection. That way it can only be accessed by the hardware HMAC peripheral. + * salt The buffer containing the salt value + * salt_len The length of the salt in bytes + * key_length The expected length of the derived key. + * iteration_count The count for which the internal cryptographic operation shall be repeated. + * output The pointer to the buffer in which the derived key shall be stored. It must of a writable buffer of size key_length bytes + * + */ +int esp_pbkdf2_hmac_sha256(hmac_key_id_t hmac_key_id, const unsigned char *salt, size_t salt_len, + size_t iteration_count, size_t key_length, unsigned char *output); +#endif diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/include/esp_secure_cert_read.h b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/include/esp_secure_cert_read.h new file mode 100644 index 000000000..50864f00e --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/include/esp_secure_cert_read.h @@ -0,0 +1,235 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once +#include "esp_err.h" + +#include "soc/soc_caps.h" +#ifdef CONFIG_ESP_SECURE_CERT_DS_PERIPHERAL +#include "rsa_sign_alt.h" +#endif + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** +@brief Enumeration of ESP Secure Certificate key types. +*/ +typedef enum key_type { + ESP_SECURE_CERT_INVALID_KEY = -1, /* Invalid key */ + ESP_SECURE_CERT_DEFAULT_FORMAT_KEY, /* Key type for the key in default format */ + ESP_SECURE_CERT_HMAC_ENCRYPTED_KEY, /* Encrypted key type */ + ESP_SECURE_CERT_HMAC_DERIVED_ECDSA_KEY, /* HMAC-derived ECDSA key type. */ + ESP_SECURE_CERT_ECDSA_PERIPHERAL_KEY, /* ECDSA peripheral key type. */ +} esp_secure_cert_key_type_t; + +/* @info + * Init the esp_secure_cert nvs partition + * + * @return + * - ESP_OK On success + * - ESP_FAIL/other relevant esp error code + * On failure + */ +esp_err_t esp_secure_cert_init_nvs_partition(void); + +/* @info + * Get the device cert from the esp_secure_cert partition + * + * @note + * If your esp_secure_cert partition is of type NVS, the API will dynamically allocate + * the required memory to store the device cert and return the pointer. + * The pointer can be freed in this case (NVS) using respective free API + * + * In case of cust_flash partition, a read only flash pointer shall be returned here. + * + * A respective call to the esp_secure_cert_free_device_cert() should be made to free any memory (if allocated) + * + * IMPORTANT: This API shall provide only the first entry of type Device cert (ESP_SECURE_CERT_DEV_CERT_TLV) present in the esp_secure_cert partition with subtype set as 0. + * If you have multiple entries of the given type with different subtypes then please use the generic API esp_secure_cert_get_tlv_info with the appropriate type and subtype. + * The type in this case shall be ESP_SECURE_CERT_DEV_CERT_TLV + * and the subtype shall be the index of the device cert that needs to be obtained. + * + * @params + * - buffer(out) This value shall be filled with the device cert address + * on successful completion + * - len(out) This value shall be filled with the length of the device cert + * If your esp_secure_cert partition is of type NVS, the API will dynamically allocate + * the required memory to store the device cert + * + * In case of cust_flash partition, a read only flash pointer shall be returned here. + * @return + * - ESP_OK On success + * - ESP_FAIL/other relevant esp error code + * On failure + */ +esp_err_t esp_secure_cert_get_device_cert(char **buffer, uint32_t *len); + +/* + * Free any internally allocated resources for the device cert. + * @note + * This API would free the memory if it is dynamically allocated + * + * @params + * - buffer(in) The data pointer + * This pointer should be the same one which has been obtained + * through "esp_secure_cert_get_device_cert" API. + */ +esp_err_t esp_secure_cert_free_device_cert(char *buffer); + +/* @info + * Get the ca cert from the esp_secure_cert partition + * + * @note + * The API shall dynamically allocate the memory if required. + * The dynamic allocation of memory shall be required in following cases: + * 1) partition type is NVS + * 2) HMAC encryption is enabled for the API needs to be called + * + * The esp_secure_cert_free_ca_cert API needs to be called in order to free the memory. + * The API shall only free the memory if it has been dynamically allocated. + * + * IMPORTANT: This API shall provide only the first entry of type CA cert (ESP_SECURE_CERT_CA_CERT_TLV) present in the esp_secure_cert partition subtype set as 0. + * If you have multiple entries of the given type with different subtypes then please use the generic API esp_secure_cert_get_tlv_info with the appropriate type and subtype. + * The type in this case shall be ESP_SECURE_CERT_CA_CERT_TLV + * and the subtype shall be the index of the device cert that needs to be obtained. + * + * @params + * - buffer(out) This value shall be filled with the ca cert address + * on successful completion + * - len(out) This value shall be filled with the length of the ca cert + * If your esp_secure_cert partition is of type NVS, the API will dynamically allocate + * the required memory to store the ca cert + * + * In case of cust_flash partition, a read only flash pointer shall be returned here. + * @return + * - ESP_OK On success + * - ESP_FAIL/other relevant esp error code + * On failure + */ +esp_err_t esp_secure_cert_get_ca_cert(char **buffer, uint32_t *len); + +/* + * Free any internally allocated resources for the ca cert. + * @note + * This API would free the memory if it is dynamically allocated + * + * @params + * - buffer(in) The data pointer + * This pointer should be the same one which + * has been obtained through "esp_secure_cert_get_ca_cert" API. + */ +esp_err_t esp_secure_cert_free_ca_cert(char *buffer); + +#ifndef CONFIG_ESP_SECURE_CERT_DS_PERIPHERAL +/* @info + * Get the private key from the esp_secure_cert partition + * + * @note + * The API shall dynamically allocate the memory if required. + * The dynamic allocation of memory shall be required in following cases: + * 1) partition type is NVS + * 2) HMAC encryption is enabled for the API needs to be called + * + * The esp_secure_cert_free_priv_key API needs to be called in order to free the memory. + * The API shall only free the memory if it has been dynamically allocated. + * + * IMPORTANT: This API shall provide only the first entry of type private key (ESP_SECURE_CERT_PRIV_KEY_TLV) present in the esp_secure_cert partition with subtype set as 0. + * If you have multiple entries of the given type with different subtypes then please use the generic API esp_secure_cert_get_tlv_info with the appropriate type and subtype. + * The type in this case shall be ESP_SECURE_CERT_PRIV_KEY_TLV + * and the subtype shall be the index of the device cert that needs to be obtained. + * + * @params + * - buffer(out) This value shall be filled with the private key address + * on successful completion + * - len(out) This value shall be filled with the length of the private key + * + * + * @return + * - ESP_OK On success + * - ESP_FAIL/other relevant esp error code + * On failure + */ +esp_err_t esp_secure_cert_get_priv_key(char **buffer, uint32_t *len); + +/* + * Free any internally allocated resources for the priv key. + * @note + * This API would free the memory if it is dynamically allocated + * + * @params + * - buffer(in) The data pointer + * This pointer should be the same one which + * has been obtained through "esp_secure_cert_get_priv_key" API. + */ +esp_err_t esp_secure_cert_free_priv_key(char *buffer); + +#else /* !CONFIG_ESP_SECURE_CERT_DS_PERIPHERAL */ +/* @info + * This function returns the flash esp_ds_context which can then be + * directly provided to an esp-tls connection through its config structure. + * The memory for the context is dynamically allocated. + * @note + * This shall generate the DS context only for the + * TLV entry with subtype 0 (First TLV entry for DS context) + * Internally this API assumes that the TLV entries with + * type ESP_SECURE_CERT_DS_CTX_TLV and ESP_SECURE_CERT_DS_DATA_TLV and subtype 0 + * are present. + * A call to esp_secure_cert_free_ds_ctx() should be made + * to free the allocated memory + * + * @return + * - ds_ctx The pointer to the DS context, On success + * - NULL On failure + */ +esp_ds_data_ctx_t *esp_secure_cert_get_ds_ctx(void); + +/* + * @info + * Free the DS context + */ +void esp_secure_cert_free_ds_ctx(esp_ds_data_ctx_t *ds_ctx); +#endif /* CONFIG_ESP_SECURE_CERT_DS_PERIPHERAL */ + +#ifndef CONFIG_ESP_SECURE_CERT_SUPPORT_LEGACY_FORMATS + +/* @info + * Get the private key type from the esp_secure_cert partition + * + * @note + * The API is only supported for the TLV format + * This API shall only provide information for the private key with subtype set to ESP_SECURE_CERT_TLV_SUBTYPE_0 (first entry) + * + * @params + * - priv_key_type(out) Pointer to store the obtained key type + * @return + * - ESP_OK On success + * - ESP_FAIL/other relevant esp error code + * On failure + */ +esp_err_t esp_secure_cert_get_priv_key_type(esp_secure_cert_key_type_t *priv_key_type); + +/* @info + * Get the efuse block id in which the private key is stored. + * @note + * The API is only supported for the TLV format. + * For now only ECDSA type of private key can be stored in the efuse block + * This API shall only provide information for the private key with subtype set to ESP_SECURE_CERT_TLV_SUBTYPE_0 (first entry) + * + * @params + * - efuse_block_id(out) Pointer to store the obtained efuse block id + * @return + * - ESP_OK On success + * - ESP_FAIL/other relevant esp error code + * On failure + */ +esp_err_t esp_secure_cert_get_priv_key_efuse_id(uint8_t *efuse_block_id); +#endif + +#ifdef __cplusplus +} +#endif diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/include/esp_secure_cert_tlv_config.h b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/include/esp_secure_cert_tlv_config.h new file mode 100644 index 000000000..86760f032 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/include/esp_secure_cert_tlv_config.h @@ -0,0 +1,65 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "esp_bit_defs.h" +#include "sdkconfig.h" +#include "soc/soc_caps.h" +#ifdef CONFIG_ESP_SECURE_CERT_DS_PERIPHERAL +#include "esp_ds.h" +#endif + +/* + * Plase note that no two TLV structures of the same type + * can be stored in the esp_secure_cert partition at one time. + */ +typedef enum esp_secure_cert_tlv_type { + ESP_SECURE_CERT_CA_CERT_TLV = 0, + ESP_SECURE_CERT_DEV_CERT_TLV, + ESP_SECURE_CERT_PRIV_KEY_TLV, + ESP_SECURE_CERT_DS_DATA_TLV, + ESP_SECURE_CERT_DS_CONTEXT_TLV, + ESP_SECURE_CERT_HMAC_ECDSA_KEY_SALT, + ESP_SECURE_CERT_TLV_SEC_CFG, + // Any new tlv types should be added above this + ESP_SECURE_CERT_TLV_END = 50, + //Custom data types + //that can be defined by the user + ESP_SECURE_CERT_USER_DATA_1 = 51, + ESP_SECURE_CERT_USER_DATA_2 = 52, + ESP_SECURE_CERT_USER_DATA_3 = 53, + ESP_SECURE_CERT_USER_DATA_4 = 54, + ESP_SECURE_CERT_USER_DATA_5 = 54, + /* The following TLV entries are reserved for project-specific + * purposes and should not be utilized by the application */ + ESP_SECURE_CERT_MATTER_TLV_1 = 201, + ESP_SECURE_CERT_MATTER_TLV_2 = 202, + ESP_SECURE_CERT_TLV_MAX = 254, /* Max TLV entry identifier (should not be assigned to a TLV entry) */ + ESP_SECURE_CERT_TLV_INVALID = 255, /* Invalid TLV type */ +} esp_secure_cert_tlv_type_t; + +typedef enum esp_secure_cert_tlv_subtype { + ESP_SECURE_CERT_SUBTYPE_0 = 0, + ESP_SECURE_CERT_SUBTYPE_1 = 1, + ESP_SECURE_CERT_SUBTYPE_2 = 2, + ESP_SECURE_CERT_SUBTYPE_3 = 3, + ESP_SECURE_CERT_SUBTYPE_4 = 4, + ESP_SECURE_CERT_SUBTYPE_5 = 5, + ESP_SECURE_CERT_SUBTYPE_6 = 6, + ESP_SECURE_CERT_SUBTYPE_7 = 7, + ESP_SECURE_CERT_SUBTYPE_8 = 8, + ESP_SECURE_CERT_SUBTYPE_9 = 9, + ESP_SECURE_CERT_SUBTYPE_10 = 10, + ESP_SECURE_CERT_SUBTYPE_11 = 11, + ESP_SECURE_CERT_SUBTYPE_12 = 12, + ESP_SECURE_CERT_SUBTYPE_13 = 13, + ESP_SECURE_CERT_SUBTYPE_14 = 14, + ESP_SECURE_CERT_SUBTYPE_15 = 15, + ESP_SECURE_CERT_SUBTYPE_16 = 16, + ESP_SECURE_CERT_SUBTYPE_MAX = 254, /* Max Subtype entry identifier (should not be assigned to a TLV entry) */ + ESP_SECURE_CERT_SUBTYPE_INVALID = 255, /* Invalid TLV subtype */ +} esp_secure_cert_tlv_subtype_t; diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/include/esp_secure_cert_tlv_read.h b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/include/esp_secure_cert_tlv_read.h new file mode 100644 index 000000000..e3901673d --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/include/esp_secure_cert_tlv_read.h @@ -0,0 +1,124 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once +#include "esp_err.h" + +#include "esp_secure_cert_tlv_config.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* + * TLV config struct + */ +typedef struct tlv_config { + esp_secure_cert_tlv_type_t type; /* TLV type */ + esp_secure_cert_tlv_subtype_t subtype; /* TLV subtype */ +} esp_secure_cert_tlv_config_t; + +/* + * TLV info struct + */ +typedef struct tlv_info { + esp_secure_cert_tlv_type_t type; /* Type of the TLV */ + esp_secure_cert_tlv_subtype_t subtype; /* Subtype of the TLV */ + char *data; /* Pointer to the buffer containting TLV data */ + uint32_t length; /* TLV data length */ + uint8_t flags; +} esp_secure_cert_tlv_info_t; + +/* + * TLV iterator struct + */ +typedef struct tlv_iterator { + void *iterator; /* Opaque TLV iterator */ +} esp_secure_cert_tlv_iterator_t; + +/* + * Get the TLV information for given TLV configuration + * + * @note + * TLV Algorithms: + * If the TLV data is stored with some additional encryption then it first needs to be decrypted and the decrypted data is + * stored in a dynamically allocated buffer. This API automatically decrypts any encryption applied to the TLV by supported algorithms. + * For this the API may look for TLV entries of other types which store necessary information, these TLV entries must be of the same subtype as of the subtype field in the config struct. + * Please see documentation regarding supported TLV storage algorithms in the TLV documentation. + * A call to the esp_secure_cert_free_tlv_info() should be made to free any memory allocated while populating the tlv information object. + * This API also validates the crc of the respective tlv before returning the offset. + * + * If tlv type in the config struct is set to ESP_SECURE_CERT_TLV_END then the address returned shall be the end address of current tlv formatted data and the length returned shall be the total length of the valid TLV entries. + * @input + * tlv_config Pointer to a readable struct of type esp_secure_cert_tlv_config_t. + * The contents of the struct must be already filled by the caller, + * This information shall be used to find the appropriate TLV entry. + * + * tlv_info Pointer to a writable struct of type esp_secure_cert_tlv_info_t, + * If TLV entry defined by tlv_config is found then the TLV information shall be populated in this struct. + * @return + * + * - ESP_OK On success + * - ESP_FAIL/other relevant esp error code + * On failure + */ +esp_err_t esp_secure_cert_get_tlv_info(esp_secure_cert_tlv_config_t *tlv_config, esp_secure_cert_tlv_info_t *tlv_info); + +/* + * Free the memory allocated while populating the tlv_info object + * @note + * Please note this does not free the tlv_info struct itself but only the memory allocated internally while populating this struct. + */ +esp_err_t esp_secure_cert_free_tlv_info(esp_secure_cert_tlv_info_t *tlv_info); + +/* + * Iterate to the next valid TLV entry + * @note + * To obtain the first TLV entry, the tlv_iterator structure must be zero initialized + * @input + * tlv_iterator Pointer to a readable struct of type esp_secure_cert_tlv_iterator_t + * + * @return + * ESP_OK On success + * The iterator location shall be moved to point to the next TLV entry. + * ESP_FAIL/other relevant error codes + * On failure + */ +esp_err_t esp_secure_cert_iterate_to_next_tlv(esp_secure_cert_tlv_iterator_t *tlv_iterator); + +/* + * Get the TLV information from a valid iterator location + * + * @note + * A call to the esp_secure_cert_free_tlv_info() should be made to free any memory allocated while populating the tlv information object. + * + * @input + * tlv_config Pointer to a readable struct of type esp_secure_cert_tlv_iterator_t. + * The iterator must be set to point to a valid TLV, + * by a previous call to esp_secure_cert_iterate_to_next_tlv();. + * + * tlv_info Pointer to a writable struct of type esp_secure_cert_tlv_info_t + * If TLV entry pointed by the iterator is valid then the TLV information shall be populated in this struct. + * @return + * ESP_OK On success + * The tlv_info object shall be populated with information of the TLV pointed by the iterator + * ESP_FAIL/other relevant error codes + * On failure + */ +esp_err_t esp_secure_cert_get_tlv_info_from_iterator(esp_secure_cert_tlv_iterator_t *tlv_iterator, esp_secure_cert_tlv_info_t *tlv_info); + +/* + * List TLV entries + * + * This API serially traverses through all of the available + * TLV entries in the esp_secure_cert partition and logs + * brief information about each TLV entry. + */ +void esp_secure_cert_list_tlv_entries(void); + +#ifdef __cplusplus +} +#endif diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/private_include/esp_secure_cert_config.h b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/private_include/esp_secure_cert_config.h new file mode 100644 index 000000000..5b315c361 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/private_include/esp_secure_cert_config.h @@ -0,0 +1,87 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once +#include + +#ifdef CONFIG_ESP_SECURE_CERT_DS_PERIPHERAL +#include "esp_ds.h" +#endif + +#define ESP_SECURE_CERT_PKEY_MAGIC_BYTE 0xC1 /* Magic byte of the generated private key */ +#define ESP_SECURE_CERT_DEV_CERT_MAGIC_BYTE 0xC2 /* Magic byte of the generated device certificate */ +#define ESP_SECURE_CERT_CA_CERT_MAGIC_BYTE 0xC3 /* Magic byte of the CA certificate */ + +/* NVS Config */ + +#define ESP_SECURE_CERT_NVS_PARTITION_NAME "esp_secure_cert" /* Name of the nvs pre prov partition */ +#define ESP_SECURE_CERT_NVS_KEYS_PARTITION "esp_secure_cert_keys" + +#define ESP_SECURE_CERT_NVS_LEGACY_PARTITION_NAME "pre_prov" +#define ESP_SECURE_CERT_NVS_LEGACY_KEYS_PARTITION "pre_prov_keys" + +#define ESP_SECURE_CERT_PRIV_KEY "priv_key" +#define ESP_SECURE_CERT_DEV_CERT "dev_cert" +#define ESP_SECURE_CERT_CA_CERT "ca_cert" +#define ESP_SECURE_CERT_NAMESPACE "esp_secure_cert" +#define ESP_SECURE_CERT_LEGACY_NAMESPACE "pre_prov" + + +#define ESP_SECURE_CERT_CIPHERTEXT "cipher_c" +#define ESP_SECURE_CERT_RSA_LEN "rsa_len" +#define ESP_SECURE_CERT_EFUSE_KEY_ID "ds_key_id" +#define ESP_SECURE_CERT_IV "iv" + +#define ESP_SECURE_CERT_METADATA_SIZE 64 /* 32 bytes are reserved for the metadata (Must be a multiple of 32)*/ + +#define ESP_SECURE_CERT_DEV_CERT_SIZE 2048 +#define ESP_SECURE_CERT_CA_CERT_SIZE 4096 +#ifndef CONFIG_ESP_SECURE_CERT_DS_PERIPHERAL +#define ESP_SECURE_CERT_PRIV_KEY_SIZE 4096 +#else +#define ESP_SECURE_CERT_CIPHERTEXT_SIZE (ESP_DS_C_LEN + 16) +#define ESP_SECURE_CERT_IV_SIZE (ESP_DS_IV_LEN + 16) +#endif + +#define ESP_SECURE_CERT_METADATA_OFFSET 0 /* 32 bytes are reserved for the metadata (Must be a multiple of 32)*/ +#define ESP_SECURE_CERT_DEV_CERT_OFFSET (ESP_SECURE_CERT_METADATA_OFFSET + ESP_SECURE_CERT_METADATA_SIZE) +#define ESP_SECURE_CERT_CA_CERT_OFFSET (ESP_SECURE_CERT_DEV_CERT_OFFSET + ESP_SECURE_CERT_DEV_CERT_SIZE) +#ifndef CONFIG_ESP_SECURE_CERT_DS_PERIPHERAL +#define ESP_SECURE_CERT_PRIV_KEY_OFFSET (ESP_SECURE_CERT_CA_CERT_OFFSET + ESP_SECURE_CERT_CA_CERT_SIZE) +#define ESP_SECURE_CERT_MAX_SIZE (ESP_SECURE_CERT_PRIV_KEY_OFFSET + ESP_SECURE_CERT_PRIV_KEY_SIZE) +#else +#define ESP_SECURE_CERT_CIPHERTEXT_OFFSET (ESP_SECURE_CERT_CA_CERT_OFFSET + ESP_SECURE_CERT_CA_CERT_SIZE) +#define ESP_SECURE_CERT_IV_OFFSET (ESP_SECURE_CERT_CIPHERTEXT_OFFSET + ESP_SECURE_CERT_CIPHERTEXT_SIZE) +#define ESP_SECURE_CERT_MAX_SIZE (ESP_SECURE_CERT_IV_OFFSET + ESP_SECURE_CERT_IV_SIZE) +#endif + +#define ESP_SECURE_CERT_CUST_FLASH_PARTITION_TYPE 0x3F /* Custom partition type */ +#define ESP_SECURE_CERT_NVS_PARTITION_TYPE 0x01 /* Data type partition */ +#define ESP_SECURE_CERT_PARTITION_NAME "esp_secure_cert" /* Name of the custom pre prov partition */ +#define ESP_SECURE_CERT_LEGACY_PARTITION_NAME "pre_prov" + +#define ESP_SECURE_CERT_METADATA_MAGIC_WORD 0x12345678 + + + +typedef struct { + uint32_t dev_cert_crc; /* CRC of the dev cert data */ + uint16_t dev_cert_len; /* The actual length of the device cert */ + uint32_t ca_cert_crc; /* CRC of the ca cert data */ + uint16_t ca_cert_len; /* The actual length of the ca cert [The length before the 32 byte alignment] */ +#ifndef CONFIG_ESP_SECURE_CERT_DS_PERIPHERAL + uint32_t priv_key_crc; /* CRC of the priv key data */ + uint16_t priv_key_len; /* The actual length of the private key */ +#else + uint32_t ciphertext_crc; /* CRC of the ciphertext data */ + uint16_t ciphertext_len; /* The actual length of the ciphertext */ + uint32_t iv_crc; /* CRC of the iv data */ + uint16_t iv_len; /* The actual length of iv*/ + uint16_t rsa_length; /* Length of the RSA private key that is encrypted as ciphertext */ + uint8_t efuse_key_id; /* The efuse key block id which holds the HMAC key used to encrypt the ciphertext */ +#endif + uint32_t magic_word; /* The magic word which shall identify the valid metadata when read from flash */ +} esp_secure_cert_metadata; diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/private_include/esp_secure_cert_tlv_private.h b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/private_include/esp_secure_cert_tlv_private.h new file mode 100644 index 000000000..05d7910d7 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/private_include/esp_secure_cert_tlv_private.h @@ -0,0 +1,202 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once +#include "esp_secure_cert_config.h" +#include "esp_secure_cert_tlv_config.h" + +#ifdef CONFIG_ESP_SECURE_CERT_DS_PERIPHERAL +#include "rsa_sign_alt.h" +#endif +#include "soc/soc_caps.h" + +#define ESP_SECURE_CERT_TLV_PARTITION_TYPE 0x3F /* Custom partition type */ +#define ESP_SECURE_CERT_TLV_PARTITION_NAME "esp_secure_cert" /* Name of the custom esp_secure_cert partition */ +#define ESP_SECURE_CERT_TLV_MAGIC 0xBA5EBA11 + +#define ESP_SECURE_CERT_HMAC_KEY_ID (0) /* The hmac_key_id value that shall be used for HMAC based ecdsa key generation */ +#define ESP_SECURE_CERT_DERIVED_ECDSA_KEY_SIZE (32) /* The key size in bytes of the derived ecdsa key */ +#define ESP_SECURE_CERT_KEY_DERIVATION_ITERATION_COUNT (2048) /* The iteration count for ecdsa key derivation */ + + + +/** + * Flags 8 bits + * Used bits: + * bit7(MSB) & bit6 - hmac_based_encryption + * 0b10 - (i.e. 2 in decimal) the data in the block needs to be + * decrypted first using the HMAC based encryption scheme + * before sending out + * 0b01 - (i.e. 1 in decimal) the hmac based ecdsa + * private key generation is enabled. Generate the private key internally using the hardware HMAC peripheral. + * + * bit5 & bit4 & bit3 - TLV key flags + * 0b001 - (i.e. 1 in decimal) The ecdsa key is stored in an eFuse key block + * + * In this case all the flags are mutually exclusive. + * Ununsed bits: + * . + * . + * bit0 (LSB) + */ + +#define ESP_SECURE_CERT_TLV_FLAG_HMAC_ENCRYPTION (2 << 6) +#define ESP_SECURE_CERT_TLV_FLAG_HMAC_ECDSA_KEY_DERIVATION (1 << 6) +#define ESP_SECURE_CERT_TLV_FLAG_KEY_ECDSA_PERIPHERAL (1 << 3) +#define ESP_SECURE_CERT_TLV_KEY_FLAGS_BIT_MASK (BIT5 | BIT4 | BIT3) + +#define ESP_SECURE_CERT_IS_TLV_ENCRYPTED(flags) \ + ((flags & (BIT7 | BIT6)) == ESP_SECURE_CERT_TLV_FLAG_HMAC_ENCRYPTION) + +#define ESP_SECURE_CERT_HMAC_ECDSA_KEY_DERIVATION(flags) \ + ((flags & (BIT7 | BIT6)) == ESP_SECURE_CERT_TLV_FLAG_HMAC_ECDSA_KEY_DERIVATION) + +#define ESP_SECURE_CERT_KEY_ECDSA_PERIPHERAL(flags) \ + ((flags & ESP_SECURE_CERT_TLV_KEY_FLAGS_BIT_MASK) == ESP_SECURE_CERT_TLV_FLAG_KEY_ECDSA_PERIPHERAL) + +/* secure cert partition of cust_flash type in this case is of 8 KB size, + * out of which 3-3.1 KB size is utilized. + */ + +/* + * Header for each tlv + */ +typedef struct esp_secure_cert_tlv_header { + uint32_t magic; + uint8_t flags; /* flags byte that identifies different characteristics for the TLV */ + uint8_t reserved[3]; /* Reserved bytes for future use, the value currently should be 0x0 */ + uint8_t type; /* Type of tlv structure, this shall be typecasted + to esp_secure_cert_tlv_type_t for further use */ + uint8_t subtype; /* Subtype of TLV structure, this acts as an index for the type */ + uint16_t length; /* Length of the data */ + uint8_t value[0]; /* Actual data in form of byte array */ +} __attribute__((packed)) esp_secure_cert_tlv_header_t; + +/* + * Footer for each tlv + */ +typedef struct esp_secure_cert_tlv_footer { + uint32_t crc; /* crc of the data */ +} esp_secure_cert_tlv_footer_t; + +_Static_assert(sizeof(esp_secure_cert_tlv_header_t) == 12, "TLV header size should be 12 bytes"); + +_Static_assert(sizeof(esp_secure_cert_tlv_footer_t) == 4, "TLV footer size should be 4 bytes"); + +/* + * Note: + * + * The data stored in a cust flash partition should be as follows: + * + * tlv_header1 -> data_1 -> tlv_footer1 -> tlv_header2... + * + */ + +typedef struct esp_secure_cert_tlv_sec_cfg { + uint8_t priv_key_efuse_id; /* eFuse key id in which the private key is stored */ + uint8_t reserved[39]; /* Reserving 39 bytes for future use */ +} __attribute__((packed)) esp_secure_cert_tlv_sec_cfg_t; + +_Static_assert(sizeof(esp_secure_cert_tlv_sec_cfg_t) == 40, "TLV sec cfg size should be 40 bytes"); + +/* + * Map the entire esp_secure_cert partition + * and return the virtual address. + * + * @note + * The mapping is done only once and function shall + * simply return same address in case of successive calls. + **/ +const void *esp_secure_cert_get_mapped_addr(void); + +/* + * Find the offset of tlv structure of given type in the esp_secure_cert partition + * + * Note: This API also validates the crc of the respective tlv before returning the offset + * @input + * esp_secure_cert_addr Memory mapped address of the esp_secure_cert partition + * type Type of the tlv structure. + * for calculating current crc for esp_secure_cert + * + * tlv_address Void pointer to store tlv address + * + */ +esp_err_t esp_secure_cert_find_tlv(const void *esp_secure_cert_addr, esp_secure_cert_tlv_type_t type, uint8_t subtype, void **tlv_address); + +/* + * Get the flash address of the data of a TLV entry + * + * Note: This API also validates the crc of the respective tlv before returning the offset. The offset is not the physical address but the address where it is mapped in the memory space. + * @input + * type Type of the TLV entry + * subtype Subtype of the TLV entry (index) + * buffer Pointer to the buffer to store the data address + * len Pointer to store the length of the data + * + * Note: If tlv type = ESP_SECURE_CERT_TLV_END then the address returned shall be the end address of current tlv formatted data. + * If tlv subtype = ESP_SECURE_CERT_SUBTYPE_MAX then the the address of tlv of given type and highest subtype found shall be returned. + * @return + * + * - ESP_OK On success + * - ESP_FAIL/other relevant esp error code + * On failure + */ +esp_err_t esp_secure_cert_tlv_get_addr(esp_secure_cert_tlv_type_t type, esp_secure_cert_tlv_subtype_t subtype, char **buffer, uint32_t *len); + +/* + * Identify if esp_secure_cert partition of type TLV is present. + * @return + * - 1 on if the partition is identified as TLV + * - 0 on failure + */ +bool esp_secure_cert_is_tlv_partition(void); + +#ifdef CONFIG_ESP_SECURE_CERT_DS_PERIPHERAL +/* @info + * This function returns the flash esp_ds_context which can then be + * directly provided to an esp-tls connection through its config structure. + * The memory for the context is dynamically allocated. + * The internal structures are however directly accessed from flash. + * e.g. esp_ds_data + * + * @params + * - ds_ctx The pointer to the DS context + * @return + * - ESP_OK On success + * - ESP_FAIL/other relevant esp error code + * On failure + */ +esp_ds_data_ctx_t *esp_secure_cert_tlv_get_ds_ctx(void); + +/* + *@info + * Free the ds context + */ +void esp_secure_cert_tlv_free_ds_ctx(esp_ds_data_ctx_t *ds_ctx); +#endif + +#if SOC_HMAC_SUPPORTED +#define HMAC_ENCRYPTION_MESSAGE_LEN (32) +#define HMAC_ENCRYPTION_IV_LEN (16) +#define HMAC_ENCRYPTION_TAG_LEN (16) +#define HMAC_ENCRYPTION_AES_GCM_KEY_LEN (32) + +/* + * @info + * Calculate the IV for the hmac based encryption + * iv The pointer to the buffer to which IV should be written + * The buffer must be a writable buffer of size HMAC_ENCRYPTION_IV_LEN + */ +esp_err_t esp_secure_cert_calculate_hmac_encryption_iv(uint8_t *iv); + +/* + * @info + * Calculate the IV for the hmac based encryption + * aes_key The pointer to the buffer to which IV should be written + * The buffer must be a writable + * buffer of size HMAC_ENCRYPTION_AES_GCM_KEY_LEN + */ +esp_err_t esp_secure_cert_calculate_hmac_encryption_key(uint8_t *aes_key); +#endif diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/srcs/esp_secure_cert_crypto.c b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/srcs/esp_secure_cert_crypto.c new file mode 100644 index 000000000..739e2367f --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/srcs/esp_secure_cert_crypto.c @@ -0,0 +1,93 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include "esp_heap_caps.h" +#include "esp_err.h" +#include "esp_log.h" +#include "soc/soc_caps.h" + +#if SOC_HMAC_SUPPORTED +static const char *TAG = "esp_secure_cert_crypto"; + +#include "esp_hmac.h" +#define SHA256_MD_SIZE 32 +int esp_pbkdf2_hmac_sha256(hmac_key_id_t hmac_key_id, const unsigned char *salt, size_t salt_len, + size_t iteration_count, size_t key_length, unsigned char *output) +{ + int ret = -1; + int j; + unsigned int i; + unsigned char md1[SHA256_MD_SIZE] = {}; + unsigned char work[SHA256_MD_SIZE] = {}; + // Considering that we only have SHA256, fixing the MD_SIZE to 32 bytes + const size_t MD_SIZE = SHA256_MD_SIZE; + size_t use_len; + unsigned char *out_p = output; + unsigned char counter[4] = {}; + + counter[3] = 1; + uint8_t *hmac_input; + esp_err_t esp_ret = ESP_FAIL; + hmac_input = (uint8_t *) heap_caps_calloc(1, salt_len + sizeof(counter) + 1, MALLOC_CAP_INTERNAL); + if (hmac_input == NULL) { + ESP_LOGE(TAG, "Failed to allocate memory for hmac input"); + return -1; + } + + while (key_length) { + // U1 ends up in work + size_t hmac_input_len = 0; + memcpy(hmac_input, salt, salt_len); + hmac_input_len = hmac_input_len + salt_len; + memcpy(hmac_input + salt_len, counter, sizeof(counter)); + hmac_input_len = hmac_input_len + sizeof(counter); + esp_ret = esp_hmac_calculate(hmac_key_id, hmac_input, hmac_input_len, work); + if (esp_ret != ESP_OK) { + ESP_LOGE(TAG, "Could not calculate the HMAC value, returned %04X", esp_ret); + ret = -1; + goto cleanup; + } + + memcpy(md1, work, MD_SIZE); + + for (i = 1; i < iteration_count; i++) { + // U2 ends up in md1 + esp_ret = esp_hmac_calculate(hmac_key_id, md1, MD_SIZE, md1); + if (esp_ret != ESP_OK) { + ESP_LOGE(TAG, "Could not calculate the HMAC value, returned %04X", esp_ret); + ret = -1; + goto cleanup; + } + // U1 xor U2 + // + for (j = 0; j < MD_SIZE; j++) { + work[j] ^= md1[j]; + } + } + + use_len = (key_length < MD_SIZE) ? key_length : MD_SIZE; + memcpy(out_p, work, use_len); + + key_length -= (uint32_t) use_len; + out_p += use_len; + + for (i = 4; i > 0; i--) { + if (++counter[i - 1] != 0) { + break; + } + } + } + //Success + ret = 0; +cleanup: + + /* Zeroise buffers to clear sensitive data from memory. */ + free(hmac_input); + memset(work, 0, SHA256_MD_SIZE); + memset(md1, 0, SHA256_MD_SIZE); + return ret; +} +#endif diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/srcs/esp_secure_cert_read.c b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/srcs/esp_secure_cert_read.c new file mode 100644 index 000000000..3d70ed3b8 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/srcs/esp_secure_cert_read.c @@ -0,0 +1,699 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include "esp_log.h" +#include "esp_err.h" +#include "esp_partition.h" +#include "esp_crc.h" +#include "nvs_flash.h" +#include "esp_secure_cert_read.h" +#include "esp_secure_cert_config.h" +#include "esp_secure_cert_tlv_config.h" +#include "esp_secure_cert_tlv_private.h" +#include "esp_heap_caps.h" + +#if __has_include("esp_idf_version.h") +#include "esp_idf_version.h" +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0) +#include "spi_flash_mmap.h" +#endif +#endif + +static const char *TAG = "esp_secure_cert"; + +typedef enum partition_format { + ESP_SECURE_CERT_PF_INVALID = -1, + ESP_SECURE_CERT_PF_CUST_FLASH, + ESP_SECURE_CERT_PF_CUST_FLASH_LEGACY, + ESP_SECURE_CERT_PF_NVS, + ESP_SECURE_CERT_PF_TLV, +} esp_secure_cert_part_fmt_t; + +static esp_secure_cert_part_fmt_t current_partition_format = ESP_SECURE_CERT_PF_INVALID; +static const char *nvs_partition_name; +static const char *nvs_namespace_name; + +// In case of esp_secure_cert nvs namespace is same as nvs partition name + +#define NVS_STR 1 +#define NVS_BLOB 2 +#define NVS_U8 3 +#define NVS_U16 4 + +/* API to find the esp_secure_cert partition + * @params + * partition_type The type of partition to find + * partition_name The name of the partition to find + * partition_format The partition_format of the partition, + * The global variable current_partition_format shall + * be set to this value if find partition operation + * was successful + */ +static const esp_partition_t *esp_secure_cert_find_partition(esp_partition_type_t partition_type, const char *partition_name, esp_secure_cert_part_fmt_t format) +{ + esp_partition_iterator_t it = esp_partition_find(partition_type, ESP_PARTITION_SUBTYPE_ANY, partition_name); + if (it != NULL) { + current_partition_format = format; + const esp_partition_t *part = esp_partition_get(it); + if (part == NULL) { + ESP_LOGE(TAG, "Failed to get partition"); + return NULL; + } else { + return part; + } + } + // if it reaches here that means it is NULL + return NULL; +} + +static const esp_partition_t *esp_secure_cert_get_partition(void) +{ + static const esp_partition_t *part; + if (part != NULL) { + return part; + } + + // This switch case statement is added for increasing readability + // The actual behaviour is a simple fall through + current_partition_format = ESP_SECURE_CERT_PF_TLV; + + switch (current_partition_format) { + case ESP_SECURE_CERT_PF_TLV: + part = esp_secure_cert_find_partition(ESP_SECURE_CERT_CUST_FLASH_PARTITION_TYPE, ESP_SECURE_CERT_TLV_PARTITION_NAME, ESP_SECURE_CERT_PF_TLV); + if (part != NULL) { + if (esp_secure_cert_is_tlv_partition()) { + ESP_LOGI(TAG, "Pre-provisioned partition information:"); + ESP_LOGI(TAG, "partition format: %s, partition name: %s", "CUST_FLASH_TLV", ESP_SECURE_CERT_PARTITION_NAME); + return part; + } + } + // fall through + case ESP_SECURE_CERT_PF_CUST_FLASH: + part = esp_secure_cert_find_partition(ESP_SECURE_CERT_CUST_FLASH_PARTITION_TYPE, ESP_SECURE_CERT_PARTITION_NAME, ESP_SECURE_CERT_PF_CUST_FLASH); + if (part != NULL) { + ESP_LOGI(TAG, "Pre-provisioned partition information:"); + ESP_LOGI(TAG, "partition format: %s, partition name: %s", "CUST_FLASH", ESP_SECURE_CERT_PARTITION_NAME); + return part; + } + + // fall through + case ESP_SECURE_CERT_PF_NVS: + nvs_partition_name = ESP_SECURE_CERT_PARTITION_NAME; + nvs_namespace_name = ESP_SECURE_CERT_PARTITION_NAME; + part = esp_secure_cert_find_partition(ESP_SECURE_CERT_NVS_PARTITION_TYPE, nvs_partition_name, ESP_SECURE_CERT_PF_NVS); + + if (part != NULL) { + if (nvs_flash_init_partition(nvs_partition_name) != ESP_OK) { + ESP_LOGE(TAG, "NVS partition %s was found but inititlization failed", nvs_partition_name); + return NULL; + } + ESP_LOGD(TAG, "Partition found, current format is NVS."); + ESP_LOGD(TAG, "NVS partition %s is inititalized", nvs_partition_name); + esp_err_t err; + nvs_handle_t handle; + + err = nvs_open_from_partition(nvs_partition_name, nvs_namespace_name, NVS_READONLY, &handle); + if (err == ESP_OK) { + ESP_LOGI(TAG, "Pre-provisioned partition information:"); + ESP_LOGI(TAG, "partition format: %s, partition name: %s, partition namespace: %s", "NVS", nvs_partition_name, nvs_namespace_name); + nvs_close(handle); + return part; + } + + nvs_namespace_name = ESP_SECURE_CERT_LEGACY_PARTITION_NAME; + err = nvs_open_from_partition(nvs_partition_name, nvs_namespace_name, NVS_READONLY, &handle); + nvs_close(handle); + if (err == ESP_OK) { + ESP_LOGI(TAG, "Pre-provisioned partition information:"); + ESP_LOGI(TAG, "partition format: %s, partition name: %s, partition namespace: %s", "NVS", nvs_partition_name, nvs_namespace_name); + return part; + } else { + ESP_LOGE(TAG, "Failed to open nvs partition %s with namespace: %s", nvs_partition_name, nvs_namespace_name); + return NULL; + } + } + + esp_err_t err; + nvs_handle_t handle; + nvs_partition_name = ESP_SECURE_CERT_LEGACY_PARTITION_NAME; + nvs_namespace_name = ESP_SECURE_CERT_LEGACY_PARTITION_NAME; + part = esp_secure_cert_find_partition(ESP_SECURE_CERT_NVS_PARTITION_TYPE, nvs_partition_name, ESP_SECURE_CERT_PF_NVS); + if (part != NULL) { + if (nvs_flash_init_partition(nvs_partition_name) != ESP_OK) { + ESP_LOGE(TAG, "NVS partition %s was found but inititlization failed", nvs_partition_name); + return NULL; + } + err = nvs_open_from_partition(nvs_partition_name, nvs_namespace_name, NVS_READONLY, &handle); + nvs_close(handle); + if (err == ESP_OK) { + ESP_LOGI(TAG, "Pre-provisioned partition information:"); + ESP_LOGI(TAG, "partition format: %s, partition name: %s, partition namespace: %s", "NVS", nvs_partition_name, nvs_namespace_name); + return part; + } else { + ESP_LOGE(TAG, "Failed to open nvs partition %s with namespace: %s", nvs_partition_name, nvs_namespace_name); + return NULL; + } + } + + // fall through + case ESP_SECURE_CERT_PF_CUST_FLASH_LEGACY: + part = esp_secure_cert_find_partition(ESP_SECURE_CERT_CUST_FLASH_PARTITION_TYPE, ESP_SECURE_CERT_LEGACY_PARTITION_NAME, ESP_SECURE_CERT_PF_CUST_FLASH_LEGACY); + if (part != NULL) { + ESP_LOGI(TAG, "Partition found, current format is cust flash legacy."); + ESP_LOGI(TAG, "Current partition format: %s, partition name: %s", "CUST_FLASH_LEGACY", ESP_SECURE_CERT_LEGACY_PARTITION_NAME); + return part; + } + + // fall through + case ESP_SECURE_CERT_PF_INVALID: + default: + current_partition_format = ESP_SECURE_CERT_PF_INVALID; + ESP_LOGE(TAG, "Failed to get esp_secure_cert partition"); + return NULL; + } + return NULL; +} + +static void esp_secure_cert_get_partition_format(void) +{ + if (current_partition_format != ESP_SECURE_CERT_PF_INVALID) { + return; + } + + const esp_partition_t *part = esp_secure_cert_get_partition(); + if (part == NULL) { + ESP_LOGE(TAG, "Failed to obtain the current partition and partition format"); + current_partition_format = ESP_SECURE_CERT_PF_INVALID; + } + return; +} + +static int nvs_get(const char *name_space, const char *key, char *value, size_t *len, size_t type) +{ + esp_err_t err; + nvs_handle_t handle; + + err = nvs_open_from_partition(nvs_partition_name, name_space, NVS_READONLY, &handle); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Could not open NVS handle (0x%x)!", err); + return err; + } + + switch (type) { + case NVS_STR: + err = nvs_get_str(handle, key, value, len); + break; + case NVS_BLOB: + err = nvs_get_blob(handle, key, value, len); + break; + case NVS_U8: + err = nvs_get_u8(handle, key, (uint8_t *)value); + break; + case NVS_U16: + err = nvs_get_u16(handle, key, (uint16_t *)value); + break; + default: + ESP_LOGE(TAG, "Invalid type of NVS data provided"); + err = ESP_ERR_INVALID_ARG; + } + + if (err != ESP_OK) { + ESP_LOGE(TAG, "Error (0x%02X) reading NVS data!", err); + return err; + } + + nvs_close(handle); + return err; +} + +esp_err_t esp_secure_cert_init_nvs_partition(void) +{ + const esp_partition_t *part = esp_secure_cert_get_partition(); + if (part == NULL) { + ESP_LOGE(TAG, "Could not get partition."); + return ESP_FAIL; + } + + if (nvs_flash_init_partition(ESP_SECURE_CERT_PARTITION_NAME) == ESP_OK) { + return ESP_OK; + } else { + return nvs_flash_init_partition(ESP_SECURE_CERT_LEGACY_PARTITION_NAME); + } +} + +static esp_err_t esp_secure_cert_read_raw_flash(const esp_partition_t *partition, uint32_t src_offset, void *dst, uint32_t size) +{ + /* Encrypted partitions need to be read via a cache mapping */ + const void *buf; + spi_flash_mmap_handle_t handle; + esp_err_t err; + + err = esp_partition_mmap(partition, src_offset, size, SPI_FLASH_MMAP_DATA, &buf, &handle); + if (err != ESP_OK) { + return err; + } + memcpy(dst, buf, size); + spi_flash_munmap(handle); + return ESP_OK; +} + +const void *esp_secure_cert_mmap(const esp_partition_t *partition, uint32_t src_offset, uint32_t size) +{ + /* Encrypted partitions need to be read via a cache mapping */ + const void *buf; + spi_flash_mmap_handle_t handle; + esp_err_t err; + + err = esp_partition_mmap(partition, src_offset, size, SPI_FLASH_MMAP_DATA, &buf, &handle); + if (err != ESP_OK) { + return NULL; + } + return buf; +} + +static esp_err_t esp_secure_cert_read_metadata(esp_secure_cert_metadata *metadata, size_t offset, const esp_partition_t *part, uint32_t *data_len, uint32_t *data_crc) +{ + esp_err_t err; + err = esp_secure_cert_read_raw_flash(part, ESP_SECURE_CERT_METADATA_OFFSET, metadata, sizeof(esp_secure_cert_metadata)); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Could not read metadata."); + return ESP_FAIL; + } + + if (metadata->magic_word != ESP_SECURE_CERT_METADATA_MAGIC_WORD) { + ESP_LOGE(TAG, "Metadata magic word does not match"); + return ESP_FAIL; + } + + switch (offset) { + case ESP_SECURE_CERT_METADATA_OFFSET: + *data_len = sizeof(metadata); + break; + case ESP_SECURE_CERT_DEV_CERT_OFFSET: + if (current_partition_format == ESP_SECURE_CERT_PF_CUST_FLASH_LEGACY) { + /* In the legacy format the order of dev_cert_len, dev_cert_crc have been interchanged with ca_cert_len and ca_cert_crc */ + /* Returning the appropriate values here */ + *data_len = metadata->ca_cert_len; + *data_crc = metadata->ca_cert_crc; + } else { + *data_len = metadata->dev_cert_len; + *data_crc = metadata->dev_cert_crc; + } + break; + case ESP_SECURE_CERT_CA_CERT_OFFSET: + if (current_partition_format == ESP_SECURE_CERT_PF_CUST_FLASH_LEGACY) { + /* In the legacy format the order of dev_cert_len, dev_cert_crc have been interchanged with ca_cert_len and ca_cert_crc */ + /* Returning the appropriate values here */ + *data_len = metadata->dev_cert_len; + *data_crc = metadata->dev_cert_crc; + } else { + *data_len = metadata->ca_cert_len; + *data_crc = metadata->ca_cert_crc; + } + break; +#ifndef CONFIG_ESP_SECURE_CERT_DS_PERIPHERAL + case ESP_SECURE_CERT_PRIV_KEY_OFFSET: + *data_len = metadata->priv_key_len; + *data_crc = metadata->priv_key_crc; + break; +#else /* !CONFIG_ESP_SECURE_CERT_DS_PERIPHERAL */ + case ESP_SECURE_CERT_CIPHERTEXT_OFFSET: + *data_len = metadata->ciphertext_len; + *data_crc = metadata->ciphertext_crc; + break; + case ESP_SECURE_CERT_IV_OFFSET: + *data_len = metadata->iv_len; + *data_crc = metadata->iv_crc; + break; +#endif /* CONFIG_ESP_SECURE_CERT_DS_PERIPHERAL */ + default: + err = ESP_ERR_INVALID_ARG; + ESP_LOGE(TAG, "Invalid offset value given"); + } + + return err; +} + +static esp_err_t esp_secure_cert_get_addr(size_t offset, char **buffer, uint32_t *len) +{ + esp_err_t err; + static esp_secure_cert_metadata metadata; + uint32_t data_len = 0; + uint32_t data_crc = 0; + + const esp_partition_t *part = esp_secure_cert_get_partition(); + if (part == NULL) { + ESP_LOGE(TAG, "Could not get partition."); + return ESP_FAIL; + } + + err = esp_secure_cert_read_metadata(&metadata, offset, part, &data_len, &data_crc); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Error in reading the metadata"); + return err; + } + + *len = data_len; + *buffer = (char *)esp_secure_cert_mmap(part, offset, *len); + if (buffer == NULL) { + return ESP_FAIL; + } + + uint32_t read_crc = esp_crc32_le(UINT32_MAX, (const uint8_t * )*buffer, data_len); + if (read_crc != data_crc) { + ESP_LOGE(TAG, "Data has been tampered"); + return ESP_FAIL; + } + return ESP_OK; +} + +esp_err_t esp_secure_cert_get_device_cert(char **buffer, uint32_t *len) +{ + // This API sets the global variable current_partition_format + esp_secure_cert_get_partition_format(); + esp_err_t ret; + switch (current_partition_format) { + case ESP_SECURE_CERT_PF_TLV: + return esp_secure_cert_tlv_get_addr(ESP_SECURE_CERT_DEV_CERT_TLV, ESP_SECURE_CERT_SUBTYPE_MAX, buffer, len); + + case ESP_SECURE_CERT_PF_CUST_FLASH: + case ESP_SECURE_CERT_PF_CUST_FLASH_LEGACY: + return esp_secure_cert_get_addr(ESP_SECURE_CERT_DEV_CERT_OFFSET, buffer, len);; + + case ESP_SECURE_CERT_PF_NVS: + ret = nvs_get(nvs_namespace_name, ESP_SECURE_CERT_DEV_CERT, NULL, (size_t *)len, NVS_STR); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to get device cert length from nvs"); + return ret; + } + + *buffer = (char *)calloc(1, *len + 1); + if (*buffer == NULL) { + ESP_LOGE(TAG, "Not enough memory for device cert buffer"); + return ESP_ERR_NO_MEM; + } + + return nvs_get(nvs_namespace_name, ESP_SECURE_CERT_DEV_CERT, *buffer, (size_t *)len, NVS_STR); + + case ESP_SECURE_CERT_PF_INVALID: + default: + ESP_LOGE(TAG, "Invalid flash format"); + return ESP_FAIL; + } + +} + +esp_err_t esp_secure_cert_free_device_cert(char *buffer) +{ + switch(current_partition_format) { + // fall through + case ESP_SECURE_CERT_PF_TLV: + case ESP_SECURE_CERT_PF_CUST_FLASH: + case ESP_SECURE_CERT_PF_CUST_FLASH_LEGACY: + return ESP_OK; + break; + + case ESP_SECURE_CERT_PF_NVS: + free(buffer); + return ESP_OK; + break; + case ESP_SECURE_CERT_PF_INVALID: + default: + return ESP_FAIL; + } +} + +esp_err_t esp_secure_cert_get_ca_cert(char **buffer, uint32_t *len) +{ + // This API sets the global variable current_partition_format + esp_secure_cert_get_partition_format(); + esp_err_t ret; + + switch (current_partition_format) { + case ESP_SECURE_CERT_PF_TLV: + return esp_secure_cert_tlv_get_addr(ESP_SECURE_CERT_CA_CERT_TLV, ESP_SECURE_CERT_SUBTYPE_MAX, buffer, len); + + case ESP_SECURE_CERT_PF_CUST_FLASH: + case ESP_SECURE_CERT_PF_CUST_FLASH_LEGACY: + return esp_secure_cert_get_addr(ESP_SECURE_CERT_CA_CERT_OFFSET, buffer, len); + + case ESP_SECURE_CERT_PF_NVS: + ret = nvs_get(nvs_namespace_name, ESP_SECURE_CERT_CA_CERT, NULL, (size_t *)len, NVS_STR); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to get ca cert length from nvs"); + return ret; + } + + *buffer = (char *)calloc(1, *len + 1); + if (*buffer == NULL) { + ESP_LOGE(TAG, "Not enough memory for ca cert buffer"); + return ESP_ERR_NO_MEM; + } + return nvs_get(nvs_namespace_name, ESP_SECURE_CERT_CA_CERT, *buffer, (size_t *)len, NVS_STR); + + case ESP_SECURE_CERT_PF_INVALID: + default: + ESP_LOGE(TAG, "Invalid flash format"); + return ESP_FAIL; + } + +} + +esp_err_t esp_secure_cert_free_ca_cert(char *buffer) +{ + switch(current_partition_format) { + // fall through + case ESP_SECURE_CERT_PF_TLV: + case ESP_SECURE_CERT_PF_CUST_FLASH: + case ESP_SECURE_CERT_PF_CUST_FLASH_LEGACY: + return ESP_OK; + break; + + case ESP_SECURE_CERT_PF_NVS: + free(buffer); + return ESP_OK; + break; + case ESP_SECURE_CERT_PF_INVALID: + default: + return ESP_FAIL; + } +} + +#ifndef CONFIG_ESP_SECURE_CERT_DS_PERIPHERAL +esp_err_t esp_secure_cert_get_priv_key(char **buffer, uint32_t *len) +{ + + // This API sets the global variable current_partition_format + esp_secure_cert_get_partition_format(); + esp_err_t ret; + + switch (current_partition_format) { + case ESP_SECURE_CERT_PF_TLV: + return esp_secure_cert_tlv_get_addr(ESP_SECURE_CERT_PRIV_KEY_TLV, ESP_SECURE_CERT_SUBTYPE_MAX, buffer, len); + case ESP_SECURE_CERT_PF_CUST_FLASH: + case ESP_SECURE_CERT_PF_CUST_FLASH_LEGACY: + return esp_secure_cert_get_addr(ESP_SECURE_CERT_PRIV_KEY_OFFSET, buffer, len);; + + case ESP_SECURE_CERT_PF_NVS: + ret = nvs_get(nvs_namespace_name, ESP_SECURE_CERT_PRIV_KEY, NULL, (size_t *)len, NVS_STR); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to get priv key length from nvs"); + return ret; + } + + *buffer = (char *)calloc(1, *len + 1); + if (*buffer == NULL) { + ESP_LOGE(TAG, "Not enough memory for priv key buffer"); + return ESP_ERR_NO_MEM; + } + + return nvs_get(nvs_namespace_name, ESP_SECURE_CERT_PRIV_KEY, *buffer, (size_t *)len, NVS_STR); + + case ESP_SECURE_CERT_PF_INVALID: + default: + ESP_LOGE(TAG, "Invalid flash format"); + return ESP_FAIL; + } + +} + +esp_err_t esp_secure_cert_free_priv_key(char *buffer) +{ + switch(current_partition_format) { + // fall through + case ESP_SECURE_CERT_PF_TLV: + case ESP_SECURE_CERT_PF_CUST_FLASH: + case ESP_SECURE_CERT_PF_CUST_FLASH_LEGACY: + return ESP_OK; + break; + + case ESP_SECURE_CERT_PF_NVS: + free(buffer); + return ESP_OK; + break; + case ESP_SECURE_CERT_PF_INVALID: + default: + return ESP_FAIL; + } +} +#endif + +#ifdef CONFIG_ESP_SECURE_CERT_DS_PERIPHERAL +static esp_err_t esp_secure_cert_read(size_t offset, unsigned char *buffer, uint32_t *len) +{ + esp_err_t err; + static esp_secure_cert_metadata metadata; + uint32_t data_len = 0; + uint32_t data_crc = 0; + + const esp_partition_t *part = esp_secure_cert_get_partition(); + if (part == NULL) { + ESP_LOGE(TAG, "Could not get partition."); + return ESP_FAIL; + } + + err = esp_secure_cert_read_metadata(&metadata, offset, part, &data_len, &data_crc); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Error in reading the metadata"); + return err; + } + + if (buffer == NULL) { + *len = data_len; + return ESP_OK; + } + + if (*len < data_len) { + ESP_LOGE(TAG, "Insufficient length of buffer. buffer size: %"PRIu32", required: %"PRIu32"", *len, data_len); + return ESP_FAIL; + } + + /* If the requested offset belongs to the medatada, return the already read metadata */ + if (offset == ESP_SECURE_CERT_METADATA_OFFSET) { + memcpy(buffer, &metadata, sizeof(metadata)); + return ESP_OK; + } + + err = esp_secure_cert_read_raw_flash(part, offset, buffer, data_len); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Could not read data."); + return ESP_FAIL; + } + + uint32_t read_crc = esp_crc32_le(UINT32_MAX, (const uint8_t * )buffer, data_len); + if (read_crc != data_crc) { + ESP_LOGE(TAG, "Data has been tampered"); + return ESP_FAIL; + } + + return ESP_OK; +} + +esp_ds_data_ctx_t *esp_secure_cert_get_ds_ctx(void) +{ + esp_secure_cert_get_partition_format(); + if (current_partition_format == ESP_SECURE_CERT_PF_TLV) { + return esp_secure_cert_tlv_get_ds_ctx(); + } + esp_err_t esp_ret; + esp_ds_data_ctx_t *ds_data_ctx; + uint32_t len = 0; + ds_data_ctx = (esp_ds_data_ctx_t *)heap_caps_malloc(sizeof(esp_ds_data_ctx_t), MALLOC_CAP_INTERNAL); + if (ds_data_ctx == NULL) { + ESP_LOGE(TAG, "Error in allocating memory for esp_ds_data_context"); + goto exit; + } + + ds_data_ctx->esp_ds_data = (esp_ds_data_t *)heap_caps_calloc(1, sizeof(esp_ds_data_t), MALLOC_CAP_INTERNAL); + if (ds_data_ctx->esp_ds_data == NULL) { + ESP_LOGE(TAG, "Could not allocate memory for DS data handle "); + goto exit; + } + + // This API sets the global variable current_partition_format + + if (current_partition_format == ESP_SECURE_CERT_PF_CUST_FLASH || current_partition_format == ESP_SECURE_CERT_PF_CUST_FLASH_LEGACY) { + char *buffer; + len = 0; + esp_ret = esp_secure_cert_get_addr(ESP_SECURE_CERT_CIPHERTEXT_OFFSET, &buffer, &len); + if (esp_ret != ESP_OK) { + ESP_LOGE(TAG, "Error in reading ciphertext"); + goto exit; + } + + memcpy((void *)ds_data_ctx->esp_ds_data->c, buffer, len); + + len = 0; + esp_ret = esp_secure_cert_get_addr(ESP_SECURE_CERT_IV_OFFSET, &buffer, &len); + if (esp_ret != ESP_OK) { + ESP_LOGE(TAG, "Error in reading initialization vector"); + goto exit; + } + + memcpy((void *)ds_data_ctx->esp_ds_data->iv, buffer, len); + unsigned char metadata[ESP_SECURE_CERT_METADATA_SIZE] = {}; + len = sizeof(metadata); + esp_err_t err = esp_secure_cert_read(ESP_SECURE_CERT_METADATA_OFFSET, metadata, &len); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Error in reading metadata"); + goto exit; + } + ds_data_ctx->rsa_length_bits = ((esp_secure_cert_metadata *)metadata)->rsa_length; + ds_data_ctx->efuse_key_id = ((esp_secure_cert_metadata *)metadata)->efuse_key_id; + return ds_data_ctx; + + } else if (current_partition_format == ESP_SECURE_CERT_PF_NVS) { + len = ESP_DS_C_LEN; + esp_ret = nvs_get(nvs_namespace_name, ESP_SECURE_CERT_CIPHERTEXT, (char *) ds_data_ctx->esp_ds_data->c, (size_t *) &len, NVS_BLOB); + if (esp_ret != ESP_OK) { + ESP_LOGE(TAG, "Error in reading ciphertext"); + goto exit; + } + + len = ESP_DS_IV_LEN; + esp_ret = nvs_get(nvs_namespace_name, ESP_SECURE_CERT_IV, (char *)ds_data_ctx->esp_ds_data->iv, (size_t *)&len, NVS_BLOB); + if (esp_ret != ESP_OK) { + ESP_LOGE(TAG, "Error in reading initialization vector"); + goto exit; + } + + esp_ret = nvs_get(nvs_namespace_name, ESP_SECURE_CERT_EFUSE_KEY_ID, (void *)&ds_data_ctx->efuse_key_id, 0, NVS_U8); + if (esp_ret != ESP_OK) { + ESP_LOGE(TAG, "Error in reading efuse key id"); + goto exit; + } + + esp_ret = nvs_get(nvs_namespace_name, ESP_SECURE_CERT_RSA_LEN, (void *)&ds_data_ctx->rsa_length_bits, 0, NVS_U16); + if (esp_ret != ESP_OK) { + ESP_LOGE(TAG, "Error in reading rsa key length"); + goto exit; + } + return ds_data_ctx; + } + +exit: + if (ds_data_ctx != NULL) { + free(ds_data_ctx->esp_ds_data); + } + free(ds_data_ctx); + return NULL; +} + +void esp_secure_cert_free_ds_ctx(esp_ds_data_ctx_t *ds_ctx) +{ + esp_secure_cert_get_partition_format(); + if (current_partition_format == ESP_SECURE_CERT_PF_TLV) { + esp_secure_cert_tlv_free_ds_ctx(ds_ctx); + } + + if (ds_ctx != NULL) { + free(ds_ctx->esp_ds_data); + } + free(ds_ctx); +} +#endif diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/srcs/esp_secure_cert_tlv_read.c b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/srcs/esp_secure_cert_tlv_read.c new file mode 100644 index 000000000..9fc5acd60 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/srcs/esp_secure_cert_tlv_read.c @@ -0,0 +1,884 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "esp_log.h" +#include "esp_err.h" +#include "esp_partition.h" +#include "esp_crc.h" +#include "inttypes.h" + +#if __has_include("esp_idf_version.h") +#include "esp_idf_version.h" + +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 4, 0) +#include "esp_random.h" +#else +#include "esp_system.h" +#endif + +#include "esp_rom_sys.h" +#include "esp_efuse.h" +#include "esp_efuse_table.h" +#include "soc/soc_caps.h" +#include "esp_fault.h" +#include "esp_heap_caps.h" + +#include "mbedtls/gcm.h" +#include "mbedtls/sha256.h" +#include "mbedtls/ecdsa.h" +#include "mbedtls/pk.h" +#include "mbedtls/version.h" + +#include "esp_secure_cert_read.h" +#include "esp_secure_cert_tlv_config.h" +#include "esp_secure_cert_tlv_read.h" +#include "esp_secure_cert_tlv_private.h" +#include "esp_secure_cert_crypto.h" + +#if SOC_HMAC_SUPPORTED +#include "esp_hmac.h" +#endif + +#if (MBEDTLS_VERSION_NUMBER < 0x03000000) +/* mbedtls 2.x backward compatibility */ +#define MBEDTLS_2X_COMPAT 1 +/** + * Mbedtls-3.0 forward compatibility + */ +#ifndef MBEDTLS_PRIVATE +#define MBEDTLS_PRIVATE(member) member +#endif +#endif /* (MBEDTLS_VERSION_NUMBER < 0x03000000) */ + +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0) +#include "spi_flash_mmap.h" +#include "esp_memory_utils.h" +#include "entropy_poll.h" +#else +#include "mbedtls/entropy_poll.h" +#include "soc/soc_memory_layout.h" +#endif + +#endif + +static const char *TAG = "esp_secure_cert_tlv"; + +#define MIN_ALIGNMENT_REQUIRED 16 + + +#if SOC_HMAC_SUPPORTED +static esp_err_t esp_secure_cert_hmac_based_decryption(char *in_buf, uint32_t len, char *output_buf); +static esp_err_t esp_secure_cert_gen_ecdsa_key(esp_secure_cert_tlv_subtype_t subtype, char *output_buf, size_t buf_len); +#define ESP_SECURE_CERT_ECDSA_DER_KEY_SIZE 121 +#endif + +/* This is the mininum required flash address alignment in bytes to write to an encrypted flash partition */ + +/* + * Map the entire esp_secure_cert partition + * and return the virtual address. + * + * @note + * The mapping is done only once and function shall + * simply return same address in case of successive calls. + **/ +const void *esp_secure_cert_get_mapped_addr(void) +{ + // Once initialized, these variable shall contain valid data till reboot. + static const void *esp_secure_cert_mapped_addr; + if (esp_secure_cert_mapped_addr) { + return esp_secure_cert_mapped_addr; + } + + esp_partition_iterator_t it = esp_partition_find(ESP_SECURE_CERT_TLV_PARTITION_TYPE, + ESP_PARTITION_SUBTYPE_ANY, ESP_SECURE_CERT_TLV_PARTITION_NAME); + if (it == NULL) { + ESP_LOGE(TAG, "Partition not found."); + return NULL; + } + + const esp_partition_t *partition = esp_partition_get(it); + if (partition == NULL) { + ESP_LOGE(TAG, "Could not get partition."); + return NULL; + } + + /* Encrypted partitions need to be read via a cache mapping */ + spi_flash_mmap_handle_t handle; + esp_err_t err; + + /* Map the entire partition */ + err = esp_partition_mmap(partition, 0, partition->size, SPI_FLASH_MMAP_DATA, &esp_secure_cert_mapped_addr, &handle); + if (err != ESP_OK) { + return NULL; + } + return esp_secure_cert_mapped_addr; +} + +/* + * Get the padding length applicable for the given TLV + * + * @input The pointer to the start of the TLV (TLV Header) + * @note The padding length is defined in the design of the TLV. + * It says that each TLV data entry should be a multiple of MIN_ALIGNMENT_REQUIRED + * The actual tlv data is automatically padded to the nearest multiple of MIN_ALIGNMENT_REQUIRED + */ +static uint8_t esp_secure_cert_get_padding_length(esp_secure_cert_tlv_header_t *tlv_header) +{ + return ((MIN_ALIGNMENT_REQUIRED - (tlv_header->length % MIN_ALIGNMENT_REQUIRED)) % MIN_ALIGNMENT_REQUIRED); +} + +/* + * Get the total length of the TLV pointed by tlv_header + * @input + * tlv_header The pointer to the start of the TLV (TLV Header) + * + * @note + * The total length of the TLV consists of following parts + * 1) TLV Header + * 2) TLV data + * 3) Padding + * 4) TLV footer + * + * It is ensured by design that this length shall always be a multiple of MIN_ALIGNMENT_REQUIRED + * + */ +static uint16_t esp_secure_cert_get_tlv_total_length(esp_secure_cert_tlv_header_t *tlv_header) +{ + uint16_t padding_length = esp_secure_cert_get_padding_length(tlv_header); + uint16_t total_length = sizeof(esp_secure_cert_tlv_header_t) + tlv_header->length + padding_length + sizeof(esp_secure_cert_tlv_footer_t); + return total_length; +} + +/* + * Verify the TLV integrity + * + * @input + * tlv_header The pointer to the start of the TLV (TLV header) + * + * @note + * This API calculates the crc value of header + tlv_data + padding + * This value is compared with the value stored in the TLV footer. + * + * @return + * True TLV integrity verified + * False TLV intefrity could not be verified + */ +static bool esp_secure_cert_verify_tlv_integrity(esp_secure_cert_tlv_header_t *tlv_header) +{ + ESP_LOGD(TAG, "Verifying the TLV integrity"); + if (!(tlv_header->magic == ESP_SECURE_CERT_TLV_MAGIC)) { + return false; + } + + uint8_t padding_length = esp_secure_cert_get_padding_length(tlv_header); + ESP_LOGD(TAG, "Padding length obtained = %u", padding_length); + size_t crc_data_len = sizeof(esp_secure_cert_tlv_header_t) + tlv_header->length + padding_length; + uint32_t data_crc = esp_crc32_le(UINT32_MAX, (const uint8_t * )tlv_header, crc_data_len); + esp_secure_cert_tlv_footer_t *tlv_footer = (esp_secure_cert_tlv_footer_t *)((void*)tlv_header + crc_data_len); + if (tlv_footer->crc != data_crc) { + ESP_LOGD(TAG, "Calculated crc = %04X does not match with crc" + " read from esp_secure_cert partition = %04X", (unsigned int)data_crc, (unsigned int)tlv_footer->crc); + return false; + } + return true; +} + +/* + * Find the offset of tlv structure of given type in the esp_secure_cert partition + * + * Note: This API also validates the crc of the respective tlv before returning the offset + * @input + * esp_secure_cert_addr Memory mapped address of the esp_secure_cert partition + * type Type of the tlv structure. + * for calculating current crc for esp_secure_cert + * subtype Subtype of the given tlv structure. If subtype is given as ESP_SECURE_CERT_SUBTYPE_MAX then the entry with highest value of subtype is given as output + * + * tlv_address Void pointer to store tlv address + * + */ +esp_err_t esp_secure_cert_find_tlv(const void *esp_secure_cert_addr, esp_secure_cert_tlv_type_t type, uint8_t subtype, void **tlv_address) +{ + /* start from the begining of the partition */ + uint16_t tlv_offset = 0; + uint8_t latest_subtype = 0; + esp_secure_cert_tlv_header_t *latest_tlv_header = NULL; + bool read_latest_tlv = 0; + + if (subtype == ESP_SECURE_CERT_SUBTYPE_MAX) { + read_latest_tlv = 1; + } + + while (1) { + esp_secure_cert_tlv_header_t *tlv_header = (esp_secure_cert_tlv_header_t *)(esp_secure_cert_addr + tlv_offset); + ESP_LOGD(TAG, "Reading from offset of %d from base of esp_secure_cert", tlv_offset); + if (tlv_header->magic != ESP_SECURE_CERT_TLV_MAGIC) { + if (read_latest_tlv) { + if (latest_tlv_header != NULL) { + // Verifying the latest TLV here because we only need to verify the last TLV entry of given subtype + // instead of all available entries of the given subtype + ESP_LOGD(TAG, "Verify integrity of latest tlv obtained of subtype = %d", latest_subtype); + if (esp_secure_cert_verify_tlv_integrity(latest_tlv_header)) { + ESP_LOGD(TAG, "tlv structure of type %d and subtype %d found and verified", type, latest_subtype); + *tlv_address = (void *)latest_tlv_header; + return ESP_OK; + } else { + return ESP_FAIL; + } + } + } + if (type == ESP_SECURE_CERT_TLV_END) { + /* The invalid magic means last tlv read successfully was the last valid tlv structure present, + * so send the end address of the tlv. + * This address can be used to add a new tlv structure. */ + *tlv_address = (void *)tlv_header; + return ESP_OK; + } + ESP_LOGD(TAG, "Unable to find tlv of type: %d", type); + ESP_LOGD(TAG, "Expected magic byte is %04X, obtained magic byte = %04X", ESP_SECURE_CERT_TLV_MAGIC, (unsigned int) tlv_header->magic); + return ESP_FAIL; + } + + if (((esp_secure_cert_tlv_type_t)tlv_header->type) == type) { + if (read_latest_tlv) { + ESP_LOGD(TAG, "TLV entry of type: %d and subtype:%d found", tlv_header->type, tlv_header->subtype); + ESP_LOGD(TAG, "Continuing to find more recent entry of given subtype"); + latest_subtype = tlv_header->subtype; + // Store the tlv address of the latest entry found with given type + latest_tlv_header = (void *)tlv_header; + // Dont stop here and keep traversing till last TLV entry + } else { + if (tlv_header->subtype == subtype) { + if (esp_secure_cert_verify_tlv_integrity(tlv_header)) { + ESP_LOGD(TAG, "tlv structure of type %d and subtype %d found and verified", type, subtype); + *tlv_address = (void *)tlv_header; + return ESP_OK; + } else { + return ESP_FAIL; + } + } + } + } + // Move the offset to the start of the next tlv entry + tlv_offset = tlv_offset + esp_secure_cert_get_tlv_total_length(tlv_header); + } +} + +/** + +@brief Retrieve the header of a specific ESP Secure Certificate TLV record. +This function retrieves the header of a specific ESP Secure Certificate TLV record, identified by the type parameter. The tlv_header parameter is a pointer to a buffer where the header will be stored. The function returns ESP_OK if the header is successfully retrieved, otherwise it returns an error code. +@param[in] type The type of the TLV record to retrieve the header for. +@param[out] tlv_header The pointer at this location shall be updated with tlv_header pointer value. +@return ESP_OK Success + ESP_FAIL/ + relevant error Failure +*/ +static esp_err_t esp_secure_cert_tlv_get_header(esp_secure_cert_tlv_type_t type, uint8_t subtype, esp_secure_cert_tlv_header_t **tlv_header) +{ + esp_err_t err = ESP_FAIL; + char *esp_secure_cert_addr = (char *)esp_secure_cert_get_mapped_addr(); + if (esp_secure_cert_addr == NULL) { + ESP_LOGE(TAG, "Error in obtaining esp_secure_cert memory mapped address"); + return ESP_FAIL; + } + err = esp_secure_cert_find_tlv(esp_secure_cert_addr, type, subtype, (void **)tlv_header); + if (err != ESP_OK) { + ESP_LOGD(TAG, "Could not find the tlv of type %d and subtype %d", type, subtype); + return err; + } + return err; +} + +esp_err_t esp_secure_cert_tlv_get_addr(esp_secure_cert_tlv_type_t type, esp_secure_cert_tlv_subtype_t subtype, char **buffer, uint32_t *len) +{ + esp_err_t err; + esp_secure_cert_tlv_header_t *tlv_header = NULL; + err = esp_secure_cert_tlv_get_header(type, (uint8_t)subtype, &tlv_header); + if (err != ESP_OK) { + ESP_LOGD(TAG, "Could not find header for TLV type %d and subtype %d", type, subtype); + return err; + } + + // Special case : We return the end address of the last + // valid TLV in this case + // and length is set to the total length of valid TLV entries + if (type == ESP_SECURE_CERT_TLV_END) { + *buffer = (char *)tlv_header; + const void *esp_secure_cert_addr = esp_secure_cert_get_mapped_addr(); + *len = (void*)tlv_header - esp_secure_cert_addr; + return ESP_OK; + } + + *buffer = (char *)&tlv_header->value; + *len = tlv_header->length; + + if (ESP_SECURE_CERT_IS_TLV_ENCRYPTED(tlv_header->flags)) { +#if SOC_HMAC_SUPPORTED + ESP_LOGD(TAG, "TLV data is encrypted"); + char *output_buf = (char *)heap_caps_calloc(1, sizeof(char) * (*len - HMAC_ENCRYPTION_TAG_LEN), MALLOC_CAP_INTERNAL); + if (output_buf == NULL) { + ESP_LOGE(TAG, "Failed to allocate memory"); + return ESP_ERR_NO_MEM; + } + + err = esp_secure_cert_hmac_based_decryption(*buffer, *len, output_buf); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to decrypt the data"); + free(output_buf); + return err; + } + ESP_FAULT_ASSERT(err == ESP_OK); + *buffer = output_buf; + *len = *len - HMAC_ENCRYPTION_TAG_LEN; +#else + return ESP_ERR_NOT_SUPPORTED; +#endif + } else if (ESP_SECURE_CERT_HMAC_ECDSA_KEY_DERIVATION(tlv_header->flags)) { +#if SOC_HMAC_SUPPORTED + ESP_LOGD(TAG, "ECDSA private key shall be generated with help of HMAC"); + char *output_buf = (char *)heap_caps_calloc(1, sizeof(char) * (ESP_SECURE_CERT_ECDSA_DER_KEY_SIZE), MALLOC_CAP_INTERNAL); + if (output_buf == NULL) { + ESP_LOGE(TAG, "Failed to allocate memory"); + return ESP_ERR_NO_MEM; + } + err = esp_secure_cert_gen_ecdsa_key(subtype, output_buf, ESP_SECURE_CERT_ECDSA_DER_KEY_SIZE); + if (err != ESP_OK) { + free(output_buf); + ESP_LOGE(TAG, "Failed to generate ECDSA key, returned %04X", err); + return ESP_FAIL; + } + ESP_FAULT_ASSERT(err == ESP_OK); + *buffer = output_buf; + *len = ESP_SECURE_CERT_ECDSA_DER_KEY_SIZE; +#else + return ESP_ERR_NOT_SUPPORTED; +#endif + } else { + ESP_LOGD(TAG, "TLV data is not encrypted"); + } + return ESP_OK; +} + +esp_err_t esp_secure_cert_get_tlv_info(esp_secure_cert_tlv_config_t *tlv_config, esp_secure_cert_tlv_info_t *tlv_info) +{ + if (tlv_config == NULL || tlv_info == NULL) { + return ESP_ERR_INVALID_ARG; + } + memset(tlv_info, 0, sizeof(esp_secure_cert_tlv_info_t)); + esp_err_t esp_ret; + + esp_secure_cert_tlv_header_t *tlv_header = NULL; + + // Try to obtain the TLV header + esp_ret = esp_secure_cert_tlv_get_header(tlv_config->type, tlv_config->subtype, &tlv_header); + if (esp_ret != ESP_OK) { + return esp_ret; + } + + // Try to obtain the TLV data + esp_ret = esp_secure_cert_tlv_get_addr(tlv_config->type, tlv_config->subtype, &tlv_info->data, &tlv_info->length); + if (esp_ret != ESP_OK) { + tlv_info->data = NULL; + tlv_info->length = 0; + return esp_ret; + } + + // Everything successfully obtained, copy to output tlv_info + tlv_info->type = tlv_header->type; + tlv_info->subtype = tlv_header->subtype; + tlv_info->flags = tlv_header->flags; + + // Special case + if (tlv_info->type == ESP_SECURE_CERT_TLV_END) { + // In this case the user is requesting the end address + // of the TLV entries, invalidate the subtype field + // in the tlv_info struct + tlv_info->subtype = ESP_SECURE_CERT_SUBTYPE_INVALID; + } + return esp_ret; +} + +esp_err_t esp_secure_cert_free_tlv_info(esp_secure_cert_tlv_info_t *tlv_info) +{ + if (tlv_info) { + if (!esp_ptr_in_drom((const void *) tlv_info->data)) { + /* Free the buffer only if it is not from the drom section */ + free(tlv_info->data); + } + } + return ESP_OK; +} + +esp_err_t esp_secure_cert_iterate_to_next_tlv(esp_secure_cert_tlv_iterator_t *tlv_iterator) +{ + if (tlv_iterator == NULL) { + return ESP_ERR_INVALID_ARG; + } + esp_secure_cert_tlv_header_t *tlv_header = (esp_secure_cert_tlv_header_t *)tlv_iterator->iterator; + if (tlv_header == NULL) { + ESP_LOGD(TAG, "tlv_header value is NULL, finding the first TLV entry"); + tlv_header = (esp_secure_cert_tlv_header_t *) esp_secure_cert_get_mapped_addr(); + // Verify the TLV entry integrity before returning + if (esp_secure_cert_verify_tlv_integrity(tlv_header)) { + tlv_iterator->iterator = (void*)tlv_header; + return ESP_OK; + } else { + ESP_LOGI(TAG, "The esp_secure_cert partition does not appear to be valid"); + return ESP_FAIL; + } + } + + // Verify the current TLV entry integrity + if (!esp_secure_cert_verify_tlv_integrity(tlv_header)) { + ESP_LOGE(TAG, "Invalid iterator value provided"); + return ESP_FAIL; + } + + // Move to the next TLV entry + tlv_header = ((void*) tlv_header + esp_secure_cert_get_tlv_total_length(tlv_header)); + if (esp_secure_cert_verify_tlv_integrity(tlv_header)) { + // Verify the TLV entry integrity before returning + tlv_iterator->iterator = (void*)tlv_header; + return ESP_OK; + } + + // We shall come here if the integrity verification + // fails above, this means no more valid TLV entries + ESP_LOGD(TAG, "Iterator is at the last TLV entry"); + // Keeping the log level as debug as this + // is acceptable failure in some cases + return ESP_FAIL; +} + +esp_err_t esp_secure_cert_get_tlv_info_from_iterator(esp_secure_cert_tlv_iterator_t *tlv_iterator, esp_secure_cert_tlv_info_t *tlv_info) +{ + if (tlv_iterator == NULL || tlv_info == NULL) { + return ESP_ERR_INVALID_ARG; + } + esp_secure_cert_tlv_header_t *tlv_header = (esp_secure_cert_tlv_header_t*)tlv_iterator->iterator; + if (!esp_secure_cert_verify_tlv_integrity(tlv_header)) { + ESP_LOGE(TAG, "Iterator does not point to a valid TLV entry"); + return ESP_ERR_INVALID_ARG; + } + + esp_secure_cert_tlv_config_t tlv_config = {}; + tlv_config.type = tlv_header->type; + tlv_config.subtype = tlv_header->subtype; + return esp_secure_cert_get_tlv_info(&tlv_config, tlv_info); +} + +static void esp_secure_cert_print_tlv_info(esp_secure_cert_tlv_info_t *tlv_info) +{ + if (tlv_info != NULL) { + ESP_LOGI(TAG, "Type: %d, Subtype: %d, Data length: %"PRIu32"", tlv_info->type, tlv_info->subtype, tlv_info->length); + ESP_LOGI(TAG, "Flags: %X", tlv_info->flags); + } +} + +void esp_secure_cert_list_tlv_entries(void) +{ + esp_secure_cert_tlv_iterator_t tlv_iterator = {}; + size_t count = 0; + while (esp_secure_cert_iterate_to_next_tlv(&tlv_iterator) == ESP_OK) { + esp_secure_cert_tlv_info_t tlv_info; + if (esp_secure_cert_get_tlv_info_from_iterator(&tlv_iterator, &tlv_info) == ESP_OK) { + count++; + printf("\n"); + ESP_LOGI(TAG, "TLV Entry No: %d", count); + esp_secure_cert_print_tlv_info(&tlv_info); + } + } +} + +#if SOC_HMAC_SUPPORTED +esp_err_t esp_secure_cert_calculate_hmac_encryption_iv(uint8_t *iv) +{ + if (iv == NULL) { + return ESP_ERR_INVALID_ARG; + } + const uint32_t iv_message[HMAC_ENCRYPTION_MESSAGE_LEN / 4] = {[0 ... 7] = 0xABCDABCD}; + esp_err_t esp_ret = ESP_FAIL; + esp_efuse_block_t efuse_block = EFUSE_BLK_MAX; + if (!esp_efuse_find_purpose(ESP_EFUSE_KEY_PURPOSE_HMAC_UP, &efuse_block)) { + ESP_LOGE(TAG, "Failed to get the block with purpose set to HMAC_UP"); + return ESP_FAIL;; + } + + hmac_key_id_t hmac_key_id = efuse_block - (int)EFUSE_BLK_KEY0; + uint8_t hmac[HMAC_ENCRYPTION_AES_GCM_KEY_LEN]; + esp_ret = esp_hmac_calculate(hmac_key_id, (uint8_t *)iv_message, HMAC_ENCRYPTION_MESSAGE_LEN, hmac); + if (esp_ret != ESP_OK) { + ESP_LOGE(TAG, "Could not calculate the HMAC value, returned %04X", esp_ret); + ESP_LOGE(TAG, "returned %04X", esp_ret); + return esp_ret; + } + memcpy(iv, hmac, HMAC_ENCRYPTION_IV_LEN); + return ESP_OK; +} + +esp_err_t esp_secure_cert_calculate_hmac_encryption_key(uint8_t *aes_key) +{ + if (aes_key == NULL) { + return ESP_ERR_INVALID_ARG; + } + const uint32_t key_message[HMAC_ENCRYPTION_MESSAGE_LEN / 4] = {[0 ... 7] = 0xFFFFFFFF}; + esp_err_t esp_ret = ESP_FAIL; + esp_efuse_block_t efuse_block = EFUSE_BLK_MAX; + if (!esp_efuse_find_purpose(ESP_EFUSE_KEY_PURPOSE_HMAC_UP, &efuse_block)) { + ESP_LOGE(TAG, "Failed to get the block with purpose set to HMAC_UP"); + return ESP_FAIL;; + } + + hmac_key_id_t hmac_key_id = efuse_block - (int)EFUSE_BLK_KEY0; + esp_ret = esp_hmac_calculate(hmac_key_id, (uint8_t *)key_message, HMAC_ENCRYPTION_MESSAGE_LEN, aes_key); + if (esp_ret != ESP_OK) { + ESP_LOGE(TAG, "Could not calculate the HMAC value, returned %04X", esp_ret); + return esp_ret; + } + return ESP_OK; +} + +#define HMAC_ENCRYPTION_RANDOM_DELAY_LIMIT 100 +/* + * @info + * Decrypt the data encrypted using hmac based encryption + * + * in_buf This is a pointer in flash that points to the encrypted data + * len Length of the encrypted data + * output_buf Buffer to write the decrypted data + * This must be of size = len - HMAC_ENCRYPTION_TAG_LEN + */ +static esp_err_t esp_secure_cert_hmac_based_decryption(char *in_buf, uint32_t len, char *output_buf) +{ + esp_err_t esp_ret = ESP_FAIL; + int ret = -1; + uint8_t aes_gcm_key[HMAC_ENCRYPTION_AES_GCM_KEY_LEN]; + uint8_t iv[HMAC_ENCRYPTION_IV_LEN]; + + esp_ret = esp_secure_cert_calculate_hmac_encryption_iv(iv); + if (esp_ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to calculate hmac encryption iv"); + return esp_ret; + } + esp_ret = esp_secure_cert_calculate_hmac_encryption_key(aes_gcm_key); + if (esp_ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to calculate hmac encryption key"); + return esp_ret; + } + + mbedtls_gcm_context gcm_ctx; + mbedtls_gcm_init(&gcm_ctx); + ret = mbedtls_gcm_setkey(&gcm_ctx, MBEDTLS_CIPHER_ID_AES, (unsigned char *)aes_gcm_key, HMAC_ENCRYPTION_AES_GCM_KEY_LEN * 8); + if (ret != 0) { + ESP_LOGE(TAG, "Failure at mbedtls_gcm_setkey with error code : -0x%04X", -ret); + mbedtls_gcm_free(&gcm_ctx); + return ESP_FAIL; + } + + uint32_t rand_delay; + rand_delay = esp_random() % HMAC_ENCRYPTION_RANDOM_DELAY_LIMIT; + esp_rom_delay_us(rand_delay); + + len = len - HMAC_ENCRYPTION_TAG_LEN; + ret = mbedtls_gcm_auth_decrypt(&gcm_ctx, len, iv, + HMAC_ENCRYPTION_IV_LEN, NULL, 0, + (unsigned char *) (in_buf + len), + HMAC_ENCRYPTION_TAG_LEN, + (const unsigned char *)(in_buf), + (unsigned char *)output_buf); + + if (ret != 0) { + ESP_LOGE(TAG, "Failed to decrypt the data, mbedtls_gcm_crypt_and_tag returned %02X", ret); + mbedtls_gcm_free(&gcm_ctx); + return ESP_FAIL; + } + + ESP_FAULT_ASSERT(ret == ESP_OK); + + return ESP_OK; +} + +static int myrand(void *rng_state, unsigned char *output, size_t len) +{ + size_t olen; + (void) olen; + return mbedtls_hardware_poll(rng_state, output, len, &olen); +} + +/* + * The API converts the 256 bit ECDSA key to DER format. + * @input + * key_buf The readable buffer containing the plaintext key + * key_buf_len The length of the key buf in bytes + * output_buf The writable buffer to write the DER key + * output_buf_len Length of the output buffer + * + */ +static esp_err_t esp_secure_cert_convert_key_to_der(char *key_buf, size_t key_buf_len, char* output_buf, size_t output_buf_len) +{ + esp_err_t ret = ESP_FAIL; + // Convert the private key to der + mbedtls_pk_context key; + mbedtls_pk_init(&key); + ret = mbedtls_pk_setup(&key, mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY)); + if (ret != 0) { + ESP_LOGE(TAG, "Failed to setup pk key, returned %04X", ret); + goto exit; + } + + mbedtls_ecdsa_context *key_ctx = mbedtls_pk_ec(key); + ret = mbedtls_ecp_group_load(&key_ctx->MBEDTLS_PRIVATE(grp), MBEDTLS_ECP_DP_SECP256R1); + if (ret != 0) { + ESP_LOGE(TAG, "Failed to load the ecp group, returned %04X", ret); + goto exit; + } + + ret = mbedtls_mpi_read_binary(&key_ctx->MBEDTLS_PRIVATE(d), (const unsigned char *) key_buf, key_buf_len); + if (ret != 0) { + ESP_LOGE(TAG, "Failed to read binary, returned %04X", ret); + goto exit; + } + + // Calculate the public key + ret = mbedtls_ecp_mul(&key_ctx->MBEDTLS_PRIVATE(grp), &key_ctx->MBEDTLS_PRIVATE(Q), &key_ctx->MBEDTLS_PRIVATE(d), &key_ctx->MBEDTLS_PRIVATE(grp).G, myrand, NULL); + if (ret != 0) { + ESP_LOGE(TAG, "Failed to generate public key, returned %04X", ret); + goto exit; + } + + // Write the private key in DER format + ret = mbedtls_pk_write_key_der(&key, (unsigned char *) output_buf, output_buf_len); + if (ret != ESP_SECURE_CERT_ECDSA_DER_KEY_SIZE) { + ESP_LOGE(TAG, "Failed to write the pem key, returned %04X", ret); + goto exit; + } + ret = ESP_OK; + +exit: + mbedtls_pk_free(&key); + return ret; +} +/* + * @info + * Generate the ECDSA private key (DER format) with help of the PBKDF2 hmac implementation. + * In this case the first eFuse key block with purpose set to HMAC_UP shall be used for generating the private key. + * The key shall be generated for the SECP256R1 curve, the length of the key in DER format shall be ESP_SECURE_CERT_ECDSA_DER_KEY_SIZE bytes. + * The API assumes that a valid salt is stored in the esp_secure_cert partition, Otherwise the API would return with failure. + * + * @input + * output_buf A writable buffer to store the DER formatted ECDSA private key + * buf_len The length of the buffer in bytes. This must be exactly ESP_SECURE_CERT_ECDSA_DER_KEY_SIZE bytes. + * + */ +static esp_err_t esp_secure_cert_gen_ecdsa_key(esp_secure_cert_tlv_subtype_t subtype, char *output_buf, size_t buf_len) +{ + esp_err_t err = ESP_FAIL; + int ret = 0; + if (buf_len != ESP_SECURE_CERT_ECDSA_DER_KEY_SIZE) { + return ESP_ERR_INVALID_ARG; + } + + // Obtain the salt stored in the esp_secure_cert partition + uint8_t *salt = NULL; + uint32_t salt_len = 0; + err = esp_secure_cert_tlv_get_addr(ESP_SECURE_CERT_HMAC_ECDSA_KEY_SALT, subtype, (void *)&salt, &salt_len); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Error in reading salt, returned %04X", err); + } + ESP_FAULT_ASSERT(err == ESP_OK); + + ESP_LOG_BUFFER_HEX_LEVEL("SALT", salt, salt_len, ESP_LOG_DEBUG); + + esp_efuse_block_t efuse_block = EFUSE_BLK_KEY_MAX; + bool res = esp_efuse_find_purpose(ESP_EFUSE_KEY_PURPOSE_HMAC_UP, &efuse_block); + if (!res) { + ESP_LOGE(TAG, "Failed to get the block with purpose set to HMAC_UP"); + return ESP_FAIL; + } + ESP_FAULT_ASSERT(res); + + // Allocate memory for private key + char *key_buf = (char *)heap_caps_calloc(1, sizeof(char) * (ESP_SECURE_CERT_DERIVED_ECDSA_KEY_SIZE), MALLOC_CAP_INTERNAL); + if (key_buf == NULL) { + ESP_LOGE(TAG, "Failed to allocate memory"); + return ESP_ERR_NO_MEM; + } + + // Generate the private key + ret = esp_pbkdf2_hmac_sha256(efuse_block - (int)EFUSE_BLK_KEY0, salt, salt_len, ESP_SECURE_CERT_KEY_DERIVATION_ITERATION_COUNT, ESP_SECURE_CERT_DERIVED_ECDSA_KEY_SIZE, (unsigned char *)key_buf); + if (ret != 0) { + ESP_LOGE(TAG, "Failed to derive the ECDSA key using HMAC, returned %04X", ret); + free(key_buf); + return ESP_FAIL; + } + ESP_FAULT_ASSERT(ret == 0); + + err = esp_secure_cert_convert_key_to_der(key_buf, ESP_SECURE_CERT_DERIVED_ECDSA_KEY_SIZE, output_buf, ESP_SECURE_CERT_ECDSA_DER_KEY_SIZE); + if (err != ESP_OK) { + free(key_buf); + free(output_buf); + ESP_LOGE(TAG, "Failed to convert the plaintext key to DER format"); + return ESP_FAIL; + } + // Free the plaintext private key as it is no longer needed + free(key_buf); + return ESP_OK; +} +#endif + +#ifdef CONFIG_ESP_SECURE_CERT_DS_PERIPHERAL +esp_ds_data_ctx_t *esp_secure_cert_tlv_get_ds_ctx(void) +{ + esp_err_t esp_ret; + esp_ds_data_ctx_t *ds_data_ctx; + + ds_data_ctx = (esp_ds_data_ctx_t *)calloc(1, sizeof(esp_ds_data_ctx_t)); + if (ds_data_ctx == NULL) { + ESP_LOGE(TAG, "Error in allocating memory for esp_ds_data_context"); + goto exit; + } + + uint32_t len; + esp_ds_data_t *esp_ds_data; + esp_ret = esp_secure_cert_tlv_get_addr(ESP_SECURE_CERT_DS_DATA_TLV, ESP_SECURE_CERT_SUBTYPE_0, (void *) &esp_ds_data, &len); + if (esp_ret != ESP_OK) { + ESP_LOGE(TAG, "Error in reading ds_data, returned %04X", esp_ret); + goto exit; + } + + esp_ds_data_ctx_t *ds_data_ctx_flash; + esp_ret = esp_secure_cert_tlv_get_addr(ESP_SECURE_CERT_DS_CONTEXT_TLV, 0, (void *) &ds_data_ctx_flash, &len); + memcpy(ds_data_ctx, ds_data_ctx_flash, len); + ds_data_ctx->esp_ds_data = esp_ds_data; + if (esp_ret != ESP_OK) { + ESP_LOGE(TAG, "Error in reading ds_context, returned %04X", esp_ret); + goto exit; + } + return ds_data_ctx; +exit: + free(ds_data_ctx); + return NULL; +} + +void esp_secure_cert_tlv_free_ds_ctx(esp_ds_data_ctx_t *ds_ctx) +{ + free(ds_ctx); +} +#endif /* CONFIG_ESP_SECURE_CERT_DS_PERIPHERAL */ + +bool esp_secure_cert_is_tlv_partition(void) +{ + char *esp_secure_cert_addr = (char *)esp_secure_cert_get_mapped_addr(); + if (esp_secure_cert_addr == NULL) { + return 0; + } + esp_secure_cert_tlv_header_t *tlv_header = (esp_secure_cert_tlv_header_t *)(esp_secure_cert_addr ); + if (tlv_header->magic == ESP_SECURE_CERT_TLV_MAGIC) { + ESP_LOGD(TAG, "TLV partition identified"); + return 1; + } + return 0; +} + +#ifndef CONFIG_ESP_SECURE_CERT_SUPPORT_LEGACY_FORMATS +esp_err_t esp_secure_cert_get_device_cert(char **buffer, uint32_t *len) +{ + return esp_secure_cert_tlv_get_addr(ESP_SECURE_CERT_DEV_CERT_TLV, ESP_SECURE_CERT_SUBTYPE_0, buffer, len); +} + +esp_err_t esp_secure_cert_free_device_cert(char *buffer) +{ + (void) buffer; /* nothing to do */ + return ESP_OK; +} + +esp_err_t esp_secure_cert_get_ca_cert(char **buffer, uint32_t *len) +{ + return esp_secure_cert_tlv_get_addr(ESP_SECURE_CERT_CA_CERT_TLV, ESP_SECURE_CERT_SUBTYPE_0, buffer, len); +} + +esp_err_t esp_secure_cert_free_ca_cert(char *buffer) +{ + (void) buffer; /* nothing to do */ + return ESP_OK; +} + +#ifndef CONFIG_ESP_SECURE_CERT_DS_PERIPHERAL +esp_err_t esp_secure_cert_get_priv_key(char **buffer, uint32_t *len) +{ + return esp_secure_cert_tlv_get_addr(ESP_SECURE_CERT_PRIV_KEY_TLV, ESP_SECURE_CERT_SUBTYPE_0, buffer, len); +} + +esp_err_t esp_secure_cert_free_priv_key(char *buffer) +{ + if (!esp_ptr_in_drom((const void *) buffer)) { + free(buffer); + return ESP_OK; + } + (void) buffer; /* nothing to do */ + return ESP_OK; +} + +#else /* !CONFIG_ESP_SECURE_CERT_DS_PEIPHERAL */ + +esp_ds_data_ctx_t *esp_secure_cert_get_ds_ctx(void) +{ + return esp_secure_cert_tlv_get_ds_ctx(); +} + +void esp_secure_cert_free_ds_ctx(esp_ds_data_ctx_t *ds_ctx) +{ + esp_secure_cert_tlv_free_ds_ctx(ds_ctx); +} +#endif /* CONFIG_ESP_SECURE_CERT_DS_PERIPHERAL */ + +esp_err_t esp_secure_cert_get_priv_key_type(esp_secure_cert_key_type_t *priv_key_type) { + esp_err_t err; + if (priv_key_type == NULL) { + return ESP_ERR_INVALID_ARG; + } + esp_secure_cert_tlv_header_t *tlv_header = NULL; + err = esp_secure_cert_tlv_get_header(ESP_SECURE_CERT_PRIV_KEY_TLV, 0, &tlv_header); + if (err != ESP_OK) { + *priv_key_type = ESP_SECURE_CERT_INVALID_KEY; + ESP_LOGE(TAG, "Could not find header for priv key"); + return err; + } + + if (ESP_SECURE_CERT_HMAC_ECDSA_KEY_DERIVATION(tlv_header->flags)) { + *priv_key_type = ESP_SECURE_CERT_HMAC_DERIVED_ECDSA_KEY; + } else if (ESP_SECURE_CERT_KEY_ECDSA_PERIPHERAL(tlv_header->flags)) { + *priv_key_type = ESP_SECURE_CERT_ECDSA_PERIPHERAL_KEY; + } else if (ESP_SECURE_CERT_IS_TLV_ENCRYPTED(tlv_header->flags)) { + *priv_key_type = ESP_SECURE_CERT_HMAC_ENCRYPTED_KEY; + } else { + *priv_key_type = ESP_SECURE_CERT_DEFAULT_FORMAT_KEY; + } + return ESP_OK; +} + +esp_err_t esp_secure_cert_get_priv_key_efuse_id(uint8_t *efuse_block_id) { + esp_err_t err; + esp_secure_cert_tlv_header_t *tlv_header = NULL; + if (efuse_block_id == NULL) { + return ESP_ERR_INVALID_ARG; + } + + err = esp_secure_cert_tlv_get_header(ESP_SECURE_CERT_TLV_SEC_CFG, 0, &tlv_header); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Could not find header for TLV security configurations"); + return ESP_ERR_NOT_SUPPORTED; + } + + esp_secure_cert_tlv_sec_cfg_t *tlv_sec_cfg; + tlv_sec_cfg = (esp_secure_cert_tlv_sec_cfg_t *) tlv_header->value; + *efuse_block_id = tlv_sec_cfg->priv_key_efuse_id; + + return ESP_OK; +} +#endif /* CONFIG_ESP_SECURE_CERT_SUPPORT_LEGACY_FORMATS */ diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/tools/LICENSE b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/tools/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/tools/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/tools/MANIFEST.in b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/tools/MANIFEST.in new file mode 100644 index 000000000..f9bd1455b --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/tools/MANIFEST.in @@ -0,0 +1 @@ +include requirements.txt diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/tools/README.md b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/tools/README.md new file mode 100644 index 000000000..90765a9a2 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/tools/README.md @@ -0,0 +1,91 @@ +# esp_secure_cert Configuration Tool +> WARNING: This tool is to be used only for development purpose. It does not enable any kind security feature for the protection of the sensitive data in the `esp_secure_cert` partition. + +The script [configure_esp_secure_cert.py](https://github.com/espressif/esp_secure_cert_mgr/blob/main/tools/configure_esp_secure_cert.py) is used for configuring the ESP platform with PKI credentials into the esp_secure_cert partition which shall reside on its flash storage. +It also configures the DS peripheral on the ESP32-S2/ESP32-S3/ESP32-C3 SoC. The steps in the script are based on technical details of certain operations in the Digital Signature calculation, which can be found in the Digital Signature Section of [ESP32-S2 TRM](https://www.espressif.com/sites/default/files/documentation/esp32-s2_technical_reference_manual_en.pdf). + +The script generates a partition named `esp_secure_cert` on host machine, that contains the parameters required by the DS peripheral. The `configure_esp_secure_cert.py` utility automatically flashes the partition to the ESP platform which has been connected. + +# Installation + +``` +pip install esp-secure-cert-tool +``` + +# Configuration + +1) Generate root ca and key pair: +``` +openssl req -newkey rsa:2048 -nodes -keyout prvtkey.pem -x509 -days 3650 -out cacert.pem -subj "/CN=Test CA" +``` + +2) Generate client private key: +``` +openssl genrsa -out client.key +``` + +3) Generate device cert: +``` +openssl req -out client.csr -key client.key -new +openssl x509 -req -days 365 -in client.csr -CA cacert.pem -CAkey prvtkey.pem -sha256 -CAcreateserial -out client.crt +``` + +# Generate `esp_secure_cert` partition +Following commands can be used to configure the DS peripheral and generate the `esp_secure_cert` partition. +The script can generate `cust_flash` as well as `nvs` type of `esp_secure_cert` partition. Please refer [upper level README](../README.md) for more details about type of partitions. + +* When configuring the DS peripheral, by default the configuration script does not enable the read protection for the efuse key block in which the DS key is programmed. This is done for allowing flexibility while using the script for development purpose. + +* Please remove the `--configure_ds` argument from these commands if use of the DS peripheral is disabled in the menu config. +> **WARNING**: This is not recommended for production purpose as the private key shall be stored as plaintext. + +## Generate `esp_secure_cert` partition of type `cust_flash_tlv`: + +This command shall generate a binary partition containing the PKI credentials stored in the TLV format and flash it at the default offset of `0xD000`. + +``` +configure_esp_secure_cert.py -p /* Serial port */ --keep_ds_data_on_host --efuse_key_id 1 --ca-cert cacert.pem --device-cert client.crt --private-key client.key --target_chip /* target chip */ --secure_cert_type cust_flash_tlv --configure_ds +``` + +* When [Flash Encryption](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/security/flash-encryption.html) is enabled for the device, the option ``--skip_flash`` (explained below) can be used to prevent the flashing opereation and only save the `esp_secure_cert.bin` on the host machine. It can then be flashed on the target using below command: + + ```esptool.py -p /* Serial Port*/ write_flash 0xD000 esp_secure_cert.bin --encrypt``` + + More details regarding [esptool.py](https://docs.espressif.com/projects/esptool/en/latest/esp32/esptool/index.html#esptool-py) utility can be found [here](https://docs.espressif.com/projects/esptool/en/latest/esp32/esptool/index.html). + + Note: This is only applicable for [Development mode](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/security/flash-encryption.html#flash-enc-development-mode) of Flash Encryption. + +## Legacy partition formats: + +1. Generate `esp_secure_cert` partition of type `cust_flash`: + +``` +configure_esp_secure_cert.py -p /* Serial port */ --keep_ds_data_on_host --efuse_key_id 1 --ca-cert cacert.pem --device-cert client.crt --private-key client.key --target_chip /* target chip */ --secure_cert_type cust_flash --configure_ds +``` + +2. Generate `esp_secure_cert` partition of type `nvs`: +``` +configure_esp_secure_cert.py -p /* Serial port */ --keep_ds_data_on_host --efuse_key_id 1 --ca-cert cacert.pem --device-cert client.crt --private-key client.key --target_chip /* target chip */ --secure_cert_type nvs --configure_ds +``` + +## Additional options for the utility +The following options can be provided additional to the main arguments given above. + +### Set the `esp_secure_cert` partition offset +By default the `esp_secure_cert` partition shall be flashed at an offset of `0xD000` by the utility. +In order to flash the `esp_secure_cert` partition at a different offset, the following argument can be provided additionally to the configure_esp_secure_cert.py script. + +``` +configure_esp_secure_cert.py --sec_cert_part_offset /* offset value in hex e.g. 0xD000 */ +``` +### Skip automatic flashing of `esp_secure_cert` partition + +By default the `esp_secure_cert` partition shall be flashed automatically at the offset value provided to `sec_cert_part_offset` argument. +In order to stop the flashing process the following argument can be provided additionally to the configure_esp_secure_cert.py script + +``` +configure_esp_secure_cert.py --skip_flash +``` + +### Help section +The additional options supported by the utility can be found at `configure_esp_secure_cert.py --help`. diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/tools/__init__.py b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/tools/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/tools/configure_esp_secure_cert.py b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/tools/configure_esp_secure_cert.py new file mode 100644 index 000000000..49c5308aa --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/tools/configure_esp_secure_cert.py @@ -0,0 +1,370 @@ +#!/usr/bin/env python +# SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: Apache-2.0 +import argparse +import os +import subprocess +import sys +from esp_secure_cert import nvs_format, custflash_format +from esp_secure_cert import configure_ds, tlv_format +from esp_secure_cert.efuse_helper import ( + log_efuse_summary, + configure_efuse_key_block +) + +idf_path = os.getenv('IDF_PATH') +if not idf_path or not os.path.exists(idf_path): + raise Exception('IDF_PATH not found') + +# Check python version is proper or not to avoid script failure +assert sys.version_info >= (3, 6, 0), 'Python version too low.' + +esp_secure_cert_data_dir = 'esp_secure_cert_data' +# hmac_key_file is generated when HMAC_KEY is calculated, +# it is used when burning HMAC_KEY to efuse +hmac_key_file = os.path.join(esp_secure_cert_data_dir, 'hmac_key.bin') +ecdsa_key_file = os.path.join(esp_secure_cert_data_dir, 'ecdsa_key.bin') +# csv and bin filenames are default filenames +# for nvs partition files created with this script +csv_filename = os.path.join(esp_secure_cert_data_dir, 'esp_secure_cert.csv') +bin_filename = os.path.join(esp_secure_cert_data_dir, 'esp_secure_cert.bin') +# Targets supported by the script +supported_targets = {'esp32', 'esp32s2', 'esp32c3', 'esp32s3', + 'esp32c6', 'esp32h2', 'esp32p4'} + + +# Flash esp_secure_cert partition after its generation +# +# @info +# The partition shall be flashed at the offset provided +# for the --sec_cert_part_offset option +def flash_esp_secure_cert_partition(idf_path, idf_target, + port, sec_cert_part_offset, + flash_filename): + print('Flashing the esp_secure_cert partition at {0} offset' + .format(sec_cert_part_offset)) + print('Note: You can skip this step by providing --skip_flash argument') + flash_command = f"python {idf_path}/components/esptool_py/" + \ + f"esptool/esptool.py --chip {idf_target} " + \ + f"-p {port} write_flash " + \ + f" {sec_cert_part_offset} {flash_filename}" + try: + flash_command_output = subprocess.check_output( + flash_command, + shell=True + ) + print(flash_command_output.decode('utf-8')) + except subprocess.CalledProcessError as e: + print(e.output.decode("utf-8")) + print('ERROR: Failed to execute the flash command') + sys.exit(-1) + + +def cleanup(args): + if args.keep_ds_data is False: + if os.path.exists(hmac_key_file): + os.remove(hmac_key_file) + if os.path.exists(csv_filename): + os.remove(csv_filename) + + +def main(): + parser = argparse.ArgumentParser(description=''' + The python utility helps to configure and provision + the device with PKI credentials, to generate the esp_secure_cert partition. + The utility also configures the DS peripheral on the SoC if available. + ''') + + parser.add_argument( + '--private-key', + dest='privkey', + default='client.key', + metavar='relative/path/to/client-priv-key', + help='relative path to client private key') + + parser.add_argument( + '--pwd', '--password', + dest='priv_key_pass', + metavar='[password]', + help='the password associated with the private key') + + parser.add_argument( + '--device-cert', + dest='device_cert', + default='client.crt', + metavar='relative/path/to/device-cert', + help='relative path to device/client certificate ' + '(which contains the public part of the client private key) ') + + parser.add_argument( + '--ca-cert', + dest='ca_cert', + default='ca.crt', + metavar='relative/path/to/ca-cert', + help='relative path to ca certificate which ' + 'has been used to sign the client certificate') + + parser.add_argument( + '--target_chip', + dest='target_chip', type=str, + choices=supported_targets, + default='esp32c3', + metavar='target chip', + help='The target chip e.g. esp32s2, s3, c3') + + parser.add_argument( + '--summary', + dest='summary', action='store_true', + help='Provide this option to print efuse summary of the chip') + + parser.add_argument( + '--secure_cert_type', + dest='sec_cert_type', type=str, + choices={'cust_flash_tlv', 'cust_flash', 'nvs'}, + default='cust_flash_tlv', + metavar='type of secure_cert partition', + help='The type of esp_secure_cert partition. ' + 'Can be \"cust_flash_tlv\" or \"cust_flash\" or \"nvs\". ' + 'Please note that \"cust_flash\" and \"nvs\" are legacy formats.') + + parser.add_argument( + '--configure_ds', + dest='configure_ds', action='store_true', + help='Provide this option to configure the DS peripheral.') + + parser.add_argument( + '--skip_flash', + dest='skip_flash', action='store_true', + help='Provide this option to skip flashing the' + ' esp_secure_cert partition at the value' + ' provided to sec_cert_part_offset option') + + parser.add_argument( + '--efuse_key_id', + dest='efuse_key_id', type=int, choices=range(0, 6), + metavar='[key_id] ', + default=1, + help='Provide the efuse key_id which ' + 'contains/will contain HMAC_KEY, default is 1') + + parser.add_argument( + '--efuse_key_file', + help='eFuse key file which contains the ' + 'key that shall be burned in ' + 'the eFuse (e.g. HMAC key, ECDSA key)', + metavar='[/path/to/efuse key file]') + + parser.add_argument( + '--port', '-p', + dest='port', + metavar='[port]', + required=True, + help='UART com port to which the ESP device is connected') + + parser.add_argument( + '--keep_ds_data_on_host', '-keep_ds_data', + dest='keep_ds_data', action='store_true', + help='Keep encrypted private key data and key ' + 'on host machine for testing purpose') + + parser.add_argument( + '--sec_cert_part_offset', + dest='sec_cert_part_offset', + default='0xD000', + help='The flash offset of esp_secure_cert partition' + ' Hex value must be given e.g. 0xD000') + + parser.add_argument( + '--priv_key_algo', + help='Signing algorithm used by the private key ' + ', e.g. RSA 2048, ECDSA 256', + nargs=2, required=True, + metavar='[sign algorithm, key size]') + + args = parser.parse_args() + + idf_target = args.target_chip + if idf_target not in supported_targets: + if idf_target is not None: + print('ERROR: The script does not support ' + 'the target {}'.format(idf_target)) + sys.exit(-1) + idf_target = str(idf_target) + + if args.summary is not False: + log_efuse_summary(idf_path, idf_target, args.port) + sys.exit(0) + + if (os.path.exists(args.privkey) is False): + print('ERROR: The provided private key file does not exist') + sys.exit(-1) + + if (os.path.exists(args.device_cert) is False): + print('ERROR: The provided client cert file does not exist') + sys.exit(-1) + + if (os.path.exists(esp_secure_cert_data_dir) is False): + os.makedirs(esp_secure_cert_data_dir) + + # Provide CA cert path only if it exists + ca_cert = None + if (os.path.exists(args.ca_cert) is True): + ca_cert = os.path.abspath(args.ca_cert) + + c = None + iv = None + key_size = None + + if args.configure_ds is not False: + if args.priv_key_algo[0] == 'RSA': + sign_algo = args.priv_key_algo[0] + sign_algo_key_size = args.priv_key_algo[1] + configure_ds.validate_ds_algorithm(sign_algo, + sign_algo_key_size, + idf_target) + + # Burn hmac_key on the efuse block (if it is empty) or read it + # from the efuse block (if the efuse block already contains a key). + efuse_purpose = 'HMAC_DOWN_DIGITAL_SIGNATURE' + efuse_key_file = args.efuse_key_file + hmac_key = None + if (args.efuse_key_file is None + or not os.path.exists(efuse_key_file)): + if not os.path.exists(hmac_key_file): + hmac_key = os.urandom(32) + with open(hmac_key_file, "wb+") as key_file: + key_file.write(hmac_key) + + efuse_key_file = hmac_key_file + else: + with open(efuse_key_file, "rb") as key_file: + hmac_key = key_file.read() + + print(f'Using the eFuse key given at {args.efuse_key_file}' + 'as the HMAC key') + + configure_efuse_key_block(idf_path, + idf_target, + args.port, + efuse_key_file, + args.efuse_key_id, + efuse_purpose) + + with open(efuse_key_file, "rb") as key_file: + hmac_key = key_file.read() + + # Calculate the encrypted private key data along + # with all other parameters + c, iv, key_size = configure_ds.calculate_rsa_ds_params(args.privkey, # type: ignore # noqa: E501 + args.priv_key_pass, # type: ignore # noqa: E501 + hmac_key, + idf_target) + + elif args.priv_key_algo[0] == 'ECDSA': + sign_algo = args.priv_key_algo[0] + sign_algo_key_size = args.priv_key_algo[1] + configure_ds.validate_ds_algorithm(sign_algo, + sign_algo_key_size, + idf_target) + + # efuse key length + expected_key_len = 32 + ecdsa_key = configure_ds.get_ecdsa_key_bytes(args.privkey, + args.priv_key_pass, + expected_key_len) + if not os.path.exists(ecdsa_key_file): + with open(ecdsa_key_file, "wb+") as key_file: + key_file.write(ecdsa_key) + efuse_key_file = ecdsa_key_file + efuse_purpose = 'ECDSA_KEY' + try: + configure_efuse_key_block(idf_path, idf_target, + args.port, + args.privkey, + args.efuse_key_id, + efuse_purpose) + except OSError: + print('Hint: For ECDSA peripheral esptool version' + ' must be >= v4.6, Please make sure the ' + 'requirement is satisfied') + raise + + else: + raise ValueError('Invalid priv key algorithm ' + f'{args.priv_key_algo[0]}') + + else: + print('--configure_ds option not set. ' + 'Configuring without use of DS peripheral.') + print('WARNING: Not Secure.\n' + 'the private shall be stored as plaintext') + + if args.sec_cert_type == 'cust_flash_tlv': + key_type = tlv_format.tlv_priv_key_type_t.ESP_SECURE_CERT_DEFAULT_FORMAT_KEY # type: ignore # noqa: E501 + tlv_priv_key = tlv_format.tlv_priv_key_t(key_type, + args.privkey, + args.priv_key_pass) + + if args.configure_ds is not False: + if args.priv_key_algo[0] == 'RSA': + tlv_priv_key.key_type = tlv_format.tlv_priv_key_type_t.ESP_SECURE_CERT_RSA_DS_PERIPHERAL_KEY # type: ignore # noqa: E501 + tlv_priv_key.ciphertext = c + tlv_priv_key.iv = iv + tlv_priv_key.efuse_key_id = args.efuse_key_id + tlv_priv_key.priv_key_len = key_size + + tlv_format.generate_partition_ds(tlv_priv_key, + args.device_cert, + ca_cert, idf_target, + bin_filename) + if args.priv_key_algo[0] == 'ECDSA': + tlv_priv_key.key_type = tlv_format.tlv_priv_key_type_t.ESP_SECURE_CERT_ECDSA_PERIPHERAL_KEY # type: ignore # noqa: E501 + print('Generating ECDSA partition') + tlv_priv_key.efuse_key_id = args.efuse_key_id + priv_key_len = int(args.priv_key_algo[1], 10) + tlv_priv_key.priv_key_len = priv_key_len + tlv_format.generate_partition_ds(tlv_priv_key, + args.device_cert, + ca_cert, idf_target, + bin_filename) + else: + tlv_format.generate_partition_no_ds(tlv_priv_key, + args.device_cert, + ca_cert, idf_target, + bin_filename) + elif args.sec_cert_type == 'cust_flash': + if args.configure_ds is not False: + custflash_format.generate_partition_ds(c, iv, args.efuse_key_id, + key_size, args.device_cert, + ca_cert, idf_target, + bin_filename) + else: + custflash_format.generate_partition_no_ds(args.device_cert, + ca_cert, + args.privkey, + args.priv_key_pass, + idf_target, bin_filename) + elif args.sec_cert_type == 'nvs': + # Generate csv file for the DS data and generate an NVS partition. + if args.configure_ds is not False: + nvs_format.generate_csv_file_ds(c, iv, args.efuse_key_id, + key_size, args.device_cert, + ca_cert, csv_filename) + else: + nvs_format.generate_csv_file_no_ds(args.device_cert, ca_cert, + args.privkey, + args.priv_key_pass, + csv_filename) + nvs_format.generate_partition(csv_filename, bin_filename) + + if args.skip_flash is False: + flash_esp_secure_cert_partition(idf_path, idf_target, + args.port, + args.sec_cert_part_offset, + bin_filename) + + cleanup(args) + + +if __name__ == '__main__': + main() diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/tools/esp_secure_cert/__init__.py b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/tools/esp_secure_cert/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/tools/esp_secure_cert/configure_ds.py b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/tools/esp_secure_cert/configure_ds.py new file mode 100644 index 000000000..562bf42e1 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/tools/esp_secure_cert/configure_ds.py @@ -0,0 +1,172 @@ +import hashlib +import hmac +import os +import struct +import sys +from cryptography.hazmat.backends import default_backend +from cryptography.hazmat.primitives.asymmetric import rsa, ec +from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes +from cryptography.utils import int_to_bytes +from esp_secure_cert.esp_secure_cert_helper import load_private_key + +supported_targets_rsa_ds = ['esp32s2', 'esp32s3', 'esp32c3', + 'esp32c6', 'esp32h2', 'esp32p4'] +supported_key_size_rsa = {'esp32s2': [1024, 2048, 3072, 4096], + 'esp32c3': [1024, 2048, 3072], + 'esp32s3': [1024, 2048, 3072, 4096], + 'esp32c6': [1024, 2048, 3072], + 'esp32h2': [1024, 2048, 3072], + 'esp32p4': [1024, 2048, 3072, 4096]} + +supported_targets_ecdsa = ['esp32h2', 'esp32p4'] +supported_key_size_ecdsa = {'esp32h2': [256], + 'esp32p4': [256]} + +idf_path = os.getenv('IDF_PATH') +if not idf_path or not os.path.exists(idf_path): + raise Exception('IDF_PATH not found') + + +def number_as_bytes(number, pad_bits=None): + """ + Given a number, format as a little endian array of bytes + """ + result = int_to_bytes(number)[::-1] + while pad_bits is not None and len(result) < (pad_bits // 8): + result += b'\x00' + return result + + +# @return +# c : ciphertext_c +# iv : initialization vector +# key_size : key size of the RSA private key in bytes. +# @input +# privkey : path to the RSA private key +# priv_key_pass : path to the RSA privaete key password +# hmac_key : HMAC key value ( to calculate DS params) +# idf_target : The target chip for the script (e.g. esp32c3) +# @info +# The function calculates the encrypted private key parameters. +# Consult the DS documentation (available for the ESP32-S2) +# in the esp-idf programming guide for more details +# about the variables and calculations. +def calculate_rsa_ds_params(privkey, priv_key_pass, hmac_key, idf_target): + private_key_data = load_private_key(privkey, priv_key_pass) + private_key = private_key_data["key_instance"] + if not isinstance(private_key, rsa.RSAPrivateKey): + print('ERROR: Only RSA private keys are supported') + sys.exit(-1) + if hmac_key is None: + print('ERROR: hmac_key cannot be None') + sys.exit(-2) + + priv_numbers = private_key.private_numbers() + pub_numbers = private_key.public_key().public_numbers() + Y = priv_numbers.d + M = pub_numbers.n + key_size = private_key.key_size + if key_size not in supported_key_size_rsa[idf_target]: + print('ERROR: Private key size {0} not supported for the target {1},' + '\nthe supported key sizes are {2}' + .format(key_size, idf_target, + str(supported_key_size_rsa[idf_target]))) + sys.exit(-1) + + iv = os.urandom(16) + + rr = 1 << (key_size * 2) + rinv = rr % pub_numbers.n + mprime = - rsa._modinv(M, 1 << 32) + mprime &= 0xFFFFFFFF + length = key_size // 32 - 1 + + # get max supported key size for the respective target + max_len = max(supported_key_size_rsa[idf_target]) + aes_key = hmac.HMAC(hmac_key, b'\xFF' * 32, hashlib.sha256).digest() + + md_in = number_as_bytes(Y, max_len) + \ + number_as_bytes(M, max_len) + \ + number_as_bytes(rinv, max_len) + \ + struct.pack(' dict: + """ + Executes an 'espefuse' command to obtain + eFuse summary in JSON format. + + Args: + idf_path (str): Path to the ESP-IDF installation directory. + idf_target (str): ESP-IDF target to build for. + port (str): Serial port to communicate with the device. + + Returns: + dict: A dictionary containing eFuse summary data in JSON format. + + Raises: + subprocess.CalledProcessError: If the 'espefuse' command exits + with a non-zero status. + json.JSONDecodeError: If the eFuse summary output + cannot be parsed as JSON. + """ + efuse_summary = None + try: + efuse_summary = subprocess.check_output( + f"python {idf_path}/components/esptool_py/esptool/espefuse.py " + f"--chip {idf_target} -p {port} summary --format json", + shell=True + ) + except subprocess.CalledProcessError as e: + print(e.output.decode("utf-8")) + sys.exit(-1) + + efuse_summary = efuse_summary.decode("utf-8") + # Remove everything before actual json data + # from efuse_summary command output. + efuse_summary = efuse_summary[efuse_summary.find("{"):] + try: + efuse_summary_json = json.loads(efuse_summary) + return efuse_summary_json + except json.JSONDecodeError: + raise json.JSONDecodeError("Failed to parse the " + "eFuse summary JSON output") + + +def log_efuse_summary(idf_path: str, idf_target: str, port: str) -> None: + """ + Prints the efuse summary on console by executing the `espefuse.py` script. + + Args: + idf_path (str): Path to the IDF installation directory. + idf_target (str): IDF target chip. + port (str): Serial port to use for communication with the chip. + + Returns: + None + + Raises: + OSError: If there is an issue executing the `espefuse.py` script. + """ + try: + os.system(f"python {idf_path}/components/esptool_py/esptool/" + f"espefuse.py --chip {idf_target} -p {port} summary") + except OSError: + raise OSError("Unable to execute `espefuse.py` script") + + +def efuse_burn_key(idf_path: str, idf_target: str, port: str, + efuse_key_file: str, efuse_key_id: int, + efuse_purpose: str): + """ + Burns a key to the efuse using the "espefuse.py" script. + + Args: + idf_path (str): Path to the ESP-IDF directory. + idf_target (str): Target chip of the ESP-IDF build. + port (str): Serial port to use. + efuse_key_file (str): Path to the key file. + efuse_key_id (int): The eFuse key id to use for burning the key. + efuse_purpose (str): The purpose to be set for the eFuse key block + + Raises: + FileNotFoundError: If the key file cannot be found or read. + """ + # In case of a development (default) usecase + # we dont enable the read protection. + key_block_status = '--no-read-protect' + + print('WARNING:Efuse key block shall not be read ' + 'protected in development mode (default)\n') + + if not os.path.isfile(efuse_key_file): + raise FileNotFoundError(f"Key file not found: {efuse_key_file}") + try: + op = os.system(f'python {idf_path}/components/esptool_py/esptool/' + f'espefuse.py --chip {idf_target} -p {port} burn_key ' + f'BLOCK_KEY{efuse_key_id} {efuse_key_file} ' + f'{efuse_purpose} {key_block_status}') + except OSError: + print('Failed to burn the eFuse key') + raise + + if (op != 0): + raise RuntimeError('Failed to burn efuse key') + + +def configure_efuse_key_block(idf_path: str, idf_target: str, port: str, + efuse_key_file: str, efuse_key_id: int, + efuse_purpose: str) -> Union[bytes, None]: + """ + Configures the provided efuse key_block. + + If the provided efuse key_block is empty the function burns the key + read from the keyfile into the efuse + If the key_block already contains a key the function reads + the key from the efuse key_block and returns the key read + + Args: + idf_path (str): Path to the ESP-IDF directory. + idf_target (str): Target chip of the ESP-IDF build. + port (str): Serial port to use. + efuse_key_file (str): Path to the key file. + efuse_key_id (int): The eFuse key id to use for burning the key. + efuse_purpose (str): The purpose to be set for the eFuse key block. + + Returns: + bytes: 256-bit key written in the given + key_block (efuse_key_id) if successful. + If key is already burned and is readable + then this API returns the same key + None: If the operation fails. + """ + efuse_summary_json = get_efuse_summary_json(idf_path, idf_target, port) + key_blk = 'BLOCK_KEY' + str(efuse_key_id) + key_purpose = 'KEY_PURPOSE_' + str(efuse_key_id) + + kb_writeable = efuse_summary_json[key_blk]['writeable'] + kb_readable = efuse_summary_json[key_blk]['readable'] + efuse_key_read = None + + # If the efuse key block is writable (empty) then generate and write + # the new efuse key and check again + # If the efuse key block is not writable (already contains a key) + # then check if it is readable + if kb_writeable is True: + print(f'Provided key block (KEY BLOCK {efuse_key_id}) is writable\n' + f'Generating a new key and burning it in the efuse..\n') + + if not os.path.exists(efuse_key_file): + raise FileNotFoundError('Key file not present') + + # Burn efuse key + efuse_burn_key(idf_path, idf_target, port, efuse_key_file, + efuse_key_id, efuse_purpose) + + new_efuse_summary_json = get_efuse_summary_json(idf_path, + idf_target, + port) + if (new_efuse_summary_json[key_purpose]['value'] + != efuse_purpose): + raise RuntimeError(f'ERROR: Failed to verify the key purpose ' + f'of the key block{efuse_key_id})') + else: + # If the efuse key block is readable, then read the key from + # efuse block and provide it as the return argument + # If the efuse key block is not readable or it has key + # purpose set to a different value than given efuse_purpose + # then we cannot use it for DS operation + if kb_readable is True: + if (efuse_summary_json[key_purpose]['value'] == + efuse_purpose): + efuse_key_read = efuse_summary_json[key_blk]['value'] + efuse_key_read = bytes.fromhex(efuse_key_read) + if (efuse_purpose == 'ECDSA_KEY'): + + # Convert hex value to bytes object + original_bytes = efuse_key_read + # Reverse the byte order from little endian to big endian + reversed_bytes = original_bytes[::-1] + reversed_hex_value = reversed_bytes.hex() + reversed_number = int(reversed_hex_value, 16) + key = load_private_key(efuse_key_file, None) + private_value = key["key_instance"].private_numbers().private_value # type: ignore # noqa: E501 + if (reversed_number != private_value): + raise RuntimeError('The private key given does not ' + 'match with the one burned in the ' + 'efuse, Please burn the key in a ' + 'different key block') + + print('Using the same ECDSA key burned ' + f'in the efuse {key_blk}') + + if (efuse_purpose == 'HMAC_DOWN_DIGITAL_SIGNATURE' + or efuse_purpose == 'HMAC_UP'): + + with open(efuse_key_file, 'wb') as hmac_key_file: + hmac_key_file.write(efuse_key_read) + + print('Using the same hmac key burned ' + f'in efuse {key_blk}') + + else: + print(f'ERROR: Provided efuse key block' + f'((KEY BLOCK {efuse_key_id})) ' + f'contains a key with key purpose different ' + f'than {efuse_purpose},' + f'\nplease execute the script again with ' + f'a different value of the efuse key id.') + raise RuntimeError('ERROR: key block already used') + else: + print(f'ERROR: Provided efuse key block (KEY BLOCK {efuse_key_id})' + f' is not readable and writeable,' + f'\nplease execute the script again ' + f'with a different value of the efuse key id.') + raise RuntimeError('ERROR: Key block already used') diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/tools/esp_secure_cert/esp_secure_cert_helper.py b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/tools/esp_secure_cert/esp_secure_cert_helper.py new file mode 100644 index 000000000..e30572932 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/tools/esp_secure_cert/esp_secure_cert_helper.py @@ -0,0 +1,126 @@ +from typing import Dict +from cryptography.hazmat.primitives import serialization +from cryptography.hazmat.backends import default_backend +from cryptography.x509 import ( + load_pem_x509_certificate, + load_der_x509_certificate +) + + +def load_private_key(key_file_path: str, + password: str = None) -> Dict[str, str]: + """ + Load a private key from a file in either PEM or DER format. + + Args: + key_file_path (str): Path to the private key file. + password (str): Password to decrypt the private key, + if it is encrypted. + Returns: + Dict[str, str]: A dictionary with the `"encoding"` and `"bytes"` keys. + The `"encoding"` key holds a value + of type `str` (a member of the `serialization.Encoding` enum) + and the `"bytes"` key holds a value of type `bytes`. + + Raises: + FileNotFoundError: If the private key file cannot be found or read. + ValueError: If the private key file is not in PEM or DER format. + + """ + result = {} + + try: + with open(key_file_path, "rb") as key_file: + key = key_file.read() + except FileNotFoundError: + raise FileNotFoundError(f"Key file not found: {key_file_path}") + + try: + # Attempt to load the key as a PEM-encoded private key + private_key = serialization.load_pem_private_key( + key, + password=password, + backend=default_backend()) + + result["encoding"] = serialization.Encoding.PEM.value + key_encoding = serialization.Encoding.PEM + key_enc_alg = serialization.NoEncryption() + priv_key_format = serialization.PrivateFormat.TraditionalOpenSSL + + result["bytes"] = private_key.private_bytes( + encoding=key_encoding, + format=priv_key_format, + encryption_algorithm=key_enc_alg + ) + result["key_instance"] = private_key + return result + except ValueError: + pass + + try: + private_key = serialization.load_der_private_key( + key, + password=password, + backend=default_backend() + ) + result["encoding"] = serialization.Encoding.DER.value + key_encoding = serialization.Encoding.DER + priv_key_format = serialization.PrivateFormat.TraditionalOpenSSL + key_enc_alg = serialization.NoEncryption() + result["bytes"] = private_key.private_bytes( + encoding=key_encoding, + format=priv_key_format, + encryption_algorithm=key_enc_alg + ) + result["key_instance"] = private_key + return result + except ValueError: + raise ValueError("Unsupported key encoding format," + " Please provide PEM or DER encoded key") + + +def load_certificate(cert_file_path: str) -> Dict[str, str]: + """ + Load a certificate from a file in either PEM or DER format. + + Args: + cert_file_path (str): The path to the certificate file. + + Returns: + Dict[str, str]: A dictionary with the `"encoding"` and `"bytes"` keys. + The `"encoding"` key holds a value of + type `str` (a member of the `serialization.Encoding enum) + and the `"bytes"` key holds a value of type `bytes`. + + Raises: + FileNotFoundError: If the certificate file cannot be found or read. + ValueError: If the certificate file is not in PEM or DER format. + """ + result = {} + + try: + with open(cert_file_path, "rb") as cert_file: + cert_data = cert_file.read() + except FileNotFoundError: + raise FileNotFoundError(f"Cert file not found: {cert_file_path}") + + try: + cert = load_pem_x509_certificate(cert_data, backend=default_backend()) + result["encoding"] = serialization.Encoding.PEM.value + cert_encoding = serialization.Encoding.PEM + result["bytes"] = cert.public_bytes(encoding=cert_encoding) + result["cert_instance"] = cert + return result + except ValueError: + pass + + try: + cert = load_der_x509_certificate(cert_data, backend=default_backend()) + result["encoding"] = serialization.Encoding.DER.value + cert_encoding = serialization.Encoding.DER + result["bytes"] = cert.public_bytes(encoding=cert_encoding) + result["cert_instance"] = cert + return result + except ValueError: + raise ValueError("Unsupported certificate encoding format," + "Please provide PEM or DER encoded certificate") diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/tools/esp_secure_cert/nvs_format.py b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/tools/esp_secure_cert/nvs_format.py new file mode 100644 index 000000000..0848e25da --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/tools/esp_secure_cert/nvs_format.py @@ -0,0 +1,84 @@ +import os +import sys + +idf_path = os.getenv('IDF_PATH') +try: + + import nvs_partition_gen as nvs_gen +except ImportError: + if not idf_path or not os.path.exists(idf_path): + raise Exception('IDF_PATH not found') + sys.path.insert(0, os.path.join(idf_path, 'components', + 'nvs_flash', 'nvs_partition_generator')) + import nvs_partition_gen as nvs_gen + + +# @info +# Generate a custom csv file of encrypted private key parameters +# when DS is enabled. +# The csv file is required by the nvs_partition_generator +# utility to create the nvs partition. +def generate_csv_file_ds(c, iv, hmac_key_id, key_size, + device_cert, ca_cert, csv_file): + + with open(csv_file, 'wt', encoding='utf8') as f: + f.write('# This is a generated csv file containing ' + 'required parameters for the Digital Signature operation\n') + f.write('key,type,encoding,value\nesp_secure_cert,namespace,,\n') + + if ca_cert is not None: + f.write('ca_cert,file,string,{}\n'.format(ca_cert)) + f.write('cipher_c,data,hex2bin,{}\n'.format(c.hex())) + f.write('dev_cert,file,string,{}\n'.format(device_cert)) + f.write('rsa_len,data,u16,{}\n'.format(key_size)) + f.write('ds_key_id,data,u8,{}\n'.format(hmac_key_id)) + f.write('iv,data,hex2bin,{}\n'.format(iv.hex())) + + +# @info +# Generate a custom csv file of encrypted private key parameters +# when DS is disabled. +# The csv file is required by the nvs_partition_generator utility +# to create the nvs partition. +def generate_csv_file_no_ds(device_cert, ca_cert, priv_key, + priv_key_pass, csv_file): + + with open(csv_file, 'wt', encoding='utf8') as f: + f.write('# This is a generated csv file containing required ' + 'parameters for the Digital Signature operation\n') + f.write('key,type,encoding,value\nesp_secure_cert,namespace,,\n') + + if ca_cert is not None: + f.write('ca_cert,file,string,{}\n'.format(ca_cert)) + f.write('dev_cert,file,string,{}\n'.format(device_cert)) + + if priv_key_pass is not None: + print('Private key is going to be written' + 'in password encrypted format.') + print('If you want to write ptivate key in plaintext,' + ' Please remove the password') + + f.write('priv_key,file,string,{}\n'.format(priv_key)) + + +class DefineArgs(object): + def __init__(self, attributes): + for key, value in attributes.items(): + self.__setattr__(key, value) + + +# @info +# This function uses the nvs_partition_generater utility +# to generate the nvs partition of the encrypted private key parameters. +def generate_partition(input_filename, output_filename): + + nvs_args = DefineArgs({ + 'input': input_filename, + 'outdir': os.getcwd(), + 'output': output_filename, + 'size': hex(0x3000), + 'version': 2, + 'keyfile': None, + }) + + nvs_gen.generate(nvs_args, is_encr_enabled=False, encr_key=None) diff --git a/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/tools/esp_secure_cert/tlv_format.py b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/tools/esp_secure_cert/tlv_format.py new file mode 100644 index 000000000..c7e2cc537 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__esp_secure_cert_mgr/tools/esp_secure_cert/tlv_format.py @@ -0,0 +1,367 @@ +import enum +import struct +import zlib +from esp_secure_cert.esp_secure_cert_helper import ( + load_private_key, + load_certificate +) +from cryptography.hazmat.primitives import serialization + + +class tlv_type_t(enum.IntEnum): + CA_CERT = 0 + DEV_CERT = 1 + PRIV_KEY = 2 + DS_DATA = 3 + DS_CONTEXT = 4 + ECDSA_KEY_SALT = 5 + SEC_CFG = 6 + TLV_END = 50 + USER_DATA_1 = 51 + USER_DATA_2 = 52 + USER_DATA_3 = 53 + USER_DATA_4 = 54 + USER_DATA_5 = 55 + + +class tlv_priv_key_type_t(enum.IntEnum): + ESP_SECURE_CERT_INVALID_KEY = -1 + ESP_SECURE_CERT_DEFAULT_FORMAT_KEY = 0 + ESP_SECURE_CERT_HMAC_ENCRYPTED_KEY = 1 + ESP_SECURE_CERT_HMAC_DERIVED_ECDSA_KEY = 2 + ESP_SECURE_CERT_ECDSA_PERIPHERAL_KEY = 3 + ESP_SECURE_CERT_RSA_DS_PERIPHERAL_KEY = 4 + + +class tlv_priv_key_t: + def __init__(self, key_type: tlv_priv_key_type_t, + key_path, key_pass): + self.key_type = key_type + self.key_path = key_path + self.key_pass = key_pass + self.efuse_key_id = -1 + self.salt = None + self.ciphertext = None + self.iv = None + self.priv_key_len = 0 + self.priv_key_format = None + + +# This is the minimum required flash address alignment to write +# to an encrypted partition on esp device +MIN_ALIGNMENT_REQUIRED = 16 + + +def _get_tlv_header_key_info_byte(key_type): + ''' + Set Nth bit to one in the given number + @input + flags Input Number + N The number of bit to be set to 1 + ''' + def _set_bit(flags, N): + return flags | (1 << N) + flags = 0 + if key_type == tlv_priv_key_type_t.ESP_SECURE_CERT_HMAC_ENCRYPTED_KEY: + flags = _set_bit(flags, 7) # i.e. 2 << 6 + + if key_type == tlv_priv_key_type_t.ESP_SECURE_CERT_HMAC_DERIVED_ECDSA_KEY: + flags = _set_bit(flags, 6) + + if key_type == tlv_priv_key_type_t.ESP_SECURE_CERT_ECDSA_PERIPHERAL_KEY: + flags = _set_bit(flags, 3) + + return hex(flags) + + +def prepare_tlv(tlv_type, tlv_type_info, data, data_len): + # Add the magic at start ( unsigned int ) + tlv_header = struct.pack('`_. + +Documentation +------------- +Visit online `esp-secure-cert-tool +documentation `_ \ +or run ``configure_esp_secure_cert.py -h``. + +License +------- +The License for the project can be found +`here `_ +""" + +setup( + name="esp-secure-cert-tool", + version=VERSION, + description="A python utility which helps to configure and provision" + "the ESP platform with PKI credentials " + "into the esp_secure_cert partition", + long_description=long_description, + long_description_content_type='text/x-rst', + url="https://github.com/espressif/" + "esp_secure_cert_mgr/blob/main/tools", + project_urls={ + "Documentation": "https://github.com/espressif/" + "esp_secure_cert_mgr/blob/main/tools/README.md", + "Source": "https://github.com/espressif/esp_secure_cert_mgr/" + "blob/main/tools/configure_esp_secure_cert.py", + }, + author="Espressif Systems", + author_email="", + license="Apache-2.0", + classifiers=[ + "License :: OSI Approved :: Apache Software License", + "Intended Audience :: Developers", + "Natural Language :: English", + "Operating System :: POSIX", + "Operating System :: Microsoft :: Windows", + "Operating System :: MacOS :: MacOS X", + "Topic :: Software Development :: Embedded Systems", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + ], + python_requires=">=3.7", + setup_requires=(["wheel"] if "bdist_wheel" in sys.argv else []), + install_requires=get_install_requires(), + include_package_data=True, + packages=find_packages(), + scripts=["configure_esp_secure_cert.py"], +) diff --git a/RainMaker_Table-Lights/managed_components/espressif__jsmn/.component_hash b/RainMaker_Table-Lights/managed_components/espressif__jsmn/.component_hash new file mode 100644 index 000000000..b234a4e6c --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__jsmn/.component_hash @@ -0,0 +1 @@ +d80350c41bbaa827c98a25b6072df00884e72f54885996fab4a4f0aebce6b6c3 \ No newline at end of file diff --git a/RainMaker_Table-Lights/managed_components/espressif__jsmn/CHECKSUMS.json b/RainMaker_Table-Lights/managed_components/espressif__jsmn/CHECKSUMS.json new file mode 100644 index 000000000..efb712a57 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__jsmn/CHECKSUMS.json @@ -0,0 +1 @@ +{"version": "1.0", "algorithm": "sha256", "created_at": "2025-05-21T16:08:22.519386+00:00", "files": [{"path": "CMakeLists.txt", "size": 380, "hash": "a67113d269258748c2c2c68993df5ab5d1e9d30f7492b93071caed2f66acd247"}, {"path": "LICENSE", "size": 1079, "hash": "258fff48e1ca3fd8d1888ae616c7e97d8b526db6138df4564c7cfa1235c50715"}, {"path": "idf_component.yml", "size": 180, "hash": "4845de197c1d4f565bca06260ed380f67f14b33705c19fbc844efce52eef81ea"}, {"path": "Kconfig", "size": 483, "hash": "1808eb58d6adf231308fb41ed4e2613a45917ddfafec938c6998b2d8dbea7e13"}, {"path": "README.md", "size": 5910, "hash": "adaa92e7dc619f9f12c76856d9bfe15d0ad27888f95c37e321bf1d856937b612"}, {"path": "include/jsmn.h", "size": 14274, "hash": "573e9f4816ad53c4ed81b36976f060584407dcd56720a45b53609457f2d5cbc5"}]} \ No newline at end of file diff --git a/RainMaker_Table-Lights/managed_components/espressif__jsmn/CMakeLists.txt b/RainMaker_Table-Lights/managed_components/espressif__jsmn/CMakeLists.txt new file mode 100644 index 000000000..8330616b3 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__jsmn/CMakeLists.txt @@ -0,0 +1,13 @@ +idf_component_register(INCLUDE_DIRS "include") + +if(CONFIG_JSMN_PARENT_LINKS) + target_compile_definitions(${COMPONENT_LIB} INTERFACE "-DJSMN_PARENT_LINKS") +endif() + +if(CONFIG_JSMN_STRICT) + target_compile_definitions(${COMPONENT_LIB} INTERFACE "-DJSMN_STRICT") +endif() + +if(CONFIG_JSMN_STATIC) + target_compile_definitions(${COMPONENT_LIB} INTERFACE "-DJSMN_STATIC") +endif() diff --git a/RainMaker_Table-Lights/managed_components/espressif__jsmn/Kconfig b/RainMaker_Table-Lights/managed_components/espressif__jsmn/Kconfig new file mode 100644 index 000000000..2face4c36 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__jsmn/Kconfig @@ -0,0 +1,22 @@ +menu "jsmn" + + + config JSMN_PARENT_LINKS + bool "Enable parent links" + default n + help + You can access parent node of parsed json + + config JSMN_STRICT + bool "Enable strict mode" + default n + help + In strict mode primitives are: numbers and booleans + + config JSMN_STATIC + bool "Declare JSMN API as static" + default node + help + Declar JSMN API as static (instead of extern) + +endmenu diff --git a/RainMaker_Table-Lights/managed_components/espressif__jsmn/LICENSE b/RainMaker_Table-Lights/managed_components/espressif__jsmn/LICENSE new file mode 100644 index 000000000..19ea8424d --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__jsmn/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2010 Serge A. Zaitsev + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/RainMaker_Table-Lights/managed_components/espressif__jsmn/README.md b/RainMaker_Table-Lights/managed_components/espressif__jsmn/README.md new file mode 100644 index 000000000..e94679775 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__jsmn/README.md @@ -0,0 +1,182 @@ +JSMN +==== + +[![Build Status](https://travis-ci.org/zserge/jsmn.svg?branch=master)](https://travis-ci.org/zserge/jsmn) + +jsmn (pronounced like 'jasmine') is a minimalistic JSON parser in C. It can be +easily integrated into resource-limited or embedded projects. + +You can find more information about JSON format at [json.org][1] + +Library sources are available at https://github.com/zserge/jsmn + +The web page with some information about jsmn can be found at +[http://zserge.com/jsmn.html][2] + +Philosophy +---------- + +Most JSON parsers offer you a bunch of functions to load JSON data, parse it +and extract any value by its name. jsmn proves that checking the correctness of +every JSON packet or allocating temporary objects to store parsed JSON fields +often is an overkill. + +JSON format itself is extremely simple, so why should we complicate it? + +jsmn is designed to be **robust** (it should work fine even with erroneous +data), **fast** (it should parse data on the fly), **portable** (no superfluous +dependencies or non-standard C extensions). And of course, **simplicity** is a +key feature - simple code style, simple algorithm, simple integration into +other projects. + +Features +-------- + +* compatible with C89 +* no dependencies (even libc!) +* highly portable (tested on x86/amd64, ARM, AVR) +* about 200 lines of code +* extremely small code footprint +* API contains only 2 functions +* no dynamic memory allocation +* incremental single-pass parsing +* library code is covered with unit-tests + +Design +------ + +The rudimentary jsmn object is a **token**. Let's consider a JSON string: + + '{ "name" : "Jack", "age" : 27 }' + +It holds the following tokens: + +* Object: `{ "name" : "Jack", "age" : 27}` (the whole object) +* Strings: `"name"`, `"Jack"`, `"age"` (keys and some values) +* Number: `27` + +In jsmn, tokens do not hold any data, but point to token boundaries in JSON +string instead. In the example above jsmn will create tokens like: Object +[0..31], String [3..7], String [12..16], String [20..23], Number [27..29]. + +Every jsmn token has a type, which indicates the type of corresponding JSON +token. jsmn supports the following token types: + +* Object - a container of key-value pairs, e.g.: + `{ "foo":"bar", "x":0.3 }` +* Array - a sequence of values, e.g.: + `[ 1, 2, 3 ]` +* String - a quoted sequence of chars, e.g.: `"foo"` +* Primitive - a number, a boolean (`true`, `false`) or `null` + +Besides start/end positions, jsmn tokens for complex types (like arrays +or objects) also contain a number of child items, so you can easily follow +object hierarchy. + +This approach provides enough information for parsing any JSON data and makes +it possible to use zero-copy techniques. + +Usage +----- + +Download `jsmn.h`, include it, done. + +``` +#include "jsmn.h" + +... +jsmn_parser p; +jsmntok_t t[128]; /* We expect no more than 128 JSON tokens */ + +jsmn_init(&p); +r = jsmn_parse(&p, s, strlen(s), t, 128); // "s" is the char array holding the json content +``` + +Since jsmn is a single-header, header-only library, for more complex use cases +you might need to define additional macros. `#define JSMN_STATIC` hides all +jsmn API symbols by making them static. Also, if you want to include `jsmn.h` +from multiple C files, to avoid duplication of symbols you may define `JSMN_HEADER` macro. + +``` +/* In every .c file that uses jsmn include only declarations: */ +#define JSMN_HEADER +#include "jsmn.h" + +/* Additionally, create one jsmn.c file for jsmn implementation: */ +#include "jsmn.h" +``` + +API +--- + +Token types are described by `jsmntype_t`: + + typedef enum { + JSMN_UNDEFINED = 0, + JSMN_OBJECT = 1 << 0, + JSMN_ARRAY = 1 << 1, + JSMN_STRING = 1 << 2, + JSMN_PRIMITIVE = 1 << 3 + } jsmntype_t; + +**Note:** Unlike JSON data types, primitive tokens are not divided into +numbers, booleans and null, because one can easily tell the type using the +first character: + +* 't', 'f' - boolean +* 'n' - null +* '-', '0'..'9' - number + +Token is an object of `jsmntok_t` type: + + typedef struct { + jsmntype_t type; // Token type + int start; // Token start position + int end; // Token end position + int size; // Number of child (nested) tokens + } jsmntok_t; + +**Note:** string tokens point to the first character after +the opening quote and the previous symbol before final quote. This was made +to simplify string extraction from JSON data. + +All job is done by `jsmn_parser` object. You can initialize a new parser using: + + jsmn_parser parser; + jsmntok_t tokens[10]; + + jsmn_init(&parser); + + // js - pointer to JSON string + // tokens - an array of tokens available + // 10 - number of tokens available + jsmn_parse(&parser, js, strlen(js), tokens, 10); + +This will create a parser, and then it tries to parse up to 10 JSON tokens from +the `js` string. + +A non-negative return value of `jsmn_parse` is the number of tokens actually +used by the parser. +Passing NULL instead of the tokens array would not store parsing results, but +instead the function will return the number of tokens needed to parse the given +string. This can be useful if you don't know yet how many tokens to allocate. + +If something goes wrong, you will get an error. Error will be one of these: + +* `JSMN_ERROR_INVAL` - bad token, JSON string is corrupted +* `JSMN_ERROR_NOMEM` - not enough tokens, JSON string is too large +* `JSMN_ERROR_PART` - JSON string is too short, expecting more JSON data + +If you get `JSMN_ERROR_NOMEM`, you can re-allocate more tokens and call +`jsmn_parse` once more. If you read json data from the stream, you can +periodically call `jsmn_parse` and check if return value is `JSMN_ERROR_PART`. +You will get this error until you reach the end of JSON data. + +Other info +---------- + +This software is distributed under [MIT license](http://www.opensource.org/licenses/mit-license.php), + so feel free to integrate it in your commercial products. + +[1]: http://www.json.org/ +[2]: http://zserge.com/jsmn.html diff --git a/RainMaker_Table-Lights/managed_components/espressif__jsmn/idf_component.yml b/RainMaker_Table-Lights/managed_components/espressif__jsmn/idf_component.yml new file mode 100644 index 000000000..ec14a347a --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__jsmn/idf_component.yml @@ -0,0 +1,6 @@ +dependencies: + idf: + version: '>=4.3' +description: 'JSMN: minimalistic JSON parser in C' +url: https://github.com/espressif/idf-extra-components/tree/master/jsmn +version: 1.1.0 diff --git a/RainMaker_Table-Lights/managed_components/espressif__jsmn/include/jsmn.h b/RainMaker_Table-Lights/managed_components/espressif__jsmn/include/jsmn.h new file mode 100644 index 000000000..31fb55fcf --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__jsmn/include/jsmn.h @@ -0,0 +1,477 @@ +/* + * MIT License + * + * Copyright (c) 2010 Serge Zaitsev + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#ifndef JSMN_H +#define JSMN_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef JSMN_STATIC +#define JSMN_API static +#else +#define JSMN_API extern +#endif + +/** + * JSON type identifier. Basic types are: + * o Object + * o Array + * o String + * o Other primitive: number, boolean (true/false) or null + */ +typedef enum { + JSMN_UNDEFINED = 0, + JSMN_OBJECT = 1 << 0, + JSMN_ARRAY = 1 << 1, + JSMN_STRING = 1 << 2, + JSMN_PRIMITIVE = 1 << 3 +} jsmntype_t; + +enum jsmnerr { + /* Not enough tokens were provided */ + JSMN_ERROR_NOMEM = -1, + /* Invalid character inside JSON string */ + JSMN_ERROR_INVAL = -2, + /* The string is not a full JSON packet, more bytes expected */ + JSMN_ERROR_PART = -3 +}; + +/** + * JSON token description. + * type type (object, array, string etc.) + * start start position in JSON data string + * end end position in JSON data string + */ +typedef struct jsmntok { + jsmntype_t type; + int start; + int end; + int size; +#ifdef JSMN_PARENT_LINKS + int parent; +#endif +} jsmntok_t; + +/** + * JSON parser. Contains an array of token blocks available. Also stores + * the string being parsed now and current position in that string. + */ +typedef struct jsmn_parser { + unsigned int pos; /* offset in the JSON string */ + unsigned int toknext; /* next token to allocate */ + int toksuper; /* superior token node, e.g. parent object or array */ +} jsmn_parser; + +/** + * Create JSON parser over an array of tokens + */ +JSMN_API void jsmn_init(jsmn_parser *parser); + +/** + * Run JSON parser. It parses a JSON data string into and array of tokens, each + * describing + * a single JSON object. + */ +JSMN_API int jsmn_parse(jsmn_parser *parser, const char *js, const size_t len, + jsmntok_t *tokens, const unsigned int num_tokens); + +#ifndef JSMN_HEADER +/** + * Allocates a fresh unused token from the token pool. + */ +static jsmntok_t *jsmn_alloc_token(jsmn_parser *parser, jsmntok_t *tokens, + const size_t num_tokens) +{ + jsmntok_t *tok; + if (parser->toknext >= num_tokens) { + return NULL; + } + tok = &tokens[parser->toknext++]; + tok->start = tok->end = -1; + tok->size = 0; +#ifdef JSMN_PARENT_LINKS + tok->parent = -1; +#endif + return tok; +} + +/** + * Fills token type and boundaries. + */ +static void jsmn_fill_token(jsmntok_t *token, const jsmntype_t type, + const int start, const int end) +{ + token->type = type; + token->start = start; + token->end = end; + token->size = 0; +} + +/** + * Fills next available token with JSON primitive. + */ +static int jsmn_parse_primitive(jsmn_parser *parser, const char *js, + const size_t len, jsmntok_t *tokens, + const size_t num_tokens) +{ + jsmntok_t *token; + int start; + + start = parser->pos; + + for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { + switch (js[parser->pos]) { +#ifndef JSMN_STRICT + /* In strict mode primitive must be followed by "," or "}" or "]" */ + case ':': +#endif + case '\t': + case '\r': + case '\n': + case ' ': + case ',': + case ']': + case '}': + goto found; + default: + /* to quiet a warning from gcc*/ + break; + } + if (js[parser->pos] < 32 || js[parser->pos] >= 127) { + parser->pos = start; + return JSMN_ERROR_INVAL; + } + } +#ifdef JSMN_STRICT + /* In strict mode primitive must be followed by a comma/object/array */ + parser->pos = start; + return JSMN_ERROR_PART; +#endif + +found: + if (tokens == NULL) { + parser->pos--; + return 0; + } + token = jsmn_alloc_token(parser, tokens, num_tokens); + if (token == NULL) { + parser->pos = start; + return JSMN_ERROR_NOMEM; + } + jsmn_fill_token(token, JSMN_PRIMITIVE, start, parser->pos); +#ifdef JSMN_PARENT_LINKS + token->parent = parser->toksuper; +#endif + parser->pos--; + return 0; +} + +/** + * Fills next token with JSON string. + */ +static int jsmn_parse_string(jsmn_parser *parser, const char *js, + const size_t len, jsmntok_t *tokens, + const size_t num_tokens) +{ + jsmntok_t *token; + + int start = parser->pos; + + /* Skip starting quote */ + parser->pos++; + + for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { + char c = js[parser->pos]; + + /* Quote: end of string */ + if (c == '\"') { + if (tokens == NULL) { + return 0; + } + token = jsmn_alloc_token(parser, tokens, num_tokens); + if (token == NULL) { + parser->pos = start; + return JSMN_ERROR_NOMEM; + } + jsmn_fill_token(token, JSMN_STRING, start + 1, parser->pos); +#ifdef JSMN_PARENT_LINKS + token->parent = parser->toksuper; +#endif + return 0; + } + + /* Backslash: Quoted symbol expected */ + if (c == '\\' && parser->pos + 1 < len) { + int i; + parser->pos++; + switch (js[parser->pos]) { + /* Allowed escaped symbols */ + case '\"': + case '/': + case '\\': + case 'b': + case 'f': + case 'r': + case 'n': + case 't': + break; + /* Allows escaped symbol \uXXXX */ + case 'u': + parser->pos++; + for (i = 0; i < 4 && parser->pos < len && js[parser->pos] != '\0'; + i++) { + /* If it isn't a hex character we have an error */ + if (!((js[parser->pos] >= 48 && js[parser->pos] <= 57) || /* 0-9 */ + (js[parser->pos] >= 65 && js[parser->pos] <= 70) || /* A-F */ + (js[parser->pos] >= 97 && js[parser->pos] <= 102))) { /* a-f */ + parser->pos = start; + return JSMN_ERROR_INVAL; + } + parser->pos++; + } + parser->pos--; + break; + /* Unexpected symbol */ + default: + parser->pos = start; + return JSMN_ERROR_INVAL; + } + } + } + parser->pos = start; + return JSMN_ERROR_PART; +} + +/** + * Parse JSON string and fill tokens. + */ +JSMN_API int jsmn_parse(jsmn_parser *parser, const char *js, const size_t len, + jsmntok_t *tokens, const unsigned int num_tokens) +{ + int r; + int i; + jsmntok_t *token; + int count = parser->toknext; + + for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { + char c; + jsmntype_t type; + + c = js[parser->pos]; + switch (c) { + case '{': + case '[': + count++; + if (tokens == NULL) { + break; + } + token = jsmn_alloc_token(parser, tokens, num_tokens); + if (token == NULL) { + return JSMN_ERROR_NOMEM; + } + if (parser->toksuper != -1) { + jsmntok_t *t = &tokens[parser->toksuper]; +#ifdef JSMN_STRICT + /* In strict mode an object or array can't become a key */ + if (t->type == JSMN_OBJECT) { + return JSMN_ERROR_INVAL; + } +#endif + t->size++; +#ifdef JSMN_PARENT_LINKS + token->parent = parser->toksuper; +#endif + } + token->type = (c == '{' ? JSMN_OBJECT : JSMN_ARRAY); + token->start = parser->pos; + parser->toksuper = parser->toknext - 1; + break; + case '}': + case ']': + if (tokens == NULL) { + break; + } + type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY); +#ifdef JSMN_PARENT_LINKS + if (parser->toknext < 1) { + return JSMN_ERROR_INVAL; + } + token = &tokens[parser->toknext - 1]; + for (;;) { + if (token->start != -1 && token->end == -1) { + if (token->type != type) { + return JSMN_ERROR_INVAL; + } + token->end = parser->pos + 1; + parser->toksuper = token->parent; + break; + } + if (token->parent == -1) { + if (token->type != type || parser->toksuper == -1) { + return JSMN_ERROR_INVAL; + } + break; + } + token = &tokens[token->parent]; + } +#else + for (i = parser->toknext - 1; i >= 0; i--) { + token = &tokens[i]; + if (token->start != -1 && token->end == -1) { + if (token->type != type) { + return JSMN_ERROR_INVAL; + } + parser->toksuper = -1; + token->end = parser->pos + 1; + break; + } + } + /* Error if unmatched closing bracket */ + if (i == -1) { + return JSMN_ERROR_INVAL; + } + for (; i >= 0; i--) { + token = &tokens[i]; + if (token->start != -1 && token->end == -1) { + parser->toksuper = i; + break; + } + } +#endif + break; + case '\"': + r = jsmn_parse_string(parser, js, len, tokens, num_tokens); + if (r < 0) { + return r; + } + count++; + if (parser->toksuper != -1 && tokens != NULL) { + tokens[parser->toksuper].size++; + } + break; + case '\t': + case '\r': + case '\n': + case ' ': + break; + case ':': + parser->toksuper = parser->toknext - 1; + break; + case ',': + if (tokens != NULL && parser->toksuper != -1 && + tokens[parser->toksuper].type != JSMN_ARRAY && + tokens[parser->toksuper].type != JSMN_OBJECT) { +#ifdef JSMN_PARENT_LINKS + parser->toksuper = tokens[parser->toksuper].parent; +#else + for (i = parser->toknext - 1; i >= 0; i--) { + if (tokens[i].type == JSMN_ARRAY || tokens[i].type == JSMN_OBJECT) { + if (tokens[i].start != -1 && tokens[i].end == -1) { + parser->toksuper = i; + break; + } + } + } +#endif + } + break; +#ifdef JSMN_STRICT + /* In strict mode primitives are: numbers and booleans */ + case '-': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case 't': + case 'f': + case 'n': + /* And they must not be keys of the object */ + if (tokens != NULL && parser->toksuper != -1) { + const jsmntok_t *t = &tokens[parser->toksuper]; + if (t->type == JSMN_OBJECT || + (t->type == JSMN_STRING && t->size != 0)) { + return JSMN_ERROR_INVAL; + } + } +#else + /* In non-strict mode every unquoted value is a primitive */ + default: +#endif + r = jsmn_parse_primitive(parser, js, len, tokens, num_tokens); + if (r < 0) { + return r; + } + count++; + if (parser->toksuper != -1 && tokens != NULL) { + tokens[parser->toksuper].size++; + } + break; + +#ifdef JSMN_STRICT + /* Unexpected char in strict mode */ + default: + return JSMN_ERROR_INVAL; +#endif + } + } + + if (tokens != NULL) { + for (i = parser->toknext - 1; i >= 0; i--) { + /* Unmatched opened object or array */ + if (tokens[i].start != -1 && tokens[i].end == -1) { + return JSMN_ERROR_PART; + } + } + } + + return count; +} + +/** + * Creates a new parser based over a given buffer with an array of tokens + * available. + */ +JSMN_API void jsmn_init(jsmn_parser *parser) +{ + parser->pos = 0; + parser->toknext = 0; + parser->toksuper = -1; +} + +#endif /* JSMN_HEADER */ + +#ifdef __cplusplus +} +#endif + +#endif /* JSMN_H */ diff --git a/RainMaker_Table-Lights/managed_components/espressif__json_generator/.component_hash b/RainMaker_Table-Lights/managed_components/espressif__json_generator/.component_hash new file mode 100644 index 000000000..7cf9bd8ae --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__json_generator/.component_hash @@ -0,0 +1 @@ +45033e1c199b13f1c8c1b544fb7d4e2df6a8e3071ebdcb1b22582b61a7974ff2 \ No newline at end of file diff --git a/RainMaker_Table-Lights/managed_components/espressif__json_generator/CHECKSUMS.json b/RainMaker_Table-Lights/managed_components/espressif__json_generator/CHECKSUMS.json new file mode 100644 index 000000000..a7c06cb6b --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__json_generator/CHECKSUMS.json @@ -0,0 +1 @@ +{"version": "1.0", "algorithm": "sha256", "created_at": "2025-05-21T17:24:51.660471+00:00", "files": [{"path": "CMakeLists.txt", "size": 116, "hash": "8aa92a9c4911668e5810e8f499308853511b421a9d4884e924d61b9790bf8827"}, {"path": "LICENSE", "size": 11365, "hash": "f0f612d1627194ddd07c8b5b238a514ae9794632e5470c00f16237def7dc2246"}, {"path": "idf_component.yml", "size": 156, "hash": "10d500bd28799dbff553c78860f942434a136d3201cce5f276e67dfef9029162"}, {"path": "README.md", "size": 844, "hash": "44641e2bc59e94cc3ea263e06d4adb07f0d0bee407acb7648348685470529ced"}, {"path": "include/json_generator.h", "size": 18979, "hash": "9e3c8daac5215a836b2f1cf9783226398faa389f24beedc0ca4ba1df7cfb7c1e"}, {"path": "src/json_generator.c", "size": 8326, "hash": "bbaacf1ee1cb431ad0d625c151a234857170bde0f8867edb88c7217e1e85e6d3"}]} \ No newline at end of file diff --git a/RainMaker_Table-Lights/managed_components/espressif__json_generator/CMakeLists.txt b/RainMaker_Table-Lights/managed_components/espressif__json_generator/CMakeLists.txt new file mode 100644 index 000000000..6fdfa9825 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__json_generator/CMakeLists.txt @@ -0,0 +1,3 @@ +idf_component_register(SRCS "src/json_generator.c" + INCLUDE_DIRS "include" + ) diff --git a/RainMaker_Table-Lights/managed_components/espressif__json_generator/LICENSE b/RainMaker_Table-Lights/managed_components/espressif__json_generator/LICENSE new file mode 100644 index 000000000..d613ddc8f --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__json_generator/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2020 Piyush Shah + + 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. diff --git a/RainMaker_Table-Lights/managed_components/espressif__json_generator/README.md b/RainMaker_Table-Lights/managed_components/espressif__json_generator/README.md new file mode 100644 index 000000000..957a2ef27 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__json_generator/README.md @@ -0,0 +1,16 @@ +# JSON Generator + +[![Component Registry](https://components.espressif.com/components/espressif/json_generator/badge.svg)](https://components.espressif.com/components/espressif/json_generator) + +A simple JSON (JavasScript Object Notation) generator with flushing capability. +Details of JSON can be found at [http://www.json.org/](http://www.json.org/). +The JSON strings generated can be validated using any standard JSON validator. Eg. [https://jsonlint.com/](https://jsonlint.com/) + +# Files +- `src/json_generator.c`: Actual source file for the JSON generator with implementation of all APIS +- `include/json_generator.h`: Header file documenting and exposing all available APIs + +# Usage + +Include the C and H files in your project's build system and that should be enough. +`json_generator` requires only standard library functions for compilation diff --git a/RainMaker_Table-Lights/managed_components/espressif__json_generator/idf_component.yml b/RainMaker_Table-Lights/managed_components/espressif__json_generator/idf_component.yml new file mode 100644 index 000000000..738de78f9 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__json_generator/idf_component.yml @@ -0,0 +1,3 @@ +description: A simple JSON (JavasScript Object Notation) generator with flushing capability +url: https://github.com/espressif/json_generator +version: 1.1.2 diff --git a/RainMaker_Table-Lights/managed_components/espressif__json_generator/include/json_generator.h b/RainMaker_Table-Lights/managed_components/espressif__json_generator/include/json_generator.h new file mode 100644 index 000000000..873c890a4 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__json_generator/include/json_generator.h @@ -0,0 +1,511 @@ +/* + * Copyright 2020 Piyush Shah + * + * 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. + */ + +/* + * JSON String Generator + * + * This module can be used to create JSON strings with a facility + * to flush out data if the destination buffer is full. All commas + * and colons as required are automatically added by the APIs + * + */ +#ifndef _JSON_GENERATOR_H +#define _JSON_GENERATOR_H + +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** Float precision i.e. number of digits after decimal point */ +#ifndef JSON_FLOAT_PRECISION +#define JSON_FLOAT_PRECISION 5 +#endif + +/** JSON string flush callback prototype + * + * This is a prototype of the function that needs to be passed to + * json_gen_str_start() and which will be invoked by the JSON generator + * module either when the buffer is full or json_gen_str_end() ins invoked. + * + * \param[in] buf Pointer to a NULL terminated JSON string + * \param[in] priv Private data to be passed to the flush callback. Will + * be the same as the one passed to json_gen_str_start() + */ +typedef void (*json_gen_flush_cb_t) (char *buf, void *priv); + +/** JSON String structure + * + * Please do not set/modify any elements. + * Just define this structure and pass a pointer to it in the APIs below + */ +typedef struct { + /** Pointer to the JSON buffer provided by the calling function */ + char *buf; + /** Size of the above buffer */ + int buf_size; + /** (Optional) callback function to invoke when the buffer gets full */ + json_gen_flush_cb_t flush_cb; + /** (Optional) Private data to pass to the callback function */ + void *priv; + /** (For Internal use only) */ + bool comma_req; + /** (For Internal use only) */ + char *free_ptr; + /** Total length */ + int total_len; +} json_gen_str_t; + +/** Start a JSON String + * + * This is the first function to be called for creating a JSON string. + * It initializes the internal data structures. After the JSON string + * generation is over, the json_gen_str_end() function should be called. + * + * \param[out] jstr Pointer to an allocated \ref json_gen_str_t structure. + * This will be initialised internally and needs to be passed to all + * subsequent function calls + * \param[out] buf Pointer to an allocated buffer into which the JSON + * string will be written + * \param[in] buf_size Size of the buffer + * \param[in] flush_cb Pointer to the flushing function of type \ref json_gen_flush_cb_t + * which will be invoked either when the buffer is full or when json_gen_str_end() + * is invoked. Can be left NULL. + * \param[in] priv Private data to be passed to the flushing function callback. + * Can be something like a session identifier (Eg. socket). Can be left NULL. + */ +void json_gen_str_start(json_gen_str_t *jstr, char *buf, int buf_size, + json_gen_flush_cb_t flush_cb, void *priv); + +/** End JSON string + * + * This should be the last function to be called after the entire JSON string + * has been generated. + * + * \param[in] jstr Pointer to the \ref json_gen_str_t structure initialised by + * json_gen_str_start() + * + * \return Total length of the JSON created, including the NULL termination byte. + */ +int json_gen_str_end(json_gen_str_t *jstr); + +/** Start a JSON object + * + * This starts a JSON object by adding a '{' + * + * \param[in] jstr Pointer to the \ref json_gen_str_t structure initialised by + * json_gen_str_start() + * + * \return 0 on Success + * \return -1 if buffer is out of space (possible only if no callback function + * is passed to json_gen_str_start(). Else, buffer will be flushed out and new data + * added after that + */ +int json_gen_start_object(json_gen_str_t *jstr); + +/** End a JSON object + * + * This ends a JSON object by adding a '}' + * + * \param[in] jstr Pointer to the \ref json_gen_str_t structure initialised by + * json_gen_str_start() + * + * \return 0 on Success + * \return -1 if buffer is out of space (possible only if no callback function + * is passed to json_gen_str_start(). Else, buffer will be flushed out and new data + * added after that + */ +int json_gen_end_object(json_gen_str_t *jstr); + +/** Start a JSON array + * + * This starts a JSON object by adding a '[' + * + * \param[in] jstr Pointer to the \ref json_gen_str_t structure initialised by + * json_gen_str_start() + * + * \return 0 on Success + * \return -1 if buffer is out of space (possible only if no callback function + * is passed to json_gen_str_start(). Else, buffer will be flushed out and new data + * added after that + */ +int json_gen_start_array(json_gen_str_t *jstr); + +/** End a JSON object + * + * This ends a JSON object by adding a ']' + * + * \param[in] jstr Pointer to the \ref json_gen_str_t structure initialised by + * json_gen_str_start() + * + * \return 0 on Success + * \return -1 if buffer is out of space (possible only if no callback function + * is passed to json_gen_str_start(). Else, buffer will be flushed out and new data + * added after that + */ +int json_gen_end_array(json_gen_str_t *jstr); + +/** Push a named JSON object + * + * This adds a JSON object like "name":{ + * + * \param[in] jstr Pointer to the \ref json_gen_str_t structure initialised by + * json_gen_str_start() + * \param[in] name Name of the object + * + * \return 0 on Success + * \return -1 if buffer is out of space (possible only if no callback function + * is passed to json_gen_str_start(). Else, buffer will be flushed out and new data + * added after that + */ +int json_gen_push_object(json_gen_str_t *jstr, const char *name); + +/** Pop a named JSON object + * + * This ends a JSON object by adding a '}'. This is basically same as + * json_gen_end_object() but included so as to complement json_gen_push_object() + * + * \param[in] jstr Pointer to the \ref json_gen_str_t structure initialised by + * json_gen_str_start() + * + * \return 0 on Success + * \return -1 if buffer is out of space (possible only if no callback function + * is passed to json_gen_str_start(). Else, buffer will be flushed out and new data + * added after that + */ +int json_gen_pop_object(json_gen_str_t *jstr); + +/** Push a JSON object string + * + * This adds a complete pre-formatted JSON object string to the JSON object. + * + * Eg. json_gen_push_object_str(jstr, "pre-formatted", "{\"a\":1,\"b\":2}"); + * This will add "pre-formatted":{"a":1,"b":2} + * + * \param[in] jstr Pointer to the \ref json_gen_str_t structure initialised by + * json_gen_str_start() + * \param[in] name Name of the JSON object string + * \param[in] object_str The pre-formatted JSON object string + * + * \return 0 on Success + * \return -1 if buffer is out of space (possible only if no callback function + * is passed to json_gen_str_start(). Else, buffer will be flushed out and new data + * added after that. + */ +int json_gen_push_object_str(json_gen_str_t *jstr, const char *name, const char *object_str); + +/** Push a named JSON array + * + * This adds a JSON array like "name":[ + * + * \param[in] jstr Pointer to the \ref json_gen_str_t structure initialised by + * json_gen_str_start() + * \param[in] name Name of the array + * + * \return 0 on Success + * \return -1 if buffer is out of space (possible only if no callback function + * is passed to json_gen_str_start(). Else, buffer will be flushed out and new data + * added after that + */ +int json_gen_push_array(json_gen_str_t *jstr, const char *name); + +/** Pop a named JSON array + * + * This ends a JSON array by adding a ']'. This is basically same as + * json_gen_end_array() but included so as to complement json_gen_push_array() + * + * \param[in] jstr Pointer to the \ref json_gen_str_t structure initialised by + * json_gen_str_start() + * + * \return 0 on Success + * \return -1 if buffer is out of space (possible only if no callback function + * is passed to json_gen_str_start(). Else, buffer will be flushed out and new data + * added after that + */ +int json_gen_pop_array(json_gen_str_t *jstr); + +/** Push a JSON array string + * + * This adds a complete pre-formatted JSON array string to the JSON object. + * + * Eg. json_gen_push_object_str(jstr, "pre-formatted", "[1,2,3]"); + * This will add "pre-formatted":[1,2,3] + * + * \param[in] jstr Pointer to the \ref json_gen_str_t structure initialised by + * json_gen_str_start() + * \param[in] name Name of the JSON array string + * \param[in] array_str The pre-formatted JSON array string + * + * \return 0 on Success + * \return -1 if buffer is out of space (possible only if no callback function + * is passed to json_gen_str_start(). Else, buffer will be flushed out and new data + * added after that. + */ +int json_gen_push_array_str(json_gen_str_t *jstr, const char *name, const char *array_str); + +/** Add a boolean element to an object + * + * This adds a boolean element to an object. Eg. "bool_val":true + * + * \note This must be called between json_gen_start_object()/json_gen_push_object() + * and json_gen_end_object()/json_gen_pop_object() + * + * \param[in] jstr Pointer to the \ref json_gen_str_t structure initialised by + * json_gen_str_start() + * \param[in] name Name of the element + * \param[in] val Boolean value of the element + * + * \return 0 on Success + * \return -1 if buffer is out of space (possible only if no callback function + * is passed to json_gen_str_start(). Else, buffer will be flushed out and new data + * added after that + */ +int json_gen_obj_set_bool(json_gen_str_t *jstr, const char *name, bool val); + +/** Add an integer element to an object + * + * This adds an integer element to an object. Eg. "int_val":28 + * + * \note This must be called between json_gen_start_object()/json_gen_push_object() + * and json_gen_end_object()/json_gen_pop_object() + * + * \param[in] jstr Pointer to the \ref json_gen_str_t structure initialised by + * json_gen_str_start() + * \param[in] name Name of the element + * \param[in] val Integer value of the element + * + * \return 0 on Success + * \return -1 if buffer is out of space (possible only if no callback function + * is passed to json_gen_str_start(). Else, buffer will be flushed out and new data + * added after that + */ +int json_gen_obj_set_int(json_gen_str_t *jstr, const char *name, int val); + +/** Add a float element to an object + * + * This adds a float element to an object. Eg. "float_val":23.8 + * + * \note This must be called between json_gen_start_object()/json_gen_push_object() + * and json_gen_end_object()/json_gen_pop_object() + * + * \param[in] jstr Pointer to the \ref json_gen_str_t structure initialised by + * json_gen_str_start() + * \param[in] name Name of the element + * \param[in] val Float value of the element + * + * \return 0 on Success + * \return -1 if buffer is out of space (possible only if no callback function + * is passed to json_gen_str_start(). Else, buffer will be flushed out and new data + * added after that + */ +int json_gen_obj_set_float(json_gen_str_t *jstr, const char *name, float val); + +/** Add a string element to an object + * + * This adds a string element to an object. Eg. "string_val":"my_string" + * + * \note This must be called between json_gen_start_object()/json_gen_push_object() + * and json_gen_end_object()/json_gen_pop_object() + * + * \param[in] jstr Pointer to the \ref json_gen_str_t structure initialised by + * json_gen_str_start() + * \param[in] name Name of the element + * \param[in] val Null terminated string value of the element + * + * \return 0 on Success + * \return -1 if buffer is out of space (possible only if no callback function + * is passed to json_gen_str_start(). Else, buffer will be flushed out and new data + * added after that + */ +int json_gen_obj_set_string(json_gen_str_t *jstr, const char *name, const char *val); + +/** Add a NULL element to an object + * + * This adds a NULL element to an object. Eg. "null_val":null + * + * \note This must be called between json_gen_start_object()/json_gen_push_object() + * and json_gen_end_object()/json_gen_pop_object() + * + * \param[in] jstr Pointer to the \ref json_gen_str_t structure initialised by + * json_gen_str_start() + * \param[in] name Name of the element + * + * \return 0 on Success + * \return -1 if buffer is out of space (possible only if no callback function + * is passed to json_gen_str_start(). Else, buffer will be flushed out and new data + * added after that + */ +int json_gen_obj_set_null(json_gen_str_t *jstr, const char *name); + +/** Add a boolean element to an array + * + * \note This must be called between json_gen_start_array()/json_gen_push_array() + * and json_gen_end_array()/json_gen_pop_array() + * + * \param[in] jstr Pointer to the \ref json_gen_str_t structure initialised by + * json_gen_str_start() + * \param[in] val Boolean value of the element + * + * \return 0 on Success + * \return -1 if buffer is out of space (possible only if no callback function + * is passed to json_gen_str_start(). Else, buffer will be flushed out and new data + * added after that + */ +int json_gen_arr_set_bool(json_gen_str_t *jstr, bool val); + +/** Add an integer element to an array + * + * \note This must be called between json_gen_start_array()/json_gen_push_array() + * and json_gen_end_array()/json_gen_pop_array() + * + * \param[in] jstr Pointer to the \ref json_gen_str_t structure initialised by + * json_gen_str_start() + * \param[in] val Integer value of the element + * + * \return 0 on Success + * \return -1 if buffer is out of space (possible only if no callback function + * is passed to json_gen_str_start(). Else, buffer will be flushed out and new data + * added after that + */ +int json_gen_arr_set_int(json_gen_str_t *jstr, int val); + +/** Add a float element to an array + * + * \note This must be called between json_gen_start_array()/json_gen_push_array() + * and json_gen_end_array()/json_gen_pop_array() + * + * \param[in] jstr Pointer to the \ref json_gen_str_t structure initialised by + * json_gen_str_start() + * \param[in] val Float value of the element + * + * \return 0 on Success + * \return -1 if buffer is out of space (possible only if no callback function + * is passed to json_gen_str_start(). Else, buffer will be flushed out and new data + * added after that + */ +int json_gen_arr_set_float(json_gen_str_t *jstr, float val); + +/** Add a string element to an array + * + * \note This must be called between json_gen_start_array()/json_gen_push_array() + * and json_gen_end_array()/json_gen_pop_array() + * + * \param[in] jstr Pointer to the \ref json_gen_str_t structure initialised by + * json_gen_str_start() + * \param[in] val Null terminated string value of the element + * + * \return 0 on Success + * \return -1 if buffer is out of space (possible only if no callback function + * is passed to json_gen_str_start(). Else, buffer will be flushed out and new data + * added after that + */ +int json_gen_arr_set_string(json_gen_str_t *jstr, const char *val); + +/** Add a NULL element to an array + * + * \note This must be called between json_gen_start_array()/json_gen_push_array() + * and json_gen_end_array()/json_gen_pop_array() + * + * \param[in] jstr Pointer to the \ref json_gen_str_t structure initialised by + * json_gen_str_start() + * + * \return 0 on Success + * \return -1 if buffer is out of space (possible only if no callback function + * is passed to json_gen_str_start(). Else, buffer will be flushed out and new data + * added after that + */ +int json_gen_arr_set_null(json_gen_str_t *jstr); + +/** Start a Long string in an object + * + * This starts a string in an object, but does not end it (i.e., does not add the + * terminating quotes. This is useful for long strings. Eg. "string_val":"my_string. + * The API json_gen_add_to_long_string() must be used to add to this string and the API + * json_gen_end_long_string() must be used to terminate it (i.e. add the ending quotes). + * + * \note This must be called between json_gen_start_object()/json_gen_push_object() + * and json_gen_end_object()/json_gen_pop_object() + * + * \param[in] jstr Pointer to the \ref json_gen_str_t structure initialised by + * json_gen_str_start() + * \param[in] name Name of the element + * \param[in] val Null terminated initial part of the string value. It can also be NULL + * + * \return 0 on Success + * \return -1 if buffer is out of space (possible only if no callback function + * is passed to json_gen_str_start(). Else, buffer will be flushed out and new data + * added after that + */ +int json_gen_obj_start_long_string(json_gen_str_t *jstr, const char *name, const char *val); + +/** Start a Long string in an array + * + * This starts a string in an arrayt, but does not end it (i.e., does not add the + * terminating quotes. This is useful for long strings. + * The API json_gen_add_to_long_string() must be used to add to this string and the API + * json_gen_end_long_string() must be used to terminate it (i.e. add the ending quotes). + * + * \note This must be called between json_gen_start_array()/json_gen_push_array() + * and json_gen_end_array()/json_gen_pop_array() + * + * \param[in] jstr Pointer to the \ref json_gen_str_t structure initialised by + * json_gen_str_start() + * \param[in] val Null terminated initial part of the string value. It can also be NULL + * + * \return 0 on Success + * \return -1 if buffer is out of space (possible only if no callback function + * is passed to json_gen_str_start(). Else, buffer will be flushed out and new data + * added after that + */ +int json_gen_arr_start_long_string(json_gen_str_t *jstr, const char *val); + +/** Add to a JSON Long string + * + * This extends the string initialised by json_gen_obj_start_long_string() or + * json_gen_arr_start_long_string(). After the entire string is created, it should be terminated + * with json_gen_end_long_string(). + * + * \param[in] jstr Pointer to the \ref json_gen_str_t structure initialised by json_gen_str_start() + * \param[in] val Null terminated extending part of the string value. + * + * \return 0 on Success + * \return -1 if buffer is out of space (possible only if no callback function + * is passed to json_gen_str_start(). Else, buffer will be flushed out and new data + * added after that + */ +int json_gen_add_to_long_string(json_gen_str_t *jstr, const char *val); + +/** End a JSON Long string + * + * This ends the string initialised by json_gen_obj_start_long_string() or + * json_gen_arr_start_long_string() by adding the ending quotes. + * + * \param[in] jstr Pointer to the \ref json_gen_str_t structure initialised by json_gen_str_start() + * + * + * \return 0 on Success + * \return -1 if buffer is out of space (possible only if no callback function + * is passed to json_gen_str_start(). Else, buffer will be flushed out and new data + * added after that + */ +int json_gen_end_long_string(json_gen_str_t *jstr); +#ifdef __cplusplus +} +#endif +#endif diff --git a/RainMaker_Table-Lights/managed_components/espressif__json_generator/src/json_generator.c b/RainMaker_Table-Lights/managed_components/espressif__json_generator/src/json_generator.c new file mode 100644 index 000000000..30e65bfd1 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__json_generator/src/json_generator.c @@ -0,0 +1,312 @@ +/* + * Copyright 2020 Piyush Shah + * + * 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. + */ + +#include +#include +#include +#include + +#include + +#define MAX_INT_IN_STR 24 +#define MAX_FLOAT_IN_STR 30 + +static inline int json_gen_get_empty_len(json_gen_str_t *jstr) +{ + return (jstr->buf_size - (jstr->free_ptr - jstr->buf) - 1); +} + +/* This will add the incoming string to the JSON string buffer + * and flush it out if the buffer is full. Note that the data being + * flushed out will always be equal to the size of the buffer unless + * this is the last chunk being flushed out on json_gen_end_str() + */ +static int json_gen_add_to_str(json_gen_str_t *jstr, const char *str) +{ + if (!str) { + return 0; + } + int len = strlen(str); + jstr->total_len += len; + if (jstr->buf == NULL) { + return 0; + } + const char *cur_ptr = str; + while (1) { + int len_remaining = json_gen_get_empty_len(jstr); + int copy_len = len_remaining > len ? len : len_remaining; + memmove(jstr->free_ptr, cur_ptr, copy_len); + cur_ptr += copy_len; + jstr->free_ptr += copy_len; + len -= copy_len; + if (len) { + *jstr->free_ptr = '\0'; + /* Report error if the buffer is full and no flush callback + * is registered + */ + if (!jstr->flush_cb) { + return -1; + } + jstr->flush_cb(jstr->buf, jstr->priv); + jstr->free_ptr = jstr->buf; + } else { + break; + } + } + return 0; +} + + +void json_gen_str_start(json_gen_str_t *jstr, char *buf, int buf_size, + json_gen_flush_cb_t flush_cb, void *priv) +{ + memset(jstr, 0, sizeof(json_gen_str_t)); + jstr->buf = buf; + jstr->buf_size = buf_size; + jstr->flush_cb = flush_cb; + jstr->free_ptr = buf; + jstr->priv = priv; +} + +int json_gen_str_end(json_gen_str_t *jstr) +{ + int total_len = jstr->total_len; + if (jstr->buf) { + *jstr->free_ptr = '\0'; + if (jstr->flush_cb) { + jstr->flush_cb(jstr->buf, jstr->priv); + } + } + memset(jstr, 0, sizeof(json_gen_str_t)); + return total_len + 1; /* +1 for the NULL termination */ +} + +static inline void json_gen_handle_comma(json_gen_str_t *jstr) +{ + if (jstr->comma_req) { + json_gen_add_to_str(jstr, ","); + } +} + + +static int json_gen_handle_name(json_gen_str_t *jstr, const char *name) +{ + json_gen_add_to_str(jstr, "\""); + json_gen_add_to_str(jstr, name); + return json_gen_add_to_str(jstr, "\":"); +} + + +int json_gen_start_object(json_gen_str_t *jstr) +{ + json_gen_handle_comma(jstr); + jstr->comma_req = false; + return json_gen_add_to_str(jstr, "{"); +} + +int json_gen_end_object(json_gen_str_t *jstr) +{ + jstr->comma_req = true; + return json_gen_add_to_str(jstr, "}"); +} + + +int json_gen_start_array(json_gen_str_t *jstr) +{ + json_gen_handle_comma(jstr); + jstr->comma_req = false; + return json_gen_add_to_str(jstr, "["); +} + +int json_gen_end_array(json_gen_str_t *jstr) +{ + jstr->comma_req = true; + return json_gen_add_to_str(jstr, "]"); +} + +int json_gen_push_object(json_gen_str_t *jstr, const char *name) +{ + json_gen_handle_comma(jstr); + json_gen_handle_name(jstr, name); + jstr->comma_req = false; + return json_gen_add_to_str(jstr, "{"); +} + +int json_gen_pop_object(json_gen_str_t *jstr) +{ + jstr->comma_req = true; + return json_gen_add_to_str(jstr, "}"); +} + +int json_gen_push_object_str(json_gen_str_t *jstr, const char *name, const char *object_str) +{ + json_gen_handle_comma(jstr); + json_gen_handle_name(jstr, name); + jstr->comma_req = true; + return json_gen_add_to_str(jstr, object_str); +} + +int json_gen_push_array(json_gen_str_t *jstr, const char *name) +{ + json_gen_handle_comma(jstr); + json_gen_handle_name(jstr, name); + jstr->comma_req = false; + return json_gen_add_to_str(jstr, "["); +} +int json_gen_pop_array(json_gen_str_t *jstr) +{ + jstr->comma_req = true; + return json_gen_add_to_str(jstr, "]"); +} + +int json_gen_push_array_str(json_gen_str_t *jstr, const char *name, const char *array_str) +{ + json_gen_handle_comma(jstr); + json_gen_handle_name(jstr, name); + jstr->comma_req = true; + return json_gen_add_to_str(jstr, array_str); +} + +static int json_gen_set_bool(json_gen_str_t *jstr, bool val) +{ + jstr->comma_req = true; + if (val) { + return json_gen_add_to_str(jstr, "true"); + } else { + return json_gen_add_to_str(jstr, "false"); + } +} +int json_gen_obj_set_bool(json_gen_str_t *jstr, const char *name, bool val) +{ + json_gen_handle_comma(jstr); + json_gen_handle_name(jstr, name); + return json_gen_set_bool(jstr, val); +} + +int json_gen_arr_set_bool(json_gen_str_t *jstr, bool val) +{ + json_gen_handle_comma(jstr); + return json_gen_set_bool(jstr, val); +} + +static int json_gen_set_int(json_gen_str_t *jstr, int val) +{ + jstr->comma_req = true; + char str[MAX_INT_IN_STR]; + snprintf(str, MAX_INT_IN_STR, "%d", val); + return json_gen_add_to_str(jstr, str); +} + +int json_gen_obj_set_int(json_gen_str_t *jstr, const char *name, int val) +{ + json_gen_handle_comma(jstr); + json_gen_handle_name(jstr, name); + return json_gen_set_int(jstr, val); +} + +int json_gen_arr_set_int(json_gen_str_t *jstr, int val) +{ + json_gen_handle_comma(jstr); + return json_gen_set_int(jstr, val); +} + + +static int json_gen_set_float(json_gen_str_t *jstr, float val) +{ + jstr->comma_req = true; + char str[MAX_FLOAT_IN_STR]; + snprintf(str, MAX_FLOAT_IN_STR, "%.*f", JSON_FLOAT_PRECISION, val); + return json_gen_add_to_str(jstr, str); +} +int json_gen_obj_set_float(json_gen_str_t *jstr, const char *name, float val) +{ + json_gen_handle_comma(jstr); + json_gen_handle_name(jstr, name); + return json_gen_set_float(jstr, val); +} +int json_gen_arr_set_float(json_gen_str_t *jstr, float val) +{ + json_gen_handle_comma(jstr); + return json_gen_set_float(jstr, val); +} + +static int json_gen_set_string(json_gen_str_t *jstr, const char *val) +{ + jstr->comma_req = true; + json_gen_add_to_str(jstr, "\""); + json_gen_add_to_str(jstr, val); + return json_gen_add_to_str(jstr, "\""); +} + +int json_gen_obj_set_string(json_gen_str_t *jstr, const char *name, const char *val) +{ + json_gen_handle_comma(jstr); + json_gen_handle_name(jstr, name); + return json_gen_set_string(jstr, val); +} + +int json_gen_arr_set_string(json_gen_str_t *jstr, const char *val) +{ + json_gen_handle_comma(jstr); + return json_gen_set_string(jstr, val); +} + +static int json_gen_set_long_string(json_gen_str_t *jstr, const char *val) +{ + jstr->comma_req = true; + json_gen_add_to_str(jstr, "\""); + return json_gen_add_to_str(jstr, val); +} + +int json_gen_obj_start_long_string(json_gen_str_t *jstr, const char *name, const char *val) +{ + json_gen_handle_comma(jstr); + json_gen_handle_name(jstr, name); + return json_gen_set_long_string(jstr, val); +} + +int json_gen_arr_start_long_string(json_gen_str_t *jstr, const char *val) +{ + json_gen_handle_comma(jstr); + return json_gen_set_long_string(jstr, val); +} + +int json_gen_add_to_long_string(json_gen_str_t *jstr, const char *val) +{ + return json_gen_add_to_str(jstr, val); +} + +int json_gen_end_long_string(json_gen_str_t *jstr) +{ + return json_gen_add_to_str(jstr, "\""); +} +static int json_gen_set_null(json_gen_str_t *jstr) +{ + jstr->comma_req = true; + return json_gen_add_to_str(jstr, "null"); +} +int json_gen_obj_set_null(json_gen_str_t *jstr, const char *name) +{ + json_gen_handle_comma(jstr); + json_gen_handle_name(jstr, name); + return json_gen_set_null(jstr); +} + +int json_gen_arr_set_null(json_gen_str_t *jstr) +{ + json_gen_handle_comma(jstr); + return json_gen_set_null(jstr); +} diff --git a/RainMaker_Table-Lights/managed_components/espressif__json_parser/.component_hash b/RainMaker_Table-Lights/managed_components/espressif__json_parser/.component_hash new file mode 100644 index 000000000..46daa6fe5 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__json_parser/.component_hash @@ -0,0 +1 @@ +d74b81729ad06ec11ff5eb5b1b0d7df1d00e6027fc11471f4b139c70dcf1b1e4 \ No newline at end of file diff --git a/RainMaker_Table-Lights/managed_components/espressif__json_parser/CHECKSUMS.json b/RainMaker_Table-Lights/managed_components/espressif__json_parser/CHECKSUMS.json new file mode 100644 index 000000000..dcfdae9b6 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__json_parser/CHECKSUMS.json @@ -0,0 +1 @@ +{"version": "1.0", "algorithm": "sha256", "created_at": "2025-05-21T15:51:48.179854+00:00", "files": [{"path": "CMakeLists.txt", "size": 149, "hash": "b3f8720c2e9236570daf79109a83314601c662e5dc665bf8dd058e3876964f35"}, {"path": "LICENSE", "size": 11365, "hash": "f0f612d1627194ddd07c8b5b238a514ae9794632e5470c00f16237def7dc2246"}, {"path": "idf_component.yml", "size": 217, "hash": "8fcfed233fc86c7462fbd614b46757c2f59af6215394c628d26ece6147ed226c"}, {"path": "README.md", "size": 458, "hash": "c86da9f8e4242bf828ea55a62f4e564bdb36c024c1ef6bbbdc6c756627c45354"}, {"path": "test/CMakeLists.txt", "size": 103, "hash": "bde1e0e6e155c09681765c78f977d2c870595a97f2a2a5fb61ae774efcae19ac"}, {"path": "test/test_json_parser.c", "size": 2421, "hash": "657fb7e483633023d94e75ed94b03f55978ed1a7d9562370f268adeed577a9ec"}, {"path": "include/json_parser.h", "size": 3117, "hash": "b035c0d3761406c13a87260bd4acf2b87cb64a9f16a967c0625bf87a659b0841"}, {"path": "src/json_parser.c", "size": 12381, "hash": "8e73a15891f90f44dca02398ddddf550a8b2c4cd848f121b2053ef1965d18a69"}]} \ No newline at end of file diff --git a/RainMaker_Table-Lights/managed_components/espressif__json_parser/CMakeLists.txt b/RainMaker_Table-Lights/managed_components/espressif__json_parser/CMakeLists.txt new file mode 100644 index 000000000..d62abc727 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__json_parser/CMakeLists.txt @@ -0,0 +1,4 @@ +idf_component_register(SRCS "src/json_parser.c" + INCLUDE_DIRS "include" + REQUIRES "jsmn" + ) diff --git a/RainMaker_Table-Lights/managed_components/espressif__json_parser/LICENSE b/RainMaker_Table-Lights/managed_components/espressif__json_parser/LICENSE new file mode 100644 index 000000000..d613ddc8f --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__json_parser/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2020 Piyush Shah + + 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. diff --git a/RainMaker_Table-Lights/managed_components/espressif__json_parser/README.md b/RainMaker_Table-Lights/managed_components/espressif__json_parser/README.md new file mode 100644 index 000000000..91d8e91ca --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__json_parser/README.md @@ -0,0 +1,10 @@ +# JSON Parser + +[![Component Registry](https://components.espressif.com/components/espressif/json_parser/badge.svg)](https://components.espressif.com/components/espressif/json_parser) + +This is a simple, light weight JSON parser built on top of [jsmn](https://github.com/zserge/jsmn). + +Files + +- `src/json_parser.c`: Source file which has all the logic for implementing the APIs built on top of JSMN +- `include/json_parser.h`: Header file that exposes all APIs diff --git a/RainMaker_Table-Lights/managed_components/espressif__json_parser/idf_component.yml b/RainMaker_Table-Lights/managed_components/espressif__json_parser/idf_component.yml new file mode 100644 index 000000000..61dd57c5c --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__json_parser/idf_component.yml @@ -0,0 +1,8 @@ +dependencies: + jsmn: + rules: + - if: idf_version >=5.0 + version: ~1.1 +description: This is a simple, light weight JSON parser built on top of jsmn +url: https://github.com/espressif/json_parser +version: 1.0.3 diff --git a/RainMaker_Table-Lights/managed_components/espressif__json_parser/include/json_parser.h b/RainMaker_Table-Lights/managed_components/espressif__json_parser/include/json_parser.h new file mode 100644 index 000000000..565cc6240 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__json_parser/include/json_parser.h @@ -0,0 +1,80 @@ +/* + * Copyright 2020 Piyush Shah + * + * 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 _JSON_PARSER_H_ +#define _JSON_PARSER_H_ + +#define JSMN_PARENT_LINKS +#define JSMN_HEADER +#include +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +#define OS_SUCCESS 0 +#define OS_FAIL -1 + +typedef jsmn_parser json_parser_t; +typedef jsmntok_t json_tok_t; + +typedef struct { + json_parser_t parser; + const char *js; + json_tok_t *tokens; + json_tok_t *cur; + int num_tokens; +} jparse_ctx_t; + +int json_parse_start(jparse_ctx_t *jctx, const char *js, int len); +int json_parse_end(jparse_ctx_t *jctx); +int json_parse_start_static(jparse_ctx_t *jctx, const char *js, int len, json_tok_t *buffer_tokens, int buffer_tokens_max_count); +int json_parse_end_static(jparse_ctx_t *jctx); + +int json_obj_get_array(jparse_ctx_t *jctx, const char *name, int *num_elem); +int json_obj_leave_array(jparse_ctx_t *jctx); +int json_obj_get_object(jparse_ctx_t *jctx, const char *name); +int json_obj_leave_object(jparse_ctx_t *jctx); +int json_obj_get_bool(jparse_ctx_t *jctx, const char *name, bool *val); +int json_obj_get_int(jparse_ctx_t *jctx, const char *name, int *val); +int json_obj_get_int64(jparse_ctx_t *jctx, const char *name, int64_t *val); +int json_obj_get_float(jparse_ctx_t *jctx, const char *name, float *val); +int json_obj_get_string(jparse_ctx_t *jctx, const char *name, char *val, int size); +int json_obj_get_strlen(jparse_ctx_t *jctx, const char *name, int *strlen); +int json_obj_get_object_str(jparse_ctx_t *jctx, const char *name, char *val, int size); +int json_obj_get_object_strlen(jparse_ctx_t *jctx, const char *name, int *strlen); +int json_obj_get_array_str(jparse_ctx_t *jctx, const char *name, char *val, int size); +int json_obj_get_array_strlen(jparse_ctx_t *jctx, const char *name, int *strlen); + +int json_arr_get_array(jparse_ctx_t *jctx, uint32_t index); +int json_arr_leave_array(jparse_ctx_t *jctx); +int json_arr_get_object(jparse_ctx_t *jctx, uint32_t index); +int json_arr_leave_object(jparse_ctx_t *jctx); +int json_arr_get_bool(jparse_ctx_t *jctx, uint32_t index, bool *val); +int json_arr_get_int(jparse_ctx_t *jctx, uint32_t index, int *val); +int json_arr_get_int64(jparse_ctx_t *jctx, uint32_t index, int64_t *val); +int json_arr_get_float(jparse_ctx_t *jctx, uint32_t index, float *val); +int json_arr_get_string(jparse_ctx_t *jctx, uint32_t index, char *val, int size); +int json_arr_get_strlen(jparse_ctx_t *jctx, uint32_t index, int *strlen); + +#ifdef __cplusplus +} +#endif + +#endif /* _JSON_PARSER_H_ */ + diff --git a/RainMaker_Table-Lights/managed_components/espressif__json_parser/src/json_parser.c b/RainMaker_Table-Lights/managed_components/espressif__json_parser/src/json_parser.c new file mode 100644 index 000000000..7311d477c --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__json_parser/src/json_parser.c @@ -0,0 +1,474 @@ +/* + * Copyright 2020 Piyush Shah + * + * 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. + */ +#include +#include +#include +#include +#define JSMN_PARENT_LINKS +#define JSMN_STRICT +#define JSMN_STATIC +#include +#include + +static bool token_matches_str(jparse_ctx_t *ctx, json_tok_t *tok, const char *str) +{ + const char *js = ctx->js; + return ((strncmp(js + tok->start, str, strlen(str)) == 0) + && (strlen(str) == (size_t) (tok->end - tok->start))); +} + +static json_tok_t *json_skip_elem(json_tok_t *token) +{ + json_tok_t *cur = token; + int cnt = cur->size; + while (cnt--) { + cur++; + cur = json_skip_elem(cur); + } + return cur; +} + +static int json_tok_to_bool(jparse_ctx_t *jctx, json_tok_t *tok, bool *val) +{ + if (token_matches_str(jctx, tok, "true") || token_matches_str(jctx, tok, "1")) { + *val = true; + } else if (token_matches_str(jctx, tok, "false") || token_matches_str(jctx, tok, "0")) { + *val = false; + } else { + return -OS_FAIL; + } + return OS_SUCCESS; +} + +static int json_tok_to_int(jparse_ctx_t *jctx, json_tok_t *tok, int *val) +{ + const char *tok_start = &jctx->js[tok->start]; + const char *tok_end = &jctx->js[tok->end]; + char *endptr; + int i = strtoul(tok_start, &endptr, 10); + if (endptr == tok_end) { + *val = i; + return OS_SUCCESS; + } + return -OS_FAIL; +} + +static int json_tok_to_int64(jparse_ctx_t *jctx, json_tok_t *tok, int64_t *val) +{ + const char *tok_start = &jctx->js[tok->start]; + const char *tok_end = &jctx->js[tok->end]; + char *endptr; + int64_t i64 = strtoull(tok_start, &endptr, 10); + if (endptr == tok_end) { + *val = i64; + return OS_SUCCESS; + } + return -OS_FAIL; +} + +static int json_tok_to_float(jparse_ctx_t *jctx, json_tok_t *tok, float *val) +{ + const char *tok_start = &jctx->js[tok->start]; + const char *tok_end = &jctx->js[tok->end]; + char *endptr; + float f = strtof(tok_start, &endptr); + if (endptr == tok_end) { + *val = f; + return OS_SUCCESS; + } + return -OS_FAIL; +} + +static int json_tok_to_string(jparse_ctx_t *jctx, json_tok_t *tok, char *val, int size) +{ + if ((tok->end - tok->start) > (size - 1)) { + return -OS_FAIL; + } + strncpy(val, jctx->js + tok->start, tok->end - tok->start); + val[tok->end - tok->start] = 0; + return OS_SUCCESS; +} + +static json_tok_t *json_obj_search(jparse_ctx_t *jctx, const char *key) +{ + json_tok_t *tok = jctx->cur; + int size = tok->size; + if (size <= 0) { + return NULL; + } + if (tok->type != JSMN_OBJECT) { + return NULL; + } + + while (size--) { + tok++; + if (token_matches_str(jctx, tok, key)) { + return tok; + } + tok = json_skip_elem(tok); + } + return NULL; +} + +static json_tok_t *json_obj_get_val_tok(jparse_ctx_t *jctx, const char *name, jsmntype_t type) +{ + json_tok_t *tok = json_obj_search(jctx, name); + if (!tok) { + return NULL; + } + tok++; + if (tok->type != type) { + return NULL; + } + return tok; +} + +int json_obj_get_array(jparse_ctx_t *jctx, const char *name, int *num_elem) +{ + json_tok_t *tok = json_obj_get_val_tok(jctx, name, JSMN_ARRAY); + if (!tok) { + return -OS_FAIL; + } + jctx->cur = tok; + *num_elem = tok->size; + return OS_SUCCESS; +} + +int json_obj_leave_array(jparse_ctx_t *jctx) +{ + /* The array's parent will be the key */ + if (jctx->cur->parent < 0) { + return -OS_FAIL; + } + jctx->cur = &jctx->tokens[jctx->cur->parent]; + + /* The key's parent will be the actual parent object */ + if (jctx->cur->parent < 0) { + return -OS_FAIL; + } + jctx->cur = &jctx->tokens[jctx->cur->parent]; + return OS_SUCCESS; +} + +int json_obj_get_object(jparse_ctx_t *jctx, const char *name) +{ + json_tok_t *tok = json_obj_get_val_tok(jctx, name, JSMN_OBJECT); + if (!tok) { + return -OS_FAIL; + } + jctx->cur = tok; + return OS_SUCCESS; +} + +int json_obj_leave_object(jparse_ctx_t *jctx) +{ + /* The objects's parent will be the key */ + if (jctx->cur->parent < 0) { + return -OS_FAIL; + } + jctx->cur = &jctx->tokens[jctx->cur->parent]; + + /* The key's parent will be the actual parent object */ + if (jctx->cur->parent < 0) { + return -OS_FAIL; + } + jctx->cur = &jctx->tokens[jctx->cur->parent]; + return OS_SUCCESS; +} + +int json_obj_get_bool(jparse_ctx_t *jctx, const char *name, bool *val) +{ + json_tok_t *tok = json_obj_get_val_tok(jctx, name, JSMN_PRIMITIVE); + if (!tok) { + return -OS_FAIL; + } + return json_tok_to_bool(jctx, tok, val); +} + +int json_obj_get_int(jparse_ctx_t *jctx, const char *name, int *val) +{ + json_tok_t *tok = json_obj_get_val_tok(jctx, name, JSMN_PRIMITIVE); + if (!tok) { + return -OS_FAIL; + } + return json_tok_to_int(jctx, tok, val); +} + +int json_obj_get_int64(jparse_ctx_t *jctx, const char *name, int64_t *val) +{ + json_tok_t *tok = json_obj_get_val_tok(jctx, name, JSMN_PRIMITIVE); + if (!tok) { + return -OS_FAIL; + } + return json_tok_to_int64(jctx, tok, val); +} + +int json_obj_get_float(jparse_ctx_t *jctx, const char *name, float *val) +{ + json_tok_t *tok = json_obj_get_val_tok(jctx, name, JSMN_PRIMITIVE); + if (!tok) { + return -OS_FAIL; + } + return json_tok_to_float(jctx, tok, val); +} + +int json_obj_get_string(jparse_ctx_t *jctx, const char *name, char *val, int size) +{ + json_tok_t *tok = json_obj_get_val_tok(jctx, name, JSMN_STRING); + if (!tok) { + return -OS_FAIL; + } + return json_tok_to_string(jctx, tok, val, size); +} + +int json_obj_get_strlen(jparse_ctx_t *jctx, const char *name, int *strlen) +{ + json_tok_t *tok = json_obj_get_val_tok(jctx, name, JSMN_STRING); + if (!tok) { + return -OS_FAIL; + } + *strlen = tok->end - tok->start; + return OS_SUCCESS; +} + +int json_obj_get_object_str(jparse_ctx_t *jctx, const char *name, char *val, int size) +{ + json_tok_t *tok = json_obj_get_val_tok(jctx, name, JSMN_OBJECT); + if (!tok) { + return -OS_FAIL; + } + return json_tok_to_string(jctx, tok, val, size); +} + +int json_obj_get_object_strlen(jparse_ctx_t *jctx, const char *name, int *strlen) +{ + json_tok_t *tok = json_obj_get_val_tok(jctx, name, JSMN_OBJECT); + if (!tok) { + return -OS_FAIL; + } + *strlen = tok->end - tok->start; + return OS_SUCCESS; +} +int json_obj_get_array_str(jparse_ctx_t *jctx, const char *name, char *val, int size) +{ + json_tok_t *tok = json_obj_get_val_tok(jctx, name, JSMN_ARRAY); + if (!tok) { + return -OS_FAIL; + } + return json_tok_to_string(jctx, tok, val, size); +} + +int json_obj_get_array_strlen(jparse_ctx_t *jctx, const char *name, int *strlen) +{ + json_tok_t *tok = json_obj_get_val_tok(jctx, name, JSMN_ARRAY); + if (!tok) { + return -OS_FAIL; + } + *strlen = tok->end - tok->start; + return OS_SUCCESS; +} + +static json_tok_t *json_arr_search(jparse_ctx_t *ctx, uint32_t index) +{ + json_tok_t *tok = ctx->cur; + if ((tok->type != JSMN_ARRAY) || (tok->size <= 0)) { + return NULL; + } + if (index > (uint32_t)(tok->size - 1)) { + return NULL; + } + /* Increment by 1, so that token points to index 0 */ + tok++; + while (index--) { + tok = json_skip_elem(tok); + tok++; + } + return tok; +} +static json_tok_t *json_arr_get_val_tok(jparse_ctx_t *jctx, uint32_t index, jsmntype_t type) +{ + json_tok_t *tok = json_arr_search(jctx, index); + if (!tok) { + return NULL; + } + if (tok->type != type) { + return NULL; + } + return tok; +} + +int json_arr_get_array(jparse_ctx_t *jctx, uint32_t index) +{ + json_tok_t *tok = json_arr_get_val_tok(jctx, index, JSMN_ARRAY); + if (!tok) { + return -OS_FAIL; + } + jctx->cur = tok; + return OS_SUCCESS; +} + +int json_arr_leave_array(jparse_ctx_t *jctx) +{ + if (jctx->cur->parent < 0) { + return -OS_FAIL; + } + jctx->cur = &jctx->tokens[jctx->cur->parent]; + return OS_SUCCESS; +} + +int json_arr_get_object(jparse_ctx_t *jctx, uint32_t index) +{ + json_tok_t *tok = json_arr_get_val_tok(jctx, index, JSMN_OBJECT); + if (!tok) { + return -OS_FAIL; + } + jctx->cur = tok; + return OS_SUCCESS; +} + +int json_arr_leave_object(jparse_ctx_t *jctx) +{ + if (jctx->cur->parent < 0) { + return -OS_FAIL; + } + jctx->cur = &jctx->tokens[jctx->cur->parent]; + return OS_SUCCESS; +} + +int json_arr_get_bool(jparse_ctx_t *jctx, uint32_t index, bool *val) +{ + json_tok_t *tok = json_arr_get_val_tok(jctx, index, JSMN_PRIMITIVE); + if (!tok) { + return -OS_FAIL; + } + return json_tok_to_bool(jctx, tok, val); +} + +int json_arr_get_int(jparse_ctx_t *jctx, uint32_t index, int *val) +{ + json_tok_t *tok = json_arr_get_val_tok(jctx, index, JSMN_PRIMITIVE); + if (!tok) { + return -OS_FAIL; + } + return json_tok_to_int(jctx, tok, val); +} + +int json_arr_get_int64(jparse_ctx_t *jctx, uint32_t index, int64_t *val) +{ + json_tok_t *tok = json_arr_get_val_tok(jctx, index, JSMN_PRIMITIVE); + if (!tok) { + return -OS_FAIL; + } + return json_tok_to_int64(jctx, tok, val); +} + +int json_arr_get_float(jparse_ctx_t *jctx, uint32_t index, float *val) +{ + json_tok_t *tok = json_arr_get_val_tok(jctx, index, JSMN_PRIMITIVE); + if (!tok) { + return -OS_FAIL; + } + return json_tok_to_float(jctx, tok, val); +} + +int json_arr_get_string(jparse_ctx_t *jctx, uint32_t index, char *val, int size) +{ + json_tok_t *tok = json_arr_get_val_tok(jctx, index, JSMN_STRING); + if (!tok) { + return -OS_FAIL; + } + return json_tok_to_string(jctx, tok, val, size); +} + +int json_arr_get_strlen(jparse_ctx_t *jctx, uint32_t index, int *strlen) +{ + json_tok_t *tok = json_arr_get_val_tok(jctx, index, JSMN_STRING); + if (!tok) { + return -OS_FAIL; + } + *strlen = tok->end - tok->start; + return OS_SUCCESS; +} + +int json_parse_start(jparse_ctx_t *jctx, const char *js, int len) +{ + memset(jctx, 0, sizeof(jparse_ctx_t)); + jsmn_init(&jctx->parser); + int num_tokens = jsmn_parse(&jctx->parser, js, len, NULL, 0); + if (num_tokens <= 0) { + return -OS_FAIL; + } + jctx->num_tokens = num_tokens; + jctx->tokens = calloc(num_tokens, sizeof(json_tok_t)); + if (!jctx->tokens) { + return -OS_FAIL; + } + jctx->js = js; + jsmn_init(&jctx->parser); + int ret = jsmn_parse(&jctx->parser, js, len, jctx->tokens, jctx->num_tokens); + if (ret <= 0) { + free(jctx->tokens); + memset(jctx, 0, sizeof(jparse_ctx_t)); + return -OS_FAIL; + } + jctx->cur = jctx->tokens; + return OS_SUCCESS; +} + +int json_parse_end(jparse_ctx_t *jctx) +{ + if (jctx->tokens) { + free(jctx->tokens); + } + memset(jctx, 0, sizeof(jparse_ctx_t)); + return OS_SUCCESS; +} + +int json_parse_start_static(jparse_ctx_t *jctx, const char *js, int len, json_tok_t *buffer_tokens, int buffer_tokens_max_count) +{ + // Init + memset(buffer_tokens, 0, buffer_tokens_max_count * sizeof(json_tok_t)); + memset(jctx, 0, sizeof(jparse_ctx_t)); + + // Check fit + jsmn_init(&jctx->parser); + int num_tokens = jsmn_parse(&jctx->parser, js, len, NULL, 0); + if (num_tokens <= 0 || num_tokens > buffer_tokens_max_count) { + return -OS_FAIL; + } + + // Set struct + jctx->num_tokens = num_tokens; + jctx->tokens = buffer_tokens; + jctx->js = js; + + // Parse + jsmn_init(&jctx->parser); + int ret = jsmn_parse(&jctx->parser, js, len, jctx->tokens, jctx->num_tokens); + if (ret <= 0) { + memset(jctx, 0, sizeof(jparse_ctx_t)); + return -OS_FAIL; + } + jctx->cur = jctx->tokens; + return OS_SUCCESS; +} + +int json_parse_end_static(jparse_ctx_t *jctx) +{ + memset(jctx, 0, sizeof(jparse_ctx_t)); + return OS_SUCCESS; +} + diff --git a/RainMaker_Table-Lights/managed_components/espressif__json_parser/test/CMakeLists.txt b/RainMaker_Table-Lights/managed_components/espressif__json_parser/test/CMakeLists.txt new file mode 100644 index 000000000..7d79f100f --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__json_parser/test/CMakeLists.txt @@ -0,0 +1,2 @@ +idf_component_register(SRCS test_json_parser.c + PRIV_REQUIRES json_parser unity) diff --git a/RainMaker_Table-Lights/managed_components/espressif__json_parser/test/test_json_parser.c b/RainMaker_Table-Lights/managed_components/espressif__json_parser/test/test_json_parser.c new file mode 100644 index 000000000..8a6310d6d --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__json_parser/test/test_json_parser.c @@ -0,0 +1,61 @@ +#include +#include +#include "json_parser.h" +#include "unity.h" + +#define json_test_str "{\n\"str_val\" : \"JSON Parser\",\n" \ + "\t\"float_val\" : 2.0,\n" \ + "\"int_val\" : 2017,\n" \ + "\"bool_val\" : false,\n" \ + "\"supported_el\" :\t [\"bool\",\"int\","\ + "\"float\",\"str\"" \ + ",\"object\",\"array\"],\n" \ + "\"features\" : { \"objects\":true, "\ + "\"arrays\":\"yes\"},\n"\ + "\"int_64\":109174583252}" + +TEST_CASE("json_parser basic tests", "[json_parser]") +{ + jparse_ctx_t jctx; + int ret = json_parse_start(&jctx, json_test_str, strlen(json_test_str)); + TEST_ASSERT_EQUAL(OS_SUCCESS, ret); + + char str_val[64]; + int int_val, num_elem; + int64_t int64_val; + bool bool_val; + float float_val; + + TEST_ASSERT_EQUAL(OS_SUCCESS, json_obj_get_string(&jctx, "str_val", str_val, sizeof(str_val))); + TEST_ASSERT_EQUAL_STRING("JSON Parser", str_val); + + TEST_ASSERT_EQUAL(OS_SUCCESS, json_obj_get_float(&jctx, "float_val", &float_val)); + TEST_ASSERT(fabs(float_val - 2.0f) < 0.0001f) + + TEST_ASSERT_EQUAL(OS_SUCCESS, json_obj_get_int(&jctx, "int_val", &int_val)); + TEST_ASSERT_EQUAL_INT(2017, int_val); + + TEST_ASSERT_EQUAL(OS_SUCCESS, json_obj_get_bool(&jctx, "bool_val", &bool_val)); + TEST_ASSERT_EQUAL(false, bool_val); + + TEST_ASSERT_EQUAL(OS_SUCCESS, json_obj_get_array(&jctx, "supported_el", &num_elem)); + const char *expected_values[] = {"bool", "int", "float", "str", "object", "array"}; + TEST_ASSERT_EQUAL(sizeof(expected_values) / sizeof(expected_values[0]), num_elem); + for (int i = 0; i < num_elem; ++i) { + TEST_ASSERT_EQUAL(OS_SUCCESS, json_arr_get_string(&jctx, i, str_val, sizeof(str_val))); + TEST_ASSERT_EQUAL_STRING(expected_values[i], str_val); + } + json_obj_leave_array(&jctx); + + TEST_ASSERT_EQUAL(OS_SUCCESS, json_obj_get_object(&jctx, "features")); + TEST_ASSERT_EQUAL(OS_SUCCESS, json_obj_get_bool(&jctx, "objects", &bool_val)); + TEST_ASSERT_EQUAL(true, bool_val); + TEST_ASSERT_EQUAL(OS_SUCCESS, json_obj_get_string(&jctx, "arrays", str_val, sizeof(str_val))); + TEST_ASSERT_EQUAL_STRING("yes", str_val); + json_obj_leave_object(&jctx); + + TEST_ASSERT_EQUAL(OS_SUCCESS, json_obj_get_int64(&jctx, "int_64", &int64_val)); + TEST_ASSERT(int64_val == 109174583252); + + json_parse_end(&jctx); +} \ No newline at end of file diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/.component_hash b/RainMaker_Table-Lights/managed_components/espressif__mdns/.component_hash new file mode 100644 index 000000000..60f40244b --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__mdns/.component_hash @@ -0,0 +1 @@ +3ec0af5f6bce310512e90f482388d21cc7c0e99668172d2f895356165fc6f7c5 \ No newline at end of file diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/.cz.yaml b/RainMaker_Table-Lights/managed_components/espressif__mdns/.cz.yaml new file mode 100644 index 000000000..2b6a74492 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__mdns/.cz.yaml @@ -0,0 +1,8 @@ +--- +commitizen: + bump_message: 'bump(mdns): $current_version -> $new_version' + pre_bump_hooks: python ../../ci/changelog.py mdns + tag_format: mdns-v$version + version: 1.8.2 + version_files: + - idf_component.yml diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/CHANGELOG.md b/RainMaker_Table-Lights/managed_components/espressif__mdns/CHANGELOG.md new file mode 100644 index 000000000..75a81db10 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__mdns/CHANGELOG.md @@ -0,0 +1,580 @@ +# Changelog + +## [1.8.2](https://github.com/espressif/esp-protocols/commits/mdns-v1.8.2) + +### Bug Fixes + +- Fix parsing incorrect txt records ([8fd2c99f](https://github.com/espressif/esp-protocols/commit/8fd2c99f)) + +## [1.8.1](https://github.com/espressif/esp-protocols/commits/mdns-v1.8.1) + +### Bug Fixes + +- Fix potential task delete race ([8ca45f34](https://github.com/espressif/esp-protocols/commit/8ca45f34)) + +## [1.8.0](https://github.com/espressif/esp-protocols/commits/mdns-v1.8.0) + +### Features + +- Add version keys ([e01e67e7](https://github.com/espressif/esp-protocols/commit/e01e67e7)) + +### Bug Fixes + +- Reformat mdns sources per indent-cont=120 ([c7663cde](https://github.com/espressif/esp-protocols/commit/c7663cde)) + +## [1.7.0](https://github.com/espressif/esp-protocols/commits/mdns-v1.7.0) + +### Features + +- Support user defined allocators ([88162d1f](https://github.com/espressif/esp-protocols/commit/88162d1f)) +- Allow allocate memory with configured caps ([7d29b476](https://github.com/espressif/esp-protocols/commit/7d29b476)) + +### Bug Fixes + +- Adjust some formatting per indent-cont=120 ([5b2077e3](https://github.com/espressif/esp-protocols/commit/5b2077e3)) + +## [1.6.0](https://github.com/espressif/esp-protocols/commits/mdns-v1.6.0) + +### Features + +- support allocating mDNS task from SPIRAM ([8fcad10c](https://github.com/espressif/esp-protocols/commit/8fcad10c)) + +### Bug Fixes + +- Use correct task delete function ([eb4ab524](https://github.com/espressif/esp-protocols/commit/eb4ab524)) + +### Updated + +- ci(mdns): Fix mdns host test layers with static task creation ([0690eba3](https://github.com/espressif/esp-protocols/commit/0690eba3)) + +## [1.5.3](https://github.com/espressif/esp-protocols/commits/mdns-v1.5.3) + +### Bug Fixes + +- Fix responder to ignore only invalid queries ([cd07228f](https://github.com/espressif/esp-protocols/commit/cd07228f), [#754](https://github.com/espressif/esp-protocols/issues/754)) + +## [1.5.2](https://github.com/espressif/esp-protocols/commits/mdns-v1.5.2) + +### Bug Fixes + +- Fix potential NULL deref when sending sub-buy ([e7273c46](https://github.com/espressif/esp-protocols/commit/e7273c46)) +- Fix _mdns_append_fqdn excessive stack usage ([bd23c233](https://github.com/espressif/esp-protocols/commit/bd23c233)) + +## [1.5.1](https://github.com/espressif/esp-protocols/commits/mdns-v1.5.1) + +### Bug Fixes + +- Fix incorrect memory free for mdns browse ([4451a8c5](https://github.com/espressif/esp-protocols/commit/4451a8c5)) + +## [1.5.0](https://github.com/espressif/esp-protocols/commits/mdns-v1.5.0) + +### Features + +- supported removal of subtype when updating service ([4ad88e29](https://github.com/espressif/esp-protocols/commit/4ad88e29)) + +### Bug Fixes + +- Fix zero-sized VLA clang-tidy warnings ([196198ec](https://github.com/espressif/esp-protocols/commit/196198ec)) +- Remove dead store to arg variable shared ([e838bf03](https://github.com/espressif/esp-protocols/commit/e838bf03)) +- Fix name mangling not to use strcpy() ([99b54ac3](https://github.com/espressif/esp-protocols/commit/99b54ac3)) +- Fix potential null derefernce in _mdns_execute_action() ([f5be2f41](https://github.com/espressif/esp-protocols/commit/f5be2f41)) +- Fix AFL test mock per espressif/esp-idf@a5bc08fb55c ([3d8835cf](https://github.com/espressif/esp-protocols/commit/3d8835cf)) +- Fixed potential out-of-bound interface error ([24f55ce9](https://github.com/espressif/esp-protocols/commit/24f55ce9)) +- Fixed incorrect error conversion ([8f8516cc](https://github.com/espressif/esp-protocols/commit/8f8516cc)) +- Fixed potential overflow when allocating txt data ([75a8e864](https://github.com/espressif/esp-protocols/commit/75a8e864)) +- Move MDNS_NAME_BUF_LEN to public headers ([907087c0](https://github.com/espressif/esp-protocols/commit/907087c0), [#724](https://github.com/espressif/esp-protocols/issues/724)) +- Cleanup includes in mdns.c ([68a9e148](https://github.com/espressif/esp-protocols/commit/68a9e148), [#725](https://github.com/espressif/esp-protocols/issues/725)) +- Allow advertizing service with port==0 ([827ea65f](https://github.com/espressif/esp-protocols/commit/827ea65f)) +- Fixed complier warning if MDNS_MAX_SERVICES==0 ([95377216](https://github.com/espressif/esp-protocols/commit/95377216), [#611](https://github.com/espressif/esp-protocols/issues/611)) + +## [1.4.3](https://github.com/espressif/esp-protocols/commits/mdns-v1.4.3) + +### Features + +- support zero item when update subtype ([5bd82c01](https://github.com/espressif/esp-protocols/commit/5bd82c01)) + +## [1.4.2](https://github.com/espressif/esp-protocols/commits/mdns-v1.4.2) + +### Features + +- support update subtype ([062b8dca](https://github.com/espressif/esp-protocols/commit/062b8dca)) + +### Updated + +- chore(mdns): Add more info to idf_component.yml ([4a1cb65c](https://github.com/espressif/esp-protocols/commit/4a1cb65c)) + +## [1.4.1](https://github.com/espressif/esp-protocols/commits/mdns-v1.4.1) + +### Features + +- Send PTR query for mdns browse when interface is ready ([010a404a](https://github.com/espressif/esp-protocols/commit/010a404a)) + +### Bug Fixes + +- Prevent deadlock when deleting a browse request ([3f48f9ea](https://github.com/espressif/esp-protocols/commit/3f48f9ea)) +- Fix use after free reported by coverity ([25b3d5fd](https://github.com/espressif/esp-protocols/commit/25b3d5fd)) +- Fixed dead-code reported by coverity ([11846c7d](https://github.com/espressif/esp-protocols/commit/11846c7d)) + +## [1.4.0](https://github.com/espressif/esp-protocols/commits/mdns-v1.4.0) + +### Major changes + +- Fixed mdns API issues when add/remove/update records from multiple threads ([Fix services API races to directly add/remove services](https://github.com/espressif/esp-protocols/commit/8a690503)) + +### Features + +- Unit tests for add/remove/update deleg/selfhosted services ([0660ece1](https://github.com/espressif/esp-protocols/commit/0660ece1)) +- Add console command for mdns browsing ([1e8ede33](https://github.com/espressif/esp-protocols/commit/1e8ede33)) +- Console test: set instance for service ([f107dcd1](https://github.com/espressif/esp-protocols/commit/f107dcd1)) +- Console test: add subtype for service ([ee00e97b](https://github.com/espressif/esp-protocols/commit/ee00e97b)) +- Console test: set port for (delegated) srvs ([07b79abf](https://github.com/espressif/esp-protocols/commit/07b79abf)) +- Console test: add/remove TXT recs for delegated srvs ([c9a58d73](https://github.com/espressif/esp-protocols/commit/c9a58d73)) +- Console test for changing TXT records ([6b9a6ce6](https://github.com/espressif/esp-protocols/commit/6b9a6ce6)) +- Console test for add/remove delegated service APIs ([43de7e5c](https://github.com/espressif/esp-protocols/commit/43de7e5c)) +- Console test for add/remove delegated host APIs ([ce7f326a](https://github.com/espressif/esp-protocols/commit/ce7f326a)) +- Console test for lookup service APIs ([a91ead8e](https://github.com/espressif/esp-protocols/commit/a91ead8e)) +- Add linux console functional tests ([50d059af](https://github.com/espressif/esp-protocols/commit/50d059af)) +- check if the txt items is changed when browsing ([e2f0477a](https://github.com/espressif/esp-protocols/commit/e2f0477a)) + +### Bug Fixes + +- Fix mdns_delegate_hostname_add() to block until done ([2c1b1661](https://github.com/espressif/esp-protocols/commit/2c1b1661)) +- Fix API races when removing all services ([169405b5](https://github.com/espressif/esp-protocols/commit/169405b5)) +- Fix API races setting instance name for services ([643dc6d4](https://github.com/espressif/esp-protocols/commit/643dc6d4)) +- Fix API races while adding subtypes for services ([f9f234c4](https://github.com/espressif/esp-protocols/commit/f9f234c4)) +- Fix API races removing txt item for services ([3f97a822](https://github.com/espressif/esp-protocols/commit/3f97a822)) +- Fix API races adding txt item for services ([c62b920b](https://github.com/espressif/esp-protocols/commit/c62b920b)) +- Fix API races while setting txt for services ([a927bf3a](https://github.com/espressif/esp-protocols/commit/a927bf3a)) +- Fix API races while setting port for services ([99d5fb27](https://github.com/espressif/esp-protocols/commit/99d5fb27)) +- Fix services API races to directly add/remove services ([8a690503](https://github.com/espressif/esp-protocols/commit/8a690503)) +- Fix mdns mdns_lookup_service() to handle empty TXT ([d4da9cb0](https://github.com/espressif/esp-protocols/commit/d4da9cb0)) + +## [1.3.2](https://github.com/espressif/esp-protocols/commits/mdns-v1.3.2) + +### Features + +- add check of instance when handling PTR query ([6af6ca5](https://github.com/espressif/esp-protocols/commit/6af6ca5)) + +### Bug Fixes + +- Fix of mdns afl tests ([139166c](https://github.com/espressif/esp-protocols/commit/139166c)) +- remove same protocol services with different instances ([042533a](https://github.com/espressif/esp-protocols/commit/042533a)) + +## [1.3.1](https://github.com/espressif/esp-protocols/commits/mdns-v1.3.1) + +### Bug Fixes + +- free txt value len ([afd98bb](https://github.com/espressif/esp-protocols/commit/afd98bb)) + +## [1.3.0](https://github.com/espressif/esp-protocols/commits/mdns-v1.3.0) + +### Features + +- add a new mdns query mode `browse` ([af330b6](https://github.com/espressif/esp-protocols/commit/af330b6)) +- Make including mdns_console KConfigurable ([27adbfe](https://github.com/espressif/esp-protocols/commit/27adbfe)) + +### Bug Fixes + +- Schedule all queued Tx packets from timer task ([d4e693e](https://github.com/espressif/esp-protocols/commit/d4e693e)) +- add lock for some common apis ([21c84bf](https://github.com/espressif/esp-protocols/commit/21c84bf)) +- fix mdns answer append while host is invalid ([7be16bc](https://github.com/espressif/esp-protocols/commit/7be16bc)) + +## [1.2.5](https://github.com/espressif/esp-protocols/commits/mdns-v1.2.5) + +### Bug Fixes + +- Fixed build issues for targets without WiFi caps ([302b46f](https://github.com/espressif/esp-protocols/commit/302b46f)) + +## [1.2.4](https://github.com/espressif/esp-protocols/commits/mdns-v1.2.4) + +### Bug Fixes + +- Correction on 6d2c475 MDNS_PREDEF_NETIF_ETH fix ([fc59f87c4e](https://github.com/espressif/esp-protocols/commit/fc59f87c4e)) +- fix the logic of creating pcb for networking socket ([5000a9a20a](https://github.com/espressif/esp-protocols/commit/5000a9a20a)) +- fix compiling issue when disabling IPv4 ([2646dcd23a](https://github.com/espressif/esp-protocols/commit/2646dcd23a)) +- Fix compile error when MDNS_PREDEF_NETIF_ETH is defined, but ETH_ENABLED is not (#459) ([6d2c475c20](https://github.com/espressif/esp-protocols/commit/6d2c475c20)) + +## [1.2.3](https://github.com/espressif/esp-protocols/commits/mdns-v1.2.3) + +### Bug Fixes + +- fixed CI issues for host and afl tests ([4be5efc84e](https://github.com/espressif/esp-protocols/commit/4be5efc84e)) +- fix copy delegated host addr ([19fb36000c](https://github.com/espressif/esp-protocols/commit/19fb36000c)) +- enable CONFIG_ESP_WIFI_ENABLED if CONFIG_SOC_WIFI_SUPPORTED is also enabled (for ESP-IDF <= 5.1) ([d20a718320](https://github.com/espressif/esp-protocols/commit/d20a718320)) +- remove protocol_examples_common ([1ee9dae6bf](https://github.com/espressif/esp-protocols/commit/1ee9dae6bf)) +- move the example into a subdirectory ([d28232b9f8](https://github.com/espressif/esp-protocols/commit/d28232b9f8)) +- reference protocol_examples_common from IDF ([c83b76ea8f](https://github.com/espressif/esp-protocols/commit/c83b76ea8f)) + +## [1.2.2](https://github.com/espressif/esp-protocols/commits/mdns-v1.2.2) + +### Bug Fixes + +- add terminator for the getting host name ([b6a4d94](https://github.com/espressif/esp-protocols/commit/b6a4d94)) +- Enable ESP_WIFI_CONFIG when ESP-IDF <= 5.1 ([0b783c0](https://github.com/espressif/esp-protocols/commit/0b783c0)) +- set host list NULL on destroy ([ea54eef](https://github.com/espressif/esp-protocols/commit/ea54eef)) +- removed Wno-format flag and fixed formatting warnings ([c48e442](https://github.com/espressif/esp-protocols/commit/c48e442)) +- remove the the range of MDNS_MAX_SERVICES and fix issues of string functions ([3dadce2](https://github.com/espressif/esp-protocols/commit/3dadce2)) + +## [1.2.1](https://github.com/espressif/esp-protocols/commits/mdns-v1.2.1) + +### Features + +- Allow setting length of mDNS action queue in menuconfig ([28cd898](https://github.com/espressif/esp-protocols/commit/28cd898)) + +### Bug Fixes + +- fix build issue if CONFIG_ESP_WIFI_ENABLED disabled ([24f7031](https://github.com/espressif/esp-protocols/commit/24f7031)) +- added idf_component.yml for examples ([d273e10](https://github.com/espressif/esp-protocols/commit/d273e10)) +- added guard check for null pointer ([71bb461](https://github.com/espressif/esp-protocols/commit/71bb461)) + +## [1.2.0](https://github.com/espressif/esp-protocols/commits/mdns-v1.2.0) + +### Features + +- add an API for setting address to a delegated host ([ddc3eb6](https://github.com/espressif/esp-protocols/commit/ddc3eb6)) +- Add support for lwip build under linux ([588465d](https://github.com/espressif/esp-protocols/commit/588465d)) +- Allow for adding a delegated host with no address ([c562461](https://github.com/espressif/esp-protocols/commit/c562461)) +- Add APIs for looking up self hosted services and getting the self hostname ([f0df12d](https://github.com/espressif/esp-protocols/commit/f0df12d)) + +### Bug Fixes + +- Refactor freertos linux compat layers ([79a0e57](https://github.com/espressif/esp-protocols/commit/79a0e57)) +- Fix delegated service PTR response ([cab0e1d](https://github.com/espressif/esp-protocols/commit/cab0e1d)) +- Added unit tests to CI + minor fix to pass it ([c974c14](https://github.com/espressif/esp-protocols/commit/c974c14)) + +### Updated + +- docs: update documentation links ([4de5298](https://github.com/espressif/esp-protocols/commit/4de5298)) + +## [1.1.0](https://github.com/espressif/esp-protocols/commits/mdns-v1.1.0) + +### Features + +- Decouple main module from mdns-networking ([d238e93](https://github.com/espressif/esp-protocols/commit/d238e93)) + +### Bug Fixes + +- Use idf-build-apps package for building mdns ([1a0a41f](https://github.com/espressif/esp-protocols/commit/1a0a41f)) +- socket networking to init interfaces properly ([ee9b04f](https://github.com/espressif/esp-protocols/commit/ee9b04f)) +- Removed unused internal lock from mdns_server struct ([a06fb77](https://github.com/espressif/esp-protocols/commit/a06fb77)) +- Resolve conflicts only on self hosted items ([e69a9eb](https://github.com/espressif/esp-protocols/commit/e69a9eb), [#185](https://github.com/espressif/esp-protocols/issues/185)) +- Fix memory issues reported by valgrind ([0a682e7](https://github.com/espressif/esp-protocols/commit/0a682e7)) + +### Updated + +- docs(common): updated component and example links ([f48d9b2](https://github.com/espressif/esp-protocols/commit/f48d9b2)) +- Add APIs to look up delegated services ([87dcd7d](https://github.com/espressif/esp-protocols/commit/87dcd7d)) +- Fix deadly mdns crash ([4fa3023](https://github.com/espressif/esp-protocols/commit/4fa3023)) +- docs(common): improving documentation ([ca3fce0](https://github.com/espressif/esp-protocols/commit/ca3fce0)) +- append all ipv6 address in mdns answer ([5ed3e9a](https://github.com/espressif/esp-protocols/commit/5ed3e9a)) +- test(mdns): Host tests to use IDF's esp_event_stub ([537d170](https://github.com/espressif/esp-protocols/commit/537d170)) + +## [1.0.9](https://github.com/espressif/esp-protocols/commits/mdns-v1.0.9) + +### Features + +- Add reverse lookup to the example and test ([d464ed7](https://github.com/espressif/esp-protocols/commit/d464ed7)) +- Add support for IPv6 reverse query ([d4825f5](https://github.com/espressif/esp-protocols/commit/d4825f5)) + +### Bug Fixes + +- Reintroduce missing CHANGELOGs ([200cbb3](https://github.com/espressif/esp-protocols/commit/200cbb3)) +- use semaphore instead of task notification bits (IDFGH-9380) ([73f2800](https://github.com/espressif/esp-protocols/commit/73f2800), [IDF#10754](https://github.com/espressif/esp-idf/issues/10754)) + +### Updated + +- ci(common): force scoping commit messages with components ([c55fcc0](https://github.com/espressif/esp-protocols/commit/c55fcc0)) +- Add homepage URL and License to all components ([ef3f0ee](https://github.com/espressif/esp-protocols/commit/ef3f0ee)) +- docs: fix of mdns link translation ([1c850dd](https://github.com/espressif/esp-protocols/commit/1c850dd)) +- unite all tags under common structure py test: update tags under common structure ([c6db3ea](https://github.com/espressif/esp-protocols/commit/c6db3ea)) + +## [1.0.8](https://github.com/espressif/esp-protocols/commits/b9b4a75) + +### Features + +- Add support for IPv4 reverse query ([b87bef5](https://github.com/espressif/esp-protocols/commit/b87bef5)) + +### Bug Fixes + +- Host test with IDFv5.1 ([fb8a2f0](https://github.com/espressif/esp-protocols/commit/fb8a2f0)) +- Remove strict mode as it's invalid ([d0c9070](https://github.com/espressif/esp-protocols/commit/d0c9070)) +- Allow setting instance name only after hostname set ([a8339e4](https://github.com/espressif/esp-protocols/commit/a8339e4), [#190](https://github.com/espressif/esp-protocols/issues/190)) +- Make unit test executable with pytest ([12cfcb5](https://github.com/espressif/esp-protocols/commit/12cfcb5)) +- AFL port layer per IDF-latest changes ([0247926](https://github.com/espressif/esp-protocols/commit/0247926)) + +### Updated + +- bump the component version to 1.0.8 ([b9b4a75](https://github.com/espressif/esp-protocols/commit/b9b4a75)) +- Make reverse query conditional per Kconfig ([91134f1](https://github.com/espressif/esp-protocols/commit/91134f1)) +- Added badges with version of components to the respective README files ([e4c8a59](https://github.com/espressif/esp-protocols/commit/e4c8a59)) +- fix some coverity reported issues ([c73c797](https://github.com/espressif/esp-protocols/commit/c73c797)) +- Examples: using pytest.ini from top level directory ([aee016d](https://github.com/espressif/esp-protocols/commit/aee016d)) +- mDNS: test_app pytest migration ([f71f61f](https://github.com/espressif/esp-protocols/commit/f71f61f)) +- CI: fixing the files to be complient with pre-commit hooks ([945bd17](https://github.com/espressif/esp-protocols/commit/945bd17)) +- prevent crash when hostname is null ([3498e86](https://github.com/espressif/esp-protocols/commit/3498e86)) +- Example tests integration ([a045c1c](https://github.com/espressif/esp-protocols/commit/a045c1c)) +- Replace hardcoded TTL values with named defines ([bb4c002](https://github.com/espressif/esp-protocols/commit/bb4c002)) +- Fix add_service() to report error if no-hostname ([656ab21](https://github.com/espressif/esp-protocols/commit/656ab21)) + + +## [1.0.7](https://github.com/espressif/esp-protocols/commits/088f7ac) + +### Updated + +- bump up the component version ([088f7ac](https://github.com/espressif/esp-protocols/commit/088f7ac)) +- fix IPV4 only build and also update CI configuration ([e079f8b](https://github.com/espressif/esp-protocols/commit/e079f8b)) +- add test configuration for IPV6 disabled build ([330332a](https://github.com/espressif/esp-protocols/commit/330332a)) + + +## [1.0.6](https://github.com/espressif/esp-protocols/commits/48c157b) + +### Bug Fixes + +- Example makefile to add only mdns as extra comps ([d74c296](https://github.com/espressif/esp-protocols/commit/d74c296)) +- ignore authoritative flag on reception ([415e04a](https://github.com/espressif/esp-protocols/commit/415e04a)) + +### Updated + +- fix build issue with CONFIG_LWIP_IPV6 disabled ([48c157b](https://github.com/espressif/esp-protocols/commit/48c157b)) +- fix bit order issue in DNS header flags ([c4e85bd](https://github.com/espressif/esp-protocols/commit/c4e85bd)) +- updated package version to 0.1.19 ([469f953](https://github.com/espressif/esp-protocols/commit/469f953)) + + +## [1.0.5](https://github.com/espressif/esp-protocols/commits/36de9af) + +### Features + +- Define explicit dependencies on esp-wifi ([36de9af](https://github.com/espressif/esp-protocols/commit/36de9af)) + +### Updated + +- bugfix: mdns IPv6 address convert error ([238ee96](https://github.com/espressif/esp-protocols/commit/238ee96)) + + +## [1.0.4](https://github.com/espressif/esp-protocols/commits/57afa38) + +### Updated + +- Bump asio/mdns/esp_websocket_client versions ([57afa38](https://github.com/espressif/esp-protocols/commit/57afa38)) +- ignore format warnings ([d66f9dc](https://github.com/espressif/esp-protocols/commit/d66f9dc)) +- Fix test_app build ([0b102f6](https://github.com/espressif/esp-protocols/commit/0b102f6)) + + +## [1.0.3](https://github.com/espressif/esp-protocols/commits/4868689) + +### Updated + +- Updated mDNS to explicitely use esp-eth dependency if needed ([4868689](https://github.com/espressif/esp-protocols/commit/4868689), [IDF@5e19b9c](https://github.com/espressif/esp-idf/commit/5e19b9c9518ae253d82400ab24b86af8af832425)) + + +## [1.0.2](https://github.com/espressif/esp-protocols/commits/8fe2a3a) + +### Features + +- fix bug when clean action memory ([81c219d](https://github.com/espressif/esp-protocols/commit/81c219d), [IDF@3d4deb9](https://github.com/espressif/esp-idf/commit/3d4deb972620cae8e8ce4d0050153cc6f39db372)) + +### Bug Fixes + +- add the maximum number of services ([0191d6f](https://github.com/espressif/esp-protocols/commit/0191d6f), [IDF@ba458c6](https://github.com/espressif/esp-idf/commit/ba458c69cfb2f18478d73690c289b09641c62004)) +- fix the exception when remove one of multiple service ([b26c866](https://github.com/espressif/esp-protocols/commit/b26c866), [IDF@696d733](https://github.com/espressif/esp-idf/commit/696d733eb04ee98f764dffdc82bcef51a724c9c6)) + +### Updated + +- Minor fixes here and there ([8fe2a3a](https://github.com/espressif/esp-protocols/commit/8fe2a3a)) +- mDNS: Initial version based on IDF 5.0 ([b6b20ad](https://github.com/espressif/esp-protocols/commit/b6b20ad)) +- soc: moved kconfig options out of the target component. ([4a52cf2](https://github.com/espressif/esp-protocols/commit/4a52cf2), [IDF@d287209](https://github.com/espressif/esp-idf/commit/d2872095f93ed82fb91c776081bc1d032493d93e)) +- cmake: fix issue with passing cxx_std option for GCC 11, a common workaround ([87c2699](https://github.com/espressif/esp-protocols/commit/87c2699), [IDF@ea0d212](https://github.com/espressif/esp-idf/commit/ea0d2123c806bd0ad77bc49843ee905cf9be65ff)) +- kconfig: Changed default values of bool configs - Some bool configs were using default values true and false, instead of y and n. ([eb536a7](https://github.com/espressif/esp-protocols/commit/eb536a7), [IDF@25c5c21](https://github.com/espressif/esp-idf/commit/25c5c214f38ca690b03533e12fb5a4d774c7eae0)) +- esp_netif: Remove tcpip_adapter compatibility layer ([3e93ea9](https://github.com/espressif/esp-protocols/commit/3e93ea9), [IDF@795b7ed](https://github.com/espressif/esp-idf/commit/795b7ed993784e3134195e12b0978504d83dfd56)) +- Fix copyright messages, update API descrition ([2c764b1](https://github.com/espressif/esp-protocols/commit/2c764b1), [IDF@42ba8a8](https://github.com/espressif/esp-idf/commit/42ba8a8338fd5efd82498a5989fc5c105938d447)) +- Add API to control custom network interfaces ([f836ae7](https://github.com/espressif/esp-protocols/commit/f836ae7), [IDF@b02468d](https://github.com/espressif/esp-idf/commit/b02468dc98d614f931d14cd8b5e2373ca51fb18d)) +- CI/mdns: Fix fuzzer build ([4b5f24f](https://github.com/espressif/esp-protocols/commit/4b5f24f), [IDF@98e9426](https://github.com/espressif/esp-idf/commit/98e9426b660a6e825f811cccd45a0722cc801ccd)) +- Add support for registering custom netif ([30f37c0](https://github.com/espressif/esp-protocols/commit/30f37c0), [IDF@bec42ff](https://github.com/espressif/esp-idf/commit/bec42ff85d5091d71e1cb1063bea20d7c6ac8c76)) +- Indicate interface using esp_netif in search results ([ddc58e8](https://github.com/espressif/esp-protocols/commit/ddc58e8), [IDF@f8495f1](https://github.com/espressif/esp-idf/commit/f8495f1e86de9a8e7d046bf13d0ca04775041b4c)) +- Use predefined interfaces to prepare for custom netifs ([fa951bf](https://github.com/espressif/esp-protocols/commit/fa951bf), [IDF@f90b3b7](https://github.com/espressif/esp-idf/commit/f90b3b798b446382d848f8c55c5e1653c81871cd)) +- Prepare for dynamic esp-netif support ([605d1fa](https://github.com/espressif/esp-protocols/commit/605d1fa), [IDF@f9892f7](https://github.com/espressif/esp-idf/commit/f9892f77b88ba77dc6608ba746175f6dc64a7607)) +- esp_hw_support/esp_system: Re-evaluate header inclusions and include directories ([58bf218](https://github.com/espressif/esp-protocols/commit/58bf218), [IDF@a9fda54](https://github.com/espressif/esp-idf/commit/a9fda54d39d1321005c3bc9b3cc268d0b7e9f052)) +- system: move kconfig options out of target component ([ec491ec](https://github.com/espressif/esp-protocols/commit/ec491ec), [IDF@bb88338](https://github.com/espressif/esp-idf/commit/bb88338118957c2214a4c0a33cd4a152e2e1f8ba)) +- Update to drop our own packet if bounced back ([94ae672](https://github.com/espressif/esp-protocols/commit/94ae672), [IDF@b5149e3](https://github.com/espressif/esp-idf/commit/b5149e3ee73728f790798e6757d732fe426e21c7)) +- Fix potential read behind parsed packet ([e5a3a3d](https://github.com/espressif/esp-protocols/commit/e5a3a3d), [IDF@51a5de2](https://github.com/espressif/esp-idf/commit/51a5de2525d0e82adea2e298a0edcc9b2dee5edd)) +- Fix memleak when adding delegated host ([7710ea9](https://github.com/espressif/esp-protocols/commit/7710ea9), [IDF@9cbdb87](https://github.com/espressif/esp-idf/commit/9cbdb8767bdf6e9745e895b2c5af74d0376965e7)) +- Fix null-service issue when parsing packets ([034c55e](https://github.com/espressif/esp-protocols/commit/034c55e), [IDF#8307](https://github.com/espressif/esp-idf/issues/8307), [IDF@a57be7b](https://github.com/espressif/esp-idf/commit/a57be7b7d1135ddb29f9da636e9ad315f7fa1fa7)) +- Update fuzzer test (add delegation, check memory) ([ec03fec](https://github.com/espressif/esp-protocols/commit/ec03fec), [IDF@2c10071](https://github.com/espressif/esp-idf/commit/2c1007156e01b4707b5c89d73cad05c0eef0264f)) +- Remove legacy esp_event API ([5909e9e](https://github.com/espressif/esp-protocols/commit/5909e9e), [IDF@e46aa51](https://github.com/espressif/esp-idf/commit/e46aa515bdf5606a3d868f1034774d5fc96904b8)) +- added missing includes ([82e2a5d](https://github.com/espressif/esp-protocols/commit/82e2a5d), [IDF@28d09c7](https://github.com/espressif/esp-idf/commit/28d09c7dbe145ffa6a7dd90531062d4f7669a9c8)) +- Clear notification value in mdns_hostname_set ([48e4d40](https://github.com/espressif/esp-protocols/commit/48e4d40), [IDF@83a4ddb](https://github.com/espressif/esp-idf/commit/83a4ddbd250e2b386bccabb4705d4c58c1a22bcb)) +- esp_timer: remove legacy ESP32 FRC timer implementation. ([ac6dcb6](https://github.com/espressif/esp-protocols/commit/ac6dcb6), [IDF@edb76f1](https://github.com/espressif/esp-idf/commit/edb76f14d6b3e925568ff04a87befe733ecc4517)) +- freertos: Remove legacy data types ([085dbd8](https://github.com/espressif/esp-protocols/commit/085dbd8), [IDF@57fd78f](https://github.com/espressif/esp-idf/commit/57fd78f5baf93a368a82cf4b2e00ca17ffc09115)) +- Tools: Custom baud-rate setup is not possible for IDF Monitor from menuconfig anymore ([f78e8cf](https://github.com/espressif/esp-protocols/commit/f78e8cf), [IDF@36a4011](https://github.com/espressif/esp-idf/commit/36a4011ff8985bfbae08ba0272194e6c3ef93bbf)) +- Use memcpy() for copy to support non-text TXTs ([6cdf5ee](https://github.com/espressif/esp-protocols/commit/6cdf5ee), [IDF@6aefe9c](https://github.com/espressif/esp-idf/commit/6aefe9c18563ed567d384a956cf02b6f57d6894c)) +- Support for null-value TXT records ([fcb5515](https://github.com/espressif/esp-protocols/commit/fcb5515), [IDF#8267](https://github.com/espressif/esp-idf/issues/8267), [IDF@23c2db4](https://github.com/espressif/esp-idf/commit/23c2db406dee8df09dbdba21cb7eef9fbca8bf27)) +- Fix alloc issue if TXT has empty value ([9fdbe5f](https://github.com/espressif/esp-protocols/commit/9fdbe5f), [IDF@205f6ba](https://github.com/espressif/esp-idf/commit/205f6ba8541e12d958c7c56af5a7136090f12a0e)) +- Fix random crash when defalt service instance queried ([20e6e9e](https://github.com/espressif/esp-protocols/commit/20e6e9e), [IDF@f46dffc](https://github.com/espressif/esp-idf/commit/f46dffca627e9578e49a510580f9754ec1e27e2e)) +- Fix minor memory leaks when creating services ([c588263](https://github.com/espressif/esp-protocols/commit/c588263), [IDF@fad62cc](https://github.com/espressif/esp-idf/commit/fad62cc1ed3dce63b58297172a72a489d7af2d9d)) +- Fix mDNS memory leak ([6258edf](https://github.com/espressif/esp-protocols/commit/6258edf), [IDF@119b4a9](https://github.com/espressif/esp-idf/commit/119b4a9dd12cf89cc5eaf63f8aa19730607ef30b)) +- Fix mDNS memory leak ([c8b0d5e](https://github.com/espressif/esp-protocols/commit/c8b0d5e), [IDF@f5ffd53](https://github.com/espressif/esp-idf/commit/f5ffd53aeb402afc1333a98168bb2fa35d7cdc77)) +- Use multi/uni-cast types in API ([5252b1d](https://github.com/espressif/esp-protocols/commit/5252b1d), [IDF@125c312](https://github.com/espressif/esp-idf/commit/125c3125524c71f4f48f635eda12e22fa3bca500)) +- Allow for unicast PTR queries ([4e11cc8](https://github.com/espressif/esp-protocols/commit/4e11cc8), [IDF@7eeeb01](https://github.com/espressif/esp-idf/commit/7eeeb01ea705745b027bd8bc11d2b142418e9927)) +- Fix potential null deref for ANY query type ([7af91ec](https://github.com/espressif/esp-protocols/commit/7af91ec), [IDF@99dd8ee](https://github.com/espressif/esp-idf/commit/99dd8eedb1a0e957f5f74344e3e4172e61c29ef8)) +- Make fuzzer layers compatible with llvm>=6 ([01256d3](https://github.com/espressif/esp-protocols/commit/01256d3), [IDF@1882cbe](https://github.com/espressif/esp-idf/commit/1882cbe44e6140bebb2d27dc18af06dfcb0157f5)) +- Fix copyright ([5a2d4ea](https://github.com/espressif/esp-protocols/commit/5a2d4ea), [IDF@c83678f](https://github.com/espressif/esp-idf/commit/c83678f64fe27844fc28050bde6433ccb04a0704)) +- Add mDNS miss comment ([9de3f53](https://github.com/espressif/esp-protocols/commit/9de3f53), [IDF@08e0813](https://github.com/espressif/esp-idf/commit/08e081340d9d76d1244e9f2dc527e5ae370b1fbe)) +- freertos: remove FREERTOS_ASSERT option ([bcabc8e](https://github.com/espressif/esp-protocols/commit/bcabc8e), [IDF@7255497](https://github.com/espressif/esp-idf/commit/72554971467a5edc9bd6e390cf8fe7b05e6ade81)) +- Minor err print fix in socket-networking layer ([dfb27b3](https://github.com/espressif/esp-protocols/commit/dfb27b3), [IDF@f1b8f5c](https://github.com/espressif/esp-idf/commit/f1b8f5c1023df7d649161bc76f2bcc9a8f8f4d8b)) +- unified errno format ([076c095](https://github.com/espressif/esp-protocols/commit/076c095), [IDF@87506f4](https://github.com/espressif/esp-idf/commit/87506f46e2922710f48a6b96ca75e53543ff45c4)) +- always send A/AAAA records in announcements ([7dd0bc1](https://github.com/espressif/esp-protocols/commit/7dd0bc1), [IDF@456f80b](https://github.com/espressif/esp-idf/commit/456f80b754ebd0bd74e02c7febdf461c6b573b7a)) +- filter instance name for ANY queries ([7e82a7c](https://github.com/espressif/esp-protocols/commit/7e82a7c), [IDF@5d0c473](https://github.com/espressif/esp-idf/commit/5d0c47303dd9ead0f2ad291dca1d4b7ce4e23b2b)) +- Fix potential null deref reported by fuzzer test ([ae381b7](https://github.com/espressif/esp-protocols/commit/ae381b7), [IDF@cb5653f](https://github.com/espressif/esp-idf/commit/cb5653fd940a9cd41e8554a6d753fab46e0459d7)) +- Minor fix of API description and API usage ([941dc5c](https://github.com/espressif/esp-protocols/commit/941dc5c), [IDF@c297301](https://github.com/espressif/esp-idf/commit/c297301ecc350f8315d7eaf78c72b4aba68d422a)) +- Added results count to MDNS ([525c649](https://github.com/espressif/esp-protocols/commit/525c649), [IDF@f391d61](https://github.com/espressif/esp-idf/commit/f391d610e8185631b5361dc6c844c4c04aac30b1)) +- fix mdns server instance mismatch ([f0839d9](https://github.com/espressif/esp-protocols/commit/f0839d9), [IDF@6173dd7](https://github.com/espressif/esp-idf/commit/6173dd78097216261277c20ebd92a53c68c47f89)) +- support multiple instance for mdns service txt set ([69902ea](https://github.com/espressif/esp-protocols/commit/69902ea), [IDF@50f6302](https://github.com/espressif/esp-idf/commit/50f6302c5d7c0498fa1baa6fd6129d8233971a81)) +- fix wrong PTR record count ([d0bbe88](https://github.com/espressif/esp-protocols/commit/d0bbe88), [IDF@5d3f815](https://github.com/espressif/esp-idf/commit/5d3f8157e0e481363ef93d54a29d957fc91cca86)) +- Build & config: Remove leftover files from the unsupported "make" build system ([4a9d55e](https://github.com/espressif/esp-protocols/commit/4a9d55e), [IDF@766aa57](https://github.com/espressif/esp-idf/commit/766aa5708443099f3f033b739cda0e1de101cca6)) +- Build & config: Remove the "make" build system ([be2a924](https://github.com/espressif/esp-protocols/commit/be2a924), [IDF@9c1d4f5](https://github.com/espressif/esp-idf/commit/9c1d4f5b549d6a7125e5c7c323c80d37361991cb)) +- freertos: update freertos folder structure to match upstream ([76fcd41](https://github.com/espressif/esp-protocols/commit/76fcd41), [IDF@4846222](https://github.com/espressif/esp-idf/commit/48462221029c7da4b1ea233e9e781cd57ff91c7e)) +- support service subtype ([fd8499c](https://github.com/espressif/esp-protocols/commit/fd8499c), [IDF#5508](https://github.com/espressif/esp-idf/issues/5508), [IDF@e7e8610](https://github.com/espressif/esp-idf/commit/e7e8610f563e0b8532a093ea8b803f0eb132fd0e)) +- Fix parsing non-standard queries ([38b4fe2](https://github.com/espressif/esp-protocols/commit/38b4fe2), [IDF#7694](https://github.com/espressif/esp-idf/issues/7694), [IDF@d16f9ba](https://github.com/espressif/esp-idf/commit/d16f9bade5beab3785677dd5b39ebc4e9c895008)) +- allow mutiple instances with same service type ([b266062](https://github.com/espressif/esp-protocols/commit/b266062), [IDF@b7a99f4](https://github.com/espressif/esp-idf/commit/b7a99f46587a69a2cd07e7616c3bb30b7b1a6edf)) +- Update copyright header ([5e087d8](https://github.com/espressif/esp-protocols/commit/5e087d8), [IDF@2a2b95b](https://github.com/espressif/esp-idf/commit/2a2b95b9c22bc5090d87a4f4317288b64b14fcd9)) +- Fix potential null dereference identified by fuzzer tests ([91a3d95](https://github.com/espressif/esp-protocols/commit/91a3d95), [IDF@e7dabb1](https://github.com/espressif/esp-idf/commit/e7dabb14f7c8fd9bd2bea55d8f1accc65323a1c0)) +- components/bt: move config BT_RESERVE_DRAM from bluedroid to ESP32 controller ([6d6dd2b](https://github.com/espressif/esp-protocols/commit/6d6dd2b), [IDF@b310c06](https://github.com/espressif/esp-idf/commit/b310c062cd25f249e00dd03dd27baed783921630)) +- add notification callback for async APIs ([52306e9](https://github.com/espressif/esp-protocols/commit/52306e9), [IDF@986603c](https://github.com/espressif/esp-idf/commit/986603cf07413b46c88c76c324bf500edcfb6171)) +- add more mdns result attributes ([d37ab6d](https://github.com/espressif/esp-protocols/commit/d37ab6d), [IDF@76ec76c](https://github.com/espressif/esp-idf/commit/76ec76c12c871554147343bb7141da1e5de58011)) +- Add host test using linux target ([5c55ea6](https://github.com/espressif/esp-protocols/commit/5c55ea6), [IDF@fc7e2d9](https://github.com/espressif/esp-idf/commit/fc7e2d9e908f61fb4b852cfae72aa5ff7c662ebc)) +- Implement mdns_networking using BSD sockets ([0c71c7b](https://github.com/espressif/esp-protocols/commit/0c71c7b), [IDF@73dfe84](https://github.com/espressif/esp-idf/commit/73dfe84bf295a850edfad39b6b097a71f15964dc)) +- fix crash when adding services without hostname set ([4c368c0](https://github.com/espressif/esp-protocols/commit/4c368c0), [IDF@5e98772](https://github.com/espressif/esp-idf/commit/5e98772eaf7e50d96cf2e6ecdfedcd928b61c864)) +- Fix fuzzer IDF-mock layer ([af22753](https://github.com/espressif/esp-protocols/commit/af22753), [IDF@619235c](https://github.com/espressif/esp-idf/commit/619235c2ee5a1fe8411bd2be2de8798209f95902)) +- Clean the main mdns module from lwip dependencies ([b0957e7](https://github.com/espressif/esp-protocols/commit/b0957e7), [IDF@54e3294](https://github.com/espressif/esp-idf/commit/54e329444a5dd19c51e84b5f1e16455a0f1c6225)) +- Add asynchronous query API ([47c7266](https://github.com/espressif/esp-protocols/commit/47c7266), [IDF#7090](https://github.com/espressif/esp-idf/issues/7090), [IDF@d81482d](https://github.com/espressif/esp-idf/commit/d81482d699232b22f4a5cbee2a76199a5285dadb)) +- Fix crashes reported by the fuzzer tests ([40da0d2](https://github.com/espressif/esp-protocols/commit/40da0d2), [IDF@4a2e726](https://github.com/espressif/esp-idf/commit/4a2e72677c6fb7681a7e2acd1a878d3deb114079)) +- mdns/fuzzer: Fix non-instrumentation test to reproduce fuzzer issues ([5f6b6f9](https://github.com/espressif/esp-protocols/commit/5f6b6f9), [IDF@dae8033](https://github.com/espressif/esp-idf/commit/dae803335e6bc6d9751a360cd3f675ce4027853b)) +- return ESP_OK rather than ERR_OK in API functions ([8a12082](https://github.com/espressif/esp-protocols/commit/8a12082), [IDF@2386113](https://github.com/espressif/esp-idf/commit/2386113972ee51ea93e9740d8c34bfe9289ce909)) +- fix memory leak in mdns_free when adding delegated hostnames ([46f28a8](https://github.com/espressif/esp-protocols/commit/46f28a8), [IDF@0baee93](https://github.com/espressif/esp-idf/commit/0baee932111268c4a2103e1c1adeb7d99914a937)) +- Support for One-Shot mDNS queries ([5a81eae](https://github.com/espressif/esp-protocols/commit/5a81eae), [IDF@f167238](https://github.com/espressif/esp-idf/commit/f167238fac37818aed75dc689eed54ad47528ab9)) +- allow explicit txt value length ([2ddaee2](https://github.com/espressif/esp-protocols/commit/2ddaee2), [IDF@b4e0088](https://github.com/espressif/esp-idf/commit/b4e0088b68321acc4698b01faec7e2ffbe1e37c1)) +- Fix crashes reported by the fuzzer ([27fc285](https://github.com/espressif/esp-protocols/commit/27fc285), [IDF@79ba738](https://github.com/espressif/esp-idf/commit/79ba738626d643d8c6f32bdcd455e0d2476f94c7)) +- Minor correction of the test code ([93e6efe](https://github.com/espressif/esp-protocols/commit/93e6efe), [IDF@7d76245](https://github.com/espressif/esp-idf/commit/7d762451731cb305c3b090509827740f0195a496)) +- Fix fuzzer from miss-interpreting adding services as timeouts ([bc4cda8](https://github.com/espressif/esp-protocols/commit/bc4cda8), [IDF@14099fe](https://github.com/espressif/esp-idf/commit/14099fe15efb1b0cde0a8370096c55bba62ff937)) +- fix test script delayed response ([8a8d58d](https://github.com/espressif/esp-protocols/commit/8a8d58d), [IDF@a4f2639](https://github.com/espressif/esp-idf/commit/a4f263948c35c13340b6f4b59a649c5073787d5e)) +- fix wrong SRV/PTR record handling ([402baeb](https://github.com/espressif/esp-protocols/commit/402baeb), [IDF@e613555](https://github.com/espressif/esp-idf/commit/e6135552d26480e39e11632437020535b1667b7a)) +- fix wrong service hostname after mangling ([9fa25ef](https://github.com/espressif/esp-protocols/commit/9fa25ef), [IDF@439b31d](https://github.com/espressif/esp-idf/commit/439b31d065eddfdfb6eb4cf9c00454edfebc3d9b)) +- fix empty address change announce packets ([121b525](https://github.com/espressif/esp-protocols/commit/121b525), [IDF@7bbb72d](https://github.com/espressif/esp-idf/commit/7bbb72d86540f04d37b0e2c4efb6dc66ee9c9ea0)) +- fix mdns probe/reply behavior ([418fb60](https://github.com/espressif/esp-protocols/commit/418fb60), [IDF@d2a5d25](https://github.com/espressif/esp-idf/commit/d2a5d25984432d149ca31aea4a0d177f3509dd7b)) +- make delegate host address a list ([4049b3b](https://github.com/espressif/esp-protocols/commit/4049b3b), [IDF@2d34352](https://github.com/espressif/esp-idf/commit/2d34352f3db0fa71366a838933a29138a90eb2af)) +- add remove delegate host api ([c882119](https://github.com/espressif/esp-protocols/commit/c882119), [IDF@2174693](https://github.com/espressif/esp-idf/commit/2174693096b73ce93261611c44ecba647cd01859)) +- add mdns delegation ([1eb5df9](https://github.com/espressif/esp-protocols/commit/1eb5df9), [IDF@401ff56](https://github.com/espressif/esp-idf/commit/401ff56cc1ad1d11284143a348cc0c0e4a363e98)) +- fix memory free issue when repeating the query in reply ([b62b4b3](https://github.com/espressif/esp-protocols/commit/b62b4b3), [IDF@5f244c8](https://github.com/espressif/esp-idf/commit/5f244c86f29da46c17610563a245d1663a46b439)) +- Fix of crash when wifi interface get deleted and mdns receives the packets ([4d8aec1](https://github.com/espressif/esp-protocols/commit/4d8aec1), [IDF#6973](https://github.com/espressif/esp-idf/issues/6973), [IDF@03de74a](https://github.com/espressif/esp-idf/commit/03de74a728d4b278f55e1fc30e0425483b806e80)) +- Docs: Added README.md for lwip fuzzer tests ([6d64910](https://github.com/espressif/esp-protocols/commit/6d64910), [IDF@53c18a8](https://github.com/espressif/esp-idf/commit/53c18a85db104bb37ebeadec2faf5d42d764d0f9)) +- Fixed the ip header TTL to be correctly set to 255 ([ab3fa69](https://github.com/espressif/esp-protocols/commit/ab3fa69), [IDF@5cce919](https://github.com/espressif/esp-idf/commit/5cce919cbef87f543bb9f5275b77b97b3b1ea67e)) +- Fix parsing answers with questions when instance name not set ([c3a5826](https://github.com/espressif/esp-protocols/commit/c3a5826), [IDF#6598](https://github.com/espressif/esp-idf/issues/6598), [IDF@3404945](https://github.com/espressif/esp-idf/commit/34049454dfaf5132d9b258ef4d04921befc8997b)) +- Fix the resolver to correctly parse it's own non-strict answers ([cbcbe4f](https://github.com/espressif/esp-protocols/commit/cbcbe4f), [IDF@b649603](https://github.com/espressif/esp-idf/commit/b649603a0d70ec804567f57752c3eddaed56198f)) +- Add MDNS_STRICT_MODE config option ([adc3430](https://github.com/espressif/esp-protocols/commit/adc3430), [IDF@0eee315](https://github.com/espressif/esp-idf/commit/0eee31546dd4e6df0d1c1cc2740da0675dffb4bf)) +- freertos: common config header ([c30617d](https://github.com/espressif/esp-protocols/commit/c30617d), [IDF@39cf818](https://github.com/espressif/esp-idf/commit/39cf818838b0259b3e00b3c198ad47b4add41939)) +- Removed freeRTOS dependancies from fuzzer tests ([1e5eeb1](https://github.com/espressif/esp-protocols/commit/1e5eeb1), [IDF@5571694](https://github.com/espressif/esp-idf/commit/55716945a9908e057743d69e1d59399df03e49bd)) +- mDNS: Updated APIs description and shows the warning when hostname contains domain name during the query ([22c7c0a](https://github.com/espressif/esp-protocols/commit/22c7c0a), [IDF#6590](https://github.com/espressif/esp-idf/issues/6590), [IDF@9f8d2b9](https://github.com/espressif/esp-idf/commit/9f8d2b944d2b3736a012e0dff1a8459b6941d295)) +- components: Use CONFIG_LWIP_IPV6 to strip IPv6 function in components ([1623c0e](https://github.com/espressif/esp-protocols/commit/1623c0e), [IDF@da58235](https://github.com/espressif/esp-idf/commit/da58235a0ee262ff552c5f1155d531b5c31e8de6)) +- add bound check when setting interface as duplicate ([b114ed6](https://github.com/espressif/esp-protocols/commit/b114ed6), [IDF@2b9d2c0](https://github.com/espressif/esp-idf/commit/2b9d2c06f54924b680c41ae641978c8d81612f65)) +- mDNS: Fix of text length calculation when detecting a collision ([2ffd223](https://github.com/espressif/esp-protocols/commit/2ffd223), [IDF@be0ae1e](https://github.com/espressif/esp-idf/commit/be0ae1ebbbe9fae6ecf7de09e8d50cba063b61f4)) +- global: fix sign-compare warnings ([1fe901f](https://github.com/espressif/esp-protocols/commit/1fe901f), [IDF@753a929](https://github.com/espressif/esp-idf/commit/753a9295259126217a9fe6ef1c5e9da21e9b4e28)) +- lwip: Moved default SNTP API to esp_sntp.h ([2cf9fd8](https://github.com/espressif/esp-protocols/commit/2cf9fd8), [IDF@76f6dd6](https://github.com/espressif/esp-idf/commit/76f6dd6214ca583b1a94c7c553ccac739a27f6d5)) +- Allow resolve its own non-strict answers ([89439e0](https://github.com/espressif/esp-protocols/commit/89439e0), [IDF#6190](https://github.com/espressif/esp-idf/issues/6190), [IDF@0693e17](https://github.com/espressif/esp-idf/commit/0693e172de392086b9bfd8cf1474d8d133af3298)) +- mDNS: Fix of collision detection during txt length calculation ([becd5d0](https://github.com/espressif/esp-protocols/commit/becd5d0), [IDF#6114](https://github.com/espressif/esp-idf/issues/6114), [IDF@f33772c](https://github.com/espressif/esp-idf/commit/f33772c96037c795366e60082bdbbefe2a69165f)) +- esp32c3: Apply one-liner/small changes for ESP32-C3 ([0d7a309](https://github.com/espressif/esp-protocols/commit/0d7a309), [IDF@5228d9f](https://github.com/espressif/esp-idf/commit/5228d9f9ced16118d87326f94d9f9dfd411e0be9)) +- test: fix several test build error ([1fdffbb](https://github.com/espressif/esp-protocols/commit/1fdffbb), [IDF@b7ecccd](https://github.com/espressif/esp-idf/commit/b7ecccd9010f1deaba83de54374231c3c7f5b472)) +- freertos: Add RISC-V port ([988d120](https://github.com/espressif/esp-protocols/commit/988d120), [IDF@87e13ba](https://github.com/espressif/esp-idf/commit/87e13baaf12fe6deae715d95e912a310fea4ba88)) +- Fix wrong mdns source address if lwIP IPv6 zones disabled ([fd47df3](https://github.com/espressif/esp-protocols/commit/fd47df3), [IDF@7ac9761](https://github.com/espressif/esp-idf/commit/7ac97616c119e4d2f4cdd377dfc5abbf75ec5e30)) +- Whitespace: Automated whitespace fixes (large commit) ([2cb3a6e](https://github.com/espressif/esp-protocols/commit/2cb3a6e), [IDF@66fb5a2](https://github.com/espressif/esp-idf/commit/66fb5a29bbdc2482d67c52e6f66b303378c9b789)) +- test_compile_fuzzers: Fix include paths for host build ([825652f](https://github.com/espressif/esp-protocols/commit/825652f), [IDF@98a0cc7](https://github.com/espressif/esp-idf/commit/98a0cc783f701b238bea232b53250a538d34920a)) +- CI: Add a test to pre-check fuzzer tests compilation before weekly run ([fc53888](https://github.com/espressif/esp-protocols/commit/fc53888), [IDF@637f5c0](https://github.com/espressif/esp-idf/commit/637f5c0a6842c42ee6cf7f41d3c5ae0cb28a68af)) +- soc: descriptive part occupy whole component ([7635c04](https://github.com/espressif/esp-protocols/commit/7635c04), [IDF@79887fd](https://github.com/espressif/esp-idf/commit/79887fdc6c3d9a2e509cc189bb43c998d3f0f4ee)) +- Coredump config option rename throughout IDF ([d5fe42b](https://github.com/espressif/esp-protocols/commit/d5fe42b), [IDF@20af94f](https://github.com/espressif/esp-idf/commit/20af94ff53c5147a76342800d007a6c49be50a7b)) +- mdns, dns, dhcp, dhcps: update fuzzer test to work in CI ([e0bc60a](https://github.com/espressif/esp-protocols/commit/e0bc60a), [IDF@a43c06a](https://github.com/espressif/esp-idf/commit/a43c06a592bcf9404297b22268c33bb7a246632c)) +- cmock: added cmock as component ([9772e49](https://github.com/espressif/esp-protocols/commit/9772e49), [IDF@20c068e](https://github.com/espressif/esp-idf/commit/20c068ef3b49999387896b90f8011b02f718485f)) +- Support queries in responses in mDNS non-strict mode ([6021a88](https://github.com/espressif/esp-protocols/commit/6021a88), [IDF#5521](https://github.com/espressif/esp-idf/issues/5521), [IDF@bcfa36d](https://github.com/espressif/esp-idf/commit/bcfa36db8ffff997f1f95eaf6b011ffc4d46a10f)) +- Fix include query ID in reponses ([78f71ec](https://github.com/espressif/esp-protocols/commit/78f71ec), [IDF#5574](https://github.com/espressif/esp-idf/issues/5574), [IDF@f62e321](https://github.com/espressif/esp-idf/commit/f62e321d87c1d520cccca951715c27730e06607a)) +- Allow config mDNS task stack size ([3319844](https://github.com/espressif/esp-protocols/commit/3319844), [IDF@cf7e48c](https://github.com/espressif/esp-idf/commit/cf7e48c779edd84c3f99d5e8ed81027932302382)) +- Remove mbedtls dependency ([ac70c9a](https://github.com/espressif/esp-protocols/commit/ac70c9a), [IDF@f4a4549](https://github.com/espressif/esp-idf/commit/f4a4549a344e7ff2444a188adbebbc136b47a7bb)) +- limit the GOT_IP6_EVENT to only known network interfaces ([2b7d43e](https://github.com/espressif/esp-protocols/commit/2b7d43e), [IDF@ab8cab1](https://github.com/espressif/esp-idf/commit/ab8cab1c553ee5312ef47a7dea002f2585605006)) +- esp32: add implementation of esp_timer based on TG0 LAC timer ([4eb3e89](https://github.com/espressif/esp-protocols/commit/4eb3e89), [IDF@739eb05](https://github.com/espressif/esp-idf/commit/739eb05bb97736b70507e7ebcfee58e670672d23)) +- fixed typos in the variable names and the comments ([b5e5a64](https://github.com/espressif/esp-protocols/commit/b5e5a64), [IDF@ecca39e](https://github.com/espressif/esp-idf/commit/ecca39e19f663e32e16aef2a09df15443de347e9)) +- fix preset of esp_netif ptr for local interfaces ([6713ffe](https://github.com/espressif/esp-protocols/commit/6713ffe), [IDF@09e36f9](https://github.com/espressif/esp-idf/commit/09e36f9f3354092b2a528baaaaccab28ff4774d6)) +- fixed crash on event during deinit ([817c4fd](https://github.com/espressif/esp-protocols/commit/817c4fd), [IDF@eaa2f12](https://github.com/espressif/esp-idf/commit/eaa2f12d6761710d2633b4934fe09f6f45e20f4f)) +- respond to discovery with the proper pseudo name _services._dns-sd._udp ([8f0dc6d](https://github.com/espressif/esp-protocols/commit/8f0dc6d), [IDF#4369](https://github.com/espressif/esp-idf/issues/4369), [IDF@de17a14](https://github.com/espressif/esp-idf/commit/de17a1487f8ba6f432b06199f2261132ec6e735f)) +- fixed forgotten merge conflicts in debug code ([d20666f](https://github.com/espressif/esp-protocols/commit/d20666f), [IDF@d9433ef](https://github.com/espressif/esp-idf/commit/d9433ef69223a32d05abdca543fb530f2e6679e4)) +- add missing include of esp_task.h ([662a4ce](https://github.com/espressif/esp-protocols/commit/662a4ce), [IDF@5884b80](https://github.com/espressif/esp-idf/commit/5884b80908d680874e27fa0c8b2df85b69d03dd3)) +- add configuration values for task priority, affinity and internal service timeouts ([fb1de80](https://github.com/espressif/esp-protocols/commit/fb1de80), [IDF@c6f38f0](https://github.com/espressif/esp-idf/commit/c6f38f04f8eec1aae937cc87c111609772681cb3)) +- tcpip_adapter: updated tcpip_adapter compatablity layer to include all public API and keep 100% backward compatibility update build of tcpip adapter when ethernet disabled ([1f35e9a](https://github.com/espressif/esp-protocols/commit/1f35e9a), [IDF@7f5cda1](https://github.com/espressif/esp-idf/commit/7f5cda1b825586903f85dc4ad7736b35712e46d7)) +- update mdns to use esp-netif for mdns supported services such as STA, AP, ETH ([48b819b](https://github.com/espressif/esp-protocols/commit/48b819b), [IDF@19e24fe](https://github.com/espressif/esp-idf/commit/19e24fe61ed5ea6698dfd5e1f427e783360aa846)) +- esp_netif: Introduction of esp-netif component as a replacement of tcpip_adpter ([53e2aa3](https://github.com/espressif/esp-protocols/commit/53e2aa3), [IDF@ffe043b](https://github.com/espressif/esp-idf/commit/ffe043b1a81a0f9e1cc2cfa8873e21318ec89143)) +- examples: removed ip4addr_ntoa and used prefered IP2STR for displaying IP addresses ([3cc6446](https://github.com/espressif/esp-protocols/commit/3cc6446), [IDF@ec9f245](https://github.com/espressif/esp-idf/commit/ec9f245dd35d3e8e7b19a8dec5e05e003dc21f39)) +- esp_event, mdns: fixes for CONFIG_ETH_ENABLED=n ([248b11b](https://github.com/espressif/esp-protocols/commit/248b11b), [IDF@569ad75](https://github.com/espressif/esp-idf/commit/569ad7545c32a2f1d0eff3f1e81df70fb76ad125)) +- build and link hello-world for esp32s2beta ([901124b](https://github.com/espressif/esp-protocols/commit/901124b), [IDF@84b2f9f](https://github.com/espressif/esp-idf/commit/84b2f9f14d16533c84db2210f13a24cd817e0b0a)) +- fix crash for hostname queries ([f6ff165](https://github.com/espressif/esp-protocols/commit/f6ff165), [IDF#4224](https://github.com/espressif/esp-idf/issues/4224), [IDF@3d11700](https://github.com/espressif/esp-idf/commit/3d1170031b340a231949fdc0d9c46d87af0d1b5d)) +- fix possible race condition when checking DHCP status on WIFI_EVENT_STA_CONNECTED event. ([f44c569](https://github.com/espressif/esp-protocols/commit/f44c569), [IDF@7f410a0](https://github.com/espressif/esp-idf/commit/7f410a0bcbafa85dba05807c53c3c38999506509)) +- use constant size of AAAA answer in mdns packets instead of deriving from lwip struct size, since the struct could contain also zones ([286c646](https://github.com/espressif/esp-protocols/commit/286c646), [IDF@e5e31c5](https://github.com/espressif/esp-idf/commit/e5e31c5d0172d68fd207fa31cc5d3bba82dad020)) +- esp_wifi: wifi support new event mechanism ([c70d527](https://github.com/espressif/esp-protocols/commit/c70d527), [IDF@003a987](https://github.com/espressif/esp-idf/commit/003a9872b7de69d799e9d37521cfbcaff9b37e85)) +- fix missing bye packet if services removed with mdns_service_remove_all() or mdns_free() ([7cdf96c](https://github.com/espressif/esp-protocols/commit/7cdf96c), [IDF#3660](https://github.com/espressif/esp-idf/issues/3660), [IDF@a001998](https://github.com/espressif/esp-idf/commit/a001998d5283b29ca9a374adf7cef3357b39a03a)) +- mdns_service_remove_all doesn't take an argument ([407875d](https://github.com/espressif/esp-protocols/commit/407875d), [IDF@c2764f6](https://github.com/espressif/esp-idf/commit/c2764f6fe85681cfaf5dbbe168295284f09c09cd)) +- tools: Mass fixing of empty prototypes (for -Wstrict-prototypes) ([3e753f5](https://github.com/espressif/esp-protocols/commit/3e753f5), [IDF@afbaf74](https://github.com/espressif/esp-idf/commit/afbaf74007e89d016dbade4072bf2e7a3874139a)) +- fix ignoring mdns packet with some invalid name entries in question field ([144d4ad](https://github.com/espressif/esp-protocols/commit/144d4ad), [IDF@4bd4c7c](https://github.com/espressif/esp-idf/commit/4bd4c7caf3f9ef8402c5a27ab44561537407eb60)) +- add esp_eth component ([680bad6](https://github.com/espressif/esp-protocols/commit/680bad6), [IDF@90c4827](https://github.com/espressif/esp-idf/commit/90c4827bd22aa61894a5b22b3b39247a7e44d6cf)) +- components: use new component registration api ([7fb6686](https://github.com/espressif/esp-protocols/commit/7fb6686), [IDF@9eccd7c](https://github.com/espressif/esp-idf/commit/9eccd7c0826d6cc2e9de59304d1e5f76c0063ccf)) +- fix static analysis warnings ([4912bef](https://github.com/espressif/esp-protocols/commit/4912bef), [IDF@c34de4c](https://github.com/espressif/esp-idf/commit/c34de4cba658e8331f8a3ab2f466190c7640595b)) +- added initial suite of api unit tests ([181a22e](https://github.com/espressif/esp-protocols/commit/181a22e), [IDF@e680191](https://github.com/espressif/esp-idf/commit/e6801912c5c4861f828ab1f447280628bba9a5d7)) +- mdns tests: adapt mdns fuzzer test to compile with event loop library ([4172219](https://github.com/espressif/esp-protocols/commit/4172219), [IDF@38d15cb](https://github.com/espressif/esp-idf/commit/38d15cbd637e8b8baacda9fc43e8e99d224530f5)) +- fixed mdns crashing on reception of txt packet without a corresponding service closes #2866 ([98d2c1a](https://github.com/espressif/esp-protocols/commit/98d2c1a), [IDF@af48977](https://github.com/espressif/esp-idf/commit/af48977f21cea6b18dae10b2c8b64a78acfc647f)) +- use const char* for mdns txt items types to remove warning when assigning ([84cbb1f](https://github.com/espressif/esp-protocols/commit/84cbb1f), [IDF@c050a75](https://github.com/espressif/esp-idf/commit/c050a75616803c7871ef11c060e440fae09000d9)) +- updated doxygen comments documenting mdns api ([4c6818e](https://github.com/espressif/esp-protocols/commit/4c6818e), [IDF#1718](https://github.com/espressif/esp-idf/issues/1718), [IDF@a851aac](https://github.com/espressif/esp-idf/commit/a851aac255311124529f504486ca55bad15c1951)) +- update mdns_out_question_s to be in line with mdns_parsed_question_s struct ([c440114](https://github.com/espressif/esp-protocols/commit/c440114), [IDF#1568]( https://github.com/espressif/esp-idf/issues/1568), [IDF@eddd5c4](https://github.com/espressif/esp-idf/commit/eddd5c4f2c686d9a1d6d3258569cc33752e78880)) +- use esp_event library to handle events ([6ea0ea9](https://github.com/espressif/esp-protocols/commit/6ea0ea9), [IDF@a2d5952](https://github.com/espressif/esp-idf/commit/a2d59525e53099ee1ad63c3d60ff853f573ab535)) +- fuzzer tests: update of mdns and lwip host compilation for fuzzer testing ([d9aec9f](https://github.com/espressif/esp-protocols/commit/d9aec9f), [IDF@bc60bbb](https://github.com/espressif/esp-idf/commit/bc60bbbeaf89f2bbfc5db4bd4f1e7ace81a2ab37)) +- fix possible crash when probing on particular interface with duplicated service instances due to naming conflicts on network ([985e691](https://github.com/espressif/esp-protocols/commit/985e691), [IDF@265e983](https://github.com/espressif/esp-idf/commit/265e983a452a7eaefc1662cdc0e6ed839a37fe1a)) +- enable pcbs before starting service thread to avoid updating pcb's internal variables from concurent tasks ([75deebb](https://github.com/espressif/esp-protocols/commit/75deebb), [IDF@c87f0cb](https://github.com/espressif/esp-idf/commit/c87f0cb6cad3c36b077f4aaeb1ca52fe6ed0cdaf)) +- fix possible deadlock on mdns deinit calling mdns_free() ([fdd27dc](https://github.com/espressif/esp-protocols/commit/fdd27dc), [IDF#1696](https://github.com/espressif/esp-idf/issues/1696), [IDF@48b5501](https://github.com/espressif/esp-idf/commit/48b5501c250ed90da51a55ad4fc18e09f466a517)) +- mdsn: fix race condition in updating packet data from user task when failed to allocate or queue a new service ([2ec3b55](https://github.com/espressif/esp-protocols/commit/2ec3b55), [IDF@021dc5d](https://github.com/espressif/esp-idf/commit/021dc5d453e21e2d1707f194668e69cf63ef4e84)) +- fix possible crash when packet scheduled to transmit contained service which might have been already removed ([450cbf0](https://github.com/espressif/esp-protocols/commit/450cbf0), [IDF@67051a2](https://github.com/espressif/esp-idf/commit/67051a286ba60a01d4755c3682129153c2f95953)) +- use binary semaphore instead of mutex when searching ([34f6d8d](https://github.com/espressif/esp-protocols/commit/34f6d8d), [IDF@eef0b50](https://github.com/espressif/esp-idf/commit/eef0b5090aee87efef1a6a37772b3b88c9ce8df8)) +- fix memory leak in pbuf if tcpipadapter failed to get netif ([b6efc68](https://github.com/espressif/esp-protocols/commit/b6efc68), [IDF@8462751](https://github.com/espressif/esp-idf/commit/8462751f95a3ff18bdc1b01d02fabd1829fd9135)) +- fix malfuctional query_txt ([90e4bab](https://github.com/espressif/esp-protocols/commit/90e4bab), [IDF@1a02773](https://github.com/espressif/esp-idf/commit/1a027734af06abf08fcb1c34ee65bdf50d12be4d)) +- fix possible crash when mdns_free called while action queue not empty ([c546ab8](https://github.com/espressif/esp-protocols/commit/c546ab8), [IDF@206b47c](https://github.com/espressif/esp-idf/commit/206b47c03aca0acdf40d1d9c250e18aeddfe1bd7)) +- fix memory leak when query for service receives multiple ptr entries for one instance ([6582b41](https://github.com/espressif/esp-protocols/commit/6582b41), [IDF@9a4da97](https://github.com/espressif/esp-idf/commit/9a4da97fb4b3c241998cb969a08c3a917ffb4cd1)) +- fix crash after init if no memory for task ([358d26c](https://github.com/espressif/esp-protocols/commit/358d26c), [IDF@a47768d](https://github.com/espressif/esp-idf/commit/a47768dc4e4750fd7e1c29b15d6e2dd3c76e6591)) +- fixed crash on free undefined ptr after skipped strdup ([2ac83d0](https://github.com/espressif/esp-protocols/commit/2ac83d0), [IDF@e0a8044](https://github.com/espressif/esp-idf/commit/e0a8044a16907e642001b883469618a999dbe6db)) +- Correct Kconfigs according to the coding style ([98e3171](https://github.com/espressif/esp-protocols/commit/98e3171), [IDF@37126d3](https://github.com/espressif/esp-idf/commit/37126d3451eabb44eeeb48b8e2ee554dc233e2a8)) +- fix networking running udp_sendif from lwip thread ([2f85c07](https://github.com/espressif/esp-protocols/commit/2f85c07), [IDF@f7d4a4b](https://github.com/espressif/esp-idf/commit/f7d4a4be6a9e0b0ac5edb9400d3b123dbbed2ffc)) +- fixed static memory leak ([b30a7fe](https://github.com/espressif/esp-protocols/commit/b30a7fe), [IDF@6bb68a5](https://github.com/espressif/esp-idf/commit/6bb68a5a7567a94c3605136d44960ff060c74663)) +- check all mallocs for failure and add default hook to log error with free heap ([7a4fdad](https://github.com/espressif/esp-protocols/commit/7a4fdad), [IDF@c8cb4cd](https://github.com/espressif/esp-idf/commit/c8cb4cd3c8eb56d5901ade03302ad1231d7f3de5)) +- resolve memory leak when txt record received multiple times ([b4e5742](https://github.com/espressif/esp-protocols/commit/b4e5742), [IDF@a6b2b73](https://github.com/espressif/esp-idf/commit/a6b2b73f03bbb75a39685ddba6cf877fd1e5e6d7)) +- skip sending search when finished, not properly locked timer task ([2763bcd](https://github.com/espressif/esp-protocols/commit/2763bcd), [IDF@31163f0](https://github.com/espressif/esp-idf/commit/31163f02d5c414d8b492dce6f729b43a0061581b)) +- sending search packets also in probing and announcing state ([8cd0e8a](https://github.com/espressif/esp-protocols/commit/8cd0e8a), [IDF@d16762a](https://github.com/espressif/esp-idf/commit/d16762a036e35ce86ece86bb44e6e99f9cc7c431)) +- fixed crashes on network changes ([9b3b41c](https://github.com/espressif/esp-protocols/commit/9b3b41c), [IDF@097282a](https://github.com/espressif/esp-idf/commit/097282a8e3f85958747430d9931ce0a545d37700)) +- Update network code for mDNS to work with newest LwIP ([ea23007](https://github.com/espressif/esp-protocols/commit/ea23007), [IDF@3ec0e7e](https://github.com/espressif/esp-idf/commit/3ec0e7e2d2ddea70e9f8fb5025664d0fe24c301a)) +- bugfix: mdns_service_txt_set() wasn't allocating memory for TXT records ([0c17121](https://github.com/espressif/esp-protocols/commit/0c17121), [IDF@e5e2702](https://github.com/espressif/esp-idf/commit/e5e2702ca3f63a29da57eb138f75a20c74fb2a94)) +- cmake: make main a component again ([67173f6](https://github.com/espressif/esp-protocols/commit/67173f6), [IDF@d9939ce](https://github.com/espressif/esp-idf/commit/d9939cedd9b44d63dc148354c3a0a139b9c7113d)) +- Feature/sync lwip as submodule ([fed787f](https://github.com/espressif/esp-protocols/commit/fed787f), [IDF@3578fe3](https://github.com/espressif/esp-idf/commit/3578fe39e01ba0c2d54824ac70c3276502661c6b)) +- Fix a portion of the queries are issued with the wildcard query type ([b4ab30b](https://github.com/espressif/esp-protocols/commit/b4ab30b), [IDF@f3f0445](https://github.com/espressif/esp-idf/commit/f3f0445f4db7c9ad97ae10a9728767337aa7bb62)) +- added CI job for AFL fuzzer tests ([dd71494](https://github.com/espressif/esp-protocols/commit/dd71494), [IDF@0c14764](https://github.com/espressif/esp-idf/commit/0c147648f7642d058b63fbe2ddd5de31c2326304)) +- Minor fix for mdns_service_remove() ([39de491](https://github.com/espressif/esp-protocols/commit/39de491), [IDF@5c7eb7e](https://github.com/espressif/esp-idf/commit/5c7eb7e27be7508130459d896cf7d13ffefda87f)) +- Replace all DOS line endings with Unix ([19acac7](https://github.com/espressif/esp-protocols/commit/19acac7), [IDF@a67d5d8](https://github.com/espressif/esp-idf/commit/a67d5d89e0e90390fa7ff02816a6a79008d75d40)) +- remove executable permission from source files ([98069f9](https://github.com/espressif/esp-protocols/commit/98069f9), [IDF@cb649e4](https://github.com/espressif/esp-idf/commit/cb649e452f3c64a7db1f4a61e162a16b70248204)) +- Fixed nullptr dereference in MDNS.c ([ad29d34](https://github.com/espressif/esp-protocols/commit/ad29d34), [IDF@fffbf7b](https://github.com/espressif/esp-idf/commit/fffbf7b75065b5852e064e04b0c5102dd0fc2244)) +- MDNS-Fuzzer: AFL fuzzer tests for mdsn packet parser ([9f1be36](https://github.com/espressif/esp-protocols/commit/9f1be36), [IDF@e983230](https://github.com/espressif/esp-idf/commit/e983230be933fb83cebdd1945ba6539a7dc99b28)) +- cmake: Add component dependency support ([c7701d4](https://github.com/espressif/esp-protocols/commit/c7701d4), [IDF@1cb5712](https://github.com/espressif/esp-idf/commit/1cb5712463a8963cd3e8331da90fb5e03f13575f)) +- cmake: Remove defaults for COMPONENT_SRCDIRS, COMPONENT_SRCS, COMPONENT_ADD_INCLUDEDIRS ([f1ccc40](https://github.com/espressif/esp-protocols/commit/f1ccc40), [IDF@4f1a856](https://github.com/espressif/esp-idf/commit/4f1a856dbfd752336cd71730105e02ad8c045541)) +- build system: Initial cmake support, work in progress ([84bd1d7](https://github.com/espressif/esp-protocols/commit/84bd1d7), [IDF@c671a0c](https://github.com/espressif/esp-idf/commit/c671a0c3ebf90f18576d6db55b51b62730c58301)) +- fix the bug that in mdns test code redefine esp_err_t to uint32_t, which should be int32_t ([259d3fc](https://github.com/espressif/esp-protocols/commit/259d3fc), [IDF@81e4cad](https://github.com/espressif/esp-idf/commit/81e4cad61593cde879a5c44a08060d9d336e5a3f)) +- Fix exception when service is removed while there are pending packets that depend on it ([7784d00](https://github.com/espressif/esp-protocols/commit/7784d00), [IDF@421c6f1](https://github.com/espressif/esp-idf/commit/421c6f154b10d9253b78875ab28ee6bdcaaaf3c0)) +- Fix case where service is NULL and that will cause exception ([bce7d52](https://github.com/espressif/esp-protocols/commit/bce7d52), [IDF@4fa130a](https://github.com/espressif/esp-idf/commit/4fa130ae4fb5de99ddddc5a7bed7e26ae645591c)) +- Fix issue with some mDNS parsers ([ef924f1](https://github.com/espressif/esp-protocols/commit/ef924f1), [IDF@51dde19](https://github.com/espressif/esp-idf/commit/51dde19a765533af67fc7be21f116641773a9be4)) +- Import mDNS changes ([ad8c92d](https://github.com/espressif/esp-protocols/commit/ad8c92d), [IDF@4bddbc0](https://github.com/espressif/esp-idf/commit/4bddbc031cee83935c0e4df1dc72cc7000c97ba5)) +- Fix compilation errors when using gcc-7.2.0 for the crosstool-ng toolchain ([3aa605f](https://github.com/espressif/esp-protocols/commit/3aa605f), [IDF@519edc3](https://github.com/espressif/esp-idf/commit/519edc332dae0160069fd790467cde8de78f1a0e)) +- components/mdns: wrong Message compression detect ([00a72b8](https://github.com/espressif/esp-protocols/commit/00a72b8), [IDF@6e24566](https://github.com/espressif/esp-idf/commit/6e24566186c52dc5432b6b25c81abda577c21e85)) +- fix leak after _mdns_create_service if we have a malloc error. ([907e7ee](https://github.com/espressif/esp-protocols/commit/907e7ee), [IDF@b6b36bd](https://github.com/espressif/esp-idf/commit/b6b36bd9ddf169039a5528f8b766048d97b975f7)) +- Use LwIP IPC for low-level API calls ([b367484](https://github.com/espressif/esp-protocols/commit/b367484), [IDF@713964f](https://github.com/espressif/esp-idf/commit/713964fe9e98b4fa34145c497b7ab638dc57614c)) +- Add AFL fuzz test ([4a8582f](https://github.com/espressif/esp-protocols/commit/4a8582f), [IDF@4c26227](https://github.com/espressif/esp-idf/commit/4c2622755d92efa1818d062d433725553437993c)) +- implement fixes for issues found while fuzz testing ([75de31c](https://github.com/espressif/esp-protocols/commit/75de31c), [IDF@99d3990](https://github.com/espressif/esp-idf/commit/99d39909c4f19c63909d663e927ac0a8933a3ed5)) +- add simple dns-sd meta query support ([4acf639](https://github.com/espressif/esp-protocols/commit/4acf639), [IDF@96e8a3c](https://github.com/espressif/esp-idf/commit/96e8a3c725095562d2725aaefa15adcfc5d78dd5)) +- address security issues with mDNS ([91bb509](https://github.com/espressif/esp-protocols/commit/91bb509), [IDF@c89e11c](https://github.com/espressif/esp-idf/commit/c89e11c8fa64641edddf9a055745d825ae3fab9d)) +- Initial mDNS component and example ([7fbf8e5](https://github.com/espressif/esp-protocols/commit/7fbf8e5), [IDF@dd3f18d](https://github.com/espressif/esp-idf/commit/dd3f18d2d88ee78909d4af2840dfdf0b9f715f28)) diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/CHECKSUMS.json b/RainMaker_Table-Lights/managed_components/espressif__mdns/CHECKSUMS.json new file mode 100644 index 000000000..26da38117 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__mdns/CHECKSUMS.json @@ -0,0 +1 @@ +{"version": "1.0", "algorithm": "sha256", "created_at": "2025-05-21T16:48:33.954015+00:00", "files": [{"path": "mdns_console.c", "size": 47930, "hash": "404e6b43423af614db393422c5af6e7898529f93c139b45470b049472bb1329d"}, {"path": "CMakeLists.txt", "size": 1302, "hash": "eaccef84e77e9b6eea8761cfbb18b9e24f62889144bd53bd6083c8f26e5ce6e9"}, {"path": "LICENSE", "size": 11358, "hash": "cfc7749b96f63bd31c3c42b5c471bf756814053e847c10f3eb003417bc523d30"}, {"path": "CHANGELOG.md", "size": 67010, "hash": "11619c66f4e205ce8c8b297f8ffe6f9b575ffe15e5594a26b670398b44cc5f92"}, {"path": "mdns_networking_socket.c", "size": 17555, "hash": "0422fd943e04dc600c9c8e568c3041eb8b5e86c839508c610128dfb5f9945a7d"}, {"path": "idf_component.yml", "size": 535, "hash": "1ad7d0f3eab912e608d4f5e0be3dbedb20eaf344be613e9092dcfcdd135bdedc"}, {"path": "mdns_mem_caps.c", "size": 2407, "hash": "eeaf91732c95432c97bd44cd1211e017f5d6e9bf9d52fe13b988099a9c9fc9ad"}, {"path": "Kconfig", "size": 6794, "hash": "67a2b3a13edd21a09f003babc216232df045b7e55ce6e4a90c7cf63ed2db0771"}, {"path": ".cz.yaml", "size": 216, "hash": "e4d7e2be4e90ca59ef0167744ee1b08831478a3d17e55b956783fa139a6ae257"}, {"path": "README.md", "size": 673, "hash": "05ae92097f344b060cbf90ae21c9fe9953d53188a363f45f3ce2af945a8b6244"}, {"path": "mdns.c", "size": 277909, "hash": "ee069fe92df66c51ad7362e05d021464c0d9b77aa716ac8f0e3c2207865cd970"}, {"path": "mem_prefix_script.py", "size": 1370, "hash": "5320bff3afb9fca57e5a12a9a217f7d68bccc28300d4a96b6aab8aa648206575"}, {"path": "mdns_networking_lwip.c", "size": 11180, "hash": "33bd6ed9ca58b4ce62ee6b7f1b419a64826e2a4242a2b0ac91107012190cadb7"}, {"path": "private_include/mdns_networking.h", "size": 1408, "hash": "12456bd2f36907252277db40f922cfd666fac4f59c02450a8652f9924db55cd5"}, {"path": "private_include/mdns_mem_caps.h", "size": 1483, "hash": "67f749086445e9eb9ba8d00120eca699e9b16865c1c8ccdf4449ad9cd6c9076d"}, {"path": "private_include/mdns_private.h", "size": 13826, "hash": "4bb7bcc7bcacfbad4ff6adc6f453105f5e7ad62f0d622f2b94148302a16ba4b6"}, {"path": "include/mdns.h", "size": 36017, "hash": "883cae69f6edc3b5743ec83fa698e416be3a69a719ad66245728837d334f1ae6"}, {"path": "include/mdns_console.h", "size": 308, "hash": "7b06003a193a2b602dc38e2f8d7b34c4ed3043e02c57345565f06030464d946a"}, {"path": "examples/query_advertise/CMakeLists.txt", "size": 239, "hash": "d0442b76ac4c9d8bd895e06b4097d1b5b878fcc5ba5833b04221a8c630bd623c"}, {"path": "examples/query_advertise/sdkconfig.ci.eth_no_ipv4", "size": 478, "hash": "e0c9f0ada36d3ede6772e5161293dcabb67aaf13bf3e88255397f435ec07f626"}, {"path": "examples/query_advertise/sdkconfig.ci.eth_def", "size": 489, "hash": "e6c46e51ac75407c09b32b6361383727337ddea0275555eb82f4f7908196ca6c"}, {"path": "examples/query_advertise/sdkconfig.ci.eth_socket", "size": 521, "hash": "f3bbfa2a648d3908d7b8235d3c3d62714bcadf5aa160ae9347d285e6512e7eb1"}, {"path": "examples/query_advertise/README.md", "size": 4517, "hash": "6e41319d31b1bc66c4a31d68516a92986ac21beeb56eabcf0c13a5e84466e878"}, {"path": "examples/query_advertise/sdkconfig.ci.eth_custom_netif", "size": 650, "hash": "be7ed6ad54d9e5fa36bbc5c24be90183e0f53f212596e956e5d8f23a1beaf14a"}, {"path": "examples/query_advertise/sdkconfig.ci.eth_no_ipv6", "size": 508, "hash": "6ec8aff6b96fbc6a3884cc7a24c9e292c7ddda4933ca708359c860d8262d8a4d"}, {"path": "examples/query_advertise/pytest_mdns.py", "size": 8744, "hash": "a62d84faa926c5baf09a5e826713419b45738d0134a7b5554c17c15cf0850f79"}, {"path": "examples/query_advertise/main/CMakeLists.txt", "size": 88, "hash": "d02d665083ea78f8aa519b770ea9c4c348889f7c4964b5d224e4898f08fc6adb"}, {"path": "examples/query_advertise/main/mdns_example_main.c", "size": 14341, "hash": "c12ed545332a730a4da204d27ec47cba762cf6b5c61e49b94056692f864d4528"}, {"path": "examples/query_advertise/main/idf_component.yml", "size": 228, "hash": "5115862e7e8d2ace9eb87e34edc0be447a6bce021b579eb79bd45fadfe2740c0"}, {"path": "examples/query_advertise/main/Kconfig.projbuild", "size": 1920, "hash": "544af51bd80b0a8be3930329b3611219e95c54a58ff2947ec22a458bba5e417f"}, {"path": "tests/unit_test/sdkconfig.ci", "size": 94, "hash": "8da7589f815a526c0e9bc8291cd1e58864041b80bec592a91840a5c8847cffa6"}, {"path": "tests/unit_test/CMakeLists.txt", "size": 254, "hash": "dc9e538d4f5d51f4a419bbb40eefb01b88fb6392f03f1d2a7217565670a25bc4"}, {"path": "tests/unit_test/pytest_app_mdns.py", "size": 213, "hash": "b15b764b8d0fcf025dbe7ae4d06f0077537749fba52bef09b46ac2ebc12c82a8"}, {"path": "tests/unit_test/sdkconfig.defaults", "size": 68, "hash": "bf225acae456eb714b977921a0e9d29bdce06d7113f5544593758357810adc56"}, {"path": "tests/test_apps/pytest_mdns_app.py", "size": 11562, "hash": "e05f0a3ed9b65a7bea960ae56e435b10d7ab1c1b950fda81147ac08ec972b17c"}, {"path": "tests/test_apps/sdkconfig.ci", "size": 426, "hash": "269731303d830c4b4833ef64d82b1415ae8cd39a2fd462d2535e95dab8521d72"}, {"path": "tests/test_apps/CMakeLists.txt", "size": 243, "hash": "664d50a77bf6a7fd8f4c0c465c23b461f1cb747f37146f2a8b6d449ccfa50b8f"}, {"path": "tests/test_apps/README.md", "size": 2600, "hash": "83e5d96b712d48a2a280126d6722c2d1780cb56483dfc42af088c6dc407830f6"}, {"path": "tests/test_apps/sdkconfig.defaults", "size": 80, "hash": "35419efd9750423871740ce1b16035eccb27abe99b058b5e1558c7901c8c0870"}, {"path": "tests/test_afl_fuzz_host/CMakeLists.txt", "size": 246, "hash": "7f765f63b68f17bc3a9a0876b500ea97d7ef3005ff2c44ae8b5672a7eae0c182"}, {"path": "tests/test_afl_fuzz_host/mdns_di.h", "size": 2623, "hash": "6b764afeb937f09f4712b44e50b60977ffa717174affa32fd1e1095717f54e27"}, {"path": "tests/test_afl_fuzz_host/Makefile", "size": 2986, "hash": "0542081a2b12b8ec7227300fb3891c84574262a6c05db204aab64d0c9e500976"}, {"path": "tests/test_afl_fuzz_host/esp_netif_mock.c", "size": 1102, "hash": "29605f11fe6cb3ab2e47a94e371b331279793c3b4e44971137d354cd69199886"}, {"path": "tests/test_afl_fuzz_host/sdkconfig.h", "size": 19870, "hash": "f4a9a68df6c7555ca58aa46201bd3450acbda1d3416d6aefe2f815195d2f6ad6"}, {"path": "tests/test_afl_fuzz_host/esp32_mock.h", "size": 3872, "hash": "dc9388f5499ff9dff2fe6cb949ad5d032ca9ac1d5d25352d70d1f21f28fe4c4a"}, {"path": "tests/test_afl_fuzz_host/README.md", "size": 3162, "hash": "e4ea309397d3ba457f8da7c7113aff012f0f53e9a058595f81dd17cf8d615b21"}, {"path": "tests/test_afl_fuzz_host/mdns_mock.h", "size": 641, "hash": "59d009c44873b19b9c6dfe8dd3a9d05bc4b1512086b9a30dbb4c3d27309b38eb"}, {"path": "tests/test_afl_fuzz_host/input_packets.txt", "size": 9036, "hash": "0e766ea9238c83fa5a6c131117d297ecd2fc2e362a7ca9756ee044198c99e0c3"}, {"path": "tests/test_afl_fuzz_host/test.c", "size": 8175, "hash": "65730ef39b8b193aab83d391f694a6aa4565aca6ed5b09e7e97385b6ca7ab65a"}, {"path": "tests/test_afl_fuzz_host/esp_attr.h", "size": 327, "hash": "416714c27021d76740af13d7f00274a22b93398c3f992c03bd9ad50caa2dbe95"}, {"path": "tests/test_afl_fuzz_host/esp32_mock.c", "size": 3030, "hash": "cc9aa786fdd4c67a9039d72eaf31498309276b399a06106d068a9bcb0b49c1ee"}, {"path": "tests/host_test/sdkconfig.ci.console", "size": 114, "hash": "36fbd4c9edc43321f412b6704d3b1ad7ad625cf8e12a6881b1ffd09ed8d6fac2"}, {"path": "tests/host_test/CMakeLists.txt", "size": 541, "hash": "d69a08646eb7af5535b1b4fbd78501eb1e8a18086e7db058677139e540fc9440"}, {"path": "tests/host_test/sdkconfig.ci.app", "size": 127, "hash": "b1a7f50d173e21fcc01d3d45e2698e8840c87d6963e2dbb27e6c5943b9125593"}, {"path": "tests/host_test/sdkconfig.ci.target", "size": 26, "hash": "b5cb63deea9b1e4d616752e09fab4ed18fbb039e5f980ea26431acf1307d67cb"}, {"path": "tests/host_test/README.md", "size": 975, "hash": "168820c132bd2c276d22856e5dd533cdc0add8952da06358e19528d4a3dea3a7"}, {"path": "tests/host_test/pytest_mdns.py", "size": 8953, "hash": "8743912240e75b85b358d8da0124ed0dcd0f931e83926c9c5cf0c73a6cc5d0de"}, {"path": "tests/host_test/dnsfixture.py", "size": 4748, "hash": "9328082027347b7d2d9ff19b312b0bbc24a96d77d21ee4b627c19f691de78075"}, {"path": "tests/host_test/sdkconfig.defaults", "size": 199, "hash": "68e2a590541166d099f182e88bf4e239c259cd79bdf516ce1d08f5a4266e7bf8"}, {"path": "tests/host_test/main/CMakeLists.txt", "size": 147, "hash": "750a466f2ab682e1aff3eea846752dc5148b7e638b14ad6842bae79d96e279c5"}, {"path": "tests/host_test/main/idf_component.yml", "size": 201, "hash": "ba446b66e793f1e609b753740c205d1cf9a7b1bad509bdbec6ef694c8401ecf5"}, {"path": "tests/host_test/main/main.c", "size": 3653, "hash": "d5b572af8b345465ff5d4069fd4da02b274d3a6cf2eabd3d33b27aadf9ca9bc9"}, {"path": "tests/host_test/main/Kconfig.projbuild", "size": 507, "hash": "43e5370c092dcace9d05489494f8178df02adace71014f025cc465a01e2e8781"}, {"path": "tests/host_test/components/esp_netif_linux/CMakeLists.txt", "size": 314, "hash": "b57723ef05c094444d19dc123ba11aee2a5693d7685c0a5a9aaf7dfaeee7110b"}, {"path": "tests/host_test/components/esp_netif_linux/esp_netif_linux.c", "size": 4982, "hash": "0ead2caefe0a8b66196b37236724cb85df69f34ccf14d530fe548ff9d5094aee"}, {"path": "tests/host_test/components/esp_netif_linux/Kconfig", "size": 257, "hash": "ac8bff8c86c8e268c11d1926ed0d70459156e00f48d9f715b856b9dbe8d9511d"}, {"path": "tests/host_test/components/esp_netif_linux/include/esp_wifi_types.h", "size": 158, "hash": "42b1dd10e6b6a54bc6f2a3f761d096bd5bbdc7c3d0ba122110fbcd879221bd86"}, {"path": "tests/host_test/components/esp_netif_linux/include/machine/endian.h", "size": 161, "hash": "6affb826a6caad86367e44a69e3ea901b19e6589120980ac73e31f076b782610"}, {"path": "tests/test_afl_fuzz_host/in/file2.bin", "size": 33, "hash": "63e175d3f16aa129587f4bfed0312cff6c3e3bbb95919e0822ea3594fbcfbe30"}, {"path": "tests/test_afl_fuzz_host/in/test-31.bin", "size": 91, "hash": "66a6a82ebd7c30221c0286c4f3126912f64dc710c1a903ef6c86ec2b285d986f"}, {"path": "tests/test_afl_fuzz_host/in/minif_query.bin", "size": 77, "hash": "58c5ae8d824f38612477aa9202394cfaa17bbe562e516871350073c11ad5a61b"}, {"path": "tests/test_afl_fuzz_host/in/minif_any.bin", "size": 109, "hash": "9cc25f3e4ebbaf4191a65397e441993ffed7858c7bdb181d9f0fd5c9cdc8ee8e"}, {"path": "tests/test_afl_fuzz_host/in/telnet_ptr.bin", "size": 72, "hash": "4d95f91cfcf550df0031b06661eae5b253333a2fb1b6aaa0378d3faab82b67ac"}, {"path": "tests/test_afl_fuzz_host/in/test-53.bin", "size": 140, "hash": "613366d3af58645f0315354e7860b7c59bff935f270086145456eadd65e1b2ee"}, {"path": "tests/test_afl_fuzz_host/in/test-83.bin", "size": 105, "hash": "7a6a22d37b7baf95e54eeca95e9684c6742e4234b78e762f5504f3a1451cf621"}, {"path": "tests/test_afl_fuzz_host/in/test-96.bin", "size": 319, "hash": "e44cfbb29156d68f011437451c8e70ff8464f014ede1c52a00ee4b279f9cda99"}, {"path": "tests/test_afl_fuzz_host/in/minif_query2.bin", "size": 64, "hash": "5c1f4e91f3636220b4e12be8b1909aa0af2b387f271b159af86d625d9eb6fc8f"}, {"path": "tests/test_afl_fuzz_host/in/test-56.bin", "size": 262, "hash": "640d1eefd491c61942c490b8f284fa991868fd07ecadeeeee9c2b230866b21fc"}, {"path": "tests/test_afl_fuzz_host/in/test-95.bin", "size": 286, "hash": "21d5fcd95b26331cca324a0e74a0108d76c006ca699d81c5856f7f3904c71063"}, {"path": "tests/test_afl_fuzz_host/in/sub_fritz_m.bin", "size": 72, "hash": "1567d0f345d1341fb12aa95c2c6f7a0cb33d43c0b1ba3aeee462ac61a91b8da7"}, {"path": "tests/test_afl_fuzz_host/in/minif_disc.bin", "size": 65, "hash": "455b13bcbd89c8174a7f627c4f5b8fd1ee36df438790d7f27d5d5b3d07560581"}, {"path": "tests/test_afl_fuzz_host/in/test-89.bin", "size": 459, "hash": "5fd5cbdc1182b10809f4f0fec583233c0d005e6290ceaf24ff32b711537fe64b"}, {"path": "tests/test_afl_fuzz_host/in/test-63.bin", "size": 147, "hash": "ef363f872866047a2a5ce2efad05c828d1bd02c197fc16ee967d05147f1c8f33"}, {"path": "tests/test_afl_fuzz_host/in/test-88.bin", "size": 48, "hash": "2a47f8315ed907b68a8f2d3b19615fad74b2a65db0b9f8f0a70728b3104ce251"}, {"path": "tests/test_afl_fuzz_host/in/minif_4a_txt.bin", "size": 39, "hash": "96f99c6fd77af3634e2329e5274f773fded84c4dec6b83ede92ee8ab9f5c5ecc"}, {"path": "tests/test_afl_fuzz_host/in/minif_ptr.bin", "size": 36, "hash": "d2d174000cbf7fb0e0cb04e05d7b8a7feb3ddad3a8eb3cc666ab83e488fe5e0b"}, {"path": "tests/test_afl_fuzz_host/in/test-16.bin", "size": 254, "hash": "1bd402094cd9ed875ad851b6120dbdf02ae9f347b8d43105f60215557f59970b"}, {"path": "tests/test_afl_fuzz_host/in/minif_aaaa.bin", "size": 33, "hash": "c5d7283539a8f5d976651cdf1e226ab1f2bf4b72249413d8bbcf9316f77adad3"}, {"path": "tests/test_afl_fuzz_host/in/test-29.bin", "size": 39, "hash": "2d1fac83bb6506cad039e3dd17a997e8e1626aaed478063b33c272bbc625e503"}, {"path": "tests/test_afl_fuzz_host/in/test-15.bin", "size": 524, "hash": "22010b88f143fbba4367b697c617ca7999a37fa1eadc8912fb21f4ecabce3258"}, {"path": "tests/test_afl_fuzz_host/in/test-14.bin", "size": 568, "hash": "851633823bf7fa62bcbc81850176d303834100341a1887f8209a7285b977e599"}, {"path": "tests/test_afl_fuzz_host/in/test-28.bin", "size": 62, "hash": "6c29e7d7c377f51d13f2afedac22de8f49f8c252f6cac576b2842896bef1b59f"}, {"path": "tests/test_apps/main/CMakeLists.txt", "size": 93, "hash": "da39a012d77ed08c2115f9365fb14c6e75c694fa73b5bafc1351f6600593c390"}, {"path": "tests/test_apps/main/mdns_test.c", "size": 5793, "hash": "493dba6479833d997ca2cc79cc0b8e48c516303362f71dbfa40608c635904fb0"}, {"path": "tests/test_apps/main/idf_component.yml", "size": 228, "hash": "5115862e7e8d2ace9eb87e34edc0be447a6bce021b579eb79bd45fadfe2740c0"}, {"path": "tests/test_apps/main/main.c", "size": 3423, "hash": "d889f6a7dd56fd90812327554ee68e86780a617dfe2737d5540dfecc300c4524"}, {"path": "tests/test_apps/main/Kconfig.projbuild", "size": 1290, "hash": "8e68cdd831c047ecccb4a0c20fbf2da283590fc17f2abee7afc0ef5d8f4cadc4"}, {"path": "tests/unit_test/main/CMakeLists.txt", "size": 175, "hash": "45f26ae5395a211f0499ef4dac97d1fc1ddccab75e0b2bd672aade8c170ada45"}, {"path": "tests/unit_test/main/test_mdns.c", "size": 14905, "hash": "345b9ddd4bb522b4b3bce79bb11c21ffd6cb4ba86fba4976ae3dba8987b7b628"}]} \ No newline at end of file diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/CMakeLists.txt b/RainMaker_Table-Lights/managed_components/espressif__mdns/CMakeLists.txt new file mode 100644 index 000000000..5823849b0 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__mdns/CMakeLists.txt @@ -0,0 +1,42 @@ +if(CONFIG_MDNS_NETWORKING_SOCKET) + set(MDNS_NETWORKING "mdns_networking_socket.c") +else() + set(MDNS_NETWORKING "mdns_networking_lwip.c") +endif() + +if(CONFIG_MDNS_ENABLE_CONSOLE_CLI) + set(MDNS_CONSOLE "mdns_console.c") +else() + set(MDNS_CONSOLE "") +endif() + +set(MDNS_MEMORY "mdns_mem_caps.c") + +idf_build_get_property(target IDF_TARGET) +if(${target} STREQUAL "linux") + set(dependencies esp_netif_linux esp_event) + set(private_dependencies esp_timer console esp_system) + set(srcs "mdns.c" ${MDNS_MEMORY} ${MDNS_NETWORKING} ${MDNS_CONSOLE}) +else() + set(dependencies lwip console esp_netif) + set(private_dependencies esp_timer esp_wifi) + set(srcs "mdns.c" ${MDNS_MEMORY} ${MDNS_NETWORKING} ${MDNS_CONSOLE}) +endif() + +idf_component_register( + SRCS ${srcs} + INCLUDE_DIRS "include" + PRIV_INCLUDE_DIRS "private_include" + REQUIRES ${dependencies} + PRIV_REQUIRES ${private_dependencies}) + +if(${target} STREQUAL "linux") + target_link_libraries(${COMPONENT_LIB} PRIVATE "-lbsd") +endif() + +if(CONFIG_ETH_ENABLED) + idf_component_optional_requires(PRIVATE esp_eth) +endif() + +idf_component_get_property(MDNS_VERSION ${COMPONENT_NAME} COMPONENT_VERSION) +target_compile_definitions(${COMPONENT_LIB} PUBLIC "-DESP_MDNS_VERSION_NUMBER=\"${MDNS_VERSION}\"") diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/Kconfig b/RainMaker_Table-Lights/managed_components/espressif__mdns/Kconfig new file mode 100644 index 000000000..04380a463 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__mdns/Kconfig @@ -0,0 +1,190 @@ +menu "mDNS" + + config MDNS_MAX_INTERFACES + int "Max number of interfaces" + range 1 9 + default 3 + help + Number of network interfaces to be served by the mDNS library. + Lowering this number helps to reduce some static RAM usage. + + config MDNS_MAX_SERVICES + int "Max number of services" + default 10 + help + Services take up a certain amount of memory, and allowing fewer + services to be open at the same time conserves memory. Specify + the maximum amount of services here. + + config MDNS_TASK_PRIORITY + int "mDNS task priority" + range 1 255 + default 1 + help + Allows setting mDNS task priority. Please do not set the task priority + higher than priorities of system tasks. Compile time warning/error + would be emitted if the chosen task priority were too high. + + config MDNS_ACTION_QUEUE_LEN + int "Maximum actions pending to the server" + range 8 64 + default 16 + help + Allows setting the length of mDNS action queue. + + config MDNS_TASK_STACK_SIZE + int "mDNS task stack size" + default 4096 + help + Allows setting mDNS task stacksize. + + choice MDNS_TASK_AFFINITY + prompt "mDNS task affinity" + default MDNS_TASK_AFFINITY_CPU0 + help + Allows setting mDNS tasks affinity, i.e. whether the task is pinned to + CPU0, pinned to CPU1, or allowed to run on any CPU. + + config MDNS_TASK_AFFINITY_NO_AFFINITY + bool "No affinity" + config MDNS_TASK_AFFINITY_CPU0 + bool "CPU0" + config MDNS_TASK_AFFINITY_CPU1 + bool "CPU1" + depends on !FREERTOS_UNICORE + + endchoice + + config MDNS_TASK_AFFINITY + hex + default FREERTOS_NO_AFFINITY if MDNS_TASK_AFFINITY_NO_AFFINITY + default 0x0 if MDNS_TASK_AFFINITY_CPU0 + default 0x1 if MDNS_TASK_AFFINITY_CPU1 + + menu "MDNS Memory Configuration" + + choice MDNS_TASK_MEMORY_ALLOC_FROM + prompt "Select mDNS task create on which type of memory" + default MDNS_TASK_CREATE_FROM_INTERNAL + config MDNS_TASK_CREATE_FROM_SPIRAM + bool "mDNS task creates on the SPIRAM (READ HELP)" + depends on (SPIRAM_USE_CAPS_ALLOC || SPIRAM_USE_MALLOC) + help + mDNS task creates on the SPIRAM. + This option requires FreeRTOS component to allow creating + tasks on the external memory. + Please read the documentation about FREERTOS_TASK_CREATE_ALLOW_EXT_MEM + + config MDNS_TASK_CREATE_FROM_INTERNAL + bool "mDNS task creates on the internal RAM" + + endchoice + + choice MDNS_MEMORY_ALLOC_FROM + prompt "Select mDNS memory allocation type" + default MDNS_MEMORY_ALLOC_INTERNAL + + config MDNS_MEMORY_ALLOC_SPIRAM + bool "Allocate mDNS memory from SPIRAM" + depends on (SPIRAM_USE_CAPS_ALLOC || SPIRAM_USE_MALLOC) + + config MDNS_MEMORY_ALLOC_INTERNAL + bool "Allocate mDNS memory from internal RAM" + + endchoice + + config MDNS_MEMORY_CUSTOM_IMPL + bool "Implement custom memory functions" + default n + help + Enable to implement custom memory functions for mDNS library. + This option is useful when the application wants to use custom + memory allocation functions for mDNS library. + + endmenu # MDNS Memory Configuration + + config MDNS_SERVICE_ADD_TIMEOUT_MS + int "mDNS adding service timeout (ms)" + range 10 30000 + default 2000 + help + Configures timeout for adding a new mDNS service. Adding a service + fails if could not be completed within this time. + + config MDNS_TIMER_PERIOD_MS + int "mDNS timer period (ms)" + range 10 10000 + default 100 + help + Configures period of mDNS timer, which periodically transmits packets + and schedules mDNS searches. + + config MDNS_NETWORKING_SOCKET + bool "Use BSD sockets for mDNS networking" + default n + help + Enables optional mDNS networking implementation using BSD sockets + in UDP multicast mode. + This option creates a new thread to serve receiving packets (TODO). + This option uses additional N sockets, where N is number of interfaces. + + config MDNS_SKIP_SUPPRESSING_OWN_QUERIES + bool "Skip suppressing our own packets" + default n + help + Enable only if the querier and the responder share the same IP address. + This usually happens in test mode, where we may run multiple instances of + responders/queriers on the same interface. + + config MDNS_ENABLE_DEBUG_PRINTS + bool "Enable debug prints of mDNS packets" + default n + help + Enable for the library to log received and sent mDNS packets to stdout. + + config MDNS_ENABLE_CONSOLE_CLI + bool "Enable Command Line Interface on device console" + default y + help + Enable for the console cli to be available on the device. + + config MDNS_RESPOND_REVERSE_QUERIES + bool "Enable responding to IPv4 reverse queries" + default n + help + Enables support for IPv4 reverse lookup. If enabled, the mDNS library + response to PTR queries of "A.B.C.D.in-addr.arpa" type. + + config MDNS_MULTIPLE_INSTANCE + bool "Multiple instances under the same service type" + default y + help + Enables adding multiple service instances under the same service type. + + menu "MDNS Predefined interfaces" + + config MDNS_PREDEF_NETIF_STA + bool "Use predefined interface for WiFi Station" + default y + help + Set up mDNS for the default WiFi station. + Disable this option if you do not need mDNS on default WiFi STA. + + config MDNS_PREDEF_NETIF_AP + bool "Use predefined interface for WiFi Access Point" + default y + help + Set up mDNS for the default WiFi Access Point. + Disable this option if you do not need mDNS on default WiFi AP. + + config MDNS_PREDEF_NETIF_ETH + bool "Use predefined interface for Ethernet" + depends on ETH_ENABLED + default y + help + Set up mDNS for the default Ethernet interface. + Disable this option if you do not need mDNS on default Ethernet. + + endmenu # MDNS Predefined interfaces + +endmenu diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/LICENSE b/RainMaker_Table-Lights/managed_components/espressif__mdns/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__mdns/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/README.md b/RainMaker_Table-Lights/managed_components/espressif__mdns/README.md new file mode 100644 index 000000000..a644ad4d4 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__mdns/README.md @@ -0,0 +1,14 @@ +# mDNS Service + +[![Component Registry](https://components.espressif.com/components/espressif/mdns/badge.svg)](https://components.espressif.com/components/espressif/mdns) + +mDNS is a multicast UDP service that is used to provide local network service and host discovery. + +## Examples + +Get started with example test [Example](https://github.com/espressif/esp-protocols/tree/master/components/mdns/examples): + +## Documentation + +* View the full [documentation(English)](https://docs.espressif.com/projects/esp-protocols/mdns/docs/latest/en/index.html) +* View the full [documentation(Chinese)](https://docs.espressif.com/projects/esp-protocols/mdns/docs/latest/zh_CN/index.html) diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/examples/query_advertise/CMakeLists.txt b/RainMaker_Table-Lights/managed_components/espressif__mdns/examples/query_advertise/CMakeLists.txt new file mode 100644 index 000000000..9a16f140a --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__mdns/examples/query_advertise/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(query_advertise) diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/examples/query_advertise/README.md b/RainMaker_Table-Lights/managed_components/espressif__mdns/examples/query_advertise/README.md new file mode 100644 index 000000000..6ccdef970 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__mdns/examples/query_advertise/README.md @@ -0,0 +1,91 @@ +# mDNS example + +Shows how to use mDNS to advertise and query services and hosts + +## Example workflow + +- mDNS is initialized with host name and instance name defined through the project configuration and `_http._tcp` service is added to be advertised +- A delegated host `esp32-delegated._local` is added and another `_http._tcp` service is added for this host. +- WiFi STA is started and trying to connect to the access point defined through the project configuration +- The system event handler is used to pass the network events to mDNS so the service is aware when the interface comes up or down +- GPIO0 (BOOT Button) is initialized as pulled-up input that can be monitored for button press +- Example task is started to check if the button is pressed so it can execute the mDNS queries defined + +### Configure the project + +* Open the project configuration menu (`idf.py menuconfig`) + +* Configure Wi-Fi or Ethernet under "Example Connection Configuration" menu +* Set `mDNS Hostname` as host name prefix for the device and its instance name in `mDNS Instance Name` +* Disable `Resolve test services` to prevent the example from querying defined names/services on startup (cause warnings in example logs, as illustrated below) + +### Build and Flash + +Build the project and flash it to the board, then run monitor tool to view serial output: + +``` +idf.py -p PORT flash monitor +``` + +- Wait for WiFi to connect to your access point +- You can now ping the device at `[board-hostname].local`, where `[board-hostname]` is preconfigured hostname, `esp32-mdns` by default. +- You can also browse for `_http._tcp` on the same network to find the advertised service +- Pressing the BOOT button will start querying the local network for the predefined in `check_button` hosts and services +- Note that for purpose of CI tests, configuration options of `MDNS_RESOLVE_TEST_SERVICES` and `MDNS_ADD_MAC_TO_HOSTNAME` are available, but disabled by default. If enabled, then the hostname suffix of last 3 bytes from device MAC address is added, e.g. `esp32-mdns-80FFFF`, and a query for test service is issued. + + +(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 +``` +I (0) cpu_start: Starting scheduler on APP CPU. +I (276) system_api: Base MAC address is not set, read default base MAC address from BLK0 of EFUSE +I (276) mdns-test: mdns hostname set to: [esp32-mdns] +I (286) wifi: wifi driver task: 3ffc2fa4, prio:23, stack:3584, core=0 +I (286) wifi: wifi firmware version: a3be639 +I (286) wifi: config NVS flash: enabled +I (296) wifi: config nano formating: disabled +I (296) system_api: Base MAC address is not set, read default base MAC address from BLK0 of EFUSE +I (306) system_api: Base MAC address is not set, read default base MAC address from BLK0 of EFUSE +I (336) wifi: Init dynamic tx buffer num: 32 +I (336) wifi: Init data frame dynamic rx buffer num: 32 +I (336) wifi: Init management frame dynamic rx buffer num: 32 +I (346) wifi: Init static rx buffer size: 1600 +I (346) wifi: Init static rx buffer num: 10 +I (346) wifi: Init dynamic rx buffer num: 32 +I (356) mdns-test: Setting WiFi configuration SSID myssid... +I (426) phy: phy_version: 4000, b6198fa, Sep 3 2018, 15:11:06, 0, 0 +I (426) wifi: mode : sta (30:ae:a4:80:FF:FF) +I (426) gpio: GPIO[0]| InputEn: 1| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 +I (1756) wifi: n:11 0, o:1 0, ap:255 255, sta:11 0, prof:1 +I (2736) wifi: state: init -> auth (b0) +I (2756) wifi: state: auth -> assoc (0) +I (2766) wifi: state: assoc -> run (10) +I (2786) wifi: connected with myssid, channel 11 +I (2786) wifi: pm start, type: 1 + +I (4786) event: sta ip: 192.168.0.139, mask: 255.255.255.0, gw: 192.168.0.2 +I (21126) mdns-test: Query A: esp32.local +W (23176) mdns-test: ESP_ERR_NOT_FOUND: Host was not found! +I (23176) mdns-test: Query PTR: _arduino._tcp.local +W (26276) mdns-test: No results found! +I (26276) mdns-test: Query PTR: _http._tcp.local +1: Interface: STA, Type: V6 + PTR : HP Color LaserJet MFP M277dw (7C2E10) + SRV : NPI7C2E10.local:80 + A : 254.128.0.0 +2: Interface: STA, Type: V4 + PTR : switch4e4919 + SRV : switch4e4919.local:80 + TXT : [1] path=/config/authentication_page.htm; + A : 192.168.0.118 +I (29396) mdns-test: Query PTR: _printer._tcp.local +1: Interface: STA, Type: V6 + PTR : HP Color LaserJet MFP M277dw (7C2E10) + SRV : NPI7C2E10.local:515 + A : 254.128.0.0 +2: Interface: STA, Type: V4 + PTR : HP Color LaserJet MFP M277dw (7C2E10) +``` diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/examples/query_advertise/main/CMakeLists.txt b/RainMaker_Table-Lights/managed_components/espressif__mdns/examples/query_advertise/main/CMakeLists.txt new file mode 100644 index 000000000..eb0e6d9eb --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__mdns/examples/query_advertise/main/CMakeLists.txt @@ -0,0 +1,2 @@ +idf_component_register(SRCS "mdns_example_main.c" + INCLUDE_DIRS ".") diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/examples/query_advertise/main/Kconfig.projbuild b/RainMaker_Table-Lights/managed_components/espressif__mdns/examples/query_advertise/main/Kconfig.projbuild new file mode 100644 index 000000000..18e1cc209 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__mdns/examples/query_advertise/main/Kconfig.projbuild @@ -0,0 +1,55 @@ +menu "Example Configuration" + + orsource "$IDF_PATH/examples/common_components/env_caps/$IDF_TARGET/Kconfig.env_caps" + + config MDNS_HOSTNAME + string "mDNS Hostname" + default "esp32-mdns" + help + mDNS Hostname for example to use + + config MDNS_INSTANCE + string "mDNS Instance Name" + default "ESP32 with mDNS" + help + mDNS Instance Name for example to use + + config MDNS_PUBLISH_DELEGATE_HOST + bool "Publish a delegated host" + help + Enable publishing a delegated host other than ESP32. + The example will also add a mock service for this host. + + config MDNS_RESOLVE_TEST_SERVICES + bool "Resolve test services" + default n + help + Enable resolving test services on startup. + These services are advertized and evaluated in automated tests. + When executed locally, these will not be resolved and warnings appear in the log. + Please set to false to disable initial querying to avoid warnings. + + config MDNS_ADD_MAC_TO_HOSTNAME + bool "Add mac suffix to hostname" + default n + help + If enabled, a portion of MAC address is added to the hostname, this is used + for evaluation of tests in CI + + config MDNS_BUTTON_GPIO + int "Button GPIO to trigger querries" + range ENV_GPIO_RANGE_MIN ENV_GPIO_IN_RANGE_MAX + default 0 + help + Set the GPIO number used as mDNS test button + + config MDNS_ADD_CUSTOM_NETIF + bool "Add user netif to mdns service" + default n + help + If enabled, we try to add a custom netif to mdns service. + Note that for using with common connection example code, we have to disable + all predefined interfaces in mdns component setup (since we're adding one + of the default interfaces) + +endmenu diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/examples/query_advertise/main/idf_component.yml b/RainMaker_Table-Lights/managed_components/espressif__mdns/examples/query_advertise/main/idf_component.yml new file mode 100644 index 000000000..e9277dfc9 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__mdns/examples/query_advertise/main/idf_component.yml @@ -0,0 +1,8 @@ +dependencies: + ## Required IDF version + idf: ">=5.0" + espressif/mdns: + version: "^1.0.0" + override_path: "../../../" + protocol_examples_common: + path: ${IDF_PATH}/examples/common_components/protocol_examples_common diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/examples/query_advertise/main/mdns_example_main.c b/RainMaker_Table-Lights/managed_components/espressif__mdns/examples/query_advertise/main/mdns_example_main.c new file mode 100644 index 000000000..afe256efb --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__mdns/examples/query_advertise/main/mdns_example_main.c @@ -0,0 +1,423 @@ +/* + * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ + +/* + * MDNS-SD Query and advertise Example +*/ +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_netif_ip_addr.h" +#include "esp_mac.h" +#include "esp_event.h" +#include "esp_log.h" +#include "nvs_flash.h" +#include "esp_netif.h" +#include "protocol_examples_common.h" +#include "mdns.h" +#include "driver/gpio.h" +#include "netdb.h" + +#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 1, 0) +/* CONFIG_LWIP_IPV4 was introduced in IDF v5.1, set CONFIG_LWIP_IPV4 to 1 by default for IDF v5.0 */ +#ifndef CONFIG_LWIP_IPV4 +#define CONFIG_LWIP_IPV4 1 +#endif // CONFIG_LWIP_IPV4 +#endif // ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 1, 0) + +#define EXAMPLE_MDNS_INSTANCE CONFIG_MDNS_INSTANCE +#define EXAMPLE_BUTTON_GPIO CONFIG_MDNS_BUTTON_GPIO + +static const char *TAG = "mdns-test"; +static char *generate_hostname(void); + +#if CONFIG_MDNS_RESOLVE_TEST_SERVICES == 1 +static void query_mdns_host_with_gethostbyname(char *host); +static void query_mdns_host_with_getaddrinfo(char *host); +#endif + +static void initialise_mdns(void) +{ + char *hostname = generate_hostname(); + + //initialize mDNS + ESP_ERROR_CHECK(mdns_init()); + //set mDNS hostname (required if you want to advertise services) + ESP_ERROR_CHECK(mdns_hostname_set(hostname)); + ESP_LOGI(TAG, "mdns hostname set to: [%s]", hostname); + //set default mDNS instance name + ESP_ERROR_CHECK(mdns_instance_name_set(EXAMPLE_MDNS_INSTANCE)); + + //structure with TXT records + mdns_txt_item_t serviceTxtData[3] = { + {"board", "esp32"}, + {"u", "user"}, + {"p", "password"} + }; + + //initialize service + ESP_ERROR_CHECK(mdns_service_add("ESP32-WebServer", "_http", "_tcp", 80, serviceTxtData, 3)); + ESP_ERROR_CHECK(mdns_service_subtype_add_for_host("ESP32-WebServer", "_http", "_tcp", NULL, "_server")); +#if CONFIG_MDNS_MULTIPLE_INSTANCE + ESP_ERROR_CHECK(mdns_service_add("ESP32-WebServer1", "_http", "_tcp", 80, NULL, 0)); +#endif + +#if CONFIG_MDNS_PUBLISH_DELEGATE_HOST + char *delegated_hostname; + if (-1 == asprintf(&delegated_hostname, "%s-delegated", hostname)) { + abort(); + } + + mdns_ip_addr_t addr4, addr6; + esp_netif_str_to_ip4("10.0.0.1", &addr4.addr.u_addr.ip4); + addr4.addr.type = ESP_IPADDR_TYPE_V4; + esp_netif_str_to_ip6("fd11:22::1", &addr6.addr.u_addr.ip6); + addr6.addr.type = ESP_IPADDR_TYPE_V6; + addr4.next = &addr6; + addr6.next = NULL; + ESP_ERROR_CHECK(mdns_delegate_hostname_add(delegated_hostname, &addr4)); + ESP_ERROR_CHECK(mdns_service_add_for_host("test0", "_http", "_tcp", delegated_hostname, 1234, serviceTxtData, 3)); + free(delegated_hostname); +#endif // CONFIG_MDNS_PUBLISH_DELEGATE_HOST + + //add another TXT item + ESP_ERROR_CHECK(mdns_service_txt_item_set("_http", "_tcp", "path", "/foobar")); + //change TXT item value + ESP_ERROR_CHECK(mdns_service_txt_item_set_with_explicit_value_len("_http", "_tcp", "u", "admin", strlen("admin"))); + free(hostname); +} + +/* these strings match mdns_ip_protocol_t enumeration */ +static const char *ip_protocol_str[] = {"V4", "V6", "MAX"}; + +static void mdns_print_results(mdns_result_t *results) +{ + mdns_result_t *r = results; + mdns_ip_addr_t *a = NULL; + int i = 1, t; + while (r) { + if (r->esp_netif) { + printf("%d: Interface: %s, Type: %s, TTL: %" PRIu32 "\n", i++, esp_netif_get_ifkey(r->esp_netif), + ip_protocol_str[r->ip_protocol], r->ttl); + } + if (r->instance_name) { + printf(" PTR : %s.%s.%s\n", r->instance_name, r->service_type, r->proto); + } + if (r->hostname) { + printf(" SRV : %s.local:%u\n", r->hostname, r->port); + } + if (r->txt_count) { + printf(" TXT : [%zu] ", r->txt_count); + for (t = 0; t < r->txt_count; t++) { + printf("%s=%s(%d); ", r->txt[t].key, r->txt[t].value ? r->txt[t].value : "NULL", r->txt_value_len[t]); + } + printf("\n"); + } + a = r->addr; + while (a) { + if (a->addr.type == ESP_IPADDR_TYPE_V6) { + printf(" AAAA: " IPV6STR "\n", IPV62STR(a->addr.u_addr.ip6)); + } else { + printf(" A : " IPSTR "\n", IP2STR(&(a->addr.u_addr.ip4))); + } + a = a->next; + } + r = r->next; + } +} + +static void query_mdns_service(const char *service_name, const char *proto) +{ + ESP_LOGI(TAG, "Query PTR: %s.%s.local", service_name, proto); + + mdns_result_t *results = NULL; + esp_err_t err = mdns_query_ptr(service_name, proto, 3000, 20, &results); + if (err) { + ESP_LOGE(TAG, "Query Failed: %s", esp_err_to_name(err)); + return; + } + if (!results) { + ESP_LOGW(TAG, "No results found!"); + return; + } + + mdns_print_results(results); + mdns_query_results_free(results); +} + +#if CONFIG_MDNS_PUBLISH_DELEGATE_HOST +static void lookup_mdns_delegated_service(const char *service_name, const char *proto) +{ + ESP_LOGI(TAG, "Lookup delegated service: %s.%s.local", service_name, proto); + + mdns_result_t *results = NULL; + esp_err_t err = mdns_lookup_delegated_service(NULL, service_name, proto, 20, &results); + if (err) { + ESP_LOGE(TAG, "Lookup Failed: %s", esp_err_to_name(err)); + return; + } + if (!results) { + ESP_LOGW(TAG, "No results found!"); + return; + } + + mdns_print_results(results); + mdns_query_results_free(results); +} +#endif // CONFIG_MDNS_PUBLISH_DELEGATE_HOST + +static void lookup_mdns_selfhosted_service(const char *service_name, const char *proto) +{ + ESP_LOGI(TAG, "Lookup selfhosted service: %s.%s.local", service_name, proto); + mdns_result_t *results = NULL; + esp_err_t err = mdns_lookup_selfhosted_service(NULL, service_name, proto, 20, &results); + if (err) { + ESP_LOGE(TAG, "Lookup Failed: %s", esp_err_to_name(err)); + return; + } + if (!results) { + ESP_LOGW(TAG, "No results found!"); + return; + } + mdns_print_results(results); + mdns_query_results_free(results); +} + +static bool check_and_print_result(mdns_search_once_t *search) +{ + // Check if any result is available + mdns_result_t *result = NULL; + if (!mdns_query_async_get_results(search, 0, &result, NULL)) { + return false; + } + + if (!result) { // search timeout, but no result + return true; + } + + // If yes, print the result + mdns_ip_addr_t *a = result->addr; + while (a) { + if (a->addr.type == ESP_IPADDR_TYPE_V6) { + printf(" AAAA: " IPV6STR "\n", IPV62STR(a->addr.u_addr.ip6)); + } else { + printf(" A : " IPSTR "\n", IP2STR(&(a->addr.u_addr.ip4))); + } + a = a->next; + } + // and free the result + mdns_query_results_free(result); + return true; +} + +static void query_mdns_hosts_async(const char *host_name) +{ + ESP_LOGI(TAG, "Query both A and AAA: %s.local", host_name); + + mdns_search_once_t *s_a = mdns_query_async_new(host_name, NULL, NULL, MDNS_TYPE_A, 1000, 1, NULL); + mdns_search_once_t *s_aaaa = mdns_query_async_new(host_name, NULL, NULL, MDNS_TYPE_AAAA, 1000, 1, NULL); + while (s_a || s_aaaa) { + if (s_a && check_and_print_result(s_a)) { + ESP_LOGI(TAG, "Query A %s.local finished", host_name); + mdns_query_async_delete(s_a); + s_a = NULL; + } + if (s_aaaa && check_and_print_result(s_aaaa)) { + ESP_LOGI(TAG, "Query AAAA %s.local finished", host_name); + mdns_query_async_delete(s_aaaa); + s_aaaa = NULL; + } + vTaskDelay(50 / portTICK_PERIOD_MS); + } +} +#ifdef CONFIG_LWIP_IPV4 +static void query_mdns_host(const char *host_name) +{ + ESP_LOGI(TAG, "Query A: %s.local", host_name); + + struct esp_ip4_addr addr; + addr.addr = 0; + + esp_err_t err = mdns_query_a(host_name, 2000, &addr); + if (err) { + if (err == ESP_ERR_NOT_FOUND) { + ESP_LOGW(TAG, "%s: Host was not found!", esp_err_to_name(err)); + return; + } + ESP_LOGE(TAG, "Query Failed: %s", esp_err_to_name(err)); + return; + } + + ESP_LOGI(TAG, "Query A: %s.local resolved to: " IPSTR, host_name, IP2STR(&addr)); +} +#endif // CONFIG_LWIP_IPV4 + +static void initialise_button(void) +{ + gpio_config_t io_conf = {0}; + io_conf.intr_type = GPIO_INTR_DISABLE; + io_conf.pin_bit_mask = BIT64(EXAMPLE_BUTTON_GPIO); + io_conf.mode = GPIO_MODE_INPUT; + io_conf.pull_up_en = 1; + io_conf.pull_down_en = 0; + gpio_config(&io_conf); +} + +static void check_button(void) +{ + static bool old_level = true; + bool new_level = gpio_get_level(EXAMPLE_BUTTON_GPIO); + if (!new_level && old_level) { + query_mdns_hosts_async("esp32-mdns"); +#ifdef CONFIG_LWIP_IPV4 + query_mdns_host("esp32"); +#endif + query_mdns_service("_arduino", "_tcp"); + query_mdns_service("_http", "_tcp"); + query_mdns_service("_printer", "_tcp"); + query_mdns_service("_ipp", "_tcp"); + query_mdns_service("_afpovertcp", "_tcp"); + query_mdns_service("_smb", "_tcp"); + query_mdns_service("_ftp", "_tcp"); + query_mdns_service("_nfs", "_tcp"); +#if CONFIG_MDNS_PUBLISH_DELEGATE_HOST + lookup_mdns_delegated_service("_http", "_tcp"); +#endif // CONFIG_MDNS_PUBLISH_DELEGATE_HOST + lookup_mdns_selfhosted_service("_http", "_tcp"); + } + old_level = new_level; +} + +static void mdns_example_task(void *pvParameters) +{ +#if CONFIG_MDNS_RESOLVE_TEST_SERVICES == 1 + /* Send initial queries that are started by CI tester */ +#ifdef CONFIG_LWIP_IPV4 + query_mdns_host("tinytester"); +#endif + query_mdns_host_with_gethostbyname("tinytester-lwip.local"); + query_mdns_host_with_getaddrinfo("tinytester-lwip.local"); +#endif + + while (1) { + check_button(); + vTaskDelay(50 / portTICK_PERIOD_MS); + } +} + +void app_main(void) +{ + ESP_ERROR_CHECK(nvs_flash_init()); + ESP_ERROR_CHECK(esp_netif_init()); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + + ESP_LOGI(TAG, "mDNS Ver: %s", ESP_MDNS_VERSION_NUMBER); + + initialise_mdns(); + + /* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig. + * Read "Establishing Wi-Fi or Ethernet Connection" section in + * examples/protocols/README.md for more information about this function. + */ + ESP_ERROR_CHECK(example_connect()); + +#if defined(CONFIG_MDNS_ADD_CUSTOM_NETIF) && !defined(CONFIG_MDNS_PREDEF_NETIF_STA) && !defined(CONFIG_MDNS_PREDEF_NETIF_ETH) + /* Demonstration of adding a custom netif to mdns service, but we're adding the default example one, + * so we must disable all predefined interfaces (PREDEF_NETIF_STA, AP and ETH) first + */ + ESP_ERROR_CHECK(mdns_register_netif(EXAMPLE_INTERFACE)); + /* It is not enough to just register the interface, we have to enable is manually. + * This is typically performed in "GOT_IP" event handler, but we call it here directly + * since the `EXAMPLE_INTERFACE` netif is connected already, to keep the example simple. + */ + ESP_ERROR_CHECK(mdns_netif_action(EXAMPLE_INTERFACE, MDNS_EVENT_ENABLE_IP4 | MDNS_EVENT_ENABLE_IP6)); + ESP_ERROR_CHECK(mdns_netif_action(EXAMPLE_INTERFACE, MDNS_EVENT_ANNOUNCE_IP4 | MDNS_EVENT_ANNOUNCE_IP6)); + +#if defined(CONFIG_MDNS_RESPOND_REVERSE_QUERIES) + ESP_ERROR_CHECK(mdns_netif_action(EXAMPLE_INTERFACE, MDNS_EVENT_IP4_REVERSE_LOOKUP | MDNS_EVENT_IP6_REVERSE_LOOKUP)); +#endif + +#endif // CONFIG_MDNS_ADD_CUSTOM_NETIF + + initialise_button(); + xTaskCreate(&mdns_example_task, "mdns_example_task", 2048, NULL, 5, NULL); +} + +/** Generate host name based on sdkconfig, optionally adding a portion of MAC address to it. + * @return host name string allocated from the heap + */ +static char *generate_hostname(void) +{ +#ifndef CONFIG_MDNS_ADD_MAC_TO_HOSTNAME + return strdup(CONFIG_MDNS_HOSTNAME); +#else + uint8_t mac[6]; + char *hostname; + esp_read_mac(mac, ESP_MAC_WIFI_STA); + if (-1 == asprintf(&hostname, "%s-%02X%02X%02X", CONFIG_MDNS_HOSTNAME, mac[3], mac[4], mac[5])) { + abort(); + } + return hostname; +#endif +} + +#if CONFIG_MDNS_RESOLVE_TEST_SERVICES == 1 +/** + * @brief Executes gethostbyname and displays list of resolved addresses. + * Note: This function is used only to test advertised mdns hostnames resolution + */ +static void query_mdns_host_with_gethostbyname(char *host) +{ + struct hostent *res = gethostbyname(host); + if (res) { + unsigned int i = 0; + while (res->h_addr_list[i] != NULL) { + ESP_LOGI(TAG, "gethostbyname: %s resolved to: %s", host, +#if defined(CONFIG_LWIP_IPV6) && defined(CONFIG_LWIP_IPV4) + res->h_addrtype == AF_INET ? inet_ntoa(*(struct in_addr *)(res->h_addr_list[i])) : + inet6_ntoa(*(struct in6_addr *)(res->h_addr_list[i])) +#elif defined(CONFIG_LWIP_IPV6) + inet6_ntoa(*(struct in6_addr *)(res->h_addr_list[i])) +#else + inet_ntoa(*(struct in_addr *)(res->h_addr_list[i])) +#endif + ); + i++; + } + } +} + +/** + * @brief Executes getaddrinfo and displays list of resolved addresses. + * Note: This function is used only to test advertised mdns hostnames resolution + */ +static void query_mdns_host_with_getaddrinfo(char *host) +{ + struct addrinfo hints; + struct addrinfo *res; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + + if (!getaddrinfo(host, NULL, &hints, &res)) { + while (res) { + char *resolved_addr; +#if defined(CONFIG_LWIP_IPV6) && defined(CONFIG_LWIP_IPV4) + resolved_addr = res->ai_family == AF_INET ? + inet_ntoa(((struct sockaddr_in *) res->ai_addr)->sin_addr) : + inet6_ntoa(((struct sockaddr_in6 *) res->ai_addr)->sin6_addr); +#elif defined(CONFIG_LWIP_IPV6) + resolved_addr = inet6_ntoa(((struct sockaddr_in6 *) res->ai_addr)->sin6_addr); +#else + resolved_addr = inet_ntoa(((struct sockaddr_in *) res->ai_addr)->sin_addr); +#endif // CONFIG_LWIP_IPV6 + ESP_LOGI(TAG, "getaddrinfo: %s resolved to: %s", host, resolved_addr); + res = res->ai_next; + } + } +} +#endif diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/examples/query_advertise/pytest_mdns.py b/RainMaker_Table-Lights/managed_components/espressif__mdns/examples/query_advertise/pytest_mdns.py new file mode 100644 index 000000000..e78e094dd --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__mdns/examples/query_advertise/pytest_mdns.py @@ -0,0 +1,203 @@ +# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: Unlicense OR CC0-1.0 +import re +import select +import socket +import struct +import subprocess +import time +from threading import Event, Thread + +try: + import dpkt + import dpkt.dns +except ImportError: + pass + + +def get_dns_query_for_esp(esp_host): + dns = dpkt.dns.DNS( + b'\x00\x00\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x01' + ) + dns.qd[0].name = esp_host + u'.local' + print('Created query for esp host: {} '.format(dns.__repr__())) + return dns.pack() + + +def get_dns_answer_to_mdns(tester_host): + dns = dpkt.dns.DNS( + b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' + ) + dns.op = dpkt.dns.DNS_QR | dpkt.dns.DNS_AA + dns.rcode = dpkt.dns.DNS_RCODE_NOERR + arr = dpkt.dns.DNS.RR() + arr.cls = dpkt.dns.DNS_IN + arr.type = dpkt.dns.DNS_A + arr.name = tester_host + arr.ip = socket.inet_aton('127.0.0.1') + dns.an.append(arr) + print('Created answer to mdns query: {} '.format(dns.__repr__())) + return dns.pack() + + +def get_dns_answer_to_mdns_lwip(tester_host, id): + dns = dpkt.dns.DNS( + b'\x5e\x39\x84\x00\x00\x01\x00\x01\x00\x00\x00\x00\x0a\x64\x61\x76\x69\x64' + b'\x2d\x63\x6f\x6d\x70\x05\x6c\x6f\x63\x61\x6c\x00\x00\x01\x00\x01\xc0\x0c' + b'\x00\x01\x00\x01\x00\x00\x00\x0a\x00\x04\xc0\xa8\x0a\x6c') + dns.qd[0].name = tester_host + dns.an[0].name = tester_host + dns.an[0].ip = socket.inet_aton('127.0.0.1') + dns.an[0].rdata = socket.inet_aton('127.0.0.1') + dns.id = id + print('Created answer to mdns (lwip) query: {} '.format(dns.__repr__())) + return dns.pack() + + +def mdns_server(esp_host, events): + UDP_IP = '0.0.0.0' + UDP_PORT = 5353 + MCAST_GRP = '224.0.0.251' + TESTER_NAME = u'tinytester.local' + TESTER_NAME_LWIP = u'tinytester-lwip.local' + QUERY_TIMEOUT = 0.2 + sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1) + sock.setblocking(False) + sock.bind((UDP_IP, UDP_PORT)) + mreq = struct.pack('4sl', socket.inet_aton(MCAST_GRP), socket.INADDR_ANY) + sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq) + last_query_timepoint = time.time() + while not events['stop'].is_set(): + try: + current_time = time.time() + if current_time - last_query_timepoint > QUERY_TIMEOUT: + last_query_timepoint = current_time + if not events['esp_answered'].is_set(): + sock.sendto(get_dns_query_for_esp(esp_host), + (MCAST_GRP, UDP_PORT)) + if not events['esp_delegated_answered'].is_set(): + sock.sendto(get_dns_query_for_esp(esp_host + '-delegated'), + (MCAST_GRP, UDP_PORT)) + timeout = max( + 0, QUERY_TIMEOUT - (current_time - last_query_timepoint)) + read_socks, _, _ = select.select([sock], [], [], timeout) + if not read_socks: + continue + data, addr = sock.recvfrom(1024) + dns = dpkt.dns.DNS(data) + if len(dns.qd) > 0: + for dns_query in dns.qd: + if dns_query.type == dpkt.dns.DNS_A: + if dns_query.name == TESTER_NAME: + print('Received query: {} '.format(dns.__repr__())) + sock.sendto(get_dns_answer_to_mdns(TESTER_NAME), + (MCAST_GRP, UDP_PORT)) + elif dns_query.name == TESTER_NAME_LWIP: + print('Received query: {} '.format(dns.__repr__())) + sock.sendto( + get_dns_answer_to_mdns_lwip(TESTER_NAME_LWIP, dns.id), + addr) + if len(dns.an) > 0: + for dns_answer in dns.an: + if dns_answer.type == dpkt.dns.DNS_A: + print('Received answer from {}'.format(dns_answer.name)) + if dns_answer.name == esp_host + u'.local': + print('Received answer to esp32-mdns query: {}'.format( + dns.__repr__())) + events['esp_answered'].set() + if dns_answer.name == esp_host + u'-delegated.local': + print('Received answer to esp32-mdns-delegate query: {}'.format( + dns.__repr__())) + events['esp_delegated_answered'].set() + except socket.timeout: + break + except dpkt.UnpackError: + continue + + +def test_examples_protocol_mdns(dut): + """ + steps: | + 1. obtain IP address + init mdns example + 2. get the dut host name (and IP address) + 3. check the mdns name is accessible + 4. check DUT output if mdns advertized host is resolved + 5. check if DUT responds to dig + 6. check the DUT is searchable via reverse IP lookup + """ + + specific_host = dut.expect(r'mdns hostname set to: \[(.*?)\]')[1].decode() + + mdns_server_events = { + 'stop': Event(), + 'esp_answered': Event(), + 'esp_delegated_answered': Event() + } + mdns_responder = Thread(target=mdns_server, + args=(str(specific_host), mdns_server_events)) + ip_addresses = [] + if dut.app.sdkconfig.get('LWIP_IPV4') is True: + ipv4 = dut.expect(r'IPv4 address: (\d+\.\d+\.\d+\.\d+)[^\d]', + timeout=30)[1].decode() + ip_addresses.append(ipv4) + if dut.app.sdkconfig.get('LWIP_IPV6') is True: + ipv6_r = r':'.join((r'[0-9a-fA-F]{4}', ) * 8) + ipv6 = dut.expect(ipv6_r, timeout=30)[0].decode() + ip_addresses.append(ipv6) + print('Connected with IP addresses: {}'.format(','.join(ip_addresses))) + try: + # TODO: Add test for example disabling IPV4 + mdns_responder.start() + if dut.app.sdkconfig.get('LWIP_IPV4') is True: + # 3. check the mdns name is accessible. + if not mdns_server_events['esp_answered'].wait(timeout=30): + raise ValueError( + 'Test has failed: did not receive mdns answer within timeout') + if not mdns_server_events['esp_delegated_answered'].wait(timeout=30): + raise ValueError( + 'Test has failed: did not receive mdns answer for delegated host within timeout' + ) + # 4. check DUT output if mdns advertized host is resolved + dut.expect( + re.compile( + b'mdns-test: Query A: tinytester.local resolved to: 127.0.0.1') + ) + dut.expect( + re.compile( + b'mdns-test: gethostbyname: tinytester-lwip.local resolved to: 127.0.0.1' + )) + dut.expect( + re.compile( + b'mdns-test: getaddrinfo: tinytester-lwip.local resolved to: 127.0.0.1' + )) + # 5. check the DUT answers to `dig` command + dig_output = subprocess.check_output([ + 'dig', '+short', '-p', '5353', '@224.0.0.251', + '{}.local'.format(specific_host) + ]) + print('Resolving {} using "dig" succeeded with:\n{}'.format( + specific_host, dig_output)) + if not ipv4.encode('utf-8') in dig_output: + raise ValueError( + 'Test has failed: Incorrectly resolved DUT hostname using dig' + "Output should've contained DUT's IP address:{}".format(ipv4)) + # 6. check the DUT reverse lookup + if dut.app.sdkconfig.get('MDNS_RESPOND_REVERSE_QUERIES') is True: + for ip_address in ip_addresses: + dig_output = subprocess.check_output([ + 'dig', '+short', '-p', '5353', '@224.0.0.251', '-x', + '{}'.format(ip_address) + ]) + print('Reverse lookup for {} using "dig" succeeded with:\n{}'. + format(ip_address, dig_output)) + if specific_host not in dig_output.decode(): + raise ValueError( + 'Test has failed: Incorrectly resolved DUT IP address using dig' + "Output should've contained DUT's name:{}".format( + specific_host)) + + finally: + mdns_server_events['stop'].set() + mdns_responder.join() diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/examples/query_advertise/sdkconfig.ci.eth_custom_netif b/RainMaker_Table-Lights/managed_components/espressif__mdns/examples/query_advertise/sdkconfig.ci.eth_custom_netif new file mode 100644 index 000000000..b9d712041 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__mdns/examples/query_advertise/sdkconfig.ci.eth_custom_netif @@ -0,0 +1,20 @@ +CONFIG_IDF_TARGET="esp32" +CONFIG_MDNS_RESOLVE_TEST_SERVICES=y +CONFIG_MDNS_ADD_MAC_TO_HOSTNAME=y +CONFIG_MDNS_PUBLISH_DELEGATE_HOST=y +CONFIG_MDNS_PREDEF_NETIF_STA=n +CONFIG_MDNS_PREDEF_NETIF_AP=n +CONFIG_MDNS_PREDEF_NETIF_ETH=n +CONFIG_MDNS_ADD_CUSTOM_NETIF=y +CONFIG_MDNS_RESPOND_REVERSE_QUERIES=y +CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES=y +CONFIG_EXAMPLE_CONNECT_ETHERNET=y +CONFIG_EXAMPLE_CONNECT_WIFI=n +CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y +CONFIG_EXAMPLE_ETH_PHY_IP101=y +CONFIG_EXAMPLE_ETH_MDC_GPIO=23 +CONFIG_EXAMPLE_ETH_MDIO_GPIO=18 +CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5 +CONFIG_EXAMPLE_ETH_PHY_ADDR=1 +CONFIG_EXAMPLE_CONNECT_IPV6=y +CONFIG_MDNS_BUTTON_GPIO=32 diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/examples/query_advertise/sdkconfig.ci.eth_def b/RainMaker_Table-Lights/managed_components/espressif__mdns/examples/query_advertise/sdkconfig.ci.eth_def new file mode 100644 index 000000000..703b4543e --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__mdns/examples/query_advertise/sdkconfig.ci.eth_def @@ -0,0 +1,15 @@ +CONFIG_IDF_TARGET="esp32" +CONFIG_MDNS_RESOLVE_TEST_SERVICES=y +CONFIG_MDNS_ADD_MAC_TO_HOSTNAME=y +CONFIG_MDNS_PUBLISH_DELEGATE_HOST=y +CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES=y +CONFIG_EXAMPLE_CONNECT_ETHERNET=y +CONFIG_EXAMPLE_CONNECT_WIFI=n +CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y +CONFIG_EXAMPLE_ETH_PHY_IP101=y +CONFIG_EXAMPLE_ETH_MDC_GPIO=23 +CONFIG_EXAMPLE_ETH_MDIO_GPIO=18 +CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5 +CONFIG_EXAMPLE_ETH_PHY_ADDR=1 +CONFIG_EXAMPLE_CONNECT_IPV6=y +CONFIG_MDNS_BUTTON_GPIO=32 diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/examples/query_advertise/sdkconfig.ci.eth_no_ipv4 b/RainMaker_Table-Lights/managed_components/espressif__mdns/examples/query_advertise/sdkconfig.ci.eth_no_ipv4 new file mode 100644 index 000000000..b77a75270 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__mdns/examples/query_advertise/sdkconfig.ci.eth_no_ipv4 @@ -0,0 +1,15 @@ +CONFIG_IDF_TARGET="esp32" +CONFIG_MDNS_RESOLVE_TEST_SERVICES=y +CONFIG_MDNS_ADD_MAC_TO_HOSTNAME=y +CONFIG_MDNS_PUBLISH_DELEGATE_HOST=y +CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES=y +CONFIG_LWIP_IPV4=n +CONFIG_EXAMPLE_CONNECT_ETHERNET=y +CONFIG_EXAMPLE_CONNECT_WIFI=n +CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y +CONFIG_EXAMPLE_ETH_PHY_IP101=y +CONFIG_EXAMPLE_ETH_MDC_GPIO=23 +CONFIG_EXAMPLE_ETH_MDIO_GPIO=18 +CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5 +CONFIG_EXAMPLE_ETH_PHY_ADDR=1 +CONFIG_MDNS_BUTTON_GPIO=32 diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/examples/query_advertise/sdkconfig.ci.eth_no_ipv6 b/RainMaker_Table-Lights/managed_components/espressif__mdns/examples/query_advertise/sdkconfig.ci.eth_no_ipv6 new file mode 100644 index 000000000..d669ec075 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__mdns/examples/query_advertise/sdkconfig.ci.eth_no_ipv6 @@ -0,0 +1,16 @@ +CONFIG_IDF_TARGET="esp32" +CONFIG_MDNS_RESOLVE_TEST_SERVICES=y +CONFIG_MDNS_ADD_MAC_TO_HOSTNAME=y +CONFIG_MDNS_PUBLISH_DELEGATE_HOST=y +CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES=y +CONFIG_LWIP_IPV6=n +CONFIG_EXAMPLE_CONNECT_IPV6=n +CONFIG_EXAMPLE_CONNECT_ETHERNET=y +CONFIG_EXAMPLE_CONNECT_WIFI=n +CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y +CONFIG_EXAMPLE_ETH_PHY_IP101=y +CONFIG_EXAMPLE_ETH_MDC_GPIO=23 +CONFIG_EXAMPLE_ETH_MDIO_GPIO=18 +CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5 +CONFIG_EXAMPLE_ETH_PHY_ADDR=1 +CONFIG_MDNS_BUTTON_GPIO=32 diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/examples/query_advertise/sdkconfig.ci.eth_socket b/RainMaker_Table-Lights/managed_components/espressif__mdns/examples/query_advertise/sdkconfig.ci.eth_socket new file mode 100644 index 000000000..5d9240526 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__mdns/examples/query_advertise/sdkconfig.ci.eth_socket @@ -0,0 +1,16 @@ +CONFIG_IDF_TARGET="esp32" +CONFIG_MDNS_RESOLVE_TEST_SERVICES=y +CONFIG_MDNS_ADD_MAC_TO_HOSTNAME=y +CONFIG_MDNS_PUBLISH_DELEGATE_HOST=y +CONFIG_MDNS_NETWORKING_SOCKET=y +CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES=y +CONFIG_EXAMPLE_CONNECT_ETHERNET=y +CONFIG_EXAMPLE_CONNECT_WIFI=n +CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y +CONFIG_EXAMPLE_ETH_PHY_IP101=y +CONFIG_EXAMPLE_ETH_MDC_GPIO=23 +CONFIG_EXAMPLE_ETH_MDIO_GPIO=18 +CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5 +CONFIG_EXAMPLE_ETH_PHY_ADDR=1 +CONFIG_EXAMPLE_CONNECT_IPV6=y +CONFIG_MDNS_BUTTON_GPIO=32 diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/idf_component.yml b/RainMaker_Table-Lights/managed_components/espressif__mdns/idf_component.yml new file mode 100644 index 000000000..c920b726e --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__mdns/idf_component.yml @@ -0,0 +1,13 @@ +dependencies: + idf: + version: '>=5.0' +description: Multicast UDP service used to provide local network service and host + discovery. +documentation: https://docs.espressif.com/projects/esp-protocols/mdns/docs/latest/en/index.html +issues: https://github.com/espressif/esp-protocols/issues +repository: git://github.com/espressif/esp-protocols.git +repository_info: + commit_sha: e9d7350219dfb5e39eb56e5ef60c094190888c55 + path: components/mdns +url: https://github.com/espressif/esp-protocols/tree/master/components/mdns +version: 1.8.2 diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/include/mdns.h b/RainMaker_Table-Lights/managed_components/espressif__mdns/include/mdns.h new file mode 100644 index 000000000..4c89dde73 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__mdns/include/mdns.h @@ -0,0 +1,937 @@ +/* + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ESP_MDNS_H_ +#define ESP_MDNS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "sdkconfig.h" +#include + +#define MDNS_TYPE_A 0x0001 +#define MDNS_TYPE_PTR 0x000C +#define MDNS_TYPE_TXT 0x0010 +#define MDNS_TYPE_AAAA 0x001C +#define MDNS_TYPE_SRV 0x0021 +#define MDNS_TYPE_OPT 0x0029 +#define MDNS_TYPE_NSEC 0x002F +#define MDNS_TYPE_ANY 0x00FF + +#if defined(CONFIG_LWIP_IPV6) && defined(CONFIG_MDNS_RESPOND_REVERSE_QUERIES) +#define MDNS_NAME_MAX_LEN (64+4) // Need to account for IPv6 reverse queries (64 char address + ".ip6" ) +#else +#define MDNS_NAME_MAX_LEN 64 // Maximum string length of hostname, instance, service and proto +#endif +#define MDNS_NAME_BUF_LEN (MDNS_NAME_MAX_LEN+1) // Maximum char buffer size to hold hostname, instance, service or proto + +/** + * @brief Asynchronous query handle + */ +typedef struct mdns_search_once_s mdns_search_once_t; + +/** + * @brief Daemon query handle + */ +typedef struct mdns_browse_s mdns_browse_t; + +typedef enum { + MDNS_EVENT_ENABLE_IP4 = 1 << 1, + MDNS_EVENT_ENABLE_IP6 = 1 << 2, + MDNS_EVENT_ANNOUNCE_IP4 = 1 << 3, + MDNS_EVENT_ANNOUNCE_IP6 = 1 << 4, + MDNS_EVENT_DISABLE_IP4 = 1 << 5, + MDNS_EVENT_DISABLE_IP6 = 1 << 6, + MDNS_EVENT_IP4_REVERSE_LOOKUP = 1 << 7, + MDNS_EVENT_IP6_REVERSE_LOOKUP = 1 << 8, +} mdns_event_actions_t; + +/** + * @brief mDNS enum to specify the ip_protocol type + */ +typedef enum { + MDNS_IP_PROTOCOL_V4, + MDNS_IP_PROTOCOL_V6, + MDNS_IP_PROTOCOL_MAX +} mdns_ip_protocol_t; + +/** + * @brief mDNS basic text item structure + * Used in mdns_service_add() + */ +typedef struct { + const char *key; /*!< item key name */ + const char *value; /*!< item value string */ +} mdns_txt_item_t; + +/** + * @brief mDNS basic subtype item structure + * Used in mdns_service_subtype_xxx() APIs + */ +typedef struct { + const char *subtype; /*!< subtype name */ +} mdns_subtype_item_t; + +/** + * @brief mDNS query linked list IP item + */ +typedef struct mdns_ip_addr_s { + esp_ip_addr_t addr; /*!< IP address */ + struct mdns_ip_addr_s *next; /*!< next IP, or NULL for the last IP in the list */ +} mdns_ip_addr_t; + +/** + * @brief mDNS query type to be explicitly set to either Unicast or Multicast + */ +typedef enum { + MDNS_QUERY_UNICAST, + MDNS_QUERY_MULTICAST, +} mdns_query_transmission_type_t; + +/** + * @brief mDNS query result structure + */ +typedef struct mdns_result_s { + struct mdns_result_s *next; /*!< next result, or NULL for the last result in the list */ + + esp_netif_t *esp_netif; /*!< ptr to corresponding esp-netif */ + uint32_t ttl; /*!< time to live */ + + mdns_ip_protocol_t ip_protocol; /*!< ip_protocol type of the interface (v4/v6) */ + // PTR + char *instance_name; /*!< instance name */ + char *service_type; /*!< service type */ + char *proto; /*!< srevice protocol */ + // SRV + char *hostname; /*!< hostname */ + uint16_t port; /*!< service port */ + // TXT + mdns_txt_item_t *txt; /*!< txt record */ + uint8_t *txt_value_len; /*!< array of txt value len of each record */ + size_t txt_count; /*!< number of txt items */ + // A and AAAA + mdns_ip_addr_t *addr; /*!< linked list of IP addresses found */ +} mdns_result_t; + +typedef void (*mdns_query_notify_t)(mdns_search_once_t *search); +typedef void (*mdns_browse_notify_t)(mdns_result_t *result); + +/** + * @brief Initialize mDNS on given interface + * + * @return + * - ESP_OK on success + * - ESP_ERR_INVALID_STATE when failed to register event handler + * - ESP_ERR_NO_MEM on memory error + * - ESP_FAIL when failed to start mdns task + */ +esp_err_t mdns_init(void); + +/** + * @brief Stop and free mDNS server + * + */ +void mdns_free(void); + +/** + * @brief Set the hostname for mDNS server + * required if you want to advertise services + * + * @param hostname Hostname to set + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_ERR_NO_MEM memory error + */ +esp_err_t mdns_hostname_set(const char *hostname); + +/** + * @brief Get the hostname for mDNS server + * + * @param hostname pointer to the hostname, it should be allocated + * and hold at least MDNS_NAME_BUF_LEN chars + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_ERR_INVALID_STATE when mdns is not initialized + */ +esp_err_t mdns_hostname_get(char *hostname); + +/** + * @brief Adds a hostname and address to be delegated + * A/AAAA queries will be replied for the hostname and + * services can be added to this host. + * + * @param hostname Hostname to add + * @param address_list The IP address list of the host + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_STATE mDNS is not running + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_ERR_NO_MEM memory error + * + */ +esp_err_t mdns_delegate_hostname_add(const char *hostname, const mdns_ip_addr_t *address_list); + +/** + * @brief Set the address to a delegated hostname + * + * @param hostname Hostname to set + * @param address_list The IP address list of the host + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_STATE mDNS is not running + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_ERR_NO_MEM memory error + * + */ +esp_err_t mdns_delegate_hostname_set_address(const char *hostname, const mdns_ip_addr_t *address_list); + +/** + * @brief Remove a delegated hostname + * All the services added to this host will also be removed. + * + * @param hostname Hostname to remove + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_STATE mDNS is not running + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_ERR_NO_MEM memory error + * + */ +esp_err_t mdns_delegate_hostname_remove(const char *hostname); + +/** + * @brief Query whether a hostname has been added + * + * @param hostname Hostname to query + * + * @return + * - true The hostname has been added. + * - false The hostname has not been added. + * + */ +bool mdns_hostname_exists(const char *hostname); + +/** + * @brief Set the default instance name for mDNS server + * + * @param instance_name Instance name to set + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_ERR_NO_MEM memory error + */ +esp_err_t mdns_instance_name_set(const char *instance_name); + +/** + * @brief Add service to mDNS server + * + * @note The value length of txt items will be automatically decided by strlen + * + * @param instance_name instance name to set. If NULL, + * global instance name or hostname will be used. + * Note that MDNS_MULTIPLE_INSTANCE config option + * needs to be enabled for adding multiple instances + * with the same instance type. + * @param service_type service type (_http, _ftp, etc) + * @param proto service protocol (_tcp, _udp) + * @param port service port + * @param txt string array of TXT data (eg. {{"var","val"},{"other","2"}}) + * @param num_items number of items in TXT data + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_ERR_NO_MEM memory error + * - ESP_FAIL failed to add service + */ +esp_err_t mdns_service_add(const char *instance_name, const char *service_type, const char *proto, uint16_t port, mdns_txt_item_t txt[], size_t num_items); + +/** + * @brief Add service to mDNS server with a delegated hostname + * + * @note The value length of txt items will be automatically decided by strlen + * + * @param instance_name instance name to set. If NULL, + * global instance name or hostname will be used + * Note that MDNS_MULTIPLE_INSTANCE config option + * needs to be enabled for adding multiple instances + * with the same instance type. + * @param service_type service type (_http, _ftp, etc) + * @param proto service protocol (_tcp, _udp) + * @param hostname service hostname. If NULL, local hostname will be used. + * @param port service port + * @param txt string array of TXT data (eg. {{"var","val"},{"other","2"}}) + * @param num_items number of items in TXT data + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_ERR_NO_MEM memory error + * - ESP_FAIL failed to add service + */ +esp_err_t mdns_service_add_for_host(const char *instance_name, const char *service_type, const char *proto, + const char *hostname, uint16_t port, mdns_txt_item_t txt[], size_t num_items); + +/** + * @brief Check whether a service has been added. + * + * @param service_type service type (_http, _ftp, etc) + * @param proto service protocol (_tcp, _udp) + * @param hostname service hostname. If NULL, checks for the local hostname. + * + * @return + * - true Correspondding service has been added. + * - false Service not found. + */ +bool mdns_service_exists(const char *service_type, const char *proto, const char *hostname); + +/** + * @brief Check whether a service has been added. + * + * @param instance instance name + * @param service_type service type (_http, _ftp, etc) + * @param proto service protocol (_tcp, _udp) + * @param hostname service hostname. If NULL, checks for the local hostname. + * + * @return + * - true Correspondding service has been added. + * - false Service not found. + */ +bool mdns_service_exists_with_instance(const char *instance, const char *service_type, const char *proto, + const char *hostname); + +/** + * @brief Remove service from mDNS server + * + * @param service_type service type (_http, _ftp, etc) + * @param proto service protocol (_tcp, _udp) + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_ERR_NOT_FOUND Service not found + * - ESP_ERR_NO_MEM memory error + */ +esp_err_t mdns_service_remove(const char *service_type, const char *proto); + +/** + * @brief Remove service from mDNS server with hostname + * + * @param instance instance name + * @param service_type service type (_http, _ftp, etc) + * @param proto service protocol (_tcp, _udp) + * @param hostname service hostname. If NULL, local hostname will be used. + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_ERR_NOT_FOUND Service not found + * - ESP_ERR_NO_MEM memory error + */ +esp_err_t mdns_service_remove_for_host(const char *instance, const char *service_type, const char *proto, const char *hostname); + +/** + * @brief Set instance name for service + * + * @param service_type service type (_http, _ftp, etc) + * @param proto service protocol (_tcp, _udp) + * @param instance_name instance name to set + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_ERR_NOT_FOUND Service not found + * - ESP_ERR_NO_MEM memory error + */ +esp_err_t mdns_service_instance_name_set(const char *service_type, const char *proto, const char *instance_name); + +/** + * @brief Set instance name for service with hostname + * + * @param instance_old original instance name + * @param service_type service type (_http, _ftp, etc) + * @param proto service protocol (_tcp, _udp) + * @param hostname service hostname. If NULL, local hostname will be used. + * @param instance_name instance name to set + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_ERR_NOT_FOUND Service not found + * - ESP_ERR_NO_MEM memory error + */ +esp_err_t mdns_service_instance_name_set_for_host(const char *instance_old, const char *service_type, const char *proto, const char *hostname, + const char *instance_name); + +/** + * @brief Set service port + * + * @param service_type service type (_http, _ftp, etc) + * @param proto service protocol (_tcp, _udp) + * @param port service port + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_ERR_NOT_FOUND Service not found + * - ESP_ERR_NO_MEM memory error + */ +esp_err_t mdns_service_port_set(const char *service_type, const char *proto, uint16_t port); + + +/** + * @brief Set service port with hostname + * + * @param instance instance name + * @param service_type service type (_http, _ftp, etc) + * @param proto service protocol (_tcp, _udp) + * @param hostname service hostname. If NULL, local hostname will be used. + * @param port service port + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_ERR_NOT_FOUND Service not found + * - ESP_ERR_NO_MEM memory error + */ +esp_err_t mdns_service_port_set_for_host(const char *instance, const char *service_type, const char *proto, const char *hostname, + uint16_t port); + +/** + * @brief Replace all TXT items for service + * + * @note The value length of txt items will be automatically decided by strlen + * + * @param service_type service type (_http, _ftp, etc) + * @param proto service protocol (_tcp, _udp) + * @param txt array of TXT data (eg. {{"var","val"},{"other","2"}}) + * @param num_items number of items in TXT data + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_ERR_NOT_FOUND Service not found + * - ESP_ERR_NO_MEM memory error + */ +esp_err_t mdns_service_txt_set(const char *service_type, const char *proto, mdns_txt_item_t txt[], uint8_t num_items); + +/** + * @brief Replace all TXT items for service with hostname + * + * @note The value length of txt items will be automatically decided by strlen + * + * @param instance instance name + * @param service_type service type (_http, _ftp, etc) + * @param proto service protocol (_tcp, _udp) + * @param hostname service hostname. If NULL, local hostname will be used. + * @param txt array of TXT data (eg. {{"var","val"},{"other","2"}}) + * @param num_items number of items in TXT data + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_ERR_NOT_FOUND Service not found + * - ESP_ERR_NO_MEM memory error + */ +esp_err_t mdns_service_txt_set_for_host(const char *instance, const char *service_type, const char *proto, const char *hostname, + mdns_txt_item_t txt[], uint8_t num_items); + +/** + * @brief Set/Add TXT item for service TXT record + * + * @note The value length will be automatically decided by strlen + * + * @param service_type service type (_http, _ftp, etc) + * @param proto service protocol (_tcp, _udp) + * @param key the key that you want to add/update + * @param value the new value of the key + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_ERR_NOT_FOUND Service not found + * - ESP_ERR_NO_MEM memory error + */ +esp_err_t mdns_service_txt_item_set(const char *service_type, const char *proto, const char *key, const char *value); + +/** + * @brief Set/Add TXT item for service TXT record + * + * @param service_type service type (_http, _ftp, etc) + * @param proto service protocol (_tcp, _udp) + * @param key the key that you want to add/update + * @param value the new value of the key + * @param value_len the length of the value + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_ERR_NOT_FOUND Service not found + * - ESP_ERR_NO_MEM memory error + */ +esp_err_t mdns_service_txt_item_set_with_explicit_value_len(const char *service_type, const char *proto, + const char *key, const char *value, uint8_t value_len); + +/** + * @brief Set/Add TXT item for service TXT record with hostname + * + * @note The value length will be automatically decided by strlen + * + * @param instance instance name + * @param service_type service type (_http, _ftp, etc) + * @param proto service protocol (_tcp, _udp) + * @param hostname service hostname. If NULL, local hostname will be used. + * @param key the key that you want to add/update + * @param value the new value of the key + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_ERR_NOT_FOUND Service not found + * - ESP_ERR_NO_MEM memory error + */ +esp_err_t mdns_service_txt_item_set_for_host(const char *instance, const char *service_type, const char *proto, const char *hostname, + const char *key, const char *value); + +/** + * @brief Set/Add TXT item for service TXT record with hostname and txt value length + * + * @param instance instance name + * @param service_type service type (_http, _ftp, etc) + * @param proto service protocol (_tcp, _udp) + * @param hostname service hostname. If NULL, local hostname will be used. + * @param key the key that you want to add/update + * @param value the new value of the key + * @param value_len the length of the value + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_ERR_NOT_FOUND Service not found + * - ESP_ERR_NO_MEM memory error + */ +esp_err_t mdns_service_txt_item_set_for_host_with_explicit_value_len(const char *instance, const char *service_type, const char *proto, + const char *hostname, const char *key, + const char *value, uint8_t value_len); + +/** + * @brief Remove TXT item for service TXT record + * + * @param service_type service type (_http, _ftp, etc) + * @param proto service protocol (_tcp, _udp) + * @param key the key that you want to remove + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_ERR_NOT_FOUND Service not found + * - ESP_ERR_NO_MEM memory error + */ +esp_err_t mdns_service_txt_item_remove(const char *service_type, const char *proto, const char *key); + +/** + * @brief Remove TXT item for service TXT record with hostname + * + * @param instance instance name + * @param service_type service type (_http, _ftp, etc) + * @param proto service protocol (_tcp, _udp) + * @param hostname service hostname. If NULL, local hostname will be used. + * @param key the key that you want to remove + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_ERR_NOT_FOUND Service not found + * - ESP_ERR_NO_MEM memory error + */ +esp_err_t mdns_service_txt_item_remove_for_host(const char *instance, const char *service_type, const char *proto, const char *hostname, + const char *key); + +/** + * @brief Add a subtype for service. + * + * @param instance_name instance name. If NULL, will find the first service with the same service type and protocol. + * @param service_type service type (_http, _ftp, etc) + * @param proto service protocol (_tcp, _udp) + * @param hostname service hostname. If NULL, local hostname will be used. + * @param subtype The subtype to add. + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_ERR_NOT_FOUND Service not found + * - ESP_ERR_NO_MEM memory error + */ +esp_err_t mdns_service_subtype_add_for_host(const char *instance_name, const char *service_type, const char *proto, + const char *hostname, const char *subtype); + +/** + * @brief Remove a subtype for service. + * + * @param instance_name instance name. If NULL, will find the first service with the same service type and protocol. + * @param service_type service type (_http, _ftp, etc) + * @param proto service protocol (_tcp, _udp) + * @param hostname service hostname. If NULL, local hostname will be used. + * @param subtype The subtype to remove. + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_ERR_NOT_FOUND Service not found + */ +esp_err_t mdns_service_subtype_remove_for_host(const char *instance_name, const char *service_type, const char *proto, + const char *hostname, const char *subtype); + +/** + * @brief Add multiple subtypes for service at once. + * + * @param instance_name instance name. If NULL, will find the first service with the same service type and protocol. + * @param service_type service type (_http, _ftp, etc) + * @param proto service protocol (_tcp, _udp) + * @param hostname service hostname. If NULL, local hostname will be used. + * @param subtype the pointer of subtype array to add. + * @param num_items number of items in subtype array + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_ERR_NOT_FOUND Service not found + * - ESP_ERR_NO_MEM memory error + */ +esp_err_t mdns_service_subtype_add_multiple_items_for_host(const char *instance_name, const char *service_type, const char *proto, + const char *hostname, mdns_subtype_item_t subtype[], uint8_t num_items); + +/** + * @brief Update subtype for service. + * + * @param instance_name instance name. If NULL, will find the first service with the same service type and protocol. + * @param service_type service type (_http, _ftp, etc) + * @param proto service protocol (_tcp, _udp) + * @param hostname service hostname. If NULL, local hostname will be used. + * @param subtype the pointer of subtype array to add. + * @param num_items number of items in subtype array + * + * @note If `num_items` is 0, then remove all subtypes. + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_ARG Parameter error + * - ESP_ERR_NOT_FOUND Service not found + * - ESP_ERR_NO_MEM memory error + */ +esp_err_t mdns_service_subtype_update_multiple_items_for_host(const char *instance_name, const char *service_type, const char *proto, + const char *hostname, mdns_subtype_item_t subtype[], uint8_t num_items); +/** + * @brief Remove and free all services from mDNS server + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_ARG Parameter error + */ +esp_err_t mdns_service_remove_all(void); + +/** + * @brief Deletes the finished query. Call this only after the search has ended! + * + * @param search pointer to search object + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_STATE search has not finished + * - ESP_ERR_INVALID_ARG pointer to search object is NULL + */ +esp_err_t mdns_query_async_delete(mdns_search_once_t *search); + +/** + * @brief Get results from search pointer. Results available as a pointer to the output parameter. + * Pointer to search object has to be deleted via `mdns_query_async_delete` once the query has finished. + * The results although have to be freed manually. + * + * @param search pointer to search object + * @param timeout time in milliseconds to wait for answers + * @param results pointer to the results of the query + * @param num_results pointer to the number of the actual result items (set to NULL to ignore this return value) + * + * @return + * True if search has finished before or at timeout + * False if search timeout is over + */ +bool mdns_query_async_get_results(mdns_search_once_t *search, uint32_t timeout, mdns_result_t **results, uint8_t *num_results); + +/** + * @brief Query mDNS for host or service asynchronousely. + * Search has to be tested for progress and deleted manually! + * + * @param name service instance or host name (NULL for PTR queries) + * @param service_type service type (_http, _arduino, _ftp etc.) (NULL for host queries) + * @param proto service protocol (_tcp, _udp, etc.) (NULL for host queries) + * @param type type of query (MDNS_TYPE_*) + * @param timeout time in milliseconds during which mDNS query is active + * @param max_results maximum results to be collected + * @param notifier Notification function to be called when the result is ready, can be NULL + * + * @return mdns_search_once_s pointer to new search object if query initiated successfully. + * NULL otherwise. + */ +mdns_search_once_t *mdns_query_async_new(const char *name, const char *service_type, const char *proto, uint16_t type, + uint32_t timeout, size_t max_results, mdns_query_notify_t notifier); + +/** + * @brief Generic mDNS query + * All following query methods are derived from this one + * + * @param name service instance or host name (NULL for PTR queries) + * @param service_type service type (_http, _arduino, _ftp etc.) (NULL for host queries) + * @param proto service protocol (_tcp, _udp, etc.) (NULL for host queries) + * @param type type of query (MDNS_TYPE_*) + * @param transmission_type either Unicast query, or Multicast query + * @param timeout time in milliseconds to wait for answers. + * @param max_results maximum results to be collected + * @param results pointer to the results of the query + * results must be freed using mdns_query_results_free below + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_STATE mDNS is not running + * - ESP_ERR_NO_MEM memory error + * - ESP_ERR_INVALID_ARG timeout was not given + */ +esp_err_t mdns_query_generic(const char *name, const char *service_type, const char *proto, uint16_t type, + mdns_query_transmission_type_t transmission_type, uint32_t timeout, size_t max_results, mdns_result_t **results); + +/** + * @brief Query mDNS for host or service + * + * Note that querying PTR types sends Multicast query, all other types send Unicast queries + * + * @param name service instance or host name (NULL for PTR queries) + * @param service_type service type (_http, _arduino, _ftp etc.) (NULL for host queries) + * @param proto service protocol (_tcp, _udp, etc.) (NULL for host queries) + * @param type type of query (MDNS_TYPE_*) + * @param timeout time in milliseconds to wait for answers. + * @param max_results maximum results to be collected + * @param results pointer to the results of the query + * results must be freed using mdns_query_results_free below + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_STATE mDNS is not running + * - ESP_ERR_NO_MEM memory error + * - ESP_ERR_INVALID_ARG timeout was not given + */ +esp_err_t mdns_query(const char *name, const char *service_type, const char *proto, uint16_t type, uint32_t timeout, size_t max_results, mdns_result_t **results); + +/** + * @brief Free query results + * + * @param results linked list of results to be freed + */ +void mdns_query_results_free(mdns_result_t *results); + +/** + * @brief Query mDNS for service + * + * @param service_type service type (_http, _arduino, _ftp etc.) + * @param proto service protocol (_tcp, _udp, etc.) + * @param timeout time in milliseconds to wait for answer. + * @param max_results maximum results to be collected + * @param results pointer to the results of the query + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_STATE mDNS is not running + * - ESP_ERR_NO_MEM memory error + * - ESP_ERR_INVALID_ARG parameter error + */ +esp_err_t mdns_query_ptr(const char *service_type, const char *proto, uint32_t timeout, size_t max_results, mdns_result_t **results); + +/** + * @brief Query mDNS for SRV record + * + * @param instance_name service instance name + * @param service_type service type (_http, _arduino, _ftp etc.) + * @param proto service protocol (_tcp, _udp, etc.) + * @param timeout time in milliseconds to wait for answer. + * @param result pointer to the result of the query + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_STATE mDNS is not running + * - ESP_ERR_NO_MEM memory error + * - ESP_ERR_INVALID_ARG parameter error + */ +esp_err_t mdns_query_srv(const char *instance_name, const char *service_type, const char *proto, uint32_t timeout, mdns_result_t **result); + +/** + * @brief Query mDNS for TXT record + * + * @param instance_name service instance name + * @param service_type service type (_http, _arduino, _ftp etc.) + * @param proto service protocol (_tcp, _udp, etc.) + * @param timeout time in milliseconds to wait for answer. + * @param result pointer to the result of the query + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_STATE mDNS is not running + * - ESP_ERR_NO_MEM memory error + * - ESP_ERR_INVALID_ARG parameter error + */ +esp_err_t mdns_query_txt(const char *instance_name, const char *service_type, const char *proto, uint32_t timeout, mdns_result_t **result); + +/** + * @brief Look up delegated services. + * + * @param instance instance name (NULL for uncertain instance) + * @param service_type service type (_http, _ftp, etc) + * @param proto service protocol (_tcp, _udp) + * @param max_results maximum results to be collected + * @param result pointer to the result of the search + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_STATE mDNS is not running + * - ESP_ERR_NO_MEM memory error + * - ESP_ERR_INVALID_ARG parameter error + */ +esp_err_t mdns_lookup_delegated_service(const char *instance, const char *service_type, const char *proto, size_t max_results, + mdns_result_t **result); + +/** + * @brief Look up self hosted services. + * + * @param instance instance name (NULL for uncertain instance) + * @param service_type service type (_http, _ftp, etc) + * @param proto service protocol (_tcp, _udp) + * @param max_results maximum results to be collected + * @param result pointer to the result of the search + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_STATE mDNS is not running + * - ESP_ERR_NO_MEM memory error + * - ESP_ERR_INVALID_ARG parameter error + */ +esp_err_t mdns_lookup_selfhosted_service(const char *instance, const char *service_type, const char *proto, size_t max_results, + mdns_result_t **result); + +/** + * @brief Query mDNS for A record + * + * @param host_name host name to look for + * @param timeout time in milliseconds to wait for answer. + * @param addr pointer to the resulting IP4 address + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_STATE mDNS is not running + * - ESP_ERR_NO_MEM memory error + * - ESP_ERR_INVALID_ARG parameter error + */ +esp_err_t mdns_query_a(const char *host_name, uint32_t timeout, esp_ip4_addr_t *addr); + +#if CONFIG_LWIP_IPV6 +/** + * @brief Query mDNS for A record + * + * Please note that hostname must not contain domain name, as mDNS uses '.local' domain. + * + * @param host_name host name to look for + * @param timeout time in milliseconds to wait for answer. If 0, max_results needs to be defined + * @param addr pointer to the resulting IP6 address + * + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_STATE mDNS is not running + * - ESP_ERR_NO_MEM memory error + * - ESP_ERR_INVALID_ARG parameter error + */ +esp_err_t mdns_query_aaaa(const char *host_name, uint32_t timeout, esp_ip6_addr_t *addr); +#endif + + +/** + * @brief Register custom esp_netif with mDNS functionality + * mDNS service runs by default on preconfigured interfaces (STA, AP, ETH). + * This API enables running the service on any customized interface, + * either using standard WiFi or Ethernet driver or any kind of user defined driver. + * + * @param esp_netif Pointer to esp-netif interface + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_STATE mDNS is not running or this netif is already registered + * - ESP_ERR_NO_MEM not enough memory for this in interface in the netif list (see CONFIG_MDNS_MAX_INTERFACES) + */ +esp_err_t mdns_register_netif(esp_netif_t *esp_netif); + +/** + * @brief Unregister esp-netif already registered in mDNS service + * + * @param esp_netif Pointer to esp-netif interface + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_STATE mDNS is not running + * - ESP_ERR_NOT_FOUND this esp-netif was not registered in mDNS service + */ +esp_err_t mdns_unregister_netif(esp_netif_t *esp_netif); + +/** + * @brief Set esp_netif to a desired state, or perform a desired action, such as enable/disable this interface + * or send announcement packets to this netif + * + * * This function is used to enable (probe, resolve conflicts and announce), announce, or disable (send bye) mDNS + * services on the specified network interface. + * * This function must be called if users registers a specific interface using mdns_register_netif() + * to enable mDNS services on that interface. + * * This function could be used in IP/connection event handlers to automatically enable/announce mDNS services + * when network properties change and/or disable them on disconnection. + * + * @param esp_netif Pointer to esp-netif interface + * @param event_action Disable/Enable/Announce on this interface over IPv4/IPv6 protocol. + * Actions enumerated in mdns_event_actions_t type. + * @return + * - ESP_OK success + * - ESP_ERR_INVALID_STATE mDNS is not running or this netif is not registered + * - ESP_ERR_NO_MEM memory error + */ +esp_err_t mdns_netif_action(esp_netif_t *esp_netif, mdns_event_actions_t event_action); + +/** + * @brief Browse mDNS for a service `_service._proto`. + * + * @param service Pointer to the `_service` which will be browsed. + * @param proto Pointer to the `_proto` which will be browsed. + * @param notifier The callback which will be called when the browsing service changed. + * @return mdns_browse_t pointer to new browse object if initiated successfully. + * NULL otherwise. + */ +mdns_browse_t *mdns_browse_new(const char *service, const char *proto, mdns_browse_notify_t notifier); + +/** + * @brief Stop the `_service._proto` browse. + * @param service Pointer to the `_service` which will be browsed. + * @param proto Pointer to the `_proto` which will be browsed. + * @return + * - ESP_OK success. + * - ESP_ERR_FAIL mDNS is not running or the browsing of `_service._proto` is never started. + * - ESP_ERR_NO_MEM memory error. + */ +esp_err_t mdns_browse_delete(const char *service, const char *proto); + +#ifdef __cplusplus +} +#endif + +#endif /* ESP_MDNS_H_ */ diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/include/mdns_console.h b/RainMaker_Table-Lights/managed_components/espressif__mdns/include/mdns_console.h new file mode 100644 index 000000000..cb28eca7a --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__mdns/include/mdns_console.h @@ -0,0 +1,14 @@ +/* + * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef _MDNS_CONSOLE_H_ +#define _MDNS_CONSOLE_H_ + +/** + * @brief Register MDNS functions with the console component + */ +void mdns_console_register(void); + +#endif /* _MDNS_CONSOLE_H_ */ diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/mdns.c b/RainMaker_Table-Lights/managed_components/espressif__mdns/mdns.c new file mode 100644 index 000000000..20ee5eead --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__mdns/mdns.c @@ -0,0 +1,7863 @@ +/* + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/queue.h" +#include "freertos/semphr.h" +#include "esp_log.h" +#include "esp_event.h" +#include "esp_random.h" +#include "esp_check.h" +#include "mdns.h" +#include "mdns_private.h" +#include "mdns_networking.h" +#include "mdns_mem_caps.h" + +static void _mdns_browse_item_free(mdns_browse_t *browse); +static esp_err_t _mdns_send_browse_action(mdns_action_type_t type, mdns_browse_t *browse); +static esp_err_t _mdns_sync_browse_action(mdns_action_type_t type, mdns_browse_sync_t *browse_sync); +static void _mdns_browse_sync(mdns_browse_sync_t *browse_sync); +static void _mdns_browse_finish(mdns_browse_t *browse); +static void _mdns_browse_add(mdns_browse_t *browse); +static void _mdns_browse_send(mdns_browse_t *browse, mdns_if_t interface); + +#if CONFIG_ETH_ENABLED && CONFIG_MDNS_PREDEF_NETIF_ETH +#include "esp_eth.h" +#endif + +#if ESP_IDF_VERSION <= ESP_IDF_VERSION_VAL(5, 1, 0) +#define MDNS_ESP_WIFI_ENABLED CONFIG_SOC_WIFI_SUPPORTED +#else +#define MDNS_ESP_WIFI_ENABLED CONFIG_ESP_WIFI_ENABLED +#endif + +#if MDNS_ESP_WIFI_ENABLED && (CONFIG_MDNS_PREDEF_NETIF_STA || CONFIG_MDNS_PREDEF_NETIF_AP) +#include "esp_wifi.h" +#endif + +#ifdef MDNS_ENABLE_DEBUG +void mdns_debug_packet(const uint8_t *data, size_t len); +#endif + +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0])) +#endif + +// Internal size of IPv6 address is defined here as size of AAAA record in mdns packet +// since the ip6_addr_t is defined in lwip and depends on using IPv6 zones +#define _MDNS_SIZEOF_IP6_ADDR (MDNS_ANSWER_AAAA_SIZE) + +static const char *MDNS_DEFAULT_DOMAIN = "local"; +static const char *MDNS_SUB_STR = "_sub"; + +mdns_server_t *_mdns_server = NULL; +static mdns_host_item_t *_mdns_host_list = NULL; +static mdns_host_item_t _mdns_self_host; + +static const char *TAG = "mdns"; + +static volatile TaskHandle_t _mdns_service_task_handle = NULL; +static SemaphoreHandle_t _mdns_service_semaphore = NULL; +static StackType_t *_mdns_stack_buffer; + +static void _mdns_search_finish_done(void); +static mdns_search_once_t *_mdns_search_find_from(mdns_search_once_t *search, mdns_name_t *name, uint16_t type, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); +static mdns_browse_t *_mdns_browse_find_from(mdns_browse_t *b, mdns_name_t *name, uint16_t type, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); +static void _mdns_browse_result_add_srv(mdns_browse_t *browse, const char *hostname, const char *instance, const char *service, const char *proto, + uint16_t port, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint32_t ttl, mdns_browse_sync_t *out_sync_browse); +static void _mdns_browse_result_add_ip(mdns_browse_t *browse, const char *hostname, esp_ip_addr_t *ip, + mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint32_t ttl, mdns_browse_sync_t *out_sync_browse); +static void _mdns_browse_result_add_txt(mdns_browse_t *browse, const char *instance, const char *service, const char *proto, + mdns_txt_item_t *txt, uint8_t *txt_value_len, size_t txt_count, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, + uint32_t ttl, mdns_browse_sync_t *out_sync_browse); +#ifdef MDNS_ENABLE_DEBUG +static void debug_printf_browse_result(mdns_result_t *r_t, mdns_browse_t *b_t); +static void debug_printf_browse_result_all(mdns_result_t *r_t); +#endif // MDNS_ENABLE_DEBUG +static void _mdns_search_result_add_ip(mdns_search_once_t *search, const char *hostname, esp_ip_addr_t *ip, + mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint32_t ttl); +static void _mdns_search_result_add_srv(mdns_search_once_t *search, const char *hostname, uint16_t port, + mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint32_t ttl); +static void _mdns_search_result_add_txt(mdns_search_once_t *search, mdns_txt_item_t *txt, uint8_t *txt_value_len, + size_t txt_count, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, + uint32_t ttl); +static mdns_result_t *_mdns_search_result_add_ptr(mdns_search_once_t *search, const char *instance, + const char *service_type, const char *proto, mdns_if_t tcpip_if, + mdns_ip_protocol_t ip_protocol, uint32_t ttl); +static bool _mdns_append_host_list_in_services(mdns_out_answer_t **destination, mdns_srv_item_t *services[], size_t services_len, bool flush, bool bye); +static bool _mdns_append_host_list(mdns_out_answer_t **destination, bool flush, bool bye); +static void _mdns_remap_self_service_hostname(const char *old_hostname, const char *new_hostname); +static esp_err_t mdns_post_custom_action_tcpip_if(mdns_if_t mdns_if, mdns_event_actions_t event_action); + +static void _mdns_query_results_free(mdns_result_t *results); +typedef enum { + MDNS_IF_STA = 0, + MDNS_IF_AP = 1, + MDNS_IF_ETH = 2, +} mdns_predef_if_t; + +typedef struct mdns_interfaces mdns_interfaces_t; + +struct mdns_interfaces { + const bool predefined; + esp_netif_t *netif; + const mdns_predef_if_t predef_if; + mdns_if_t duplicate; +}; + +/* + * @brief Internal collection of mdns supported interfaces + * + */ +static mdns_interfaces_t s_esp_netifs[MDNS_MAX_INTERFACES] = { +#if CONFIG_MDNS_PREDEF_NETIF_STA + { .predefined = true, .netif = NULL, .predef_if = MDNS_IF_STA, .duplicate = MDNS_MAX_INTERFACES }, +#endif +#if CONFIG_MDNS_PREDEF_NETIF_AP + { .predefined = true, .netif = NULL, .predef_if = MDNS_IF_AP, .duplicate = MDNS_MAX_INTERFACES }, +#endif +#if CONFIG_MDNS_PREDEF_NETIF_ETH + { .predefined = true, .netif = NULL, .predef_if = MDNS_IF_ETH, .duplicate = MDNS_MAX_INTERFACES }, +#endif +}; + + +/** + * @brief Convert Predefined interface to the netif id from the internal netif list + * @param predef_if Predefined interface enum + * @return Ordinal number of internal list of mdns network interface. + * Returns MDNS_MAX_INTERFACES if the predefined interface wasn't found in the list + */ +static mdns_if_t mdns_if_from_preset_if(mdns_predef_if_t predef_if) +{ + for (int i = 0; i < MDNS_MAX_INTERFACES; ++i) { + if (s_esp_netifs[i].predefined && s_esp_netifs[i].predef_if == predef_if) { + return i; + } + } + return MDNS_MAX_INTERFACES; +} + +/** + * @brief Convert Predefined interface to esp-netif handle + * @param predef_if Predefined interface enum + * @return esp_netif pointer from system list of network interfaces + */ +static inline esp_netif_t *esp_netif_from_preset_if(mdns_predef_if_t predef_if) +{ + switch (predef_if) { + case MDNS_IF_STA: + return esp_netif_get_handle_from_ifkey("WIFI_STA_DEF"); + case MDNS_IF_AP: + return esp_netif_get_handle_from_ifkey("WIFI_AP_DEF"); +#if CONFIG_ETH_ENABLED && CONFIG_MDNS_PREDEF_NETIF_ETH + case MDNS_IF_ETH: + return esp_netif_get_handle_from_ifkey("ETH_DEF"); +#endif + default: + return NULL; + } +} + +/** + * @brief Gets the actual esp_netif pointer from the internal network interface list + * + * The supplied ordinal number could + * - point to a predef netif -> "STA", "AP", "ETH" + * - if no entry in the list (NULL) -> check if the system added this netif + * - point to a custom netif -> just return the entry in the list + * - users is responsible for the lifetime of this netif (to be valid between mdns-init -> deinit) + * + * @param tcpip_if Ordinal number of the interface + * @return Pointer ot the esp_netif object if the interface is available, NULL otherwise + */ +esp_netif_t *_mdns_get_esp_netif(mdns_if_t tcpip_if) +{ + if (tcpip_if < MDNS_MAX_INTERFACES) { + if (s_esp_netifs[tcpip_if].netif == NULL && s_esp_netifs[tcpip_if].predefined) { + // If the local copy is NULL and this netif is predefined -> we can find it in the global netif list + s_esp_netifs[tcpip_if].netif = esp_netif_from_preset_if(s_esp_netifs[tcpip_if].predef_if); + // failing to find it means that the netif is *not* available -> return NULL + } + return s_esp_netifs[tcpip_if].netif; + } + return NULL; +} + + +/* + * @brief Clean internal mdns interface's pointer + */ +static inline void _mdns_clean_netif_ptr(mdns_if_t tcpip_if) +{ + if (tcpip_if < MDNS_MAX_INTERFACES) { + s_esp_netifs[tcpip_if].netif = NULL; + } +} + + +/* + * @brief Convert esp-netif handle to mdns if + */ +static mdns_if_t _mdns_get_if_from_esp_netif(esp_netif_t *esp_netif) +{ + for (int i = 0; i < MDNS_MAX_INTERFACES; ++i) { + // The predefined netifs in the static array are NULL when firstly calling this function + // if IPv4 is disabled. Set these netifs here. + if (s_esp_netifs[i].netif == NULL && s_esp_netifs[i].predefined) { + s_esp_netifs[i].netif = esp_netif_from_preset_if(s_esp_netifs[i].predef_if); + } + if (esp_netif == s_esp_netifs[i].netif) { + return i; + } + } + return MDNS_MAX_INTERFACES; +} + + + +static inline bool _str_null_or_empty(const char *str) +{ + return (str == NULL || *str == 0); +} + +/* + * @brief Appends/increments a number to name/instance in case of collision + * */ +static char *_mdns_mangle_name(char *in) +{ + char *p = strrchr(in, '-'); + int suffix = 0; + if (p == NULL) { + //No - in ``in`` + suffix = 2; + } else { + char *endp = NULL; + suffix = strtol(p + 1, &endp, 10); + if (*endp != 0) { + //suffix is not numerical + suffix = 2; + p = NULL; //so we append -suffix to the entire string + } + } + char *ret; + if (p == NULL) { + //need to add -2 to string + ret = mdns_mem_malloc(strlen(in) + 3); + if (ret == NULL) { + HOOK_MALLOC_FAILED; + return NULL; + } + sprintf(ret, "%s-2", in); + } else { + size_t in_len = strlen(in); + ret = mdns_mem_malloc(in_len + 2); //one extra byte in case 9-10 or 99-100 etc + if (ret == NULL) { + HOOK_MALLOC_FAILED; + return NULL; + } + memcpy(ret, in, in_len); + int baseLen = p - in; //length of 'bla' in 'bla-123' + //overwrite suffix with new suffix + sprintf(ret + baseLen, "-%d", suffix + 1); + } + return ret; +} + +static bool _mdns_service_match(const mdns_service_t *srv, const char *service, const char *proto, + const char *hostname) +{ + if (!service || !proto || !srv->hostname) { + return false; + } + return !strcasecmp(srv->service, service) && !strcasecmp(srv->proto, proto) && + (_str_null_or_empty(hostname) || !strcasecmp(srv->hostname, hostname)); +} + +/** + * @brief finds service from given service type + * @param server the server + * @param service service type to match + * @param proto proto to match + * @param hostname hostname of the service (if non-null) + * + * @return the service item if found or NULL on error + */ +static mdns_srv_item_t *_mdns_get_service_item(const char *service, const char *proto, const char *hostname) +{ + mdns_srv_item_t *s = _mdns_server->services; + while (s) { + if (_mdns_service_match(s->service, service, proto, hostname)) { + return s; + } + s = s->next; + } + return NULL; +} + +static mdns_srv_item_t *_mdns_get_service_item_subtype(const char *subtype, const char *service, const char *proto) +{ + mdns_srv_item_t *s = _mdns_server->services; + while (s) { + if (_mdns_service_match(s->service, service, proto, NULL)) { + mdns_subtype_t *subtype_item = s->service->subtype; + while (subtype_item) { + if (!strcasecmp(subtype_item->subtype, subtype)) { + return s; + } + subtype_item = subtype_item->next; + } + } + s = s->next; + } + return NULL; +} + +static mdns_host_item_t *mdns_get_host_item(const char *hostname) +{ + if (hostname == NULL || strcasecmp(hostname, _mdns_server->hostname) == 0) { + return &_mdns_self_host; + } + mdns_host_item_t *host = _mdns_host_list; + while (host != NULL) { + if (strcasecmp(host->hostname, hostname) == 0) { + return host; + } + host = host->next; + } + return NULL; +} + +static bool _mdns_can_add_more_services(void) +{ +#if MDNS_MAX_SERVICES == 0 + return false; +#else + mdns_srv_item_t *s = _mdns_server->services; + uint16_t service_num = 0; + while (s) { + service_num ++; + s = s->next; + if (service_num >= MDNS_MAX_SERVICES) { + return false; + } + } + return true; +#endif +} + +esp_err_t _mdns_send_rx_action(mdns_rx_packet_t *packet) +{ + mdns_action_t *action = NULL; + + action = (mdns_action_t *)mdns_mem_malloc(sizeof(mdns_action_t)); + if (!action) { + HOOK_MALLOC_FAILED; + return ESP_ERR_NO_MEM; + } + + action->type = ACTION_RX_HANDLE; + action->data.rx_handle.packet = packet; + if (xQueueSend(_mdns_server->action_queue, &action, (TickType_t)0) != pdPASS) { + mdns_mem_free(action); + return ESP_ERR_NO_MEM; + } + return ESP_OK; +} + +static const char *_mdns_get_default_instance_name(void) +{ + if (_mdns_server && !_str_null_or_empty(_mdns_server->instance)) { + return _mdns_server->instance; + } + + if (_mdns_server && !_str_null_or_empty(_mdns_server->hostname)) { + return _mdns_server->hostname; + } + + return NULL; +} + +/** + * @brief Get the service name of a service + */ +static const char *_mdns_get_service_instance_name(const mdns_service_t *service) +{ + if (service && !_str_null_or_empty(service->instance)) { + return service->instance; + } + + return _mdns_get_default_instance_name(); +} + +static bool _mdns_instance_name_match(const char *lhs, const char *rhs) +{ + if (lhs == NULL) { + lhs = _mdns_get_default_instance_name(); + } + if (rhs == NULL) { + rhs = _mdns_get_default_instance_name(); + } + return !strcasecmp(lhs, rhs); +} + +static bool _mdns_service_match_instance(const mdns_service_t *srv, const char *instance, const char *service, + const char *proto, const char *hostname) +{ + // service and proto must be supplied, if not this instance won't match + if (!service || !proto) { + return false; + } + // instance==NULL -> _mdns_instance_name_match() will check the default instance + // hostname==NULL -> matches if instance, service and proto matches + return !strcasecmp(srv->service, service) && _mdns_instance_name_match(srv->instance, instance) && + !strcasecmp(srv->proto, proto) && (_str_null_or_empty(hostname) || !strcasecmp(srv->hostname, hostname)); +} + +static mdns_srv_item_t *_mdns_get_service_item_instance(const char *instance, const char *service, const char *proto, + const char *hostname) +{ + mdns_srv_item_t *s = _mdns_server->services; + while (s) { + if (instance) { + if (_mdns_service_match_instance(s->service, instance, service, proto, hostname)) { + return s; + } + } else { + if (_mdns_service_match(s->service, service, proto, hostname)) { + return s; + } + } + s = s->next; + } + return NULL; +} + +/** + * @brief reads MDNS FQDN into mdns_name_t structure + * FQDN is in format: [hostname.|[instance.]_service._proto.]local. + * + * @param packet MDNS packet + * @param start Starting point of FQDN + * @param name mdns_name_t structure to populate + * @param buf temporary char buffer + * + * @return the address after the parsed FQDN in the packet or NULL on error + */ +static const uint8_t *_mdns_read_fqdn(const uint8_t *packet, const uint8_t *start, mdns_name_t *name, char *buf, size_t packet_len) +{ + size_t index = 0; + const uint8_t *packet_end = packet + packet_len; + while (start + index < packet_end && start[index]) { + if (name->parts == 4) { + name->invalid = true; + } + uint8_t len = start[index++]; + if (len < 0xC0) { + if (len > 63) { + //length can not be more than 63 + return NULL; + } + uint8_t i; + for (i = 0; i < len; i++) { + if (start + index >= packet_end) { + return NULL; + } + buf[i] = start[index++]; + } + buf[len] = '\0'; + if (name->parts == 1 && buf[0] != '_' + && (strcasecmp(buf, MDNS_DEFAULT_DOMAIN) != 0) + && (strcasecmp(buf, "arpa") != 0) +#ifndef CONFIG_MDNS_RESPOND_REVERSE_QUERIES + && (strcasecmp(buf, "ip6") != 0) + && (strcasecmp(buf, "in-addr") != 0) +#endif + ) { + strlcat(name->host, ".", sizeof(name->host)); + strlcat(name->host, buf, sizeof(name->host)); + } else if (strcasecmp(buf, MDNS_SUB_STR) == 0) { + name->sub = 1; + } else if (!name->invalid) { + char *mdns_name_ptrs[] = {name->host, name->service, name->proto, name->domain}; + memcpy(mdns_name_ptrs[name->parts++], buf, len + 1); + } + } else { + size_t address = (((uint16_t)len & 0x3F) << 8) | start[index++]; + if ((packet + address) >= start) { + //reference address can not be after where we are + return NULL; + } + if (_mdns_read_fqdn(packet, packet + address, name, buf, packet_len)) { + return start + index; + } + return NULL; + } + } + return start + index + 1; +} + +/** + * @brief sets uint16_t value in a packet + * + * @param packet MDNS packet + * @param index offset of uint16_t value + * @param value the value to set + */ +static inline void _mdns_set_u16(uint8_t *packet, uint16_t index, uint16_t value) +{ + if ((index + 1) >= MDNS_MAX_PACKET_SIZE) { + return; + } + packet[index] = (value >> 8) & 0xFF; + packet[index + 1] = value & 0xFF; +} + +/** + * @brief appends byte in a packet, incrementing the index + * + * @param packet MDNS packet + * @param index offset in the packet + * @param value the value to set + * + * @return length of added data: 0 on error or 1 on success + */ +static inline uint8_t _mdns_append_u8(uint8_t *packet, uint16_t *index, uint8_t value) +{ + if (*index >= MDNS_MAX_PACKET_SIZE) { + return 0; + } + packet[*index] = value; + *index += 1; + return 1; +} + +/** + * @brief appends uint16_t in a packet, incrementing the index + * + * @param packet MDNS packet + * @param index offset in the packet + * @param value the value to set + * + * @return length of added data: 0 on error or 2 on success + */ +static inline uint8_t _mdns_append_u16(uint8_t *packet, uint16_t *index, uint16_t value) +{ + if ((*index + 1) >= MDNS_MAX_PACKET_SIZE) { + return 0; + } + _mdns_append_u8(packet, index, (value >> 8) & 0xFF); + _mdns_append_u8(packet, index, value & 0xFF); + return 2; +} + +/** + * @brief appends uint32_t in a packet, incrementing the index + * + * @param packet MDNS packet + * @param index offset in the packet + * @param value the value to set + * + * @return length of added data: 0 on error or 4 on success + */ +static inline uint8_t _mdns_append_u32(uint8_t *packet, uint16_t *index, uint32_t value) +{ + if ((*index + 3) >= MDNS_MAX_PACKET_SIZE) { + return 0; + } + _mdns_append_u8(packet, index, (value >> 24) & 0xFF); + _mdns_append_u8(packet, index, (value >> 16) & 0xFF); + _mdns_append_u8(packet, index, (value >> 8) & 0xFF); + _mdns_append_u8(packet, index, value & 0xFF); + return 4; +} + +/** + * @brief appends answer type, class, ttl and data length to a packet, incrementing the index + * + * @param packet MDNS packet + * @param index offset in the packet + * @param type answer type + * @param ttl answer ttl + * + * @return length of added data: 0 on error or 10 on success + */ +static inline uint8_t _mdns_append_type(uint8_t *packet, uint16_t *index, uint8_t type, bool flush, uint32_t ttl) +{ + if ((*index + 10) >= MDNS_MAX_PACKET_SIZE) { + return 0; + } + uint16_t mdns_class = MDNS_CLASS_IN; + if (flush) { + mdns_class = MDNS_CLASS_IN_FLUSH_CACHE; + } + if (type == MDNS_ANSWER_PTR) { + _mdns_append_u16(packet, index, MDNS_TYPE_PTR); + _mdns_append_u16(packet, index, mdns_class); + } else if (type == MDNS_ANSWER_TXT) { + _mdns_append_u16(packet, index, MDNS_TYPE_TXT); + _mdns_append_u16(packet, index, mdns_class); + } else if (type == MDNS_ANSWER_SRV) { + _mdns_append_u16(packet, index, MDNS_TYPE_SRV); + _mdns_append_u16(packet, index, mdns_class); + } else if (type == MDNS_ANSWER_A) { + _mdns_append_u16(packet, index, MDNS_TYPE_A); + _mdns_append_u16(packet, index, mdns_class); + } else if (type == MDNS_ANSWER_AAAA) { + _mdns_append_u16(packet, index, MDNS_TYPE_AAAA); + _mdns_append_u16(packet, index, mdns_class); + } else { + return 0; + } + _mdns_append_u32(packet, index, ttl); + _mdns_append_u16(packet, index, 0); + return 10; +} + +static inline uint8_t _mdns_append_string_with_len(uint8_t *packet, uint16_t *index, const char *string, uint8_t len) +{ + if ((*index + len + 1) >= MDNS_MAX_PACKET_SIZE) { + return 0; + } + _mdns_append_u8(packet, index, len); + memcpy(packet + *index, string, len); + *index += len; + return len + 1; +} + +/** + * @brief appends single string to a packet, incrementing the index + * + * @param packet MDNS packet + * @param index offset in the packet + * @param string the string to append + * + * @return length of added data: 0 on error or length of the string + 1 on success + */ +static inline uint8_t _mdns_append_string(uint8_t *packet, uint16_t *index, const char *string) +{ + uint8_t len = strlen(string); + if ((*index + len + 1) >= MDNS_MAX_PACKET_SIZE) { + return 0; + } + _mdns_append_u8(packet, index, len); + memcpy(packet + *index, string, len); + *index += len; + return len + 1; +} + +/** + * @brief appends one TXT record ("key=value" or "key") + * + * @param packet MDNS packet + * @param index offset in the packet + * @param txt one txt record + * + * @return length of added data: length of the added txt value + 1 on success + * 0 if data won't fit the packet + * -1 if invalid TXT entry + */ +static inline int append_one_txt_record_entry(uint8_t *packet, uint16_t *index, mdns_txt_linked_item_t *txt) +{ + if (txt == NULL || txt->key == NULL) { + return -1; + } + size_t key_len = strlen(txt->key); + size_t len = key_len + txt->value_len + (txt->value ? 1 : 0); + if ((*index + len + 1) >= MDNS_MAX_PACKET_SIZE) { + return 0; + } + _mdns_append_u8(packet, index, len); + memcpy(packet + *index, txt->key, key_len); + if (txt->value) { + packet[*index + key_len] = '='; + memcpy(packet + *index + key_len + 1, txt->value, txt->value_len); + } + *index += len; + return len + 1; +} + +#ifdef CONFIG_MDNS_RESPOND_REVERSE_QUERIES +static inline int append_single_str(uint8_t *packet, uint16_t *index, const char *str, int len) +{ + if ((*index + len + 1) >= MDNS_MAX_PACKET_SIZE) { + return 0; + } + if (!_mdns_append_u8(packet, index, len)) { + return 0; + } + memcpy(packet + *index, str, len); + *index += len; + return *index; +} + +/** + * @brief appends FQDN to a packet from hostname separated by dots. This API works the same way as + * _mdns_append_fqdn(), but refrains from DNS compression (as it's mainly used for IP addresses (many short items), + * where we gain very little (or compression even gets counter-productive mainly for IPv6 addresses) + * + * @param packet MDNS packet + * @param index offset in the packet + * @param name name representing FQDN in '.' separated parts + * @param last true if appending the last part (domain, typically "arpa") + * + * @return length of added data: 0 on error or length on success + */ +static uint16_t append_fqdn_dots(uint8_t *packet, uint16_t *index, const char *name, bool last) +{ + int len = strlen(name); + char *host = (char *)name; + char *end = host; + char *start = host; + do { + end = memchr(start, '.', host + len - start); + end = end ? end : host + len; + int part_len = end - start; + if (!append_single_str(packet, index, start, part_len)) { + return 0; + } + start = ++end; + } while (end < name + len); + + if (!append_single_str(packet, index, "arpa", sizeof("arpa") - 1)) { + return 0; + } + + //empty string so terminate + if (!_mdns_append_u8(packet, index, 0)) { + return 0; + } + return *index; +} +#endif /* CONFIG_MDNS_RESPOND_REVERSE_QUERIES */ + +/** + * @brief appends FQDN to a packet, incrementing the index and + * compressing the output if previous occurrence of the string (or part of it) has been found + * + * @param packet MDNS packet + * @param index offset in the packet + * @param strings string array containing the parts of the FQDN + * @param count number of strings in the array + * + * @return length of added data: 0 on error or length on success + */ +static uint16_t _mdns_append_fqdn(uint8_t *packet, uint16_t *index, const char *strings[], uint8_t count, size_t packet_len) +{ + if (!count) { + //empty string so terminate + return _mdns_append_u8(packet, index, 0); + } + static char buf[MDNS_NAME_BUF_LEN]; + uint8_t len = strlen(strings[0]); + //try to find first the string length in the packet (if it exists) + uint8_t *len_location = (uint8_t *)memchr(packet, (char)len, *index); + while (len_location) { + mdns_name_t name; + //check if the string after len_location is the string that we are looking for + if (memcmp(len_location + 1, strings[0], len)) { //not continuing with our string +search_next: + //try and find the length byte further in the packet + len_location = (uint8_t *)memchr(len_location + 1, (char)len, *index - (len_location + 1 - packet)); + continue; + } + //seems that we might have found the string that we are looking for + //read the destination into name and compare + name.parts = 0; + name.sub = 0; + name.invalid = false; + name.host[0] = 0; + name.service[0] = 0; + name.proto[0] = 0; + name.domain[0] = 0; + const uint8_t *content = _mdns_read_fqdn(packet, len_location, &name, buf, packet_len); + if (!content) { + //not a readable fqdn? + goto search_next; // could be our unfinished fqdn, continue searching + } + if (name.parts == count) { + uint8_t i; + for (i = 0; i < count; i++) { + if (strcasecmp(strings[i], (const char *)&name + (i * (MDNS_NAME_BUF_LEN)))) { + //not our string! let's search more + goto search_next; + } + } + //we actually have found the string + break; + } else { + goto search_next; + } + } + //string is not yet in the packet, so let's add it + if (!len_location) { + uint8_t written = _mdns_append_string(packet, index, strings[0]); + if (!written) { + return 0; + } + //run the same for the other strings in the name + return written + _mdns_append_fqdn(packet, index, &strings[1], count - 1, packet_len); + } + + //we have found the string so let's insert a pointer to it instead + uint16_t offset = len_location - packet; + offset |= MDNS_NAME_REF; + return _mdns_append_u16(packet, index, offset); +} + +/** + * @brief appends PTR record for service to a packet, incrementing the index + * + * @param packet MDNS packet + * @param index offset in the packet + * @param server the server that is hosting the service + * @param service the service to add record for + * + * @return length of added data: 0 on error or length on success + */ +static uint16_t _mdns_append_ptr_record(uint8_t *packet, uint16_t *index, const char *instance, const char *service, const char *proto, bool flush, bool bye) +{ + const char *str[4]; + uint16_t record_length = 0; + uint8_t part_length; + + if (service == NULL) { + return 0; + } + + str[0] = instance; + str[1] = service; + str[2] = proto; + str[3] = MDNS_DEFAULT_DOMAIN; + + part_length = _mdns_append_fqdn(packet, index, str + 1, 3, MDNS_MAX_PACKET_SIZE); + if (!part_length) { + return 0; + } + record_length += part_length; + + part_length = _mdns_append_type(packet, index, MDNS_ANSWER_PTR, false, bye ? 0 : MDNS_ANSWER_PTR_TTL); + if (!part_length) { + return 0; + } + record_length += part_length; + + uint16_t data_len_location = *index - 2; + part_length = _mdns_append_fqdn(packet, index, str, 4, MDNS_MAX_PACKET_SIZE); + if (!part_length) { + return 0; + } + _mdns_set_u16(packet, data_len_location, part_length); + record_length += part_length; + return record_length; +} + +/** + * @brief appends PTR record for a subtype to a packet, incrementing the index + * + * @param packet MDNS packet + * @param index offset in the packet + * @param instance the service instance name + * @param subtype the service subtype + * @param proto the service protocol + * @param flush whether to set the flush flag + * @param bye whether to set the bye flag + * + * @return length of added data: 0 on error or length on success + */ +static uint16_t _mdns_append_subtype_ptr_record(uint8_t *packet, uint16_t *index, const char *instance, + const char *subtype, const char *service, const char *proto, bool flush, + bool bye) +{ + const char *subtype_str[5] = {subtype, MDNS_SUB_STR, service, proto, MDNS_DEFAULT_DOMAIN}; + const char *instance_str[4] = {instance, service, proto, MDNS_DEFAULT_DOMAIN}; + uint16_t record_length = 0; + uint8_t part_length; + + if (service == NULL) { + return 0; + } + + part_length = _mdns_append_fqdn(packet, index, subtype_str, ARRAY_SIZE(subtype_str), MDNS_MAX_PACKET_SIZE); + if (!part_length) { + return 0; + } + record_length += part_length; + + part_length = _mdns_append_type(packet, index, MDNS_ANSWER_PTR, false, bye ? 0 : MDNS_ANSWER_PTR_TTL); + if (!part_length) { + return 0; + } + record_length += part_length; + + uint16_t data_len_location = *index - 2; + part_length = _mdns_append_fqdn(packet, index, instance_str, ARRAY_SIZE(instance_str), MDNS_MAX_PACKET_SIZE); + if (!part_length) { + return 0; + } + _mdns_set_u16(packet, data_len_location, part_length); + record_length += part_length; + return record_length; +} + +/** + * @brief appends DNS-SD PTR record for service to a packet, incrementing the index + * + * @param packet MDNS packet + * @param index offset in the packet + * @param server the server that is hosting the service + * @param service the service to add record for + * + * @return length of added data: 0 on error or length on success + */ +static uint16_t _mdns_append_sdptr_record(uint8_t *packet, uint16_t *index, mdns_service_t *service, bool flush, bool bye) +{ + const char *str[3]; + const char *sd_str[4]; + uint16_t record_length = 0; + uint8_t part_length; + + if (service == NULL) { + return 0; + } + + sd_str[0] = (char *)"_services"; + sd_str[1] = (char *)"_dns-sd"; + sd_str[2] = (char *)"_udp"; + sd_str[3] = MDNS_DEFAULT_DOMAIN; + + str[0] = service->service; + str[1] = service->proto; + str[2] = MDNS_DEFAULT_DOMAIN; + + part_length = _mdns_append_fqdn(packet, index, sd_str, 4, MDNS_MAX_PACKET_SIZE); + + record_length += part_length; + + part_length = _mdns_append_type(packet, index, MDNS_ANSWER_PTR, flush, MDNS_ANSWER_PTR_TTL); + if (!part_length) { + return 0; + } + record_length += part_length; + + uint16_t data_len_location = *index - 2; + part_length = _mdns_append_fqdn(packet, index, str, 3, MDNS_MAX_PACKET_SIZE); + if (!part_length) { + return 0; + } + _mdns_set_u16(packet, data_len_location, part_length); + record_length += part_length; + return record_length; +} + +/** + * @brief appends TXT record for service to a packet, incrementing the index + * + * @param packet MDNS packet + * @param index offset in the packet + * @param server the server that is hosting the service + * @param service the service to add record for + * + * @return length of added data: 0 on error or length on success + */ +static uint16_t _mdns_append_txt_record(uint8_t *packet, uint16_t *index, mdns_service_t *service, bool flush, bool bye) +{ + const char *str[4]; + uint16_t record_length = 0; + uint8_t part_length; + + if (service == NULL) { + return 0; + } + + str[0] = _mdns_get_service_instance_name(service); + str[1] = service->service; + str[2] = service->proto; + str[3] = MDNS_DEFAULT_DOMAIN; + + if (!str[0]) { + return 0; + } + + part_length = _mdns_append_fqdn(packet, index, str, 4, MDNS_MAX_PACKET_SIZE); + if (!part_length) { + return 0; + } + record_length += part_length; + + part_length = _mdns_append_type(packet, index, MDNS_ANSWER_TXT, flush, bye ? 0 : MDNS_ANSWER_TXT_TTL); + if (!part_length) { + return 0; + } + record_length += part_length; + + uint16_t data_len_location = *index - 2; + uint16_t data_len = 0; + + mdns_txt_linked_item_t *txt = service->txt; + while (txt) { + int l = append_one_txt_record_entry(packet, index, txt); + if (l > 0) { + data_len += l; + } else if (l == 0) { // TXT entry won't fit into the mdns packet + return 0; + } + txt = txt->next; + } + if (!data_len) { + data_len = 1; + packet[*index] = 0; + *index = *index + 1; + } + _mdns_set_u16(packet, data_len_location, data_len); + record_length += data_len; + return record_length; +} + +/** + * @brief appends SRV record for service to a packet, incrementing the index + * + * @param packet MDNS packet + * @param index offset in the packet + * @param server the server that is hosting the service + * @param service the service to add record for + * + * @return length of added data: 0 on error or length on success + */ +static uint16_t _mdns_append_srv_record(uint8_t *packet, uint16_t *index, mdns_service_t *service, bool flush, bool bye) +{ + const char *str[4]; + uint16_t record_length = 0; + uint8_t part_length; + + if (service == NULL) { + return 0; + } + + str[0] = _mdns_get_service_instance_name(service); + str[1] = service->service; + str[2] = service->proto; + str[3] = MDNS_DEFAULT_DOMAIN; + + if (!str[0]) { + return 0; + } + + part_length = _mdns_append_fqdn(packet, index, str, 4, MDNS_MAX_PACKET_SIZE); + if (!part_length) { + return 0; + } + record_length += part_length; + + part_length = _mdns_append_type(packet, index, MDNS_ANSWER_SRV, flush, bye ? 0 : MDNS_ANSWER_SRV_TTL); + if (!part_length) { + return 0; + } + record_length += part_length; + + uint16_t data_len_location = *index - 2; + + part_length = 0; + part_length += _mdns_append_u16(packet, index, service->priority); + part_length += _mdns_append_u16(packet, index, service->weight); + part_length += _mdns_append_u16(packet, index, service->port); + if (part_length != 6) { + return 0; + } + + if (service->hostname) { + str[0] = service->hostname; + } else { + str[0] = _mdns_server->hostname; + } + str[1] = MDNS_DEFAULT_DOMAIN; + + if (_str_null_or_empty(str[0])) { + return 0; + } + + part_length = _mdns_append_fqdn(packet, index, str, 2, MDNS_MAX_PACKET_SIZE); + if (!part_length) { + return 0; + } + _mdns_set_u16(packet, data_len_location, part_length + 6); + + record_length += part_length + 6; + return record_length; +} + +#ifdef CONFIG_LWIP_IPV4 +/** + * @brief appends A record to a packet, incrementing the index + * + * @param packet MDNS packet + * @param index offset in the packet + * @param hostname the hostname address to add + * @param ip the IP address to add + * + * @return length of added data: 0 on error or length on success + */ +static uint16_t _mdns_append_a_record(uint8_t *packet, uint16_t *index, const char *hostname, uint32_t ip, bool flush, bool bye) +{ + const char *str[2]; + uint16_t record_length = 0; + uint8_t part_length; + + str[0] = hostname; + str[1] = MDNS_DEFAULT_DOMAIN; + + if (_str_null_or_empty(str[0])) { + return 0; + } + + part_length = _mdns_append_fqdn(packet, index, str, 2, MDNS_MAX_PACKET_SIZE); + if (!part_length) { + return 0; + } + record_length += part_length; + + part_length = _mdns_append_type(packet, index, MDNS_ANSWER_A, flush, bye ? 0 : MDNS_ANSWER_A_TTL); + if (!part_length) { + return 0; + } + record_length += part_length; + + uint16_t data_len_location = *index - 2; + + if ((*index + 3) >= MDNS_MAX_PACKET_SIZE) { + return 0; + } + _mdns_append_u8(packet, index, ip & 0xFF); + _mdns_append_u8(packet, index, (ip >> 8) & 0xFF); + _mdns_append_u8(packet, index, (ip >> 16) & 0xFF); + _mdns_append_u8(packet, index, (ip >> 24) & 0xFF); + _mdns_set_u16(packet, data_len_location, 4); + + record_length += 4; + return record_length; +} +#endif /* CONFIG_LWIP_IPV4 */ + +#ifdef CONFIG_LWIP_IPV6 +/** + * @brief appends AAAA record to a packet, incrementing the index + * + * @param packet MDNS packet + * @param index offset in the packet + * @param hostname the hostname address to add + * @param ipv6 the IPv6 address to add + * + * @return length of added data: 0 on error or length on success + */ +static uint16_t _mdns_append_aaaa_record(uint8_t *packet, uint16_t *index, const char *hostname, uint8_t *ipv6, bool flush, bool bye) +{ + const char *str[2]; + uint16_t record_length = 0; + uint8_t part_length; + + str[0] = hostname; + str[1] = MDNS_DEFAULT_DOMAIN; + + if (_str_null_or_empty(str[0])) { + return 0; + } + + + part_length = _mdns_append_fqdn(packet, index, str, 2, MDNS_MAX_PACKET_SIZE); + if (!part_length) { + return 0; + } + record_length += part_length; + + part_length = _mdns_append_type(packet, index, MDNS_ANSWER_AAAA, flush, bye ? 0 : MDNS_ANSWER_AAAA_TTL); + if (!part_length) { + return 0; + } + record_length += part_length; + + uint16_t data_len_location = *index - 2; + + if ((*index + MDNS_ANSWER_AAAA_SIZE) > MDNS_MAX_PACKET_SIZE) { + return 0; + } + + part_length = MDNS_ANSWER_AAAA_SIZE; + memcpy(packet + *index, ipv6, part_length); + *index += part_length; + _mdns_set_u16(packet, data_len_location, part_length); + record_length += part_length; + return record_length; +} +#endif + +/** + * @brief Append question to packet + */ +static uint16_t _mdns_append_question(uint8_t *packet, uint16_t *index, mdns_out_question_t *q) +{ + uint8_t part_length; +#ifdef CONFIG_MDNS_RESPOND_REVERSE_QUERIES + if (q->host && (strstr(q->host, "in-addr") || strstr(q->host, "ip6"))) { + part_length = append_fqdn_dots(packet, index, q->host, false); + if (!part_length) { + return 0; + } + } else +#endif /* CONFIG_MDNS_RESPOND_REVERSE_QUERIES */ + { + const char *str[4]; + uint8_t str_index = 0; + if (q->host) { + str[str_index++] = q->host; + } + if (q->service) { + str[str_index++] = q->service; + } + if (q->proto) { + str[str_index++] = q->proto; + } + if (q->domain) { + str[str_index++] = q->domain; + } + part_length = _mdns_append_fqdn(packet, index, str, str_index, MDNS_MAX_PACKET_SIZE); + if (!part_length) { + return 0; + } + } + + part_length += _mdns_append_u16(packet, index, q->type); + part_length += _mdns_append_u16(packet, index, q->unicast ? 0x8001 : 0x0001); + return part_length; +} + +/** + * @brief Helper to get either ETH or STA if the other is provided + * Used when two interfaces are on the same subnet + */ +static mdns_if_t _mdns_get_other_if(mdns_if_t tcpip_if) +{ + if (tcpip_if < MDNS_MAX_INTERFACES) { + return s_esp_netifs[tcpip_if].duplicate; + } + return MDNS_MAX_INTERFACES; +} + +/** + * @brief Check if interface is duplicate (two interfaces on the same subnet) + */ +static bool _mdns_if_is_dup(mdns_if_t tcpip_if) +{ + mdns_if_t other_if = _mdns_get_other_if(tcpip_if); + if (other_if == MDNS_MAX_INTERFACES) { + return false; + } + if (_mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V4].state == PCB_DUP + || _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V6].state == PCB_DUP + || _mdns_server->interfaces[other_if].pcbs[MDNS_IP_PROTOCOL_V4].state == PCB_DUP + || _mdns_server->interfaces[other_if].pcbs[MDNS_IP_PROTOCOL_V6].state == PCB_DUP + ) { + return true; + } + return false; +} + +#ifdef CONFIG_LWIP_IPV6 +/** + * @brief Check if IPv6 address is NULL + */ +static bool _ipv6_address_is_zero(esp_ip6_addr_t ip6) +{ + uint8_t i; + uint8_t *data = (uint8_t *)ip6.addr; + for (i = 0; i < _MDNS_SIZEOF_IP6_ADDR; i++) { + if (data[i]) { + return false; + } + } + return true; +} +#endif /* CONFIG_LWIP_IPV6 */ + +static uint8_t _mdns_append_host_answer(uint8_t *packet, uint16_t *index, mdns_host_item_t *host, + uint8_t address_type, bool flush, bool bye) +{ + mdns_ip_addr_t *addr = host->address_list; + uint8_t num_records = 0; + + while (addr != NULL) { + if (addr->addr.type == address_type) { +#ifdef CONFIG_LWIP_IPV4 + if (address_type == ESP_IPADDR_TYPE_V4 && + _mdns_append_a_record(packet, index, host->hostname, addr->addr.u_addr.ip4.addr, flush, bye) <= 0) { + break; + } +#endif /* CONFIG_LWIP_IPV4 */ +#ifdef CONFIG_LWIP_IPV6 + if (address_type == ESP_IPADDR_TYPE_V6 && + _mdns_append_aaaa_record(packet, index, host->hostname, (uint8_t *)addr->addr.u_addr.ip6.addr, flush, + bye) <= 0) { + break; + } +#endif /* CONFIG_LWIP_IPV6 */ + num_records++; + } + addr = addr->next; + } + return num_records; +} + +#ifdef CONFIG_MDNS_RESPOND_REVERSE_QUERIES +/** + * @brief Appends reverse lookup PTR record + */ +static uint8_t _mdns_append_reverse_ptr_record(uint8_t *packet, uint16_t *index, const char *name) +{ + if (strstr(name, "in-addr") == NULL && strstr(name, "ip6") == NULL) { + return 0; + } + + if (!append_fqdn_dots(packet, index, name, false)) { + return 0; + } + + if (!_mdns_append_type(packet, index, MDNS_ANSWER_PTR, false, 10 /* TTL set to 10s*/)) { + return 0; + } + + uint16_t data_len_location = *index - 2; /* store the position of size (2=16bis) of this record */ + const char *str[2] = { _mdns_self_host.hostname, MDNS_DEFAULT_DOMAIN }; + + int part_length = _mdns_append_fqdn(packet, index, str, 2, MDNS_MAX_PACKET_SIZE); + if (!part_length) { + return 0; + } + + _mdns_set_u16(packet, data_len_location, part_length); + return 1; /* appending only 1 record */ +} +#endif /* CONFIG_MDNS_RESPOND_REVERSE_QUERIES */ + +/** + * @brief Append PTR answers to packet + * + * @return number of answers added to the packet + */ +static uint8_t _mdns_append_service_ptr_answers(uint8_t *packet, uint16_t *index, mdns_service_t *service, bool flush, + bool bye) +{ + uint8_t appended_answers = 0; + + if (_mdns_append_ptr_record(packet, index, _mdns_get_service_instance_name(service), service->service, + service->proto, flush, bye) <= 0) { + return appended_answers; + } + appended_answers++; + + mdns_subtype_t *subtype = service->subtype; + while (subtype) { + appended_answers += + (_mdns_append_subtype_ptr_record(packet, index, _mdns_get_service_instance_name(service), subtype->subtype, + service->service, service->proto, flush, bye) > 0); + subtype = subtype->next; + } + + return appended_answers; +} + + +/** + * @brief Append answer to packet + * + * @return number of answers added to the packet + */ +static uint8_t _mdns_append_answer(uint8_t *packet, uint16_t *index, mdns_out_answer_t *answer, mdns_if_t tcpip_if) +{ + if (answer->host) { + bool is_host_valid = (&_mdns_self_host == answer->host); + mdns_host_item_t *target_host = _mdns_host_list; + while (target_host && !is_host_valid) { + if (target_host == answer->host) { + is_host_valid = true; + } + target_host = target_host->next; + } + if (!is_host_valid) { + return 0; + } + } + + if (answer->type == MDNS_TYPE_PTR) { + if (answer->service) { + return _mdns_append_service_ptr_answers(packet, index, answer->service, answer->flush, answer->bye); +#ifdef CONFIG_MDNS_RESPOND_REVERSE_QUERIES + } else if (answer->host && answer->host->hostname && + (strstr(answer->host->hostname, "in-addr") || strstr(answer->host->hostname, "ip6"))) { + return _mdns_append_reverse_ptr_record(packet, index, answer->host->hostname) > 0; +#endif /* CONFIG_MDNS_RESPOND_REVERSE_QUERIES */ + } else { + return _mdns_append_ptr_record(packet, index, + answer->custom_instance, answer->custom_service, answer->custom_proto, + answer->flush, answer->bye) > 0; + } + } else if (answer->type == MDNS_TYPE_SRV) { + return _mdns_append_srv_record(packet, index, answer->service, answer->flush, answer->bye) > 0; + } else if (answer->type == MDNS_TYPE_TXT) { + return _mdns_append_txt_record(packet, index, answer->service, answer->flush, answer->bye) > 0; + } else if (answer->type == MDNS_TYPE_SDPTR) { + return _mdns_append_sdptr_record(packet, index, answer->service, answer->flush, answer->bye) > 0; + } +#ifdef CONFIG_LWIP_IPV4 + else if (answer->type == MDNS_TYPE_A) { + if (answer->host == &_mdns_self_host) { + esp_netif_ip_info_t if_ip_info; + if (!mdns_is_netif_ready(tcpip_if, MDNS_IP_PROTOCOL_V4) && _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V4].state != PCB_DUP) { + return 0; + } + if (esp_netif_get_ip_info(_mdns_get_esp_netif(tcpip_if), &if_ip_info)) { + return 0; + } + if (_mdns_append_a_record(packet, index, _mdns_server->hostname, if_ip_info.ip.addr, answer->flush, answer->bye) <= 0) { + return 0; + } + if (!_mdns_if_is_dup(tcpip_if)) { + return 1; + } + mdns_if_t other_if = _mdns_get_other_if(tcpip_if); + if (esp_netif_get_ip_info(_mdns_get_esp_netif(other_if), &if_ip_info)) { + return 1; + } + if (_mdns_append_a_record(packet, index, _mdns_server->hostname, if_ip_info.ip.addr, answer->flush, answer->bye) > 0) { + return 2; + } + return 1; + } else if (answer->host != NULL) { + return _mdns_append_host_answer(packet, index, answer->host, ESP_IPADDR_TYPE_V4, answer->flush, answer->bye); + } + } +#endif /* CONFIG_LWIP_IPV4 */ +#ifdef CONFIG_LWIP_IPV6 + else if (answer->type == MDNS_TYPE_AAAA) { + if (answer->host == &_mdns_self_host) { + struct esp_ip6_addr if_ip6s[NETIF_IPV6_MAX_NUMS]; + uint8_t count = 0; + if (!mdns_is_netif_ready(tcpip_if, MDNS_IP_PROTOCOL_V6) && _mdns_server->interfaces[tcpip_if].pcbs[MDNS_IP_PROTOCOL_V6].state != PCB_DUP) { + return 0; + } + count = esp_netif_get_all_ip6(_mdns_get_esp_netif(tcpip_if), if_ip6s); + assert(count <= NETIF_IPV6_MAX_NUMS); + for (int i = 0; i < count; i++) { + if (_ipv6_address_is_zero(if_ip6s[i])) { + return 0; + } + if (_mdns_append_aaaa_record(packet, index, _mdns_server->hostname, (uint8_t *)if_ip6s[i].addr, + answer->flush, answer->bye) <= 0) { + return 0; + } + } + if (!_mdns_if_is_dup(tcpip_if)) { + return count; + } + + mdns_if_t other_if = _mdns_get_other_if(tcpip_if); + struct esp_ip6_addr other_ip6; + if (esp_netif_get_ip6_linklocal(_mdns_get_esp_netif(other_if), &other_ip6)) { + return count; + } + if (_mdns_append_aaaa_record(packet, index, _mdns_server->hostname, (uint8_t *)other_ip6.addr, + answer->flush, answer->bye) > 0) { + return 1 + count; + } + return count; + } else if (answer->host != NULL) { + return _mdns_append_host_answer(packet, index, answer->host, ESP_IPADDR_TYPE_V6, answer->flush, + answer->bye); + } + } +#endif /* CONFIG_LWIP_IPV6 */ + return 0; +} + +/** + * @brief sends a packet + * + * @param p the packet + */ +static void _mdns_dispatch_tx_packet(mdns_tx_packet_t *p) +{ + static uint8_t packet[MDNS_MAX_PACKET_SIZE]; + uint16_t index = MDNS_HEAD_LEN; + memset(packet, 0, MDNS_HEAD_LEN); + mdns_out_question_t *q; + mdns_out_answer_t *a; + uint8_t count; + + _mdns_set_u16(packet, MDNS_HEAD_FLAGS_OFFSET, p->flags); + _mdns_set_u16(packet, MDNS_HEAD_ID_OFFSET, p->id); + + count = 0; + q = p->questions; + while (q) { + if (_mdns_append_question(packet, &index, q)) { + count++; + } + q = q->next; + } + _mdns_set_u16(packet, MDNS_HEAD_QUESTIONS_OFFSET, count); + + count = 0; + a = p->answers; + while (a) { + count += _mdns_append_answer(packet, &index, a, p->tcpip_if); + a = a->next; + } + _mdns_set_u16(packet, MDNS_HEAD_ANSWERS_OFFSET, count); + + count = 0; + a = p->servers; + while (a) { + count += _mdns_append_answer(packet, &index, a, p->tcpip_if); + a = a->next; + } + _mdns_set_u16(packet, MDNS_HEAD_SERVERS_OFFSET, count); + + count = 0; + a = p->additional; + while (a) { + count += _mdns_append_answer(packet, &index, a, p->tcpip_if); + a = a->next; + } + _mdns_set_u16(packet, MDNS_HEAD_ADDITIONAL_OFFSET, count); + +#ifdef MDNS_ENABLE_DEBUG + _mdns_dbg_printf("\nTX[%lu][%lu]: ", (unsigned long)p->tcpip_if, (unsigned long)p->ip_protocol); +#ifdef CONFIG_LWIP_IPV4 + if (p->dst.type == ESP_IPADDR_TYPE_V4) { + _mdns_dbg_printf("To: " IPSTR ":%u, ", IP2STR(&p->dst.u_addr.ip4), p->port); + } +#endif +#ifdef CONFIG_LWIP_IPV6 + if (p->dst.type == ESP_IPADDR_TYPE_V6) { + _mdns_dbg_printf("To: " IPV6STR ":%u, ", IPV62STR(p->dst.u_addr.ip6), p->port); + } +#endif + mdns_debug_packet(packet, index); +#endif + + _mdns_udp_pcb_write(p->tcpip_if, p->ip_protocol, &p->dst, p->port, packet, index); +} + +/** + * @brief frees a packet + * + * @param packet the packet + */ +static void _mdns_free_tx_packet(mdns_tx_packet_t *packet) +{ + if (!packet) { + return; + } + mdns_out_question_t *q = packet->questions; + while (q) { + mdns_out_question_t *next = q->next; + if (q->own_dynamic_memory) { + mdns_mem_free((char *)q->host); + mdns_mem_free((char *)q->service); + mdns_mem_free((char *)q->proto); + mdns_mem_free((char *)q->domain); + } + mdns_mem_free(q); + q = next; + } + queueFree(mdns_out_answer_t, packet->answers); + queueFree(mdns_out_answer_t, packet->servers); + queueFree(mdns_out_answer_t, packet->additional); + mdns_mem_free(packet); +} + +/** + * @brief schedules a packet to be sent after given milliseconds + * + * @param packet the packet + * @param ms_after number of milliseconds after which the packet should be dispatched + */ +static void _mdns_schedule_tx_packet(mdns_tx_packet_t *packet, uint32_t ms_after) +{ + if (!packet) { + return; + } + packet->send_at = (xTaskGetTickCount() * portTICK_PERIOD_MS) + ms_after; + packet->next = NULL; + if (!_mdns_server->tx_queue_head || _mdns_server->tx_queue_head->send_at > packet->send_at) { + packet->next = _mdns_server->tx_queue_head; + _mdns_server->tx_queue_head = packet; + return; + } + mdns_tx_packet_t *q = _mdns_server->tx_queue_head; + while (q->next && q->next->send_at <= packet->send_at) { + q = q->next; + } + packet->next = q->next; + q->next = packet; +} + +/** + * @brief free all packets scheduled for sending + */ +static void _mdns_clear_tx_queue_head(void) +{ + mdns_tx_packet_t *q; + while (_mdns_server->tx_queue_head) { + q = _mdns_server->tx_queue_head; + _mdns_server->tx_queue_head = _mdns_server->tx_queue_head->next; + _mdns_free_tx_packet(q); + } +} + +/** + * @brief clear packets scheduled for sending on a specific interface + * + * @param tcpip_if the interface + * @param ip_protocol pcb type V4/V6 + */ +static void _mdns_clear_pcb_tx_queue_head(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +{ + mdns_tx_packet_t *q, * p; + while (_mdns_server->tx_queue_head && _mdns_server->tx_queue_head->tcpip_if == tcpip_if && _mdns_server->tx_queue_head->ip_protocol == ip_protocol) { + q = _mdns_server->tx_queue_head; + _mdns_server->tx_queue_head = _mdns_server->tx_queue_head->next; + _mdns_free_tx_packet(q); + } + if (_mdns_server->tx_queue_head) { + q = _mdns_server->tx_queue_head; + while (q->next) { + if (q->next->tcpip_if == tcpip_if && q->next->ip_protocol == ip_protocol) { + p = q->next; + q->next = p->next; + _mdns_free_tx_packet(p); + } else { + q = q->next; + } + } + } +} + +/** + * @brief get the next packet scheduled for sending on a specific interface + * + * @param tcpip_if the interface + * @param ip_protocol pcb type V4/V6 + */ +static mdns_tx_packet_t *_mdns_get_next_pcb_packet(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +{ + mdns_tx_packet_t *q = _mdns_server->tx_queue_head; + while (q) { + if (q->tcpip_if == tcpip_if && q->ip_protocol == ip_protocol) { + return q; + } + q = q->next; + } + return NULL; +} + +/** + * @brief Find, remove and free answer from the scheduled packets + */ +static void _mdns_remove_scheduled_answer(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint16_t type, mdns_srv_item_t *service) +{ + mdns_srv_item_t s = {NULL, NULL}; + if (!service) { + service = &s; + } + mdns_tx_packet_t *q = _mdns_server->tx_queue_head; + while (q) { + if (q->tcpip_if == tcpip_if && q->ip_protocol == ip_protocol && q->distributed) { + mdns_out_answer_t *a = q->answers; + if (a) { + if (a->type == type && a->service == service->service) { + q->answers = q->answers->next; + mdns_mem_free(a); + } else { + while (a->next) { + if (a->next->type == type && a->next->service == service->service) { + mdns_out_answer_t *b = a->next; + a->next = b->next; + mdns_mem_free(b); + break; + } + a = a->next; + } + } + } + } + q = q->next; + } +} + +/** + * @brief Remove and free answer from answer list (destination) + */ +static void _mdns_dealloc_answer(mdns_out_answer_t **destination, uint16_t type, mdns_srv_item_t *service) +{ + mdns_out_answer_t *d = *destination; + if (!d) { + return; + } + mdns_srv_item_t s = {NULL, NULL}; + if (!service) { + service = &s; + } + if (d->type == type && d->service == service->service) { + *destination = d->next; + mdns_mem_free(d); + return; + } + while (d->next) { + mdns_out_answer_t *a = d->next; + if (a->type == type && a->service == service->service) { + d->next = a->next; + mdns_mem_free(a); + return; + } + d = d->next; + } +} + +/** + * @brief Allocate new answer and add it to answer list (destination) + */ +static bool _mdns_alloc_answer(mdns_out_answer_t **destination, uint16_t type, mdns_service_t *service, + mdns_host_item_t *host, bool flush, bool bye) +{ + mdns_out_answer_t *d = *destination; + while (d) { + if (d->type == type && d->service == service && d->host == host) { + return true; + } + d = d->next; + } + + mdns_out_answer_t *a = (mdns_out_answer_t *)mdns_mem_malloc(sizeof(mdns_out_answer_t)); + if (!a) { + HOOK_MALLOC_FAILED; + return false; + } + a->type = type; + a->service = service; + a->host = host; + a->custom_service = NULL; + a->bye = bye; + a->flush = flush; + a->next = NULL; + queueToEnd(mdns_out_answer_t, *destination, a); + return true; +} + +/** + * @brief Allocate new packet for sending + */ +static mdns_tx_packet_t *_mdns_alloc_packet_default(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +{ + mdns_tx_packet_t *packet = (mdns_tx_packet_t *)mdns_mem_malloc(sizeof(mdns_tx_packet_t)); + if (!packet) { + HOOK_MALLOC_FAILED; + return NULL; + } + memset((uint8_t *)packet, 0, sizeof(mdns_tx_packet_t)); + packet->tcpip_if = tcpip_if; + packet->ip_protocol = ip_protocol; + packet->port = MDNS_SERVICE_PORT; +#ifdef CONFIG_LWIP_IPV4 + if (ip_protocol == MDNS_IP_PROTOCOL_V4) { + esp_ip_addr_t addr = ESP_IP4ADDR_INIT(224, 0, 0, 251); + memcpy(&packet->dst, &addr, sizeof(esp_ip_addr_t)); + } +#endif +#ifdef CONFIG_LWIP_IPV6 + if (ip_protocol == MDNS_IP_PROTOCOL_V6) { + esp_ip_addr_t addr = ESP_IP6ADDR_INIT(0x000002ff, 0, 0, 0xfb000000); + memcpy(&packet->dst, &addr, sizeof(esp_ip_addr_t)); + } +#endif + return packet; +} + +static bool _mdns_create_answer_from_service(mdns_tx_packet_t *packet, mdns_service_t *service, + mdns_parsed_question_t *question, bool shared, bool send_flush) +{ + mdns_host_item_t *host = mdns_get_host_item(service->hostname); + bool is_delegated = (host != &_mdns_self_host); + if (question->type == MDNS_TYPE_PTR || question->type == MDNS_TYPE_ANY) { + // According to RFC6763-section12.1, for DNS-SD, SRV, TXT and all address records + // should be included in additional records. + if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_PTR, service, NULL, false, false) || + !_mdns_alloc_answer(is_delegated ? &packet->additional : &packet->answers, MDNS_TYPE_SRV, service, NULL, send_flush, false) || + !_mdns_alloc_answer(is_delegated ? &packet->additional : &packet->answers, MDNS_TYPE_TXT, service, NULL, send_flush, false) || + !_mdns_alloc_answer((shared || is_delegated) ? &packet->additional : &packet->answers, MDNS_TYPE_A, service, host, send_flush, + false) || + !_mdns_alloc_answer((shared || is_delegated) ? &packet->additional : &packet->answers, MDNS_TYPE_AAAA, service, host, + send_flush, false)) { + return false; + } + } else if (question->type == MDNS_TYPE_SRV) { + if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_SRV, service, NULL, send_flush, false) || + !_mdns_alloc_answer(&packet->additional, MDNS_TYPE_A, service, host, send_flush, false) || + !_mdns_alloc_answer(&packet->additional, MDNS_TYPE_AAAA, service, host, send_flush, false)) { + return false; + } + } else if (question->type == MDNS_TYPE_TXT) { + if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_TXT, service, NULL, send_flush, false)) { + return false; + } + } else if (question->type == MDNS_TYPE_SDPTR) { + if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_SDPTR, service, NULL, false, false)) { + return false; + } + } + return true; +} + +static bool _mdns_create_answer_from_hostname(mdns_tx_packet_t *packet, const char *hostname, bool send_flush) +{ + mdns_host_item_t *host = mdns_get_host_item(hostname); + if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_A, NULL, host, send_flush, false) || + !_mdns_alloc_answer(&packet->answers, MDNS_TYPE_AAAA, NULL, host, send_flush, false)) { + return false; + } + return true; +} + +static bool _mdns_service_match_ptr_question(const mdns_service_t *service, const mdns_parsed_question_t *question) +{ + if (!_mdns_service_match(service, question->service, question->proto, NULL)) { + return false; + } + // The question parser stores anything before _type._proto in question->host + // So the question->host can be subtype or instance name based on its content + if (question->sub) { + mdns_subtype_t *subtype = service->subtype; + while (subtype) { + if (!strcasecmp(subtype->subtype, question->host)) { + return true; + } + subtype = subtype->next; + } + return false; + } + if (question->host) { + if (strcasecmp(_mdns_get_service_instance_name(service), question->host) != 0) { + return false; + } + } + return true; +} + +/** + * @brief Create answer packet to questions from parsed packet + */ +static void _mdns_create_answer_from_parsed_packet(mdns_parsed_packet_t *parsed_packet) +{ + if (!parsed_packet->questions) { + return; + } + bool send_flush = parsed_packet->src_port == MDNS_SERVICE_PORT; + bool unicast = false; + bool shared = false; + mdns_tx_packet_t *packet = _mdns_alloc_packet_default(parsed_packet->tcpip_if, parsed_packet->ip_protocol); + if (!packet) { + return; + } + packet->flags = MDNS_FLAGS_QR_AUTHORITATIVE; + packet->distributed = parsed_packet->distributed; + packet->id = parsed_packet->id; + + mdns_parsed_question_t *q = parsed_packet->questions; + uint32_t out_record_nums = 0; + while (q) { + shared = q->type == MDNS_TYPE_PTR || q->type == MDNS_TYPE_SDPTR || !parsed_packet->probe; + if (q->type == MDNS_TYPE_SRV || q->type == MDNS_TYPE_TXT) { + mdns_srv_item_t *service = _mdns_get_service_item_instance(q->host, q->service, q->proto, NULL); + if (service == NULL) { // Service not found, but we continue to the next question + q = q->next; + continue; + } + if (!_mdns_create_answer_from_service(packet, service->service, q, shared, send_flush)) { + _mdns_free_tx_packet(packet); + return; + } else { + out_record_nums++; + } + } else if (q->service && q->proto) { + mdns_srv_item_t *service = _mdns_server->services; + while (service) { + if (_mdns_service_match_ptr_question(service->service, q)) { + mdns_parsed_record_t *r = parsed_packet->records; + bool is_record_exist = false; + while (r) { + if (service->service->instance && r->host) { + if (_mdns_service_match_instance(service->service, r->host, r->service, r->proto, NULL) && r->ttl > (MDNS_ANSWER_PTR_TTL / 2)) { + is_record_exist = true; + break; + } + } else if (!service->service->instance && !r->host) { + if (_mdns_service_match(service->service, r->service, r->proto, NULL) && r->ttl > (MDNS_ANSWER_PTR_TTL / 2)) { + is_record_exist = true; + break; + } + } + r = r->next; + } + if (!is_record_exist) { + if (!_mdns_create_answer_from_service(packet, service->service, q, shared, send_flush)) { + _mdns_free_tx_packet(packet); + return; + } else { + out_record_nums++; + } + } + } + service = service->next; + } + } else if (q->type == MDNS_TYPE_A || q->type == MDNS_TYPE_AAAA) { + if (!_mdns_create_answer_from_hostname(packet, q->host, send_flush)) { + _mdns_free_tx_packet(packet); + return; + } else { + out_record_nums++; + } + } else if (q->type == MDNS_TYPE_ANY) { + if (!_mdns_append_host_list(&packet->answers, send_flush, false)) { + _mdns_free_tx_packet(packet); + return; + } else { + out_record_nums++; + } +#ifdef CONFIG_MDNS_RESPOND_REVERSE_QUERIES + } else if (q->type == MDNS_TYPE_PTR) { + mdns_host_item_t *host = mdns_get_host_item(q->host); + if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_PTR, NULL, host, send_flush, false)) { + _mdns_free_tx_packet(packet); + return; + } else { + out_record_nums++; + } +#endif /* CONFIG_MDNS_RESPOND_REVERSE_QUERIES */ + } else if (!_mdns_alloc_answer(&packet->answers, q->type, NULL, NULL, send_flush, false)) { + _mdns_free_tx_packet(packet); + return; + } else { + out_record_nums++; + } + + if (parsed_packet->src_port != MDNS_SERVICE_PORT && // Repeat the queries only for "One-Shot mDNS queries" + (q->type == MDNS_TYPE_ANY || q->type == MDNS_TYPE_A || q->type == MDNS_TYPE_AAAA +#ifdef CONFIG_MDNS_RESPOND_REVERSE_QUERIES + || q->type == MDNS_TYPE_PTR +#endif /* CONFIG_MDNS_RESPOND_REVERSE_QUERIES */ + )) { + mdns_out_question_t *out_question = mdns_mem_malloc(sizeof(mdns_out_question_t)); + if (out_question == NULL) { + HOOK_MALLOC_FAILED; + _mdns_free_tx_packet(packet); + return; + } + out_question->type = q->type; + out_question->unicast = q->unicast; + out_question->host = q->host; + q->host = NULL; + out_question->service = q->service; + q->service = NULL; + out_question->proto = q->proto; + q->proto = NULL; + out_question->domain = q->domain; + q->domain = NULL; + out_question->next = NULL; + out_question->own_dynamic_memory = true; + queueToEnd(mdns_out_question_t, packet->questions, out_question); + } + if (q->unicast) { + unicast = true; + } + q = q->next; + } + if (out_record_nums == 0) { + _mdns_free_tx_packet(packet); + return; + } + if (unicast || !send_flush) { + memcpy(&packet->dst, &parsed_packet->src, sizeof(esp_ip_addr_t)); + packet->port = parsed_packet->src_port; + } + + static uint8_t share_step = 0; + if (shared) { + _mdns_schedule_tx_packet(packet, 25 + (share_step * 25)); + share_step = (share_step + 1) & 0x03; + } else { + _mdns_dispatch_tx_packet(packet); + _mdns_free_tx_packet(packet); + } +} + +/** + * @brief Check if question is already in the list + */ +static bool _mdns_question_exists(mdns_out_question_t *needle, mdns_out_question_t *haystack) +{ + while (haystack) { + if (haystack->type == needle->type + && haystack->host == needle->host + && haystack->service == needle->service + && haystack->proto == needle->proto) { + return true; + } + haystack = haystack->next; + } + return false; +} + +static bool _mdns_append_host(mdns_out_answer_t **destination, mdns_host_item_t *host, bool flush, bool bye) +{ + if (!_mdns_alloc_answer(destination, MDNS_TYPE_A, NULL, host, flush, bye)) { + return false; + } + if (!_mdns_alloc_answer(destination, MDNS_TYPE_AAAA, NULL, host, flush, bye)) { + return false; + } + return true; +} + +static bool _mdns_append_host_list_in_services(mdns_out_answer_t **destination, mdns_srv_item_t *services[], + size_t services_len, bool flush, bool bye) +{ + if (services == NULL) { + mdns_host_item_t *host = mdns_get_host_item(_mdns_server->hostname); + if (host != NULL) { + return _mdns_append_host(destination, host, flush, bye); + } + return true; + } + for (size_t i = 0; i < services_len; i++) { + mdns_host_item_t *host = mdns_get_host_item(services[i]->service->hostname); + if (!_mdns_append_host(destination, host, flush, bye)) { + return false; + } + } + return true; +} + +static bool _mdns_append_host_list(mdns_out_answer_t **destination, bool flush, bool bye) +{ + if (!_str_null_or_empty(_mdns_server->hostname)) { + mdns_host_item_t *self_host = mdns_get_host_item(_mdns_server->hostname); + if (!_mdns_append_host(destination, self_host, flush, bye)) { + return false; + } + } + mdns_host_item_t *host = _mdns_host_list; + while (host != NULL) { + host = host->next; + if (!_mdns_append_host(destination, host, flush, bye)) { + return false; + } + } + return true; +} + +static bool _mdns_append_host_question(mdns_out_question_t **questions, const char *hostname, bool unicast) +{ + mdns_out_question_t *q = (mdns_out_question_t *)mdns_mem_malloc(sizeof(mdns_out_question_t)); + if (!q) { + HOOK_MALLOC_FAILED; + return false; + } + q->next = NULL; + q->unicast = unicast; + q->type = MDNS_TYPE_ANY; + q->host = hostname; + q->service = NULL; + q->proto = NULL; + q->domain = MDNS_DEFAULT_DOMAIN; + q->own_dynamic_memory = false; + if (_mdns_question_exists(q, *questions)) { + mdns_mem_free(q); + } else { + queueToEnd(mdns_out_question_t, *questions, q); + } + return true; +} + +static bool _mdns_append_host_questions_for_services(mdns_out_question_t **questions, mdns_srv_item_t *services[], + size_t len, bool unicast) +{ + if (!_str_null_or_empty(_mdns_server->hostname) && + !_mdns_append_host_question(questions, _mdns_server->hostname, unicast)) { + return false; + } + for (size_t i = 0; i < len; i++) { + if (!_mdns_append_host_question(questions, services[i]->service->hostname, unicast)) { + return false; + } + } + return true; +} + +/** + * @brief Create probe packet for particular services on particular PCB + */ +static mdns_tx_packet_t *_mdns_create_probe_packet(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t *services[], size_t len, bool first, bool include_ip) +{ + mdns_tx_packet_t *packet = _mdns_alloc_packet_default(tcpip_if, ip_protocol); + if (!packet) { + return NULL; + } + + size_t i; + for (i = 0; i < len; i++) { + mdns_out_question_t *q = (mdns_out_question_t *)mdns_mem_malloc(sizeof(mdns_out_question_t)); + if (!q) { + HOOK_MALLOC_FAILED; + _mdns_free_tx_packet(packet); + return NULL; + } + q->next = NULL; + q->unicast = first; + q->type = MDNS_TYPE_ANY; + q->host = _mdns_get_service_instance_name(services[i]->service); + q->service = services[i]->service->service; + q->proto = services[i]->service->proto; + q->domain = MDNS_DEFAULT_DOMAIN; + q->own_dynamic_memory = false; + if (!q->host || _mdns_question_exists(q, packet->questions)) { + mdns_mem_free(q); + continue; + } else { + queueToEnd(mdns_out_question_t, packet->questions, q); + } + + if (!q->host || !_mdns_alloc_answer(&packet->servers, MDNS_TYPE_SRV, services[i]->service, NULL, false, false)) { + _mdns_free_tx_packet(packet); + return NULL; + } + } + + if (include_ip) { + if (!_mdns_append_host_questions_for_services(&packet->questions, services, len, first)) { + _mdns_free_tx_packet(packet); + return NULL; + } + + if (!_mdns_append_host_list_in_services(&packet->servers, services, len, false, false)) { + _mdns_free_tx_packet(packet); + return NULL; + } + } + + return packet; +} + +/** + * @brief Create announce packet for particular services on particular PCB + */ +static mdns_tx_packet_t *_mdns_create_announce_packet(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t *services[], size_t len, bool include_ip) +{ + mdns_tx_packet_t *packet = _mdns_alloc_packet_default(tcpip_if, ip_protocol); + if (!packet) { + return NULL; + } + packet->flags = MDNS_FLAGS_QR_AUTHORITATIVE; + + uint8_t i; + for (i = 0; i < len; i++) { + if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_SDPTR, services[i]->service, NULL, false, false) + || !_mdns_alloc_answer(&packet->answers, MDNS_TYPE_PTR, services[i]->service, NULL, false, false) + || !_mdns_alloc_answer(&packet->answers, MDNS_TYPE_SRV, services[i]->service, NULL, true, false) + || !_mdns_alloc_answer(&packet->answers, MDNS_TYPE_TXT, services[i]->service, NULL, true, false)) { + _mdns_free_tx_packet(packet); + return NULL; + } + } + if (include_ip) { + if (!_mdns_append_host_list_in_services(&packet->servers, services, len, true, false)) { + _mdns_free_tx_packet(packet); + return NULL; + } + } + return packet; +} + +/** + * @brief Convert probe packet to announce + */ +static mdns_tx_packet_t *_mdns_create_announce_from_probe(mdns_tx_packet_t *probe) +{ + mdns_tx_packet_t *packet = _mdns_alloc_packet_default(probe->tcpip_if, probe->ip_protocol); + if (!packet) { + return NULL; + } + packet->flags = MDNS_FLAGS_QR_AUTHORITATIVE; + + mdns_out_answer_t *s = probe->servers; + while (s) { + if (s->type == MDNS_TYPE_SRV) { + if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_SDPTR, s->service, NULL, false, false) + || !_mdns_alloc_answer(&packet->answers, MDNS_TYPE_PTR, s->service, NULL, false, false) + || !_mdns_alloc_answer(&packet->answers, MDNS_TYPE_SRV, s->service, NULL, true, false) + || !_mdns_alloc_answer(&packet->answers, MDNS_TYPE_TXT, s->service, NULL, true, false)) { + _mdns_free_tx_packet(packet); + return NULL; + } + mdns_host_item_t *host = mdns_get_host_item(s->service->hostname); + if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_A, NULL, host, true, false) + || !_mdns_alloc_answer(&packet->answers, MDNS_TYPE_AAAA, NULL, host, true, false)) { + _mdns_free_tx_packet(packet); + return NULL; + } + + } else if (s->type == MDNS_TYPE_A || s->type == MDNS_TYPE_AAAA) { + if (!_mdns_alloc_answer(&packet->answers, s->type, NULL, s->host, true, false)) { + _mdns_free_tx_packet(packet); + return NULL; + } + } + + s = s->next; + } + return packet; +} + +/** + * @brief Send by for particular services on particular PCB + */ +static void _mdns_pcb_send_bye(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t **services, size_t len, bool include_ip) +{ + mdns_tx_packet_t *packet = _mdns_alloc_packet_default(tcpip_if, ip_protocol); + if (!packet) { + return; + } + packet->flags = MDNS_FLAGS_QR_AUTHORITATIVE; + size_t i; + for (i = 0; i < len; i++) { + if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_PTR, services[i]->service, NULL, true, true)) { + _mdns_free_tx_packet(packet); + return; + } + } + if (include_ip) { + _mdns_append_host_list_in_services(&packet->answers, services, len, true, true); + } + _mdns_dispatch_tx_packet(packet); + _mdns_free_tx_packet(packet); +} + +/** + * @brief Send probe for additional services on particular PCB + */ +static void _mdns_init_pcb_probe_new_service(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t **services, size_t len, bool probe_ip) +{ + mdns_pcb_t *pcb = &_mdns_server->interfaces[tcpip_if].pcbs[ip_protocol]; + size_t services_final_len = len; + + if (PCB_STATE_IS_PROBING(pcb)) { + services_final_len += pcb->probe_services_len; + } + mdns_srv_item_t **_services = NULL; + if (services_final_len) { + _services = (mdns_srv_item_t **)mdns_mem_malloc(sizeof(mdns_srv_item_t *) * services_final_len); + if (!_services) { + HOOK_MALLOC_FAILED; + return; + } + + size_t i; + for (i = 0; i < len; i++) { + _services[i] = services[i]; + } + if (pcb->probe_services) { + for (i = 0; i < pcb->probe_services_len; i++) { + _services[len + i] = pcb->probe_services[i]; + } + mdns_mem_free(pcb->probe_services); + } + } + + probe_ip = pcb->probe_ip || probe_ip; + + pcb->probe_ip = false; + pcb->probe_services = NULL; + pcb->probe_services_len = 0; + pcb->probe_running = false; + + mdns_tx_packet_t *packet = _mdns_create_probe_packet(tcpip_if, ip_protocol, _services, services_final_len, true, probe_ip); + if (!packet) { + mdns_mem_free(_services); + return; + } + + pcb->probe_ip = probe_ip; + pcb->probe_services = _services; + pcb->probe_services_len = services_final_len; + pcb->probe_running = true; + _mdns_schedule_tx_packet(packet, ((pcb->failed_probes > 5) ? 1000 : 120) + (esp_random() & 0x7F)); + pcb->state = PCB_PROBE_1; +} + +/** + * @brief Send probe for particular services on particular PCB + * + * Tests possible duplication on probing service structure and probes only for new entries. + * - If pcb probing then add only non-probing services and restarts probing + * - If pcb not probing, run probing for all specified services + */ +static void _mdns_init_pcb_probe(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t **services, size_t len, bool probe_ip) +{ + mdns_pcb_t *pcb = &_mdns_server->interfaces[tcpip_if].pcbs[ip_protocol]; + + _mdns_clear_pcb_tx_queue_head(tcpip_if, ip_protocol); + + if (_str_null_or_empty(_mdns_server->hostname)) { + pcb->state = PCB_RUNNING; + return; + } + + if (PCB_STATE_IS_PROBING(pcb)) { + // Looking for already probing services to resolve duplications + mdns_srv_item_t *new_probe_services[len]; + int new_probe_service_len = 0; + bool found; + for (size_t j = 0; j < len; ++j) { + found = false; + for (int i = 0; i < pcb->probe_services_len; ++i) { + if (pcb->probe_services[i] == services[j]) { + found = true; + break; + } + } + if (!found) { + new_probe_services[new_probe_service_len++] = services[j]; + } + } + // init probing for newly added services + _mdns_init_pcb_probe_new_service(tcpip_if, ip_protocol, + new_probe_service_len ? new_probe_services : NULL, new_probe_service_len, probe_ip); + } else { + // not probing, so init for all services + _mdns_init_pcb_probe_new_service(tcpip_if, ip_protocol, services, len, probe_ip); + } +} + +/** + * @brief Restart the responder on particular PCB + */ +static void _mdns_restart_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +{ + size_t srv_count = 0; + mdns_srv_item_t *a = _mdns_server->services; + while (a) { + srv_count++; + a = a->next; + } + if (srv_count == 0) { + // proble only IP + _mdns_init_pcb_probe(tcpip_if, ip_protocol, NULL, 0, true); + return; + } + mdns_srv_item_t *services[srv_count]; + size_t i = 0; + a = _mdns_server->services; + while (a) { + services[i++] = a; + a = a->next; + } + _mdns_init_pcb_probe(tcpip_if, ip_protocol, services, srv_count, true); +} + +/** + * @brief Send by for particular services + */ +static void _mdns_send_bye(mdns_srv_item_t **services, size_t len, bool include_ip) +{ + uint8_t i, j; + if (_str_null_or_empty(_mdns_server->hostname)) { + return; + } + + for (i = 0; i < MDNS_MAX_INTERFACES; i++) { + for (j = 0; j < MDNS_IP_PROTOCOL_MAX; j++) { + if (mdns_is_netif_ready(i, j) && _mdns_server->interfaces[i].pcbs[j].state == PCB_RUNNING) { + _mdns_pcb_send_bye((mdns_if_t)i, (mdns_ip_protocol_t)j, services, len, include_ip); + } + } + } +} + +/** + * @brief Send bye for particular subtypes + */ +static void _mdns_send_bye_subtype(mdns_srv_item_t *service, const char *instance_name, mdns_subtype_t *remove_subtypes) +{ + uint8_t i, j; + for (i = 0; i < MDNS_MAX_INTERFACES; i++) { + for (j = 0; j < MDNS_IP_PROTOCOL_MAX; j++) { + if (mdns_is_netif_ready(i, j)) { + mdns_tx_packet_t *packet = _mdns_alloc_packet_default((mdns_if_t)i, (mdns_ip_protocol_t)j); + if (packet == NULL) { + return; + } + packet->flags = MDNS_FLAGS_QR_AUTHORITATIVE; + if (!_mdns_alloc_answer(&packet->answers, MDNS_TYPE_PTR, service->service, NULL, true, true)) { + _mdns_free_tx_packet(packet); + return; + } + + static uint8_t pkt[MDNS_MAX_PACKET_SIZE]; + uint16_t index = MDNS_HEAD_LEN; + memset(pkt, 0, MDNS_HEAD_LEN); + mdns_out_answer_t *a; + uint8_t count; + + _mdns_set_u16(pkt, MDNS_HEAD_FLAGS_OFFSET, packet->flags); + _mdns_set_u16(pkt, MDNS_HEAD_ID_OFFSET, packet->id); + + count = 0; + a = packet->answers; + while (a) { + if (a->type == MDNS_TYPE_PTR && a->service) { + const mdns_subtype_t *current_subtype = remove_subtypes; + while (current_subtype) { + count += (_mdns_append_subtype_ptr_record(pkt, &index, instance_name, current_subtype->subtype, a->service->service, a->service->proto, a->flush, a->bye) > 0); + current_subtype = current_subtype->next; + } + } + a = a->next; + } + _mdns_set_u16(pkt, MDNS_HEAD_ANSWERS_OFFSET, count); + + _mdns_udp_pcb_write(packet->tcpip_if, packet->ip_protocol, &packet->dst, packet->port, pkt, index); + + _mdns_free_tx_packet(packet); + } + } + } +} + +/** + * @brief Send announcement on particular PCB + */ +static void _mdns_announce_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, mdns_srv_item_t **services, size_t len, bool include_ip) +{ + mdns_pcb_t *_pcb = &_mdns_server->interfaces[tcpip_if].pcbs[ip_protocol]; + size_t i; + if (mdns_is_netif_ready(tcpip_if, ip_protocol)) { + if (PCB_STATE_IS_PROBING(_pcb)) { + _mdns_init_pcb_probe(tcpip_if, ip_protocol, services, len, include_ip); + } else if (PCB_STATE_IS_ANNOUNCING(_pcb)) { + mdns_tx_packet_t *p = _mdns_get_next_pcb_packet(tcpip_if, ip_protocol); + if (p) { + for (i = 0; i < len; i++) { + if (!_mdns_alloc_answer(&p->answers, MDNS_TYPE_SDPTR, services[i]->service, NULL, false, false) + || !_mdns_alloc_answer(&p->answers, MDNS_TYPE_PTR, services[i]->service, NULL, false, false) + || !_mdns_alloc_answer(&p->answers, MDNS_TYPE_SRV, services[i]->service, NULL, true, false) + || !_mdns_alloc_answer(&p->answers, MDNS_TYPE_TXT, services[i]->service, NULL, true, false)) { + break; + } + } + if (include_ip) { + _mdns_dealloc_answer(&p->additional, MDNS_TYPE_A, NULL); + _mdns_dealloc_answer(&p->additional, MDNS_TYPE_AAAA, NULL); + _mdns_append_host_list_in_services(&p->answers, services, len, true, false); + } + _pcb->state = PCB_ANNOUNCE_1; + } + } else if (_pcb->state == PCB_RUNNING) { + + if (_str_null_or_empty(_mdns_server->hostname)) { + return; + } + + _pcb->state = PCB_ANNOUNCE_1; + mdns_tx_packet_t *p = _mdns_create_announce_packet(tcpip_if, ip_protocol, services, len, include_ip); + if (p) { + _mdns_schedule_tx_packet(p, 0); + } + } + } +} + +/** + * @brief Send probe on all active PCBs + */ +static void _mdns_probe_all_pcbs(mdns_srv_item_t **services, size_t len, bool probe_ip, bool clear_old_probe) +{ + uint8_t i, j; + for (i = 0; i < MDNS_MAX_INTERFACES; i++) { + for (j = 0; j < MDNS_IP_PROTOCOL_MAX; j++) { + if (mdns_is_netif_ready(i, j)) { + mdns_pcb_t *_pcb = &_mdns_server->interfaces[i].pcbs[j]; + if (clear_old_probe) { + mdns_mem_free(_pcb->probe_services); + _pcb->probe_services = NULL; + _pcb->probe_services_len = 0; + _pcb->probe_running = false; + } + _mdns_init_pcb_probe((mdns_if_t)i, (mdns_ip_protocol_t)j, services, len, probe_ip); + } + } + } +} + +/** + * @brief Send announcement on all active PCBs + */ +static void _mdns_announce_all_pcbs(mdns_srv_item_t **services, size_t len, bool include_ip) +{ + uint8_t i, j; + for (i = 0; i < MDNS_MAX_INTERFACES; i++) { + for (j = 0; j < MDNS_IP_PROTOCOL_MAX; j++) { + _mdns_announce_pcb((mdns_if_t)i, (mdns_ip_protocol_t)j, services, len, include_ip); + } + } +} + +/** + * @brief Restart the responder on all active PCBs + */ +static void _mdns_send_final_bye(bool include_ip) +{ + //collect all services and start probe + size_t srv_count = 0; + mdns_srv_item_t *a = _mdns_server->services; + while (a) { + srv_count++; + a = a->next; + } + if (!srv_count) { + return; + } + mdns_srv_item_t *services[srv_count]; + size_t i = 0; + a = _mdns_server->services; + while (a) { + services[i++] = a; + a = a->next; + } + _mdns_send_bye(services, srv_count, include_ip); +} + +/** + * @brief Stop the responder on all services without instance + */ +static void _mdns_send_bye_all_pcbs_no_instance(bool include_ip) +{ + size_t srv_count = 0; + mdns_srv_item_t *a = _mdns_server->services; + while (a) { + if (!a->service->instance) { + srv_count++; + } + a = a->next; + } + if (!srv_count) { + return; + } + mdns_srv_item_t *services[srv_count]; + size_t i = 0; + a = _mdns_server->services; + while (a) { + if (!a->service->instance) { + services[i++] = a; + } + a = a->next; + } + _mdns_send_bye(services, srv_count, include_ip); +} + +/** + * @brief Restart the responder on all services without instance + */ +static void _mdns_restart_all_pcbs_no_instance(void) +{ + size_t srv_count = 0; + mdns_srv_item_t *a = _mdns_server->services; + while (a) { + if (!a->service->instance) { + srv_count++; + } + a = a->next; + } + if (!srv_count) { + return; + } + mdns_srv_item_t *services[srv_count]; + size_t i = 0; + a = _mdns_server->services; + while (a) { + if (!a->service->instance) { + services[i++] = a; + } + a = a->next; + } + _mdns_probe_all_pcbs(services, srv_count, false, true); +} + +/** + * @brief Restart the responder on all active PCBs + */ +static void _mdns_restart_all_pcbs(void) +{ + _mdns_clear_tx_queue_head(); + size_t srv_count = 0; + mdns_srv_item_t *a = _mdns_server->services; + while (a) { + srv_count++; + a = a->next; + } + if (srv_count == 0) { + _mdns_probe_all_pcbs(NULL, 0, true, true); + return; + } + mdns_srv_item_t *services[srv_count]; + size_t l = 0; + a = _mdns_server->services; + while (a) { + services[l++] = a; + a = a->next; + } + + _mdns_probe_all_pcbs(services, srv_count, true, true); +} + + + +/** + * @brief creates/allocates new text item list + * @param num_items service number of txt items or 0 + * @param txt service txt items array or NULL + * + * @return pointer to the linked txt item list or NULL + */ +static mdns_txt_linked_item_t *_mdns_allocate_txt(size_t num_items, mdns_txt_item_t txt[]) +{ + mdns_txt_linked_item_t *new_txt = NULL; + size_t i = 0; + if (num_items) { + for (i = 0; i < num_items; i++) { + mdns_txt_linked_item_t *new_item = (mdns_txt_linked_item_t *)mdns_mem_malloc(sizeof(mdns_txt_linked_item_t)); + if (!new_item) { + HOOK_MALLOC_FAILED; + break; + } + new_item->key = mdns_mem_strdup(txt[i].key); + if (!new_item->key) { + mdns_mem_free(new_item); + break; + } + new_item->value = mdns_mem_strdup(txt[i].value); + if (!new_item->value) { + mdns_mem_free((char *)new_item->key); + mdns_mem_free(new_item); + break; + } + new_item->value_len = strlen(new_item->value); + new_item->next = new_txt; + new_txt = new_item; + } + } + return new_txt; +} + +/** + * @brief Deallocate the txt linked list + * @param txt pointer to the txt pointer to free, noop if txt==NULL + */ +static void _mdns_free_linked_txt(mdns_txt_linked_item_t *txt) +{ + mdns_txt_linked_item_t *t; + while (txt) { + t = txt; + txt = txt->next; + mdns_mem_free((char *)t->value); + mdns_mem_free((char *)t->key); + mdns_mem_free(t); + } +} + +/** + * @brief creates/allocates new service + * @param service service type + * @param proto service proto + * @param hostname service hostname + * @param port service port + * @param instance service instance + * @param num_items service number of txt items or 0 + * @param txt service txt items array or NULL + * + * @return pointer to the service or NULL on error + */ +static mdns_service_t *_mdns_create_service(const char *service, const char *proto, const char *hostname, + uint16_t port, const char *instance, size_t num_items, + mdns_txt_item_t txt[]) +{ + mdns_service_t *s = (mdns_service_t *)mdns_mem_calloc(1, sizeof(mdns_service_t)); + if (!s) { + HOOK_MALLOC_FAILED; + return NULL; + } + + mdns_txt_linked_item_t *new_txt = _mdns_allocate_txt(num_items, txt); + if (num_items && new_txt == NULL) { + goto fail; + } + + s->priority = 0; + s->weight = 0; + s->instance = instance ? mdns_mem_strndup(instance, MDNS_NAME_BUF_LEN - 1) : NULL; + s->txt = new_txt; + s->port = port; + s->subtype = NULL; + + if (hostname) { + s->hostname = mdns_mem_strndup(hostname, MDNS_NAME_BUF_LEN - 1); + if (!s->hostname) { + goto fail; + } + } else { + s->hostname = NULL; + } + + s->service = mdns_mem_strndup(service, MDNS_NAME_BUF_LEN - 1); + if (!s->service) { + goto fail; + } + + s->proto = mdns_mem_strndup(proto, MDNS_NAME_BUF_LEN - 1); + if (!s->proto) { + goto fail; + } + return s; + +fail: + _mdns_free_linked_txt(s->txt); + mdns_mem_free((char *)s->instance); + mdns_mem_free((char *)s->service); + mdns_mem_free((char *)s->proto); + mdns_mem_free((char *)s->hostname); + mdns_mem_free(s); + + return NULL; +} + +/** + * @brief Remove and free service answer from answer list (destination) + */ +static void _mdns_dealloc_scheduled_service_answers(mdns_out_answer_t **destination, mdns_service_t *service) +{ + mdns_out_answer_t *d = *destination; + if (!d) { + return; + } + while (d && d->service == service) { + *destination = d->next; + mdns_mem_free(d); + d = *destination; + } + while (d && d->next) { + mdns_out_answer_t *a = d->next; + if (a->service == service) { + d->next = a->next; + mdns_mem_free(a); + } else { + d = d->next; + } + } +} + +/** + * @brief Find, remove and free answers and scheduled packets for service + */ +static void _mdns_remove_scheduled_service_packets(mdns_service_t *service) +{ + if (!service) { + return; + } + mdns_tx_packet_t *p = NULL; + mdns_tx_packet_t *q = _mdns_server->tx_queue_head; + while (q) { + bool had_answers = (q->answers != NULL); + + _mdns_dealloc_scheduled_service_answers(&(q->answers), service); + _mdns_dealloc_scheduled_service_answers(&(q->additional), service); + _mdns_dealloc_scheduled_service_answers(&(q->servers), service); + + + mdns_pcb_t *_pcb = &_mdns_server->interfaces[q->tcpip_if].pcbs[q->ip_protocol]; + if (mdns_is_netif_ready(q->tcpip_if, q->ip_protocol)) { + if (PCB_STATE_IS_PROBING(_pcb)) { + uint8_t i; + //check if we are probing this service + for (i = 0; i < _pcb->probe_services_len; i++) { + mdns_srv_item_t *s = _pcb->probe_services[i]; + if (s->service == service) { + break; + } + } + if (i < _pcb->probe_services_len) { + if (_pcb->probe_services_len > 1) { + uint8_t n; + for (n = (i + 1); n < _pcb->probe_services_len; n++) { + _pcb->probe_services[n - 1] = _pcb->probe_services[n]; + } + _pcb->probe_services_len--; + } else { + _pcb->probe_services_len = 0; + mdns_mem_free(_pcb->probe_services); + _pcb->probe_services = NULL; + if (!_pcb->probe_ip) { + _pcb->probe_running = false; + _pcb->state = PCB_RUNNING; + } + } + + if (q->questions) { + mdns_out_question_t *qsn = NULL; + mdns_out_question_t *qs = q->questions; + if (qs->type == MDNS_TYPE_ANY + && qs->service && strcmp(qs->service, service->service) == 0 + && qs->proto && strcmp(qs->proto, service->proto) == 0) { + q->questions = q->questions->next; + mdns_mem_free(qs); + } else while (qs->next) { + qsn = qs->next; + if (qsn->type == MDNS_TYPE_ANY + && qsn->service && strcmp(qsn->service, service->service) == 0 + && qsn->proto && strcmp(qsn->proto, service->proto) == 0) { + qs->next = qsn->next; + mdns_mem_free(qsn); + break; + } + qs = qs->next; + } + } + } + } else if (PCB_STATE_IS_ANNOUNCING(_pcb)) { + //if answers were cleared, set to running + if (had_answers && q->answers == NULL) { + _pcb->state = PCB_RUNNING; + } + } + } + + p = q; + q = q->next; + if (!p->questions && !p->answers && !p->additional && !p->servers) { + queueDetach(mdns_tx_packet_t, _mdns_server->tx_queue_head, p); + _mdns_free_tx_packet(p); + } + } +} + +static void _mdns_free_subtype(mdns_subtype_t *subtype) +{ + while (subtype) { + mdns_subtype_t *next = subtype->next; + mdns_mem_free((char *)subtype->subtype); + mdns_mem_free(subtype); + subtype = next; + } +} + +static void _mdns_free_service_subtype(mdns_service_t *service) +{ + _mdns_free_subtype(service->subtype); + service->subtype = NULL; +} + +/** + * @brief free service memory + * + * @param service the service + */ +static void _mdns_free_service(mdns_service_t *service) +{ + if (!service) { + return; + } + mdns_mem_free((char *)service->instance); + mdns_mem_free((char *)service->service); + mdns_mem_free((char *)service->proto); + mdns_mem_free((char *)service->hostname); + while (service->txt) { + mdns_txt_linked_item_t *s = service->txt; + service->txt = service->txt->next; + mdns_mem_free((char *)s->key); + mdns_mem_free((char *)s->value); + mdns_mem_free(s); + } + _mdns_free_service_subtype(service); + mdns_mem_free(service); +} + + +/* + * Received Packet Handling + * */ + +/** + * @brief Detect SRV collision + */ +static int _mdns_check_srv_collision(mdns_service_t *service, uint16_t priority, uint16_t weight, uint16_t port, const char *host, const char *domain) +{ + if (_str_null_or_empty(_mdns_server->hostname)) { + return 0; + } + + size_t our_host_len = strlen(_mdns_server->hostname); + size_t our_len = 14 + our_host_len; + + size_t their_host_len = strlen(host); + size_t their_domain_len = strlen(domain); + size_t their_len = 9 + their_host_len + their_domain_len; + + if (their_len > our_len) { + return 1;//they win + } else if (their_len < our_len) { + return -1;//we win + } + + uint16_t our_index = 0; + uint8_t our_data[our_len]; + _mdns_append_u16(our_data, &our_index, service->priority); + _mdns_append_u16(our_data, &our_index, service->weight); + _mdns_append_u16(our_data, &our_index, service->port); + our_data[our_index++] = our_host_len; + memcpy(our_data + our_index, _mdns_server->hostname, our_host_len); + our_index += our_host_len; + our_data[our_index++] = 5; + memcpy(our_data + our_index, MDNS_DEFAULT_DOMAIN, 5); + our_index += 5; + our_data[our_index++] = 0; + + uint16_t their_index = 0; + uint8_t their_data[their_len]; + _mdns_append_u16(their_data, &their_index, priority); + _mdns_append_u16(their_data, &their_index, weight); + _mdns_append_u16(their_data, &their_index, port); + their_data[their_index++] = their_host_len; + memcpy(their_data + their_index, host, their_host_len); + their_index += their_host_len; + their_data[their_index++] = their_domain_len; + memcpy(their_data + their_index, domain, their_domain_len); + their_index += their_domain_len; + their_data[their_index++] = 0; + + int ret = memcmp(our_data, their_data, our_len); + if (ret > 0) { + return -1;//we win + } else if (ret < 0) { + return 1;//they win + } + return 0;//same +} + +/** + * @brief Detect TXT collision + */ +static int _mdns_check_txt_collision(mdns_service_t *service, const uint8_t *data, size_t len) +{ + size_t data_len = 0; + if (len <= 1 && service->txt) { // len==0 means incorrect packet (and handled by the packet parser) + // but handled here again to fix clang-tidy warning on VLA "uint8_t our[0];" + return -1;//we win + } else if (len > 1 && !service->txt) { + return 1;//they win + } else if (len <= 1 && !service->txt) { + return 0;//same + } + + mdns_txt_linked_item_t *txt = service->txt; + while (txt) { + data_len += 1 /* record-len */ + strlen(txt->key) + txt->value_len + (txt->value ? 1 : 0 /* "=" */); + txt = txt->next; + } + + if (len > data_len) { + return 1;//they win + } else if (len < data_len) { + return -1;//we win + } + + uint8_t ours[len]; + uint16_t index = 0; + + txt = service->txt; + while (txt) { + append_one_txt_record_entry(ours, &index, txt); + txt = txt->next; + } + + int ret = memcmp(ours, data, len); + if (ret > 0) { + return -1;//we win + } else if (ret < 0) { + return 1;//they win + } + return 0;//same +} + +static esp_err_t mdns_pcb_deinit_local(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_proto) +{ + esp_err_t err = _mdns_pcb_deinit(tcpip_if, ip_proto); + mdns_pcb_t *_pcb = &_mdns_server->interfaces[tcpip_if].pcbs[ip_proto]; + if (_pcb == NULL || err != ESP_OK) { + return err; + } + mdns_mem_free(_pcb->probe_services); + _pcb->state = PCB_OFF; + _pcb->probe_ip = false; + _pcb->probe_services = NULL; + _pcb->probe_services_len = 0; + _pcb->probe_running = false; + _pcb->failed_probes = 0; + return ESP_OK; +} +/** + * @brief Set interface as duplicate if another is found on the same subnet + */ +static void _mdns_dup_interface(mdns_if_t tcpip_if) +{ + uint8_t i; + mdns_if_t other_if = _mdns_get_other_if(tcpip_if); + if (other_if == MDNS_MAX_INTERFACES) { + return; // no other interface found + } + for (i = 0; i < MDNS_IP_PROTOCOL_MAX; i++) { + if (mdns_is_netif_ready(other_if, i)) { + //stop this interface and mark as dup + if (mdns_is_netif_ready(tcpip_if, i)) { + _mdns_clear_pcb_tx_queue_head(tcpip_if, i); + mdns_pcb_deinit_local(tcpip_if, i); + } + _mdns_server->interfaces[tcpip_if].pcbs[i].state = PCB_DUP; + _mdns_announce_pcb(other_if, i, NULL, 0, true); + } + } +} + +#ifdef CONFIG_LWIP_IPV4 +/** + * @brief Detect IPv4 address collision + */ +static int _mdns_check_a_collision(esp_ip4_addr_t *ip, mdns_if_t tcpip_if) +{ + esp_netif_ip_info_t if_ip_info; + esp_netif_ip_info_t other_ip_info; + if (!ip->addr) { + return 1;//denial! they win + } + if (esp_netif_get_ip_info(_mdns_get_esp_netif(tcpip_if), &if_ip_info)) { + return 1;//they win + } + int ret = memcmp((uint8_t *)&if_ip_info.ip.addr, (uint8_t *)&ip->addr, sizeof(esp_ip4_addr_t)); + if (ret > 0) { + return -1;//we win + } else if (ret < 0) { + //is it the other interface? + mdns_if_t other_if = _mdns_get_other_if(tcpip_if); + if (other_if == MDNS_MAX_INTERFACES) { + return 1;//AP interface! They win + } + if (esp_netif_get_ip_info(_mdns_get_esp_netif(other_if), &other_ip_info)) { + return 1;//IPv4 not active! They win + } + if (ip->addr != other_ip_info.ip.addr) { + return 1;//IPv4 not ours! They win + } + _mdns_dup_interface(tcpip_if); + return 2;//they win + } + return 0;//same +} +#endif /* CONFIG_LWIP_IPV4 */ + +#ifdef CONFIG_LWIP_IPV6 +/** + * @brief Detect IPv6 address collision + */ +static int _mdns_check_aaaa_collision(esp_ip6_addr_t *ip, mdns_if_t tcpip_if) +{ + struct esp_ip6_addr if_ip6; + struct esp_ip6_addr other_ip6; + if (_ipv6_address_is_zero(*ip)) { + return 1;//denial! they win + } + if (esp_netif_get_ip6_linklocal(_mdns_get_esp_netif(tcpip_if), &if_ip6)) { + return 1;//they win + } + int ret = memcmp((uint8_t *)&if_ip6.addr, (uint8_t *)ip->addr, _MDNS_SIZEOF_IP6_ADDR); + if (ret > 0) { + return -1;//we win + } else if (ret < 0) { + //is it the other interface? + mdns_if_t other_if = _mdns_get_other_if(tcpip_if); + if (other_if == MDNS_MAX_INTERFACES) { + return 1;//AP interface! They win + } + if (esp_netif_get_ip6_linklocal(_mdns_get_esp_netif(other_if), &other_ip6)) { + return 1;//IPv6 not active! They win + } + if (memcmp((uint8_t *)&other_ip6.addr, (uint8_t *)ip->addr, _MDNS_SIZEOF_IP6_ADDR)) { + return 1;//IPv6 not ours! They win + } + _mdns_dup_interface(tcpip_if); + return 2;//they win + } + return 0;//same +} +#endif /* CONFIG_LWIP_IPV6 */ + +static bool _hostname_is_ours(const char *hostname) +{ + if (!_str_null_or_empty(_mdns_server->hostname) && + strcasecmp(hostname, _mdns_server->hostname) == 0) { + return true; + } + mdns_host_item_t *host = _mdns_host_list; + while (host != NULL) { + if (strcasecmp(hostname, host->hostname) == 0) { + return true; + } + host = host->next; + } + return false; +} + +/** + * @brief Adds a delegated hostname to the linked list + * @param hostname Host name pointer + * @param address_list Address list + * @return true on success + * false if the host wasn't attached (this is our hostname, or alloc failure) so we have to free the structs + */ +static bool _mdns_delegate_hostname_add(const char *hostname, mdns_ip_addr_t *address_list) +{ + if (_hostname_is_ours(hostname)) { + return false; + } + + mdns_host_item_t *host = (mdns_host_item_t *)mdns_mem_malloc(sizeof(mdns_host_item_t)); + + if (host == NULL) { + return false; + } + host->address_list = address_list; + host->hostname = hostname; + host->next = _mdns_host_list; + _mdns_host_list = host; + return true; +} + +static void free_address_list(mdns_ip_addr_t *address_list) +{ + while (address_list != NULL) { + mdns_ip_addr_t *next = address_list->next; + mdns_mem_free(address_list); + address_list = next; + } +} + + +static bool _mdns_delegate_hostname_set_address(const char *hostname, mdns_ip_addr_t *address_list) +{ + if (!_str_null_or_empty(_mdns_server->hostname) && + strcasecmp(hostname, _mdns_server->hostname) == 0) { + return false; + } + mdns_host_item_t *host = _mdns_host_list; + while (host != NULL) { + if (strcasecmp(hostname, host->hostname) == 0) { + // free previous address list + free_address_list(host->address_list); + // set current address list to the host + host->address_list = address_list; + return true; + } + host = host->next; + } + return false; +} + +static mdns_ip_addr_t *copy_address_list(const mdns_ip_addr_t *address_list) +{ + mdns_ip_addr_t *head = NULL; + mdns_ip_addr_t *tail = NULL; + while (address_list != NULL) { + mdns_ip_addr_t *addr = (mdns_ip_addr_t *)mdns_mem_malloc(sizeof(mdns_ip_addr_t)); + if (addr == NULL) { + free_address_list(head); + return NULL; + } + addr->addr = address_list->addr; + addr->next = NULL; + if (head == NULL) { + head = addr; + tail = addr; + } else { + tail->next = addr; + tail = tail->next; + } + address_list = address_list->next; + } + return head; +} + +static void free_delegated_hostnames(void) +{ + mdns_host_item_t *host = _mdns_host_list; + while (host != NULL) { + free_address_list(host->address_list); + mdns_mem_free((char *)host->hostname); + mdns_host_item_t *item = host; + host = host->next; + mdns_mem_free(item); + } + _mdns_host_list = NULL; +} + +static bool _mdns_delegate_hostname_remove(const char *hostname) +{ + mdns_srv_item_t *srv = _mdns_server->services; + mdns_srv_item_t *prev_srv = NULL; + while (srv) { + if (strcasecmp(srv->service->hostname, hostname) == 0) { + mdns_srv_item_t *to_free = srv; + _mdns_send_bye(&srv, 1, false); + _mdns_remove_scheduled_service_packets(srv->service); + if (prev_srv == NULL) { + _mdns_server->services = srv->next; + srv = srv->next; + } else { + prev_srv->next = srv->next; + srv = srv->next; + } + _mdns_free_service(to_free->service); + mdns_mem_free(to_free); + } else { + prev_srv = srv; + srv = srv->next; + } + } + mdns_host_item_t *host = _mdns_host_list; + mdns_host_item_t *prev_host = NULL; + while (host != NULL) { + if (strcasecmp(hostname, host->hostname) == 0) { + if (prev_host == NULL) { + _mdns_host_list = host->next; + } else { + prev_host->next = host->next; + } + free_address_list(host->address_list); + mdns_mem_free((char *)host->hostname); + mdns_mem_free(host); + break; + } else { + prev_host = host; + host = host->next; + } + } + return true; +} + +/** + * @brief Check if parsed name is discovery + */ +static bool _mdns_name_is_discovery(mdns_name_t *name, uint16_t type) +{ + return ( + (name->host[0] && !strcasecmp(name->host, "_services")) + && (name->service[0] && !strcasecmp(name->service, "_dns-sd")) + && (name->proto[0] && !strcasecmp(name->proto, "_udp")) + && (name->domain[0] && !strcasecmp(name->domain, MDNS_DEFAULT_DOMAIN)) + && type == MDNS_TYPE_PTR + ); +} + +/** + * @brief Check if the parsed name is self-hosted, i.e. we should resolve conflicts + */ +static bool _mdns_name_is_selfhosted(mdns_name_t *name) +{ + if (_str_null_or_empty(_mdns_server->hostname)) { // self-hostname needs to be defined + return false; + } + + // hostname only -- check if selfhosted name + if (_str_null_or_empty(name->service) && _str_null_or_empty(name->proto) && + strcasecmp(name->host, _mdns_server->hostname) == 0) { + return true; + } + + // service -- check if selfhosted service + mdns_srv_item_t *srv = _mdns_get_service_item(name->service, name->proto, NULL); + if (srv && strcasecmp(_mdns_server->hostname, srv->service->hostname) == 0) { + return true; + } + return false; +} + +/** + * @brief Check if the parsed name is ours (matches service or host name) + */ +static bool _mdns_name_is_ours(mdns_name_t *name) +{ + //domain have to be "local" + if (_str_null_or_empty(name->domain) || (strcasecmp(name->domain, MDNS_DEFAULT_DOMAIN) +#ifdef CONFIG_MDNS_RESPOND_REVERSE_QUERIES + && strcasecmp(name->domain, "arpa") +#endif /* CONFIG_MDNS_RESPOND_REVERSE_QUERIES */ + )) { + return false; + } + + //if service and proto are empty, host must match out hostname + if (_str_null_or_empty(name->service) && _str_null_or_empty(name->proto)) { + if (!_str_null_or_empty(name->host) + && !_str_null_or_empty(_mdns_server->hostname) + && _hostname_is_ours(name->host)) { + return true; + } + return false; + } + + //if service or proto is empty, name is invalid + if (_str_null_or_empty(name->service) || _str_null_or_empty(name->proto)) { + return false; + } + + + //find the service + mdns_srv_item_t *service; + if (name->sub) { + service = _mdns_get_service_item_subtype(name->host, name->service, name->proto); + } else if (_str_null_or_empty(name->host)) { + service = _mdns_get_service_item(name->service, name->proto, NULL); + } else { + service = _mdns_get_service_item_instance(name->host, name->service, name->proto, NULL); + } + if (!service) { + return false; + } + + //if query is PTR query and we have service, we have success + if (name->sub || _str_null_or_empty(name->host)) { + return true; + } + + //OK we have host in the name. find what is the instance of the service + const char *instance = _mdns_get_service_instance_name(service->service); + if (instance == NULL) { + return false; + } + + //compare the instance against the name + if (strcasecmp(name->host, instance) == 0) { + return true; + } + + return false; +} + +/** + * @brief read uint16_t from a packet + * @param packet the packet + * @param index index in the packet where the value starts + * + * @return the value + */ +static inline uint16_t _mdns_read_u16(const uint8_t *packet, uint16_t index) +{ + return (uint16_t)(packet[index]) << 8 | packet[index + 1]; +} + +/** + * @brief read uint32_t from a packet + * @param packet the packet + * @param index index in the packet where the value starts + * + * @return the value + */ +static inline uint32_t _mdns_read_u32(const uint8_t *packet, uint16_t index) +{ + return (uint32_t)(packet[index]) << 24 | (uint32_t)(packet[index + 1]) << 16 | (uint32_t)(packet[index + 2]) << 8 | packet[index + 3]; +} + +/** + * @brief reads and formats MDNS FQDN into mdns_name_t structure + * + * @param packet MDNS packet + * @param start Starting point of FQDN + * @param name mdns_name_t structure to populate + * + * @return the address after the parsed FQDN in the packet or NULL on error + */ +static const uint8_t *_mdns_parse_fqdn(const uint8_t *packet, const uint8_t *start, mdns_name_t *name, size_t packet_len) +{ + name->parts = 0; + name->sub = 0; + name->host[0] = 0; + name->service[0] = 0; + name->proto[0] = 0; + name->domain[0] = 0; + name->invalid = false; + + static char buf[MDNS_NAME_BUF_LEN]; + + const uint8_t *next_data = (uint8_t *)_mdns_read_fqdn(packet, start, name, buf, packet_len); + if (!next_data) { + return 0; + } + if (!name->parts || name->invalid) { + return next_data; + } + if (name->parts == 3) { + memmove((uint8_t *)name + (MDNS_NAME_BUF_LEN), (uint8_t *)name, 3 * (MDNS_NAME_BUF_LEN)); + name->host[0] = 0; + } else if (name->parts == 2) { + memmove((uint8_t *)(name->domain), (uint8_t *)(name->service), (MDNS_NAME_BUF_LEN)); + name->service[0] = 0; + name->proto[0] = 0; + } + if (strcasecmp(name->domain, MDNS_DEFAULT_DOMAIN) == 0 || strcasecmp(name->domain, "arpa") == 0) { + return next_data; + } + name->invalid = true; // mark the current name invalid, but continue with other question + return next_data; +} + +/** + * @brief Called from parser to check if question matches particular service + */ +static bool _mdns_question_matches(mdns_parsed_question_t *question, uint16_t type, mdns_srv_item_t *service) +{ + if (question->type != type) { + return false; + } + if (type == MDNS_TYPE_A || type == MDNS_TYPE_AAAA) { + return true; + } else if (type == MDNS_TYPE_PTR || type == MDNS_TYPE_SDPTR) { + if (question->service && question->proto && question->domain + && !strcasecmp(service->service->service, question->service) + && !strcasecmp(service->service->proto, question->proto) + && !strcasecmp(MDNS_DEFAULT_DOMAIN, question->domain)) { + if (!service->service->instance) { + return true; + } else if (service->service->instance && question->host && !strcasecmp(service->service->instance, question->host)) { + return true; + } + } + } else if (service && (type == MDNS_TYPE_SRV || type == MDNS_TYPE_TXT)) { + const char *name = _mdns_get_service_instance_name(service->service); + if (name && question->host && question->service && question->proto && question->domain + && !strcasecmp(name, question->host) + && !strcasecmp(service->service->service, question->service) + && !strcasecmp(service->service->proto, question->proto) + && !strcasecmp(MDNS_DEFAULT_DOMAIN, question->domain)) { + return true; + } + } + + return false; +} + +/** + * @brief Removes saved question from parsed data + */ +static void _mdns_remove_parsed_question(mdns_parsed_packet_t *parsed_packet, uint16_t type, mdns_srv_item_t *service) +{ + mdns_parsed_question_t *q = parsed_packet->questions; + + if (_mdns_question_matches(q, type, service)) { + parsed_packet->questions = q->next; + mdns_mem_free(q->host); + mdns_mem_free(q->service); + mdns_mem_free(q->proto); + mdns_mem_free(q->domain); + mdns_mem_free(q); + return; + } + + while (q->next) { + mdns_parsed_question_t *p = q->next; + if (_mdns_question_matches(p, type, service)) { + q->next = p->next; + mdns_mem_free(p->host); + mdns_mem_free(p->service); + mdns_mem_free(p->proto); + mdns_mem_free(p->domain); + mdns_mem_free(p); + return; + } + q = q->next; + } +} + +/** + * @brief Get number of items in TXT parsed data + */ +static int _mdns_txt_items_count_get(const uint8_t *data, size_t len) +{ + if (len == 1) { + return 0; + } + + int num_items = 0; + uint16_t i = 0; + size_t partLen = 0; + + while (i < len) { + partLen = data[i++]; + if (!partLen) { + break; + } + if ((i + partLen) > len) { + return -1;//error + } + i += partLen; + num_items++; + } + return num_items; +} + +/** + * @brief Get the length of TXT item's key name + */ +static int _mdns_txt_item_name_get_len(const uint8_t *data, size_t len) +{ + if (*data == '=') { + return -1; + } + for (size_t i = 0; i < len; i++) { + if (data[i] == '=') { + return i; + } + } + return len; +} + +/** + * @brief Create TXT result array from parsed TXT data + */ +static void _mdns_result_txt_create(const uint8_t *data, size_t len, mdns_txt_item_t **out_txt, uint8_t **out_value_len, + size_t *out_count) +{ + *out_txt = NULL; + *out_count = 0; + uint16_t i = 0, y; + size_t partLen = 0; + int num_items = _mdns_txt_items_count_get(data, len); + if (num_items < 0 || num_items > SIZE_MAX / sizeof(mdns_txt_item_t)) { + // Error: num_items is incorrect (or too large to allocate) + return; + } + + if (!num_items) { + return; + } + + mdns_txt_item_t *txt = (mdns_txt_item_t *)mdns_mem_malloc(sizeof(mdns_txt_item_t) * num_items); + if (!txt) { + HOOK_MALLOC_FAILED; + return; + } + uint8_t *txt_value_len = (uint8_t *)mdns_mem_malloc(num_items); + if (!txt_value_len) { + mdns_mem_free(txt); + HOOK_MALLOC_FAILED; + return; + } + memset(txt, 0, sizeof(mdns_txt_item_t) * num_items); + memset(txt_value_len, 0, num_items); + size_t txt_num = 0; + + while (i < len) { + partLen = data[i++]; + if (!partLen) { + break; + } + + if ((i + partLen) > len) { + goto handle_error;//error + } + + int name_len = _mdns_txt_item_name_get_len(data + i, partLen); + if (name_len < 0 || txt_num >= num_items) {//invalid item (no name or more items than expected) + i += partLen; + continue; + } + char *key = (char *)mdns_mem_malloc(name_len + 1); + if (!key) { + HOOK_MALLOC_FAILED; + goto handle_error;//error + } + mdns_txt_item_t *t = &txt[txt_num]; + uint8_t *value_len = &txt_value_len[txt_num]; + txt_num++; + + memcpy(key, data + i, name_len); + key[name_len] = 0; + i += name_len + 1; + t->key = key; + + int new_value_len = partLen - name_len - 1; + if (new_value_len > 0) { + char *value = (char *)mdns_mem_malloc(new_value_len + 1); + if (!value) { + HOOK_MALLOC_FAILED; + goto handle_error;//error + } + memcpy(value, data + i, new_value_len); + value[new_value_len] = 0; + *value_len = new_value_len; + i += new_value_len; + t->value = value; + } else { + t->value = NULL; + } + } + + *out_txt = txt; + *out_count = txt_num; + *out_value_len = txt_value_len; + return; + +handle_error : + for (y = 0; y < txt_num; y++) { + mdns_txt_item_t *t = &txt[y]; + mdns_mem_free((char *)t->key); + mdns_mem_free((char *)t->value); + } + mdns_mem_free(txt_value_len); + mdns_mem_free(txt); +} + +/** + * @brief Duplicate string or return error + */ +static esp_err_t _mdns_strdup_check(char **out, char *in) +{ + if (in && in[0]) { + *out = mdns_mem_strdup(in); + if (!*out) { + return ESP_FAIL; + } + return ESP_OK; + } + *out = NULL; + return ESP_OK; +} + +/** + * @brief main packet parser + * + * @param packet the packet + */ +void mdns_parse_packet(mdns_rx_packet_t *packet) +{ + static mdns_name_t n; + mdns_header_t header; + const uint8_t *data = _mdns_get_packet_data(packet); + size_t len = _mdns_get_packet_len(packet); + const uint8_t *content = data + MDNS_HEAD_LEN; + bool do_not_reply = false; + mdns_search_once_t *search_result = NULL; + mdns_browse_t *browse_result = NULL; + char *browse_result_instance = NULL; + char *browse_result_service = NULL; + char *browse_result_proto = NULL; + mdns_browse_sync_t *out_sync_browse = NULL; + +#ifdef MDNS_ENABLE_DEBUG + _mdns_dbg_printf("\nRX[%lu][%lu]: ", (unsigned long)packet->tcpip_if, (unsigned long)packet->ip_protocol); +#ifdef CONFIG_LWIP_IPV4 + if (packet->src.type == ESP_IPADDR_TYPE_V4) { + _mdns_dbg_printf("From: " IPSTR ":%u, To: " IPSTR ", ", IP2STR(&packet->src.u_addr.ip4), packet->src_port, IP2STR(&packet->dest.u_addr.ip4)); + } +#endif +#ifdef CONFIG_LWIP_IPV6 + if (packet->src.type == ESP_IPADDR_TYPE_V6) { + _mdns_dbg_printf("From: " IPV6STR ":%u, To: " IPV6STR ", ", IPV62STR(packet->src.u_addr.ip6), packet->src_port, IPV62STR(packet->dest.u_addr.ip6)); + } +#endif + mdns_debug_packet(data, len); +#endif + +#ifndef CONFIG_MDNS_SKIP_SUPPRESSING_OWN_QUERIES + // Check if the packet wasn't sent by us +#ifdef CONFIG_LWIP_IPV4 + if (packet->ip_protocol == MDNS_IP_PROTOCOL_V4) { + esp_netif_ip_info_t if_ip_info; + if (esp_netif_get_ip_info(_mdns_get_esp_netif(packet->tcpip_if), &if_ip_info) == ESP_OK && + memcmp(&if_ip_info.ip.addr, &packet->src.u_addr.ip4.addr, sizeof(esp_ip4_addr_t)) == 0) { + return; + } + } +#endif /* CONFIG_LWIP_IPV4 */ +#ifdef CONFIG_LWIP_IPV6 + if (packet->ip_protocol == MDNS_IP_PROTOCOL_V6) { + struct esp_ip6_addr if_ip6; + if (esp_netif_get_ip6_linklocal(_mdns_get_esp_netif(packet->tcpip_if), &if_ip6) == ESP_OK && + memcmp(&if_ip6, &packet->src.u_addr.ip6, sizeof(esp_ip6_addr_t)) == 0) { + return; + } + } +#endif /* CONFIG_LWIP_IPV6 */ +#endif // CONFIG_MDNS_SKIP_SUPPRESSING_OWN_QUERIES + + // Check for the minimum size of mdns packet + if (len <= MDNS_HEAD_ADDITIONAL_OFFSET) { + return; + } + + mdns_parsed_packet_t *parsed_packet = (mdns_parsed_packet_t *)mdns_mem_malloc(sizeof(mdns_parsed_packet_t)); + if (!parsed_packet) { + HOOK_MALLOC_FAILED; + return; + } + memset(parsed_packet, 0, sizeof(mdns_parsed_packet_t)); + + mdns_name_t *name = &n; + memset(name, 0, sizeof(mdns_name_t)); + + header.id = _mdns_read_u16(data, MDNS_HEAD_ID_OFFSET); + header.flags = _mdns_read_u16(data, MDNS_HEAD_FLAGS_OFFSET); + header.questions = _mdns_read_u16(data, MDNS_HEAD_QUESTIONS_OFFSET); + header.answers = _mdns_read_u16(data, MDNS_HEAD_ANSWERS_OFFSET); + header.servers = _mdns_read_u16(data, MDNS_HEAD_SERVERS_OFFSET); + header.additional = _mdns_read_u16(data, MDNS_HEAD_ADDITIONAL_OFFSET); + + if (header.flags == MDNS_FLAGS_QR_AUTHORITATIVE && packet->src_port != MDNS_SERVICE_PORT) { + mdns_mem_free(parsed_packet); + return; + } + + //if we have not set the hostname, we can not answer questions + if (header.questions && !header.answers && _str_null_or_empty(_mdns_server->hostname)) { + mdns_mem_free(parsed_packet); + return; + } + + parsed_packet->tcpip_if = packet->tcpip_if; + parsed_packet->ip_protocol = packet->ip_protocol; + parsed_packet->multicast = packet->multicast; + parsed_packet->authoritative = (header.flags == MDNS_FLAGS_QR_AUTHORITATIVE); + parsed_packet->distributed = header.flags == MDNS_FLAGS_DISTRIBUTED; + parsed_packet->id = header.id; + esp_netif_ip_addr_copy(&parsed_packet->src, &packet->src); + parsed_packet->src_port = packet->src_port; + parsed_packet->records = NULL; + + if (header.questions) { + uint8_t qs = header.questions; + + while (qs--) { + content = _mdns_parse_fqdn(data, content, name, len); + if (!content) { + header.answers = 0; + header.additional = 0; + header.servers = 0; + goto clear_rx_packet;//error + } + + if (content + MDNS_CLASS_OFFSET + 1 >= data + len) { + goto clear_rx_packet; // malformed packet, won't read behind it + } + uint16_t type = _mdns_read_u16(content, MDNS_TYPE_OFFSET); + uint16_t mdns_class = _mdns_read_u16(content, MDNS_CLASS_OFFSET); + bool unicast = !!(mdns_class & 0x8000); + mdns_class &= 0x7FFF; + content = content + 4; + + if (mdns_class != 0x0001 || name->invalid) {//bad class or invalid name for this question entry + continue; + } + + if (_mdns_name_is_discovery(name, type)) { + //service discovery + parsed_packet->discovery = true; + mdns_srv_item_t *a = _mdns_server->services; + while (a) { + mdns_parsed_question_t *question = (mdns_parsed_question_t *)mdns_mem_calloc(1, sizeof(mdns_parsed_question_t)); + if (!question) { + HOOK_MALLOC_FAILED; + goto clear_rx_packet; + } + question->next = parsed_packet->questions; + parsed_packet->questions = question; + + question->unicast = unicast; + question->type = MDNS_TYPE_SDPTR; + question->host = NULL; + question->service = mdns_mem_strdup(a->service->service); + question->proto = mdns_mem_strdup(a->service->proto); + question->domain = mdns_mem_strdup(MDNS_DEFAULT_DOMAIN); + if (!question->service || !question->proto || !question->domain) { + goto clear_rx_packet; + } + a = a->next; + } + continue; + } + if (!_mdns_name_is_ours(name)) { + continue; + } + + if (type == MDNS_TYPE_ANY && !_str_null_or_empty(name->host)) { + parsed_packet->probe = true; + } + + mdns_parsed_question_t *question = (mdns_parsed_question_t *)mdns_mem_calloc(1, sizeof(mdns_parsed_question_t)); + if (!question) { + HOOK_MALLOC_FAILED; + goto clear_rx_packet; + } + question->next = parsed_packet->questions; + parsed_packet->questions = question; + + question->unicast = unicast; + question->type = type; + question->sub = name->sub; + if (_mdns_strdup_check(&(question->host), name->host) + || _mdns_strdup_check(&(question->service), name->service) + || _mdns_strdup_check(&(question->proto), name->proto) + || _mdns_strdup_check(&(question->domain), name->domain)) { + goto clear_rx_packet; + } + } + } + + if (header.questions && !parsed_packet->questions && !parsed_packet->discovery && !header.answers) { + goto clear_rx_packet; + } else if (header.answers || header.servers || header.additional) { + uint16_t recordIndex = 0; + + while (content < (data + len)) { + + content = _mdns_parse_fqdn(data, content, name, len); + if (!content) { + goto clear_rx_packet;//error + } + + if (content + MDNS_LEN_OFFSET + 1 >= data + len) { + goto clear_rx_packet; // malformed packet, won't read behind it + } + uint16_t type = _mdns_read_u16(content, MDNS_TYPE_OFFSET); + uint16_t mdns_class = _mdns_read_u16(content, MDNS_CLASS_OFFSET); + uint32_t ttl = _mdns_read_u32(content, MDNS_TTL_OFFSET); + uint16_t data_len = _mdns_read_u16(content, MDNS_LEN_OFFSET); + const uint8_t *data_ptr = content + MDNS_DATA_OFFSET; + mdns_class &= 0x7FFF; + + content = data_ptr + data_len; + if (content > (data + len) || data_len == 0) { + goto clear_rx_packet; + } + + bool discovery = false; + bool ours = false; + mdns_srv_item_t *service = NULL; + mdns_parsed_record_type_t record_type = MDNS_ANSWER; + + if (recordIndex >= (header.answers + header.servers)) { + record_type = MDNS_EXTRA; + } else if (recordIndex >= (header.answers)) { + record_type = MDNS_NS; + } + recordIndex++; + + if (type == MDNS_TYPE_NSEC || type == MDNS_TYPE_OPT) { + //skip NSEC and OPT + continue; + } + + if (parsed_packet->discovery && _mdns_name_is_discovery(name, type)) { + discovery = true; + } else if (!name->sub && _mdns_name_is_ours(name)) { + ours = true; + if (name->service[0] && name->proto[0]) { + service = _mdns_get_service_item(name->service, name->proto, NULL); + } + } else { + if ((header.flags & MDNS_FLAGS_QUERY_REPSONSE) == 0 || record_type == MDNS_NS) { + //skip this record + continue; + } + search_result = _mdns_search_find_from(_mdns_server->search_once, name, type, packet->tcpip_if, packet->ip_protocol); + browse_result = _mdns_browse_find_from(_mdns_server->browse, name, type, packet->tcpip_if, packet->ip_protocol); + if (browse_result) { + if (!out_sync_browse) { + // will be freed in function `_mdns_browse_sync` + out_sync_browse = (mdns_browse_sync_t *)mdns_mem_malloc(sizeof(mdns_browse_sync_t)); + if (!out_sync_browse) { + HOOK_MALLOC_FAILED; + goto clear_rx_packet; + } + out_sync_browse->browse = browse_result; + out_sync_browse->sync_result = NULL; + } + if (!browse_result_service) { + browse_result_service = (char *)mdns_mem_malloc(MDNS_NAME_BUF_LEN); + if (!browse_result_service) { + HOOK_MALLOC_FAILED; + goto clear_rx_packet; + } + } + memcpy(browse_result_service, browse_result->service, MDNS_NAME_BUF_LEN); + if (!browse_result_proto) { + browse_result_proto = (char *)mdns_mem_malloc(MDNS_NAME_BUF_LEN); + if (!browse_result_proto) { + HOOK_MALLOC_FAILED; + goto clear_rx_packet; + } + } + memcpy(browse_result_proto, browse_result->proto, MDNS_NAME_BUF_LEN); + if (type == MDNS_TYPE_SRV || type == MDNS_TYPE_TXT) { + if (!browse_result_instance) { + browse_result_instance = (char *)mdns_mem_malloc(MDNS_NAME_BUF_LEN); + if (!browse_result_instance) { + HOOK_MALLOC_FAILED; + goto clear_rx_packet; + } + } + memcpy(browse_result_instance, name->host, MDNS_NAME_BUF_LEN); + } + } + } + + if (type == MDNS_TYPE_PTR) { + if (!_mdns_parse_fqdn(data, data_ptr, name, len)) { + continue;//error + } + if (search_result) { + _mdns_search_result_add_ptr(search_result, name->host, name->service, name->proto, + packet->tcpip_if, packet->ip_protocol, ttl); + } else if ((discovery || ours) && !name->sub && _mdns_name_is_ours(name)) { + if (name->host[0]) { + service = _mdns_get_service_item_instance(name->host, name->service, name->proto, NULL); + } else { + service = _mdns_get_service_item(name->service, name->proto, NULL); + } + if (discovery && service) { + _mdns_remove_parsed_question(parsed_packet, MDNS_TYPE_SDPTR, service); + } else if (service && parsed_packet->questions && !parsed_packet->probe) { + _mdns_remove_parsed_question(parsed_packet, type, service); + } else if (service) { + //check if TTL is more than half of the full TTL value (4500) + if (ttl > (MDNS_ANSWER_PTR_TTL / 2)) { + _mdns_remove_scheduled_answer(packet->tcpip_if, packet->ip_protocol, type, service); + } + } + if (service) { + mdns_parsed_record_t *record = mdns_mem_malloc(sizeof(mdns_parsed_record_t)); + if (!record) { + HOOK_MALLOC_FAILED; + goto clear_rx_packet; + } + record->next = parsed_packet->records; + parsed_packet->records = record; + record->type = MDNS_TYPE_PTR; + record->record_type = MDNS_ANSWER; + record->ttl = ttl; + record->host = NULL; + record->service = NULL; + record->proto = NULL; + if (name->host[0]) { + record->host = mdns_mem_malloc(MDNS_NAME_BUF_LEN); + if (!record->host) { + HOOK_MALLOC_FAILED; + goto clear_rx_packet; + } + memcpy(record->host, name->host, MDNS_NAME_BUF_LEN); + } + if (name->service[0]) { + record->service = mdns_mem_malloc(MDNS_NAME_BUF_LEN); + if (!record->service) { + HOOK_MALLOC_FAILED; + goto clear_rx_packet; + } + memcpy(record->service, name->service, MDNS_NAME_BUF_LEN); + } + if (name->proto[0]) { + record->proto = mdns_mem_malloc(MDNS_NAME_BUF_LEN); + if (!record->proto) { + HOOK_MALLOC_FAILED; + goto clear_rx_packet; + } + memcpy(record->proto, name->proto, MDNS_NAME_BUF_LEN); + } + } + } + } else if (type == MDNS_TYPE_SRV) { + mdns_result_t *result = NULL; + if (search_result && search_result->type == MDNS_TYPE_PTR) { + result = search_result->result; + while (result) { + if (_mdns_get_esp_netif(packet->tcpip_if) == result->esp_netif + && packet->ip_protocol == result->ip_protocol + && result->instance_name && !strcmp(name->host, result->instance_name)) { + break; + } + result = result->next; + } + if (!result) { + result = _mdns_search_result_add_ptr(search_result, name->host, name->service, name->proto, + packet->tcpip_if, packet->ip_protocol, ttl); + if (!result) { + continue;//error + } + } + } + bool is_selfhosted = _mdns_name_is_selfhosted(name); + if (!_mdns_parse_fqdn(data, data_ptr + MDNS_SRV_FQDN_OFFSET, name, len)) { + continue;//error + } + if (data_ptr + MDNS_SRV_PORT_OFFSET + 1 >= data + len) { + goto clear_rx_packet; // malformed packet, won't read behind it + } + uint16_t priority = _mdns_read_u16(data_ptr, MDNS_SRV_PRIORITY_OFFSET); + uint16_t weight = _mdns_read_u16(data_ptr, MDNS_SRV_WEIGHT_OFFSET); + uint16_t port = _mdns_read_u16(data_ptr, MDNS_SRV_PORT_OFFSET); + + if (browse_result) { + _mdns_browse_result_add_srv(browse_result, name->host, browse_result_instance, browse_result_service, + browse_result_proto, port, packet->tcpip_if, packet->ip_protocol, ttl, out_sync_browse); + } + if (search_result) { + if (search_result->type == MDNS_TYPE_PTR) { + if (!result->hostname) { // assign host/port for this entry only if not previously set + result->port = port; + result->hostname = mdns_mem_strdup(name->host); + } + } else { + _mdns_search_result_add_srv(search_result, name->host, port, packet->tcpip_if, packet->ip_protocol, ttl); + } + } else if (ours) { + if (parsed_packet->questions && !parsed_packet->probe) { + _mdns_remove_parsed_question(parsed_packet, type, service); + continue; + } else if (parsed_packet->distributed) { + _mdns_remove_scheduled_answer(packet->tcpip_if, packet->ip_protocol, type, service); + continue; + } + if (!is_selfhosted) { + continue; + } + //detect collision (-1=won, 0=none, 1=lost) + int col = 0; + if (mdns_class > 1) { + col = 1; + } else if (!mdns_class) { + col = -1; + } else if (service) { // only detect srv collision if service existed + col = _mdns_check_srv_collision(service->service, priority, weight, port, name->host, name->domain); + } + if (service && col && (parsed_packet->probe || parsed_packet->authoritative)) { + if (col > 0 || !port) { + do_not_reply = true; + if (_mdns_server->interfaces[packet->tcpip_if].pcbs[packet->ip_protocol].probe_running) { + _mdns_server->interfaces[packet->tcpip_if].pcbs[packet->ip_protocol].failed_probes++; + if (!_str_null_or_empty(service->service->instance)) { + char *new_instance = _mdns_mangle_name((char *)service->service->instance); + if (new_instance) { + mdns_mem_free((char *)service->service->instance); + service->service->instance = new_instance; + } + _mdns_probe_all_pcbs(&service, 1, false, false); + } else if (!_str_null_or_empty(_mdns_server->instance)) { + char *new_instance = _mdns_mangle_name((char *)_mdns_server->instance); + if (new_instance) { + mdns_mem_free((char *)_mdns_server->instance); + _mdns_server->instance = new_instance; + } + _mdns_restart_all_pcbs_no_instance(); + } else { + char *new_host = _mdns_mangle_name((char *)_mdns_server->hostname); + if (new_host) { + _mdns_remap_self_service_hostname(_mdns_server->hostname, new_host); + mdns_mem_free((char *)_mdns_server->hostname); + _mdns_server->hostname = new_host; + _mdns_self_host.hostname = new_host; + } + _mdns_restart_all_pcbs(); + } + } else if (service) { + _mdns_pcb_send_bye(packet->tcpip_if, packet->ip_protocol, &service, 1, false); + _mdns_init_pcb_probe(packet->tcpip_if, packet->ip_protocol, &service, 1, false); + } + } + } else if (ttl > 60 && !col && !parsed_packet->authoritative && !parsed_packet->probe && !parsed_packet->questions) { + _mdns_remove_scheduled_answer(packet->tcpip_if, packet->ip_protocol, type, service); + } + } + } else if (type == MDNS_TYPE_TXT) { + mdns_txt_item_t *txt = NULL; + uint8_t *txt_value_len = NULL; + size_t txt_count = 0; + + mdns_result_t *result = NULL; + if (browse_result) { + _mdns_result_txt_create(data_ptr, data_len, &txt, &txt_value_len, &txt_count); + _mdns_browse_result_add_txt(browse_result, browse_result_instance, browse_result_service, browse_result_proto, + txt, txt_value_len, txt_count, packet->tcpip_if, packet->ip_protocol, ttl, out_sync_browse); + } + if (search_result) { + if (search_result->type == MDNS_TYPE_PTR) { + result = search_result->result; + while (result) { + if (_mdns_get_esp_netif(packet->tcpip_if) == result->esp_netif + && packet->ip_protocol == result->ip_protocol + && result->instance_name && !strcmp(name->host, result->instance_name)) { + break; + } + result = result->next; + } + if (!result) { + result = _mdns_search_result_add_ptr(search_result, name->host, name->service, name->proto, + packet->tcpip_if, packet->ip_protocol, ttl); + if (!result) { + continue;//error + } + } + if (!result->txt) { + _mdns_result_txt_create(data_ptr, data_len, &txt, &txt_value_len, &txt_count); + if (txt_count) { + result->txt = txt; + result->txt_count = txt_count; + result->txt_value_len = txt_value_len; + } + } + } else { + _mdns_result_txt_create(data_ptr, data_len, &txt, &txt_value_len, &txt_count); + if (txt_count) { + _mdns_search_result_add_txt(search_result, txt, txt_value_len, txt_count, packet->tcpip_if, packet->ip_protocol, ttl); + } + } + } else if (ours) { + if (parsed_packet->questions && !parsed_packet->probe && service) { + _mdns_remove_parsed_question(parsed_packet, type, service); + continue; + } + if (!_mdns_name_is_selfhosted(name)) { + continue; + } + //detect collision (-1=won, 0=none, 1=lost) + int col = 0; + if (mdns_class > 1) { + col = 1; + } else if (!mdns_class) { + col = -1; + } else if (service) { // only detect txt collision if service existed + col = _mdns_check_txt_collision(service->service, data_ptr, data_len); + } + if (col && !_mdns_server->interfaces[packet->tcpip_if].pcbs[packet->ip_protocol].probe_running && service) { + do_not_reply = true; + _mdns_init_pcb_probe(packet->tcpip_if, packet->ip_protocol, &service, 1, true); + } else if (ttl > (MDNS_ANSWER_TXT_TTL / 2) && !col && !parsed_packet->authoritative && !parsed_packet->probe && !parsed_packet->questions && !_mdns_server->interfaces[packet->tcpip_if].pcbs[packet->ip_protocol].probe_running) { + _mdns_remove_scheduled_answer(packet->tcpip_if, packet->ip_protocol, type, service); + } + } + + } +#ifdef CONFIG_LWIP_IPV6 + else if (type == MDNS_TYPE_AAAA) {//ipv6 + esp_ip_addr_t ip6; + ip6.type = ESP_IPADDR_TYPE_V6; + memcpy(ip6.u_addr.ip6.addr, data_ptr, MDNS_ANSWER_AAAA_SIZE); + if (browse_result) { + _mdns_browse_result_add_ip(browse_result, name->host, &ip6, packet->tcpip_if, packet->ip_protocol, ttl, out_sync_browse); + } + if (search_result) { + //check for more applicable searches (PTR & A/AAAA at the same time) + while (search_result) { + _mdns_search_result_add_ip(search_result, name->host, &ip6, packet->tcpip_if, packet->ip_protocol, ttl); + search_result = _mdns_search_find_from(search_result->next, name, type, packet->tcpip_if, packet->ip_protocol); + } + } else if (ours) { + if (parsed_packet->questions && !parsed_packet->probe) { + _mdns_remove_parsed_question(parsed_packet, type, NULL); + continue; + } + if (!_mdns_name_is_selfhosted(name)) { + continue; + } + //detect collision (-1=won, 0=none, 1=lost) + int col = 0; + if (mdns_class > 1) { + col = 1; + } else if (!mdns_class) { + col = -1; + } else { + col = _mdns_check_aaaa_collision(&(ip6.u_addr.ip6), packet->tcpip_if); + } + if (col == 2) { + goto clear_rx_packet; + } else if (col == 1) { + do_not_reply = true; + if (_mdns_server->interfaces[packet->tcpip_if].pcbs[packet->ip_protocol].probe_running) { + if (col && (parsed_packet->probe || parsed_packet->authoritative)) { + _mdns_server->interfaces[packet->tcpip_if].pcbs[packet->ip_protocol].failed_probes++; + char *new_host = _mdns_mangle_name((char *)_mdns_server->hostname); + if (new_host) { + _mdns_remap_self_service_hostname(_mdns_server->hostname, new_host); + mdns_mem_free((char *)_mdns_server->hostname); + _mdns_server->hostname = new_host; + _mdns_self_host.hostname = new_host; + } + _mdns_restart_all_pcbs(); + } + } else { + _mdns_init_pcb_probe(packet->tcpip_if, packet->ip_protocol, NULL, 0, true); + } + } else if (ttl > 60 && !col && !parsed_packet->authoritative && !parsed_packet->probe && !parsed_packet->questions && !_mdns_server->interfaces[packet->tcpip_if].pcbs[packet->ip_protocol].probe_running) { + _mdns_remove_scheduled_answer(packet->tcpip_if, packet->ip_protocol, type, NULL); + } + } + + } +#endif /* CONFIG_LWIP_IPV6 */ +#ifdef CONFIG_LWIP_IPV4 + else if (type == MDNS_TYPE_A) { + esp_ip_addr_t ip; + ip.type = ESP_IPADDR_TYPE_V4; + memcpy(&(ip.u_addr.ip4.addr), data_ptr, 4); + if (browse_result) { + _mdns_browse_result_add_ip(browse_result, name->host, &ip, packet->tcpip_if, packet->ip_protocol, ttl, out_sync_browse); + } + if (search_result) { + //check for more applicable searches (PTR & A/AAAA at the same time) + while (search_result) { + _mdns_search_result_add_ip(search_result, name->host, &ip, packet->tcpip_if, packet->ip_protocol, ttl); + search_result = _mdns_search_find_from(search_result->next, name, type, packet->tcpip_if, packet->ip_protocol); + } + } else if (ours) { + if (parsed_packet->questions && !parsed_packet->probe) { + _mdns_remove_parsed_question(parsed_packet, type, NULL); + continue; + } + if (!_mdns_name_is_selfhosted(name)) { + continue; + } + //detect collision (-1=won, 0=none, 1=lost) + int col = 0; + if (mdns_class > 1) { + col = 1; + } else if (!mdns_class) { + col = -1; + } else { + col = _mdns_check_a_collision(&(ip.u_addr.ip4), packet->tcpip_if); + } + if (col == 2) { + goto clear_rx_packet; + } else if (col == 1) { + do_not_reply = true; + if (_mdns_server->interfaces[packet->tcpip_if].pcbs[packet->ip_protocol].probe_running) { + if (col && (parsed_packet->probe || parsed_packet->authoritative)) { + _mdns_server->interfaces[packet->tcpip_if].pcbs[packet->ip_protocol].failed_probes++; + char *new_host = _mdns_mangle_name((char *)_mdns_server->hostname); + if (new_host) { + _mdns_remap_self_service_hostname(_mdns_server->hostname, new_host); + mdns_mem_free((char *)_mdns_server->hostname); + _mdns_server->hostname = new_host; + _mdns_self_host.hostname = new_host; + } + _mdns_restart_all_pcbs(); + } + } else { + _mdns_init_pcb_probe(packet->tcpip_if, packet->ip_protocol, NULL, 0, true); + } + } else if (ttl > 60 && !col && !parsed_packet->authoritative && !parsed_packet->probe && !parsed_packet->questions && !_mdns_server->interfaces[packet->tcpip_if].pcbs[packet->ip_protocol].probe_running) { + _mdns_remove_scheduled_answer(packet->tcpip_if, packet->ip_protocol, type, NULL); + } + } + + } +#endif /* CONFIG_LWIP_IPV4 */ + } + //end while + if (parsed_packet->authoritative) { + _mdns_search_finish_done(); + } + } + + if (!do_not_reply && _mdns_server->interfaces[packet->tcpip_if].pcbs[packet->ip_protocol].state > PCB_PROBE_3 && (parsed_packet->questions || parsed_packet->discovery)) { + _mdns_create_answer_from_parsed_packet(parsed_packet); + } + if (out_sync_browse) { +#ifdef MDNS_ENABLE_DEBUG + _mdns_dbg_printf("Browse %s%s total result:", out_sync_browse->browse->service, out_sync_browse->browse->proto); + debug_printf_browse_result_all(out_sync_browse->browse->result); +#endif // MDNS_ENABLE_DEBUG + if (out_sync_browse->sync_result) { +#ifdef MDNS_ENABLE_DEBUG + _mdns_dbg_printf("Changed result:"); + debug_printf_browse_result_all(out_sync_browse->sync_result->result); +#endif // MDNS_ENABLE_DEBUG + _mdns_sync_browse_action(ACTION_BROWSE_SYNC, out_sync_browse); + } else { + mdns_mem_free(out_sync_browse); + } + out_sync_browse = NULL; + } + +clear_rx_packet: + while (parsed_packet->questions) { + mdns_parsed_question_t *question = parsed_packet->questions; + parsed_packet->questions = parsed_packet->questions->next; + if (question->host) { + mdns_mem_free(question->host); + } + if (question->service) { + mdns_mem_free(question->service); + } + if (question->proto) { + mdns_mem_free(question->proto); + } + if (question->domain) { + mdns_mem_free(question->domain); + } + mdns_mem_free(question); + } + while (parsed_packet->records) { + mdns_parsed_record_t *record = parsed_packet->records; + parsed_packet->records = parsed_packet->records->next; + if (record->host) { + mdns_mem_free(record->host); + } + if (record->service) { + mdns_mem_free(record->service); + } + if (record->proto) { + mdns_mem_free(record->proto); + } + record->next = NULL; + mdns_mem_free(record); + } + mdns_mem_free(parsed_packet); + mdns_mem_free(browse_result_instance); + mdns_mem_free(browse_result_service); + mdns_mem_free(browse_result_proto); + mdns_mem_free(out_sync_browse); +} + +/** + * @brief Enable mDNS interface + */ +void _mdns_enable_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +{ + if (!mdns_is_netif_ready(tcpip_if, ip_protocol)) { + if (_mdns_pcb_init(tcpip_if, ip_protocol)) { + _mdns_server->interfaces[tcpip_if].pcbs[ip_protocol].failed_probes = 0; + return; + } + } + _mdns_restart_pcb(tcpip_if, ip_protocol); +} + +/** + * @brief Disable mDNS interface + */ +void _mdns_disable_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +{ + _mdns_clean_netif_ptr(tcpip_if); + + if (mdns_is_netif_ready(tcpip_if, ip_protocol)) { + _mdns_clear_pcb_tx_queue_head(tcpip_if, ip_protocol); + mdns_pcb_deinit_local(tcpip_if, ip_protocol); + mdns_if_t other_if = _mdns_get_other_if(tcpip_if); + if (other_if != MDNS_MAX_INTERFACES && _mdns_server->interfaces[other_if].pcbs[ip_protocol].state == PCB_DUP) { + _mdns_server->interfaces[other_if].pcbs[ip_protocol].state = PCB_OFF; + _mdns_enable_pcb(other_if, ip_protocol); + } + } + _mdns_server->interfaces[tcpip_if].pcbs[ip_protocol].state = PCB_OFF; +} + +#ifdef CONFIG_MDNS_RESPOND_REVERSE_QUERIES +static inline char nibble_to_hex(int var) +{ + return var > 9 ? var - 10 + 'a' : var + '0'; +} +#endif + +/** + * @brief Performs interface changes based on system events or custom commands + */ +static void perform_event_action(mdns_if_t mdns_if, mdns_event_actions_t action) +{ + if (!_mdns_server || mdns_if >= MDNS_MAX_INTERFACES) { + return; + } + if (action & MDNS_EVENT_ENABLE_IP4) { + _mdns_enable_pcb(mdns_if, MDNS_IP_PROTOCOL_V4); + } + if (action & MDNS_EVENT_ENABLE_IP6) { + _mdns_enable_pcb(mdns_if, MDNS_IP_PROTOCOL_V6); + } + if (action & MDNS_EVENT_DISABLE_IP4) { + _mdns_disable_pcb(mdns_if, MDNS_IP_PROTOCOL_V4); + } + if (action & MDNS_EVENT_DISABLE_IP6) { + _mdns_disable_pcb(mdns_if, MDNS_IP_PROTOCOL_V6); + } + if (action & MDNS_EVENT_ANNOUNCE_IP4) { + _mdns_announce_pcb(mdns_if, MDNS_IP_PROTOCOL_V4, NULL, 0, true); + } + if (action & MDNS_EVENT_ANNOUNCE_IP6) { + _mdns_announce_pcb(mdns_if, MDNS_IP_PROTOCOL_V6, NULL, 0, true); + } + +#ifdef CONFIG_MDNS_RESPOND_REVERSE_QUERIES +#ifdef CONFIG_LWIP_IPV4 + if (action & MDNS_EVENT_IP4_REVERSE_LOOKUP) { + esp_netif_ip_info_t if_ip_info; + if (esp_netif_get_ip_info(_mdns_get_esp_netif(mdns_if), &if_ip_info) == ESP_OK) { + esp_ip4_addr_t *ip = &if_ip_info.ip; + char *reverse_query_name = NULL; + if (asprintf(&reverse_query_name, "%d.%d.%d.%d.in-addr", + esp_ip4_addr4_16(ip), esp_ip4_addr3_16(ip), + esp_ip4_addr2_16(ip), esp_ip4_addr1_16(ip)) > 0 && reverse_query_name) { + ESP_LOGD(TAG, "Registered reverse query: %s.arpa", reverse_query_name); + _mdns_delegate_hostname_add(reverse_query_name, NULL); + } + } + } +#endif /* CONFIG_LWIP_IPV4 */ +#ifdef CONFIG_LWIP_IPV6 + if (action & MDNS_EVENT_IP6_REVERSE_LOOKUP) { + esp_ip6_addr_t addr6; + if (!esp_netif_get_ip6_linklocal(_mdns_get_esp_netif(mdns_if), &addr6) && !_ipv6_address_is_zero(addr6)) { + uint8_t *paddr = (uint8_t *)&addr6.addr; + const char sub[] = "ip6"; + const size_t query_name_size = 4 * sizeof(addr6.addr) /* (2 nibbles + 2 dots)/per byte of IP address */ + sizeof(sub); + char *reverse_query_name = mdns_mem_malloc(query_name_size); + if (reverse_query_name) { + char *ptr = &reverse_query_name[query_name_size]; // point to the end + memcpy(ptr - sizeof(sub), sub, sizeof(sub)); // copy the IP sub-domain + ptr -= sizeof(sub) + 1; // move before the sub-domain + while (reverse_query_name < ptr) { // continue populating reverse query from the end + *ptr-- = '.'; // nibble by nibble, until we reach the beginning + *ptr-- = nibble_to_hex(((*paddr) >> 4) & 0x0F); + *ptr-- = '.'; + *ptr-- = nibble_to_hex((*paddr) & 0x0F); + paddr++; + } + ESP_LOGD(TAG, "Registered reverse query: %s.arpa", reverse_query_name); + _mdns_delegate_hostname_add(reverse_query_name, NULL); + } + } + } +#endif /* CONFIG_LWIP_IPV6 */ +#endif /* CONFIG_MDNS_RESPOND_REVERSE_QUERIES */ +} + +/** + * @brief Dispatch interface changes based on system events + */ +static inline void post_mdns_disable_pcb(mdns_predef_if_t preset_if, mdns_ip_protocol_t protocol) +{ + mdns_post_custom_action_tcpip_if(mdns_if_from_preset_if(preset_if), protocol == MDNS_IP_PROTOCOL_V4 ? MDNS_EVENT_DISABLE_IP4 : MDNS_EVENT_DISABLE_IP6); +} + +static inline void post_mdns_enable_pcb(mdns_predef_if_t preset_if, mdns_ip_protocol_t protocol) +{ + mdns_post_custom_action_tcpip_if(mdns_if_from_preset_if(preset_if), protocol == MDNS_IP_PROTOCOL_V4 ? MDNS_EVENT_ENABLE_IP4 : MDNS_EVENT_ENABLE_IP6); +} + +static inline void post_mdns_announce_pcb(mdns_predef_if_t preset_if, mdns_ip_protocol_t protocol) +{ + mdns_post_custom_action_tcpip_if(mdns_if_from_preset_if(preset_if), protocol == MDNS_IP_PROTOCOL_V4 ? MDNS_EVENT_ANNOUNCE_IP4 : MDNS_EVENT_ANNOUNCE_IP6); +} + +#if CONFIG_MDNS_PREDEF_NETIF_STA || CONFIG_MDNS_PREDEF_NETIF_AP || CONFIG_MDNS_PREDEF_NETIF_ETH +void mdns_preset_if_handle_system_event(void *arg, esp_event_base_t event_base, + int32_t event_id, void *event_data) +{ + if (!_mdns_server) { + return; + } + + esp_netif_dhcp_status_t dcst; +#if MDNS_ESP_WIFI_ENABLED && (CONFIG_MDNS_PREDEF_NETIF_STA || CONFIG_MDNS_PREDEF_NETIF_AP) + if (event_base == WIFI_EVENT) { + switch (event_id) { + case WIFI_EVENT_STA_CONNECTED: + if (!esp_netif_dhcpc_get_status(esp_netif_from_preset_if(MDNS_IF_STA), &dcst)) { + if (dcst == ESP_NETIF_DHCP_STOPPED) { + post_mdns_enable_pcb(MDNS_IF_STA, MDNS_IP_PROTOCOL_V4); + } + } + break; + case WIFI_EVENT_STA_DISCONNECTED: + post_mdns_disable_pcb(MDNS_IF_STA, MDNS_IP_PROTOCOL_V4); + post_mdns_disable_pcb(MDNS_IF_STA, MDNS_IP_PROTOCOL_V6); + break; + case WIFI_EVENT_AP_START: + post_mdns_enable_pcb(MDNS_IF_AP, MDNS_IP_PROTOCOL_V4); + break; + case WIFI_EVENT_AP_STOP: + post_mdns_disable_pcb(MDNS_IF_AP, MDNS_IP_PROTOCOL_V4); + post_mdns_disable_pcb(MDNS_IF_AP, MDNS_IP_PROTOCOL_V6); + break; + default: + break; + } + } else +#endif +#if CONFIG_ETH_ENABLED && CONFIG_MDNS_PREDEF_NETIF_ETH + if (event_base == ETH_EVENT) { + switch (event_id) { + case ETHERNET_EVENT_CONNECTED: + if (!esp_netif_dhcpc_get_status(esp_netif_from_preset_if(MDNS_IF_ETH), &dcst)) { + if (dcst == ESP_NETIF_DHCP_STOPPED) { + post_mdns_enable_pcb(MDNS_IF_ETH, MDNS_IP_PROTOCOL_V4); + } + } + break; + case ETHERNET_EVENT_DISCONNECTED: + post_mdns_disable_pcb(MDNS_IF_ETH, MDNS_IP_PROTOCOL_V4); + post_mdns_disable_pcb(MDNS_IF_ETH, MDNS_IP_PROTOCOL_V6); + break; + default: + break; + } + } else +#endif + if (event_base == IP_EVENT) { + switch (event_id) { + case IP_EVENT_STA_GOT_IP: + post_mdns_enable_pcb(MDNS_IF_STA, MDNS_IP_PROTOCOL_V4); + post_mdns_announce_pcb(MDNS_IF_STA, MDNS_IP_PROTOCOL_V6); + break; +#if CONFIG_ETH_ENABLED && CONFIG_MDNS_PREDEF_NETIF_ETH + case IP_EVENT_ETH_GOT_IP: + post_mdns_enable_pcb(MDNS_IF_ETH, MDNS_IP_PROTOCOL_V4); + break; +#endif + case IP_EVENT_GOT_IP6: { + ip_event_got_ip6_t *event = (ip_event_got_ip6_t *) event_data; + mdns_if_t mdns_if = _mdns_get_if_from_esp_netif(event->esp_netif); + if (mdns_if >= MDNS_MAX_INTERFACES) { + return; + } + post_mdns_enable_pcb(mdns_if, MDNS_IP_PROTOCOL_V6); + post_mdns_announce_pcb(mdns_if, MDNS_IP_PROTOCOL_V4); + mdns_browse_t *browse = _mdns_server->browse; + while (browse) { + _mdns_browse_send(browse, mdns_if); + browse = browse->next; + } + } + break; + default: + break; + } + } +} +#endif /* CONFIG_MDNS_PREDEF_NETIF_STA || CONFIG_MDNS_PREDEF_NETIF_AP || CONFIG_MDNS_PREDEF_NETIF_ETH */ + +/* + * MDNS Search + * */ + +/** + * @brief Free search structure (except the results) + */ +static void _mdns_search_free(mdns_search_once_t *search) +{ + mdns_mem_free(search->instance); + mdns_mem_free(search->service); + mdns_mem_free(search->proto); + vSemaphoreDelete(search->done_semaphore); + mdns_mem_free(search); +} + +/** + * @brief Allocate new search structure + */ +static mdns_search_once_t *_mdns_search_init(const char *name, const char *service, const char *proto, uint16_t type, bool unicast, + uint32_t timeout, uint8_t max_results, mdns_query_notify_t notifier) +{ + mdns_search_once_t *search = (mdns_search_once_t *)mdns_mem_malloc(sizeof(mdns_search_once_t)); + if (!search) { + HOOK_MALLOC_FAILED; + return NULL; + } + memset(search, 0, sizeof(mdns_search_once_t)); + + search->done_semaphore = xSemaphoreCreateBinary(); + if (!search->done_semaphore) { + mdns_mem_free(search); + return NULL; + } + + if (!_str_null_or_empty(name)) { + search->instance = mdns_mem_strndup(name, MDNS_NAME_BUF_LEN - 1); + if (!search->instance) { + _mdns_search_free(search); + return NULL; + } + } + + if (!_str_null_or_empty(service)) { + search->service = mdns_mem_strndup(service, MDNS_NAME_BUF_LEN - 1); + if (!search->service) { + _mdns_search_free(search); + return NULL; + } + } + + if (!_str_null_or_empty(proto)) { + search->proto = mdns_mem_strndup(proto, MDNS_NAME_BUF_LEN - 1); + if (!search->proto) { + _mdns_search_free(search); + return NULL; + } + } + + search->type = type; + search->unicast = unicast; + search->timeout = timeout; + search->num_results = 0; + search->max_results = max_results; + search->result = NULL; + search->state = SEARCH_INIT; + search->sent_at = 0; + search->started_at = xTaskGetTickCount() * portTICK_PERIOD_MS; + search->notifier = notifier; + search->next = NULL; + + return search; +} + +/** + * @brief Mark search as finished and remove it from search chain + */ +static void _mdns_search_finish(mdns_search_once_t *search) +{ + search->state = SEARCH_OFF; + queueDetach(mdns_search_once_t, _mdns_server->search_once, search); + if (search->notifier) { + search->notifier(search); + } + xSemaphoreGive(search->done_semaphore); +} + +/** + * @brief Add new search to the search chain + */ +static void _mdns_search_add(mdns_search_once_t *search) +{ + search->next = _mdns_server->search_once; + _mdns_server->search_once = search; +} + +/** + * @brief Called from parser to finish any searches that have reached maximum results + */ +static void _mdns_search_finish_done(void) +{ + mdns_search_once_t *search = _mdns_server->search_once; + mdns_search_once_t *s = NULL; + while (search) { + s = search; + search = search->next; + if (s->max_results && s->num_results >= s->max_results) { + _mdns_search_finish(s); + } + } +} + +/** + * @brief Create linked IP (copy) from parsed one + */ +static mdns_ip_addr_t *_mdns_result_addr_create_ip(esp_ip_addr_t *ip) +{ + mdns_ip_addr_t *a = (mdns_ip_addr_t *)mdns_mem_malloc(sizeof(mdns_ip_addr_t)); + if (!a) { + HOOK_MALLOC_FAILED; + return NULL; + } + memset(a, 0, sizeof(mdns_ip_addr_t)); + a->addr.type = ip->type; + if (ip->type == ESP_IPADDR_TYPE_V6) { + memcpy(a->addr.u_addr.ip6.addr, ip->u_addr.ip6.addr, 16); + } else { + a->addr.u_addr.ip4.addr = ip->u_addr.ip4.addr; + } + return a; +} + +static inline void _mdns_result_update_ttl(mdns_result_t *r, uint32_t ttl) +{ + r->ttl = r->ttl < ttl ? r->ttl : ttl; +} + +/** + * @brief Chain new IP to search result + */ +static void _mdns_result_add_ip(mdns_result_t *r, esp_ip_addr_t *ip) +{ + mdns_ip_addr_t *a = r->addr; + while (a) { + if (a->addr.type == ip->type) { +#ifdef CONFIG_LWIP_IPV4 + if (a->addr.type == ESP_IPADDR_TYPE_V4 && a->addr.u_addr.ip4.addr == ip->u_addr.ip4.addr) { + return; + } +#endif +#ifdef CONFIG_LWIP_IPV6 + if (a->addr.type == ESP_IPADDR_TYPE_V6 && !memcmp(a->addr.u_addr.ip6.addr, ip->u_addr.ip6.addr, 16)) { + return; + } +#endif + } + a = a->next; + } + a = _mdns_result_addr_create_ip(ip); + if (!a) { + return; + } + a->next = r->addr; + r->addr = a; +} + +/** + * @brief Called from parser to add A/AAAA data to search result + */ +static void _mdns_search_result_add_ip(mdns_search_once_t *search, const char *hostname, esp_ip_addr_t *ip, + mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint32_t ttl) +{ + mdns_result_t *r = NULL; + mdns_ip_addr_t *a = NULL; + + if ((search->type == MDNS_TYPE_A && ip->type == ESP_IPADDR_TYPE_V4) + || (search->type == MDNS_TYPE_AAAA && ip->type == ESP_IPADDR_TYPE_V6) + || search->type == MDNS_TYPE_ANY) { + r = search->result; + while (r) { + if (r->esp_netif == _mdns_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol) { + _mdns_result_add_ip(r, ip); + _mdns_result_update_ttl(r, ttl); + return; + } + r = r->next; + } + if (!search->max_results || search->num_results < search->max_results) { + r = (mdns_result_t *)mdns_mem_malloc(sizeof(mdns_result_t)); + if (!r) { + HOOK_MALLOC_FAILED; + return; + } + + memset(r, 0, sizeof(mdns_result_t)); + + a = _mdns_result_addr_create_ip(ip); + if (!a) { + mdns_mem_free(r); + return; + } + a->next = r->addr; + r->hostname = mdns_mem_strdup(hostname); + r->addr = a; + r->esp_netif = _mdns_get_esp_netif(tcpip_if); + r->ip_protocol = ip_protocol; + r->next = search->result; + r->ttl = ttl; + search->result = r; + search->num_results++; + } + } else if (search->type == MDNS_TYPE_PTR || search->type == MDNS_TYPE_SRV) { + r = search->result; + while (r) { + if (r->esp_netif == _mdns_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol && !_str_null_or_empty(r->hostname) && !strcasecmp(hostname, r->hostname)) { + _mdns_result_add_ip(r, ip); + _mdns_result_update_ttl(r, ttl); + break; + } + r = r->next; + } + } +} + +/** + * @brief Called from parser to add PTR data to search result + */ +static mdns_result_t *_mdns_search_result_add_ptr(mdns_search_once_t *search, const char *instance, + const char *service_type, const char *proto, mdns_if_t tcpip_if, + mdns_ip_protocol_t ip_protocol, uint32_t ttl) +{ + mdns_result_t *r = search->result; + while (r) { + if (r->esp_netif == _mdns_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol && !_str_null_or_empty(r->instance_name) && !strcasecmp(instance, r->instance_name)) { + _mdns_result_update_ttl(r, ttl); + return r; + } + r = r->next; + } + if (!search->max_results || search->num_results < search->max_results) { + r = (mdns_result_t *)mdns_mem_malloc(sizeof(mdns_result_t)); + if (!r) { + HOOK_MALLOC_FAILED; + return NULL; + } + + memset(r, 0, sizeof(mdns_result_t)); + r->instance_name = mdns_mem_strdup(instance); + r->service_type = mdns_mem_strdup(service_type); + r->proto = mdns_mem_strdup(proto); + if (!r->instance_name) { + mdns_mem_free(r); + return NULL; + } + + r->esp_netif = _mdns_get_esp_netif(tcpip_if); + r->ip_protocol = ip_protocol; + r->ttl = ttl; + r->next = search->result; + search->result = r; + search->num_results++; + return r; + } + return NULL; +} + +/** + * @brief Called from parser to add SRV data to search result + */ +static void _mdns_search_result_add_srv(mdns_search_once_t *search, const char *hostname, uint16_t port, + mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint32_t ttl) +{ + mdns_result_t *r = search->result; + while (r) { + if (r->esp_netif == _mdns_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol && !_str_null_or_empty(r->hostname) && !strcasecmp(hostname, r->hostname)) { + _mdns_result_update_ttl(r, ttl); + return; + } + r = r->next; + } + if (!search->max_results || search->num_results < search->max_results) { + r = (mdns_result_t *)mdns_mem_malloc(sizeof(mdns_result_t)); + if (!r) { + HOOK_MALLOC_FAILED; + return; + } + + memset(r, 0, sizeof(mdns_result_t)); + r->hostname = mdns_mem_strdup(hostname); + if (!r->hostname) { + mdns_mem_free(r); + return; + } + if (search->instance) { + r->instance_name = mdns_mem_strdup(search->instance); + } + r->service_type = mdns_mem_strdup(search->service); + r->proto = mdns_mem_strdup(search->proto); + r->port = port; + r->esp_netif = _mdns_get_esp_netif(tcpip_if); + r->ip_protocol = ip_protocol; + r->ttl = ttl; + r->next = search->result; + search->result = r; + search->num_results++; + } +} + +/** + * @brief Called from parser to add TXT data to search result + */ +static void _mdns_search_result_add_txt(mdns_search_once_t *search, mdns_txt_item_t *txt, uint8_t *txt_value_len, + size_t txt_count, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, + uint32_t ttl) +{ + mdns_result_t *r = search->result; + while (r) { + if (r->esp_netif == _mdns_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol) { + if (r->txt) { + goto free_txt; + } + r->txt = txt; + r->txt_value_len = txt_value_len; + r->txt_count = txt_count; + _mdns_result_update_ttl(r, ttl); + return; + } + r = r->next; + } + if (!search->max_results || search->num_results < search->max_results) { + r = (mdns_result_t *)mdns_mem_malloc(sizeof(mdns_result_t)); + if (!r) { + HOOK_MALLOC_FAILED; + goto free_txt; + } + + memset(r, 0, sizeof(mdns_result_t)); + r->txt = txt; + r->txt_value_len = txt_value_len; + r->txt_count = txt_count; + r->esp_netif = _mdns_get_esp_netif(tcpip_if); + r->ip_protocol = ip_protocol; + r->ttl = ttl; + r->next = search->result; + search->result = r; + search->num_results++; + } + return; + +free_txt: + for (size_t i = 0; i < txt_count; i++) { + mdns_mem_free((char *)(txt[i].key)); + mdns_mem_free((char *)(txt[i].value)); + } + mdns_mem_free(txt); + mdns_mem_free(txt_value_len); +} + +/** + * @brief Called from packet parser to find matching running search + */ +static mdns_search_once_t *_mdns_search_find_from(mdns_search_once_t *s, mdns_name_t *name, uint16_t type, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +{ + mdns_result_t *r = NULL; + while (s) { + if (s->state == SEARCH_OFF) { + s = s->next; + continue; + } + + if (type == MDNS_TYPE_A || type == MDNS_TYPE_AAAA) { + if ((s->type == MDNS_TYPE_ANY && s->service != NULL) + || (s->type != MDNS_TYPE_ANY && s->type != type && s->type != MDNS_TYPE_PTR && s->type != MDNS_TYPE_SRV)) { + s = s->next; + continue; + } + if (s->type != MDNS_TYPE_PTR && s->type != MDNS_TYPE_SRV) { + if (!strcasecmp(name->host, s->instance)) { + return s; + } + s = s->next; + continue; + } + r = s->result; + while (r) { + if (r->esp_netif == _mdns_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol && !_str_null_or_empty(r->hostname) && !strcasecmp(name->host, r->hostname)) { + return s; + } + r = r->next; + } + s = s->next; + continue; + } + + if (type == MDNS_TYPE_SRV || type == MDNS_TYPE_TXT) { + if ((s->type == MDNS_TYPE_ANY && s->service == NULL) + || (s->type != MDNS_TYPE_ANY && s->type != type && s->type != MDNS_TYPE_PTR)) { + s = s->next; + continue; + } + if (strcasecmp(name->service, s->service) + || strcasecmp(name->proto, s->proto)) { + s = s->next; + continue; + } + if (s->type != MDNS_TYPE_PTR) { + if (s->instance && strcasecmp(name->host, s->instance) == 0) { + return s; + } + s = s->next; + continue; + } + return s; + } + + if (type == MDNS_TYPE_PTR && type == s->type && !strcasecmp(name->service, s->service) && !strcasecmp(name->proto, s->proto)) { + return s; + } + + s = s->next; + } + + return NULL; +} + +/** + * @brief Create search packet for particular interface + */ +static mdns_tx_packet_t *_mdns_create_search_packet(mdns_search_once_t *search, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +{ + mdns_result_t *r = NULL; + mdns_tx_packet_t *packet = _mdns_alloc_packet_default(tcpip_if, ip_protocol); + if (!packet) { + return NULL; + } + + mdns_out_question_t *q = (mdns_out_question_t *)mdns_mem_malloc(sizeof(mdns_out_question_t)); + if (!q) { + HOOK_MALLOC_FAILED; + _mdns_free_tx_packet(packet); + return NULL; + } + q->next = NULL; + q->unicast = search->unicast; + q->type = search->type; + q->host = search->instance; + q->service = search->service; + q->proto = search->proto; + q->domain = MDNS_DEFAULT_DOMAIN; + q->own_dynamic_memory = false; + queueToEnd(mdns_out_question_t, packet->questions, q); + + if (search->type == MDNS_TYPE_PTR) { + r = search->result; + while (r) { + //full record on the same interface is available + if (r->esp_netif != _mdns_get_esp_netif(tcpip_if) || r->ip_protocol != ip_protocol || r->instance_name == NULL || r->hostname == NULL || r->addr == NULL) { + r = r->next; + continue; + } + mdns_out_answer_t *a = (mdns_out_answer_t *)mdns_mem_malloc(sizeof(mdns_out_answer_t)); + if (!a) { + HOOK_MALLOC_FAILED; + _mdns_free_tx_packet(packet); + return NULL; + } + a->type = MDNS_TYPE_PTR; + a->service = NULL; + a->custom_instance = r->instance_name; + a->custom_service = search->service; + a->custom_proto = search->proto; + a->bye = false; + a->flush = false; + a->next = NULL; + queueToEnd(mdns_out_answer_t, packet->answers, a); + r = r->next; + } + } + + return packet; +} + +/** + * @brief Send search packet to particular interface + */ +static void _mdns_search_send_pcb(mdns_search_once_t *search, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +{ + mdns_tx_packet_t *packet = NULL; + if (mdns_is_netif_ready(tcpip_if, ip_protocol) && _mdns_server->interfaces[tcpip_if].pcbs[ip_protocol].state > PCB_INIT) { + packet = _mdns_create_search_packet(search, tcpip_if, ip_protocol); + if (!packet) { + return; + } + _mdns_dispatch_tx_packet(packet); + _mdns_free_tx_packet(packet); + } +} + +/** + * @brief Send search packet to all available interfaces + */ +static void _mdns_search_send(mdns_search_once_t *search) +{ + mdns_search_once_t *queue = _mdns_server->search_once; + bool found = false; + // looking for this search in active searches + while (queue) { + if (queue == search) { + found = true; + break; + } + queue = queue->next; + } + + if (!found) { + // no longer active -> skip sending this search + return; + } + + uint8_t i, j; + for (i = 0; i < MDNS_MAX_INTERFACES; i++) { + for (j = 0; j < MDNS_IP_PROTOCOL_MAX; j++) { + _mdns_search_send_pcb(search, (mdns_if_t)i, (mdns_ip_protocol_t)j); + } + } +} + +static void _mdns_tx_handle_packet(mdns_tx_packet_t *p) +{ + mdns_tx_packet_t *a = NULL; + mdns_out_question_t *q = NULL; + mdns_pcb_t *pcb = &_mdns_server->interfaces[p->tcpip_if].pcbs[p->ip_protocol]; + uint32_t send_after = 1000; + + if (pcb->state == PCB_OFF) { + _mdns_free_tx_packet(p); + return; + } + _mdns_dispatch_tx_packet(p); + + switch (pcb->state) { + case PCB_PROBE_1: + q = p->questions; + while (q) { + q->unicast = false; + q = q->next; + } + //fallthrough + case PCB_PROBE_2: + _mdns_schedule_tx_packet(p, 250); + pcb->state = (mdns_pcb_state_t)((uint8_t)(pcb->state) + 1); + break; + case PCB_PROBE_3: + a = _mdns_create_announce_from_probe(p); + if (!a) { + _mdns_schedule_tx_packet(p, 250); + break; + } + pcb->probe_running = false; + pcb->probe_ip = false; + pcb->probe_services_len = 0; + pcb->failed_probes = 0; + mdns_mem_free(pcb->probe_services); + pcb->probe_services = NULL; + _mdns_free_tx_packet(p); + p = a; + send_after = 250; + //fallthrough + case PCB_ANNOUNCE_1: + //fallthrough + case PCB_ANNOUNCE_2: + _mdns_schedule_tx_packet(p, send_after); + pcb->state = (mdns_pcb_state_t)((uint8_t)(pcb->state) + 1); + break; + case PCB_ANNOUNCE_3: + pcb->state = PCB_RUNNING; + _mdns_free_tx_packet(p); + break; + default: + _mdns_free_tx_packet(p); + break; + } +} + +static void _mdns_remap_self_service_hostname(const char *old_hostname, const char *new_hostname) +{ + mdns_srv_item_t *service = _mdns_server->services; + + while (service) { + if (service->service->hostname && + strcmp(service->service->hostname, old_hostname) == 0) { + mdns_mem_free((char *)service->service->hostname); + service->service->hostname = mdns_mem_strdup(new_hostname); + } + service = service->next; + } +} + +static void _mdns_sync_browse_result_link_free(mdns_browse_sync_t *browse_sync) +{ + mdns_browse_result_sync_t *current = browse_sync->sync_result; + mdns_browse_result_sync_t *need_free; + while (current) { + need_free = current; + current = current->next; + mdns_mem_free(need_free); + } + mdns_mem_free(browse_sync); +} + +/** + * @brief Free action data + */ +static void _mdns_free_action(mdns_action_t *action) +{ + switch (action->type) { + case ACTION_HOSTNAME_SET: + mdns_mem_free(action->data.hostname_set.hostname); + break; + case ACTION_INSTANCE_SET: + mdns_mem_free(action->data.instance); + break; + case ACTION_SEARCH_ADD: + //fallthrough + case ACTION_SEARCH_SEND: + //fallthrough + case ACTION_SEARCH_END: + _mdns_search_free(action->data.search_add.search); + break; + case ACTION_BROWSE_ADD: + //fallthrough + case ACTION_BROWSE_END: + _mdns_browse_item_free(action->data.browse_add.browse); + break; + case ACTION_BROWSE_SYNC: + _mdns_sync_browse_result_link_free(action->data.browse_sync.browse_sync); + break; + case ACTION_TX_HANDLE: + _mdns_free_tx_packet(action->data.tx_handle.packet); + break; + case ACTION_RX_HANDLE: + _mdns_packet_free(action->data.rx_handle.packet); + break; + case ACTION_DELEGATE_HOSTNAME_SET_ADDR: + case ACTION_DELEGATE_HOSTNAME_ADD: + mdns_mem_free((char *)action->data.delegate_hostname.hostname); + free_address_list(action->data.delegate_hostname.address_list); + break; + case ACTION_DELEGATE_HOSTNAME_REMOVE: + mdns_mem_free((char *)action->data.delegate_hostname.hostname); + break; + default: + break; + } + mdns_mem_free(action); +} + +/** + * @brief Called from service thread to execute given action + */ +static void _mdns_execute_action(mdns_action_t *action) +{ + switch (action->type) { + case ACTION_SYSTEM_EVENT: + perform_event_action(action->data.sys_event.interface, action->data.sys_event.event_action); + break; + case ACTION_HOSTNAME_SET: + _mdns_send_bye_all_pcbs_no_instance(true); + _mdns_remap_self_service_hostname(_mdns_server->hostname, action->data.hostname_set.hostname); + mdns_mem_free((char *)_mdns_server->hostname); + _mdns_server->hostname = action->data.hostname_set.hostname; + _mdns_self_host.hostname = action->data.hostname_set.hostname; + _mdns_restart_all_pcbs(); + xSemaphoreGive(_mdns_server->action_sema); + break; + case ACTION_INSTANCE_SET: + _mdns_send_bye_all_pcbs_no_instance(false); + mdns_mem_free((char *)_mdns_server->instance); + _mdns_server->instance = action->data.instance; + _mdns_restart_all_pcbs_no_instance(); + + break; + case ACTION_SEARCH_ADD: + _mdns_search_add(action->data.search_add.search); + break; + case ACTION_SEARCH_SEND: + _mdns_search_send(action->data.search_add.search); + break; + case ACTION_SEARCH_END: + _mdns_search_finish(action->data.search_add.search); + break; + + case ACTION_BROWSE_ADD: + _mdns_browse_add(action->data.browse_add.browse); + break; + case ACTION_BROWSE_SYNC: + _mdns_browse_sync(action->data.browse_sync.browse_sync); + _mdns_sync_browse_result_link_free(action->data.browse_sync.browse_sync); + break; + case ACTION_BROWSE_END: + _mdns_browse_finish(action->data.browse_add.browse); + break; + + case ACTION_TX_HANDLE: { + mdns_tx_packet_t *p = _mdns_server->tx_queue_head; + // packet to be handled should be at tx head, but must be consistent with the one pushed to action queue + if (p && p == action->data.tx_handle.packet && p->queued) { + p->queued = false; // clearing, as the packet might be reused (pushed and transmitted again) + _mdns_server->tx_queue_head = p->next; + _mdns_tx_handle_packet(p); + } else { + ESP_LOGD(TAG, "Skipping transmit of an unexpected packet!"); + } + } + break; + case ACTION_RX_HANDLE: + mdns_parse_packet(action->data.rx_handle.packet); + _mdns_packet_free(action->data.rx_handle.packet); + break; + case ACTION_DELEGATE_HOSTNAME_ADD: + if (!_mdns_delegate_hostname_add(action->data.delegate_hostname.hostname, + action->data.delegate_hostname.address_list)) { + mdns_mem_free((char *)action->data.delegate_hostname.hostname); + free_address_list(action->data.delegate_hostname.address_list); + } + xSemaphoreGive(_mdns_server->action_sema); + break; + case ACTION_DELEGATE_HOSTNAME_SET_ADDR: + if (!_mdns_delegate_hostname_set_address(action->data.delegate_hostname.hostname, + action->data.delegate_hostname.address_list)) { + free_address_list(action->data.delegate_hostname.address_list); + } + mdns_mem_free((char *)action->data.delegate_hostname.hostname); + break; + case ACTION_DELEGATE_HOSTNAME_REMOVE: + _mdns_delegate_hostname_remove(action->data.delegate_hostname.hostname); + mdns_mem_free((char *)action->data.delegate_hostname.hostname); + break; + default: + break; + } + mdns_mem_free(action); +} + +/** + * @brief Queue search action + */ +static esp_err_t _mdns_send_search_action(mdns_action_type_t type, mdns_search_once_t *search) +{ + mdns_action_t *action = NULL; + + action = (mdns_action_t *)mdns_mem_malloc(sizeof(mdns_action_t)); + if (!action) { + HOOK_MALLOC_FAILED; + return ESP_ERR_NO_MEM; + } + + action->type = type; + action->data.search_add.search = search; + if (xQueueSend(_mdns_server->action_queue, &action, (TickType_t)0) != pdPASS) { + mdns_mem_free(action); + return ESP_ERR_NO_MEM; + } + return ESP_OK; +} + +/** + * @brief Called from timer task to run mDNS responder + * + * periodically checks first unqueued packet (from tx head). + * if it is scheduled to be transmitted, then pushes the packet to action queue to be handled. + * + */ +static void _mdns_scheduler_run(void) +{ + MDNS_SERVICE_LOCK(); + mdns_tx_packet_t *p = _mdns_server->tx_queue_head; + mdns_action_t *action = NULL; + + // find first unqueued packet + while (p && p->queued) { + p = p->next; + } + if (!p) { + MDNS_SERVICE_UNLOCK(); + return; + } + while (p && (int32_t)(p->send_at - (xTaskGetTickCount() * portTICK_PERIOD_MS)) < 0) { + action = (mdns_action_t *)mdns_mem_malloc(sizeof(mdns_action_t)); + if (action) { + action->type = ACTION_TX_HANDLE; + action->data.tx_handle.packet = p; + p->queued = true; + if (xQueueSend(_mdns_server->action_queue, &action, (TickType_t)0) != pdPASS) { + mdns_mem_free(action); + p->queued = false; + } + } else { + HOOK_MALLOC_FAILED; + break; + } + //Find the next unqued packet + p = p->next; + } + MDNS_SERVICE_UNLOCK(); +} + +/** + * @brief Called from timer task to run active searches + */ +static void _mdns_search_run(void) +{ + MDNS_SERVICE_LOCK(); + mdns_search_once_t *s = _mdns_server->search_once; + uint32_t now = xTaskGetTickCount() * portTICK_PERIOD_MS; + if (!s) { + MDNS_SERVICE_UNLOCK(); + return; + } + while (s) { + if (s->state != SEARCH_OFF) { + if (now > (s->started_at + s->timeout)) { + s->state = SEARCH_OFF; + if (_mdns_send_search_action(ACTION_SEARCH_END, s) != ESP_OK) { + s->state = SEARCH_RUNNING; + } + } else if (s->state == SEARCH_INIT || (now - s->sent_at) > 1000) { + s->state = SEARCH_RUNNING; + s->sent_at = now; + if (_mdns_send_search_action(ACTION_SEARCH_SEND, s) != ESP_OK) { + s->sent_at -= 1000; + } + } + } + s = s->next; + } + MDNS_SERVICE_UNLOCK(); +} + +/** + * @brief the main MDNS service task. Packets are received and parsed here + */ +static void _mdns_service_task(void *pvParameters) +{ + mdns_action_t *a = NULL; + for (;;) { + if (_mdns_server && _mdns_server->action_queue) { + if (xQueueReceive(_mdns_server->action_queue, &a, portMAX_DELAY) == pdTRUE) { + assert(a); + if (a->type == ACTION_TASK_STOP) { + break; + } + MDNS_SERVICE_LOCK(); + _mdns_execute_action(a); + MDNS_SERVICE_UNLOCK(); + } + } else { + vTaskDelay(500 * portTICK_PERIOD_MS); + } + } + _mdns_service_task_handle = NULL; + vTaskDelay(portMAX_DELAY); +} + +static void _mdns_timer_cb(void *arg) +{ + _mdns_scheduler_run(); + _mdns_search_run(); +} + +static esp_err_t _mdns_start_timer(void) +{ + esp_timer_create_args_t timer_conf = { + .callback = _mdns_timer_cb, + .arg = NULL, + .dispatch_method = ESP_TIMER_TASK, + .name = "mdns_timer" + }; + esp_err_t err = esp_timer_create(&timer_conf, &(_mdns_server->timer_handle)); + if (err) { + return err; + } + return esp_timer_start_periodic(_mdns_server->timer_handle, MDNS_TIMER_PERIOD_US); +} + +static esp_err_t _mdns_stop_timer(void) +{ + esp_err_t err = ESP_OK; + if (_mdns_server->timer_handle) { + err = esp_timer_stop(_mdns_server->timer_handle); + if (err) { + return err; + } + err = esp_timer_delete(_mdns_server->timer_handle); + } + return err; +} + +static esp_err_t _mdns_task_create_with_caps(void) +{ + esp_err_t ret = ESP_OK; + static StaticTask_t mdns_task_buffer; + + _mdns_stack_buffer = mdns_mem_task_malloc(MDNS_SERVICE_STACK_DEPTH); + ESP_GOTO_ON_FALSE(_mdns_stack_buffer != NULL, ESP_FAIL, err, TAG, "failed to allocate memory for the mDNS task's stack"); + + _mdns_service_task_handle = xTaskCreateStaticPinnedToCore(_mdns_service_task, "mdns", MDNS_SERVICE_STACK_DEPTH, NULL, MDNS_TASK_PRIORITY, _mdns_stack_buffer, &mdns_task_buffer, MDNS_TASK_AFFINITY); + ESP_GOTO_ON_FALSE(_mdns_service_task_handle != NULL, ESP_FAIL, err, TAG, "failed to create task for the mDNS"); + + return ret; + +err: + mdns_mem_task_free(_mdns_stack_buffer); + return ret; +} + +/** + * @brief Start the service thread if not running + * + * @return + * - ESP_OK on success + * - ESP_FAIL on error + */ +static esp_err_t _mdns_service_task_start(void) +{ + esp_err_t ret = ESP_OK; + if (!_mdns_service_semaphore) { + _mdns_service_semaphore = xSemaphoreCreateMutex(); + ESP_RETURN_ON_FALSE(_mdns_service_semaphore != NULL, ESP_FAIL, TAG, "Failed to create the mDNS service lock"); + } + MDNS_SERVICE_LOCK(); + ESP_GOTO_ON_ERROR(_mdns_start_timer(), err, TAG, "Failed to start the mDNS service timer"); + + if (!_mdns_service_task_handle) { + ESP_GOTO_ON_ERROR(_mdns_task_create_with_caps(), err_stop_timer, TAG, "Failed to start the mDNS service task"); +#ifdef MDNS_ENABLE_DEBUG +#if !CONFIG_IDF_TARGET_LINUX + StackType_t *mdns_debug_stack_buffer; + StaticTask_t *mdns_debug_task_buffer; + xTaskGetStaticBuffers(_mdns_service_task_handle, &mdns_debug_stack_buffer, &mdns_debug_task_buffer); + _mdns_dbg_printf("mdns_debug_stack_buffer:%p mdns_debug_task_buffer:%p\n", mdns_debug_stack_buffer, mdns_debug_task_buffer); +#endif // CONFIG_IDF_TARGET_LINUX +#endif // MDNS_ENABLE_DEBUG + } + MDNS_SERVICE_UNLOCK(); + return ret; + +err_stop_timer: + _mdns_stop_timer(); +err: + MDNS_SERVICE_UNLOCK(); + vSemaphoreDelete(_mdns_service_semaphore); + _mdns_service_semaphore = NULL; + return ret; +} + +/** + * @brief Stop the service thread + * + * @return + * - ESP_OK + */ +static esp_err_t _mdns_service_task_stop(void) +{ + _mdns_stop_timer(); + if (_mdns_service_task_handle) { + TaskHandle_t task_handle = _mdns_service_task_handle; + mdns_action_t action; + mdns_action_t *a = &action; + action.type = ACTION_TASK_STOP; + if (xQueueSend(_mdns_server->action_queue, &a, (TickType_t)0) != pdPASS) { + _mdns_service_task_handle = NULL; + } + while (_mdns_service_task_handle) { + vTaskDelay(10 / portTICK_PERIOD_MS); + } + vTaskDelete(task_handle); + } + vSemaphoreDelete(_mdns_service_semaphore); + _mdns_service_semaphore = NULL; + return ESP_OK; +} + +static esp_err_t mdns_post_custom_action_tcpip_if(mdns_if_t mdns_if, mdns_event_actions_t event_action) +{ + if (!_mdns_server || mdns_if >= MDNS_MAX_INTERFACES) { + return ESP_ERR_INVALID_STATE; + } + + mdns_action_t *action = (mdns_action_t *)mdns_mem_calloc(1, sizeof(mdns_action_t)); + if (!action) { + HOOK_MALLOC_FAILED; + return ESP_ERR_NO_MEM; + } + action->type = ACTION_SYSTEM_EVENT; + action->data.sys_event.event_action = event_action; + action->data.sys_event.interface = mdns_if; + + if (xQueueSend(_mdns_server->action_queue, &action, (TickType_t)0) != pdPASS) { + mdns_mem_free(action); + } + return ESP_OK; +} + +static inline void set_default_duplicated_interfaces(void) +{ + mdns_if_t wifi_sta_if = MDNS_MAX_INTERFACES; + mdns_if_t eth_if = MDNS_MAX_INTERFACES; + for (mdns_if_t i = 0; i < MDNS_MAX_INTERFACES; i++) { + if (s_esp_netifs[i].predefined && s_esp_netifs[i].predef_if == MDNS_IF_STA) { + wifi_sta_if = i; + } + if (s_esp_netifs[i].predefined && s_esp_netifs[i].predef_if == MDNS_IF_ETH) { + eth_if = i; + } + } + if (wifi_sta_if != MDNS_MAX_INTERFACES && eth_if != MDNS_MAX_INTERFACES) { + s_esp_netifs[wifi_sta_if].duplicate = eth_if; + s_esp_netifs[eth_if].duplicate = wifi_sta_if; + } +} + +static inline void unregister_predefined_handlers(void) +{ +#if MDNS_ESP_WIFI_ENABLED && (CONFIG_MDNS_PREDEF_NETIF_STA || CONFIG_MDNS_PREDEF_NETIF_AP) + esp_event_handler_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, mdns_preset_if_handle_system_event); +#endif +#if CONFIG_MDNS_PREDEF_NETIF_STA || CONFIG_MDNS_PREDEF_NETIF_AP || CONFIG_MDNS_PREDEF_NETIF_ETH + esp_event_handler_unregister(IP_EVENT, ESP_EVENT_ANY_ID, mdns_preset_if_handle_system_event); +#endif +#if CONFIG_ETH_ENABLED && CONFIG_MDNS_PREDEF_NETIF_ETH + esp_event_handler_unregister(ETH_EVENT, ESP_EVENT_ANY_ID, mdns_preset_if_handle_system_event); +#endif +} + +/* + * Public Methods + * */ + +esp_err_t mdns_netif_action(esp_netif_t *esp_netif, mdns_event_actions_t event_action) +{ + return mdns_post_custom_action_tcpip_if(_mdns_get_if_from_esp_netif(esp_netif), event_action); +} + +esp_err_t mdns_register_netif(esp_netif_t *esp_netif) +{ + if (!_mdns_server) { + return ESP_ERR_INVALID_STATE; + } + + esp_err_t err = ESP_ERR_NO_MEM; + MDNS_SERVICE_LOCK(); + for (mdns_if_t i = 0; i < MDNS_MAX_INTERFACES; ++i) { + if (s_esp_netifs[i].netif == esp_netif) { + MDNS_SERVICE_UNLOCK(); + return ESP_ERR_INVALID_STATE; + } + } + + for (mdns_if_t i = 0; i < MDNS_MAX_INTERFACES; ++i) { + if (!s_esp_netifs[i].predefined && s_esp_netifs[i].netif == NULL) { + s_esp_netifs[i].netif = esp_netif; + err = ESP_OK; + break; + } + } + MDNS_SERVICE_UNLOCK(); + return err; +} + +esp_err_t mdns_unregister_netif(esp_netif_t *esp_netif) +{ + if (!_mdns_server) { + return ESP_ERR_INVALID_STATE; + } + + esp_err_t err = ESP_ERR_NOT_FOUND; + MDNS_SERVICE_LOCK(); + for (mdns_if_t i = 0; i < MDNS_MAX_INTERFACES; ++i) { + if (!s_esp_netifs[i].predefined && s_esp_netifs[i].netif == esp_netif) { + s_esp_netifs[i].netif = NULL; + err = ESP_OK; + break; + } + } + MDNS_SERVICE_UNLOCK(); + return err; +} + + +esp_err_t mdns_init(void) +{ + esp_err_t err = ESP_OK; + + if (_mdns_server) { + return err; + } + + _mdns_server = (mdns_server_t *)mdns_mem_malloc(sizeof(mdns_server_t)); + if (!_mdns_server) { + HOOK_MALLOC_FAILED; + return ESP_ERR_NO_MEM; + } + memset((uint8_t *)_mdns_server, 0, sizeof(mdns_server_t)); + // zero-out local copy of netifs to initiate a fresh search by interface key whenever a netif ptr is needed + for (mdns_if_t i = 0; i < MDNS_MAX_INTERFACES; ++i) { + s_esp_netifs[i].netif = NULL; + } + + _mdns_server->action_queue = xQueueCreate(MDNS_ACTION_QUEUE_LEN, sizeof(mdns_action_t *)); + if (!_mdns_server->action_queue) { + err = ESP_ERR_NO_MEM; + goto free_server; + } + + _mdns_server->action_sema = xSemaphoreCreateBinary(); + if (!_mdns_server->action_sema) { + err = ESP_ERR_NO_MEM; + goto free_queue; + } + +#if MDNS_ESP_WIFI_ENABLED && (CONFIG_MDNS_PREDEF_NETIF_STA || CONFIG_MDNS_PREDEF_NETIF_AP) + if ((err = esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, mdns_preset_if_handle_system_event, NULL)) != ESP_OK) { + goto free_event_handlers; + } +#endif +#if CONFIG_MDNS_PREDEF_NETIF_STA || CONFIG_MDNS_PREDEF_NETIF_AP || CONFIG_MDNS_PREDEF_NETIF_ETH + if ((err = esp_event_handler_register(IP_EVENT, ESP_EVENT_ANY_ID, mdns_preset_if_handle_system_event, NULL)) != ESP_OK) { + goto free_event_handlers; + } +#endif +#if CONFIG_ETH_ENABLED && CONFIG_MDNS_PREDEF_NETIF_ETH + if ((err = esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, mdns_preset_if_handle_system_event, NULL)) != ESP_OK) { + goto free_event_handlers; + } +#endif + +#if CONFIG_MDNS_PREDEF_NETIF_STA || CONFIG_MDNS_PREDEF_NETIF_AP || CONFIG_MDNS_PREDEF_NETIF_ETH + set_default_duplicated_interfaces(); +#endif + + uint8_t i; +#ifdef CONFIG_LWIP_IPV6 + esp_ip6_addr_t tmp_addr6; +#endif +#ifdef CONFIG_LWIP_IPV4 + esp_netif_ip_info_t if_ip_info; +#endif + + for (i = 0; i < MDNS_MAX_INTERFACES; i++) { +#ifdef CONFIG_LWIP_IPV6 + if (!esp_netif_get_ip6_linklocal(_mdns_get_esp_netif(i), &tmp_addr6) && !_ipv6_address_is_zero(tmp_addr6)) { + _mdns_enable_pcb(i, MDNS_IP_PROTOCOL_V6); + } +#endif +#ifdef CONFIG_LWIP_IPV4 + if (!esp_netif_get_ip_info(_mdns_get_esp_netif(i), &if_ip_info) && if_ip_info.ip.addr) { + _mdns_enable_pcb(i, MDNS_IP_PROTOCOL_V4); + } +#endif + } + if (_mdns_service_task_start()) { + //service start failed! + err = ESP_FAIL; + goto free_all_and_disable_pcbs; + } + + return ESP_OK; + +free_all_and_disable_pcbs: + for (i = 0; i < MDNS_MAX_INTERFACES; i++) { + _mdns_disable_pcb(i, MDNS_IP_PROTOCOL_V6); + _mdns_disable_pcb(i, MDNS_IP_PROTOCOL_V4); + s_esp_netifs[i].duplicate = MDNS_MAX_INTERFACES; + } +#if CONFIG_MDNS_PREDEF_NETIF_STA || CONFIG_MDNS_PREDEF_NETIF_AP || CONFIG_MDNS_PREDEF_NETIF_ETH +free_event_handlers: + unregister_predefined_handlers(); +#endif + vSemaphoreDelete(_mdns_server->action_sema); +free_queue: + vQueueDelete(_mdns_server->action_queue); +free_server: + mdns_mem_free(_mdns_server); + _mdns_server = NULL; + return err; +} + +void mdns_free(void) +{ + uint8_t i, j; + if (!_mdns_server) { + return; + } + + // Unregister handlers before destroying the mdns internals to avoid receiving async events while deinit + unregister_predefined_handlers(); + + mdns_service_remove_all(); + free_delegated_hostnames(); + _mdns_service_task_stop(); + // at this point, the service task is deleted, so we can destroy the stack size + mdns_mem_task_free(_mdns_stack_buffer); + for (i = 0; i < MDNS_MAX_INTERFACES; i++) { + for (j = 0; j < MDNS_IP_PROTOCOL_MAX; j++) { + mdns_pcb_deinit_local(i, j); + } + } + mdns_mem_free((char *)_mdns_server->hostname); + mdns_mem_free((char *)_mdns_server->instance); + if (_mdns_server->action_queue) { + mdns_action_t *c; + while (xQueueReceive(_mdns_server->action_queue, &c, 0) == pdTRUE) { + _mdns_free_action(c); + } + vQueueDelete(_mdns_server->action_queue); + } + _mdns_clear_tx_queue_head(); + while (_mdns_server->search_once) { + mdns_search_once_t *h = _mdns_server->search_once; + _mdns_server->search_once = h->next; + mdns_mem_free(h->instance); + mdns_mem_free(h->service); + mdns_mem_free(h->proto); + vSemaphoreDelete(h->done_semaphore); + if (h->result) { + _mdns_query_results_free(h->result); + } + mdns_mem_free(h); + } + while (_mdns_server->browse) { + mdns_browse_t *b = _mdns_server->browse; + _mdns_server->browse = _mdns_server->browse->next; + _mdns_browse_item_free(b); + + } + vSemaphoreDelete(_mdns_server->action_sema); + mdns_mem_free(_mdns_server); + _mdns_server = NULL; +} + +esp_err_t mdns_hostname_set(const char *hostname) +{ + if (!_mdns_server) { + return ESP_ERR_INVALID_ARG; + } + if (_str_null_or_empty(hostname) || strlen(hostname) > (MDNS_NAME_BUF_LEN - 1)) { + return ESP_ERR_INVALID_ARG; + } + char *new_hostname = mdns_mem_strndup(hostname, MDNS_NAME_BUF_LEN - 1); + if (!new_hostname) { + return ESP_ERR_NO_MEM; + } + + mdns_action_t *action = (mdns_action_t *)mdns_mem_malloc(sizeof(mdns_action_t)); + if (!action) { + HOOK_MALLOC_FAILED; + mdns_mem_free(new_hostname); + return ESP_ERR_NO_MEM; + } + action->type = ACTION_HOSTNAME_SET; + action->data.hostname_set.hostname = new_hostname; + if (xQueueSend(_mdns_server->action_queue, &action, (TickType_t)0) != pdPASS) { + mdns_mem_free(new_hostname); + mdns_mem_free(action); + return ESP_ERR_NO_MEM; + } + xSemaphoreTake(_mdns_server->action_sema, portMAX_DELAY); + return ESP_OK; +} + +esp_err_t mdns_hostname_get(char *hostname) +{ + if (!hostname) { + return ESP_ERR_INVALID_ARG; + } + + if (!_mdns_server || !_mdns_server->hostname) { + return ESP_ERR_INVALID_STATE; + } + + MDNS_SERVICE_LOCK(); + size_t len = strnlen(_mdns_server->hostname, MDNS_NAME_BUF_LEN - 1); + strncpy(hostname, _mdns_server->hostname, len); + hostname[len] = 0; + MDNS_SERVICE_UNLOCK(); + return ESP_OK; +} + +esp_err_t mdns_delegate_hostname_add(const char *hostname, const mdns_ip_addr_t *address_list) +{ + if (!_mdns_server) { + return ESP_ERR_INVALID_STATE; + } + if (_str_null_or_empty(hostname) || strlen(hostname) > (MDNS_NAME_BUF_LEN - 1)) { + return ESP_ERR_INVALID_ARG; + } + char *new_hostname = mdns_mem_strndup(hostname, MDNS_NAME_BUF_LEN - 1); + if (!new_hostname) { + return ESP_ERR_NO_MEM; + } + + mdns_action_t *action = (mdns_action_t *)mdns_mem_malloc(sizeof(mdns_action_t)); + if (!action) { + HOOK_MALLOC_FAILED; + mdns_mem_free(new_hostname); + return ESP_ERR_NO_MEM; + } + action->type = ACTION_DELEGATE_HOSTNAME_ADD; + action->data.delegate_hostname.hostname = new_hostname; + action->data.delegate_hostname.address_list = copy_address_list(address_list); + if (xQueueSend(_mdns_server->action_queue, &action, (TickType_t)0) != pdPASS) { + mdns_mem_free(new_hostname); + mdns_mem_free(action); + return ESP_ERR_NO_MEM; + } + xSemaphoreTake(_mdns_server->action_sema, portMAX_DELAY); + return ESP_OK; +} + +esp_err_t mdns_delegate_hostname_remove(const char *hostname) +{ + if (!_mdns_server) { + return ESP_ERR_INVALID_STATE; + } + if (_str_null_or_empty(hostname) || strlen(hostname) > (MDNS_NAME_BUF_LEN - 1)) { + return ESP_ERR_INVALID_ARG; + } + char *new_hostname = mdns_mem_strndup(hostname, MDNS_NAME_BUF_LEN - 1); + if (!new_hostname) { + return ESP_ERR_NO_MEM; + } + + mdns_action_t *action = (mdns_action_t *)mdns_mem_malloc(sizeof(mdns_action_t)); + if (!action) { + HOOK_MALLOC_FAILED; + mdns_mem_free(new_hostname); + return ESP_ERR_NO_MEM; + } + action->type = ACTION_DELEGATE_HOSTNAME_REMOVE; + action->data.delegate_hostname.hostname = new_hostname; + if (xQueueSend(_mdns_server->action_queue, &action, (TickType_t)0) != pdPASS) { + mdns_mem_free(new_hostname); + mdns_mem_free(action); + return ESP_ERR_NO_MEM; + } + return ESP_OK; +} + +esp_err_t mdns_delegate_hostname_set_address(const char *hostname, const mdns_ip_addr_t *address_list) +{ + if (!_mdns_server) { + return ESP_ERR_INVALID_STATE; + } + if (_str_null_or_empty(hostname) || strlen(hostname) > (MDNS_NAME_BUF_LEN - 1)) { + return ESP_ERR_INVALID_ARG; + } + char *new_hostname = mdns_mem_strndup(hostname, MDNS_NAME_BUF_LEN - 1); + if (!new_hostname) { + return ESP_ERR_NO_MEM; + } + + mdns_action_t *action = (mdns_action_t *)mdns_mem_malloc(sizeof(mdns_action_t)); + if (!action) { + HOOK_MALLOC_FAILED; + mdns_mem_free(new_hostname); + return ESP_ERR_NO_MEM; + } + action->type = ACTION_DELEGATE_HOSTNAME_SET_ADDR; + action->data.delegate_hostname.hostname = new_hostname; + action->data.delegate_hostname.address_list = copy_address_list(address_list); + if (xQueueSend(_mdns_server->action_queue, &action, (TickType_t)0) != pdPASS) { + mdns_mem_free(new_hostname); + mdns_mem_free(action); + return ESP_ERR_NO_MEM; + } + return ESP_OK; +} + +bool mdns_hostname_exists(const char *hostname) +{ + bool ret = false; + MDNS_SERVICE_LOCK(); + ret = _hostname_is_ours(hostname); + MDNS_SERVICE_UNLOCK(); + return ret; +} + +esp_err_t mdns_instance_name_set(const char *instance) +{ + if (!_mdns_server) { + return ESP_ERR_INVALID_STATE; + } + if (_str_null_or_empty(instance) || _mdns_server->hostname == NULL || strlen(instance) > (MDNS_NAME_BUF_LEN - 1)) { + return ESP_ERR_INVALID_ARG; + } + char *new_instance = mdns_mem_strndup(instance, MDNS_NAME_BUF_LEN - 1); + if (!new_instance) { + return ESP_ERR_NO_MEM; + } + + mdns_action_t *action = (mdns_action_t *)mdns_mem_malloc(sizeof(mdns_action_t)); + if (!action) { + HOOK_MALLOC_FAILED; + mdns_mem_free(new_instance); + return ESP_ERR_NO_MEM; + } + action->type = ACTION_INSTANCE_SET; + action->data.instance = new_instance; + if (xQueueSend(_mdns_server->action_queue, &action, (TickType_t)0) != pdPASS) { + mdns_mem_free(new_instance); + mdns_mem_free(action); + return ESP_ERR_NO_MEM; + } + return ESP_OK; +} + +/* + * MDNS SERVICES + * */ + +esp_err_t mdns_service_add_for_host(const char *instance, const char *service, const char *proto, const char *host, + uint16_t port, mdns_txt_item_t txt[], size_t num_items) +{ + if (!_mdns_server || _str_null_or_empty(service) || _str_null_or_empty(proto) || !_mdns_server->hostname) { + return ESP_ERR_INVALID_ARG; + } + + MDNS_SERVICE_LOCK(); + esp_err_t ret = ESP_OK; + const char *hostname = host ? host : _mdns_server->hostname; + mdns_service_t *s = NULL; + + ESP_GOTO_ON_FALSE(_mdns_can_add_more_services(), ESP_ERR_NO_MEM, err, TAG, + "Cannot add more services, please increase CONFIG_MDNS_MAX_SERVICES (%d)", CONFIG_MDNS_MAX_SERVICES); + + mdns_srv_item_t *item = _mdns_get_service_item_instance(instance, service, proto, hostname); + ESP_GOTO_ON_FALSE(!item, ESP_ERR_INVALID_ARG, err, TAG, "Service already exists"); + + s = _mdns_create_service(service, proto, hostname, port, instance, num_items, txt); + ESP_GOTO_ON_FALSE(s, ESP_ERR_NO_MEM, err, TAG, "Cannot create service: Out of memory"); + + item = (mdns_srv_item_t *)mdns_mem_malloc(sizeof(mdns_srv_item_t)); + ESP_GOTO_ON_FALSE(item, ESP_ERR_NO_MEM, err, TAG, "Cannot create service: Out of memory"); + + item->service = s; + item->next = NULL; + + item->next = _mdns_server->services; + _mdns_server->services = item; + _mdns_probe_all_pcbs(&item, 1, false, false); + MDNS_SERVICE_UNLOCK(); + return ESP_OK; + +err: + MDNS_SERVICE_UNLOCK(); + _mdns_free_service(s); + if (ret == ESP_ERR_NO_MEM) { + HOOK_MALLOC_FAILED; + } + return ret; +} + +esp_err_t mdns_service_add(const char *instance, const char *service, const char *proto, uint16_t port, + mdns_txt_item_t txt[], size_t num_items) +{ + if (!_mdns_server) { + return ESP_ERR_INVALID_STATE; + } + return mdns_service_add_for_host(instance, service, proto, NULL, port, txt, num_items); +} + +bool mdns_service_exists(const char *service_type, const char *proto, const char *hostname) +{ + bool ret = false; + MDNS_SERVICE_LOCK(); + ret = _mdns_get_service_item(service_type, proto, hostname) != NULL; + MDNS_SERVICE_UNLOCK(); + return ret; +} + +bool mdns_service_exists_with_instance(const char *instance, const char *service_type, const char *proto, + const char *hostname) +{ + bool ret = false; + MDNS_SERVICE_LOCK(); + ret = _mdns_get_service_item_instance(instance, service_type, proto, hostname) != NULL; + MDNS_SERVICE_UNLOCK(); + return ret; +} + +static mdns_txt_item_t *_copy_mdns_txt_items(mdns_txt_linked_item_t *items, uint8_t **txt_value_len, size_t *txt_count) +{ + mdns_txt_item_t *ret = NULL; + size_t ret_index = 0; + for (mdns_txt_linked_item_t *tmp = items; tmp != NULL; tmp = tmp->next) { + ret_index++; + } + *txt_count = ret_index; + if (ret_index == 0) { // handle empty TXT + *txt_value_len = NULL; + return NULL; + } + ret = (mdns_txt_item_t *)mdns_mem_calloc(ret_index, sizeof(mdns_txt_item_t)); + *txt_value_len = (uint8_t *)mdns_mem_calloc(ret_index, sizeof(uint8_t)); + if (!ret || !(*txt_value_len)) { + HOOK_MALLOC_FAILED; + goto handle_error; + } + ret_index = 0; + for (mdns_txt_linked_item_t *tmp = items; tmp != NULL; tmp = tmp->next) { + size_t key_len = strlen(tmp->key); + char *key = (char *)mdns_mem_malloc(key_len + 1); + if (!key) { + HOOK_MALLOC_FAILED; + goto handle_error; + } + memcpy(key, tmp->key, key_len); + key[key_len] = 0; + ret[ret_index].key = key; + char *value = (char *)mdns_mem_malloc(tmp->value_len + 1); + if (!value) { + HOOK_MALLOC_FAILED; + goto handle_error; + } + memcpy(value, tmp->value, tmp->value_len); + value[tmp->value_len] = 0; + ret[ret_index].value = value; + (*txt_value_len)[ret_index] = tmp->value_len; + ret_index++; + } + return ret; + +handle_error: + for (size_t y = 0; y < ret_index + 1 && ret != NULL; y++) { + mdns_txt_item_t *t = &ret[y]; + mdns_mem_free((char *)t->key); + mdns_mem_free((char *)t->value); + } + mdns_mem_free(*txt_value_len); + mdns_mem_free(ret); + return NULL; +} + +static mdns_ip_addr_t *_copy_delegated_host_address_list(char *hostname) +{ + mdns_host_item_t *host = _mdns_host_list; + while (host) { + if (strcasecmp(host->hostname, hostname) == 0) { + return copy_address_list(host->address_list); + } + host = host->next; + } + return NULL; +} + +static mdns_result_t *_mdns_lookup_service(const char *instance, const char *service, const char *proto, size_t max_results, bool selfhost) +{ + if (_str_null_or_empty(service) || _str_null_or_empty(proto)) { + return NULL; + } + mdns_result_t *results = NULL; + size_t num_results = 0; + mdns_srv_item_t *s = _mdns_server->services; + while (s) { + mdns_service_t *srv = s->service; + if (!srv || !srv->hostname) { + s = s->next; + continue; + } + bool is_service_selfhosted = !_str_null_or_empty(_mdns_server->hostname) && !strcasecmp(_mdns_server->hostname, srv->hostname); + bool is_service_delegated = _str_null_or_empty(_mdns_server->hostname) || strcasecmp(_mdns_server->hostname, srv->hostname); + if ((selfhost && is_service_selfhosted) || (!selfhost && is_service_delegated)) { + if (!strcasecmp(srv->service, service) && !strcasecmp(srv->proto, proto) && + (_str_null_or_empty(instance) || _mdns_instance_name_match(srv->instance, instance))) { + mdns_result_t *item = (mdns_result_t *)mdns_mem_malloc(sizeof(mdns_result_t)); + if (!item) { + HOOK_MALLOC_FAILED; + goto handle_error; + } + item->next = results; + results = item; + item->esp_netif = NULL; + item->ttl = _str_null_or_empty(instance) ? MDNS_ANSWER_PTR_TTL : MDNS_ANSWER_SRV_TTL; + item->ip_protocol = MDNS_IP_PROTOCOL_MAX; + if (srv->instance) { + item->instance_name = mdns_mem_strndup(srv->instance, MDNS_NAME_BUF_LEN - 1); + if (!item->instance_name) { + HOOK_MALLOC_FAILED; + goto handle_error; + } + } else { + item->instance_name = NULL; + } + item->service_type = mdns_mem_strndup(srv->service, MDNS_NAME_BUF_LEN - 1); + if (!item->service_type) { + HOOK_MALLOC_FAILED; + goto handle_error; + } + item->proto = mdns_mem_strndup(srv->proto, MDNS_NAME_BUF_LEN - 1); + if (!item->proto) { + HOOK_MALLOC_FAILED; + goto handle_error; + } + item->hostname = mdns_mem_strndup(srv->hostname, MDNS_NAME_BUF_LEN - 1); + if (!item->hostname) { + HOOK_MALLOC_FAILED; + goto handle_error; + } + item->port = srv->port; + item->txt = _copy_mdns_txt_items(srv->txt, &(item->txt_value_len), &(item->txt_count)); + // We should not append addresses for selfhost lookup result as we don't know which interface's address to append. + if (selfhost) { + item->addr = NULL; + } else { + item->addr = _copy_delegated_host_address_list(item->hostname); + if (!item->addr) { + goto handle_error; + } + } + if (num_results < max_results) { + num_results++; + } + if (num_results >= max_results) { + break; + } + } + } + s = s->next; + } + return results; +handle_error: + _mdns_query_results_free(results); + return NULL; +} + +esp_err_t mdns_service_port_set_for_host(const char *instance, const char *service, const char *proto, const char *host, uint16_t port) +{ + MDNS_SERVICE_LOCK(); + esp_err_t ret = ESP_OK; + const char *hostname = host ? host : _mdns_server->hostname; + ESP_GOTO_ON_FALSE(_mdns_server && _mdns_server->services && !_str_null_or_empty(service) && !_str_null_or_empty(proto) && port, + ESP_ERR_INVALID_ARG, err, TAG, "Invalid state or arguments"); + mdns_srv_item_t *s = _mdns_get_service_item_instance(instance, service, proto, hostname); + ESP_GOTO_ON_FALSE(s, ESP_ERR_NOT_FOUND, err, TAG, "Service doesn't exist"); + + s->service->port = port; + _mdns_announce_all_pcbs(&s, 1, true); + +err: + MDNS_SERVICE_UNLOCK(); + return ret; +} + +esp_err_t mdns_service_port_set(const char *service, const char *proto, uint16_t port) +{ + if (!_mdns_server) { + return ESP_ERR_INVALID_STATE; + } + return mdns_service_port_set_for_host(NULL, service, proto, NULL, port); +} + +esp_err_t mdns_service_txt_set_for_host(const char *instance, const char *service, const char *proto, const char *host, + mdns_txt_item_t txt_items[], uint8_t num_items) +{ + MDNS_SERVICE_LOCK(); + esp_err_t ret = ESP_OK; + const char *hostname = host ? host : _mdns_server->hostname; + ESP_GOTO_ON_FALSE(_mdns_server && _mdns_server->services && !_str_null_or_empty(service) && !_str_null_or_empty(proto) && !(num_items && txt_items == NULL), + ESP_ERR_INVALID_ARG, err, TAG, "Invalid state or arguments"); + mdns_srv_item_t *s = _mdns_get_service_item_instance(instance, service, proto, hostname); + ESP_GOTO_ON_FALSE(s, ESP_ERR_NOT_FOUND, err, TAG, "Service doesn't exist"); + + mdns_txt_linked_item_t *new_txt = NULL; + if (num_items) { + new_txt = _mdns_allocate_txt(num_items, txt_items); + if (!new_txt) { + return ESP_ERR_NO_MEM; + } + } + mdns_service_t *srv = s->service; + mdns_txt_linked_item_t *txt = srv->txt; + srv->txt = NULL; + _mdns_free_linked_txt(txt); + srv->txt = new_txt; + _mdns_announce_all_pcbs(&s, 1, false); + +err: + MDNS_SERVICE_UNLOCK(); + return ret; +} + +esp_err_t mdns_service_txt_set(const char *service, const char *proto, mdns_txt_item_t txt[], uint8_t num_items) +{ + if (!_mdns_server) { + return ESP_ERR_INVALID_STATE; + } + return mdns_service_txt_set_for_host(NULL, service, proto, NULL, txt, num_items); +} + +esp_err_t mdns_service_txt_item_set_for_host_with_explicit_value_len(const char *instance, const char *service, const char *proto, + const char *host, const char *key, const char *value_arg, uint8_t value_len) +{ + MDNS_SERVICE_LOCK(); + esp_err_t ret = ESP_OK; + char *value = NULL; + mdns_txt_linked_item_t *new_txt = NULL; + const char *hostname = host ? host : _mdns_server->hostname; + ESP_GOTO_ON_FALSE(_mdns_server && _mdns_server->services && !_str_null_or_empty(service) && !_str_null_or_empty(proto) && !_str_null_or_empty(key) && + !((!value_arg && value_len)), ESP_ERR_INVALID_ARG, err, TAG, "Invalid state or arguments"); + + mdns_srv_item_t *s = _mdns_get_service_item_instance(instance, service, proto, hostname); + ESP_GOTO_ON_FALSE(s, ESP_ERR_NOT_FOUND, err, TAG, "Service doesn't exist"); + + mdns_service_t *srv = s->service; + if (value_len > 0) { + value = (char *) mdns_mem_malloc(value_len); + ESP_GOTO_ON_FALSE(value, ESP_ERR_NO_MEM, out_of_mem, TAG, "Out of memory"); + memcpy(value, value_arg, value_len); + } else { + value_len = 0; + } + mdns_txt_linked_item_t *txt = srv->txt; + while (txt) { + if (strcmp(txt->key, key) == 0) { + mdns_mem_free((char *)txt->value); + txt->value = value; + txt->value_len = value_len; + break; + } + txt = txt->next; + } + if (!txt) { + new_txt = (mdns_txt_linked_item_t *)mdns_mem_malloc(sizeof(mdns_txt_linked_item_t)); + ESP_GOTO_ON_FALSE(new_txt, ESP_ERR_NO_MEM, out_of_mem, TAG, "Out of memory"); + new_txt->key = mdns_mem_strdup(key); + ESP_GOTO_ON_FALSE(new_txt->key, ESP_ERR_NO_MEM, out_of_mem, TAG, "Out of memory"); + new_txt->value = value; + new_txt->value_len = value_len; + new_txt->next = srv->txt; + srv->txt = new_txt; + } + + _mdns_announce_all_pcbs(&s, 1, false); + +err: + MDNS_SERVICE_UNLOCK(); + return ret; +out_of_mem: + MDNS_SERVICE_UNLOCK(); + HOOK_MALLOC_FAILED; + mdns_mem_free(value); + mdns_mem_free(new_txt); + return ret; +} + +esp_err_t mdns_service_txt_item_set_for_host(const char *instance, const char *service, const char *proto, const char *hostname, + const char *key, const char *value) +{ + return mdns_service_txt_item_set_for_host_with_explicit_value_len(instance, service, proto, hostname, key, value, + strlen(value)); +} + + +esp_err_t mdns_service_txt_item_set(const char *service, const char *proto, const char *key, const char *value) +{ + if (!_mdns_server) { + return ESP_ERR_INVALID_STATE; + } + return mdns_service_txt_item_set_for_host_with_explicit_value_len(NULL, service, proto, NULL, key, + value, strlen(value)); +} + +esp_err_t mdns_service_txt_item_set_with_explicit_value_len(const char *service, const char *proto, const char *key, + const char *value, uint8_t value_len) +{ + if (!_mdns_server) { + return ESP_ERR_INVALID_STATE; + } + return mdns_service_txt_item_set_for_host_with_explicit_value_len(NULL, service, proto, NULL, key, value, value_len); +} + +esp_err_t mdns_service_txt_item_remove_for_host(const char *instance, const char *service, const char *proto, const char *host, + const char *key) +{ + MDNS_SERVICE_LOCK(); + esp_err_t ret = ESP_OK; + const char *hostname = host ? host : _mdns_server->hostname; + ESP_GOTO_ON_FALSE(_mdns_server && _mdns_server->services && !_str_null_or_empty(service) && !_str_null_or_empty(proto) && !_str_null_or_empty(key), + ESP_ERR_INVALID_ARG, err, TAG, "Invalid state or arguments"); + + mdns_srv_item_t *s = _mdns_get_service_item_instance(instance, service, proto, hostname); + ESP_GOTO_ON_FALSE(s, ESP_ERR_NOT_FOUND, err, TAG, "Service doesn't exist"); + + mdns_service_t *srv = s->service; + mdns_txt_linked_item_t *txt = srv->txt; + if (!txt) { + goto err; + } + if (strcmp(txt->key, key) == 0) { + srv->txt = txt->next; + mdns_mem_free((char *)txt->key); + mdns_mem_free((char *)txt->value); + mdns_mem_free(txt); + } else { + while (txt->next) { + if (strcmp(txt->next->key, key) == 0) { + mdns_txt_linked_item_t *t = txt->next; + txt->next = t->next; + mdns_mem_free((char *)t->key); + mdns_mem_free((char *)t->value); + mdns_mem_free(t); + break; + } else { + txt = txt->next; + } + } + } + + _mdns_announce_all_pcbs(&s, 1, false); + +err: + MDNS_SERVICE_UNLOCK(); + if (ret == ESP_ERR_NO_MEM) { + HOOK_MALLOC_FAILED; + } + return ret; +} + +esp_err_t mdns_service_txt_item_remove(const char *service, const char *proto, const char *key) +{ + if (!_mdns_server) { + return ESP_ERR_INVALID_STATE; + } + return mdns_service_txt_item_remove_for_host(NULL, service, proto, NULL, key); +} + +static esp_err_t _mdns_service_subtype_remove_for_host(mdns_srv_item_t *service, const char *subtype) +{ + esp_err_t ret = ESP_ERR_NOT_FOUND; + mdns_subtype_t *srv_subtype = service->service->subtype; + mdns_subtype_t *pre = service->service->subtype; + while (srv_subtype) { + if (strcmp(srv_subtype->subtype, subtype) == 0) { + // Target subtype is found. + if (srv_subtype == service->service->subtype) { + // The first node needs to be removed + service->service->subtype = service->service->subtype->next; + } else { + pre->next = srv_subtype->next; + } + mdns_mem_free((char *)srv_subtype->subtype); + mdns_mem_free(srv_subtype); + ret = ESP_OK; + break; + } + pre = srv_subtype; + srv_subtype = srv_subtype->next; + } + if (ret == ESP_ERR_NOT_FOUND) { + ESP_LOGE(TAG, "Subtype : %s doesn't exist", subtype); + } + + return ret; +} + +esp_err_t mdns_service_subtype_remove_for_host(const char *instance_name, const char *service, const char *proto, + const char *hostname, const char *subtype) +{ + MDNS_SERVICE_LOCK(); + esp_err_t ret = ESP_OK; + ESP_GOTO_ON_FALSE(_mdns_server && _mdns_server->services && !_str_null_or_empty(service) && !_str_null_or_empty(proto) && + !_str_null_or_empty(subtype), ESP_ERR_INVALID_ARG, err, TAG, "Invalid state or arguments"); + + mdns_srv_item_t *s = _mdns_get_service_item_instance(instance_name, service, proto, hostname); + ESP_GOTO_ON_FALSE(s, ESP_ERR_NOT_FOUND, err, TAG, "Service doesn't exist"); + + ret = _mdns_service_subtype_remove_for_host(s, subtype); + ESP_GOTO_ON_ERROR(ret, err, TAG, "Failed to remove the subtype: %s", subtype); + + // Transmit a sendbye message for the removed subtype. + mdns_subtype_t *remove_subtypes = (mdns_subtype_t *)mdns_mem_malloc(sizeof(mdns_subtype_t)); + ESP_GOTO_ON_FALSE(remove_subtypes, ESP_ERR_NO_MEM, out_of_mem, TAG, "Out of memory"); + remove_subtypes->subtype = mdns_mem_strdup(subtype); + ESP_GOTO_ON_FALSE(remove_subtypes->subtype, ESP_ERR_NO_MEM, out_of_mem, TAG, "Out of memory"); + remove_subtypes->next = NULL; + + _mdns_send_bye_subtype(s, instance_name, remove_subtypes); + _mdns_free_subtype(remove_subtypes); +err: + MDNS_SERVICE_UNLOCK(); + return ret; +out_of_mem: + HOOK_MALLOC_FAILED; + mdns_mem_free(remove_subtypes); + MDNS_SERVICE_UNLOCK(); + return ret; +} + +static esp_err_t _mdns_service_subtype_add_for_host(mdns_srv_item_t *service, const char *subtype) +{ + esp_err_t ret = ESP_OK; + mdns_subtype_t *srv_subtype = service->service->subtype; + while (srv_subtype) { + ESP_GOTO_ON_FALSE(strcmp(srv_subtype->subtype, subtype) != 0, ESP_ERR_INVALID_ARG, err, TAG, "Subtype: %s has already been added", subtype); + srv_subtype = srv_subtype->next; + } + + mdns_subtype_t *subtype_item = (mdns_subtype_t *)mdns_mem_malloc(sizeof(mdns_subtype_t)); + ESP_GOTO_ON_FALSE(subtype_item, ESP_ERR_NO_MEM, out_of_mem, TAG, "Out of memory"); + subtype_item->subtype = mdns_mem_strdup(subtype); + ESP_GOTO_ON_FALSE(subtype_item->subtype, ESP_ERR_NO_MEM, out_of_mem, TAG, "Out of memory"); + subtype_item->next = service->service->subtype; + service->service->subtype = subtype_item; + +err: + return ret; +out_of_mem: + HOOK_MALLOC_FAILED; + mdns_mem_free(subtype_item); + return ret; +} + +esp_err_t mdns_service_subtype_add_multiple_items_for_host(const char *instance_name, const char *service, const char *proto, + const char *hostname, mdns_subtype_item_t subtype[], uint8_t num_items) +{ + MDNS_SERVICE_LOCK(); + esp_err_t ret = ESP_OK; + int cur_index = 0; + ESP_GOTO_ON_FALSE(_mdns_server && _mdns_server->services && !_str_null_or_empty(service) && !_str_null_or_empty(proto) && + (num_items > 0), ESP_ERR_INVALID_ARG, err, TAG, "Invalid state or arguments"); + + mdns_srv_item_t *s = _mdns_get_service_item_instance(instance_name, service, proto, hostname); + ESP_GOTO_ON_FALSE(s, ESP_ERR_NOT_FOUND, err, TAG, "Service doesn't exist"); + + for (; cur_index < num_items; cur_index++) { + ret = _mdns_service_subtype_add_for_host(s, subtype[cur_index].subtype); + if (ret == ESP_OK) { + continue; + } else if (ret == ESP_ERR_NO_MEM) { + ESP_LOGE(TAG, "Out of memory"); + goto err; + } else { + ESP_LOGE(TAG, "Failed to add subtype: %s", subtype[cur_index].subtype); + goto exit; + } + } + + _mdns_announce_all_pcbs(&s, 1, false); +err: + if (ret == ESP_ERR_NO_MEM) { + for (int idx = 0; idx < cur_index; idx++) { + _mdns_service_subtype_remove_for_host(s, subtype[idx].subtype); + } + } +exit: + MDNS_SERVICE_UNLOCK(); + return ret; +} + +esp_err_t mdns_service_subtype_add_for_host(const char *instance_name, const char *service_type, const char *proto, + const char *hostname, const char *subtype) +{ + mdns_subtype_item_t _subtype[1]; + _subtype[0].subtype = subtype; + return mdns_service_subtype_add_multiple_items_for_host(instance_name, service_type, proto, hostname, _subtype, 1); +} + +static mdns_subtype_t *_mdns_service_find_subtype_needed_sendbye(mdns_service_t *service, mdns_subtype_item_t subtype[], + uint8_t num_items) +{ + if (!service) { + return NULL; + } + + mdns_subtype_t *current = service->subtype; + mdns_subtype_t *prev = NULL; + mdns_subtype_t *prev_goodbye = NULL; + mdns_subtype_t *out_goodbye_subtype = NULL; + + while (current) { + bool subtype_in_update = false; + + for (int i = 0; i < num_items; i++) { + if (strcmp(subtype[i].subtype, current->subtype) == 0) { + subtype_in_update = true; + break; + } + } + + if (!subtype_in_update) { + // Remove from original list + if (prev) { + prev->next = current->next; + } else { + service->subtype = current->next; + } + + mdns_subtype_t *to_move = current; + current = current->next; + + // Add to goodbye list + to_move->next = NULL; + if (prev_goodbye) { + prev_goodbye->next = to_move; + } else { + out_goodbye_subtype = to_move; + } + prev_goodbye = to_move; + } else { + prev = current; + current = current->next; + } + } + + return out_goodbye_subtype; +} + +esp_err_t mdns_service_subtype_update_multiple_items_for_host(const char *instance_name, const char *service_type, const char *proto, + const char *hostname, mdns_subtype_item_t subtype[], uint8_t num_items) +{ + MDNS_SERVICE_LOCK(); + esp_err_t ret = ESP_OK; + int cur_index = 0; + ESP_GOTO_ON_FALSE(_mdns_server && _mdns_server->services && !_str_null_or_empty(service_type) && !_str_null_or_empty(proto), + ESP_ERR_INVALID_ARG, err, TAG, "Invalid state or arguments"); + + mdns_srv_item_t *s = _mdns_get_service_item_instance(instance_name, service_type, proto, hostname); + ESP_GOTO_ON_FALSE(s, ESP_ERR_NOT_FOUND, err, TAG, "Service doesn't exist"); + + mdns_subtype_t *goodbye_subtype = _mdns_service_find_subtype_needed_sendbye(s->service, subtype, num_items); + + if (goodbye_subtype) { + _mdns_send_bye_subtype(s, instance_name, goodbye_subtype); + } + + _mdns_free_subtype(goodbye_subtype); + _mdns_free_service_subtype(s->service); + + for (; cur_index < num_items; cur_index++) { + ret = _mdns_service_subtype_add_for_host(s, subtype[cur_index].subtype); + if (ret == ESP_OK) { + continue; + } else if (ret == ESP_ERR_NO_MEM) { + ESP_LOGE(TAG, "Out of memory"); + goto err; + } else { + ESP_LOGE(TAG, "Failed to add subtype: %s", subtype[cur_index].subtype); + goto exit; + } + } + if (num_items) { + _mdns_announce_all_pcbs(&s, 1, false); + } +err: + if (ret == ESP_ERR_NO_MEM) { + for (int idx = 0; idx < cur_index; idx++) { + _mdns_service_subtype_remove_for_host(s, subtype[idx].subtype); + } + } +exit: + MDNS_SERVICE_UNLOCK(); + return ret; +} + +esp_err_t mdns_service_instance_name_set_for_host(const char *instance_old, const char *service, const char *proto, const char *host, + const char *instance) +{ + MDNS_SERVICE_LOCK(); + esp_err_t ret = ESP_OK; + const char *hostname = host ? host : _mdns_server->hostname; + + ESP_GOTO_ON_FALSE(_mdns_server && _mdns_server->services && !_str_null_or_empty(service) && !_str_null_or_empty(proto) && + !_str_null_or_empty(instance) && strlen(instance) <= (MDNS_NAME_BUF_LEN - 1), ESP_ERR_INVALID_ARG, err, TAG, "Invalid state or arguments"); + + mdns_srv_item_t *s = _mdns_get_service_item_instance(instance_old, service, proto, hostname); + ESP_GOTO_ON_FALSE(s, ESP_ERR_NOT_FOUND, err, TAG, "Service doesn't exist"); + + if (s->service->instance) { + _mdns_send_bye(&s, 1, false); + mdns_mem_free((char *)s->service->instance); + } + s->service->instance = mdns_mem_strndup(instance, MDNS_NAME_BUF_LEN - 1); + ESP_GOTO_ON_FALSE(s->service->instance, ESP_ERR_NO_MEM, err, TAG, "Out of memory"); + _mdns_probe_all_pcbs(&s, 1, false, false); + +err: + MDNS_SERVICE_UNLOCK(); + return ret; +} + +esp_err_t mdns_service_instance_name_set(const char *service, const char *proto, const char *instance) +{ + if (!_mdns_server) { + return ESP_ERR_INVALID_STATE; + } + return mdns_service_instance_name_set_for_host(NULL, service, proto, NULL, instance); +} + +esp_err_t mdns_service_remove_for_host(const char *instance, const char *service, const char *proto, const char *host) +{ + MDNS_SERVICE_LOCK(); + esp_err_t ret = ESP_OK; + const char *hostname = host ? host : _mdns_server->hostname; + ESP_GOTO_ON_FALSE(_mdns_server && _mdns_server->services && !_str_null_or_empty(service) && !_str_null_or_empty(proto), + ESP_ERR_INVALID_ARG, err, TAG, "Invalid state or arguments"); + mdns_srv_item_t *s = _mdns_get_service_item_instance(instance, service, proto, hostname); + ESP_GOTO_ON_FALSE(s, ESP_ERR_NOT_FOUND, err, TAG, "Service doesn't exist"); + + mdns_srv_item_t *a = _mdns_server->services; + mdns_srv_item_t *b = a; + if (instance) { + while (a) { + if (_mdns_service_match_instance(a->service, instance, service, proto, hostname)) { + if (_mdns_server->services != a) { + b->next = a->next; + } else { + _mdns_server->services = a->next; + } + _mdns_send_bye(&a, 1, false); + _mdns_remove_scheduled_service_packets(a->service); + _mdns_free_service(a->service); + mdns_mem_free(a); + break; + } + b = a; + a = a->next; + } + } else { + while (a) { + if (_mdns_service_match(a->service, service, proto, hostname)) { + if (_mdns_server->services != a) { + b->next = a->next; + } else { + _mdns_server->services = a->next; + } + _mdns_send_bye(&a, 1, false); + _mdns_remove_scheduled_service_packets(a->service); + _mdns_free_service(a->service); + mdns_mem_free(a); + break; + } + b = a; + a = a->next; + } + } + +err: + MDNS_SERVICE_UNLOCK(); + return ret; +} + +esp_err_t mdns_service_remove(const char *service_type, const char *proto) +{ + if (!_mdns_server) { + return ESP_ERR_INVALID_STATE; + } + return mdns_service_remove_for_host(NULL, service_type, proto, NULL); +} + +esp_err_t mdns_service_remove_all(void) +{ + MDNS_SERVICE_LOCK(); + esp_err_t ret = ESP_OK; + ESP_GOTO_ON_FALSE(_mdns_server, ESP_ERR_INVALID_ARG, done, TAG, "Invalid state"); + if (!_mdns_server->services) { + goto done; + } + + _mdns_send_final_bye(false); + mdns_srv_item_t *services = _mdns_server->services; + _mdns_server->services = NULL; + while (services) { + mdns_srv_item_t *s = services; + services = services->next; + _mdns_remove_scheduled_service_packets(s->service); + _mdns_free_service(s->service); + mdns_mem_free(s); + } + +done: + MDNS_SERVICE_UNLOCK(); + return ret; +} + +/* + * MDNS QUERY + * */ +void mdns_query_results_free(mdns_result_t *results) +{ + MDNS_SERVICE_LOCK(); + _mdns_query_results_free(results); + MDNS_SERVICE_UNLOCK(); +} + +static void _mdns_query_results_free(mdns_result_t *results) +{ + mdns_result_t *r; + mdns_ip_addr_t *a; + + while (results) { + r = results; + + mdns_mem_free((char *)(r->hostname)); + mdns_mem_free((char *)(r->instance_name)); + mdns_mem_free((char *)(r->service_type)); + mdns_mem_free((char *)(r->proto)); + + for (size_t i = 0; i < r->txt_count; i++) { + mdns_mem_free((char *)(r->txt[i].key)); + mdns_mem_free((char *)(r->txt[i].value)); + } + mdns_mem_free(r->txt); + mdns_mem_free(r->txt_value_len); + + while (r->addr) { + a = r->addr; + r->addr = r->addr->next; + mdns_mem_free(a); + } + + results = results->next; + mdns_mem_free(r); + } +} + +esp_err_t mdns_query_async_delete(mdns_search_once_t *search) +{ + if (!search) { + return ESP_ERR_INVALID_ARG; + } + if (search->state != SEARCH_OFF) { + return ESP_ERR_INVALID_STATE; + } + + MDNS_SERVICE_LOCK(); + _mdns_search_free(search); + MDNS_SERVICE_UNLOCK(); + + return ESP_OK; +} + +bool mdns_query_async_get_results(mdns_search_once_t *search, uint32_t timeout, mdns_result_t **results, uint8_t *num_results) +{ + if (xSemaphoreTake(search->done_semaphore, pdMS_TO_TICKS(timeout)) == pdTRUE) { + if (results) { + *results = search->result; + } + if (num_results) { + *num_results = search->num_results; + } + return true; + } + return false; +} + +mdns_search_once_t *mdns_query_async_new(const char *name, const char *service, const char *proto, uint16_t type, + uint32_t timeout, size_t max_results, mdns_query_notify_t notifier) +{ + mdns_search_once_t *search = NULL; + + if (!_mdns_server || !timeout || _str_null_or_empty(service) != _str_null_or_empty(proto)) { + return NULL; + } + + search = _mdns_search_init(name, service, proto, type, type != MDNS_TYPE_PTR, timeout, max_results, notifier); + if (!search) { + return NULL; + } + + if (_mdns_send_search_action(ACTION_SEARCH_ADD, search)) { + _mdns_search_free(search); + return NULL; + } + + return search; +} + +esp_err_t mdns_query_generic(const char *name, const char *service, const char *proto, uint16_t type, mdns_query_transmission_type_t transmission_type, uint32_t timeout, size_t max_results, mdns_result_t **results) +{ + mdns_search_once_t *search = NULL; + + *results = NULL; + + if (!_mdns_server) { + return ESP_ERR_INVALID_STATE; + } + + if (!timeout || _str_null_or_empty(service) != _str_null_or_empty(proto)) { + return ESP_ERR_INVALID_ARG; + } + + search = _mdns_search_init(name, service, proto, type, transmission_type == MDNS_QUERY_UNICAST, timeout, max_results, NULL); + if (!search) { + return ESP_ERR_NO_MEM; + } + + if (_mdns_send_search_action(ACTION_SEARCH_ADD, search)) { + _mdns_search_free(search); + return ESP_ERR_NO_MEM; + } + xSemaphoreTake(search->done_semaphore, portMAX_DELAY); + + *results = search->result; + _mdns_search_free(search); + + return ESP_OK; +} + +esp_err_t mdns_query(const char *name, const char *service_type, const char *proto, uint16_t type, uint32_t timeout, size_t max_results, mdns_result_t **results) +{ + return mdns_query_generic(name, service_type, proto, type, type != MDNS_TYPE_PTR, timeout, max_results, results); +} + +esp_err_t mdns_query_ptr(const char *service, const char *proto, uint32_t timeout, size_t max_results, mdns_result_t **results) +{ + if (_str_null_or_empty(service) || _str_null_or_empty(proto)) { + return ESP_ERR_INVALID_ARG; + } + + return mdns_query(NULL, service, proto, MDNS_TYPE_PTR, timeout, max_results, results); +} + +esp_err_t mdns_query_srv(const char *instance, const char *service, const char *proto, uint32_t timeout, mdns_result_t **result) +{ + if (_str_null_or_empty(instance) || _str_null_or_empty(service) || _str_null_or_empty(proto)) { + return ESP_ERR_INVALID_ARG; + } + + return mdns_query(instance, service, proto, MDNS_TYPE_SRV, timeout, 1, result); +} + +esp_err_t mdns_query_txt(const char *instance, const char *service, const char *proto, uint32_t timeout, mdns_result_t **result) +{ + if (_str_null_or_empty(instance) || _str_null_or_empty(service) || _str_null_or_empty(proto)) { + return ESP_ERR_INVALID_ARG; + } + + return mdns_query(instance, service, proto, MDNS_TYPE_TXT, timeout, 1, result); +} + +esp_err_t mdns_lookup_delegated_service(const char *instance, const char *service, const char *proto, size_t max_results, + mdns_result_t **result) +{ + if (!_mdns_server) { + return ESP_ERR_INVALID_STATE; + } + if (!result || _str_null_or_empty(service) || _str_null_or_empty(proto)) { + return ESP_ERR_INVALID_ARG; + } + MDNS_SERVICE_LOCK(); + *result = _mdns_lookup_service(instance, service, proto, max_results, false); + MDNS_SERVICE_UNLOCK(); + return ESP_OK; +} + +esp_err_t mdns_lookup_selfhosted_service(const char *instance, const char *service, const char *proto, size_t max_results, + mdns_result_t **result) +{ + if (!_mdns_server) { + return ESP_ERR_INVALID_STATE; + } + if (!result || _str_null_or_empty(service) || _str_null_or_empty(proto)) { + return ESP_ERR_INVALID_ARG; + } + MDNS_SERVICE_LOCK(); + *result = _mdns_lookup_service(instance, service, proto, max_results, true); + MDNS_SERVICE_UNLOCK(); + return ESP_OK; +} + +#ifdef CONFIG_LWIP_IPV4 +esp_err_t mdns_query_a(const char *name, uint32_t timeout, esp_ip4_addr_t *addr) +{ + mdns_result_t *result = NULL; + esp_err_t err; + + if (_str_null_or_empty(name)) { + return ESP_ERR_INVALID_ARG; + } + + if (strstr(name, ".local")) { + ESP_LOGW(TAG, "Please note that hostname must not contain domain name, as mDNS uses '.local' domain"); + } + + err = mdns_query(name, NULL, NULL, MDNS_TYPE_A, timeout, 1, &result); + + if (err) { + return err; + } + + if (!result) { + return ESP_ERR_NOT_FOUND; + } + + mdns_ip_addr_t *a = result->addr; + while (a) { + if (a->addr.type == ESP_IPADDR_TYPE_V4) { + addr->addr = a->addr.u_addr.ip4.addr; + mdns_query_results_free(result); + return ESP_OK; + } + a = a->next; + } + + mdns_query_results_free(result); + return ESP_ERR_NOT_FOUND; +} +#endif /* CONFIG_LWIP_IPV4 */ + +#ifdef CONFIG_LWIP_IPV6 +esp_err_t mdns_query_aaaa(const char *name, uint32_t timeout, esp_ip6_addr_t *addr) +{ + mdns_result_t *result = NULL; + esp_err_t err; + + if (_str_null_or_empty(name)) { + return ESP_ERR_INVALID_ARG; + } + + if (strstr(name, ".local")) { + ESP_LOGW(TAG, "Please note that hostname must not contain domain name, as mDNS uses '.local' domain"); + } + + err = mdns_query(name, NULL, NULL, MDNS_TYPE_AAAA, timeout, 1, &result); + + if (err) { + return err; + } + + if (!result) { + return ESP_ERR_NOT_FOUND; + } + + mdns_ip_addr_t *a = result->addr; + while (a) { + if (a->addr.type == ESP_IPADDR_TYPE_V6) { + memcpy(addr->addr, a->addr.u_addr.ip6.addr, 16); + mdns_query_results_free(result); + return ESP_OK; + } + a = a->next; + } + + mdns_query_results_free(result); + return ESP_ERR_NOT_FOUND; +} +#endif /* CONFIG_LWIP_IPV6 */ + +#ifdef MDNS_ENABLE_DEBUG + +void mdns_debug_packet(const uint8_t *data, size_t len) +{ + static mdns_name_t n; + mdns_header_t header; + const uint8_t *content = data + MDNS_HEAD_LEN; + uint32_t t = xTaskGetTickCount() * portTICK_PERIOD_MS; + mdns_name_t *name = &n; + memset(name, 0, sizeof(mdns_name_t)); + + _mdns_dbg_printf("Packet[%" PRIu32 "]: ", t); + + header.id = _mdns_read_u16(data, MDNS_HEAD_ID_OFFSET); + header.flags = _mdns_read_u16(data, MDNS_HEAD_FLAGS_OFFSET); + header.questions = _mdns_read_u16(data, MDNS_HEAD_QUESTIONS_OFFSET); + header.answers = _mdns_read_u16(data, MDNS_HEAD_ANSWERS_OFFSET); + header.servers = _mdns_read_u16(data, MDNS_HEAD_SERVERS_OFFSET); + header.additional = _mdns_read_u16(data, MDNS_HEAD_ADDITIONAL_OFFSET); + + _mdns_dbg_printf("%s", + (header.flags == MDNS_FLAGS_QR_AUTHORITATIVE) ? "AUTHORITATIVE\n" : + (header.flags == MDNS_FLAGS_DISTRIBUTED) ? "DISTRIBUTED\n" : + (header.flags == 0) ? "\n" : " " + ); + if (header.flags && header.flags != MDNS_FLAGS_QR_AUTHORITATIVE) { + _mdns_dbg_printf("0x%04X\n", header.flags); + } + + if (header.questions) { + uint8_t qs = header.questions; + + while (qs--) { + content = _mdns_parse_fqdn(data, content, name, len); + if (!content || content + MDNS_CLASS_OFFSET + 1 >= data + len) { + header.answers = 0; + header.additional = 0; + header.servers = 0; + _mdns_dbg_printf("ERROR: parse header questions\n"); + break; + } + + uint16_t type = _mdns_read_u16(content, MDNS_TYPE_OFFSET); + uint16_t mdns_class = _mdns_read_u16(content, MDNS_CLASS_OFFSET); + bool unicast = !!(mdns_class & 0x8000); + mdns_class &= 0x7FFF; + content = content + 4; + + _mdns_dbg_printf(" Q: "); + if (unicast) { + _mdns_dbg_printf("*U* "); + } + if (type == MDNS_TYPE_PTR) { + _mdns_dbg_printf("%s.%s%s.%s.%s. PTR ", name->host, name->sub ? "_sub." : "", name->service, name->proto, name->domain); + } else if (type == MDNS_TYPE_SRV) { + _mdns_dbg_printf("%s.%s%s.%s.%s. SRV ", name->host, name->sub ? "_sub." : "", name->service, name->proto, name->domain); + } else if (type == MDNS_TYPE_TXT) { + _mdns_dbg_printf("%s.%s%s.%s.%s. TXT ", name->host, name->sub ? "_sub." : "", name->service, name->proto, name->domain); + } else if (type == MDNS_TYPE_A) { + _mdns_dbg_printf("%s.%s. A ", name->host, name->domain); + } else if (type == MDNS_TYPE_AAAA) { + _mdns_dbg_printf("%s.%s. AAAA ", name->host, name->domain); + } else if (type == MDNS_TYPE_NSEC) { + _mdns_dbg_printf("%s.%s%s.%s.%s. NSEC ", name->host, name->sub ? "_sub." : "", name->service, name->proto, name->domain); + } else if (type == MDNS_TYPE_ANY) { + _mdns_dbg_printf("%s.%s%s.%s.%s. ANY ", name->host, name->sub ? "_sub." : "", name->service, name->proto, name->domain); + } else { + _mdns_dbg_printf("%s.%s%s.%s.%s. %04X ", name->host, name->sub ? "_sub." : "", name->service, name->proto, name->domain, type); + } + + if (mdns_class == 0x0001) { + _mdns_dbg_printf("IN"); + } else { + _mdns_dbg_printf("%04X", mdns_class); + } + _mdns_dbg_printf("\n"); + } + } + + if (header.answers || header.servers || header.additional) { + uint16_t recordIndex = 0; + + while (content < (data + len)) { + + content = _mdns_parse_fqdn(data, content, name, len); + if (!content) { + _mdns_dbg_printf("ERROR: parse mdns records\n"); + break; + } + + uint16_t type = _mdns_read_u16(content, MDNS_TYPE_OFFSET); + uint16_t mdns_class = _mdns_read_u16(content, MDNS_CLASS_OFFSET); + uint32_t ttl = _mdns_read_u32(content, MDNS_TTL_OFFSET); + uint16_t data_len = _mdns_read_u16(content, MDNS_LEN_OFFSET); + const uint8_t *data_ptr = content + MDNS_DATA_OFFSET; + bool flush = !!(mdns_class & 0x8000); + mdns_class &= 0x7FFF; + + content = data_ptr + data_len; + if (content > (data + len)) { + _mdns_dbg_printf("ERROR: content length overflow\n"); + break; + } + + mdns_parsed_record_type_t record_type = MDNS_ANSWER; + + if (recordIndex >= (header.answers + header.servers)) { + record_type = MDNS_EXTRA; + } else if (recordIndex >= (header.answers)) { + record_type = MDNS_NS; + } + recordIndex++; + + if (record_type == MDNS_EXTRA) { + _mdns_dbg_printf(" X"); + } else if (record_type == MDNS_NS) { + _mdns_dbg_printf(" S"); + } else { + _mdns_dbg_printf(" A"); + } + + if (type == MDNS_TYPE_PTR) { + _mdns_dbg_printf(": %s%s%s.%s.%s. PTR ", name->host, name->host[0] ? "." : "", name->service, name->proto, name->domain); + } else if (type == MDNS_TYPE_SRV) { + _mdns_dbg_printf(": %s.%s.%s.%s. SRV ", name->host, name->service, name->proto, name->domain); + } else if (type == MDNS_TYPE_TXT) { + _mdns_dbg_printf(": %s.%s.%s.%s. TXT ", name->host, name->service, name->proto, name->domain); + } else if (type == MDNS_TYPE_A) { + _mdns_dbg_printf(": %s.%s. A ", name->host, name->domain); + } else if (type == MDNS_TYPE_AAAA) { + _mdns_dbg_printf(": %s.%s. AAAA ", name->host, name->domain); + } else if (type == MDNS_TYPE_NSEC) { + _mdns_dbg_printf(": %s.%s.%s.%s. NSEC ", name->host, name->service, name->proto, name->domain); + } else if (type == MDNS_TYPE_ANY) { + _mdns_dbg_printf(": %s.%s.%s.%s. ANY ", name->host, name->service, name->proto, name->domain); + } else if (type == MDNS_TYPE_OPT) { + _mdns_dbg_printf(": . OPT "); + } else { + _mdns_dbg_printf(": %s.%s.%s.%s. %04X ", name->host, name->service, name->proto, name->domain, type); + } + + if (mdns_class == 0x0001) { + _mdns_dbg_printf("IN "); + } else { + _mdns_dbg_printf("%04X ", mdns_class); + } + if (flush) { + _mdns_dbg_printf("FLUSH "); + } + _mdns_dbg_printf("%" PRIu32, ttl); + _mdns_dbg_printf("[%u] ", data_len); + if (type == MDNS_TYPE_PTR) { + if (!_mdns_parse_fqdn(data, data_ptr, name, len)) { + _mdns_dbg_printf("ERROR: parse PTR\n"); + continue; + } + _mdns_dbg_printf("%s.%s.%s.%s.\n", name->host, name->service, name->proto, name->domain); + } else if (type == MDNS_TYPE_SRV) { + if (!_mdns_parse_fqdn(data, data_ptr + MDNS_SRV_FQDN_OFFSET, name, len)) { + _mdns_dbg_printf("ERROR: parse SRV\n"); + continue; + } + uint16_t priority = _mdns_read_u16(data_ptr, MDNS_SRV_PRIORITY_OFFSET); + uint16_t weight = _mdns_read_u16(data_ptr, MDNS_SRV_WEIGHT_OFFSET); + uint16_t port = _mdns_read_u16(data_ptr, MDNS_SRV_PORT_OFFSET); + _mdns_dbg_printf("%u %u %u %s.%s.\n", priority, weight, port, name->host, name->domain); + } else if (type == MDNS_TYPE_TXT) { + uint16_t i = 0, y; + while (i < data_len) { + uint8_t partLen = data_ptr[i++]; + if ((i + partLen) > data_len) { + _mdns_dbg_printf("ERROR: parse TXT\n"); + break; + } + char txt[partLen + 1]; + for (y = 0; y < partLen; y++) { + char d = data_ptr[i++]; + txt[y] = d; + } + txt[partLen] = 0; + _mdns_dbg_printf("%s", txt); + if (i < data_len) { + _mdns_dbg_printf("; "); + } + } + _mdns_dbg_printf("\n"); + } else if (type == MDNS_TYPE_AAAA) { + esp_ip6_addr_t ip6; + memcpy(&ip6, data_ptr, sizeof(esp_ip6_addr_t)); + _mdns_dbg_printf(IPV6STR "\n", IPV62STR(ip6)); + } else if (type == MDNS_TYPE_A) { + esp_ip4_addr_t ip; + memcpy(&ip, data_ptr, sizeof(esp_ip4_addr_t)); + _mdns_dbg_printf(IPSTR "\n", IP2STR(&ip)); + } else if (type == MDNS_TYPE_NSEC) { + const uint8_t *old_ptr = data_ptr; + const uint8_t *new_ptr = _mdns_parse_fqdn(data, data_ptr, name, len); + if (new_ptr) { + _mdns_dbg_printf("%s.%s.%s.%s. ", name->host, name->service, name->proto, name->domain); + size_t diff = new_ptr - old_ptr; + data_len -= diff; + data_ptr = new_ptr; + } + size_t i; + for (i = 0; i < data_len; i++) { + _mdns_dbg_printf(" %02x", data_ptr[i]); + } + _mdns_dbg_printf("\n"); + } else if (type == MDNS_TYPE_OPT) { + uint16_t opCode = _mdns_read_u16(data_ptr, 0); + uint16_t opLen = _mdns_read_u16(data_ptr, 2); + _mdns_dbg_printf(" Code: %04x Data[%u]:", opCode, opLen); + size_t i; + for (i = 4; i < data_len; i++) { + _mdns_dbg_printf(" %02x", data_ptr[i]); + } + _mdns_dbg_printf("\n"); + } else { + size_t i; + for (i = 0; i < data_len; i++) { + _mdns_dbg_printf(" %02x", data_ptr[i]); + } + _mdns_dbg_printf("\n"); + } + } + } +} +#endif /* MDNS_ENABLE_DEBUG */ + +/** + * @brief Browse sync result action + */ +static esp_err_t _mdns_sync_browse_action(mdns_action_type_t type, mdns_browse_sync_t *browse_sync) +{ + mdns_action_t *action = NULL; + + action = (mdns_action_t *)mdns_mem_malloc(sizeof(mdns_action_t)); + if (!action) { + HOOK_MALLOC_FAILED; + return ESP_ERR_NO_MEM; + } + + action->type = type; + action->data.browse_sync.browse_sync = browse_sync; + if (xQueueSend(_mdns_server->action_queue, &action, (TickType_t)0) != pdPASS) { + mdns_mem_free(action); + return ESP_ERR_NO_MEM; + } + return ESP_OK; +} + +/** + * @brief Browse action + */ +static esp_err_t _mdns_send_browse_action(mdns_action_type_t type, mdns_browse_t *browse) +{ + mdns_action_t *action = NULL; + + action = (mdns_action_t *)mdns_mem_malloc(sizeof(mdns_action_t)); + + if (!action) { + HOOK_MALLOC_FAILED; + return ESP_ERR_NO_MEM; + } + + action->type = type; + action->data.browse_add.browse = browse; + if (xQueueSend(_mdns_server->action_queue, &action, (TickType_t)0) != pdPASS) { + mdns_mem_free(action); + return ESP_ERR_NO_MEM; + } + return ESP_OK; +} + +/** + * @brief Free a browse item (Not free the list). + */ +static void _mdns_browse_item_free(mdns_browse_t *browse) +{ + mdns_mem_free(browse->service); + mdns_mem_free(browse->proto); + if (browse->result) { + _mdns_query_results_free(browse->result); + } + mdns_mem_free(browse); +} + +/** + * @brief Allocate new browse structure + */ +static mdns_browse_t *_mdns_browse_init(const char *service, const char *proto, mdns_browse_notify_t notifier) +{ + mdns_browse_t *browse = (mdns_browse_t *)mdns_mem_malloc(sizeof(mdns_browse_t)); + + if (!browse) { + HOOK_MALLOC_FAILED; + return NULL; + } + memset(browse, 0, sizeof(mdns_browse_t)); + + browse->state = BROWSE_INIT; + if (!_str_null_or_empty(service)) { + browse->service = mdns_mem_strndup(service, MDNS_NAME_BUF_LEN - 1); + if (!browse->service) { + _mdns_browse_item_free(browse); + return NULL; + } + } + + if (!_str_null_or_empty(proto)) { + browse->proto = mdns_mem_strndup(proto, MDNS_NAME_BUF_LEN - 1); + if (!browse->proto) { + _mdns_browse_item_free(browse); + return NULL; + } + } + + browse->notifier = notifier; + return browse; +} + +mdns_browse_t *mdns_browse_new(const char *service, const char *proto, mdns_browse_notify_t notifier) +{ + mdns_browse_t *browse = NULL; + + if (!_mdns_server || _str_null_or_empty(service) || _str_null_or_empty(proto)) { + return NULL; + } + + browse = _mdns_browse_init(service, proto, notifier); + if (!browse) { + return NULL; + } + + if (_mdns_send_browse_action(ACTION_BROWSE_ADD, browse)) { + _mdns_browse_item_free(browse); + return NULL; + } + + return browse; +} + +esp_err_t mdns_browse_delete(const char *service, const char *proto) +{ + mdns_browse_t *browse = NULL; + + if (!_mdns_server || _str_null_or_empty(service) || _str_null_or_empty(proto)) { + return ESP_FAIL; + } + + browse = _mdns_browse_init(service, proto, NULL); + if (!browse) { + return ESP_ERR_NO_MEM; + } + + if (_mdns_send_browse_action(ACTION_BROWSE_END, browse)) { + _mdns_browse_item_free(browse); + return ESP_ERR_NO_MEM; + } + return ESP_OK; +} + +/** + * @brief Mark browse as finished, remove and free it from browse chain + */ +static void _mdns_browse_finish(mdns_browse_t *browse) +{ + browse->state = BROWSE_OFF; + mdns_browse_t *b = _mdns_server->browse; + mdns_browse_t *target_free = NULL; + while (b) { + if (strlen(b->service) == strlen(browse->service) && memcmp(b->service, browse->service, strlen(b->service)) == 0 && + strlen(b->proto) == strlen(browse->proto) && memcmp(b->proto, browse->proto, strlen(b->proto)) == 0) { + target_free = b; + b = b->next; + queueDetach(mdns_browse_t, _mdns_server->browse, target_free); + _mdns_browse_item_free(target_free); + } else { + b = b->next; + } + } + _mdns_browse_item_free(browse); +} + +/** + * @brief Add new browse to the browse chain + */ +static void _mdns_browse_add(mdns_browse_t *browse) +{ + browse->state = BROWSE_RUNNING; + mdns_browse_t *queue = _mdns_server->browse; + bool found = false; + // looking for this browse in active browses + while (queue) { + if (strlen(queue->service) == strlen(browse->service) && memcmp(queue->service, browse->service, strlen(queue->service)) == 0 && + strlen(queue->proto) == strlen(browse->proto) && memcmp(queue->proto, browse->proto, strlen(queue->proto)) == 0) { + found = true; + break; + } + queue = queue->next; + } + if (!found) { + browse->next = _mdns_server->browse; + _mdns_server->browse = browse; + } + for (uint8_t interface_idx = 0; interface_idx < MDNS_MAX_INTERFACES; interface_idx++) { + _mdns_browse_send(browse, (mdns_if_t)interface_idx); + } + if (found) { + _mdns_browse_item_free(browse); + } +} + +/** + * @brief Send PTR query packet to all available interfaces for browsing. + */ +static void _mdns_browse_send(mdns_browse_t *browse, mdns_if_t interface) +{ + // Using search once for sending the PTR query + mdns_search_once_t search = {0}; + + search.instance = NULL; + search.service = browse->service; + search.proto = browse->proto; + search.type = MDNS_TYPE_PTR; + search.unicast = false; + search.result = NULL; + search.next = NULL; + + for (uint8_t protocol_idx = 0; protocol_idx < MDNS_IP_PROTOCOL_MAX; protocol_idx++) { + _mdns_search_send_pcb(&search, interface, (mdns_ip_protocol_t)protocol_idx); + } +} + +/** + * @brief Add result to browse, only add when the result is a new one. + */ +static esp_err_t _mdns_add_browse_result(mdns_browse_sync_t *sync_browse, mdns_result_t *r) +{ + mdns_browse_result_sync_t *sync_r = sync_browse->sync_result; + while (sync_r) { + if (sync_r->result == r) { + break; + } + sync_r = sync_r->next; + } + if (!sync_r) { + // Do not find, need to add the result to the list + mdns_browse_result_sync_t *new = (mdns_browse_result_sync_t *)mdns_mem_malloc(sizeof(mdns_browse_result_sync_t)); + + if (!new) { + HOOK_MALLOC_FAILED; + return ESP_ERR_NO_MEM; + } + new->result = r; + new->next = sync_browse->sync_result; + sync_browse->sync_result = new; + } + return ESP_OK; +} + +/** + * @brief Called from parser to add A/AAAA data to search result + */ +static void _mdns_browse_result_add_ip(mdns_browse_t *browse, const char *hostname, esp_ip_addr_t *ip, + mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint32_t ttl, mdns_browse_sync_t *out_sync_browse) +{ + if (out_sync_browse->browse == NULL) { + return; + } else { + if (out_sync_browse->browse != browse) { + return; + } + } + mdns_result_t *r = NULL; + mdns_ip_addr_t *r_a = NULL; + if (browse) { + r = browse->result; + while (r) { + if (r->ip_protocol == ip_protocol) { + // Find the target result in browse result. + if (r->esp_netif == _mdns_get_esp_netif(tcpip_if) && !_str_null_or_empty(r->hostname) && !strcasecmp(hostname, r->hostname)) { + r_a = r->addr; + // Check if the address has already added in result. + while (r_a) { +#ifdef CONFIG_LWIP_IPV4 + if (r_a->addr.type == ip->type && r_a->addr.type == ESP_IPADDR_TYPE_V4 && r_a->addr.u_addr.ip4.addr == ip->u_addr.ip4.addr) { + break; + } +#endif +#ifdef CONFIG_LWIP_IPV6 + if (r_a->addr.type == ip->type && r_a->addr.type == ESP_IPADDR_TYPE_V6 && !memcmp(r_a->addr.u_addr.ip6.addr, ip->u_addr.ip6.addr, 16)) { + break; + } +#endif + r_a = r_a->next; + } + if (!r_a) { + // The current IP is a new one, add it to the link list. + mdns_ip_addr_t *a = NULL; + a = _mdns_result_addr_create_ip(ip); + if (!a) { + return; + } + a->next = r->addr; + r->addr = a; + if (r->ttl != ttl) { + if (r->ttl == 0) { + r->ttl = ttl; + } else { + _mdns_result_update_ttl(r, ttl); + } + } + if (_mdns_add_browse_result(out_sync_browse, r) != ESP_OK) { + return; + } + break; + } + } + } + r = r->next; + } + } + return; +} + +/** + * @brief Called from packet parser to find matching running search + */ +static mdns_browse_t *_mdns_browse_find_from(mdns_browse_t *b, mdns_name_t *name, uint16_t type, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +{ + // For browse, we only care about the SRV, TXT, A and AAAA + if (type != MDNS_TYPE_SRV && type != MDNS_TYPE_A && type != MDNS_TYPE_AAAA && type != MDNS_TYPE_TXT) { + return NULL; + } + mdns_result_t *r = NULL; + while (b) { + if (type == MDNS_TYPE_SRV || type == MDNS_TYPE_TXT) { + if (strcasecmp(name->service, b->service) + || strcasecmp(name->proto, b->proto)) { + b = b->next; + continue; + } + return b; + } else if (type == MDNS_TYPE_A || type == MDNS_TYPE_AAAA) { + r = b->result; + while (r) { + if (r->esp_netif == _mdns_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol && !_str_null_or_empty(r->hostname) && !strcasecmp(name->host, r->hostname)) { + return b; + } + r = r->next; + } + b = b->next; + continue; + } + } + return b; +} + +static bool is_txt_item_in_list(mdns_txt_item_t txt, uint8_t txt_value_len, mdns_txt_item_t *txt_list, uint8_t *txt_value_len_list, size_t txt_count) +{ + for (size_t i = 0; i < txt_count; i++) { + if (strcmp(txt.key, txt_list[i].key) == 0) { + if (txt_value_len == txt_value_len_list[i] && memcmp(txt.value, txt_list[i].value, txt_value_len) == 0) { + return true; + } else { + // The key value is unique, so there is no need to continue searching. + return false; + } + } + } + return false; +} + +/** + * @brief Called from parser to add TXT data to search result + */ +static void _mdns_browse_result_add_txt(mdns_browse_t *browse, const char *instance, const char *service, const char *proto, + mdns_txt_item_t *txt, uint8_t *txt_value_len, size_t txt_count, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, + uint32_t ttl, mdns_browse_sync_t *out_sync_browse) +{ + if (out_sync_browse->browse == NULL) { + return; + } else { + if (out_sync_browse->browse != browse) { + return; + } + } + mdns_result_t *r = browse->result; + while (r) { + if (r->esp_netif == _mdns_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol && + !_str_null_or_empty(r->instance_name) && !strcasecmp(instance, r->instance_name) && + !_str_null_or_empty(r->service_type) && !strcasecmp(service, r->service_type) && + !_str_null_or_empty(r->proto) && !strcasecmp(proto, r->proto)) { + bool should_update = false; + if (r->txt) { + // Check if txt changed + if (txt_count != r->txt_count) { + should_update = true; + } else { + for (size_t txt_index = 0; txt_index < txt_count; txt_index++) { + if (!is_txt_item_in_list(txt[txt_index], txt_value_len[txt_index], r->txt, r->txt_value_len, r->txt_count)) { + should_update = true; + break; + } + } + } + // If the result has a previous txt entry, we delete it and re-add. + for (size_t i = 0; i < r->txt_count; i++) { + mdns_mem_free((char *)(r->txt[i].key)); + mdns_mem_free((char *)(r->txt[i].value)); + } + mdns_mem_free(r->txt); + mdns_mem_free(r->txt_value_len); + } + r->txt = txt; + r->txt_value_len = txt_value_len; + r->txt_count = txt_count; + if (r->ttl != ttl) { + uint32_t previous_ttl = r->ttl; + if (r->ttl == 0) { + r->ttl = ttl; + } else { + _mdns_result_update_ttl(r, ttl); + } + if (previous_ttl != r->ttl) { + should_update = true; + } + } + if (should_update) { + if (_mdns_add_browse_result(out_sync_browse, r) != ESP_OK) { + return; + } + } + return; + } + r = r->next; + } + r = (mdns_result_t *)mdns_mem_malloc(sizeof(mdns_result_t)); + if (!r) { + HOOK_MALLOC_FAILED; + goto free_txt; + } + memset(r, 0, sizeof(mdns_result_t)); + r->instance_name = mdns_mem_strdup(instance); + r->service_type = mdns_mem_strdup(service); + r->proto = mdns_mem_strdup(proto); + if (!r->instance_name || !r->service_type || !r->proto) { + mdns_mem_free(r->instance_name); + mdns_mem_free(r->service_type); + mdns_mem_free(r->proto); + mdns_mem_free(r); + return; + } + r->txt = txt; + r->txt_value_len = txt_value_len; + r->txt_count = txt_count; + r->esp_netif = _mdns_get_esp_netif(tcpip_if); + r->ip_protocol = ip_protocol; + r->ttl = ttl; + r->next = browse->result; + browse->result = r; + _mdns_add_browse_result(out_sync_browse, r); + return; + +free_txt: + for (size_t i = 0; i < txt_count; i++) { + mdns_mem_free((char *)(txt[i].key)); + mdns_mem_free((char *)(txt[i].value)); + } + mdns_mem_free(txt); + mdns_mem_free(txt_value_len); + return; +} + +static esp_err_t _mdns_copy_address_in_previous_result(mdns_result_t *result_list, mdns_result_t *r) +{ + while (result_list) { + if (!_str_null_or_empty(result_list->hostname) && !_str_null_or_empty(r->hostname) && !strcasecmp(result_list->hostname, r->hostname) && + result_list->ip_protocol == r->ip_protocol && result_list->addr && !r->addr) { + // If there is a same hostname in previous result, we need to copy the address here. + r->addr = copy_address_list(result_list->addr); + if (!r->addr) { + return ESP_ERR_NO_MEM; + } + break; + } else { + result_list = result_list->next; + } + } + return ESP_OK; +} + +/** + * @brief Called from parser to add SRV data to search result + */ +static void _mdns_browse_result_add_srv(mdns_browse_t *browse, const char *hostname, const char *instance, const char *service, const char *proto, + uint16_t port, mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, uint32_t ttl, mdns_browse_sync_t *out_sync_browse) +{ + if (out_sync_browse->browse == NULL) { + return; + } else { + if (out_sync_browse->browse != browse) { + return; + } + } + mdns_result_t *r = browse->result; + while (r) { + if (r->esp_netif == _mdns_get_esp_netif(tcpip_if) && r->ip_protocol == ip_protocol && + !_str_null_or_empty(r->instance_name) && !strcasecmp(instance, r->instance_name) && + !_str_null_or_empty(r->service_type) && !strcasecmp(service, r->service_type) && + !_str_null_or_empty(r->proto) && !strcasecmp(proto, r->proto)) { + if (_str_null_or_empty(r->hostname) || strcasecmp(hostname, r->hostname)) { + r->hostname = mdns_mem_strdup(hostname); + r->port = port; + if (!r->hostname) { + HOOK_MALLOC_FAILED; + return; + } + if (!r->addr) { + esp_err_t err = _mdns_copy_address_in_previous_result(browse->result, r); + if (err == ESP_ERR_NO_MEM) { + return; + } + } + if (_mdns_add_browse_result(out_sync_browse, r) != ESP_OK) { + return; + } + } + if (r->ttl != ttl) { + uint32_t previous_ttl = r->ttl; + if (r->ttl == 0) { + r->ttl = ttl; + } else { + _mdns_result_update_ttl(r, ttl); + } + if (previous_ttl != r->ttl) { + if (_mdns_add_browse_result(out_sync_browse, r) != ESP_OK) { + return; + } + } + } + return; + } + r = r->next; + } + r = (mdns_result_t *)mdns_mem_malloc(sizeof(mdns_result_t)); + if (!r) { + HOOK_MALLOC_FAILED; + return; + } + + memset(r, 0, sizeof(mdns_result_t)); + r->hostname = mdns_mem_strdup(hostname); + r->instance_name = mdns_mem_strdup(instance); + r->service_type = mdns_mem_strdup(service); + r->proto = mdns_mem_strdup(proto); + if (!r->hostname || !r->instance_name || !r->service_type || !r->proto) { + HOOK_MALLOC_FAILED; + mdns_mem_free(r->hostname); + mdns_mem_free(r->instance_name); + mdns_mem_free(r->service_type); + mdns_mem_free(r->proto); + mdns_mem_free(r); + return; + } + r->port = port; + r->esp_netif = _mdns_get_esp_netif(tcpip_if); + r->ip_protocol = ip_protocol; + r->ttl = ttl; + r->next = browse->result; + browse->result = r; + _mdns_add_browse_result(out_sync_browse, r); + return; +} + +static void _mdns_browse_sync(mdns_browse_sync_t *browse_sync) +{ + mdns_browse_t *browse = browse_sync->browse; + mdns_browse_result_sync_t *sync_result = browse_sync->sync_result; + while (sync_result) { + mdns_result_t *result = sync_result->result; +#ifdef MDNS_ENABLE_DEBUG + debug_printf_browse_result(result, browse_sync->browse); +#endif + browse->notifier(result); + if (result->ttl == 0) { + queueDetach(mdns_result_t, browse->result, result); + // Just free current result + result->next = NULL; + mdns_query_results_free(result); + } + sync_result = sync_result->next; + } +} + +#ifdef MDNS_ENABLE_DEBUG +void _debug_printf_result(mdns_result_t *r_t) +{ + mdns_ip_addr_t *r_a = NULL; + int addr_count = 0; + _mdns_dbg_printf("result esp_netif: %p\n", r_t->esp_netif); + _mdns_dbg_printf("result ip_protocol: %d\n", r_t->ip_protocol); + _mdns_dbg_printf("result hostname: %s\n", _str_null_or_empty(r_t->hostname) ? "NULL" : r_t->hostname); + _mdns_dbg_printf("result instance_name: %s\n", _str_null_or_empty(r_t->instance_name) ? "NULL" : r_t->instance_name); + _mdns_dbg_printf("result service_type: %s\n", _str_null_or_empty(r_t->service_type) ? "NULL" : r_t->service_type); + _mdns_dbg_printf("result proto: %s\n", _str_null_or_empty(r_t->proto) ? "NULL" : r_t->proto); + _mdns_dbg_printf("result port: %d\n", r_t->port); + _mdns_dbg_printf("result ttl: %" PRIu32 "\n", r_t->ttl); + for (int i = 0; i < r_t->txt_count; i++) { + _mdns_dbg_printf("result txt item%d, key: %s, value: %s\n", i, r_t->txt[i].key, r_t->txt[i].value); + } + r_a = r_t->addr; + while (r_a) { +#ifdef CONFIG_LWIP_IPV4 + if (r_a->addr.type == ESP_IPADDR_TYPE_V4) { + _mdns_dbg_printf("Addr%d: " IPSTR "\n", addr_count++, IP2STR(&r_a->addr.u_addr.ip4)); + } +#endif +#ifdef CONFIG_LWIP_IPV6 + if (r_a->addr.type == ESP_IPADDR_TYPE_V6) { + _mdns_dbg_printf("Addr%d: " IPV6STR "\n", addr_count++, IPV62STR(r_a->addr.u_addr.ip6)); + } +#endif + r_a = r_a->next; + } +} + +static void debug_printf_browse_result(mdns_result_t *r_t, mdns_browse_t *b_t) +{ + _mdns_dbg_printf("----------------sync browse %s.%s result---------------\n", b_t->service, b_t->proto); + _mdns_dbg_printf("browse pointer: %p\n", b_t); + _debug_printf_result(r_t); +} + +static void debug_printf_browse_result_all(mdns_result_t *r_t) +{ + int count = 0; + while (r_t) { + _mdns_dbg_printf("----------------result %d---------------\n", count++); + _debug_printf_result(r_t); + r_t = r_t->next; + } +} +#endif // MDNS_ENABLE_DEBUG diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/mdns_console.c b/RainMaker_Table-Lights/managed_components/espressif__mdns/mdns_console.c new file mode 100644 index 000000000..b3448ff92 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__mdns/mdns_console.c @@ -0,0 +1,1452 @@ +/* + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include "esp_console.h" +#include "argtable3/argtable3.h" +#include "mdns.h" +#include "mdns_private.h" +#include "inttypes.h" +#include "mdns_mem_caps.h" + +static const char *ip_protocol_str[] = {"V4", "V6", "MAX"}; + +static void mdns_print_results(mdns_result_t *results) +{ + mdns_result_t *r = results; + mdns_ip_addr_t *a = NULL; + int i = 1; + while (r) { + if (r->esp_netif) { + printf("%d: Interface: %s, Type: %s, TTL: %" PRIu32 "\n", i++, esp_netif_get_ifkey(r->esp_netif), + ip_protocol_str[r->ip_protocol], r->ttl); + } + if (r->instance_name) { + printf(" PTR : %s\n", r->instance_name); + } + if (r->hostname) { + printf(" SRV : %s.local:%u\n", r->hostname, r->port); + } + if (r->txt_count) { + printf(" TXT : [%u] ", (int)r->txt_count); + for (size_t t = 0; t < r->txt_count; t++) { + printf("%s=%s; ", r->txt[t].key, r->txt[t].value); + } + printf("\n"); + } + a = r->addr; + while (a) { + if (a->addr.type == ESP_IPADDR_TYPE_V6) { + printf(" AAAA: " IPV6STR "\n", IPV62STR(a->addr.u_addr.ip6)); + } else { + printf(" A : " IPSTR "\n", IP2STR(&(a->addr.u_addr.ip4))); + } + a = a->next; + } + r = r->next; + } +} + +static struct { + struct arg_str *hostname; + struct arg_int *timeout; + struct arg_end *end; +} mdns_query_a_args; + +#ifdef CONFIG_LWIP_IPV4 +static int cmd_mdns_query_a(int argc, char **argv) +{ + int nerrors = arg_parse(argc, argv, (void **) &mdns_query_a_args); + if (nerrors != 0) { + arg_print_errors(stderr, mdns_query_a_args.end, argv[0]); + return 1; + } + + const char *hostname = mdns_query_a_args.hostname->sval[0]; + int timeout = mdns_query_a_args.timeout->ival[0]; + + if (!hostname || !hostname[0]) { + printf("ERROR: Hostname not supplied\n"); + return 1; + } + + if (timeout <= 0) { + timeout = 1000; + } + + printf("Query A: %s.local, Timeout: %d\n", hostname, timeout); + + struct esp_ip4_addr addr; + addr.addr = 0; + + esp_err_t err = mdns_query_a(hostname, timeout, &addr); + if (err) { + if (err == ESP_ERR_NOT_FOUND) { + printf("ERROR: Host was not found!\n"); + return 0; + } + printf("ERROR: Query Failed\n"); + return 1; + } + + printf(IPSTR "\n", IP2STR(&addr)); + + return 0; +} + +static void register_mdns_query_a(void) +{ + mdns_query_a_args.hostname = arg_str1(NULL, NULL, "", "Hostname that is searched for"); + mdns_query_a_args.timeout = arg_int0("t", "timeout", "", "Timeout for this query"); + mdns_query_a_args.end = arg_end(2); + + const esp_console_cmd_t cmd_init = { + .command = "mdns_query_a", + .help = "Query MDNS for IPv4", + .hint = NULL, + .func = &cmd_mdns_query_a, + .argtable = &mdns_query_a_args + }; + + ESP_ERROR_CHECK(esp_console_cmd_register(&cmd_init)); +} +#endif /* CONFIG_LWIP_IPV4 */ + +#ifdef CONFIG_LWIP_IPV6 +static int cmd_mdns_query_aaaa(int argc, char **argv) +{ + int nerrors = arg_parse(argc, argv, (void **) &mdns_query_a_args); + if (nerrors != 0) { + arg_print_errors(stderr, mdns_query_a_args.end, argv[0]); + return 1; + } + + const char *hostname = mdns_query_a_args.hostname->sval[0]; + int timeout = mdns_query_a_args.timeout->ival[0]; + + if (!hostname || !hostname[0]) { + printf("ERROR: Hostname not supplied\n"); + return 1; + } + + if (timeout <= 0) { + timeout = 1000; + } + + printf("Query AAAA: %s.local, Timeout: %d\n", hostname, timeout); + + struct esp_ip6_addr addr; + memset(addr.addr, 0, 16); + + esp_err_t err = mdns_query_aaaa(hostname, timeout, &addr); + if (err) { + if (err == ESP_ERR_NOT_FOUND) { + printf("Host was not found!\n"); + return 0; + } + printf("ERROR: Query Failed\n"); + return 1; + } + + printf(IPV6STR "\n", IPV62STR(addr)); + + return 0; +} + +static void register_mdns_query_aaaa(void) +{ + mdns_query_a_args.hostname = arg_str1(NULL, NULL, "", "Hostname that is searched for"); + mdns_query_a_args.timeout = arg_int0("t", "timeout", "", "Timeout for this query"); + mdns_query_a_args.end = arg_end(2); + + const esp_console_cmd_t cmd_init = { + .command = "mdns_query_aaaa", + .help = "Query MDNS for IPv6", + .hint = NULL, + .func = &cmd_mdns_query_aaaa, + .argtable = &mdns_query_a_args + }; + + ESP_ERROR_CHECK(esp_console_cmd_register(&cmd_init)); +} +#endif /* CONFIG_LWIP_IPV6 */ + +static struct { + struct arg_str *instance; + struct arg_str *service; + struct arg_str *proto; + struct arg_int *timeout; + struct arg_end *end; +} mdns_query_srv_args; + +static int cmd_mdns_query_srv(int argc, char **argv) +{ + int nerrors = arg_parse(argc, argv, (void **) &mdns_query_srv_args); + if (nerrors != 0) { + arg_print_errors(stderr, mdns_query_srv_args.end, argv[0]); + return 1; + } + + const char *instance = mdns_query_srv_args.instance->sval[0]; + const char *service = mdns_query_srv_args.service->sval[0]; + const char *proto = mdns_query_srv_args.proto->sval[0]; + int timeout = mdns_query_srv_args.timeout->ival[0]; + + if (timeout <= 0) { + timeout = 1000; + } + + printf("Query SRV: %s.%s.%s.local, Timeout: %d\n", instance, service, proto, timeout); + + mdns_result_t *results = NULL; + esp_err_t err = mdns_query_srv(instance, service, proto, timeout, &results); + if (err) { + printf("ERROR: Query Failed\n"); + return 1; + } + if (!results) { + printf("No results found!\n"); + return 0; + } + mdns_print_results(results); + mdns_query_results_free(results); + return 0; +} + +static void register_mdns_query_srv(void) +{ + mdns_query_srv_args.instance = arg_str1(NULL, NULL, "", "Instance to search for"); + mdns_query_srv_args.service = arg_str1(NULL, NULL, "", "Service to search for (ex. _http, _smb, etc.)"); + mdns_query_srv_args.proto = arg_str1(NULL, NULL, "", "Protocol to search for (_tcp, _udp, etc.)"); + mdns_query_srv_args.timeout = arg_int0("t", "timeout", "", "Timeout for this query"); + mdns_query_srv_args.end = arg_end(2); + + const esp_console_cmd_t cmd_init = { + .command = "mdns_query_srv", + .help = "Query MDNS for Service SRV", + .hint = NULL, + .func = &cmd_mdns_query_srv, + .argtable = &mdns_query_srv_args + }; + + ESP_ERROR_CHECK(esp_console_cmd_register(&cmd_init)); +} + +static struct { + struct arg_str *instance; + struct arg_str *service; + struct arg_str *proto; + struct arg_int *timeout; + struct arg_end *end; +} mdns_query_txt_args; + +static int cmd_mdns_query_txt(int argc, char **argv) +{ + int nerrors = arg_parse(argc, argv, (void **) &mdns_query_txt_args); + if (nerrors != 0) { + arg_print_errors(stderr, mdns_query_txt_args.end, argv[0]); + return 1; + } + + const char *instance = mdns_query_txt_args.instance->sval[0]; + const char *service = mdns_query_txt_args.service->sval[0]; + const char *proto = mdns_query_txt_args.proto->sval[0]; + int timeout = mdns_query_txt_args.timeout->ival[0]; + + printf("Query TXT: %s.%s.%s.local, Timeout: %d\n", instance, service, proto, timeout); + + if (timeout <= 0) { + timeout = 5000; + } + + mdns_result_t *results = NULL; + esp_err_t err = mdns_query_txt(instance, service, proto, timeout, &results); + if (err) { + printf("ERROR: Query Failed\n"); + return 1; + } + if (!results) { + printf("No results found!\n"); + return 0; + } + + mdns_print_results(results); + mdns_query_results_free(results); + return 0; +} + +static void register_mdns_query_txt(void) +{ + mdns_query_txt_args.instance = arg_str1(NULL, NULL, "", "Instance to search for"); + mdns_query_txt_args.service = arg_str1(NULL, NULL, "", "Service to search for (ex. _http, _smb, etc.)"); + mdns_query_txt_args.proto = arg_str1(NULL, NULL, "", "Protocol to search for (_tcp, _udp, etc.)"); + mdns_query_txt_args.timeout = arg_int0("t", "timeout", "", "Timeout for this query"); + mdns_query_txt_args.end = arg_end(2); + + const esp_console_cmd_t cmd_init = { + .command = "mdns_query_txt", + .help = "Query MDNS for Service TXT", + .hint = NULL, + .func = &cmd_mdns_query_txt, + .argtable = &mdns_query_txt_args + }; + + ESP_ERROR_CHECK(esp_console_cmd_register(&cmd_init)); +} + +static struct { + struct arg_str *service; + struct arg_str *proto; + struct arg_int *timeout; + struct arg_int *max_results; + struct arg_end *end; +} mdns_query_ptr_args; + +static int cmd_mdns_query_ptr(int argc, char **argv) +{ + int nerrors = arg_parse(argc, argv, (void **) &mdns_query_ptr_args); + if (nerrors != 0) { + arg_print_errors(stderr, mdns_query_ptr_args.end, argv[0]); + return 1; + } + + const char *service = mdns_query_ptr_args.service->sval[0]; + const char *proto = mdns_query_ptr_args.proto->sval[0]; + int timeout = mdns_query_ptr_args.timeout->ival[0]; + int max_results = mdns_query_ptr_args.max_results->ival[0]; + + if (timeout <= 0) { + timeout = 5000; + } + + if (max_results <= 0 || max_results > 255) { + max_results = 255; + } + + printf("Query PTR: %s.%s.local, Timeout: %d, Max Results: %d\n", service, proto, timeout, max_results); + + mdns_result_t *results = NULL; + esp_err_t err = mdns_query_ptr(service, proto, timeout, max_results, &results); + if (err) { + printf("ERROR: Query Failed\n"); + return 1; + } + if (!results) { + printf("No results found!\n"); + return 0; + } + + mdns_print_results(results); + mdns_query_results_free(results); + return 0; +} + +static void register_mdns_query_ptr(void) +{ + mdns_query_ptr_args.service = arg_str1(NULL, NULL, "", "Service to search for (ex. _http, _smb, etc.)"); + mdns_query_ptr_args.proto = arg_str1(NULL, NULL, "", "Protocol to search for (_tcp, _udp, etc.)"); + mdns_query_ptr_args.timeout = arg_int0("t", "timeout", "", "Timeout for this query"); + mdns_query_ptr_args.max_results = arg_int0("m", "max_results", "", "Maximum results returned"); + mdns_query_ptr_args.end = arg_end(2); + + const esp_console_cmd_t cmd_init = { + .command = "mdns_query_ptr", + .help = "Query MDNS for Service", + .hint = NULL, + .func = &cmd_mdns_query_ptr, + .argtable = &mdns_query_ptr_args + }; + + ESP_ERROR_CHECK(esp_console_cmd_register(&cmd_init)); +} + +static struct { + struct arg_str *hostname; + struct arg_int *timeout; + struct arg_int *max_results; + struct arg_end *end; +} mdns_query_ip_args; + +static int cmd_mdns_query_ip(int argc, char **argv) +{ + int nerrors = arg_parse(argc, argv, (void **) &mdns_query_ip_args); + if (nerrors != 0) { + arg_print_errors(stderr, mdns_query_ip_args.end, argv[0]); + return 1; + } + + const char *hostname = mdns_query_ip_args.hostname->sval[0]; + int timeout = mdns_query_ip_args.timeout->ival[0]; + int max_results = mdns_query_ip_args.max_results->ival[0]; + + if (!hostname || !hostname[0]) { + printf("ERROR: Hostname not supplied\n"); + return 1; + } + + if (timeout <= 0) { + timeout = 1000; + } + + if (max_results < 0 || max_results > 255) { + max_results = 255; + } + + printf("Query IP: %s.local, Timeout: %d, Max Results: %d\n", hostname, timeout, max_results); + + mdns_result_t *results = NULL; + esp_err_t err = mdns_query(hostname, NULL, NULL, MDNS_TYPE_ANY, timeout, max_results, &results); + if (err) { + printf("ERROR: Query Failed\n"); + return 1; + } + if (!results) { + printf("No results found!\n"); + return 0; + } + mdns_print_results(results); + mdns_query_results_free(results); + + return 0; +} + +static void register_mdns_query_ip(void) +{ + mdns_query_ip_args.hostname = arg_str1(NULL, NULL, "", "Hostname that is searched for"); + mdns_query_ip_args.timeout = arg_int0("t", "timeout", "", "Timeout for this query"); + mdns_query_ip_args.max_results = arg_int0("m", "max_results", "", "Maximum results returned"); + mdns_query_ip_args.end = arg_end(2); + + const esp_console_cmd_t cmd_init = { + .command = "mdns_query_ip", + .help = "Query MDNS for IP", + .hint = NULL, + .func = &cmd_mdns_query_ip, + .argtable = &mdns_query_ip_args + }; + + ESP_ERROR_CHECK(esp_console_cmd_register(&cmd_init)); +} + +static struct { + struct arg_str *instance; + struct arg_str *service; + struct arg_str *proto; + struct arg_int *timeout; + struct arg_int *max_results; + struct arg_end *end; +} mdns_query_svc_args; + +static int cmd_mdns_query_svc(int argc, char **argv) +{ + int nerrors = arg_parse(argc, argv, (void **) &mdns_query_svc_args); + if (nerrors != 0) { + arg_print_errors(stderr, mdns_query_svc_args.end, argv[0]); + return 1; + } + + const char *instance = mdns_query_svc_args.instance->sval[0]; + const char *service = mdns_query_svc_args.service->sval[0]; + const char *proto = mdns_query_svc_args.proto->sval[0]; + int timeout = mdns_query_svc_args.timeout->ival[0]; + int max_results = mdns_query_svc_args.max_results->ival[0]; + + if (timeout <= 0) { + timeout = 5000; + } + + if (max_results < 0 || max_results > 255) { + max_results = 255; + } + + printf("Query SVC: %s.%s.%s.local, Timeout: %d, Max Results: %d\n", instance, service, proto, timeout, max_results); + + mdns_result_t *results = NULL; + esp_err_t err = mdns_query(instance, service, proto, MDNS_TYPE_ANY, timeout, max_results, &results); + if (err) { + printf("ERROR: Query Failed\n"); + return 1; + } + if (!results) { + printf("No results found!\n"); + return 0; + } + + mdns_print_results(results); + mdns_query_results_free(results); + return 0; +} + +static void register_mdns_query_svc(void) +{ + mdns_query_svc_args.instance = arg_str1(NULL, NULL, "", "Instance to search for"); + mdns_query_svc_args.service = arg_str1(NULL, NULL, "", "Service to search for (ex. _http, _smb, etc.)"); + mdns_query_svc_args.proto = arg_str1(NULL, NULL, "", "Protocol to search for (_tcp, _udp, etc.)"); + mdns_query_svc_args.timeout = arg_int0("t", "timeout", "", "Timeout for this query"); + mdns_query_svc_args.max_results = arg_int0("m", "max_results", "", "Maximum results returned"); + mdns_query_svc_args.end = arg_end(2); + + const esp_console_cmd_t cmd_init = { + .command = "mdns_query_svc", + .help = "Query MDNS for Service TXT & SRV", + .hint = NULL, + .func = &cmd_mdns_query_svc, + .argtable = &mdns_query_svc_args + }; + + ESP_ERROR_CHECK(esp_console_cmd_register(&cmd_init)); +} + +static struct { + struct arg_str *hostname; + struct arg_str *instance; + struct arg_end *end; +} mdns_init_args; + +static int cmd_mdns_init(int argc, char **argv) +{ + int nerrors = arg_parse(argc, argv, (void **) &mdns_init_args); + if (nerrors != 0) { + arg_print_errors(stderr, mdns_init_args.end, argv[0]); + return 1; + } + + ESP_ERROR_CHECK(mdns_init()); + + if (mdns_init_args.hostname->sval[0]) { + ESP_ERROR_CHECK(mdns_hostname_set(mdns_init_args.hostname->sval[0])); + printf("MDNS: Hostname: %s\n", mdns_init_args.hostname->sval[0]); + } + + if (mdns_init_args.instance->count) { + ESP_ERROR_CHECK(mdns_instance_name_set(mdns_init_args.instance->sval[0])); + printf("MDNS: Instance: %s\n", mdns_init_args.instance->sval[0]); + } + + return 0; +} + +static void register_mdns_init(void) +{ + mdns_init_args.hostname = arg_str0("h", "hostname", "", "Hostname that the server will advertise"); + mdns_init_args.instance = arg_str0("i", "instance", "", "Default instance name for services"); + mdns_init_args.end = arg_end(2); + + const esp_console_cmd_t cmd_init = { + .command = "mdns_init", + .help = "Start MDNS Server", + .hint = NULL, + .func = &cmd_mdns_init, + .argtable = &mdns_init_args + }; + + ESP_ERROR_CHECK(esp_console_cmd_register(&cmd_init)); +} + +static int cmd_mdns_free(int argc, char **argv) +{ + mdns_free(); + return 0; +} + +static void register_mdns_free(void) +{ + const esp_console_cmd_t cmd_free = { + .command = "mdns_free", + .help = "Stop MDNS Server", + .hint = NULL, + .func = &cmd_mdns_free, + .argtable = NULL + }; + + ESP_ERROR_CHECK(esp_console_cmd_register(&cmd_free)); +} + +static struct { + struct arg_str *hostname; + struct arg_end *end; +} mdns_set_hostname_args; + +static int cmd_mdns_set_hostname(int argc, char **argv) +{ + int nerrors = arg_parse(argc, argv, (void **) &mdns_set_hostname_args); + if (nerrors != 0) { + arg_print_errors(stderr, mdns_set_hostname_args.end, argv[0]); + return 1; + } + + if (mdns_set_hostname_args.hostname->sval[0] == NULL) { + printf("ERROR: Bad arguments!\n"); + return 1; + } + + ESP_ERROR_CHECK(mdns_hostname_set(mdns_set_hostname_args.hostname->sval[0])); + return 0; +} + +static void register_mdns_set_hostname(void) +{ + mdns_set_hostname_args.hostname = arg_str1(NULL, NULL, "", "Hostname that the server will advertise"); + mdns_set_hostname_args.end = arg_end(2); + + const esp_console_cmd_t cmd_set_hostname = { + .command = "mdns_set_hostname", + .help = "Set MDNS Server hostname", + .hint = NULL, + .func = &cmd_mdns_set_hostname, + .argtable = &mdns_set_hostname_args + }; + + ESP_ERROR_CHECK(esp_console_cmd_register(&cmd_set_hostname)); +} + +static struct { + struct arg_str *instance; + struct arg_end *end; +} mdns_set_instance_args; + +static int cmd_mdns_set_instance(int argc, char **argv) +{ + int nerrors = arg_parse(argc, argv, (void **) &mdns_set_instance_args); + if (nerrors != 0) { + arg_print_errors(stderr, mdns_set_instance_args.end, argv[0]); + return 1; + } + + if (mdns_set_instance_args.instance->sval[0] == NULL) { + printf("ERROR: Bad arguments!\n"); + return 1; + } + + ESP_ERROR_CHECK(mdns_instance_name_set(mdns_set_instance_args.instance->sval[0])); + return 0; +} + +static void register_mdns_set_instance(void) +{ + mdns_set_instance_args.instance = arg_str1(NULL, NULL, "", "Default instance name for services"); + mdns_set_instance_args.end = arg_end(2); + + const esp_console_cmd_t cmd_set_instance = { + .command = "mdns_set_instance", + .help = "Set MDNS Server Istance Name", + .hint = NULL, + .func = &cmd_mdns_set_instance, + .argtable = &mdns_set_instance_args + }; + + ESP_ERROR_CHECK(esp_console_cmd_register(&cmd_set_instance)); +} + +static mdns_txt_item_t *_convert_items(const char **values, int count) +{ + int i = 0, e; + const char *value = NULL; + mdns_txt_item_t *items = (mdns_txt_item_t *) mdns_mem_malloc(sizeof(mdns_txt_item_t) * count); + if (!items) { + printf("ERROR: No Memory!\n"); + goto fail; + + } + memset(items, 0, sizeof(mdns_txt_item_t) * count); + + for (i = 0; i < count; i++) { + value = values[i]; + char *esign = strchr(value, '='); + if (!esign) { + printf("ERROR: Equal sign not found in '%s'!\n", value); + goto fail; + } + int var_len = esign - value; + int val_len = strlen(value) - var_len - 1; + char *var = (char *)mdns_mem_malloc(var_len + 1); + if (var == NULL) { + printf("ERROR: No Memory!\n"); + goto fail; + } + char *val = (char *)mdns_mem_malloc(val_len + 1); + if (val == NULL) { + printf("ERROR: No Memory!\n"); + mdns_mem_free(var); + goto fail; + } + memcpy(var, value, var_len); + var[var_len] = 0; + memcpy(val, esign + 1, val_len); + val[val_len] = 0; + + items[i].key = var; + items[i].value = val; + } + + return items; + +fail: + for (e = 0; e < i; e++) { + mdns_mem_free((char *)items[e].key); + mdns_mem_free((char *)items[e].value); + } + mdns_mem_free(items); + return NULL; +} + +static struct { + struct arg_str *service; + struct arg_str *proto; + struct arg_int *port; + struct arg_str *instance; + struct arg_str *host; + struct arg_str *txt; + struct arg_end *end; +} mdns_add_args; + +static int cmd_mdns_service_add(int argc, char **argv) +{ + int nerrors = arg_parse(argc, argv, (void **) &mdns_add_args); + if (nerrors != 0) { + arg_print_errors(stderr, mdns_add_args.end, argv[0]); + return 1; + } + + if (!mdns_add_args.service->sval[0] || !mdns_add_args.proto->sval[0] || !mdns_add_args.port->ival[0]) { + printf("ERROR: Bad arguments!\n"); + return 1; + } + const char *instance = NULL; + if (mdns_add_args.instance->sval[0] && mdns_add_args.instance->sval[0][0]) { + instance = mdns_add_args.instance->sval[0]; + printf("MDNS: Service Instance: %s\n", instance); + } + const char *host = NULL; + if (mdns_add_args.host->count && mdns_add_args.host->sval[0]) { + host = mdns_add_args.host->sval[0]; + printf("MDNS: Service for delegated host: %s\n", host); + } + mdns_txt_item_t *items = NULL; + if (mdns_add_args.txt->count) { + items = _convert_items(mdns_add_args.txt->sval, mdns_add_args.txt->count); + if (!items) { + printf("ERROR: No Memory!\n"); + return 1; + + } + } + + ESP_ERROR_CHECK(mdns_service_add_for_host(instance, mdns_add_args.service->sval[0], mdns_add_args.proto->sval[0], + host, mdns_add_args.port->ival[0], items, mdns_add_args.txt->count)); + mdns_mem_free(items); + return 0; +} + +static void register_mdns_service_add(void) +{ + mdns_add_args.service = arg_str1(NULL, NULL, "", "MDNS Service"); + mdns_add_args.proto = arg_str1(NULL, NULL, "", "IP Protocol"); + mdns_add_args.port = arg_int1(NULL, NULL, "", "Service Port"); + mdns_add_args.instance = arg_str0("i", "instance", "", "Instance name"); + mdns_add_args.host = arg_str0("h", "host", "", "Service for this (delegated) host"); + mdns_add_args.txt = arg_strn(NULL, NULL, "item", 0, 30, "TXT Items (name=value)"); + mdns_add_args.end = arg_end(2); + + const esp_console_cmd_t cmd_add = { + .command = "mdns_service_add", + .help = "Add service to MDNS", + .hint = NULL, + .func = &cmd_mdns_service_add, + .argtable = &mdns_add_args + }; + + ESP_ERROR_CHECK(esp_console_cmd_register(&cmd_add)); +} + +static struct { + struct arg_str *instance; + struct arg_str *service; + struct arg_str *proto; + struct arg_str *host; + struct arg_end *end; +} mdns_remove_args; + +static int cmd_mdns_service_remove(int argc, char **argv) +{ + int nerrors = arg_parse(argc, argv, (void **) &mdns_remove_args); + if (nerrors != 0) { + arg_print_errors(stderr, mdns_remove_args.end, argv[0]); + return 1; + } + + if (!mdns_remove_args.service->sval[0] || !mdns_remove_args.proto->sval[0]) { + printf("ERROR: Bad arguments!\n"); + return 1; + } + + const char *instance = NULL; + if (mdns_remove_args.instance->count && mdns_remove_args.instance->sval[0]) { + instance = mdns_remove_args.instance->sval[0]; + } + const char *host = NULL; + if (mdns_remove_args.host->count && mdns_remove_args.host->sval[0]) { + host = mdns_remove_args.host->sval[0]; + } + + ESP_ERROR_CHECK(mdns_service_remove_for_host(instance, mdns_remove_args.service->sval[0], mdns_remove_args.proto->sval[0], host)); + return 0; +} + +static void register_mdns_service_remove(void) +{ + mdns_remove_args.service = arg_str1(NULL, NULL, "", "MDNS Service"); + mdns_remove_args.proto = arg_str1(NULL, NULL, "", "IP Protocol"); + mdns_remove_args.host = arg_str0("h", "host", "", "Service for this (delegated) host"); + mdns_remove_args.instance = arg_str0("i", "instance", "", "Instance name"); + mdns_remove_args.end = arg_end(4); + + const esp_console_cmd_t cmd_remove = { + .command = "mdns_service_remove", + .help = "Remove service from MDNS", + .hint = NULL, + .func = &cmd_mdns_service_remove, + .argtable = &mdns_remove_args + }; + + ESP_ERROR_CHECK(esp_console_cmd_register(&cmd_remove)); +} + +static struct { + struct arg_str *service; + struct arg_str *proto; + struct arg_str *instance; + struct arg_str *host; + struct arg_str *old_instance; + struct arg_end *end; +} mdns_service_instance_set_args; + +static int cmd_mdns_service_instance_set(int argc, char **argv) +{ + int nerrors = arg_parse(argc, argv, (void **) &mdns_service_instance_set_args); + if (nerrors != 0) { + arg_print_errors(stderr, mdns_service_instance_set_args.end, argv[0]); + return 1; + } + + if (!mdns_service_instance_set_args.service->sval[0] || !mdns_service_instance_set_args.proto->sval[0] || !mdns_service_instance_set_args.instance->sval[0]) { + printf("ERROR: Bad arguments!\n"); + return 1; + } + const char *host = NULL; + if (mdns_service_instance_set_args.host->count && mdns_service_instance_set_args.host->sval[0]) { + host = mdns_service_instance_set_args.host->sval[0]; + } + const char *old_instance = NULL; + if (mdns_service_instance_set_args.old_instance->count && mdns_service_instance_set_args.old_instance->sval[0]) { + old_instance = mdns_service_instance_set_args.old_instance->sval[0]; + } + esp_err_t err = mdns_service_instance_name_set_for_host(old_instance, mdns_service_instance_set_args.service->sval[0], mdns_service_instance_set_args.proto->sval[0], host, mdns_service_instance_set_args.instance->sval[0]); + if (err != ESP_OK) { + printf("mdns_service_instance_name_set_for_host() failed with %s\n", esp_err_to_name(err)); + return 1; + } + + return 0; +} + +static void register_mdns_service_instance_set(void) +{ + mdns_service_instance_set_args.service = arg_str1(NULL, NULL, "", "MDNS Service"); + mdns_service_instance_set_args.proto = arg_str1(NULL, NULL, "", "IP Protocol"); + mdns_service_instance_set_args.instance = arg_str1(NULL, NULL, "", "Instance name"); + mdns_service_instance_set_args.host = arg_str0("h", "host", "", "Service for this (delegated) host"); + mdns_service_instance_set_args.old_instance = arg_str0("i", "old_instance", "", "Instance name before update"); + mdns_service_instance_set_args.end = arg_end(4); + + const esp_console_cmd_t cmd_add = { + .command = "mdns_service_instance_set", + .help = "Set MDNS Service Instance Name", + .hint = NULL, + .func = &cmd_mdns_service_instance_set, + .argtable = &mdns_service_instance_set_args + }; + + ESP_ERROR_CHECK(esp_console_cmd_register(&cmd_add)); +} + +static struct { + struct arg_str *service; + struct arg_str *proto; + struct arg_int *port; + struct arg_str *host; + struct arg_str *instance; + struct arg_end *end; +} mdns_service_port_set_args; + +static int cmd_mdns_service_port_set(int argc, char **argv) +{ + int nerrors = arg_parse(argc, argv, (void **) &mdns_service_port_set_args); + if (nerrors != 0) { + arg_print_errors(stderr, mdns_service_port_set_args.end, argv[0]); + return 1; + } + + if (!mdns_service_port_set_args.service->sval[0] || !mdns_service_port_set_args.proto->sval[0] || !mdns_service_port_set_args.port->ival[0]) { + printf("ERROR: Bad arguments!\n"); + return 1; + } + + const char *host = NULL; + if (mdns_service_port_set_args.host->count && mdns_service_port_set_args.host->sval[0]) { + host = mdns_service_port_set_args.host->sval[0]; + } + const char *instance = NULL; + if (mdns_service_port_set_args.instance->count && mdns_service_port_set_args.instance->sval[0]) { + instance = mdns_service_port_set_args.instance->sval[0]; + } + esp_err_t err = mdns_service_port_set_for_host(instance, mdns_service_port_set_args.service->sval[0], mdns_service_port_set_args.proto->sval[0], host, mdns_service_port_set_args.port->ival[0]); + if (err != ESP_OK) { + printf("mdns_service_port_set_for_host() failed with %s\n", esp_err_to_name(err)); + return 1; + } + return 0; +} + +static void register_mdns_service_port_set(void) +{ + mdns_service_port_set_args.service = arg_str1(NULL, NULL, "", "MDNS Service"); + mdns_service_port_set_args.proto = arg_str1(NULL, NULL, "", "IP Protocol"); + mdns_service_port_set_args.port = arg_int1(NULL, NULL, "", "Service Port"); + mdns_service_port_set_args.host = arg_str0("h", "host", "", "Service for this (delegated) host"); + mdns_service_port_set_args.instance = arg_str0("i", "instance", "", "Instance name"); + mdns_service_port_set_args.end = arg_end(2); + + const esp_console_cmd_t cmd_add = { + .command = "mdns_service_port_set", + .help = "Set MDNS Service port", + .hint = NULL, + .func = &cmd_mdns_service_port_set, + .argtable = &mdns_service_port_set_args + }; + + ESP_ERROR_CHECK(esp_console_cmd_register(&cmd_add)); +} + +static struct { + struct arg_str *service; + struct arg_str *proto; + struct arg_str *instance; + struct arg_str *host; + struct arg_str *txt; + struct arg_end *end; +} mdns_txt_replace_args; + +static int cmd_mdns_service_txt_replace(int argc, char **argv) +{ + mdns_txt_item_t *items = NULL; + int nerrors = arg_parse(argc, argv, (void **) &mdns_txt_replace_args); + if (nerrors != 0) { + arg_print_errors(stderr, mdns_txt_replace_args.end, argv[0]); + return 1; + } + + if (!mdns_txt_replace_args.service->sval[0] || !mdns_txt_replace_args.proto->sval[0]) { + printf("ERROR: Bad arguments!\n"); + return 1; + } + const char *instance = NULL; + if (mdns_txt_replace_args.instance->count && mdns_txt_replace_args.instance->sval[0]) { + instance = mdns_txt_replace_args.instance->sval[0]; + printf("MDNS: Service Instance: %s\n", instance); + } + const char *host = NULL; + if (mdns_txt_replace_args.host->count && mdns_txt_replace_args.host->sval[0]) { + host = mdns_txt_replace_args.host->sval[0]; + printf("MDNS: Service for delegated host: %s\n", host); + } + if (mdns_txt_replace_args.txt->count) { + items = _convert_items(mdns_txt_replace_args.txt->sval, mdns_txt_replace_args.txt->count); + if (!items) { + printf("ERROR: No Memory!\n"); + return 1; + + } + } + ESP_ERROR_CHECK(mdns_service_txt_set_for_host(instance, mdns_txt_replace_args.service->sval[0], mdns_txt_replace_args.proto->sval[0], host, items, mdns_txt_replace_args.txt->count)); + mdns_mem_free(items); + return 0; +} + +static void register_mdns_service_txt_replace(void) +{ + mdns_txt_replace_args.service = arg_str1(NULL, NULL, "", "MDNS Service"); + mdns_txt_replace_args.proto = arg_str1(NULL, NULL, "", "IP Protocol"); + mdns_txt_replace_args.instance = arg_str0("i", "instance", "", "Instance name"); + mdns_txt_replace_args.host = arg_str0("h", "host", "", "Service for this (delegated) host"); + mdns_txt_replace_args.txt = arg_strn(NULL, NULL, "item", 0, 30, "TXT Items (name=value)"); + mdns_txt_replace_args.end = arg_end(5); + + const esp_console_cmd_t cmd_txt_set = { + .command = "mdns_service_txt_replace", + .help = "Replace MDNS service TXT items", + .hint = NULL, + .func = &cmd_mdns_service_txt_replace, + .argtable = &mdns_txt_replace_args + }; + + ESP_ERROR_CHECK(esp_console_cmd_register(&cmd_txt_set)); +} + +static struct { + struct arg_str *service; + struct arg_str *proto; + struct arg_str *instance; + struct arg_str *host; + struct arg_str *var; + struct arg_str *value; + struct arg_end *end; +} mdns_txt_set_args; + +static int cmd_mdns_service_txt_set(int argc, char **argv) +{ + int nerrors = arg_parse(argc, argv, (void **) &mdns_txt_set_args); + if (nerrors != 0) { + arg_print_errors(stderr, mdns_txt_set_args.end, argv[0]); + return 1; + } + + if (!mdns_txt_set_args.service->sval[0] || !mdns_txt_set_args.proto->sval[0] || !mdns_txt_set_args.var->sval[0]) { + printf("ERROR: Bad arguments!\n"); + return 1; + } + const char *instance = NULL; + if (mdns_txt_set_args.instance->count && mdns_txt_set_args.instance->sval[0]) { + instance = mdns_txt_set_args.instance->sval[0]; + printf("MDNS: Service Instance: %s\n", instance); + } + const char *host = NULL; + if (mdns_txt_set_args.host->count && mdns_txt_set_args.host->sval[0]) { + host = mdns_txt_set_args.host->sval[0]; + printf("MDNS: Service for delegated host: %s\n", host); + } + + ESP_ERROR_CHECK(mdns_service_txt_item_set_for_host(instance, mdns_txt_set_args.service->sval[0], mdns_txt_set_args.proto->sval[0], host, mdns_txt_set_args.var->sval[0], mdns_txt_set_args.value->sval[0])); + return 0; +} + +static void register_mdns_service_txt_set(void) +{ + mdns_txt_set_args.service = arg_str1(NULL, NULL, "", "MDNS Service"); + mdns_txt_set_args.proto = arg_str1(NULL, NULL, "", "IP Protocol"); + mdns_txt_set_args.var = arg_str1(NULL, NULL, "", "Item Name"); + mdns_txt_set_args.value = arg_str1(NULL, NULL, "", "Item Value"); + mdns_txt_set_args.instance = arg_str0("i", "instance", "", "Instance name"); + mdns_txt_set_args.host = arg_str0("h", "host", "", "Service for this (delegated) host"); + mdns_txt_set_args.end = arg_end(6); + + const esp_console_cmd_t cmd_txt_set = { + .command = "mdns_service_txt_set", + .help = "Add/Set MDNS service TXT item", + .hint = NULL, + .func = &cmd_mdns_service_txt_set, + .argtable = &mdns_txt_set_args + }; + + ESP_ERROR_CHECK(esp_console_cmd_register(&cmd_txt_set)); +} + +static struct { + struct arg_str *service; + struct arg_str *proto; + struct arg_str *var; + struct arg_str *instance; + struct arg_str *host; + struct arg_end *end; +} mdns_txt_remove_args; + +static int cmd_mdns_service_txt_remove(int argc, char **argv) +{ + int nerrors = arg_parse(argc, argv, (void **) &mdns_txt_remove_args); + if (nerrors != 0) { + arg_print_errors(stderr, mdns_txt_remove_args.end, argv[0]); + return 1; + } + + if (!mdns_txt_remove_args.service->sval[0] || !mdns_txt_remove_args.proto->sval[0] || !mdns_txt_remove_args.var->sval[0]) { + printf("ERROR: Bad arguments!\n"); + return 1; + } + const char *instance = NULL; + if (mdns_txt_remove_args.instance->count && mdns_txt_remove_args.instance->sval[0]) { + instance = mdns_txt_remove_args.instance->sval[0]; + } + const char *host = NULL; + if (mdns_txt_remove_args.host->count && mdns_txt_remove_args.host->sval[0]) { + host = mdns_txt_remove_args.host->sval[0]; + } + ESP_ERROR_CHECK(mdns_service_txt_item_remove_for_host(instance, mdns_txt_remove_args.service->sval[0], mdns_txt_remove_args.proto->sval[0], host, mdns_txt_remove_args.var->sval[0])); + return 0; +} + +static void register_mdns_service_txt_remove(void) +{ + mdns_txt_remove_args.service = arg_str1(NULL, NULL, "", "MDNS Service"); + mdns_txt_remove_args.proto = arg_str1(NULL, NULL, "", "IP Protocol"); + mdns_txt_remove_args.var = arg_str1(NULL, NULL, "", "Item Name"); + mdns_txt_remove_args.instance = arg_str0("i", "instance", "", "Instance name"); + mdns_txt_remove_args.host = arg_str0("h", "host", "", "Service for this (delegated) host"); + mdns_txt_remove_args.end = arg_end(2); + + const esp_console_cmd_t cmd_txt_remove = { + .command = "mdns_service_txt_remove", + .help = "Remove MDNS service TXT item", + .hint = NULL, + .func = &cmd_mdns_service_txt_remove, + .argtable = &mdns_txt_remove_args + }; + + ESP_ERROR_CHECK(esp_console_cmd_register(&cmd_txt_remove)); +} + +static int cmd_mdns_service_remove_all(int argc, char **argv) +{ + mdns_service_remove_all(); + return 0; +} + +static void register_mdns_service_remove_all(void) +{ + const esp_console_cmd_t cmd_free = { + .command = "mdns_service_remove_all", + .help = "Remove all MDNS services", + .hint = NULL, + .func = &cmd_mdns_service_remove_all, + .argtable = NULL + }; + + ESP_ERROR_CHECK(esp_console_cmd_register(&cmd_free)); +} + +#define MDNS_MAX_LOOKUP_RESULTS CONFIG_MDNS_MAX_SERVICES + +static struct { + struct arg_str *instance; + struct arg_str *service; + struct arg_str *proto; + struct arg_lit *delegated; + struct arg_end *end; +} mdns_lookup_service_args; + +static esp_err_t lookup_service(const char *instance, const char *service, const char *proto, size_t max_results, + mdns_result_t **result, bool delegated) +{ + if (delegated) { + return mdns_lookup_delegated_service(instance, service, proto, max_results, result); + } + return mdns_lookup_selfhosted_service(instance, service, proto, max_results, result); +} + +static int cmd_mdns_lookup_service(int argc, char **argv) +{ + int nerrors = arg_parse(argc, argv, (void **) &mdns_lookup_service_args); + if (nerrors != 0) { + arg_print_errors(stderr, mdns_lookup_service_args.end, argv[0]); + return 1; + } + + if (!mdns_lookup_service_args.instance->sval[0] || !mdns_lookup_service_args.service->sval[0] || !mdns_lookup_service_args.proto->sval[0]) { + printf("ERROR: Bad arguments!\n"); + return 1; + } + mdns_result_t *results = NULL; + esp_err_t err = lookup_service(mdns_lookup_service_args.instance->count ? mdns_lookup_service_args.instance->sval[0] : NULL, + mdns_lookup_service_args.service->sval[0], mdns_lookup_service_args.proto->sval[0], + MDNS_MAX_LOOKUP_RESULTS, &results, mdns_lookup_service_args.delegated->count); + if (err) { + printf("Service lookup failed\n"); + return 1; + } + if (!results) { + printf("No results found!\n"); + return 0; + } + mdns_print_results(results); + mdns_query_results_free(results); + return 0; +} + +static void register_mdns_lookup_service(void) +{ + mdns_lookup_service_args.service = arg_str1(NULL, NULL, "", "MDNS Service"); + mdns_lookup_service_args.proto = arg_str1(NULL, NULL, "", "IP Protocol"); + mdns_lookup_service_args.instance = arg_str0("i", "instance", "", "Instance name"); + mdns_lookup_service_args.delegated = arg_lit0("d", "delegated", "Lookup delegated services"); + mdns_lookup_service_args.end = arg_end(4); + + const esp_console_cmd_t cmd_lookup_service = { + .command = "mdns_service_lookup", + .help = "Lookup registered service", + .hint = NULL, + .func = &cmd_mdns_lookup_service, + .argtable = &mdns_lookup_service_args + }; + + ESP_ERROR_CHECK(esp_console_cmd_register(&cmd_lookup_service)); +} + +static struct { + struct arg_str *hostname; + struct arg_str *address; + struct arg_end *end; +} mdns_delegate_host_args; + +static int cmd_mdns_delegate_host(int argc, char **argv) +{ + int nerrors = arg_parse(argc, argv, (void **) &mdns_delegate_host_args); + if (nerrors != 0) { + arg_print_errors(stderr, mdns_delegate_host_args.end, argv[0]); + return 1; + } + + if (!mdns_delegate_host_args.hostname->sval[0] || !mdns_delegate_host_args.address->sval[0]) { + printf("ERROR: Bad arguments!\n"); + return 1; + } + + mdns_ip_addr_t addr = { .next = NULL}; + esp_netif_str_to_ip4(mdns_delegate_host_args.address->sval[0], &addr.addr.u_addr.ip4); + addr.addr.type = ESP_IPADDR_TYPE_V4; + + esp_err_t err = mdns_delegate_hostname_add(mdns_delegate_host_args.hostname->sval[0], &addr); + if (err) { + printf("mdns_delegate_hostname_add() failed\n"); + return 1; + } + return 0; +} + +static void register_mdns_delegate_host(void) +{ + mdns_delegate_host_args.hostname = arg_str1(NULL, NULL, "", "Delegated hostname"); + mdns_delegate_host_args.address = arg_str1(NULL, NULL, "
", "Delegated hosts address"); + mdns_delegate_host_args.end = arg_end(2); + + const esp_console_cmd_t cmd_delegate_host = { + .command = "mdns_delegate_host", + .help = "Add delegated hostname", + .hint = NULL, + .func = &cmd_mdns_delegate_host, + .argtable = &mdns_delegate_host_args + }; + + ESP_ERROR_CHECK(esp_console_cmd_register(&cmd_delegate_host)); +} + +static struct { + struct arg_str *hostname; + struct arg_end *end; +} mdns_undelegate_host_args; + +static int cmd_mdns_undelegate_host(int argc, char **argv) +{ + int nerrors = arg_parse(argc, argv, (void **) &mdns_undelegate_host_args); + if (nerrors != 0) { + arg_print_errors(stderr, mdns_undelegate_host_args.end, argv[0]); + return 1; + } + + if (!mdns_undelegate_host_args.hostname->sval[0]) { + printf("ERROR: Bad arguments!\n"); + return 1; + } + + if (mdns_delegate_hostname_remove(mdns_undelegate_host_args.hostname->sval[0]) != ESP_OK) { + printf("mdns_delegate_hostname_remove() failed\n"); + return 1; + } + return 0; +} + +static void register_mdns_undelegate_host(void) +{ + mdns_undelegate_host_args.hostname = arg_str1(NULL, NULL, "", "Delegated hostname"); + mdns_undelegate_host_args.end = arg_end(2); + + const esp_console_cmd_t cmd_undelegate_host = { + .command = "mdns_undelegate_host", + .help = "Remove delegated hostname", + .hint = NULL, + .func = &cmd_mdns_undelegate_host, + .argtable = &mdns_undelegate_host_args + }; + + ESP_ERROR_CHECK(esp_console_cmd_register(&cmd_undelegate_host)); +} + +static struct { + struct arg_str *service; + struct arg_str *proto; + struct arg_str *sub; + struct arg_str *instance; + struct arg_str *host; + struct arg_end *end; +} mdns_service_subtype_args; + +static int cmd_mdns_service_subtype(int argc, char **argv) +{ + int nerrors = arg_parse(argc, argv, (void **) &mdns_service_subtype_args); + if (nerrors != 0) { + arg_print_errors(stderr, mdns_service_subtype_args.end, argv[0]); + return 1; + } + + if (!mdns_service_subtype_args.service->sval[0] || !mdns_service_subtype_args.proto->sval[0] || !mdns_service_subtype_args.sub->sval[0]) { + printf("ERROR: Bad arguments!\n"); + return 1; + } + const char *instance = NULL; + if (mdns_service_subtype_args.instance->count && mdns_service_subtype_args.instance->sval[0]) { + instance = mdns_service_subtype_args.instance->sval[0]; + } + const char *host = NULL; + if (mdns_service_subtype_args.host->count && mdns_service_subtype_args.host->sval[0]) { + host = mdns_service_subtype_args.host->sval[0]; + } + ESP_ERROR_CHECK(mdns_service_subtype_add_for_host(instance, mdns_service_subtype_args.service->sval[0], mdns_service_subtype_args.proto->sval[0], host, mdns_service_subtype_args.sub->sval[0])); + return 0; +} + +static void register_mdns_service_subtype_set(void) +{ + mdns_service_subtype_args.service = arg_str1(NULL, NULL, "", "MDNS Service"); + mdns_service_subtype_args.proto = arg_str1(NULL, NULL, "", "IP Protocol"); + mdns_service_subtype_args.sub = arg_str1(NULL, NULL, "", "Subtype"); + mdns_service_subtype_args.instance = arg_str0("i", "instance", "", "Instance name"); + mdns_service_subtype_args.host = arg_str0("h", "host", "", "Service for this (delegated) host"); + mdns_service_subtype_args.end = arg_end(5); + + const esp_console_cmd_t cmd_service_sub = { + .command = "mdns_service_subtype", + .help = "Adds subtype for service", + .hint = NULL, + .func = &cmd_mdns_service_subtype, + .argtable = &mdns_service_subtype_args + }; + + ESP_ERROR_CHECK(esp_console_cmd_register(&cmd_service_sub)); +} + +static struct { + struct arg_str *service; + struct arg_str *proto; + struct arg_end *end; +} mdns_browse_args; + +static void mdns_browse_notifier(mdns_result_t *result) +{ + if (result) { + mdns_print_results(result); + } +} + +static int cmd_mdns_browse(int argc, char **argv) +{ + int nerrors = arg_parse(argc, argv, (void **) &mdns_browse_args); + if (nerrors != 0) { + arg_print_errors(stderr, mdns_browse_args.end, argv[0]); + return 1; + } + + if (!mdns_browse_args.service->sval[0] || !mdns_browse_args.proto->sval[0]) { + printf("ERROR: Bad arguments!\n"); + return 1; + } + mdns_browse_t *handle = mdns_browse_new(mdns_browse_args.service->sval[0], mdns_browse_args.proto->sval[0], mdns_browse_notifier); + return handle ? 0 : 1; +} + +static void register_mdns_browse(void) +{ + mdns_browse_args.service = arg_str1(NULL, NULL, "", "MDNS Service"); + mdns_browse_args.proto = arg_str1(NULL, NULL, "", "IP Protocol"); + mdns_browse_args.end = arg_end(2); + + const esp_console_cmd_t cmd_browse = { + .command = "mdns_browse", + .help = "Start browsing", + .hint = NULL, + .func = &cmd_mdns_browse, + .argtable = &mdns_browse_args + }; + + ESP_ERROR_CHECK(esp_console_cmd_register(&cmd_browse)); +} + +static int cmd_mdns_browse_del(int argc, char **argv) +{ + int nerrors = arg_parse(argc, argv, (void **) &mdns_browse_args); + if (nerrors != 0) { + arg_print_errors(stderr, mdns_browse_args.end, argv[0]); + return 1; + } + + if (!mdns_browse_args.service->sval[0] || !mdns_browse_args.proto->sval[0]) { + printf("ERROR: Bad arguments!\n"); + return 1; + } + esp_err_t err = mdns_browse_delete(mdns_browse_args.service->sval[0], mdns_browse_args.proto->sval[0]); + return err == ESP_OK ? 0 : 1; +} + +static void register_mdns_browse_del(void) +{ + mdns_browse_args.service = arg_str1(NULL, NULL, "", "MDNS Service"); + mdns_browse_args.proto = arg_str1(NULL, NULL, "", "IP Protocol"); + mdns_browse_args.end = arg_end(2); + + const esp_console_cmd_t cmd_browse_del = { + .command = "mdns_browse_del", + .help = "Stop browsing", + .hint = NULL, + .func = &cmd_mdns_browse_del, + .argtable = &mdns_browse_args + }; + + ESP_ERROR_CHECK(esp_console_cmd_register(&cmd_browse_del)); +} + +void mdns_console_register(void) +{ + register_mdns_init(); + register_mdns_free(); + register_mdns_set_hostname(); + register_mdns_set_instance(); + register_mdns_service_add(); + register_mdns_service_remove(); + register_mdns_service_instance_set(); + register_mdns_service_port_set(); + register_mdns_service_txt_replace(); + register_mdns_service_txt_set(); + register_mdns_service_txt_remove(); + register_mdns_service_remove_all(); + + register_mdns_lookup_service(); + register_mdns_delegate_host(); + register_mdns_undelegate_host(); + register_mdns_service_subtype_set(); + + register_mdns_browse(); + register_mdns_browse_del(); + +#ifdef CONFIG_LWIP_IPV4 + register_mdns_query_a(); +#endif +#ifdef CONFIG_LWIP_IPV6 + register_mdns_query_aaaa(); +#endif + register_mdns_query_txt(); + register_mdns_query_srv(); + register_mdns_query_ptr(); + + register_mdns_query_ip(); + register_mdns_query_svc(); +} diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/mdns_mem_caps.c b/RainMaker_Table-Lights/managed_components/espressif__mdns/mdns_mem_caps.c new file mode 100644 index 000000000..78bdbc1f6 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__mdns/mdns_mem_caps.c @@ -0,0 +1,96 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include "sdkconfig.h" +#include "mdns_private.h" +#include "mdns_mem_caps.h" +#include "esp_heap_caps.h" +#include "esp_log.h" + +#if CONFIG_MDNS_MEMORY_CUSTOM_IMPL +#define ALLOW_WEAK __attribute__((weak)) +#else +#define ALLOW_WEAK +#endif + +#if CONFIG_MDNS_TASK_CREATE_FROM_SPIRAM +#define MDNS_TASK_MEMORY_CAPS (MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT) +#define MDNS_TASK_MEMORY_LOG "SPIRAM" +#endif +#if CONFIG_MDNS_TASK_CREATE_FROM_INTERNAL +#define MDNS_TASK_MEMORY_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT) +#define MDNS_TASK_MEMORY_LOG "internal RAM" +#endif + +#if CONFIG_MDNS_MEMORY_ALLOC_SPIRAM +#define MDNS_MEMORY_CAPS (MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT) +#endif +#if CONFIG_MDNS_MEMORY_ALLOC_INTERNAL +#define MDNS_MEMORY_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT) +#endif + +// Allocate memory from internal heap as default. +#ifndef MDNS_MEMORY_CAPS +#warning "No memory allocation method defined, using internal memory" +#define MDNS_MEMORY_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT) +#endif +#ifndef MDNS_TASK_MEMORY_CAPS +#define MDNS_TASK_MEMORY_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT) +#define MDNS_TASK_MEMORY_LOG "internal RAM" +#endif + +void ALLOW_WEAK *mdns_mem_malloc(size_t size) +{ + return heap_caps_malloc(size, MDNS_MEMORY_CAPS); +} + +void ALLOW_WEAK *mdns_mem_calloc(size_t num, size_t size) +{ + return heap_caps_calloc(num, size, MDNS_MEMORY_CAPS); +} + +void ALLOW_WEAK mdns_mem_free(void *ptr) +{ + heap_caps_free(ptr); +} + +char ALLOW_WEAK *mdns_mem_strdup(const char *s) +{ + if (!s) { + return NULL; + } + size_t len = strlen(s) + 1; + char *copy = (char *)heap_caps_malloc(len, MDNS_MEMORY_CAPS); + if (copy) { + memcpy(copy, s, len); + } + return copy; +} + +char ALLOW_WEAK *mdns_mem_strndup(const char *s, size_t n) +{ + if (!s) { + return NULL; + } + size_t len = strnlen(s, n); + char *copy = (char *)heap_caps_malloc(len + 1, MDNS_MEMORY_CAPS); + if (copy) { + memcpy(copy, s, len); + copy[len] = '\0'; + } + return copy; +} + +void ALLOW_WEAK *mdns_mem_task_malloc(size_t size) +{ + ESP_LOGI("mdns_mem", "mDNS task will be created from %s", MDNS_TASK_MEMORY_LOG); + return heap_caps_malloc(size, MDNS_TASK_MEMORY_CAPS); +} + +void ALLOW_WEAK mdns_mem_task_free(void *ptr) +{ + heap_caps_free(ptr); +} diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/mdns_networking_lwip.c b/RainMaker_Table-Lights/managed_components/espressif__mdns/mdns_networking_lwip.c new file mode 100644 index 000000000..a68672764 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__mdns/mdns_networking_lwip.c @@ -0,0 +1,398 @@ +/* + * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * MDNS Server Networking + * + */ +#include +#include "esp_log.h" +#include "lwip/ip_addr.h" +#include "lwip/pbuf.h" +#include "lwip/igmp.h" +#include "lwip/udp.h" +#include "lwip/mld6.h" +#include "lwip/priv/tcpip_priv.h" +#include "esp_system.h" +#include "esp_event.h" +#include "mdns_networking.h" +#include "esp_netif_net_stack.h" +#include "mdns_mem_caps.h" + +/* + * MDNS Server Networking + * + */ +enum interface_protocol { + PROTO_IPV4 = 1 << MDNS_IP_PROTOCOL_V4, + PROTO_IPV6 = 1 << MDNS_IP_PROTOCOL_V6 +}; + +typedef struct interfaces { + bool ready; + int proto; +} interfaces_t; + +static interfaces_t s_interfaces[MDNS_MAX_INTERFACES]; + +static struct udp_pcb *_pcb_main = NULL; + +static const char *TAG = "mdns_networking"; + +static void _udp_recv(void *arg, struct udp_pcb *upcb, struct pbuf *pb, const ip_addr_t *raddr, uint16_t rport); + +/** + * @brief Low level UDP PCB Initialize + */ +static esp_err_t _udp_pcb_main_init(void) +{ + if (_pcb_main) { + return ESP_OK; + } + _pcb_main = udp_new(); + if (!_pcb_main) { + return ESP_ERR_NO_MEM; + } + if (udp_bind(_pcb_main, IP_ANY_TYPE, MDNS_SERVICE_PORT) != 0) { + udp_remove(_pcb_main); + _pcb_main = NULL; + return ESP_ERR_INVALID_STATE; + } + _pcb_main->mcast_ttl = 255; + _pcb_main->remote_port = MDNS_SERVICE_PORT; + ip_addr_copy(_pcb_main->remote_ip, *(IP_ANY_TYPE)); + udp_recv(_pcb_main, &_udp_recv, NULL); + return ESP_OK; +} + +/** + * @brief Low level UDP PCB Free + */ +static void _udp_pcb_main_deinit(void) +{ + if (_pcb_main) { + udp_recv(_pcb_main, NULL, NULL); + udp_disconnect(_pcb_main); + udp_remove(_pcb_main); + _pcb_main = NULL; + } +} + +/** + * @brief Low level UDP Multicast membership control + */ +static esp_err_t _udp_join_group(mdns_if_t if_inx, mdns_ip_protocol_t ip_protocol, bool join) +{ + struct netif *netif = NULL; + esp_netif_t *tcpip_if = _mdns_get_esp_netif(if_inx); + + if (!esp_netif_is_netif_up(tcpip_if)) { + // Network interface went down before event propagated, skipping IGMP config + return ESP_ERR_INVALID_STATE; + } + + netif = esp_netif_get_netif_impl(tcpip_if); + assert(netif); + +#if LWIP_IPV4 + if (ip_protocol == MDNS_IP_PROTOCOL_V4) { + ip4_addr_t multicast_addr; + IP4_ADDR(&multicast_addr, 224, 0, 0, 251); + + if (join) { + if (igmp_joingroup_netif(netif, &multicast_addr)) { + return ESP_ERR_INVALID_STATE; + } + } else { + if (igmp_leavegroup_netif(netif, &multicast_addr)) { + return ESP_ERR_INVALID_STATE; + } + } + } +#endif // LWIP_IPV4 +#if LWIP_IPV6 + if (ip_protocol == MDNS_IP_PROTOCOL_V6) { + ip_addr_t multicast_addr = IPADDR6_INIT(0x000002ff, 0, 0, 0xfb000000); + + if (join) { + if (mld6_joingroup_netif(netif, ip_2_ip6(&multicast_addr))) { + return ESP_ERR_INVALID_STATE; + } + } else { + if (mld6_leavegroup_netif(netif, ip_2_ip6(&multicast_addr))) { + return ESP_ERR_INVALID_STATE; + } + } + } +#endif // LWIP_IPV6 + return ESP_OK; +} + +/** + * @brief the receive callback of the raw udp api. Packets are received here + * + */ +static void _udp_recv(void *arg, struct udp_pcb *upcb, struct pbuf *pb, const ip_addr_t *raddr, uint16_t rport) +{ + + uint8_t i; + while (pb != NULL) { + struct pbuf *this_pb = pb; + pb = pb->next; + this_pb->next = NULL; + + mdns_rx_packet_t *packet = (mdns_rx_packet_t *)mdns_mem_malloc(sizeof(mdns_rx_packet_t)); + if (!packet) { + HOOK_MALLOC_FAILED; + //missed packet - no memory + pbuf_free(this_pb); + continue; + } + + packet->tcpip_if = MDNS_MAX_INTERFACES; + packet->pb = this_pb; + packet->src_port = rport; +#if LWIP_IPV4 && LWIP_IPV6 + packet->src.type = raddr->type; + memcpy(&packet->src.u_addr, &raddr->u_addr, sizeof(raddr->u_addr)); +#elif LWIP_IPV4 + packet->src.type = IPADDR_TYPE_V4; + packet->src.u_addr.ip4.addr = raddr->addr; +#elif LWIP_IPV6 + packet->src.type = IPADDR_TYPE_V6; + memcpy(&packet->src.u_addr.ip6, raddr, sizeof(ip_addr_t)); +#endif + packet->dest.type = packet->src.type; + +#if LWIP_IPV4 + if (packet->src.type == IPADDR_TYPE_V4) { + packet->ip_protocol = MDNS_IP_PROTOCOL_V4; + struct ip_hdr *iphdr = (struct ip_hdr *)(((uint8_t *)(packet->pb->payload)) - UDP_HLEN - IP_HLEN); + packet->dest.u_addr.ip4.addr = iphdr->dest.addr; + packet->multicast = ip4_addr_ismulticast(&(packet->dest.u_addr.ip4)); + } +#endif // LWIP_IPV4 +#if LWIP_IPV6 + if (packet->src.type == IPADDR_TYPE_V6) { + packet->ip_protocol = MDNS_IP_PROTOCOL_V6; + struct ip6_hdr *ip6hdr = (struct ip6_hdr *)(((uint8_t *)(packet->pb->payload)) - UDP_HLEN - IP6_HLEN); + memcpy(&packet->dest.u_addr.ip6.addr, (uint8_t *)ip6hdr->dest.addr, 16); + packet->multicast = ip6_addr_ismulticast(&(packet->dest.u_addr.ip6)); + } +#endif // LWIP_IPV6 + + //lwip does not return the proper pcb if you have more than one for the same multicast address (but different interfaces) + struct netif *netif = NULL; + bool found = false; + for (i = 0; i < MDNS_MAX_INTERFACES; i++) { + netif = esp_netif_get_netif_impl(_mdns_get_esp_netif(i)); + if (s_interfaces[i].proto && netif && netif == ip_current_input_netif()) { +#if LWIP_IPV4 + if (packet->src.type == IPADDR_TYPE_V4) { + if ((packet->src.u_addr.ip4.addr & ip_2_ip4(&netif->netmask)->addr) != (ip_2_ip4(&netif->ip_addr)->addr & ip_2_ip4(&netif->netmask)->addr)) { + //packet source is not in the same subnet + break; + } + } +#endif // LWIP_IPV4 + packet->tcpip_if = i; + found = true; + break; + } + } + + if (!found || _mdns_send_rx_action(packet) != ESP_OK) { + pbuf_free(this_pb); + mdns_mem_free(packet); + } + } + +} + +bool mdns_is_netif_ready(mdns_if_t netif, mdns_ip_protocol_t ip_proto) +{ + return s_interfaces[netif].ready && + s_interfaces[netif].proto & (ip_proto == MDNS_IP_PROTOCOL_V4 ? PROTO_IPV4 : PROTO_IPV6); +} + +/** + * @brief Check if any of the interfaces is up + */ +static bool _udp_pcb_is_in_use(void) +{ + int i, p; + for (i = 0; i < MDNS_MAX_INTERFACES; i++) { + for (p = 0; p < MDNS_IP_PROTOCOL_MAX; p++) { + if (mdns_is_netif_ready(i, p)) { + return true; + } + } + } + return false; +} + +/** + * @brief Stop PCB Main code + */ +static void _udp_pcb_deinit(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +{ + s_interfaces[tcpip_if].proto &= ~(ip_protocol == MDNS_IP_PROTOCOL_V4 ? PROTO_IPV4 : PROTO_IPV6); + if (s_interfaces[tcpip_if].proto == 0) { + s_interfaces[tcpip_if].ready = false; + _udp_join_group(tcpip_if, ip_protocol, false); + if (!_udp_pcb_is_in_use()) { + _udp_pcb_main_deinit(); + } + } +} + +/** + * @brief Start PCB Main code + */ +static esp_err_t _udp_pcb_init(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +{ + if (mdns_is_netif_ready(tcpip_if, ip_protocol)) { + return ESP_ERR_INVALID_STATE; + } + + esp_err_t err = _udp_join_group(tcpip_if, ip_protocol, true); + if (err) { + return err; + } + + err = _udp_pcb_main_init(); + if (err) { + return err; + } + s_interfaces[tcpip_if].proto |= (ip_protocol == MDNS_IP_PROTOCOL_V4 ? PROTO_IPV4 : PROTO_IPV6); + s_interfaces[tcpip_if].ready = true; + + return ESP_OK; +} + +typedef struct { + struct tcpip_api_call_data call; + mdns_if_t tcpip_if; + mdns_ip_protocol_t ip_protocol; + struct pbuf *pbt; + const ip_addr_t *ip; + uint16_t port; + esp_err_t err; +} mdns_api_call_t; + +/** + * @brief Start PCB from LwIP thread + */ +static err_t _mdns_pcb_init_api(struct tcpip_api_call_data *api_call_msg) +{ + mdns_api_call_t *msg = (mdns_api_call_t *)api_call_msg; + msg->err = _udp_pcb_init(msg->tcpip_if, msg->ip_protocol) == ESP_OK ? ERR_OK : ERR_IF; + return msg->err; +} + +/** + * @brief Stop PCB from LwIP thread + */ +static err_t _mdns_pcb_deinit_api(struct tcpip_api_call_data *api_call_msg) +{ + mdns_api_call_t *msg = (mdns_api_call_t *)api_call_msg; + _udp_pcb_deinit(msg->tcpip_if, msg->ip_protocol); + msg->err = ESP_OK; + return ESP_OK; +} + +/* + * Non-static functions below are + * - _mdns prefixed + * - commented in mdns_networking.h header + */ +esp_err_t _mdns_pcb_init(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +{ + mdns_api_call_t msg = { + .tcpip_if = tcpip_if, + .ip_protocol = ip_protocol + }; + tcpip_api_call(_mdns_pcb_init_api, &msg.call); + return msg.err; +} + +esp_err_t _mdns_pcb_deinit(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +{ + mdns_api_call_t msg = { + .tcpip_if = tcpip_if, + .ip_protocol = ip_protocol + }; + tcpip_api_call(_mdns_pcb_deinit_api, &msg.call); + return msg.err; +} + +static err_t _mdns_udp_pcb_write_api(struct tcpip_api_call_data *api_call_msg) +{ + void *nif = NULL; + mdns_api_call_t *msg = (mdns_api_call_t *)api_call_msg; + nif = esp_netif_get_netif_impl(_mdns_get_esp_netif(msg->tcpip_if)); + if (!nif || !mdns_is_netif_ready(msg->tcpip_if, msg->ip_protocol) || _pcb_main == NULL) { + pbuf_free(msg->pbt); + msg->err = ERR_IF; + return ERR_IF; + } + esp_err_t err = udp_sendto_if(_pcb_main, msg->pbt, msg->ip, msg->port, (struct netif *)nif); + pbuf_free(msg->pbt); + msg->err = err; + return err; +} + +size_t _mdns_udp_pcb_write(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, const esp_ip_addr_t *ip, uint16_t port, uint8_t *data, size_t len) +{ + struct pbuf *pbt = pbuf_alloc(PBUF_TRANSPORT, len, PBUF_RAM); + if (pbt == NULL) { + return 0; + } + memcpy((uint8_t *)pbt->payload, data, len); + + ip_addr_t ip_add_copy; +#if LWIP_IPV6 && LWIP_IPV4 + ip_add_copy.type = ip->type; + memcpy(&(ip_add_copy.u_addr), &(ip->u_addr), sizeof(ip_add_copy.u_addr)); +#elif LWIP_IPV4 + ip_add_copy.addr = ip->u_addr.ip4.addr; +#elif LWIP_IPV6 +#if LWIP_IPV6_SCOPES + ip_add_copy.zone = ip->u_addr.ip6.zone; +#endif // LWIP_IPV6_SCOPES + memcpy(ip_add_copy.addr, ip->u_addr.ip6.addr, sizeof(ip_add_copy.addr)); +#endif + + mdns_api_call_t msg = { + .tcpip_if = tcpip_if, + .ip_protocol = ip_protocol, + .pbt = pbt, + .ip = &ip_add_copy, + .port = port + }; + tcpip_api_call(_mdns_udp_pcb_write_api, &msg.call); + + if (msg.err) { + return 0; + } + return len; +} + +void *_mdns_get_packet_data(mdns_rx_packet_t *packet) +{ + return packet->pb->payload; +} + +size_t _mdns_get_packet_len(mdns_rx_packet_t *packet) +{ + return packet->pb->len; +} + +void _mdns_packet_free(mdns_rx_packet_t *packet) +{ + pbuf_free(packet->pb); + mdns_mem_free(packet); +} diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/mdns_networking_socket.c b/RainMaker_Table-Lights/managed_components/espressif__mdns/mdns_networking_socket.c new file mode 100644 index 000000000..7bcafbb9c --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__mdns/mdns_networking_socket.c @@ -0,0 +1,499 @@ +/* + * SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @brief MDNS Server Networking module implemented using BSD sockets + */ + +#include +#include "esp_event.h" +#include "mdns_networking.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "esp_log.h" +#include "mdns_mem_caps.h" + +#if defined(CONFIG_IDF_TARGET_LINUX) +#include +#include +#endif + +enum interface_protocol { + PROTO_IPV4 = 1 << MDNS_IP_PROTOCOL_V4, + PROTO_IPV6 = 1 << MDNS_IP_PROTOCOL_V6 +}; + +typedef struct interfaces { + int sock; + int proto; +} interfaces_t; + +static interfaces_t s_interfaces[MDNS_MAX_INTERFACES]; + +static const char *TAG = "mdns_networking"; +static bool s_run_sock_recv_task = false; +static int create_socket(esp_netif_t *netif); +static int join_mdns_multicast_group(int sock, esp_netif_t *netif, mdns_ip_protocol_t ip_protocol); + +#if defined(CONFIG_IDF_TARGET_LINUX) +// Need to define packet buffer struct on linux +struct pbuf { + struct pbuf *next; + void *payload; + size_t tot_len; + size_t len; +}; +#else +// Compatibility define to access sock-addr struct the same way for lwip and linux +#define s6_addr32 un.u32_addr +#endif // CONFIG_IDF_TARGET_LINUX + +static void __attribute__((constructor)) ctor_networking_socket(void) +{ + for (int i = 0; i < sizeof(s_interfaces) / sizeof(s_interfaces[0]); ++i) { + s_interfaces[i].sock = -1; + s_interfaces[i].proto = 0; + } +} + +static void delete_socket(int sock) +{ + close(sock); +} + +bool mdns_is_netif_ready(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +{ + return s_interfaces[tcpip_if].proto & (ip_protocol == MDNS_IP_PROTOCOL_V4 ? PROTO_IPV4 : PROTO_IPV6); +} + +void *_mdns_get_packet_data(mdns_rx_packet_t *packet) +{ + return packet->pb->payload; +} + +size_t _mdns_get_packet_len(mdns_rx_packet_t *packet) +{ + return packet->pb->len; +} + +void _mdns_packet_free(mdns_rx_packet_t *packet) +{ + mdns_mem_free(packet->pb->payload); + mdns_mem_free(packet->pb); + mdns_mem_free(packet); +} + +esp_err_t _mdns_pcb_deinit(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +{ + s_interfaces[tcpip_if].proto &= ~(ip_protocol == MDNS_IP_PROTOCOL_V4 ? PROTO_IPV4 : PROTO_IPV6); + if (s_interfaces[tcpip_if].proto == 0) { + // if the interface for both protocols uninitialized, close the interface socket + if (s_interfaces[tcpip_if].sock >= 0) { + delete_socket(s_interfaces[tcpip_if].sock); + } + } + + for (int i = 0; i < MDNS_MAX_INTERFACES; i++) { + if (s_interfaces[i].sock >= 0) { + // If any of the interfaces initialized + return ESP_OK; + } + } + + // no interface alive, stop the rx task + s_run_sock_recv_task = false; + vTaskDelay(pdMS_TO_TICKS(500)); + return ESP_OK; +} + +#if defined(CONFIG_IDF_TARGET_LINUX) +#ifdef CONFIG_LWIP_IPV6 +static char *inet6_ntoa_r(struct in6_addr addr, char *ptr, size_t size) +{ + inet_ntop(AF_INET6, &(addr.s6_addr32[0]), ptr, size); + return ptr; +} +#endif // CONFIG_LWIP_IPV6 +static char *inet_ntoa_r(struct in_addr addr, char *ptr, size_t size) +{ + char *res = inet_ntoa(addr); + if (res && strlen(res) < size) { + strcpy(ptr, res); + } + return res; +} +#endif // CONFIG_IDF_TARGET_LINUX + +static inline char *get_string_address(struct sockaddr_storage *source_addr) +{ + static char address_str[40]; // 40=(8*4+7+term) is the max size of ascii IPv6 addr "XXXX:XX...XX:XXXX" + char *res = NULL; + // Convert ip address to string +#ifdef CONFIG_LWIP_IPV4 + if (source_addr->ss_family == PF_INET) { + res = inet_ntoa_r(((struct sockaddr_in *)source_addr)->sin_addr, address_str, sizeof(address_str)); + } +#endif +#ifdef CONFIG_LWIP_IPV6 + if (source_addr->ss_family == PF_INET6) { + res = inet6_ntoa_r(((struct sockaddr_in6 *)source_addr)->sin6_addr, address_str, sizeof(address_str)); + } +#endif + if (!res) { + address_str[0] = '\0'; // Returns empty string if conversion didn't succeed + } + return address_str; +} + + +static inline size_t espaddr_to_inet(const esp_ip_addr_t *addr, const uint16_t port, const mdns_ip_protocol_t ip_protocol, struct sockaddr_storage *in_addr) +{ + size_t ss_addr_len = 0; + memset(in_addr, 0, sizeof(struct sockaddr_storage)); +#ifdef CONFIG_LWIP_IPV4 + if (ip_protocol == MDNS_IP_PROTOCOL_V4 && addr->type == ESP_IPADDR_TYPE_V4) { + in_addr->ss_family = PF_INET; +#if !defined(CONFIG_IDF_TARGET_LINUX) + in_addr->s2_len = sizeof(struct sockaddr_in); +#endif + ss_addr_len = sizeof(struct sockaddr_in); + struct sockaddr_in *in_addr_ip4 = (struct sockaddr_in *) in_addr; + in_addr_ip4->sin_port = port; + in_addr_ip4->sin_addr.s_addr = addr->u_addr.ip4.addr; + } +#endif // CONFIG_LWIP_IPV4 +#ifdef CONFIG_LWIP_IPV6 + if (ip_protocol == MDNS_IP_PROTOCOL_V6 && addr->type == ESP_IPADDR_TYPE_V6) { + memset(in_addr, 0, sizeof(struct sockaddr_storage)); + in_addr->ss_family = PF_INET6; +#if !defined(CONFIG_IDF_TARGET_LINUX) + in_addr->s2_len = sizeof(struct sockaddr_in6); +#endif + ss_addr_len = sizeof(struct sockaddr_in6); + struct sockaddr_in6 *in_addr_ip6 = (struct sockaddr_in6 *)in_addr; + uint32_t *u32_addr = in_addr_ip6->sin6_addr.s6_addr32; + in_addr_ip6->sin6_port = port; + u32_addr[0] = addr->u_addr.ip6.addr[0]; + u32_addr[1] = addr->u_addr.ip6.addr[1]; + u32_addr[2] = addr->u_addr.ip6.addr[2]; + u32_addr[3] = addr->u_addr.ip6.addr[3]; + } +#endif // CONFIG_LWIP_IPV6 + return ss_addr_len; +} + +size_t _mdns_udp_pcb_write(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, const esp_ip_addr_t *ip, uint16_t port, uint8_t *data, size_t len) +{ + if (!(s_interfaces[tcpip_if].proto & (ip_protocol == MDNS_IP_PROTOCOL_V4 ? PROTO_IPV4 : PROTO_IPV6))) { + return 0; + } + int sock = s_interfaces[tcpip_if].sock; + if (sock < 0) { + return 0; + } + struct sockaddr_storage in_addr; + size_t ss_size = espaddr_to_inet(ip, htons(port), ip_protocol, &in_addr); + if (!ss_size) { + ESP_LOGE(TAG, "espaddr_to_inet() failed: Mismatch of IP protocols"); + return 0; + } + ESP_LOGD(TAG, "[sock=%d]: Sending to IP %s port %d", sock, get_string_address(&in_addr), port); + ssize_t actual_len = sendto(sock, data, len, 0, (struct sockaddr *)&in_addr, ss_size); + if (actual_len < 0) { + ESP_LOGE(TAG, "[sock=%d]: _mdns_udp_pcb_write sendto() has failed\n errno=%d: %s", sock, errno, strerror(errno)); + } + return actual_len; +} + +static inline void inet_to_espaddr(const struct sockaddr_storage *in_addr, esp_ip_addr_t *addr, uint16_t *port) +{ +#ifdef CONFIG_LWIP_IPV4 + if (in_addr->ss_family == PF_INET) { + struct sockaddr_in *in_addr_ip4 = (struct sockaddr_in *)in_addr; + memset(addr, 0, sizeof(esp_ip_addr_t)); + *port = in_addr_ip4->sin_port; + addr->u_addr.ip4.addr = in_addr_ip4->sin_addr.s_addr; + addr->type = ESP_IPADDR_TYPE_V4; + } +#endif /* CONFIG_LWIP_IPV4 */ +#ifdef CONFIG_LWIP_IPV6 + if (in_addr->ss_family == PF_INET6) { + struct sockaddr_in6 *in_addr_ip6 = (struct sockaddr_in6 *)in_addr; + memset(addr, 0, sizeof(esp_ip_addr_t)); + *port = in_addr_ip6->sin6_port; + uint32_t *u32_addr = in_addr_ip6->sin6_addr.s6_addr32; + if (u32_addr[0] == 0 && u32_addr[1] == 0 && u32_addr[2] == esp_netif_htonl(0x0000FFFFUL)) { + // Mapped IPv4 address, convert directly to IPv4 + addr->type = ESP_IPADDR_TYPE_V4; + addr->u_addr.ip4.addr = u32_addr[3]; + } else { + addr->type = ESP_IPADDR_TYPE_V6; + addr->u_addr.ip6.addr[0] = u32_addr[0]; + addr->u_addr.ip6.addr[1] = u32_addr[1]; + addr->u_addr.ip6.addr[2] = u32_addr[2]; + addr->u_addr.ip6.addr[3] = u32_addr[3]; + } + } +#endif // CONFIG_LWIP_IPV6 +} + +void sock_recv_task(void *arg) +{ + while (s_run_sock_recv_task) { + struct timeval tv = { + .tv_sec = 1, + .tv_usec = 0, + }; + fd_set rfds; + FD_ZERO(&rfds); + int max_sock = -1; + for (int i = 0; i < MDNS_MAX_INTERFACES; i++) { + int sock = s_interfaces[i].sock; + if (sock >= 0) { + FD_SET(sock, &rfds); + max_sock = MAX(max_sock, sock); + } + } + if (max_sock < 0) { + vTaskDelay(pdMS_TO_TICKS(1000)); + ESP_LOGI(TAG, "No sock!"); + continue; + } + + int s = select(max_sock + 1, &rfds, NULL, NULL, &tv); + if (s < 0) { + ESP_LOGE(TAG, "Select failed. errno=%d: %s", errno, strerror(errno)); + break; + } else if (s > 0) { + for (int tcpip_if = 0; tcpip_if < MDNS_MAX_INTERFACES; tcpip_if++) { + int sock = s_interfaces[tcpip_if].sock; + if (sock < 0) { + continue; + } + if (FD_ISSET(sock, &rfds)) { + static char recvbuf[MDNS_MAX_PACKET_SIZE]; + uint16_t port = 0; + + struct sockaddr_storage raddr; // Large enough for both IPv4 or IPv6 + socklen_t socklen = sizeof(struct sockaddr_storage); + esp_ip_addr_t addr = {0}; + int len = recvfrom(sock, recvbuf, sizeof(recvbuf), 0, + (struct sockaddr *) &raddr, &socklen); + if (len < 0) { + ESP_LOGE(TAG, "multicast recvfrom failed. errno=%d: %s", errno, strerror(errno)); + break; + } + ESP_LOGD(TAG, "[sock=%d]: Received from IP:%s", sock, get_string_address(&raddr)); + ESP_LOG_BUFFER_HEXDUMP(TAG, recvbuf, len, ESP_LOG_VERBOSE); + inet_to_espaddr(&raddr, &addr, &port); + + // Allocate the packet structure and pass it to the mdns main engine + mdns_rx_packet_t *packet = (mdns_rx_packet_t *) mdns_mem_calloc(1, sizeof(mdns_rx_packet_t)); + struct pbuf *packet_pbuf = mdns_mem_calloc(1, sizeof(struct pbuf)); + uint8_t *buf = mdns_mem_malloc(len); + if (packet == NULL || packet_pbuf == NULL || buf == NULL) { + mdns_mem_free(buf); + mdns_mem_free(packet_pbuf); + mdns_mem_free(packet); + HOOK_MALLOC_FAILED; + ESP_LOGE(TAG, "Failed to allocate the mdns packet"); + continue; + } + memcpy(buf, recvbuf, len); + packet_pbuf->next = NULL; + packet_pbuf->payload = buf; + packet_pbuf->tot_len = len; + packet_pbuf->len = len; + packet->tcpip_if = tcpip_if; + packet->pb = packet_pbuf; + packet->src_port = ntohs(port); + memcpy(&packet->src, &addr, sizeof(esp_ip_addr_t)); + // TODO(IDF-3651): Add the correct dest addr -- for mdns to decide multicast/unicast + // Currently it's enough to assume the packet is multicast and mdns to check the source port of the packet + memset(&packet->dest, 0, sizeof(esp_ip_addr_t)); + packet->multicast = 1; + packet->dest.type = packet->src.type; + packet->ip_protocol = + packet->src.type == ESP_IPADDR_TYPE_V4 ? MDNS_IP_PROTOCOL_V4 : MDNS_IP_PROTOCOL_V6; + if (_mdns_send_rx_action(packet) != ESP_OK) { + ESP_LOGE(TAG, "_mdns_send_rx_action failed!"); + mdns_mem_free(packet->pb->payload); + mdns_mem_free(packet->pb); + mdns_mem_free(packet); + } + } + } + } + } + vTaskDelete(NULL); +} + +static void mdns_networking_init(void) +{ + if (s_run_sock_recv_task == false) { + s_run_sock_recv_task = true; + xTaskCreate(sock_recv_task, "mdns recv task", 3 * 1024, NULL, 5, NULL); + } +} + +static bool create_pcb(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +{ + if (s_interfaces[tcpip_if].proto & (ip_protocol == MDNS_IP_PROTOCOL_V4 ? PROTO_IPV4 : PROTO_IPV6)) { + return true; + } + int sock = s_interfaces[tcpip_if].sock; + esp_netif_t *netif = _mdns_get_esp_netif(tcpip_if); + if (sock < 0) { + sock = create_socket(netif); + } + if (sock < 0) { + ESP_LOGE(TAG, "Failed to create the socket!"); + return false; + } + int err = join_mdns_multicast_group(sock, netif, ip_protocol); + if (err < 0) { + ESP_LOGE(TAG, "Failed to add ipv6 multicast group for protocol %d", ip_protocol); + } + s_interfaces[tcpip_if].proto |= (ip_protocol == MDNS_IP_PROTOCOL_V4 ? PROTO_IPV4 : PROTO_IPV6); + s_interfaces[tcpip_if].sock = sock; + return true; +} + +esp_err_t _mdns_pcb_init(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +{ + ESP_LOGI(TAG, "_mdns_pcb_init(tcpip_if=%lu, ip_protocol=%lu)", (unsigned long)tcpip_if, (unsigned long)ip_protocol); + if (!create_pcb(tcpip_if, ip_protocol)) { + return ESP_FAIL; + } + + mdns_networking_init(); + return ESP_OK; +} + +static int create_socket(esp_netif_t *netif) +{ +#ifdef CONFIG_LWIP_IPV6 + int sock = socket(PF_INET6, SOCK_DGRAM, 0); +#else + int sock = socket(PF_INET, SOCK_DGRAM, 0); +#endif + if (sock < 0) { + ESP_LOGE(TAG, "Failed to create socket. errno=%d: %s", errno, strerror(errno)); + return -1; + } + + int on = 1; + if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) { + ESP_LOGE(TAG, "Failed setsockopt() to set SO_REUSEADDR. errno=%d: %s\n", errno, strerror(errno)); + } + // Bind the socket to any address +#ifdef CONFIG_LWIP_IPV6 + struct sockaddr_in6 saddr = { INADDR_ANY }; + saddr.sin6_family = AF_INET6; + saddr.sin6_port = htons(5353); + bzero(&saddr.sin6_addr.s6_addr, sizeof(saddr.sin6_addr.s6_addr)); + int err = bind(sock, (struct sockaddr *)&saddr, sizeof(struct sockaddr_in6)); + if (err < 0) { + ESP_LOGE(TAG, "Failed to bind socket. errno=%d: %s", errno, strerror(errno)); + goto err; + } +#else + struct sockaddr_in saddr = { 0 }; + saddr.sin_family = AF_INET; + saddr.sin_port = htons(5353); + bzero(&saddr.sin_addr.s_addr, sizeof(saddr.sin_addr.s_addr)); + int err = bind(sock, (struct sockaddr *)&saddr, sizeof(struct sockaddr_in)); + if (err < 0) { + ESP_LOGE(TAG, "Failed to bind socket. errno=%d: %s", errno, strerror(errno)); + goto err; + } +#endif // CONFIG_LWIP_IPV6 + struct ifreq ifr; + esp_netif_get_netif_impl_name(netif, ifr.ifr_name); + int ret = setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(struct ifreq)); + if (ret < 0) { + ESP_LOGE(TAG, "\"%s\" Unable to bind socket to specified interface. errno=%d: %s", esp_netif_get_desc(netif), errno, strerror(errno)); + goto err; + } + + return sock; + +err: + close(sock); + return -1; +} + +#ifdef CONFIG_LWIP_IPV6 +static int socket_add_ipv6_multicast_group(int sock, esp_netif_t *netif) +{ + int ifindex = esp_netif_get_netif_impl_index(netif); + int err = setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_IF, &ifindex, sizeof(ifindex)); + if (err < 0) { + ESP_LOGE(TAG, "Failed to set IPV6_MULTICAST_IF. errno=%d: %s", errno, strerror(errno)); + return err; + } + + struct ipv6_mreq v6imreq = { 0 }; + esp_ip_addr_t multi_addr = ESP_IP6ADDR_INIT(0x000002ff, 0, 0, 0xfb000000); + memcpy(&v6imreq.ipv6mr_multiaddr, &multi_addr.u_addr.ip6.addr, sizeof(v6imreq.ipv6mr_multiaddr)); + v6imreq.ipv6mr_interface = ifindex; + err = setsockopt(sock, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &v6imreq, sizeof(struct ipv6_mreq)); + if (err < 0) { + ESP_LOGE(TAG, "Failed to set IPV6_ADD_MEMBERSHIP. errno=%d: %s", errno, strerror(errno)); + return err; + } + return err; +} +#endif // CONFIG_LWIP_IPV6 + +#ifdef CONFIG_LWIP_IPV4 +static int socket_add_ipv4_multicast_group(int sock, esp_netif_t *netif) +{ + struct ip_mreq imreq = { 0 }; + int err = 0; + esp_netif_ip_info_t ip_info = { 0 }; + + if (esp_netif_get_ip_info(netif, &ip_info) != ESP_OK) { + ESP_LOGE(TAG, "Failed to esp_netif_get_ip_info()"); + goto err; + } + imreq.imr_interface.s_addr = ip_info.ip.addr; + + esp_ip_addr_t multicast_addr = ESP_IP4ADDR_INIT(224, 0, 0, 251); + imreq.imr_multiaddr.s_addr = multicast_addr.u_addr.ip4.addr; + + err = setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &imreq, sizeof(struct ip_mreq)); + if (err < 0) { + ESP_LOGE(TAG, "[sock=%d] Failed to set IP_ADD_MEMBERSHIP. errno=%d: %s", sock, errno, strerror(errno)); + goto err; + } + +err: + return err; +} +#endif // CONFIG_LWIP_IPV4 + +static int join_mdns_multicast_group(int sock, esp_netif_t *netif, mdns_ip_protocol_t ip_protocol) +{ +#ifdef CONFIG_LWIP_IPV4 + if (ip_protocol == MDNS_IP_PROTOCOL_V4) { + return socket_add_ipv4_multicast_group(sock, netif); + } +#endif // CONFIG_LWIP_IPV4 +#ifdef CONFIG_LWIP_IPV6 + if (ip_protocol == MDNS_IP_PROTOCOL_V6) { + return socket_add_ipv6_multicast_group(sock, netif); + } +#endif // CONFIG_LWIP_IPV6 + return -1; +} diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/mem_prefix_script.py b/RainMaker_Table-Lights/managed_components/espressif__mdns/mem_prefix_script.py new file mode 100644 index 000000000..b9af09d32 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__mdns/mem_prefix_script.py @@ -0,0 +1,54 @@ +# SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: Apache-2.0 +import re +import sys + +# Configurable prefix for memory functions +MDNS_MEM_PREFIX = 'mdns_mem_' # Change this to modify the prefix + + +def add_prefix_to_mem_funcs(content): + # List of memory functions to prefix + mem_funcs = [ + 'malloc', + 'calloc', + 'free', + 'strdup', + 'strndup' + ] + + # Create regex pattern matching the memory functions but not already prefixed ones + pattern = fr'(?') + sys.exit(1) + + process_file(sys.argv[1]) diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/private_include/mdns_mem_caps.h b/RainMaker_Table-Lights/managed_components/espressif__mdns/private_include/mdns_mem_caps.h new file mode 100644 index 000000000..2d633908a --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__mdns/private_include/mdns_mem_caps.h @@ -0,0 +1,65 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Allocate memory. + * @param size Number of bytes to allocate. + * @return Pointer to allocated memory, or NULL on failure. + */ +void *mdns_mem_malloc(size_t size); + +/** + * @brief Allocate and zero memory. + * @param num Number of elements. + * @param size Size of each element. + * @return Pointer to allocated memory, or NULL on failure. + */ +void *mdns_mem_calloc(size_t num, size_t size); + +/** + * @brief Free allocated memory. + * @param ptr Pointer to memory to free. + */ +void mdns_mem_free(void *ptr); + +/** + * @brief Duplicate a string. + * @param s String to duplicate. + * @return Pointer to duplicated string, or NULL on failure. + */ +char *mdns_mem_strdup(const char *s); + +/** + * @brief Duplicate a string with length limit. + * @param s String to duplicate. + * @param n Maximum number of characters to copy. + * @return Pointer to duplicated string, or NULL on failure. + */ +char *mdns_mem_strndup(const char *s, size_t n); + +/** + * @brief Allocate memory for mDNS task. + * @param size Number of bytes to allocate. + * @return Pointer to allocated memory, or NULL on failure. + */ +void *mdns_mem_task_malloc(size_t size); + +/** + * @brief Free allocated memory for mDNS task. + * @param ptr Pointer to memory to free. + */ +void mdns_mem_task_free(void *ptr); + +#ifdef __cplusplus +} +#endif diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/private_include/mdns_networking.h b/RainMaker_Table-Lights/managed_components/espressif__mdns/private_include/mdns_networking.h new file mode 100644 index 000000000..83cbe90cc --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__mdns/private_include/mdns_networking.h @@ -0,0 +1,60 @@ +/* + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ESP_MDNS_NETWORKING_H_ +#define ESP_MDNS_NETWORKING_H_ + +/* + * MDNS Server Networking -- private include + * + */ +#include "mdns.h" +#include "mdns_private.h" + + +/** + * @brief Queue RX packet action + */ +esp_err_t _mdns_send_rx_action(mdns_rx_packet_t *packet); + +bool mdns_is_netif_ready(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); + +/** + * @brief Start PCB + */ +esp_err_t _mdns_pcb_init(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); + +/** + * @brief Stop PCB + */ +esp_err_t _mdns_pcb_deinit(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol); + +/** + * @brief send packet over UDP + * + * @param server The server + * @param data byte array containing the packet data + * @param len length of the packet data + * + * @return length of sent packet or 0 on error + */ +size_t _mdns_udp_pcb_write(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol, const esp_ip_addr_t *ip, uint16_t port, uint8_t *data, size_t len); + +/** + * @brief Gets data pointer to the mDNS packet + */ +void *_mdns_get_packet_data(mdns_rx_packet_t *packet); + +/** + * @brief Gets data length of c + */ +size_t _mdns_get_packet_len(mdns_rx_packet_t *packet); + +/** + * @brief Free the mDNS packet + */ +void _mdns_packet_free(mdns_rx_packet_t *packet); + +#endif /* ESP_MDNS_NETWORKING_H_ */ diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/private_include/mdns_private.h b/RainMaker_Table-Lights/managed_components/espressif__mdns/private_include/mdns_private.h new file mode 100644 index 000000000..ce4c96b63 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__mdns/private_include/mdns_private.h @@ -0,0 +1,468 @@ +/* + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef MDNS_PRIVATE_H_ +#define MDNS_PRIVATE_H_ + +#include "sdkconfig.h" +#include "mdns.h" +#include "esp_task.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/queue.h" +#include "freertos/semphr.h" +#include "esp_timer.h" +#include "esp_system.h" + +#ifdef CONFIG_MDNS_ENABLE_DEBUG_PRINTS +#define MDNS_ENABLE_DEBUG +#define _mdns_dbg_printf(...) printf(__VA_ARGS__) +#endif + +/** Number of predefined interfaces */ +#ifndef CONFIG_MDNS_PREDEF_NETIF_STA +#define CONFIG_MDNS_PREDEF_NETIF_STA 0 +#endif +#ifndef CONFIG_MDNS_PREDEF_NETIF_AP +#define CONFIG_MDNS_PREDEF_NETIF_AP 0 +#endif +#ifndef CONFIG_MDNS_PREDEF_NETIF_ETH +#define CONFIG_MDNS_PREDEF_NETIF_ETH 0 +#endif +#define MDNS_MAX_PREDEF_INTERFACES (CONFIG_MDNS_PREDEF_NETIF_STA + CONFIG_MDNS_PREDEF_NETIF_AP + CONFIG_MDNS_PREDEF_NETIF_ETH) + +#ifdef CONFIG_LWIP_IPV6_NUM_ADDRESSES +#define NETIF_IPV6_MAX_NUMS CONFIG_LWIP_IPV6_NUM_ADDRESSES +#else +#define NETIF_IPV6_MAX_NUMS 3 +#endif + +#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 1, 0) +/* CONFIG_LWIP_IPV4 was introduced in IDF v5.1 */ +/* For IDF v5.0, set CONFIG_LWIP_IPV4 to 1 by default */ +#ifndef CONFIG_LWIP_IPV4 +#define CONFIG_LWIP_IPV4 1 +#endif // CONFIG_LWIP_IPV4 +#endif // ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 1, 0) + +/** Number of configured interfaces */ +#if MDNS_MAX_PREDEF_INTERFACES > CONFIG_MDNS_MAX_INTERFACES +#warning Number of configured interfaces is less then number of predefined interfaces. Please update CONFIG_MDNS_MAX_INTERFACES. +#define MDNS_MAX_INTERFACES (MDNS_MAX_PREDEF_INTERFACES) +#else +#define MDNS_MAX_INTERFACES (CONFIG_MDNS_MAX_INTERFACES) +#endif + +/** The maximum number of services */ +#define MDNS_MAX_SERVICES CONFIG_MDNS_MAX_SERVICES + +#define MDNS_ANSWER_PTR_TTL 4500 +#define MDNS_ANSWER_TXT_TTL 4500 +#define MDNS_ANSWER_SRV_TTL 120 +#define MDNS_ANSWER_A_TTL 120 +#define MDNS_ANSWER_AAAA_TTL 120 + +#define MDNS_FLAGS_QUERY_REPSONSE 0x8000 +#define MDNS_FLAGS_AUTHORITATIVE 0x0400 +#define MDNS_FLAGS_QR_AUTHORITATIVE (MDNS_FLAGS_QUERY_REPSONSE | MDNS_FLAGS_AUTHORITATIVE) +#define MDNS_FLAGS_DISTRIBUTED 0x0200 + +#define MDNS_NAME_REF 0xC000 + +//custom type! only used by this implementation +//to help manage service discovery handling +#define MDNS_TYPE_SDPTR 0x0032 + +#define MDNS_CLASS_IN 0x0001 +#define MDNS_CLASS_ANY 0x00FF +#define MDNS_CLASS_IN_FLUSH_CACHE 0x8001 + +#define MDNS_ANSWER_ALL 0x3F +#define MDNS_ANSWER_PTR 0x08 +#define MDNS_ANSWER_TXT 0x04 +#define MDNS_ANSWER_SRV 0x02 +#define MDNS_ANSWER_A 0x01 +#define MDNS_ANSWER_AAAA 0x10 +#define MDNS_ANSWER_NSEC 0x20 +#define MDNS_ANSWER_SDPTR 0x80 +#define MDNS_ANSWER_AAAA_SIZE 16 + +#define MDNS_SERVICE_PORT 5353 // UDP port that the server runs on +#define MDNS_SERVICE_STACK_DEPTH CONFIG_MDNS_TASK_STACK_SIZE +#define MDNS_TASK_PRIORITY CONFIG_MDNS_TASK_PRIORITY +#if (MDNS_TASK_PRIORITY > ESP_TASK_PRIO_MAX) +#error "mDNS task priority is higher than ESP_TASK_PRIO_MAX" +#elif (MDNS_TASK_PRIORITY > ESP_TASKD_EVENT_PRIO) +#warning "mDNS task priority is higher than ESP_TASKD_EVENT_PRIO, mDNS library might not work correctly" +#endif +#define MDNS_TASK_AFFINITY CONFIG_MDNS_TASK_AFFINITY +#define MDNS_SERVICE_ADD_TIMEOUT_MS CONFIG_MDNS_SERVICE_ADD_TIMEOUT_MS + +#define MDNS_PACKET_QUEUE_LEN 16 // Maximum packets that can be queued for parsing +#define MDNS_ACTION_QUEUE_LEN CONFIG_MDNS_ACTION_QUEUE_LEN // Maximum actions pending to the server +#define MDNS_TXT_MAX_LEN 1024 // Maximum string length of text data in TXT record +#define MDNS_MAX_PACKET_SIZE 1460 // Maximum size of mDNS outgoing packet + +#define MDNS_HEAD_LEN 12 +#define MDNS_HEAD_ID_OFFSET 0 +#define MDNS_HEAD_FLAGS_OFFSET 2 +#define MDNS_HEAD_QUESTIONS_OFFSET 4 +#define MDNS_HEAD_ANSWERS_OFFSET 6 +#define MDNS_HEAD_SERVERS_OFFSET 8 +#define MDNS_HEAD_ADDITIONAL_OFFSET 10 + +#define MDNS_TYPE_OFFSET 0 +#define MDNS_CLASS_OFFSET 2 +#define MDNS_TTL_OFFSET 4 +#define MDNS_LEN_OFFSET 8 +#define MDNS_DATA_OFFSET 10 + +#define MDNS_SRV_PRIORITY_OFFSET 0 +#define MDNS_SRV_WEIGHT_OFFSET 2 +#define MDNS_SRV_PORT_OFFSET 4 +#define MDNS_SRV_FQDN_OFFSET 6 + +#define MDNS_TIMER_PERIOD_US (CONFIG_MDNS_TIMER_PERIOD_MS*1000) + +#define MDNS_SERVICE_LOCK() xSemaphoreTake(_mdns_service_semaphore, portMAX_DELAY) +#define MDNS_SERVICE_UNLOCK() xSemaphoreGive(_mdns_service_semaphore) + +#define queueToEnd(type, queue, item) \ + if (!queue) { \ + queue = item; \ + } else { \ + type * _q = queue; \ + while (_q->next) { _q = _q->next; } \ + _q->next = item; \ + } + +#define queueDetach(type, queue, item) \ + if (queue) { \ + if (queue == item) { \ + queue = queue->next; \ + } else { \ + type * _q = queue; \ + while (_q->next && _q->next != item) { \ + _q = _q->next; \ + } \ + if (_q->next == item) { \ + _q->next = item->next; \ + item->next = NULL; \ + } \ + } \ + } + +#define queueFree(type, queue) while (queue) { type * _q = queue; queue = queue->next; free(_q); } + +#define PCB_STATE_IS_PROBING(s) (s->state > PCB_OFF && s->state < PCB_ANNOUNCE_1) +#define PCB_STATE_IS_ANNOUNCING(s) (s->state > PCB_PROBE_3 && s->state < PCB_RUNNING) +#define PCB_STATE_IS_RUNNING(s) (s->state == PCB_RUNNING) + +#ifndef HOOK_MALLOC_FAILED +#define HOOK_MALLOC_FAILED ESP_LOGE(TAG, "Cannot allocate memory (line: %d, free heap: %" PRIu32 " bytes)", __LINE__, esp_get_free_heap_size()); +#endif + +typedef size_t mdns_if_t; + +typedef enum { + PCB_OFF, PCB_DUP, PCB_INIT, + PCB_PROBE_1, PCB_PROBE_2, PCB_PROBE_3, + PCB_ANNOUNCE_1, PCB_ANNOUNCE_2, PCB_ANNOUNCE_3, + PCB_RUNNING +} mdns_pcb_state_t; + +typedef enum { + MDNS_ANSWER, MDNS_NS, MDNS_EXTRA +} mdns_parsed_record_type_t; + +typedef enum { + ACTION_SYSTEM_EVENT, + ACTION_HOSTNAME_SET, + ACTION_INSTANCE_SET, + ACTION_SEARCH_ADD, + ACTION_SEARCH_SEND, + ACTION_SEARCH_END, + ACTION_BROWSE_ADD, + ACTION_BROWSE_SYNC, + ACTION_BROWSE_END, + ACTION_TX_HANDLE, + ACTION_RX_HANDLE, + ACTION_TASK_STOP, + ACTION_DELEGATE_HOSTNAME_ADD, + ACTION_DELEGATE_HOSTNAME_REMOVE, + ACTION_DELEGATE_HOSTNAME_SET_ADDR, + ACTION_MAX +} mdns_action_type_t; + + +typedef struct { + uint16_t id; + uint16_t flags; + uint16_t questions; //QDCOUNT + uint16_t answers; //ANCOUNT + uint16_t servers; //NSCOUNT + uint16_t additional;//ARCOUNT +} mdns_header_t; + +typedef struct { + char host[MDNS_NAME_BUF_LEN]; // hostname for A/AAAA records, instance name for SRV records + char service[MDNS_NAME_BUF_LEN]; + char proto[MDNS_NAME_BUF_LEN]; + char domain[MDNS_NAME_BUF_LEN]; + uint8_t parts; + uint8_t sub; + bool invalid; +} mdns_name_t; + +typedef struct mdns_parsed_question_s { + struct mdns_parsed_question_s *next; + uint16_t type; + bool sub; + bool unicast; + char *host; + char *service; + char *proto; + char *domain; +} mdns_parsed_question_t; + +typedef struct mdns_parsed_record_s { + struct mdns_parsed_record_s *next; + mdns_parsed_record_type_t record_type; + uint16_t type; + uint16_t clas; + uint8_t flush; + uint32_t ttl; + char *host; + char *service; + char *proto; + char *domain; + uint16_t data_len; + uint8_t *data; +} mdns_parsed_record_t; + +typedef struct { + mdns_if_t tcpip_if; + mdns_ip_protocol_t ip_protocol; + esp_ip_addr_t src; + uint16_t src_port; + uint8_t multicast; + uint8_t authoritative; + uint8_t probe; + uint8_t discovery; + uint8_t distributed; + mdns_parsed_question_t *questions; + mdns_parsed_record_t *records; + uint16_t id; +} mdns_parsed_packet_t; + +typedef struct { + mdns_if_t tcpip_if; + mdns_ip_protocol_t ip_protocol; + struct pbuf *pb; + esp_ip_addr_t src; + esp_ip_addr_t dest; + uint16_t src_port; + uint8_t multicast; +} mdns_rx_packet_t; + +typedef struct mdns_txt_linked_item_s { + const char *key; /*!< item key name */ + char *value; /*!< item value string */ + uint8_t value_len; /*!< item value length */ + struct mdns_txt_linked_item_s *next; /*!< next result, or NULL for the last result in the list */ +} mdns_txt_linked_item_t; + +typedef struct mdns_subtype_s { + const char *subtype; /*!< subtype */ + struct mdns_subtype_s *next; /*!< next result, or NULL for the last result in the list */ +} mdns_subtype_t; + +typedef struct { + const char *instance; + const char *service; + const char *proto; + const char *hostname; + uint16_t priority; + uint16_t weight; + uint16_t port; + mdns_txt_linked_item_t *txt; + mdns_subtype_t *subtype; +} mdns_service_t; + +typedef struct mdns_srv_item_s { + struct mdns_srv_item_s *next; + mdns_service_t *service; +} mdns_srv_item_t; + +typedef struct mdns_out_question_s { + struct mdns_out_question_s *next; + uint16_t type; + bool unicast; + const char *host; + const char *service; + const char *proto; + const char *domain; + bool own_dynamic_memory; +} mdns_out_question_t; + +typedef struct mdns_host_item_t { + const char *hostname; + mdns_ip_addr_t *address_list; + struct mdns_host_item_t *next; +} mdns_host_item_t; + +typedef struct mdns_out_answer_s { + struct mdns_out_answer_s *next; + uint16_t type; + uint8_t bye; + uint8_t flush; + mdns_service_t *service; + mdns_host_item_t *host; + const char *custom_instance; + const char *custom_service; + const char *custom_proto; +} mdns_out_answer_t; + +typedef struct mdns_tx_packet_s { + struct mdns_tx_packet_s *next; + uint32_t send_at; + mdns_if_t tcpip_if; + mdns_ip_protocol_t ip_protocol; + esp_ip_addr_t dst; + uint16_t port; + uint16_t flags; + uint8_t distributed; + mdns_out_question_t *questions; + mdns_out_answer_t *answers; + mdns_out_answer_t *servers; + mdns_out_answer_t *additional; + bool queued; + uint16_t id; +} mdns_tx_packet_t; + +typedef struct { + mdns_pcb_state_t state; + mdns_srv_item_t **probe_services; + uint8_t probe_services_len; + uint8_t probe_ip; + uint8_t probe_running; + uint16_t failed_probes; +} mdns_pcb_t; + +typedef enum { + SEARCH_OFF, + SEARCH_INIT, + SEARCH_RUNNING, + SEARCH_MAX +} mdns_search_once_state_t; + +typedef enum { + BROWSE_OFF, + BROWSE_INIT, + BROWSE_RUNNING, + BROWSE_MAX +} mdns_browse_state_t; + +typedef struct mdns_search_once_s { + struct mdns_search_once_s *next; + + mdns_search_once_state_t state; + uint32_t started_at; + uint32_t sent_at; + uint32_t timeout; + mdns_query_notify_t notifier; + SemaphoreHandle_t done_semaphore; + uint16_t type; + bool unicast; + uint8_t max_results; + uint8_t num_results; + char *instance; + char *service; + char *proto; + mdns_result_t *result; +} mdns_search_once_t; + +typedef struct mdns_browse_s { + struct mdns_browse_s *next; + + mdns_browse_state_t state; + mdns_browse_notify_t notifier; + + char *service; + char *proto; + mdns_result_t *result; +} mdns_browse_t; + +typedef struct mdns_browse_result_sync_t { + mdns_result_t *result; + struct mdns_browse_result_sync_t *next; +} mdns_browse_result_sync_t; + +typedef struct mdns_browse_sync { + mdns_browse_t *browse; + mdns_browse_result_sync_t *sync_result; +} mdns_browse_sync_t; + +typedef struct mdns_server_s { + struct { + mdns_pcb_t pcbs[MDNS_IP_PROTOCOL_MAX]; + } interfaces[MDNS_MAX_INTERFACES]; + const char *hostname; + const char *instance; + mdns_srv_item_t *services; + QueueHandle_t action_queue; + SemaphoreHandle_t action_sema; + mdns_tx_packet_t *tx_queue_head; + mdns_search_once_t *search_once; + esp_timer_handle_t timer_handle; + mdns_browse_t *browse; +} mdns_server_t; + +typedef struct { + mdns_action_type_t type; + union { + struct { + char *hostname; + } hostname_set; + char *instance; + struct { + mdns_if_t interface; + mdns_event_actions_t event_action; + } sys_event; + struct { + mdns_search_once_t *search; + } search_add; + struct { + mdns_tx_packet_t *packet; + } tx_handle; + struct { + mdns_rx_packet_t *packet; + } rx_handle; + struct { + const char *hostname; + mdns_ip_addr_t *address_list; + } delegate_hostname; + struct { + mdns_browse_t *browse; + } browse_add; + struct { + mdns_browse_sync_t *browse_sync; + } browse_sync; + } data; +} mdns_action_t; + +/* + * @brief Convert mnds if to esp-netif handle + * + * @param tcpip_if mdns supported interface as internal enum + * + * @return + * - ptr to esp-netif on success + * - NULL if no available netif for current interface index + */ +esp_netif_t *_mdns_get_esp_netif(mdns_if_t tcpip_if); + + +#endif /* MDNS_PRIVATE_H_ */ diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/host_test/CMakeLists.txt b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/host_test/CMakeLists.txt new file mode 100644 index 000000000..5f0d7bdd6 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/host_test/CMakeLists.txt @@ -0,0 +1,16 @@ +cmake_minimum_required(VERSION 3.5) + + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +if(${IDF_TARGET} STREQUAL "linux") + set(EXTRA_COMPONENT_DIRS "../../../../common_components/linux_compat") + set(COMPONENTS main) +endif() + +project(mdns_host) + +# Enable sanitizers only without console (we'd see some leaks on argtable when console exits) +if(NOT CONFIG_TEST_CONSOLE AND CONFIG_IDF_TARGET_LINUX) +idf_component_get_property(mdns mdns COMPONENT_LIB) +target_link_options(${mdns} INTERFACE -fsanitize=address -fsanitize=undefined) +endif() diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/host_test/README.md b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/host_test/README.md new file mode 100644 index 000000000..4953f0e28 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/host_test/README.md @@ -0,0 +1,33 @@ +# Setup dummy network interfaces + +Note: Set two addresses so we could use one as source and another as destination +``` +sudo ip link add eth2 type dummy +sudo ip addr add 192.168.1.200/24 dev eth2 +sudo ip addr add 192.168.1.201/24 dev eth2 +sudo ip link set eth2 up +sudo ifconfig eth2 multicast +``` + +# Dig on a specified interface + +``` +dig +short -b 192.168.1.200 -p 5353 @224.0.0.251 myesp.local +``` + +or a reverse query: +``` +dig +short -b 192.168.2.200 -p 5353 @224.0.0.251 -x 192.168.1.200 +``` + +# Run avahi to browse services + +Avahi needs the netif to have the "multicast" flag set + +```bash +david@david-comp:~/esp/idf (feature/mdns_networking_socket)$ avahi-browse -a -r -p ++;eth2;IPv6;myesp-service2;Web Site;local ++;eth2;IPv4;myesp-service2;Web Site;local +=;eth2;IPv6;myesp-service2;Web Site;local;myesp.local;192.168.1.200;80;"board=esp32" "u=user" "p=password" +=;eth2;IPv4;myesp-service2;Web Site;local;myesp.local;192.168.1.200;80;"board=esp32" "u=user" "p=password" +``` diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/host_test/components/esp_netif_linux/CMakeLists.txt b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/host_test/components/esp_netif_linux/CMakeLists.txt new file mode 100644 index 000000000..6f8d51ec8 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/host_test/components/esp_netif_linux/CMakeLists.txt @@ -0,0 +1,8 @@ +idf_build_get_property(idf_target IDF_TARGET) +if(${IDF_TARGET} STREQUAL "linux") + idf_component_register(SRCS esp_netif_linux.c + INCLUDE_DIRS include $ENV{IDF_PATH}/components/esp_netif/include + REQUIRES esp_event) +else() + idf_component_register() +endif() diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/host_test/components/esp_netif_linux/Kconfig b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/host_test/components/esp_netif_linux/Kconfig new file mode 100644 index 000000000..3b3c30992 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/host_test/components/esp_netif_linux/Kconfig @@ -0,0 +1,15 @@ +menu "LWIP-MOCK-CONFIG" + + config LWIP_IPV6 + bool "Enable IPv6" + default y + help + Enable/disable IPv6 + + config LWIP_IPV4 + bool "Enable IPv4" + default y + help + Enable/disable IPv4 + +endmenu diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/host_test/components/esp_netif_linux/esp_netif_linux.c b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/host_test/components/esp_netif_linux/esp_netif_linux.c new file mode 100644 index 000000000..13cf412e0 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/host_test/components/esp_netif_linux/esp_netif_linux.c @@ -0,0 +1,197 @@ +/* + * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include + +#include "esp_netif.h" +#include "esp_err.h" +#include //strlen +#include +#include //inet_addr +#include +#include +#include +#include "esp_netif_types.h" +#include "esp_log.h" + +#define MAX_NETIFS 4 + +static const char *TAG = "esp_netif_linux"; + +static esp_netif_t *s_netif_list[MAX_NETIFS] = { 0 }; + +struct esp_netif_obj { + const char *if_key; + const char *if_desc; +}; + +esp_netif_t *esp_netif_get_handle_from_ifkey(const char *if_key) +{ + for (int i = 0; i < MAX_NETIFS; ++i) { + if (s_netif_list[i] && strcmp(s_netif_list[i]->if_key, if_key) == 0) { + return s_netif_list[i]; + } + } + return NULL; +} + +esp_err_t esp_netif_get_ip_info(esp_netif_t *esp_netif, esp_netif_ip_info_t *ip_info) +{ + if (esp_netif == NULL) { + return ESP_ERR_INVALID_STATE; + } + struct ifaddrs *addrs, *tmp; + getifaddrs(&addrs); + tmp = addrs; + + while (tmp) { + if (tmp->ifa_addr && tmp->ifa_addr->sa_family == AF_INET) { + char addr[20]; + struct sockaddr_in *pAddr = (struct sockaddr_in *) tmp->ifa_addr; + inet_ntop(AF_INET, &pAddr->sin_addr, addr, sizeof(addr)); + if (strcmp(esp_netif->if_desc, tmp->ifa_name) == 0) { + ESP_LOGD(TAG, "AF_INET4: %s: %s\n", tmp->ifa_name, addr); + memcpy(&ip_info->ip.addr, &pAddr->sin_addr, 4); + } + } + tmp = tmp->ifa_next; + } + freeifaddrs(addrs); + return ESP_OK; +} + +esp_err_t esp_netif_dhcpc_get_status(esp_netif_t *esp_netif, esp_netif_dhcp_status_t *status) +{ + return ESP_OK; +} + +int esp_netif_get_all_ip6(esp_netif_t *esp_netif, esp_ip6_addr_t if_ip6[]) +{ + if (esp_netif == NULL) { + return 0; + } + struct ifaddrs *addrs, *tmp; + int addr_count = 0; + getifaddrs(&addrs); + tmp = addrs; + + while (tmp) { + if (tmp->ifa_addr && tmp->ifa_addr->sa_family == AF_INET6) { + struct sockaddr_in6 *pAddr = (struct sockaddr_in6 *)tmp->ifa_addr; + if (strcmp(esp_netif->if_desc, tmp->ifa_name) == 0) { + memcpy(&if_ip6[addr_count++], &pAddr->sin6_addr, 4 * 4); + } + } + tmp = tmp->ifa_next; + } + + freeifaddrs(addrs); + return addr_count; +} + +esp_err_t esp_netif_get_ip6_linklocal(esp_netif_t *esp_netif, esp_ip6_addr_t *if_ip6) +{ + if (esp_netif == NULL) { + return ESP_ERR_INVALID_STATE; + } + struct ifaddrs *addrs, *tmp; + getifaddrs(&addrs); + tmp = addrs; + + while (tmp) { + if (tmp->ifa_addr && tmp->ifa_addr->sa_family == AF_INET6) { + char addr[64]; + struct sockaddr_in6 *pAddr = (struct sockaddr_in6 *)tmp->ifa_addr; + inet_ntop(AF_INET6, &pAddr->sin6_addr, addr, sizeof(addr)); + if (strcmp(esp_netif->if_desc, tmp->ifa_name) == 0) { + ESP_LOGD(TAG, "AF_INET6: %s: %s\n", tmp->ifa_name, addr); + memcpy(if_ip6->addr, &pAddr->sin6_addr, 4 * 4); + break; + } + } + tmp = tmp->ifa_next; + } + + freeifaddrs(addrs); + return ESP_OK; +} + + +int esp_netif_get_netif_impl_index(esp_netif_t *esp_netif) +{ + if (esp_netif == NULL) { + return -1; + } + uint32_t interfaceIndex = if_nametoindex(esp_netif->if_desc); + return interfaceIndex; +} + +esp_err_t esp_netif_get_netif_impl_name(esp_netif_t *esp_netif, char *name) +{ + if (esp_netif == NULL) { + return ESP_ERR_INVALID_STATE; + } + strcpy(name, esp_netif->if_desc); + return ESP_OK; +} + +const char *esp_netif_get_desc(esp_netif_t *esp_netif) +{ + if (esp_netif == NULL) { + return NULL; + } + return esp_netif->if_desc; +} + +esp_netif_t *esp_netif_new(const esp_netif_config_t *config) +{ + if (esp_netif_get_handle_from_ifkey(config->base->if_key)) { + return NULL; + } + esp_netif_t *netif = calloc(1, sizeof(struct esp_netif_obj)); + if (netif) { + netif->if_desc = config->base->if_desc; + netif->if_key = config->base->if_key; + } + + for (int i = 0; i < MAX_NETIFS; ++i) { + if (s_netif_list[i] == NULL) { + s_netif_list[i] = netif; + break; + } + } + + return netif; +} + +void esp_netif_destroy(esp_netif_t *esp_netif) +{ + for (int i = 0; i < MAX_NETIFS; ++i) { + if (s_netif_list[i] == esp_netif) { + s_netif_list[i] = NULL; + break; + } + } + free(esp_netif); +} + +const char *esp_netif_get_ifkey(esp_netif_t *esp_netif) +{ + return esp_netif->if_key; +} + +esp_err_t esp_netif_str_to_ip4(const char *src, esp_ip4_addr_t *dst) +{ + if (src == NULL || dst == NULL) { + return ESP_ERR_INVALID_ARG; + } + struct in_addr addr; + if (inet_pton(AF_INET, src, &addr) != 1) { + return ESP_FAIL; + } + dst->addr = addr.s_addr; + return ESP_OK; +} diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/host_test/components/esp_netif_linux/include/esp_wifi_types.h b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/host_test/components/esp_netif_linux/include/esp_wifi_types.h new file mode 100644 index 000000000..e878e2715 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/host_test/components/esp_netif_linux/include/esp_wifi_types.h @@ -0,0 +1,7 @@ +/* + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once +#include "esp_event.h" diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/host_test/components/esp_netif_linux/include/machine/endian.h b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/host_test/components/esp_netif_linux/include/machine/endian.h new file mode 100644 index 000000000..488bce0e3 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/host_test/components/esp_netif_linux/include/machine/endian.h @@ -0,0 +1,8 @@ +/* + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#include_next "endian.h" diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/host_test/dnsfixture.py b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/host_test/dnsfixture.py new file mode 100644 index 000000000..6dcf0c99f --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/host_test/dnsfixture.py @@ -0,0 +1,130 @@ +# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: Unlicense OR CC0-1.0 +import logging +import re +import socket +import sys + +import dns.message +import dns.query +import dns.rdataclass +import dns.rdatatype +import dns.resolver + +# Configure logging +logging.basicConfig(level=logging.INFO) +logger = logging.getLogger(__name__) + + +class DnsPythonWrapper: + def __init__(self, server='224.0.0.251', port=5353, retries=3): + self.server = server + self.port = port + self.retries = retries + + def send_and_receive_query(self, query, timeout=3): + logger.info(f'Sending DNS query to {self.server}:{self.port}') + try: + # Create a UDP socket + with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as sock: + sock.settimeout(timeout) + + # Send the DNS query + query_data = query.to_wire() + sock.sendto(query_data, (self.server, self.port)) + + # Receive the DNS response + response_data, _ = sock.recvfrom(512) # 512 bytes is the typical size for a DNS response + + # Parse the response + response = dns.message.from_wire(response_data) + + return response + + except socket.timeout as e: + logger.warning(f'DNS query timed out: {e}') + return None + except dns.exception.DNSException as e: + logger.error(f'DNS query failed: {e}') + return None + + def run_query(self, name, query_type='PTR', timeout=3): + logger.info(f'Running DNS query for {name} with type {query_type}') + query = dns.message.make_query(name, dns.rdatatype.from_text(query_type), dns.rdataclass.IN) + + # Print the DNS question section + logger.info(f'DNS question section: {query.question}') + + # Send and receive the DNS query + response = None + for attempt in range(1, self.retries + 1): + logger.info(f'Attempt {attempt}/{self.retries}') + response = self.send_and_receive_query(query, timeout) + if response: + break + + if response: + logger.info(f'DNS query response:\n{response}') + else: + logger.warning('No response received or response was invalid.') + + return response + + def parse_answer_section(self, response, query_type): + answers = [] + if response: + for answer in response.answer: + if dns.rdatatype.to_text(answer.rdtype) == query_type: + for item in answer.items: + full_answer = ( + f'{answer.name} {answer.ttl} ' + f'{dns.rdataclass.to_text(answer.rdclass)} ' + f'{dns.rdatatype.to_text(answer.rdtype)} ' + f'{item.to_text()}' + ) + answers.append(full_answer) + return answers + + def check_record(self, name, query_type, expected=True, expect=None): + output = self.run_query(name, query_type=query_type) + answers = self.parse_answer_section(output, query_type) + logger.info(f'answers: {answers}') + if expect is None: + expect = name + if expected: + assert any(expect in answer for answer in answers), f"Expected record '{expect}' not found in answer section" + else: + assert not any(expect in answer for answer in answers), f"Unexpected record '{expect}' found in answer section" + + +if __name__ == '__main__': + if len(sys.argv) < 3: + print('Usage: python dns_fixture.py ') + sys.exit(1) + + query_type = sys.argv[1] + name = sys.argv[2] + ip_only = len(sys.argv) > 3 and sys.argv[3] == '--ip_only' + if ip_only: + logger.setLevel(logging.WARNING) + + dns_wrapper = DnsPythonWrapper() + if query_type == 'X' and '.' in name: + # Sends an IPv4 reverse query + reversed_ip = '.'.join(reversed(name.split('.'))) + name = f'{reversed_ip}.in-addr.arpa' + query_type = 'PTR' + response = dns_wrapper.run_query(name, query_type=query_type) + answers = dns_wrapper.parse_answer_section(response, query_type) + + if answers: + for answer in answers: + logger.info(f'DNS query response: {answer}') + if ip_only: + ipv4_pattern = re.compile(r'\b(?:\d{1,3}\.){3}\d{1,3}\b') + ipv4_addresses = ipv4_pattern.findall(answer) + if ipv4_addresses: + print(f"{', '.join(ipv4_addresses)}") + else: + logger.info(f'No response for {name} with query type {query_type}') + exit(9) # Same as dig timeout diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/host_test/main/CMakeLists.txt b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/host_test/main/CMakeLists.txt new file mode 100644 index 000000000..0e6f226ab --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/host_test/main/CMakeLists.txt @@ -0,0 +1,4 @@ +idf_component_register(SRCS "main.c" + INCLUDE_DIRS + "." + REQUIRES mdns console nvs_flash) diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/host_test/main/Kconfig.projbuild b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/host_test/main/Kconfig.projbuild new file mode 100644 index 000000000..9bf4bba23 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/host_test/main/Kconfig.projbuild @@ -0,0 +1,21 @@ +menu "Test Configuration" + + config TEST_HOSTNAME + string "mDNS Hostname" + default "esp32-mdns" + help + mDNS Hostname for example to use + + config TEST_NETIF_NAME + string "Network interface name" + default "eth2" + help + Name/ID if the network interface on which we run the mDNS host test + + config TEST_CONSOLE + bool "Start console" + default n + help + Test uses esp_console for interactive testing. + +endmenu diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/host_test/main/idf_component.yml b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/host_test/main/idf_component.yml new file mode 100644 index 000000000..e2d4fe9ba --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/host_test/main/idf_component.yml @@ -0,0 +1,7 @@ +dependencies: + idf: ">=5.0" + espressif/mdns: + version: "^1.0.0" + override_path: "../../.." + protocol_examples_common: + path: ${IDF_PATH}/examples/common_components/protocol_examples_common diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/host_test/main/main.c b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/host_test/main/main.c new file mode 100644 index 000000000..a02b8e106 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/host_test/main/main.c @@ -0,0 +1,126 @@ +/* + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ +#include +#include "esp_log.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_console.h" +#include "mdns.h" +#include "mdns_console.h" + +static const char *TAG = "mdns-test"; + +static void mdns_test_app(esp_netif_t *interface); + +#ifdef CONFIG_TEST_CONSOLE +static EventGroupHandle_t s_exit_signal = NULL; + +static int exit_console(int argc, char **argv) +{ + xEventGroupSetBits(s_exit_signal, 1); + return 0; +} + +#else +static void query_mdns_host(const char *host_name) +{ + ESP_LOGI(TAG, "Query A: %s.local", host_name); + + struct esp_ip4_addr addr; + addr.addr = 0; + + esp_err_t err = mdns_query_a(host_name, 2000, &addr); + if (err) { + if (err == ESP_ERR_NOT_FOUND) { + ESP_LOGW(TAG, "%x: Host was not found!", (err)); + return; + } + ESP_LOGE(TAG, "Query Failed: %x", (err)); + return; + } + + ESP_LOGI(TAG, "Query A: %s.local resolved to: " IPSTR, host_name, IP2STR(&addr)); +} +#endif // TEST_CONSOLE + +#ifndef CONFIG_IDF_TARGET_LINUX +#include "protocol_examples_common.h" +#include "esp_event.h" +#include "nvs_flash.h" + +/** + * @brief This is an entry point for the real target device, + * need to init few components and connect to a network interface + */ +void app_main(void) +{ + ESP_ERROR_CHECK(nvs_flash_init()); + ESP_ERROR_CHECK(esp_netif_init()); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + ESP_ERROR_CHECK(example_connect()); + + mdns_test_app(EXAMPLE_INTERFACE); + + ESP_ERROR_CHECK(example_disconnect()); +} +#else + +/** + * @brief This is an entry point for the linux target (simulator on host) + * need to create a dummy WiFi station and use it as mdns network interface + */ +int main(int argc, char *argv[]) +{ + setvbuf(stdout, NULL, _IONBF, 0); + const esp_netif_inherent_config_t base_cg = { .if_key = "WIFI_STA_DEF", .if_desc = CONFIG_TEST_NETIF_NAME }; + esp_netif_config_t cfg = { .base = &base_cg }; + esp_netif_t *sta = esp_netif_new(&cfg); + + mdns_test_app(sta); + + esp_netif_destroy(sta); + return 0; +} +#endif + +static void mdns_test_app(esp_netif_t *interface) +{ + ESP_ERROR_CHECK(mdns_init()); + ESP_ERROR_CHECK(mdns_hostname_set(CONFIG_TEST_HOSTNAME)); + ESP_LOGI(TAG, "mdns hostname set to: [%s]", CONFIG_TEST_HOSTNAME); + ESP_ERROR_CHECK(mdns_register_netif(interface)); + ESP_ERROR_CHECK(mdns_netif_action(interface, MDNS_EVENT_ENABLE_IP4 /*| MDNS_EVENT_ENABLE_IP6 */ | MDNS_EVENT_IP4_REVERSE_LOOKUP | MDNS_EVENT_IP6_REVERSE_LOOKUP)); + +#ifdef CONFIG_TEST_CONSOLE + esp_console_repl_t *repl = NULL; + esp_console_repl_config_t repl_config = ESP_CONSOLE_REPL_CONFIG_DEFAULT(); + esp_console_dev_uart_config_t uart_config = ESP_CONSOLE_DEV_UART_CONFIG_DEFAULT(); + s_exit_signal = xEventGroupCreate(); + + repl_config.prompt = "mdns>"; + // init console REPL environment + ESP_ERROR_CHECK(esp_console_new_repl_uart(&uart_config, &repl_config, &repl)); + + const esp_console_cmd_t cmd_exit = { + .command = "exit", + .help = "exit mDNS console application", + .hint = NULL, + .func = exit_console, + .argtable = NULL + }; + ESP_ERROR_CHECK(esp_console_cmd_register(&cmd_exit)); + mdns_console_register(); + ESP_ERROR_CHECK(esp_console_start_repl(repl)); + xEventGroupWaitBits(s_exit_signal, 1, pdTRUE, pdFALSE, portMAX_DELAY); + repl->del(repl); +#else + vTaskDelay(pdMS_TO_TICKS(10000)); + query_mdns_host("david-work"); + vTaskDelay(pdMS_TO_TICKS(1000)); +#endif + mdns_free(); + ESP_LOGI(TAG, "Exit"); +} diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/host_test/pytest_mdns.py b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/host_test/pytest_mdns.py new file mode 100644 index 000000000..f8b95f551 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/host_test/pytest_mdns.py @@ -0,0 +1,180 @@ +# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: Unlicense OR CC0-1.0 +import logging + +import pexpect +import pytest +from dnsfixture import DnsPythonWrapper + +# Configure logging +logging.basicConfig(level=logging.INFO) +logger = logging.getLogger(__name__) +ipv6_enabled = False + + +class MdnsConsole: + def __init__(self, command): + self.process = pexpect.spawn(command, encoding='utf-8') + self.process.logfile = open('mdns_interaction.log', 'w') # Log all interactions + self.process.expect('mdns> ', timeout=10) + + def send_input(self, input_data): + logger.info(f'Sending to stdin: {input_data}') + self.process.sendline(input_data) + + def get_output(self, expected_data): + logger.info(f'Expecting: {expected_data}') + self.process.expect(expected_data, timeout=10) + output = self.process.before.strip() + logger.info(f'Received from stdout: {output}') + return output + + def terminate(self): + self.send_input('exit') + self.get_output('Exit') + self.process.wait() + self.process.close() + assert self.process.exitstatus == 0 + + +@pytest.fixture(scope='module') +def mdns_console(): + app = MdnsConsole('./build_linux_console/mdns_host.elf') + yield app + app.terminate() + + +@pytest.fixture(scope='module') +def dig_app(): + return DnsPythonWrapper() + + +def test_mdns_init(mdns_console, dig_app): + mdns_console.send_input('mdns_init -h hostname') + mdns_console.get_output('MDNS: Hostname: hostname') + dig_app.check_record('hostname.local', query_type='A', expected=True) + if ipv6_enabled: + dig_app.check_record('hostname.local', query_type='AAAA', expected=True) + + +def test_add_service(mdns_console, dig_app): + mdns_console.send_input('mdns_service_add _http _tcp 80 -i test_service') + mdns_console.get_output('MDNS: Service Instance: test_service') + mdns_console.send_input('mdns_service_lookup _http _tcp') + mdns_console.get_output('PTR : test_service') + dig_app.check_record('_http._tcp.local', query_type='PTR', expected=True) + + +def test_remove_service(mdns_console, dig_app): + mdns_console.send_input('mdns_service_remove _http _tcp') + mdns_console.send_input('mdns_service_lookup _http _tcp') + mdns_console.get_output('No results found!') + dig_app.check_record('_http._tcp.local', query_type='PTR', expected=False) + + +def test_delegate_host(mdns_console, dig_app): + mdns_console.send_input('mdns_delegate_host delegated 1.2.3.4') + dig_app.check_record('delegated.local', query_type='A', expected=True) + + +def test_undelegate_host(mdns_console, dig_app): + mdns_console.send_input('mdns_undelegate_host delegated') + dig_app.check_record('delegated.local', query_type='A', expected=False) + + +def test_add_delegated_service(mdns_console, dig_app): + mdns_console.send_input('mdns_delegate_host delegated 1.2.3.4') + dig_app.check_record('delegated.local', query_type='A', expected=True) + mdns_console.send_input('mdns_service_add _test _tcp 80 -i local') + mdns_console.get_output('MDNS: Service Instance: local') + mdns_console.send_input('mdns_service_add _test2 _tcp 80 -i extern -h delegated') + mdns_console.get_output('MDNS: Service Instance: extern') + mdns_console.send_input('mdns_service_lookup _test _tcp') + mdns_console.get_output('PTR : local') + mdns_console.send_input('mdns_service_lookup _test2 _tcp -d') + mdns_console.get_output('PTR : extern') + dig_app.check_record('_test2._tcp.local', query_type='PTR', expected=True) + dig_app.check_record('extern._test2._tcp.local', query_type='SRV', expected=True) + + +def test_remove_delegated_service(mdns_console, dig_app): + mdns_console.send_input('mdns_service_remove _test2 _tcp -h delegated') + mdns_console.send_input('mdns_service_lookup _test2 _tcp -d') + mdns_console.get_output('No results found!') + dig_app.check_record('_test2._tcp.local', query_type='PTR', expected=False) + # add the delegated service again, would be used in the TXT test + mdns_console.send_input('mdns_service_add _test2 _tcp 80 -i extern -h delegated') + mdns_console.get_output('MDNS: Service Instance: extern') + + +def check_txt_for_service(instance, service, proto, mdns_console, dig_app, host=None, with_inst=False): + for_host_arg = f'-h {host}' if host is not None else '' + for_inst_arg = f'-i {instance}' if with_inst else '' + mdns_console.send_input(f'mdns_service_txt_set {service} {proto} {for_host_arg} {for_inst_arg} key1 value1') + dig_app.check_record(f'{instance}.{service}.{proto}.local', query_type='SRV', expected=True) + dig_app.check_record(f'{service}.{proto}.local', query_type='TXT', expected=True, expect='key1=value1') + mdns_console.send_input(f'mdns_service_txt_set {service} {proto} {for_host_arg} {for_inst_arg} key2 value2') + dig_app.check_record(f'{service}.{proto}.local', query_type='TXT', expected=True, expect='key2=value2') + mdns_console.send_input(f'mdns_service_txt_remove {service} {proto} {for_host_arg} {for_inst_arg} key2') + dig_app.check_record(f'{service}.{proto}.local', query_type='TXT', expected=False, expect='key2=value2') + dig_app.check_record(f'{service}.{proto}.local', query_type='TXT', expected=True, expect='key1=value1') + mdns_console.send_input(f'mdns_service_txt_replace {service} {proto} {for_host_arg} {for_inst_arg} key3=value3 key4=value4') + dig_app.check_record(f'{service}.{proto}.local', query_type='TXT', expected=False, expect='key1=value1') + dig_app.check_record(f'{service}.{proto}.local', query_type='TXT', expected=True, expect='key3=value3') + dig_app.check_record(f'{service}.{proto}.local', query_type='TXT', expected=True, expect='key4=value4') + + +def test_update_txt(mdns_console, dig_app): + check_txt_for_service('local', '_test', '_tcp', mdns_console=mdns_console, dig_app=dig_app) + check_txt_for_service('local', '_test', '_tcp', mdns_console=mdns_console, dig_app=dig_app, with_inst=True) + + +def test_update_delegated_txt(mdns_console, dig_app): + check_txt_for_service('extern', '_test2', '_tcp', mdns_console=mdns_console, dig_app=dig_app, host='delegated') + check_txt_for_service('extern', '_test2', '_tcp', mdns_console=mdns_console, dig_app=dig_app, host='delegated', with_inst=True) + + +def test_service_port_set(mdns_console, dig_app): + dig_app.check_record('local._test._tcp.local', query_type='SRV', expected=True, expect='80') + mdns_console.send_input('mdns_service_port_set _test _tcp 81') + dig_app.check_record('local._test._tcp.local', query_type='SRV', expected=True, expect='81') + mdns_console.send_input('mdns_service_port_set _test2 _tcp -h delegated 82') + dig_app.check_record('extern._test2._tcp.local', query_type='SRV', expected=True, expect='82') + mdns_console.send_input('mdns_service_port_set _test2 _tcp -h delegated -i extern 83') + dig_app.check_record('extern._test2._tcp.local', query_type='SRV', expected=True, expect='83') + mdns_console.send_input('mdns_service_port_set _test2 _tcp -h delegated -i invalid_inst 84') + mdns_console.get_output('ESP_ERR_NOT_FOUND') + dig_app.check_record('extern._test2._tcp.local', query_type='SRV', expected=True, expect='83') + + +def test_service_subtype(mdns_console, dig_app): + dig_app.check_record('local._test._tcp.local', query_type='SRV', expected=True) + mdns_console.send_input('mdns_service_subtype _test _tcp _subtest -i local') + dig_app.check_record('_subtest._sub._test._tcp.local', query_type='PTR', expected=True) + mdns_console.send_input('mdns_service_subtype _test2 _tcp _subtest2 -i extern -h delegated') + dig_app.check_record('_subtest2._sub._test2._tcp.local', query_type='PTR', expected=True) + + +def test_service_set_instance(mdns_console, dig_app): + dig_app.check_record('local._test._tcp.local', query_type='SRV', expected=True) + mdns_console.send_input('mdns_service_instance_set _test _tcp local2') + dig_app.check_record('local2._test._tcp.local', query_type='SRV', expected=True) + mdns_console.send_input('mdns_service_instance_set _test2 _tcp extern2 -h delegated') + mdns_console.send_input('mdns_service_lookup _test2 _tcp -d') + mdns_console.get_output('PTR : extern2') + dig_app.check_record('extern2._test2._tcp.local', query_type='SRV', expected=True) + mdns_console.send_input('mdns_service_instance_set _test2 _tcp extern3 -h delegated -i extern') + mdns_console.get_output('ESP_ERR_NOT_FOUND') + + +def test_service_remove_all(mdns_console, dig_app): + mdns_console.send_input('mdns_service_remove_all') + mdns_console.send_input('mdns_service_lookup _test2 _tcp -d') + mdns_console.get_output('No results found!') + mdns_console.send_input('mdns_service_lookup _test _tcp') + mdns_console.get_output('No results found!') + dig_app.check_record('_test._tcp.local', query_type='PTR', expected=False) + + +if __name__ == '__main__': + pytest.main(['-s', 'test_mdns.py']) diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/host_test/sdkconfig.ci.app b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/host_test/sdkconfig.ci.app new file mode 100644 index 000000000..809c518a1 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/host_test/sdkconfig.ci.app @@ -0,0 +1,4 @@ +CONFIG_IDF_TARGET="linux" +CONFIG_TEST_HOSTNAME="myesp" +CONFIG_MDNS_ENABLE_DEBUG_PRINTS=y +CONFIG_MDNS_RESPOND_REVERSE_QUERIES=y diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/host_test/sdkconfig.ci.console b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/host_test/sdkconfig.ci.console new file mode 100644 index 000000000..3b6dcb674 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/host_test/sdkconfig.ci.console @@ -0,0 +1,4 @@ +CONFIG_IDF_TARGET="linux" +CONFIG_ESP_EVENT_POST_FROM_ISR=n +CONFIG_MDNS_ENABLE_CONSOLE_CLI=y +CONFIG_TEST_CONSOLE=y diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/host_test/sdkconfig.ci.target b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/host_test/sdkconfig.ci.target new file mode 100644 index 000000000..2a43df1a3 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/host_test/sdkconfig.ci.target @@ -0,0 +1 @@ +CONFIG_IDF_TARGET="esp32" diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/host_test/sdkconfig.defaults b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/host_test/sdkconfig.defaults new file mode 100644 index 000000000..7e79ce497 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/host_test/sdkconfig.defaults @@ -0,0 +1,6 @@ +CONFIG_TEST_NETIF_NAME="eth0" +CONFIG_ESP_EVENT_POST_FROM_ISR=n +CONFIG_MDNS_NETWORKING_SOCKET=y +CONFIG_MDNS_SKIP_SUPPRESSING_OWN_QUERIES=y +CONFIG_MDNS_PREDEF_NETIF_STA=n +CONFIG_MDNS_PREDEF_NETIF_AP=n diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/CMakeLists.txt b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/CMakeLists.txt new file mode 100644 index 000000000..d65845194 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/CMakeLists.txt @@ -0,0 +1,7 @@ +# The following four 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(fuzz_test_update) diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/Makefile b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/Makefile new file mode 100644 index 000000000..6f45edb9d --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/Makefile @@ -0,0 +1,82 @@ +TEST_NAME=test +FUZZ=afl-fuzz +COMPONENTS_DIR=$(IDF_PATH)/components +COMPILER_ICLUDE_DIR=$(shell echo `which xtensa-esp32-elf-gcc | xargs dirname | xargs dirname`/xtensa-esp32-elf) + +CFLAGS=-g -Wno-unused-value -Wno-missing-declarations -Wno-pointer-bool-conversion -Wno-macro-redefined -Wno-int-to-void-pointer-cast -DHOOK_MALLOC_FAILED -DESP_EVENT_H_ -D__ESP_LOG_H__ \ + -I. -I../.. -I../../include -I../../private_include -I ./build/config \ + -I$(COMPONENTS_DIR) \ + -I$(COMPONENTS_DIR)/driver/include \ + -I$(COMPONENTS_DIR)/esp_common/include \ + -I$(COMPONENTS_DIR)/esp_event/include \ + -I$(COMPONENTS_DIR)/esp_eth/include \ + -I$(COMPONENTS_DIR)/esp_hw_support/include \ + -I$(COMPONENTS_DIR)/esp_netif/include \ + -I$(COMPONENTS_DIR)/esp_netif/private_include \ + -I$(COMPONENTS_DIR)/esp_netif/lwip \ + -I$(COMPONENTS_DIR)/esp_rom/include \ + -I$(COMPONENTS_DIR)/esp_system/include \ + -I$(COMPONENTS_DIR)/esp_timer/include \ + -I$(COMPONENTS_DIR)/esp_wifi/include \ + -I$(COMPONENTS_DIR)/freertos/FreeRTOS-Kernel \ + -I$(COMPONENTS_DIR)/freertos/FreeRTOS-Kernel/include \ + -I$(COMPONENTS_DIR)/freertos/esp_additions/include/freertos \ + -I$(COMPONENTS_DIR)/hal/include \ + -I$(COMPONENTS_DIR)/hal/esp32/include \ + -I$(COMPONENTS_DIR)/heap/include \ + -I$(COMPONENTS_DIR)/log/include \ + -I$(COMPONENTS_DIR)/lwip/lwip/src/include \ + -I$(COMPONENTS_DIR)/linux/include \ + -I$(COMPONENTS_DIR)/lwip/port/esp32/include \ + -I$(COMPONENTS_DIR)/lwip/lwip/src/include/lwip/apps \ + -I$(COMPONENTS_DIR)/soc/include \ + -I$(COMPONENTS_DIR)/soc/esp32/include \ + -I$(COMPONENTS_DIR)/soc/src/esp32/include \ + -I$(COMPONENTS_DIR)/xtensa/include \ + -I$(COMPONENTS_DIR)/xtensa/esp32/include \ + -I$(COMPILER_ICLUDE_DIR)/include + + +MDNS_C_DEPENDENCY_INJECTION=-include mdns_di.h +ifeq ($(MDNS_NO_SERVICES),on) + CFLAGS+=-DMDNS_NO_SERVICES +endif + +ifeq ($(INSTR),off) + CC=gcc + CFLAGS+=-DINSTR_IS_OFF + TEST_NAME=test_sim +else + CC=afl-clang-fast +endif +CPP=$(CC) +LD=$(CC) +OBJECTS=esp32_mock.o mdns.o test.o esp_netif_mock.o + +OS := $(shell uname) +ifeq ($(OS),Darwin) + LDLIBS= +else + LDLIBS=-lbsd + CFLAGS+=-DUSE_BSD_STRING +endif + +all: $(TEST_NAME) + +%.o: %.c + @echo "[CC] $<" + @$(CC) $(CFLAGS) -c $< -o $@ + +mdns.o: ../../mdns.c + @echo "[CC] $<" + @$(CC) $(CFLAGS) -include mdns_mock.h $(MDNS_C_DEPENDENCY_INJECTION) -c $< -o $@ + +$(TEST_NAME): $(OBJECTS) + @echo "[LD] $@" + @$(LD) $(OBJECTS) -o $@ $(LDLIBS) + +fuzz: $(TEST_NAME) + @$(FUZZ) -i "in" -o "out" -- ./$(TEST_NAME) + +clean: + @rm -rf *.o *.SYM $(TEST_NAME) out diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/README.md b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/README.md new file mode 100644 index 000000000..e22a89606 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/README.md @@ -0,0 +1,80 @@ +## Introduction +This test uses [american fuzzy lop](http://lcamtuf.coredump.cx/afl/) to mangle real mdns packets and look for exceptions caused by the parser. + +A few actual packets are collected and exported as bins in the `in` folder, which is then passed as input to AFL when testing. The setup procedure for the test includes all possible services and scenarios that could be used with the given input packets.The output of the parser before fuzzing can be found in [input_packets.txt](input_packets.txt) + +## Building and running the tests using AFL +To build and run the tests using AFL(afl-clang-fast) instrumentation + +```bash +cd $IDF_PATH/components/mdns/test_afl_host +make fuzz +``` + +(Please note you have to install AFL instrumentation first, check `Installing AFL` section) + +## Building the tests using GCC INSTR(off) + +To build the tests without AFL instrumentations and instead of that use GCC compiler(In this case it will only check for compilation issues and will not run AFL tests). + +```bash +cd $IDF_PATH/components/mdns/test_afl_host +make INSTR=off +``` + +Note, that this setup is useful if we want to reproduce issues reported by fuzzer tests executed in the CI, or to simulate how the packet parser treats the input packets on the host machine. + +## Installing AFL +To run the test yourself, you need to download the [latest afl archive](http://lcamtuf.coredump.cx/afl/releases/afl-latest.tgz) and extract it to a folder on your computer. + +The rest of the document will refer to that folder as ```PATH_TO_AFL```. + +### Preparation +- On Mac, you will need to install the latest Xcode and llvm support from [Homebrew](https://brew.sh) + + ```bash + /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" + brew install --with-clang --with-lld --HEAD llvm + export PATH="/usr/local/opt/llvm/bin:$PATH" + ``` + +- On Ubuntu you need the following packages: + + ```bash + sudo apt-get install make clang-4.0(or <=4.0) llvm-4.0(or <=4.0) libbsd-dev + ``` + +Please note that if specified package version can't be installed(due to system is the latest), you can download, build and install it manually. + +### Compile AFL +Compiling AFL is as easy as running make: + +```bash +cd [PATH_TO_AFL] +make +cd llvm_mode/ +make +``` + +After successful compilation, you can export the following variables to your shell (you can also add them to your profile if you want to use AFL in other projects). + +```bash +export AFL_PATH=[PATH_TO_AFL] +export PATH="$AFL_PATH:$PATH" +``` + +Please note LLVM must be <=4.0.0, otherwise afl does not compile, as there are some limitations with building AFL on MacOS/Linux with the latest LLVM. Also, Windows build on cygwin is not fully supported. + +## Additional info +Apple has a crash reporting service that could interfere with AFLs normal operation. To turn that off, run the following command: + +```bash +launchctl unload -w /System/Library/LaunchAgents/com.apple.ReportCrash.plist +sudo launchctl unload -w /System/Library/LaunchDaemons/com.apple.ReportCrash.Root.plist +``` + +Ubuntu has a similar service. To turn that off, run as root: + +```bash +echo core >/proc/sys/kernel/core_pattern +``` diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/esp32_mock.c b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/esp32_mock.c new file mode 100644 index 000000000..7f14dc6ba --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/esp32_mock.c @@ -0,0 +1,162 @@ +/* + * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ +#include +#include +#include +#include +#include +#include "esp32_mock.h" +#include "esp_log.h" + +void *g_queue; +int g_queue_send_shall_fail = 0; +int g_size = 0; + +const char *WIFI_EVENT = "wifi_event"; +const char *ETH_EVENT = "eth_event"; + +esp_err_t esp_event_handler_register(const char *event_base, + int32_t event_id, + void *event_handler, + void *event_handler_arg) +{ + return ESP_OK; +} + +esp_err_t esp_event_handler_unregister(const char *event_base, int32_t event_id, void *event_handler) +{ + return ESP_OK; +} + +esp_err_t esp_timer_delete(esp_timer_handle_t timer) +{ + return ESP_OK; +} + +esp_err_t esp_timer_stop(esp_timer_handle_t timer) +{ + return ESP_OK; +} + +esp_err_t esp_timer_start_periodic(esp_timer_handle_t timer, uint64_t period) +{ + return ESP_OK; +} + +esp_err_t esp_timer_create(const esp_timer_create_args_t *create_args, + esp_timer_handle_t *out_handle) +{ + return ESP_OK; +} + +uint32_t xTaskGetTickCount(void) +{ + static uint32_t tick = 0; + return tick++; +} + +/// Queue mock +QueueHandle_t xQueueCreate(uint32_t uxQueueLength, uint32_t uxItemSize) +{ + g_size = uxItemSize; + g_queue = malloc((uxQueueLength) * (uxItemSize)); + return g_queue; +} + + +void vQueueDelete(QueueHandle_t xQueue) +{ + free(xQueue); +} + +uint32_t xQueueSend(QueueHandle_t xQueue, const void *pvItemToQueue, TickType_t xTicksToWait) +{ + if (g_queue_send_shall_fail) { + return pdFALSE; + } else { + memcpy(xQueue, pvItemToQueue, g_size); + return pdPASS; + } +} + + +uint32_t xQueueReceive(QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksToWait) +{ + return pdFALSE; +} + +void GetLastItem(void *pvBuffer) +{ + memcpy(pvBuffer, g_queue, g_size); +} + +void ForceTaskDelete(void) +{ + g_queue_send_shall_fail = 1; +} + +TaskHandle_t xTaskGetCurrentTaskHandle(void) +{ + return NULL; +} + +void xTaskNotifyGive(TaskHandle_t task) +{ + return; +} + +BaseType_t xTaskNotifyWait(uint32_t bits_entry_clear, uint32_t bits_exit_clear, uint32_t *value, TickType_t wait_time) +{ + return pdTRUE; +} + +void esp_log_write(esp_log_level_t level, const char *tag, const char *format, ...) +{ +} + +void esp_log(esp_log_config_t config, const char *tag, const char *format, ...) +{ +} + +uint32_t esp_log_timestamp(void) +{ + return 0; +} + +void *mdns_mem_malloc(size_t size) +{ + return malloc(size); +} + +void *mdns_mem_calloc(size_t num, size_t size) +{ + return calloc(num, size); +} + +void mdns_mem_free(void *ptr) +{ + free(ptr); +} + +char *mdns_mem_strdup(const char *s) +{ + return strdup(s); +} + +char *mdns_mem_strndup(const char *s, size_t n) +{ + return strndup(s, n); +} + +void *mdns_mem_task_malloc(size_t size) +{ + return malloc(size); +} + +void mdns_mem_task_free(void *ptr) +{ + free(ptr); +} diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/esp32_mock.h b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/esp32_mock.h new file mode 100644 index 000000000..68a346105 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/esp32_mock.h @@ -0,0 +1,142 @@ +/* + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef _ESP32_COMPAT_H_ +#define _ESP32_COMPAT_H_ + +// Skip these include files +#define ESP_MDNS_NETWORKING_H_ +#define INC_FREERTOS_H +#define QUEUE_H +#define SEMAPHORE_H +#define _ESP_TASK_H_ + +#ifdef USE_BSD_STRING +#include +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include "esp_timer.h" + +#define ESP_FAIL -1 + +#define ESP_ERR_NO_MEM 0x101 +#define ESP_ERR_INVALID_ARG 0x102 +#define ESP_ERR_INVALID_STATE 0x103 +#define ESP_ERR_INVALID_SIZE 0x104 +#define ESP_ERR_NOT_FOUND 0x105 +#define ESP_ERR_NOT_SUPPORTED 0x106 +#define ESP_ERR_TIMEOUT 0x107 +#define ESP_ERR_INVALID_RESPONSE 0x108 +#define ESP_ERR_INVALID_CRC 0x109 + +#define MDNS_TASK_MEMORY_LOG "internal RAM" +#define MALLOC_CAP_8BIT (1<<2) +#define MALLOC_CAP_INTERNAL (1<<11) + +#define pdTRUE true +#define pdFALSE false +#define pdPASS ( pdTRUE ) +#define pdFAIL ( pdFALSE ) + +#define portMAX_DELAY 0xFFFFFFFF +#define portTICK_PERIOD_MS 1 +#define LWIP_HDR_PBUF_H +#define __ESP_RANDOM_H__ +#define INC_TASK_H + +#define pdMS_TO_TICKS(a) a +#define xSemaphoreTake(s,d) true +#define xTaskDelete(a) +#define vTaskDelete(a) free(a) +#define xSemaphoreGive(s) +#define xQueueCreateMutex(s) +#define _mdns_pcb_init(a,b) true +#define _mdns_pcb_deinit(a,b) true +#define xSemaphoreCreateMutex() malloc(1) +#define xSemaphoreCreateBinary() malloc(1) +#define vSemaphoreDelete(s) free(s) +#define queueQUEUE_TYPE_MUTEX ( ( uint8_t ) 1U +#define xTaskCreatePinnedToCore(a,b,c,d,e,f,g) *(f) = malloc(1) +#define xTaskCreateStaticPinnedToCore(a,b,c,d,e,f,g,h) true +#define vTaskDelay(m) usleep((m)*0) +#define esp_random() (rand()%UINT32_MAX) + + +#define ESP_TASK_PRIO_MAX 25 +#define ESP_TASKD_EVENT_PRIO 5 +#define _mdns_udp_pcb_write(tcpip_if, ip_protocol, ip, port, data, len) len +#define TaskHandle_t TaskHandle_t + + +typedef int32_t esp_err_t; + +typedef void *SemaphoreHandle_t; +typedef void *QueueHandle_t; +typedef void *TaskHandle_t; +typedef int BaseType_t; +typedef uint32_t TickType_t; +typedef void *StackType_t; +typedef void *StaticTask_t; + +struct udp_pcb { + uint8_t dummy; +}; + +struct ip4_addr { + uint32_t addr; +}; +typedef struct ip4_addr ip4_addr_t; + +struct ip6_addr { + uint32_t addr[4]; +}; +typedef struct ip6_addr ip6_addr_t; + +typedef void *system_event_t; + +struct pbuf { + struct pbuf *next; + void *payload; + uint16_t tot_len; + uint16_t len; + uint8_t /*pbuf_type*/ type; + uint8_t flags; + uint16_t ref; +}; + +uint32_t xTaskGetTickCount(void); +typedef void (*esp_timer_cb_t)(void *arg); + +// Queue mock +QueueHandle_t xQueueCreate(uint32_t uxQueueLength, + uint32_t uxItemSize); + +void vQueueDelete(QueueHandle_t xQueue); + +uint32_t xQueueSend(QueueHandle_t xQueue, const void *pvItemToQueue, TickType_t xTicksToWait); + +uint32_t xQueueReceive(QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksToWait); + +void GetLastItem(void *pvBuffer); + +void ForceTaskDelete(void); + +esp_err_t esp_event_handler_register(const char *event_base, int32_t event_id, void *event_handler, void *event_handler_arg); + +esp_err_t esp_event_handler_unregister(const char *event_base, int32_t event_id, void *event_handler); + + +TaskHandle_t xTaskGetCurrentTaskHandle(void); +void xTaskNotifyGive(TaskHandle_t task); +BaseType_t xTaskNotifyWait(uint32_t bits_entry_clear, uint32_t bits_exit_clear, uint32_t *value, TickType_t wait_time); + +#endif //_ESP32_COMPAT_H_ diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/esp_attr.h b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/esp_attr.h new file mode 100644 index 000000000..75b66786a --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/esp_attr.h @@ -0,0 +1,14 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ +#pragma once +#define IRAM_ATTR +#define FLAG_ATTR(TYPE) +#define QUEUE_H +#define __ARCH_CC_H__ +#define __XTENSA_API_H__ +#define SSIZE_MAX INT_MAX +#define LWIP_HDR_IP6_ADDR_H +#define LWIP_HDR_IP4_ADDR_H diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/esp_netif_mock.c b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/esp_netif_mock.c new file mode 100644 index 000000000..80629ad63 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/esp_netif_mock.c @@ -0,0 +1,55 @@ +/* + * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include "esp32_mock.h" + +typedef struct esp_netif_s esp_netif_t; +typedef struct esp_netif_ip_info esp_netif_ip_info_t; +typedef struct esp_netif_dhcp_status esp_netif_dhcp_status_t; + + +const char *IP_EVENT = "IP_EVENT"; + + +esp_err_t esp_netif_add_to_list(esp_netif_t *netif) +{ + return ESP_OK; +} + +esp_err_t esp_netif_remove_from_list(esp_netif_t *netif) +{ + return ESP_ERR_NOT_FOUND; +} + +esp_netif_t *esp_netif_next(esp_netif_t *netif) +{ + return NULL; +} + +esp_netif_t *esp_netif_next_unsafe(esp_netif_t *netif) +{ + return NULL; +} + +esp_netif_t *esp_netif_get_handle_from_ifkey(const char *if_key) +{ + return NULL; +} + +esp_err_t esp_netif_get_ip_info(esp_netif_t *esp_netif, esp_netif_ip_info_t *ip_info) +{ + return ESP_ERR_NOT_SUPPORTED; +} + +esp_err_t esp_netif_dhcpc_get_status(esp_netif_t *esp_netif, esp_netif_dhcp_status_t *status) +{ + return ESP_ERR_NOT_SUPPORTED; +} diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/in/file2.bin b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/in/file2.bin new file mode 100644 index 0000000000000000000000000000000000000000..a7ce859cc0fdf7cef7985d51d480e03cef0bde7e GIT binary patch literal 33 kcmZQz00Kr3!N9*z=%+RBzQm% hBz1s?L6LzGXixSyIIkUy@wFnv;?$zD)FPJn;?g9x__U(Tk}8(?lH>x`oc!d(90mp+2F3$CAd-PW Ra1sL#XKrR*CRo)0NdPDN5l#RA literal 0 HcmV?d00001 diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/in/telnet_ptr.bin b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/in/telnet_ptr.bin new file mode 100644 index 0000000000000000000000000000000000000000..1cd8e85d8021f55039566cdd619235aeb952ffa6 GIT binary patch literal 72 zcmZQzXkh>XMi9XnUz}Q0mYJMd%pRYTSFBr{!V+JaQox#%pPZP(z`z4iB{+paggw3_ PH775%geATt872z=Qoj-} literal 0 HcmV?d00001 diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/in/test-14.bin b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/in/test-14.bin new file mode 100644 index 0000000000000000000000000000000000000000..b9d059d8202682602e7232a8505c495a3047e3a4 GIT binary patch literal 568 zcmaiwPfNov7{)Vc-GqW7j)|wjsGcf~S~hRiF&W~a2k#+k0~WgWB}sAnMEe#aev*0f zYnYmKpg5L8@;*Gj_g@gw=M=T;r$cDQq2$scG66d;6PhFBpq5SEqy*Ki;|>9y6_W8k z(juaoD$gKwot!QVViQiwP4*$FL_!N=w2csr$^a@cZR*xs(X_FMHk)!f+~gb+NOM1> zk_yQgof*O+&`j$PkuwH9@N&MeNR@)Rs7LhfhXIZT<8b&C;fD#&geg za3+LG&Fd@xs>KLTNcn;-*5pXh{6Hl3Gf@0Bv?l!J7wTd;niT zpQFAGPvJB)ejMCnH#5JT{b&BO0M9^cBj1M?YNV6sL|5fVbt9Ej+lyF*S{proq+$Y_ zy(EZB<0$aQ0F|dTfW0^Pc%S>15?e0gf=P$9ZRU2E6gBl1yUeqg)y}c?t9peygs&#} z7|j&Zdeo=X8zO0VLkn$-((43yUL=X?$Ick}!j;^kSawken}R!yj@dNbnpQ!IPSfSw z6t(+@>poibXblSGtk>cz>tEHauqc}6a-MwrlizE$|MzI+T(JBX1>O+*nyq$)j zQylnX9d7k~Ow=qiw8BP1a9+~%qG`nQ)xD8Uv1!|NXD5mA#_QH@&$~uSCEPYe#h+j? zazWa{-WhziU)BS1Dn2W)3#)mrXUl8}NBQ(&0aZF-|Mg&HNV7tR6XMi3VDD9S7@$yYB{2+7P%Rd7x$C@#%O<%mzrEGoz^Dq)E)NiJZ`$xlwq zVPFtw0BRAO!mwg_d7`hQt+|1&xv{RZldhAAuCt}Cld(<_s<4x;fr+lGIY`(DNi{^+ z0x0a4YnzvpS*%-zV0U=oA+vm)V+|Sr{1T8R{fu1*g~=8yw(a(1*I26Ub&|U}#`) F005APLjnK* literal 0 HcmV?d00001 diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/in/test-28.bin b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/in/test-28.bin new file mode 100644 index 0000000000000000000000000000000000000000..537352ae67db92f820ff0d1299dae3534eef1f48 GIT binary patch literal 62 zcmZQz00Kr3!N4HuQIuI+lCNH@5R#djs^FYhP+Xdm${nAWR*+woT2zu;z!DE6Sab4| L6LT0C6dM=;y^9dW literal 0 HcmV?d00001 diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/in/test-29.bin b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/in/test-29.bin new file mode 100644 index 0000000000000000000000000000000000000000..837737b32e12e3f33ff3f1c3b59f6ff351b05fba GIT binary patch literal 39 qcmZQz00Jfu!N9XCLm_y%+1WpOe@MPsbbB^PfpBXV328G1WHse2>fdR(m)`h7xI6{k-wY= bco-O=ax4c{{1X83^`U$YAe+U3fq?@6q#+cG literal 0 HcmV?d00001 diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/in/test-53.bin b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/in/test-53.bin new file mode 100644 index 0000000000000000000000000000000000000000..73181ea8c378d33efed725aa209387113edffdd3 GIT binary patch literal 140 zcmZQz00Jf;1Ok@$;@l*b_>$xT)|~w0#2f|&9tKA7;QX}A%0ykyvc$anvczIt-^666 z{QT?#VhoH7j0bo?Y8V)}zcR>5K~yS0RX%E%S*!q4%mY{WjX^@xqbReuBwxK)AtW<5 PRlzy2ptv+A^#Bh5gdisG literal 0 HcmV?d00001 diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/in/test-56.bin b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/in/test-56.bin new file mode 100644 index 0000000000000000000000000000000000000000..980b6516a20908c4b681b1cf3717c7ef35f062b6 GIT binary patch literal 262 zcmZQzXkh>XCLm@L_9)6MF3Eq?Ftb>}H!)cuH#0AjCq5;$EHgP(H#09SpC!H|xqvk% zKRGdnfkA+Qk%2*Q3WJP5ZhlH?jxA6JNQ0S<5m$b3MOkW5v8|yQOMG!|(g9rt9;jk5 zY<3)oKTyCR&;T)xkpak21aTND7=%D>W8BLLGB~X$v!v>P(SfB5GEiB8e+?jc1_lwm xkpDZ5{N)77F+$~74y^bm05nM-YAh#^&C0;gz~BH>1QrAu&jDn!I5049006}!N5=pF literal 0 HcmV?d00001 diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/in/test-63.bin b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/in/test-63.bin new file mode 100644 index 0000000000000000000000000000000000000000..883d444ba269c8938aa87f3ba8da53a1305f9763 GIT binary patch literal 147 zcmZQz00Jf;1Oo2(#I%C^vecrIAisgkVmtU4x ztm~VY?3ACMeL$9hk%9354@eEr1V;v0DTqo1sLDqTGm8~qig}O}N{D(CWfqs@s~0PT SWag$SI42eqm*%7%-~j;3q9}|2 literal 0 HcmV?d00001 diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/in/test-83.bin b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/in/test-83.bin new file mode 100644 index 0000000000000000000000000000000000000000..c6cc159a2597bc35b4316a796af18534bfee7dc3 GIT binary patch literal 105 zcmZQzXkh>XMj&Pq56(}^tW4DPEKAJGFH0=e^-WB6%FoYc&B;$r%mFHD04b|rU^%ej opU43o1{o+{;9mn!90-_XHvj*(sc11!P9G}A0c5i{Ffecc09-p6=Kufz literal 0 HcmV?d00001 diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/in/test-88.bin b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/in/test-88.bin new file mode 100644 index 0000000000000000000000000000000000000000..fcbb384438a28961526215b8b66e32193b6fd0e8 GIT binary patch literal 48 xcmZQz00Jfu!N9;0UzC=_5?_*Bz?zevoS4JFz{9}E5ucb@RFGd(azGHo1pvO@39SGC literal 0 HcmV?d00001 diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/in/test-89.bin b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/in/test-89.bin new file mode 100644 index 0000000000000000000000000000000000000000..d60a987cad92fe5e9e86e83ea8d2ee16f7fe93e2 GIT binary patch literal 459 zcmZut!AiqG6nsjH6?&*>t%!$uQZQS0laj>4LYts?QG|-ulBSVH(x&XjT5mmg=~3_> ztY`gzT*ZHizSvY0e6Z}id9$-S3-AC~%eYnwZO0eGP(-mV!P{&eAgrX;5v-UP|9p7oBgos1w8f0EOdo2ePiw} zNje}4^KDp~;Po(uTs%uyd;q1i$LGwR@0_zHHz+YQVq3(j6Z?o*nj-$v7NK==Y^1dM zOFgGeq|f_&(D5aSJQ-nY_c&vUuzMxFc@pCZ#o|bZ%N*uF-f3J6VQOGQliZLVkQEZ||>|XE&P_Qhxn0o}&II^Gj0M Z$Nq4kL7Zy<6!6?PhySpOI1ey^#uu&jeZK$z literal 0 HcmV?d00001 diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/in/test-95.bin b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/in/test-95.bin new file mode 100644 index 0000000000000000000000000000000000000000..26553090fa6d7cddb5fb7c748fc72d8d20c77364 GIT binary patch literal 286 zcmZQz00L$PHW0-fpO{vVUzS=_l3c(N4XCLm@O^(e|LF3DFfRtU+=O;vDCEGRC`N#%)8NiEAvPSwrKOUq}8FG((7 z&B;$r%wb>1yv^6)dGB>tzcCvCZv2wPwax&IQObK(dHK;H&FfedS$u_cu z^DV$~ezs8iK?*}{O-<7hlaefwbQ8^tlXOi@Obm4`EzC`H%~Dg6Obtv@lZ*`#fi^3G pY-XrnkOhSV1E&Zi7>ad4{?UaRc)$dxP#@|pb->payload; +} + +static inline size_t _mdns_get_packet_len(mdns_rx_packet_t *packet) +{ + return packet->pb->len; +} + +static inline void _mdns_packet_free(mdns_rx_packet_t *packet) +{ + free(packet->pb); + free(packet); +} + +static inline bool mdns_is_netif_ready(mdns_if_t tcpip_if, mdns_ip_protocol_t ip_protocol) +{ + return true; +} diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/sdkconfig.h b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/sdkconfig.h new file mode 100644 index 000000000..da75d1475 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/sdkconfig.h @@ -0,0 +1,424 @@ +/* + * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ +/* + * This config file commited in order to not run `idf.py reconfigure` each time when running fuzzer test. You can modify it manually or run `idf.py reconfigure` to generate new one if needed. + * Espressif IoT Development Framework (ESP-IDF) Configuration Header + */ +#pragma once +#define CONFIG_IDF_TARGET "esp32" +#define CONFIG_IDF_TARGET_ESP32 1 +#define CONFIG_IDF_FIRMWARE_CHIP_ID 0x0000 +#define CONFIG_SDK_TOOLPREFIX "xtensa-esp32-elf-" +#define CONFIG_APP_BUILD_TYPE_APP_2NDBOOT 1 +#define CONFIG_APP_BUILD_GENERATE_BINARIES 1 +#define CONFIG_APP_BUILD_BOOTLOADER 1 +#define CONFIG_APP_BUILD_USE_FLASH_SECTIONS 1 +#define CONFIG_APP_COMPILE_TIME_DATE 1 +#define CONFIG_APP_RETRIEVE_LEN_ELF_SHA 16 +#define CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE 1 +#define CONFIG_BOOTLOADER_LOG_LEVEL_INFO 1 +#define CONFIG_BOOTLOADER_LOG_LEVEL 3 +#define CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V 1 +#define CONFIG_BOOTLOADER_WDT_ENABLE 1 +#define CONFIG_BOOTLOADER_WDT_TIME_MS 9000 +#define CONFIG_BOOTLOADER_RESERVE_RTC_SIZE 0x0 +#define CONFIG_ESPTOOLPY_WITH_STUB 1 +#define CONFIG_ESPTOOLPY_FLASHMODE_DIO 1 +#define CONFIG_ESPTOOLPY_FLASHMODE "dio" +#define CONFIG_ESPTOOLPY_FLASHFREQ_40M 1 +#define CONFIG_ESPTOOLPY_FLASHFREQ "40m" +#define CONFIG_ESPTOOLPY_FLASHSIZE_2MB 1 +#define CONFIG_ESPTOOLPY_FLASHSIZE "2MB" +#define CONFIG_ESPTOOLPY_FLASHSIZE_DETECT 1 +#define CONFIG_ESPTOOLPY_BEFORE_RESET 1 +#define CONFIG_ESPTOOLPY_BEFORE "default_reset" +#define CONFIG_ESPTOOLPY_AFTER_RESET 1 +#define CONFIG_ESPTOOLPY_AFTER "hard_reset" +#define CONFIG_PARTITION_TABLE_SINGLE_APP 1 +#define CONFIG_PARTITION_TABLE_CUSTOM_FILENAME "partitions.csv" +#define CONFIG_PARTITION_TABLE_FILENAME "partitions_singleapp.csv" +#define CONFIG_PARTITION_TABLE_OFFSET 0x8000 +#define CONFIG_PARTITION_TABLE_MD5 1 +#define CONFIG_COMPILER_OPTIMIZATION_DEFAULT 1 +#define CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE 1 +#define CONFIG_COMPILER_STACK_CHECK_MODE_NONE 1 +#define CONFIG_APPTRACE_DEST_NONE 1 +#define CONFIG_APPTRACE_LOCK_ENABLE 1 +#define CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF 0 +#define CONFIG_BTDM_CTRL_BLE_MAX_CONN_EFF 0 +#define CONFIG_BTDM_CTRL_BR_EDR_MAX_ACL_CONN_EFF 0 +#define CONFIG_BTDM_CTRL_BR_EDR_MAX_SYNC_CONN_EFF 0 +#define CONFIG_BTDM_CTRL_PINNED_TO_CORE 0 +#define CONFIG_BTDM_BLE_SLEEP_CLOCK_ACCURACY_INDEX_EFF 1 +#define CONFIG_BTDM_RESERVE_DRAM 0x0 +#define CONFIG_COAP_MBEDTLS_PSK 1 +#define CONFIG_COAP_LOG_DEFAULT_LEVEL 0 +#define CONFIG_ADC_DISABLE_DAC 1 +#define CONFIG_SPI_MASTER_ISR_IN_IRAM 1 +#define CONFIG_SPI_SLAVE_ISR_IN_IRAM 1 +#define CONFIG_EFUSE_CODE_SCHEME_COMPAT_3_4 1 +#define CONFIG_EFUSE_MAX_BLK_LEN 192 +#define CONFIG_ESP_TLS_USING_MBEDTLS 1 +#define CONFIG_ESP32_REV_MIN_0 1 +#define CONFIG_ESP32_REV_MIN 0 +#define CONFIG_ESP32_DPORT_WORKAROUND 1 +#define CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_160 1 +#define CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ 160 +#define CONFIG_ESP32_TRACEMEM_RESERVE_DRAM 0x0 +#define CONFIG_ESP32_UNIVERSAL_MAC_ADDRESSES_FOUR 1 +#define CONFIG_ESP32_UNIVERSAL_MAC_ADDRESSES 4 +#define CONFIG_ULP_COPROC_RESERVE_MEM 0 +#define CONFIG_ESP_DEBUG_OCDAWARE 1 +#define CONFIG_ESP_BROWNOUT_DET 1 +#define CONFIG_ESP_BROWNOUT_DET_LVL_SEL_0 1 +#define CONFIG_ESP_BROWNOUT_DET_LVL 0 +#define CONFIG_ESP32_REDUCE_PHY_TX_POWER 1 +#define CONFIG_NEWLIB_TIME_SYSCALL_USE_RTC_HRT 1 +#define CONFIG_RTC_CLK_SRC_INT_RC 1 +#define CONFIG_RTC_CLK_CAL_CYCLES 1024 +#define CONFIG_ESP32_DEEP_SLEEP_WAKEUP_DELAY 2000 +#define CONFIG_ESP32_XTAL_FREQ_40 1 +#define CONFIG_ESP32_XTAL_FREQ 40 +#define CONFIG_ESP32_DPORT_DIS_INTERRUPT_LVL 5 +#define CONFIG_ADC_CAL_EFUSE_TP_ENABLE 1 +#define CONFIG_ADC_CAL_EFUSE_VREF_ENABLE 1 +#define CONFIG_ADC_CAL_LUT_ENABLE 1 +#define CONFIG_ESP_ERR_TO_NAME_LOOKUP 1 +#define CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE 32 +#define CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE 2304 +#define CONFIG_ESP_MAIN_TASK_STACK_SIZE 3584 +#define CONFIG_ESP_IPC_TASK_STACK_SIZE 1024 +#define CONFIG_ESP_IPC_USES_CALLERS_PRIORITY 1 +#define CONFIG_ESP_MINIMAL_SHARED_STACK_SIZE 2048 +#define CONFIG_ESP_CONSOLE_UART_DEFAULT 1 +#define CONFIG_ESP_CONSOLE_UART_NUM 0 +#define CONFIG_ESP_CONSOLE_UART_TX_GPIO 1 +#define CONFIG_ESP_CONSOLE_UART_RX_GPIO 3 +#define CONFIG_ESP_CONSOLE_UART_BAUDRATE 115200 +#define CONFIG_ESP_INT_WDT 1 +#define CONFIG_ESP_INT_WDT_TIMEOUT_MS 300 +#define CONFIG_ESP_INT_WDT_CHECK_CPU1 1 +#define CONFIG_ESP_TASK_WDT 1 +#define CONFIG_ESP_TASK_WDT_TIMEOUT_S 5 +#define CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0 1 +#define CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1 1 +#define CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_STA 1 +#define CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_AP 1 +#define CONFIG_ESP_MAC_ADDR_UNIVERSE_BT 1 +#define CONFIG_ESP_MAC_ADDR_UNIVERSE_BT_OFFSET 2 +#define CONFIG_ESP_MAC_ADDR_UNIVERSE_ETH 1 +#define CONFIG_ETH_ENABLED 1 +#define CONFIG_ETH_USE_ESP32_EMAC 1 +#define CONFIG_ETH_PHY_INTERFACE_RMII 1 +#define CONFIG_ETH_RMII_CLK_INPUT 1 +#define CONFIG_ETH_RMII_CLK_IN_GPIO 0 +#define CONFIG_ETH_DMA_BUFFER_SIZE 512 +#define CONFIG_ETH_DMA_RX_BUFFER_NUM 10 +#define CONFIG_ETH_DMA_TX_BUFFER_NUM 10 +#define CONFIG_ETH_USE_SPI_ETHERNET 1 +#define CONFIG_ESP_EVENT_POST_FROM_ISR 1 +#define CONFIG_ESP_EVENT_POST_FROM_IRAM_ISR 1 +#define CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS 1 +#define CONFIG_HTTPD_MAX_REQ_HDR_LEN 512 +#define CONFIG_HTTPD_MAX_URI_LEN 512 +#define CONFIG_HTTPD_ERR_RESP_NO_DELAY 1 +#define CONFIG_HTTPD_PURGE_BUF_LEN 32 +#define CONFIG_ESP_NETIF_IP_LOST_TIMER_INTERVAL 120 +#define CONFIG_ESP_NETIF_TCPIP_LWIP 1 +#define CONFIG_ESP_SYSTEM_PANIC_PRINT_REBOOT 1 +#define CONFIG_ESP_TIMER_TASK_STACK_SIZE 3584 +#define CONFIG_ESP_TIMER_IMPL_TG0_LAC 1 +#define CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM 10 +#define CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM 32 +#define CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER 1 +#define CONFIG_ESP32_WIFI_TX_BUFFER_TYPE 1 +#define CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM 32 +#define CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED 1 +#define CONFIG_ESP32_WIFI_TX_BA_WIN 6 +#define CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED 1 +#define CONFIG_ESP32_WIFI_RX_BA_WIN 6 +#define CONFIG_ESP32_WIFI_NVS_ENABLED 1 +#define CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_0 1 +#define CONFIG_ESP32_WIFI_SOFTAP_BEACON_MAX_LEN 752 +#define CONFIG_ESP32_WIFI_MGMT_SBUF_NUM 32 +#define CONFIG_ESP32_WIFI_IRAM_OPT 1 +#define CONFIG_ESP32_WIFI_RX_IRAM_OPT 1 +#define CONFIG_ESP32_WIFI_ENABLE_WPA3_SAE 1 +#define CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE 1 +#define CONFIG_ESP32_PHY_MAX_WIFI_TX_POWER 20 +#define CONFIG_ESP32_PHY_MAX_TX_POWER 20 +#define CONFIG_ESP_COREDUMP_ENABLE_TO_NONE 1 +#define CONFIG_FATFS_CODEPAGE_437 1 +#define CONFIG_FATFS_CODEPAGE 437 +#define CONFIG_FATFS_LFN_NONE 1 +#define CONFIG_FATFS_FS_LOCK 0 +#define CONFIG_FATFS_TIMEOUT_MS 10000 +#define CONFIG_FATFS_PER_FILE_CACHE 1 +#define CONFIG_FMB_COMM_MODE_RTU_EN 1 +#define CONFIG_FMB_COMM_MODE_ASCII_EN 1 +#define CONFIG_FMB_MASTER_TIMEOUT_MS_RESPOND 150 +#define CONFIG_FMB_MASTER_DELAY_MS_CONVERT 200 +#define CONFIG_FMB_QUEUE_LENGTH 20 +#define CONFIG_FMB_SERIAL_TASK_STACK_SIZE 2048 +#define CONFIG_FMB_SERIAL_BUF_SIZE 256 +#define CONFIG_FMB_SERIAL_ASCII_BITS_PER_SYMB 8 +#define CONFIG_FMB_SERIAL_ASCII_TIMEOUT_RESPOND_MS 1000 +#define CONFIG_FMB_SERIAL_TASK_PRIO 10 +#define CONFIG_FMB_CONTROLLER_NOTIFY_TIMEOUT 20 +#define CONFIG_FMB_CONTROLLER_NOTIFY_QUEUE_SIZE 20 +#define CONFIG_FMB_CONTROLLER_STACK_SIZE 4096 +#define CONFIG_FMB_EVENT_QUEUE_TIMEOUT 20 +#define CONFIG_FMB_TIMER_PORT_ENABLED 1 +#define CONFIG_FMB_TIMER_GROUP 0 +#define CONFIG_FMB_TIMER_INDEX 0 +#define CONFIG_FREERTOS_NO_AFFINITY 0x7FFFFFFF +#define CONFIG_FREERTOS_CORETIMER_0 1 +#define CONFIG_FREERTOS_HZ 100 +#define CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION 1 +#define CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY 1 +#define CONFIG_FREERTOS_INTERRUPT_BACKTRACE 1 +#define CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS 1 +#define CONFIG_FREERTOS_IDLE_TASK_STACKSIZE 1536 +#define CONFIG_FREERTOS_ISR_STACKSIZE 1536 +#define CONFIG_FREERTOS_MAX_TASK_NAME_LEN 16 +#define CONFIG_FREERTOS_TIMER_TASK_PRIORITY 1 +#define CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH 2048 +#define CONFIG_FREERTOS_TIMER_QUEUE_LENGTH 10 +#define CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE 0 +#define CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER 1 +#define CONFIG_FREERTOS_CHECK_MUTEX_GIVEN_BY_OWNER 1 +#define CONFIG_FREERTOS_DEBUG_OCDAWARE 1 +#define CONFIG_HEAP_POISONING_DISABLED 1 +#define CONFIG_HEAP_TRACING_OFF 1 +#define CONFIG_LOG_DEFAULT_LEVEL_INFO 1 +#define CONFIG_LOG_DEFAULT_LEVEL 3 +#define CONFIG_LOG_MAXIMUM_LEVEL 3 +#define CONFIG_LOG_COLORS 1 +#define CONFIG_LOG_TIMESTAMP_SOURCE_RTOS 1 +#define CONFIG_LWIP_LOCAL_HOSTNAME "espressif" +#define CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES 1 +#define CONFIG_LWIP_TIMERS_ONDEMAND 1 +#define CONFIG_LWIP_MAX_SOCKETS 10 +#define CONFIG_LWIP_SO_REUSE 1 +#define CONFIG_LWIP_SO_REUSE_RXTOALL 1 +#define CONFIG_LWIP_IP_FRAG 1 +#define CONFIG_LWIP_ESP_GRATUITOUS_ARP 1 +#define CONFIG_LWIP_GARP_TMR_INTERVAL 60 +#define CONFIG_LWIP_TCPIP_RECVMBOX_SIZE 32 +#define CONFIG_LWIP_DHCP_DOES_ARP_CHECK 1 +#define CONFIG_LWIP_DHCPS_LEASE_UNIT 60 +#define CONFIG_LWIP_DHCPS_MAX_STATION_NUM 8 +#define CONFIG_LWIP_NETIF_LOOPBACK 1 +#define CONFIG_LWIP_LOOPBACK_MAX_PBUFS 8 +#define CONFIG_LWIP_MAX_ACTIVE_TCP 16 +#define CONFIG_LWIP_MAX_LISTENING_TCP 16 +#define CONFIG_LWIP_TCP_MAXRTX 12 +#define CONFIG_LWIP_TCP_SYNMAXRTX 6 +#define CONFIG_LWIP_TCP_MSS 1440 +#define CONFIG_LWIP_TCP_TMR_INTERVAL 250 +#define CONFIG_LWIP_TCP_MSL 60000 +#define CONFIG_LWIP_TCP_SND_BUF_DEFAULT 5744 +#define CONFIG_LWIP_TCP_WND_DEFAULT 5744 +#define CONFIG_LWIP_TCP_RECVMBOX_SIZE 6 +#define CONFIG_LWIP_TCP_QUEUE_OOSEQ 1 +#define CONFIG_LWIP_TCP_OVERSIZE_MSS 1 +#define CONFIG_LWIP_MAX_UDP_PCBS 16 +#define CONFIG_LWIP_UDP_RECVMBOX_SIZE 6 +#define CONFIG_LWIP_TCPIP_TASK_STACK_SIZE 3072 +#define CONFIG_LWIP_TCPIP_TASK_AFFINITY_NO_AFFINITY 1 +#define CONFIG_LWIP_TCPIP_TASK_AFFINITY 0x7FFFFFFF +#define CONFIG_LWIP_MAX_RAW_PCBS 16 +#define CONFIG_LWIP_DHCP_MAX_NTP_SERVERS 1 +#define CONFIG_LWIP_SNTP_UPDATE_DELAY 3600000 +#define CONFIG_LWIP_ESP_LWIP_ASSERT 1 +#define CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC 1 +#define CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN 1 +#define CONFIG_MBEDTLS_SSL_IN_CONTENT_LEN 16384 +#define CONFIG_MBEDTLS_SSL_OUT_CONTENT_LEN 4096 +#define CONFIG_MBEDTLS_CERTIFICATE_BUNDLE 1 +#define CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_FULL 1 +#define CONFIG_MBEDTLS_HARDWARE_AES 1 +#define CONFIG_MBEDTLS_HARDWARE_MPI 1 +#define CONFIG_MBEDTLS_HARDWARE_SHA 1 +#define CONFIG_MBEDTLS_HAVE_TIME 1 +#define CONFIG_MBEDTLS_ECDSA_DETERMINISTIC 1 +#define CONFIG_MBEDTLS_SHA512_C 1 +#define CONFIG_MBEDTLS_TLS_SERVER_AND_CLIENT 1 +#define CONFIG_MBEDTLS_TLS_SERVER 1 +#define CONFIG_MBEDTLS_TLS_CLIENT 1 +#define CONFIG_MBEDTLS_TLS_ENABLED 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_RSA 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_RSA 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_RSA 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA 1 +#define CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_RSA 1 +#define CONFIG_MBEDTLS_SSL_RENEGOTIATION 1 +#define CONFIG_MBEDTLS_SSL_PROTO_TLS1 1 +#define CONFIG_MBEDTLS_SSL_PROTO_TLS1_1 1 +#define CONFIG_MBEDTLS_SSL_PROTO_TLS1_2 1 +#define CONFIG_MBEDTLS_SSL_ALPN 1 +#define CONFIG_MBEDTLS_CLIENT_SSL_SESSION_TICKETS 1 +#define CONFIG_MBEDTLS_SERVER_SSL_SESSION_TICKETS 1 +#define CONFIG_MBEDTLS_AES_C 1 +#define CONFIG_MBEDTLS_RC4_DISABLED 1 +#define CONFIG_MBEDTLS_CCM_C 1 +#define CONFIG_MBEDTLS_GCM_C 1 +#define CONFIG_MBEDTLS_PEM_PARSE_C 1 +#define CONFIG_MBEDTLS_PEM_WRITE_C 1 +#define CONFIG_MBEDTLS_X509_CRL_PARSE_C 1 +#define CONFIG_MBEDTLS_X509_CSR_PARSE_C 1 +#define CONFIG_MBEDTLS_ECP_C 1 +#define CONFIG_MBEDTLS_ECDH_C 1 +#define CONFIG_MBEDTLS_ECDSA_C 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP192R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP224R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP384R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP521R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP192K1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP224K1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_SECP256K1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_BP256R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_BP384R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_BP512R1_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_DP_CURVE25519_ENABLED 1 +#define CONFIG_MBEDTLS_ECP_NIST_OPTIM 1 +#define CONFIG_MDNS_MAX_SERVICES 25 +#define CONFIG_MDNS_MAX_INTERFACES 3 +#define CONFIG_MDNS_TASK_PRIORITY 1 +#define CONFIG_MDNS_ACTION_QUEUE_LEN 16 +#define CONFIG_MDNS_TASK_STACK_SIZE 4096 +#define CONFIG_MDNS_TASK_AFFINITY_CPU0 1 +#define CONFIG_MDNS_TASK_AFFINITY 0x0 +#define CONFIG_MDNS_SERVICE_ADD_TIMEOUT_MS 1 +#define CONFIG_MDNS_TIMER_PERIOD_MS 100 +#define CONFIG_MQTT_PROTOCOL_311 1 +#define CONFIG_MQTT_TRANSPORT_SSL 1 +#define CONFIG_MQTT_TRANSPORT_WEBSOCKET 1 +#define CONFIG_MQTT_TRANSPORT_WEBSOCKET_SECURE 1 +#define CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF 1 +#define CONFIG_NEWLIB_STDIN_LINE_ENDING_CR 1 +#define CONFIG_OPENSSL_ASSERT_EXIT 1 +#define CONFIG_PTHREAD_TASK_PRIO_DEFAULT 5 +#define CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT 3072 +#define CONFIG_PTHREAD_STACK_MIN 768 +#define CONFIG_PTHREAD_DEFAULT_CORE_NO_AFFINITY 1 +#define CONFIG_PTHREAD_TASK_CORE_DEFAULT -1 +#define CONFIG_PTHREAD_TASK_NAME_DEFAULT "pthread" +#define CONFIG_SPI_FLASH_ROM_DRIVER_PATCH 1 +#define CONFIG_SPI_FLASH_DANGEROUS_WRITE_ABORTS 1 +#define CONFIG_SPI_FLASH_YIELD_DURING_ERASE 1 +#define CONFIG_SPI_FLASH_ERASE_YIELD_DURATION_MS 20 +#define CONFIG_SPI_FLASH_ERASE_YIELD_TICKS 1 +#define CONFIG_SPI_FLASH_SUPPORT_ISSI_CHIP 1 +#define CONFIG_SPI_FLASH_SUPPORT_MXIC_CHIP 1 +#define CONFIG_SPI_FLASH_SUPPORT_GD_CHIP 1 +#define CONFIG_SPIFFS_MAX_PARTITIONS 3 +#define CONFIG_SPIFFS_CACHE 1 +#define CONFIG_SPIFFS_CACHE_WR 1 +#define CONFIG_SPIFFS_PAGE_CHECK 1 +#define CONFIG_SPIFFS_GC_MAX_RUNS 10 +#define CONFIG_SPIFFS_PAGE_SIZE 256 +#define CONFIG_SPIFFS_OBJ_NAME_LEN 32 +#define CONFIG_SPIFFS_USE_MAGIC 1 +#define CONFIG_SPIFFS_USE_MAGIC_LENGTH 1 +#define CONFIG_SPIFFS_META_LENGTH 4 +#define CONFIG_SPIFFS_USE_MTIME 1 +#define CONFIG_USB_DESC_CUSTOM_VID 0x1234 +#define CONFIG_USB_DESC_CUSTOM_PID 0x5678 +#define CONFIG_UNITY_ENABLE_FLOAT 1 +#define CONFIG_UNITY_ENABLE_DOUBLE 1 +#define CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER 1 +#define CONFIG_VFS_SUPPORT_IO 1 +#define CONFIG_VFS_SUPPORT_DIR 1 +#define CONFIG_VFS_SUPPORT_SELECT 1 +#define CONFIG_VFS_SUPPRESS_SELECT_DEBUG_OUTPUT 1 +#define CONFIG_VFS_SUPPORT_TERMIOS 1 +#define CONFIG_VFS_SEMIHOSTFS_MAX_MOUNT_POINTS 1 +#define CONFIG_VFS_SEMIHOSTFS_HOST_PATH_MAX_LEN 128 +#define CONFIG_WL_SECTOR_SIZE_4096 1 +#define CONFIG_WL_SECTOR_SIZE 4096 +#define CONFIG_WIFI_PROV_SCAN_MAX_ENTRIES 16 +#define CONFIG_WIFI_PROV_AUTOSTOP_TIMEOUT 30 +#define CONFIG_WPA_MBEDTLS_CRYPTO 1 + +/* List of deprecated options */ +#define CONFIG_ADC2_DISABLE_DAC CONFIG_ADC_DISABLE_DAC +#define CONFIG_BROWNOUT_DET CONFIG_ESP_BROWNOUT_DET +#define CONFIG_BROWNOUT_DET_LVL_SEL_0 CONFIG_ESP_BROWNOUT_DET_LVL_SEL_0 +#define CONFIG_COMPILER_OPTIMIZATION_LEVEL_DEBUG CONFIG_COMPILER_OPTIMIZATION_DEFAULT +#define CONFIG_CONSOLE_UART_BAUDRATE CONFIG_ESP_CONSOLE_UART_BAUDRATE +#define CONFIG_CONSOLE_UART_DEFAULT CONFIG_ESP_CONSOLE_UART_DEFAULT +#define CONFIG_CONSOLE_UART_RX_GPIO CONFIG_ESP_CONSOLE_UART_RX_GPIO +#define CONFIG_CONSOLE_UART_TX_GPIO CONFIG_ESP_CONSOLE_UART_TX_GPIO +#define CONFIG_ESP32S2_PANIC_PRINT_REBOOT CONFIG_ESP_SYSTEM_PANIC_PRINT_REBOOT +#define CONFIG_ESP32_APPTRACE_DEST_NONE CONFIG_APPTRACE_DEST_NONE +#define CONFIG_ESP32_DEFAULT_PTHREAD_CORE_NO_AFFINITY CONFIG_PTHREAD_DEFAULT_CORE_NO_AFFINITY +#define CONFIG_ESP32_PANIC_PRINT_REBOOT CONFIG_ESP_SYSTEM_PANIC_PRINT_REBOOT +#define CONFIG_ESP32_PTHREAD_STACK_MIN CONFIG_PTHREAD_STACK_MIN +#define CONFIG_ESP32_PTHREAD_TASK_NAME_DEFAULT CONFIG_PTHREAD_TASK_NAME_DEFAULT +#define CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT CONFIG_PTHREAD_TASK_PRIO_DEFAULT +#define CONFIG_ESP32_PTHREAD_TASK_STACK_SIZE_DEFAULT CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT +#define CONFIG_ESP_GRATUITOUS_ARP CONFIG_LWIP_ESP_GRATUITOUS_ARP +#define CONFIG_FLASHMODE_DIO CONFIG_ESPTOOLPY_FLASHMODE_DIO +#define CONFIG_FOUR_UNIVERSAL_MAC_ADDRESS CONFIG_ESP32_UNIVERSAL_MAC_ADDRESSES_FOUR +#define CONFIG_GARP_TMR_INTERVAL CONFIG_LWIP_GARP_TMR_INTERVAL +#define CONFIG_INT_WDT CONFIG_ESP_INT_WDT +#define CONFIG_INT_WDT_CHECK_CPU1 CONFIG_ESP_INT_WDT_CHECK_CPU1 +#define CONFIG_INT_WDT_TIMEOUT_MS CONFIG_ESP_INT_WDT_TIMEOUT_MS +#define CONFIG_IPC_TASK_STACK_SIZE CONFIG_ESP_IPC_TASK_STACK_SIZE +#define CONFIG_LOG_BOOTLOADER_LEVEL_INFO CONFIG_BOOTLOADER_LOG_LEVEL_INFO +#define CONFIG_MAIN_TASK_STACK_SIZE CONFIG_ESP_MAIN_TASK_STACK_SIZE +#define CONFIG_MB_CONTROLLER_NOTIFY_QUEUE_SIZE CONFIG_FMB_CONTROLLER_NOTIFY_QUEUE_SIZE +#define CONFIG_MB_CONTROLLER_NOTIFY_TIMEOUT CONFIG_FMB_CONTROLLER_NOTIFY_TIMEOUT +#define CONFIG_MB_CONTROLLER_STACK_SIZE CONFIG_FMB_CONTROLLER_STACK_SIZE +#define CONFIG_MB_EVENT_QUEUE_TIMEOUT CONFIG_FMB_EVENT_QUEUE_TIMEOUT +#define CONFIG_MB_MASTER_DELAY_MS_CONVERT CONFIG_FMB_MASTER_DELAY_MS_CONVERT +#define CONFIG_MB_MASTER_TIMEOUT_MS_RESPOND CONFIG_FMB_MASTER_TIMEOUT_MS_RESPOND +#define CONFIG_MB_QUEUE_LENGTH CONFIG_FMB_QUEUE_LENGTH +#define CONFIG_MB_SERIAL_BUF_SIZE CONFIG_FMB_SERIAL_BUF_SIZE +#define CONFIG_MB_SERIAL_TASK_PRIO CONFIG_FMB_SERIAL_TASK_PRIO +#define CONFIG_MB_SERIAL_TASK_STACK_SIZE CONFIG_FMB_SERIAL_TASK_STACK_SIZE +#define CONFIG_MB_TIMER_GROUP CONFIG_FMB_TIMER_GROUP +#define CONFIG_MB_TIMER_INDEX CONFIG_FMB_TIMER_INDEX +#define CONFIG_MB_TIMER_PORT_ENABLED CONFIG_FMB_TIMER_PORT_ENABLED +#define CONFIG_OPTIMIZATION_ASSERTIONS_ENABLED CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE +#define CONFIG_OPTIMIZATION_LEVEL_DEBUG CONFIG_COMPILER_OPTIMIZATION_DEFAULT +#define CONFIG_POST_EVENTS_FROM_IRAM_ISR CONFIG_ESP_EVENT_POST_FROM_IRAM_ISR +#define CONFIG_POST_EVENTS_FROM_ISR CONFIG_ESP_EVENT_POST_FROM_ISR +#define CONFIG_REDUCE_PHY_TX_POWER CONFIG_ESP32_REDUCE_PHY_TX_POWER +#define CONFIG_SEMIHOSTFS_HOST_PATH_MAX_LEN CONFIG_VFS_SEMIHOSTFS_HOST_PATH_MAX_LEN +#define CONFIG_SEMIHOSTFS_MAX_MOUNT_POINTS CONFIG_VFS_SEMIHOSTFS_MAX_MOUNT_POINTS +#define CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ABORTS CONFIG_SPI_FLASH_DANGEROUS_WRITE_ABORTS +#define CONFIG_STACK_CHECK_NONE CONFIG_COMPILER_STACK_CHECK_MODE_NONE +#define CONFIG_SUPPORT_TERMIOS CONFIG_VFS_SUPPORT_TERMIOS +#define CONFIG_SUPPRESS_SELECT_DEBUG_OUTPUT CONFIG_VFS_SUPPRESS_SELECT_DEBUG_OUTPUT +#define CONFIG_SYSTEM_EVENT_QUEUE_SIZE CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE +#define CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE +#define CONFIG_TASK_WDT CONFIG_ESP_TASK_WDT +#define CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU0 CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0 +#define CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU1 CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1 +#define CONFIG_TASK_WDT_TIMEOUT_S CONFIG_ESP_TASK_WDT_TIMEOUT_S +#define CONFIG_TCPIP_RECVMBOX_SIZE CONFIG_LWIP_TCPIP_RECVMBOX_SIZE +#define CONFIG_TCPIP_TASK_AFFINITY_NO_AFFINITY CONFIG_LWIP_TCPIP_TASK_AFFINITY_NO_AFFINITY +#define CONFIG_TCPIP_TASK_STACK_SIZE CONFIG_LWIP_TCPIP_TASK_STACK_SIZE +#define CONFIG_TCP_MAXRTX CONFIG_LWIP_TCP_MAXRTX +#define CONFIG_TCP_MSL CONFIG_LWIP_TCP_MSL +#define CONFIG_TCP_MSS CONFIG_LWIP_TCP_MSS +#define CONFIG_TCP_OVERSIZE_MSS CONFIG_LWIP_TCP_OVERSIZE_MSS +#define CONFIG_TCP_QUEUE_OOSEQ CONFIG_LWIP_TCP_QUEUE_OOSEQ +#define CONFIG_TCP_RECVMBOX_SIZE CONFIG_LWIP_TCP_RECVMBOX_SIZE +#define CONFIG_TCP_SND_BUF_DEFAULT CONFIG_LWIP_TCP_SND_BUF_DEFAULT +#define CONFIG_TCP_SYNMAXRTX CONFIG_LWIP_TCP_SYNMAXRTX +#define CONFIG_TCP_WND_DEFAULT CONFIG_LWIP_TCP_WND_DEFAULT +#define CONFIG_TIMER_QUEUE_LENGTH CONFIG_FREERTOS_TIMER_QUEUE_LENGTH +#define CONFIG_TIMER_TASK_PRIORITY CONFIG_FREERTOS_TIMER_TASK_PRIORITY +#define CONFIG_TIMER_TASK_STACK_DEPTH CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH +#define CONFIG_TIMER_TASK_STACK_SIZE CONFIG_ESP_TIMER_TASK_STACK_SIZE +#define CONFIG_TOOLPREFIX CONFIG_SDK_TOOLPREFIX +#define CONFIG_UDP_RECVMBOX_SIZE CONFIG_LWIP_UDP_RECVMBOX_SIZE diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/test.c b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/test.c new file mode 100644 index 000000000..afbf02384 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_afl_fuzz_host/test.c @@ -0,0 +1,276 @@ +/* + * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include + +#include "esp32_mock.h" +#include "mdns.h" +#include "mdns_private.h" + +// +// Global stuctures containing packet payload, search +mdns_rx_packet_t g_packet; +struct pbuf mypbuf; +mdns_search_once_t *search = NULL; + +// +// Dependency injected test functions +void mdns_test_execute_action(void *action); +mdns_srv_item_t *mdns_test_mdns_get_service_item(const char *service, const char *proto); +mdns_search_once_t *mdns_test_search_init(const char *name, const char *service, const char *proto, uint16_t type, uint32_t timeout, uint8_t max_results); +esp_err_t mdns_test_send_search_action(mdns_action_type_t type, mdns_search_once_t *search); +void mdns_test_search_free(mdns_search_once_t *search); +void mdns_test_init_di(void); +extern mdns_server_t *_mdns_server; + +// +// mdns function wrappers for mdns setup in test mode +static int mdns_test_hostname_set(const char *mdns_hostname) +{ + for (int i = 0; i < MDNS_MAX_INTERFACES; i++) { + _mdns_server->interfaces[i].pcbs[MDNS_IP_PROTOCOL_V4].state = PCB_RUNNING; // mark the PCB running to exercise mdns in fully operational mode + _mdns_server->interfaces[i].pcbs[MDNS_IP_PROTOCOL_V6].state = PCB_RUNNING; + } + int ret = mdns_hostname_set(mdns_hostname); + mdns_action_t *a = NULL; + GetLastItem(&a); + mdns_test_execute_action(a); + return ret; +} + +static int mdns_test_add_delegated_host(const char *mdns_hostname) +{ + mdns_ip_addr_t addr = { .addr = { .u_addr = ESP_IPADDR_TYPE_V4 } }; + addr.addr.u_addr.ip4.addr = 0x11111111; + int ret = mdns_delegate_hostname_add(mdns_hostname, &addr); + mdns_action_t *a = NULL; + GetLastItem(&a); + mdns_test_execute_action(a); + return ret; +} + + +static int mdns_test_service_instance_name_set(const char *service, const char *proto, const char *instance) +{ + int ret = mdns_service_instance_name_set(service, proto, instance); + mdns_action_t *a = NULL; + GetLastItem(&a); + mdns_test_execute_action(a); + return ret; +} + +static int mdns_test_service_txt_set(const char *service, const char *proto, uint8_t num_items, mdns_txt_item_t txt[]) +{ + int ret = mdns_service_txt_set(service, proto, txt, num_items); + mdns_action_t *a = NULL; + GetLastItem(&a); + mdns_test_execute_action(a); + return ret; +} + +static int mdns_test_sub_service_add(const char *sub_name, const char *service_name, const char *proto, uint32_t port) +{ + if (mdns_service_add(NULL, service_name, proto, port, NULL, 0)) { + // This is expected failure as the service thread is not running + } + mdns_action_t *a = NULL; + GetLastItem(&a); + mdns_test_execute_action(a); + + if (mdns_test_mdns_get_service_item(service_name, proto) == NULL) { + return ESP_FAIL; + } + int ret = mdns_service_subtype_add_for_host(NULL, service_name, proto, NULL, sub_name); + a = NULL; + GetLastItem(&a); + mdns_test_execute_action(a); + return ret; +} + +static int mdns_test_service_add(const char *service_name, const char *proto, uint32_t port) +{ + if (mdns_service_add(NULL, service_name, proto, port, NULL, 0)) { + // This is expected failure as the service thread is not running + } + mdns_action_t *a = NULL; + GetLastItem(&a); + mdns_test_execute_action(a); + + if (mdns_test_mdns_get_service_item(service_name, proto) == NULL) { + return ESP_FAIL; + } + return ESP_OK; +} + +static mdns_result_t *mdns_test_query(const char *name, const char *service, const char *proto, uint16_t type) +{ + search = mdns_test_search_init(name, service, proto, type, 3000, 20); + if (!search) { + abort(); + } + + if (mdns_test_send_search_action(ACTION_SEARCH_ADD, search)) { + mdns_test_search_free(search); + abort(); + } + + mdns_action_t *a = NULL; + GetLastItem(&a); + mdns_test_execute_action(a); + return NULL; +} + +static void mdns_test_query_free(void) +{ + mdns_test_search_free(search); +} + +// +// function "under test" where afl-mangled packets passed +// +void mdns_parse_packet(mdns_rx_packet_t *packet); + +// +// Test starts here +// +int main(int argc, char **argv) +{ + int i; + const char *mdns_hostname = "minifritz"; + const char *mdns_instance = "Hristo's Time Capsule"; + mdns_txt_item_t arduTxtData[4] = { + {"board", "esp32"}, + {"tcp_check", "no"}, + {"ssh_upload", "no"}, + {"auth_upload", "no"} + }; + + const uint8_t mac[6] = {0xDE, 0xAD, 0xBE, 0xEF, 0x00, 0x32}; + + uint8_t buf[1460]; + char winstance[21 + strlen(mdns_hostname)]; + + sprintf(winstance, "%s [%02x:%02x:%02x:%02x:%02x:%02x]", mdns_hostname, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + + // Init depencency injected methods + mdns_test_init_di(); + + if (mdns_init()) { + abort(); + } + + if (mdns_test_hostname_set(mdns_hostname)) { + abort(); + } + + if (mdns_test_add_delegated_host(mdns_hostname) || mdns_test_add_delegated_host("megafritz")) { + abort(); + } + +#ifndef MDNS_NO_SERVICES + + if (mdns_test_sub_service_add("_server", "_fritz", "_tcp", 22)) { + abort(); + } + + if (mdns_test_service_add("_telnet", "_tcp", 22)) { + abort(); + } + + if (mdns_test_service_add("_workstation", "_tcp", 9)) { + abort(); + } + if (mdns_test_service_instance_name_set("_workstation", "_tcp", winstance)) { + abort(); + } + + if (mdns_test_service_add("_arduino", "_tcp", 3232)) { + abort(); + } + + if (mdns_test_service_txt_set("_arduino", "_tcp", 4, arduTxtData)) { + abort(); + } + + if (mdns_test_service_add("_http", "_tcp", 80)) { + abort(); + } + + if (mdns_test_service_instance_name_set("_http", "_tcp", "ESP WebServer")) { + abort(); + } + + if ( + mdns_test_service_add("_afpovertcp", "_tcp", 548) + || mdns_test_service_add("_rfb", "_tcp", 885) + || mdns_test_service_add("_smb", "_tcp", 885) + || mdns_test_service_add("_adisk", "_tcp", 885) + || mdns_test_service_add("_airport", "_tcp", 885) + || mdns_test_service_add("_printer", "_tcp", 885) + || mdns_test_service_add("_airplay", "_tcp", 885) + || mdns_test_service_add("_raop", "_tcp", 885) + || mdns_test_service_add("_uscan", "_tcp", 885) + || mdns_test_service_add("_uscans", "_tcp", 885) + || mdns_test_service_add("_ippusb", "_tcp", 885) + || mdns_test_service_add("_scanner", "_tcp", 885) + || mdns_test_service_add("_ipp", "_tcp", 885) + || mdns_test_service_add("_ipps", "_tcp", 885) + || mdns_test_service_add("_pdl-datastream", "_tcp", 885) + || mdns_test_service_add("_ptp", "_tcp", 885) + || mdns_test_service_add("_sleep-proxy", "_udp", 885)) { + abort(); + } +#endif + mdns_result_t *results = NULL; + FILE *file; + size_t nread; + +#ifdef INSTR_IS_OFF + size_t len = 1460; + memset(buf, 0, 1460); + + if (argc != 2) { + printf("Non-instrumentation mode: please supply a file name created by AFL to reproduce crash\n"); + return 1; + } else { + // + // Note: parameter1 is a file (mangled packet) which caused the crash + file = fopen(argv[1], "r"); + assert(file >= 0); + len = fread(buf, 1, 1460, file); + fclose(file); + } + + for (i = 0; i < 1; i++) { +#else + while (__AFL_LOOP(1000)) { + memset(buf, 0, 1460); + size_t len = read(0, buf, 1460); +#endif + mypbuf.payload = malloc(len); + memcpy(mypbuf.payload, buf, len); + mypbuf.len = len; + g_packet.pb = &mypbuf; + mdns_test_query("minifritz", "_fritz", "_tcp", MDNS_TYPE_ANY); + mdns_test_query(NULL, "_fritz", "_tcp", MDNS_TYPE_PTR); + mdns_test_query(NULL, "_afpovertcp", "_tcp", MDNS_TYPE_PTR); + mdns_parse_packet(&g_packet); + free(mypbuf.payload); + } +#ifndef MDNS_NO_SERVICES + mdns_service_remove_all(); + mdns_action_t *a = NULL; + GetLastItem(&a); + mdns_test_execute_action(a); +#endif + ForceTaskDelete(); + mdns_free(); + return 0; +} diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_apps/CMakeLists.txt b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_apps/CMakeLists.txt new file mode 100644 index 000000000..62d1565f9 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_apps/CMakeLists.txt @@ -0,0 +1,7 @@ +# The following four 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(mdns_test_app) diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_apps/README.md b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_apps/README.md new file mode 100644 index 000000000..96b76dcb7 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_apps/README.md @@ -0,0 +1,49 @@ +| Supported Targets | ESP32 | ESP32-S2 | ESP32-C3 | +| ----------------- | ----- | -------- | -------- | + +# mDNS test project + +Main purpose of this application is to test the mDNS library to correctly advertise, lookup services and hosts. +The "app_test.py" logically separated from two sets of test cases 1. "ESP32 board sends queries -> Host sends answers" and 2. "Host sends queries" -> "ESP32 board sends answers". +Two first sets of test cases are starting by 'test_query_' and the second ones by 'start_case'. + +## Runtime settings + +1. For first sets of test cases python creates and sends dns queries using "dpkt" library +2. For the second sets of test cases this app waits for user input to provide test case(e.g. CONFIG_TEST_QUERY_HOST, CONFIG_TEST_QUERY_HOST_ASYNC or CONFIG_TEST_QUERY_SERVICE) +In order to run both of them just needed to set up the project and run by 'python app_test.py' + +## Test app workflow + +- mDNS is initialized with hostname and instance name defined through the project configuration and `_http._tcp` service is added to be advertised +- A delegated host `esp32-delegated._local` is added and another `_http._tcp` service is added for this host. +- WiFi STA is started and tries to connect to the access point defined through the project configuration + +### Configure the project + +* Open the project configuration menu (`idf.py menuconfig`) + +* Configure Wi-Fi or Ethernet under "Example Connection Configuration" menu. + +* Set `mDNS Hostname` as host name prefix for the device and its instance name in `mDNS Instance Name` + +### Build and Flash + +Build the project and flash it to the board, then run the monitor tool to view the serial output: + +``` +idf.py -p PORT flash monitor +``` + +- Wait for WiFi to connect to your access point +- You can now ping the device at `[board-hostname].local`, where `[board-hostname]` is preconfigured hostname, `esp32-mdns` by default. +- You can also browse for `_http._tcp` on the same network to find the advertised service +- Note that for purpose of CI tests, configuration options of `MDNS_RESOLVE_TEST_SERVICES` and `MDNS_ADD_MAC_TO_HOSTNAME` are available, but disabled by default. If enabled, then the hostname suffix of last 3 bytes from device MAC address is added, e.g. `esp32-mdns-80FFFF`, and a query for test service is issued. + + +(To exit the serial monitor, type ``Ctrl-]``.) + +See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects. + +## Hardware Required +This test-app can be executed on any ESP32 board, the only required interface is WiFi and connection to a local network and tls server. diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_apps/main/CMakeLists.txt b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_apps/main/CMakeLists.txt new file mode 100644 index 000000000..b5902d589 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_apps/main/CMakeLists.txt @@ -0,0 +1,2 @@ +idf_component_register(SRCS "main.c" "mdns_test.c" + INCLUDE_DIRS ".") diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_apps/main/Kconfig.projbuild b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_apps/main/Kconfig.projbuild new file mode 100644 index 000000000..a1c0d729c --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_apps/main/Kconfig.projbuild @@ -0,0 +1,40 @@ +menu "Example Configuration" + + config TEST_MDNS_HOSTNAME + string "mDNS Hostname" + default "esp32-mdns" + help + mDNS Hostname for example to use + + config TEST_MDNS_INSTANCE + string "mDNS Instance Name" + default "ESP32 with mDNS" + help + mDNS Instance Name for example to use + + config TEST_MDNS_PUBLISH_DELEGATE_HOST + bool "Publish a delegated host" + help + Enable publishing a delegated host other than ESP32. + The example will also add a mock service for this host. + + config TEST_MDNS_ADD_MAC_TO_HOSTNAME + bool "Add mac suffix to hostname" + default n + help + If enabled, a portion of MAC address is added to the hostname, this is used + for evaluation of tests in CI + config MDNS_ADD_MAC_TO_HOSTNAME + bool "Add mac suffix to hostname" + default n + help + If enabled, a portion of MAC address is added to the hostname, this is used + for evaluation of tests in CI + config MDNS_PUBLISH_DELEGATE_HOST + bool "Publish a delegated host" + help + Enable publishing a delegated host other than ESP32. + The example will also add a mock service for this host. + + +endmenu diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_apps/main/idf_component.yml b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_apps/main/idf_component.yml new file mode 100644 index 000000000..e9277dfc9 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_apps/main/idf_component.yml @@ -0,0 +1,8 @@ +dependencies: + ## Required IDF version + idf: ">=5.0" + espressif/mdns: + version: "^1.0.0" + override_path: "../../../" + protocol_examples_common: + path: ${IDF_PATH}/examples/common_components/protocol_examples_common diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_apps/main/main.c b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_apps/main/main.c new file mode 100644 index 000000000..1ff0cc1c1 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_apps/main/main.c @@ -0,0 +1,117 @@ +/* + * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include "esp_mac.h" +#include "nvs_flash.h" +#include "esp_event.h" +#include "esp_netif.h" +#include "esp_log.h" +#include "protocol_examples_common.h" +#include "mdns.h" + +static const char *TAG = "mdns_test"; +void mdns_test(char *line); + +static void get_string(char *line, size_t size) +{ + int count = 0; + while (count < size) { + int c = fgetc(stdin); + if (c == '\n') { + line[count] = '\0'; + break; + } else if (c > 0 && c < 127) { + line[count] = c; + ++count; + } + vTaskDelay(20 / portTICK_PERIOD_MS); + } +} + +/** Generate host name based on sdkconfig, optionally adding a portion of MAC address to it. + * @return host name string allocated from the heap + */ +static char *generate_hostname(void) +{ +#ifndef CONFIG_TEST_MDNS_ADD_MAC_TO_HOSTNAME + return strdup(CONFIG_TEST_MDNS_HOSTNAME); +#else + uint8_t mac[6]; + char *hostname; + esp_read_mac(mac, ESP_MAC_WIFI_STA); + if (-1 == asprintf(&hostname, "%s-%02X%02X%02X", CONFIG_TEST_MDNS_HOSTNAME, mac[3], mac[4], mac[5])) { + abort(); + } + return hostname; +#endif +} + +static void initialise_mdns(void) +{ + char *hostname = generate_hostname(); + + //initialize mDNS + ESP_ERROR_CHECK(mdns_init()); + + //set mDNS hostname (required if you want to advertise services) + ESP_ERROR_CHECK(mdns_hostname_set(hostname)); + + ESP_LOGI(TAG, "mdns hostname set to: [%s]", hostname); + //set default mDNS instance name + ESP_ERROR_CHECK(mdns_instance_name_set(CONFIG_TEST_MDNS_INSTANCE)); + + //initialize service + ESP_ERROR_CHECK(mdns_service_add("ESP32-WebServer", "_http", "_tcp", 80, NULL, 0)); + +#if CONFIG_TEST_MDNS_PUBLISH_DELEGATE_HOST + char *delegated_hostname; + if (-1 == asprintf(&delegated_hostname, "%s-delegated", hostname)) { + abort(); + } + + mdns_ip_addr_t addr4, addr6; + esp_netif_str_to_ip4("10.0.0.1", &addr4.addr.u_addr.ip4); + addr4.addr.type = ESP_IPADDR_TYPE_V4; + esp_netif_str_to_ip6("fd11:22::1", &addr6.addr.u_addr.ip6); + addr6.addr.type = ESP_IPADDR_TYPE_V6; + addr4.next = &addr6; + addr6.next = NULL; + ESP_ERROR_CHECK(mdns_delegate_hostname_add(delegated_hostname, &addr4)); + ESP_ERROR_CHECK(mdns_service_add_for_host("test0", "_http", "_tcp", delegated_hostname, 1234, NULL, 0)); + free(delegated_hostname); +#endif // CONFIG_TEST_MDNS_PUBLISH_DELEGATE_HOST + + ESP_ERROR_CHECK(mdns_service_subtype_add_for_host("ESP32-WebServer", "_http", "_tcp", NULL, "_server")); + + free(hostname); +} + +void app_main(void) +{ + ESP_LOGI(TAG, "[APP] Free memory: %" PRIu32 " bytes", esp_get_free_heap_size()); + ESP_LOGI(TAG, "[APP] IDF version: %s", esp_get_idf_version()); + + ESP_ERROR_CHECK(nvs_flash_init()); + ESP_ERROR_CHECK(esp_netif_init()); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + + initialise_mdns(); + + /* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig. + * Read "Establishing Wi-Fi or Ethernet Connection" section in + * examples/protocols/README.md for more information about this function. + */ + ESP_ERROR_CHECK(example_connect()); + + while (1) { + char line[256]; + + get_string(line, sizeof(line)); + mdns_test(line); + continue; + } +} diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_apps/main/mdns_test.c b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_apps/main/mdns_test.c new file mode 100644 index 000000000..06df424f8 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_apps/main/mdns_test.c @@ -0,0 +1,189 @@ +/* + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "mdns.h" +#include "esp_log.h" +#include "esp_netif.h" + +static const char *TAG = "mdns_test_app"; +static const int RETRY_COUNT = 10; + +static void mdns_print_results(mdns_result_t *results) +{ + mdns_result_t *r = results; + mdns_ip_addr_t *a = NULL; + int t; + while (r) { + if (r->instance_name) { + printf("PTR:%s.%s.%s\n", r->instance_name, r->service_type, r->proto); + } + if (r->hostname) { + printf("SRV:%s.local:%u\n", r->hostname, r->port); + } + if (r->txt_count) { + printf("TXT:[%zu] ", r->txt_count); + for (t = 0; t < r->txt_count; t++) { + printf("%s=%s(%d); ", r->txt[t].key, r->txt[t].value ? r->txt[t].value : "NULL", r->txt_value_len[t]); + } + printf("\n"); + } + a = r->addr; + while (a) { + if (a->addr.type == ESP_IPADDR_TYPE_V6) { + printf(" AAAA: " IPV6STR "\n", IPV62STR(a->addr.u_addr.ip6)); + } else { + printf(" A : " IPSTR "\n", IP2STR(&(a->addr.u_addr.ip4))); + } + a = a->next; + } + r = r->next; + } +} + +static bool check_and_print_result(mdns_search_once_t *search) +{ + // Check if any result is available + mdns_result_t *result = NULL; + if (!mdns_query_async_get_results(search, 0, &result, NULL)) { + return false; + } + + if (!result) { // search timeout, but no result + return false; + } + + // If yes, print the result + mdns_ip_addr_t *a = result->addr; + while (a) { + if (a->addr.type == ESP_IPADDR_TYPE_V6) { + printf("Async query resolved to AAAA:" IPV6STR "\n", IPV62STR(a->addr.u_addr.ip6)); + } else { + printf("Async query resolved to A:" IPSTR "\n", IP2STR(&(a->addr.u_addr.ip4))); + } + a = a->next; + } + // and free the result + mdns_query_results_free(result); + return true; +} + +static bool query_mdns_hosts_async(const char *host_name) +{ + ESP_LOGI(TAG, "Query both A and AAA: %s.local", host_name); + bool res = false; + + mdns_search_once_t *s_a = mdns_query_async_new(host_name, NULL, NULL, MDNS_TYPE_A, 1000, 1, NULL); + mdns_query_async_delete(s_a); + mdns_search_once_t *s_aaaa = mdns_query_async_new(host_name, NULL, NULL, MDNS_TYPE_AAAA, 1000, 1, NULL); + while (s_a || s_aaaa) { + if (s_a && check_and_print_result(s_a)) { + ESP_LOGI(TAG, "Query A %s.local finished", host_name); + mdns_query_async_delete(s_a); + s_a = NULL; + res = true; + } + if (s_aaaa && check_and_print_result(s_aaaa)) { + ESP_LOGI(TAG, "Query AAAA %s.local finished", host_name); + mdns_query_async_delete(s_aaaa); + s_aaaa = NULL; + res = true; + } + } + return res; +} + +static esp_err_t query_mdns_host(const char *host_name) +{ + ESP_LOGI(TAG, "Query A: %s.local", host_name); + + struct esp_ip4_addr addr; + addr.addr = 0; + + esp_err_t err = mdns_query_a(host_name, 2000, &addr); + if (err) { + if (err == ESP_ERR_NOT_FOUND) { + ESP_LOGW(TAG, "%s: Host was not found!", esp_err_to_name(err)); + } + ESP_LOGE(TAG, "Query Failed: %s", esp_err_to_name(err)); + return err; + } + + ESP_LOGI(TAG, "Query A: %s.local resolved to: " IPSTR, host_name, IP2STR(&addr)); + return ESP_OK; +} + +static esp_err_t query_mdns_service(const char *instance, const char *service_name, const char *proto) +{ + ESP_LOGI(TAG, "Query SRV: %s.%s.local", service_name, proto); + + mdns_result_t *results = NULL; + esp_err_t err = mdns_query_srv(instance, service_name, proto, 3000, &results); + if (err) { + ESP_LOGE(TAG, "Query Failed: %s", esp_err_to_name(err)); + return err; + } + if (!results) { + ESP_LOGW(TAG, "No results found!"); + } + + mdns_print_results(results); + mdns_query_results_free(results); + return ESP_OK; +} + +void query_mdns_service_sub_type(const char *subtype, const char *service_name, const char *proto) +{ + ESP_LOGI(TAG, "Query PTR: %s.%s.local", service_name, proto); + + mdns_result_t *results = NULL; + esp_err_t err = mdns_query_ptr(service_name, proto, 3000, 20, &results); + if (err) { + ESP_LOGE(TAG, "Query Failed: %s", esp_err_to_name(err)); + } + if (!results) { + ESP_LOGW(TAG, "No results found!"); + } + + mdns_print_results(results); + mdns_query_results_free(results); +} + +void mdns_test(const char *line) +{ + char test_case[32]; + int i = 0; + const TickType_t xDelay = 1000 / portTICK_PERIOD_MS; + + sscanf(line, "%s", test_case); + ESP_LOGI(TAG, "test case = %s", test_case); + + if (strcmp(test_case, "CONFIG_TEST_QUERY_HOST") == 0) { + i = 0; + while (query_mdns_host("tinytester") != ESP_OK && i != RETRY_COUNT) { + query_mdns_host("tinytester"); + i++; + vTaskDelay(xDelay); + } + } else if (strcmp(test_case, "CONFIG_TEST_QUERY_HOST_ASYNC") == 0) { + i = 0; + while (query_mdns_hosts_async("tinytester") == false && i != RETRY_COUNT) { + query_mdns_hosts_async("tinytester"); + i++; + vTaskDelay(xDelay); + } + } else if (strcmp(test_case, "CONFIG_TEST_QUERY_SERVICE") == 0) { + i = 0; + while (query_mdns_service("ESP32", "_http", "_tcp") != ESP_OK && i != RETRY_COUNT) { + query_mdns_service("ESP32", "_http", "_tcp"); + i++; + vTaskDelay(xDelay); + } + } else { + ESP_LOGE(TAG, "%s: No such test case", test_case); + } +} diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_apps/pytest_mdns_app.py b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_apps/pytest_mdns_app.py new file mode 100644 index 000000000..2b04cb75a --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_apps/pytest_mdns_app.py @@ -0,0 +1,320 @@ +# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: Apache-2.0 + +import re +import select +import socket +import struct +import time +from threading import Event, Thread + +import dpkt +import dpkt.dns +import pytest + +UDP_PORT = 5353 +MCAST_GRP = '224.0.0.251' + +# This service is created from esp board startup +SERVICE_NAME = u'ESP32-WebServer._http._tcp.local' +SUB_SERVICE_NAME = u'_server._sub._http._tcp.local' + +# This host name answer sent by host, when there is query from board +HOST_NAME = u'tinytester.local' + +# This servce answer sent by host, when there is query from board +MDNS_HOST_SERVICE = u'ESP32._http._tcp.local' + +# Number of retries to receive mdns answear +RETRY_COUNT = 10 + +stop_mdns_listener = Event() +start_mdns_listener = Event() +esp_service_answered = Event() +esp_sub_service_answered = Event() +esp_host_answered = Event() +esp_delegated_host_answered = Event() + + +@pytest.mark.skip +# Get query of ESP32-WebServer._http._tcp.local service +def get_mdns_service_query(service): # type:(str) -> dpkt.dns.Msg + dns = dpkt.dns.DNS() + dns.op = dpkt.dns.DNS_QR | dpkt.dns.DNS_AA + dns.rcode = dpkt.dns.DNS_RCODE_NOERR + arr = dpkt.dns.DNS.RR() + arr.cls = dpkt.dns.DNS_IN + arr.type = dpkt.dns.DNS_SRV + arr.name = service + arr.target = socket.inet_aton('127.0.0.1') + arr.srvname = service + dns.qd.append(arr) + print('Created mdns service query: {} '.format(dns.__repr__())) + return dns.pack() + + +@pytest.mark.skip +# Get query of _server_.sub._http._tcp.local sub service +def get_mdns_sub_service_query(sub_service): # type:(str) -> dpkt.dns.Msg + dns = dpkt.dns.DNS() + dns.op = dpkt.dns.DNS_QR | dpkt.dns.DNS_AA + dns.rcode = dpkt.dns.DNS_RCODE_NOERR + arr = dpkt.dns.DNS.RR() + arr.cls = dpkt.dns.DNS_IN + arr.type = dpkt.dns.DNS_PTR + arr.name = sub_service + arr.target = socket.inet_aton('127.0.0.1') + arr.ptrname = sub_service + dns.qd.append(arr) + print('Created mdns subtype service query: {} '.format(dns.__repr__())) + return dns.pack() + + +@pytest.mark.skip +# Get query for host resolution +def get_dns_query_for_esp(esp_host): # type:(str) -> dpkt.dns.Msg + dns = dpkt.dns.DNS() + arr = dpkt.dns.DNS.RR() + arr.cls = dpkt.dns.DNS_IN + arr.name = esp_host + u'.local' + dns.qd.append(arr) + print('Created query for esp host: {} '.format(dns.__repr__())) + return dns.pack() + + +@pytest.mark.skip +# Get mdns answer for host resoloution +def get_dns_answer_to_mdns(tester_host): # type:(str) -> dpkt.dns.Msg + dns = dpkt.dns.DNS() + dns.op = dpkt.dns.DNS_QR | dpkt.dns.DNS_AA + dns.rcode = dpkt.dns.DNS_RCODE_NOERR + arr = dpkt.dns.DNS.RR() + arr.cls = dpkt.dns.DNS_IN + arr.type = dpkt.dns.DNS_A + arr.name = tester_host + arr.ip = socket.inet_aton('127.0.0.1') + dns.an.append(arr) + print('Created answer to mdns query: {} '.format(dns.__repr__())) + return dns.pack() + + +@pytest.mark.skip +# Get mdns answer for service query +def get_dns_answer_to_service_query( + mdns_service): # type:(str) -> dpkt.dns.Msg + dns = dpkt.dns.DNS() + dns.op = dpkt.dns.DNS_QR | dpkt.dns.DNS_AA + dns.rcode = dpkt.dns.DNS_RCODE_NOERR + arr = dpkt.dns.DNS.RR() + arr.name = mdns_service + arr.cls = dpkt.dns.DNS_IN + arr.type = dpkt.dns.DNS_SRV + arr.priority = 0 + arr.weight = 0 + arr.port = 100 + arr.srvname = mdns_service + arr.ip = socket.inet_aton('127.0.0.1') + dns.an.append(arr) + print('Created answer to mdns query: {} '.format(dns.__repr__())) + return dns.pack() + + +@pytest.mark.skip +def mdns_listener(esp_host): # type:(str) -> None + print('mdns_listener thread started') + + UDP_IP = '0.0.0.0' + sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1) + sock.setblocking(False) + sock.bind((UDP_IP, UDP_PORT)) + mreq = struct.pack('4sl', socket.inet_aton(MCAST_GRP), socket.INADDR_ANY) + sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq) + last_query_timepoint = time.time() + QUERY_TIMEOUT = 0.2 + while not stop_mdns_listener.is_set(): + try: + start_mdns_listener.set() + current_time = time.time() + if current_time - last_query_timepoint > QUERY_TIMEOUT: + last_query_timepoint = current_time + timeout = max( + 0, QUERY_TIMEOUT - (current_time - last_query_timepoint)) + read_socks, _, _ = select.select([sock], [], [], timeout) + if not read_socks: + continue + data, _ = sock.recvfrom(1024) + dns = dpkt.dns.DNS(data) + # Receives queries from esp board and sends answers + if len(dns.qd) > 0: + if dns.qd[0].name == HOST_NAME: + print('Received query: {} '.format(dns.__repr__())) + sock.sendto(get_dns_answer_to_mdns(HOST_NAME), + (MCAST_GRP, UDP_PORT)) + if dns.qd[0].name == HOST_NAME: + print('Received query: {} '.format(dns.__repr__())) + sock.sendto(get_dns_answer_to_mdns(HOST_NAME), + (MCAST_GRP, UDP_PORT)) + if dns.qd[0].name == MDNS_HOST_SERVICE: + print('Received query: {} '.format(dns.__repr__())) + sock.sendto( + get_dns_answer_to_service_query(MDNS_HOST_SERVICE), + (MCAST_GRP, UDP_PORT)) + # Receives answers from esp board and sets event flags for python test cases + if len(dns.an) == 1: + if dns.an[0].name.startswith(SERVICE_NAME): + print('Received answer to service query: {}'.format( + dns.__repr__())) + esp_service_answered.set() + if len(dns.an) > 1: + if dns.an[1].name.startswith(SUB_SERVICE_NAME): + print('Received answer for sub service query: {}'.format( + dns.__repr__())) + esp_sub_service_answered.set() + if len(dns.an) > 0 and dns.an[0].type == dpkt.dns.DNS_A: + if dns.an[0].name == esp_host + u'.local': + print('Received answer to esp32-mdns query: {}'.format( + dns.__repr__())) + esp_host_answered.set() + if dns.an[0].name == esp_host + u'-delegated.local': + print('Received answer to esp32-mdns-delegate query: {}'. + format(dns.__repr__())) + esp_delegated_host_answered.set() + except socket.timeout: + break + except dpkt.UnpackError: + continue + + +@pytest.mark.skip +def create_socket(): # type:() -> socket.socket + UDP_IP = '0.0.0.0' + sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1) + sock.setblocking(False) + sock.bind((UDP_IP, UDP_PORT)) + mreq = struct.pack('4sl', socket.inet_aton(MCAST_GRP), socket.INADDR_ANY) + sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq) + return sock + + +@pytest.mark.skip +def test_query_dns_http_service(service): # type: (str) -> None + print('SRV: Query {}'.format(service)) + sock = create_socket() + packet = get_mdns_service_query(service) + for _ in range(RETRY_COUNT): + if esp_service_answered.wait(timeout=25): + break + sock.sendto(packet, (MCAST_GRP, UDP_PORT)) + else: + raise RuntimeError( + 'Test has failed: did not receive mdns answer within timeout') + + +@pytest.mark.skip +def test_query_dns_sub_service(sub_service): # type: (str) -> None + print('PTR: Query {}'.format(sub_service)) + sock = create_socket() + packet = get_mdns_sub_service_query(sub_service) + for _ in range(RETRY_COUNT): + if esp_sub_service_answered.wait(timeout=25): + break + sock.sendto(packet, (MCAST_GRP, UDP_PORT)) + else: + raise RuntimeError( + 'Test has failed: did not receive mdns answer within timeout') + + +@pytest.mark.skip +def test_query_dns_host(esp_host): # type: (str) -> None + print('A: {}'.format(esp_host)) + sock = create_socket() + packet = get_dns_query_for_esp(esp_host) + for _ in range(RETRY_COUNT): + if esp_host_answered.wait(timeout=25): + break + sock.sendto(packet, (MCAST_GRP, UDP_PORT)) + else: + raise RuntimeError( + 'Test has failed: did not receive mdns answer within timeout') + + +@pytest.mark.skip +def test_query_dns_host_delegated(esp_host): # type: (str) -> None + print('A: {}'.format(esp_host)) + sock = create_socket() + packet = get_dns_query_for_esp(esp_host + '-delegated') + for _ in range(RETRY_COUNT): + if esp_delegated_host_answered.wait(timeout=25): + break + sock.sendto(packet, (MCAST_GRP, UDP_PORT)) + else: + raise RuntimeError( + 'Test has failed: did not receive mdns answer within timeout') + + +@pytest.mark.esp32 +@pytest.mark.esp32s2 +@pytest.mark.esp32c3 +@pytest.mark.generic +def test_app_esp_mdns(dut): + + # 1. get the dut host name (and IP address) + specific_host = dut.expect( + re.compile(b'mdns hostname set to: \[([^\]]+)\]'), # noqa: W605 + timeout=30).group(1).decode() + + esp_ip = dut.expect( + re.compile( + b' IPv4 address: ([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)'), # noqa: W605 + timeout=30).group(1).decode() + print('Got IP={}'.format(esp_ip)) + + mdns_responder = Thread(target=mdns_listener, args=(str(specific_host), )) + + def start_case(case, desc, result): # type: (str, str, str) -> None + print('Starting {}: {}'.format(case, desc)) + dut.write(case) + res = bytes(result, encoding='utf8') + dut.expect(re.compile(res), timeout=30) + + try: + # start dns listener thread + mdns_responder.start() + + # wait untill mdns listener thred started + if not start_mdns_listener.wait(timeout=5): + raise ValueError( + 'Test has failed: mdns listener thread did not start') + + # query dns service from host, answer should be received from esp board + test_query_dns_http_service(SERVICE_NAME) + + # query dns sub-service from host, answer should be received from esp board + test_query_dns_sub_service(SUB_SERVICE_NAME) + + # query dns host name, answer should be received from esp board + test_query_dns_host(specific_host) + + # query dns host name delegated, answer should be received from esp board + test_query_dns_host_delegated(specific_host) + + # query service from esp board, answer should be received from host + start_case('CONFIG_TEST_QUERY_SERVICE', + 'Query SRV ESP32._http._tcp.local', 'SRV:ESP32') + + # query dns-host from esp board, answer should be received from host + start_case('CONFIG_TEST_QUERY_HOST', 'Query tinytester.local', + 'tinytester.local resolved to: 127.0.0.1') + + # query dns-host aynchrounusely from esp board, answer should be received from host + start_case('CONFIG_TEST_QUERY_HOST_ASYNC', + 'Query tinytester.local async', + 'Async query resolved to A:127.0.0.1') + + finally: + stop_mdns_listener.set() + mdns_responder.join() diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_apps/sdkconfig.ci b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_apps/sdkconfig.ci new file mode 100644 index 000000000..d89171dda --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_apps/sdkconfig.ci @@ -0,0 +1,13 @@ +CONFIG_IDF_TARGET="esp32" +CONFIG_MDNS_ADD_MAC_TO_HOSTNAME=y +CONFIG_MDNS_PUBLISH_DELEGATE_HOST=y +CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES=y +CONFIG_EXAMPLE_CONNECT_ETHERNET=y +CONFIG_EXAMPLE_CONNECT_WIFI=n +CONFIG_EXAMPLE_USE_INTERNAL_ETHERNET=y +CONFIG_EXAMPLE_ETH_PHY_IP101=y +CONFIG_EXAMPLE_ETH_MDC_GPIO=23 +CONFIG_EXAMPLE_ETH_MDIO_GPIO=18 +CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5 +CONFIG_EXAMPLE_ETH_PHY_ADDR=1 +CONFIG_EXAMPLE_CONNECT_IPV6=y diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_apps/sdkconfig.defaults b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_apps/sdkconfig.defaults new file mode 100644 index 000000000..0c4ffe915 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/test_apps/sdkconfig.defaults @@ -0,0 +1,2 @@ +CONFIG_TEST_MDNS_ADD_MAC_TO_HOSTNAME=y +CONFIG_TEST_MDNS_PUBLISH_DELEGATE_HOST=y diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/unit_test/CMakeLists.txt b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/unit_test/CMakeLists.txt new file mode 100644 index 000000000..450d475e4 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/unit_test/CMakeLists.txt @@ -0,0 +1,7 @@ +# This is the project CMakeLists.txt file for the test subproject +cmake_minimum_required(VERSION 3.16) + +set(EXTRA_COMPONENT_DIRS ../.. "$ENV{IDF_PATH}/tools/unit-test-app/components") + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(mdns_test) diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/unit_test/main/CMakeLists.txt b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/unit_test/main/CMakeLists.txt new file mode 100644 index 000000000..d04d217e4 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/unit_test/main/CMakeLists.txt @@ -0,0 +1,5 @@ + +idf_component_register(SRCS "test_mdns.c" + REQUIRES test_utils + INCLUDE_DIRS "." + PRIV_REQUIRES unity mdns) diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/unit_test/main/test_mdns.c b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/unit_test/main/test_mdns.c new file mode 100644 index 000000000..6b9bfbe1d --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/unit_test/main/test_mdns.c @@ -0,0 +1,299 @@ +/* + * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ + +#include +#include "mdns.h" +#include "esp_event.h" +#include "unity.h" +#include "test_utils.h" + +#include "unity_fixture.h" +#include "memory_checks.h" + +#define MDNS_HOSTNAME "test-hostname" +#define MDNS_DELEGATE_HOSTNAME "delegate-hostname" +#define MDNS_INSTANCE "test-instance" +#define MDNS_SERVICE_NAME "_http" +#define MDNS_SERVICE_PROTO "_tcp" +#define MDNS_SERVICE_PORT 80 + +TEST_GROUP(mdns); + +TEST_SETUP(mdns) +{ + test_utils_record_free_mem(); + TEST_ESP_OK(test_utils_set_leak_level(0, ESP_LEAK_TYPE_CRITICAL, ESP_COMP_LEAK_GENERAL)); +} + +TEST_TEAR_DOWN(mdns) +{ + test_utils_finish_and_evaluate_leaks(32, 64); +} + +static void yield_to_all_priorities(void) +{ + // Lower the test-task priority before testing to ensure other tasks got executed on forced context switch + size_t test_task_prio_before = uxTaskPriorityGet(NULL); + vTaskPrioritySet(NULL, tskIDLE_PRIORITY); + taskYIELD(); // Let the RTOS to switch context + vTaskPrioritySet(NULL, test_task_prio_before); +} + + +TEST(mdns, api_fails_with_invalid_state) +{ + TEST_ASSERT_NOT_EQUAL(ESP_OK, mdns_init()); + TEST_ASSERT_NOT_EQUAL(ESP_OK, mdns_hostname_set(MDNS_HOSTNAME)); + TEST_ASSERT_NOT_EQUAL(ESP_OK, mdns_instance_name_set(MDNS_INSTANCE)); + TEST_ASSERT_NOT_EQUAL(ESP_OK, mdns_service_add(MDNS_INSTANCE, MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, MDNS_SERVICE_PORT, NULL, 0)); +} + +TEST(mdns, init_deinit) +{ + test_case_uses_tcpip(); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_create_default()); + TEST_ASSERT_EQUAL(ESP_OK, mdns_init()); + yield_to_all_priorities(); // Make sure that mdns task has executed to complete initialization + mdns_free(); + esp_event_loop_delete_default(); +} + +TEST(mdns, api_fails_with_expected_err) +{ + mdns_txt_item_t serviceTxtData[CONFIG_MDNS_MAX_SERVICES] = { {NULL, NULL}, + }; + mdns_ip_addr_t addr; + addr.addr.type = ESP_IPADDR_TYPE_V4; + addr.addr.u_addr.ip4.addr = esp_ip4addr_aton("127.0.0.1"); + addr.next = NULL; + for (int i = 0; i < CONFIG_MDNS_MAX_SERVICES; ++i) { + serviceTxtData[i].key = "Key"; + serviceTxtData[i].value = "Value"; + } + test_case_uses_tcpip(); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_create_default()); + + TEST_ASSERT_EQUAL(ESP_OK, mdns_init()); + TEST_ASSERT_EQUAL(ESP_OK, mdns_hostname_set(MDNS_HOSTNAME)); + TEST_ASSERT_EQUAL(ESP_OK, mdns_delegate_hostname_add(MDNS_DELEGATE_HOSTNAME, &addr)); + yield_to_all_priorities(); // Make sure that mdns task has executed to add the hostname + TEST_ASSERT_TRUE(mdns_hostname_exists(MDNS_DELEGATE_HOSTNAME)); + TEST_ASSERT_EQUAL(ESP_OK, mdns_instance_name_set(MDNS_INSTANCE)); + TEST_ASSERT_EQUAL(ESP_OK, mdns_service_add(MDNS_INSTANCE, MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, MDNS_SERVICE_PORT, serviceTxtData, CONFIG_MDNS_MAX_SERVICES)); + TEST_ASSERT_FALSE(mdns_service_exists(MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, MDNS_DELEGATE_HOSTNAME)); + TEST_ASSERT_EQUAL(ESP_OK, mdns_service_add_for_host(MDNS_INSTANCE, MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, MDNS_DELEGATE_HOSTNAME, + MDNS_SERVICE_PORT, serviceTxtData, CONFIG_MDNS_MAX_SERVICES)); + TEST_ASSERT_TRUE(mdns_service_exists(MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, MDNS_DELEGATE_HOSTNAME)); + TEST_ASSERT_EQUAL(ESP_OK, mdns_service_txt_set(MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, serviceTxtData, CONFIG_MDNS_MAX_SERVICES)); + TEST_ASSERT_EQUAL(ESP_OK, mdns_service_txt_item_set(MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, "key1", "value1")); + TEST_ASSERT_EQUAL(ESP_OK, mdns_service_txt_item_remove(MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, "key1")); + TEST_ASSERT_EQUAL(ESP_OK, mdns_service_port_set(MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, 8080)); + yield_to_all_priorities(); // to remove the service with the updated txt records + TEST_ASSERT_EQUAL(ESP_OK, mdns_service_remove(MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO)); + yield_to_all_priorities(); // Make sure that mdns task has executed to remove the service + + TEST_ASSERT_EQUAL(ESP_OK, mdns_service_add(MDNS_INSTANCE, MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, MDNS_SERVICE_PORT, NULL, 0)); + TEST_ASSERT_EQUAL(ESP_OK, mdns_delegate_hostname_remove(MDNS_DELEGATE_HOSTNAME)); + yield_to_all_priorities(); // Make sure that mdns task has executed to remove the hostname + TEST_ASSERT_FALSE(mdns_service_exists(MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, MDNS_DELEGATE_HOSTNAME)); + TEST_ASSERT_EQUAL(ESP_OK, mdns_service_remove_all()); + yield_to_all_priorities(); // Make sure that mdns task has executed to remove all services + + TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, mdns_service_port_set(MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, 8080)); + + mdns_free(); + esp_event_loop_delete_default(); +} + +TEST(mdns, query_api_fails_with_expected_err) +{ + mdns_result_t *results = NULL; + esp_ip6_addr_t addr6; + esp_ip4_addr_t addr4; + test_case_uses_tcpip(); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_create_default()); + + TEST_ASSERT_EQUAL(ESP_OK, mdns_init()); + // check it is not possible to register a service or set an instance without configuring the hostname + TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, mdns_service_add(MDNS_INSTANCE, MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, MDNS_SERVICE_PORT, NULL, 0)); + TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, mdns_instance_name_set(MDNS_INSTANCE)); + TEST_ASSERT_EQUAL(ESP_OK, mdns_hostname_set(MDNS_HOSTNAME)); + // hostname is set, now adding a service and instance should succeed + TEST_ASSERT_EQUAL(ESP_OK, mdns_service_add(MDNS_INSTANCE, MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, MDNS_SERVICE_PORT, NULL, 0)); + TEST_ASSERT_EQUAL(ESP_OK, mdns_instance_name_set(MDNS_INSTANCE)); + + TEST_ASSERT_EQUAL(ESP_OK, mdns_query_ptr(MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, 10, CONFIG_MDNS_MAX_SERVICES, &results)); + mdns_query_results_free(results); + + TEST_ASSERT_EQUAL(ESP_OK, mdns_query_srv(MDNS_INSTANCE, MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, 10, &results)); + mdns_query_results_free(results); + + TEST_ASSERT_EQUAL(ESP_OK, mdns_query_txt(MDNS_INSTANCE, MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, 10, &results)); + mdns_query_results_free(results); + + TEST_ASSERT_EQUAL(ESP_ERR_NOT_FOUND, mdns_query_a(MDNS_HOSTNAME, 10, &addr4)); + mdns_query_results_free(results); + + TEST_ASSERT_EQUAL(ESP_ERR_NOT_FOUND, mdns_query_aaaa(MDNS_HOSTNAME, 10, &addr6)); + mdns_query_results_free(results); + + mdns_free(); + esp_event_loop_delete_default(); +} + +TEST(mdns, add_remove_service) +{ + mdns_result_t *results = NULL; + test_case_uses_tcpip(); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_create_default()); + TEST_ASSERT_EQUAL(ESP_OK, mdns_init()); + TEST_ASSERT_EQUAL(ESP_OK, mdns_hostname_set(MDNS_HOSTNAME)); + TEST_ASSERT_EQUAL(ESP_OK, mdns_service_add(MDNS_INSTANCE, MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, MDNS_SERVICE_PORT, NULL, 0)); + yield_to_all_priorities(); // Make sure that mdns task has executed to add the hostname + TEST_ASSERT_EQUAL(ESP_OK, mdns_lookup_selfhosted_service(NULL, MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, 1, &results)); + TEST_ASSERT_NOT_EQUAL(NULL, results); + TEST_ASSERT_EQUAL_STRING(MDNS_INSTANCE, results->instance_name); + TEST_ASSERT_EQUAL_STRING(MDNS_SERVICE_NAME, results->service_type); + TEST_ASSERT_EQUAL(MDNS_SERVICE_PORT, results->port); + TEST_ASSERT_EQUAL(NULL, results->txt); + mdns_query_results_free(results); + + // Update service properties: port + TEST_ASSERT_EQUAL(ESP_OK, mdns_service_port_set(MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, MDNS_SERVICE_PORT + 1)); + yield_to_all_priorities(); // Make sure that mdns task has executed to add the hostname + TEST_ASSERT_EQUAL(ESP_OK, mdns_lookup_selfhosted_service(NULL, MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, 1, &results)); + TEST_ASSERT_NOT_EQUAL(NULL, results); + TEST_ASSERT_EQUAL(MDNS_SERVICE_PORT + 1, results->port); + mdns_query_results_free(results); + + // Update service properties: instance + TEST_ASSERT_EQUAL(ESP_OK, mdns_service_instance_name_set(MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, MDNS_INSTANCE "1")); + yield_to_all_priorities(); // Make sure that mdns task has executed to add the hostname + TEST_ASSERT_EQUAL(ESP_OK, mdns_lookup_selfhosted_service(MDNS_INSTANCE "1", MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, 1, &results)); + TEST_ASSERT_NOT_EQUAL(NULL, results); + TEST_ASSERT_EQUAL_STRING(MDNS_INSTANCE "1", results->instance_name); + mdns_query_results_free(results); + + // Update service properties: txt + mdns_txt_item_t txt_data[] = { + {"key1", "esp32"}, + {"key2", "value"}, + {"key3", "value3"}, + }; + const size_t txt_data_cout = sizeof(txt_data) / sizeof(txt_data[0]); + TEST_ASSERT_EQUAL(ESP_OK, mdns_service_txt_set(MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, txt_data, txt_data_cout)); + yield_to_all_priorities(); // Make sure that mdns task has executed to add the hostname + TEST_ASSERT_EQUAL(ESP_OK, mdns_lookup_selfhosted_service(NULL, MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, 1, &results)); + TEST_ASSERT_NOT_EQUAL(NULL, results); + TEST_ASSERT_NOT_EQUAL(NULL, results->txt); + TEST_ASSERT_EQUAL(txt_data_cout, results->txt_count); + // compare txt values by keys + size_t matches = 0; + for (int i = 0; i < results->txt_count; ++i) // iterates over the results we get from mdns_lookup() + for (int j = 0; j < txt_data_cout; ++j) // iterates over our test records + if (strcmp(results->txt[i].key, txt_data[j].key) == 0) { // we compare the value only if the key matches + TEST_ASSERT_EQUAL_STRING(results->txt[i].value, txt_data[j].value); + ++matches; + } + TEST_ASSERT_EQUAL(txt_data_cout, matches); // checks that we went over all our txt items + mdns_query_results_free(results); + + // Now remove the service + TEST_ASSERT_EQUAL(ESP_OK, mdns_service_remove(MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO)); + yield_to_all_priorities(); // Make sure that mdns task has executed to add the hostname + TEST_ASSERT_EQUAL(ESP_OK, mdns_lookup_selfhosted_service(NULL, MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, 1, &results)); + TEST_ASSERT_EQUAL(NULL, results); + + mdns_free(); + esp_event_loop_delete_default(); +} + +TEST(mdns, add_remove_deleg_service) +{ + mdns_ip_addr_t addr; + addr.addr.type = ESP_IPADDR_TYPE_V4; + addr.addr.u_addr.ip4.addr = esp_ip4addr_aton("127.0.0.1"); + addr.next = NULL; + mdns_result_t *results = NULL; + test_case_uses_tcpip(); + TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_create_default()); + TEST_ASSERT_EQUAL(ESP_OK, mdns_init()); + TEST_ASSERT_EQUAL(ESP_OK, mdns_hostname_set(MDNS_HOSTNAME)); + TEST_ASSERT_EQUAL(ESP_OK, mdns_delegate_hostname_add(MDNS_DELEGATE_HOSTNAME, &addr)); + + TEST_ASSERT_EQUAL(ESP_OK, mdns_service_add_for_host(MDNS_INSTANCE, MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, MDNS_DELEGATE_HOSTNAME, MDNS_SERVICE_PORT, NULL, 0)); + yield_to_all_priorities(); // Make sure that mdns task has executed to add the hostname + TEST_ASSERT_EQUAL(ESP_OK, mdns_lookup_delegated_service(NULL, MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, 1, &results)); + TEST_ASSERT_NOT_EQUAL(NULL, results); + TEST_ASSERT_EQUAL_STRING(MDNS_INSTANCE, results->instance_name); + TEST_ASSERT_EQUAL_STRING(MDNS_SERVICE_NAME, results->service_type); + TEST_ASSERT_EQUAL(MDNS_SERVICE_PORT, results->port); + TEST_ASSERT_EQUAL(NULL, results->txt); + mdns_query_results_free(results); + + // Update service properties: port + TEST_ASSERT_EQUAL(ESP_OK, mdns_service_port_set_for_host(NULL, MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, MDNS_DELEGATE_HOSTNAME, MDNS_SERVICE_PORT + 1)); + yield_to_all_priorities(); // Make sure that mdns task has executed to add the hostname + TEST_ASSERT_EQUAL(ESP_OK, mdns_lookup_delegated_service(NULL, MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, 1, &results)); + TEST_ASSERT_NOT_EQUAL(NULL, results); + TEST_ASSERT_EQUAL(MDNS_SERVICE_PORT + 1, results->port); + mdns_query_results_free(results); + + // Update service properties: instance + TEST_ASSERT_EQUAL(ESP_OK, mdns_service_instance_name_set_for_host(NULL, MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, MDNS_DELEGATE_HOSTNAME, MDNS_INSTANCE "1")); + yield_to_all_priorities(); // Make sure that mdns task has executed to add the hostname + TEST_ASSERT_EQUAL(ESP_OK, mdns_lookup_delegated_service(MDNS_INSTANCE "1", MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, 1, &results)); + TEST_ASSERT_NOT_EQUAL(NULL, results); + TEST_ASSERT_EQUAL_STRING(MDNS_INSTANCE "1", results->instance_name); + mdns_query_results_free(results); + + // Update service properties: txt + mdns_txt_item_t txt_data[] = { + {"key1", "esp32"}, + {"key2", "value"}, + }; + const size_t txt_data_cout = sizeof(txt_data) / sizeof(txt_data[0]); + TEST_ASSERT_EQUAL(ESP_OK, mdns_service_txt_set_for_host(NULL, MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, MDNS_DELEGATE_HOSTNAME, txt_data, txt_data_cout)); + yield_to_all_priorities(); // Make sure that mdns task has executed to add the hostname + TEST_ASSERT_EQUAL(ESP_OK, mdns_lookup_delegated_service(NULL, MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, 1, &results)); + TEST_ASSERT_NOT_EQUAL(NULL, results); + TEST_ASSERT_NOT_EQUAL(NULL, results->txt); + TEST_ASSERT_EQUAL(txt_data_cout, results->txt_count); + // compare txt values by keys + size_t matches = 0; + for (int i = 0; i < results->txt_count; ++i) // iterates over the results we get from mdns_lookup() + for (int j = 0; j < txt_data_cout; ++j) // iterates over our test records + if (strcmp(results->txt[i].key, txt_data[j].key) == 0) { // we compare the value only if the key matches + TEST_ASSERT_EQUAL_STRING(results->txt[i].value, txt_data[j].value); + ++matches; + } + TEST_ASSERT_EQUAL(txt_data_cout, matches); // checks that we went over all our txt items + mdns_query_results_free(results); + + // Now remove the service + TEST_ASSERT_EQUAL(ESP_OK, mdns_service_remove_for_host(NULL, MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, MDNS_DELEGATE_HOSTNAME)); + yield_to_all_priorities(); // Make sure that mdns task has executed to add the hostname + TEST_ASSERT_EQUAL(ESP_OK, mdns_lookup_delegated_service(NULL, MDNS_SERVICE_NAME, MDNS_SERVICE_PROTO, 1, &results)); + TEST_ASSERT_EQUAL(NULL, results); + + mdns_free(); + esp_event_loop_delete_default(); +} +TEST_GROUP_RUNNER(mdns) +{ + RUN_TEST_CASE(mdns, api_fails_with_invalid_state) + RUN_TEST_CASE(mdns, api_fails_with_expected_err) + RUN_TEST_CASE(mdns, query_api_fails_with_expected_err) + RUN_TEST_CASE(mdns, init_deinit) + RUN_TEST_CASE(mdns, add_remove_service) + RUN_TEST_CASE(mdns, add_remove_deleg_service) + +} + +void app_main(void) +{ + UNITY_MAIN(mdns); +} diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/unit_test/pytest_app_mdns.py b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/unit_test/pytest_app_mdns.py new file mode 100644 index 000000000..510611273 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/unit_test/pytest_app_mdns.py @@ -0,0 +1,8 @@ +# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: Apache-2.0 + +from pytest_embedded import Dut + + +def test_mdns(dut: Dut) -> None: + dut.expect_unity_test_output() diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/unit_test/sdkconfig.ci b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/unit_test/sdkconfig.ci new file mode 100644 index 000000000..966071918 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/unit_test/sdkconfig.ci @@ -0,0 +1,3 @@ +CONFIG_IDF_TARGET="esp32" +CONFIG_UNITY_ENABLE_FIXTURE=y +CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=n diff --git a/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/unit_test/sdkconfig.defaults b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/unit_test/sdkconfig.defaults new file mode 100644 index 000000000..168e08d4c --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__mdns/tests/unit_test/sdkconfig.defaults @@ -0,0 +1,2 @@ +CONFIG_UNITY_ENABLE_FIXTURE=y +CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=n diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/.component_hash b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/.component_hash new file mode 100644 index 000000000..f8b83c1a3 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/.component_hash @@ -0,0 +1 @@ +21c45dd9cf570c12671e1678ddcfabe77471afa979bcff207a8478b45b58667a \ No newline at end of file diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/CHANGELOG.md b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/CHANGELOG.md new file mode 100644 index 000000000..41533bd1b --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/CHANGELOG.md @@ -0,0 +1,22 @@ +# 01-April-2025 + +- Extend provisioning check for `ESP_WIFI_REMOTE_ENABLED` as well along with existing `ESP_WIFI_ENABLED` +- This enables provisioning for the devices not having native Wi-Fi (e.g., ESP32-P4) and using external/remote Wi-Fi solution such as esp-hosted for Wi-Fi connectivity. + +# 17-March-2025 + +- Update the network provisioning component to work with the protocomm component which fixes incorrect AES-GCM IV usage in security2 scheme. + +# 19-June-2024 + +- Change the proto files to make the network provisioning component stay backward compatible with the wifi_provisioing + +# 23-April-2024 + +- Add `wifi_prov` or `thread_prov` in provision capabilities in the network provisioning manager for the provisioner to distinguish Thread or Wi-Fi devices + +# 16-April-2024 + +- Move wifi_provisioning component from ESP-IDF at commit 5a40bb8746 and rename it to network_provisioning with the addition of Thread provisioning support. +- Update esp_prov tool to support both Wi-Fi provisioning and Thread provisioning. +- Create thread_prov and wifi_prov examples diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/CHECKSUMS.json b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/CHECKSUMS.json new file mode 100644 index 000000000..76bb9b2fa --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/CHECKSUMS.json @@ -0,0 +1 @@ +{"version": "1.0", "algorithm": "sha256", "created_at": "2025-05-21T16:10:54.609667+00:00", "files": [{"path": "CMakeLists.txt", "size": 996, "hash": "0a16a0633a337b20339afbf83fdeae076cb37ee4668e77fa458db92c40aeaf97"}, {"path": "LICENSE", "size": 11365, "hash": "f0f612d1627194ddd07c8b5b238a514ae9794632e5470c00f16237def7dc2246"}, {"path": "CHANGELOG.md", "size": 1062, "hash": "df97ee3829807b4dbd7084111a46dee8f02b6e7cacca7e1a5606eef88624220f"}, {"path": "idf_component.yml", "size": 369, "hash": "8329838901c047bacd4ee2c083a84c77abc69fac98b0bab7467e0e037c30be53"}, {"path": "Kconfig", "size": 3025, "hash": "3a8325db754368e578be2dd347ada74abc1d3735c56247029601159f10eea342"}, {"path": "README.md", "size": 689, "hash": "765460849767d8753337609ef76cd16e3084a69915e01b211ac06e29d5a894a6"}, {"path": "proto/CMakeLists.txt", "size": 916, "hash": "80ec8dad906e3b7f1d1d3c52435bc29724ee3489aba3c6a0f2e5818fa3c34e91"}, {"path": "proto/makefile", "size": 243, "hash": "00a3f16a982a11fb8f758ddf3f47c0fdbf5846de7bec324e8895eae6801a1057"}, {"path": "proto/README.md", "size": 1793, "hash": "e9ac18a87b99823656bf6ccb50eb2dbe7bb6bc36456efedd13ba09bdbf3ad5d6"}, {"path": "proto/network_scan.proto", "size": 2449, "hash": "2c756397e596298eef262bf004a37961b152f96a54b33bcc9275fc0700aaf1cc"}, {"path": "proto/network_constants.proto", "size": 867, "hash": "1561f1d9864eaf7557b7278282639a5454481ed95a8b9932584780ecbf4d505f"}, {"path": "proto/network_config.proto", "size": 2234, "hash": "793c167bbaeeb7d492f868744a8167d697c0d220dda1a6878305d2273be22b22"}, {"path": "proto/network_ctrl.proto", "size": 1165, "hash": "01d3812b0a291c540a4a9152be945ac0564a337409e3cba69749398332547e91"}, {"path": "python/network_ctrl_pb2.py", "size": 3280, "hash": "fb5f2ee562c45df45e8f680b813b0e2c01a6e356598933e577d0d76b3abd6ec7"}, {"path": "python/network_config_pb2.py", "size": 5299, "hash": "57d87f764a831730a8d22581d86c1bd4f7107bf175d224a5b6be97632bee51c8"}, {"path": "python/network_constants_pb2.py", "size": 2661, "hash": "78df39ce7bf11655cd62552f97404fb81a4a29598854954dac28fb169be920eb"}, {"path": "python/network_scan_pb2.py", "size": 5705, "hash": "4718403ef737547bc1a0d07221c7fd98dc3f563571dedcbc0c45228da8128657"}, {"path": "examples/README.md", "size": 683, "hash": "f62f39e521e370fa2a711a8c772efb09268d9f7b4abfbb06522fe7a3541e966c"}, {"path": "proto-c/network_scan.pb-c.h", "size": 24195, "hash": "163501892e108ba2c3d6d7b2cb41c7ab5b205e315d9848608e70441efecb11dd"}, {"path": "proto-c/network_constants.pb-c.c", "size": 12784, "hash": "c5c402c0cc5904af7deb2e2868c0fef0b05af6d4453062ace61abd427629917a"}, {"path": "proto-c/network_config.pb-c.c", "size": 45336, "hash": "a02bec496ae47bc6db5fc3adffc85ab3798901b0d1c047f52f3d43cecf2e7d4c"}, {"path": "proto-c/network_ctrl.pb-c.c", "size": 27396, "hash": "b41a3971bcde639582305730283b75b938044cc266fffeec0e002c4efd1dca3f"}, {"path": "proto-c/network_scan.pb-c.c", "size": 53092, "hash": "b92de47f977b7b7cceb1d55f60ea303380aa55e2fcc6b64fec132b8ed5124a59"}, {"path": "proto-c/network_constants.pb-c.h", "size": 5659, "hash": "5d38764f02d1a1b668f15e58a985d7a33daa46ec2a16117d7373a3f37d6dbdc1"}, {"path": "proto-c/network_ctrl.pb-c.h", "size": 14775, "hash": "74477506db022bfbf44b2895618c940f9559c3be8e9cb67c276bb5447e530228"}, {"path": "proto-c/network_config.pb-c.h", "size": 22309, "hash": "fad2d6bd3496fc8cd0d75354368ff360ecb5d608c0de725452922aab56d3d673"}, {"path": "src/network_scan.c", "size": 18691, "hash": "d5dcef1754ba87692e1d36c0c5e87f6669036d5da05801d8be1dfea419691f4b"}, {"path": "src/scheme_ble.c", "size": 9153, "hash": "4512daafca8720275ac88f635a8e8a14a26db6f4dfa49fb33cd14c826338150c"}, {"path": "src/network_provisioning_priv.h", "size": 4330, "hash": "457ed56075df72c11800dc6134565cd694e886706e92094af24568dd0d456179"}, {"path": "src/network_ctrl.c", "size": 8218, "hash": "6467b9646633083ea22bf7742f8e7e40c97e00b990d23cb42e73899145911f89"}, {"path": "src/scheme_console.c", "size": 2367, "hash": "1e23ee3e56edb89a2791dca8ce6a3e5ff35cb0b16610cb205b2ab8a876b441bf"}, {"path": "src/scheme_softap.c", "size": 5695, "hash": "c1bb69750475076d1b820b58df01ad3706a4c6230f34c7252034d418eb8535e4"}, {"path": "src/network_ctrl.h", "size": 1525, "hash": "1164c2e70fb8421fccc8fdbbc10facfc0920ad8a104098ff32f7485763303500"}, {"path": "src/network_config.c", "size": 22091, "hash": "57c1872325d34e9759891a3d43d7a163548741aa0bff91dc860b697df994861b"}, {"path": "src/manager.c", "size": 84420, "hash": "819df46afc8ba8391494ad22bf14cf92a742bcef95324f7c200d65dfdb99022e"}, {"path": "src/handlers.c", "size": 14313, "hash": "f79dfbeacd6c3756bf170c5dfa6a6ae5eb53ae0e812605e544d5178f099f6bcb"}, {"path": "tool/esp_prov/__init__.py", "size": 178, "hash": "75be31c7745393e5a84efd1de9c93894c36d3d7ed97007a60acc02f88122d044"}, {"path": "tool/esp_prov/README.md", "size": 7125, "hash": "eb8d5694d2ea4272f09ec1bccc72dcc68f689a4ccfa3a7b7d62ed43d55094e4b"}, {"path": "tool/esp_prov/esp_prov.py", "size": 30707, "hash": "16eb0626ad2c5d5690e23b798bc2cdd8002f4edbdc1c8e664e4d649de16386f7"}, {"path": "tool/esp_prov/prov/network_ctrl.py", "size": 2371, "hash": "5bcc670ecbdd866375474339296f81e2dedc59a5f117fc63180becd57f831c57"}, {"path": "tool/esp_prov/prov/__init__.py", "size": 276, "hash": "d544661f29da4274f8a408cccfffe136155cd672c9d71c548c2f9576d332811d"}, {"path": "tool/esp_prov/prov/custom_prov.py", "size": 854, "hash": "ccbc5b717d7ee4fc6e3e86078b2dce38af841d08220461c437a3fe6e517bb5a9"}, {"path": "tool/esp_prov/prov/network_prov.py", "size": 6870, "hash": "2803ccc6478c3a46460566a839e7a0f4310f25b46fd10633c05e768ca07bb0b6"}, {"path": "tool/esp_prov/prov/network_scan.py", "size": 5994, "hash": "6cabc5f08c5a05cdee7ce812547890bd81ef22ca33bdb2bccead69f193f3b219"}, {"path": "tool/esp_prov/transport/transport_http.py", "size": 2143, "hash": "9e5a9ec63f9c707dcb68615909c6ba40b9754a25251b3c082e008d3e350c7e17"}, {"path": "tool/esp_prov/transport/transport.py", "size": 382, "hash": "a656caf1e0d1ab519d3d89bccfdb5c9693adb8d54bb6ad1e1059a068cb594729"}, {"path": "tool/esp_prov/transport/transport_console.py", "size": 571, "hash": "9cef5a6fbb21dd45362d65593fde39ec50af49e11b2cfb5ce4c2269055d47d7f"}, {"path": "tool/esp_prov/transport/__init__.py", "size": 260, "hash": "d80aa038dad20b2498644bc5c2bd0a2c0d5387c4cbd605d3d63339702cdb9480"}, {"path": "tool/esp_prov/transport/transport_ble.py", "size": 2228, "hash": "f32ae397e59c9a289d3294b518e850da4a48a6cb8e655775ef13348cdda3bf10"}, {"path": "tool/esp_prov/transport/ble_cli.py", "size": 7713, "hash": "8a336417c11acc8583bcca621a1d7bd92f9dfde3677ffc587fc0cc69eac3835d"}, {"path": "tool/esp_prov/proto/__init__.py", "size": 1788, "hash": "77d9616d62f96162ce3f9643af3cebd86cb4ca353278b64eaed1cd60ce7dd1f6"}, {"path": "tool/esp_prov/security/security0.py", "size": 1860, "hash": "d2ee1fbd64566f93c27c206800d34f1e84e683c6c3e853302d141c6a6303ca5c"}, {"path": "tool/esp_prov/security/security1.py", "size": 6322, "hash": "e1f2e4d5bb92fd4db4065be699b012e265091952fcdbfa397c67c8556109041c"}, {"path": "tool/esp_prov/security/srp6a.py", "size": 10228, "hash": "6074ab48d653669b6da24525cf7b7d6ac6ab4b88e4274ae69c2df8597c2a0834"}, {"path": "tool/esp_prov/security/security.py", "size": 258, "hash": "37a88d266d730154b0b914e51b68e0e50d2565a192cedf76ac57f2743f79c58e"}, {"path": "tool/esp_prov/security/__init__.py", "size": 248, "hash": "67f6cb07545b5e01e952ee6f6035dc991cdb824f901c43f14908d22005ed9b8e"}, {"path": "tool/esp_prov/security/security2.py", "size": 7686, "hash": "bdc90f36a754a9a767aa7298bd697b7ed0ddf42777bda159d13ed646a7c39445"}, {"path": "tool/esp_prov/utils/convenience.py", "size": 754, "hash": "ca6c639a8285bfa2c757d2b3d4879b25c63c8a1fdc71a395479836686c2c667e"}, {"path": "tool/esp_prov/utils/__init__.py", "size": 155, "hash": "e88fdf01f49df6317af44a84b1328b75909037d0965e7f2936edb48cfeac1cb1"}, {"path": "examples/wifi_prov/CMakeLists.txt", "size": 255, "hash": "4fb16b56b99115b874222a73a668f4f13c8dc5cf08efd6651cef4fd00f20d14d"}, {"path": "examples/wifi_prov/README.md", "size": 19839, "hash": "5d6c729a67055b18eca4492e1f0302671b4150fd41104df8b70cc9a02eff27f3"}, {"path": "examples/wifi_prov/partitions.csv", "size": 268, "hash": "11bd2719678c09eef468e34eee8005b73ce3dcf91c752250d5e661668d6eb045"}, {"path": "examples/wifi_prov/sdkconfig.defaults", "size": 390, "hash": "918ea60b94dc631546bb0bfb01fa1fc0def61db0491c7c040573265ca1135f81"}, {"path": "examples/thread_prov/CMakeLists.txt", "size": 236, "hash": "2679f255f02c7748c69d7058390862b484a8c848b6fca003ab93d612e34d7e54"}, {"path": "examples/thread_prov/README.md", "size": 18646, "hash": "e8543919fa40a49fb1a2dbf0ef9ba796bb1ff2ef46235ee0c9e71b782772a0bc"}, {"path": "examples/thread_prov/partitions.csv", "size": 268, "hash": "11bd2719678c09eef468e34eee8005b73ce3dcf91c752250d5e661668d6eb045"}, {"path": "examples/thread_prov/sdkconfig.defaults", "size": 889, "hash": "ea8fa4a8480311b1d644d18a4930b8b016972df67a54beebb42164e21bc0d70b"}, {"path": "examples/thread_prov/main/CMakeLists.txt", "size": 79, "hash": "149bc0c91991870276494f6fec9900170bc04720874e1c42821909d55e47cf59"}, {"path": "examples/thread_prov/main/idf_component.yml", "size": 167, "hash": "63d71a9f58e8ccfb26df9c249c6674f73faf60cf190f1cf03dd7daa10b8ae26b"}, {"path": "examples/thread_prov/main/esp_ot_config.h", "size": 3232, "hash": "3f40bb64ccb3f3489af8e071abebf6a79cc9181e6ec9e7e8a5753ed5e820f284"}, {"path": "examples/thread_prov/main/app_main.c", "size": 21258, "hash": "3152208c0eef7570f947e9f84343dc7ec4cb91054b538047a2a2639bdc39bdaf"}, {"path": "examples/thread_prov/main/Kconfig.projbuild", "size": 3011, "hash": "79c509dc3533e2773d182b5da373fdf8ba0a52d7d1497233c423dfebb0905c8a"}, {"path": "examples/wifi_prov/main/CMakeLists.txt", "size": 79, "hash": "149bc0c91991870276494f6fec9900170bc04720874e1c42821909d55e47cf59"}, {"path": "examples/wifi_prov/main/idf_component.yml", "size": 166, "hash": "e2424d143e5b82667909dbe420fc036de94c9604464d5539599698a4770991f7"}, {"path": "examples/wifi_prov/main/app_main.c", "size": 23253, "hash": "5759d9ae812c055e444492ddd9a245992159f29aaa6009a085014a01711b5174"}, {"path": "examples/wifi_prov/main/Kconfig.projbuild", "size": 3882, "hash": "6c0161d9fcbd22c3ddeeb3c3c2d3653a4914d7c3d52caa9d2ce280a656248d59"}, {"path": "include/network_provisioning/manager.h", "size": 29037, "hash": "d8113518789f9587992cfa86a04e88e80b1359a3d35c59b9d60aa37da27588e2"}, {"path": "include/network_provisioning/network_config.h", "size": 6732, "hash": "ae9ee61e87866a554a6c5e6f52938f4d99dba3903fbf1a01e65c78c173ecc3cb"}, {"path": "include/network_provisioning/scheme_ble.h", "size": 3682, "hash": "ca17f4d209891f0cc2d7224b4e97e715313cde2b50db055fdb7b764c39c3c2e0"}, {"path": "include/network_provisioning/network_scan.h", "size": 6990, "hash": "617ba76754386bb598471687fddec7fa70eb3a0f9619b45ca6ddddd691a29ebc"}, {"path": "include/network_provisioning/scheme_softap.h", "size": 929, "hash": "e9f309e130e708fcc1e659b3fe401ef39bf38c34a4d169abbd649bcfbee916f5"}, {"path": "include/network_provisioning/scheme_console.h", "size": 479, "hash": "b4bb3683763e46ee25c337b39e5b266eb84f543eaf0df97562ae6cb6e51c1b28"}]} \ No newline at end of file diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/CMakeLists.txt b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/CMakeLists.txt new file mode 100644 index 000000000..51e526e98 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/CMakeLists.txt @@ -0,0 +1,29 @@ +set(srcs "src/network_config.c" + "src/network_scan.c" + "src/network_ctrl.c" + "src/manager.c" + "src/handlers.c" + "src/scheme_console.c" + "proto-c/network_config.pb-c.c" + "proto-c/network_scan.pb-c.c" + "proto-c/network_ctrl.pb-c.c" + "proto-c/network_constants.pb-c.c") + +if((CONFIG_ESP_WIFI_ENABLED OR CONFIG_ESP_WIFI_REMOTE_ENABLED) AND CONFIG_ESP_WIFI_SOFTAP_SUPPORT) + list(APPEND srcs "src/scheme_softap.c") +endif() + +if(CONFIG_BT_ENABLED) + if(CONFIG_BT_BLUEDROID_ENABLED OR CONFIG_BT_NIMBLE_ENABLED) + list(APPEND srcs + "src/scheme_ble.c") + endif() +endif() + +idf_component_get_property(protocomm_dir protocomm COMPONENT_DIR) + +idf_component_register(SRCS "${srcs}" + INCLUDE_DIRS include + PRIV_INCLUDE_DIRS src proto-c ${protocomm_dir}/proto-c + REQUIRES lwip protocomm + PRIV_REQUIRES protobuf-c bt json esp_timer esp_wifi openthread) diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/Kconfig b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/Kconfig new file mode 100644 index 000000000..bd8abb551 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/Kconfig @@ -0,0 +1,80 @@ +menu "Network Provisioning Manager" + + choice NETWORK_PROV_NETWORK_TYPE + prompt "Network Type" + default NETWORK_PROV_NETWORK_TYPE_WIFI if (ESP_WIFI_ENABLED || ESP_WIFI_REMOTE_ENABLED) + default NETWORK_PROV_NETWORK_TYPE_THREAD if !ESP_WIFI_ENABLE && OPENTHREAD_ENABLED + + config NETWORK_PROV_NETWORK_TYPE_WIFI + bool "Network Type - Wi-Fi" + depends on ESP_WIFI_ENABLED || ESP_WIFI_REMOTE_ENABLED + + config NETWORK_PROV_NETWORK_TYPE_THREAD + bool "Network Type - Thread" + depends on OPENTHREAD_ENABLED + + endchoice + + config NETWORK_PROV_SCAN_MAX_ENTRIES + int "Max Network Scan Result Entries" + default 16 + range 1 255 + help + This sets the maximum number of entries of network scan results that will be kept by the + provisioning manager + + config NETWORK_PROV_AUTOSTOP_TIMEOUT + int "Provisioning auto-stop timeout" + default 30 + range 5 600 + help + Time (in seconds) after which the network provisioning manager will auto-stop after connecting to + a network successfully. + + config NETWORK_PROV_BLE_BONDING + bool + prompt "Enable BLE bonding" + depends on BT_ENABLED + help + This option is applicable only when provisioning transport is BLE. Used to enable BLE bonding process + where the information from the pairing process will be stored on the devices. + + config NETWORK_PROV_BLE_SEC_CONN + bool + prompt "Enable BLE Secure connection flag" + depends on BT_NIMBLE_ENABLED + default y + help + Used to enable Secure connection support when provisioning transport is BLE. + + config NETWORK_PROV_BLE_FORCE_ENCRYPTION + bool + prompt "Force Link Encryption during characteristic Read / Write" + help + Used to enforce link encryption when attempting to read / write characteristic + + config NETWORK_PROV_KEEP_BLE_ON_AFTER_PROV + bool "Keep BT on after provisioning is done" + depends on BT_ENABLED + select ESP_PROTOCOMM_KEEP_BLE_ON_AFTER_BLE_STOP + + config NETWORK_PROV_DISCONNECT_AFTER_PROV + bool "Terminate connection after provisioning is done" + depends on NETWORK_PROV_KEEP_BLE_ON_AFTER_PROV + default y + select ESP_PROTOCOMM_DISCONNECT_AFTER_BLE_STOP + + choice NETWORK_PROV_WIFI_STA_SCAN_METHOD + bool "Wifi Provisioning Scan Method" + depends on NETWORK_PROV_NETWORK_TYPE_WIFI + default NETWORK_PROV_WIFI_STA_ALL_CHANNEL_SCAN + config NETWORK_PROV_WIFI_STA_ALL_CHANNEL_SCAN + bool "All Channel Scan" + help + Scan will end after scanning the entire channel. This option is useful in Mesh WiFi Systems. + config NETWORK_PROV_WIFI_STA_FAST_SCAN + bool "Fast Scan" + help + Scan will end after an AP matching with the SSID has been detected. + endchoice +endmenu diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/LICENSE b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/LICENSE new file mode 100644 index 000000000..d613ddc8f --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2020 Piyush Shah + + 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. diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/README.md b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/README.md new file mode 100644 index 000000000..378eccc30 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/README.md @@ -0,0 +1,9 @@ +# Network Provisioning component + +[![Component Registry](https://components.espressif.com/components/espressif/network_provisioning/badge.svg)](https://components.espressif.com/components/espressif/network_provisioning) + +The network provisioning component provides APIs that control the network provisioning service for receiving and configuring network credentials via secure [Protocol Communication](https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-reference/provisioning/protocomm.html) sessions. + +It currently supports both Wi-Fi and Thread network provisioning: +- Provision Wi-Fi credentials over SoftAP or Bluetooth LE +- Provision Thread credentials over Bluetooth LE diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/examples/README.md b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/examples/README.md new file mode 100644 index 000000000..88827ecb2 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/examples/README.md @@ -0,0 +1,11 @@ +# Provisioning Application Examples + +This primarily consists of two examples `wifi_prov` and `thread_prov`. + +* wifi_prov + Abstracts out most of the complexity of Wi-Fi provisioning and allows easy switching between the SoftAP (using HTTP) and BLE transports. It also demonstrates how applications can register and use additional custom data endpoints. + +* thread_prov + Abstracts out most of the complexity of Thread provisioning over BLE transport. It also demonstrates how applications can register and use additional custom data endpoints. + +Provisioning applications are available for `Linux / Windows / macOS` platform as `esp_prov.py` [script](../tool/esp_prov/esp_prov.py) diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/examples/thread_prov/CMakeLists.txt b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/examples/thread_prov/CMakeLists.txt new file mode 100644 index 000000000..d5820b38c --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/examples/thread_prov/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.16) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(thread_prov) diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/examples/thread_prov/README.md b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/examples/thread_prov/README.md new file mode 100644 index 000000000..48ac77850 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/examples/thread_prov/README.md @@ -0,0 +1,375 @@ +| Supported Targets | ESP32-C6 | ESP32-H2 | +| ----------------- | -------- | -------- | + +# Network Provisioning Manager Example for Thread Provisioning + +(See the README.md file in the upper level 'examples' directory for more information about examples.) + +`thread_prov` example demonstrates the usage of `network_provisioning` manager component for building a Thread provisioning application. + +For this example, Bluetooth LE is chosen as the mode of transport, over which the provisioning related communication is to take place. NimBLE has been configured as the host. + +In the provisioning process the device is configured as a Thread FTD with specified dataset. Once configured, the device will retain the Thread configuration, until a flash erase is performed. + +Right after the provisioning is complete, Bluetooth LE is turned off and disabled to free the memory used by the Bluetooth LE stack. Though, that is specific to this example, and the user can choose to keep Bluetooth LE stack intact in their own application. + +`thread_prov` uses the following components : +* `network_provisioning` : Provides provisioning manager, data structures and protocomm endpoint handlers for Thread configuration +* `protocomm` : For protocol based communication and secure session establishment +* `protobuf` : Google's protocol buffer library for serialization of protocomm data structures +* `bt` : ESP-IDF's Bluetooth LE stack for transport of protobuf packets + +This example can be used, as it is, for adding a provisioning service to any application intended for IoT. + +> Note: If you use this example code in your own project, in Bluetooth LE mode, then remember to enable the BT stack and BTDM BLE control settings in your SDK configuration (e.g. by using the `sdkconfig.defaults` file from this project). + +## Security Scheme + +The `protocomm` component is used for establishing secure communication channel at the time of provisioning. It supports two security schemes for establishing secure communication which are [Security 1 Scheme](https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-reference/provisioning/provisioning.html#security-1-scheme) and [Security 2 Scheme](https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-reference/provisioning/provisioning.html#security-2-scheme). The example uses `Security 2 Scheme` (latest) by default. + +## How to use example + +### Hardware Required + +Example should be able to run on any commonly available ESP32-H2/ESP32-C6 development board. + +### Script Required + +Currently, provisioning script is available for `Linux / Windows / macOS` platforms. + +#### Platform : Linux / Windows / macOS + +To install the dependency packages needed, please refer to the ESP-IDF examples [README file](https://github.com/espressif/esp-idf/blob/master/examples/README.md#running-test-python-script-ttfw). + +`esp_prov` supports Bluetooth LE and SoftAP transport for Linux, MacOS and Windows platforms. For Bluetooth LE, however, if dependencies are not met, the script falls back to console mode and requires another application through which the communication can take place. The `esp_prov` console will guide you through the provisioning process of locating the correct Bluetooth LE GATT services and characteristics, the values to write, and input read values. + +### Configure the project + +``` +idf.py menuconfig +``` + +### Build and Flash + +Build the project and flash it to the board, then run monitor tool to view serial output: + +``` +idf.py -p PORT 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 + +``` +I (445) app: Starting provisioning +I (1035) app: Provisioning started +I (1045) network_prov_mgr: Provisioning started with service name : PROV_F72E6B +``` + +Make sure to note down the Bluetooth LE device name (starting with `PROV_`) displayed in the serial monitor log (eg. PROV_F72E6B). This will depend on the MAC ID and will be unique for every device. + +In a separate terminal run the `esp_prov.py` script under [directory](../../tool/esp_prov/) (make sure to replace `dataset_tlvs` with the dataset of the Thread network to which the device is supposed to connect to after provisioning). Assuming default example configuration, which uses the protocomm security version 2: + +``` +python esp_prov.py --transport ble --service_name PROV_F72E6B --sec_ver 2 --sec2_username threadprov --sec2_pwd abcd1234 --dataset_tlvs +``` + +For security scheme 1 with PoP-based (proof-of-possession) authentication, the following command can be used: +``` +python esp_prov.py --transport ble --service_name PROV_F72E6B --sec_ver 1 --pop abcd1234 --dataset_tlvs +``` + +Above command will perform the provisioning steps, and the monitor log should display something like this : + +``` +I(125493) OPENTHREAD:[N] Mle-----------: Role disabled -> detached +I (125503) OT_STATE: netif up +I(125883) OPENTHREAD:[N] Mle-----------: Attach attempt 1, AnyPartition reattaching with Active Dataset +I(126793) OPENTHREAD:[N] Mle-----------: RLOC16 fffe -> a40d +I(126793) OPENTHREAD:[N] Mle-----------: Role detached -> child +I (126813) OT_STATE: Set dns server address: FDE6:8626:404B:2::808:808 +I (126823) network_prov_mgr: Thread attached +I (126823) app: Provisioning successful +I (126823) app: Hello World! +I (127833) app: Hello World! +I (128833) app: Hello World! +. +. +. +I (131883) network_prov_mgr: Provisioning stopped +. +. +. +I (52355) app: Hello World! +I (53355) app: Hello World! +I (54355) app: Hello World! +I (55355) app: Hello World! +``` + +**Note:** For generating the credentials for security version 2 (`SRP6a` salt and verifier) for the device-side, the following example command can be used. The output can then directly be used in this example. + +The config option `CONFIG_EXAMPLE_PROV_SEC2_DEV_MODE` should be enabled for the example and in `main/app_main.c`, the macro `EXAMPLE_PROV_SEC2_USERNAME` should be set to the same username used in the salt-verifier generation. + +```log +$ python esp_prov.py --transport ble --sec_ver 2 --sec2_gen_cred --sec2_username threadprov --sec2_pwd abcd1234 +==== Salt-verifier for security scheme 2 (SRP6a) ==== +static const char sec2_salt[] = { + 0x1f, 0xff, 0x29, 0xf5, 0xc7, 0x7e, 0x07, 0x48, 0x02, 0xe9, 0x93, 0x3e, 0xa3, 0xa2, 0x26, 0x73 +}; + +static const char sec2_verifier[] = { + 0xa7, 0x29, 0xe6, 0xa5, 0x4d, 0x20, 0x57, 0x71, 0x7c, 0x9d, 0x78, 0x2d, 0x0a, 0xb0, 0x9f, 0xec, + 0x7e, 0x8b, 0xab, 0xf5, 0xe6, 0xc3, 0x36, 0x41, 0x93, 0xfd, 0xb9, 0x49, 0x67, 0xe7, 0x7f, 0x79, + 0x66, 0x25, 0x2e, 0xac, 0x89, 0x19, 0xb2, 0xb3, 0x14, 0xb1, 0x16, 0xb0, 0xb0, 0xe4, 0x34, 0xd4, + 0x99, 0x40, 0x85, 0xa4, 0x99, 0x2b, 0x84, 0x21, 0xa1, 0xfb, 0x15, 0x48, 0x04, 0x91, 0xf5, 0x74, + . + . + . + 0x80, 0x86, 0xf4, 0xd5, 0x08, 0xbc, 0xb0, 0xdd, 0x6b, 0x50, 0xfa, 0xdd, 0x16, 0x10, 0x23, 0x4b +}; + +``` + +### QR Code Scanning + +Enabling `CONFIG_EXAMPLE_PROV_SHOW_QR` will display a QR code on the serial terminal, which can be scanned from the ESP Provisioning phone apps to start the Thread provisioning process. The ESP Provisioning phone apps will be released later. + +The monitor log should display something like this : + +``` +I (673) app: Provisioning started +I (673) app: Scan this QR code from the provisioning application for Provisioning. +I (693) QRCODE: Encoding below text with ECC LVL 0 & QR Code Version 10 +I (774) QRCODE: {"ver":"v1","name":"PROV_F72E6B","username":"threadprov","pop":"abcd1234","transport":"ble","network":"thread"} +> + █▀▀▀▀▀█ ▄▄▄█ ██▄▀█▀▀▀▀ ▀▄ ▄█▀█▄▀ █▀▀▀▀▀█ + █ ███ █ ▄▄██ ▀▄▄▄▀▀▀▄▀▄▀▀▄▄▄▄▄█▀▄ █ ███ █ + █ ▀▀▀ █ ▄ █ █▄ ▀ ▄ ▄▀▄ █▄███▀ █ ▀▀▀ █ + ▀▀▀▀▀▀▀ ▀ ▀ ▀ ▀▄▀ ▀ ▀▄▀ █ █▄█ █▄▀ ▀▀▀▀▀▀▀ + ▀▀▀██▄▀██▄▀██▀▀▀ ▀▄▄█▄▀█ ▀▄▀▀▀█▄ █▄▀▄█ ▀▄ + ██▄ ▀ ▀ ▀▄▄█ ▄█▄ ▀ ██ ▀█▀█▀█ █▀ ▀█▄▀█▄ + ▄█▀▀▄▄▀█▄▀▀ ▀▄▄▄▄ ▀▀▄▄▀▄▀▀▀▀▄▀▄▄ ▄▄▄▄ ▀▀▄ + ▀ █▄▄ ▀ ▀▀█▀▀█ ▄ ▀█▄█▄ ▀▀▀▀▄▀█ ▄█▄ ▄▀▀▄▄ + ▀█▄█▀▀▀ ▄ ▀█▀██ █▄█▄▄▀▄▀▄▀ ▀ ▄▄█▄▀▄█▀▀▄ + █ ▀██ ▀▀▄▄▄▄██▀▀ █▄ ▄█▄▄▄▀█▀▄▀█ █▄█▄▄█ ▀ + ▀▀▄ ▄ ▀▄ ▄█ ▄ ▀█▀ ▄ ▀ ▀▄ ▀█▀▄▀▄██ ▄█▄█▀█▄ + █▄▄ ▀▀ ▄▀ ▄ █▀ ▄ ▀██▄█▀ ▀ █▄ ▄▀▄█ ▀▄ + ▄▄ ██▄▀▄█▀█▄▀▀ ▀ ▀ ▄█▄▀▄ ▀ █▄▄ ▄▄█▄█▄ ▀▀█ + █▄█ ▄▄▀▀ ▀ ▄ ▄▀▄ ▀▄ █▀ ▀ ▀█ ▄ ▀▀▄ ▄ ▀█ + █ ▄▀▀▀▀█▄▄ ▀ ▄█▄ ▀ ▄▄ ▄█▀▀ ▀▄▄█ ▄█▄ ▀ ▄ + █ █▀█ ▀█▄ ██▀▀ ▄ ██▄██▄█▀ █▄▀█▄██▄ ▄ ▀ ▄ + ▀ ▀▀ ▀ ▄ ▀█▀█▄ ██ █ ▄ █ █ ▄█ ▄▀█▀▀▀█ ▀▄█ + █▀▀▀▀▀█ ▀▄ ▄██▀▀██▄▄ ▄ ▄█▀▄▀▄ ██ ▀ █ ▀ ▄ + █ ███ █ █▀▀ ▄▄▀▄▀ ▄▀ ▄█▄▄█ ▀ ██ █▀▀▀▀███▄ + █ ▀▀▀ █ ███ ▄▀ █▀▀█ █▄ ▄█ ▀▀ ▀ ▀██▀ ▀ ▄ + ▀▀▀▀▀▀▀ ▀ ▀▀ ▀ ▀ ▀▀ ▀▀ ▀▀ ▀ ▀ ▀ + +I (1134) app: If QR code is not visible, copy paste the below URL in a browser. +https://espressif.github.io/esp-jumpstart/qrcode.html?data={"ver":"v1","name":"PROV_F72E6B","username":"threadprov","pop":"abcd1234","transport":"ble","network":"thread"} + +``` + +### Thread Scanning + +Provisioning manager also supports providing real-time Thread scan results (performed on the device) during provisioning. This allows the client side applications to choose the Thread network for which the device is to be configured. Various information about the visible Thread networks is available, like signal strength (RSSI) and link quality (LQI), etc. Also, the manager now provides capabilities information which can be used by client applications to determine availability of specific features (like `thread_scan`). + +When using the scan based provisioning, we don't need to specify the `--dataset_tlvs` fields explicitly: + +``` +python esp_prov.py --transport ble --service_name PROV_F72E6B --pop abcd1234 +``` + +See below the sample output from `esp_prov` tool on running above command: + +``` +Connecting... +Connected +Getting Services... +Security scheme determined to be : 1 + +==== Starting Session ==== +==== Session Established ==== + +==== Scanning Thread Networks ==== +++++ Scan process executed in 6.247516632080078 sec +++++ Scan results : 12 + +++++ Scan finished in 7.349079132080078 sec +==== Thread Scan results ==== +S.N. PAN ID EXT PAN ID NAME EXT ADDR CHN RSSI LQI +[ 1] 34121 9a6526ce2aaf4383 ST-34EW e2848e0e9e315357 11 -53 9 +[ 2] 14311 7e010e5a22beb040 OpenThread-37e7 02a2ab187a4fb728 21 -47 10 +[ 3] 14311 7e010e5a22beb040 OpenThread-37e7 22bfc4ba63cf3bb8 21 -44 9 +[ 4] 4660 dead00beef00cafe OpenThread-13b4 1e4d2bb3a614163f 22 -40 10 +[ 5] 48989 516f754f983e50c6 OpenThread-bf5d be64e2845dc1d21a 22 -46 9 +[ 6] 4660 dead00beef00cafe OpenThread-79c0 3e19ed4f89be20ee 22 -53 10 +[ 7] 31233 6c5105b3cb215393 qqqQQQQQQQQ 86ba2d8a2ded00d0 24 -47 8 +[ 8] 32231 0458ef52172c21d6 OpenThread-7de7 deca5eddda6da2a7 25 -50 10 +[ 9] 32231 0458ef52172c21d6 OpenThread-7de7 0e085d0f1d89db89 25 -45 10 +[10] 10299 07f592f684bc4266 MyHome1926416771 b268d0525d81f5c4 25 -59 9 +[11] 10299 07f592f684bc4266 MyHome1926416771 6ee0445b8d49d4b8 25 -56 9 +[12] 51344 7899e5214acf64db OpenThread-c890 b22f21bc5ce8a058 26 -40 10 +Select Network by number (0 to rescan) : 4 +Enter Thread network key string : + +==== Sending Thread Dataset to Target ==== +==== Thread Dataset sent successfully ==== + +==== Applying Thread Config to Target ==== +==== Apply config sent successfully ==== + +==== Thread connection state ==== +==== Thread state: Attaching ==== + +==== Thread connection state ==== +==== Thread state: Attaching ==== + +==== Thread connection state ==== +==== Thread state: Attached ==== +==== Provisioning was successful ==== + +``` + +### Interactive Provisioning + +`esp_prov` supports interactive provisioning. You can trigger the script with a simplified command and input the necessary details +(`Proof-of-possession` for security scheme 1 and `SRP6a username`, `SRP6a password` for security scheme 2) as the provisioning process advances. + +The command `python esp_prov.py --transport ble --sec_ver 2` gives out the following sample output: + +``` +Discovering... +==== BLE Discovery results ==== +S.N. Name Address +. +. +. +[35] PROV_F73E7E 60:55:F9:F7:3E:7E +[36] 62-37-56-08-AA-64 62:37:56:08:AA:64 +. +. +. +Select device by number (0 to rescan) : 35 +Connecting... +Getting Services.. +Security Scheme 2 - SRP6a Username required: threadprov +Security Scheme 2 - SRP6a Password required: + +==== Starting Session ==== +==== Session Established ==== + +==== Scanning Thread Networks ==== +++++ Scan process executed in 6.247041702270508 sec +++++ Scan results : 14 + +++++ Scan finished in 7.40191650390625 sec +==== Thread Scan results ==== +S.N. PAN ID EXT PAN ID NAME EXT ADDR CHN RSSI LQI +[ 1] 34121 9a6526ce2aaf4383 ST-34EW e2848e0e9e315357 11 -53 9 +[ 2] 14311 7e010e5a22beb040 OpenThread-37e7 02a2ab187a4fb728 21 -45 9 +[ 3] 14311 7e010e5a22beb040 OpenThread-37e7 22bfc4ba63cf3bb8 21 -40 10 +[ 4] 4660 dead00beef00cafe OpenThread-79c0 3e19ed4f89be20ee 22 -59 10 +[ 5] 4660 dead00beef00cafe OpenThread-13b4 1e4d2bb3a614163f 22 -43 9 +[ 6] 48989 516f754f983e50c6 OpenThread-bf5d be64e2845dc1d21a 22 -47 10 +[ 7] 23427 5b83dead5b83beef 5b83 8a1e30a60615c16c 24 -57 8 +[ 8] 31233 6c5105b3cb215393 qqqQQQQQQQQ 86ba2d8a2ded00d0 24 -48 10 +[ 9] 10299 07f592f684bc4266 MyHome1926416771 6ee0445b8d49d4b8 25 -55 9 +[10] 32231 0458ef52172c21d6 OpenThread-7de7 deca5eddda6da2a7 25 -50 10 +[11] 10299 07f592f684bc4266 MyHome1926416771 b268d0525d81f5c4 25 -55 9 +[12] 32231 0458ef52172c21d6 OpenThread-7de7 0e085d0f1d89db89 25 -47 10 +[13] 10299 07f592f684bc4266 MyHome1926416771 7e06f10b32fe678f 25 -54 10 +[14] 51344 7899e5214acf64db OpenThread-c890 b22f21bc5ce8a058 26 -42 10 +Select Network by number (0 to rescan) : 5 +Enter Thread network key string : + +==== Sending Thread Dataset to Target ==== +==== Thread Dataset sent successfully ==== + +==== Applying Thread Config to Target ==== +==== Apply config sent successfully ==== + +==== Thread connection state ==== +==== Thread state: Attaching ==== + +==== Thread connection state ==== +==== Thread state: Attaching ==== + +==== Thread connection state ==== +==== Thread state: Attached ==== +==== Provisioning was successful ==== +``` + +### Sending Custom Data + +The provisioning manager allows applications to send some custom data during provisioning, which may be +required for some other operations like connecting to some cloud service. This is achieved by creating +and registering additional endpoints using the below APIs + +``` +network_prov_mgr_endpoint_create(); +network_prov_mgr_endpoint_register(); +``` + +In this particular example, we have added an endpoint named "custom-data" which can be tested +by passing the `--custom_data ` option to the esp\_prov tool. Following output is +expected on success: + +``` +==== Sending Custom data to esp32 ==== +CustomData response: SUCCESS +``` + +## Troubleshooting + +### Provisioning failed + +It is possible that the Thread dataset provided were incorrect, or the device was not able to establish connection to the network, in which the the `esp_prov` script will notify failure (with reason). Serial monitor log will display the failure along with disconnect reason : + +``` +E (367015) app: Provisioning failed! + Reason : Thread network not found + Please reset to factory and retry provisioning +``` + +Once dataset have been applied, even though wrong dataset were provided, the device will no longer go into provisioning mode on subsequent reboots until NVS is erased (see following section). + +### Provisioning does not start + +If the serial monitor log shows the following : + +``` +I (465) app: Already provisioned, enabling netif and starting Thread +``` + +it means either the device has been provisioned earlier with or without success (e.g. scenario covered in above section), or that the Thread dataset was already set by some other application flashed previously onto your device. + +To fix this we simple need to erase the NVS partition from flash. First we need to find out its address and size. This can be seen from the monitor log on the top right after reboot. + +``` +I (47) boot: Partition Table: +I (50) boot: ## Label Usage Type ST Offset Length +I (58) boot: 0 nvs WiFi data 01 02 00009000 00006000 +I (65) boot: 1 phy_init RF data 01 01 0000f000 00001000 +I (73) boot: 2 factory factory app 00 00 00010000 00124f80 +I (80) boot: End of partition table +``` + +Now erase NVS partition by running the following commands : + +``` +$IDF_PATH/components/esptool_py/esptool/esptool.py erase_region 0x9000 0x6000 +``` + +### Bluetooth Pairing Request during provisioning + +ESP-IDF now has functionality to enforce link encryption requirement while performing GATT write on characteristics of provisioning service. This will however result in a pairing pop-up dialog, if link is not encrypted. This feature is disabled by default. In order to enable this feature, please set `CONFIG_WIFI_PROV_BLE_FORCE_ENCRYPTION=y` in the sdkconfig or select the configuration using "idf.py menuconfig" . + +``` +Component Config --> Network Provisioning Manager --> Force Link Encryption during Characteristic Read/Write + +``` +Recompiling the application with above changes should suffice to enable this functionality. + diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/examples/thread_prov/main/CMakeLists.txt b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/examples/thread_prov/main/CMakeLists.txt new file mode 100644 index 000000000..61fac40e6 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/examples/thread_prov/main/CMakeLists.txt @@ -0,0 +1,2 @@ +idf_component_register(SRCS "app_main.c" + INCLUDE_DIRS ".") diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/examples/thread_prov/main/Kconfig.projbuild b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/examples/thread_prov/main/Kconfig.projbuild new file mode 100644 index 000000000..ac4652bef --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/examples/thread_prov/main/Kconfig.projbuild @@ -0,0 +1,82 @@ +menu "Example Configuration" + + choice EXAMPLE_PROV_SECURITY_VERSION + bool "Protocomm security version" + default EXAMPLE_PROV_SECURITY_VERSION_2 + help + Network provisioning component offers 3 security versions. + The example offers a choice between security version 1 and 2. + + config EXAMPLE_PROV_SECURITY_VERSION_1 + bool "Security version 1" + select ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_1 + + config EXAMPLE_PROV_SECURITY_VERSION_2 + bool "Security version 2" + select ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_2 + endchoice + + choice EXAMPLE_PROV_MODE + bool "Security version 2 mode" + depends on EXAMPLE_PROV_SECURITY_VERSION_2 + default EXAMPLE_PROV_SEC2_DEV_MODE + + config EXAMPLE_PROV_SEC2_DEV_MODE + bool "Security version 2 development mode" + depends on EXAMPLE_PROV_SECURITY_VERSION_2 + help + This enables the development mode for + security version 2. + Please note that this mode is NOT recommended for production purpose. + + config EXAMPLE_PROV_SEC2_PROD_MODE + bool "Security version 2 production mode" + depends on EXAMPLE_PROV_SECURITY_VERSION_2 + help + This enables the production mode for + security version 2. + endchoice + + config EXAMPLE_PROV_TRANSPORT + int + default 1 if EXAMPLE_PROV_TRANSPORT_BLE + + config EXAMPLE_RESET_PROVISIONED + bool + default n + prompt "Reset provisioned status of the device" + help + This erases the NVS to reset provisioned status of the device on every reboot. + Provisioned status is determined by the Wi-Fi STA configuration, saved on the NVS. + + config EXAMPLE_RESET_PROV_MGR_ON_FAILURE + bool + default y + prompt "Reset provisioned credentials and state machine after session failure" + help + Enable reseting provisioned credentials and state machine after session failure. + This will restart the provisioning service after retries are exhausted. + + config EXAMPLE_PROV_MGR_MAX_RETRY_CNT + int + default 5 + prompt "Max retries before reseting provisioning state machine" + depends on EXAMPLE_RESET_PROV_MGR_ON_FAILURE + help + Set the Maximum retry to avoid reconnecting to an inexistent AP or if credentials + are misconfigured. Provisioned credentials are erased and internal state machine + is reset after this threshold is reached. + + config EXAMPLE_PROV_SHOW_QR + bool "Show provisioning QR code" + default y + help + Show the QR code for provisioning. + + config EXAMPLE_REPROVISIONING + bool "Re-provisioning" + help + Enable re-provisioning - allow the device to provision for new credentials + after previous successful provisioning. + +endmenu diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/examples/thread_prov/main/app_main.c b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/examples/thread_prov/main/app_main.c new file mode 100644 index 000000000..ecb7f419f --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/examples/thread_prov/main/app_main.c @@ -0,0 +1,495 @@ +/* Network Provisioning Manager Example for Thread network + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ + +#include +#include + +#include +#include +#include + +#include +#include +#include "esp_openthread_cli.h" +#include "esp_openthread_netif_glue.h" +#include "esp_openthread_types.h" +#include +#include +#include +#include +#include +#include + +#include + +#include "openthread/cli.h" +#include "openthread/instance.h" +#include "openthread/logging.h" +#include "openthread/tasklet.h" +#include "openthread/thread.h" + +#include + +#include "qrcode.h" + +static const char *TAG = "app"; + +#if CONFIG_EXAMPLE_PROV_SECURITY_VERSION_2 +#if CONFIG_EXAMPLE_PROV_SEC2_DEV_MODE +#define EXAMPLE_PROV_SEC2_USERNAME "threadprov" +#define EXAMPLE_PROV_SEC2_PWD "abcd1234" + +/* This salt,verifier has been generated for username = "threadprov" and password = "abcd1234" + * IMPORTANT NOTE: For production cases, this must be unique to every device + * and should come from device manufacturing partition.*/ +static const char sec2_salt[] = { + 0x1f, 0xff, 0x29, 0xf5, 0xc7, 0x7e, 0x07, 0x48, 0x02, 0xe9, 0x93, 0x3e, 0xa3, 0xa2, 0x26, 0x73 +}; + +static const char sec2_verifier[] = { + 0xa7, 0x29, 0xe6, 0xa5, 0x4d, 0x20, 0x57, 0x71, 0x7c, 0x9d, 0x78, 0x2d, 0x0a, 0xb0, 0x9f, 0xec, + 0x7e, 0x8b, 0xab, 0xf5, 0xe6, 0xc3, 0x36, 0x41, 0x93, 0xfd, 0xb9, 0x49, 0x67, 0xe7, 0x7f, 0x79, + 0x66, 0x25, 0x2e, 0xac, 0x89, 0x19, 0xb2, 0xb3, 0x14, 0xb1, 0x16, 0xb0, 0xb0, 0xe4, 0x34, 0xd4, + 0x99, 0x40, 0x85, 0xa4, 0x99, 0x2b, 0x84, 0x21, 0xa1, 0xfb, 0x15, 0x48, 0x04, 0x91, 0xf5, 0x74, + 0x95, 0x8a, 0x88, 0xd4, 0x4e, 0x25, 0xf6, 0xf3, 0x8e, 0x5c, 0xf9, 0x3c, 0xda, 0xbb, 0x4f, 0xa2, + 0x47, 0xe1, 0x01, 0x8f, 0x1c, 0xf5, 0xe0, 0x34, 0x41, 0x0c, 0x88, 0x76, 0x46, 0xd0, 0x16, 0xd9, + 0xfa, 0x57, 0x3d, 0x78, 0x46, 0xf1, 0xcb, 0xb1, 0x05, 0x16, 0xab, 0xf7, 0xbf, 0x9d, 0xeb, 0x05, + 0x2e, 0xc1, 0xd5, 0xe1, 0xde, 0x92, 0xe6, 0x20, 0x5f, 0xe4, 0x27, 0xda, 0xe3, 0x59, 0x91, 0x27, + 0x7b, 0x40, 0x83, 0x4c, 0xe8, 0xb5, 0xe0, 0x75, 0xe6, 0xbf, 0x26, 0xa9, 0x67, 0x06, 0xa3, 0x15, + 0x2d, 0x20, 0x81, 0xd5, 0x2a, 0x2e, 0x30, 0x84, 0xdf, 0xa2, 0x82, 0x62, 0xc4, 0x47, 0x25, 0xb6, + 0x93, 0x73, 0x87, 0x3c, 0xa7, 0x57, 0x2a, 0x47, 0x96, 0x1d, 0x89, 0xce, 0x49, 0xc6, 0x9d, 0x4f, + 0x6b, 0x39, 0x38, 0x67, 0xbb, 0x85, 0x24, 0xdf, 0xcd, 0xf5, 0xf1, 0x9f, 0x0a, 0x9e, 0x1c, 0x31, + 0xfa, 0xf1, 0x01, 0xa5, 0x30, 0xf0, 0xcb, 0x5e, 0x1c, 0xd6, 0xa0, 0x11, 0x3f, 0xf8, 0xdd, 0x07, + 0x09, 0x53, 0x62, 0x9f, 0x76, 0x5c, 0x69, 0xd1, 0x5e, 0x5b, 0xc7, 0xb0, 0x0e, 0x53, 0xeb, 0x8c, + 0x67, 0x88, 0xc7, 0x45, 0xc0, 0x26, 0xd9, 0xfa, 0xf8, 0x63, 0x0c, 0x64, 0xcb, 0x9e, 0xf4, 0x1b, + 0xb3, 0xfd, 0x78, 0x0c, 0x47, 0x0f, 0x66, 0xf3, 0xf7, 0xcd, 0xe9, 0xc6, 0x36, 0xa5, 0x58, 0xe5, + 0x9d, 0x31, 0x53, 0xb2, 0xe4, 0x8e, 0xdd, 0xd0, 0x8d, 0x13, 0xe8, 0xc6, 0x96, 0x60, 0x30, 0x50, + 0xbc, 0xef, 0xce, 0xbc, 0x23, 0xe3, 0x60, 0x63, 0x54, 0x11, 0x24, 0xba, 0x68, 0x47, 0x6a, 0xb2, + 0x5e, 0x70, 0xa3, 0xa6, 0xc3, 0xad, 0x58, 0xd1, 0x3b, 0xce, 0xce, 0x90, 0xe9, 0x90, 0x7e, 0x7a, + 0xfb, 0x4f, 0x69, 0xa2, 0x81, 0xdf, 0x15, 0xec, 0xa7, 0x8f, 0xd6, 0x5a, 0xb8, 0x1f, 0x42, 0x18, + 0x0e, 0x4f, 0x3e, 0x45, 0x2d, 0x08, 0xf2, 0xd6, 0x51, 0x90, 0xef, 0x64, 0x77, 0xee, 0xcc, 0x3c, + 0xb4, 0xa6, 0x6f, 0x0b, 0x10, 0xb2, 0xce, 0x31, 0x19, 0x10, 0x8d, 0x75, 0x8f, 0xa8, 0xa2, 0x6e, + 0x7a, 0x00, 0x92, 0x91, 0xe2, 0x16, 0xe3, 0x7a, 0xf9, 0x1d, 0x4e, 0x39, 0xe5, 0xd0, 0xd1, 0x7e, + 0x80, 0x86, 0xf4, 0xd5, 0x08, 0xbc, 0xb0, 0xdd, 0x6b, 0x50, 0xfa, 0xdd, 0x16, 0x10, 0x23, 0x4b +}; +#endif + +static esp_err_t example_get_sec2_salt(const char **salt, uint16_t *salt_len) +{ +#if CONFIG_EXAMPLE_PROV_SEC2_DEV_MODE + ESP_LOGI(TAG, "Development mode: using hard coded salt"); + *salt = sec2_salt; + *salt_len = sizeof(sec2_salt); + return ESP_OK; +#elif CONFIG_EXAMPLE_PROV_SEC2_PROD_MODE + ESP_LOGE(TAG, "Not implemented!"); + return ESP_FAIL; +#endif +} + +static esp_err_t example_get_sec2_verifier(const char **verifier, uint16_t *verifier_len) +{ +#if CONFIG_EXAMPLE_PROV_SEC2_DEV_MODE + ESP_LOGI(TAG, "Development mode: using hard coded verifier"); + *verifier = sec2_verifier; + *verifier_len = sizeof(sec2_verifier); + return ESP_OK; +#elif CONFIG_EXAMPLE_PROV_SEC2_PROD_MODE + /* This code needs to be updated with appropriate implementation to provide verifier */ + ESP_LOGE(TAG, "Not implemented!"); + return ESP_FAIL; +#endif +} +#endif + +/* Signal Thread events on this event-group */ +const int THREAD_ATTACHED_EVENT = BIT0; +static EventGroupHandle_t thread_event_group; + +#define PROV_QR_VERSION "v1" +#define PROV_TRANSPORT_BLE "ble" +#define QRCODE_BASE_URL "https://espressif.github.io/esp-jumpstart/qrcode.html" + +/* Event handler for catching system events */ +static void event_handler(void *arg, esp_event_base_t event_base, + int32_t event_id, void *event_data) +{ + if (event_base == NETWORK_PROV_EVENT) { + switch (event_id) { + case NETWORK_PROV_START: + ESP_LOGI(TAG, "Provisioning started"); + break; + case NETWORK_PROV_THREAD_DATASET_RECV: { + // TODO Log thread dataset + break; + } + case NETWORK_PROV_THREAD_DATASET_FAIL: { + network_prov_thread_fail_reason_t *reason = (network_prov_thread_fail_reason_t *)event_data; + ESP_LOGE(TAG, "Provisioning failed!\n\tReason : %s" + "\n\tPlease reset to factory and retry provisioning", + (*reason == NETWORK_PROV_THREAD_DATASET_INVALID) ? + "Invalid Thread dataset" : "Thread network not found"); + break; + } + case NETWORK_PROV_THREAD_DATASET_SUCCESS: + ESP_LOGI(TAG, "Provisioning successful"); + break; + case NETWORK_PROV_END: + /* De-initialize manager once provisioning is finished */ + network_prov_mgr_deinit(); + break; + default: + break; + } + } else if (event_base == OPENTHREAD_EVENT && event_id == OPENTHREAD_EVENT_ATTACHED) { + xEventGroupSetBits(thread_event_group, THREAD_ATTACHED_EVENT); + } else if (event_base == PROTOCOMM_SECURITY_SESSION_EVENT) { + switch (event_id) { + case PROTOCOMM_SECURITY_SESSION_SETUP_OK: + ESP_LOGI(TAG, "Secured session established!"); + break; + case PROTOCOMM_SECURITY_SESSION_INVALID_SECURITY_PARAMS: + ESP_LOGE(TAG, "Received invalid security parameters for establishing secure session!"); + break; + case PROTOCOMM_SECURITY_SESSION_CREDENTIALS_MISMATCH: + ESP_LOGE(TAG, "Received incorrect username and/or PoP for establishing secure session!"); + break; + default: + break; + } + } +} + +static void get_device_service_name(char *service_name, size_t max) +{ + uint8_t ieee802154_mac[8]; + const char *ssid_prefix = "PROV_"; + esp_read_mac(ieee802154_mac, ESP_MAC_IEEE802154); + snprintf(service_name, max, "%s%02X%02X%02X", + ssid_prefix, ieee802154_mac[5], ieee802154_mac[6], ieee802154_mac[7]); +} + +/* Handler for the optional provisioning endpoint registered by the application. + * The data format can be chosen by applications. Here, we are using plain ascii text. + * Applications can choose to use other formats like protobuf, JSON, XML, etc. + */ +esp_err_t custom_prov_data_handler(uint32_t session_id, const uint8_t *inbuf, ssize_t inlen, + uint8_t **outbuf, ssize_t *outlen, void *priv_data) +{ + if (inbuf) { + ESP_LOGI(TAG, "Received data: %.*s", inlen, (char *)inbuf); + } + char response[] = "SUCCESS"; + *outbuf = (uint8_t *)strdup(response); + if (*outbuf == NULL) { + ESP_LOGE(TAG, "System out of memory"); + return ESP_ERR_NO_MEM; + } + *outlen = strlen(response) + 1; /* +1 for NULL terminating byte */ + + return ESP_OK; +} + +static void network_prov_print_qr(const char *name, const char *username, const char *pop, const char *transport) +{ + if (!name || !transport) { + ESP_LOGW(TAG, "Cannot generate QR code payload. Data missing."); + return; + } + char payload[150] = {0}; + if (pop) { +#if CONFIG_EXAMPLE_PROV_SECURITY_VERSION_1 + snprintf(payload, sizeof(payload), "{\"ver\":\"%s\",\"name\":\"%s\"" \ + ",\"pop\":\"%s\",\"transport\":\"%s\"}", + PROV_QR_VERSION, name, pop, transport); +#elif CONFIG_EXAMPLE_PROV_SECURITY_VERSION_2 + snprintf(payload, sizeof(payload), "{\"ver\":\"%s\",\"name\":\"%s\"" \ + ",\"username\":\"%s\",\"pop\":\"%s\",\"transport\":\"%s\"}", + PROV_QR_VERSION, name, username, pop, transport); +#endif + } else { + snprintf(payload, sizeof(payload), "{\"ver\":\"%s\",\"name\":\"%s\"" \ + ",\"transport\":\"%s\"}", + PROV_QR_VERSION, name, transport); + } +#ifdef CONFIG_EXAMPLE_PROV_SHOW_QR + ESP_LOGI(TAG, "Scan this QR code from the provisioning application for Provisioning."); + esp_qrcode_config_t cfg = ESP_QRCODE_CONFIG_DEFAULT(); + esp_qrcode_generate(&cfg, payload); + //TODO: Add the network protocol type to the QR code payload +#endif /* CONFIG EXAMPLE_PROV_SHOW_QR */ + ESP_LOGI(TAG, "If QR code is not visible, copy paste the below URL in a browser.\n%s?data=%s", QRCODE_BASE_URL, payload); +} + +static esp_netif_t *init_openthread_netif(const esp_openthread_platform_config_t *config) +{ + esp_netif_config_t cfg = ESP_NETIF_DEFAULT_OPENTHREAD(); + esp_netif_t *netif = esp_netif_new(&cfg); + assert(netif != NULL); + ESP_ERROR_CHECK(esp_netif_attach(netif, esp_openthread_netif_glue_init(config))); + + return netif; +} + +static void ot_task_worker(void *aContext) +{ + esp_openthread_platform_config_t config = { + .radio_config = ESP_OPENTHREAD_DEFAULT_RADIO_CONFIG(), + .host_config = ESP_OPENTHREAD_DEFAULT_HOST_CONFIG(), + .port_config = ESP_OPENTHREAD_DEFAULT_PORT_CONFIG(), + }; + + // Initialize the OpenThread stack + ESP_ERROR_CHECK(esp_openthread_init(&config)); +#if CONFIG_OPENTHREAD_LOG_LEVEL_DYNAMIC + // The OpenThread log level directly matches ESP log level + (void)otLoggingSetLevel(CONFIG_LOG_DEFAULT_LEVEL); +#endif +#if CONFIG_OPENTHREAD_CLI + // Initialize the OpenThread cli + esp_openthread_cli_init(); +#endif + esp_netif_t *openthread_netif = init_openthread_netif(&config); + // Initialize the esp_netif bindings + esp_netif_set_default_netif(openthread_netif); + + // Run the main loop +#if CONFIG_OPENTHREAD_CLI + esp_openthread_cli_create_task(); +#endif + esp_openthread_launch_mainloop(); + + // Clean up + esp_netif_destroy(openthread_netif); + esp_openthread_netif_glue_deinit(); + + esp_vfs_eventfd_unregister(); + vTaskDelete(NULL); +} + +void app_main(void) +{ + /* Initialize NVS partition */ + esp_err_t ret = nvs_flash_init(); + if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { + /* NVS partition was truncated + * and needs to be erased */ + ESP_ERROR_CHECK(nvs_flash_erase()); + + /* Retry nvs_flash_init */ + ESP_ERROR_CHECK(nvs_flash_init()); + } + + /* Initialize TCP/IP */ + ESP_ERROR_CHECK(esp_netif_init()); + + /* Initialize the event loop */ + ESP_ERROR_CHECK(esp_event_loop_create_default()); + + thread_event_group = xEventGroupCreate(); + + /* Register our event handler for OpenThread and Provisioning related events */ + ESP_ERROR_CHECK(esp_event_handler_register(NETWORK_PROV_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL)); +#ifdef CONFIG_EXAMPLE_PROV_TRANSPORT_BLE + ESP_ERROR_CHECK(esp_event_handler_register(PROTOCOMM_TRANSPORT_BLE_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL)); +#endif + ESP_ERROR_CHECK(esp_event_handler_register(PROTOCOMM_SECURITY_SESSION_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL)); + ESP_ERROR_CHECK(esp_event_handler_register(OPENTHREAD_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL)); + + esp_vfs_eventfd_config_t eventfd_config = { + .max_fds = 3, + }; + ESP_ERROR_CHECK(esp_vfs_eventfd_register(&eventfd_config)); + xTaskCreate(ot_task_worker, "ot_task", 6144, xTaskGetCurrentTaskHandle(), 5, NULL); + + /* Configuration for the provisioning manager */ + network_prov_mgr_config_t config = { + /* Use network_prov_scheme_ble as the Provisioning Scheme */ + .scheme = network_prov_scheme_ble, + + /* Any default scheme specific event handler that you would + * like to choose. Since our example application requires + * neither BT nor BLE, we can choose to release the associated + * memory once provisioning is complete, or not needed + * (in case when device is already provisioned). Choosing + * appropriate scheme specific event handler allows the manager + * to take care of this automatically. */ + .scheme_event_handler = NETWORK_PROV_SCHEME_BLE_EVENT_HANDLER_FREE_BLE + }; + + /* Initialize provisioning manager with the + * configuration parameters set above */ + ESP_ERROR_CHECK(network_prov_mgr_init(config)); + + bool provisioned = false; +#ifdef CONFIG_EXAMPLE_RESET_PROVISIONED + network_prov_mgr_reset_thread_provisioning(); +#else + /* Let's find out if the device is provisioned */ + ESP_ERROR_CHECK(network_prov_mgr_is_thread_provisioned(&provisioned)); + +#endif + /* If device is not yet provisioned start provisioning service */ + if (!provisioned) { + ESP_LOGI(TAG, "Starting provisioning"); + + /* What is the Device Service Name that we want + * This translates to : + * - device name when scheme is network_prov_scheme_ble + */ + char service_name[12]; + get_device_service_name(service_name, sizeof(service_name)); + +#ifdef CONFIG_EXAMPLE_PROV_SECURITY_VERSION_1 + /* What is the security level that we want (0, 1, 2): + * - NETWORK_PROV_SECURITY_0 is simply plain text communication. + * - NETWORK_PROV_SECURITY_1 is secure communication which consists of secure handshake + * using X25519 key exchange and proof of possession (pop) and AES-CTR + * for encryption/decryption of messages. + * - NETWORK_PROV_SECURITY_2 SRP6a based authentication and key exchange + * + AES-GCM encryption/decryption of messages + */ + network_prov_security_t security = NETWORK_PROV_SECURITY_1; + + /* Do we want a proof-of-possession (ignored if Security 0 is selected): + * - this should be a string with length > 0 + * - NULL if not used + */ + const char *pop = "abcd1234"; + + /* This is the structure for passing security parameters + * for the protocomm security 1. + */ + network_prov_security1_params_t *sec_params = pop; + + const char *username = NULL; + +#elif CONFIG_EXAMPLE_PROV_SECURITY_VERSION_2 + network_prov_security_t security = NETWORK_PROV_SECURITY_2; + /* The username must be the same one, which has been used in the generation of salt and verifier */ + +#if CONFIG_EXAMPLE_PROV_SEC2_DEV_MODE + /* This pop field represents the password that will be used to generate salt and verifier. + * The field is present here in order to generate the QR code containing password. + * In production this password field shall not be stored on the device */ + const char *username = EXAMPLE_PROV_SEC2_USERNAME; + const char *pop = EXAMPLE_PROV_SEC2_PWD; +#elif CONFIG_EXAMPLE_PROV_SEC2_PROD_MODE + /* The username and password shall not be embedded in the firmware, + * they should be provided to the user by other means. + * e.g. QR code sticker */ + const char *username = NULL; + const char *pop = NULL; +#endif + /* This is the structure for passing security parameters + * for the protocomm security 2. + * If dynamically allocated, sec2_params pointer and its content + * must be valid till WIFI_PROV_END event is triggered. + */ + network_prov_security2_params_t sec2_params = {}; + + ESP_ERROR_CHECK(example_get_sec2_salt(&sec2_params.salt, &sec2_params.salt_len)); + ESP_ERROR_CHECK(example_get_sec2_verifier(&sec2_params.verifier, &sec2_params.verifier_len)); + + network_prov_security2_params_t *sec_params = &sec2_params; +#endif + /* What is the service key (could be NULL) + * This translates to : + * - simply ignored when scheme is network_prov_scheme_ble + */ + const char *service_key = NULL; + +#ifdef CONFIG_EXAMPLE_PROV_TRANSPORT_BLE + /* This step is only useful when scheme is network_prov_scheme_ble. This will + * set a custom 128 bit UUID which will be included in the BLE advertisement + * and will correspond to the primary GATT service that provides provisioning + * endpoints as GATT characteristics. Each GATT characteristic will be + * formed using the primary service UUID as base, with different auto assigned + * 12th and 13th bytes (assume counting starts from 0th byte). The client side + * applications must identify the endpoints by reading the User Characteristic + * Description descriptor (0x2901) for each characteristic, which contains the + * endpoint name of the characteristic */ + uint8_t custom_service_uuid[] = { + /* LSB <--------------------------------------- + * ---------------------------------------> MSB */ + 0xb4, 0xdf, 0x5a, 0x1c, 0x3f, 0x6b, 0xf4, 0xbf, + 0xea, 0x4a, 0x82, 0x03, 0x04, 0x90, 0x1a, 0x02, + }; + + /* If your build fails with linker errors at this point, then you may have + * forgotten to enable the BT stack or BTDM BLE settings in the SDK (e.g. see + * the sdkconfig.defaults in the example project) */ + network_prov_scheme_ble_set_service_uuid(custom_service_uuid); +#endif /* CONFIG_EXAMPLE_PROV_TRANSPORT_BLE */ + + /* An optional endpoint that applications can create if they expect to + * get some additional custom data during provisioning workflow. + * The endpoint name can be anything of your choice. + * This call must be made before starting the provisioning. + */ + network_prov_mgr_endpoint_create("custom-data"); + + /* Do not stop and de-init provisioning even after success, + * so that we can restart it later. */ +#ifdef CONFIG_EXAMPLE_REPROVISIONING + network_prov_mgr_disable_auto_stop(1000); +#endif + /* Start provisioning service */ + ESP_ERROR_CHECK(network_prov_mgr_start_provisioning(security, (const void *) sec_params, service_name, service_key)); + + /* The handler for the optional endpoint created above. + * This call must be made after starting the provisioning, and only if the endpoint + * has already been created above. + */ + network_prov_mgr_endpoint_register("custom-data", custom_prov_data_handler, NULL); + + /* Uncomment the following to wait for the provisioning to finish and then release + * the resources of the manager. Since in this case de-initialization is triggered + * by the default event loop handler, we don't need to call the following */ + // network_prov_mgr_wait(); + // network_prov_mgr_deinit(); + /* Print QR code for provisioning */ + network_prov_print_qr(service_name, username, pop, PROV_TRANSPORT_BLE); + } else { + ESP_LOGI(TAG, "Already provisioned, enabling netif and starting Thread"); + + /* We don't need the manager as device is already provisioned, + * so let's release it's resources */ + network_prov_mgr_deinit(); + + otInstance *instance = esp_openthread_get_instance(); + (void)otIp6SetEnabled(instance, true); + (void)otThreadSetEnabled(instance, true); + } + + /* Wait for Thread connection */ + xEventGroupWaitBits(thread_event_group, THREAD_ATTACHED_EVENT, true, true, portMAX_DELAY); + + /* Start main application now */ +#if CONFIG_EXAMPLE_REPROVISIONING + while (1) { + for (int i = 0; i < 10; i++) { + ESP_LOGI(TAG, "Hello World!"); + vTaskDelay(1000 / portTICK_PERIOD_MS); + } + + /* Resetting provisioning state machine to enable re-provisioning */ + network_prov_mgr_reset_thread_sm_state_for_reprovision(); + + /* Wait for thread connection */ + xEventGroupWaitBits(thread_event_group, THREAD_ATTACHED_EVENT, true, true, portMAX_DELAY); + } +#else + while (1) { + ESP_LOGI(TAG, "Hello World!"); + vTaskDelay(1000 / portTICK_PERIOD_MS); + } +#endif + +} diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/examples/thread_prov/main/esp_ot_config.h b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/examples/thread_prov/main/esp_ot_config.h new file mode 100644 index 000000000..7f0762fb4 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/examples/thread_prov/main/esp_ot_config.h @@ -0,0 +1,67 @@ +/* Network Provisioning Manager Example for Thread network + * + * This example code is in the Public Domain (or CC0 licensed, at your option.) + * + * Unless required by applicable law or agreed to in writing, this + * software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. + */ + +#pragma once + +#include "esp_openthread_types.h" + +#if SOC_IEEE802154_SUPPORTED +#define ESP_OPENTHREAD_DEFAULT_RADIO_CONFIG() \ + { \ + .radio_mode = RADIO_MODE_NATIVE, \ + } + +#else +#define ESP_OPENTHREAD_DEFAULT_RADIO_CONFIG() \ + { \ + .radio_mode = RADIO_MODE_UART_RCP, \ + .radio_uart_config = { \ + .port = 1, \ + .uart_config = \ + { \ + .baud_rate = 115200, \ + .data_bits = UART_DATA_8_BITS, \ + .parity = UART_PARITY_DISABLE, \ + .stop_bits = UART_STOP_BITS_1, \ + .flow_ctrl = UART_HW_FLOWCTRL_DISABLE, \ + .rx_flow_ctrl_thresh = 0, \ + .source_clk = UART_SCLK_DEFAULT, \ + }, \ + .rx_pin = 4, \ + .tx_pin = 5, \ + }, \ + } +#endif + +#define ESP_OPENTHREAD_DEFAULT_HOST_CONFIG() \ + { \ + .host_connection_mode = HOST_CONNECTION_MODE_CLI_UART, \ + .host_uart_config = { \ + .port = 0, \ + .uart_config = \ + { \ + .baud_rate = 115200, \ + .data_bits = UART_DATA_8_BITS, \ + .parity = UART_PARITY_DISABLE, \ + .stop_bits = UART_STOP_BITS_1, \ + .flow_ctrl = UART_HW_FLOWCTRL_DISABLE, \ + .rx_flow_ctrl_thresh = 0, \ + .source_clk = UART_SCLK_DEFAULT, \ + }, \ + .rx_pin = UART_PIN_NO_CHANGE, \ + .tx_pin = UART_PIN_NO_CHANGE, \ + }, \ + } + +#define ESP_OPENTHREAD_DEFAULT_PORT_CONFIG() \ + { \ + .storage_partition_name = "nvs", \ + .netif_queue_size = 10, \ + .task_queue_size = 10, \ + } diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/examples/thread_prov/main/idf_component.yml b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/examples/thread_prov/main/idf_component.yml new file mode 100644 index 000000000..1d238e036 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/examples/thread_prov/main/idf_component.yml @@ -0,0 +1,8 @@ +version: "1.0.0" +dependencies: + espressif/qrcode: + version: "^0.1.0" + espressif/network_provisioning: + version: "^1.0.0" + override_path: '../../../' + diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/examples/thread_prov/partitions.csv b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/examples/thread_prov/partitions.csv new file mode 100644 index 000000000..d4af98dfb --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/examples/thread_prov/partitions.csv @@ -0,0 +1,5 @@ +# Name, Type, SubType, Offset, Size, Flags +# Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap +nvs, data, nvs, , 0x6000, +phy_init, data, phy, , 0x1000, +factory, app, factory, , 0x180000, diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/examples/thread_prov/sdkconfig.defaults b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/examples/thread_prov/sdkconfig.defaults new file mode 100644 index 000000000..2d1ab8c0d --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/examples/thread_prov/sdkconfig.defaults @@ -0,0 +1,34 @@ +# Override some defaults so BT stack is enabled and +CONFIG_BT_ENABLED=y +CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y +CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n +CONFIG_BTDM_CTRL_MODE_BTDM=n +CONFIG_BT_NIMBLE_ENABLED=y + +## For Bluedroid as binary is larger than default size +CONFIG_PARTITION_TABLE_CUSTOM=y +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" +CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" + +# mbedTLS +CONFIG_MBEDTLS_CMAC_C=y +CONFIG_MBEDTLS_SSL_PROTO_DTLS=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECJPAKE=y +CONFIG_MBEDTLS_ECJPAKE_C=y + +# OpenThread +CONFIG_OPENTHREAD_ENABLED=y +CONFIG_OPENTHREAD_BORDER_ROUTER=n +CONFIG_OPENTHREAD_DNS64_CLIENT=y + +# Network type +CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD=y + +# LwIP +CONFIG_LWIP_TCPIP_TASK_STACK_SIZE=4096 +CONFIG_LWIP_IPV6_NUM_ADDRESSES=8 +CONFIG_LWIP_MULTICAST_PING=y +CONFIG_LWIP_HOOK_IP6_SELECT_SRC_ADDR_CUSTOM=y + +# IEEE 802.15.4 +CONFIG_IEEE802154_ENABLED=y diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/examples/wifi_prov/CMakeLists.txt b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/examples/wifi_prov/CMakeLists.txt new file mode 100644 index 000000000..6df4dd77c --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/examples/wifi_prov/CMakeLists.txt @@ -0,0 +1,7 @@ +# 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.16) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +set(COMPONENTS main) +project(wifi_prov) diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/examples/wifi_prov/README.md b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/examples/wifi_prov/README.md new file mode 100644 index 000000000..b4dae62f8 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/examples/wifi_prov/README.md @@ -0,0 +1,402 @@ +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | + +# Wi-Fi Provisioning Example + +(See the README.md file in the upper level 'examples' directory for more information about examples.) + +`wifi_prov` example demonstrates the usage of `network_provisioning` manager component for building a Wi-Fi provisioning application. + +For this example, Bluetooth LE is chosen as the default mode of transport, over which the provisioning related communication is to take place. NimBLE has been configured as the default host, but you can also switch to Bluedroid using menuconfig -> Components -> Bluetooth -> Bluetooth Host. + +> Note: Since ESP32-S2 does not support Bluetooth LE, the SoftAP will be the default mode of transport in that case. Even for ESP32, you can change to SoftAP transport from menuconfig. + +In the provisioning process the device is configured as a Wi-Fi station with specified credentials. Once configured, the device will retain the Wi-Fi configuration, until a flash erase is performed. + +Right after provisioning is complete, Bluetooth LE is turned off and disabled to free the memory used by the Bluetooth LE stack. Though, that is specific to this example, and the user can choose to keep Bluetooth LE stack intact in their own application. + +`wifi_prov` uses the following components : +* `network_provisioning` : Provides provisioning manager, data structures and protocomm endpoint handlers for Wi-Fi configuration +* `protocomm` : For protocol based communication and secure session establishment +* `protobuf` : Google's protocol buffer library for serialization of protocomm data structures +* `bt` : ESP-IDF's Bluetooth LE stack for transport of protobuf packets + +This example can be used, as it is, for adding a provisioning service to any application intended for IoT. + +> Note: If you use this example code in your own project, in Bluetooth LE mode, then remember to enable the BT stack and BTDM BLE control settings in your SDK configuration (e.g. by using the `sdkconfig.defaults` file from this project). + +## How to use example + +### Hardware Required + +Example should be able to run on any commonly available ESP32/ESP32-C2/ESP32-C3/ESP32-C6/ESP32-S2/ESP32-S3 development board. + +### Script Required + +Currently, Provisioning script is available for `Linux / Windows / macOS` platforms. + +#### Platform : Linux / Windows / macOS + +To install the dependency packages needed, please refer to the ESP-IDF examples [README file](https://github.com/espressif/esp-idf/blob/master/examples/README.md#running-test-python-script-ttfw). + +`esp_prov` supports Bluetooth LE and SoftAP transport for Linux, MacOS and Windows platforms. For Bluetooth LE, however, if dependencies are not met, the script falls back to console mode and requires another application through which the communication can take place. The `esp_prov` console will guide you through the provisioning process of locating the correct Bluetooth LE GATT services and characteristics, the values to write, and input read values. + +### Configure the project + +``` +idf.py menuconfig +``` +* Set the Bluetooth LE/Soft AP transport under "Example Configuration" options. ESP32-S2 will have only SoftAP option (SoftAP option cannot be used if IPv4 is disabled in lwIP) + +### Build and Flash + +Build the project and flash it to the board, then run monitor tool to view serial output: + +``` +idf.py -p PORT 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 + +``` +I (445) app: Starting provisioning +I (1035) app: Provisioning started +I (1045) network_prov_mgr: Provisioning started with service name : PROV_01B1E8 +``` + +Make sure to note down the Bluetooth LE device name (starting with `PROV_`) displayed in the serial monitor log (eg. PROV_01B1E8). This will depend on the MAC ID and will be unique for every device. + +In a separate terminal run the `esp_prov.py` script under [directory](../../tool/esp_prov) (make sure to replace `myssid` and `mypassword` with the credentials of the AP to which the device is supposed to connect to after provisioning). Assuming default example configuration, which uses the protocomm security version 2 with username and password authentication: + +``` +python esp_prov.py --transport ble --service_name PROV_01B1E8 --sec_ver 2 --sec2_username wifiprov --sec2_pwd abcd1234 --ssid myssid --passphrase mypassword +``` + +For security scheme 1 with PoP-based (proof-of-possession) authentication, the following command can be used: +``` +python esp_prov.py --transport ble --service_name PROV_01B1E8 --sec_ver 1 --pop abcd1234 --ssid myssid --passphrase mypassword +``` + +Above command will perform the provisioning steps, and the monitor log should display something like this : + +``` +I (39725) app: Received Wi-Fi credentials + SSID : myssid + Password : mypassword +. +. +. +I (45335) esp_netif_handlers: sta ip: 192.168.43.243, mask: 255.255.255.0, gw: 192.168.43.1 +I (45345) app: Provisioning successful +I (45345) app: Connected with IP Address:192.168.43.243 +I (46355) app: Hello World! +I (47355) app: Hello World! +I (48355) app: Hello World! +I (49355) app: Hello World! +. +. +. +I (52315) network_prov_mgr: Provisioning stopped +. +. +. +I (52355) app: Hello World! +I (53355) app: Hello World! +I (54355) app: Hello World! +I (55355) app: Hello World! +``` + +**Note:** For generating the credentials for security version 2 (`SRP6a` salt and verifier) for the device-side, the following example command can be used. The output can then directly be used in this example. + +The config option `CONFIG_EXAMPLE_PROV_SEC2_DEV_MODE` should be enabled for the example and in `main/app_main.c`, the macro `EXAMPLE_PROV_SEC2_USERNAME` should be set to the same username used in the salt-verifier generation. + +```log +$ python esp_prov.py --transport softap --sec_ver 2 --sec2_gen_cred --sec2_username wifiprov --sec2_pwd abcd1234 +==== Salt-verifier for security scheme 2 (SRP6a) ==== +static const char sec2_salt[] = { + 0x03, 0x6e, 0xe0, 0xc7, 0xbc, 0xb9, 0xed, 0xa8, 0x4c, 0x9e, 0xac, 0x97, 0xd9, 0x3d, 0xec, 0xf4 +}; + +static const char sec2_verifier[] = { + 0x7c, 0x7c, 0x85, 0x47, 0x65, 0x08, 0x94, 0x6d, 0xd6, 0x36, 0xaf, 0x37, 0xd7, 0xe8, 0x91, 0x43, + 0x78, 0xcf, 0xfd, 0x61, 0x6c, 0x59, 0xd2, 0xf8, 0x39, 0x08, 0x12, 0x72, 0x38, 0xde, 0x9e, 0x24, + . + . + . + 0xe6, 0xf6, 0x53, 0xc8, 0x31, 0xa8, 0x78, 0xde, 0x50, 0x40, 0xf7, 0x62, 0xde, 0x36, 0xb2, 0xba +}; + +``` + +### QR Code Scanning + +Enabling `CONFIG_EXAMPLE_PROV_SHOW_QR` will display a QR code on the serial terminal, which can be scanned from the ESP Provisioning phone apps to start the Wi-Fi provisioning process. + +The monitor log should display something like this : + +``` +I (690) app: Provisioning started +I (690) app: Scan this QR code from the provisioning application for Provisioning. +I (700) QRCODE: Encoding below text with ECC LVL 0 & QR Code Version 10 +I (710) QRCODE: {"ver":"v1","name":"PROV_01B1E8","username":"wifiprov","pop":"abcd1234","transport":"ble","network":"wifi"} + + █▀▀▀▀▀█ ▄▀▀████▄██▀▀▀▀ ▀▄██▄ ▄▄▀ █▀▀▀▀▀█ + █ ███ █ ▄▀ ▀▀▀▄ █▀▀▀█▀▄▀█▄█▄ ▄▀▀ █ ███ █ + █ ▀▀▀ █ ▄█▄▀▄ █▄▀█ ▄ █▀▀ ▀▄███▀▀ █ ▀▀▀ █ + ▀▀▀▀▀▀▀ ▀▄▀ █ ▀▄▀ ▀ ▀▄▀ █ █ █ █▄▀ ▀▀▀▀▀▀▀ + ▀▀█▀▀ ▀█▀ ██▀▀ ▀▄▀ ▄▄ ▀█ ▀█▄██▄ █▄▀▄█ █▄ + ▀ █▀▀██▄█▀▀ ▄█ ▀ ▀██ ▀ █▀ ▄ █▀▄▀█▄▀█ + ▀▄ ▀▄ ▀█ ██ ▀ ▄█▄ ▀▀▄█ ▄▀▀▀▀█▀▄▄ ▄█▄ ▀ ▄ + █▄▄█ ▄▀▀▀ █▀▀ ▄ ██▄█▄▄▀ ██▄▀█▄ █▄▄ ▀▄▄ + ▀██▀█▄▀ █▄▀█▄█▄ ██ █▄ ▀▄▀█▄▀▀ █▄█▄▀▄▄▀▀▄ + ▄▄▀▀▄ ▀▄▄▀▀ ▀█▀▀ █▄▄█ ▀▄▄▀▄█ ██ ▄▄█ ▀▄ + █▀█▄▀▀ █▀ ▄▄▀█▀ ▄ ▀▀▀▄▀█ ▀█▀██▀▄▄▄▄███▄ + █▄▀▄▀▀▀▀▄█ ▄▀ █▀▀█ ▀██ ▄ ██ █▄ ▄▀▀█ ▀▄ + ▀▄█▀▀ ▀ ▀ ▄▄▀▀ ▀ ▀▄▄█▄▀█ ▀ ▀▀ ▄▄█▄█▄ ▀▀█ + ▀ █▀▀█▀▄▀ ▄▄▄ ▄█▄ ▀▄ █▄ ▀ ▀█▀█ ▀ █ ▄ ▀█▄ + █▀▀█▄▄▀█ ▄ ▀ ▄▄▄▄▀ ▄█▄▄▀▀▄ ▄▀█▄ ▄▄▄ ▀▀▄ + █ ▄ █▀▀▄█▀▄█▀▀ ▄▀ █▄██▄ ▀ ▀▄▀█ ▄█▄ ▄▄▀ ▄ + ▀ ▀ ▀ ▀▀█▄██▀█▀ █ █ ▄ █ ▄█▄▄ █▀▀▀█▀▀▀█ + █▀▀▀▀▀█ ▀▀█▄██▀▀ █▄▄ ▀▄█▀ ▀▄ ▄██ ▀ █ ▀▀ + █ ███ █ █▀▀ ▄ ▀█▀ ▄▀▀█▀▄ █ ▀▄██ █▀▀▀▀█▀█▄ + █ ▀▀▀ █ █▄ ▄ ▄█▀▀▄ ▀▄ ▄█ ▀▀ ▀ ███▀ ▀▄ ▄ + ▀▀▀▀▀▀▀ ▀▀▀ ▀▀▀▀ ▀▀ ▀ ▀▀ ▀▀ ▀ ▀▀ ▀▀ + +I (1000) app: If QR code is not visible, copy paste the below URL in a browser. +https://espressif.github.io/esp-jumpstart/qrcode.html?data={"ver":"v1","name":"PROV_01B1E8","username":"wifiprov","pop":"abcd1234","transport":"ble","network":"wifi"} +``` + +### Wi-Fi Scanning + +Provisioning manager also supports providing real-time Wi-Fi scan results (performed on the device) during provisioning. This allows the client side applications to choose the AP for which the device Wi-Fi station is to be configured. Various information about the visible APs is available, like signal strength (RSSI) and security type, etc. Also, the manager now provides capabilities information which can be used by client applications to determine the security type and availability of specific features (like `wifi_scan`). + +When using the scan based provisioning, we don't need to specify the `--ssid` and `--passphrase` fields explicitly: + +``` +python esp_prov.py --transport ble --service_name PROV_01B1E8 --pop abcd1234 +``` + +See below the sample output from `esp_prov` tool on running above command: + +``` +Connecting... +Connected +Getting Services... +Security scheme determined to be : 1 + +==== Starting Session ==== +==== Session Established ==== + +==== Scanning Wi-Fi APs ==== +++++ Scan process executed in 1.9967520237 sec +++++ Scan results : 5 + +++++ Scan finished in 2.7374596596 sec +==== Wi-Fi Scan results ==== +S.N. SSID BSSID CHN RSSI AUTH +[ 1] MyHomeWiFiAP 788a20841996 1 -45 WPA2_PSK +[ 2] MobileHotspot 7a8a20841996 11 -46 WPA2_PSK +[ 3] MyHomeWiFiAP 788a208daa26 11 -54 WPA2_PSK +[ 4] NeighborsWiFiAP 8a8a20841996 6 -61 WPA2_PSK +[ 5] InsecureWiFiAP dca4caf1227c 7 -74 Open + +Select AP by number (0 to rescan) : 1 +Enter passphrase for MyHomeWiFiAP : + +==== Sending Wi-Fi Credentials to Target ==== +==== Wi-Fi Credentials sent successfully ==== + +==== Applying Wi-Fi Config to Target ==== +==== Apply config sent successfully ==== + +==== Wi-Fi connection state ==== +==== WiFi state: Connected ==== +==== Provisioning was successful ==== +``` + +### Interactive Provisioning + +`esp_prov` supports interactive provisioning. You can trigger the script with a simplified command and input the necessary details +(`Proof-of-possession` for security scheme 1 and `SRP6a username`, `SRP6a password` for security scheme 2) as the provisioning process advances. + +The command `python esp_prov.py --transport ble --sec_ver 1` gives out the following sample output: + +``` +Discovering... +==== BLE Discovery results ==== +S.N. Name Address +[ 1] PROV_4C33E8 01:02:03:04:05:06 +[ 1] BT_DEVICE_SBC 0A:0B:0C:0D:0E:0F +Select device by number (0 to rescan) : 1 +Connecting... +Getting Services... +Proof of Possession required: + +==== Starting Session ==== +==== Session Established ==== + +==== Scanning Wi-Fi APs ==== +++++ Scan process executed in 3.8695244789123535 sec +++++ Scan results : 2 + +++++ Scan finished in 4.4132080078125 sec +==== Wi-Fi Scan results ==== +S.N. SSID BSSID CHN RSSI AUTH +[ 1] MyHomeWiFiAP 788a20841996 1 -45 WPA2_PSK +[ 2] MobileHotspot 7a8a20841996 11 -46 WPA2_PSK + +Select AP by number (0 to rescan) : 1 +Enter passphrase for myssid : + +==== Sending Wi-Fi Credentials to Target ==== +==== Wi-Fi Credentials sent successfully ==== + +==== Applying Wi-Fi Config to Target ==== +==== Apply config sent successfully ==== + +==== Wi-Fi connection state ==== +==== WiFi state: Connected ==== +==== Provisioning was successful ==== +``` + +### Sending Custom Data + +The provisioning manager allows applications to send some custom data during provisioning, which may be +required for some other operations like connecting to some cloud service. This is achieved by creating +and registering additional endpoints using the below APIs + +``` +network_prov_mgr_endpoint_create(); +network_prov_mgr_endpoint_register(); +``` + +In this particular example, we have added an endpoint named "custom-data" which can be tested +by passing the `--custom_data ` option to the esp\_prov tool. Following output is +expected on success: + +``` +==== Sending Custom data to esp32 ==== +CustomData response: SUCCESS +``` + +## Troubleshooting + +### Provisioning failed + +It is possible that the Wi-Fi credentials provided were incorrect, or the device was not able to establish connection to the network, in which the the `esp_prov` script will notify failure (with reason). Serial monitor log will display the failure along with disconnect reason : + +``` +E (367015) app: Provisioning failed! + Reason : Wi-Fi AP password incorrect + Please reset to factory and retry provisioning +``` + +Once credentials have been applied, even though wrong credentials were provided, the device will no longer go into provisioning mode on subsequent reboots until NVS is erased (see following section). + +### Provisioning does not start + +If the serial monitor log shows the following : + +``` +I (465) app: Already provisioned, starting Wi-Fi STA +``` + +it means either the device has been provisioned earlier with or without success (e.g. scenario covered in above section), or that the Wi-Fi credentials were already set by some other application flashed previously onto your device. On setting the log level to DEBUG this is clearly evident : + +``` +D (455) network_prov_mgr: Found Wi-Fi SSID : myssid +D (465) network_prov_mgr: Found Wi-Fi Password : m********d +I (465) app: Already provisioned, starting Wi-Fi STA +``` + +To fix this we simple need to erase the NVS partition from flash. First we need to find out its address and size. This can be seen from the monitor log on the top right after reboot. + +``` +I (47) boot: Partition Table: +I (50) boot: ## Label Usage Type ST Offset Length +I (58) boot: 0 nvs WiFi data 01 02 00009000 00006000 +I (65) boot: 1 phy_init RF data 01 01 0000f000 00001000 +I (73) boot: 2 factory factory app 00 00 00010000 00124f80 +I (80) boot: End of partition table +``` + +Now erase NVS partition by running the following commands : + +``` +$IDF_PATH/components/esptool_py/esptool/esptool.py erase_region 0x9000 0x6000 +``` + +### Bluetooth Pairing Request during provisioning + +ESP-IDF now has functionality to enforce link encryption requirement while performing GATT write on characteristics of provisioning service. This will however result in a pairing pop-up dialog, if link is not encrypted. This feature is disabled by default. In order to enable this feature, please set `CONFIG_WIFI_PROV_BLE_FORCE_ENCRYPTION=y` in the sdkconfig or select the configuration using "idf.py menuconfig" . + +``` +Component Config --> Wi-Fi Provisioning Manager --> Force Link Encryption during Characteristic Read/Write + +``` +Recompiling the application with above changes should suffice to enable this functionality. + + +### Unsupported platform + +If the platform requirement, for running `esp_prov` is not satisfied, then the script execution will fallback to console mode, in which case the full process (involving user inputs) will look like this : + +``` +==== Esp_Prov Version: v1.0 ==== +BLE client is running in console mode + This could be due to your platform not being supported or dependencies not being met + Please ensure all pre-requisites are met to run the full fledged client +BLECLI >> Please connect to BLE device `PROV_01B1E8` manually using your tool of choice +BLECLI >> Was the device connected successfully? [y/n] y +BLECLI >> List available attributes of the connected device +BLECLI >> Is the service UUID '0000ffff-0000-1000-8000-00805f9b34fb' listed among available attributes? [y/n] y +BLECLI >> Is the characteristic UUID '0000ff53-0000-1000-8000-00805f9b34fb' listed among available attributes? [y/n] y +BLECLI >> Is the characteristic UUID '0000ff51-0000-1000-8000-00805f9b34fb' listed among available attributes? [y/n] y +BLECLI >> Is the characteristic UUID '0000ff52-0000-1000-8000-00805f9b34fb' listed among available attributes? [y/n] y + +==== Verifying protocol version ==== +BLECLI >> Write following data to characteristic with UUID '0000ff53-0000-1000-8000-00805f9b34fb' : + >> 56302e31 +BLECLI >> Enter data read from characteristic (in hex) : + << 53554343455353 +==== Verified protocol version successfully ==== + +==== Starting Session ==== +BLECLI >> Write following data to characteristic with UUID '0000ff51-0000-1000-8000-00805f9b34fb' : + >> 10015a25a201220a20ae6d9d5d1029f8c366892252d2d5a0ffa7ce1ee5829312545dd5f2aba057294d +BLECLI >> Enter data read from characteristic (in hex) : + << 10015a390801aa0134122048008bfc365fad4753dc75912e0c764d60749cb26dd609595b6fbc72e12614031a1089733af233c7448e7d7fb7963682c6d8 +BLECLI >> Write following data to characteristic with UUID '0000ff51-0000-1000-8000-00805f9b34fb' : + >> 10015a270802b2012212204051088dc294fe4621fac934a8ea22e948fcc3e8ac458aac088ce705c65dbfb9 +BLECLI >> Enter data read from characteristic (in hex) : + << 10015a270803ba01221a20c8d38059d5206a3d92642973ac6ba8ac2f6ecf2b7a3632964eb35a0f20133adb +==== Session Established ==== + +==== Sending Wifi credential to esp32 ==== +BLECLI >> Write following data to characteristic with UUID '0000ff52-0000-1000-8000-00805f9b34fb' : + >> 98471ac4019a46765c28d87df8c8ae71c1ae6cfe0bc9c615bc6d2c +BLECLI >> Enter data read from characteristic (in hex) : + << 3271f39a +==== Wifi Credentials sent successfully ==== + +==== Applying config to esp32 ==== +BLECLI >> Write following data to characteristic with UUID '0000ff52-0000-1000-8000-00805f9b34fb' : + >> 5355 +BLECLI >> Enter data read from characteristic (in hex) : + << 1664db24 +==== Apply config sent successfully ==== + +==== Wifi connection state ==== +BLECLI >> Write following data to characteristic with UUID '0000ff52-0000-1000-8000-00805f9b34fb' : + >> 290d +BLECLI >> Enter data read from characteristic (in hex) : + << 505f72a9f8521025c1964d7789c4d7edc56aedebd144e1b667bc7c0975757b80cc091aa9f3e95b06eaefbc30290fa1 +++++ WiFi state: connected ++++ +==== Provisioning was successful ==== +``` + +The write data is to be copied from the console output ```>>``` to the platform specific application and the data read from the application is to be pasted at the user input prompt ```<<``` of the console, in the format (hex) indicated in above sample log. diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/examples/wifi_prov/main/CMakeLists.txt b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/examples/wifi_prov/main/CMakeLists.txt new file mode 100644 index 000000000..61fac40e6 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/examples/wifi_prov/main/CMakeLists.txt @@ -0,0 +1,2 @@ +idf_component_register(SRCS "app_main.c" + INCLUDE_DIRS ".") diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/examples/wifi_prov/main/Kconfig.projbuild b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/examples/wifi_prov/main/Kconfig.projbuild new file mode 100644 index 000000000..be36720ad --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/examples/wifi_prov/main/Kconfig.projbuild @@ -0,0 +1,107 @@ +menu "Example Configuration" + + choice EXAMPLE_PROV_TRANSPORT + bool "Provisioning Transport" + default EXAMPLE_PROV_TRANSPORT_SOFTAP if IDF_TARGET_ESP32S2 + default EXAMPLE_PROV_TRANSPORT_BLE + help + Wi-Fi provisioning component offers both, SoftAP and BLE transports. Choose any one. + + config EXAMPLE_PROV_TRANSPORT_BLE + bool "BLE" + select BT_ENABLED + depends on !IDF_TARGET_ESP32S2 + config EXAMPLE_PROV_TRANSPORT_SOFTAP + bool "Soft AP" + select LWIP_IPV4 + endchoice + + choice EXAMPLE_PROV_SECURITY_VERSION + bool "Protocomm security version" + default EXAMPLE_PROV_SECURITY_VERSION_2 + help + Wi-Fi provisioning component offers 3 security versions. + The example offers a choice between security version 1 and 2. + + config EXAMPLE_PROV_SECURITY_VERSION_1 + bool "Security version 1" + select ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_1 + + config EXAMPLE_PROV_SECURITY_VERSION_2 + bool "Security version 2" + select ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_2 + endchoice + + choice EXAMPLE_PROV_MODE + bool "Security version 2 mode" + depends on EXAMPLE_PROV_SECURITY_VERSION_2 + default EXAMPLE_PROV_SEC2_DEV_MODE + + config EXAMPLE_PROV_SEC2_DEV_MODE + bool "Security version 2 development mode" + depends on EXAMPLE_PROV_SECURITY_VERSION_2 + help + This enables the development mode for + security version 2. + Please note that this mode is NOT recommended for production purpose. + + config EXAMPLE_PROV_SEC2_PROD_MODE + bool "Security version 2 production mode" + depends on EXAMPLE_PROV_SECURITY_VERSION_2 + help + This enables the production mode for + security version 2. + endchoice + + config EXAMPLE_PROV_TRANSPORT + int + default 1 if EXAMPLE_PROV_TRANSPORT_BLE + default 2 if EXAMPLE_PROV_TRANSPORT_SOFTAP + + config EXAMPLE_RESET_PROVISIONED + bool + default n + prompt "Reset provisioned status of the device" + help + This erases the NVS to reset provisioned status of the device on every reboot. + Provisioned status is determined by the Wi-Fi STA configuration, saved on the NVS. + + config EXAMPLE_RESET_PROV_MGR_ON_FAILURE + bool + default y + prompt "Reset provisioned credentials and state machine after session failure" + help + Enable reseting provisioned credentials and state machine after session failure. + This will restart the provisioning service after retries are exhausted. + + config EXAMPLE_PROV_MGR_MAX_RETRY_CNT + int + default 5 + prompt "Max retries before reseting provisioning state machine" + depends on EXAMPLE_RESET_PROV_MGR_ON_FAILURE + help + Set the Maximum retry to avoid reconnecting to an inexistent AP or if credentials + are misconfigured. Provisioned credentials are erased and internal state machine + is reset after this threshold is reached. + + config EXAMPLE_PROV_SHOW_QR + bool "Show provisioning QR code" + default y + help + Show the QR code for provisioning. + + config EXAMPLE_PROV_USING_BLUEDROID + bool + depends on (BT_BLUEDROID_ENABLED && (IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S3)) + select BT_BLE_42_FEATURES_SUPPORTED + default y + help + This enables BLE 4.2 features for Bluedroid. + + config EXAMPLE_REPROVISIONING + bool "Re-provisioning" + help + Enable re-provisioning - allow the device to provision for new credentials + after previous successful provisioning. + +endmenu diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/examples/wifi_prov/main/app_main.c b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/examples/wifi_prov/main/app_main.c new file mode 100644 index 000000000..b6f7b0b66 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/examples/wifi_prov/main/app_main.c @@ -0,0 +1,525 @@ +/* Wi-Fi Provisioning Manager Example + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include + +#ifdef CONFIG_EXAMPLE_PROV_TRANSPORT_BLE +#include +#endif /* CONFIG_EXAMPLE_PROV_TRANSPORT_BLE */ + +#ifdef CONFIG_EXAMPLE_PROV_TRANSPORT_SOFTAP +#include +#endif /* CONFIG_EXAMPLE_PROV_TRANSPORT_SOFTAP */ +#include "qrcode.h" + +static const char *TAG = "app"; + +#if CONFIG_EXAMPLE_PROV_SECURITY_VERSION_2 +#if CONFIG_EXAMPLE_PROV_SEC2_DEV_MODE +#define EXAMPLE_PROV_SEC2_USERNAME "wifiprov" +#define EXAMPLE_PROV_SEC2_PWD "abcd1234" + +/* This salt,verifier has been generated for username = "wifiprov" and password = "abcd1234" + * IMPORTANT NOTE: For production cases, this must be unique to every device + * and should come from device manufacturing partition.*/ +static const char sec2_salt[] = { + 0x03, 0x6e, 0xe0, 0xc7, 0xbc, 0xb9, 0xed, 0xa8, 0x4c, 0x9e, 0xac, 0x97, 0xd9, 0x3d, 0xec, 0xf4 +}; + +static const char sec2_verifier[] = { + 0x7c, 0x7c, 0x85, 0x47, 0x65, 0x08, 0x94, 0x6d, 0xd6, 0x36, 0xaf, 0x37, 0xd7, 0xe8, 0x91, 0x43, + 0x78, 0xcf, 0xfd, 0x61, 0x6c, 0x59, 0xd2, 0xf8, 0x39, 0x08, 0x12, 0x72, 0x38, 0xde, 0x9e, 0x24, + 0xa4, 0x70, 0x26, 0x1c, 0xdf, 0xa9, 0x03, 0xc2, 0xb2, 0x70, 0xe7, 0xb1, 0x32, 0x24, 0xda, 0x11, + 0x1d, 0x97, 0x18, 0xdc, 0x60, 0x72, 0x08, 0xcc, 0x9a, 0xc9, 0x0c, 0x48, 0x27, 0xe2, 0xae, 0x89, + 0xaa, 0x16, 0x25, 0xb8, 0x04, 0xd2, 0x1a, 0x9b, 0x3a, 0x8f, 0x37, 0xf6, 0xe4, 0x3a, 0x71, 0x2e, + 0xe1, 0x27, 0x86, 0x6e, 0xad, 0xce, 0x28, 0xff, 0x54, 0x46, 0x60, 0x1f, 0xb9, 0x96, 0x87, 0xdc, + 0x57, 0x40, 0xa7, 0xd4, 0x6c, 0xc9, 0x77, 0x54, 0xdc, 0x16, 0x82, 0xf0, 0xed, 0x35, 0x6a, 0xc4, + 0x70, 0xad, 0x3d, 0x90, 0xb5, 0x81, 0x94, 0x70, 0xd7, 0xbc, 0x65, 0xb2, 0xd5, 0x18, 0xe0, 0x2e, + 0xc3, 0xa5, 0xf9, 0x68, 0xdd, 0x64, 0x7b, 0xb8, 0xb7, 0x3c, 0x9c, 0xfc, 0x00, 0xd8, 0x71, 0x7e, + 0xb7, 0x9a, 0x7c, 0xb1, 0xb7, 0xc2, 0xc3, 0x18, 0x34, 0x29, 0x32, 0x43, 0x3e, 0x00, 0x99, 0xe9, + 0x82, 0x94, 0xe3, 0xd8, 0x2a, 0xb0, 0x96, 0x29, 0xb7, 0xdf, 0x0e, 0x5f, 0x08, 0x33, 0x40, 0x76, + 0x52, 0x91, 0x32, 0x00, 0x9f, 0x97, 0x2c, 0x89, 0x6c, 0x39, 0x1e, 0xc8, 0x28, 0x05, 0x44, 0x17, + 0x3f, 0x68, 0x02, 0x8a, 0x9f, 0x44, 0x61, 0xd1, 0xf5, 0xa1, 0x7e, 0x5a, 0x70, 0xd2, 0xc7, 0x23, + 0x81, 0xcb, 0x38, 0x68, 0xe4, 0x2c, 0x20, 0xbc, 0x40, 0x57, 0x76, 0x17, 0xbd, 0x08, 0xb8, 0x96, + 0xbc, 0x26, 0xeb, 0x32, 0x46, 0x69, 0x35, 0x05, 0x8c, 0x15, 0x70, 0xd9, 0x1b, 0xe9, 0xbe, 0xcc, + 0xa9, 0x38, 0xa6, 0x67, 0xf0, 0xad, 0x50, 0x13, 0x19, 0x72, 0x64, 0xbf, 0x52, 0xc2, 0x34, 0xe2, + 0x1b, 0x11, 0x79, 0x74, 0x72, 0xbd, 0x34, 0x5b, 0xb1, 0xe2, 0xfd, 0x66, 0x73, 0xfe, 0x71, 0x64, + 0x74, 0xd0, 0x4e, 0xbc, 0x51, 0x24, 0x19, 0x40, 0x87, 0x0e, 0x92, 0x40, 0xe6, 0x21, 0xe7, 0x2d, + 0x4e, 0x37, 0x76, 0x2f, 0x2e, 0xe2, 0x68, 0xc7, 0x89, 0xe8, 0x32, 0x13, 0x42, 0x06, 0x84, 0x84, + 0x53, 0x4a, 0xb3, 0x0c, 0x1b, 0x4c, 0x8d, 0x1c, 0x51, 0x97, 0x19, 0xab, 0xae, 0x77, 0xff, 0xdb, + 0xec, 0xf0, 0x10, 0x95, 0x34, 0x33, 0x6b, 0xcb, 0x3e, 0x84, 0x0f, 0xb9, 0xd8, 0x5f, 0xb8, 0xa0, + 0xb8, 0x55, 0x53, 0x3e, 0x70, 0xf7, 0x18, 0xf5, 0xce, 0x7b, 0x4e, 0xbf, 0x27, 0xce, 0xce, 0xa8, + 0xb3, 0xbe, 0x40, 0xc5, 0xc5, 0x32, 0x29, 0x3e, 0x71, 0x64, 0x9e, 0xde, 0x8c, 0xf6, 0x75, 0xa1, + 0xe6, 0xf6, 0x53, 0xc8, 0x31, 0xa8, 0x78, 0xde, 0x50, 0x40, 0xf7, 0x62, 0xde, 0x36, 0xb2, 0xba +}; +#endif + +static esp_err_t example_get_sec2_salt(const char **salt, uint16_t *salt_len) +{ +#if CONFIG_EXAMPLE_PROV_SEC2_DEV_MODE + ESP_LOGI(TAG, "Development mode: using hard coded salt"); + *salt = sec2_salt; + *salt_len = sizeof(sec2_salt); + return ESP_OK; +#elif CONFIG_EXAMPLE_PROV_SEC2_PROD_MODE + ESP_LOGE(TAG, "Not implemented!"); + return ESP_FAIL; +#endif +} + +static esp_err_t example_get_sec2_verifier(const char **verifier, uint16_t *verifier_len) +{ +#if CONFIG_EXAMPLE_PROV_SEC2_DEV_MODE + ESP_LOGI(TAG, "Development mode: using hard coded verifier"); + *verifier = sec2_verifier; + *verifier_len = sizeof(sec2_verifier); + return ESP_OK; +#elif CONFIG_EXAMPLE_PROV_SEC2_PROD_MODE + /* This code needs to be updated with appropriate implementation to provide verifier */ + ESP_LOGE(TAG, "Not implemented!"); + return ESP_FAIL; +#endif +} +#endif + +/* Signal Wi-Fi events on this event-group */ +const int WIFI_CONNECTED_EVENT = BIT0; +static EventGroupHandle_t wifi_event_group; + +#define PROV_QR_VERSION "v1" +#define PROV_TRANSPORT_SOFTAP "softap" +#define PROV_TRANSPORT_BLE "ble" +#define QRCODE_BASE_URL "https://espressif.github.io/esp-jumpstart/qrcode.html" + +/* Event handler for catching system events */ +static void event_handler(void *arg, esp_event_base_t event_base, + int32_t event_id, void *event_data) +{ +#ifdef CONFIG_EXAMPLE_RESET_PROV_MGR_ON_FAILURE + static int retries; +#endif + if (event_base == NETWORK_PROV_EVENT) { + switch (event_id) { + case NETWORK_PROV_START: + ESP_LOGI(TAG, "Provisioning started"); + break; + case NETWORK_PROV_WIFI_CRED_RECV: { + wifi_sta_config_t *wifi_sta_cfg = (wifi_sta_config_t *)event_data; + ESP_LOGI(TAG, "Received Wi-Fi credentials" + "\n\tSSID : %s\n\tPassword : %s", + (const char *) wifi_sta_cfg->ssid, + (const char *) wifi_sta_cfg->password); + break; + } + case NETWORK_PROV_WIFI_CRED_FAIL: { + network_prov_wifi_sta_fail_reason_t *reason = (network_prov_wifi_sta_fail_reason_t *)event_data; + ESP_LOGE(TAG, "Provisioning failed!\n\tReason : %s" + "\n\tPlease reset to factory and retry provisioning", + (*reason == NETWORK_PROV_WIFI_STA_AUTH_ERROR) ? + "Wi-Fi station authentication failed" : "Wi-Fi access-point not found"); +#ifdef CONFIG_EXAMPLE_RESET_PROV_MGR_ON_FAILURE + retries++; + if (retries >= CONFIG_EXAMPLE_PROV_MGR_MAX_RETRY_CNT) { + ESP_LOGI(TAG, "Failed to connect with provisioned AP, reseting provisioned credentials"); + network_prov_mgr_reset_wifi_sm_state_on_failure(); + retries = 0; + } +#endif + break; + } + case NETWORK_PROV_WIFI_CRED_SUCCESS: + ESP_LOGI(TAG, "Provisioning successful"); +#ifdef CONFIG_EXAMPLE_RESET_PROV_MGR_ON_FAILURE + retries = 0; +#endif + break; + case NETWORK_PROV_END: + /* De-initialize manager once provisioning is finished */ + network_prov_mgr_deinit(); + break; + default: + break; + } + } else if (event_base == WIFI_EVENT) { + switch (event_id) { + case WIFI_EVENT_STA_START: + esp_wifi_connect(); + break; + case WIFI_EVENT_STA_DISCONNECTED: + ESP_LOGI(TAG, "Disconnected. Connecting to the AP again..."); + esp_wifi_connect(); + break; +#ifdef CONFIG_EXAMPLE_PROV_TRANSPORT_SOFTAP + case WIFI_EVENT_AP_STACONNECTED: + ESP_LOGI(TAG, "SoftAP transport: Connected!"); + break; + case WIFI_EVENT_AP_STADISCONNECTED: + ESP_LOGI(TAG, "SoftAP transport: Disconnected!"); + break; +#endif + default: + break; + } + } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) { + ip_event_got_ip_t *event = (ip_event_got_ip_t *) event_data; + ESP_LOGI(TAG, "Connected with IP Address:" IPSTR, IP2STR(&event->ip_info.ip)); + /* Signal main application to continue execution */ + xEventGroupSetBits(wifi_event_group, WIFI_CONNECTED_EVENT); +#ifdef CONFIG_EXAMPLE_PROV_TRANSPORT_BLE + } else if (event_base == PROTOCOMM_TRANSPORT_BLE_EVENT) { + switch (event_id) { + case PROTOCOMM_TRANSPORT_BLE_CONNECTED: + ESP_LOGI(TAG, "BLE transport: Connected!"); + break; + case PROTOCOMM_TRANSPORT_BLE_DISCONNECTED: + ESP_LOGI(TAG, "BLE transport: Disconnected!"); + break; + default: + break; + } +#endif + } else if (event_base == PROTOCOMM_SECURITY_SESSION_EVENT) { + switch (event_id) { + case PROTOCOMM_SECURITY_SESSION_SETUP_OK: + ESP_LOGI(TAG, "Secured session established!"); + break; + case PROTOCOMM_SECURITY_SESSION_INVALID_SECURITY_PARAMS: + ESP_LOGE(TAG, "Received invalid security parameters for establishing secure session!"); + break; + case PROTOCOMM_SECURITY_SESSION_CREDENTIALS_MISMATCH: + ESP_LOGE(TAG, "Received incorrect username and/or PoP for establishing secure session!"); + break; + default: + break; + } + } +} + +static void wifi_init_sta(void) +{ + /* Start Wi-Fi in station mode */ + ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); + ESP_ERROR_CHECK(esp_wifi_start()); +} + +static void get_device_service_name(char *service_name, size_t max) +{ + uint8_t eth_mac[6]; + const char *ssid_prefix = "PROV_"; + esp_wifi_get_mac(WIFI_IF_STA, eth_mac); + snprintf(service_name, max, "%s%02X%02X%02X", + ssid_prefix, eth_mac[3], eth_mac[4], eth_mac[5]); +} + +/* Handler for the optional provisioning endpoint registered by the application. + * The data format can be chosen by applications. Here, we are using plain ascii text. + * Applications can choose to use other formats like protobuf, JSON, XML, etc. + * Note that memory for the response buffer must be allocated using heap as this buffer + * gets freed by the protocomm layer once it has been sent by the transport layer. + */ +esp_err_t custom_prov_data_handler(uint32_t session_id, const uint8_t *inbuf, ssize_t inlen, + uint8_t **outbuf, ssize_t *outlen, void *priv_data) +{ + if (inbuf) { + ESP_LOGI(TAG, "Received data: %.*s", inlen, (char *)inbuf); + } + char response[] = "SUCCESS"; + *outbuf = (uint8_t *)strdup(response); + if (*outbuf == NULL) { + ESP_LOGE(TAG, "System out of memory"); + return ESP_ERR_NO_MEM; + } + *outlen = strlen(response) + 1; /* +1 for NULL terminating byte */ + + return ESP_OK; +} + +static void wifi_prov_print_qr(const char *name, const char *username, const char *pop, const char *transport) +{ + if (!name || !transport) { + ESP_LOGW(TAG, "Cannot generate QR code payload. Data missing."); + return; + } + char payload[150] = {0}; + if (pop) { +#if CONFIG_EXAMPLE_PROV_SECURITY_VERSION_1 + snprintf(payload, sizeof(payload), "{\"ver\":\"%s\",\"name\":\"%s\"" \ + ",\"pop\":\"%s\",\"transport\":\"%s\"}", + PROV_QR_VERSION, name, pop, transport); +#elif CONFIG_EXAMPLE_PROV_SECURITY_VERSION_2 + snprintf(payload, sizeof(payload), "{\"ver\":\"%s\",\"name\":\"%s\"" \ + ",\"username\":\"%s\",\"pop\":\"%s\",\"transport\":\"%s\"}", + PROV_QR_VERSION, name, username, pop, transport); +#endif + } else { + snprintf(payload, sizeof(payload), "{\"ver\":\"%s\",\"name\":\"%s\"" \ + ",\"transport\":\"%s\",\"network\":\"wifi\"}", + PROV_QR_VERSION, name, transport); + } + //TODO: Add the network protocol type to the QR code payload +#ifdef CONFIG_EXAMPLE_PROV_SHOW_QR + ESP_LOGI(TAG, "Scan this QR code from the provisioning application for Provisioning."); + esp_qrcode_config_t cfg = ESP_QRCODE_CONFIG_DEFAULT(); + esp_qrcode_generate(&cfg, payload); +#endif /* CONFIG_EXAMPLE_PROV_SHOW_QR */ + ESP_LOGI(TAG, "If QR code is not visible, copy paste the below URL in a browser.\n%s?data=%s", QRCODE_BASE_URL, payload); +} + +void app_main(void) +{ + /* Initialize NVS partition */ + esp_err_t ret = nvs_flash_init(); + if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { + /* NVS partition was truncated + * and needs to be erased */ + ESP_ERROR_CHECK(nvs_flash_erase()); + + /* Retry nvs_flash_init */ + ESP_ERROR_CHECK(nvs_flash_init()); + } + + /* Initialize TCP/IP */ + ESP_ERROR_CHECK(esp_netif_init()); + + /* Initialize the event loop */ + ESP_ERROR_CHECK(esp_event_loop_create_default()); + wifi_event_group = xEventGroupCreate(); + + /* Register our event handler for Wi-Fi, IP and Provisioning related events */ + ESP_ERROR_CHECK(esp_event_handler_register(NETWORK_PROV_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL)); +#ifdef CONFIG_EXAMPLE_PROV_TRANSPORT_BLE + ESP_ERROR_CHECK(esp_event_handler_register(PROTOCOMM_TRANSPORT_BLE_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL)); +#endif + ESP_ERROR_CHECK(esp_event_handler_register(PROTOCOMM_SECURITY_SESSION_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL)); + ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL)); + ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL)); + + /* Initialize Wi-Fi including netif with default config */ + esp_netif_create_default_wifi_sta(); +#ifdef CONFIG_EXAMPLE_PROV_TRANSPORT_SOFTAP + esp_netif_create_default_wifi_ap(); +#endif /* CONFIG_EXAMPLE_PROV_TRANSPORT_SOFTAP */ + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); + ESP_ERROR_CHECK(esp_wifi_init(&cfg)); + + /* Configuration for the provisioning manager */ + network_prov_mgr_config_t config = { + /* What is the Provisioning Scheme that we want ? + * network_prov_scheme_softap or network_prov_scheme_ble */ +#ifdef CONFIG_EXAMPLE_PROV_TRANSPORT_BLE + .scheme = network_prov_scheme_ble, +#endif /* CONFIG_EXAMPLE_PROV_TRANSPORT_BLE */ +#ifdef CONFIG_EXAMPLE_PROV_TRANSPORT_SOFTAP + .scheme = network_prov_scheme_softap, +#endif /* CONFIG_EXAMPLE_PROV_TRANSPORT_SOFTAP */ + + /* Any default scheme specific event handler that you would + * like to choose. Since our example application requires + * neither BT nor BLE, we can choose to release the associated + * memory once provisioning is complete, or not needed + * (in case when device is already provisioned). Choosing + * appropriate scheme specific event handler allows the manager + * to take care of this automatically. This can be set to + * NETWORK_PROV_EVENT_HANDLER_NONE when using network_prov_scheme_softap*/ +#ifdef CONFIG_EXAMPLE_PROV_TRANSPORT_BLE + .scheme_event_handler = NETWORK_PROV_SCHEME_BLE_EVENT_HANDLER_FREE_BTDM +#endif /* CONFIG_EXAMPLE_PROV_TRANSPORT_BLE */ +#ifdef CONFIG_EXAMPLE_PROV_TRANSPORT_SOFTAP + .scheme_event_handler = NETWORK_PROV_EVENT_HANDLER_NONE +#endif /* CONFIG_EXAMPLE_PROV_TRANSPORT_SOFTAP */ + }; + + /* Initialize provisioning manager with the + * configuration parameters set above */ + ESP_ERROR_CHECK(network_prov_mgr_init(config)); + + bool provisioned = false; +#ifdef CONFIG_EXAMPLE_RESET_PROVISIONED + network_prov_mgr_reset_wifi_provisioning(); +#else + /* Let's find out if the device is provisioned */ + ESP_ERROR_CHECK(network_prov_mgr_is_wifi_provisioned(&provisioned)); + +#endif + /* If device is not yet provisioned start provisioning service */ + if (!provisioned) { + ESP_LOGI(TAG, "Starting provisioning"); + + /* What is the Device Service Name that we want + * This translates to : + * - Wi-Fi SSID when scheme is network_prov_scheme_softap + * - device name when scheme is network_prov_scheme_ble + */ + char service_name[12]; + get_device_service_name(service_name, sizeof(service_name)); + +#ifdef CONFIG_EXAMPLE_PROV_SECURITY_VERSION_1 + /* What is the security level that we want (0, 1, 2): + * - NETWORK_PROV_SECURITY_0 is simply plain text communication. + * - NETWORK_PROV_SECURITY_1 is secure communication which consists of secure handshake + * using X25519 key exchange and proof of possession (pop) and AES-CTR + * for encryption/decryption of messages. + * - NETWORK_PROV_SECURITY_2 SRP6a based authentication and key exchange + * + AES-GCM encryption/decryption of messages + */ + network_prov_security_t security = NETWORK_PROV_SECURITY_1; + + /* Do we want a proof-of-possession (ignored if Security 0 is selected): + * - this should be a string with length > 0 + * - NULL if not used + */ + const char *pop = "abcd1234"; + + /* This is the structure for passing security parameters + * for the protocomm security 1. + */ + network_prov_security1_params_t *sec_params = pop; + + const char *username = NULL; + +#elif CONFIG_EXAMPLE_PROV_SECURITY_VERSION_2 + network_prov_security_t security = NETWORK_PROV_SECURITY_2; + /* The username must be the same one, which has been used in the generation of salt and verifier */ + +#if CONFIG_EXAMPLE_PROV_SEC2_DEV_MODE + /* This pop field represents the password that will be used to generate salt and verifier. + * The field is present here in order to generate the QR code containing password. + * In production this password field shall not be stored on the device */ + const char *username = EXAMPLE_PROV_SEC2_USERNAME; + const char *pop = EXAMPLE_PROV_SEC2_PWD; +#elif CONFIG_EXAMPLE_PROV_SEC2_PROD_MODE + /* The username and password shall not be embedded in the firmware, + * they should be provided to the user by other means. + * e.g. QR code sticker */ + const char *username = NULL; + const char *pop = NULL; +#endif + /* This is the structure for passing security parameters + * for the protocomm security 2. + * If dynamically allocated, sec2_params pointer and its content + * must be valid till NETWORK_PROV_END event is triggered. + */ + network_prov_security2_params_t sec2_params = {}; + + ESP_ERROR_CHECK(example_get_sec2_salt(&sec2_params.salt, &sec2_params.salt_len)); + ESP_ERROR_CHECK(example_get_sec2_verifier(&sec2_params.verifier, &sec2_params.verifier_len)); + + network_prov_security2_params_t *sec_params = &sec2_params; +#endif + /* What is the service key (could be NULL) + * This translates to : + * - Wi-Fi password when scheme is network_prov_scheme_softap + * (Minimum expected length: 8, maximum 64 for WPA2-PSK) + * - simply ignored when scheme is network_prov_scheme_ble + */ + const char *service_key = NULL; + +#ifdef CONFIG_EXAMPLE_PROV_TRANSPORT_BLE + /* This step is only useful when scheme is network_prov_scheme_ble. This will + * set a custom 128 bit UUID which will be included in the BLE advertisement + * and will correspond to the primary GATT service that provides provisioning + * endpoints as GATT characteristics. Each GATT characteristic will be + * formed using the primary service UUID as base, with different auto assigned + * 12th and 13th bytes (assume counting starts from 0th byte). The client side + * applications must identify the endpoints by reading the User Characteristic + * Description descriptor (0x2901) for each characteristic, which contains the + * endpoint name of the characteristic */ + uint8_t custom_service_uuid[] = { + /* LSB <--------------------------------------- + * ---------------------------------------> MSB */ + 0xb4, 0xdf, 0x5a, 0x1c, 0x3f, 0x6b, 0xf4, 0xbf, + 0xea, 0x4a, 0x82, 0x03, 0x04, 0x90, 0x1a, 0x02, + }; + + /* If your build fails with linker errors at this point, then you may have + * forgotten to enable the BT stack or BTDM BLE settings in the SDK (e.g. see + * the sdkconfig.defaults in the example project) */ + network_prov_scheme_ble_set_service_uuid(custom_service_uuid); +#endif /* CONFIG_EXAMPLE_PROV_TRANSPORT_BLE */ + + /* An optional endpoint that applications can create if they expect to + * get some additional custom data during provisioning workflow. + * The endpoint name can be anything of your choice. + * This call must be made before starting the provisioning. + */ + network_prov_mgr_endpoint_create("custom-data"); + + /* Do not stop and de-init provisioning even after success, + * so that we can restart it later. */ +#ifdef CONFIG_EXAMPLE_REPROVISIONING + network_prov_mgr_disable_auto_stop(1000); +#endif + /* Start provisioning service */ + ESP_ERROR_CHECK(network_prov_mgr_start_provisioning(security, (const void *) sec_params, service_name, service_key)); + + /* The handler for the optional endpoint created above. + * This call must be made after starting the provisioning, and only if the endpoint + * has already been created above. + */ + network_prov_mgr_endpoint_register("custom-data", custom_prov_data_handler, NULL); + + /* Uncomment the following to wait for the provisioning to finish and then release + * the resources of the manager. Since in this case de-initialization is triggered + * by the default event loop handler, we don't need to call the following */ + // network_prov_mgr_wait(); + // network_prov_mgr_deinit(); + /* Print QR code for provisioning */ +#ifdef CONFIG_EXAMPLE_PROV_TRANSPORT_BLE + wifi_prov_print_qr(service_name, username, pop, PROV_TRANSPORT_BLE); +#else /* CONFIG_EXAMPLE_PROV_TRANSPORT_SOFTAP */ + wifi_prov_print_qr(service_name, username, pop, PROV_TRANSPORT_SOFTAP); +#endif /* CONFIG_EXAMPLE_PROV_TRANSPORT_BLE */ + } else { + ESP_LOGI(TAG, "Already provisioned, starting Wi-Fi STA"); + + /* We don't need the manager as device is already provisioned, + * so let's release it's resources */ + network_prov_mgr_deinit(); + + /* Start Wi-Fi station */ + wifi_init_sta(); + } + + /* Wait for Wi-Fi connection */ + xEventGroupWaitBits(wifi_event_group, WIFI_CONNECTED_EVENT, true, true, portMAX_DELAY); + + /* Start main application now */ +#if CONFIG_EXAMPLE_REPROVISIONING + while (1) { + for (int i = 0; i < 10; i++) { + ESP_LOGI(TAG, "Hello World!"); + vTaskDelay(1000 / portTICK_PERIOD_MS); + } + + /* Resetting provisioning state machine to enable re-provisioning */ + network_prov_mgr_reset_wifi_sm_state_for_reprovision(); + + /* Wait for Wi-Fi connection */ + xEventGroupWaitBits(wifi_event_group, WIFI_CONNECTED_EVENT, true, true, portMAX_DELAY); + } +#else + while (1) { + ESP_LOGI(TAG, "Hello World!"); + vTaskDelay(1000 / portTICK_PERIOD_MS); + } +#endif + +} diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/examples/wifi_prov/main/idf_component.yml b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/examples/wifi_prov/main/idf_component.yml new file mode 100644 index 000000000..8f312bfa2 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/examples/wifi_prov/main/idf_component.yml @@ -0,0 +1,8 @@ +vesion: "1.0.0" +dependencies: + espressif/qrcode: + version: "^0.1.0" + espressif/network_provisioning: + version: "^1.0.0" + override_path: '../../../' + diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/examples/wifi_prov/partitions.csv b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/examples/wifi_prov/partitions.csv new file mode 100644 index 000000000..d4af98dfb --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/examples/wifi_prov/partitions.csv @@ -0,0 +1,5 @@ +# Name, Type, SubType, Offset, Size, Flags +# Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap +nvs, data, nvs, , 0x6000, +phy_init, data, phy, , 0x1000, +factory, app, factory, , 0x180000, diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/examples/wifi_prov/sdkconfig.defaults b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/examples/wifi_prov/sdkconfig.defaults new file mode 100644 index 000000000..9125e679d --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/examples/wifi_prov/sdkconfig.defaults @@ -0,0 +1,11 @@ +# Override some defaults so BT stack is enabled and +CONFIG_BT_ENABLED=y +CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y +CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=n +CONFIG_BTDM_CTRL_MODE_BTDM=n +CONFIG_BT_NIMBLE_ENABLED=y + +## For Bluedroid as binary is larger than default size +CONFIG_PARTITION_TABLE_CUSTOM=y +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" +CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/idf_component.yml b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/idf_component.yml new file mode 100644 index 000000000..c5bac5a88 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/idf_component.yml @@ -0,0 +1,9 @@ +dependencies: + idf: '>=5.1' +description: Network provisioning component for Wi-Fi or Thread devices +repository: git://github.com/espressif/idf-extra-components.git +repository_info: + commit_sha: 2eaf9375478f8867204fcd9ae1ffd43662288b98 + path: network_provisioning +url: https://github.com/espressif/idf-extra-components/tree/master/network_provisioning +version: 1.0.5 diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/include/network_provisioning/manager.h b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/include/network_provisioning/manager.h new file mode 100644 index 000000000..343283749 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/include/network_provisioning/manager.h @@ -0,0 +1,760 @@ +/* + * SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include + +#include "esp_event.h" +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI +#include "esp_wifi_types.h" +#endif +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD +#include "openthread/dataset.h" +#endif +#include "network_provisioning/network_config.h" + +#ifdef __cplusplus +extern "C" { +#endif + +ESP_EVENT_DECLARE_BASE(NETWORK_PROV_EVENT); + +/** + * @brief Events generated by manager + * + * These events are generated in order of declaration and, for the + * stretch of time between initialization and de-initialization of + * the manager, each event is signaled only once + */ +typedef enum { + /** + * Emitted when the manager is initialized + */ + NETWORK_PROV_INIT, + + /** + * Indicates that provisioning has started + */ + NETWORK_PROV_START, +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI + /** + * Emitted when Wi-Fi AP credentials are received via `protocomm` + * endpoint `network_config`. The event data in this case is a pointer + * to the corresponding `wifi_sta_config_t` structure + */ + NETWORK_PROV_WIFI_CRED_RECV, +#endif // CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD + /** + * Emitted when Thread Dataset is received via `protocomm` endpoint + * `network_config`, The event data in this case is a pointer to the + * corresponding `otOperationalDatasetTlvs` structure + */ + NETWORK_PROV_THREAD_DATASET_RECV, +#endif // CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI + /** + * Emitted when device fails to connect to the AP of which the + * credentials were received earlier on event `NETWORK_PROV_WIFI_CRED_RECV`. + * The event data in this case is a pointer to the disconnection + * reason code with type `network_prov_wifi_sta_fail_reason_t` + */ + NETWORK_PROV_WIFI_CRED_FAIL, +#endif // CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD + /** + * Emitted when device fails to connect to the Thread network of which + * dataset was received earlier on event `NETWORK_PROv_THREAD_DATASET_RECV`. + * The event data in this case is a pointer to the disconnection + * reason code with type `network_prov_thread_fail_reason_t` + */ + NETWORK_PROV_THREAD_DATASET_FAIL, +#endif // CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI + /** + * Emitted when device successfully connects to the AP of which the + * credentials were received earlier on event `NETWORK_PROV_WIFI_CRED_RECV` + */ + NETWORK_PROV_WIFI_CRED_SUCCESS, +#endif // CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD + /** + * Emitted when device successfully connects to the Thread etwork of + * which the dataset was received earlier on event + * `NETWORK_PROV_THREAD_DATASET_RECV` + */ + NETWORK_PROV_THREAD_DATASET_SUCCESS, +#endif // CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD + + /** + * Signals that provisioning service has stopped + */ + NETWORK_PROV_END, + + /** + * Signals that manager has been de-initialized + */ + NETWORK_PROV_DEINIT, +} network_prov_cb_event_t; + +typedef void (*network_prov_cb_func_t)(void *user_data, network_prov_cb_event_t event, void *event_data); + +/** + * @brief Event handler that is used by the manager while + * provisioning service is active + */ +typedef struct { + /** + * Callback function to be executed on provisioning events + */ + network_prov_cb_func_t event_cb; + + /** + * User context data to pass as parameter to callback function + */ + void *user_data; +} network_prov_event_handler_t; + +/** + * @brief Event handler can be set to none if not used + */ +#define NETWORK_PROV_EVENT_HANDLER_NONE { \ + .event_cb = NULL, \ + .user_data = NULL \ +} + +/** + * @brief Structure for specifying the provisioning scheme to be + * followed by the manager + * + * @note Ready to use schemes are available: + * - network_prov_scheme_ble : for provisioning over BLE transport + GATT server + * - network_prov_scheme_softap : for provisioning over SoftAP transport + HTTP server + * - network_prov_scheme_console : for provisioning over Serial UART transport + Console (for debugging) + */ +typedef struct network_prov_scheme { + /** + * Function which is to be called by the manager when it is to + * start the provisioning service associated with a protocomm instance + * and a scheme specific configuration + */ + esp_err_t (*prov_start) (protocomm_t *pc, void *config); + + /** + * Function which is to be called by the manager to stop the + * provisioning service previously associated with a protocomm instance + */ + esp_err_t (*prov_stop) (protocomm_t *pc); + + /** + * Function which is to be called by the manager to generate + * a new configuration for the provisioning service, that is + * to be passed to prov_start() + */ + void *(*new_config) (void); + + /** + * Function which is to be called by the manager to delete a + * configuration generated using new_config() + */ + void (*delete_config) (void *config); + + /** + * Function which is to be called by the manager to set the + * service name and key values in the configuration structure + */ + esp_err_t (*set_config_service) (void *config, const char *service_name, const char *service_key); + + /** + * Function which is to be called by the manager to set a protocomm endpoint + * with an identifying name and UUID in the configuration structure + */ + esp_err_t (*set_config_endpoint) (void *config, const char *endpoint_name, uint16_t uuid); + +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI + /** + * Sets mode of operation of Wi-Fi during provisioning + * This is set to : + * - WIFI_MODE_APSTA for SoftAP transport + * - WIFI_MODE_STA for BLE transport + */ + wifi_mode_t wifi_mode; +#endif // CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI +} network_prov_scheme_t; + +/** + * @brief Structure for specifying the manager configuration + */ +typedef struct { + /** + * Provisioning scheme to use. Following schemes are already available: + * - network_prov_scheme_ble : for provisioning over BLE transport + GATT server + * - network_prov_scheme_softap : for provisioning over SoftAP transport + HTTP server + mDNS (optional) + * - network_prov_scheme_console : for provisioning over Serial UART transport + Console (for debugging) + */ + network_prov_scheme_t scheme; + + /** + * Event handler required by the scheme for incorporating scheme specific + * behavior while provisioning manager is running. Various options may be + * provided by the scheme for setting this field. Use NETWORK_PROV_EVENT_HANDLER_NONE + * when not used. When using scheme network_prov_scheme_ble, the following + * options are available: + * - NETWORK_PROV_SCHEME_BLE_EVENT_HANDLER_FREE_BTDM + * - NETWORK_PROV_SCHEME_BLE_EVENT_HANDLER_FREE_BLE + * - NETWORK_PROV_SCHEME_BLE_EVENT_HANDLER_FREE_BT + */ + network_prov_event_handler_t scheme_event_handler; + + /** + * Event handler that can be set for the purpose of incorporating application + * specific behavior. Use NETWORK_PROV_EVENT_HANDLER_NONE when not used. + */ + network_prov_event_handler_t app_event_handler; +} network_prov_mgr_config_t; + +/** + * @brief Security modes supported by the Provisioning Manager. + * + * These are same as the security modes provided by protocomm + */ +typedef enum network_prov_security { +#ifdef CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_0 + /** + * No security (plain-text communication) + */ + NETWORK_PROV_SECURITY_0 = 0, +#endif +#ifdef CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_1 + /** + * This secure communication mode consists of + * X25519 key exchange + * + proof of possession (pop) based authentication + * + AES-CTR encryption + */ + NETWORK_PROV_SECURITY_1 = 1, +#endif +#ifdef CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_2 + /** + * This secure communication mode consists of + * SRP6a based authentication and key exchange + * + AES-GCM encryption/decryption + */ + NETWORK_PROV_SECURITY_2 = 2 +#endif +} network_prov_security_t; + +/** + * @brief Security 1 params structure + * This needs to be passed when using NETWORK_PROV_SECURITY_1 + */ +typedef const char network_prov_security1_params_t; + +/** + * @brief Security 2 params structure + * This needs to be passed when using NETWORK_PROV_SECURITY_2 + */ +typedef protocomm_security2_params_t network_prov_security2_params_t; + +/** + * @brief Initialize provisioning manager instance + * + * Configures the manager and allocates internal resources + * + * Configuration specifies the provisioning scheme (transport) + * and event handlers + * + * Event NETWORK_PROV_INIT is emitted right after initialization + * is complete + * + * @param[in] config Configuration structure + * + * @return + * - ESP_OK : Success + * - ESP_FAIL : Fail + */ +esp_err_t network_prov_mgr_init(network_prov_mgr_config_t config); + +/** + * @brief Stop provisioning (if running) and release + * resource used by the manager + * + * Event NETWORK_PROV_DEINIT is emitted right after de-initialization + * is finished + * + * If provisioning service is still active when this API is called, + * it first stops the service, hence emitting NETWORK_PROV_END, and + * then performs the de-initialization + */ +void network_prov_mgr_deinit(void); + +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI +/** + * @brief Checks if device is provisioned + * + * This checks if Wi-Fi credentials are present on the NVS + * + * The Wi-Fi credentials are assumed to be kept in the same + * NVS namespace as used by esp_wifi component + * + * If one were to call esp_wifi_set_config() directly instead + * of going through the provisioning process, this function will + * still yield true (i.e. device will be found to be provisioned) + * + * @note Calling network_prov_mgr_start_provisioning() automatically + * resets the provision state, irrespective of what the + * state was prior to making the call. + * + * @param[out] provisioned True if provisioned, else false + * + * @return + * - ESP_OK : Retrieved provision state successfully + * - ESP_FAIL : Wi-Fi not initialized + * - ESP_ERR_INVALID_ARG : Null argument supplied + */ +esp_err_t network_prov_mgr_is_wifi_provisioned(bool *provisioned); +#endif // CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI + +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD +/** + * @brief Checks if device is provisioned + * + * This checks if there is active dataset for Thread device + * + * @note Calling network_prov_mgr_start_provisioning() automatically + * resets the provision state, irrespective of what the + * state was prior to making the call. + * + * @param[out] provisioned True if provisioned, else false + * + * @return + * - ESP_OK : Retrieved provision state successfully + * - ESP_FAIL : Not initialized + * - ESP_ERR_INVALID_ARG : Null argument supplied + */ +esp_err_t network_prov_mgr_is_thread_provisioned(bool *provisioned); +#endif // CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD + +/** + * @brief Checks whether the provisioning state machine is idle + * + * @return True if state machine is idle, else false + */ +bool network_prov_mgr_is_sm_idle(void); + +/** + * @brief Start provisioning service + * + * This starts the provisioning service according to the scheme + * configured at the time of initialization. For scheme : + * - network_prov_scheme_ble : This starts protocomm_ble, which internally initializes + * BLE transport and starts GATT server for handling + * provisioning requests + * - network_prov_scheme_softap : This activates SoftAP mode of Wi-Fi and starts + * protocomm_httpd, which internally starts an HTTP + * server for handling provisioning requests (If mDNS is + * active it also starts advertising service with type + * _esp_wifi_prov._tcp) + * + * Event NETWORK_PROV_START is emitted right after provisioning starts without failure + * + * @note This API will start provisioning service even if device is found to be + * already provisioned, i.e. network_prov_mgr_is_wifi_provisioned() yields true + * + * @param[in] security Specify which protocomm security scheme to use : + * - NETWORK_PROV_SECURITY_0 : For no security + * - NETWORK_PROV_SECURITY_1 : x25519 secure handshake for session + * establishment followed by AES-CTR encryption of provisioning messages + * - NETWORK_PROV_SECURITY_2: SRP6a based authentication and key exchange + * followed by AES-GCM encryption/decryption of provisioning messages + * @param[in] network_prov_sec_params + * Pointer to security params (NULL if not needed). + * This is not needed for protocomm security 0 + * This pointer should hold the struct of type + * network_prov_security1_params_t for protocomm security 1 + * and network_prov_security2_params_t for protocomm security 2 respectively. + * This pointer and its contents should be valid till the provisioning service is + * running and has not been stopped or de-inited. + * @param[in] service_name Unique name of the service. This translates to: + * - Wi-Fi SSID when provisioning mode is softAP + * - Device name when provisioning mode is BLE + * @param[in] service_key Key required by client to access the service (NULL if not needed). + * This translates to: + * - Wi-Fi password when provisioning mode is softAP + * - ignored when provisioning mode is BLE + * + * @return + * - ESP_OK : Provisioning started successfully + * - ESP_FAIL : Failed to start provisioning service + * - ESP_ERR_INVALID_STATE : Provisioning manager not initialized or already started + */ +esp_err_t network_prov_mgr_start_provisioning(network_prov_security_t security, const void *network_prov_sec_params, const char *service_name, const char *service_key); + +/** + * @brief Stop provisioning service + * + * If provisioning service is active, this API will initiate a process to stop + * the service and return. Once the service actually stops, the event NETWORK_PROV_END + * will be emitted. + * + * If network_prov_mgr_deinit() is called without calling this API first, it will + * automatically stop the provisioning service and emit the NETWORK_PROV_END, followed + * by NETWORK_PROV_DEINIT, before returning. + * + * This API will generally be used along with network_prov_mgr_disable_auto_stop() + * in the scenario when the main application has registered its own endpoints, + * and wishes that the provisioning service is stopped only when some protocomm + * command from the client side application is received. + * + * Calling this API inside an endpoint handler, with sufficient cleanup_delay, + * will allow the response / acknowledgment to be sent successfully before the + * underlying protocomm service is stopped. + * + * Cleaup_delay is set when calling network_prov_mgr_disable_auto_stop(). + * If not specified, it defaults to 1000ms. + * + * For straightforward cases, using this API is usually not necessary as + * provisioning is stopped automatically once NETWORK_PROV_CRED_SUCCESS is emitted. + * Stopping is delayed (maximum 30 seconds) thus allowing the client side + * application to query for network state, i.e. after receiving the first query + * and sending `network state connected` response the service is stopped immediately. + */ +void network_prov_mgr_stop_provisioning(void); + +/** + * @brief Wait for provisioning service to finish + * + * Calling this API will block until provisioning service is stopped + * i.e. till event NETWORK_PROV_END is emitted. + * + * This will not block if provisioning is not started or not initialized. + */ +void network_prov_mgr_wait(void); + +/** + * @brief Disable auto stopping of provisioning service upon completion + * + * By default, once provisioning is complete, the provisioning service is automatically + * stopped, and all endpoints (along with those registered by main application) are + * deactivated. + * + * This API is useful in the case when main application wishes to close provisioning service + * only after it receives some protocomm command from the client side app. For example, after + * connecting to network, the device may want to connect to the cloud, and only once that is + * successfully, the device is said to be fully configured. But, then it is upto the main + * application to explicitly call network_prov_mgr_stop_provisioning() later when the device is + * fully configured and the provisioning service is no longer required. + * + * @note This must be called before executing network_prov_mgr_start_provisioning() + * + * @param[in] cleanup_delay Sets the delay after which the actual cleanup of transport related + * resources is done after a call to network_prov_mgr_stop_provisioning() + * returns. Minimum allowed value is 100ms. If not specified, this will + * default to 1000ms. + * + * @return + * - ESP_OK : Success + * - ESP_ERR_INVALID_STATE : Manager not initialized or + * provisioning service already started + */ +esp_err_t network_prov_mgr_disable_auto_stop(uint32_t cleanup_delay); + +/** + * @brief Set application version and capabilities in the JSON data returned by + * proto-ver endpoint + * + * This function can be called multiple times, to specify information about the various + * application specific services running on the device, identified by unique labels. + * + * The provisioning service itself registers an entry in the JSON data, by the label "prov", + * containing only provisioning service version and capabilities. Application services should + * use a label other than "prov" so as not to overwrite this. + * + * @note This must be called before executing network_prov_mgr_start_provisioning() + * + * @param[in] label String indicating the application name. + * + * @param[in] version String indicating the application version. + * There is no constraint on format. + * + * @param[in] capabilities Array of strings with capabilities. + * These could be used by the client side app to know + * the application registered endpoint capabilities + * + * @param[in] total_capabilities Size of capabilities array + * + * @return + * - ESP_OK : Success + * - ESP_ERR_INVALID_STATE : Manager not initialized or + * provisioning service already started + * - ESP_ERR_NO_MEM : Failed to allocate memory for version string + * - ESP_ERR_INVALID_ARG : Null argument + */ +esp_err_t network_prov_mgr_set_app_info(const char *label, const char *version, + const char **capabilities, size_t total_capabilities); + +/** + * @brief Create an additional endpoint and allocate internal resources for it + * + * This API is to be called by the application if it wants to create an additional + * endpoint. All additional endpoints will be assigned UUIDs starting from 0xFF54 + * and so on in the order of execution. + * + * protocomm handler for the created endpoint is to be registered later using + * network_prov_mgr_endpoint_register() after provisioning has started. + * + * @note This API can only be called BEFORE provisioning is started + * + * @note Additional endpoints can be used for configuring client provided + * parameters other than Wi-Fi credentials or Thread dataset, that are necessary + * for the main application and hence must be set prior to starting the application + * + * @note After session establishment, the additional endpoints must be targeted + * first by the client side application before sending Wi-Fi/Thread configuration, + * because once Wi-Fi/Thread configuration finishes the provisioning service is + * stopped and hence all endpoints are unregistered + * + * @param[in] ep_name unique name of the endpoint + * + * @return + * - ESP_OK : Success + * - ESP_FAIL : Failure + */ +esp_err_t network_prov_mgr_endpoint_create(const char *ep_name); + +/** + * @brief Register a handler for the previously created endpoint + * + * This API can be called by the application to register a protocomm handler + * to any endpoint that was created using network_prov_mgr_endpoint_create(). + * + * @note This API can only be called AFTER provisioning has started + * + * @note Additional endpoints can be used for configuring client provided + * parameters other than Wi-Fi credentials or Thread dataset, that are necessary + * for the main application and hence must be set prior to starting the application + * + * @note After session establishment, the additional endpoints must be targeted + * first by the client side application before sending Wi-Fi/Thread configuration, + * because once Wi-Fi/Thread configuration finishes the provisioning service is + * stopped and hence all endpoints are unregistered + * + * @param[in] ep_name Name of the endpoint + * @param[in] handler Endpoint handler function + * @param[in] user_ctx User data + * + * @return + * - ESP_OK : Success + * - ESP_FAIL : Failure + */ +esp_err_t network_prov_mgr_endpoint_register(const char *ep_name, + protocomm_req_handler_t handler, + void *user_ctx); + +/** + * @brief Unregister the handler for an endpoint + * + * This API can be called if the application wants to selectively + * unregister the handler of an endpoint while the provisioning + * is still in progress. + * + * All the endpoint handlers are unregistered automatically when + * the provisioning stops. + * + * @param[in] ep_name Name of the endpoint + */ +void network_prov_mgr_endpoint_unregister(const char *ep_name); + +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI +/** + * @brief Get state of Wi-Fi Station during provisioning + * + * @param[out] state Pointer to network_prov_wifi_sta_state_t + * variable to be filled + * + * @return + * - ESP_OK : Successfully retrieved Wi-Fi state + * - ESP_FAIL : Provisioning app not running + */ +esp_err_t network_prov_mgr_get_wifi_state(network_prov_wifi_sta_state_t *state); + +/** + * @brief Get reason code in case of Wi-Fi station + * disconnection during provisioning + * +* @param[out] reason Pointer to network_prov_wifi_sta_fail_reason_t +* variable to be filled + * + * @return + * - ESP_OK : Successfully retrieved Wi-Fi disconnect reason + * - ESP_FAIL : Provisioning app not running + */ +esp_err_t network_prov_mgr_get_wifi_disconnect_reason(network_prov_wifi_sta_fail_reason_t *reason); + +/** + * @brief Runs Wi-Fi as Station with the supplied configuration + * + * Configures the Wi-Fi station mode to connect to the AP with + * SSID and password specified in config structure and sets + * Wi-Fi to run as station. + * + * This is automatically called by provisioning service upon + * receiving new credentials. + * + * If credentials are to be supplied to the manager via a + * different mode other than through protocomm, then this + * API needs to be called. + * + * Event NETWORK_PROV_CRED_RECV is emitted after credentials have + * been applied and Wi-Fi station started + * + * @param[in] wifi_cfg Pointer to Wi-Fi configuration structure + * + * @return + * - ESP_OK : Wi-Fi configured and started successfully + * - ESP_FAIL : Failed to set configuration + */ +esp_err_t network_prov_mgr_configure_wifi_sta(wifi_config_t *wifi_cfg); + +/** + * @brief Reset Wi-Fi provisioning config + * + * Calling this API will restore WiFi stack persistent settings to default values. + * + * @return + * - ESP_OK : Reset provisioning config successfully + * - ESP_FAIL : Failed to reset provisioning config + */ +esp_err_t network_prov_mgr_reset_wifi_provisioning(void); + +/** + * @brief Reset internal state machine and clear provisioned credentials. + * + * This API should be used to restart provisioning ONLY in the case + * of provisioning failures without rebooting the device. + * + * @return + * - ESP_OK : Reset provisioning state machine successfully + * - ESP_FAIL : Failed to reset provisioning state machine + * - ESP_ERR_INVALID_STATE : Manager not initialized + */ +esp_err_t network_prov_mgr_reset_wifi_sm_state_on_failure(void); + +/** + * @brief Reset internal state machine and clear provisioned credentials. + * + * This API can be used to restart provisioning ONLY in case the device is + * to be provisioned again for new credentials after a previous successful + * provisioning without rebooting the device. + * + * @note This API can be used only if provisioning auto-stop has been + * disabled using network_prov_mgr_disable_auto_stop() + * + * @return + * - ESP_OK : Reset provisioning state machine successfully + * - ESP_FAIL : Failed to reset provisioning state machine + * - ESP_ERR_INVALID_STATE : Manager not initialized + */ +esp_err_t network_prov_mgr_reset_wifi_sm_state_for_reprovision(void); +#endif // CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI + +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD +/** + * @brief Reset Thread provisioning config + * + * Calling this API will restore Thread stack persistent settings to default values. + * + * @return + * - ESP_OK : Reset provisioning config successfully + * - ESP_FAIL : Failed to reset provisioning config + */ +esp_err_t network_prov_mgr_reset_thread_provisioning(void); + +/** + * @brief Get state of Thread during provisioning + * + * @param[out] state Pointer to network_prov_thread_state_t + * variable to be filled + * + * @return + * - ESP_OK : Successfully retrieved Thread state + * - ESP_FAIL : Provisioning app not running + */ +esp_err_t network_prov_mgr_get_thread_state(network_prov_thread_state_t *state); + +/** + * @brief Get reason code in case of thread detached during provisioning + * +* @param[out] reason Pointer to network_prov_thread_fail_reason_t +* variable to be filled + * + * @return + * - ESP_OK : Successfully retrieved thread detached reason + * - ESP_FAIL : Provisioning app not running + */ +esp_err_t network_prov_mgr_get_thread_detached_reason(network_prov_thread_fail_reason_t *reason); + +/** + * @brief Runs Thread with the supplied configuration + * + * Configures the Thread Dataset so that the device can be attached + * to a specific Thread network + * + * This is automatically called by provisioning service upon + * receiving new Thread dataset. + * + * If the dataset is to be supplied to the manager via a + * different mode other than through protocomm, then this + * API needs to be called. + * + * Event THREAD_PROV_CRED_RECV is emitted after credentials have + * been applied and Thread started + * + * @param[in] thread_dataset Pointer to Dataset Tlvs structure + * + * @return + * - ESP_OK : Thread dataset configured and started successfully + * - ESP_FAIL : Failed to set configuration + */ +esp_err_t network_prov_mgr_configure_thread_dataset(otOperationalDatasetTlvs *thread_dataset); + +/** + * @brief Reset internal state machine and clear provisioned credentials. + * + * This API should be used to restart provisioning ONLY in the case + * of provisioning failures without rebooting the device. + * + * @return + * - ESP_OK : Reset provisioning state machine successfully + * - ESP_FAIL : Failed to reset provisioning state machine + * - ESP_ERR_INVALID_STATE : Manager not initialized + */ +esp_err_t network_prov_mgr_reset_thread_sm_state_on_failure(void); + +/** + * @brief Reset internal state machine and clear provisioned credentials. + * + * This API can be used to restart provisioning ONLY in case the device is + * to be provisioned again for new credentials after a previous successful + * provisioning without rebooting the device. + * + * @note This API can be used only if provisioning auto-stop has been + * disabled using network_prov_mgr_disable_auto_stop() + * + * @return + * - ESP_OK : Reset provisioning state machine successfully + * - ESP_FAIL : Failed to reset provisioning state machine + * - ESP_ERR_INVALID_STATE : Manager not initialized + */ +esp_err_t network_prov_mgr_reset_thread_sm_state_for_reprovision(void); + +#endif // CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD + + +#ifdef __cplusplus +} +#endif diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/include/network_provisioning/network_config.h b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/include/network_provisioning/network_config.h new file mode 100644 index 000000000..d46915127 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/include/network_provisioning/network_config.h @@ -0,0 +1,206 @@ +/* + * SPDX-FileCopyrightText: 2018-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _NETWORK_PROV_CONFIG_H_ +#define _NETWORK_PROV_CONFIG_H_ + +#include "esp_netif_ip_addr.h" +#include "esp_err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI +/** + * @brief WiFi STA status for conveying back to the provisioning master + */ +typedef enum { + NETWORK_PROV_WIFI_STA_CONNECTING, + NETWORK_PROV_WIFI_STA_CONNECTED, + NETWORK_PROV_WIFI_STA_DISCONNECTED +} network_prov_wifi_sta_state_t; + +/** + * @brief WiFi STA connection fail reason + */ +typedef enum { + NETWORK_PROV_WIFI_STA_AUTH_ERROR, + NETWORK_PROV_WIFI_STA_AP_NOT_FOUND +} network_prov_wifi_sta_fail_reason_t; + +/** + * @brief WiFi STA connected status information + */ +typedef struct { + /** + * IP Address received by station + */ + char ip_addr[IP4ADDR_STRLEN_MAX]; + + char bssid[6]; /*!< BSSID of the AP to which connection was estalished */ + char ssid[33]; /*!< SSID of the to which connection was estalished */ + uint8_t channel; /*!< Channel of the AP */ + uint8_t auth_mode; /*!< Authorization mode of the AP */ +} network_prov_wifi_sta_conn_info_t; + +/** + * @brief WiFi status data to be sent in response to `get_status` request from master + */ +typedef struct { + network_prov_wifi_sta_state_t wifi_state; /*!< WiFi state of the station */ + union { + /** + * Reason for disconnection (valid only when `wifi_state` is `WIFI_STATION_DISCONNECTED`) + */ + network_prov_wifi_sta_fail_reason_t fail_reason; + + /** + * Connection information (valid only when `wifi_state` is `WIFI_STATION_CONNECTED`) + */ + network_prov_wifi_sta_conn_info_t conn_info; + }; +} network_prov_config_get_wifi_data_t; + +/** + * @brief WiFi config data received by slave during `set_config` request from master + */ +typedef struct { + char ssid[33]; /*!< SSID of the AP to which the slave is to be connected */ + char password[64]; /*!< Password of the AP */ + char bssid[6]; /*!< BSSID of the AP */ + uint8_t channel; /*!< Channel of the AP */ +} network_prov_config_set_wifi_data_t; +#endif // CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI + +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD +/** + * @brief Thread status for conveying back to the provisioning master + */ +typedef enum { + NETWORK_PROV_THREAD_ATTACHING, + NETWORK_PROV_THREAD_ATTACHED, + NETWORK_PROV_THREAD_DETACHED, +} network_prov_thread_state_t; + +/** + * @brief Thread attaching fail reason + */ +typedef enum { + NETWORK_PROV_THREAD_DATASET_INVALID, + NETWORK_PROV_THREAD_NETWORK_NOT_FOUND, +} network_prov_thread_fail_reason_t; + +/** + * @brief Thread attached status information + */ +typedef struct { + uint32_t pan_id; /*!< PAN ID */ + uint16_t channel; /*!< Channel */ + char name[17]; /*!< Network Name */ + uint8_t ext_pan_id[8]; /*!< Extended PAN ID */ +} network_prov_thread_conn_info_t; + +/** + * @brief Thread status data to be sent in response to `get_status` request from master + */ +typedef struct { + network_prov_thread_state_t thread_state; + union { + /** + * Reason for disconnection (valid only when `thread_state` is `THREAD_DETACHED`) + */ + network_prov_thread_fail_reason_t fail_reason; + + /** + * Connection information (valid only when `thread_state` is `THREAD_ATTACHED`) + */ + network_prov_thread_conn_info_t conn_info; + }; +} network_prov_config_get_thread_data_t; + +/** + * @brief Thread config data received by slave during `set_config` request from master + */ +typedef struct { + uint8_t dataset[254]; + uint8_t length; +} network_prov_config_set_thread_data_t; +#endif // CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD + +/** + * @brief Type of context data passed to each get/set/apply handler + * function set in `network_prov_config_handlers` structure. + * + * This is passed as an opaque pointer, thereby allowing it be defined + * later in application code as per requirements. + */ +typedef struct network_prov_ctx network_prov_ctx_t; + +/** + * @brief Internal handlers for receiving and responding to protocomm + * requests from master + * + * This is to be passed as priv_data for protocomm request handler + * (refer to `network_prov_config_data_handler()`) when calling `protocomm_add_endpoint()`. + */ +typedef struct network_prov_config_handlers { +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI + /** + * Handler function called when connection status + * of the slave (in WiFi station mode) is requested + */ + esp_err_t (*wifi_get_status_handler)(network_prov_config_get_wifi_data_t *resp_data, + network_prov_ctx_t **ctx); + + /** + * Handler function called when WiFi connection configuration + * (eg. AP SSID, password, etc.) of the slave (in WiFi station mode) + * is to be set to user provided values + */ + esp_err_t (*wifi_set_config_handler)(const network_prov_config_set_wifi_data_t *req_data, + network_prov_ctx_t **ctx); + + /** + * Handler function for applying the configuration that was set in + * `set_config_handler`. After applying the station may get connected to + * the AP or may fail to connect. The slave must be ready to convey the + * updated connection status information when `get_status_handler` is + * invoked again by the master. + */ + esp_err_t (*wifi_apply_config_handler)(network_prov_ctx_t **ctx); +#endif // CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI + +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD + esp_err_t (*thread_get_status_handler)(network_prov_config_get_thread_data_t *resp_data, + network_prov_ctx_t **ctx); + + esp_err_t (*thread_set_config_handler)(const network_prov_config_set_thread_data_t *req_data, + network_prov_ctx_t **ctx); + + esp_err_t (*thread_apply_config_handler)(network_prov_ctx_t **ctx); +#endif // CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD + + /** + * Context pointer to be passed to above handler functions upon invocation + */ + network_prov_ctx_t *ctx; +} network_prov_config_handlers_t; + +/** + * @brief Handler for receiving and responding to requests from master + * + * This is to be registered as the `network_config` endpoint handler + * (protocomm `protocomm_req_handler_t`) using `protocomm_add_endpoint()` + */ +esp_err_t network_prov_config_data_handler(uint32_t session_id, const uint8_t *inbuf, ssize_t inlen, + uint8_t **outbuf, ssize_t *outlen, void *priv_data); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/include/network_provisioning/network_scan.h b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/include/network_provisioning/network_scan.h new file mode 100644 index 000000000..709311be9 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/include/network_provisioning/network_scan.h @@ -0,0 +1,193 @@ +/* + * SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _PROV_NETWORK_SCAN_H_ +#define _PROV_NETWORK_SCAN_H_ + +#ifdef __cplusplus +extern "C" { +#endif +#include +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI +#include + +#define WIFI_SSID_LEN sizeof(((wifi_ap_record_t *)0)->ssid) +#define WIFI_BSSID_LEN sizeof(((wifi_ap_record_t *)0)->bssid) +#endif // CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI + +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD +#include +#include +#endif // CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD + +/** + * @brief Type of context data passed to each get/set/apply handler + * function set in `network_prov_scan_handlers` structure. + * + * This is passed as an opaque pointer, thereby allowing it be defined + * later in application code as per requirements. + */ +typedef struct network_prov_scan_ctx network_prov_scan_ctx_t; + +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI +/** + * @brief Structure of entries in the scan results list + */ +typedef struct { + /** + * SSID of Wi-Fi AP + */ + char ssid[WIFI_SSID_LEN]; + + /** + * BSSID of Wi-Fi AP + */ + char bssid[WIFI_BSSID_LEN]; + + /** + * Wi-Fi channel number + */ + uint8_t channel; + + /** + * Signal strength + */ + int rssi; + + /** + * Wi-Fi security mode + */ + uint8_t auth; +} network_prov_scan_wifi_result_t; +#endif // CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI + +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD +typedef struct { + uint16_t pan_id; + uint8_t ext_pan_id[OT_EXT_ADDRESS_SIZE]; + char network_name[OT_NETWORK_NAME_MAX_SIZE + 1]; + uint16_t channel; + uint8_t ext_addr[OT_EXT_ADDRESS_SIZE]; + int8_t rssi; + uint8_t lqi; +} network_prov_scan_thread_result_t; +#endif // CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD + +/** + * @brief Internal handlers for receiving and responding to protocomm + * requests from client + * + * This is to be passed as priv_data for protocomm request handler + * (refer to `network_prov_scan_handler()`) when calling `protocomm_add_endpoint()`. + */ +typedef struct network_prov_scan_handlers { +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI + /** + * Handler function called when scan start command is received + * with various scan parameters : + * + * blocking (input) - If true, the function should return only + * when the scanning is finished + * + * passive (input) - If true, scan is to be started in passive + * mode (this may be slower) instead of active mode + * + * group_channels (input) - This specifies whether to scan + * all channels in one go (when zero) or perform scanning of + * channels in groups, with 120ms delay between scanning of + * consecutive groups, and the value of this parameter sets the + * number of channels in each group. This is useful when transport + * mode is SoftAP, where scanning all channels in one go may not + * give the Wi-Fi driver enough time to send out beacons, and + * hence may cause disconnection with any connected stations. + * When scanning in groups, the manager will wait for atleast + * 120ms after completing scan on a group of channels, and thus + * allow the driver to send out the beacons. For example, given + * that the total number of Wi-Fi channels is 14, then setting + * group_channels to 4, will create 5 groups, with each group + * having 3 channels, except the last one which will have + * 14 % 3 = 2 channels. So, when scan is started, the first 3 + * channels will be scanned, followed by a 120ms delay, and then + * the next 3 channels, and so on, until all the 14 channels have + * been scanned. One may need to adjust this parameter as having + * only few channels in a group may slow down the overall scan + * time, while having too many may again cause disconnection. + * Usually a value of 4 should work for most cases. Note that + * for any other mode of transport, e.g. BLE, this can be safely + * set to 0, and hence achieve the fastest overall scanning time. + * + * period_ms (input) - Scan parameter specifying how long to + * wait on each channel (in milli-seconds) + */ + esp_err_t (*wifi_scan_start)(bool blocking, bool passive, + uint8_t group_channels, uint32_t period_ms, + network_prov_scan_ctx_t **ctx); + + /** + * Handler function called when scan status is requested. Status + * is given the parameters : + * + * scan_finished (output) - When scan has finished this returns true + * + * result_count (output) - This gives the total number of results + * obtained till now. If scan is yet happening this number will + * keep on updating + */ + esp_err_t (*wifi_scan_status)(bool *scan_finished, + uint16_t *result_count, + network_prov_scan_ctx_t **ctx); + + /** + * Handler function called when scan result is requested. Parameters : + * + * scan_result - For fetching scan results. This can be called even + * if scan is still on going + * + * start_index (input) - Starting index from where to fetch the + * entries from the results list + * + * count (input) - Number of entries to fetch from the starting index + * + * entries (output) - List of entries returned. Each entry consists + * of ssid, channel and rssi information + */ + esp_err_t (*wifi_scan_result)(uint16_t result_index, + network_prov_scan_wifi_result_t *result, + network_prov_scan_ctx_t **ctx); +#endif // CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI + +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD + esp_err_t (*thread_scan_start)(bool blocking, uint32_t channel_mask, network_prov_scan_ctx_t **ctx); + + esp_err_t (*thread_scan_status)(bool *scan_finished, + uint16_t *result_count, + network_prov_scan_ctx_t **ctx); + + esp_err_t (*thread_scan_result)(uint16_t result_index, + network_prov_scan_thread_result_t *result, + network_prov_scan_ctx_t **ctx); +#endif // CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD + + /** + * Context pointer to be passed to above handler functions upon invocation + */ + network_prov_scan_ctx_t *ctx; +} network_prov_scan_handlers_t; + +/** + * @brief Handler for sending on demand Wi-Fi scan results + * + * This is to be registered as the `prov-scan` endpoint handler + * (protocomm `protocomm_req_handler_t`) using `protocomm_add_endpoint()` + */ +esp_err_t network_prov_scan_handler(uint32_t session_id, const uint8_t *inbuf, ssize_t inlen, + uint8_t **outbuf, ssize_t *outlen, void *priv_data); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/include/network_provisioning/scheme_ble.h b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/include/network_provisioning/scheme_ble.h new file mode 100644 index 000000000..b9d92f381 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/include/network_provisioning/scheme_ble.h @@ -0,0 +1,97 @@ +/* + * SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include + +#include "network_provisioning/manager.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Scheme that can be used by manager for provisioning + * over BLE transport with GATT server + */ +extern const network_prov_scheme_t network_prov_scheme_ble; + +/* This scheme specific event handler is to be used when application + * doesn't require BT and BLE after provisioning has finished */ +#define NETWORK_PROV_SCHEME_BLE_EVENT_HANDLER_FREE_BTDM { \ + .event_cb = network_prov_scheme_ble_event_cb_free_btdm, \ + .user_data = NULL \ +} + +/* This scheme specific event handler is to be used when application + * doesn't require BLE to be active after provisioning has finished */ +#define NETWORK_PROV_SCHEME_BLE_EVENT_HANDLER_FREE_BLE { \ + .event_cb = network_prov_scheme_ble_event_cb_free_ble, \ + .user_data = NULL \ +} + +/* This scheme specific event handler is to be used when application + * doesn't require BT to be active after provisioning has finished */ +#define NETWORK_PROV_SCHEME_BLE_EVENT_HANDLER_FREE_BT { \ + .event_cb = network_prov_scheme_ble_event_cb_free_bt, \ + .user_data = NULL \ +} + +void network_prov_scheme_ble_event_cb_free_btdm(void *user_data, network_prov_cb_event_t event, void *event_data); +void network_prov_scheme_ble_event_cb_free_ble (void *user_data, network_prov_cb_event_t event, void *event_data); +void network_prov_scheme_ble_event_cb_free_bt (void *user_data, network_prov_cb_event_t event, void *event_data); + +/** + * @brief Set the 128 bit GATT service UUID used for provisioning + * + * This API is used to override the default 128 bit provisioning + * service UUID, which is 0000ffff-0000-1000-8000-00805f9b34fb. + * + * This must be called before starting provisioning, i.e. before + * making a call to network_prov_mgr_start_provisioning(), otherwise + * the default UUID will be used. + * + * @note The data being pointed to by the argument must be valid + * atleast till provisioning is started. Upon start, the + * manager will store an internal copy of this UUID, and + * this data can be freed or invalidated afterwords. + * + * @param[in] uuid128 A custom 128 bit UUID + * + * @return + * - ESP_OK : Success + * - ESP_ERR_INVALID_ARG : Null argument + */ +esp_err_t network_prov_scheme_ble_set_service_uuid(uint8_t *uuid128); + +/** + * @brief Set manufacturer specific data in scan response + * + * This must be called before starting provisioning, i.e. before + * making a call to network_prov_mgr_start_provisioning(). + * + * @note It is important to understand that length of custom manufacturer + * data should be within limits. The manufacturer data goes into scan + * response along with BLE device name. By default, BLE device name + * length is of 11 Bytes, however it can vary as per application use + * case. So, one has to honour the scan response data size limits i.e. + * (mfg_data_len + 2) < 31 - (device_name_length + 2 ). If the + * mfg_data length exceeds this limit, the length will be truncated. + * + * @param[in] mfg_data Custom manufacturer data + * @param[in] mfg_data_len Manufacturer data length + * + * @return + * - ESP_OK : Success + * - ESP_ERR_INVALID_ARG : Null argument + */ +esp_err_t network_prov_scheme_ble_set_mfg_data(uint8_t *mfg_data, ssize_t mfg_data_len); + +#ifdef __cplusplus +} +#endif diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/include/network_provisioning/scheme_console.h b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/include/network_provisioning/scheme_console.h new file mode 100644 index 000000000..2f8e38982 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/include/network_provisioning/scheme_console.h @@ -0,0 +1,26 @@ +/* + * SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include + +#include "network_provisioning/manager.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Scheme that can be used by manager for provisioning + * over console (Serial UART) + */ +extern const network_prov_scheme_t network_prov_scheme_console; + +#ifdef __cplusplus +} +#endif diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/include/network_provisioning/scheme_softap.h b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/include/network_provisioning/scheme_softap.h new file mode 100644 index 000000000..1d905075e --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/include/network_provisioning/scheme_softap.h @@ -0,0 +1,39 @@ +/* + * SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include + +#include "network_provisioning/manager.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Scheme that can be used by manager for provisioning + * over SoftAP transport with HTTP server + */ +extern const network_prov_scheme_t network_prov_scheme_softap; + +/** + * + * @brief Provide HTTPD Server handle externally. + * + * Useful in cases wherein applications need the webserver for some + * different operations, and do not want the wifi provisioning component + * to start/stop a new instance. + * + * @note This API should be called before network_prov_mgr_start_provisioning() + * + * @param[in] handle Handle to HTTPD server instance + */ +void network_prov_scheme_softap_set_httpd_handle(void *handle); +#ifdef __cplusplus +} +#endif diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/proto-c/network_config.pb-c.c b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/proto-c/network_config.pb-c.c new file mode 100644 index 000000000..9bc098d3f --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/proto-c/network_config.pb-c.c @@ -0,0 +1,1332 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ +/* Generated from: network_config.proto */ + +/* Do not generate deprecated warnings for self */ +#ifndef PROTOBUF_C__NO_DEPRECATED +#define PROTOBUF_C__NO_DEPRECATED +#endif + +#include "network_config.pb-c.h" +void cmd_get_wifi_status__init + (CmdGetWifiStatus *message) +{ + static const CmdGetWifiStatus init_value = CMD_GET_WIFI_STATUS__INIT; + *message = init_value; +} +size_t cmd_get_wifi_status__get_packed_size + (const CmdGetWifiStatus *message) +{ + assert(message->base.descriptor == &cmd_get_wifi_status__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t cmd_get_wifi_status__pack + (const CmdGetWifiStatus *message, + uint8_t *out) +{ + assert(message->base.descriptor == &cmd_get_wifi_status__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t cmd_get_wifi_status__pack_to_buffer + (const CmdGetWifiStatus *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &cmd_get_wifi_status__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +CmdGetWifiStatus * + cmd_get_wifi_status__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (CmdGetWifiStatus *) + protobuf_c_message_unpack (&cmd_get_wifi_status__descriptor, + allocator, len, data); +} +void cmd_get_wifi_status__free_unpacked + (CmdGetWifiStatus *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &cmd_get_wifi_status__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void resp_get_wifi_status__init + (RespGetWifiStatus *message) +{ + static const RespGetWifiStatus init_value = RESP_GET_WIFI_STATUS__INIT; + *message = init_value; +} +size_t resp_get_wifi_status__get_packed_size + (const RespGetWifiStatus *message) +{ + assert(message->base.descriptor == &resp_get_wifi_status__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t resp_get_wifi_status__pack + (const RespGetWifiStatus *message, + uint8_t *out) +{ + assert(message->base.descriptor == &resp_get_wifi_status__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t resp_get_wifi_status__pack_to_buffer + (const RespGetWifiStatus *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &resp_get_wifi_status__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +RespGetWifiStatus * + resp_get_wifi_status__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (RespGetWifiStatus *) + protobuf_c_message_unpack (&resp_get_wifi_status__descriptor, + allocator, len, data); +} +void resp_get_wifi_status__free_unpacked + (RespGetWifiStatus *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &resp_get_wifi_status__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void cmd_get_thread_status__init + (CmdGetThreadStatus *message) +{ + static const CmdGetThreadStatus init_value = CMD_GET_THREAD_STATUS__INIT; + *message = init_value; +} +size_t cmd_get_thread_status__get_packed_size + (const CmdGetThreadStatus *message) +{ + assert(message->base.descriptor == &cmd_get_thread_status__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t cmd_get_thread_status__pack + (const CmdGetThreadStatus *message, + uint8_t *out) +{ + assert(message->base.descriptor == &cmd_get_thread_status__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t cmd_get_thread_status__pack_to_buffer + (const CmdGetThreadStatus *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &cmd_get_thread_status__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +CmdGetThreadStatus * + cmd_get_thread_status__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (CmdGetThreadStatus *) + protobuf_c_message_unpack (&cmd_get_thread_status__descriptor, + allocator, len, data); +} +void cmd_get_thread_status__free_unpacked + (CmdGetThreadStatus *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &cmd_get_thread_status__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void resp_get_thread_status__init + (RespGetThreadStatus *message) +{ + static const RespGetThreadStatus init_value = RESP_GET_THREAD_STATUS__INIT; + *message = init_value; +} +size_t resp_get_thread_status__get_packed_size + (const RespGetThreadStatus *message) +{ + assert(message->base.descriptor == &resp_get_thread_status__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t resp_get_thread_status__pack + (const RespGetThreadStatus *message, + uint8_t *out) +{ + assert(message->base.descriptor == &resp_get_thread_status__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t resp_get_thread_status__pack_to_buffer + (const RespGetThreadStatus *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &resp_get_thread_status__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +RespGetThreadStatus * + resp_get_thread_status__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (RespGetThreadStatus *) + protobuf_c_message_unpack (&resp_get_thread_status__descriptor, + allocator, len, data); +} +void resp_get_thread_status__free_unpacked + (RespGetThreadStatus *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &resp_get_thread_status__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void cmd_set_wifi_config__init + (CmdSetWifiConfig *message) +{ + static const CmdSetWifiConfig init_value = CMD_SET_WIFI_CONFIG__INIT; + *message = init_value; +} +size_t cmd_set_wifi_config__get_packed_size + (const CmdSetWifiConfig *message) +{ + assert(message->base.descriptor == &cmd_set_wifi_config__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t cmd_set_wifi_config__pack + (const CmdSetWifiConfig *message, + uint8_t *out) +{ + assert(message->base.descriptor == &cmd_set_wifi_config__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t cmd_set_wifi_config__pack_to_buffer + (const CmdSetWifiConfig *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &cmd_set_wifi_config__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +CmdSetWifiConfig * + cmd_set_wifi_config__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (CmdSetWifiConfig *) + protobuf_c_message_unpack (&cmd_set_wifi_config__descriptor, + allocator, len, data); +} +void cmd_set_wifi_config__free_unpacked + (CmdSetWifiConfig *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &cmd_set_wifi_config__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void cmd_set_thread_config__init + (CmdSetThreadConfig *message) +{ + static const CmdSetThreadConfig init_value = CMD_SET_THREAD_CONFIG__INIT; + *message = init_value; +} +size_t cmd_set_thread_config__get_packed_size + (const CmdSetThreadConfig *message) +{ + assert(message->base.descriptor == &cmd_set_thread_config__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t cmd_set_thread_config__pack + (const CmdSetThreadConfig *message, + uint8_t *out) +{ + assert(message->base.descriptor == &cmd_set_thread_config__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t cmd_set_thread_config__pack_to_buffer + (const CmdSetThreadConfig *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &cmd_set_thread_config__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +CmdSetThreadConfig * + cmd_set_thread_config__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (CmdSetThreadConfig *) + protobuf_c_message_unpack (&cmd_set_thread_config__descriptor, + allocator, len, data); +} +void cmd_set_thread_config__free_unpacked + (CmdSetThreadConfig *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &cmd_set_thread_config__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void resp_set_wifi_config__init + (RespSetWifiConfig *message) +{ + static const RespSetWifiConfig init_value = RESP_SET_WIFI_CONFIG__INIT; + *message = init_value; +} +size_t resp_set_wifi_config__get_packed_size + (const RespSetWifiConfig *message) +{ + assert(message->base.descriptor == &resp_set_wifi_config__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t resp_set_wifi_config__pack + (const RespSetWifiConfig *message, + uint8_t *out) +{ + assert(message->base.descriptor == &resp_set_wifi_config__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t resp_set_wifi_config__pack_to_buffer + (const RespSetWifiConfig *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &resp_set_wifi_config__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +RespSetWifiConfig * + resp_set_wifi_config__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (RespSetWifiConfig *) + protobuf_c_message_unpack (&resp_set_wifi_config__descriptor, + allocator, len, data); +} +void resp_set_wifi_config__free_unpacked + (RespSetWifiConfig *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &resp_set_wifi_config__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void resp_set_thread_config__init + (RespSetThreadConfig *message) +{ + static const RespSetThreadConfig init_value = RESP_SET_THREAD_CONFIG__INIT; + *message = init_value; +} +size_t resp_set_thread_config__get_packed_size + (const RespSetThreadConfig *message) +{ + assert(message->base.descriptor == &resp_set_thread_config__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t resp_set_thread_config__pack + (const RespSetThreadConfig *message, + uint8_t *out) +{ + assert(message->base.descriptor == &resp_set_thread_config__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t resp_set_thread_config__pack_to_buffer + (const RespSetThreadConfig *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &resp_set_thread_config__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +RespSetThreadConfig * + resp_set_thread_config__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (RespSetThreadConfig *) + protobuf_c_message_unpack (&resp_set_thread_config__descriptor, + allocator, len, data); +} +void resp_set_thread_config__free_unpacked + (RespSetThreadConfig *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &resp_set_thread_config__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void cmd_apply_wifi_config__init + (CmdApplyWifiConfig *message) +{ + static const CmdApplyWifiConfig init_value = CMD_APPLY_WIFI_CONFIG__INIT; + *message = init_value; +} +size_t cmd_apply_wifi_config__get_packed_size + (const CmdApplyWifiConfig *message) +{ + assert(message->base.descriptor == &cmd_apply_wifi_config__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t cmd_apply_wifi_config__pack + (const CmdApplyWifiConfig *message, + uint8_t *out) +{ + assert(message->base.descriptor == &cmd_apply_wifi_config__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t cmd_apply_wifi_config__pack_to_buffer + (const CmdApplyWifiConfig *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &cmd_apply_wifi_config__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +CmdApplyWifiConfig * + cmd_apply_wifi_config__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (CmdApplyWifiConfig *) + protobuf_c_message_unpack (&cmd_apply_wifi_config__descriptor, + allocator, len, data); +} +void cmd_apply_wifi_config__free_unpacked + (CmdApplyWifiConfig *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &cmd_apply_wifi_config__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void cmd_apply_thread_config__init + (CmdApplyThreadConfig *message) +{ + static const CmdApplyThreadConfig init_value = CMD_APPLY_THREAD_CONFIG__INIT; + *message = init_value; +} +size_t cmd_apply_thread_config__get_packed_size + (const CmdApplyThreadConfig *message) +{ + assert(message->base.descriptor == &cmd_apply_thread_config__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t cmd_apply_thread_config__pack + (const CmdApplyThreadConfig *message, + uint8_t *out) +{ + assert(message->base.descriptor == &cmd_apply_thread_config__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t cmd_apply_thread_config__pack_to_buffer + (const CmdApplyThreadConfig *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &cmd_apply_thread_config__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +CmdApplyThreadConfig * + cmd_apply_thread_config__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (CmdApplyThreadConfig *) + protobuf_c_message_unpack (&cmd_apply_thread_config__descriptor, + allocator, len, data); +} +void cmd_apply_thread_config__free_unpacked + (CmdApplyThreadConfig *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &cmd_apply_thread_config__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void resp_apply_wifi_config__init + (RespApplyWifiConfig *message) +{ + static const RespApplyWifiConfig init_value = RESP_APPLY_WIFI_CONFIG__INIT; + *message = init_value; +} +size_t resp_apply_wifi_config__get_packed_size + (const RespApplyWifiConfig *message) +{ + assert(message->base.descriptor == &resp_apply_wifi_config__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t resp_apply_wifi_config__pack + (const RespApplyWifiConfig *message, + uint8_t *out) +{ + assert(message->base.descriptor == &resp_apply_wifi_config__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t resp_apply_wifi_config__pack_to_buffer + (const RespApplyWifiConfig *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &resp_apply_wifi_config__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +RespApplyWifiConfig * + resp_apply_wifi_config__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (RespApplyWifiConfig *) + protobuf_c_message_unpack (&resp_apply_wifi_config__descriptor, + allocator, len, data); +} +void resp_apply_wifi_config__free_unpacked + (RespApplyWifiConfig *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &resp_apply_wifi_config__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void resp_apply_thread_config__init + (RespApplyThreadConfig *message) +{ + static const RespApplyThreadConfig init_value = RESP_APPLY_THREAD_CONFIG__INIT; + *message = init_value; +} +size_t resp_apply_thread_config__get_packed_size + (const RespApplyThreadConfig *message) +{ + assert(message->base.descriptor == &resp_apply_thread_config__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t resp_apply_thread_config__pack + (const RespApplyThreadConfig *message, + uint8_t *out) +{ + assert(message->base.descriptor == &resp_apply_thread_config__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t resp_apply_thread_config__pack_to_buffer + (const RespApplyThreadConfig *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &resp_apply_thread_config__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +RespApplyThreadConfig * + resp_apply_thread_config__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (RespApplyThreadConfig *) + protobuf_c_message_unpack (&resp_apply_thread_config__descriptor, + allocator, len, data); +} +void resp_apply_thread_config__free_unpacked + (RespApplyThreadConfig *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &resp_apply_thread_config__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void network_config_payload__init + (NetworkConfigPayload *message) +{ + static const NetworkConfigPayload init_value = NETWORK_CONFIG_PAYLOAD__INIT; + *message = init_value; +} +size_t network_config_payload__get_packed_size + (const NetworkConfigPayload *message) +{ + assert(message->base.descriptor == &network_config_payload__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t network_config_payload__pack + (const NetworkConfigPayload *message, + uint8_t *out) +{ + assert(message->base.descriptor == &network_config_payload__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t network_config_payload__pack_to_buffer + (const NetworkConfigPayload *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &network_config_payload__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +NetworkConfigPayload * + network_config_payload__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (NetworkConfigPayload *) + protobuf_c_message_unpack (&network_config_payload__descriptor, + allocator, len, data); +} +void network_config_payload__free_unpacked + (NetworkConfigPayload *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &network_config_payload__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +#define cmd_get_wifi_status__field_descriptors NULL +#define cmd_get_wifi_status__field_indices_by_name NULL +#define cmd_get_wifi_status__number_ranges NULL +const ProtobufCMessageDescriptor cmd_get_wifi_status__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "CmdGetWifiStatus", + "CmdGetWifiStatus", + "CmdGetWifiStatus", + "", + sizeof(CmdGetWifiStatus), + 0, + cmd_get_wifi_status__field_descriptors, + cmd_get_wifi_status__field_indices_by_name, + 0, cmd_get_wifi_status__number_ranges, + (ProtobufCMessageInit) cmd_get_wifi_status__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor resp_get_wifi_status__field_descriptors[4] = +{ + { + "status", + 1, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_ENUM, + 0, /* quantifier_offset */ + offsetof(RespGetWifiStatus, status), + &status__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "wifi_sta_state", + 2, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_ENUM, + 0, /* quantifier_offset */ + offsetof(RespGetWifiStatus, wifi_sta_state), + &wifi_station_state__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "wifi_fail_reason", + 10, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_ENUM, + offsetof(RespGetWifiStatus, state_case), + offsetof(RespGetWifiStatus, wifi_fail_reason), + &wifi_connect_failed_reason__descriptor, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "wifi_connected", + 11, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(RespGetWifiStatus, state_case), + offsetof(RespGetWifiStatus, wifi_connected), + &wifi_connected_state__descriptor, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned resp_get_wifi_status__field_indices_by_name[] = { + 0, /* field[0] = status */ + 3, /* field[3] = wifi_connected */ + 2, /* field[2] = wifi_fail_reason */ + 1, /* field[1] = wifi_sta_state */ +}; +static const ProtobufCIntRange resp_get_wifi_status__number_ranges[2 + 1] = +{ + { 1, 0 }, + { 10, 2 }, + { 0, 4 } +}; +const ProtobufCMessageDescriptor resp_get_wifi_status__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "RespGetWifiStatus", + "RespGetWifiStatus", + "RespGetWifiStatus", + "", + sizeof(RespGetWifiStatus), + 4, + resp_get_wifi_status__field_descriptors, + resp_get_wifi_status__field_indices_by_name, + 2, resp_get_wifi_status__number_ranges, + (ProtobufCMessageInit) resp_get_wifi_status__init, + NULL,NULL,NULL /* reserved[123] */ +}; +#define cmd_get_thread_status__field_descriptors NULL +#define cmd_get_thread_status__field_indices_by_name NULL +#define cmd_get_thread_status__number_ranges NULL +const ProtobufCMessageDescriptor cmd_get_thread_status__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "CmdGetThreadStatus", + "CmdGetThreadStatus", + "CmdGetThreadStatus", + "", + sizeof(CmdGetThreadStatus), + 0, + cmd_get_thread_status__field_descriptors, + cmd_get_thread_status__field_indices_by_name, + 0, cmd_get_thread_status__number_ranges, + (ProtobufCMessageInit) cmd_get_thread_status__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor resp_get_thread_status__field_descriptors[4] = +{ + { + "status", + 1, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_ENUM, + 0, /* quantifier_offset */ + offsetof(RespGetThreadStatus, status), + &status__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "thread_state", + 2, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_ENUM, + 0, /* quantifier_offset */ + offsetof(RespGetThreadStatus, thread_state), + &thread_network_state__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "thread_fail_reason", + 10, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_ENUM, + offsetof(RespGetThreadStatus, state_case), + offsetof(RespGetThreadStatus, thread_fail_reason), + &thread_attach_failed_reason__descriptor, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "thread_attached", + 11, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(RespGetThreadStatus, state_case), + offsetof(RespGetThreadStatus, thread_attached), + &thread_attach_state__descriptor, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned resp_get_thread_status__field_indices_by_name[] = { + 0, /* field[0] = status */ + 3, /* field[3] = thread_attached */ + 2, /* field[2] = thread_fail_reason */ + 1, /* field[1] = thread_state */ +}; +static const ProtobufCIntRange resp_get_thread_status__number_ranges[2 + 1] = +{ + { 1, 0 }, + { 10, 2 }, + { 0, 4 } +}; +const ProtobufCMessageDescriptor resp_get_thread_status__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "RespGetThreadStatus", + "RespGetThreadStatus", + "RespGetThreadStatus", + "", + sizeof(RespGetThreadStatus), + 4, + resp_get_thread_status__field_descriptors, + resp_get_thread_status__field_indices_by_name, + 2, resp_get_thread_status__number_ranges, + (ProtobufCMessageInit) resp_get_thread_status__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor cmd_set_wifi_config__field_descriptors[4] = +{ + { + "ssid", + 1, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_BYTES, + 0, /* quantifier_offset */ + offsetof(CmdSetWifiConfig, ssid), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "passphrase", + 2, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_BYTES, + 0, /* quantifier_offset */ + offsetof(CmdSetWifiConfig, passphrase), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "bssid", + 3, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_BYTES, + 0, /* quantifier_offset */ + offsetof(CmdSetWifiConfig, bssid), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "channel", + 4, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_INT32, + 0, /* quantifier_offset */ + offsetof(CmdSetWifiConfig, channel), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned cmd_set_wifi_config__field_indices_by_name[] = { + 2, /* field[2] = bssid */ + 3, /* field[3] = channel */ + 1, /* field[1] = passphrase */ + 0, /* field[0] = ssid */ +}; +static const ProtobufCIntRange cmd_set_wifi_config__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 4 } +}; +const ProtobufCMessageDescriptor cmd_set_wifi_config__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "CmdSetWifiConfig", + "CmdSetWifiConfig", + "CmdSetWifiConfig", + "", + sizeof(CmdSetWifiConfig), + 4, + cmd_set_wifi_config__field_descriptors, + cmd_set_wifi_config__field_indices_by_name, + 1, cmd_set_wifi_config__number_ranges, + (ProtobufCMessageInit) cmd_set_wifi_config__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor cmd_set_thread_config__field_descriptors[1] = +{ + { + "dataset", + 1, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_BYTES, + 0, /* quantifier_offset */ + offsetof(CmdSetThreadConfig, dataset), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned cmd_set_thread_config__field_indices_by_name[] = { + 0, /* field[0] = dataset */ +}; +static const ProtobufCIntRange cmd_set_thread_config__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 1 } +}; +const ProtobufCMessageDescriptor cmd_set_thread_config__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "CmdSetThreadConfig", + "CmdSetThreadConfig", + "CmdSetThreadConfig", + "", + sizeof(CmdSetThreadConfig), + 1, + cmd_set_thread_config__field_descriptors, + cmd_set_thread_config__field_indices_by_name, + 1, cmd_set_thread_config__number_ranges, + (ProtobufCMessageInit) cmd_set_thread_config__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor resp_set_wifi_config__field_descriptors[1] = +{ + { + "status", + 1, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_ENUM, + 0, /* quantifier_offset */ + offsetof(RespSetWifiConfig, status), + &status__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned resp_set_wifi_config__field_indices_by_name[] = { + 0, /* field[0] = status */ +}; +static const ProtobufCIntRange resp_set_wifi_config__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 1 } +}; +const ProtobufCMessageDescriptor resp_set_wifi_config__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "RespSetWifiConfig", + "RespSetWifiConfig", + "RespSetWifiConfig", + "", + sizeof(RespSetWifiConfig), + 1, + resp_set_wifi_config__field_descriptors, + resp_set_wifi_config__field_indices_by_name, + 1, resp_set_wifi_config__number_ranges, + (ProtobufCMessageInit) resp_set_wifi_config__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor resp_set_thread_config__field_descriptors[1] = +{ + { + "status", + 1, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_ENUM, + 0, /* quantifier_offset */ + offsetof(RespSetThreadConfig, status), + &status__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned resp_set_thread_config__field_indices_by_name[] = { + 0, /* field[0] = status */ +}; +static const ProtobufCIntRange resp_set_thread_config__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 1 } +}; +const ProtobufCMessageDescriptor resp_set_thread_config__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "RespSetThreadConfig", + "RespSetThreadConfig", + "RespSetThreadConfig", + "", + sizeof(RespSetThreadConfig), + 1, + resp_set_thread_config__field_descriptors, + resp_set_thread_config__field_indices_by_name, + 1, resp_set_thread_config__number_ranges, + (ProtobufCMessageInit) resp_set_thread_config__init, + NULL,NULL,NULL /* reserved[123] */ +}; +#define cmd_apply_wifi_config__field_descriptors NULL +#define cmd_apply_wifi_config__field_indices_by_name NULL +#define cmd_apply_wifi_config__number_ranges NULL +const ProtobufCMessageDescriptor cmd_apply_wifi_config__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "CmdApplyWifiConfig", + "CmdApplyWifiConfig", + "CmdApplyWifiConfig", + "", + sizeof(CmdApplyWifiConfig), + 0, + cmd_apply_wifi_config__field_descriptors, + cmd_apply_wifi_config__field_indices_by_name, + 0, cmd_apply_wifi_config__number_ranges, + (ProtobufCMessageInit) cmd_apply_wifi_config__init, + NULL,NULL,NULL /* reserved[123] */ +}; +#define cmd_apply_thread_config__field_descriptors NULL +#define cmd_apply_thread_config__field_indices_by_name NULL +#define cmd_apply_thread_config__number_ranges NULL +const ProtobufCMessageDescriptor cmd_apply_thread_config__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "CmdApplyThreadConfig", + "CmdApplyThreadConfig", + "CmdApplyThreadConfig", + "", + sizeof(CmdApplyThreadConfig), + 0, + cmd_apply_thread_config__field_descriptors, + cmd_apply_thread_config__field_indices_by_name, + 0, cmd_apply_thread_config__number_ranges, + (ProtobufCMessageInit) cmd_apply_thread_config__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor resp_apply_wifi_config__field_descriptors[1] = +{ + { + "status", + 1, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_ENUM, + 0, /* quantifier_offset */ + offsetof(RespApplyWifiConfig, status), + &status__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned resp_apply_wifi_config__field_indices_by_name[] = { + 0, /* field[0] = status */ +}; +static const ProtobufCIntRange resp_apply_wifi_config__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 1 } +}; +const ProtobufCMessageDescriptor resp_apply_wifi_config__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "RespApplyWifiConfig", + "RespApplyWifiConfig", + "RespApplyWifiConfig", + "", + sizeof(RespApplyWifiConfig), + 1, + resp_apply_wifi_config__field_descriptors, + resp_apply_wifi_config__field_indices_by_name, + 1, resp_apply_wifi_config__number_ranges, + (ProtobufCMessageInit) resp_apply_wifi_config__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor resp_apply_thread_config__field_descriptors[1] = +{ + { + "status", + 1, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_ENUM, + 0, /* quantifier_offset */ + offsetof(RespApplyThreadConfig, status), + &status__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned resp_apply_thread_config__field_indices_by_name[] = { + 0, /* field[0] = status */ +}; +static const ProtobufCIntRange resp_apply_thread_config__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 1 } +}; +const ProtobufCMessageDescriptor resp_apply_thread_config__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "RespApplyThreadConfig", + "RespApplyThreadConfig", + "RespApplyThreadConfig", + "", + sizeof(RespApplyThreadConfig), + 1, + resp_apply_thread_config__field_descriptors, + resp_apply_thread_config__field_indices_by_name, + 1, resp_apply_thread_config__number_ranges, + (ProtobufCMessageInit) resp_apply_thread_config__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor network_config_payload__field_descriptors[13] = +{ + { + "msg", + 1, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_ENUM, + 0, /* quantifier_offset */ + offsetof(NetworkConfigPayload, msg), + &network_config_msg_type__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "cmd_get_wifi_status", + 10, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(NetworkConfigPayload, payload_case), + offsetof(NetworkConfigPayload, cmd_get_wifi_status), + &cmd_get_wifi_status__descriptor, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "resp_get_wifi_status", + 11, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(NetworkConfigPayload, payload_case), + offsetof(NetworkConfigPayload, resp_get_wifi_status), + &resp_get_wifi_status__descriptor, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "cmd_set_wifi_config", + 12, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(NetworkConfigPayload, payload_case), + offsetof(NetworkConfigPayload, cmd_set_wifi_config), + &cmd_set_wifi_config__descriptor, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "resp_set_wifi_config", + 13, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(NetworkConfigPayload, payload_case), + offsetof(NetworkConfigPayload, resp_set_wifi_config), + &resp_set_wifi_config__descriptor, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "cmd_apply_wifi_config", + 14, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(NetworkConfigPayload, payload_case), + offsetof(NetworkConfigPayload, cmd_apply_wifi_config), + &cmd_apply_wifi_config__descriptor, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "resp_apply_wifi_config", + 15, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(NetworkConfigPayload, payload_case), + offsetof(NetworkConfigPayload, resp_apply_wifi_config), + &resp_apply_wifi_config__descriptor, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "cmd_get_thread_status", + 16, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(NetworkConfigPayload, payload_case), + offsetof(NetworkConfigPayload, cmd_get_thread_status), + &cmd_get_thread_status__descriptor, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "resp_get_thread_status", + 17, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(NetworkConfigPayload, payload_case), + offsetof(NetworkConfigPayload, resp_get_thread_status), + &resp_get_thread_status__descriptor, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "cmd_set_thread_config", + 18, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(NetworkConfigPayload, payload_case), + offsetof(NetworkConfigPayload, cmd_set_thread_config), + &cmd_set_thread_config__descriptor, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "resp_set_thread_config", + 19, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(NetworkConfigPayload, payload_case), + offsetof(NetworkConfigPayload, resp_set_thread_config), + &resp_set_thread_config__descriptor, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "cmd_apply_thread_config", + 20, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(NetworkConfigPayload, payload_case), + offsetof(NetworkConfigPayload, cmd_apply_thread_config), + &cmd_apply_thread_config__descriptor, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "resp_apply_thread_config", + 21, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(NetworkConfigPayload, payload_case), + offsetof(NetworkConfigPayload, resp_apply_thread_config), + &resp_apply_thread_config__descriptor, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned network_config_payload__field_indices_by_name[] = { + 11, /* field[11] = cmd_apply_thread_config */ + 5, /* field[5] = cmd_apply_wifi_config */ + 7, /* field[7] = cmd_get_thread_status */ + 1, /* field[1] = cmd_get_wifi_status */ + 9, /* field[9] = cmd_set_thread_config */ + 3, /* field[3] = cmd_set_wifi_config */ + 0, /* field[0] = msg */ + 12, /* field[12] = resp_apply_thread_config */ + 6, /* field[6] = resp_apply_wifi_config */ + 8, /* field[8] = resp_get_thread_status */ + 2, /* field[2] = resp_get_wifi_status */ + 10, /* field[10] = resp_set_thread_config */ + 4, /* field[4] = resp_set_wifi_config */ +}; +static const ProtobufCIntRange network_config_payload__number_ranges[2 + 1] = +{ + { 1, 0 }, + { 10, 1 }, + { 0, 13 } +}; +const ProtobufCMessageDescriptor network_config_payload__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "NetworkConfigPayload", + "NetworkConfigPayload", + "NetworkConfigPayload", + "", + sizeof(NetworkConfigPayload), + 13, + network_config_payload__field_descriptors, + network_config_payload__field_indices_by_name, + 2, network_config_payload__number_ranges, + (ProtobufCMessageInit) network_config_payload__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCEnumValue network_config_msg_type__enum_values_by_number[12] = +{ + { "TypeCmdGetWifiStatus", "NETWORK_CONFIG_MSG_TYPE__TypeCmdGetWifiStatus", 0 }, + { "TypeRespGetWifiStatus", "NETWORK_CONFIG_MSG_TYPE__TypeRespGetWifiStatus", 1 }, + { "TypeCmdSetWifiConfig", "NETWORK_CONFIG_MSG_TYPE__TypeCmdSetWifiConfig", 2 }, + { "TypeRespSetWifiConfig", "NETWORK_CONFIG_MSG_TYPE__TypeRespSetWifiConfig", 3 }, + { "TypeCmdApplyWifiConfig", "NETWORK_CONFIG_MSG_TYPE__TypeCmdApplyWifiConfig", 4 }, + { "TypeRespApplyWifiConfig", "NETWORK_CONFIG_MSG_TYPE__TypeRespApplyWifiConfig", 5 }, + { "TypeCmdGetThreadStatus", "NETWORK_CONFIG_MSG_TYPE__TypeCmdGetThreadStatus", 6 }, + { "TypeRespGetThreadStatus", "NETWORK_CONFIG_MSG_TYPE__TypeRespGetThreadStatus", 7 }, + { "TypeCmdSetThreadConfig", "NETWORK_CONFIG_MSG_TYPE__TypeCmdSetThreadConfig", 8 }, + { "TypeRespSetThreadConfig", "NETWORK_CONFIG_MSG_TYPE__TypeRespSetThreadConfig", 9 }, + { "TypeCmdApplyThreadConfig", "NETWORK_CONFIG_MSG_TYPE__TypeCmdApplyThreadConfig", 10 }, + { "TypeRespApplyThreadConfig", "NETWORK_CONFIG_MSG_TYPE__TypeRespApplyThreadConfig", 11 }, +}; +static const ProtobufCIntRange network_config_msg_type__value_ranges[] = { +{0, 0},{0, 12} +}; +static const ProtobufCEnumValueIndex network_config_msg_type__enum_values_by_name[12] = +{ + { "TypeCmdApplyThreadConfig", 10 }, + { "TypeCmdApplyWifiConfig", 4 }, + { "TypeCmdGetThreadStatus", 6 }, + { "TypeCmdGetWifiStatus", 0 }, + { "TypeCmdSetThreadConfig", 8 }, + { "TypeCmdSetWifiConfig", 2 }, + { "TypeRespApplyThreadConfig", 11 }, + { "TypeRespApplyWifiConfig", 5 }, + { "TypeRespGetThreadStatus", 7 }, + { "TypeRespGetWifiStatus", 1 }, + { "TypeRespSetThreadConfig", 9 }, + { "TypeRespSetWifiConfig", 3 }, +}; +const ProtobufCEnumDescriptor network_config_msg_type__descriptor = +{ + PROTOBUF_C__ENUM_DESCRIPTOR_MAGIC, + "NetworkConfigMsgType", + "NetworkConfigMsgType", + "NetworkConfigMsgType", + "", + 12, + network_config_msg_type__enum_values_by_number, + 12, + network_config_msg_type__enum_values_by_name, + 1, + network_config_msg_type__value_ranges, + NULL,NULL,NULL,NULL /* reserved[1234] */ +}; diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/proto-c/network_config.pb-c.h b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/proto-c/network_config.pb-c.h new file mode 100644 index 000000000..6ce8881c4 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/proto-c/network_config.pb-c.h @@ -0,0 +1,554 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ +/* Generated from: network_config.proto */ + +#ifndef PROTOBUF_C_network_5fconfig_2eproto__INCLUDED +#define PROTOBUF_C_network_5fconfig_2eproto__INCLUDED + +#include + +PROTOBUF_C__BEGIN_DECLS + +#if PROTOBUF_C_VERSION_NUMBER < 1003000 +# error This file was generated by a newer version of protoc-c which is incompatible with your libprotobuf-c headers. Please update your headers. +#elif 1004000 < PROTOBUF_C_MIN_COMPILER_VERSION +# error This file was generated by an older version of protoc-c which is incompatible with your libprotobuf-c headers. Please regenerate this file with a newer version of protoc-c. +#endif + +#include "constants.pb-c.h" +#include "network_constants.pb-c.h" + +typedef struct CmdGetWifiStatus CmdGetWifiStatus; +typedef struct RespGetWifiStatus RespGetWifiStatus; +typedef struct CmdGetThreadStatus CmdGetThreadStatus; +typedef struct RespGetThreadStatus RespGetThreadStatus; +typedef struct CmdSetWifiConfig CmdSetWifiConfig; +typedef struct CmdSetThreadConfig CmdSetThreadConfig; +typedef struct RespSetWifiConfig RespSetWifiConfig; +typedef struct RespSetThreadConfig RespSetThreadConfig; +typedef struct CmdApplyWifiConfig CmdApplyWifiConfig; +typedef struct CmdApplyThreadConfig CmdApplyThreadConfig; +typedef struct RespApplyWifiConfig RespApplyWifiConfig; +typedef struct RespApplyThreadConfig RespApplyThreadConfig; +typedef struct NetworkConfigPayload NetworkConfigPayload; + + +/* --- enums --- */ + +typedef enum _NetworkConfigMsgType { + NETWORK_CONFIG_MSG_TYPE__TypeCmdGetWifiStatus = 0, + NETWORK_CONFIG_MSG_TYPE__TypeRespGetWifiStatus = 1, + NETWORK_CONFIG_MSG_TYPE__TypeCmdSetWifiConfig = 2, + NETWORK_CONFIG_MSG_TYPE__TypeRespSetWifiConfig = 3, + NETWORK_CONFIG_MSG_TYPE__TypeCmdApplyWifiConfig = 4, + NETWORK_CONFIG_MSG_TYPE__TypeRespApplyWifiConfig = 5, + NETWORK_CONFIG_MSG_TYPE__TypeCmdGetThreadStatus = 6, + NETWORK_CONFIG_MSG_TYPE__TypeRespGetThreadStatus = 7, + NETWORK_CONFIG_MSG_TYPE__TypeCmdSetThreadConfig = 8, + NETWORK_CONFIG_MSG_TYPE__TypeRespSetThreadConfig = 9, + NETWORK_CONFIG_MSG_TYPE__TypeCmdApplyThreadConfig = 10, + NETWORK_CONFIG_MSG_TYPE__TypeRespApplyThreadConfig = 11 + PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE(NETWORK_CONFIG_MSG_TYPE) +} NetworkConfigMsgType; + +/* --- messages --- */ + +struct CmdGetWifiStatus +{ + ProtobufCMessage base; +}; +#define CMD_GET_WIFI_STATUS__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&cmd_get_wifi_status__descriptor) \ + } + + +typedef enum { + RESP_GET_WIFI_STATUS__STATE__NOT_SET = 0, + RESP_GET_WIFI_STATUS__STATE_WIFI_FAIL_REASON = 10, + RESP_GET_WIFI_STATUS__STATE_WIFI_CONNECTED = 11 + PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE(RESP_GET_WIFI_STATUS__STATE__CASE) +} RespGetWifiStatus__StateCase; + +struct RespGetWifiStatus +{ + ProtobufCMessage base; + Status status; + WifiStationState wifi_sta_state; + RespGetWifiStatus__StateCase state_case; + union { + WifiConnectFailedReason wifi_fail_reason; + WifiConnectedState *wifi_connected; + }; +}; +#define RESP_GET_WIFI_STATUS__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&resp_get_wifi_status__descriptor) \ + , STATUS__Success, WIFI_STATION_STATE__Connected, RESP_GET_WIFI_STATUS__STATE__NOT_SET, {0} } + + +struct CmdGetThreadStatus +{ + ProtobufCMessage base; +}; +#define CMD_GET_THREAD_STATUS__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&cmd_get_thread_status__descriptor) \ + } + + +typedef enum { + RESP_GET_THREAD_STATUS__STATE__NOT_SET = 0, + RESP_GET_THREAD_STATUS__STATE_THREAD_FAIL_REASON = 10, + RESP_GET_THREAD_STATUS__STATE_THREAD_ATTACHED = 11 + PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE(RESP_GET_THREAD_STATUS__STATE__CASE) +} RespGetThreadStatus__StateCase; + +struct RespGetThreadStatus +{ + ProtobufCMessage base; + Status status; + ThreadNetworkState thread_state; + RespGetThreadStatus__StateCase state_case; + union { + ThreadAttachFailedReason thread_fail_reason; + ThreadAttachState *thread_attached; + }; +}; +#define RESP_GET_THREAD_STATUS__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&resp_get_thread_status__descriptor) \ + , STATUS__Success, THREAD_NETWORK_STATE__Attached, RESP_GET_THREAD_STATUS__STATE__NOT_SET, {0} } + + +struct CmdSetWifiConfig +{ + ProtobufCMessage base; + ProtobufCBinaryData ssid; + ProtobufCBinaryData passphrase; + ProtobufCBinaryData bssid; + int32_t channel; +}; +#define CMD_SET_WIFI_CONFIG__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&cmd_set_wifi_config__descriptor) \ + , {0,NULL}, {0,NULL}, {0,NULL}, 0 } + + +struct CmdSetThreadConfig +{ + ProtobufCMessage base; + ProtobufCBinaryData dataset; +}; +#define CMD_SET_THREAD_CONFIG__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&cmd_set_thread_config__descriptor) \ + , {0,NULL} } + + +struct RespSetWifiConfig +{ + ProtobufCMessage base; + Status status; +}; +#define RESP_SET_WIFI_CONFIG__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&resp_set_wifi_config__descriptor) \ + , STATUS__Success } + + +struct RespSetThreadConfig +{ + ProtobufCMessage base; + Status status; +}; +#define RESP_SET_THREAD_CONFIG__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&resp_set_thread_config__descriptor) \ + , STATUS__Success } + + +struct CmdApplyWifiConfig +{ + ProtobufCMessage base; +}; +#define CMD_APPLY_WIFI_CONFIG__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&cmd_apply_wifi_config__descriptor) \ + } + + +struct CmdApplyThreadConfig +{ + ProtobufCMessage base; +}; +#define CMD_APPLY_THREAD_CONFIG__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&cmd_apply_thread_config__descriptor) \ + } + + +struct RespApplyWifiConfig +{ + ProtobufCMessage base; + Status status; +}; +#define RESP_APPLY_WIFI_CONFIG__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&resp_apply_wifi_config__descriptor) \ + , STATUS__Success } + + +struct RespApplyThreadConfig +{ + ProtobufCMessage base; + Status status; +}; +#define RESP_APPLY_THREAD_CONFIG__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&resp_apply_thread_config__descriptor) \ + , STATUS__Success } + + +typedef enum { + NETWORK_CONFIG_PAYLOAD__PAYLOAD__NOT_SET = 0, + NETWORK_CONFIG_PAYLOAD__PAYLOAD_CMD_GET_WIFI_STATUS = 10, + NETWORK_CONFIG_PAYLOAD__PAYLOAD_RESP_GET_WIFI_STATUS = 11, + NETWORK_CONFIG_PAYLOAD__PAYLOAD_CMD_SET_WIFI_CONFIG = 12, + NETWORK_CONFIG_PAYLOAD__PAYLOAD_RESP_SET_WIFI_CONFIG = 13, + NETWORK_CONFIG_PAYLOAD__PAYLOAD_CMD_APPLY_WIFI_CONFIG = 14, + NETWORK_CONFIG_PAYLOAD__PAYLOAD_RESP_APPLY_WIFI_CONFIG = 15, + NETWORK_CONFIG_PAYLOAD__PAYLOAD_CMD_GET_THREAD_STATUS = 16, + NETWORK_CONFIG_PAYLOAD__PAYLOAD_RESP_GET_THREAD_STATUS = 17, + NETWORK_CONFIG_PAYLOAD__PAYLOAD_CMD_SET_THREAD_CONFIG = 18, + NETWORK_CONFIG_PAYLOAD__PAYLOAD_RESP_SET_THREAD_CONFIG = 19, + NETWORK_CONFIG_PAYLOAD__PAYLOAD_CMD_APPLY_THREAD_CONFIG = 20, + NETWORK_CONFIG_PAYLOAD__PAYLOAD_RESP_APPLY_THREAD_CONFIG = 21 + PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE(NETWORK_CONFIG_PAYLOAD__PAYLOAD__CASE) +} NetworkConfigPayload__PayloadCase; + +struct NetworkConfigPayload +{ + ProtobufCMessage base; + NetworkConfigMsgType msg; + NetworkConfigPayload__PayloadCase payload_case; + union { + CmdGetWifiStatus *cmd_get_wifi_status; + RespGetWifiStatus *resp_get_wifi_status; + CmdSetWifiConfig *cmd_set_wifi_config; + RespSetWifiConfig *resp_set_wifi_config; + CmdApplyWifiConfig *cmd_apply_wifi_config; + RespApplyWifiConfig *resp_apply_wifi_config; + CmdGetThreadStatus *cmd_get_thread_status; + RespGetThreadStatus *resp_get_thread_status; + CmdSetThreadConfig *cmd_set_thread_config; + RespSetThreadConfig *resp_set_thread_config; + CmdApplyThreadConfig *cmd_apply_thread_config; + RespApplyThreadConfig *resp_apply_thread_config; + }; +}; +#define NETWORK_CONFIG_PAYLOAD__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&network_config_payload__descriptor) \ + , NETWORK_CONFIG_MSG_TYPE__TypeCmdGetWifiStatus, NETWORK_CONFIG_PAYLOAD__PAYLOAD__NOT_SET, {0} } + + +/* CmdGetWifiStatus methods */ +void cmd_get_wifi_status__init + (CmdGetWifiStatus *message); +size_t cmd_get_wifi_status__get_packed_size + (const CmdGetWifiStatus *message); +size_t cmd_get_wifi_status__pack + (const CmdGetWifiStatus *message, + uint8_t *out); +size_t cmd_get_wifi_status__pack_to_buffer + (const CmdGetWifiStatus *message, + ProtobufCBuffer *buffer); +CmdGetWifiStatus * + cmd_get_wifi_status__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void cmd_get_wifi_status__free_unpacked + (CmdGetWifiStatus *message, + ProtobufCAllocator *allocator); +/* RespGetWifiStatus methods */ +void resp_get_wifi_status__init + (RespGetWifiStatus *message); +size_t resp_get_wifi_status__get_packed_size + (const RespGetWifiStatus *message); +size_t resp_get_wifi_status__pack + (const RespGetWifiStatus *message, + uint8_t *out); +size_t resp_get_wifi_status__pack_to_buffer + (const RespGetWifiStatus *message, + ProtobufCBuffer *buffer); +RespGetWifiStatus * + resp_get_wifi_status__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void resp_get_wifi_status__free_unpacked + (RespGetWifiStatus *message, + ProtobufCAllocator *allocator); +/* CmdGetThreadStatus methods */ +void cmd_get_thread_status__init + (CmdGetThreadStatus *message); +size_t cmd_get_thread_status__get_packed_size + (const CmdGetThreadStatus *message); +size_t cmd_get_thread_status__pack + (const CmdGetThreadStatus *message, + uint8_t *out); +size_t cmd_get_thread_status__pack_to_buffer + (const CmdGetThreadStatus *message, + ProtobufCBuffer *buffer); +CmdGetThreadStatus * + cmd_get_thread_status__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void cmd_get_thread_status__free_unpacked + (CmdGetThreadStatus *message, + ProtobufCAllocator *allocator); +/* RespGetThreadStatus methods */ +void resp_get_thread_status__init + (RespGetThreadStatus *message); +size_t resp_get_thread_status__get_packed_size + (const RespGetThreadStatus *message); +size_t resp_get_thread_status__pack + (const RespGetThreadStatus *message, + uint8_t *out); +size_t resp_get_thread_status__pack_to_buffer + (const RespGetThreadStatus *message, + ProtobufCBuffer *buffer); +RespGetThreadStatus * + resp_get_thread_status__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void resp_get_thread_status__free_unpacked + (RespGetThreadStatus *message, + ProtobufCAllocator *allocator); +/* CmdSetWifiConfig methods */ +void cmd_set_wifi_config__init + (CmdSetWifiConfig *message); +size_t cmd_set_wifi_config__get_packed_size + (const CmdSetWifiConfig *message); +size_t cmd_set_wifi_config__pack + (const CmdSetWifiConfig *message, + uint8_t *out); +size_t cmd_set_wifi_config__pack_to_buffer + (const CmdSetWifiConfig *message, + ProtobufCBuffer *buffer); +CmdSetWifiConfig * + cmd_set_wifi_config__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void cmd_set_wifi_config__free_unpacked + (CmdSetWifiConfig *message, + ProtobufCAllocator *allocator); +/* CmdSetThreadConfig methods */ +void cmd_set_thread_config__init + (CmdSetThreadConfig *message); +size_t cmd_set_thread_config__get_packed_size + (const CmdSetThreadConfig *message); +size_t cmd_set_thread_config__pack + (const CmdSetThreadConfig *message, + uint8_t *out); +size_t cmd_set_thread_config__pack_to_buffer + (const CmdSetThreadConfig *message, + ProtobufCBuffer *buffer); +CmdSetThreadConfig * + cmd_set_thread_config__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void cmd_set_thread_config__free_unpacked + (CmdSetThreadConfig *message, + ProtobufCAllocator *allocator); +/* RespSetWifiConfig methods */ +void resp_set_wifi_config__init + (RespSetWifiConfig *message); +size_t resp_set_wifi_config__get_packed_size + (const RespSetWifiConfig *message); +size_t resp_set_wifi_config__pack + (const RespSetWifiConfig *message, + uint8_t *out); +size_t resp_set_wifi_config__pack_to_buffer + (const RespSetWifiConfig *message, + ProtobufCBuffer *buffer); +RespSetWifiConfig * + resp_set_wifi_config__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void resp_set_wifi_config__free_unpacked + (RespSetWifiConfig *message, + ProtobufCAllocator *allocator); +/* RespSetThreadConfig methods */ +void resp_set_thread_config__init + (RespSetThreadConfig *message); +size_t resp_set_thread_config__get_packed_size + (const RespSetThreadConfig *message); +size_t resp_set_thread_config__pack + (const RespSetThreadConfig *message, + uint8_t *out); +size_t resp_set_thread_config__pack_to_buffer + (const RespSetThreadConfig *message, + ProtobufCBuffer *buffer); +RespSetThreadConfig * + resp_set_thread_config__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void resp_set_thread_config__free_unpacked + (RespSetThreadConfig *message, + ProtobufCAllocator *allocator); +/* CmdApplyWifiConfig methods */ +void cmd_apply_wifi_config__init + (CmdApplyWifiConfig *message); +size_t cmd_apply_wifi_config__get_packed_size + (const CmdApplyWifiConfig *message); +size_t cmd_apply_wifi_config__pack + (const CmdApplyWifiConfig *message, + uint8_t *out); +size_t cmd_apply_wifi_config__pack_to_buffer + (const CmdApplyWifiConfig *message, + ProtobufCBuffer *buffer); +CmdApplyWifiConfig * + cmd_apply_wifi_config__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void cmd_apply_wifi_config__free_unpacked + (CmdApplyWifiConfig *message, + ProtobufCAllocator *allocator); +/* CmdApplyThreadConfig methods */ +void cmd_apply_thread_config__init + (CmdApplyThreadConfig *message); +size_t cmd_apply_thread_config__get_packed_size + (const CmdApplyThreadConfig *message); +size_t cmd_apply_thread_config__pack + (const CmdApplyThreadConfig *message, + uint8_t *out); +size_t cmd_apply_thread_config__pack_to_buffer + (const CmdApplyThreadConfig *message, + ProtobufCBuffer *buffer); +CmdApplyThreadConfig * + cmd_apply_thread_config__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void cmd_apply_thread_config__free_unpacked + (CmdApplyThreadConfig *message, + ProtobufCAllocator *allocator); +/* RespApplyWifiConfig methods */ +void resp_apply_wifi_config__init + (RespApplyWifiConfig *message); +size_t resp_apply_wifi_config__get_packed_size + (const RespApplyWifiConfig *message); +size_t resp_apply_wifi_config__pack + (const RespApplyWifiConfig *message, + uint8_t *out); +size_t resp_apply_wifi_config__pack_to_buffer + (const RespApplyWifiConfig *message, + ProtobufCBuffer *buffer); +RespApplyWifiConfig * + resp_apply_wifi_config__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void resp_apply_wifi_config__free_unpacked + (RespApplyWifiConfig *message, + ProtobufCAllocator *allocator); +/* RespApplyThreadConfig methods */ +void resp_apply_thread_config__init + (RespApplyThreadConfig *message); +size_t resp_apply_thread_config__get_packed_size + (const RespApplyThreadConfig *message); +size_t resp_apply_thread_config__pack + (const RespApplyThreadConfig *message, + uint8_t *out); +size_t resp_apply_thread_config__pack_to_buffer + (const RespApplyThreadConfig *message, + ProtobufCBuffer *buffer); +RespApplyThreadConfig * + resp_apply_thread_config__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void resp_apply_thread_config__free_unpacked + (RespApplyThreadConfig *message, + ProtobufCAllocator *allocator); +/* NetworkConfigPayload methods */ +void network_config_payload__init + (NetworkConfigPayload *message); +size_t network_config_payload__get_packed_size + (const NetworkConfigPayload *message); +size_t network_config_payload__pack + (const NetworkConfigPayload *message, + uint8_t *out); +size_t network_config_payload__pack_to_buffer + (const NetworkConfigPayload *message, + ProtobufCBuffer *buffer); +NetworkConfigPayload * + network_config_payload__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void network_config_payload__free_unpacked + (NetworkConfigPayload *message, + ProtobufCAllocator *allocator); +/* --- per-message closures --- */ + +typedef void (*CmdGetWifiStatus_Closure) + (const CmdGetWifiStatus *message, + void *closure_data); +typedef void (*RespGetWifiStatus_Closure) + (const RespGetWifiStatus *message, + void *closure_data); +typedef void (*CmdGetThreadStatus_Closure) + (const CmdGetThreadStatus *message, + void *closure_data); +typedef void (*RespGetThreadStatus_Closure) + (const RespGetThreadStatus *message, + void *closure_data); +typedef void (*CmdSetWifiConfig_Closure) + (const CmdSetWifiConfig *message, + void *closure_data); +typedef void (*CmdSetThreadConfig_Closure) + (const CmdSetThreadConfig *message, + void *closure_data); +typedef void (*RespSetWifiConfig_Closure) + (const RespSetWifiConfig *message, + void *closure_data); +typedef void (*RespSetThreadConfig_Closure) + (const RespSetThreadConfig *message, + void *closure_data); +typedef void (*CmdApplyWifiConfig_Closure) + (const CmdApplyWifiConfig *message, + void *closure_data); +typedef void (*CmdApplyThreadConfig_Closure) + (const CmdApplyThreadConfig *message, + void *closure_data); +typedef void (*RespApplyWifiConfig_Closure) + (const RespApplyWifiConfig *message, + void *closure_data); +typedef void (*RespApplyThreadConfig_Closure) + (const RespApplyThreadConfig *message, + void *closure_data); +typedef void (*NetworkConfigPayload_Closure) + (const NetworkConfigPayload *message, + void *closure_data); + +/* --- services --- */ + + +/* --- descriptors --- */ + +extern const ProtobufCEnumDescriptor network_config_msg_type__descriptor; +extern const ProtobufCMessageDescriptor cmd_get_wifi_status__descriptor; +extern const ProtobufCMessageDescriptor resp_get_wifi_status__descriptor; +extern const ProtobufCMessageDescriptor cmd_get_thread_status__descriptor; +extern const ProtobufCMessageDescriptor resp_get_thread_status__descriptor; +extern const ProtobufCMessageDescriptor cmd_set_wifi_config__descriptor; +extern const ProtobufCMessageDescriptor cmd_set_thread_config__descriptor; +extern const ProtobufCMessageDescriptor resp_set_wifi_config__descriptor; +extern const ProtobufCMessageDescriptor resp_set_thread_config__descriptor; +extern const ProtobufCMessageDescriptor cmd_apply_wifi_config__descriptor; +extern const ProtobufCMessageDescriptor cmd_apply_thread_config__descriptor; +extern const ProtobufCMessageDescriptor resp_apply_wifi_config__descriptor; +extern const ProtobufCMessageDescriptor resp_apply_thread_config__descriptor; +extern const ProtobufCMessageDescriptor network_config_payload__descriptor; + +PROTOBUF_C__END_DECLS + + +#endif /* PROTOBUF_C_network_5fconfig_2eproto__INCLUDED */ diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/proto-c/network_constants.pb-c.c b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/proto-c/network_constants.pb-c.c new file mode 100644 index 000000000..70953674c --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/proto-c/network_constants.pb-c.c @@ -0,0 +1,426 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ +/* Generated from: network_constants.proto */ + +/* Do not generate deprecated warnings for self */ +#ifndef PROTOBUF_C__NO_DEPRECATED +#define PROTOBUF_C__NO_DEPRECATED +#endif + +#include "network_constants.pb-c.h" +void wifi_connected_state__init + (WifiConnectedState *message) +{ + static const WifiConnectedState init_value = WIFI_CONNECTED_STATE__INIT; + *message = init_value; +} +size_t wifi_connected_state__get_packed_size + (const WifiConnectedState *message) +{ + assert(message->base.descriptor == &wifi_connected_state__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t wifi_connected_state__pack + (const WifiConnectedState *message, + uint8_t *out) +{ + assert(message->base.descriptor == &wifi_connected_state__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t wifi_connected_state__pack_to_buffer + (const WifiConnectedState *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &wifi_connected_state__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +WifiConnectedState * + wifi_connected_state__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (WifiConnectedState *) + protobuf_c_message_unpack (&wifi_connected_state__descriptor, + allocator, len, data); +} +void wifi_connected_state__free_unpacked + (WifiConnectedState *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &wifi_connected_state__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void thread_attach_state__init + (ThreadAttachState *message) +{ + static const ThreadAttachState init_value = THREAD_ATTACH_STATE__INIT; + *message = init_value; +} +size_t thread_attach_state__get_packed_size + (const ThreadAttachState *message) +{ + assert(message->base.descriptor == &thread_attach_state__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t thread_attach_state__pack + (const ThreadAttachState *message, + uint8_t *out) +{ + assert(message->base.descriptor == &thread_attach_state__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t thread_attach_state__pack_to_buffer + (const ThreadAttachState *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &thread_attach_state__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +ThreadAttachState * + thread_attach_state__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (ThreadAttachState *) + protobuf_c_message_unpack (&thread_attach_state__descriptor, + allocator, len, data); +} +void thread_attach_state__free_unpacked + (ThreadAttachState *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &thread_attach_state__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +static const ProtobufCFieldDescriptor wifi_connected_state__field_descriptors[5] = +{ + { + "ip4_addr", + 1, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_STRING, + 0, /* quantifier_offset */ + offsetof(WifiConnectedState, ip4_addr), + NULL, + &protobuf_c_empty_string, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "auth_mode", + 2, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_ENUM, + 0, /* quantifier_offset */ + offsetof(WifiConnectedState, auth_mode), + &wifi_auth_mode__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "ssid", + 3, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_BYTES, + 0, /* quantifier_offset */ + offsetof(WifiConnectedState, ssid), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "bssid", + 4, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_BYTES, + 0, /* quantifier_offset */ + offsetof(WifiConnectedState, bssid), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "channel", + 5, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_INT32, + 0, /* quantifier_offset */ + offsetof(WifiConnectedState, channel), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned wifi_connected_state__field_indices_by_name[] = { + 1, /* field[1] = auth_mode */ + 3, /* field[3] = bssid */ + 4, /* field[4] = channel */ + 0, /* field[0] = ip4_addr */ + 2, /* field[2] = ssid */ +}; +static const ProtobufCIntRange wifi_connected_state__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 5 } +}; +const ProtobufCMessageDescriptor wifi_connected_state__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "WifiConnectedState", + "WifiConnectedState", + "WifiConnectedState", + "", + sizeof(WifiConnectedState), + 5, + wifi_connected_state__field_descriptors, + wifi_connected_state__field_indices_by_name, + 1, wifi_connected_state__number_ranges, + (ProtobufCMessageInit) wifi_connected_state__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor thread_attach_state__field_descriptors[4] = +{ + { + "pan_id", + 1, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_UINT32, + 0, /* quantifier_offset */ + offsetof(ThreadAttachState, pan_id), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "ext_pan_id", + 2, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_BYTES, + 0, /* quantifier_offset */ + offsetof(ThreadAttachState, ext_pan_id), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "channel", + 3, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_UINT32, + 0, /* quantifier_offset */ + offsetof(ThreadAttachState, channel), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "name", + 4, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_STRING, + 0, /* quantifier_offset */ + offsetof(ThreadAttachState, name), + NULL, + &protobuf_c_empty_string, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned thread_attach_state__field_indices_by_name[] = { + 2, /* field[2] = channel */ + 1, /* field[1] = ext_pan_id */ + 3, /* field[3] = name */ + 0, /* field[0] = pan_id */ +}; +static const ProtobufCIntRange thread_attach_state__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 4 } +}; +const ProtobufCMessageDescriptor thread_attach_state__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "ThreadAttachState", + "ThreadAttachState", + "ThreadAttachState", + "", + sizeof(ThreadAttachState), + 4, + thread_attach_state__field_descriptors, + thread_attach_state__field_indices_by_name, + 1, thread_attach_state__number_ranges, + (ProtobufCMessageInit) thread_attach_state__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCEnumValue wifi_station_state__enum_values_by_number[4] = +{ + { "Connected", "WIFI_STATION_STATE__Connected", 0 }, + { "Connecting", "WIFI_STATION_STATE__Connecting", 1 }, + { "Disconnected", "WIFI_STATION_STATE__Disconnected", 2 }, + { "ConnectionFailed", "WIFI_STATION_STATE__ConnectionFailed", 3 }, +}; +static const ProtobufCIntRange wifi_station_state__value_ranges[] = { +{0, 0},{0, 4} +}; +static const ProtobufCEnumValueIndex wifi_station_state__enum_values_by_name[4] = +{ + { "Connected", 0 }, + { "Connecting", 1 }, + { "ConnectionFailed", 3 }, + { "Disconnected", 2 }, +}; +const ProtobufCEnumDescriptor wifi_station_state__descriptor = +{ + PROTOBUF_C__ENUM_DESCRIPTOR_MAGIC, + "WifiStationState", + "WifiStationState", + "WifiStationState", + "", + 4, + wifi_station_state__enum_values_by_number, + 4, + wifi_station_state__enum_values_by_name, + 1, + wifi_station_state__value_ranges, + NULL,NULL,NULL,NULL /* reserved[1234] */ +}; +static const ProtobufCEnumValue wifi_connect_failed_reason__enum_values_by_number[2] = +{ + { "AuthError", "WIFI_CONNECT_FAILED_REASON__AuthError", 0 }, + { "WifiNetworkNotFound", "WIFI_CONNECT_FAILED_REASON__WifiNetworkNotFound", 1 }, +}; +static const ProtobufCIntRange wifi_connect_failed_reason__value_ranges[] = { +{0, 0},{0, 2} +}; +static const ProtobufCEnumValueIndex wifi_connect_failed_reason__enum_values_by_name[2] = +{ + { "AuthError", 0 }, + { "WifiNetworkNotFound", 1 }, +}; +const ProtobufCEnumDescriptor wifi_connect_failed_reason__descriptor = +{ + PROTOBUF_C__ENUM_DESCRIPTOR_MAGIC, + "WifiConnectFailedReason", + "WifiConnectFailedReason", + "WifiConnectFailedReason", + "", + 2, + wifi_connect_failed_reason__enum_values_by_number, + 2, + wifi_connect_failed_reason__enum_values_by_name, + 1, + wifi_connect_failed_reason__value_ranges, + NULL,NULL,NULL,NULL /* reserved[1234] */ +}; +static const ProtobufCEnumValue wifi_auth_mode__enum_values_by_number[8] = +{ + { "Open", "WIFI_AUTH_MODE__Open", 0 }, + { "WEP", "WIFI_AUTH_MODE__WEP", 1 }, + { "WPA_PSK", "WIFI_AUTH_MODE__WPA_PSK", 2 }, + { "WPA2_PSK", "WIFI_AUTH_MODE__WPA2_PSK", 3 }, + { "WPA_WPA2_PSK", "WIFI_AUTH_MODE__WPA_WPA2_PSK", 4 }, + { "WPA2_ENTERPRISE", "WIFI_AUTH_MODE__WPA2_ENTERPRISE", 5 }, + { "WPA3_PSK", "WIFI_AUTH_MODE__WPA3_PSK", 6 }, + { "WPA2_WPA3_PSK", "WIFI_AUTH_MODE__WPA2_WPA3_PSK", 7 }, +}; +static const ProtobufCIntRange wifi_auth_mode__value_ranges[] = { +{0, 0},{0, 8} +}; +static const ProtobufCEnumValueIndex wifi_auth_mode__enum_values_by_name[8] = +{ + { "Open", 0 }, + { "WEP", 1 }, + { "WPA2_ENTERPRISE", 5 }, + { "WPA2_PSK", 3 }, + { "WPA2_WPA3_PSK", 7 }, + { "WPA3_PSK", 6 }, + { "WPA_PSK", 2 }, + { "WPA_WPA2_PSK", 4 }, +}; +const ProtobufCEnumDescriptor wifi_auth_mode__descriptor = +{ + PROTOBUF_C__ENUM_DESCRIPTOR_MAGIC, + "WifiAuthMode", + "WifiAuthMode", + "WifiAuthMode", + "", + 8, + wifi_auth_mode__enum_values_by_number, + 8, + wifi_auth_mode__enum_values_by_name, + 1, + wifi_auth_mode__value_ranges, + NULL,NULL,NULL,NULL /* reserved[1234] */ +}; +static const ProtobufCEnumValue thread_network_state__enum_values_by_number[4] = +{ + { "Attached", "THREAD_NETWORK_STATE__Attached", 0 }, + { "Attaching", "THREAD_NETWORK_STATE__Attaching", 1 }, + { "Dettached", "THREAD_NETWORK_STATE__Dettached", 2 }, + { "AttachingFailed", "THREAD_NETWORK_STATE__AttachingFailed", 3 }, +}; +static const ProtobufCIntRange thread_network_state__value_ranges[] = { +{0, 0},{0, 4} +}; +static const ProtobufCEnumValueIndex thread_network_state__enum_values_by_name[4] = +{ + { "Attached", 0 }, + { "Attaching", 1 }, + { "AttachingFailed", 3 }, + { "Dettached", 2 }, +}; +const ProtobufCEnumDescriptor thread_network_state__descriptor = +{ + PROTOBUF_C__ENUM_DESCRIPTOR_MAGIC, + "ThreadNetworkState", + "ThreadNetworkState", + "ThreadNetworkState", + "", + 4, + thread_network_state__enum_values_by_number, + 4, + thread_network_state__enum_values_by_name, + 1, + thread_network_state__value_ranges, + NULL,NULL,NULL,NULL /* reserved[1234] */ +}; +static const ProtobufCEnumValue thread_attach_failed_reason__enum_values_by_number[2] = +{ + { "DatasetInvalid", "THREAD_ATTACH_FAILED_REASON__DatasetInvalid", 0 }, + { "ThreadNetworkNotFound", "THREAD_ATTACH_FAILED_REASON__ThreadNetworkNotFound", 1 }, +}; +static const ProtobufCIntRange thread_attach_failed_reason__value_ranges[] = { +{0, 0},{0, 2} +}; +static const ProtobufCEnumValueIndex thread_attach_failed_reason__enum_values_by_name[2] = +{ + { "DatasetInvalid", 0 }, + { "ThreadNetworkNotFound", 1 }, +}; +const ProtobufCEnumDescriptor thread_attach_failed_reason__descriptor = +{ + PROTOBUF_C__ENUM_DESCRIPTOR_MAGIC, + "ThreadAttachFailedReason", + "ThreadAttachFailedReason", + "ThreadAttachFailedReason", + "", + 2, + thread_attach_failed_reason__enum_values_by_number, + 2, + thread_attach_failed_reason__enum_values_by_name, + 1, + thread_attach_failed_reason__value_ranges, + NULL,NULL,NULL,NULL /* reserved[1234] */ +}; diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/proto-c/network_constants.pb-c.h b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/proto-c/network_constants.pb-c.h new file mode 100644 index 000000000..e9aceddb2 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/proto-c/network_constants.pb-c.h @@ -0,0 +1,152 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ +/* Generated from: network_constants.proto */ + +#ifndef PROTOBUF_C_network_5fconstants_2eproto__INCLUDED +#define PROTOBUF_C_network_5fconstants_2eproto__INCLUDED + +#include + +PROTOBUF_C__BEGIN_DECLS + +#if PROTOBUF_C_VERSION_NUMBER < 1003000 +# error This file was generated by a newer version of protoc-c which is incompatible with your libprotobuf-c headers. Please update your headers. +#elif 1004000 < PROTOBUF_C_MIN_COMPILER_VERSION +# error This file was generated by an older version of protoc-c which is incompatible with your libprotobuf-c headers. Please regenerate this file with a newer version of protoc-c. +#endif + + +typedef struct WifiConnectedState WifiConnectedState; +typedef struct ThreadAttachState ThreadAttachState; + + +/* --- enums --- */ + +typedef enum _WifiStationState { + WIFI_STATION_STATE__Connected = 0, + WIFI_STATION_STATE__Connecting = 1, + WIFI_STATION_STATE__Disconnected = 2, + WIFI_STATION_STATE__ConnectionFailed = 3 + PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE(WIFI_STATION_STATE) +} WifiStationState; +typedef enum _WifiConnectFailedReason { + WIFI_CONNECT_FAILED_REASON__AuthError = 0, + WIFI_CONNECT_FAILED_REASON__WifiNetworkNotFound = 1 + PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE(WIFI_CONNECT_FAILED_REASON) +} WifiConnectFailedReason; +typedef enum _WifiAuthMode { + WIFI_AUTH_MODE__Open = 0, + WIFI_AUTH_MODE__WEP = 1, + WIFI_AUTH_MODE__WPA_PSK = 2, + WIFI_AUTH_MODE__WPA2_PSK = 3, + WIFI_AUTH_MODE__WPA_WPA2_PSK = 4, + WIFI_AUTH_MODE__WPA2_ENTERPRISE = 5, + WIFI_AUTH_MODE__WPA3_PSK = 6, + WIFI_AUTH_MODE__WPA2_WPA3_PSK = 7 + PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE(WIFI_AUTH_MODE) +} WifiAuthMode; +typedef enum _ThreadNetworkState { + THREAD_NETWORK_STATE__Attached = 0, + THREAD_NETWORK_STATE__Attaching = 1, + THREAD_NETWORK_STATE__Dettached = 2, + THREAD_NETWORK_STATE__AttachingFailed = 3 + PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE(THREAD_NETWORK_STATE) +} ThreadNetworkState; +typedef enum _ThreadAttachFailedReason { + THREAD_ATTACH_FAILED_REASON__DatasetInvalid = 0, + THREAD_ATTACH_FAILED_REASON__ThreadNetworkNotFound = 1 + PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE(THREAD_ATTACH_FAILED_REASON) +} ThreadAttachFailedReason; + +/* --- messages --- */ + +struct WifiConnectedState +{ + ProtobufCMessage base; + char *ip4_addr; + WifiAuthMode auth_mode; + ProtobufCBinaryData ssid; + ProtobufCBinaryData bssid; + int32_t channel; +}; +#define WIFI_CONNECTED_STATE__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&wifi_connected_state__descriptor) \ + , (char *)protobuf_c_empty_string, WIFI_AUTH_MODE__Open, {0,NULL}, {0,NULL}, 0 } + + +struct ThreadAttachState +{ + ProtobufCMessage base; + uint32_t pan_id; + ProtobufCBinaryData ext_pan_id; + uint32_t channel; + char *name; +}; +#define THREAD_ATTACH_STATE__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&thread_attach_state__descriptor) \ + , 0, {0,NULL}, 0, (char *)protobuf_c_empty_string } + + +/* WifiConnectedState methods */ +void wifi_connected_state__init + (WifiConnectedState *message); +size_t wifi_connected_state__get_packed_size + (const WifiConnectedState *message); +size_t wifi_connected_state__pack + (const WifiConnectedState *message, + uint8_t *out); +size_t wifi_connected_state__pack_to_buffer + (const WifiConnectedState *message, + ProtobufCBuffer *buffer); +WifiConnectedState * + wifi_connected_state__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void wifi_connected_state__free_unpacked + (WifiConnectedState *message, + ProtobufCAllocator *allocator); +/* ThreadAttachState methods */ +void thread_attach_state__init + (ThreadAttachState *message); +size_t thread_attach_state__get_packed_size + (const ThreadAttachState *message); +size_t thread_attach_state__pack + (const ThreadAttachState *message, + uint8_t *out); +size_t thread_attach_state__pack_to_buffer + (const ThreadAttachState *message, + ProtobufCBuffer *buffer); +ThreadAttachState * + thread_attach_state__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void thread_attach_state__free_unpacked + (ThreadAttachState *message, + ProtobufCAllocator *allocator); +/* --- per-message closures --- */ + +typedef void (*WifiConnectedState_Closure) + (const WifiConnectedState *message, + void *closure_data); +typedef void (*ThreadAttachState_Closure) + (const ThreadAttachState *message, + void *closure_data); + +/* --- services --- */ + + +/* --- descriptors --- */ + +extern const ProtobufCEnumDescriptor wifi_station_state__descriptor; +extern const ProtobufCEnumDescriptor wifi_connect_failed_reason__descriptor; +extern const ProtobufCEnumDescriptor wifi_auth_mode__descriptor; +extern const ProtobufCEnumDescriptor thread_network_state__descriptor; +extern const ProtobufCEnumDescriptor thread_attach_failed_reason__descriptor; +extern const ProtobufCMessageDescriptor wifi_connected_state__descriptor; +extern const ProtobufCMessageDescriptor thread_attach_state__descriptor; + +PROTOBUF_C__END_DECLS + + +#endif /* PROTOBUF_C_network_5fconstants_2eproto__INCLUDED */ diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/proto-c/network_ctrl.pb-c.c b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/proto-c/network_ctrl.pb-c.c new file mode 100644 index 000000000..423e2a772 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/proto-c/network_ctrl.pb-c.c @@ -0,0 +1,756 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ +/* Generated from: network_ctrl.proto */ + +/* Do not generate deprecated warnings for self */ +#ifndef PROTOBUF_C__NO_DEPRECATED +#define PROTOBUF_C__NO_DEPRECATED +#endif + +#include "network_ctrl.pb-c.h" +void cmd_ctrl_wifi_reset__init + (CmdCtrlWifiReset *message) +{ + static const CmdCtrlWifiReset init_value = CMD_CTRL_WIFI_RESET__INIT; + *message = init_value; +} +size_t cmd_ctrl_wifi_reset__get_packed_size + (const CmdCtrlWifiReset *message) +{ + assert(message->base.descriptor == &cmd_ctrl_wifi_reset__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t cmd_ctrl_wifi_reset__pack + (const CmdCtrlWifiReset *message, + uint8_t *out) +{ + assert(message->base.descriptor == &cmd_ctrl_wifi_reset__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t cmd_ctrl_wifi_reset__pack_to_buffer + (const CmdCtrlWifiReset *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &cmd_ctrl_wifi_reset__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +CmdCtrlWifiReset * + cmd_ctrl_wifi_reset__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (CmdCtrlWifiReset *) + protobuf_c_message_unpack (&cmd_ctrl_wifi_reset__descriptor, + allocator, len, data); +} +void cmd_ctrl_wifi_reset__free_unpacked + (CmdCtrlWifiReset *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &cmd_ctrl_wifi_reset__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void resp_ctrl_wifi_reset__init + (RespCtrlWifiReset *message) +{ + static const RespCtrlWifiReset init_value = RESP_CTRL_WIFI_RESET__INIT; + *message = init_value; +} +size_t resp_ctrl_wifi_reset__get_packed_size + (const RespCtrlWifiReset *message) +{ + assert(message->base.descriptor == &resp_ctrl_wifi_reset__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t resp_ctrl_wifi_reset__pack + (const RespCtrlWifiReset *message, + uint8_t *out) +{ + assert(message->base.descriptor == &resp_ctrl_wifi_reset__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t resp_ctrl_wifi_reset__pack_to_buffer + (const RespCtrlWifiReset *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &resp_ctrl_wifi_reset__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +RespCtrlWifiReset * + resp_ctrl_wifi_reset__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (RespCtrlWifiReset *) + protobuf_c_message_unpack (&resp_ctrl_wifi_reset__descriptor, + allocator, len, data); +} +void resp_ctrl_wifi_reset__free_unpacked + (RespCtrlWifiReset *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &resp_ctrl_wifi_reset__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void cmd_ctrl_wifi_reprov__init + (CmdCtrlWifiReprov *message) +{ + static const CmdCtrlWifiReprov init_value = CMD_CTRL_WIFI_REPROV__INIT; + *message = init_value; +} +size_t cmd_ctrl_wifi_reprov__get_packed_size + (const CmdCtrlWifiReprov *message) +{ + assert(message->base.descriptor == &cmd_ctrl_wifi_reprov__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t cmd_ctrl_wifi_reprov__pack + (const CmdCtrlWifiReprov *message, + uint8_t *out) +{ + assert(message->base.descriptor == &cmd_ctrl_wifi_reprov__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t cmd_ctrl_wifi_reprov__pack_to_buffer + (const CmdCtrlWifiReprov *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &cmd_ctrl_wifi_reprov__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +CmdCtrlWifiReprov * + cmd_ctrl_wifi_reprov__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (CmdCtrlWifiReprov *) + protobuf_c_message_unpack (&cmd_ctrl_wifi_reprov__descriptor, + allocator, len, data); +} +void cmd_ctrl_wifi_reprov__free_unpacked + (CmdCtrlWifiReprov *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &cmd_ctrl_wifi_reprov__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void resp_ctrl_wifi_reprov__init + (RespCtrlWifiReprov *message) +{ + static const RespCtrlWifiReprov init_value = RESP_CTRL_WIFI_REPROV__INIT; + *message = init_value; +} +size_t resp_ctrl_wifi_reprov__get_packed_size + (const RespCtrlWifiReprov *message) +{ + assert(message->base.descriptor == &resp_ctrl_wifi_reprov__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t resp_ctrl_wifi_reprov__pack + (const RespCtrlWifiReprov *message, + uint8_t *out) +{ + assert(message->base.descriptor == &resp_ctrl_wifi_reprov__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t resp_ctrl_wifi_reprov__pack_to_buffer + (const RespCtrlWifiReprov *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &resp_ctrl_wifi_reprov__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +RespCtrlWifiReprov * + resp_ctrl_wifi_reprov__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (RespCtrlWifiReprov *) + protobuf_c_message_unpack (&resp_ctrl_wifi_reprov__descriptor, + allocator, len, data); +} +void resp_ctrl_wifi_reprov__free_unpacked + (RespCtrlWifiReprov *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &resp_ctrl_wifi_reprov__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void cmd_ctrl_thread_reset__init + (CmdCtrlThreadReset *message) +{ + static const CmdCtrlThreadReset init_value = CMD_CTRL_THREAD_RESET__INIT; + *message = init_value; +} +size_t cmd_ctrl_thread_reset__get_packed_size + (const CmdCtrlThreadReset *message) +{ + assert(message->base.descriptor == &cmd_ctrl_thread_reset__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t cmd_ctrl_thread_reset__pack + (const CmdCtrlThreadReset *message, + uint8_t *out) +{ + assert(message->base.descriptor == &cmd_ctrl_thread_reset__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t cmd_ctrl_thread_reset__pack_to_buffer + (const CmdCtrlThreadReset *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &cmd_ctrl_thread_reset__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +CmdCtrlThreadReset * + cmd_ctrl_thread_reset__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (CmdCtrlThreadReset *) + protobuf_c_message_unpack (&cmd_ctrl_thread_reset__descriptor, + allocator, len, data); +} +void cmd_ctrl_thread_reset__free_unpacked + (CmdCtrlThreadReset *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &cmd_ctrl_thread_reset__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void resp_ctrl_thread_reset__init + (RespCtrlThreadReset *message) +{ + static const RespCtrlThreadReset init_value = RESP_CTRL_THREAD_RESET__INIT; + *message = init_value; +} +size_t resp_ctrl_thread_reset__get_packed_size + (const RespCtrlThreadReset *message) +{ + assert(message->base.descriptor == &resp_ctrl_thread_reset__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t resp_ctrl_thread_reset__pack + (const RespCtrlThreadReset *message, + uint8_t *out) +{ + assert(message->base.descriptor == &resp_ctrl_thread_reset__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t resp_ctrl_thread_reset__pack_to_buffer + (const RespCtrlThreadReset *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &resp_ctrl_thread_reset__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +RespCtrlThreadReset * + resp_ctrl_thread_reset__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (RespCtrlThreadReset *) + protobuf_c_message_unpack (&resp_ctrl_thread_reset__descriptor, + allocator, len, data); +} +void resp_ctrl_thread_reset__free_unpacked + (RespCtrlThreadReset *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &resp_ctrl_thread_reset__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void cmd_ctrl_thread_reprov__init + (CmdCtrlThreadReprov *message) +{ + static const CmdCtrlThreadReprov init_value = CMD_CTRL_THREAD_REPROV__INIT; + *message = init_value; +} +size_t cmd_ctrl_thread_reprov__get_packed_size + (const CmdCtrlThreadReprov *message) +{ + assert(message->base.descriptor == &cmd_ctrl_thread_reprov__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t cmd_ctrl_thread_reprov__pack + (const CmdCtrlThreadReprov *message, + uint8_t *out) +{ + assert(message->base.descriptor == &cmd_ctrl_thread_reprov__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t cmd_ctrl_thread_reprov__pack_to_buffer + (const CmdCtrlThreadReprov *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &cmd_ctrl_thread_reprov__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +CmdCtrlThreadReprov * + cmd_ctrl_thread_reprov__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (CmdCtrlThreadReprov *) + protobuf_c_message_unpack (&cmd_ctrl_thread_reprov__descriptor, + allocator, len, data); +} +void cmd_ctrl_thread_reprov__free_unpacked + (CmdCtrlThreadReprov *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &cmd_ctrl_thread_reprov__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void resp_ctrl_thread_reprov__init + (RespCtrlThreadReprov *message) +{ + static const RespCtrlThreadReprov init_value = RESP_CTRL_THREAD_REPROV__INIT; + *message = init_value; +} +size_t resp_ctrl_thread_reprov__get_packed_size + (const RespCtrlThreadReprov *message) +{ + assert(message->base.descriptor == &resp_ctrl_thread_reprov__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t resp_ctrl_thread_reprov__pack + (const RespCtrlThreadReprov *message, + uint8_t *out) +{ + assert(message->base.descriptor == &resp_ctrl_thread_reprov__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t resp_ctrl_thread_reprov__pack_to_buffer + (const RespCtrlThreadReprov *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &resp_ctrl_thread_reprov__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +RespCtrlThreadReprov * + resp_ctrl_thread_reprov__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (RespCtrlThreadReprov *) + protobuf_c_message_unpack (&resp_ctrl_thread_reprov__descriptor, + allocator, len, data); +} +void resp_ctrl_thread_reprov__free_unpacked + (RespCtrlThreadReprov *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &resp_ctrl_thread_reprov__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void network_ctrl_payload__init + (NetworkCtrlPayload *message) +{ + static const NetworkCtrlPayload init_value = NETWORK_CTRL_PAYLOAD__INIT; + *message = init_value; +} +size_t network_ctrl_payload__get_packed_size + (const NetworkCtrlPayload *message) +{ + assert(message->base.descriptor == &network_ctrl_payload__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t network_ctrl_payload__pack + (const NetworkCtrlPayload *message, + uint8_t *out) +{ + assert(message->base.descriptor == &network_ctrl_payload__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t network_ctrl_payload__pack_to_buffer + (const NetworkCtrlPayload *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &network_ctrl_payload__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +NetworkCtrlPayload * + network_ctrl_payload__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (NetworkCtrlPayload *) + protobuf_c_message_unpack (&network_ctrl_payload__descriptor, + allocator, len, data); +} +void network_ctrl_payload__free_unpacked + (NetworkCtrlPayload *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &network_ctrl_payload__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +#define cmd_ctrl_wifi_reset__field_descriptors NULL +#define cmd_ctrl_wifi_reset__field_indices_by_name NULL +#define cmd_ctrl_wifi_reset__number_ranges NULL +const ProtobufCMessageDescriptor cmd_ctrl_wifi_reset__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "CmdCtrlWifiReset", + "CmdCtrlWifiReset", + "CmdCtrlWifiReset", + "", + sizeof(CmdCtrlWifiReset), + 0, + cmd_ctrl_wifi_reset__field_descriptors, + cmd_ctrl_wifi_reset__field_indices_by_name, + 0, cmd_ctrl_wifi_reset__number_ranges, + (ProtobufCMessageInit) cmd_ctrl_wifi_reset__init, + NULL,NULL,NULL /* reserved[123] */ +}; +#define resp_ctrl_wifi_reset__field_descriptors NULL +#define resp_ctrl_wifi_reset__field_indices_by_name NULL +#define resp_ctrl_wifi_reset__number_ranges NULL +const ProtobufCMessageDescriptor resp_ctrl_wifi_reset__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "RespCtrlWifiReset", + "RespCtrlWifiReset", + "RespCtrlWifiReset", + "", + sizeof(RespCtrlWifiReset), + 0, + resp_ctrl_wifi_reset__field_descriptors, + resp_ctrl_wifi_reset__field_indices_by_name, + 0, resp_ctrl_wifi_reset__number_ranges, + (ProtobufCMessageInit) resp_ctrl_wifi_reset__init, + NULL,NULL,NULL /* reserved[123] */ +}; +#define cmd_ctrl_wifi_reprov__field_descriptors NULL +#define cmd_ctrl_wifi_reprov__field_indices_by_name NULL +#define cmd_ctrl_wifi_reprov__number_ranges NULL +const ProtobufCMessageDescriptor cmd_ctrl_wifi_reprov__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "CmdCtrlWifiReprov", + "CmdCtrlWifiReprov", + "CmdCtrlWifiReprov", + "", + sizeof(CmdCtrlWifiReprov), + 0, + cmd_ctrl_wifi_reprov__field_descriptors, + cmd_ctrl_wifi_reprov__field_indices_by_name, + 0, cmd_ctrl_wifi_reprov__number_ranges, + (ProtobufCMessageInit) cmd_ctrl_wifi_reprov__init, + NULL,NULL,NULL /* reserved[123] */ +}; +#define resp_ctrl_wifi_reprov__field_descriptors NULL +#define resp_ctrl_wifi_reprov__field_indices_by_name NULL +#define resp_ctrl_wifi_reprov__number_ranges NULL +const ProtobufCMessageDescriptor resp_ctrl_wifi_reprov__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "RespCtrlWifiReprov", + "RespCtrlWifiReprov", + "RespCtrlWifiReprov", + "", + sizeof(RespCtrlWifiReprov), + 0, + resp_ctrl_wifi_reprov__field_descriptors, + resp_ctrl_wifi_reprov__field_indices_by_name, + 0, resp_ctrl_wifi_reprov__number_ranges, + (ProtobufCMessageInit) resp_ctrl_wifi_reprov__init, + NULL,NULL,NULL /* reserved[123] */ +}; +#define cmd_ctrl_thread_reset__field_descriptors NULL +#define cmd_ctrl_thread_reset__field_indices_by_name NULL +#define cmd_ctrl_thread_reset__number_ranges NULL +const ProtobufCMessageDescriptor cmd_ctrl_thread_reset__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "CmdCtrlThreadReset", + "CmdCtrlThreadReset", + "CmdCtrlThreadReset", + "", + sizeof(CmdCtrlThreadReset), + 0, + cmd_ctrl_thread_reset__field_descriptors, + cmd_ctrl_thread_reset__field_indices_by_name, + 0, cmd_ctrl_thread_reset__number_ranges, + (ProtobufCMessageInit) cmd_ctrl_thread_reset__init, + NULL,NULL,NULL /* reserved[123] */ +}; +#define resp_ctrl_thread_reset__field_descriptors NULL +#define resp_ctrl_thread_reset__field_indices_by_name NULL +#define resp_ctrl_thread_reset__number_ranges NULL +const ProtobufCMessageDescriptor resp_ctrl_thread_reset__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "RespCtrlThreadReset", + "RespCtrlThreadReset", + "RespCtrlThreadReset", + "", + sizeof(RespCtrlThreadReset), + 0, + resp_ctrl_thread_reset__field_descriptors, + resp_ctrl_thread_reset__field_indices_by_name, + 0, resp_ctrl_thread_reset__number_ranges, + (ProtobufCMessageInit) resp_ctrl_thread_reset__init, + NULL,NULL,NULL /* reserved[123] */ +}; +#define cmd_ctrl_thread_reprov__field_descriptors NULL +#define cmd_ctrl_thread_reprov__field_indices_by_name NULL +#define cmd_ctrl_thread_reprov__number_ranges NULL +const ProtobufCMessageDescriptor cmd_ctrl_thread_reprov__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "CmdCtrlThreadReprov", + "CmdCtrlThreadReprov", + "CmdCtrlThreadReprov", + "", + sizeof(CmdCtrlThreadReprov), + 0, + cmd_ctrl_thread_reprov__field_descriptors, + cmd_ctrl_thread_reprov__field_indices_by_name, + 0, cmd_ctrl_thread_reprov__number_ranges, + (ProtobufCMessageInit) cmd_ctrl_thread_reprov__init, + NULL,NULL,NULL /* reserved[123] */ +}; +#define resp_ctrl_thread_reprov__field_descriptors NULL +#define resp_ctrl_thread_reprov__field_indices_by_name NULL +#define resp_ctrl_thread_reprov__number_ranges NULL +const ProtobufCMessageDescriptor resp_ctrl_thread_reprov__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "RespCtrlThreadReprov", + "RespCtrlThreadReprov", + "RespCtrlThreadReprov", + "", + sizeof(RespCtrlThreadReprov), + 0, + resp_ctrl_thread_reprov__field_descriptors, + resp_ctrl_thread_reprov__field_indices_by_name, + 0, resp_ctrl_thread_reprov__number_ranges, + (ProtobufCMessageInit) resp_ctrl_thread_reprov__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor network_ctrl_payload__field_descriptors[10] = +{ + { + "msg", + 1, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_ENUM, + 0, /* quantifier_offset */ + offsetof(NetworkCtrlPayload, msg), + &network_ctrl_msg_type__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "status", + 2, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_ENUM, + 0, /* quantifier_offset */ + offsetof(NetworkCtrlPayload, status), + &status__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "cmd_ctrl_wifi_reset", + 11, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(NetworkCtrlPayload, payload_case), + offsetof(NetworkCtrlPayload, cmd_ctrl_wifi_reset), + &cmd_ctrl_wifi_reset__descriptor, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "resp_ctrl_wifi_reset", + 12, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(NetworkCtrlPayload, payload_case), + offsetof(NetworkCtrlPayload, resp_ctrl_wifi_reset), + &resp_ctrl_wifi_reset__descriptor, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "cmd_ctrl_wifi_reprov", + 13, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(NetworkCtrlPayload, payload_case), + offsetof(NetworkCtrlPayload, cmd_ctrl_wifi_reprov), + &cmd_ctrl_wifi_reprov__descriptor, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "resp_ctrl_wifi_reprov", + 14, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(NetworkCtrlPayload, payload_case), + offsetof(NetworkCtrlPayload, resp_ctrl_wifi_reprov), + &resp_ctrl_wifi_reprov__descriptor, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "cmd_ctrl_thread_reset", + 15, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(NetworkCtrlPayload, payload_case), + offsetof(NetworkCtrlPayload, cmd_ctrl_thread_reset), + &cmd_ctrl_thread_reset__descriptor, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "resp_ctrl_thread_reset", + 16, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(NetworkCtrlPayload, payload_case), + offsetof(NetworkCtrlPayload, resp_ctrl_thread_reset), + &resp_ctrl_thread_reset__descriptor, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "cmd_ctrl_thread_reprov", + 17, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(NetworkCtrlPayload, payload_case), + offsetof(NetworkCtrlPayload, cmd_ctrl_thread_reprov), + &cmd_ctrl_thread_reprov__descriptor, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "resp_ctrl_thread_reprov", + 18, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(NetworkCtrlPayload, payload_case), + offsetof(NetworkCtrlPayload, resp_ctrl_thread_reprov), + &resp_ctrl_thread_reprov__descriptor, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned network_ctrl_payload__field_indices_by_name[] = { + 8, /* field[8] = cmd_ctrl_thread_reprov */ + 6, /* field[6] = cmd_ctrl_thread_reset */ + 4, /* field[4] = cmd_ctrl_wifi_reprov */ + 2, /* field[2] = cmd_ctrl_wifi_reset */ + 0, /* field[0] = msg */ + 9, /* field[9] = resp_ctrl_thread_reprov */ + 7, /* field[7] = resp_ctrl_thread_reset */ + 5, /* field[5] = resp_ctrl_wifi_reprov */ + 3, /* field[3] = resp_ctrl_wifi_reset */ + 1, /* field[1] = status */ +}; +static const ProtobufCIntRange network_ctrl_payload__number_ranges[2 + 1] = +{ + { 1, 0 }, + { 11, 2 }, + { 0, 10 } +}; +const ProtobufCMessageDescriptor network_ctrl_payload__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "NetworkCtrlPayload", + "NetworkCtrlPayload", + "NetworkCtrlPayload", + "", + sizeof(NetworkCtrlPayload), + 10, + network_ctrl_payload__field_descriptors, + network_ctrl_payload__field_indices_by_name, + 2, network_ctrl_payload__number_ranges, + (ProtobufCMessageInit) network_ctrl_payload__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCEnumValue network_ctrl_msg_type__enum_values_by_number[9] = +{ + { "TypeCtrlReserved", "NETWORK_CTRL_MSG_TYPE__TypeCtrlReserved", 0 }, + { "TypeCmdCtrlWifiReset", "NETWORK_CTRL_MSG_TYPE__TypeCmdCtrlWifiReset", 1 }, + { "TypeRespCtrlWifiReset", "NETWORK_CTRL_MSG_TYPE__TypeRespCtrlWifiReset", 2 }, + { "TypeCmdCtrlWifiReprov", "NETWORK_CTRL_MSG_TYPE__TypeCmdCtrlWifiReprov", 3 }, + { "TypeRespCtrlWifiReprov", "NETWORK_CTRL_MSG_TYPE__TypeRespCtrlWifiReprov", 4 }, + { "TypeCmdCtrlThreadReset", "NETWORK_CTRL_MSG_TYPE__TypeCmdCtrlThreadReset", 5 }, + { "TypeRespCtrlThreadReset", "NETWORK_CTRL_MSG_TYPE__TypeRespCtrlThreadReset", 6 }, + { "TypeCmdCtrlThreadReprov", "NETWORK_CTRL_MSG_TYPE__TypeCmdCtrlThreadReprov", 7 }, + { "TypeRespCtrlThreadReprov", "NETWORK_CTRL_MSG_TYPE__TypeRespCtrlThreadReprov", 8 }, +}; +static const ProtobufCIntRange network_ctrl_msg_type__value_ranges[] = { +{0, 0},{0, 9} +}; +static const ProtobufCEnumValueIndex network_ctrl_msg_type__enum_values_by_name[9] = +{ + { "TypeCmdCtrlThreadReprov", 7 }, + { "TypeCmdCtrlThreadReset", 5 }, + { "TypeCmdCtrlWifiReprov", 3 }, + { "TypeCmdCtrlWifiReset", 1 }, + { "TypeCtrlReserved", 0 }, + { "TypeRespCtrlThreadReprov", 8 }, + { "TypeRespCtrlThreadReset", 6 }, + { "TypeRespCtrlWifiReprov", 4 }, + { "TypeRespCtrlWifiReset", 2 }, +}; +const ProtobufCEnumDescriptor network_ctrl_msg_type__descriptor = +{ + PROTOBUF_C__ENUM_DESCRIPTOR_MAGIC, + "NetworkCtrlMsgType", + "NetworkCtrlMsgType", + "NetworkCtrlMsgType", + "", + 9, + network_ctrl_msg_type__enum_values_by_number, + 9, + network_ctrl_msg_type__enum_values_by_name, + 1, + network_ctrl_msg_type__value_ranges, + NULL,NULL,NULL,NULL /* reserved[1234] */ +}; diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/proto-c/network_ctrl.pb-c.h b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/proto-c/network_ctrl.pb-c.h new file mode 100644 index 000000000..3e48f09a4 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/proto-c/network_ctrl.pb-c.h @@ -0,0 +1,374 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ +/* Generated from: network_ctrl.proto */ + +#ifndef PROTOBUF_C_network_5fctrl_2eproto__INCLUDED +#define PROTOBUF_C_network_5fctrl_2eproto__INCLUDED + +#include + +PROTOBUF_C__BEGIN_DECLS + +#if PROTOBUF_C_VERSION_NUMBER < 1003000 +# error This file was generated by a newer version of protoc-c which is incompatible with your libprotobuf-c headers. Please update your headers. +#elif 1004000 < PROTOBUF_C_MIN_COMPILER_VERSION +# error This file was generated by an older version of protoc-c which is incompatible with your libprotobuf-c headers. Please regenerate this file with a newer version of protoc-c. +#endif + +#include "constants.pb-c.h" + +typedef struct CmdCtrlWifiReset CmdCtrlWifiReset; +typedef struct RespCtrlWifiReset RespCtrlWifiReset; +typedef struct CmdCtrlWifiReprov CmdCtrlWifiReprov; +typedef struct RespCtrlWifiReprov RespCtrlWifiReprov; +typedef struct CmdCtrlThreadReset CmdCtrlThreadReset; +typedef struct RespCtrlThreadReset RespCtrlThreadReset; +typedef struct CmdCtrlThreadReprov CmdCtrlThreadReprov; +typedef struct RespCtrlThreadReprov RespCtrlThreadReprov; +typedef struct NetworkCtrlPayload NetworkCtrlPayload; + + +/* --- enums --- */ + +typedef enum _NetworkCtrlMsgType { + NETWORK_CTRL_MSG_TYPE__TypeCtrlReserved = 0, + NETWORK_CTRL_MSG_TYPE__TypeCmdCtrlWifiReset = 1, + NETWORK_CTRL_MSG_TYPE__TypeRespCtrlWifiReset = 2, + NETWORK_CTRL_MSG_TYPE__TypeCmdCtrlWifiReprov = 3, + NETWORK_CTRL_MSG_TYPE__TypeRespCtrlWifiReprov = 4, + NETWORK_CTRL_MSG_TYPE__TypeCmdCtrlThreadReset = 5, + NETWORK_CTRL_MSG_TYPE__TypeRespCtrlThreadReset = 6, + NETWORK_CTRL_MSG_TYPE__TypeCmdCtrlThreadReprov = 7, + NETWORK_CTRL_MSG_TYPE__TypeRespCtrlThreadReprov = 8 + PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE(NETWORK_CTRL_MSG_TYPE) +} NetworkCtrlMsgType; + +/* --- messages --- */ + +struct CmdCtrlWifiReset +{ + ProtobufCMessage base; +}; +#define CMD_CTRL_WIFI_RESET__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&cmd_ctrl_wifi_reset__descriptor) \ + } + + +struct RespCtrlWifiReset +{ + ProtobufCMessage base; +}; +#define RESP_CTRL_WIFI_RESET__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&resp_ctrl_wifi_reset__descriptor) \ + } + + +struct CmdCtrlWifiReprov +{ + ProtobufCMessage base; +}; +#define CMD_CTRL_WIFI_REPROV__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&cmd_ctrl_wifi_reprov__descriptor) \ + } + + +struct RespCtrlWifiReprov +{ + ProtobufCMessage base; +}; +#define RESP_CTRL_WIFI_REPROV__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&resp_ctrl_wifi_reprov__descriptor) \ + } + + +struct CmdCtrlThreadReset +{ + ProtobufCMessage base; +}; +#define CMD_CTRL_THREAD_RESET__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&cmd_ctrl_thread_reset__descriptor) \ + } + + +struct RespCtrlThreadReset +{ + ProtobufCMessage base; +}; +#define RESP_CTRL_THREAD_RESET__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&resp_ctrl_thread_reset__descriptor) \ + } + + +struct CmdCtrlThreadReprov +{ + ProtobufCMessage base; +}; +#define CMD_CTRL_THREAD_REPROV__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&cmd_ctrl_thread_reprov__descriptor) \ + } + + +struct RespCtrlThreadReprov +{ + ProtobufCMessage base; +}; +#define RESP_CTRL_THREAD_REPROV__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&resp_ctrl_thread_reprov__descriptor) \ + } + + +typedef enum { + NETWORK_CTRL_PAYLOAD__PAYLOAD__NOT_SET = 0, + NETWORK_CTRL_PAYLOAD__PAYLOAD_CMD_CTRL_WIFI_RESET = 11, + NETWORK_CTRL_PAYLOAD__PAYLOAD_RESP_CTRL_WIFI_RESET = 12, + NETWORK_CTRL_PAYLOAD__PAYLOAD_CMD_CTRL_WIFI_REPROV = 13, + NETWORK_CTRL_PAYLOAD__PAYLOAD_RESP_CTRL_WIFI_REPROV = 14, + NETWORK_CTRL_PAYLOAD__PAYLOAD_CMD_CTRL_THREAD_RESET = 15, + NETWORK_CTRL_PAYLOAD__PAYLOAD_RESP_CTRL_THREAD_RESET = 16, + NETWORK_CTRL_PAYLOAD__PAYLOAD_CMD_CTRL_THREAD_REPROV = 17, + NETWORK_CTRL_PAYLOAD__PAYLOAD_RESP_CTRL_THREAD_REPROV = 18 + PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE(NETWORK_CTRL_PAYLOAD__PAYLOAD__CASE) +} NetworkCtrlPayload__PayloadCase; + +struct NetworkCtrlPayload +{ + ProtobufCMessage base; + NetworkCtrlMsgType msg; + Status status; + NetworkCtrlPayload__PayloadCase payload_case; + union { + CmdCtrlWifiReset *cmd_ctrl_wifi_reset; + RespCtrlWifiReset *resp_ctrl_wifi_reset; + CmdCtrlWifiReprov *cmd_ctrl_wifi_reprov; + RespCtrlWifiReprov *resp_ctrl_wifi_reprov; + CmdCtrlThreadReset *cmd_ctrl_thread_reset; + RespCtrlThreadReset *resp_ctrl_thread_reset; + CmdCtrlThreadReprov *cmd_ctrl_thread_reprov; + RespCtrlThreadReprov *resp_ctrl_thread_reprov; + }; +}; +#define NETWORK_CTRL_PAYLOAD__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&network_ctrl_payload__descriptor) \ + , NETWORK_CTRL_MSG_TYPE__TypeCtrlReserved, STATUS__Success, NETWORK_CTRL_PAYLOAD__PAYLOAD__NOT_SET, {0} } + + +/* CmdCtrlWifiReset methods */ +void cmd_ctrl_wifi_reset__init + (CmdCtrlWifiReset *message); +size_t cmd_ctrl_wifi_reset__get_packed_size + (const CmdCtrlWifiReset *message); +size_t cmd_ctrl_wifi_reset__pack + (const CmdCtrlWifiReset *message, + uint8_t *out); +size_t cmd_ctrl_wifi_reset__pack_to_buffer + (const CmdCtrlWifiReset *message, + ProtobufCBuffer *buffer); +CmdCtrlWifiReset * + cmd_ctrl_wifi_reset__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void cmd_ctrl_wifi_reset__free_unpacked + (CmdCtrlWifiReset *message, + ProtobufCAllocator *allocator); +/* RespCtrlWifiReset methods */ +void resp_ctrl_wifi_reset__init + (RespCtrlWifiReset *message); +size_t resp_ctrl_wifi_reset__get_packed_size + (const RespCtrlWifiReset *message); +size_t resp_ctrl_wifi_reset__pack + (const RespCtrlWifiReset *message, + uint8_t *out); +size_t resp_ctrl_wifi_reset__pack_to_buffer + (const RespCtrlWifiReset *message, + ProtobufCBuffer *buffer); +RespCtrlWifiReset * + resp_ctrl_wifi_reset__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void resp_ctrl_wifi_reset__free_unpacked + (RespCtrlWifiReset *message, + ProtobufCAllocator *allocator); +/* CmdCtrlWifiReprov methods */ +void cmd_ctrl_wifi_reprov__init + (CmdCtrlWifiReprov *message); +size_t cmd_ctrl_wifi_reprov__get_packed_size + (const CmdCtrlWifiReprov *message); +size_t cmd_ctrl_wifi_reprov__pack + (const CmdCtrlWifiReprov *message, + uint8_t *out); +size_t cmd_ctrl_wifi_reprov__pack_to_buffer + (const CmdCtrlWifiReprov *message, + ProtobufCBuffer *buffer); +CmdCtrlWifiReprov * + cmd_ctrl_wifi_reprov__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void cmd_ctrl_wifi_reprov__free_unpacked + (CmdCtrlWifiReprov *message, + ProtobufCAllocator *allocator); +/* RespCtrlWifiReprov methods */ +void resp_ctrl_wifi_reprov__init + (RespCtrlWifiReprov *message); +size_t resp_ctrl_wifi_reprov__get_packed_size + (const RespCtrlWifiReprov *message); +size_t resp_ctrl_wifi_reprov__pack + (const RespCtrlWifiReprov *message, + uint8_t *out); +size_t resp_ctrl_wifi_reprov__pack_to_buffer + (const RespCtrlWifiReprov *message, + ProtobufCBuffer *buffer); +RespCtrlWifiReprov * + resp_ctrl_wifi_reprov__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void resp_ctrl_wifi_reprov__free_unpacked + (RespCtrlWifiReprov *message, + ProtobufCAllocator *allocator); +/* CmdCtrlThreadReset methods */ +void cmd_ctrl_thread_reset__init + (CmdCtrlThreadReset *message); +size_t cmd_ctrl_thread_reset__get_packed_size + (const CmdCtrlThreadReset *message); +size_t cmd_ctrl_thread_reset__pack + (const CmdCtrlThreadReset *message, + uint8_t *out); +size_t cmd_ctrl_thread_reset__pack_to_buffer + (const CmdCtrlThreadReset *message, + ProtobufCBuffer *buffer); +CmdCtrlThreadReset * + cmd_ctrl_thread_reset__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void cmd_ctrl_thread_reset__free_unpacked + (CmdCtrlThreadReset *message, + ProtobufCAllocator *allocator); +/* RespCtrlThreadReset methods */ +void resp_ctrl_thread_reset__init + (RespCtrlThreadReset *message); +size_t resp_ctrl_thread_reset__get_packed_size + (const RespCtrlThreadReset *message); +size_t resp_ctrl_thread_reset__pack + (const RespCtrlThreadReset *message, + uint8_t *out); +size_t resp_ctrl_thread_reset__pack_to_buffer + (const RespCtrlThreadReset *message, + ProtobufCBuffer *buffer); +RespCtrlThreadReset * + resp_ctrl_thread_reset__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void resp_ctrl_thread_reset__free_unpacked + (RespCtrlThreadReset *message, + ProtobufCAllocator *allocator); +/* CmdCtrlThreadReprov methods */ +void cmd_ctrl_thread_reprov__init + (CmdCtrlThreadReprov *message); +size_t cmd_ctrl_thread_reprov__get_packed_size + (const CmdCtrlThreadReprov *message); +size_t cmd_ctrl_thread_reprov__pack + (const CmdCtrlThreadReprov *message, + uint8_t *out); +size_t cmd_ctrl_thread_reprov__pack_to_buffer + (const CmdCtrlThreadReprov *message, + ProtobufCBuffer *buffer); +CmdCtrlThreadReprov * + cmd_ctrl_thread_reprov__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void cmd_ctrl_thread_reprov__free_unpacked + (CmdCtrlThreadReprov *message, + ProtobufCAllocator *allocator); +/* RespCtrlThreadReprov methods */ +void resp_ctrl_thread_reprov__init + (RespCtrlThreadReprov *message); +size_t resp_ctrl_thread_reprov__get_packed_size + (const RespCtrlThreadReprov *message); +size_t resp_ctrl_thread_reprov__pack + (const RespCtrlThreadReprov *message, + uint8_t *out); +size_t resp_ctrl_thread_reprov__pack_to_buffer + (const RespCtrlThreadReprov *message, + ProtobufCBuffer *buffer); +RespCtrlThreadReprov * + resp_ctrl_thread_reprov__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void resp_ctrl_thread_reprov__free_unpacked + (RespCtrlThreadReprov *message, + ProtobufCAllocator *allocator); +/* NetworkCtrlPayload methods */ +void network_ctrl_payload__init + (NetworkCtrlPayload *message); +size_t network_ctrl_payload__get_packed_size + (const NetworkCtrlPayload *message); +size_t network_ctrl_payload__pack + (const NetworkCtrlPayload *message, + uint8_t *out); +size_t network_ctrl_payload__pack_to_buffer + (const NetworkCtrlPayload *message, + ProtobufCBuffer *buffer); +NetworkCtrlPayload * + network_ctrl_payload__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void network_ctrl_payload__free_unpacked + (NetworkCtrlPayload *message, + ProtobufCAllocator *allocator); +/* --- per-message closures --- */ + +typedef void (*CmdCtrlWifiReset_Closure) + (const CmdCtrlWifiReset *message, + void *closure_data); +typedef void (*RespCtrlWifiReset_Closure) + (const RespCtrlWifiReset *message, + void *closure_data); +typedef void (*CmdCtrlWifiReprov_Closure) + (const CmdCtrlWifiReprov *message, + void *closure_data); +typedef void (*RespCtrlWifiReprov_Closure) + (const RespCtrlWifiReprov *message, + void *closure_data); +typedef void (*CmdCtrlThreadReset_Closure) + (const CmdCtrlThreadReset *message, + void *closure_data); +typedef void (*RespCtrlThreadReset_Closure) + (const RespCtrlThreadReset *message, + void *closure_data); +typedef void (*CmdCtrlThreadReprov_Closure) + (const CmdCtrlThreadReprov *message, + void *closure_data); +typedef void (*RespCtrlThreadReprov_Closure) + (const RespCtrlThreadReprov *message, + void *closure_data); +typedef void (*NetworkCtrlPayload_Closure) + (const NetworkCtrlPayload *message, + void *closure_data); + +/* --- services --- */ + + +/* --- descriptors --- */ + +extern const ProtobufCEnumDescriptor network_ctrl_msg_type__descriptor; +extern const ProtobufCMessageDescriptor cmd_ctrl_wifi_reset__descriptor; +extern const ProtobufCMessageDescriptor resp_ctrl_wifi_reset__descriptor; +extern const ProtobufCMessageDescriptor cmd_ctrl_wifi_reprov__descriptor; +extern const ProtobufCMessageDescriptor resp_ctrl_wifi_reprov__descriptor; +extern const ProtobufCMessageDescriptor cmd_ctrl_thread_reset__descriptor; +extern const ProtobufCMessageDescriptor resp_ctrl_thread_reset__descriptor; +extern const ProtobufCMessageDescriptor cmd_ctrl_thread_reprov__descriptor; +extern const ProtobufCMessageDescriptor resp_ctrl_thread_reprov__descriptor; +extern const ProtobufCMessageDescriptor network_ctrl_payload__descriptor; + +PROTOBUF_C__END_DECLS + + +#endif /* PROTOBUF_C_network_5fctrl_2eproto__INCLUDED */ diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/proto-c/network_scan.pb-c.c b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/proto-c/network_scan.pb-c.c new file mode 100644 index 000000000..0b2a02086 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/proto-c/network_scan.pb-c.c @@ -0,0 +1,1626 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ +/* Generated from: network_scan.proto */ + +/* Do not generate deprecated warnings for self */ +#ifndef PROTOBUF_C__NO_DEPRECATED +#define PROTOBUF_C__NO_DEPRECATED +#endif + +#include "network_scan.pb-c.h" +void cmd_scan_wifi_start__init + (CmdScanWifiStart *message) +{ + static const CmdScanWifiStart init_value = CMD_SCAN_WIFI_START__INIT; + *message = init_value; +} +size_t cmd_scan_wifi_start__get_packed_size + (const CmdScanWifiStart *message) +{ + assert(message->base.descriptor == &cmd_scan_wifi_start__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t cmd_scan_wifi_start__pack + (const CmdScanWifiStart *message, + uint8_t *out) +{ + assert(message->base.descriptor == &cmd_scan_wifi_start__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t cmd_scan_wifi_start__pack_to_buffer + (const CmdScanWifiStart *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &cmd_scan_wifi_start__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +CmdScanWifiStart * + cmd_scan_wifi_start__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (CmdScanWifiStart *) + protobuf_c_message_unpack (&cmd_scan_wifi_start__descriptor, + allocator, len, data); +} +void cmd_scan_wifi_start__free_unpacked + (CmdScanWifiStart *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &cmd_scan_wifi_start__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void cmd_scan_thread_start__init + (CmdScanThreadStart *message) +{ + static const CmdScanThreadStart init_value = CMD_SCAN_THREAD_START__INIT; + *message = init_value; +} +size_t cmd_scan_thread_start__get_packed_size + (const CmdScanThreadStart *message) +{ + assert(message->base.descriptor == &cmd_scan_thread_start__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t cmd_scan_thread_start__pack + (const CmdScanThreadStart *message, + uint8_t *out) +{ + assert(message->base.descriptor == &cmd_scan_thread_start__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t cmd_scan_thread_start__pack_to_buffer + (const CmdScanThreadStart *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &cmd_scan_thread_start__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +CmdScanThreadStart * + cmd_scan_thread_start__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (CmdScanThreadStart *) + protobuf_c_message_unpack (&cmd_scan_thread_start__descriptor, + allocator, len, data); +} +void cmd_scan_thread_start__free_unpacked + (CmdScanThreadStart *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &cmd_scan_thread_start__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void resp_scan_wifi_start__init + (RespScanWifiStart *message) +{ + static const RespScanWifiStart init_value = RESP_SCAN_WIFI_START__INIT; + *message = init_value; +} +size_t resp_scan_wifi_start__get_packed_size + (const RespScanWifiStart *message) +{ + assert(message->base.descriptor == &resp_scan_wifi_start__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t resp_scan_wifi_start__pack + (const RespScanWifiStart *message, + uint8_t *out) +{ + assert(message->base.descriptor == &resp_scan_wifi_start__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t resp_scan_wifi_start__pack_to_buffer + (const RespScanWifiStart *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &resp_scan_wifi_start__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +RespScanWifiStart * + resp_scan_wifi_start__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (RespScanWifiStart *) + protobuf_c_message_unpack (&resp_scan_wifi_start__descriptor, + allocator, len, data); +} +void resp_scan_wifi_start__free_unpacked + (RespScanWifiStart *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &resp_scan_wifi_start__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void resp_scan_thread_start__init + (RespScanThreadStart *message) +{ + static const RespScanThreadStart init_value = RESP_SCAN_THREAD_START__INIT; + *message = init_value; +} +size_t resp_scan_thread_start__get_packed_size + (const RespScanThreadStart *message) +{ + assert(message->base.descriptor == &resp_scan_thread_start__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t resp_scan_thread_start__pack + (const RespScanThreadStart *message, + uint8_t *out) +{ + assert(message->base.descriptor == &resp_scan_thread_start__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t resp_scan_thread_start__pack_to_buffer + (const RespScanThreadStart *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &resp_scan_thread_start__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +RespScanThreadStart * + resp_scan_thread_start__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (RespScanThreadStart *) + protobuf_c_message_unpack (&resp_scan_thread_start__descriptor, + allocator, len, data); +} +void resp_scan_thread_start__free_unpacked + (RespScanThreadStart *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &resp_scan_thread_start__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void cmd_scan_wifi_status__init + (CmdScanWifiStatus *message) +{ + static const CmdScanWifiStatus init_value = CMD_SCAN_WIFI_STATUS__INIT; + *message = init_value; +} +size_t cmd_scan_wifi_status__get_packed_size + (const CmdScanWifiStatus *message) +{ + assert(message->base.descriptor == &cmd_scan_wifi_status__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t cmd_scan_wifi_status__pack + (const CmdScanWifiStatus *message, + uint8_t *out) +{ + assert(message->base.descriptor == &cmd_scan_wifi_status__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t cmd_scan_wifi_status__pack_to_buffer + (const CmdScanWifiStatus *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &cmd_scan_wifi_status__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +CmdScanWifiStatus * + cmd_scan_wifi_status__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (CmdScanWifiStatus *) + protobuf_c_message_unpack (&cmd_scan_wifi_status__descriptor, + allocator, len, data); +} +void cmd_scan_wifi_status__free_unpacked + (CmdScanWifiStatus *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &cmd_scan_wifi_status__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void cmd_scan_thread_status__init + (CmdScanThreadStatus *message) +{ + static const CmdScanThreadStatus init_value = CMD_SCAN_THREAD_STATUS__INIT; + *message = init_value; +} +size_t cmd_scan_thread_status__get_packed_size + (const CmdScanThreadStatus *message) +{ + assert(message->base.descriptor == &cmd_scan_thread_status__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t cmd_scan_thread_status__pack + (const CmdScanThreadStatus *message, + uint8_t *out) +{ + assert(message->base.descriptor == &cmd_scan_thread_status__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t cmd_scan_thread_status__pack_to_buffer + (const CmdScanThreadStatus *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &cmd_scan_thread_status__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +CmdScanThreadStatus * + cmd_scan_thread_status__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (CmdScanThreadStatus *) + protobuf_c_message_unpack (&cmd_scan_thread_status__descriptor, + allocator, len, data); +} +void cmd_scan_thread_status__free_unpacked + (CmdScanThreadStatus *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &cmd_scan_thread_status__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void resp_scan_wifi_status__init + (RespScanWifiStatus *message) +{ + static const RespScanWifiStatus init_value = RESP_SCAN_WIFI_STATUS__INIT; + *message = init_value; +} +size_t resp_scan_wifi_status__get_packed_size + (const RespScanWifiStatus *message) +{ + assert(message->base.descriptor == &resp_scan_wifi_status__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t resp_scan_wifi_status__pack + (const RespScanWifiStatus *message, + uint8_t *out) +{ + assert(message->base.descriptor == &resp_scan_wifi_status__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t resp_scan_wifi_status__pack_to_buffer + (const RespScanWifiStatus *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &resp_scan_wifi_status__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +RespScanWifiStatus * + resp_scan_wifi_status__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (RespScanWifiStatus *) + protobuf_c_message_unpack (&resp_scan_wifi_status__descriptor, + allocator, len, data); +} +void resp_scan_wifi_status__free_unpacked + (RespScanWifiStatus *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &resp_scan_wifi_status__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void resp_scan_thread_status__init + (RespScanThreadStatus *message) +{ + static const RespScanThreadStatus init_value = RESP_SCAN_THREAD_STATUS__INIT; + *message = init_value; +} +size_t resp_scan_thread_status__get_packed_size + (const RespScanThreadStatus *message) +{ + assert(message->base.descriptor == &resp_scan_thread_status__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t resp_scan_thread_status__pack + (const RespScanThreadStatus *message, + uint8_t *out) +{ + assert(message->base.descriptor == &resp_scan_thread_status__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t resp_scan_thread_status__pack_to_buffer + (const RespScanThreadStatus *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &resp_scan_thread_status__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +RespScanThreadStatus * + resp_scan_thread_status__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (RespScanThreadStatus *) + protobuf_c_message_unpack (&resp_scan_thread_status__descriptor, + allocator, len, data); +} +void resp_scan_thread_status__free_unpacked + (RespScanThreadStatus *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &resp_scan_thread_status__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void cmd_scan_wifi_result__init + (CmdScanWifiResult *message) +{ + static const CmdScanWifiResult init_value = CMD_SCAN_WIFI_RESULT__INIT; + *message = init_value; +} +size_t cmd_scan_wifi_result__get_packed_size + (const CmdScanWifiResult *message) +{ + assert(message->base.descriptor == &cmd_scan_wifi_result__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t cmd_scan_wifi_result__pack + (const CmdScanWifiResult *message, + uint8_t *out) +{ + assert(message->base.descriptor == &cmd_scan_wifi_result__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t cmd_scan_wifi_result__pack_to_buffer + (const CmdScanWifiResult *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &cmd_scan_wifi_result__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +CmdScanWifiResult * + cmd_scan_wifi_result__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (CmdScanWifiResult *) + protobuf_c_message_unpack (&cmd_scan_wifi_result__descriptor, + allocator, len, data); +} +void cmd_scan_wifi_result__free_unpacked + (CmdScanWifiResult *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &cmd_scan_wifi_result__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void cmd_scan_thread_result__init + (CmdScanThreadResult *message) +{ + static const CmdScanThreadResult init_value = CMD_SCAN_THREAD_RESULT__INIT; + *message = init_value; +} +size_t cmd_scan_thread_result__get_packed_size + (const CmdScanThreadResult *message) +{ + assert(message->base.descriptor == &cmd_scan_thread_result__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t cmd_scan_thread_result__pack + (const CmdScanThreadResult *message, + uint8_t *out) +{ + assert(message->base.descriptor == &cmd_scan_thread_result__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t cmd_scan_thread_result__pack_to_buffer + (const CmdScanThreadResult *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &cmd_scan_thread_result__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +CmdScanThreadResult * + cmd_scan_thread_result__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (CmdScanThreadResult *) + protobuf_c_message_unpack (&cmd_scan_thread_result__descriptor, + allocator, len, data); +} +void cmd_scan_thread_result__free_unpacked + (CmdScanThreadResult *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &cmd_scan_thread_result__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void wi_fi_scan_result__init + (WiFiScanResult *message) +{ + static const WiFiScanResult init_value = WI_FI_SCAN_RESULT__INIT; + *message = init_value; +} +size_t wi_fi_scan_result__get_packed_size + (const WiFiScanResult *message) +{ + assert(message->base.descriptor == &wi_fi_scan_result__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t wi_fi_scan_result__pack + (const WiFiScanResult *message, + uint8_t *out) +{ + assert(message->base.descriptor == &wi_fi_scan_result__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t wi_fi_scan_result__pack_to_buffer + (const WiFiScanResult *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &wi_fi_scan_result__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +WiFiScanResult * + wi_fi_scan_result__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (WiFiScanResult *) + protobuf_c_message_unpack (&wi_fi_scan_result__descriptor, + allocator, len, data); +} +void wi_fi_scan_result__free_unpacked + (WiFiScanResult *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &wi_fi_scan_result__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void thread_scan_result__init + (ThreadScanResult *message) +{ + static const ThreadScanResult init_value = THREAD_SCAN_RESULT__INIT; + *message = init_value; +} +size_t thread_scan_result__get_packed_size + (const ThreadScanResult *message) +{ + assert(message->base.descriptor == &thread_scan_result__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t thread_scan_result__pack + (const ThreadScanResult *message, + uint8_t *out) +{ + assert(message->base.descriptor == &thread_scan_result__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t thread_scan_result__pack_to_buffer + (const ThreadScanResult *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &thread_scan_result__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +ThreadScanResult * + thread_scan_result__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (ThreadScanResult *) + protobuf_c_message_unpack (&thread_scan_result__descriptor, + allocator, len, data); +} +void thread_scan_result__free_unpacked + (ThreadScanResult *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &thread_scan_result__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void resp_scan_wifi_result__init + (RespScanWifiResult *message) +{ + static const RespScanWifiResult init_value = RESP_SCAN_WIFI_RESULT__INIT; + *message = init_value; +} +size_t resp_scan_wifi_result__get_packed_size + (const RespScanWifiResult *message) +{ + assert(message->base.descriptor == &resp_scan_wifi_result__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t resp_scan_wifi_result__pack + (const RespScanWifiResult *message, + uint8_t *out) +{ + assert(message->base.descriptor == &resp_scan_wifi_result__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t resp_scan_wifi_result__pack_to_buffer + (const RespScanWifiResult *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &resp_scan_wifi_result__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +RespScanWifiResult * + resp_scan_wifi_result__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (RespScanWifiResult *) + protobuf_c_message_unpack (&resp_scan_wifi_result__descriptor, + allocator, len, data); +} +void resp_scan_wifi_result__free_unpacked + (RespScanWifiResult *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &resp_scan_wifi_result__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void resp_scan_thread_result__init + (RespScanThreadResult *message) +{ + static const RespScanThreadResult init_value = RESP_SCAN_THREAD_RESULT__INIT; + *message = init_value; +} +size_t resp_scan_thread_result__get_packed_size + (const RespScanThreadResult *message) +{ + assert(message->base.descriptor == &resp_scan_thread_result__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t resp_scan_thread_result__pack + (const RespScanThreadResult *message, + uint8_t *out) +{ + assert(message->base.descriptor == &resp_scan_thread_result__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t resp_scan_thread_result__pack_to_buffer + (const RespScanThreadResult *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &resp_scan_thread_result__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +RespScanThreadResult * + resp_scan_thread_result__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (RespScanThreadResult *) + protobuf_c_message_unpack (&resp_scan_thread_result__descriptor, + allocator, len, data); +} +void resp_scan_thread_result__free_unpacked + (RespScanThreadResult *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &resp_scan_thread_result__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void network_scan_payload__init + (NetworkScanPayload *message) +{ + static const NetworkScanPayload init_value = NETWORK_SCAN_PAYLOAD__INIT; + *message = init_value; +} +size_t network_scan_payload__get_packed_size + (const NetworkScanPayload *message) +{ + assert(message->base.descriptor == &network_scan_payload__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t network_scan_payload__pack + (const NetworkScanPayload *message, + uint8_t *out) +{ + assert(message->base.descriptor == &network_scan_payload__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t network_scan_payload__pack_to_buffer + (const NetworkScanPayload *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &network_scan_payload__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +NetworkScanPayload * + network_scan_payload__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (NetworkScanPayload *) + protobuf_c_message_unpack (&network_scan_payload__descriptor, + allocator, len, data); +} +void network_scan_payload__free_unpacked + (NetworkScanPayload *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &network_scan_payload__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +static const ProtobufCFieldDescriptor cmd_scan_wifi_start__field_descriptors[4] = +{ + { + "blocking", + 1, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_BOOL, + 0, /* quantifier_offset */ + offsetof(CmdScanWifiStart, blocking), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "passive", + 2, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_BOOL, + 0, /* quantifier_offset */ + offsetof(CmdScanWifiStart, passive), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "group_channels", + 3, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_UINT32, + 0, /* quantifier_offset */ + offsetof(CmdScanWifiStart, group_channels), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "period_ms", + 4, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_UINT32, + 0, /* quantifier_offset */ + offsetof(CmdScanWifiStart, period_ms), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned cmd_scan_wifi_start__field_indices_by_name[] = { + 0, /* field[0] = blocking */ + 2, /* field[2] = group_channels */ + 1, /* field[1] = passive */ + 3, /* field[3] = period_ms */ +}; +static const ProtobufCIntRange cmd_scan_wifi_start__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 4 } +}; +const ProtobufCMessageDescriptor cmd_scan_wifi_start__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "CmdScanWifiStart", + "CmdScanWifiStart", + "CmdScanWifiStart", + "", + sizeof(CmdScanWifiStart), + 4, + cmd_scan_wifi_start__field_descriptors, + cmd_scan_wifi_start__field_indices_by_name, + 1, cmd_scan_wifi_start__number_ranges, + (ProtobufCMessageInit) cmd_scan_wifi_start__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor cmd_scan_thread_start__field_descriptors[2] = +{ + { + "blocking", + 1, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_BOOL, + 0, /* quantifier_offset */ + offsetof(CmdScanThreadStart, blocking), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "channel_mask", + 2, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_UINT32, + 0, /* quantifier_offset */ + offsetof(CmdScanThreadStart, channel_mask), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned cmd_scan_thread_start__field_indices_by_name[] = { + 0, /* field[0] = blocking */ + 1, /* field[1] = channel_mask */ +}; +static const ProtobufCIntRange cmd_scan_thread_start__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 2 } +}; +const ProtobufCMessageDescriptor cmd_scan_thread_start__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "CmdScanThreadStart", + "CmdScanThreadStart", + "CmdScanThreadStart", + "", + sizeof(CmdScanThreadStart), + 2, + cmd_scan_thread_start__field_descriptors, + cmd_scan_thread_start__field_indices_by_name, + 1, cmd_scan_thread_start__number_ranges, + (ProtobufCMessageInit) cmd_scan_thread_start__init, + NULL,NULL,NULL /* reserved[123] */ +}; +#define resp_scan_wifi_start__field_descriptors NULL +#define resp_scan_wifi_start__field_indices_by_name NULL +#define resp_scan_wifi_start__number_ranges NULL +const ProtobufCMessageDescriptor resp_scan_wifi_start__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "RespScanWifiStart", + "RespScanWifiStart", + "RespScanWifiStart", + "", + sizeof(RespScanWifiStart), + 0, + resp_scan_wifi_start__field_descriptors, + resp_scan_wifi_start__field_indices_by_name, + 0, resp_scan_wifi_start__number_ranges, + (ProtobufCMessageInit) resp_scan_wifi_start__init, + NULL,NULL,NULL /* reserved[123] */ +}; +#define resp_scan_thread_start__field_descriptors NULL +#define resp_scan_thread_start__field_indices_by_name NULL +#define resp_scan_thread_start__number_ranges NULL +const ProtobufCMessageDescriptor resp_scan_thread_start__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "RespScanThreadStart", + "RespScanThreadStart", + "RespScanThreadStart", + "", + sizeof(RespScanThreadStart), + 0, + resp_scan_thread_start__field_descriptors, + resp_scan_thread_start__field_indices_by_name, + 0, resp_scan_thread_start__number_ranges, + (ProtobufCMessageInit) resp_scan_thread_start__init, + NULL,NULL,NULL /* reserved[123] */ +}; +#define cmd_scan_wifi_status__field_descriptors NULL +#define cmd_scan_wifi_status__field_indices_by_name NULL +#define cmd_scan_wifi_status__number_ranges NULL +const ProtobufCMessageDescriptor cmd_scan_wifi_status__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "CmdScanWifiStatus", + "CmdScanWifiStatus", + "CmdScanWifiStatus", + "", + sizeof(CmdScanWifiStatus), + 0, + cmd_scan_wifi_status__field_descriptors, + cmd_scan_wifi_status__field_indices_by_name, + 0, cmd_scan_wifi_status__number_ranges, + (ProtobufCMessageInit) cmd_scan_wifi_status__init, + NULL,NULL,NULL /* reserved[123] */ +}; +#define cmd_scan_thread_status__field_descriptors NULL +#define cmd_scan_thread_status__field_indices_by_name NULL +#define cmd_scan_thread_status__number_ranges NULL +const ProtobufCMessageDescriptor cmd_scan_thread_status__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "CmdScanThreadStatus", + "CmdScanThreadStatus", + "CmdScanThreadStatus", + "", + sizeof(CmdScanThreadStatus), + 0, + cmd_scan_thread_status__field_descriptors, + cmd_scan_thread_status__field_indices_by_name, + 0, cmd_scan_thread_status__number_ranges, + (ProtobufCMessageInit) cmd_scan_thread_status__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor resp_scan_wifi_status__field_descriptors[2] = +{ + { + "scan_finished", + 1, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_BOOL, + 0, /* quantifier_offset */ + offsetof(RespScanWifiStatus, scan_finished), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "result_count", + 2, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_UINT32, + 0, /* quantifier_offset */ + offsetof(RespScanWifiStatus, result_count), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned resp_scan_wifi_status__field_indices_by_name[] = { + 1, /* field[1] = result_count */ + 0, /* field[0] = scan_finished */ +}; +static const ProtobufCIntRange resp_scan_wifi_status__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 2 } +}; +const ProtobufCMessageDescriptor resp_scan_wifi_status__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "RespScanWifiStatus", + "RespScanWifiStatus", + "RespScanWifiStatus", + "", + sizeof(RespScanWifiStatus), + 2, + resp_scan_wifi_status__field_descriptors, + resp_scan_wifi_status__field_indices_by_name, + 1, resp_scan_wifi_status__number_ranges, + (ProtobufCMessageInit) resp_scan_wifi_status__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor resp_scan_thread_status__field_descriptors[2] = +{ + { + "scan_finished", + 1, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_BOOL, + 0, /* quantifier_offset */ + offsetof(RespScanThreadStatus, scan_finished), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "result_count", + 2, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_UINT32, + 0, /* quantifier_offset */ + offsetof(RespScanThreadStatus, result_count), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned resp_scan_thread_status__field_indices_by_name[] = { + 1, /* field[1] = result_count */ + 0, /* field[0] = scan_finished */ +}; +static const ProtobufCIntRange resp_scan_thread_status__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 2 } +}; +const ProtobufCMessageDescriptor resp_scan_thread_status__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "RespScanThreadStatus", + "RespScanThreadStatus", + "RespScanThreadStatus", + "", + sizeof(RespScanThreadStatus), + 2, + resp_scan_thread_status__field_descriptors, + resp_scan_thread_status__field_indices_by_name, + 1, resp_scan_thread_status__number_ranges, + (ProtobufCMessageInit) resp_scan_thread_status__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor cmd_scan_wifi_result__field_descriptors[2] = +{ + { + "start_index", + 1, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_UINT32, + 0, /* quantifier_offset */ + offsetof(CmdScanWifiResult, start_index), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "count", + 2, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_UINT32, + 0, /* quantifier_offset */ + offsetof(CmdScanWifiResult, count), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned cmd_scan_wifi_result__field_indices_by_name[] = { + 1, /* field[1] = count */ + 0, /* field[0] = start_index */ +}; +static const ProtobufCIntRange cmd_scan_wifi_result__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 2 } +}; +const ProtobufCMessageDescriptor cmd_scan_wifi_result__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "CmdScanWifiResult", + "CmdScanWifiResult", + "CmdScanWifiResult", + "", + sizeof(CmdScanWifiResult), + 2, + cmd_scan_wifi_result__field_descriptors, + cmd_scan_wifi_result__field_indices_by_name, + 1, cmd_scan_wifi_result__number_ranges, + (ProtobufCMessageInit) cmd_scan_wifi_result__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor cmd_scan_thread_result__field_descriptors[2] = +{ + { + "start_index", + 1, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_UINT32, + 0, /* quantifier_offset */ + offsetof(CmdScanThreadResult, start_index), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "count", + 2, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_UINT32, + 0, /* quantifier_offset */ + offsetof(CmdScanThreadResult, count), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned cmd_scan_thread_result__field_indices_by_name[] = { + 1, /* field[1] = count */ + 0, /* field[0] = start_index */ +}; +static const ProtobufCIntRange cmd_scan_thread_result__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 2 } +}; +const ProtobufCMessageDescriptor cmd_scan_thread_result__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "CmdScanThreadResult", + "CmdScanThreadResult", + "CmdScanThreadResult", + "", + sizeof(CmdScanThreadResult), + 2, + cmd_scan_thread_result__field_descriptors, + cmd_scan_thread_result__field_indices_by_name, + 1, cmd_scan_thread_result__number_ranges, + (ProtobufCMessageInit) cmd_scan_thread_result__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor wi_fi_scan_result__field_descriptors[5] = +{ + { + "ssid", + 1, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_BYTES, + 0, /* quantifier_offset */ + offsetof(WiFiScanResult, ssid), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "channel", + 2, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_UINT32, + 0, /* quantifier_offset */ + offsetof(WiFiScanResult, channel), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "rssi", + 3, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_INT32, + 0, /* quantifier_offset */ + offsetof(WiFiScanResult, rssi), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "bssid", + 4, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_BYTES, + 0, /* quantifier_offset */ + offsetof(WiFiScanResult, bssid), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "auth", + 5, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_ENUM, + 0, /* quantifier_offset */ + offsetof(WiFiScanResult, auth), + &wifi_auth_mode__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned wi_fi_scan_result__field_indices_by_name[] = { + 4, /* field[4] = auth */ + 3, /* field[3] = bssid */ + 1, /* field[1] = channel */ + 2, /* field[2] = rssi */ + 0, /* field[0] = ssid */ +}; +static const ProtobufCIntRange wi_fi_scan_result__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 5 } +}; +const ProtobufCMessageDescriptor wi_fi_scan_result__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "WiFiScanResult", + "WiFiScanResult", + "WiFiScanResult", + "", + sizeof(WiFiScanResult), + 5, + wi_fi_scan_result__field_descriptors, + wi_fi_scan_result__field_indices_by_name, + 1, wi_fi_scan_result__number_ranges, + (ProtobufCMessageInit) wi_fi_scan_result__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor thread_scan_result__field_descriptors[7] = +{ + { + "pan_id", + 1, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_UINT32, + 0, /* quantifier_offset */ + offsetof(ThreadScanResult, pan_id), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "channel", + 2, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_UINT32, + 0, /* quantifier_offset */ + offsetof(ThreadScanResult, channel), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "rssi", + 3, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_INT32, + 0, /* quantifier_offset */ + offsetof(ThreadScanResult, rssi), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "lqi", + 4, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_UINT32, + 0, /* quantifier_offset */ + offsetof(ThreadScanResult, lqi), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "ext_addr", + 5, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_BYTES, + 0, /* quantifier_offset */ + offsetof(ThreadScanResult, ext_addr), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "network_name", + 6, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_STRING, + 0, /* quantifier_offset */ + offsetof(ThreadScanResult, network_name), + NULL, + &protobuf_c_empty_string, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "ext_pan_id", + 7, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_BYTES, + 0, /* quantifier_offset */ + offsetof(ThreadScanResult, ext_pan_id), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned thread_scan_result__field_indices_by_name[] = { + 1, /* field[1] = channel */ + 4, /* field[4] = ext_addr */ + 6, /* field[6] = ext_pan_id */ + 3, /* field[3] = lqi */ + 5, /* field[5] = network_name */ + 0, /* field[0] = pan_id */ + 2, /* field[2] = rssi */ +}; +static const ProtobufCIntRange thread_scan_result__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 7 } +}; +const ProtobufCMessageDescriptor thread_scan_result__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "ThreadScanResult", + "ThreadScanResult", + "ThreadScanResult", + "", + sizeof(ThreadScanResult), + 7, + thread_scan_result__field_descriptors, + thread_scan_result__field_indices_by_name, + 1, thread_scan_result__number_ranges, + (ProtobufCMessageInit) thread_scan_result__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor resp_scan_wifi_result__field_descriptors[1] = +{ + { + "entries", + 1, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(RespScanWifiResult, n_entries), + offsetof(RespScanWifiResult, entries), + &wi_fi_scan_result__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned resp_scan_wifi_result__field_indices_by_name[] = { + 0, /* field[0] = entries */ +}; +static const ProtobufCIntRange resp_scan_wifi_result__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 1 } +}; +const ProtobufCMessageDescriptor resp_scan_wifi_result__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "RespScanWifiResult", + "RespScanWifiResult", + "RespScanWifiResult", + "", + sizeof(RespScanWifiResult), + 1, + resp_scan_wifi_result__field_descriptors, + resp_scan_wifi_result__field_indices_by_name, + 1, resp_scan_wifi_result__number_ranges, + (ProtobufCMessageInit) resp_scan_wifi_result__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor resp_scan_thread_result__field_descriptors[1] = +{ + { + "entries", + 1, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(RespScanThreadResult, n_entries), + offsetof(RespScanThreadResult, entries), + &thread_scan_result__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned resp_scan_thread_result__field_indices_by_name[] = { + 0, /* field[0] = entries */ +}; +static const ProtobufCIntRange resp_scan_thread_result__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 1 } +}; +const ProtobufCMessageDescriptor resp_scan_thread_result__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "RespScanThreadResult", + "RespScanThreadResult", + "RespScanThreadResult", + "", + sizeof(RespScanThreadResult), + 1, + resp_scan_thread_result__field_descriptors, + resp_scan_thread_result__field_indices_by_name, + 1, resp_scan_thread_result__number_ranges, + (ProtobufCMessageInit) resp_scan_thread_result__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor network_scan_payload__field_descriptors[14] = +{ + { + "msg", + 1, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_ENUM, + 0, /* quantifier_offset */ + offsetof(NetworkScanPayload, msg), + &network_scan_msg_type__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "status", + 2, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_ENUM, + 0, /* quantifier_offset */ + offsetof(NetworkScanPayload, status), + &status__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "cmd_scan_wifi_start", + 10, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(NetworkScanPayload, payload_case), + offsetof(NetworkScanPayload, cmd_scan_wifi_start), + &cmd_scan_wifi_start__descriptor, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "resp_scan_wifi_start", + 11, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(NetworkScanPayload, payload_case), + offsetof(NetworkScanPayload, resp_scan_wifi_start), + &resp_scan_wifi_start__descriptor, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "cmd_scan_wifi_status", + 12, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(NetworkScanPayload, payload_case), + offsetof(NetworkScanPayload, cmd_scan_wifi_status), + &cmd_scan_wifi_status__descriptor, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "resp_scan_wifi_status", + 13, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(NetworkScanPayload, payload_case), + offsetof(NetworkScanPayload, resp_scan_wifi_status), + &resp_scan_wifi_status__descriptor, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "cmd_scan_wifi_result", + 14, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(NetworkScanPayload, payload_case), + offsetof(NetworkScanPayload, cmd_scan_wifi_result), + &cmd_scan_wifi_result__descriptor, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "resp_scan_wifi_result", + 15, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(NetworkScanPayload, payload_case), + offsetof(NetworkScanPayload, resp_scan_wifi_result), + &resp_scan_wifi_result__descriptor, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "cmd_scan_thread_start", + 16, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(NetworkScanPayload, payload_case), + offsetof(NetworkScanPayload, cmd_scan_thread_start), + &cmd_scan_thread_start__descriptor, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "resp_scan_thread_start", + 17, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(NetworkScanPayload, payload_case), + offsetof(NetworkScanPayload, resp_scan_thread_start), + &resp_scan_thread_start__descriptor, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "cmd_scan_thread_status", + 18, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(NetworkScanPayload, payload_case), + offsetof(NetworkScanPayload, cmd_scan_thread_status), + &cmd_scan_thread_status__descriptor, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "resp_scan_thread_status", + 19, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(NetworkScanPayload, payload_case), + offsetof(NetworkScanPayload, resp_scan_thread_status), + &resp_scan_thread_status__descriptor, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "cmd_scan_thread_result", + 20, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(NetworkScanPayload, payload_case), + offsetof(NetworkScanPayload, cmd_scan_thread_result), + &cmd_scan_thread_result__descriptor, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "resp_scan_thread_result", + 21, + PROTOBUF_C_LABEL_NONE, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(NetworkScanPayload, payload_case), + offsetof(NetworkScanPayload, resp_scan_thread_result), + &resp_scan_thread_result__descriptor, + NULL, + 0 | PROTOBUF_C_FIELD_FLAG_ONEOF, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned network_scan_payload__field_indices_by_name[] = { + 12, /* field[12] = cmd_scan_thread_result */ + 8, /* field[8] = cmd_scan_thread_start */ + 10, /* field[10] = cmd_scan_thread_status */ + 6, /* field[6] = cmd_scan_wifi_result */ + 2, /* field[2] = cmd_scan_wifi_start */ + 4, /* field[4] = cmd_scan_wifi_status */ + 0, /* field[0] = msg */ + 13, /* field[13] = resp_scan_thread_result */ + 9, /* field[9] = resp_scan_thread_start */ + 11, /* field[11] = resp_scan_thread_status */ + 7, /* field[7] = resp_scan_wifi_result */ + 3, /* field[3] = resp_scan_wifi_start */ + 5, /* field[5] = resp_scan_wifi_status */ + 1, /* field[1] = status */ +}; +static const ProtobufCIntRange network_scan_payload__number_ranges[2 + 1] = +{ + { 1, 0 }, + { 10, 2 }, + { 0, 14 } +}; +const ProtobufCMessageDescriptor network_scan_payload__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "NetworkScanPayload", + "NetworkScanPayload", + "NetworkScanPayload", + "", + sizeof(NetworkScanPayload), + 14, + network_scan_payload__field_descriptors, + network_scan_payload__field_indices_by_name, + 2, network_scan_payload__number_ranges, + (ProtobufCMessageInit) network_scan_payload__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCEnumValue network_scan_msg_type__enum_values_by_number[12] = +{ + { "TypeCmdScanWifiStart", "NETWORK_SCAN_MSG_TYPE__TypeCmdScanWifiStart", 0 }, + { "TypeRespScanWifiStart", "NETWORK_SCAN_MSG_TYPE__TypeRespScanWifiStart", 1 }, + { "TypeCmdScanWifiStatus", "NETWORK_SCAN_MSG_TYPE__TypeCmdScanWifiStatus", 2 }, + { "TypeRespScanWifiStatus", "NETWORK_SCAN_MSG_TYPE__TypeRespScanWifiStatus", 3 }, + { "TypeCmdScanWifiResult", "NETWORK_SCAN_MSG_TYPE__TypeCmdScanWifiResult", 4 }, + { "TypeRespScanWifiResult", "NETWORK_SCAN_MSG_TYPE__TypeRespScanWifiResult", 5 }, + { "TypeCmdScanThreadStart", "NETWORK_SCAN_MSG_TYPE__TypeCmdScanThreadStart", 6 }, + { "TypeRespScanThreadStart", "NETWORK_SCAN_MSG_TYPE__TypeRespScanThreadStart", 7 }, + { "TypeCmdScanThreadStatus", "NETWORK_SCAN_MSG_TYPE__TypeCmdScanThreadStatus", 8 }, + { "TypeRespScanThreadStatus", "NETWORK_SCAN_MSG_TYPE__TypeRespScanThreadStatus", 9 }, + { "TypeCmdScanThreadResult", "NETWORK_SCAN_MSG_TYPE__TypeCmdScanThreadResult", 10 }, + { "TypeRespScanThreadResult", "NETWORK_SCAN_MSG_TYPE__TypeRespScanThreadResult", 11 }, +}; +static const ProtobufCIntRange network_scan_msg_type__value_ranges[] = { +{0, 0},{0, 12} +}; +static const ProtobufCEnumValueIndex network_scan_msg_type__enum_values_by_name[12] = +{ + { "TypeCmdScanThreadResult", 10 }, + { "TypeCmdScanThreadStart", 6 }, + { "TypeCmdScanThreadStatus", 8 }, + { "TypeCmdScanWifiResult", 4 }, + { "TypeCmdScanWifiStart", 0 }, + { "TypeCmdScanWifiStatus", 2 }, + { "TypeRespScanThreadResult", 11 }, + { "TypeRespScanThreadStart", 7 }, + { "TypeRespScanThreadStatus", 9 }, + { "TypeRespScanWifiResult", 5 }, + { "TypeRespScanWifiStart", 1 }, + { "TypeRespScanWifiStatus", 3 }, +}; +const ProtobufCEnumDescriptor network_scan_msg_type__descriptor = +{ + PROTOBUF_C__ENUM_DESCRIPTOR_MAGIC, + "NetworkScanMsgType", + "NetworkScanMsgType", + "NetworkScanMsgType", + "", + 12, + network_scan_msg_type__enum_values_by_number, + 12, + network_scan_msg_type__enum_values_by_name, + 1, + network_scan_msg_type__value_ranges, + NULL,NULL,NULL,NULL /* reserved[1234] */ +}; diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/proto-c/network_scan.pb-c.h b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/proto-c/network_scan.pb-c.h new file mode 100644 index 000000000..37c79b9a7 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/proto-c/network_scan.pb-c.h @@ -0,0 +1,614 @@ +/* Generated by the protocol buffer compiler. DO NOT EDIT! */ +/* Generated from: network_scan.proto */ + +#ifndef PROTOBUF_C_network_5fscan_2eproto__INCLUDED +#define PROTOBUF_C_network_5fscan_2eproto__INCLUDED + +#include + +PROTOBUF_C__BEGIN_DECLS + +#if PROTOBUF_C_VERSION_NUMBER < 1003000 +# error This file was generated by a newer version of protoc-c which is incompatible with your libprotobuf-c headers. Please update your headers. +#elif 1004000 < PROTOBUF_C_MIN_COMPILER_VERSION +# error This file was generated by an older version of protoc-c which is incompatible with your libprotobuf-c headers. Please regenerate this file with a newer version of protoc-c. +#endif + +#include "constants.pb-c.h" +#include "network_constants.pb-c.h" + +typedef struct CmdScanWifiStart CmdScanWifiStart; +typedef struct CmdScanThreadStart CmdScanThreadStart; +typedef struct RespScanWifiStart RespScanWifiStart; +typedef struct RespScanThreadStart RespScanThreadStart; +typedef struct CmdScanWifiStatus CmdScanWifiStatus; +typedef struct CmdScanThreadStatus CmdScanThreadStatus; +typedef struct RespScanWifiStatus RespScanWifiStatus; +typedef struct RespScanThreadStatus RespScanThreadStatus; +typedef struct CmdScanWifiResult CmdScanWifiResult; +typedef struct CmdScanThreadResult CmdScanThreadResult; +typedef struct WiFiScanResult WiFiScanResult; +typedef struct ThreadScanResult ThreadScanResult; +typedef struct RespScanWifiResult RespScanWifiResult; +typedef struct RespScanThreadResult RespScanThreadResult; +typedef struct NetworkScanPayload NetworkScanPayload; + + +/* --- enums --- */ + +typedef enum _NetworkScanMsgType { + NETWORK_SCAN_MSG_TYPE__TypeCmdScanWifiStart = 0, + NETWORK_SCAN_MSG_TYPE__TypeRespScanWifiStart = 1, + NETWORK_SCAN_MSG_TYPE__TypeCmdScanWifiStatus = 2, + NETWORK_SCAN_MSG_TYPE__TypeRespScanWifiStatus = 3, + NETWORK_SCAN_MSG_TYPE__TypeCmdScanWifiResult = 4, + NETWORK_SCAN_MSG_TYPE__TypeRespScanWifiResult = 5, + NETWORK_SCAN_MSG_TYPE__TypeCmdScanThreadStart = 6, + NETWORK_SCAN_MSG_TYPE__TypeRespScanThreadStart = 7, + NETWORK_SCAN_MSG_TYPE__TypeCmdScanThreadStatus = 8, + NETWORK_SCAN_MSG_TYPE__TypeRespScanThreadStatus = 9, + NETWORK_SCAN_MSG_TYPE__TypeCmdScanThreadResult = 10, + NETWORK_SCAN_MSG_TYPE__TypeRespScanThreadResult = 11 + PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE(NETWORK_SCAN_MSG_TYPE) +} NetworkScanMsgType; + +/* --- messages --- */ + +struct CmdScanWifiStart +{ + ProtobufCMessage base; + protobuf_c_boolean blocking; + protobuf_c_boolean passive; + uint32_t group_channels; + uint32_t period_ms; +}; +#define CMD_SCAN_WIFI_START__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&cmd_scan_wifi_start__descriptor) \ + , 0, 0, 0, 0 } + + +struct CmdScanThreadStart +{ + ProtobufCMessage base; + protobuf_c_boolean blocking; + uint32_t channel_mask; +}; +#define CMD_SCAN_THREAD_START__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&cmd_scan_thread_start__descriptor) \ + , 0, 0 } + + +struct RespScanWifiStart +{ + ProtobufCMessage base; +}; +#define RESP_SCAN_WIFI_START__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&resp_scan_wifi_start__descriptor) \ + } + + +struct RespScanThreadStart +{ + ProtobufCMessage base; +}; +#define RESP_SCAN_THREAD_START__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&resp_scan_thread_start__descriptor) \ + } + + +struct CmdScanWifiStatus +{ + ProtobufCMessage base; +}; +#define CMD_SCAN_WIFI_STATUS__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&cmd_scan_wifi_status__descriptor) \ + } + + +struct CmdScanThreadStatus +{ + ProtobufCMessage base; +}; +#define CMD_SCAN_THREAD_STATUS__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&cmd_scan_thread_status__descriptor) \ + } + + +struct RespScanWifiStatus +{ + ProtobufCMessage base; + protobuf_c_boolean scan_finished; + uint32_t result_count; +}; +#define RESP_SCAN_WIFI_STATUS__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&resp_scan_wifi_status__descriptor) \ + , 0, 0 } + + +struct RespScanThreadStatus +{ + ProtobufCMessage base; + protobuf_c_boolean scan_finished; + uint32_t result_count; +}; +#define RESP_SCAN_THREAD_STATUS__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&resp_scan_thread_status__descriptor) \ + , 0, 0 } + + +struct CmdScanWifiResult +{ + ProtobufCMessage base; + uint32_t start_index; + uint32_t count; +}; +#define CMD_SCAN_WIFI_RESULT__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&cmd_scan_wifi_result__descriptor) \ + , 0, 0 } + + +struct CmdScanThreadResult +{ + ProtobufCMessage base; + uint32_t start_index; + uint32_t count; +}; +#define CMD_SCAN_THREAD_RESULT__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&cmd_scan_thread_result__descriptor) \ + , 0, 0 } + + +struct WiFiScanResult +{ + ProtobufCMessage base; + ProtobufCBinaryData ssid; + uint32_t channel; + int32_t rssi; + ProtobufCBinaryData bssid; + WifiAuthMode auth; +}; +#define WI_FI_SCAN_RESULT__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&wi_fi_scan_result__descriptor) \ + , {0,NULL}, 0, 0, {0,NULL}, WIFI_AUTH_MODE__Open } + + +struct ThreadScanResult +{ + ProtobufCMessage base; + uint32_t pan_id; + uint32_t channel; + int32_t rssi; + uint32_t lqi; + ProtobufCBinaryData ext_addr; + char *network_name; + ProtobufCBinaryData ext_pan_id; +}; +#define THREAD_SCAN_RESULT__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&thread_scan_result__descriptor) \ + , 0, 0, 0, 0, {0,NULL}, (char *)protobuf_c_empty_string, {0,NULL} } + + +struct RespScanWifiResult +{ + ProtobufCMessage base; + size_t n_entries; + WiFiScanResult **entries; +}; +#define RESP_SCAN_WIFI_RESULT__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&resp_scan_wifi_result__descriptor) \ + , 0,NULL } + + +struct RespScanThreadResult +{ + ProtobufCMessage base; + size_t n_entries; + ThreadScanResult **entries; +}; +#define RESP_SCAN_THREAD_RESULT__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&resp_scan_thread_result__descriptor) \ + , 0,NULL } + + +typedef enum { + NETWORK_SCAN_PAYLOAD__PAYLOAD__NOT_SET = 0, + NETWORK_SCAN_PAYLOAD__PAYLOAD_CMD_SCAN_WIFI_START = 10, + NETWORK_SCAN_PAYLOAD__PAYLOAD_RESP_SCAN_WIFI_START = 11, + NETWORK_SCAN_PAYLOAD__PAYLOAD_CMD_SCAN_WIFI_STATUS = 12, + NETWORK_SCAN_PAYLOAD__PAYLOAD_RESP_SCAN_WIFI_STATUS = 13, + NETWORK_SCAN_PAYLOAD__PAYLOAD_CMD_SCAN_WIFI_RESULT = 14, + NETWORK_SCAN_PAYLOAD__PAYLOAD_RESP_SCAN_WIFI_RESULT = 15, + NETWORK_SCAN_PAYLOAD__PAYLOAD_CMD_SCAN_THREAD_START = 16, + NETWORK_SCAN_PAYLOAD__PAYLOAD_RESP_SCAN_THREAD_START = 17, + NETWORK_SCAN_PAYLOAD__PAYLOAD_CMD_SCAN_THREAD_STATUS = 18, + NETWORK_SCAN_PAYLOAD__PAYLOAD_RESP_SCAN_THREAD_STATUS = 19, + NETWORK_SCAN_PAYLOAD__PAYLOAD_CMD_SCAN_THREAD_RESULT = 20, + NETWORK_SCAN_PAYLOAD__PAYLOAD_RESP_SCAN_THREAD_RESULT = 21 + PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE(NETWORK_SCAN_PAYLOAD__PAYLOAD__CASE) +} NetworkScanPayload__PayloadCase; + +struct NetworkScanPayload +{ + ProtobufCMessage base; + NetworkScanMsgType msg; + Status status; + NetworkScanPayload__PayloadCase payload_case; + union { + CmdScanWifiStart *cmd_scan_wifi_start; + RespScanWifiStart *resp_scan_wifi_start; + CmdScanWifiStatus *cmd_scan_wifi_status; + RespScanWifiStatus *resp_scan_wifi_status; + CmdScanWifiResult *cmd_scan_wifi_result; + RespScanWifiResult *resp_scan_wifi_result; + CmdScanThreadStart *cmd_scan_thread_start; + RespScanThreadStart *resp_scan_thread_start; + CmdScanThreadStatus *cmd_scan_thread_status; + RespScanThreadStatus *resp_scan_thread_status; + CmdScanThreadResult *cmd_scan_thread_result; + RespScanThreadResult *resp_scan_thread_result; + }; +}; +#define NETWORK_SCAN_PAYLOAD__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&network_scan_payload__descriptor) \ + , NETWORK_SCAN_MSG_TYPE__TypeCmdScanWifiStart, STATUS__Success, NETWORK_SCAN_PAYLOAD__PAYLOAD__NOT_SET, {0} } + + +/* CmdScanWifiStart methods */ +void cmd_scan_wifi_start__init + (CmdScanWifiStart *message); +size_t cmd_scan_wifi_start__get_packed_size + (const CmdScanWifiStart *message); +size_t cmd_scan_wifi_start__pack + (const CmdScanWifiStart *message, + uint8_t *out); +size_t cmd_scan_wifi_start__pack_to_buffer + (const CmdScanWifiStart *message, + ProtobufCBuffer *buffer); +CmdScanWifiStart * + cmd_scan_wifi_start__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void cmd_scan_wifi_start__free_unpacked + (CmdScanWifiStart *message, + ProtobufCAllocator *allocator); +/* CmdScanThreadStart methods */ +void cmd_scan_thread_start__init + (CmdScanThreadStart *message); +size_t cmd_scan_thread_start__get_packed_size + (const CmdScanThreadStart *message); +size_t cmd_scan_thread_start__pack + (const CmdScanThreadStart *message, + uint8_t *out); +size_t cmd_scan_thread_start__pack_to_buffer + (const CmdScanThreadStart *message, + ProtobufCBuffer *buffer); +CmdScanThreadStart * + cmd_scan_thread_start__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void cmd_scan_thread_start__free_unpacked + (CmdScanThreadStart *message, + ProtobufCAllocator *allocator); +/* RespScanWifiStart methods */ +void resp_scan_wifi_start__init + (RespScanWifiStart *message); +size_t resp_scan_wifi_start__get_packed_size + (const RespScanWifiStart *message); +size_t resp_scan_wifi_start__pack + (const RespScanWifiStart *message, + uint8_t *out); +size_t resp_scan_wifi_start__pack_to_buffer + (const RespScanWifiStart *message, + ProtobufCBuffer *buffer); +RespScanWifiStart * + resp_scan_wifi_start__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void resp_scan_wifi_start__free_unpacked + (RespScanWifiStart *message, + ProtobufCAllocator *allocator); +/* RespScanThreadStart methods */ +void resp_scan_thread_start__init + (RespScanThreadStart *message); +size_t resp_scan_thread_start__get_packed_size + (const RespScanThreadStart *message); +size_t resp_scan_thread_start__pack + (const RespScanThreadStart *message, + uint8_t *out); +size_t resp_scan_thread_start__pack_to_buffer + (const RespScanThreadStart *message, + ProtobufCBuffer *buffer); +RespScanThreadStart * + resp_scan_thread_start__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void resp_scan_thread_start__free_unpacked + (RespScanThreadStart *message, + ProtobufCAllocator *allocator); +/* CmdScanWifiStatus methods */ +void cmd_scan_wifi_status__init + (CmdScanWifiStatus *message); +size_t cmd_scan_wifi_status__get_packed_size + (const CmdScanWifiStatus *message); +size_t cmd_scan_wifi_status__pack + (const CmdScanWifiStatus *message, + uint8_t *out); +size_t cmd_scan_wifi_status__pack_to_buffer + (const CmdScanWifiStatus *message, + ProtobufCBuffer *buffer); +CmdScanWifiStatus * + cmd_scan_wifi_status__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void cmd_scan_wifi_status__free_unpacked + (CmdScanWifiStatus *message, + ProtobufCAllocator *allocator); +/* CmdScanThreadStatus methods */ +void cmd_scan_thread_status__init + (CmdScanThreadStatus *message); +size_t cmd_scan_thread_status__get_packed_size + (const CmdScanThreadStatus *message); +size_t cmd_scan_thread_status__pack + (const CmdScanThreadStatus *message, + uint8_t *out); +size_t cmd_scan_thread_status__pack_to_buffer + (const CmdScanThreadStatus *message, + ProtobufCBuffer *buffer); +CmdScanThreadStatus * + cmd_scan_thread_status__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void cmd_scan_thread_status__free_unpacked + (CmdScanThreadStatus *message, + ProtobufCAllocator *allocator); +/* RespScanWifiStatus methods */ +void resp_scan_wifi_status__init + (RespScanWifiStatus *message); +size_t resp_scan_wifi_status__get_packed_size + (const RespScanWifiStatus *message); +size_t resp_scan_wifi_status__pack + (const RespScanWifiStatus *message, + uint8_t *out); +size_t resp_scan_wifi_status__pack_to_buffer + (const RespScanWifiStatus *message, + ProtobufCBuffer *buffer); +RespScanWifiStatus * + resp_scan_wifi_status__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void resp_scan_wifi_status__free_unpacked + (RespScanWifiStatus *message, + ProtobufCAllocator *allocator); +/* RespScanThreadStatus methods */ +void resp_scan_thread_status__init + (RespScanThreadStatus *message); +size_t resp_scan_thread_status__get_packed_size + (const RespScanThreadStatus *message); +size_t resp_scan_thread_status__pack + (const RespScanThreadStatus *message, + uint8_t *out); +size_t resp_scan_thread_status__pack_to_buffer + (const RespScanThreadStatus *message, + ProtobufCBuffer *buffer); +RespScanThreadStatus * + resp_scan_thread_status__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void resp_scan_thread_status__free_unpacked + (RespScanThreadStatus *message, + ProtobufCAllocator *allocator); +/* CmdScanWifiResult methods */ +void cmd_scan_wifi_result__init + (CmdScanWifiResult *message); +size_t cmd_scan_wifi_result__get_packed_size + (const CmdScanWifiResult *message); +size_t cmd_scan_wifi_result__pack + (const CmdScanWifiResult *message, + uint8_t *out); +size_t cmd_scan_wifi_result__pack_to_buffer + (const CmdScanWifiResult *message, + ProtobufCBuffer *buffer); +CmdScanWifiResult * + cmd_scan_wifi_result__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void cmd_scan_wifi_result__free_unpacked + (CmdScanWifiResult *message, + ProtobufCAllocator *allocator); +/* CmdScanThreadResult methods */ +void cmd_scan_thread_result__init + (CmdScanThreadResult *message); +size_t cmd_scan_thread_result__get_packed_size + (const CmdScanThreadResult *message); +size_t cmd_scan_thread_result__pack + (const CmdScanThreadResult *message, + uint8_t *out); +size_t cmd_scan_thread_result__pack_to_buffer + (const CmdScanThreadResult *message, + ProtobufCBuffer *buffer); +CmdScanThreadResult * + cmd_scan_thread_result__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void cmd_scan_thread_result__free_unpacked + (CmdScanThreadResult *message, + ProtobufCAllocator *allocator); +/* WiFiScanResult methods */ +void wi_fi_scan_result__init + (WiFiScanResult *message); +size_t wi_fi_scan_result__get_packed_size + (const WiFiScanResult *message); +size_t wi_fi_scan_result__pack + (const WiFiScanResult *message, + uint8_t *out); +size_t wi_fi_scan_result__pack_to_buffer + (const WiFiScanResult *message, + ProtobufCBuffer *buffer); +WiFiScanResult * + wi_fi_scan_result__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void wi_fi_scan_result__free_unpacked + (WiFiScanResult *message, + ProtobufCAllocator *allocator); +/* ThreadScanResult methods */ +void thread_scan_result__init + (ThreadScanResult *message); +size_t thread_scan_result__get_packed_size + (const ThreadScanResult *message); +size_t thread_scan_result__pack + (const ThreadScanResult *message, + uint8_t *out); +size_t thread_scan_result__pack_to_buffer + (const ThreadScanResult *message, + ProtobufCBuffer *buffer); +ThreadScanResult * + thread_scan_result__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void thread_scan_result__free_unpacked + (ThreadScanResult *message, + ProtobufCAllocator *allocator); +/* RespScanWifiResult methods */ +void resp_scan_wifi_result__init + (RespScanWifiResult *message); +size_t resp_scan_wifi_result__get_packed_size + (const RespScanWifiResult *message); +size_t resp_scan_wifi_result__pack + (const RespScanWifiResult *message, + uint8_t *out); +size_t resp_scan_wifi_result__pack_to_buffer + (const RespScanWifiResult *message, + ProtobufCBuffer *buffer); +RespScanWifiResult * + resp_scan_wifi_result__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void resp_scan_wifi_result__free_unpacked + (RespScanWifiResult *message, + ProtobufCAllocator *allocator); +/* RespScanThreadResult methods */ +void resp_scan_thread_result__init + (RespScanThreadResult *message); +size_t resp_scan_thread_result__get_packed_size + (const RespScanThreadResult *message); +size_t resp_scan_thread_result__pack + (const RespScanThreadResult *message, + uint8_t *out); +size_t resp_scan_thread_result__pack_to_buffer + (const RespScanThreadResult *message, + ProtobufCBuffer *buffer); +RespScanThreadResult * + resp_scan_thread_result__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void resp_scan_thread_result__free_unpacked + (RespScanThreadResult *message, + ProtobufCAllocator *allocator); +/* NetworkScanPayload methods */ +void network_scan_payload__init + (NetworkScanPayload *message); +size_t network_scan_payload__get_packed_size + (const NetworkScanPayload *message); +size_t network_scan_payload__pack + (const NetworkScanPayload *message, + uint8_t *out); +size_t network_scan_payload__pack_to_buffer + (const NetworkScanPayload *message, + ProtobufCBuffer *buffer); +NetworkScanPayload * + network_scan_payload__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void network_scan_payload__free_unpacked + (NetworkScanPayload *message, + ProtobufCAllocator *allocator); +/* --- per-message closures --- */ + +typedef void (*CmdScanWifiStart_Closure) + (const CmdScanWifiStart *message, + void *closure_data); +typedef void (*CmdScanThreadStart_Closure) + (const CmdScanThreadStart *message, + void *closure_data); +typedef void (*RespScanWifiStart_Closure) + (const RespScanWifiStart *message, + void *closure_data); +typedef void (*RespScanThreadStart_Closure) + (const RespScanThreadStart *message, + void *closure_data); +typedef void (*CmdScanWifiStatus_Closure) + (const CmdScanWifiStatus *message, + void *closure_data); +typedef void (*CmdScanThreadStatus_Closure) + (const CmdScanThreadStatus *message, + void *closure_data); +typedef void (*RespScanWifiStatus_Closure) + (const RespScanWifiStatus *message, + void *closure_data); +typedef void (*RespScanThreadStatus_Closure) + (const RespScanThreadStatus *message, + void *closure_data); +typedef void (*CmdScanWifiResult_Closure) + (const CmdScanWifiResult *message, + void *closure_data); +typedef void (*CmdScanThreadResult_Closure) + (const CmdScanThreadResult *message, + void *closure_data); +typedef void (*WiFiScanResult_Closure) + (const WiFiScanResult *message, + void *closure_data); +typedef void (*ThreadScanResult_Closure) + (const ThreadScanResult *message, + void *closure_data); +typedef void (*RespScanWifiResult_Closure) + (const RespScanWifiResult *message, + void *closure_data); +typedef void (*RespScanThreadResult_Closure) + (const RespScanThreadResult *message, + void *closure_data); +typedef void (*NetworkScanPayload_Closure) + (const NetworkScanPayload *message, + void *closure_data); + +/* --- services --- */ + + +/* --- descriptors --- */ + +extern const ProtobufCEnumDescriptor network_scan_msg_type__descriptor; +extern const ProtobufCMessageDescriptor cmd_scan_wifi_start__descriptor; +extern const ProtobufCMessageDescriptor cmd_scan_thread_start__descriptor; +extern const ProtobufCMessageDescriptor resp_scan_wifi_start__descriptor; +extern const ProtobufCMessageDescriptor resp_scan_thread_start__descriptor; +extern const ProtobufCMessageDescriptor cmd_scan_wifi_status__descriptor; +extern const ProtobufCMessageDescriptor cmd_scan_thread_status__descriptor; +extern const ProtobufCMessageDescriptor resp_scan_wifi_status__descriptor; +extern const ProtobufCMessageDescriptor resp_scan_thread_status__descriptor; +extern const ProtobufCMessageDescriptor cmd_scan_wifi_result__descriptor; +extern const ProtobufCMessageDescriptor cmd_scan_thread_result__descriptor; +extern const ProtobufCMessageDescriptor wi_fi_scan_result__descriptor; +extern const ProtobufCMessageDescriptor thread_scan_result__descriptor; +extern const ProtobufCMessageDescriptor resp_scan_wifi_result__descriptor; +extern const ProtobufCMessageDescriptor resp_scan_thread_result__descriptor; +extern const ProtobufCMessageDescriptor network_scan_payload__descriptor; + +PROTOBUF_C__END_DECLS + + +#endif /* PROTOBUF_C_network_5fscan_2eproto__INCLUDED */ diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/proto/CMakeLists.txt b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/proto/CMakeLists.txt new file mode 100644 index 000000000..a066c9812 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/proto/CMakeLists.txt @@ -0,0 +1,29 @@ +cmake_minimum_required(VERSION 3.16) + +set(PROTO_COMPILER "protoc") +set(PROTO_C_COMPILER "protoc-c") +set(C_OUT_PATH "${CMAKE_CURRENT_LIST_DIR}/../proto-c") +set(PY_OUT_PATH "${CMAKE_CURRENT_LIST_DIR}/../python") +set(PROTOCOMM_INCL_PATH "${IDF_PATH}/component/protocomm/proto") + +set(PROTO_SRCS "network_constants.proto" + "network_config.proto" + "network_scan.proto") + +add_custom_target(c_proto + COMMAND ${PROTO_C_COMPILER} --c_out=${C_OUT_PATH} -I . -I ${PROTOCOMM_INCL_PATH} ${PROTO_SRCS} + VERBATIM + WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} + ) + +add_custom_target(python_proto + COMMAND ${PROTO_COMPILER} --python_out=${PY_OUT_PATH} -I . -I ${PROTOCOMM_INCL_PATH} ${PROTO_SRCS} + VERBATIM + WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} + ) + +add_custom_target(proto ALL + DEPENDS c_proto python_proto + VERBATIM + WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} + ) diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/proto/README.md b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/proto/README.md new file mode 100644 index 000000000..93f855db3 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/proto/README.md @@ -0,0 +1,29 @@ +# Protobuf files for defining Network provisioning packet structures + +`network_provisioning` uses Google Protobuf for language, transport and architecture agnostic protocol communication. These proto files define the protocomm packet structure, separated across multiple files: +* network_contants.proto - Defines the various enums for indicating state of network (connected / disconnect / connecting), diconnect reasons, auth modes, etc. +* network_config.proto - Defines network configuration structures and commands for setting Wi-Fi credentials (SSID, passphrase, BSSID) or Thread dataset, applying credentials and getting connection state. +* network_scan.proto - Defines network scan commands and result structures +* network_ctrl.proto - Defines network control commands(reset and re-provision) and result structures + +Note : These proto files are not automatically compiled during the build process. + +# Compilation + +Compilation requires protoc (Protobuf Compiler) and protoc-c (Protobuf C Compiler) installed. Since the generated files are to remain the same, as long as the proto files are not modified, therefore the generated files are already available under `components/network_provisioning/proto-c` and `components/network_provisioning/python` directories, and thus running cmake / make (and installing the Protobuf compilers) is optional. + +If using `cmake` follow the below steps. If using `make`, jump to Step 2 directly. + +## Step 1 (Only for cmake) + +When using cmake, first create a build directory and call cmake from inside: + +``` +mkdir build +cd build +cmake .. +``` + +## Step 2 + +Simply run `make` to generate the respective C and Python files. The newly created files will overwrite those under `components/network_provisioning/proto-c` and `components/network_provisioning/python` diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/proto/makefile b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/proto/makefile new file mode 100644 index 000000000..127bd536a --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/proto/makefile @@ -0,0 +1,7 @@ +all: c_proto python_proto + +c_proto: *.proto + @protoc-c --c_out=../proto-c/ -I . -I ${IDF_PATH}/components/protocomm/proto/ *.proto + +python_proto: *.proto + @protoc --python_out=../python/ -I . -I ${IDF_PATH}/components/protocomm/proto/ *.proto diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/proto/network_config.proto b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/proto/network_config.proto new file mode 100644 index 000000000..b73b64d7e --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/proto/network_config.proto @@ -0,0 +1,95 @@ +syntax = "proto3"; + +import "constants.proto"; +import "network_constants.proto"; + +message CmdGetWifiStatus { +} + +message RespGetWifiStatus { + Status status = 1; + WifiStationState wifi_sta_state = 2; + oneof state { + WifiConnectFailedReason wifi_fail_reason = 10; + WifiConnectedState wifi_connected = 11; + } +} + +message CmdGetThreadStatus { +} + +message RespGetThreadStatus { + Status status = 1; + ThreadNetworkState thread_state = 2; + oneof state { + ThreadAttachFailedReason thread_fail_reason = 10; + ThreadAttachState thread_attached = 11; + } +} + +message CmdSetWifiConfig { + bytes ssid = 1; + bytes passphrase = 2; + bytes bssid = 3; + int32 channel = 4; +} + +message CmdSetThreadConfig { + bytes dataset = 1; +} + +message RespSetWifiConfig { + Status status = 1; +} + +message RespSetThreadConfig { + Status status = 1; +} + +message CmdApplyWifiConfig { +} + +message CmdApplyThreadConfig { +} + +message RespApplyWifiConfig { + Status status = 1; +} + +message RespApplyThreadConfig { + Status status = 1; +} + +enum NetworkConfigMsgType { + TypeCmdGetWifiStatus = 0; + TypeRespGetWifiStatus = 1; + TypeCmdSetWifiConfig = 2; + TypeRespSetWifiConfig = 3; + TypeCmdApplyWifiConfig = 4; + TypeRespApplyWifiConfig = 5; + TypeCmdGetThreadStatus = 6; + TypeRespGetThreadStatus = 7; + TypeCmdSetThreadConfig = 8; + TypeRespSetThreadConfig = 9; + TypeCmdApplyThreadConfig = 10; + TypeRespApplyThreadConfig = 11; + +} + +message NetworkConfigPayload { + NetworkConfigMsgType msg = 1; + oneof payload { + CmdGetWifiStatus cmd_get_wifi_status = 10; + RespGetWifiStatus resp_get_wifi_status = 11; + CmdSetWifiConfig cmd_set_wifi_config = 12; + RespSetWifiConfig resp_set_wifi_config = 13; + CmdApplyWifiConfig cmd_apply_wifi_config = 14; + RespApplyWifiConfig resp_apply_wifi_config = 15; + CmdGetThreadStatus cmd_get_thread_status = 16; + RespGetThreadStatus resp_get_thread_status = 17; + CmdSetThreadConfig cmd_set_thread_config = 18; + RespSetThreadConfig resp_set_thread_config = 19; + CmdApplyThreadConfig cmd_apply_thread_config = 20; + RespApplyThreadConfig resp_apply_thread_config = 21; + } +} diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/proto/network_constants.proto b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/proto/network_constants.proto new file mode 100644 index 000000000..21248ac3f --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/proto/network_constants.proto @@ -0,0 +1,51 @@ +syntax = "proto3"; + +enum WifiStationState { + Connected = 0; + Connecting = 1; + Disconnected = 2; + ConnectionFailed = 3; +} + +enum WifiConnectFailedReason { + AuthError = 0; + WifiNetworkNotFound = 1; +} + +enum WifiAuthMode { + Open = 0; + WEP = 1; + WPA_PSK = 2; + WPA2_PSK = 3; + WPA_WPA2_PSK = 4; + WPA2_ENTERPRISE = 5; + WPA3_PSK = 6; + WPA2_WPA3_PSK = 7; +} + +message WifiConnectedState { + string ip4_addr = 1; + WifiAuthMode auth_mode = 2; + bytes ssid = 3; + bytes bssid = 4; + int32 channel = 5; +} + +enum ThreadNetworkState { + Attached = 0; + Attaching = 1; + Dettached = 2; + AttachingFailed = 3; +} + +enum ThreadAttachFailedReason { + DatasetInvalid = 0; + ThreadNetworkNotFound = 1; +} + +message ThreadAttachState { + uint32 pan_id = 1; + bytes ext_pan_id = 2; + uint32 channel = 3; + string name = 4; +} diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/proto/network_ctrl.proto b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/proto/network_ctrl.proto new file mode 100644 index 000000000..3da679de4 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/proto/network_ctrl.proto @@ -0,0 +1,55 @@ +syntax = "proto3"; + +import "constants.proto"; + +message CmdCtrlWifiReset { +} + +message RespCtrlWifiReset { +} + +message CmdCtrlWifiReprov { +} + +message RespCtrlWifiReprov{ +} + +message CmdCtrlThreadReset { +} + +message RespCtrlThreadReset { +} + +message CmdCtrlThreadReprov { +} + +message RespCtrlThreadReprov{ +} + +enum NetworkCtrlMsgType { + TypeCtrlReserved = 0; + TypeCmdCtrlWifiReset = 1; + TypeRespCtrlWifiReset = 2; + TypeCmdCtrlWifiReprov = 3; + TypeRespCtrlWifiReprov = 4; + TypeCmdCtrlThreadReset = 5; + TypeRespCtrlThreadReset = 6; + TypeCmdCtrlThreadReprov = 7; + TypeRespCtrlThreadReprov = 8; + +} + +message NetworkCtrlPayload { + NetworkCtrlMsgType msg = 1; + Status status = 2; + oneof payload { + CmdCtrlWifiReset cmd_ctrl_wifi_reset = 11; + RespCtrlWifiReset resp_ctrl_wifi_reset = 12; + CmdCtrlWifiReprov cmd_ctrl_wifi_reprov = 13; + RespCtrlWifiReprov resp_ctrl_wifi_reprov = 14; + CmdCtrlThreadReset cmd_ctrl_thread_reset = 15; + RespCtrlThreadReset resp_ctrl_thread_reset = 16; + CmdCtrlThreadReprov cmd_ctrl_thread_reprov = 17; + RespCtrlThreadReprov resp_ctrl_thread_reprov = 18; + } +} diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/proto/network_scan.proto b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/proto/network_scan.proto new file mode 100644 index 000000000..590799907 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/proto/network_scan.proto @@ -0,0 +1,109 @@ +syntax = "proto3"; + +import "constants.proto"; +import "network_constants.proto"; + +message CmdScanWifiStart { + bool blocking = 1; + bool passive = 2; + uint32 group_channels = 3; + uint32 period_ms = 4; +} + +message CmdScanThreadStart { + bool blocking = 1; + uint32 channel_mask = 2; +} + +message RespScanWifiStart { +} + +message RespScanThreadStart { +} + +message CmdScanWifiStatus { +} + +message CmdScanThreadStatus { +} + +message RespScanWifiStatus { + bool scan_finished = 1; + uint32 result_count = 2; +} + +message RespScanThreadStatus { + bool scan_finished = 1; + uint32 result_count = 2; +} + +message CmdScanWifiResult { + uint32 start_index = 1; + uint32 count = 2; +} + +message CmdScanThreadResult { + uint32 start_index = 1; + uint32 count = 2; +} + +message WiFiScanResult { + bytes ssid = 1; + uint32 channel = 2; + int32 rssi = 3; + bytes bssid = 4; + WifiAuthMode auth = 5; +} + +message ThreadScanResult { + uint32 pan_id = 1; + uint32 channel = 2; + int32 rssi = 3; + uint32 lqi = 4; + bytes ext_addr = 5; + string network_name = 6; + bytes ext_pan_id = 7; +} + +message RespScanWifiResult { + repeated WiFiScanResult entries = 1; +} + +message RespScanThreadResult { + repeated ThreadScanResult entries = 1; +} + + +enum NetworkScanMsgType { + TypeCmdScanWifiStart = 0; + TypeRespScanWifiStart = 1; + TypeCmdScanWifiStatus = 2; + TypeRespScanWifiStatus = 3; + TypeCmdScanWifiResult = 4; + TypeRespScanWifiResult = 5; + TypeCmdScanThreadStart = 6; + TypeRespScanThreadStart = 7; + TypeCmdScanThreadStatus = 8; + TypeRespScanThreadStatus = 9; + TypeCmdScanThreadResult = 10; + TypeRespScanThreadResult = 11; +} + +message NetworkScanPayload { + NetworkScanMsgType msg = 1; + Status status = 2; + oneof payload { + CmdScanWifiStart cmd_scan_wifi_start = 10; + RespScanWifiStart resp_scan_wifi_start = 11; + CmdScanWifiStatus cmd_scan_wifi_status = 12; + RespScanWifiStatus resp_scan_wifi_status = 13; + CmdScanWifiResult cmd_scan_wifi_result = 14; + RespScanWifiResult resp_scan_wifi_result = 15; + CmdScanThreadStart cmd_scan_thread_start = 16; + RespScanThreadStart resp_scan_thread_start = 17; + CmdScanThreadStatus cmd_scan_thread_status = 18; + RespScanThreadStatus resp_scan_thread_status = 19; + CmdScanThreadResult cmd_scan_thread_result = 20; + RespScanThreadResult resp_scan_thread_result = 21; + } +} diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/python/network_config_pb2.py b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/python/network_config_pb2.py new file mode 100644 index 000000000..1734660ce --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/python/network_config_pb2.py @@ -0,0 +1,53 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: network_config.proto +"""Generated protocol buffer code.""" +from google.protobuf.internal import builder as _builder +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +import constants_pb2 as constants__pb2 +import network_constants_pb2 as network__constants__pb2 + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x14network_config.proto\x1a\x0f\x63onstants.proto\x1a\x17network_constants.proto\"\x12\n\x10\x43mdGetWifiStatus\"\xc5\x01\n\x11RespGetWifiStatus\x12\x17\n\x06status\x18\x01 \x01(\x0e\x32\x07.Status\x12)\n\x0ewifi_sta_state\x18\x02 \x01(\x0e\x32\x11.WifiStationState\x12\x34\n\x10wifi_fail_reason\x18\n \x01(\x0e\x32\x18.WifiConnectFailedReasonH\x00\x12-\n\x0ewifi_connected\x18\x0b \x01(\x0b\x32\x13.WifiConnectedStateH\x00\x42\x07\n\x05state\"\x14\n\x12\x43mdGetThreadStatus\"\xca\x01\n\x13RespGetThreadStatus\x12\x17\n\x06status\x18\x01 \x01(\x0e\x32\x07.Status\x12)\n\x0cthread_state\x18\x02 \x01(\x0e\x32\x13.ThreadNetworkState\x12\x37\n\x12thread_fail_reason\x18\n \x01(\x0e\x32\x19.ThreadAttachFailedReasonH\x00\x12-\n\x0fthread_attached\x18\x0b \x01(\x0b\x32\x12.ThreadAttachStateH\x00\x42\x07\n\x05state\"T\n\x10\x43mdSetWifiConfig\x12\x0c\n\x04ssid\x18\x01 \x01(\x0c\x12\x12\n\npassphrase\x18\x02 \x01(\x0c\x12\r\n\x05\x62ssid\x18\x03 \x01(\x0c\x12\x0f\n\x07\x63hannel\x18\x04 \x01(\x05\"%\n\x12\x43mdSetThreadConfig\x12\x0f\n\x07\x64\x61taset\x18\x01 \x01(\x0c\",\n\x11RespSetWifiConfig\x12\x17\n\x06status\x18\x01 \x01(\x0e\x32\x07.Status\".\n\x13RespSetThreadConfig\x12\x17\n\x06status\x18\x01 \x01(\x0e\x32\x07.Status\"\x14\n\x12\x43mdApplyWifiConfig\"\x16\n\x14\x43mdApplyThreadConfig\".\n\x13RespApplyWifiConfig\x12\x17\n\x06status\x18\x01 \x01(\x0e\x32\x07.Status\"0\n\x15RespApplyThreadConfig\x12\x17\n\x06status\x18\x01 \x01(\x0e\x32\x07.Status\"\xd1\x05\n\x14NetworkConfigPayload\x12\"\n\x03msg\x18\x01 \x01(\x0e\x32\x15.NetworkConfigMsgType\x12\x30\n\x13\x63md_get_wifi_status\x18\n \x01(\x0b\x32\x11.CmdGetWifiStatusH\x00\x12\x32\n\x14resp_get_wifi_status\x18\x0b \x01(\x0b\x32\x12.RespGetWifiStatusH\x00\x12\x30\n\x13\x63md_set_wifi_config\x18\x0c \x01(\x0b\x32\x11.CmdSetWifiConfigH\x00\x12\x32\n\x14resp_set_wifi_config\x18\r \x01(\x0b\x32\x12.RespSetWifiConfigH\x00\x12\x34\n\x15\x63md_apply_wifi_config\x18\x0e \x01(\x0b\x32\x13.CmdApplyWifiConfigH\x00\x12\x36\n\x16resp_apply_wifi_config\x18\x0f \x01(\x0b\x32\x14.RespApplyWifiConfigH\x00\x12\x34\n\x15\x63md_get_thread_status\x18\x10 \x01(\x0b\x32\x13.CmdGetThreadStatusH\x00\x12\x36\n\x16resp_get_thread_status\x18\x11 \x01(\x0b\x32\x14.RespGetThreadStatusH\x00\x12\x34\n\x15\x63md_set_thread_config\x18\x12 \x01(\x0b\x32\x13.CmdSetThreadConfigH\x00\x12\x36\n\x16resp_set_thread_config\x18\x13 \x01(\x0b\x32\x14.RespSetThreadConfigH\x00\x12\x38\n\x17\x63md_apply_thread_config\x18\x14 \x01(\x0b\x32\x15.CmdApplyThreadConfigH\x00\x12:\n\x18resp_apply_thread_config\x18\x15 \x01(\x0b\x32\x16.RespApplyThreadConfigH\x00\x42\t\n\x07payload*\xe8\x02\n\x14NetworkConfigMsgType\x12\x18\n\x14TypeCmdGetWifiStatus\x10\x00\x12\x19\n\x15TypeRespGetWifiStatus\x10\x01\x12\x18\n\x14TypeCmdSetWifiConfig\x10\x02\x12\x19\n\x15TypeRespSetWifiConfig\x10\x03\x12\x1a\n\x16TypeCmdApplyWifiConfig\x10\x04\x12\x1b\n\x17TypeRespApplyWifiConfig\x10\x05\x12\x1a\n\x16TypeCmdGetThreadStatus\x10\x06\x12\x1b\n\x17TypeRespGetThreadStatus\x10\x07\x12\x1a\n\x16TypeCmdSetThreadConfig\x10\x08\x12\x1b\n\x17TypeRespSetThreadConfig\x10\t\x12\x1c\n\x18TypeCmdApplyThreadConfig\x10\n\x12\x1d\n\x19TypeRespApplyThreadConfig\x10\x0b\x62\x06proto3') + +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'network_config_pb2', globals()) +if _descriptor._USE_C_DESCRIPTORS == False: + + DESCRIPTOR._options = None + _NETWORKCONFIGMSGTYPE._serialized_start=1601 + _NETWORKCONFIGMSGTYPE._serialized_end=1961 + _CMDGETWIFISTATUS._serialized_start=66 + _CMDGETWIFISTATUS._serialized_end=84 + _RESPGETWIFISTATUS._serialized_start=87 + _RESPGETWIFISTATUS._serialized_end=284 + _CMDGETTHREADSTATUS._serialized_start=286 + _CMDGETTHREADSTATUS._serialized_end=306 + _RESPGETTHREADSTATUS._serialized_start=309 + _RESPGETTHREADSTATUS._serialized_end=511 + _CMDSETWIFICONFIG._serialized_start=513 + _CMDSETWIFICONFIG._serialized_end=597 + _CMDSETTHREADCONFIG._serialized_start=599 + _CMDSETTHREADCONFIG._serialized_end=636 + _RESPSETWIFICONFIG._serialized_start=638 + _RESPSETWIFICONFIG._serialized_end=682 + _RESPSETTHREADCONFIG._serialized_start=684 + _RESPSETTHREADCONFIG._serialized_end=730 + _CMDAPPLYWIFICONFIG._serialized_start=732 + _CMDAPPLYWIFICONFIG._serialized_end=752 + _CMDAPPLYTHREADCONFIG._serialized_start=754 + _CMDAPPLYTHREADCONFIG._serialized_end=776 + _RESPAPPLYWIFICONFIG._serialized_start=778 + _RESPAPPLYWIFICONFIG._serialized_end=824 + _RESPAPPLYTHREADCONFIG._serialized_start=826 + _RESPAPPLYTHREADCONFIG._serialized_end=874 + _NETWORKCONFIGPAYLOAD._serialized_start=877 + _NETWORKCONFIGPAYLOAD._serialized_end=1598 +# @@protoc_insertion_point(module_scope) diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/python/network_constants_pb2.py b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/python/network_constants_pb2.py new file mode 100644 index 000000000..0d79e50b4 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/python/network_constants_pb2.py @@ -0,0 +1,37 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: network_constants.proto +"""Generated protocol buffer code.""" +from google.protobuf.internal import builder as _builder +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x17network_constants.proto\"v\n\x12WifiConnectedState\x12\x10\n\x08ip4_addr\x18\x01 \x01(\t\x12 \n\tauth_mode\x18\x02 \x01(\x0e\x32\r.WifiAuthMode\x12\x0c\n\x04ssid\x18\x03 \x01(\x0c\x12\r\n\x05\x62ssid\x18\x04 \x01(\x0c\x12\x0f\n\x07\x63hannel\x18\x05 \x01(\x05\"V\n\x11ThreadAttachState\x12\x0e\n\x06pan_id\x18\x01 \x01(\r\x12\x12\n\next_pan_id\x18\x02 \x01(\x0c\x12\x0f\n\x07\x63hannel\x18\x03 \x01(\r\x12\x0c\n\x04name\x18\x04 \x01(\t*Y\n\x10WifiStationState\x12\r\n\tConnected\x10\x00\x12\x0e\n\nConnecting\x10\x01\x12\x10\n\x0c\x44isconnected\x10\x02\x12\x14\n\x10\x43onnectionFailed\x10\x03*A\n\x17WifiConnectFailedReason\x12\r\n\tAuthError\x10\x00\x12\x17\n\x13WifiNetworkNotFound\x10\x01*\x84\x01\n\x0cWifiAuthMode\x12\x08\n\x04Open\x10\x00\x12\x07\n\x03WEP\x10\x01\x12\x0b\n\x07WPA_PSK\x10\x02\x12\x0c\n\x08WPA2_PSK\x10\x03\x12\x10\n\x0cWPA_WPA2_PSK\x10\x04\x12\x13\n\x0fWPA2_ENTERPRISE\x10\x05\x12\x0c\n\x08WPA3_PSK\x10\x06\x12\x11\n\rWPA2_WPA3_PSK\x10\x07*U\n\x12ThreadNetworkState\x12\x0c\n\x08\x41ttached\x10\x00\x12\r\n\tAttaching\x10\x01\x12\r\n\tDettached\x10\x02\x12\x13\n\x0f\x41ttachingFailed\x10\x03*I\n\x18ThreadAttachFailedReason\x12\x12\n\x0e\x44\x61tasetInvalid\x10\x00\x12\x19\n\x15ThreadNetworkNotFound\x10\x01\x62\x06proto3') + +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'network_constants_pb2', globals()) +if _descriptor._USE_C_DESCRIPTORS == False: + + DESCRIPTOR._options = None + _WIFISTATIONSTATE._serialized_start=235 + _WIFISTATIONSTATE._serialized_end=324 + _WIFICONNECTFAILEDREASON._serialized_start=326 + _WIFICONNECTFAILEDREASON._serialized_end=391 + _WIFIAUTHMODE._serialized_start=394 + _WIFIAUTHMODE._serialized_end=526 + _THREADNETWORKSTATE._serialized_start=528 + _THREADNETWORKSTATE._serialized_end=613 + _THREADATTACHFAILEDREASON._serialized_start=615 + _THREADATTACHFAILEDREASON._serialized_end=688 + _WIFICONNECTEDSTATE._serialized_start=27 + _WIFICONNECTEDSTATE._serialized_end=145 + _THREADATTACHSTATE._serialized_start=147 + _THREADATTACHSTATE._serialized_end=233 +# @@protoc_insertion_point(module_scope) diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/python/network_ctrl_pb2.py b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/python/network_ctrl_pb2.py new file mode 100644 index 000000000..97c40b371 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/python/network_ctrl_pb2.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: network_ctrl.proto +"""Generated protocol buffer code.""" +from google.protobuf.internal import builder as _builder +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +import constants_pb2 as constants__pb2 + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x12network_ctrl.proto\x1a\x0f\x63onstants.proto\"\x12\n\x10\x43mdCtrlWifiReset\"\x13\n\x11RespCtrlWifiReset\"\x13\n\x11\x43mdCtrlWifiReprov\"\x14\n\x12RespCtrlWifiReprov\"\x14\n\x12\x43mdCtrlThreadReset\"\x15\n\x13RespCtrlThreadReset\"\x15\n\x13\x43mdCtrlThreadReprov\"\x16\n\x14RespCtrlThreadReprov\"\x8a\x04\n\x12NetworkCtrlPayload\x12 \n\x03msg\x18\x01 \x01(\x0e\x32\x13.NetworkCtrlMsgType\x12\x17\n\x06status\x18\x02 \x01(\x0e\x32\x07.Status\x12\x30\n\x13\x63md_ctrl_wifi_reset\x18\x0b \x01(\x0b\x32\x11.CmdCtrlWifiResetH\x00\x12\x32\n\x14resp_ctrl_wifi_reset\x18\x0c \x01(\x0b\x32\x12.RespCtrlWifiResetH\x00\x12\x32\n\x14\x63md_ctrl_wifi_reprov\x18\r \x01(\x0b\x32\x12.CmdCtrlWifiReprovH\x00\x12\x34\n\x15resp_ctrl_wifi_reprov\x18\x0e \x01(\x0b\x32\x13.RespCtrlWifiReprovH\x00\x12\x34\n\x15\x63md_ctrl_thread_reset\x18\x0f \x01(\x0b\x32\x13.CmdCtrlThreadResetH\x00\x12\x36\n\x16resp_ctrl_thread_reset\x18\x10 \x01(\x0b\x32\x14.RespCtrlThreadResetH\x00\x12\x36\n\x16\x63md_ctrl_thread_reprov\x18\x11 \x01(\x0b\x32\x14.CmdCtrlThreadReprovH\x00\x12\x38\n\x17resp_ctrl_thread_reprov\x18\x12 \x01(\x0b\x32\x15.RespCtrlThreadReprovH\x00\x42\t\n\x07payload*\x8a\x02\n\x12NetworkCtrlMsgType\x12\x14\n\x10TypeCtrlReserved\x10\x00\x12\x18\n\x14TypeCmdCtrlWifiReset\x10\x01\x12\x19\n\x15TypeRespCtrlWifiReset\x10\x02\x12\x19\n\x15TypeCmdCtrlWifiReprov\x10\x03\x12\x1a\n\x16TypeRespCtrlWifiReprov\x10\x04\x12\x1a\n\x16TypeCmdCtrlThreadReset\x10\x05\x12\x1b\n\x17TypeRespCtrlThreadReset\x10\x06\x12\x1b\n\x17TypeCmdCtrlThreadReprov\x10\x07\x12\x1c\n\x18TypeRespCtrlThreadReprov\x10\x08\x62\x06proto3') + +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'network_ctrl_pb2', globals()) +if _descriptor._USE_C_DESCRIPTORS == False: + + DESCRIPTOR._options = None + _NETWORKCTRLMSGTYPE._serialized_start=741 + _NETWORKCTRLMSGTYPE._serialized_end=1007 + _CMDCTRLWIFIRESET._serialized_start=39 + _CMDCTRLWIFIRESET._serialized_end=57 + _RESPCTRLWIFIRESET._serialized_start=59 + _RESPCTRLWIFIRESET._serialized_end=78 + _CMDCTRLWIFIREPROV._serialized_start=80 + _CMDCTRLWIFIREPROV._serialized_end=99 + _RESPCTRLWIFIREPROV._serialized_start=101 + _RESPCTRLWIFIREPROV._serialized_end=121 + _CMDCTRLTHREADRESET._serialized_start=123 + _CMDCTRLTHREADRESET._serialized_end=143 + _RESPCTRLTHREADRESET._serialized_start=145 + _RESPCTRLTHREADRESET._serialized_end=166 + _CMDCTRLTHREADREPROV._serialized_start=168 + _CMDCTRLTHREADREPROV._serialized_end=189 + _RESPCTRLTHREADREPROV._serialized_start=191 + _RESPCTRLTHREADREPROV._serialized_end=213 + _NETWORKCTRLPAYLOAD._serialized_start=216 + _NETWORKCTRLPAYLOAD._serialized_end=738 +# @@protoc_insertion_point(module_scope) diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/python/network_scan_pb2.py b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/python/network_scan_pb2.py new file mode 100644 index 000000000..72c21222d --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/python/network_scan_pb2.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: network_scan.proto +"""Generated protocol buffer code.""" +from google.protobuf.internal import builder as _builder +from google.protobuf import descriptor as _descriptor +from google.protobuf import descriptor_pool as _descriptor_pool +from google.protobuf import symbol_database as _symbol_database +# @@protoc_insertion_point(imports) + +_sym_db = _symbol_database.Default() + + +import constants_pb2 as constants__pb2 +import network_constants_pb2 as network__constants__pb2 + + +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x12network_scan.proto\x1a\x0f\x63onstants.proto\x1a\x17network_constants.proto\"`\n\x10\x43mdScanWifiStart\x12\x10\n\x08\x62locking\x18\x01 \x01(\x08\x12\x0f\n\x07passive\x18\x02 \x01(\x08\x12\x16\n\x0egroup_channels\x18\x03 \x01(\r\x12\x11\n\tperiod_ms\x18\x04 \x01(\r\"<\n\x12\x43mdScanThreadStart\x12\x10\n\x08\x62locking\x18\x01 \x01(\x08\x12\x14\n\x0c\x63hannel_mask\x18\x02 \x01(\r\"\x13\n\x11RespScanWifiStart\"\x15\n\x13RespScanThreadStart\"\x13\n\x11\x43mdScanWifiStatus\"\x15\n\x13\x43mdScanThreadStatus\"A\n\x12RespScanWifiStatus\x12\x15\n\rscan_finished\x18\x01 \x01(\x08\x12\x14\n\x0cresult_count\x18\x02 \x01(\r\"C\n\x14RespScanThreadStatus\x12\x15\n\rscan_finished\x18\x01 \x01(\x08\x12\x14\n\x0cresult_count\x18\x02 \x01(\r\"7\n\x11\x43mdScanWifiResult\x12\x13\n\x0bstart_index\x18\x01 \x01(\r\x12\r\n\x05\x63ount\x18\x02 \x01(\r\"9\n\x13\x43mdScanThreadResult\x12\x13\n\x0bstart_index\x18\x01 \x01(\r\x12\r\n\x05\x63ount\x18\x02 \x01(\r\"i\n\x0eWiFiScanResult\x12\x0c\n\x04ssid\x18\x01 \x01(\x0c\x12\x0f\n\x07\x63hannel\x18\x02 \x01(\r\x12\x0c\n\x04rssi\x18\x03 \x01(\x05\x12\r\n\x05\x62ssid\x18\x04 \x01(\x0c\x12\x1b\n\x04\x61uth\x18\x05 \x01(\x0e\x32\r.WifiAuthMode\"\x8a\x01\n\x10ThreadScanResult\x12\x0e\n\x06pan_id\x18\x01 \x01(\r\x12\x0f\n\x07\x63hannel\x18\x02 \x01(\r\x12\x0c\n\x04rssi\x18\x03 \x01(\x05\x12\x0b\n\x03lqi\x18\x04 \x01(\r\x12\x10\n\x08\x65xt_addr\x18\x05 \x01(\x0c\x12\x14\n\x0cnetwork_name\x18\x06 \x01(\t\x12\x12\n\next_pan_id\x18\x07 \x01(\x0c\"6\n\x12RespScanWifiResult\x12 \n\x07\x65ntries\x18\x01 \x03(\x0b\x32\x0f.WiFiScanResult\":\n\x14RespScanThreadResult\x12\"\n\x07\x65ntries\x18\x01 \x03(\x0b\x32\x11.ThreadScanResult\"\xe6\x05\n\x12NetworkScanPayload\x12 \n\x03msg\x18\x01 \x01(\x0e\x32\x13.NetworkScanMsgType\x12\x17\n\x06status\x18\x02 \x01(\x0e\x32\x07.Status\x12\x30\n\x13\x63md_scan_wifi_start\x18\n \x01(\x0b\x32\x11.CmdScanWifiStartH\x00\x12\x32\n\x14resp_scan_wifi_start\x18\x0b \x01(\x0b\x32\x12.RespScanWifiStartH\x00\x12\x32\n\x14\x63md_scan_wifi_status\x18\x0c \x01(\x0b\x32\x12.CmdScanWifiStatusH\x00\x12\x34\n\x15resp_scan_wifi_status\x18\r \x01(\x0b\x32\x13.RespScanWifiStatusH\x00\x12\x32\n\x14\x63md_scan_wifi_result\x18\x0e \x01(\x0b\x32\x12.CmdScanWifiResultH\x00\x12\x34\n\x15resp_scan_wifi_result\x18\x0f \x01(\x0b\x32\x13.RespScanWifiResultH\x00\x12\x34\n\x15\x63md_scan_thread_start\x18\x10 \x01(\x0b\x32\x13.CmdScanThreadStartH\x00\x12\x36\n\x16resp_scan_thread_start\x18\x11 \x01(\x0b\x32\x14.RespScanThreadStartH\x00\x12\x36\n\x16\x63md_scan_thread_status\x18\x12 \x01(\x0b\x32\x14.CmdScanThreadStatusH\x00\x12\x38\n\x17resp_scan_thread_status\x18\x13 \x01(\x0b\x32\x15.RespScanThreadStatusH\x00\x12\x36\n\x16\x63md_scan_thread_result\x18\x14 \x01(\x0b\x32\x14.CmdScanThreadResultH\x00\x12\x38\n\x17resp_scan_thread_result\x18\x15 \x01(\x0b\x32\x15.RespScanThreadResultH\x00\x42\t\n\x07payload*\xe6\x02\n\x12NetworkScanMsgType\x12\x18\n\x14TypeCmdScanWifiStart\x10\x00\x12\x19\n\x15TypeRespScanWifiStart\x10\x01\x12\x19\n\x15TypeCmdScanWifiStatus\x10\x02\x12\x1a\n\x16TypeRespScanWifiStatus\x10\x03\x12\x19\n\x15TypeCmdScanWifiResult\x10\x04\x12\x1a\n\x16TypeRespScanWifiResult\x10\x05\x12\x1a\n\x16TypeCmdScanThreadStart\x10\x06\x12\x1b\n\x17TypeRespScanThreadStart\x10\x07\x12\x1b\n\x17TypeCmdScanThreadStatus\x10\x08\x12\x1c\n\x18TypeRespScanThreadStatus\x10\t\x12\x1b\n\x17TypeCmdScanThreadResult\x10\n\x12\x1c\n\x18TypeRespScanThreadResult\x10\x0b\x62\x06proto3') + +_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) +_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'network_scan_pb2', globals()) +if _descriptor._USE_C_DESCRIPTORS == False: + + DESCRIPTOR._options = None + _NETWORKSCANMSGTYPE._serialized_start=1674 + _NETWORKSCANMSGTYPE._serialized_end=2032 + _CMDSCANWIFISTART._serialized_start=64 + _CMDSCANWIFISTART._serialized_end=160 + _CMDSCANTHREADSTART._serialized_start=162 + _CMDSCANTHREADSTART._serialized_end=222 + _RESPSCANWIFISTART._serialized_start=224 + _RESPSCANWIFISTART._serialized_end=243 + _RESPSCANTHREADSTART._serialized_start=245 + _RESPSCANTHREADSTART._serialized_end=266 + _CMDSCANWIFISTATUS._serialized_start=268 + _CMDSCANWIFISTATUS._serialized_end=287 + _CMDSCANTHREADSTATUS._serialized_start=289 + _CMDSCANTHREADSTATUS._serialized_end=310 + _RESPSCANWIFISTATUS._serialized_start=312 + _RESPSCANWIFISTATUS._serialized_end=377 + _RESPSCANTHREADSTATUS._serialized_start=379 + _RESPSCANTHREADSTATUS._serialized_end=446 + _CMDSCANWIFIRESULT._serialized_start=448 + _CMDSCANWIFIRESULT._serialized_end=503 + _CMDSCANTHREADRESULT._serialized_start=505 + _CMDSCANTHREADRESULT._serialized_end=562 + _WIFISCANRESULT._serialized_start=564 + _WIFISCANRESULT._serialized_end=669 + _THREADSCANRESULT._serialized_start=672 + _THREADSCANRESULT._serialized_end=810 + _RESPSCANWIFIRESULT._serialized_start=812 + _RESPSCANWIFIRESULT._serialized_end=866 + _RESPSCANTHREADRESULT._serialized_start=868 + _RESPSCANTHREADRESULT._serialized_end=926 + _NETWORKSCANPAYLOAD._serialized_start=929 + _NETWORKSCANPAYLOAD._serialized_end=1671 +# @@protoc_insertion_point(module_scope) diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/src/handlers.c b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/src/handlers.c new file mode 100644 index 000000000..a06b33132 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/src/handlers.c @@ -0,0 +1,408 @@ +/* + * SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI +#include +#endif +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD +#include +#endif +#include + +#include "network_provisioning/network_config.h" +#include "network_provisioning/network_scan.h" +#include "network_ctrl.h" +#include "network_provisioning/manager.h" +#include "network_provisioning_priv.h" + +#if defined(CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI) || defined(CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD) +static const char *TAG = "network_prov_handlers"; + +/* Provide definition of network_prov_ctx_t */ +struct network_prov_ctx { +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI + wifi_config_t wifi_cfg; +#endif +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD + otOperationalDatasetTlvs thread_dataset; +#endif +}; + +static void free_network_prov_ctx(network_prov_ctx_t **ctx) +{ + free(*ctx); + *ctx = NULL; +} +#endif + +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI +static wifi_config_t *get_wifi_config(network_prov_ctx_t **ctx) +{ + return (*ctx ? & (*ctx)->wifi_cfg : NULL); +} + +static wifi_config_t *new_wifi_config(network_prov_ctx_t **ctx) +{ + free(*ctx); + (*ctx) = (network_prov_ctx_t *) calloc(1, sizeof(network_prov_ctx_t)); + return get_wifi_config(ctx); +} + +static esp_err_t wifi_get_status_handler(network_prov_config_get_wifi_data_t *resp_data, network_prov_ctx_t **ctx) +{ + /* Initialize to zero */ + memset(resp_data, 0, sizeof(network_prov_config_get_wifi_data_t)); + + if (network_prov_mgr_get_wifi_state(&resp_data->wifi_state) != ESP_OK) { + ESP_LOGW(TAG, "Network provisioning manager for Wi-Fi not running"); + return ESP_ERR_INVALID_STATE; + } + + if (resp_data->wifi_state == NETWORK_PROV_WIFI_STA_CONNECTED) { + ESP_LOGD(TAG, "Got state : connected"); + + /* IP Addr assigned to STA */ + esp_netif_ip_info_t ip_info; + esp_netif_get_ip_info(esp_netif_get_handle_from_ifkey("WIFI_STA_DEF"), &ip_info); + esp_ip4addr_ntoa(&ip_info.ip, resp_data->conn_info.ip_addr, sizeof(resp_data->conn_info.ip_addr)); + + + /* AP information to which STA is connected */ + wifi_ap_record_t ap_info; + esp_wifi_sta_get_ap_info(&ap_info); + memcpy(resp_data->conn_info.bssid, (char *)ap_info.bssid, sizeof(ap_info.bssid)); + memcpy(resp_data->conn_info.ssid, (char *)ap_info.ssid, sizeof(ap_info.ssid)); + resp_data->conn_info.channel = ap_info.primary; + resp_data->conn_info.auth_mode = ap_info.authmode; + + /* Tell manager to stop provisioning service */ + network_prov_mgr_done(); + } else if (resp_data->wifi_state == NETWORK_PROV_WIFI_STA_DISCONNECTED) { + ESP_LOGD(TAG, "Got state : disconnected"); + + /* If disconnected, convey reason */ + network_prov_mgr_get_wifi_disconnect_reason(&resp_data->fail_reason); + } else { + ESP_LOGD(TAG, "Got state : connecting"); + } + return ESP_OK; +} + +static esp_err_t wifi_set_config_handler(const network_prov_config_set_wifi_data_t *req_data, network_prov_ctx_t **ctx) +{ + wifi_config_t *wifi_cfg = get_wifi_config(ctx); + if (wifi_cfg) { + free_network_prov_ctx(ctx); + } + + wifi_cfg = new_wifi_config(ctx); + if (!wifi_cfg) { + ESP_LOGE(TAG, "Unable to allocate Wi-Fi config"); + return ESP_ERR_NO_MEM; + } + + ESP_LOGD(TAG, "Wi-Fi Credentials Received"); + + /* Using memcpy allows the max SSID length to be 32 bytes (as per 802.11 standard). + * But this doesn't guarantee that the saved SSID will be null terminated, because + * wifi_cfg->sta.ssid is also 32 bytes long (without extra 1 byte for null character). + * Although, this is not a matter for concern because esp_wifi library reads the SSID + * upto 32 bytes in absence of null termination */ + const size_t ssid_len = strnlen(req_data->ssid, sizeof(wifi_cfg->sta.ssid)); + /* Ensure SSID less than 32 bytes is null terminated */ + memset(wifi_cfg->sta.ssid, 0, sizeof(wifi_cfg->sta.ssid)); + memcpy(wifi_cfg->sta.ssid, req_data->ssid, ssid_len); + + /* Using strlcpy allows both max passphrase length (63 bytes) and ensures null termination + * because size of wifi_cfg->sta.password is 64 bytes (1 extra byte for null character) */ + strlcpy((char *) wifi_cfg->sta.password, req_data->password, sizeof(wifi_cfg->sta.password)); + +#ifdef CONFIG_NETWORK_PROV_WIFI_STA_ALL_CHANNEL_SCAN + wifi_cfg->sta.scan_method = WIFI_ALL_CHANNEL_SCAN; +#else /* CONFIG_NETWORK_PROV_WIFI_STA_FAST_SCAN */ + wifi_cfg->sta.scan_method = WIFI_FAST_SCAN; +#endif + + return ESP_OK; +} + +static esp_err_t wifi_apply_config_handler(network_prov_ctx_t **ctx) +{ + wifi_config_t *wifi_cfg = get_wifi_config(ctx); + if (!wifi_cfg) { + ESP_LOGE(TAG, "Wi-Fi config not set"); + return ESP_ERR_INVALID_STATE; + } + + esp_err_t ret = network_prov_mgr_configure_wifi_sta(wifi_cfg); + if (ret == ESP_OK) { + ESP_LOGD(TAG, "Wi-Fi Credentials Applied"); + } else { + ESP_LOGE(TAG, "Failed to apply Wi-Fi Credentials"); + } + + free_network_prov_ctx(ctx); + return ret; +} +#endif // CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI + +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD +static otOperationalDatasetTlvs *get_thread_dataset(network_prov_ctx_t **ctx) +{ + return (*ctx ? & (*ctx)->thread_dataset : NULL); +} + +static otOperationalDatasetTlvs *new_thread_dataset(network_prov_ctx_t **ctx) +{ + free(*ctx); + (*ctx) = (network_prov_ctx_t *) calloc(1, sizeof(network_prov_ctx_t)); + return get_thread_dataset(ctx); +} + +static esp_err_t thread_get_status_handler(network_prov_config_get_thread_data_t *resp_data, network_prov_ctx_t **ctx) +{ + /* Initialize to zero */ + memset(resp_data, 0, sizeof(network_prov_config_get_thread_data_t)); + + if (network_prov_mgr_get_thread_state(&resp_data->thread_state) != ESP_OK) { + ESP_LOGW(TAG, "Network provisioning manager not running"); + return ESP_ERR_INVALID_STATE; + } + + if (resp_data->thread_state == NETWORK_PROV_THREAD_ATTACHED) { + ESP_LOGD(TAG, "Got state : attached"); + otOperationalDataset dataset; + if (otDatasetGetActive(esp_openthread_get_instance(), &dataset) != OT_ERROR_NONE) { + ESP_LOGE(TAG, "Failed to get Thread dataset"); + return ESP_FAIL; + } + resp_data->conn_info.channel = dataset.mChannel; + memcpy(resp_data->conn_info.ext_pan_id, dataset.mExtendedPanId.m8, sizeof(dataset.mExtendedPanId.m8)); + strncpy(resp_data->conn_info.name, dataset.mNetworkName.m8, + strnlen(dataset.mNetworkName.m8, sizeof(dataset.mNetworkName.m8))); + resp_data->conn_info.pan_id = dataset.mPanId; + /* Tell manager to stop provisioning service */ + network_prov_mgr_done(); + } else if (resp_data->thread_state == NETWORK_PROV_THREAD_DETACHED) { + ESP_LOGD(TAG, "Got state : disconnected"); + + /* If disconnected, convey reason */ + network_prov_mgr_get_thread_detached_reason(&resp_data->fail_reason); + } else { + ESP_LOGD(TAG, "Got state : attaching"); + } + return ESP_OK; +} + +static esp_err_t thread_set_config_handler(const network_prov_config_set_thread_data_t *req_data, network_prov_ctx_t **ctx) +{ + otOperationalDatasetTlvs *thread_dataset = get_thread_dataset(ctx); + if (thread_dataset) { + free_network_prov_ctx(ctx); + } + + thread_dataset = new_thread_dataset(ctx); + if (!thread_dataset) { + ESP_LOGE(TAG, "Unable to allocate Thread dataset"); + return ESP_ERR_NO_MEM; + } + + ESP_LOGD(TAG, "Thread Dataset Received"); + + thread_dataset->mLength = req_data->length; + memcpy(thread_dataset->mTlvs, req_data->dataset, thread_dataset->mLength); + + return ESP_OK; +} + +static esp_err_t thread_apply_config_handler(network_prov_ctx_t **ctx) +{ + otOperationalDatasetTlvs *thread_dataset = get_thread_dataset(ctx); + if (!thread_dataset) { + ESP_LOGE(TAG, "Thread Dataset not set"); + return ESP_ERR_INVALID_STATE; + } + + esp_err_t ret = network_prov_mgr_configure_thread_dataset(thread_dataset); + if (ret == ESP_OK) { + ESP_LOGD(TAG, "Thread Dataset Applied"); + } else { + ESP_LOGE(TAG, "Failed to apply Thread Dataset"); + } + + free_network_prov_ctx(ctx); + return ret; +} +#endif // CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD + + +esp_err_t get_network_prov_handlers(network_prov_config_handlers_t *ptr) +{ + if (!ptr) { + return ESP_ERR_INVALID_ARG; + } +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI + ptr->wifi_get_status_handler = wifi_get_status_handler; + ptr->wifi_set_config_handler = wifi_set_config_handler; + ptr->wifi_apply_config_handler = wifi_apply_config_handler; +#endif // CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD + ptr->thread_get_status_handler = thread_get_status_handler; + ptr->thread_set_config_handler = thread_set_config_handler; + ptr->thread_apply_config_handler = thread_apply_config_handler; +#endif // CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD + ptr->ctx = NULL; + return ESP_OK; +} + +/*************************************************************************/ +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI +static esp_err_t wifi_scan_start(bool blocking, bool passive, + uint8_t group_channels, uint32_t period_ms, + network_prov_scan_ctx_t **ctx) +{ + return network_prov_mgr_wifi_scan_start(blocking, passive, group_channels, period_ms); +} + +static esp_err_t wifi_scan_status(bool *scan_finished, + uint16_t *result_count, + network_prov_scan_ctx_t **ctx) +{ + *scan_finished = network_prov_mgr_wifi_scan_finished(); + *result_count = network_prov_mgr_wifi_scan_result_count(); + return ESP_OK; +} + +static esp_err_t wifi_scan_result(uint16_t result_index, + network_prov_scan_wifi_result_t *result, + network_prov_scan_ctx_t **ctx) +{ + const wifi_ap_record_t *record = network_prov_mgr_wifi_scan_result(result_index); + if (!record) { + return ESP_FAIL; + } + + /* Compile time check ensures memory safety in case SSID length in + * record / result structure definition changes in future */ + _Static_assert(sizeof(result->ssid) == sizeof(record->ssid), + "source and destination should be of same size"); + memcpy(result->ssid, record->ssid, sizeof(record->ssid)); + memcpy(result->bssid, record->bssid, sizeof(record->bssid)); + result->channel = record->primary; + result->rssi = record->rssi; + result->auth = record->authmode; + return ESP_OK; +} +#endif // CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI + +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD +static esp_err_t thread_scan_start(bool blocking, uint32_t channel_mask, network_prov_scan_ctx_t **ctx) +{ + return network_prov_mgr_thread_scan_start(blocking, channel_mask); +} + +static esp_err_t thread_scan_status(bool *scan_finished, + uint16_t *result_count, + network_prov_scan_ctx_t **ctx) +{ + *scan_finished = network_prov_mgr_thread_scan_finished(); + *result_count = network_prov_mgr_thread_scan_result_count(); + return ESP_OK; +} + +static esp_err_t thread_scan_result(uint16_t result_index, + network_prov_scan_thread_result_t *result, + network_prov_scan_ctx_t **ctx) +{ + const otActiveScanResult *record = network_prov_mgr_thread_scan_result(result_index); + if (!record) { + return ESP_FAIL; + } + + result->channel = record->mChannel; + result->pan_id = record->mPanId; + result->rssi = record->mRssi; + result->lqi = record->mLqi; + memcpy(result->ext_addr, record->mExtAddress.m8, sizeof(record->mExtAddress.m8)); + + if (record->mDiscover) { + memcpy(result->ext_pan_id, record->mExtendedPanId.m8, sizeof(result->ext_pan_id)); + memcpy(result->network_name, record->mNetworkName.m8, sizeof(record->mNetworkName.m8)); + } else { + memset(result->ext_pan_id, 0, sizeof(result->ext_pan_id)); + memset(result->network_name, 0, sizeof(result->network_name)); + } + + return ESP_OK; +} + +#endif // CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD + +esp_err_t get_network_scan_handlers(network_prov_scan_handlers_t *ptr) +{ + if (!ptr) { + return ESP_ERR_INVALID_ARG; + } +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI + ptr->wifi_scan_start = wifi_scan_start; + ptr->wifi_scan_status = wifi_scan_status; + ptr->wifi_scan_result = wifi_scan_result; +#endif // CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD + ptr->thread_scan_start = thread_scan_start; + ptr->thread_scan_status = thread_scan_status; + ptr->thread_scan_result = thread_scan_result; +#endif // CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD + ptr->ctx = NULL; + return ESP_OK; +} + +/*************************************************************************/ + +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI +static esp_err_t wifi_ctrl_reset(void) +{ + return network_prov_mgr_reset_wifi_sm_state_on_failure(); +} + +static esp_err_t wifi_ctrl_reprov(void) +{ + return network_prov_mgr_reset_wifi_sm_state_for_reprovision(); +} +#endif // CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI + +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD +static esp_err_t thread_ctrl_reset(void) +{ + return network_prov_mgr_reset_thread_sm_state_on_failure(); +} + +static esp_err_t thread_ctrl_reprov(void) +{ + return network_prov_mgr_reset_thread_sm_state_for_reprovision(); +} +#endif // CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD + +esp_err_t get_network_ctrl_handlers(network_ctrl_handlers_t *ptr) +{ + if (!ptr) { + return ESP_ERR_INVALID_ARG; + } +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI + ptr->wifi_ctrl_reset = wifi_ctrl_reset; + ptr->wifi_ctrl_reprov = wifi_ctrl_reprov; +#endif +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD + ptr->thread_ctrl_reset = thread_ctrl_reset; + ptr->thread_ctrl_reprov = thread_ctrl_reprov; +#endif + return ESP_OK; +} diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/src/manager.c b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/src/manager.c new file mode 100644 index 000000000..f53d3e9a2 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/src/manager.c @@ -0,0 +1,2476 @@ +/* + * SPDX-FileCopyrightText: 2019-2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include +#include + +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "network_provisioning_priv.h" + +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD +#include +#include +#include +#endif // CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD + +#define NETWORK_PROV_MGR_VERSION "netprov-v1.2" +#define WIFI_PROV_STORAGE_BIT BIT0 +#define WIFI_PROV_SETTING_BIT BIT1 +#define MAX_SCAN_RESULTS CONFIG_NETWORK_PROV_SCAN_MAX_ENTRIES + +#define ACQUIRE_LOCK(mux) assert(xSemaphoreTake(mux, portMAX_DELAY) == pdTRUE) +#define RELEASE_LOCK(mux) assert(xSemaphoreGive(mux) == pdTRUE) + +static const char *TAG = "network_prov_mgr"; + +ESP_EVENT_DEFINE_BASE(NETWORK_PROV_EVENT); +ESP_EVENT_DEFINE_BASE(NETWORK_PROV_MGR_PVT_EVENT); + +typedef enum { + NETWORK_PROV_STATE_IDLE, + NETWORK_PROV_STATE_STARTING, + NETWORK_PROV_STATE_STARTED, +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI + NETWORK_PROV_STATE_CRED_RECV, +#endif // CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD + NETWORK_PROV_STATE_DATASET_RECV, +#endif // CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD + NETWORK_PROV_STATE_FAIL, + NETWORK_PROV_STATE_SUCCESS, + NETWORK_PROV_STATE_STOPPING +} network_prov_mgr_state_t; + +typedef enum { + NETWORK_PROV_MGR_STOP, +} network_prov_mgr_pvt_event_t; + +/** + * @brief Structure for storing capabilities supported by + * the provisioning service + */ +struct network_prov_capabilities { + /* Security 0 is used */ + bool no_sec; + + /* Proof of Possession is not required for establishing session */ + bool no_pop; + + /* Provisioning doesn't stop on it's own after receiving Wi-Fi credentials or + * Thread dataset instead application has to explicitly call + * network_prov_mgr_stop_provisioning() */ + bool no_auto_stop; +}; + +/** + * @brief Structure for storing miscellaneous information about + * provisioning service that will be conveyed to clients + */ +struct network_prov_info { + const char *version; + struct network_prov_capabilities capabilities; +}; + +/** + * @brief Context data for provisioning manager + */ +struct network_prov_mgr_ctx { + /* Provisioning manager configuration */ + network_prov_mgr_config_t mgr_config; + + /* State of the provisioning service */ + network_prov_mgr_state_t prov_state; + + /* Provisioning scheme configuration */ + void *prov_scheme_config; + + /* Protocomm handle */ + protocomm_t *pc; + + /* Type of security to use with protocomm */ + int security; + + /* Pointer to security params */ + const void *protocomm_sec_params; + + /* Handle for Provisioning Auto Stop timer */ + esp_timer_handle_t autostop_timer; + + /* Handle for delayed cleanup timer */ + esp_timer_handle_t cleanup_delay_timer; + + /* Protocomm handlers for network configuration endpoint */ + network_prov_config_handlers_t *network_prov_handlers; + + /* Protocomm handlers for network scan endpoint */ + network_prov_scan_handlers_t *network_scan_handlers; + + /* Protocomm handlers for network ctrl endpoint */ + network_ctrl_handlers_t *network_ctrl_handlers; + + /* Count of used endpoint UUIDs */ + unsigned int endpoint_uuid_used; + + /* Provisioning service information */ + struct network_prov_info mgr_info; + + /* Application related information in JSON format */ + cJSON *app_info_json; + + /* Delay after which resources will be cleaned up asynchronously + * upon execution of network_prov_mgr_stop_provisioning() */ + uint32_t cleanup_delay; + /* Scan status */ + bool scanning; +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI + /* Handle for delayed wifi connection timer */ + esp_timer_handle_t wifi_connect_timer; + + /* State of Wi-Fi Station */ + network_prov_wifi_sta_state_t wifi_state; + + /* Code for Wi-Fi station disconnection (if disconnected) */ + network_prov_wifi_sta_fail_reason_t wifi_disconnect_reason; + + /* Wi-Fi scan parameters and state variables */ + uint8_t channels_per_group; + uint16_t curr_channel; + uint16_t ap_list_len[14]; // 14 entries corresponding to each channel + wifi_ap_record_t *ap_list[14]; + wifi_ap_record_t *ap_list_sorted[MAX_SCAN_RESULTS]; + wifi_scan_config_t scan_cfg; +#endif // CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI + +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD + /* Handle for Thread attaching timeout timer */ + esp_timer_handle_t thread_timeout_timer; + + /* State of Thread */ + network_prov_thread_state_t thread_state; + + /* Code for Thread detached (if detached) */ + network_prov_thread_fail_reason_t thread_detached_reason; + + /* Thread scan parameters and state variables */ + uint16_t scan_result_count; + otActiveScanResult *scan_result[MAX_SCAN_RESULTS]; +#endif // CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD +}; + +/* Mutex to lock/unlock access to provisioning singleton + * context data. This is allocated only once on first init + * and never deleted as network_prov_mgr is a singleton */ +static SemaphoreHandle_t prov_ctx_lock = NULL; + +/* Pointer to provisioning context data */ +static struct network_prov_mgr_ctx *prov_ctx; + +/* This executes registered app_event_callback for a particular event + * + * NOTE : By the time this fucntion returns, it is possible that + * the manager got de-initialized due to a call to network_prov_mgr_deinit() + * either inside the event callbacks or from another thread. Therefore + * post execution of execute_event_cb(), the validity of prov_ctx must + * always be checked. A cleaner way, to avoid this pitfall safely, would + * be to limit the usage of this function to only public APIs, and that + * too at the very end, just before returning. + * + * NOTE: This function should be called only after ensuring that the + * context is valid and the control mutex is locked. */ +static void execute_event_cb(network_prov_cb_event_t event_id, void *event_data, size_t event_data_size) +{ + ESP_LOGD(TAG, "execute_event_cb : %d", event_id); + + if (prov_ctx) { + network_prov_cb_func_t app_cb = prov_ctx->mgr_config.app_event_handler.event_cb; + void *app_data = prov_ctx->mgr_config.app_event_handler.user_data; + + network_prov_cb_func_t scheme_cb = prov_ctx->mgr_config.scheme_event_handler.event_cb; + void *scheme_data = prov_ctx->mgr_config.scheme_event_handler.user_data; + + /* Release the mutex before executing the callbacks. This is done so that + * network_prov_mgr_event_handler() doesn't stay blocked for the duration */ + RELEASE_LOCK(prov_ctx_lock); + + if (scheme_cb) { + /* Call scheme specific event handler */ + scheme_cb(scheme_data, event_id, event_data); + } + + if (app_cb) { + /* Call application specific event handler */ + app_cb(app_data, event_id, event_data); + } + + if (esp_event_post(NETWORK_PROV_EVENT, event_id, + event_data, event_data_size, + portMAX_DELAY) != ESP_OK) { + ESP_LOGE(TAG, "Failed to post event %d to default event loop", event_id); + } + + ACQUIRE_LOCK(prov_ctx_lock); + } +} + +esp_err_t network_prov_mgr_set_app_info(const char *label, const char *version, + const char **capabilities, size_t total_capabilities) +{ + if (!label || !version || !capabilities) { + return ESP_ERR_INVALID_ARG; + } + + if (!prov_ctx_lock) { + ESP_LOGE(TAG, "Provisioning manager not initialized"); + return ESP_ERR_INVALID_STATE; + } + + esp_err_t ret = ESP_FAIL; + ACQUIRE_LOCK(prov_ctx_lock); + + if (prov_ctx && prov_ctx->prov_state == NETWORK_PROV_STATE_IDLE) { + if (!prov_ctx->app_info_json) { + prov_ctx->app_info_json = cJSON_CreateObject(); + } + + cJSON *new_entry_json = cJSON_CreateObject(); + cJSON *capabilities_json = cJSON_CreateArray(); + cJSON_AddItemToObject(prov_ctx->app_info_json, label, new_entry_json); + + /* Version ("ver") */ + cJSON_AddStringToObject(new_entry_json, "ver", version); + + /* List of capabilities ("cap") */ + cJSON_AddItemToObject(new_entry_json, "cap", capabilities_json); + for (unsigned int i = 0; i < total_capabilities; i++) { + if (capabilities[i]) { + cJSON_AddItemToArray(capabilities_json, cJSON_CreateString(capabilities[i])); + } + } + ret = ESP_OK; + } else { + ret = ESP_ERR_INVALID_STATE; + } + + RELEASE_LOCK(prov_ctx_lock); + return ret; +} + +static cJSON *network_prov_get_info_json(void) +{ + cJSON *full_info_json = prov_ctx->app_info_json ? + cJSON_Duplicate(prov_ctx->app_info_json, 1) : cJSON_CreateObject(); + cJSON *prov_info_json = cJSON_CreateObject(); + cJSON *prov_capabilities = cJSON_CreateArray(); + + /* Use label "prov" to indicate provisioning related information */ + cJSON_AddItemToObject(full_info_json, "prov", prov_info_json); + + /* Version field */ + cJSON_AddStringToObject(prov_info_json, "ver", prov_ctx->mgr_info.version); + + /* Security field */ + cJSON_AddNumberToObject(prov_info_json, "sec_ver", prov_ctx->security); +#ifdef CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_PATCH_VERSION + int sec_ver = 0; + uint8_t sec_patch_ver = 0; + protocomm_get_sec_version(prov_ctx->pc, &sec_ver, &sec_patch_ver); + assert(sec_ver == prov_ctx->security); + cJSON_AddNumberToObject(prov_info_json, "sec_patch_ver", sec_patch_ver); +#endif + + /* Capabilities field */ + cJSON_AddItemToObject(prov_info_json, "cap", prov_capabilities); + + /* If Security / Proof of Possession is not used, indicate in capabilities */ + if (prov_ctx->mgr_info.capabilities.no_sec) { + cJSON_AddItemToArray(prov_capabilities, cJSON_CreateString("no_sec")); + } else if (prov_ctx->mgr_info.capabilities.no_pop) { + cJSON_AddItemToArray(prov_capabilities, cJSON_CreateString("no_pop")); + } + +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI + /* Indicate capability for performing Wi-Fi provision */ + cJSON_AddItemToArray(prov_capabilities, cJSON_CreateString("wifi_prov")); + /* Indicate capability for performing Wi-Fi scan */ + cJSON_AddItemToArray(prov_capabilities, cJSON_CreateString("wifi_scan")); +#endif +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD + /* Indicate capability for performing Thread provision */ + cJSON_AddItemToArray(prov_capabilities, cJSON_CreateString("thread_prov")); + /* Indicate capability for performing Thread scan */ + cJSON_AddItemToArray(prov_capabilities, cJSON_CreateString("thread_scan")); +#endif + return full_info_json; +} + +/* Declare the internal event handler */ +static void network_prov_mgr_event_handler_internal(void *arg, esp_event_base_t event_base, + int32_t event_id, void *event_data); + +static esp_err_t network_prov_mgr_start_service(const char *service_name, const char *service_key) +{ + const network_prov_scheme_t *scheme = &prov_ctx->mgr_config.scheme; + esp_err_t ret; + + /* Create new protocomm instance */ + prov_ctx->pc = protocomm_new(); + if (prov_ctx->pc == NULL) { + ESP_LOGE(TAG, "Failed to create new protocomm instance"); + return ESP_FAIL; + } + + ret = scheme->set_config_service(prov_ctx->prov_scheme_config, service_name, service_key); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to configure service"); + protocomm_delete(prov_ctx->pc); + return ret; + } + + /* Start provisioning */ + ret = scheme->prov_start(prov_ctx->pc, prov_ctx->prov_scheme_config); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to start service"); + protocomm_delete(prov_ctx->pc); + return ret; + } + + /* Set protocomm security type for endpoint */ + if (prov_ctx->security == 0) { +#ifdef CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_0 + ret = protocomm_set_security(prov_ctx->pc, "prov-session", + &protocomm_security0, NULL); +#else + // Enable SECURITY_VERSION_0 in Protocomm configuration menu + return ESP_ERR_NOT_SUPPORTED; +#endif + } else if (prov_ctx->security == 1) { +#ifdef CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_1 + ret = protocomm_set_security(prov_ctx->pc, "prov-session", + &protocomm_security1, prov_ctx->protocomm_sec_params); +#else + // Enable SECURITY_VERSION_1 in Protocomm configuration menu + return ESP_ERR_NOT_SUPPORTED; +#endif + } else if (prov_ctx->security == 2) { +#ifdef CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_2 + ret = protocomm_set_security(prov_ctx->pc, "prov-session", + &protocomm_security2, prov_ctx->protocomm_sec_params); +#else + // Enable SECURITY_VERSION_2 in Protocomm configuration menu + return ESP_ERR_NOT_SUPPORTED; +#endif + } else { + ESP_LOGE(TAG, "Unsupported protocomm security version %d", prov_ctx->security); + ret = ESP_ERR_INVALID_ARG; + } + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to set security endpoint"); + scheme->prov_stop(prov_ctx->pc); + protocomm_delete(prov_ctx->pc); + return ret; + } + + /* Set version information / capabilities of provisioning service and application */ + cJSON *version_json = network_prov_get_info_json(); + char *version_str = cJSON_Print(version_json); + ret = protocomm_set_version(prov_ctx->pc, "proto-ver", version_str); + free(version_str); + cJSON_Delete(version_json); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to set version endpoint"); + scheme->prov_stop(prov_ctx->pc); + protocomm_delete(prov_ctx->pc); + return ret; + } + + prov_ctx->network_prov_handlers = malloc(sizeof(network_prov_config_handlers_t)); + ret = get_network_prov_handlers(prov_ctx->network_prov_handlers); + if (ret != ESP_OK) { + ESP_LOGD(TAG, "Failed to allocate memory for provisioning handlers"); + scheme->prov_stop(prov_ctx->pc); + protocomm_delete(prov_ctx->pc); + return ESP_ERR_NO_MEM; + } + + /* Add protocomm endpoint for network configuration */ + ret = protocomm_add_endpoint(prov_ctx->pc, "prov-config", + network_prov_config_data_handler, + prov_ctx->network_prov_handlers); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to set provisioning endpoint"); + free(prov_ctx->network_prov_handlers); + scheme->prov_stop(prov_ctx->pc); + protocomm_delete(prov_ctx->pc); + return ret; + } + + prov_ctx->network_scan_handlers = malloc(sizeof(network_prov_scan_handlers_t)); + ret = get_network_scan_handlers(prov_ctx->network_scan_handlers); + if (ret != ESP_OK) { + ESP_LOGD(TAG, "Failed to allocate memory for network scan handlers"); + free(prov_ctx->network_prov_handlers); + scheme->prov_stop(prov_ctx->pc); + protocomm_delete(prov_ctx->pc); + return ESP_ERR_NO_MEM; + } + + /* Add endpoint for scanning networks and sending scan list */ + ret = protocomm_add_endpoint(prov_ctx->pc, "prov-scan", + network_prov_scan_handler, + prov_ctx->network_scan_handlers); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to set network scan endpoint"); + free(prov_ctx->network_scan_handlers); + free(prov_ctx->network_prov_handlers); + scheme->prov_stop(prov_ctx->pc); + protocomm_delete(prov_ctx->pc); + return ret; + } + + prov_ctx->network_ctrl_handlers = malloc(sizeof(network_ctrl_handlers_t)); + ret = get_network_ctrl_handlers(prov_ctx->network_ctrl_handlers); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to allocate memory for network ctrl handlers"); + free(prov_ctx->network_prov_handlers); + scheme->prov_stop(prov_ctx->pc); + protocomm_delete(prov_ctx->pc); + return ESP_ERR_NO_MEM; + } + + /* Add endpoint for controlling state of network provisioning */ + ret = protocomm_add_endpoint(prov_ctx->pc, "prov-ctrl", + network_ctrl_handler, + prov_ctx->network_ctrl_handlers); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to set network ctrl endpoint"); + free(prov_ctx->network_ctrl_handlers); + free(prov_ctx->network_prov_handlers); + scheme->prov_stop(prov_ctx->pc); + protocomm_delete(prov_ctx->pc); + return ret; + } + + /* Register global event handler */ +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI + ret = esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, + network_prov_mgr_event_handler_internal, NULL); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to register WiFi event handler"); + free(prov_ctx->network_scan_handlers); + free(prov_ctx->network_ctrl_handlers); + free(prov_ctx->network_prov_handlers); + scheme->prov_stop(prov_ctx->pc); + protocomm_delete(prov_ctx->pc); + return ret; + } + + ret = esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, + network_prov_mgr_event_handler_internal, NULL); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to register IP event handler"); + esp_event_handler_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, + network_prov_mgr_event_handler_internal); + free(prov_ctx->network_scan_handlers); + free(prov_ctx->network_ctrl_handlers); + free(prov_ctx->network_prov_handlers); + scheme->prov_stop(prov_ctx->pc); + protocomm_delete(prov_ctx->pc); + return ret; + } +#endif // CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI + +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD + ret = esp_event_handler_register(OPENTHREAD_EVENT, ESP_EVENT_ANY_ID, + network_prov_mgr_event_handler_internal, NULL); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to register OpenThread event handler"); + free(prov_ctx->network_scan_handlers); + free(prov_ctx->network_ctrl_handlers); + free(prov_ctx->network_prov_handlers); + scheme->prov_stop(prov_ctx->pc); + protocomm_delete(prov_ctx->pc); + return ret; + } +#endif // CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD + + ret = esp_event_handler_register(NETWORK_PROV_MGR_PVT_EVENT, NETWORK_PROV_MGR_STOP, + network_prov_mgr_event_handler_internal, NULL); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to register provisioning event handler"); +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI + esp_event_handler_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, + network_prov_mgr_event_handler_internal); + esp_event_handler_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP, + network_prov_mgr_event_handler_internal); +#endif // CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI + +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD + esp_event_handler_unregister(OPENTHREAD_EVENT, ESP_EVENT_ANY_ID, + network_prov_mgr_event_handler_internal); +#endif // CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD + free(prov_ctx->network_scan_handlers); + free(prov_ctx->network_ctrl_handlers); + free(prov_ctx->network_prov_handlers); + scheme->prov_stop(prov_ctx->pc); + protocomm_delete(prov_ctx->pc); + return ret; + } + + + ESP_LOGI(TAG, "Provisioning started with service name : %s ", + service_name ? service_name : ""); + return ESP_OK; +} + +esp_err_t network_prov_mgr_endpoint_create(const char *ep_name) +{ + if (!prov_ctx_lock) { + ESP_LOGE(TAG, "Provisioning manager not initialized"); + return ESP_ERR_INVALID_STATE; + } + + esp_err_t err = ESP_FAIL; + + ACQUIRE_LOCK(prov_ctx_lock); + if (prov_ctx && + prov_ctx->prov_state == NETWORK_PROV_STATE_IDLE) { + err = prov_ctx->mgr_config.scheme.set_config_endpoint( + prov_ctx->prov_scheme_config, ep_name, + prov_ctx->endpoint_uuid_used + 1); + } + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to create additional endpoint"); + } else { + prov_ctx->endpoint_uuid_used++; + } + RELEASE_LOCK(prov_ctx_lock); + return err; +} + +esp_err_t network_prov_mgr_endpoint_register(const char *ep_name, protocomm_req_handler_t handler, void *user_ctx) +{ + if (!prov_ctx_lock) { + ESP_LOGE(TAG, "Provisioning manager not initialized"); + return ESP_ERR_INVALID_STATE; + } + + esp_err_t err = ESP_FAIL; + + ACQUIRE_LOCK(prov_ctx_lock); + if (prov_ctx && + prov_ctx->prov_state > NETWORK_PROV_STATE_STARTING && + prov_ctx->prov_state < NETWORK_PROV_STATE_STOPPING) { + err = protocomm_add_endpoint(prov_ctx->pc, ep_name, handler, user_ctx); + } + RELEASE_LOCK(prov_ctx_lock); + + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to register handler for endpoint"); + } + return err; +} + +void network_prov_mgr_endpoint_unregister(const char *ep_name) +{ + if (!prov_ctx_lock) { + ESP_LOGE(TAG, "Provisioning manager not initialized"); + return; + } + + ACQUIRE_LOCK(prov_ctx_lock); + if (prov_ctx && + prov_ctx->prov_state > NETWORK_PROV_STATE_STARTING && + prov_ctx->prov_state < NETWORK_PROV_STATE_STOPPING) { + protocomm_remove_endpoint(prov_ctx->pc, ep_name); + } + RELEASE_LOCK(prov_ctx_lock); +} + +static void prov_stop_and_notify(bool is_async) +{ + esp_event_handler_unregister(NETWORK_PROV_MGR_PVT_EVENT, NETWORK_PROV_MGR_STOP, + network_prov_mgr_event_handler_internal); + + if (prov_ctx->cleanup_delay_timer) { + esp_timer_stop(prov_ctx->cleanup_delay_timer); + esp_timer_delete(prov_ctx->cleanup_delay_timer); + prov_ctx->cleanup_delay_timer = NULL; + } + + network_prov_cb_func_t app_cb = prov_ctx->mgr_config.app_event_handler.event_cb; + void *app_data = prov_ctx->mgr_config.app_event_handler.user_data; + + network_prov_cb_func_t scheme_cb = prov_ctx->mgr_config.scheme_event_handler.event_cb; + void *scheme_data = prov_ctx->mgr_config.scheme_event_handler.user_data; + + /* This delay is so that the client side app is notified first + * and then the provisioning is stopped. Generally 1000ms is enough. */ + if (!is_async) { + uint32_t cleanup_delay = prov_ctx->cleanup_delay > 100 ? prov_ctx->cleanup_delay : 100; + vTaskDelay(cleanup_delay / portTICK_PERIOD_MS); + } + + protocomm_remove_endpoint(prov_ctx->pc, "prov-ctrl"); + + protocomm_remove_endpoint(prov_ctx->pc, "prov-scan"); + + protocomm_remove_endpoint(prov_ctx->pc, "prov-config"); + + protocomm_unset_security(prov_ctx->pc, "prov-session"); + + protocomm_unset_version(prov_ctx->pc, "proto-ver"); + + /* All the extra application added endpoints are also + * removed automatically when prov_stop is called */ + prov_ctx->mgr_config.scheme.prov_stop(prov_ctx->pc); + + /* Delete protocomm instance */ + protocomm_delete(prov_ctx->pc); + prov_ctx->pc = NULL; + + /* Free provisioning handlers */ + free(prov_ctx->network_prov_handlers->ctx); + free(prov_ctx->network_prov_handlers); + prov_ctx->network_prov_handlers = NULL; + + free(prov_ctx->network_scan_handlers->ctx); + free(prov_ctx->network_scan_handlers); + prov_ctx->network_scan_handlers = NULL; + + free(prov_ctx->network_ctrl_handlers); + prov_ctx->network_ctrl_handlers = NULL; +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI + /* Switch device to Wi-Fi STA mode irrespective of + * whether provisioning was completed or not */ + esp_wifi_set_mode(WIFI_MODE_STA); +#endif + + ESP_LOGI(TAG, "Provisioning stopped"); + + if (is_async) { + /* NOTE: While calling this API in an async fashion, + * the context lock prov_ctx_lock has already been taken + */ + prov_ctx->prov_state = NETWORK_PROV_STATE_IDLE; + + ESP_LOGD(TAG, "execute_event_cb : %d", NETWORK_PROV_END); + if (scheme_cb) { + scheme_cb(scheme_data, NETWORK_PROV_END, NULL); + } + if (app_cb) { + app_cb(app_data, NETWORK_PROV_END, NULL); + } + if (esp_event_post(NETWORK_PROV_EVENT, NETWORK_PROV_END, NULL, 0, portMAX_DELAY) != ESP_OK) { + ESP_LOGE(TAG, "Failed to post event THREAD_PROV_END"); + } + } +} + +/* This will do one of these: + * 1) if blocking is false, start a cleanup timer for stopping the provisioning service (returns true) + * 2) if blocking is true, stop provisioning service immediately (returns true) + * 3) if service was already in the process of termination, in blocking mode this will + * wait till the service is stopped (returns false) + * 4) if service was not running, this will return immediately (returns false) + * + * NOTE: This function should be called only after ensuring that the context + * is valid and the control mutex is locked + * + * NOTE: When blocking mode is selected, the event callbacks are not executed. + * This help with de-initialization. + */ +static bool network_prov_mgr_stop_service(bool blocking) +{ + if (blocking) { + /* Wait for any ongoing calls to network_prov_mgr_start_service() or + * network_prov_mgr_stop_service() from another thread to finish */ + while (prov_ctx && ( + prov_ctx->prov_state == NETWORK_PROV_STATE_STARTING || + prov_ctx->prov_state == NETWORK_PROV_STATE_STOPPING)) { + RELEASE_LOCK(prov_ctx_lock); + vTaskDelay(100 / portTICK_PERIOD_MS); + ACQUIRE_LOCK(prov_ctx_lock); + } + } else { + /* Wait for any ongoing call to network_prov_mgr_start_service() + * from another thread to finish */ + while (prov_ctx && + prov_ctx->prov_state == NETWORK_PROV_STATE_STARTING) { + RELEASE_LOCK(prov_ctx_lock); + vTaskDelay(100 / portTICK_PERIOD_MS); + ACQUIRE_LOCK(prov_ctx_lock); + } + + if (prov_ctx && prov_ctx->prov_state == NETWORK_PROV_STATE_STOPPING) { + ESP_LOGD(TAG, "Provisioning is already stopping"); + return false; + } + } + + if (!prov_ctx || prov_ctx->prov_state == NETWORK_PROV_STATE_IDLE) { + ESP_LOGD(TAG, "Provisioning not running"); + return false; + } + + /* Timers not needed anymore */ + if (prov_ctx->autostop_timer) { + esp_timer_stop(prov_ctx->autostop_timer); + esp_timer_delete(prov_ctx->autostop_timer); + prov_ctx->autostop_timer = NULL; + } +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI + if (prov_ctx->wifi_connect_timer) { + esp_timer_stop(prov_ctx->wifi_connect_timer); + esp_timer_delete(prov_ctx->wifi_connect_timer); + prov_ctx->wifi_connect_timer = NULL; + } +#endif // CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD + if (prov_ctx->thread_timeout_timer) { + esp_timer_stop(prov_ctx->thread_timeout_timer); + esp_timer_delete(prov_ctx->thread_timeout_timer); + prov_ctx->thread_timeout_timer = NULL; + } +#endif // CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD + + ESP_LOGD(TAG, "Stopping provisioning"); + prov_ctx->prov_state = NETWORK_PROV_STATE_STOPPING; + + /* Free proof of possession */ + if (prov_ctx->protocomm_sec_params) { + if (prov_ctx->security == 1) { + // In case of security 1 we keep an internal copy of "pop". + // Hence free it at this point + uint8_t *pop = (uint8_t *)((protocomm_security1_params_t *) prov_ctx->protocomm_sec_params)->data; + free(pop); + } + prov_ctx->protocomm_sec_params = NULL; + } + +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI + /* Delete all scan results */ + for (uint16_t channel = 0; channel < 14; channel++) { + free(prov_ctx->ap_list[channel]); + prov_ctx->ap_list[channel] = NULL; + } + prov_ctx->scanning = false; + for (uint8_t i = 0; i < MAX_SCAN_RESULTS; i++) { + prov_ctx->ap_list_sorted[i] = NULL; + } + + /* Remove event handler */ + esp_event_handler_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, + network_prov_mgr_event_handler_internal); + esp_event_handler_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP, + network_prov_mgr_event_handler_internal); +#endif // CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI + +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD + /* Delete all scan results */ + prov_ctx->scanning = false; + for (uint8_t i = 0; i < MAX_SCAN_RESULTS; ++i) { + if (prov_ctx->scan_result[i]) { + free(prov_ctx->scan_result[i]); + } + prov_ctx->scan_result[i] = NULL; + } + prov_ctx->scan_result_count = 0; + + /* Remove event handler */ + esp_event_handler_unregister(OPENTHREAD_EVENT, ESP_EVENT_ANY_ID, + network_prov_mgr_event_handler_internal); +#endif // CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD + + if (blocking) { + /* Run the cleanup without launching a separate task. Also the + * NETWORK_PROV_END event is not emitted in this case */ + RELEASE_LOCK(prov_ctx_lock); + prov_stop_and_notify(false); + ACQUIRE_LOCK(prov_ctx_lock); + prov_ctx->prov_state = NETWORK_PROV_STATE_IDLE; + } else { + /* Launch cleanup timer to perform the cleanup asynchronously. + * It is important to do this asynchronously because, there are + * situations in which the transport level resources have to be + * released - some duration after - returning from a call to + * network_prov_mgr_stop_provisioning(), like when it is called + * inside a protocomm handler */ + uint64_t cleanup_delay_ms = prov_ctx->cleanup_delay > 100 ? prov_ctx->cleanup_delay : 100; + esp_timer_start_once(prov_ctx->cleanup_delay_timer, cleanup_delay_ms * 1000U); + ESP_LOGD(TAG, "Provisioning scheduled for stopping"); + } + return true; +} + +/* Task spawned by timer callback */ +static void stop_prov_timer_cb(void *arg) +{ + network_prov_mgr_stop_provisioning(); +} + +static void cleanup_delay_timer_cb(void *arg) +{ + esp_err_t ret = esp_event_post(NETWORK_PROV_MGR_PVT_EVENT, NETWORK_PROV_MGR_STOP, NULL, 0, pdMS_TO_TICKS(100)); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to post NETWORK_PROV_MGR_STOP event! %d %s", ret, esp_err_to_name(ret)); + } +} + +esp_err_t network_prov_mgr_disable_auto_stop(uint32_t cleanup_delay) +{ + if (!prov_ctx_lock) { + ESP_LOGE(TAG, "Provisioning manager not initialized"); + return ESP_ERR_INVALID_STATE; + } + + esp_err_t ret = ESP_FAIL; + ACQUIRE_LOCK(prov_ctx_lock); + + if (prov_ctx && prov_ctx->prov_state == NETWORK_PROV_STATE_IDLE) { + prov_ctx->mgr_info.capabilities.no_auto_stop = true; + prov_ctx->cleanup_delay = cleanup_delay; + ret = ESP_OK; + } else { + ret = ESP_ERR_INVALID_STATE; + } + + RELEASE_LOCK(prov_ctx_lock); + return ret; +} + +/* Call this if provisioning is completed before the timeout occurs */ +esp_err_t network_prov_mgr_done(void) +{ + if (!prov_ctx_lock) { + ESP_LOGE(TAG, "Provisioning manager not initialized"); + return ESP_ERR_INVALID_STATE; + } + + bool auto_stop_enabled = false; + ACQUIRE_LOCK(prov_ctx_lock); + if (prov_ctx && !prov_ctx->mgr_info.capabilities.no_auto_stop) { + auto_stop_enabled = true; + } + RELEASE_LOCK(prov_ctx_lock); + + /* Stop provisioning if auto stop is enabled */ + if (auto_stop_enabled) { + network_prov_mgr_stop_provisioning(); + } + return ESP_OK; +} + +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI +static esp_err_t update_wifi_scan_results(void) +{ + if (!prov_ctx->scanning) { + return ESP_ERR_INVALID_STATE; + } + ESP_LOGD(TAG, "Scan finished"); + + esp_err_t ret = ESP_FAIL; + uint16_t count = 0; + uint16_t curr_channel = prov_ctx->curr_channel; + + if (prov_ctx->ap_list[curr_channel]) { + free(prov_ctx->ap_list[curr_channel]); + prov_ctx->ap_list[curr_channel] = NULL; + prov_ctx->ap_list_len[curr_channel] = 0; + } + + if (esp_wifi_scan_get_ap_num(&count) != ESP_OK) { + ESP_LOGE(TAG, "Failed to get count of scanned APs"); + goto exit; + } + + if (!count) { + ESP_LOGD(TAG, "Scan result empty"); + ret = ESP_OK; + goto exit; + } + + uint16_t get_count = MIN(count, MAX_SCAN_RESULTS); + prov_ctx->ap_list[curr_channel] = (wifi_ap_record_t *) calloc(get_count, sizeof(wifi_ap_record_t)); + if (!prov_ctx->ap_list[curr_channel]) { + ESP_LOGE(TAG, "Failed to allocate memory for AP list"); + esp_wifi_clear_ap_list(); + goto exit; + } + if (esp_wifi_scan_get_ap_records(&get_count, prov_ctx->ap_list[curr_channel]) != ESP_OK) { + ESP_LOGE(TAG, "Failed to get scanned AP records"); + goto exit; + } + prov_ctx->ap_list_len[curr_channel] = get_count; + + if (prov_ctx->channels_per_group) { + ESP_LOGD(TAG, "Scan results for channel %d :", curr_channel); + } else { + ESP_LOGD(TAG, "Scan results :"); + } + ESP_LOGD(TAG, "\tS.N. %-32s %-12s %s %s", "SSID", "BSSID", "RSSI", "AUTH"); + for (uint8_t i = 0; i < prov_ctx->ap_list_len[curr_channel]; i++) { + ESP_LOGD(TAG, "\t[%2d] %-32s %02x%02x%02x%02x%02x%02x %4d %4d", i, + prov_ctx->ap_list[curr_channel][i].ssid, + prov_ctx->ap_list[curr_channel][i].bssid[0], + prov_ctx->ap_list[curr_channel][i].bssid[1], + prov_ctx->ap_list[curr_channel][i].bssid[2], + prov_ctx->ap_list[curr_channel][i].bssid[3], + prov_ctx->ap_list[curr_channel][i].bssid[4], + prov_ctx->ap_list[curr_channel][i].bssid[5], + prov_ctx->ap_list[curr_channel][i].rssi, + prov_ctx->ap_list[curr_channel][i].authmode); + } + + /* Store results in sorted list */ + { + int rc = get_count; + int is = MAX_SCAN_RESULTS - rc - 1; + while (rc > 0 && is >= 0) { + if (prov_ctx->ap_list_sorted[is]) { + if (prov_ctx->ap_list_sorted[is]->rssi > prov_ctx->ap_list[curr_channel][rc - 1].rssi) { + prov_ctx->ap_list_sorted[is + rc] = &prov_ctx->ap_list[curr_channel][rc - 1]; + rc--; + continue; + } + prov_ctx->ap_list_sorted[is + rc] = prov_ctx->ap_list_sorted[is]; + } + is--; + } + while (rc > 0) { + prov_ctx->ap_list_sorted[rc - 1] = &prov_ctx->ap_list[curr_channel][rc - 1]; + rc--; + } + } + + ret = ESP_OK; +exit: + + if (!prov_ctx->channels_per_group) { + /* All channel scan was performed + * so nothing more to do */ + prov_ctx->scanning = false; + goto final; + } + + curr_channel = prov_ctx->curr_channel = (prov_ctx->curr_channel + 1) % 14; + if (ret != ESP_OK || curr_channel == 0) { + prov_ctx->scanning = false; + goto final; + } + + if ((curr_channel % prov_ctx->channels_per_group) == 0) { + vTaskDelay(120 / portTICK_PERIOD_MS); + } + + ESP_LOGD(TAG, "Scan starting on channel %u...", curr_channel); + prov_ctx->scan_cfg.channel = curr_channel; + ret = esp_wifi_scan_start(&prov_ctx->scan_cfg, false); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to start scan"); + prov_ctx->scanning = false; + goto final; + } + ESP_LOGD(TAG, "Scan started"); + +final: + + return ret; +} + +esp_err_t network_prov_mgr_wifi_scan_start(bool blocking, bool passive, + uint8_t group_channels, uint32_t period_ms) +{ + if (!prov_ctx_lock) { + ESP_LOGE(TAG, "Provisioning manager not initialized"); + return ESP_ERR_INVALID_STATE; + } + ACQUIRE_LOCK(prov_ctx_lock); + + if (!prov_ctx) { + ESP_LOGE(TAG, "Provisioning manager not initialized"); + RELEASE_LOCK(prov_ctx_lock); + return ESP_ERR_INVALID_STATE; + } + + if (prov_ctx->scanning) { + ESP_LOGD(TAG, "Scan already running"); + RELEASE_LOCK(prov_ctx_lock); + return ESP_OK; + } + + /* Clear sorted list for new entries */ + for (uint8_t i = 0; i < MAX_SCAN_RESULTS; i++) { + prov_ctx->ap_list_sorted[i] = NULL; + } + + if (passive) { + prov_ctx->scan_cfg.scan_type = WIFI_SCAN_TYPE_PASSIVE; + /* We do not recommend scan configuration modification in Wi-Fi and BT coexistence mode */ +#if !CONFIG_BT_ENABLED + prov_ctx->scan_cfg.scan_time.passive = period_ms; +#endif + } else { + prov_ctx->scan_cfg.scan_type = WIFI_SCAN_TYPE_ACTIVE; + /* We do not recommend scan configuration modification in Wi-Fi and BT coexistence mode */ +#if !CONFIG_BT_ENABLED + prov_ctx->scan_cfg.scan_time.active.min = period_ms; + prov_ctx->scan_cfg.scan_time.active.max = period_ms; +#endif + } + prov_ctx->channels_per_group = group_channels; + + if (prov_ctx->channels_per_group) { + ESP_LOGD(TAG, "Scan starting on channel 1..."); + prov_ctx->scan_cfg.channel = 1; + } else { + ESP_LOGD(TAG, "Scan starting..."); + prov_ctx->scan_cfg.channel = 0; + } + + if (esp_wifi_scan_start(&prov_ctx->scan_cfg, false) != ESP_OK) { + ESP_LOGE(TAG, "Failed to start scan"); + RELEASE_LOCK(prov_ctx_lock); + return ESP_FAIL; + } + + ESP_LOGD(TAG, "Scan started"); + prov_ctx->scanning = true; + prov_ctx->curr_channel = prov_ctx->scan_cfg.channel; + RELEASE_LOCK(prov_ctx_lock); + + /* If scan is to be non-blocking, return immediately */ + if (!blocking) { + return ESP_OK; + } + + /* Loop till scan is complete */ + bool scanning = true; + while (scanning) { + ACQUIRE_LOCK(prov_ctx_lock); + scanning = (prov_ctx && prov_ctx->scanning); + RELEASE_LOCK(prov_ctx_lock); + + /* 120ms delay is sufficient for Wi-Fi beacons to be sent */ + vTaskDelay(120 / portTICK_PERIOD_MS); + } + return ESP_OK; +} + +bool network_prov_mgr_wifi_scan_finished(void) +{ + bool scan_finished = true; + if (!prov_ctx_lock) { + ESP_LOGE(TAG, "Provisioning manager not initialized"); + return scan_finished; + } + + ACQUIRE_LOCK(prov_ctx_lock); + if (!prov_ctx) { + ESP_LOGE(TAG, "Provisioning manager not initialized"); + RELEASE_LOCK(prov_ctx_lock); + return scan_finished; + } + + scan_finished = !prov_ctx->scanning; + RELEASE_LOCK(prov_ctx_lock); + return scan_finished; +} + +uint16_t network_prov_mgr_wifi_scan_result_count(void) +{ + uint16_t rval = 0; + if (!prov_ctx_lock) { + ESP_LOGE(TAG, "Provisioning manager not initialized"); + return rval; + } + + ACQUIRE_LOCK(prov_ctx_lock); + if (!prov_ctx) { + ESP_LOGE(TAG, "Provisioning manager not initialized"); + RELEASE_LOCK(prov_ctx_lock); + return rval; + } + + while (rval < MAX_SCAN_RESULTS) { + if (!prov_ctx->ap_list_sorted[rval]) { + break; + } + rval++; + } + RELEASE_LOCK(prov_ctx_lock); + return rval; +} + +const wifi_ap_record_t *network_prov_mgr_wifi_scan_result(uint16_t index) +{ + const wifi_ap_record_t *rval = NULL; + if (!prov_ctx_lock) { + ESP_LOGE(TAG, "Provisioning manager not initialized"); + return rval; + } + + ACQUIRE_LOCK(prov_ctx_lock); + if (!prov_ctx) { + ESP_LOGE(TAG, "Provisioning manager not initialized"); + RELEASE_LOCK(prov_ctx_lock); + return rval; + } + + if (index < MAX_SCAN_RESULTS) { + rval = prov_ctx->ap_list_sorted[index]; + } + RELEASE_LOCK(prov_ctx_lock); + return rval; +} + +esp_err_t network_prov_mgr_get_wifi_state(network_prov_wifi_sta_state_t *state) +{ + if (!prov_ctx_lock) { + ESP_LOGE(TAG, "Provisioning manager not initialized"); + return ESP_ERR_INVALID_STATE; + } + + ACQUIRE_LOCK(prov_ctx_lock); + if (prov_ctx == NULL || state == NULL) { + RELEASE_LOCK(prov_ctx_lock); + return ESP_FAIL; + } + + *state = prov_ctx->wifi_state; + RELEASE_LOCK(prov_ctx_lock); + return ESP_OK; +} + +esp_err_t network_prov_mgr_get_wifi_disconnect_reason(network_prov_wifi_sta_fail_reason_t *reason) +{ + if (!prov_ctx_lock) { + ESP_LOGE(TAG, "Provisioning manager not initialized"); + return ESP_ERR_INVALID_STATE; + } + + ACQUIRE_LOCK(prov_ctx_lock); + if (prov_ctx == NULL || reason == NULL) { + RELEASE_LOCK(prov_ctx_lock); + return ESP_FAIL; + } + + if (prov_ctx->wifi_state != NETWORK_PROV_WIFI_STA_DISCONNECTED) { + RELEASE_LOCK(prov_ctx_lock); + return ESP_FAIL; + } + + *reason = prov_ctx->wifi_disconnect_reason; + RELEASE_LOCK(prov_ctx_lock); + return ESP_OK; +} + +static void debug_print_wifi_credentials(wifi_sta_config_t sta, const char *pretext) +{ + size_t passlen = strlen((const char *) sta.password); + ESP_LOGD(TAG, "%s Wi-Fi SSID : %.*s", pretext, + strnlen((const char *) sta.ssid, sizeof(sta.ssid)), (const char *) sta.ssid); + + if (passlen) { + /* Mask password partially if longer than 3, else mask it completely */ + memset(sta.password + (passlen > 3), '*', passlen - 2 * (passlen > 3)); + ESP_LOGD(TAG, "%s Wi-Fi Password : %s", pretext, (const char *) sta.password); + } +} + +esp_err_t network_prov_mgr_is_wifi_provisioned(bool *provisioned) +{ + if (!provisioned) { + return ESP_ERR_INVALID_ARG; + } + + *provisioned = false; + + /* Get Wi-Fi Station configuration */ + wifi_config_t wifi_cfg; + if (esp_wifi_get_config(WIFI_IF_STA, &wifi_cfg) != ESP_OK) { + return ESP_FAIL; + } + + if (strlen((const char *) wifi_cfg.sta.ssid)) { + *provisioned = true; + debug_print_wifi_credentials(wifi_cfg.sta, "Found"); + } + return ESP_OK; +} + +bool network_prov_mgr_is_sm_idle(void) +{ + return (prov_ctx->prov_state == NETWORK_PROV_STATE_IDLE); +} + +static void wifi_connect_timer_cb(void *arg) +{ + if (esp_wifi_connect() != ESP_OK) { + ESP_LOGE(TAG, "Failed to connect Wi-Fi"); + } +} + +esp_err_t network_prov_mgr_configure_wifi_sta(wifi_config_t *wifi_cfg) +{ + if (!prov_ctx_lock) { + ESP_LOGE(TAG, "Provisioning manager not initialized"); + return ESP_ERR_INVALID_STATE; + } + + ACQUIRE_LOCK(prov_ctx_lock); + if (!prov_ctx) { + ESP_LOGE(TAG, "Invalid state of Provisioning app"); + RELEASE_LOCK(prov_ctx_lock); + return ESP_FAIL; + } + if (prov_ctx->prov_state >= NETWORK_PROV_STATE_CRED_RECV) { + ESP_LOGE(TAG, "Wi-Fi credentials already received by provisioning app"); + RELEASE_LOCK(prov_ctx_lock); + return ESP_FAIL; + } + debug_print_wifi_credentials(wifi_cfg->sta, "Received"); + + /* Configure Wi-Fi as both AP and/or Station */ + if (esp_wifi_set_mode(prov_ctx->mgr_config.scheme.wifi_mode) != ESP_OK) { + ESP_LOGE(TAG, "Failed to set Wi-Fi mode"); + RELEASE_LOCK(prov_ctx_lock); + return ESP_FAIL; + } + + /* Don't release mutex yet as it is possible that right after + * esp_wifi_connect() is called below, the related Wi-Fi event + * happens even before manager state is updated in the next + * few lines causing the internal event handler to miss */ + + /* Set Wi-Fi storage again to flash to keep the newly + * provided credentials on NVS */ + if (esp_wifi_set_storage(WIFI_STORAGE_FLASH) != ESP_OK) { + ESP_LOGE(TAG, "Failed to set storage Wi-Fi"); + RELEASE_LOCK(prov_ctx_lock); + return ESP_FAIL; + } + /* Configure Wi-Fi station with host credentials + * provided during provisioning */ + if (esp_wifi_set_config(WIFI_IF_STA, wifi_cfg) != ESP_OK) { + ESP_LOGE(TAG, "Failed to set Wi-Fi configuration"); + RELEASE_LOCK(prov_ctx_lock); + return ESP_FAIL; + } + /* Connect to AP after one second so that the response can + * be sent to the client successfully, before a channel change happens*/ + if (esp_timer_start_once(prov_ctx->wifi_connect_timer, 1000 * 1000U) != ESP_OK) { + ESP_LOGE(TAG, "Failed to start Wi-Fi connect timer"); + RELEASE_LOCK(prov_ctx_lock); + return ESP_FAIL; + } + + /* Reset Wi-Fi station state for provisioning app */ + prov_ctx->wifi_state = NETWORK_PROV_WIFI_STA_CONNECTING; + prov_ctx->prov_state = NETWORK_PROV_STATE_CRED_RECV; + /* Execute user registered callback handler */ + execute_event_cb(NETWORK_PROV_WIFI_CRED_RECV, (void *)&wifi_cfg->sta, sizeof(wifi_cfg->sta)); + RELEASE_LOCK(prov_ctx_lock); + + return ESP_OK; +} +#endif // CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI + +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD +static char hex_byte_to_char(uint8_t byte) +{ + byte = byte & 0x0f; + if (byte <= 9) { + return '0' + byte; + } + return 'A' + byte - 10; +} + +static bool hex_to_string(uint8_t *hex, size_t hex_len, char *str, size_t str_len) +{ + if (hex_len * 2 < str_len) { + for (size_t i = 0; i < hex_len; ++i) { + str[2 * i + 1] = hex_byte_to_char(hex[i]); + str[2 * i] = hex_byte_to_char(hex[i] >> 4); + } + str[hex_len * 2] = 0; + return true; + } + return false; +} + +static void debug_print_thread_dataset(otOperationalDataset *dataset) +{ + if (dataset) { + ESP_LOGD(TAG, "Thread Network Name: %s", dataset->mNetworkName.m8); + char str[33]; + if (hex_to_string(dataset->mNetworkKey.m8, sizeof(dataset->mNetworkKey.m8), str, sizeof(str))) { + ESP_LOGD(TAG, "Thread Network Key: %s", str); + } + if (hex_to_string(dataset->mExtendedPanId.m8, sizeof(dataset->mExtendedPanId.m8), str, sizeof(str))) { + ESP_LOGD(TAG, "Thread Extended PAN ID: %s", str); + } + ESP_LOGD(TAG, "Thread Channel: %d", dataset->mChannel); + ESP_LOGD(TAG, "Thread PAN ID: %d", dataset->mPanId); + } +} + +static void thread_timeout_timer_cb(void *arg) +{ + if (!prov_ctx_lock) { + ESP_LOGE(TAG, "Provisioning manager not initialized"); + return; + } + + ACQUIRE_LOCK(prov_ctx_lock); + if (!prov_ctx) { + ESP_LOGE(TAG, "Invalid state of Provisioning app"); + RELEASE_LOCK(prov_ctx_lock); + return; + } + + prov_ctx->thread_state = NETWORK_PROV_THREAD_DETACHED; + prov_ctx->prov_state = NETWORK_PROV_STATE_FAIL; + prov_ctx->thread_detached_reason = NETWORK_PROV_THREAD_NETWORK_NOT_FOUND; + execute_event_cb(NETWORK_PROV_THREAD_DATASET_FAIL, (void *)&prov_ctx->thread_detached_reason, + sizeof(prov_ctx->thread_detached_reason)); + RELEASE_LOCK(prov_ctx_lock); + return; +} + + +static esp_err_t set_thread_enable(bool val) +{ + esp_openthread_lock_acquire(portMAX_DELAY); + otInstance *instance = esp_openthread_get_instance(); + bool is_enabled = (otThreadGetDeviceRole(instance) != OT_DEVICE_ROLE_DISABLED); + bool is_ip6_enabled = otIp6IsEnabled(instance); + if (val && !is_ip6_enabled) { + if (otIp6SetEnabled(instance, val) != OT_ERROR_NONE) { + esp_openthread_lock_release(); + return ESP_FAIL; + } + } + if (val != is_enabled) { + if (otThreadSetEnabled(instance, val) != OT_ERROR_NONE) { + esp_openthread_lock_release(); + return ESP_FAIL; + } + } + if (!val && is_ip6_enabled) { + if (otIp6SetEnabled(instance, val) != OT_ERROR_NONE) { + esp_openthread_lock_release(); + return ESP_FAIL; + } + } + esp_openthread_lock_release(); + return ESP_OK; +} + +static esp_err_t set_thread_dataset(otOperationalDatasetTlvs *dataset_tlvs) +{ + otError err = OT_ERROR_NONE; + esp_openthread_lock_acquire(portMAX_DELAY); + otInstance *instance = esp_openthread_get_instance(); + err = otDatasetSetActiveTlvs(instance, dataset_tlvs); + esp_openthread_lock_release(); + return err == OT_ERROR_NONE ? ESP_OK : ESP_FAIL; +} + +static void update_thread_scan_result(otActiveScanResult *result, void *context) +{ + if (!prov_ctx_lock) { + ESP_LOGE(TAG, "Provisioning manager not initialized"); + return; + } + ACQUIRE_LOCK(prov_ctx_lock); + + if (!prov_ctx) { + ESP_LOGE(TAG, "Provisioning manager not initialized"); + RELEASE_LOCK(prov_ctx_lock); + return; + } + + if (!prov_ctx->scanning) { + ESP_LOGD(TAG, "Scan not running"); + RELEASE_LOCK(prov_ctx_lock); + return; + } + + if (!result) { + prov_ctx->scanning = false; + ESP_LOGD(TAG, "Scan finished"); + RELEASE_LOCK(prov_ctx_lock); + return; + } + + otActiveScanResult *new_result = (otActiveScanResult *)malloc(sizeof(otActiveScanResult)); + if (!new_result) { + ESP_LOGE(TAG, "Failed to allocate memory for Thread scan result"); + RELEASE_LOCK(prov_ctx_lock); + return; + } + memcpy(new_result, result, sizeof(otActiveScanResult)); + + if (prov_ctx->scan_result_count < MAX_SCAN_RESULTS) { + prov_ctx->scan_result[prov_ctx->scan_result_count] = new_result; + prov_ctx->scan_result_count++; + } + RELEASE_LOCK(prov_ctx_lock); +} + +esp_err_t network_prov_mgr_thread_scan_start(bool blocking, uint32_t channel_mask) +{ + if (!prov_ctx_lock) { + ESP_LOGE(TAG, "Provisioning manager not initialized"); + return ESP_ERR_INVALID_STATE; + } + ACQUIRE_LOCK(prov_ctx_lock); + + if (!prov_ctx) { + ESP_LOGE(TAG, "Provisioning manager not initialized"); + RELEASE_LOCK(prov_ctx_lock); + return ESP_ERR_INVALID_STATE; + } + + if (prov_ctx->scanning) { + ESP_LOGD(TAG, "Scan already running"); + RELEASE_LOCK(prov_ctx_lock); + return ESP_OK; + } + + /* Clear sorted list for new entries */ + for (uint8_t i = 0; i < MAX_SCAN_RESULTS; i++) { + if (prov_ctx->scan_result[i]) { + free(prov_ctx->scan_result[i]); + prov_ctx->scan_result[i] = 0; + } + } + prov_ctx->scan_result_count = 0; + + esp_openthread_lock_acquire(portMAX_DELAY); + otInstance *instance = esp_openthread_get_instance(); + // Make netif enabled before start scaning + if (!otIp6IsEnabled(instance)) { + if (otIp6SetEnabled(instance, true) != OT_ERROR_NONE) { + ESP_LOGE(TAG, "Failed to enable netif"); + RELEASE_LOCK(prov_ctx_lock); + esp_openthread_lock_release(); + return ESP_FAIL; + } + } + + if (otThreadDiscover(instance, channel_mask, OT_PANID_BROADCAST, false, false, update_thread_scan_result, NULL) != OT_ERROR_NONE) { + ESP_LOGE(TAG, "Failed to start scan"); + RELEASE_LOCK(prov_ctx_lock); + esp_openthread_lock_release(); + return ESP_FAIL; + } + esp_openthread_lock_release(); + + ESP_LOGI(TAG, "Scan started"); + prov_ctx->scanning = true; + RELEASE_LOCK(prov_ctx_lock); + + /* If scan is to be non-blocking, return immediately */ + if (!blocking) { + return ESP_OK; + } + + /* Loop till scan is complete */ + bool scanning = true; + while (scanning) { + ACQUIRE_LOCK(prov_ctx_lock); + scanning = (prov_ctx && prov_ctx->scanning); + RELEASE_LOCK(prov_ctx_lock); + + /* 500ms delay is sufficient for Thread beacons to be sent */ + vTaskDelay(500 / portTICK_PERIOD_MS); + } + return ESP_OK; +} + +bool network_prov_mgr_thread_scan_finished(void) +{ + bool scan_finished = true; + if (!prov_ctx_lock) { + ESP_LOGE(TAG, "Provisioning manager not initialized"); + return scan_finished; + } + + ACQUIRE_LOCK(prov_ctx_lock); + if (!prov_ctx) { + ESP_LOGE(TAG, "Provisioning manager not initialized"); + RELEASE_LOCK(prov_ctx_lock); + return scan_finished; + } + + scan_finished = !prov_ctx->scanning; + RELEASE_LOCK(prov_ctx_lock); + return scan_finished; +} + +uint16_t network_prov_mgr_thread_scan_result_count(void) +{ + uint16_t rval = 0; + if (!prov_ctx_lock) { + ESP_LOGE(TAG, "Provisioning manager not initialized"); + return rval; + } + + ACQUIRE_LOCK(prov_ctx_lock); + if (!prov_ctx) { + ESP_LOGE(TAG, "Provisioning manager not initialized"); + RELEASE_LOCK(prov_ctx_lock); + return rval; + } + + rval = prov_ctx->scan_result_count; + RELEASE_LOCK(prov_ctx_lock); + return rval; +} + +const otActiveScanResult *network_prov_mgr_thread_scan_result(uint16_t index) +{ + const otActiveScanResult *rval = NULL; + if (!prov_ctx_lock) { + ESP_LOGE(TAG, "Provisioning manager not initialized"); + return rval; + } + + ACQUIRE_LOCK(prov_ctx_lock); + if (!prov_ctx) { + ESP_LOGE(TAG, "Provisioning manager not initialized"); + RELEASE_LOCK(prov_ctx_lock); + return rval; + } + + if (index < MAX_SCAN_RESULTS) { + rval = prov_ctx->scan_result[index]; + } + RELEASE_LOCK(prov_ctx_lock); + return rval; +} + +esp_err_t network_prov_mgr_get_thread_state(network_prov_thread_state_t *state) +{ + if (!prov_ctx_lock) { + ESP_LOGE(TAG, "Provisioning manager not initialized"); + return ESP_ERR_INVALID_STATE; + } + + ACQUIRE_LOCK(prov_ctx_lock); + if (prov_ctx == NULL || state == NULL) { + RELEASE_LOCK(prov_ctx_lock); + return ESP_FAIL; + } + + *state = prov_ctx->thread_state; + RELEASE_LOCK(prov_ctx_lock); + return ESP_OK; +} + +esp_err_t network_prov_mgr_get_thread_detached_reason(network_prov_thread_fail_reason_t *reason) +{ + if (!prov_ctx_lock) { + ESP_LOGE(TAG, "Provisioning manager not initialized"); + return ESP_ERR_INVALID_STATE; + } + + ACQUIRE_LOCK(prov_ctx_lock); + if (prov_ctx == NULL || reason == NULL) { + RELEASE_LOCK(prov_ctx_lock); + return ESP_FAIL; + } + + if (prov_ctx->thread_state != NETWORK_PROV_THREAD_DETACHED) { + RELEASE_LOCK(prov_ctx_lock); + return ESP_FAIL; + } + + *reason = prov_ctx->thread_detached_reason; + RELEASE_LOCK(prov_ctx_lock); + return ESP_OK; +} + +esp_err_t network_prov_mgr_is_thread_provisioned(bool *provisioned) +{ + if (!provisioned) { + return ESP_ERR_INVALID_ARG; + } + + *provisioned = false; + otOperationalDataset dataset; + esp_openthread_lock_acquire(portMAX_DELAY); + otError ot_err = otDatasetGetActive(esp_openthread_get_instance(), &dataset); + esp_openthread_lock_release(); + if (ot_err == OT_ERROR_NONE) { + *provisioned = true; + debug_print_thread_dataset(&dataset); + } + + return ESP_OK; +} + + +esp_err_t network_prov_mgr_configure_thread_dataset(otOperationalDatasetTlvs *dataset_tlvs) +{ + esp_err_t err = ESP_OK; + if (!prov_ctx_lock) { + ESP_LOGE(TAG, "Provisioning manager not initialized"); + return ESP_ERR_INVALID_STATE; + } + + ACQUIRE_LOCK(prov_ctx_lock); + if (!prov_ctx) { + ESP_LOGE(TAG, "Invalid state of Provisioning app"); + RELEASE_LOCK(prov_ctx_lock); + return ESP_FAIL; + } + if (prov_ctx->prov_state >= NETWORK_PROV_STATE_DATASET_RECV) { + ESP_LOGE(TAG, "Dataset already received by provisioning app"); + RELEASE_LOCK(prov_ctx_lock); + return ESP_FAIL; + } + + otOperationalDataset dataset; + otError ot_err = otDatasetParseTlvs(dataset_tlvs, &dataset); + if (ot_err != OT_ERROR_NONE) { + prov_ctx->thread_state = NETWORK_PROV_THREAD_DETACHED; + prov_ctx->prov_state = NETWORK_PROV_STATE_FAIL; + prov_ctx->thread_detached_reason = NETWORK_PROV_THREAD_DATASET_INVALID; + execute_event_cb(NETWORK_PROV_THREAD_DATASET_FAIL, (void *)&prov_ctx->thread_detached_reason, + sizeof(prov_ctx->thread_detached_reason)); + RELEASE_LOCK(prov_ctx_lock); + return ESP_FAIL; + } + debug_print_thread_dataset(&dataset); + + err = set_thread_enable(false); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to stop Thread"); + RELEASE_LOCK(prov_ctx_lock); + return err; + } + err = set_thread_dataset(dataset_tlvs); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to set Thread dataset"); + RELEASE_LOCK(prov_ctx_lock); + return err; + } + err = set_thread_enable(true); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to start Thread"); + RELEASE_LOCK(prov_ctx_lock); + return err; + } + + /* Start the timeout timer*/ + if (esp_timer_start_once(prov_ctx->thread_timeout_timer, 20000 * 1000U) != ESP_OK) { + ESP_LOGE(TAG, "Failed to start Thread attaching timer"); + RELEASE_LOCK(prov_ctx_lock); + return ESP_FAIL; + } + + /* Reset Thread state for provisioning app */ + prov_ctx->thread_state = NETWORK_PROV_THREAD_ATTACHING; + prov_ctx->prov_state = NETWORK_PROV_STATE_DATASET_RECV; + /* Execute user registered callback handler */ + execute_event_cb(NETWORK_PROV_THREAD_DATASET_RECV, &dataset, sizeof(dataset)); + RELEASE_LOCK(prov_ctx_lock); + + return ESP_OK; +} +#endif // CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD + +static void network_prov_mgr_event_handler_internal( + void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data) +{ + if (!prov_ctx_lock) { + ESP_LOGE(TAG, "Provisioning manager not initialized"); + return; + } + + ACQUIRE_LOCK(prov_ctx_lock); + + /* If pointer to provisioning application data is NULL + * then provisioning manager is not running, therefore + * return with error to allow the global handler to act */ + if (!prov_ctx) { + RELEASE_LOCK(prov_ctx_lock); + return; + } +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI + /* If scan completed then update scan result */ + if (prov_ctx->prov_state == NETWORK_PROV_STATE_STARTED && + event_base == WIFI_EVENT && + event_id == WIFI_EVENT_SCAN_DONE) { + update_wifi_scan_results(); + } + + /* Only handle events when credential is received and + * Wi-Fi STA is yet to complete trying the connection */ + if (prov_ctx->prov_state < NETWORK_PROV_STATE_CRED_RECV) { + RELEASE_LOCK(prov_ctx_lock); + return; + } + + if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) { + ESP_LOGI(TAG, "STA Start"); + /* Once configuration is received through protocomm, + * device is started as station. Once station starts, + * wait for connection to establish with configured + * host SSID and password */ + prov_ctx->wifi_state = NETWORK_PROV_WIFI_STA_CONNECTING; + } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) { + ESP_LOGI(TAG, "STA Got IP"); + /* Station got IP. That means configuration is successful. */ + prov_ctx->wifi_state = NETWORK_PROV_WIFI_STA_CONNECTED; + prov_ctx->prov_state = NETWORK_PROV_STATE_SUCCESS; + + /* If auto stop is enabled (default), schedule timer to + * stop provisioning after configured timeout. */ + if (!prov_ctx->mgr_info.capabilities.no_auto_stop) { + ESP_LOGD(TAG, "Starting %d sec timer for stop_prov_timer_cb()", + CONFIG_NETWORK_PROV_AUTOSTOP_TIMEOUT); + esp_timer_start_once(prov_ctx->autostop_timer, CONFIG_NETWORK_PROV_AUTOSTOP_TIMEOUT * 1000000U); + } + + /* Execute user registered callback handler */ + execute_event_cb(NETWORK_PROV_WIFI_CRED_SUCCESS, NULL, 0); + } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) { + ESP_LOGE(TAG, "STA Disconnected"); + /* Station couldn't connect to configured host SSID */ + prov_ctx->wifi_state = NETWORK_PROV_WIFI_STA_DISCONNECTED; + + wifi_event_sta_disconnected_t *disconnected = (wifi_event_sta_disconnected_t *) event_data; + ESP_LOGE(TAG, "Disconnect reason : %d", disconnected->reason); + + /* Set code corresponding to the reason for disconnection */ + switch (disconnected->reason) { + case WIFI_REASON_4WAY_HANDSHAKE_TIMEOUT: + case WIFI_REASON_AUTH_FAIL: + case WIFI_REASON_HANDSHAKE_TIMEOUT: + case WIFI_REASON_MIC_FAILURE: + ESP_LOGE(TAG, "STA Auth Error"); + prov_ctx->wifi_disconnect_reason = NETWORK_PROV_WIFI_STA_AUTH_ERROR; + break; + case WIFI_REASON_NO_AP_FOUND: + ESP_LOGE(TAG, "STA AP Not found"); + prov_ctx->wifi_disconnect_reason = NETWORK_PROV_WIFI_STA_AP_NOT_FOUND; + break; + default: + /* If none of the expected reasons, + * retry connecting to host SSID */ + prov_ctx->wifi_state = NETWORK_PROV_WIFI_STA_CONNECTING; + esp_wifi_connect(); + } + + /* In case of disconnection, update state of service and + * run the event handler with disconnection reason as data */ + if (prov_ctx->wifi_state == NETWORK_PROV_WIFI_STA_DISCONNECTED) { + prov_ctx->prov_state = NETWORK_PROV_STATE_FAIL; + network_prov_wifi_sta_fail_reason_t reason = prov_ctx->wifi_disconnect_reason; + /* Execute user registered callback handler */ + execute_event_cb(NETWORK_PROV_WIFI_CRED_FAIL, (void *)&reason, sizeof(reason)); + } + } +#endif // CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD + /* Only handle events when dataset is received and + * Thread is yet to complete trying the connection */ + if (prov_ctx->prov_state < NETWORK_PROV_STATE_DATASET_RECV) { + RELEASE_LOCK(prov_ctx_lock); + return; + } + + if (event_base == OPENTHREAD_EVENT && event_id == OPENTHREAD_EVENT_ATTACHED) { + ESP_LOGI(TAG, "Thread attached"); + prov_ctx->thread_state = NETWORK_PROV_THREAD_ATTACHED; + prov_ctx->prov_state = NETWORK_PROV_STATE_SUCCESS; + /* If auto stop is enabled (default), schedule timer to + * stop provisioning after configured timeout. */ + if (!prov_ctx->mgr_info.capabilities.no_auto_stop) { + ESP_LOGD(TAG, "Starting %d sec timer for stop_prov_timer_cb()", + CONFIG_NETWORK_PROV_AUTOSTOP_TIMEOUT); + esp_timer_start_once(prov_ctx->autostop_timer, CONFIG_NETWORK_PROV_AUTOSTOP_TIMEOUT * 1000000U); + } + esp_timer_stop(prov_ctx->thread_timeout_timer); + /* Execute user registered callback handler */ + execute_event_cb(NETWORK_PROV_THREAD_DATASET_SUCCESS, NULL, 0); + } + +#endif // CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD + + if (event_base == NETWORK_PROV_MGR_PVT_EVENT && event_id == NETWORK_PROV_MGR_STOP) { + prov_stop_and_notify(true); + } + + RELEASE_LOCK(prov_ctx_lock); +} + + +esp_err_t network_prov_mgr_init(network_prov_mgr_config_t config) +{ + if (!prov_ctx_lock) { + /* Create mutex if this is the first time init is being called. + * This is created only once and never deleted because if some + * other thread is trying to take this mutex while it is being + * deleted from another thread then the reference may become + * invalid and cause exception */ + prov_ctx_lock = xSemaphoreCreateMutex(); + if (!prov_ctx_lock) { + ESP_LOGE(TAG, "Failed to create mutex"); + return ESP_ERR_NO_MEM; + } + } + + void *fn_ptrs[] = { + config.scheme.prov_stop, + config.scheme.prov_start, + config.scheme.new_config, + config.scheme.delete_config, + config.scheme.set_config_service, + config.scheme.set_config_endpoint + }; + + /* All function pointers in the scheme structure must be non-null */ + for (size_t i = 0; i < sizeof(fn_ptrs) / sizeof(fn_ptrs[0]); i++) { + if (!fn_ptrs[i]) { + return ESP_ERR_INVALID_ARG; + } + } + + ACQUIRE_LOCK(prov_ctx_lock); + if (prov_ctx) { + ESP_LOGE(TAG, "Provisioning manager already initialized"); + RELEASE_LOCK(prov_ctx_lock); + return ESP_ERR_INVALID_STATE; + } + + /* Allocate memory for provisioning app data */ + prov_ctx = (struct network_prov_mgr_ctx *) calloc(1, sizeof(struct network_prov_mgr_ctx)); + if (!prov_ctx) { + ESP_LOGE(TAG, "Error allocating memory for singleton instance"); + RELEASE_LOCK(prov_ctx_lock); + return ESP_ERR_NO_MEM; + } + + prov_ctx->mgr_config = config; + prov_ctx->prov_state = NETWORK_PROV_STATE_IDLE; + prov_ctx->mgr_info.version = NETWORK_PROV_MGR_VERSION; + + /* Allocate memory for provisioning scheme configuration */ + const network_prov_scheme_t *scheme = &prov_ctx->mgr_config.scheme; + esp_err_t ret = ESP_OK; + prov_ctx->prov_scheme_config = scheme->new_config(); + if (!prov_ctx->prov_scheme_config) { + ESP_LOGE(TAG, "failed to allocate provisioning scheme configuration"); + ret = ESP_ERR_NO_MEM; + goto exit; + } + + ret = scheme->set_config_endpoint(prov_ctx->prov_scheme_config, "prov-ctrl", 0xFF4F); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "failed to configure Network state control endpoint"); + goto exit; + } + + ret = scheme->set_config_endpoint(prov_ctx->prov_scheme_config, "prov-scan", 0xFF50); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "failed to configure Network scanning endpoint"); + goto exit; + } + + ret = scheme->set_config_endpoint(prov_ctx->prov_scheme_config, "prov-session", 0xFF51); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "failed to configure security endpoint"); + goto exit; + } + + ret = scheme->set_config_endpoint(prov_ctx->prov_scheme_config, "prov-config", 0xFF52); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "failed to configure Network configuration endpoint"); + goto exit; + } + + ret = scheme->set_config_endpoint(prov_ctx->prov_scheme_config, "proto-ver", 0xFF53); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "failed to configure version endpoint"); + goto exit; + } + + /* Application specific custom endpoints will be assigned + * incremental UUIDs starting after this value */ + prov_ctx->endpoint_uuid_used = 0xFF53; + + /* This delay is so that the client side app is notified first + * and then the provisioning is stopped. Default is 1000ms. */ + prov_ctx->cleanup_delay = 1000; + +exit: + if (ret != ESP_OK) { + if (prov_ctx->prov_scheme_config) { + config.scheme.delete_config(prov_ctx->prov_scheme_config); + } + free(prov_ctx); + } else { + execute_event_cb(NETWORK_PROV_INIT, NULL, 0); + } + RELEASE_LOCK(prov_ctx_lock); + return ret; +} + +void network_prov_mgr_wait(void) +{ + if (!prov_ctx_lock) { + ESP_LOGE(TAG, "Provisioning manager not initialized"); + return; + } + + while (1) { + ACQUIRE_LOCK(prov_ctx_lock); + if (prov_ctx && + prov_ctx->prov_state != NETWORK_PROV_STATE_IDLE) { + RELEASE_LOCK(prov_ctx_lock); + vTaskDelay(1000 / portTICK_PERIOD_MS); + continue; + } + break; + } + RELEASE_LOCK(prov_ctx_lock); +} + +void network_prov_mgr_deinit(void) +{ + if (!prov_ctx_lock) { + ESP_LOGE(TAG, "Provisioning manager not initialized"); + return; + } + + ACQUIRE_LOCK(prov_ctx_lock); + + /* This will do one of these: + * 1) if found running, stop the provisioning service (returns true) + * 2) if service was already in the process of termination, this will + * wait till the service is stopped (returns false) + * 3) if service was not running, this will return immediately (returns false) + */ + bool service_was_running = network_prov_mgr_stop_service(1); + + /* If service was not running, its also possible that manager + * was not even initialized */ + if (!service_was_running && !prov_ctx) { + ESP_LOGD(TAG, "Manager already de-initialized"); + RELEASE_LOCK(prov_ctx_lock); + vSemaphoreDelete(prov_ctx_lock); + prov_ctx_lock = NULL; + return; + } + + if (prov_ctx->app_info_json) { + cJSON_Delete(prov_ctx->app_info_json); + } + + if (prov_ctx->prov_scheme_config) { + prov_ctx->mgr_config.scheme.delete_config(prov_ctx->prov_scheme_config); + } + + /* Extract the callbacks to be called post deinit */ + network_prov_cb_func_t app_cb = prov_ctx->mgr_config.app_event_handler.event_cb; + void *app_data = prov_ctx->mgr_config.app_event_handler.user_data; + + network_prov_cb_func_t scheme_cb = prov_ctx->mgr_config.scheme_event_handler.event_cb; + void *scheme_data = prov_ctx->mgr_config.scheme_event_handler.user_data; + + /* Free manager context */ + free(prov_ctx); + prov_ctx = NULL; + RELEASE_LOCK(prov_ctx_lock); + + /* If a running service was also stopped during de-initialization + * then NETWORK_PROV_END event also needs to be emitted before deinit */ + if (service_was_running) { + ESP_LOGD(TAG, "execute_event_cb : %d", NETWORK_PROV_END); + if (scheme_cb) { + scheme_cb(scheme_data, NETWORK_PROV_END, NULL); + } + if (app_cb) { + app_cb(app_data, NETWORK_PROV_END, NULL); + } + if (esp_event_post(NETWORK_PROV_EVENT, NETWORK_PROV_END, NULL, 0, portMAX_DELAY) != ESP_OK) { + ESP_LOGE(TAG, "Failed to post event NETWORK_PROV_END"); + } + } + + ESP_LOGD(TAG, "execute_event_cb : %d", NETWORK_PROV_DEINIT); + + /* Execute deinit event callbacks */ + if (scheme_cb) { + scheme_cb(scheme_data, NETWORK_PROV_DEINIT, NULL); + } + if (app_cb) { + app_cb(app_data, NETWORK_PROV_DEINIT, NULL); + } + if (esp_event_post(NETWORK_PROV_EVENT, NETWORK_PROV_DEINIT, NULL, 0, portMAX_DELAY) != ESP_OK) { + ESP_LOGE(TAG, "Failed to post event NETWORK_PROV_DEINIT"); + } + + vSemaphoreDelete(prov_ctx_lock); + prov_ctx_lock = NULL; +} + +esp_err_t network_prov_mgr_start_provisioning(network_prov_security_t security, const void *network_prov_sec_params, + const char *service_name, const char *service_key) +{ + if (!prov_ctx_lock) { + ESP_LOGE(TAG, "Provisioning manager not initialized"); + return ESP_ERR_INVALID_STATE; + } + + ACQUIRE_LOCK(prov_ctx_lock); + if (!prov_ctx) { + ESP_LOGE(TAG, "Provisioning manager not initialized"); + RELEASE_LOCK(prov_ctx_lock); + return ESP_ERR_INVALID_STATE; + } + + if (prov_ctx->prov_state != NETWORK_PROV_STATE_IDLE) { + ESP_LOGE(TAG, "Provisioning service already started"); + RELEASE_LOCK(prov_ctx_lock); + return ESP_ERR_INVALID_STATE; + } + + esp_err_t ret = ESP_OK; + /* Update state so that parallel call to network_prov_mgr_start_provisioning() + * or network_prov_mgr_stop_provisioning() or network_prov_mgr_deinit() from another + * thread doesn't interfere with this process */ + prov_ctx->prov_state = NETWORK_PROV_STATE_STARTING; +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI + uint8_t restore_wifi_flag = 0; + /* Start Wi-Fi in Station Mode. + * This is necessary for scanning to work */ + ret = esp_wifi_set_mode(WIFI_MODE_STA); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to set Wi-Fi mode to STA"); + goto err; + } + ret = esp_wifi_start(); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to start Wi-Fi"); + goto err; + } + + /* Change Wi-Fi storage to RAM temporarily and erase any old + * credentials in RAM(i.e. without erasing the copy on NVS). Also + * call disconnect to make sure device doesn't remain connected + * to the AP whose credentials were present earlier */ + wifi_config_t wifi_cfg_empty, wifi_cfg_old; + memset(&wifi_cfg_empty, 0, sizeof(wifi_config_t)); + esp_wifi_get_config(WIFI_IF_STA, &wifi_cfg_old); + ret = esp_wifi_set_storage(WIFI_STORAGE_RAM); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to set Wi-Fi storage to RAM"); + goto err; + } + + /* WiFi storage needs to be restored before exiting this API */ + restore_wifi_flag |= WIFI_PROV_STORAGE_BIT; + /* Erase Wi-Fi credentials in RAM, when call disconnect and user code + * receive WIFI_EVENT_STA_DISCONNECTED and maybe call esp_wifi_connect, at + * this time Wi-Fi will have no configuration to connect */ + ret = esp_wifi_set_config(WIFI_IF_STA, &wifi_cfg_empty); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to set empty Wi-Fi credentials"); + goto err; + } + /* WiFi settings needs to be restored if provisioning error before exiting this API */ + restore_wifi_flag |= WIFI_PROV_SETTING_BIT; + + ret = esp_wifi_disconnect(); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to disconnect"); + goto err; + } +#endif // CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI + +#ifdef CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_0 + /* Initialize app data */ + if (security == NETWORK_PROV_SECURITY_0) { + prov_ctx->mgr_info.capabilities.no_sec = true; + } +#endif +#ifdef CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_1 + if (security == NETWORK_PROV_SECURITY_1) { + if (network_prov_sec_params) { + static protocomm_security1_params_t sec1_params; + // Generate internal copy of "pop", that shall be freed at the end + char *pop = strdup(network_prov_sec_params); + if (pop == NULL) { + ESP_LOGE(TAG, "Failed to allocate memory for pop"); + ret = ESP_ERR_NO_MEM; + goto err; + } + sec1_params.data = (const uint8_t *)pop; + sec1_params.len = strlen(pop); + prov_ctx->protocomm_sec_params = (const void *) &sec1_params; + } else { + prov_ctx->mgr_info.capabilities.no_pop = true; + } + } +#endif +#ifdef CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_2 + if (security == NETWORK_PROV_SECURITY_2) { + if (network_prov_sec_params) { + prov_ctx->protocomm_sec_params = network_prov_sec_params; + } + } +#endif + prov_ctx->security = security; + +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI + esp_timer_create_args_t wifi_connect_timer_conf = { + .callback = wifi_connect_timer_cb, + .arg = NULL, + .dispatch_method = ESP_TIMER_TASK, + .name = "network_prov_wifi_connect_tm" + }; + ret = esp_timer_create(&wifi_connect_timer_conf, &prov_ctx->wifi_connect_timer); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to create Wi-Fi connect timer"); + goto err; + } +#endif // CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD + esp_timer_create_args_t thread_timeout_timer_conf = { + .callback = thread_timeout_timer_cb, + .arg = NULL, + .dispatch_method = ESP_TIMER_TASK, + .name = "thread_prov_timeout_tm" + }; + ret = esp_timer_create(&thread_timeout_timer_conf, &prov_ctx->thread_timeout_timer); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to create Thread attaching timeout timer"); + goto err; + } +#endif // CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD + + /* If auto stop on completion is enabled (default) create the stopping timer */ + if (!prov_ctx->mgr_info.capabilities.no_auto_stop) { + /* Create timer object as a member of app data */ + esp_timer_create_args_t autostop_timer_conf = { + .callback = stop_prov_timer_cb, + .arg = NULL, + .dispatch_method = ESP_TIMER_TASK, + .name = "network_prov_autostop_tm" + }; + ret = esp_timer_create(&autostop_timer_conf, &prov_ctx->autostop_timer); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to create auto-stop timer"); +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI + esp_timer_delete(prov_ctx->wifi_connect_timer); +#endif // CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD + esp_timer_delete(prov_ctx->thread_timeout_timer); +#endif // CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD + goto err; + } + } + + esp_timer_create_args_t cleanup_delay_timer = { + .callback = cleanup_delay_timer_cb, + .arg = NULL, + .dispatch_method = ESP_TIMER_TASK, + .name = "cleanup_delay_tm" + }; + ret = esp_timer_create(&cleanup_delay_timer, &prov_ctx->cleanup_delay_timer); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to create cleanup delay timer"); +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI + esp_timer_delete(prov_ctx->wifi_connect_timer); +#endif // CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD + esp_timer_delete(prov_ctx->thread_timeout_timer); +#endif // CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD + esp_timer_delete(prov_ctx->autostop_timer); + goto err; + } + + + /* System APIs for BLE / Wi-Fi / Thread will be called inside network_prov_mgr_start_service(), + * which may trigger system level events. Hence, releasing the context lock will + * ensure that network_prov_mgr_event_handler() doesn't block the global event_loop + * handler when system events need to be handled */ + RELEASE_LOCK(prov_ctx_lock); + + /* Start provisioning service */ + ret = network_prov_mgr_start_service(service_name, service_key); + if (ret != ESP_OK) { + esp_timer_delete(prov_ctx->autostop_timer); +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI + esp_timer_delete(prov_ctx->wifi_connect_timer); +#endif +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD + esp_timer_delete(prov_ctx->thread_timeout_timer); +#endif + esp_timer_delete(prov_ctx->cleanup_delay_timer); + } + ACQUIRE_LOCK(prov_ctx_lock); + if (ret == ESP_OK) { + prov_ctx->prov_state = NETWORK_PROV_STATE_STARTED; + /* Execute user registered callback handler */ + execute_event_cb(NETWORK_PROV_START, NULL, 0); + goto exit; + } + +err: + prov_ctx->prov_state = NETWORK_PROV_STATE_IDLE; +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI + if (restore_wifi_flag & WIFI_PROV_SETTING_BIT) { + /* Restore current WiFi settings, since provisioning start has failed */ + esp_wifi_set_config(WIFI_IF_STA, &wifi_cfg_old); + } +#endif +exit: +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI + if (restore_wifi_flag & WIFI_PROV_STORAGE_BIT) { + /* Restore WiFi storage back to FLASH */ + esp_wifi_set_storage(WIFI_STORAGE_FLASH); + } +#endif + RELEASE_LOCK(prov_ctx_lock); + return ret; +} + +void network_prov_mgr_stop_provisioning(void) +{ + if (!prov_ctx_lock) { + ESP_LOGE(TAG, "Provisioning manager not initialized"); + return; + } + + ACQUIRE_LOCK(prov_ctx_lock); + + /* Launches task for stopping the provisioning service. This will do one of these: + * 1) start a task for stopping the provisioning service (returns true) + * 2) if service was already in the process of termination, this will + * wait till the service is stopped (returns false) + * 3) if service was not running, this will return immediately (returns false) + */ + network_prov_mgr_stop_service(0); + + RELEASE_LOCK(prov_ctx_lock); +} + +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI +esp_err_t network_prov_mgr_reset_wifi_provisioning(void) +{ + esp_err_t ret = esp_wifi_restore(); + + if (ret != ESP_OK) { + ESP_LOGE(TAG, "esp_wifi_restore fail, ret is %d", ret); + ret = ESP_FAIL; + } + + return ret; +} + +esp_err_t network_prov_mgr_reset_wifi_sm_state_on_failure(void) +{ + if (!prov_ctx_lock) { + ESP_LOGE(TAG, "Provisioning manager not initialized"); + return ESP_ERR_INVALID_STATE; + } + + ACQUIRE_LOCK(prov_ctx_lock); + + esp_err_t err = ESP_OK; + if (prov_ctx->prov_state != NETWORK_PROV_STATE_FAIL) { + ESP_LOGE(TAG, "Trying reset when not in failure state. Current state: %d", prov_ctx->prov_state); + err = ESP_ERR_INVALID_STATE; + goto exit; + } + + wifi_config_t wifi_cfg = {0}; + + err = esp_wifi_set_config(WIFI_IF_STA, &wifi_cfg); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to set wifi config, 0x%x", err); + goto exit; + } + + prov_ctx->prov_state = NETWORK_PROV_STATE_STARTED; + +exit: + RELEASE_LOCK(prov_ctx_lock); + return err; +} + +esp_err_t network_prov_mgr_reset_wifi_sm_state_for_reprovision(void) +{ + if (!prov_ctx_lock) { + ESP_LOGE(TAG, "Provisioning manager not initialized"); + return ESP_ERR_INVALID_STATE; + } + + ACQUIRE_LOCK(prov_ctx_lock); + + esp_err_t ret = ESP_OK; + wifi_config_t wifi_cfg_empty = {0}; + uint8_t restore_wifi_flag = 0; + + if (!prov_ctx->mgr_info.capabilities.no_auto_stop) { + ESP_LOGE(TAG, "Execute network_prov_mgr_disable_auto_stop() before calling this API"); + ret = ESP_ERR_INVALID_STATE; + goto exit; + } + + ret = esp_wifi_set_storage(WIFI_STORAGE_RAM); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to set Wi-Fi storage to RAM"); + goto exit; + } + restore_wifi_flag |= WIFI_PROV_STORAGE_BIT; + + ret = esp_wifi_set_config(WIFI_IF_STA, &wifi_cfg_empty); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to set empty Wi-Fi credentials, 0x%x", ret); + goto exit; + } + + ret = esp_wifi_disconnect(); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Failed to disconnect wifi, 0x%x", ret); + goto exit; + } + + prov_ctx->prov_state = NETWORK_PROV_STATE_STARTED; + execute_event_cb(NETWORK_PROV_START, NULL, 0); + +exit: + if (restore_wifi_flag & WIFI_PROV_STORAGE_BIT) { + esp_wifi_set_storage(WIFI_STORAGE_FLASH); + } + RELEASE_LOCK(prov_ctx_lock); + return ret; +} +#endif // CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI + +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD +esp_err_t network_prov_mgr_reset_thread_provisioning(void) +{ + otInstance *instance = esp_openthread_get_instance(); + esp_openthread_lock_acquire(portMAX_DELAY); + if (otInstanceErasePersistentInfo(instance) != OT_ERROR_NONE) { + ESP_LOGE(TAG, "Failed to Erase Thread Network Info"); + esp_openthread_lock_release(); + return ESP_FAIL; + } + esp_openthread_lock_release(); + return ESP_OK; +} + +esp_err_t network_prov_mgr_reset_thread_sm_state_on_failure(void) +{ + if (!prov_ctx_lock) { + ESP_LOGE(TAG, "Provisioning manager not initialized"); + return ESP_ERR_INVALID_STATE; + } + + ACQUIRE_LOCK(prov_ctx_lock); + + esp_err_t err = ESP_OK; + otInstance *instance = esp_openthread_get_instance(); + + esp_openthread_lock_acquire(portMAX_DELAY); + if (prov_ctx->prov_state != NETWORK_PROV_STATE_FAIL) { + ESP_LOGE(TAG, "Trying reset when not in failure state. Current state: %d", prov_ctx->prov_state); + err = ESP_ERR_INVALID_STATE; + goto exit; + } + + if (otThreadSetEnabled(instance, false) != OT_ERROR_NONE) { + ESP_LOGE(TAG, "Failed to stop Thread"); + err = ESP_FAIL; + goto exit; + } + + if (otIp6SetEnabled(instance, false) != OT_ERROR_NONE) { + ESP_LOGE(TAG, "Failed to disable Thread netif"); + err = ESP_FAIL; + goto exit; + } + + if (otInstanceErasePersistentInfo(instance) != OT_ERROR_NONE) { + ESP_LOGE(TAG, "Failed to erase Thread network info"); + err = ESP_FAIL; + goto exit; + } + + prov_ctx->prov_state = NETWORK_PROV_STATE_STARTED; + +exit: + esp_openthread_lock_release(); + RELEASE_LOCK(prov_ctx_lock); + return err; +} + +esp_err_t network_prov_mgr_reset_thread_sm_state_for_reprovision(void) +{ + if (!prov_ctx_lock) { + ESP_LOGE(TAG, "Provisioning manager not initialized"); + return ESP_ERR_INVALID_STATE; + } + + ACQUIRE_LOCK(prov_ctx_lock); + + esp_err_t ret = ESP_OK; + otInstance *instance = esp_openthread_get_instance(); + + esp_openthread_lock_acquire(portMAX_DELAY); + if (!prov_ctx->mgr_info.capabilities.no_auto_stop) { + ESP_LOGE(TAG, "Execute network_prov_mgr_disable_auto_stop() before calling this API"); + ret = ESP_ERR_INVALID_STATE; + goto exit; + } + + if (otThreadSetEnabled(instance, false) != OT_ERROR_NONE) { + ESP_LOGE(TAG, "Failed to stop Thread"); + ret = ESP_FAIL; + goto exit; + } + + if (otIp6SetEnabled(instance, false) != OT_ERROR_NONE) { + ESP_LOGE(TAG, "Failed to disable Thread netif"); + ret = ESP_FAIL; + goto exit; + } + + prov_ctx->prov_state = NETWORK_PROV_STATE_STARTED; + execute_event_cb(NETWORK_PROV_START, NULL, 0); + +exit: + esp_openthread_lock_release(); + RELEASE_LOCK(prov_ctx_lock); + return ret; +} +#endif // CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/src/network_config.c b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/src/network_config.c new file mode 100644 index 000000000..5a4e99813 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/src/network_config.c @@ -0,0 +1,505 @@ +/* + * SPDX-FileCopyrightText: 2018-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#include "network_constants.pb-c.h" +#include "network_config.pb-c.h" + +#include + +static const char *TAG = "NetworkProvConfig"; + +typedef struct network_prov_config_cmd { + int cmd_num; + esp_err_t (*command_handler)(NetworkConfigPayload *req, + NetworkConfigPayload *resp, void *priv_data); +} network_prov_config_cmd_t; + +static esp_err_t cmd_get_status_handler(NetworkConfigPayload *req, + NetworkConfigPayload *resp, void *priv_data); + +static esp_err_t cmd_set_config_handler(NetworkConfigPayload *req, + NetworkConfigPayload *resp, void *priv_data); + +static esp_err_t cmd_apply_config_handler(NetworkConfigPayload *req, + NetworkConfigPayload *resp, void *priv_data); + +static network_prov_config_cmd_t cmd_table[] = { + { + .cmd_num = NETWORK_CONFIG_MSG_TYPE__TypeCmdGetWifiStatus, + .command_handler = cmd_get_status_handler + }, + { + .cmd_num = NETWORK_CONFIG_MSG_TYPE__TypeCmdSetWifiConfig, + .command_handler = cmd_set_config_handler + }, + { + .cmd_num = NETWORK_CONFIG_MSG_TYPE__TypeCmdApplyWifiConfig, + .command_handler = cmd_apply_config_handler + }, + { + .cmd_num = NETWORK_CONFIG_MSG_TYPE__TypeCmdGetThreadStatus, + .command_handler = cmd_get_status_handler + }, + { + .cmd_num = NETWORK_CONFIG_MSG_TYPE__TypeCmdSetThreadConfig, + .command_handler = cmd_set_config_handler + }, + { + .cmd_num = NETWORK_CONFIG_MSG_TYPE__TypeCmdApplyThreadConfig, + .command_handler = cmd_apply_config_handler + } +}; + +static esp_err_t cmd_get_status_handler(NetworkConfigPayload *req, + NetworkConfigPayload *resp, void *priv_data) +{ + ESP_LOGD(TAG, "Enter cmd_get_status_handler"); + network_prov_config_handlers_t *h = (network_prov_config_handlers_t *) priv_data; + if (!h) { + ESP_LOGE(TAG, "Command invoked without handlers"); + return ESP_ERR_INVALID_STATE; + } + + if (req->msg == NETWORK_CONFIG_MSG_TYPE__TypeCmdGetWifiStatus) { + RespGetWifiStatus *resp_payload = (RespGetWifiStatus *) malloc(sizeof(RespGetWifiStatus)); + if (!resp_payload) { + ESP_LOGE(TAG, "Error allocating memory"); + return ESP_ERR_NO_MEM; + } + resp_get_wifi_status__init(resp_payload); +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI + network_prov_config_get_wifi_data_t resp_data; + if (h->wifi_get_status_handler) { + if (h->wifi_get_status_handler(&resp_data, &h->ctx) == ESP_OK) { + if (resp_data.wifi_state == NETWORK_PROV_WIFI_STA_CONNECTING) { + resp_payload->wifi_sta_state = WIFI_STATION_STATE__Connecting; + resp_payload->state_case = RESP_GET_WIFI_STATUS__STATE_WIFI_CONNECTED; + } else if (resp_data.wifi_state == NETWORK_PROV_WIFI_STA_CONNECTED) { + resp_payload->wifi_sta_state = WIFI_STATION_STATE__Connected; + resp_payload->state_case = RESP_GET_WIFI_STATUS__STATE_WIFI_CONNECTED; + WifiConnectedState *connected = (WifiConnectedState *)( + malloc(sizeof(WifiConnectedState))); + if (!connected) { + free(resp_payload); + ESP_LOGE(TAG, "Error allocating memory"); + return ESP_ERR_NO_MEM; + } + resp_payload->wifi_connected = connected; + wifi_connected_state__init(connected); + + connected->ip4_addr = strdup(resp_data.conn_info.ip_addr); + if (connected->ip4_addr == NULL) { + free(connected); + free(resp_payload); + return ESP_ERR_NO_MEM; + } + + connected->bssid.len = sizeof(resp_data.conn_info.bssid); + connected->bssid.data = (uint8_t *) strndup(resp_data.conn_info.bssid, + sizeof(resp_data.conn_info.bssid)); + if (connected->bssid.data == NULL) { + free(connected->ip4_addr); + free(connected); + free(resp_payload); + return ESP_ERR_NO_MEM; + } + + connected->ssid.len = strlen(resp_data.conn_info.ssid); + connected->ssid.data = (uint8_t *) strdup(resp_data.conn_info.ssid); + if (connected->ssid.data == NULL) { + free(connected->bssid.data); + free(connected->ip4_addr); + free(connected); + free(resp_payload); + return ESP_ERR_NO_MEM; + } + + connected->channel = resp_data.conn_info.channel; + connected->auth_mode = resp_data.conn_info.auth_mode; + } else if (resp_data.wifi_state == NETWORK_PROV_WIFI_STA_DISCONNECTED) { + resp_payload->wifi_sta_state = WIFI_STATION_STATE__ConnectionFailed; + resp_payload->state_case = RESP_GET_WIFI_STATUS__STATE_WIFI_FAIL_REASON; + + if (resp_data.fail_reason == NETWORK_PROV_WIFI_STA_AUTH_ERROR) { + resp_payload->wifi_fail_reason = WIFI_CONNECT_FAILED_REASON__AuthError; + } else if (resp_data.fail_reason == NETWORK_PROV_WIFI_STA_AP_NOT_FOUND) { + resp_payload->wifi_fail_reason = WIFI_CONNECT_FAILED_REASON__WifiNetworkNotFound; + } + } + resp_payload->status = STATUS__Success; + } else { + resp_payload->status = STATUS__InternalError; + } + } else { + resp_payload->status = STATUS__InternalError; + } +#else // CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI + resp_payload->status = STATUS__InvalidArgument; +#endif // !CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI + resp->payload_case = NETWORK_CONFIG_PAYLOAD__PAYLOAD_RESP_GET_WIFI_STATUS; + resp->resp_get_wifi_status = resp_payload; + } else if (req->msg == NETWORK_CONFIG_MSG_TYPE__TypeCmdGetThreadStatus) { + RespGetThreadStatus *resp_payload = (RespGetThreadStatus *) malloc(sizeof(RespGetThreadStatus)); + if (!resp_payload) { + ESP_LOGE(TAG, "Error allocating memory"); + return ESP_ERR_NO_MEM; + } + resp_get_thread_status__init(resp_payload); +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD + network_prov_config_get_thread_data_t resp_data; + if (h->thread_get_status_handler) { + if (h->thread_get_status_handler(&resp_data, &h->ctx) == ESP_OK) { + if (resp_data.thread_state == NETWORK_PROV_THREAD_ATTACHING) { + resp_payload->thread_state = THREAD_NETWORK_STATE__Attaching; + resp_payload->state_case = RESP_GET_THREAD_STATUS__STATE_THREAD_ATTACHED; + } else if (resp_data.thread_state == NETWORK_PROV_THREAD_ATTACHED) { + resp_payload->thread_state = THREAD_NETWORK_STATE__Attached; + resp_payload->state_case = RESP_GET_THREAD_STATUS__STATE_THREAD_ATTACHED; + ThreadAttachState *attached = (ThreadAttachState *)malloc(sizeof(ThreadAttachState)); + if (!attached) { + free(resp_payload); + ESP_LOGE(TAG, "Error allocating memory"); + return ESP_ERR_NO_MEM; + } + resp_payload->thread_attached = attached; + thread_attach_state__init(attached); + attached->channel = resp_data.conn_info.channel; + attached->ext_pan_id.len = sizeof(resp_data.conn_info.ext_pan_id); + attached->ext_pan_id.data = (uint8_t *)malloc(attached->ext_pan_id.len); + if (!attached->ext_pan_id.data) { + free(attached); + free(resp_payload); + return ESP_ERR_NO_MEM; + } + memcpy(attached->ext_pan_id.data, resp_data.conn_info.ext_pan_id, sizeof(resp_data.conn_info.ext_pan_id)); + attached->pan_id = resp_data.conn_info.pan_id; + + attached->name = (char *)malloc(sizeof(resp_data.conn_info.name)); + if (!attached->name) { + free(attached->ext_pan_id.data); + free(attached); + free(resp_payload); + return ESP_ERR_NO_MEM; + } + memcpy(attached->name, resp_data.conn_info.name, sizeof(resp_data.conn_info.name)); + } else if (resp_data.thread_state == NETWORK_PROV_THREAD_DETACHED) { + resp_payload->thread_state = THREAD_NETWORK_STATE__AttachingFailed; + resp_payload->state_case = RESP_GET_THREAD_STATUS__STATE_THREAD_FAIL_REASON; + + if (resp_data.fail_reason == NETWORK_PROV_THREAD_DATASET_INVALID) { + resp_payload->thread_fail_reason = THREAD_ATTACH_FAILED_REASON__DatasetInvalid; + } else if (resp_data.fail_reason == NETWORK_PROV_THREAD_NETWORK_NOT_FOUND) { + resp_payload->thread_fail_reason = THREAD_ATTACH_FAILED_REASON__ThreadNetworkNotFound; + } + } + resp_payload->status = STATUS__Success; + } else { + resp_payload->status = STATUS__InternalError; + } + } else { + resp_payload->status = STATUS__InternalError; + } +#else // CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD + resp_payload->status = STATUS__InvalidArgument; +#endif // !CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD + resp->payload_case = NETWORK_CONFIG_PAYLOAD__PAYLOAD_RESP_GET_THREAD_STATUS; + resp->resp_get_thread_status = resp_payload; + } + return ESP_OK; +} + +static esp_err_t cmd_set_config_handler(NetworkConfigPayload *req, + NetworkConfigPayload *resp, void *priv_data) +{ + ESP_LOGD(TAG, "Enter cmd_set_config_handler"); + network_prov_config_handlers_t *h = (network_prov_config_handlers_t *) priv_data; + if (!h) { + ESP_LOGE(TAG, "Command invoked without handlers"); + return ESP_ERR_INVALID_STATE; + } + + if (req->msg == NETWORK_CONFIG_MSG_TYPE__TypeCmdSetWifiConfig) { + RespSetWifiConfig *resp_payload = (RespSetWifiConfig *) malloc(sizeof(RespSetWifiConfig)); + if (resp_payload == NULL) { + ESP_LOGE(TAG, "Error allocating memory"); + return ESP_ERR_NO_MEM; + } + resp_set_wifi_config__init(resp_payload); +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI + network_prov_config_set_wifi_data_t req_data; + memset(&req_data, 0, sizeof(req_data)); + + /* Check arguments provided in protobuf packet: + * - SSID / Passphrase string length must be within the standard limits + * - BSSID must either be NULL or have length equal to that imposed by the standard + * If any of these conditions are not satisfied, don't invoke the handler and + * send error status without closing connection */ + resp_payload->status = STATUS__InvalidArgument; + if (req->cmd_set_wifi_config->bssid.len != 0 && + req->cmd_set_wifi_config->bssid.len != sizeof(req_data.bssid)) { + ESP_LOGD(TAG, "Received invalid BSSID"); + } else if (req->cmd_set_wifi_config->ssid.len >= sizeof(req_data.ssid)) { + ESP_LOGD(TAG, "Received invalid SSID"); + } else if (req->cmd_set_wifi_config->passphrase.len >= sizeof(req_data.password)) { + ESP_LOGD(TAG, "Received invalid Passphrase"); + } else { + /* The received SSID and Passphrase are not NULL terminated so + * we memcpy over zeroed out arrays. Above length checks ensure + * that there is atleast 1 extra byte for null termination */ + memcpy(req_data.ssid, req->cmd_set_wifi_config->ssid.data, + req->cmd_set_wifi_config->ssid.len); + memcpy(req_data.password, req->cmd_set_wifi_config->passphrase.data, + req->cmd_set_wifi_config->passphrase.len); + memcpy(req_data.bssid, req->cmd_set_wifi_config->bssid.data, + req->cmd_set_wifi_config->bssid.len); + req_data.channel = req->cmd_set_wifi_config->channel; + if (h->wifi_set_config_handler(&req_data, &h->ctx) == ESP_OK) { + resp_payload->status = STATUS__Success; + } else { + resp_payload->status = STATUS__InternalError; + } + } +#else // CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI + resp_payload->status = STATUS__InvalidArgument; +#endif // !CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI + resp->payload_case = NETWORK_CONFIG_PAYLOAD__PAYLOAD_RESP_SET_WIFI_CONFIG; + resp->resp_set_wifi_config = resp_payload; + } else if (req->msg == NETWORK_CONFIG_MSG_TYPE__TypeCmdSetThreadConfig) { + RespSetThreadConfig *resp_payload = (RespSetThreadConfig *) malloc(sizeof(RespSetThreadConfig)); + if (resp_payload == NULL) { + ESP_LOGE(TAG, "Error allocating memory"); + return ESP_ERR_NO_MEM; + } + resp_set_thread_config__init(resp_payload); +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD + network_prov_config_set_thread_data_t req_data; + memset(&req_data, 0, sizeof(req_data)); + resp_payload->status = STATUS__InvalidArgument; + if (req->cmd_set_thread_config->dataset.len > sizeof(req_data.dataset)) { + ESP_LOGD(TAG, "Received invalid dataset"); + } + memcpy(req_data.dataset, req->cmd_set_thread_config->dataset.data, + req->cmd_set_thread_config->dataset.len); + req_data.length = req->cmd_set_thread_config->dataset.len; + if (h->thread_set_config_handler(&req_data, &h->ctx) == ESP_OK) { + resp_payload->status = STATUS__Success; + } else { + resp_payload->status = STATUS__InternalError; + } +#else // CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD + resp_payload->status = STATUS__InvalidArgument; +#endif // !CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD + resp->payload_case = NETWORK_CONFIG_PAYLOAD__PAYLOAD_RESP_SET_THREAD_CONFIG; + resp->resp_set_thread_config = resp_payload; + } + return ESP_OK; +} + +static esp_err_t cmd_apply_config_handler(NetworkConfigPayload *req, + NetworkConfigPayload *resp, void *priv_data) +{ + ESP_LOGD(TAG, "Enter cmd_apply_config_handler"); + network_prov_config_handlers_t *h = (network_prov_config_handlers_t *) priv_data; + if (!h) { + ESP_LOGE(TAG, "Command invoked without handlers"); + return ESP_ERR_INVALID_STATE; + } + if (req->msg == NETWORK_CONFIG_MSG_TYPE__TypeCmdApplyWifiConfig) { + RespApplyWifiConfig *resp_payload = (RespApplyWifiConfig *) malloc(sizeof(RespApplyWifiConfig)); + if (!resp_payload) { + ESP_LOGE(TAG, "Error allocating memory"); + return ESP_ERR_NO_MEM; + } + resp_apply_wifi_config__init(resp_payload); +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI + if (h->wifi_apply_config_handler && h->wifi_apply_config_handler(&h->ctx) == ESP_OK) { + resp_payload->status = STATUS__Success; + } else { + resp_payload->status = STATUS__InternalError; + } +#else // CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI + resp_payload->status = STATUS__InvalidArgument; +#endif // !CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI + resp->payload_case = NETWORK_CONFIG_PAYLOAD__PAYLOAD_RESP_APPLY_WIFI_CONFIG; + resp->resp_apply_wifi_config = resp_payload; + } else if (req->msg == NETWORK_CONFIG_MSG_TYPE__TypeCmdApplyThreadConfig) { + RespApplyThreadConfig *resp_payload = (RespApplyThreadConfig *) malloc(sizeof(RespApplyThreadConfig)); + if (!resp_payload) { + ESP_LOGE(TAG, "Error allocating memory"); + return ESP_ERR_NO_MEM; + } + resp_apply_thread_config__init(resp_payload); +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD + if (h->thread_apply_config_handler && h->thread_apply_config_handler(&h->ctx) == ESP_OK) { + resp_payload->status = STATUS__Success; + } else { + resp_payload->status = STATUS__InternalError; + } +#else // CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD + resp_payload->status = STATUS__InvalidArgument; +#endif // !CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD + resp->payload_case = NETWORK_CONFIG_PAYLOAD__PAYLOAD_RESP_APPLY_THREAD_CONFIG; + resp->resp_apply_thread_config = resp_payload; + } + return ESP_OK; +} + +static int lookup_cmd_handler(int cmd_id) +{ + for (size_t i = 0; i < sizeof(cmd_table) / sizeof(network_prov_config_cmd_t); i++) { + if (cmd_table[i].cmd_num == cmd_id) { + return i; + } + } + + return -1; +} +static void network_prov_config_command_cleanup(NetworkConfigPayload *resp, void *priv_data) +{ + if (!resp) { + return; + } + + switch (resp->msg) { + case NETWORK_CONFIG_MSG_TYPE__TypeRespGetWifiStatus: { +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI + switch (resp->resp_get_wifi_status->wifi_sta_state) { + case WIFI_STATION_STATE__Connecting: + break; + case WIFI_STATION_STATE__Connected: + if (resp->resp_get_wifi_status->wifi_connected) { + if (resp->resp_get_wifi_status->wifi_connected->ip4_addr) { + free(resp->resp_get_wifi_status->wifi_connected->ip4_addr); + } + if (resp->resp_get_wifi_status->wifi_connected->bssid.data) { + free(resp->resp_get_wifi_status->wifi_connected->bssid.data); + } + if (resp->resp_get_wifi_status->wifi_connected->ssid.data) { + free(resp->resp_get_wifi_status->wifi_connected->ssid.data); + } + free(resp->resp_get_wifi_status->wifi_connected); + } + break; + case WIFI_STATION_STATE__ConnectionFailed: + break; + default: + break; + } +#endif // CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI + free(resp->resp_get_wifi_status); + } + break; + case NETWORK_CONFIG_MSG_TYPE__TypeRespGetThreadStatus: { +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD + switch (resp->resp_get_thread_status->thread_state) { + case THREAD_NETWORK_STATE__Attaching: + break; + case THREAD_NETWORK_STATE__Attached: + if (resp->resp_get_thread_status->thread_attached) { + if (resp->resp_get_thread_status->thread_attached->name) { + free(resp->resp_get_thread_status->thread_attached->name); + } + free(resp->resp_get_thread_status->thread_attached); + } + break; + case THREAD_NETWORK_STATE__AttachingFailed: + break; + default: + break; + } +#endif // CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD + free(resp->resp_get_thread_status); + } + break; + case NETWORK_CONFIG_MSG_TYPE__TypeRespSetWifiConfig: { + free(resp->resp_set_wifi_config); + } + break; + case NETWORK_CONFIG_MSG_TYPE__TypeRespSetThreadConfig: { + free(resp->resp_set_thread_config); + } + break; + case NETWORK_CONFIG_MSG_TYPE__TypeRespApplyWifiConfig: { + free(resp->resp_apply_wifi_config); + } + break; + case NETWORK_CONFIG_MSG_TYPE__TypeRespApplyThreadConfig: { + free(resp->resp_apply_thread_config); + } + break; + default: + ESP_LOGE(TAG, "Unsupported response type in cleanup_handler"); + break; + } + return; +} + +static esp_err_t network_prov_config_command_dispatcher(NetworkConfigPayload *req, + NetworkConfigPayload *resp, void *priv_data) +{ + esp_err_t ret; + + ESP_LOGD(TAG, "In network_prov_config_command_dispatcher Cmd=%d", req->msg); + + int cmd_index = lookup_cmd_handler(req->msg); + if (cmd_index < 0) { + ESP_LOGE(TAG, "Invalid command handler lookup"); + return ESP_FAIL; + } + + ret = cmd_table[cmd_index].command_handler(req, resp, priv_data); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Error executing command handler"); + return ESP_FAIL; + } + + return ESP_OK; +} + +esp_err_t network_prov_config_data_handler(uint32_t session_id, const uint8_t *inbuf, ssize_t inlen, + uint8_t **outbuf, ssize_t *outlen, void *priv_data) +{ + NetworkConfigPayload *req; + NetworkConfigPayload resp; + esp_err_t ret; + + req = network_config_payload__unpack(NULL, inlen, inbuf); + if (!req) { + ESP_LOGE(TAG, "Unable to unpack config data"); + return ESP_ERR_INVALID_ARG; + } + + network_config_payload__init(&resp); + ret = network_prov_config_command_dispatcher(req, &resp, priv_data); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Proto command dispatcher error %d", ret); + return ESP_FAIL; + } + + resp.msg = req->msg + 1; /* Response is request + 1 */ + network_config_payload__free_unpacked(req, NULL); + + *outlen = network_config_payload__get_packed_size(&resp); + if (*outlen <= 0) { + ESP_LOGE(TAG, "Invalid encoding for response"); + return ESP_FAIL; + } + + *outbuf = (uint8_t *) malloc(*outlen); + if (!*outbuf) { + ESP_LOGE(TAG, "System out of memory"); + return ESP_ERR_NO_MEM; + } + network_config_payload__pack(&resp, *outbuf); + network_prov_config_command_cleanup(&resp, priv_data); + + return ESP_OK; +} diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/src/network_ctrl.c b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/src/network_ctrl.c new file mode 100644 index 000000000..93ca5f018 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/src/network_ctrl.c @@ -0,0 +1,247 @@ +/* + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#include "network_ctrl.pb-c.h" + +#include "network_ctrl.h" + +static const char *TAG = "proto_network_ctrl"; + +typedef struct network_ctrl_cmd { + int cmd_id; + esp_err_t (*command_handler)(NetworkCtrlPayload *req, + NetworkCtrlPayload *resp, void *priv_data); +} network_ctrl_cmd_t; + +static esp_err_t cmd_ctrl_reset_handler(NetworkCtrlPayload *req, + NetworkCtrlPayload *resp, + void *priv_data); + +static esp_err_t cmd_ctrl_reprov_handler(NetworkCtrlPayload *req, + NetworkCtrlPayload *resp, + void *priv_data); + +static network_ctrl_cmd_t cmd_table[] = { + { + .cmd_id = NETWORK_CTRL_MSG_TYPE__TypeCmdCtrlWifiReset, + .command_handler = cmd_ctrl_reset_handler + }, + { + .cmd_id = NETWORK_CTRL_MSG_TYPE__TypeCmdCtrlThreadReset, + .command_handler = cmd_ctrl_reset_handler + }, + { + .cmd_id = NETWORK_CTRL_MSG_TYPE__TypeCmdCtrlWifiReprov, + .command_handler = cmd_ctrl_reprov_handler + }, + { + .cmd_id = NETWORK_CTRL_MSG_TYPE__TypeCmdCtrlThreadReprov, + .command_handler = cmd_ctrl_reprov_handler + }, +}; + +static esp_err_t cmd_ctrl_reset_handler(NetworkCtrlPayload *req, + NetworkCtrlPayload *resp, void *priv_data) +{ + network_ctrl_handlers_t *h = (network_ctrl_handlers_t *) priv_data; + if (!h) { + ESP_LOGE(TAG, "Command invoked without handlers"); + return ESP_ERR_INVALID_STATE; + } + if (req->msg == NETWORK_CTRL_MSG_TYPE__TypeCmdCtrlWifiReset) { + RespCtrlWifiReset *resp_payload = (RespCtrlWifiReset *) malloc(sizeof(RespCtrlWifiReset)); + if (!resp_payload) { + ESP_LOGE(TAG, "Error allocating memory"); + return ESP_ERR_NO_MEM; + } + resp_ctrl_wifi_reset__init(resp_payload); +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI + if (h->wifi_ctrl_reset) { + resp->status = (h->wifi_ctrl_reset() == ESP_OK ? STATUS__Success : STATUS__InternalError); + } else { + resp->status = STATUS__InternalError; + } +#else + resp->status = STATUS__InvalidArgument; +#endif + resp->payload_case = NETWORK_CTRL_PAYLOAD__PAYLOAD_RESP_CTRL_WIFI_RESET; + resp->resp_ctrl_wifi_reset = resp_payload; + } else if (req->msg == NETWORK_CTRL_MSG_TYPE__TypeCmdCtrlThreadReset) { + RespCtrlThreadReset *resp_payload = (RespCtrlThreadReset *) malloc(sizeof(RespCtrlThreadReset)); + if (!resp_payload) { + ESP_LOGE(TAG, "Error allocating memory"); + return ESP_ERR_NO_MEM; + } + resp_ctrl_thread_reset__init(resp_payload); +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD + if (h->thread_ctrl_reset) { + resp->status = (h->thread_ctrl_reset() == ESP_OK ? STATUS__Success : STATUS__InternalError); + } else { + resp->status = STATUS__InternalError; + } +#else + resp->status = STATUS__InvalidArgument; +#endif + resp->payload_case = NETWORK_CTRL_PAYLOAD__PAYLOAD_RESP_CTRL_THREAD_RESET; + resp->resp_ctrl_thread_reset = resp_payload; + } + return ESP_OK; +} + +static esp_err_t cmd_ctrl_reprov_handler(NetworkCtrlPayload *req, + NetworkCtrlPayload *resp, void *priv_data) +{ + network_ctrl_handlers_t *h = (network_ctrl_handlers_t *) priv_data; + if (!h) { + ESP_LOGE(TAG, "Command invoked without handlers"); + return ESP_ERR_INVALID_STATE; + } + if (req->msg == NETWORK_CTRL_MSG_TYPE__TypeCmdCtrlWifiReprov) { + RespCtrlWifiReprov *resp_payload = (RespCtrlWifiReprov *) malloc(sizeof(RespCtrlWifiReprov)); + if (!resp_payload) { + ESP_LOGE(TAG, "Error allocating memory"); + return ESP_ERR_NO_MEM; + } + resp_ctrl_wifi_reprov__init(resp_payload); +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI + if (h->wifi_ctrl_reprov) { + resp->status = (h->wifi_ctrl_reprov() == ESP_OK ? STATUS__Success : STATUS__InternalError); + } else { + resp->status = STATUS__InternalError; + } +#else + resp->status = STATUS__InvalidArgument; +#endif + resp->payload_case = NETWORK_CTRL_PAYLOAD__PAYLOAD_RESP_CTRL_WIFI_REPROV; + resp->resp_ctrl_wifi_reprov = resp_payload; + } else if (req->msg == NETWORK_CTRL_MSG_TYPE__TypeCmdCtrlThreadReprov) { + RespCtrlThreadReprov *resp_payload = (RespCtrlThreadReprov *) malloc(sizeof(RespCtrlThreadReprov)); + if (!resp_payload) { + ESP_LOGE(TAG, "Error allocating memory"); + return ESP_ERR_NO_MEM; + } + resp_ctrl_thread_reprov__init(resp_payload); +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD + if (h->thread_ctrl_reprov) { + resp->status = (h->thread_ctrl_reprov() == ESP_OK ? STATUS__Success : STATUS__InternalError); + } else { + resp->status = STATUS__InternalError; + } +#else + resp->status = STATUS__InvalidArgument; +#endif + resp->payload_case = NETWORK_CTRL_PAYLOAD__PAYLOAD_RESP_CTRL_THREAD_REPROV; + resp->resp_ctrl_thread_reprov = resp_payload; + } + return ESP_OK; +} + +static int lookup_cmd_handler(int cmd_id) +{ + for (size_t i = 0; i < sizeof(cmd_table) / sizeof(network_ctrl_cmd_t); i++) { + if (cmd_table[i].cmd_id == cmd_id) { + return i; + } + } + + return -1; +} + +static void network_ctrl_cmd_cleanup(NetworkCtrlPayload *resp, void *priv_data) +{ + switch (resp->msg) { + case NETWORK_CTRL_MSG_TYPE__TypeRespCtrlWifiReset: { + free(resp->resp_ctrl_wifi_reset); + } + break; + case NETWORK_CTRL_MSG_TYPE__TypeRespCtrlWifiReprov: { + free(resp->resp_ctrl_wifi_reprov); + } + break; + case NETWORK_CTRL_MSG_TYPE__TypeRespCtrlThreadReset: { + free(resp->resp_ctrl_thread_reset); + } + break; + case NETWORK_CTRL_MSG_TYPE__TypeRespCtrlThreadReprov: { + free(resp->resp_ctrl_thread_reprov); + } + break; + default: + ESP_LOGE(TAG, "Unsupported response type in cleanup_handler"); + break; + } + return; +} + +static esp_err_t network_ctrl_cmd_dispatcher(NetworkCtrlPayload *req, + NetworkCtrlPayload *resp, void *priv_data) +{ + esp_err_t ret; + + ESP_LOGD(TAG, "In network_ctrl_cmd_dispatcher Cmd=%d", req->msg); + + int cmd_index = lookup_cmd_handler(req->msg); + if (cmd_index < 0) { + ESP_LOGE(TAG, "Failed to find cmd with ID = %d in the command table", req->msg); + return ESP_FAIL; + } + + ret = cmd_table[cmd_index].command_handler(req, resp, priv_data); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Error executing command handler"); + } + + return ret; +} + +esp_err_t network_ctrl_handler(uint32_t session_id, const uint8_t *inbuf, ssize_t inlen, + uint8_t **outbuf, ssize_t *outlen, void *priv_data) +{ + NetworkCtrlPayload *req; + NetworkCtrlPayload resp; + esp_err_t ret = ESP_OK; + + req = network_ctrl_payload__unpack(NULL, inlen, inbuf); + if (!req) { + ESP_LOGE(TAG, "Unable to unpack ctrl message"); + return ESP_ERR_INVALID_ARG; + } + + network_ctrl_payload__init(&resp); + ret = network_ctrl_cmd_dispatcher(req, &resp, priv_data); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Command dispatcher error %02X", ret); + ret = ESP_FAIL; + goto exit; + } + + resp.msg = req->msg + 1; /* Response is request + 1 */ + *outlen = network_ctrl_payload__get_packed_size(&resp); + if (*outlen <= 0) { + ESP_LOGE(TAG, "Invalid encoding for response"); + ret = ESP_FAIL; + goto exit; + } + + *outbuf = (uint8_t *) malloc(*outlen); + if (!*outbuf) { + ESP_LOGE(TAG, "Failed to allocate memory for the output buffer"); + ret = ESP_ERR_NO_MEM; + goto exit; + } + network_ctrl_payload__pack(&resp, *outbuf); + ESP_LOGD(TAG, "Response packet size : %d", *outlen); +exit: + + network_ctrl_payload__free_unpacked(req, NULL); + network_ctrl_cmd_cleanup(&resp, priv_data); + return ret; +} diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/src/network_ctrl.h b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/src/network_ctrl.h new file mode 100644 index 000000000..65b2b51c3 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/src/network_ctrl.h @@ -0,0 +1,55 @@ +/* + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _PROV_NETWORK_CTRL_H_ +#define _PROV_NETWORK_CTRL_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Internal handlers for receiving and responding to protocomm + * requests from client + * + * This is to be passed as priv_data for protocomm request handler + * (refer to `network_ctrl_handler()`) when calling `protocomm_add_endpoint()`. + */ +typedef struct network_ctrl_handlers { +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI + /** + * Handler functions called when ctrl reset command is received + */ + esp_err_t (*wifi_ctrl_reset)(void); + + /** + * Handler functions called when ctrl reprov command is received + */ + esp_err_t (*wifi_ctrl_reprov)(void); +#endif // CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI + +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD + esp_err_t (*thread_ctrl_reset)(void); + esp_err_t (*thread_ctrl_reprov)(void); +#endif // CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD +} network_ctrl_handlers_t; + +/** + * @brief Handler for sending on demand network ctrl results + * + * This is to be registered as the `prov-ctrl` endpoint handler + * (protocomm `protocomm_req_handler_t`) using `protocomm_add_endpoint()` + */ +esp_err_t network_ctrl_handler(uint32_t session_id, const uint8_t *inbuf, ssize_t inlen, + uint8_t **outbuf, ssize_t *outlen, void *priv_data); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/src/network_provisioning_priv.h b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/src/network_provisioning_priv.h new file mode 100644 index 000000000..055df2922 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/src/network_provisioning_priv.h @@ -0,0 +1,153 @@ +/* + * SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include + +#include "network_provisioning/manager.h" +#include "network_provisioning/network_config.h" +#include "network_provisioning/network_scan.h" +#include "network_ctrl.h" + +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD +#include "openthread/link.h" +#endif // CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD + +/** + * @brief Notify manager that provisioning is done + * + * Stops the provisioning. This is called by the get_status_handler() + * when the status is connected. This has no effect if main application + * has disabled auto stop on completion by calling + * network_prov_mgr_disable_auto_stop() + * + * @return + * - ESP_OK : Provisioning will be stopped + * - ESP_FAIL : Failed to stop provisioning + */ +esp_err_t network_prov_mgr_done(void); + +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI +/** + * @brief Start Wi-Fi AP Scan + * + * @param[in] blocking Set true to return only after scanning is complete + * @param[in] passive Set true to perform passive scan instead of default active scan + * @param[in] group_channels Number of channels to scan in one go + * (set to 0 for scanning all channels in one go) + * @param[in] period_ms Scan time (in milli-seconds) on each channel + * + * @return + * - ESP_OK : Successfully started Wi-Fi scanning + * - ESP_FAIL : Provisioning app not running + */ +esp_err_t network_prov_mgr_wifi_scan_start(bool blocking, bool passive, + uint8_t group_channels, + uint32_t period_ms); + +/** + * @brief Use to query the state of Wi-Fi scan + * + * @return + * - true : Scan finished + * - false : Scan running + */ +bool network_prov_mgr_wifi_scan_finished(void); + +/** + * @brief Get the count of results in the scan list + * + * @return + * - count : Number of Wi-Fi Access Points detected while scanning + */ +uint16_t network_prov_mgr_wifi_scan_result_count(void); + +/** + * @brief Get AP record for a particular index in the scan list result + * + * @param[out] index Index of the result to fetch + * + * @return + * - result : Pointer to Access Point record + */ +const wifi_ap_record_t *network_prov_mgr_wifi_scan_result(uint16_t index); +#endif // CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI + +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD +/** + * @brief Start Thread network Scan + * + * @param[in] blocking Set true to return only after scanning is complete + * + * @return + * - ESP_OK : Successfully started Thread scanning + * - ESP_FAIL : Provisioning app not running + */ +esp_err_t network_prov_mgr_thread_scan_start(bool blocking, uint32_t channel_mask); + +/** + * @brief Use to query the state of Thread scan + * + * @return + * - true : Scan finished + * - false : Scan running + */ +bool network_prov_mgr_thread_scan_finished(void); + +/** + * @brief Get the count of results in the scan list + * + * @return + * - count : Number of Thread networks detected while scanning + */ +uint16_t network_prov_mgr_thread_scan_result_count(void); + +/** + * @brief Get Thread network record for a particular index in the scan list result + * + * @param[out] index Index of the result to fetch + * + * @return + * - result : Pointer to Thread network record + */ +const otActiveScanResult *network_prov_mgr_thread_scan_result(uint16_t index); + +#endif // CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD + +/** + * @brief Get protocomm handlers for network_config provisioning endpoint + * + * @param[out] ptr pointer to structure to be set + * + * @return + * - ESP_OK : success + * - ESP_ERR_INVALID_ARG : null argument + */ +esp_err_t get_network_prov_handlers(network_prov_config_handlers_t *ptr); + +/** + * @brief Get protocomm handlers for network_scan provisioning endpoint + * + * @param[out] ptr pointer to structure to be set + * + * @return + * - ESP_OK : success + * - ESP_ERR_INVALID_ARG : null argument + */ +esp_err_t get_network_scan_handlers(network_prov_scan_handlers_t *ptr); + +/** + * @brief Get protocomm handlers for network_ctrl provisioning endpoint + * + * @param[in] ptr pointer to structure to be set + * + * @return + * - ESP_OK : success + * - ESP_ERR_INVALID_ARG : null argument + */ +esp_err_t get_network_ctrl_handlers(network_ctrl_handlers_t *ptr); diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/src/network_scan.c b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/src/network_scan.c new file mode 100644 index 000000000..4a4cd9962 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/src/network_scan.c @@ -0,0 +1,480 @@ +/* + * SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include + +#include "network_scan.pb-c.h" + +#include + +static const char *TAG = "proto_network_scan"; + +typedef struct network_prov_scan_cmd { + int cmd_num; + esp_err_t (*command_handler)(NetworkScanPayload *req, + NetworkScanPayload *resp, void *priv_data); +} network_prov_scan_cmd_t; + +static esp_err_t cmd_scan_start_handler(NetworkScanPayload *req, + NetworkScanPayload *resp, + void *priv_data); + +static esp_err_t cmd_scan_status_handler(NetworkScanPayload *req, + NetworkScanPayload *resp, + void *priv_data); + +static esp_err_t cmd_scan_result_handler(NetworkScanPayload *req, + NetworkScanPayload *resp, + void *priv_data); + +static network_prov_scan_cmd_t cmd_table[] = { + { + .cmd_num = NETWORK_SCAN_MSG_TYPE__TypeCmdScanWifiStart, + .command_handler = cmd_scan_start_handler + }, + { + .cmd_num = NETWORK_SCAN_MSG_TYPE__TypeCmdScanWifiStatus, + .command_handler = cmd_scan_status_handler + }, + { + .cmd_num = NETWORK_SCAN_MSG_TYPE__TypeCmdScanWifiResult, + .command_handler = cmd_scan_result_handler + }, + { + .cmd_num = NETWORK_SCAN_MSG_TYPE__TypeCmdScanThreadStart, + .command_handler = cmd_scan_start_handler + }, + { + .cmd_num = NETWORK_SCAN_MSG_TYPE__TypeCmdScanThreadStatus, + .command_handler = cmd_scan_status_handler + }, + { + .cmd_num = NETWORK_SCAN_MSG_TYPE__TypeCmdScanThreadResult, + .command_handler = cmd_scan_result_handler + } +}; + +static esp_err_t cmd_scan_start_handler(NetworkScanPayload *req, + NetworkScanPayload *resp, void *priv_data) +{ + network_prov_scan_handlers_t *h = (network_prov_scan_handlers_t *) priv_data; + if (!h) { + ESP_LOGE(TAG, "Command invoked without handlers"); + return ESP_ERR_INVALID_STATE; + } + if (req->msg == NETWORK_SCAN_MSG_TYPE__TypeCmdScanWifiStart) { + RespScanWifiStart *resp_payload = (RespScanWifiStart *) malloc(sizeof(RespScanWifiStart)); + if (!resp_payload) { + ESP_LOGE(TAG, "Error allocating memory"); + return ESP_ERR_NO_MEM; + } + resp_scan_wifi_start__init(resp_payload); +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI + if (h->wifi_scan_start) { + resp->status = (h->wifi_scan_start(req->cmd_scan_wifi_start->blocking, + req->cmd_scan_wifi_start->passive, + req->cmd_scan_wifi_start->group_channels, + req->cmd_scan_wifi_start->period_ms, + &h->ctx) == ESP_OK ? STATUS__Success : STATUS__InternalError); + } else { + resp->status = STATUS__InternalError; + } +#else + resp->status = STATUS__InvalidArgument; +#endif + resp->payload_case = NETWORK_SCAN_PAYLOAD__PAYLOAD_RESP_SCAN_WIFI_START; + resp->resp_scan_wifi_start = resp_payload; + } else if (req->msg == NETWORK_SCAN_MSG_TYPE__TypeCmdScanThreadStart) { + RespScanThreadStart *resp_payload = (RespScanThreadStart *) malloc(sizeof(RespScanThreadStart)); + if (!resp_payload) { + ESP_LOGE(TAG, "Error allocating memory"); + return ESP_ERR_NO_MEM; + } + resp_scan_thread_start__init(resp_payload); +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD + if (h->thread_scan_start) { + resp->status = (h->thread_scan_start(req->cmd_scan_thread_start->blocking, + req->cmd_scan_thread_start->channel_mask, + &h->ctx) == ESP_OK ? STATUS__Success : STATUS__InternalError); + } else { + resp->status = STATUS__InternalError; + } +#else + resp->status = STATUS__InvalidArgument; +#endif + resp->payload_case = NETWORK_SCAN_PAYLOAD__PAYLOAD_RESP_SCAN_THREAD_START; + resp->resp_scan_thread_start = resp_payload; + } + return ESP_OK; +} + +static esp_err_t cmd_scan_status_handler(NetworkScanPayload *req, + NetworkScanPayload *resp, void *priv_data) +{ + bool scan_finished = false; + uint16_t result_count = 0; + + network_prov_scan_handlers_t *h = (network_prov_scan_handlers_t *) priv_data; + if (!h) { + ESP_LOGE(TAG, "Command invoked without handlers"); + return ESP_ERR_INVALID_STATE; + } + if (req->msg == NETWORK_SCAN_MSG_TYPE__TypeCmdScanWifiStatus) { + RespScanWifiStatus *resp_payload = (RespScanWifiStatus *) malloc(sizeof(RespScanWifiStatus)); + if (!resp_payload) { + ESP_LOGE(TAG, "Error allocating memory"); + return ESP_ERR_NO_MEM; + } + resp_scan_wifi_status__init(resp_payload); +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI + if (h->wifi_scan_status) { + resp->status = (h->wifi_scan_status(&scan_finished, &result_count, &h->ctx) == ESP_OK ? + STATUS__Success : STATUS__InternalError); + } else { + resp->status = STATUS__InternalError; + } +#else + resp->status = STATUS__InvalidArgument; +#endif + resp_payload->scan_finished = scan_finished; + resp_payload->result_count = result_count; + resp->payload_case = NETWORK_SCAN_PAYLOAD__PAYLOAD_RESP_SCAN_WIFI_STATUS; + resp->resp_scan_wifi_status = resp_payload; + } else if (req->msg == NETWORK_SCAN_MSG_TYPE__TypeCmdScanThreadStatus) { + RespScanThreadStatus *resp_payload = (RespScanThreadStatus *) malloc(sizeof(RespScanThreadStatus)); + if (!resp_payload) { + ESP_LOGE(TAG, "Error allocating memory"); + return ESP_ERR_NO_MEM; + } + resp_scan_thread_status__init(resp_payload); +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD + if (h->thread_scan_status) { + resp->status = (h->thread_scan_status(&scan_finished, &result_count, &h->ctx) == ESP_OK ? + STATUS__Success : STATUS__InternalError); + } else { + resp->status = STATUS__InternalError; + } +#else + resp->status = STATUS__InvalidArgument; +#endif + resp_payload->scan_finished = scan_finished; + resp_payload->result_count = result_count; + resp->payload_case = NETWORK_SCAN_PAYLOAD__PAYLOAD_RESP_SCAN_THREAD_STATUS; + resp->resp_scan_thread_status = resp_payload; + } + return ESP_OK; +} + +static esp_err_t cmd_scan_result_handler(NetworkScanPayload *req, + NetworkScanPayload *resp, void *priv_data) +{ + esp_err_t err = ESP_OK; + network_prov_scan_handlers_t *h = (network_prov_scan_handlers_t *) priv_data; + if (!h) { + ESP_LOGE(TAG, "Command invoked without handlers"); + return ESP_ERR_INVALID_STATE; + } + if (req->msg == NETWORK_SCAN_MSG_TYPE__TypeCmdScanWifiResult) { + RespScanWifiResult *resp_payload = (RespScanWifiResult *) malloc(sizeof(RespScanWifiResult)); + if (!resp_payload) { + ESP_LOGE(TAG, "Error allocating memory"); + return ESP_ERR_NO_MEM; + } + resp_scan_wifi_result__init(resp_payload); + resp->status = STATUS__Success; + resp->payload_case = NETWORK_SCAN_PAYLOAD__PAYLOAD_RESP_SCAN_WIFI_RESULT; + resp->resp_scan_wifi_result = resp_payload; +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI + network_prov_scan_wifi_result_t scan_result = {{0}, {0}, 0, 0, 0}; + WiFiScanResult **results = NULL; + + /* Allocate memory only if there are non-zero scan results */ + if (req->cmd_scan_wifi_result->count) { + results = (WiFiScanResult **) calloc(req->cmd_scan_wifi_result->count, + sizeof(WiFiScanResult *)); + if (!results) { + ESP_LOGE(TAG, "Failed to allocate memory for results array"); + return ESP_ERR_NO_MEM; + } + } + resp_payload->entries = results; + resp_payload->n_entries = req->cmd_scan_wifi_result->count; + + /* If req->cmd_scan_wifi_result->count is 0, the below loop will + * be skipped. + */ + for (uint16_t i = 0; i < req->cmd_scan_wifi_result->count; i++) { + if (!h->wifi_scan_result) { + resp->status = STATUS__InternalError; + break; + } + err = h->wifi_scan_result(i + req->cmd_scan_wifi_result->start_index, + &scan_result, &h->ctx); + if (err != ESP_OK) { + resp->status = STATUS__InternalError; + break; + } + + results[i] = (WiFiScanResult *) malloc(sizeof(WiFiScanResult)); + if (!results[i]) { + ESP_LOGE(TAG, "Failed to allocate memory for result entry"); + return ESP_ERR_NO_MEM; + } + wi_fi_scan_result__init(results[i]); + + results[i]->ssid.len = strnlen(scan_result.ssid, 32); + results[i]->ssid.data = (uint8_t *) strndup(scan_result.ssid, 32); + if (!results[i]->ssid.data) { + ESP_LOGE(TAG, "Failed to allocate memory for scan result entry SSID"); + return ESP_ERR_NO_MEM; + } + + results[i]->channel = scan_result.channel; + results[i]->rssi = scan_result.rssi; + results[i]->auth = scan_result.auth; + + results[i]->bssid.len = sizeof(scan_result.bssid); + results[i]->bssid.data = malloc(results[i]->bssid.len); + if (!results[i]->bssid.data) { + ESP_LOGE(TAG, "Failed to allocate memory for scan result entry BSSID"); + return ESP_ERR_NO_MEM; + } + memcpy(results[i]->bssid.data, scan_result.bssid, results[i]->bssid.len); + } +#else // CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI + resp->status = STATUS__InvalidArgument; +#endif // !CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI + } else if (req->msg == NETWORK_SCAN_MSG_TYPE__TypeCmdScanThreadResult) { + RespScanThreadResult *resp_payload = (RespScanThreadResult *) malloc(sizeof(RespScanThreadResult)); + if (!resp_payload) { + ESP_LOGE(TAG, "Error allocating memory"); + return ESP_ERR_NO_MEM; + } + resp_scan_thread_result__init(resp_payload); + resp->status = STATUS__Success; + resp->payload_case = NETWORK_SCAN_PAYLOAD__PAYLOAD_RESP_SCAN_THREAD_RESULT; + resp->resp_scan_thread_result = resp_payload; +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD + network_prov_scan_thread_result_t scan_result; + memset(&scan_result, 0, sizeof(scan_result)); + ThreadScanResult **results = NULL; + + /* Allocate memory only if there are non-zero scan results */ + if (req->cmd_scan_thread_result->count) { + results = (ThreadScanResult **) calloc(req->cmd_scan_thread_result->count, + sizeof(ThreadScanResult *)); + if (!results) { + ESP_LOGE(TAG, "Failed to allocate memory for results array"); + return ESP_ERR_NO_MEM; + } + } + resp_payload->entries = results; + resp_payload->n_entries = req->cmd_scan_thread_result->count; + + /* If req->cmd_scan_result->count is 0, the below loop will + * be skipped. + */ + for (uint16_t i = 0; i < req->cmd_scan_thread_result->count; i++) { + if (!h->thread_scan_result) { + resp->status = STATUS__InternalError; + break; + } + err = h->thread_scan_result(i + req->cmd_scan_thread_result->start_index, + &scan_result, &h->ctx); + if (err != ESP_OK) { + resp->status = STATUS__InternalError; + break; + } + + results[i] = (ThreadScanResult *) malloc(sizeof(ThreadScanResult)); + if (!results[i]) { + ESP_LOGE(TAG, "Failed to allocate memory for result entry"); + return ESP_ERR_NO_MEM; + } + thread_scan_result__init(results[i]); + results[i]->pan_id = scan_result.pan_id; + results[i]->channel = scan_result.channel; + results[i]->rssi = scan_result.rssi; + results[i]->lqi = scan_result.lqi; + + results[i]->ext_addr.len = sizeof(scan_result.ext_addr); + results[i]->ext_addr.data = (uint8_t *)malloc(results[i]->ext_addr.len); + if (!results[i]->ext_addr.data) { + ESP_LOGE(TAG, "Failed to allocate memory for scan result entry extended address"); + return ESP_ERR_NO_MEM; + } + memcpy(results[i]->ext_addr.data, scan_result.ext_addr, results[i]->ext_addr.len); + + results[i]->ext_pan_id.len = sizeof(scan_result.ext_pan_id); + results[i]->ext_pan_id.data = (uint8_t *)malloc(results[i]->ext_pan_id.len); + if (!results[i]->ext_pan_id.data) { + ESP_LOGE(TAG, "Failed to allocate memory for scan result entry extended PAN ID"); + return ESP_ERR_NO_MEM; + } + memcpy(results[i]->ext_pan_id.data, scan_result.ext_pan_id, results[i]->ext_pan_id.len); + + results[i]->network_name = (char *)malloc(sizeof(scan_result.network_name)); + if (!results[i]->network_name) { + ESP_LOGE(TAG, "Failed to allocate memory for scan result entry networkname"); + } + memcpy(results[i]->network_name, scan_result.network_name, sizeof(scan_result.network_name)); + } +#else // CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD + resp->status = STATUS__InvalidArgument; + err = ESP_ERR_INVALID_ARG; +#endif // !CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD + } + return err; +} + + +static int lookup_cmd_handler(int cmd_id) +{ + for (size_t i = 0; i < sizeof(cmd_table) / sizeof(network_prov_scan_cmd_t); i++) { + if (cmd_table[i].cmd_num == cmd_id) { + return i; + } + } + + return -1; +} + +static void network_prov_scan_cmd_cleanup(NetworkScanPayload *resp, void *priv_data) +{ + switch (resp->msg) { + case NETWORK_SCAN_MSG_TYPE__TypeRespScanWifiStart: { + free(resp->resp_scan_wifi_start); + } + break; + case NETWORK_SCAN_MSG_TYPE__TypeRespScanThreadStart: { + free(resp->resp_scan_thread_start); + } + break; + case NETWORK_SCAN_MSG_TYPE__TypeRespScanWifiStatus: { + free(resp->resp_scan_wifi_status); + } + break; + case NETWORK_SCAN_MSG_TYPE__TypeRespScanThreadStatus: { + free(resp->resp_scan_thread_status); + } + break; + + case NETWORK_SCAN_MSG_TYPE__TypeRespScanWifiResult: { + if (!resp->resp_scan_wifi_result) { + return; + } +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI + if (resp->resp_scan_wifi_result->entries) { + for (uint16_t i = 0; i < resp->resp_scan_wifi_result->n_entries; i++) { + if (!resp->resp_scan_wifi_result->entries[i]) { + continue; + } + free(resp->resp_scan_wifi_result->entries[i]->ssid.data); + free(resp->resp_scan_wifi_result->entries[i]->bssid.data); + } + free(resp->resp_scan_wifi_result->entries); + } +#endif // CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI + free(resp->resp_scan_wifi_result); + } + break; + case NETWORK_SCAN_MSG_TYPE__TypeRespScanThreadResult: { + if (!resp->resp_scan_thread_result) { + return; + } +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD + if (resp->resp_scan_thread_result->entries) { + for (uint16_t i = 0; i < resp->resp_scan_thread_result->n_entries; i++) { + if (!resp->resp_scan_thread_result->entries[i]) { + continue; + } + free(resp->resp_scan_thread_result->entries[i]->ext_addr.data); + free(resp->resp_scan_thread_result->entries[i]->ext_pan_id.data); + free(resp->resp_scan_thread_result->entries[i]->network_name); + free(resp->resp_scan_thread_result->entries[i]); + } + free(resp->resp_scan_thread_result->entries); + } +#endif // CONFIG_NETWORK_PROV_NETWORK_TYPE_THREAD + free(resp->resp_scan_thread_result); + } + break; + default: + ESP_LOGE(TAG, "Unsupported response type in cleanup_handler"); + break; + } + return; +} + +static esp_err_t network_prov_scan_cmd_dispatcher(NetworkScanPayload *req, + NetworkScanPayload *resp, void *priv_data) +{ + esp_err_t ret; + + ESP_LOGD(TAG, "In network_prov_scan_cmd_dispatcher Cmd=%d", req->msg); + + int cmd_index = lookup_cmd_handler(req->msg); + if (cmd_index < 0) { + ESP_LOGE(TAG, "Invalid command handler lookup"); + return ESP_FAIL; + } + + ret = cmd_table[cmd_index].command_handler(req, resp, priv_data); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Error executing command handler"); + return ESP_FAIL; + } + + return ESP_OK; +} + +esp_err_t network_prov_scan_handler(uint32_t session_id, const uint8_t *inbuf, ssize_t inlen, + uint8_t **outbuf, ssize_t *outlen, void *priv_data) +{ + NetworkScanPayload *req; + NetworkScanPayload resp; + esp_err_t ret = ESP_OK; + + req = network_scan_payload__unpack(NULL, inlen, inbuf); + if (!req) { + ESP_LOGE(TAG, "Unable to unpack scan message"); + return ESP_ERR_INVALID_ARG; + } + + network_scan_payload__init(&resp); + ret = network_prov_scan_cmd_dispatcher(req, &resp, priv_data); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Command dispatcher error %d", ret); + ret = ESP_FAIL; + goto exit; + } + + resp.msg = req->msg + 1; /* Response is request + 1 */ + *outlen = network_scan_payload__get_packed_size(&resp); + if (*outlen <= 0) { + ESP_LOGE(TAG, "Invalid encoding for response"); + ret = ESP_FAIL; + goto exit; + } + + *outbuf = (uint8_t *) malloc(*outlen); + if (!*outbuf) { + ESP_LOGE(TAG, "System out of memory"); + ret = ESP_ERR_NO_MEM; + goto exit; + } + network_scan_payload__pack(&resp, *outbuf); + ESP_LOGD(TAG, "Response packet size : %d", *outlen); +exit: + + network_scan_payload__free_unpacked(req, NULL); + network_prov_scan_cmd_cleanup(&resp, priv_data); + return ret; +} diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/src/scheme_ble.c b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/src/scheme_ble.c new file mode 100644 index 000000000..89cc95bc2 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/src/scheme_ble.c @@ -0,0 +1,289 @@ +/* + * SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#ifdef CONFIG_BT_CONTROLLER_ENABLED +#include "esp_bt.h" +#endif + +#include +#include + +#include "network_provisioning/scheme_ble.h" +#include "network_provisioning_priv.h" + +static const char *TAG = "network_prov_scheme_ble"; + +extern const network_prov_scheme_t network_prov_scheme_ble; + +static uint8_t *custom_service_uuid; + +static uint8_t *custom_manufacturer_data; +static size_t custom_manufacturer_data_len; + +static esp_err_t prov_start(protocomm_t *pc, void *config) +{ + if (!pc) { + ESP_LOGE(TAG, "Protocomm handle cannot be null"); + return ESP_ERR_INVALID_ARG; + } + + if (!config) { + ESP_LOGE(TAG, "Cannot start with null configuration"); + return ESP_ERR_INVALID_ARG; + } + + protocomm_ble_config_t *ble_config = (protocomm_ble_config_t *) config; + +#if defined(CONFIG_NETWORK_PROV_BLE_BONDING) + ble_config->ble_bonding = 1; +#endif + +#if defined(CONFIG_NETWORK_PROV_BLE_SEC_CONN) || defined(CONFIG_BT_BLUEDROID_ENABLED) + ble_config->ble_sm_sc = 1; +#endif + +#if defined(CONFIG_NETWORK_PROV_BLE_FORCE_ENCRYPTION) + ble_config->ble_link_encryption = 1; +#endif + /* Start protocomm as BLE service */ + if (protocomm_ble_start(pc, ble_config) != ESP_OK) { + ESP_LOGE(TAG, "Failed to start protocomm BLE service"); + return ESP_FAIL; + } + return ESP_OK; +} + +esp_err_t network_prov_scheme_ble_set_service_uuid(uint8_t *uuid128) +{ + if (!uuid128) { + return ESP_ERR_INVALID_ARG; + } + custom_service_uuid = uuid128; + return ESP_OK; +} + +esp_err_t network_prov_scheme_ble_set_mfg_data(uint8_t *mfg_data, ssize_t mfg_data_len) +{ + if (!mfg_data || !mfg_data_len) { + return ESP_ERR_INVALID_ARG; + } + + custom_manufacturer_data = (uint8_t *) malloc(mfg_data_len); + if (custom_manufacturer_data == NULL) { + ESP_LOGE(TAG, "Error allocating memory for mfg_data"); + return ESP_ERR_NO_MEM; + } + + custom_manufacturer_data_len = mfg_data_len; + memcpy(custom_manufacturer_data, mfg_data, mfg_data_len); + return ESP_OK; +} + +static void *new_config(void) +{ + protocomm_ble_config_t *ble_config = calloc(1, sizeof(protocomm_ble_config_t)); + if (!ble_config) { + ESP_LOGE(TAG, "Error allocating memory for new configuration"); + return NULL; + } + + /* The default provisioning service UUID */ + const uint8_t service_uuid[16] = { + /* LSB <--------------------------------------- + * ---------------------------------------> MSB */ + 0x07, 0xed, 0x9b, 0x2d, 0x0f, 0x06, 0x7c, 0x87, + 0x9b, 0x43, 0x43, 0x6b, 0x4d, 0x24, 0x75, 0x17, + }; + + memcpy(ble_config->service_uuid, service_uuid, sizeof(ble_config->service_uuid)); + return ble_config; +} + +static void delete_config(void *config) +{ + if (!config) { + ESP_LOGE(TAG, "Cannot delete null configuration"); + return; + } + + protocomm_ble_config_t *ble_config = (protocomm_ble_config_t *) config; + for (unsigned int i = 0; i < ble_config->nu_lookup_count; i++) { + free((void *)ble_config->nu_lookup[i].name); + } + free(ble_config->nu_lookup); + free(ble_config); +} + +static esp_err_t set_config_service(void *config, const char *service_name, const char *service_key) +{ + if (!config) { + ESP_LOGE(TAG, "Cannot set null configuration"); + return ESP_ERR_INVALID_ARG; + } + + if (!service_name) { + ESP_LOGE(TAG, "Service name cannot be NULL"); + return ESP_ERR_INVALID_ARG; + } + + protocomm_ble_config_t *ble_config = (protocomm_ble_config_t *) config; + strlcpy(ble_config->device_name, service_name, sizeof(ble_config->device_name)); + + /* If a custom service UUID has been provided, override the default one */ + if (custom_service_uuid) { + memcpy(ble_config->service_uuid, custom_service_uuid, sizeof(ble_config->service_uuid)); + } + /* Set manufacturer data if it is provided by app */ + if (custom_manufacturer_data) { + size_t mfg_data_len = custom_manufacturer_data_len; + /* Manufacturer Data Length + 2 Byte header + BLE Device name + 2 Byte + * header <= 31 Bytes */ + if (mfg_data_len > (MAX_BLE_MANUFACTURER_DATA_LEN - sizeof(ble_config->device_name) - 2)) { + ESP_LOGE(TAG, "Manufacturer data length is more than the max allowed size; expect truncated mfg_data "); + /* XXX Does it even make any sense to set truncated mfg_data ? The + * only reason to not return failure from here is provisioning + * should continue as it is with error prints for mfg_data length */ + mfg_data_len = MAX_BLE_MANUFACTURER_DATA_LEN - sizeof(ble_config->device_name) - 2; + } + + ble_config->manufacturer_data = custom_manufacturer_data; + ble_config->manufacturer_data_len = mfg_data_len; + } else { + ble_config->manufacturer_data = NULL; + ble_config->manufacturer_data_len = 0; + } + + return ESP_OK; +} + +static esp_err_t set_config_endpoint(void *config, const char *endpoint_name, uint16_t uuid) +{ + if (!config) { + ESP_LOGE(TAG, "Cannot set null configuration"); + return ESP_ERR_INVALID_ARG; + } + + if (!endpoint_name) { + ESP_LOGE(TAG, "EP name cannot be null"); + return ESP_ERR_INVALID_ARG; + } + + protocomm_ble_config_t *ble_config = (protocomm_ble_config_t *) config; + + char *copy_ep_name = strdup(endpoint_name); + if (!copy_ep_name) { + ESP_LOGE(TAG, "Error allocating memory for EP name"); + return ESP_ERR_NO_MEM; + } + + protocomm_ble_name_uuid_t *lookup_table = ( + realloc(ble_config->nu_lookup, (ble_config->nu_lookup_count + 1) * sizeof(protocomm_ble_name_uuid_t))); + if (!lookup_table) { + ESP_LOGE(TAG, "Error allocating memory for EP-UUID lookup table"); + return ESP_ERR_NO_MEM; + } + + lookup_table[ble_config->nu_lookup_count].name = copy_ep_name; + lookup_table[ble_config->nu_lookup_count].uuid = uuid; + ble_config->nu_lookup = lookup_table; + ble_config->nu_lookup_count += 1; + return ESP_OK; +} + +/* Used when both BT and BLE are not needed by application */ +void network_prov_scheme_ble_event_cb_free_btdm(void *user_data, network_prov_cb_event_t event, void *event_data) +{ +#ifdef CONFIG_BT_CONTROLLER_ENABLED + esp_err_t err; + switch (event) { + case NETWORK_PROV_INIT: + /* Release BT memory, as we need only BLE */ + err = esp_bt_mem_release(ESP_BT_MODE_CLASSIC_BT); + if (err != ESP_OK) { + ESP_LOGE(TAG, "bt_mem_release of classic BT failed %d", err); + } else { + ESP_LOGI(TAG, "BT memory released"); + } + break; + + case NETWORK_PROV_DEINIT: +#ifndef CONFIG_NETWORK_PROV_KEEP_BLE_ON_AFTER_PROV + /* Release memory used by BLE and Bluedroid host stack */ + err = esp_bt_mem_release(ESP_BT_MODE_BTDM); + if (err != ESP_OK) { + ESP_LOGE(TAG, "bt_mem_release of BTDM failed %d", err); + } else { + ESP_LOGI(TAG, "BTDM memory released"); + } +#endif /* !CONFIG_NETWORK_PROV_KEEP_BLE_ON_AFTER_PROV */ + break; + + default: + break; + } +#endif /* CONFIG_BT_CONTROLLER_ENABLED */ +} + +/* Used when BT is not needed by application */ +void network_prov_scheme_ble_event_cb_free_bt(void *user_data, network_prov_cb_event_t event, void *event_data) +{ +#ifdef CONFIG_BT_CONTROLLER_ENABLED + esp_err_t err; + switch (event) { + case NETWORK_PROV_INIT: + /* Release BT memory, as we need only BLE */ + err = esp_bt_mem_release(ESP_BT_MODE_CLASSIC_BT); + if (err != ESP_OK) { + ESP_LOGE(TAG, "bt_mem_release of classic BT failed %d", err); + } else { + ESP_LOGI(TAG, "BT memory released"); + } + break; + + default: + break; + } +#endif /* CONFIG_BT_CONTROLLER_ENABLED */ +} + +/* Used when BLE is not needed by application */ +void network_prov_scheme_ble_event_cb_free_ble(void *user_data, network_prov_cb_event_t event, void *event_data) +{ +#ifdef CONFIG_BT_CONTROLLER_ENABLED + esp_err_t err; + switch (event) { + case NETWORK_PROV_DEINIT: +#ifndef CONFIG_NETWORK_PROV_KEEP_BLE_ON_AFTER_PROV + /* Release memory used by BLE stack */ + err = esp_bt_mem_release(ESP_BT_MODE_BLE); + if (err != ESP_OK) { + ESP_LOGE(TAG, "bt_mem_release of BLE failed %d", err); + } else { + ESP_LOGI(TAG, "BLE memory released"); + } +#endif /* !CONFIG_NETWORK_PROV_KEEP_BLE_ON_AFTER_PROV */ + break; + + default: + break; + } +#endif /* CONFIG_BT_CONTROLLER_ENABLED */ +} + +const network_prov_scheme_t network_prov_scheme_ble = { + .prov_start = prov_start, + .prov_stop = protocomm_ble_stop, + .new_config = new_config, + .delete_config = delete_config, + .set_config_service = set_config_service, + .set_config_endpoint = set_config_endpoint, +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI + .wifi_mode = WIFI_MODE_STA +#endif +}; diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/src/scheme_console.c b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/src/scheme_console.c new file mode 100644 index 000000000..e380c8126 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/src/scheme_console.c @@ -0,0 +1,86 @@ +/* + * SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#include +#include + +#include "network_provisioning/scheme_console.h" +#include "network_provisioning_priv.h" + +static const char *TAG = "network_prov_scheme_console"; + +extern const network_prov_scheme_t network_prov_scheme_console; + +static esp_err_t prov_start(protocomm_t *pc, void *config) +{ + if (!pc) { + ESP_LOGE(TAG, "Protocomm handle cannot be null"); + return ESP_ERR_INVALID_ARG; + } + + if (!config) { + ESP_LOGE(TAG, "Cannot start with null configuration"); + return ESP_ERR_INVALID_ARG; + } + + protocomm_console_config_t *console_config = (protocomm_console_config_t *) config; + + /* Start protocomm console */ + esp_err_t err = protocomm_console_start(pc, console_config); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to start protocomm HTTP server"); + return ESP_FAIL; + } + return ESP_OK; +} + +static void *new_config(void) +{ + protocomm_console_config_t *console_config = malloc(sizeof(protocomm_console_config_t)); + if (!console_config) { + ESP_LOGE(TAG, "Error allocating memory for new configuration"); + return NULL; + } + protocomm_console_config_t default_config = PROTOCOMM_CONSOLE_DEFAULT_CONFIG(); + memcpy(console_config, &default_config, sizeof(default_config)); + return console_config; +} + +static void delete_config(void *config) +{ + if (!config) { + ESP_LOGE(TAG, "Cannot delete null configuration"); + return; + } + free(config); +} + +static esp_err_t set_config_service(void *config, const char *service_name, const char *service_key) +{ + return ESP_OK; +} + +static esp_err_t set_config_endpoint(void *config, const char *endpoint_name, uint16_t uuid) +{ + return ESP_OK; +} + +const network_prov_scheme_t network_prov_scheme_console = { + .prov_start = prov_start, + .prov_stop = protocomm_console_stop, + .new_config = new_config, + .delete_config = delete_config, + .set_config_service = set_config_service, + .set_config_endpoint = set_config_endpoint, +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI + .wifi_mode = WIFI_MODE_STA +#endif +}; diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/src/scheme_softap.c b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/src/scheme_softap.c new file mode 100644 index 000000000..a4a9e3236 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/src/scheme_softap.c @@ -0,0 +1,188 @@ +/* + * SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "sdkconfig.h" + +#include +#include +#include +#include + +#include +#include + +#include "network_provisioning/scheme_softap.h" +#include "network_provisioning_priv.h" + +typedef struct softap_config { + protocomm_httpd_config_t httpd_config; + char ssid[33]; + char password[65]; +} network_prov_softap_config_t; + +static const char *TAG = "network_prov_scheme_softap"; + +extern const network_prov_scheme_t network_prov_scheme_softap; +static void *scheme_softap_prov_httpd_handle; +static esp_err_t start_wifi_ap(const char *ssid, const char *pass) +{ + /* Build Wi-Fi configuration for AP mode */ + wifi_config_t wifi_config = { + .ap = { + .max_connection = 5, + }, + }; + + /* SSID can be a non NULL terminated string if `ap.ssid_len` is specified + * Hence, memcpy is used to support 32 bytes long SSID per 802.11 standard */ + const size_t ssid_len = strnlen(ssid, sizeof(wifi_config.ap.ssid)); + memcpy(wifi_config.ap.ssid, ssid, ssid_len); + wifi_config.ap.ssid_len = ssid_len; + + if (strlen(pass) == 0) { + memset(wifi_config.ap.password, 0, sizeof(wifi_config.ap.password)); + wifi_config.ap.authmode = WIFI_AUTH_OPEN; + } else { + strlcpy((char *) wifi_config.ap.password, pass, sizeof(wifi_config.ap.password)); + wifi_config.ap.authmode = WIFI_AUTH_WPA_WPA2_PSK; + } + + /* Run Wi-Fi in AP + STA mode with configuration built above */ + esp_err_t err = esp_wifi_set_mode(WIFI_MODE_APSTA); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to set Wi-Fi mode : %d", err); + return err; + } + err = esp_wifi_set_config(WIFI_IF_AP, &wifi_config); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to set Wi-Fi config : %d", err); + return err; + } + + return ESP_OK; +} + +static esp_err_t prov_start(protocomm_t *pc, void *config) +{ + if (!pc) { + ESP_LOGE(TAG, "Protocomm handle cannot be null"); + return ESP_ERR_INVALID_ARG; + } + + if (!config) { + ESP_LOGE(TAG, "Cannot start with null configuration"); + return ESP_ERR_INVALID_ARG; + } + + network_prov_softap_config_t *softap_config = (network_prov_softap_config_t *) config; + + protocomm_httpd_config_t *httpd_config = &softap_config->httpd_config; + + if (scheme_softap_prov_httpd_handle) { + httpd_config->ext_handle_provided = true; + httpd_config->data.handle = scheme_softap_prov_httpd_handle; + } + + /* Start protocomm server on top of HTTP */ + esp_err_t err = protocomm_httpd_start(pc, httpd_config); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to start protocomm HTTP server"); + return err; + } + + /* Start Wi-Fi softAP with specified ssid and password */ + err = start_wifi_ap(softap_config->ssid, softap_config->password); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to start Wi-Fi AP"); + protocomm_httpd_stop(pc); + return err; + } + + return ESP_OK; +} + +static esp_err_t prov_stop(protocomm_t *pc) +{ + esp_err_t err = protocomm_httpd_stop(pc); + if (err != ESP_OK) { + ESP_LOGW(TAG, "Error occurred while stopping protocomm_httpd"); + } + + return err; +} + +static void *new_config(void) +{ + network_prov_softap_config_t *softap_config = calloc(1, sizeof(network_prov_softap_config_t)); + if (!softap_config) { + ESP_LOGE(TAG, "Error allocating memory for new configuration"); + return NULL; + } + protocomm_httpd_config_t default_config = { + .data = { + .config = PROTOCOMM_HTTPD_DEFAULT_CONFIG() + } + }; + softap_config->httpd_config = default_config; + return softap_config; +} + +static void delete_config(void *config) +{ + if (!config) { + ESP_LOGE(TAG, "Cannot delete null configuration"); + return; + } + + network_prov_softap_config_t *softap_config = (network_prov_softap_config_t *) config; + free(softap_config); +} + +static esp_err_t set_config_service(void *config, const char *service_name, const char *service_key) +{ + if (!config) { + ESP_LOGE(TAG, "Cannot set null configuration"); + return ESP_ERR_INVALID_ARG; + } + + if (!service_name) { + ESP_LOGE(TAG, "Service name cannot be NULL"); + return ESP_ERR_INVALID_ARG; + } + + network_prov_softap_config_t *softap_config = (network_prov_softap_config_t *) config; + if (service_key) { + const int service_key_len = strlen(service_key); + if (service_key_len < 8 || service_key_len >= sizeof(softap_config->password)) { + ESP_LOGE(TAG, "Incorrect passphrase length for softAP: %d (Expected: Min - 8, Max - 64)", service_key_len); + return ESP_ERR_INVALID_ARG; + } + strlcpy(softap_config->password, service_key, sizeof(softap_config->password)); + } + strlcpy(softap_config->ssid, service_name, sizeof(softap_config->ssid)); + return ESP_OK; +} + +static esp_err_t set_config_endpoint(void *config, const char *endpoint_name, uint16_t uuid) +{ + return ESP_OK; +} + +void network_prov_scheme_softap_set_httpd_handle(void *handle) +{ + scheme_softap_prov_httpd_handle = handle; +} + +const network_prov_scheme_t network_prov_scheme_softap = { + .prov_start = prov_start, + .prov_stop = prov_stop, + .new_config = new_config, + .delete_config = delete_config, + .set_config_service = set_config_service, + .set_config_endpoint = set_config_endpoint, +#ifdef CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI + .wifi_mode = WIFI_MODE_APSTA +#endif +}; diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/README.md b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/README.md new file mode 100644 index 000000000..4fdcf891d --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/README.md @@ -0,0 +1,122 @@ +# ESP Provisioning Tool + +## Description + +`esp_prov` - A python-based utility for testing the provisioning examples over a host machine. + +Usage of `esp-prov` assumes that the provisioning app has specific protocomm endpoints active. These endpoints are active in the provisioning examples and accept specific protobuf data structure: + +| Endpoint Name | URI (HTTP server on ip:port) | Description | +|---------------|------------------------------|------------------------------------------------------------------------------------------| +| prov-session | http://ip:port/prov-session | Security endpoint used for session establishment | +| prov-config | http://ip:port/prov-config | Endpoint used for configuring Wi-Fi credentials or Thread dataset on device | +| proto-ver | http://ip:port/proto-ver | Version endpoint for checking protocol compatibility | +| prov-scan | http://ip:port/prov-scan | Endpoint used for scanning Wi-Fi APs or Thread network | +| prov-ctrl | http://ip:port/prov-ctrl | Endpoint used for controlling Wi-Fi / Thread provisioning state | +| custom-data | http://ip:port/custom-data | Optional endpoint for sending custom data (refer `wifi_prov` or `thread_prov` example) | + + +## Usage + +``` +python esp_prov.py --transport < mode of provisioning : softap \ ble \ console > [ Optional parameters... ] +``` +### Parameters + +* `--help` + Print the list of options along with brief descriptions + +* `--verbose`, `-v` + Sets the verbosity level of output log + +* `--transport ` + - Three options are available: + * `softap` - for SoftAP + HTTPD based provisioning + * Requires the device to be running in Wi-Fi SoftAP mode and hosting an HTTP server supporting specific endpoint URIs + * The client needs to be connected to the device softAP network before running the `esp_prov` tool. + * `ble` - for Bluetooth LE based provisioning + * Supports Linux, Windows and macOS; redirected to console if dependencies are not met + * Assumes that the provisioning endpoints are active on the device with specific Bluetooth LE service UUIDs + * `console` - for debugging via console-based provisioning + * The client->device commands are printed to STDOUT and device->client messages are accepted via STDIN. + * This is to be used when the device is accepting provisioning commands on UART console. + * `httpd` - the script works the same as for `softap`. This could be used on any other network interface than WiFi soft AP, e.g. Ethernet or USB. + +* `--service_name ` (Optional) + - When transport mode is `ble`, this specifies the Bluetooth LE device name to which connection is to be established for provisioned. If not provided, Bluetooth LE scanning is initiated and a list of nearby devices, as seen by the host, is displayed, of which the target device can be chosen. + - When transport mode is `softap` or `httpd`, this specifies the HTTP server hostname / IP which is running the provisioning service, on the SoftAP network (or any other interface for `httpd` mode) of the device which is to be provisioned. This defaults to `192.168.4.1:80` if not specified + +* `--ssid ` (Optional) + - For specifying the SSID of the Wi-Fi AP to which the device is to connect after provisioning. + - If not provided, scanning is initiated and scan results, as seen by the device, are displayed, of which an SSID can be picked and the corresponding password specified. + +* `--passphrase ` (Optional) + - For specifying the password of the Wi-Fi AP to which the device is to connect after provisioning. + - Only used when corresponding SSID is provided using the `--ssid` option + +* `--dataset_tlvs ` (Optional) + - For specifying the Dataset Tlvs of the Thread network to which the device is to connect after provisioning. + +* `--sec_ver ` + - For specifying the version of protocomm endpoint security to use. Following 3 versions are supported: + * `0` for `protocomm_security0` - No security + * `1` for `protocomm_security1` - X25519 key exchange + Authentication using Proof of Possession (PoP) + AES-CTR encryption + * `2` for `protocomm_security2` - Secure Remote Password protocol (SRP6a) + AES-GCM encryption + +* `--pop ` (Optional) + - For specifying optional Proof of Possession string to use for protocomm endpoint security version 1 + - Ignored when other security versions are used + +* `--sec2_username ` (Optional) + - For specifying optional username to use for protocomm endpoint security version 2 + - Ignored when other security versions are used + +* `--sec2_pwd ` (Optional) + - For specifying optional password to use for protocomm endpoint security version 2 + - Ignored when other security versions are used + +* `--sec2_gen_cred` (Optional) + - For generating the `SRP6a` credentials (salt and verifier) from the provided username and password for protocomm endpoint security version 2 + - Ignored when other security versions are used + +* `--sec2_salt_len ` (Optional) + - For specifying the optional `SRP6a` salt length to be used for generating protocomm endpoint security version 2 credentials + - Ignored when other security versions are used and the `--sec2_gen_cred` option is not set + +* `--reset` (Optional) + - Resets internal state machine of the device and clears provisioned credentials; to be used only in case of provisioning failures + +* `--reprov` (Optional) + - Resets internal state machine of the device and clears provisioned credentials; to be used only in case the device is to be provisioned again for new credentials after a previous successful provisioning + +* `--custom_data ` (Optional) + An information string can be sent to the `custom-data` endpoint during provisioning using this argument. + (Assumes the provisioning app has an endpoint called `custom-data` - see [wifi_prov](../../examples/wifi_prov/) example for implementation details). + + +### Example Usage + +Please refer to the `README.md` file with the `wifi_prov` or `thread_prov` example present under `{path-to-network_provisioning-component}/examples`. + +This example uses specific options of the `esp_prov` tool and gives an overview of simple as well as advanced usage scenarios. + +## Dependencies + +This requires the following python libraries to run: +* `bleak` +* `protobuf` +* `cryptography` + +To install the dependency packages needed, please run the following command in `$IDF_PATH` directory: + +For ESP-IDF v5.1: +```shell +bash install.sh --enable-ttfw +``` + +For ESP-IDF v5.2 or later: +```shell +bash install.sh --enable-pytest +``` + +**Note:** For troubleshooting errors with Bluetooth LE transport, please refer this [link](https://bleak.readthedocs.io/en/latest/troubleshooting.html). diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/__init__.py b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/__init__.py new file mode 100644 index 000000000..b1423ba08 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/__init__.py @@ -0,0 +1,5 @@ +# SPDX-FileCopyrightText: 2018-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: Apache-2.0 +# + +from .esp_prov import * # noqa: export esp_prov module to users diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/esp_prov.py b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/esp_prov.py new file mode 100644 index 000000000..bbe2512e5 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/esp_prov.py @@ -0,0 +1,758 @@ +#!/usr/bin/env python +# +# SPDX-FileCopyrightText: 2018-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: Apache-2.0 +# + +import argparse +import asyncio +import json +import os +import sys +import textwrap +import time +from getpass import getpass + +from utils import int_to_hex_str + +try: + import prov + import security + import transport + +except ImportError: + idf_path = os.environ['IDF_PATH'] + sys.path.insert(0, idf_path + '/components/protocomm/python') + sys.path.insert(1, idf_path + '/tools/esp_prov') + + import prov + import security + import transport + +# Set this to true to allow exceptions to be thrown +config_throw_except = False + + +def on_except(err): + if config_throw_except: + raise RuntimeError(err) + else: + print(err) + + +def get_security(secver, sec_patch_ver, username, password, pop='', verbose=False): + if secver == 2: + return security.Security2(sec_patch_ver, username, password, verbose) + elif secver == 1: + return security.Security1(pop, verbose) + elif secver == 0: + return security.Security0(verbose) + return None + + +def get_thread_dataset_tlvs(network_info, network_key): + # Get the simple dataset tlvs from the PAN ID, Channel, Extended PAN ID, and Network Key + pan_id = network_info['pan_id'] + channel = network_info['channel'] + ext_pan_id = network_info['ext_pan_id'] + dataset_tlvs = '00030000' + int_to_hex_str(channel) + '0208' + ext_pan_id + '0510' + network_key + '0102' + int_to_hex_str(pan_id) + return dataset_tlvs + + +async def get_transport(sel_transport, service_name): + try: + tp = None + if (sel_transport in ['softap', 'httpd']): + if service_name is None: + service_name = '192.168.4.1:80' + tp = transport.Transport_HTTP(service_name) + elif (sel_transport == 'ble'): + # BLE client is now capable of automatically figuring out + # the primary service from the advertisement data and the + # characteristics corresponding to each endpoint. + # Below, the service_uuid field and 16bit UUIDs in the nu_lookup + # table are provided only to support devices running older firmware, + # in which case, the automated discovery will fail and the client + # will fallback to using the provided UUIDs instead + nu_lookup = {'prov-session': 'ff51', 'prov-config': 'ff52', 'proto-ver': 'ff53'} + tp = transport.Transport_BLE(service_uuid='021a9004-0382-4aea-bff4-6b3f1c5adfb4', + nu_lookup=nu_lookup) + await tp.connect(devname=service_name) + elif (sel_transport == 'console'): + tp = transport.Transport_Console() + return tp + except RuntimeError as e: + on_except(e) + return None + + +async def version_match(tp, protover, verbose=False): + try: + response = await tp.send_data('proto-ver', protover) + + if verbose: + print('proto-ver response : ', response) + + # First assume this to be a simple version string + if response.lower() == protover.lower(): + return True + + try: + # Else interpret this as JSON structure containing + # information with versions and capabilities of both + # provisioning service and application + info = json.loads(response) + if info['prov']['ver'].lower() == protover.lower(): + return True + + except ValueError: + # If decoding as JSON fails, it means that capabilities + # are not supported + return False + + except Exception as e: + on_except(e) + return None + + +async def has_capability(tp, capability='none', verbose=False): + # Note : default value of `capability` argument cannot be empty string + # because protocomm_httpd expects non zero content lengths + try: + response = await tp.send_data('proto-ver', capability) + + if verbose: + print('proto-ver response : ', response) + + try: + # Interpret this as JSON structure containing + # information with versions and capabilities of both + # provisioning service and application + info = json.loads(response) + supported_capabilities = info['prov']['cap'] + if capability.lower() == 'none': + # No specific capability to check, but capabilities + # feature is present so return True + return True + elif capability in supported_capabilities: + return True + return False + + except ValueError: + # If decoding as JSON fails, it means that capabilities + # are not supported + return False + + except RuntimeError as e: + on_except(e) + + return False + + +async def get_version(tp): + response = None + try: + response = await tp.send_data('proto-ver', '---') + except RuntimeError as e: + on_except(e) + response = '' + return response + + +async def get_sec_patch_ver(tp, verbose=False): + response = await get_version(tp) + + if verbose: + print('proto-ver response : ', response) + + try: + # Interpret this as JSON structure containing + # information with security version information + info = json.loads(response) + try: + sec_patch_ver = info['prov']['sec_patch_ver'] + except KeyError: + sec_patch_ver = 0 + return sec_patch_ver + + except ValueError: + # If decoding as JSON fails, we assume default patch level + return 0 + + +async def establish_session(tp, sec): + try: + response = None + while True: + request = sec.security_session(response) + if request is None: + break + response = await tp.send_data('prov-session', request) + if (response is None): + return False + return True + except RuntimeError as e: + on_except(e) + return None + + +async def custom_config(tp, sec, custom_info, custom_ver): + try: + message = prov.custom_config_request(sec, custom_info, custom_ver) + response = await tp.send_data('custom-config', message) + return (prov.custom_config_response(sec, response) == 0) + except RuntimeError as e: + on_except(e) + return None + + +async def custom_data(tp, sec, custom_data): + try: + message = prov.custom_data_request(sec, custom_data) + response = await tp.send_data('custom-data', message) + return (prov.custom_data_response(sec, response) == 0) + except RuntimeError as e: + on_except(e) + return None + + +async def scan_wifi_APs(sel_transport, tp, sec): + APs = [] + group_channels = 0 + readlen = 100 + if sel_transport in ['softap', 'httpd']: + # In case of softAP/httpd we must perform the scan on individual channels, one by one, + # so that the Wi-Fi controller gets ample time to send out beacons (necessary to + # maintain connectivity with authenticated stations. As scanning one channel at a + # time will be slow, we can group more than one channels to be scanned in quick + # succession, hence speeding up the scan process. Though if too many channels are + # present in a group, the controller may again miss out on sending beacons. Hence, + # the application must should use an optimum value. The following value usually + # works out in most cases + group_channels = 5 + elif sel_transport == 'ble': + # Read at most 4 entries at a time. This is because if we are using BLE transport + # then the response packet size should not exceed the present limit of 256 bytes of + # characteristic value imposed by protocomm_ble. This limit may be removed in the + # future + readlen = 4 + try: + message = prov.scan_start_request('wifi', sec, blocking=True, group_channels=group_channels) + start_time = time.time() + response = await tp.send_data('prov-scan', message) + stop_time = time.time() + print('++++ Scan process executed in ' + str(stop_time - start_time) + ' sec') + prov.scan_start_response(sec, response) + + message = prov.scan_status_request('wifi', sec) + response = await tp.send_data('prov-scan', message) + result = prov.scan_status_response(sec, response) + print('++++ Scan results : ' + str(result['count'])) + if result['count'] != 0: + index = 0 + remaining = result['count'] + while remaining: + count = [remaining, readlen][remaining > readlen] + message = prov.scan_result_request('wifi', sec, index, count) + response = await tp.send_data('prov-scan', message) + APs += prov.scan_result_response(sec, response) + remaining -= count + index += count + + except RuntimeError as e: + on_except(e) + return None + + return APs + + +async def send_wifi_config(tp, sec, ssid, passphrase): + try: + message = prov.config_set_config_request('wifi', sec, ssid, passphrase) + response = await tp.send_data('prov-config', message) + return (prov.config_set_config_response(sec, response) == 0) + except RuntimeError as e: + on_except(e) + return None + + +async def apply_wifi_config(tp, sec): + try: + message = prov.config_apply_config_request('wifi', sec) + response = await tp.send_data('prov-config', message) + return (prov.config_apply_config_response(sec, response) == 0) + except RuntimeError as e: + on_except(e) + return None + + +async def get_wifi_config(tp, sec): + try: + message = prov.config_get_status_request('wifi', sec) + response = await tp.send_data('prov-config', message) + return prov.config_get_status_response(sec, response) + except RuntimeError as e: + on_except(e) + return None + + +async def wait_wifi_connected(tp, sec): + """ + Wait for provisioning to report Wi-Fi is connected + + Returns True if Wi-Fi connection succeeded, False if connection consistently failed + """ + TIME_PER_POLL = 5 + retry = 3 + + while True: + time.sleep(TIME_PER_POLL) + print('\n==== Wi-Fi connection state ====') + ret = await get_wifi_config(tp, sec) + if ret == 'connecting': + continue + elif ret == 'connected': + print('==== Provisioning was successful ====') + return True + elif retry > 0: + retry -= 1 + print('Waiting to poll status again (status %s, %d tries left)...' % (ret, retry)) + else: + print('---- Provisioning failed! ----') + return False + + +async def reset_wifi(tp, sec): + try: + message = prov.ctrl_reset_request('wifi', sec) + response = await tp.send_data('prov-ctrl', message) + prov.ctrl_reset_response(sec, response) + + except RuntimeError as e: + on_except(e) + return None + + +async def reprov_wifi(tp, sec): + try: + message = prov.ctrl_reprov_request('wifi', sec) + response = await tp.send_data('prov-ctrl', message) + prov.ctrl_reprov_response(sec, response) + + except RuntimeError as e: + on_except(e) + return None + + +async def scan_thread_networks(sel_transport, tp, sec): + Networks = [] + # Read at most 4 entries at a time. This is because if we are using BLE transport + # then the response packet size should not exceed the present limit of 256 bytes of + # characteristic value imposed by protocomm_ble. This limit may be removed in the + # future + readlen = 4 + try: + message = prov.scan_start_request('thread', sec, blocking=True, group_channels=0) + start_time = time.time() + response = await tp.send_data('prov-scan', message) + stop_time = time.time() + print('++++ Scan process executed in ' + str(stop_time - start_time) + ' sec') + prov.scan_start_response(sec, response) + + message = prov.scan_status_request('thread', sec) + response = await tp.send_data('prov-scan', message) + result = prov.scan_status_response(sec, response) + print('++++ Scan results : ' + str(result['count'])) + if result['count'] != 0: + index = 0 + remaining = result['count'] + while remaining: + count = [remaining, readlen][remaining > readlen] + message = prov.scan_result_request('thread', sec, index, count) + response = await tp.send_data('prov-scan', message) + Networks += prov.scan_result_response(sec, response) + remaining -= count + index += count + + except RuntimeError as e: + on_except(e) + return None + + return Networks + + +async def send_thread_config(tp, sec, dataset_tlvs): + try: + message = prov.config_set_config_request('thread', sec, dataset_tlvs) + response = await tp.send_data('prov-config', message) + return (prov.config_set_config_response(sec, response) == 0) + except RuntimeError as e: + on_except(e) + return None + + +async def apply_thread_config(tp, sec): + try: + message = prov.config_apply_config_request('thread', sec) + response = await tp.send_data('prov-config', message) + return (prov.config_apply_config_response(sec, response) == 0) + except RuntimeError as e: + on_except(e) + return None + + +async def get_thread_config(tp, sec): + try: + message = prov.config_get_status_request('thread', sec) + response = await tp.send_data('prov-config', message) + return prov.config_get_status_response(sec, response) + except RuntimeError as e: + on_except(e) + return None + + +async def wait_thread_connected(tp, sec): + """ + Wait for provisioning to report Thread is attached + + Returns True if Thread connection succeeded, False if connection consistently failed + """ + TIME_PER_POLL = 5 + retry = 3 + + while True: + time.sleep(TIME_PER_POLL) + print('\n==== Thread connection state ====') + ret = await get_thread_config(tp, sec) + if ret == 'attaching': + continue + elif ret == 'attached': + print('==== Provisioning was successful ====') + return True + elif retry > 0: + retry -= 1 + print('Waiting to poll status again (status %s, %d tries left)...' % (ret, retry)) + else: + print('---- Provisioning failed! ----') + return False + + +async def reset_thread(tp, sec): + try: + message = prov.ctrl_reset_request('thread', sec) + response = await tp.send_data('prov-ctrl', message) + prov.ctrl_reset_response(sec, response) + + except RuntimeError as e: + on_except(e) + return None + + +async def reprov_thread(tp, sec): + try: + message = prov.ctrl_reprov_request('thread', sec) + response = await tp.send_data('prov-ctrl', message) + prov.ctrl_reprov_response(sec, response) + + except RuntimeError as e: + on_except(e) + return None + + +def desc_format(*args): + desc = '' + for arg in args: + desc += textwrap.fill(replace_whitespace=False, text=arg) + '\n' + return desc + + +async def main(): + parser = argparse.ArgumentParser(description=desc_format( + 'ESP Provisioning tool for configuring devices ' + 'running protocomm based provisioning service.', + 'See esp-idf/examples/provisioning for sample applications'), + formatter_class=argparse.RawTextHelpFormatter) + + parser.add_argument('--transport', required=True, dest='mode', type=str, + help=desc_format( + 'Mode of transport over which provisioning is to be performed.', + 'This should be one of "softap", "ble", "console" (or "httpd" which is an alias of softap)')) + + parser.add_argument('--service_name', dest='name', type=str, + help=desc_format( + 'This specifies the name of the provisioning service to connect to, ' + 'depending upon the mode of transport :', + '\t- transport "ble" : The BLE Device Name', + '\t- transport "softap/httpd" : HTTP Server hostname or IP', + '\t (default "192.168.4.1:80")')) + + parser.add_argument('--proto_ver', dest='version', type=str, default='', + help=desc_format( + 'This checks the protocol version of the provisioning service running ' + 'on the device before initiating Wi-Fi configuration')) + + parser.add_argument('--sec_ver', dest='secver', type=int, default=None, + help=desc_format( + 'Protocomm security scheme used by the provisioning service for secure ' + 'session establishment. Accepted values are :', + '\t- 0 : No security', + '\t- 1 : X25519 key exchange + AES-CTR encryption', + '\t + Authentication using Proof of Possession (PoP)', + '\t- 2 : SRP6a + AES-GCM encryption', + 'In case device side application uses IDF\'s provisioning manager, ' + 'the compatible security version is automatically determined from ' + 'capabilities retrieved via the version endpoint')) + + parser.add_argument('--pop', dest='sec1_pop', type=str, default='', + help=desc_format( + 'This specifies the Proof of possession (PoP) when security scheme 1 ' + 'is used')) + + parser.add_argument('--sec2_username', dest='sec2_usr', type=str, default='', + help=desc_format( + 'Username for security scheme 2 (SRP6a)')) + + parser.add_argument('--sec2_pwd', dest='sec2_pwd', type=str, default='', + help=desc_format( + 'Password for security scheme 2 (SRP6a)')) + + parser.add_argument('--sec2_gen_cred', help='Generate salt and verifier for security scheme 2 (SRP6a)', action='store_true') + + parser.add_argument('--sec2_salt_len', dest='sec2_salt_len', type=int, default=16, + help=desc_format( + 'Salt length for security scheme 2 (SRP6a)')) + + parser.add_argument('--ssid', dest='ssid', type=str, default='', + help=desc_format( + 'This configures the device to use SSID of the Wi-Fi network to which ' + 'we would like it to connect to permanently, once provisioning is complete. ' + 'If Wi-Fi scanning is supported by the provisioning service, this need not ' + 'be specified')) + + parser.add_argument('--passphrase', dest='passphrase', type=str, + help=desc_format( + 'This configures the device to use Passphrase for the Wi-Fi network to which ' + 'we would like it to connect to permanently, once provisioning is complete. ' + 'If Wi-Fi scanning is supported by the provisioning service, this need not ' + 'be specified')) + + parser.add_argument('--dataset_tlvs', dest='dataset_tlvs', type=str, + help=desc_format( + 'This configures the device to use Dataset Tlvs of the Thread network to ' + 'which we would like it to attach to permanently, once provisioning is ' + 'complete. If Thread scanning is supported by the provisioning service, this ' + 'need not be specified')) + + parser.add_argument('--custom_data', dest='custom_data', type=str, default='', + help=desc_format( + 'This is an optional parameter, only intended for use with ' + '"examples/wifi_prov"')) + + parser.add_argument('--reset', help='Reset WiFi', action='store_true') + + parser.add_argument('--reprov', help='Reprovision WiFi', action='store_true') + + parser.add_argument('-v','--verbose', help='Increase output verbosity', action='store_true') + + args = parser.parse_args() + + if args.secver == 2 and args.sec2_gen_cred: + if not args.sec2_usr or not args.sec2_pwd: + raise ValueError('Username/password cannot be empty for security scheme 2 (SRP6a)') + + print('==== Salt-verifier for security scheme 2 (SRP6a) ====') + security.sec2_gen_salt_verifier(args.sec2_usr, args.sec2_pwd, args.sec2_salt_len) + sys.exit() + + obj_transport = await get_transport(args.mode.lower(), args.name) + if obj_transport is None: + raise RuntimeError('Failed to establish connection') + + try: + sec_patch_ver = 0 + # If security version not specified check in capabilities + if args.secver is None: + # First check if capabilities are supported or not + if not await has_capability(obj_transport): + print('Security capabilities could not be determined, please specify "--sec_ver" explicitly') + raise ValueError('Invalid Security Version') + + # When no_sec is present, use security 0, else security 1 + args.secver = int(not await has_capability(obj_transport, 'no_sec')) + print(f'==== Security Scheme: {args.secver} ====') + + if (args.secver == 1): + if not await has_capability(obj_transport, 'no_pop'): + if len(args.sec1_pop) == 0: + prompt_str = 'Proof of Possession required: ' + args.sec1_pop = getpass(prompt_str) + elif len(args.sec1_pop) != 0: + print('Proof of Possession will be ignored') + args.sec1_pop = '' + + if (args.secver == 2): + sec_patch_ver = await get_sec_patch_ver(obj_transport, args.verbose) + if len(args.sec2_usr) == 0: + args.sec2_usr = input('Security Scheme 2 - SRP6a Username required: ') + if len(args.sec2_pwd) == 0: + prompt_str = 'Security Scheme 2 - SRP6a Password required: ' + args.sec2_pwd = getpass(prompt_str) + + obj_security = get_security(args.secver, sec_patch_ver, args.sec2_usr, args.sec2_pwd, args.sec1_pop, args.verbose) + if obj_security is None: + raise ValueError('Invalid Security Version') + + if args.version != '': + print('\n==== Verifying protocol version ====') + if not await version_match(obj_transport, args.version, args.verbose): + raise RuntimeError('Error in protocol version matching') + print('==== Verified protocol version successfully ====') + + print('\n==== Starting Session ====') + if not await establish_session(obj_transport, obj_security): + print('Failed to establish session. Ensure that security scheme and proof of possession are correct') + raise RuntimeError('Error in establishing session') + print('==== Session Established ====') + + if await has_capability(obj_transport, 'thread_prov'): + if args.reset: + print('==== Resetting Thread====') + await reset_thread(obj_transport, obj_security) + sys.exit() + + if args.reprov: + print('==== Reprovisioning Thread====') + await reprov_thread(obj_transport, obj_security) + sys.exit() + + if args.dataset_tlvs is None: + if not await has_capability(obj_transport, 'thread_scan'): + prompt_str = 'Enter Thread dataset tlvs string : ' + args.dataset_tlvs = input(prompt_str) + else: + while True: + print('\n==== Scanning Thread Networks ====') + start_time = time.time() + Networks = await scan_thread_networks(args.mode.lower(), obj_transport, obj_security) + end_time = time.time() + print('\n++++ Scan finished in ' + str(end_time - start_time) + ' sec') + if Networks is None: + raise RuntimeError('Error in scanning Thread Networks') + + if len(Networks) == 0: + print('No Thread Networks found!') + sys.exit() + + print('==== Thread Scan results ====') + print('{0: >4} {1: <8} {2: <18} {3: <18} {4: <18} {5: <4} {6: <4} {7: <16}'.format( + 'S.N.', 'PAN ID', 'EXT PAN ID', 'NAME', 'EXT ADDR', 'CHN', 'RSSI', 'LQI')) + for i in range(len(Networks)): + print('[{0: >2}] {1: <8} {2: <18} {3: <18} {4: <18} {5: <4} {6: <4} {7: <16}'.format( + i + 1, Networks[i]['pan_id'], Networks[i]['ext_pan_id'], Networks[i]['network_name'], + Networks[i]['ext_addr'], Networks[i]['channel'], Networks[i]['rssi'], Networks[i]['lqi'])) + + while True: + try: + select = int(input('Select Network by number (0 to rescan) : ')) + if select < 0 or select > len(Networks): + raise ValueError + break + except ValueError: + print('Invalid input! Retry') + + if select != 0: + network_key = getpass('Enter Thread network key string : ') + args.dataset_tlvs = get_thread_dataset_tlvs(Networks[select], network_key) + break + + print('\n==== Sending Thread Dataset to Target ====') + if not await send_thread_config(obj_transport, obj_security, args.dataset_tlvs): + raise RuntimeError('Error in send Thread config') + print('==== Thread Dataset sent successfully ====') + + print('\n==== Applying Thread Config to Target ====') + if not await apply_thread_config(obj_transport, obj_security): + raise RuntimeError('Error in apply Thread config') + print('==== Apply config sent successfully ====') + + await wait_thread_connected(obj_transport, obj_security) + else: + if not await has_capability(obj_transport, 'wifi_prov'): + print('Use wifi_provisioning for device without "wifi_prov" capabilities') + print('The device might be using previous wifi_provisioning in ESP-IDF') + + if args.reset: + print('==== Resetting WiFi====') + await reset_wifi(obj_transport, obj_security) + sys.exit() + + if args.reprov: + print('==== Reprovisioning WiFi====') + await reprov_wifi(obj_transport, obj_security) + sys.exit() + + if args.custom_data != '': + print('\n==== Sending Custom data to Target ====') + if not await custom_data(obj_transport, obj_security, args.custom_data): + raise RuntimeError('Error in custom data') + print('==== Custom data sent successfully ====') + + if args.ssid == '': + if not await has_capability(obj_transport, 'wifi_scan'): + raise RuntimeError('Wi-Fi Scan List is not supported by provisioning service') + + while True: + print('\n==== Scanning Wi-Fi APs ====') + start_time = time.time() + APs = await scan_wifi_APs(args.mode.lower(), obj_transport, obj_security) + end_time = time.time() + print('\n++++ Scan finished in ' + str(end_time - start_time) + ' sec') + if APs is None: + raise RuntimeError('Error in scanning Wi-Fi APs') + + if len(APs) == 0: + print('No APs found!') + sys.exit() + + print('==== Wi-Fi Scan results ====') + print('{0: >4} {1: <33} {2: <12} {3: >4} {4: <4} {5: <16}'.format( + 'S.N.', 'SSID', 'BSSID', 'CHN', 'RSSI', 'AUTH')) + for i in range(len(APs)): + print('[{0: >2}] {1: <33} {2: <12} {3: >4} {4: <4} {5: <16}'.format( + i + 1, APs[i]['ssid'], APs[i]['bssid'], APs[i]['channel'], APs[i]['rssi'], APs[i]['auth'])) + + while True: + try: + select = int(input('Select AP by number (0 to rescan) : ')) + if select < 0 or select > len(APs): + raise ValueError + break + except ValueError: + print('Invalid input! Retry') + + if select != 0: + break + + args.ssid = APs[select - 1]['ssid'] + + if args.passphrase is None: + prompt_str = 'Enter passphrase for {0} : '.format(args.ssid) + args.passphrase = getpass(prompt_str) + + print('\n==== Sending Wi-Fi Credentials to Target ====') + if not await send_wifi_config(obj_transport, obj_security, args.ssid, args.passphrase): + raise RuntimeError('Error in send Wi-Fi config') + print('==== Wi-Fi Credentials sent successfully ====') + + print('\n==== Applying Wi-Fi Config to Target ====') + if not await apply_wifi_config(obj_transport, obj_security): + raise RuntimeError('Error in apply Wi-Fi config') + print('==== Apply config sent successfully ====') + + await wait_wifi_connected(obj_transport, obj_security) + + finally: + await obj_transport.disconnect() + +if __name__ == '__main__': + asyncio.run(main()) diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/proto/__init__.py b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/proto/__init__.py new file mode 100644 index 000000000..29a3d9ede --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/proto/__init__.py @@ -0,0 +1,38 @@ +# SPDX-FileCopyrightText: 2018-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: Apache-2.0 +# + +import importlib.util +import os +import sys +from importlib.abc import Loader +from typing import Any + + +def _load_source(name: str, path: str) -> Any: + spec = importlib.util.spec_from_file_location(name, path) + if not spec: + return None + + module = importlib.util.module_from_spec(spec) + sys.modules[spec.name] = module + assert isinstance(spec.loader, Loader) + spec.loader.exec_module(module) + return module + + +idf_path = os.environ['IDF_PATH'] +esp_prov_path = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + +# protocomm component related python files generated from .proto files +constants_pb2 = _load_source('constants_pb2', idf_path + '/components/protocomm/python/constants_pb2.py') +sec0_pb2 = _load_source('sec0_pb2', idf_path + '/components/protocomm/python/sec0_pb2.py') +sec1_pb2 = _load_source('sec1_pb2', idf_path + '/components/protocomm/python/sec1_pb2.py') +sec2_pb2 = _load_source('sec2_pb2', idf_path + '/components/protocomm/python/sec2_pb2.py') +session_pb2 = _load_source('session_pb2', idf_path + '/components/protocomm/python/session_pb2.py') + +# network_provisioning component related python files generated from .proto files +network_constants_pb2 = _load_source('network_constants_pb2', esp_prov_path + '/../../python/network_constants_pb2.py') +network_config_pb2 = _load_source('network_config_pb2', esp_prov_path + '/../../python/network_config_pb2.py') +network_scan_pb2 = _load_source('network_scan_pb2', esp_prov_path + '/../../python/network_scan_pb2.py') +network_ctrl_pb2 = _load_source('network_ctrl_pb2', esp_prov_path + '/../../python/network_ctrl_pb2.py') diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/prov/__init__.py b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/prov/__init__.py new file mode 100644 index 000000000..8305b0c2b --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/prov/__init__.py @@ -0,0 +1,8 @@ +# SPDX-FileCopyrightText: 2018-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: Apache-2.0 +# + +from .custom_prov import * # noqa F403 +from .network_ctrl import * # noqa F403 +from .network_prov import * # noqa F403 +from .network_scan import * # noqa F403 diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/prov/custom_prov.py b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/prov/custom_prov.py new file mode 100644 index 000000000..7b798dc4c --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/prov/custom_prov.py @@ -0,0 +1,26 @@ +# SPDX-FileCopyrightText: 2018-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: Apache-2.0 +# + +# APIs for interpreting and creating protobuf packets for `custom-config` protocomm endpoint + +from utils import str_to_bytes + + +def print_verbose(security_ctx, data): + if (security_ctx.verbose): + print(f'\x1b[32;20m++++ {data} ++++\x1b[0m') + + +def custom_data_request(security_ctx, data): + # Encrypt the custom data + enc_cmd = security_ctx.encrypt_data(str_to_bytes(data)) + print_verbose(security_ctx, f'Client -> Device (CustomData cmd): 0x{enc_cmd.hex()}') + return enc_cmd.decode('latin-1') + + +def custom_data_response(security_ctx, response_data): + # Decrypt response packet + decrypt = security_ctx.decrypt_data(str_to_bytes(response_data)) + print(f'++++ CustomData response: {str(decrypt)}++++') + return 0 diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/prov/network_ctrl.py b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/prov/network_ctrl.py new file mode 100644 index 000000000..1f785c2b1 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/prov/network_ctrl.py @@ -0,0 +1,61 @@ +# SPDX-FileCopyrightText: 2018-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: Apache-2.0 +# + +# APIs for interpreting and creating protobuf packets for Wi-Fi State Controlling + +import proto +from utils import str_to_bytes + + +def print_verbose(security_ctx, data): + if (security_ctx.verbose): + print(f'\x1b[32;20m++++ {data} ++++\x1b[0m') + + +def ctrl_reset_request(network_type, security_ctx): + # Form protobuf request packet for CtrlReset command + cmd = proto.network_ctrl_pb2.NetworkCtrlPayload() + if network_type == 'wifi': + cmd.msg = proto.network_ctrl_pb2.TypeCmdCtrlWifiReset + elif network_type == 'thread': + cmd.msg = proto.network_ctrl_pb2.TypeCmdCtrlThreadReset + else: + raise RuntimeError + enc_cmd = security_ctx.encrypt_data(cmd.SerializeToString()) + print_verbose(security_ctx, f'Client -> Device (Encrypted CmdCtrlReset): 0x{enc_cmd.hex()}') + return enc_cmd.decode('latin-1') + + +def ctrl_reset_response(security_ctx, response_data): + # Interpret protobuf response packet from CtrlReset command + dec_resp = security_ctx.decrypt_data(str_to_bytes(response_data)) + resp = proto.network_ctrl_pb2.NetworkCtrlPayload() + resp.ParseFromString(dec_resp) + print_verbose(security_ctx, f'CtrlReset status: 0x{str(resp.status)}') + if resp.status != 0: + raise RuntimeError + + +def ctrl_reprov_request(network_type, security_ctx): + # Form protobuf request packet for CtrlReprov command + cmd = proto.network_ctrl_pb2.NetworkCtrlPayload() + if network_type == 'wifi': + cmd.msg = proto.network_ctrl_pb2.TypeCmdCtrlWifiReprov + elif network_type == 'thread': + cmd.msg = proto.network_ctrl_pb2.TypeCmdCtrlThreadReprov + else: + raise RuntimeError + enc_cmd = security_ctx.encrypt_data(cmd.SerializeToString()) + print_verbose(security_ctx, f'Client -> Device (Encrypted CmdCtrlReset): 0x{enc_cmd.hex()}') + return enc_cmd.decode('latin-1') + + +def ctrl_reprov_response(security_ctx, response_data): + # Interpret protobuf response packet from CtrlReprov command + dec_resp = security_ctx.decrypt_data(str_to_bytes(response_data)) + resp = proto.network_ctrl_pb2.NetworkCtrlPayload() + resp.ParseFromString(dec_resp) + print_verbose(security_ctx, f'CtrlReset status: 0x{str(resp.status)}') + if resp.status != 0: + raise RuntimeError diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/prov/network_prov.py b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/prov/network_prov.py new file mode 100644 index 000000000..930e3db8a --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/prov/network_prov.py @@ -0,0 +1,135 @@ +# SPDX-FileCopyrightText: 2018-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: Apache-2.0 +# + +# APIs for interpreting and creating protobuf packets for Wi-Fi provisioning + +import proto +from utils import hex_str_to_bytes, str_to_bytes + + +def print_verbose(security_ctx, data): + if (security_ctx.verbose): + print(f'\x1b[32;20m++++ {data} ++++\x1b[0m') + + +def config_get_status_request(network_type, security_ctx): + # Form protobuf request packet for GetStatus command + cfg1 = proto.network_config_pb2.NetworkConfigPayload() + if network_type == 'wifi': + cfg1.msg = proto.network_config_pb2.TypeCmdGetWifiStatus + cmd_get_wifi_status = proto.network_config_pb2.CmdGetWifiStatus() + cfg1.cmd_get_wifi_status.MergeFrom(cmd_get_wifi_status) + elif network_type == 'thread': + cfg1.msg = proto.network_config_pb2.TypeCmdGetThreadStatus + cmd_get_thread_status = proto.network_config_pb2.CmdGetThreadStatus() + cfg1.cmd_get_thread_status.MergeFrom(cmd_get_thread_status) + else: + raise RuntimeError + encrypted_cfg = security_ctx.encrypt_data(cfg1.SerializeToString()) + print_verbose(security_ctx, f'Client -> Device (Encrypted CmdGetStatus): 0x{encrypted_cfg.hex()}') + return encrypted_cfg.decode('latin-1') + + +def config_get_status_response(security_ctx, response_data): + # Interpret protobuf response packet from GetStatus command + decrypted_message = security_ctx.decrypt_data(str_to_bytes(response_data)) + cmd_resp1 = proto.network_config_pb2.NetworkConfigPayload() + cmd_resp1.ParseFromString(decrypted_message) + print_verbose(security_ctx, f'CmdGetStatus type: {str(cmd_resp1.msg)}') + + if cmd_resp1.msg == proto.network_config_pb2.TypeRespGetWifiStatus: + print_verbose(security_ctx, f'CmdGetStatus status: {str(cmd_resp1.resp_get_wifi_status.status)}') + if cmd_resp1.resp_get_wifi_status.wifi_sta_state == 0: + print('==== WiFi state: Connected ====') + return 'connected' + elif cmd_resp1.resp_get_wifi_status.wifi_sta_state == 1: + print('++++ WiFi state: Connecting... ++++') + return 'connecting' + elif cmd_resp1.resp_get_wifi_status.wifi_sta_state == 2: + print('---- WiFi state: Disconnected ----') + return 'disconnected' + elif cmd_resp1.resp_get_wifi_status.wifi_sta_state == 3: + print('---- WiFi state: Connection Failed ----') + if cmd_resp1.resp_get_wifi_status.wifi_fail_reason == 0: + print('---- Failure reason: Incorrect Password ----') + elif cmd_resp1.resp_get_wifi_status.wifi_fail_reason == 1: + print('---- Failure reason: Incorrect SSID ----') + return 'failed' + elif cmd_resp1.msg == proto.network_config_pb2.TypeRespGetThreadStatus: + print_verbose(security_ctx, f'CmdGetStatus status: {str(cmd_resp1.resp_get_thread_status.status)}') + if cmd_resp1.resp_get_thread_status.thread_state == 0: + print('==== Thread state: Attached ====') + return 'attached' + elif cmd_resp1.resp_get_thread_status.thread_state == 1: + print('==== Thread state: Attaching ====') + return 'attaching' + elif cmd_resp1.resp_get_thread_status.thread_state == 2: + print('==== Thread state: Detached ====') + return 'detached' + elif cmd_resp1.resp_get_thread_status.thread_state == 3: + print('==== Thread state: Attaching Failed ====') + if cmd_resp1.resp_get_thread_status.thread_fail_reason == 0: + print('---- Failure reason: Invalid Dataset ----') + elif cmd_resp1.resp_get_thread_status.thread_fail_reason == 1: + print('---- Failure reason: Network Not Found ----') + return 'failed' + + return 'unknown' + + +def config_set_config_request(network_type, security_ctx, ssid_or_dataset_tlvs, passphrase=''): + # Form protobuf request packet for SetConfig command + cmd = proto.network_config_pb2.NetworkConfigPayload() + if network_type == 'wifi': + cmd.msg = proto.network_config_pb2.TypeCmdSetWifiConfig + cmd.cmd_set_wifi_config.ssid = str_to_bytes(ssid_or_dataset_tlvs) + cmd.cmd_set_wifi_config.passphrase = str_to_bytes(passphrase) + elif network_type == 'thread': + cmd.msg = proto.network_config_pb2.TypeCmdSetThreadConfig + cmd.cmd_set_thread_config.dataset = hex_str_to_bytes(ssid_or_dataset_tlvs) + else: + raise RuntimeError + enc_cmd = security_ctx.encrypt_data(cmd.SerializeToString()) + print_verbose(security_ctx, f'Client -> Device (SetConfig cmd): 0x{enc_cmd.hex()}') + return enc_cmd.decode('latin-1') + + +def config_set_config_response(security_ctx, response_data): + # Interpret protobuf response packet from SetConfig command + decrypt = security_ctx.decrypt_data(str_to_bytes(response_data)) + cmd_resp4 = proto.network_config_pb2.NetworkConfigPayload() + cmd_resp4.ParseFromString(decrypt) + if cmd_resp4.msg == proto.network_config_pb2.TypeRespSetWifiConfig: + print_verbose(security_ctx, f'SetConfig status: 0x{str(cmd_resp4.resp_set_wifi_config.status)}') + return cmd_resp4.resp_set_wifi_config.status + elif cmd_resp4.msg == proto.network_config_pb2.TypeRespSetThreadConfig: + print_verbose(security_ctx, f'SetConfig status: 0x{str(cmd_resp4.resp_set_thread_config.status)}') + return cmd_resp4.resp_set_thread_config.status + + +def config_apply_config_request(network_type, security_ctx): + # Form protobuf request packet for ApplyConfig command + cmd = proto.network_config_pb2.NetworkConfigPayload() + if network_type == 'wifi': + cmd.msg = proto.network_config_pb2.TypeCmdApplyWifiConfig + elif network_type == 'thread': + cmd.msg = proto.network_config_pb2.TypeCmdApplyThreadConfig + else: + raise RuntimeError + enc_cmd = security_ctx.encrypt_data(cmd.SerializeToString()) + print_verbose(security_ctx, f'Client -> Device (ApplyConfig cmd): 0x{enc_cmd.hex()}') + return enc_cmd.decode('latin-1') + + +def config_apply_config_response(security_ctx, response_data): + # Interpret protobuf response packet from ApplyConfig command + decrypt = security_ctx.decrypt_data(str_to_bytes(response_data)) + cmd_resp5 = proto.network_config_pb2.NetworkConfigPayload() + cmd_resp5.ParseFromString(decrypt) + if cmd_resp5.msg == proto.network_config_pb2.TypeRespApplyWifiConfig: + print_verbose(security_ctx, f'ApplyConfig status: 0x{str(cmd_resp5.resp_apply_wifi_config.status)}') + return cmd_resp5.resp_apply_wifi_config.status + elif cmd_resp5.msg == proto.network_config_pb2.TypeRespApplyThreadConfig: + print_verbose(security_ctx, f'ApplyConfig status: 0x{str(cmd_resp5.resp_apply_thread_config.status)}') + return cmd_resp5.resp_apply_thread_config.status diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/prov/network_scan.py b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/prov/network_scan.py new file mode 100644 index 000000000..d6106c259 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/prov/network_scan.py @@ -0,0 +1,129 @@ +# SPDX-FileCopyrightText: 2018-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: Apache-2.0 +# + +# APIs for interpreting and creating protobuf packets for Wi-Fi Scanning +import proto +from utils import str_to_bytes + + +def print_verbose(security_ctx, data): + if (security_ctx.verbose): + print(f'\x1b[32;20m++++ {data} ++++\x1b[0m') + + +def scan_start_request(network_type, security_ctx, blocking=True, passive=False, group_channels=5, period_ms=120): + # Form protobuf request packet for ScanStart command + cmd = proto.network_scan_pb2.NetworkScanPayload() + if network_type == 'wifi': + cmd.msg = proto.network_scan_pb2.TypeCmdScanWifiStart + cmd.cmd_scan_wifi_start.blocking = blocking + cmd.cmd_scan_wifi_start.passive = passive + cmd.cmd_scan_wifi_start.group_channels = group_channels + cmd.cmd_scan_wifi_start.period_ms = period_ms + elif network_type == 'thread': + cmd.msg = proto.network_scan_pb2.TypeCmdScanThreadStart + cmd.cmd_scan_thread_start.blocking = blocking + cmd.cmd_scan_thread_start.channel_mask = 0 + else: + raise RuntimeError + + enc_cmd = security_ctx.encrypt_data(cmd.SerializeToString()) + print_verbose(security_ctx, f'Client -> Device (Encrypted CmdScanStart): 0x{enc_cmd.hex()}') + return enc_cmd.decode('latin-1') + + +def scan_start_response(security_ctx, response_data): + # Interpret protobuf response packet from ScanStart command + dec_resp = security_ctx.decrypt_data(str_to_bytes(response_data)) + resp = proto.network_scan_pb2.NetworkScanPayload() + resp.ParseFromString(dec_resp) + print_verbose(security_ctx, f'ScanStart status: 0x{str(resp.status)}') + if resp.status != 0: + raise RuntimeError + + +def scan_status_request(network_type, security_ctx): + # Form protobuf request packet for ScanStatus command + cmd = proto.network_scan_pb2.NetworkScanPayload() + if network_type == 'wifi': + cmd.msg = proto.network_scan_pb2.TypeCmdScanWifiStatus + elif network_type == 'thread': + cmd.msg = proto.network_scan_pb2.TypeCmdScanThreadStatus + else: + raise RuntimeError + enc_cmd = security_ctx.encrypt_data(cmd.SerializeToString()) + print_verbose(security_ctx, f'Client -> Device (Encrypted CmdScanStatus): 0x{enc_cmd.hex()}') + return enc_cmd.decode('latin-1') + + +def scan_status_response(security_ctx, response_data): + # Interpret protobuf response packet from ScanStatus command + dec_resp = security_ctx.decrypt_data(str_to_bytes(response_data)) + resp = proto.network_scan_pb2.NetworkScanPayload() + resp.ParseFromString(dec_resp) + print_verbose(security_ctx, f'ScanStatus status: 0x{str(resp.status)}') + if resp.status != 0: + raise RuntimeError + if resp.msg == proto.network_scan_pb2.TypeRespScanWifiStatus: + return {'finished': resp.resp_scan_wifi_status.scan_finished, 'count': resp.resp_scan_wifi_status.result_count} + elif resp.msg == proto.network_scan_pb2.TypeRespScanThreadStatus: + return {'finished': resp.resp_scan_thread_status.scan_finished, 'count': resp.resp_scan_thread_status.result_count} + else: + raise RuntimeError + + +def scan_result_request(network_type, security_ctx, index, count): + # Form protobuf request packet for ScanResult command + cmd = proto.network_scan_pb2.NetworkScanPayload() + if network_type == 'wifi': + cmd.msg = proto.network_scan_pb2.TypeCmdScanWifiResult + cmd.cmd_scan_wifi_result.start_index = index + cmd.cmd_scan_wifi_result.count = count + elif network_type == 'thread': + cmd.msg = proto.network_scan_pb2.TypeCmdScanThreadResult + cmd.cmd_scan_thread_result.start_index = index + cmd.cmd_scan_thread_result.count = count + else: + raise RuntimeError + enc_cmd = security_ctx.encrypt_data(cmd.SerializeToString()) + print_verbose(security_ctx, f'Client -> Device (Encrypted CmdScanResult): 0x{enc_cmd.hex()}') + return enc_cmd.decode('latin-1') + + +def scan_result_response(security_ctx, response_data): + # Interpret protobuf response packet from ScanResult command + dec_resp = security_ctx.decrypt_data(str_to_bytes(response_data)) + resp = proto.network_scan_pb2.NetworkScanPayload() + resp.ParseFromString(dec_resp) + print_verbose(security_ctx, f'ScanResult status: 0x{str(resp.status)}') + if resp.status != 0: + raise RuntimeError + results = [] + if resp.msg == proto.network_scan_pb2.TypeRespScanWifiResult: + authmode_str = ['Open', 'WEP', 'WPA_PSK', 'WPA2_PSK', 'WPA_WPA2_PSK', + 'WPA2_ENTERPRISE', 'WPA3_PSK', 'WPA2_WPA3_PSK'] + for entry in resp.resp_scan_wifi_result.entries: + results += [{'ssid': entry.ssid.decode('latin-1').rstrip('\x00'), + 'bssid': entry.bssid.hex(), + 'channel': entry.channel, + 'rssi': entry.rssi, + 'auth': authmode_str[entry.auth]}] + print_verbose(security_ctx, f"ScanResult SSID : {str(results[-1]['ssid'])}") + print_verbose(security_ctx, f"ScanResult BSSID : {str(results[-1]['bssid'])}") + print_verbose(security_ctx, f"ScanResult Channel : {str(results[-1]['channel'])}") + print_verbose(security_ctx, f"ScanResult RSSI : {str(results[-1]['rssi'])}") + print_verbose(security_ctx, f"ScanResult AUTH : {str(results[-1]['auth'])}") + elif resp.msg == proto.network_scan_pb2.TypeRespScanThreadResult: + for entry in resp.resp_scan_thread_result.entries: + results += [{'pan_id': entry.pan_id, + 'ext_pan_id': entry.ext_pan_id.hex(), + 'network_name': entry.network_name, + 'channel': entry.channel, + 'rssi': entry.rssi, + 'lqi': entry.lqi, + 'ext_addr': entry.ext_addr.hex()}] + else: + raise RuntimeError + + return results diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/security/__init__.py b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/security/__init__.py new file mode 100644 index 000000000..4bec5d650 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/security/__init__.py @@ -0,0 +1,7 @@ +# SPDX-FileCopyrightText: 2018-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: Apache-2.0 +# + +from .security0 import * # noqa: F403, F401 +from .security1 import * # noqa: F403, F401 +from .security2 import * # noqa: F403, F401 diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/security/security.py b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/security/security.py new file mode 100644 index 000000000..527df3b3a --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/security/security.py @@ -0,0 +1,10 @@ +# SPDX-FileCopyrightText: 2018-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: Apache-2.0 +# + +# Base class for protocomm security + + +class Security: + def __init__(self, security_session): + self.security_session = security_session diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/security/security0.py b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/security/security0.py new file mode 100644 index 000000000..e155ba82f --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/security/security0.py @@ -0,0 +1,53 @@ +# SPDX-FileCopyrightText: 2018-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: Apache-2.0 +# + +# APIs for interpreting and creating protobuf packets for +# protocomm endpoint with security type protocomm_security0 + +import proto +from utils import str_to_bytes + +from .security import Security + + +class Security0(Security): + def __init__(self, verbose): + # Initialize state of the security1 FSM + self.session_state = 0 + self.verbose = verbose + Security.__init__(self, self.security0_session) + + def security0_session(self, response_data): + # protocomm security0 FSM which interprets/forms + # protobuf packets according to present state of session + if (self.session_state == 0): + self.session_state = 1 + return self.setup0_request() + if (self.session_state == 1): + self.setup0_response(response_data) + return None + + def setup0_request(self): + # Form protocomm security0 request packet + setup_req = proto.session_pb2.SessionData() + setup_req.sec_ver = 0 + session_cmd = proto.sec0_pb2.S0SessionCmd() + setup_req.sec0.sc.MergeFrom(session_cmd) + return setup_req.SerializeToString().decode('latin-1') + + def setup0_response(self, response_data): + # Interpret protocomm security0 response packet + setup_resp = proto.session_pb2.SessionData() + setup_resp.ParseFromString(str_to_bytes(response_data)) + # Check if security scheme matches + if setup_resp.sec_ver != proto.session_pb2.SecScheme0: + raise RuntimeError('Incorrect security scheme') + + def encrypt_data(self, data): + # Passive. No encryption when security0 used + return data + + def decrypt_data(self, data): + # Passive. No encryption when security0 used + return data diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/security/security1.py b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/security/security1.py new file mode 100644 index 000000000..20fa2eb29 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/security/security1.py @@ -0,0 +1,140 @@ +# SPDX-FileCopyrightText: 2018-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: Apache-2.0 +# + +# APIs for interpreting and creating protobuf packets for +# protocomm endpoint with security type protocomm_security1 + +import proto +from cryptography.hazmat.backends import default_backend +from cryptography.hazmat.primitives import hashes, serialization +from cryptography.hazmat.primitives.asymmetric.x25519 import X25519PrivateKey, X25519PublicKey +from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes +from utils import long_to_bytes, str_to_bytes + +from .security import Security + + +def a_xor_b(a: bytes, b: bytes) -> bytes: + return b''.join(long_to_bytes(a[i] ^ b[i]) for i in range(0, len(b))) + + +# Enum for state of protocomm_security1 FSM +class security_state: + REQUEST1 = 0 + RESPONSE1_REQUEST2 = 1 + RESPONSE2 = 2 + FINISHED = 3 + + +class Security1(Security): + def __init__(self, pop, verbose): + # Initialize state of the security1 FSM + self.session_state = security_state.REQUEST1 + self.pop = str_to_bytes(pop) + self.verbose = verbose + Security.__init__(self, self.security1_session) + + def security1_session(self, response_data): + # protocomm security1 FSM which interprets/forms + # protobuf packets according to present state of session + if (self.session_state == security_state.REQUEST1): + self.session_state = security_state.RESPONSE1_REQUEST2 + return self.setup0_request() + elif (self.session_state == security_state.RESPONSE1_REQUEST2): + self.session_state = security_state.RESPONSE2 + self.setup0_response(response_data) + return self.setup1_request() + elif (self.session_state == security_state.RESPONSE2): + self.session_state = security_state.FINISHED + self.setup1_response(response_data) + return None + + print('Unexpected state') + return None + + def __generate_key(self): + # Generate private and public key pair for client + self.client_private_key = X25519PrivateKey.generate() + self.client_public_key = self.client_private_key.public_key().public_bytes( + encoding=serialization.Encoding.Raw, + format=serialization.PublicFormat.Raw) + + def _print_verbose(self, data): + if (self.verbose): + print(f'\x1b[32;20m++++ {data} ++++\x1b[0m') + + def setup0_request(self): + # Form SessionCmd0 request packet using client public key + setup_req = proto.session_pb2.SessionData() + setup_req.sec_ver = proto.session_pb2.SecScheme1 + self.__generate_key() + setup_req.sec1.sc0.client_pubkey = self.client_public_key + self._print_verbose(f'Client Public Key:\t0x{self.client_public_key.hex()}') + return setup_req.SerializeToString().decode('latin-1') + + def setup0_response(self, response_data): + # Interpret SessionResp0 response packet + setup_resp = proto.session_pb2.SessionData() + setup_resp.ParseFromString(str_to_bytes(response_data)) + self._print_verbose('Security version:\t' + str(setup_resp.sec_ver)) + if setup_resp.sec_ver != proto.session_pb2.SecScheme1: + raise RuntimeError('Incorrect security scheme') + + self.device_public_key = setup_resp.sec1.sr0.device_pubkey + # Device random is the initialization vector + device_random = setup_resp.sec1.sr0.device_random + self._print_verbose(f'Device Public Key:\t0x{self.device_public_key.hex()}') + self._print_verbose(f'Device Random:\t0x{device_random.hex()}') + + # Calculate Curve25519 shared key using Client private key and Device public key + sharedK = self.client_private_key.exchange(X25519PublicKey.from_public_bytes(self.device_public_key)) + self._print_verbose(f'Shared Key:\t0x{sharedK.hex()}') + + # If PoP is provided, XOR SHA256 of PoP with the previously + # calculated Shared Key to form the actual Shared Key + if len(self.pop) > 0: + # Calculate SHA256 of PoP + h = hashes.Hash(hashes.SHA256(), backend=default_backend()) + h.update(self.pop) + digest = h.finalize() + # XOR with and update Shared Key + sharedK = a_xor_b(sharedK, digest) + self._print_verbose(f'Updated Shared Key (Shared key XORed with PoP):\t0x{sharedK.hex()}') + # Initialize the encryption engine with Shared Key and initialization vector + cipher = Cipher(algorithms.AES(sharedK), modes.CTR(device_random), backend=default_backend()) + self.cipher = cipher.encryptor() + + def setup1_request(self): + # Form SessionCmd1 request packet using encrypted device public key + setup_req = proto.session_pb2.SessionData() + setup_req.sec_ver = proto.session_pb2.SecScheme1 + setup_req.sec1.msg = proto.sec1_pb2.Session_Command1 + # Encrypt device public key and attach to the request packet + client_verify = self.cipher.update(self.device_public_key) + self._print_verbose(f'Client Proof:\t0x{client_verify.hex()}') + setup_req.sec1.sc1.client_verify_data = client_verify + return setup_req.SerializeToString().decode('latin-1') + + def setup1_response(self, response_data): + # Interpret SessionResp1 response packet + setup_resp = proto.session_pb2.SessionData() + setup_resp.ParseFromString(str_to_bytes(response_data)) + # Ensure security scheme matches + if setup_resp.sec_ver == proto.session_pb2.SecScheme1: + # Read encrypyed device verify string + device_verify = setup_resp.sec1.sr1.device_verify_data + self._print_verbose(f'Device Proof:\t0x{device_verify.hex()}') + # Decrypt the device verify string + enc_client_pubkey = self.cipher.update(setup_resp.sec1.sr1.device_verify_data) + # Match decryped string with client public key + if enc_client_pubkey != self.client_public_key: + raise RuntimeError('Failed to verify device!') + else: + raise RuntimeError('Unsupported security protocol') + + def encrypt_data(self, data): + return self.cipher.update(data) + + def decrypt_data(self, data): + return self.cipher.update(data) diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/security/security2.py b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/security/security2.py new file mode 100644 index 000000000..9d427f1d4 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/security/security2.py @@ -0,0 +1,182 @@ +# SPDX-FileCopyrightText: 2018-2025 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: Apache-2.0 +# APIs for interpreting and creating protobuf packets for +# protocomm endpoint with security type protocomm_security2 +import struct +from typing import Any +from typing import Type + +import proto +from cryptography.hazmat.primitives.ciphers.aead import AESGCM +from utils import long_to_bytes +from utils import str_to_bytes + +from .security import Security +from .srp6a import generate_salt_and_verifier +from .srp6a import Srp6a + +AES_KEY_LEN = 256 // 8 + + +# Enum for state of protocomm_security1 FSM +class security_state: + REQUEST1 = 0 + RESPONSE1_REQUEST2 = 1 + RESPONSE2 = 2 + FINISHED = 3 + + +def sec2_gen_salt_verifier(username: str, password: str, salt_len: int) -> Any: + salt, verifier = generate_salt_and_verifier(username, password, len_s=salt_len) + + salt_str = ', '.join([format(b, '#04x') for b in salt]) + salt_c_arr = '\n '.join(salt_str[i: i + 96] for i in range(0, len(salt_str), 96)) + print(f'static const char sec2_salt[] = {{\n {salt_c_arr}\n}};\n') # noqa E702 + + verifier_str = ', '.join([format(b, '#04x') for b in verifier]) + verifier_c_arr = '\n '.join(verifier_str[i: i + 96] for i in range(0, len(verifier_str), 96)) + print(f'static const char sec2_verifier[] = {{\n {verifier_c_arr}\n}};\n') # noqa E702 + + +class Security2(Security): + def __init__(self, sec_patch_ver:int, username: str, password: str, verbose: bool) -> None: + # Initialize state of the security2 FSM + self.session_state = security_state.REQUEST1 + self.sec_patch_ver = sec_patch_ver + self.username = username + self.password = password + self.verbose = verbose + + self.srp6a_ctx: Type[Srp6a] + self.cipher: Type[AESGCM] + + self.client_pop_key = None + self.nonce = bytearray() + + Security.__init__(self, self.security2_session) + + def security2_session(self, response_data: bytes) -> Any: + # protocomm security2 FSM which interprets/forms + # protobuf packets according to present state of session + if (self.session_state == security_state.REQUEST1): + self.session_state = security_state.RESPONSE1_REQUEST2 + return self.setup0_request() + + if (self.session_state == security_state.RESPONSE1_REQUEST2): + self.session_state = security_state.RESPONSE2 + self.setup0_response(response_data) + return self.setup1_request() + + if (self.session_state == security_state.RESPONSE2): + self.session_state = security_state.FINISHED + self.setup1_response(response_data) + return None + + print('---- Unexpected state! ----') + return None + + def _print_verbose(self, data: str) -> None: + if (self.verbose): + print(f'\x1b[32;20m++++ {data} ++++\x1b[0m') # noqa E702 + + def setup0_request(self) -> Any: + # Form SessionCmd0 request packet using client public key + setup_req = proto.session_pb2.SessionData() + setup_req.sec_ver = proto.session_pb2.SecScheme2 + setup_req.sec2.msg = proto.sec2_pb2.S2Session_Command0 + + setup_req.sec2.sc0.client_username = str_to_bytes(self.username) + self.srp6a_ctx = Srp6a(self.username, self.password) + if self.srp6a_ctx is None: + raise RuntimeError('Failed to initialize SRP6a instance!') + + client_pubkey = long_to_bytes(self.srp6a_ctx.A) + setup_req.sec2.sc0.client_pubkey = client_pubkey + + self._print_verbose(f'Client Public Key:\t0x{client_pubkey.hex()}') + return setup_req.SerializeToString().decode('latin-1') + + def setup0_response(self, response_data: bytes) -> None: + # Interpret SessionResp0 response packet + setup_resp = proto.session_pb2.SessionData() + setup_resp.ParseFromString(str_to_bytes(response_data)) + self._print_verbose(f'Security version:\t{str(setup_resp.sec_ver)}') + if setup_resp.sec_ver != proto.session_pb2.SecScheme2: + raise RuntimeError('Incorrect security scheme') + + # Device public key, random salt and password verifier + device_pubkey = setup_resp.sec2.sr0.device_pubkey + device_salt = setup_resp.sec2.sr0.device_salt + + self._print_verbose(f'Device Public Key:\t0x{device_pubkey.hex()}') + self.client_pop_key = self.srp6a_ctx.process_challenge(device_salt, device_pubkey) + + def setup1_request(self) -> Any: + # Form SessionCmd1 request packet using encrypted device public key + setup_req = proto.session_pb2.SessionData() + setup_req.sec_ver = proto.session_pb2.SecScheme2 + setup_req.sec2.msg = proto.sec2_pb2.S2Session_Command1 + + # Encrypt device public key and attach to the request packet + if self.client_pop_key is None: + raise RuntimeError('Failed to generate client proof!') + + self._print_verbose(f'Client Proof:\t0x{self.client_pop_key.hex()}') + setup_req.sec2.sc1.client_proof = self.client_pop_key + + return setup_req.SerializeToString().decode('latin-1') + + def setup1_response(self, response_data: bytes) -> Any: + # Interpret SessionResp1 response packet + setup_resp = proto.session_pb2.SessionData() + setup_resp.ParseFromString(str_to_bytes(response_data)) + # Ensure security scheme matches + if setup_resp.sec_ver == proto.session_pb2.SecScheme2: + # Read encrypyed device proof string + device_proof = setup_resp.sec2.sr1.device_proof + self._print_verbose(f'Device Proof:\t0x{device_proof.hex()}') + self.srp6a_ctx.verify_session(device_proof) + if not self.srp6a_ctx.authenticated(): + raise RuntimeError('Failed to verify device proof') + else: + raise RuntimeError('Unsupported security protocol') + + # Getting the shared secret + shared_secret = self.srp6a_ctx.get_session_key() + self._print_verbose(f'Shared Secret:\t0x{shared_secret.hex()}') + + # Using the first 256 bits of a 512 bit key + session_key = shared_secret[:AES_KEY_LEN] + self._print_verbose(f'Session Key:\t0x{session_key.hex()}') + + # 96-bit nonce + self.nonce = bytearray(setup_resp.sec2.sr1.device_nonce) + if self.nonce is None: + raise RuntimeError('Received invalid nonce from device!') + self._print_verbose(f'Nonce:\t0x{self.nonce.hex()}') + + # Initialize the encryption engine with Shared Key and initialization vector + self.cipher = AESGCM(session_key) + if self.cipher is None: + raise RuntimeError('Failed to initialize AES-GCM cryptographic engine!') + + def _increment_nonce(self) -> None: + """Increment the last 4 bytes of nonce (big-endian counter).""" + if self.sec_patch_ver == 1: + counter = struct.unpack('>I', self.nonce[8:])[0] # Read last 4 bytes as big-endian integer + counter += 1 # Increment counter + if counter > 0xFFFFFFFF: # Check for overflow + raise RuntimeError('Nonce counter overflow') + self.nonce[8:] = struct.pack('>I', counter) # Store back as big-endian + + def encrypt_data(self, data: bytes) -> Any: + self._print_verbose(f'Nonce:\t0x{self.nonce.hex()}') + ciphertext = self.cipher.encrypt(self.nonce, data, None) + self._increment_nonce() + return ciphertext + + def decrypt_data(self, data: bytes) -> Any: + self._print_verbose(f'Nonce:\t0x{self.nonce.hex()}') + plaintext = self.cipher.decrypt(self.nonce, data, None) + self._increment_nonce() + return plaintext diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/security/srp6a.py b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/security/srp6a.py new file mode 100644 index 000000000..757bc4d78 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/security/srp6a.py @@ -0,0 +1,301 @@ +# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: Apache-2.0 +# + +# N A large safe prime (N = 2q+1, where q is prime) [All arithmetic is done modulo N] +# g A generator modulo N +# k Multiplier parameter (k = H(N, g) in SRP-6a, k = 3 for legacy SRP-6) +# s User's salt +# Iu Username +# p Cleartext Password +# H() One-way hash function +# ^ (Modular) Exponentiation +# u Random scrambling parameter +# a, b Secret ephemeral values +# A, B Public ephemeral values +# x Private key (derived from p and s) +# v Password verifier + +import hashlib +import os +from typing import Any, Callable, Optional, Tuple + +from utils import bytes_to_long, long_to_bytes + +SHA1 = 0 +SHA224 = 1 +SHA256 = 2 +SHA384 = 3 +SHA512 = 4 + +NG_1024 = 0 +NG_2048 = 1 +NG_3072 = 2 +NG_4096 = 3 +NG_8192 = 4 + +_hash_map = {SHA1: hashlib.sha1, + SHA224: hashlib.sha224, + SHA256: hashlib.sha256, + SHA384: hashlib.sha384, + SHA512: hashlib.sha512} + + +_ng_const = ( + # 1024-bit + ('''\ +EEAF0AB9ADB38DD69C33F80AFA8FC5E86072618775FF3C0B9EA2314C9C256576D674DF7496\ +EA81D3383B4813D692C6E0E0D5D8E250B98BE48E495C1D6089DAD15DC7D7B46154D6B6CE8E\ +F4AD69B15D4982559B297BCF1885C529F566660E57EC68EDBC3C05726CC02FD4CBF4976EAA\ +9AFD5138FE8376435B9FC61D2FC0EB06E3''', + '2'), + # 2048 + ('''\ +AC6BDB41324A9A9BF166DE5E1389582FAF72B6651987EE07FC3192943DB56050A37329CBB4\ +A099ED8193E0757767A13DD52312AB4B03310DCD7F48A9DA04FD50E8083969EDB767B0CF60\ +95179A163AB3661A05FBD5FAAAE82918A9962F0B93B855F97993EC975EEAA80D740ADBF4FF\ +747359D041D5C33EA71D281E446B14773BCA97B43A23FB801676BD207A436C6481F1D2B907\ +8717461A5B9D32E688F87748544523B524B0D57D5EA77A2775D2ECFA032CFBDBF52FB37861\ +60279004E57AE6AF874E7303CE53299CCC041C7BC308D82A5698F3A8D0C38271AE35F8E9DB\ +FBB694B5C803D89F7AE435DE236D525F54759B65E372FCD68EF20FA7111F9E4AFF73''', + '2'), + # 3072 + ('''\ +FFFFFFFFFFFFFFFFC90FDAA22168C2\ +34C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E\ +3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B5\ +76625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE\ +9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D3\ +9A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED5290770\ +96966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E77\ +2C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF69558171839\ +95497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A\ +33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6\ +E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA\ +06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C77\ +0988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A93AD2\ +CAFFFFFFFFFFFFFFFF''', + '5'), + # 4096 + ('''\ +FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E08\ +8A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B\ +302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9\ +A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE6\ +49286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8\ +FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D\ +670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C\ +180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718\ +3995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D\ +04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7D\ +B3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D226\ +1AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200C\ +BBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFC\ +E0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B26\ +99C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB\ +04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2\ +233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127\ +D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199\ +FFFFFFFFFFFFFFFF''', + '5'), + # 8192 + ('''\ +FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E08\ +8A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B\ +302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9\ +A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE6\ +49286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8\ +FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D\ +670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C\ +180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718\ +3995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D\ +04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7D\ +B3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D226\ +1AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200C\ +BBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFC\ +E0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B26\ +99C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB\ +04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2\ +233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127\ +D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492\ +36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BDF8FF9406\ +AD9E530EE5DB382F413001AEB06A53ED9027D831179727B0865A8918\ +DA3EDBEBCF9B14ED44CE6CBACED4BB1BDB7F1447E6CC254B33205151\ +2BD7AF426FB8F401378CD2BF5983CA01C64B92ECF032EA15D1721D03\ +F482D7CE6E74FEF6D55E702F46980C82B5A84031900B1C9E59E7C97F\ +BEC7E8F323A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA\ +CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE32806A1D58B\ +B7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55CDA56C9EC2EF29632\ +387FE8D76E3C0468043E8F663F4860EE12BF2D5B0B7474D6E694F91E\ +6DBE115974A3926F12FEE5E438777CB6A932DF8CD8BEC4D073B931BA\ +3BC832B68D9DD300741FA7BF8AFC47ED2576F6936BA424663AAB639C\ +5AE4F5683423B4742BF1C978238F16CBE39D652DE3FDB8BEFC848AD9\ +22222E04A4037C0713EB57A81A23F0C73473FC646CEA306B4BCBC886\ +2F8385DDFA9D4B7FA2C087E879683303ED5BDD3A062B3CF5B3A278A6\ +6D2A13F83F44F82DDF310EE074AB6A364597E899A0255DC164F31CC5\ +0846851DF9AB48195DED7EA1B1D510BD7EE74D73FAF36BC31ECFA268\ +359046F4EB879F924009438B481C6CD7889A002ED5EE382BC9190DA6\ +FC026E479558E4475677E9AA9E3050E2765694DFC81F56E880B96E71\ +60C980DD98EDD3DFFFFFFFFFFFFFFFFF''', + '0x13') +) + + +def get_ng(ng_type: int) -> Tuple[int, int]: + n_hex, g_hex = _ng_const[ng_type] + return int(n_hex, 16), int(g_hex, 16) + + +def get_random(nbytes: int) -> Any: + return bytes_to_long(os.urandom(nbytes)) + + +def get_random_of_length(nbytes: int) -> Any: + offset = (nbytes * 8) - 1 + return get_random(nbytes) | (1 << offset) + + +def H(hash_class: Callable, *args: Any, **kwargs: Any) -> int: + width = kwargs.get('width', None) + + h = hash_class() + + for s in args: + if s is not None: + data = long_to_bytes(s) if isinstance(s, int) else s + if width is not None: + h.update(bytes(width - len(data))) + h.update(data) + + return int(h.hexdigest(), 16) + + +def H_N_xor_g(hash_class: Callable, N: int, g: int) -> bytes: + bin_N = long_to_bytes(N) + bin_g = long_to_bytes(g) + + padding = len(bin_N) - len(bin_g) + + hN = hash_class(bin_N).digest() + hg = hash_class(b''.join([b'\0' * padding, bin_g])).digest() + + return b''.join(long_to_bytes(hN[i] ^ hg[i]) for i in range(0, len(hN))) + + +def calculate_x(hash_class: Callable, s: Any, Iu: str, p: str) -> int: + _Iu = Iu.encode() + _p = p.encode() + + return H(hash_class, s, H(hash_class, _Iu + b':' + _p)) + + +def generate_salt_and_verifier(Iu: str, p: str, len_s: int, hash_alg: int = SHA512, ng_type: int = NG_3072) -> Tuple[bytes, bytes]: + hash_class = _hash_map[hash_alg] + N, g = get_ng(ng_type) + + _s = long_to_bytes(get_random(len_s)) + _v = long_to_bytes(pow(g, calculate_x(hash_class, _s, Iu, p), N)) + + return _s, _v + + +def calculate_M(hash_class: Callable, N: int, g: int, Iu: str, s: int, A: int, B: int, K: bytes) -> Any: + _Iu = Iu.encode() + h = hash_class() + h.update(H_N_xor_g(hash_class, N, g)) + h.update(hash_class(_Iu).digest()) + h.update(long_to_bytes(s)) + h.update(long_to_bytes(A)) + h.update(long_to_bytes(B)) + h.update(K) + return h.digest() + + +def calculate_H_AMK(hash_class: Callable, A: int, M: bytes, K: bytes) -> Any: + h = hash_class() + h.update(long_to_bytes(A)) + h.update(M) + h.update(K) + return h.digest() + + +class Srp6a (object): + def __init__(self, username: str, password: str, hash_alg: int = SHA512, ng_type: int = NG_3072): + hash_class = _hash_map[hash_alg] + + N, g = get_ng(ng_type) + k = H(hash_class, N, g, width=len(long_to_bytes(N))) + + self.Iu = username + self.p = password + + self.a = get_random_of_length(32) + self.A = pow(g, self.a, N) + + self.v: Optional[int] = None + self.K: Optional[bytes] = None + self.H_AMK = None + self._authenticated = False + + self.hash_class = hash_class + self.N = N + self.g = g + self.k = k + + def authenticated(self) -> bool: + return self._authenticated + + def get_username(self) -> str: + return self.Iu + + def get_ephemeral_secret(self) -> Any: + return long_to_bytes(self.a) + + def get_session_key(self) -> Any: + return self.K if self._authenticated else None + + def start_authentication(self) -> Tuple[str, bytes]: + return (self.Iu, long_to_bytes(self.A)) + + # Returns M or None if SRP-6a safety check is violated + def process_challenge(self, bytes_s: bytes, bytes_B: bytes) -> Any: + s = bytes_to_long(bytes_s) + B = bytes_to_long(bytes_B) + + N = self.N + g = self.g + k = self.k + + hash_class = self.hash_class + + # SRP-6a safety check + if (B % N) == 0: + return None + + u = H(hash_class, self.A, B, width=len(long_to_bytes(N))) + if u == 0: # SRP-6a safety check + return None + + x = calculate_x(hash_class, s, self.Iu, self.p) + + v = pow(g, x, N) + + S = pow((B - k * v), (self.a + u * x), N) + + self.K = hash_class(long_to_bytes(S)).digest() + + M = calculate_M(hash_class, N, g, self.Iu, s, self.A, B, self.K) + if not M: + return None + + self.H_AMK = calculate_H_AMK(hash_class, self.A, M, self.K) + + return M + + def verify_session(self, host_HAMK: bytes) -> None: + if self.H_AMK == host_HAMK: + self._authenticated = True + + +class AuthenticationFailed (Exception): + pass diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/transport/__init__.py b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/transport/__init__.py new file mode 100644 index 000000000..82ae39a1f --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/transport/__init__.py @@ -0,0 +1,7 @@ +# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: Apache-2.0 +# + +from .transport_ble import * # noqa: F403, F401 +from .transport_console import * # noqa: F403, F401 +from .transport_http import * # noqa: F403, F401 diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/transport/ble_cli.py b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/transport/ble_cli.py new file mode 100644 index 000000000..c87926261 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/transport/ble_cli.py @@ -0,0 +1,213 @@ +# SPDX-FileCopyrightText: 2018-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: Apache-2.0 +# + +import platform + +from utils import hex_str_to_bytes, str_to_bytes + +fallback = True + + +# Check if required packages are installed +# else fallback to console mode +try: + import bleak + fallback = False +except ImportError: + pass + + +# -------------------------------------------------------------------- + +def device_sort(device): + return device[0].address + + +class BLE_Bleak_Client: + def __init__(self): + self.adapter = None + self.adapter_props = None + self.characteristics = dict() + self.chrc_names = None + self.device = None + self.devname = None + self.iface = None + self.nu_lookup = None + self.services = None + self.srv_uuid_adv = None + self.srv_uuid_fallback = None + + async def connect(self, devname, iface, chrc_names, fallback_srv_uuid): + self.devname = devname + self.srv_uuid_fallback = fallback_srv_uuid + self.chrc_names = [name.lower() for name in chrc_names] + self.iface = iface + + print('Discovering...') + try: + discovery = await bleak.BleakScanner.discover(return_adv=True) + devices = list(discovery.values()) + except bleak.exc.BleakDBusError as e: + if str(e) == '[org.bluez.Error.NotReady] Resource Not Ready': + raise RuntimeError('Bluetooth is not ready. Maybe try `bluetoothctl power on`?') + raise + + found_device = None + + if self.devname is None: + if len(devices) == 0: + print('No devices found!') + exit(1) + + while True: + devices.sort(key=device_sort) + print('==== BLE Discovery results ====') + print('{0: >4} {1: <33} {2: <12}'.format( + 'S.N.', 'Name', 'Address')) + for i, _ in enumerate(devices): + print('[{0: >2}] {1: <33} {2: <12}'.format(i + 1, devices[i][0].name or 'Unknown', devices[i][0].address)) + + while True: + try: + select = int(input('Select device by number (0 to rescan) : ')) + if select < 0 or select > len(devices): + raise ValueError + break + except ValueError: + print('Invalid input! Retry') + + if select != 0: + break + + discovery = await bleak.BleakScanner.discover(return_adv=True) + devices = list(discovery.values()) + + self.devname = devices[select - 1][0].name + found_device = devices[select - 1] + else: + for d in devices: + if d[0].name == self.devname: + found_device = d + + if not found_device: + raise RuntimeError('Device not found') + + uuids = found_device[1].service_uuids + # There should be 1 service UUID in advertising data + # If bluez had cached an old version of the advertisement data + # the list of uuids may be incorrect, in which case connection + # or service discovery may fail the first time. If that happens + # the cache will be refreshed before next retry + if len(uuids) == 1: + self.srv_uuid_adv = uuids[0] + + print('Connecting...') + self.device = bleak.BleakClient(found_device[0].address) + await self.device.connect() + # must be paired on Windows to access characteristics; + # cannot be paired on Mac + if platform.system() == 'Windows': + await self.device.pair() + + print('Getting Services...') + services = self.device.services + + service = services[self.srv_uuid_adv] or services[self.srv_uuid_fallback] + if not service: + await self.device.disconnect() + self.device = None + raise RuntimeError('Provisioning service not found') + + nu_lookup = dict() + for characteristic in service.characteristics: + for descriptor in characteristic.descriptors: + if descriptor.uuid[4:8] != '2901': + continue + readval = await self.device.read_gatt_descriptor(descriptor.handle) + found_name = ''.join(chr(b) for b in readval).lower() + nu_lookup[found_name] = characteristic.uuid + self.characteristics[characteristic.uuid] = characteristic + + match_found = True + for name in self.chrc_names: + if name not in nu_lookup: + # Endpoint name not present + match_found = False + break + + # Create lookup table only if all endpoint names found + self.nu_lookup = [None, nu_lookup][match_found] + + return True + + def get_nu_lookup(self): + return self.nu_lookup + + def has_characteristic(self, uuid): + print('checking for characteristic ' + uuid) + if uuid in self.characteristics: + return True + return False + + async def disconnect(self): + if self.device: + print('Disconnecting...') + if platform.system() == 'Windows': + await self.device.unpair() + await self.device.disconnect() + self.device = None + self.nu_lookup = None + self.characteristics = dict() + + async def send_data(self, characteristic_uuid, data): + await self.device.write_gatt_char(characteristic_uuid, bytearray(data.encode('latin-1')), True) + readval = await self.device.read_gatt_char(characteristic_uuid) + return ''.join(chr(b) for b in readval) +# -------------------------------------------------------------------- + + +# Console based BLE client for Cross Platform support +class BLE_Console_Client: + async def connect(self, devname, iface, chrc_names, fallback_srv_uuid): + print('BLE client is running in console mode') + print('\tThis could be due to your platform not being supported or dependencies not being met') + print('\tPlease ensure all pre-requisites are met to run the full fledged client') + print('BLECLI >> Please connect to BLE device `' + devname + '` manually using your tool of choice') + resp = input('BLECLI >> Was the device connected successfully? [y/n] ') + if resp != 'Y' and resp != 'y': + return False + print('BLECLI >> List available attributes of the connected device') + resp = input("BLECLI >> Is the service UUID '" + fallback_srv_uuid + "' listed among available attributes? [y/n] ") + if resp != 'Y' and resp != 'y': + return False + return True + + def get_nu_lookup(self): + return None + + def has_characteristic(self, uuid): + resp = input("BLECLI >> Is the characteristic UUID '" + uuid + "' listed among available attributes? [y/n] ") + if resp != 'Y' and resp != 'y': + return False + return True + + async def disconnect(self): + pass + + async def send_data(self, characteristic_uuid, data): + print("BLECLI >> Write following data to characteristic with UUID '" + characteristic_uuid + "' :") + print('\t>> ' + str_to_bytes(data).hex()) + print('BLECLI >> Enter data read from characteristic (in hex) :') + resp = input('\t<< ') + return hex_str_to_bytes(resp) + + +# -------------------------------------------------------------------- + + +# Function to get client instance depending upon platform +def get_client(): + if fallback: + return BLE_Console_Client() + return BLE_Bleak_Client() diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/transport/transport.py b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/transport/transport.py new file mode 100644 index 000000000..4dab81e85 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/transport/transport.py @@ -0,0 +1,21 @@ +# SPDX-FileCopyrightText: 2018-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: Apache-2.0 +# + +# Base class for protocomm transport + +import abc + + +class Transport(): + + @abc.abstractmethod + def send_session_data(self, data): + pass + + @abc.abstractmethod + def send_config_data(self, data): + pass + + async def disconnect(self): + pass diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/transport/transport_ble.py b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/transport/transport_ble.py new file mode 100644 index 000000000..671dd7a7d --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/transport/transport_ble.py @@ -0,0 +1,50 @@ +# SPDX-FileCopyrightText: 2018-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: Apache-2.0 +# + +from . import ble_cli +from .transport import Transport + + +class Transport_BLE(Transport): + def __init__(self, service_uuid, nu_lookup): + self.nu_lookup = nu_lookup + self.service_uuid = service_uuid + self.name_uuid_lookup = None + # Expect service UUID like '0000ffff-0000-1000-8000-00805f9b34fb' + for name in nu_lookup.keys(): + # Calculate characteristic UUID for each endpoint + nu_lookup[name] = service_uuid[:4] + '{:02x}'.format( + int(nu_lookup[name], 16) & int(service_uuid[4:8], 16)) + service_uuid[8:] + + # Get BLE client module + self.cli = ble_cli.get_client() + + async def connect(self, devname): + # Use client to connect to BLE device and bind to service + if not await self.cli.connect(devname=devname, iface='hci0', + chrc_names=self.nu_lookup.keys(), + fallback_srv_uuid=self.service_uuid): + raise RuntimeError('Failed to initialize transport') + + # Irrespective of provided parameters, let the client + # generate a lookup table by reading advertisement data + # and characteristic user descriptors + self.name_uuid_lookup = self.cli.get_nu_lookup() + + # If that doesn't work, use the lookup table provided as parameter + if self.name_uuid_lookup is None: + self.name_uuid_lookup = self.nu_lookup + # Check if expected characteristics are provided by the service + for name in self.name_uuid_lookup.keys(): + if not self.cli.has_characteristic(self.name_uuid_lookup[name]): + raise RuntimeError(f"'{name}' endpoint not found") + + async def disconnect(self): + await self.cli.disconnect() + + async def send_data(self, ep_name, data): + # Write (and read) data to characteristic corresponding to the endpoint + if ep_name not in self.name_uuid_lookup.keys(): + raise RuntimeError(f'Invalid endpoint: {ep_name}') + return await self.cli.send_data(self.name_uuid_lookup[ep_name], data) diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/transport/transport_console.py b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/transport/transport_console.py new file mode 100644 index 000000000..8fbcc2fe9 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/transport/transport_console.py @@ -0,0 +1,19 @@ +# SPDX-FileCopyrightText: 2018-2022 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: Apache-2.0 +# + +from utils import hex_str_to_bytes, str_to_bytes + +from .transport import Transport + + +class Transport_Console(Transport): + + async def send_data(self, path, data, session_id=0): + print('Client->Device msg :', path, session_id, str_to_bytes(data).hex()) + try: + resp = input('Enter device->client msg : ') + except Exception as err: + print('error:', err) + return None + return hex_str_to_bytes(resp) diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/transport/transport_http.py b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/transport/transport_http.py new file mode 100644 index 000000000..f17cfc8f6 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/transport/transport_http.py @@ -0,0 +1,49 @@ +# SPDX-FileCopyrightText: 2018-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: Apache-2.0 +# +import socket +from http.client import HTTPConnection, HTTPSConnection + +from utils import str_to_bytes + +from .transport import Transport + + +class Transport_HTTP(Transport): + def __init__(self, hostname, ssl_context=None): + try: + socket.gethostbyname(hostname.split(':')[0]) + except socket.gaierror: + raise RuntimeError(f'Unable to resolve hostname: {hostname}') + + if ssl_context is None: + self.conn = HTTPConnection(hostname, timeout=60) + else: + self.conn = HTTPSConnection(hostname, context=ssl_context, timeout=60) + try: + print(f'++++ Connecting to {hostname}++++') + self.conn.connect() + except Exception as err: + raise RuntimeError('Connection Failure : ' + str(err)) + self.headers = {'Content-type': 'application/x-www-form-urlencoded','Accept': 'text/plain'} + + def _send_post_request(self, path, data): + data = str_to_bytes(data) if isinstance(data, str) else data + try: + self.conn.request('POST', path, data, self.headers) + response = self.conn.getresponse() + # While establishing a session, the device sends the Set-Cookie header + # with value 'session=cookie_session_id' in its first response of the session to the tool. + # To maintain the same session, successive requests from the tool should include + # an additional 'Cookie' header with the above recieved value. + for hdr_key, hdr_val in response.getheaders(): + if hdr_key == 'Set-Cookie': + self.headers['Cookie'] = hdr_val + if response.status == 200: + return response.read().decode('latin-1') + except Exception as err: + raise RuntimeError('Connection Failure : ' + str(err)) + raise RuntimeError('Server responded with error code ' + str(response.status)) + + async def send_data(self, ep_name, data): + return self._send_post_request('/' + ep_name, data) diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/utils/__init__.py b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/utils/__init__.py new file mode 100644 index 000000000..24d184246 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/utils/__init__.py @@ -0,0 +1,5 @@ +# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: Apache-2.0 +# + +from .convenience import * # noqa: F403, F401 diff --git a/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/utils/convenience.py b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/utils/convenience.py new file mode 100644 index 000000000..84413082d --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__network_provisioning/tool/esp_prov/utils/convenience.py @@ -0,0 +1,31 @@ +# SPDX-FileCopyrightText: 2018-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: Apache-2.0 +# + +# Convenience functions for commonly used data type conversions + +def bytes_to_long(s: bytes) -> int: + return int.from_bytes(s, 'big') + + +def long_to_bytes(n: int) -> bytes: + if n == 0: + return b'\x00' + return n.to_bytes((n.bit_length() + 7) // 8, 'big') + + +# 'deadbeef' -> b'deadbeef' +def str_to_bytes(s: str) -> bytes: + return bytes(s, encoding='latin-1') + + +# 'deadbeef' -> b'\xde\xad\xbe\xef' +def hex_str_to_bytes(s: str) -> bytes: + return bytes.fromhex(s) + + +def int_to_hex_str(n: int) -> str: + hex_string = format(n, 'x') + if len(hex_string) % 2 != 0: + hex_string = '0' + hex_string + return hex_string diff --git a/RainMaker_Table-Lights/managed_components/espressif__qrcode/.component_hash b/RainMaker_Table-Lights/managed_components/espressif__qrcode/.component_hash new file mode 100644 index 000000000..e04759674 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__qrcode/.component_hash @@ -0,0 +1 @@ +3b493771bc5d6ad30cbf87c25bf784aada8a08c941504355b55d6b75518ed7bc \ No newline at end of file diff --git a/RainMaker_Table-Lights/managed_components/espressif__qrcode/CHECKSUMS.json b/RainMaker_Table-Lights/managed_components/espressif__qrcode/CHECKSUMS.json new file mode 100644 index 000000000..c1cb8cfe1 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__qrcode/CHECKSUMS.json @@ -0,0 +1 @@ +{"version": "1.0", "algorithm": "sha256", "created_at": "2025-05-21T17:27:01.813204+00:00", "files": [{"path": "CMakeLists.txt", "size": 150, "hash": "bef5499f834549e3c2eac9cd7417c4f4d704d35810f8dfb8ef75e4ab13f7760d"}, {"path": "LICENSE", "size": 11358, "hash": "cfc7749b96f63bd31c3c42b5c471bf756814053e847c10f3eb003417bc523d30"}, {"path": "idf_component.yml", "size": 122, "hash": "d6bf953451ab05816fda32a1cea1fc57d03d5e6372f5bb9062879ba27a17c2f5"}, {"path": "qrcodegen.h", "size": 14731, "hash": "d21849bb5509aa515cf3a61907dcc2e5f00245eb284a228dbab88043df8da743"}, {"path": "esp_qrcode_wrapper.c", "size": 422, "hash": "9f043b92a50dcfe26b46627feb8ff53819b316e4ffe5a23d3b27eecd5d1c7cc0"}, {"path": "README.md", "size": 723, "hash": "7c9999591459e3ec8a2edee2028e17a72212c37a4d9c33b31ac96b923fe87403"}, {"path": "esp_qrcode_main.c", "size": 3208, "hash": "ff010e8324d0bbd15e0f69a175ee0c3e66a2899366e43286434bd0f3b611013c"}, {"path": "qrcodegen.c", "size": 46637, "hash": "2e050dfb5d86a2e22842546efb034d27b5b5f56d29651c1e2eb5c5402870fb9c"}, {"path": "include/qrcode.h", "size": 3086, "hash": "f6fb6a1b439a6097fed128ad079b48040d20a25063678e81f78daaeb623ee636"}]} \ No newline at end of file diff --git a/RainMaker_Table-Lights/managed_components/espressif__qrcode/CMakeLists.txt b/RainMaker_Table-Lights/managed_components/espressif__qrcode/CMakeLists.txt new file mode 100644 index 000000000..fa3bd8e41 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__qrcode/CMakeLists.txt @@ -0,0 +1,3 @@ +idf_component_register(SRCS "esp_qrcode_main.c" "esp_qrcode_wrapper.c" "qrcodegen.c" + INCLUDE_DIRS "include" + ) diff --git a/RainMaker_Table-Lights/managed_components/espressif__qrcode/LICENSE b/RainMaker_Table-Lights/managed_components/espressif__qrcode/LICENSE new file mode 100644 index 000000000..d64569567 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__qrcode/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/RainMaker_Table-Lights/managed_components/espressif__qrcode/README.md b/RainMaker_Table-Lights/managed_components/espressif__qrcode/README.md new file mode 100644 index 000000000..4292a84c9 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__qrcode/README.md @@ -0,0 +1,9 @@ +# QR Code generator component + +[![Component Registry](https://components.espressif.com/components/espressif/qrcode/badge.svg)](https://components.espressif.com/components/espressif/qrcode) + +This component contains a QR code generator written in C. This component is based on [QR-Code-generator](https://github.com/nayuki/QR-Code-generator). +This component is used as part of the following ESP-IDF examples: +- [DPP Enrollee Example](https://github.com/espressif/esp-idf/tree/master/examples/wifi/wifi_easy_connect/dpp-enrollee). + +To learn more about how to use this component, please check API Documentation from header file [qrcode.h](https://github.com/espressif/idf-extra-components/tree/master/qrcode/include/qrcode.h). diff --git a/RainMaker_Table-Lights/managed_components/espressif__qrcode/esp_qrcode_main.c b/RainMaker_Table-Lights/managed_components/espressif__qrcode/esp_qrcode_main.c new file mode 100644 index 000000000..ddce9c2d2 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__qrcode/esp_qrcode_main.c @@ -0,0 +1,113 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include "esp_log.h" + +#include "qrcodegen.h" +#include "qrcode.h" + +static const char *TAG = "QRCODE"; + +static const char *lt[] = { + /* 0 */ " ", + /* 1 */ "\u2580 ", + /* 2 */ " \u2580", + /* 3 */ "\u2580\u2580", + /* 4 */ "\u2584 ", + /* 5 */ "\u2588 ", + /* 6 */ "\u2584\u2580", + /* 7 */ "\u2588\u2580", + /* 8 */ " \u2584", + /* 9 */ "\u2580\u2584", + /* 10 */ " \u2588", + /* 11 */ "\u2580\u2588", + /* 12 */ "\u2584\u2584", + /* 13 */ "\u2588\u2584", + /* 14 */ "\u2584\u2588", + /* 15 */ "\u2588\u2588", +}; + +void esp_qrcode_print_console(esp_qrcode_handle_t qrcode) +{ + int size = qrcodegen_getSize(qrcode); + int border = 2; + unsigned char num = 0; + + for (int y = -border; y < size + border; y += 2) { + for (int x = -border; x < size + border; x += 2) { + num = 0; + if (qrcodegen_getModule(qrcode, x, y)) { + num |= 1 << 0; + } + if ((x < size + border) && qrcodegen_getModule(qrcode, x + 1, y)) { + num |= 1 << 1; + } + if ((y < size + border) && qrcodegen_getModule(qrcode, x, y + 1)) { + num |= 1 << 2; + } + if ((x < size + border) && (y < size + border) && qrcodegen_getModule(qrcode, x + 1, y + 1)) { + num |= 1 << 3; + } + printf("%s", lt[num]); + } + printf("\n"); + } + printf("\n"); +} + +esp_err_t esp_qrcode_generate(esp_qrcode_config_t *cfg, const char *text) +{ + enum qrcodegen_Ecc ecc_lvl; + uint8_t *qrcode, *tempbuf; + esp_err_t err = ESP_FAIL; + + qrcode = calloc(1, qrcodegen_BUFFER_LEN_FOR_VERSION(cfg->max_qrcode_version)); + if (!qrcode) { + return ESP_ERR_NO_MEM; + } + + tempbuf = calloc(1, qrcodegen_BUFFER_LEN_FOR_VERSION(cfg->max_qrcode_version)); + if (!tempbuf) { + free(qrcode); + return ESP_ERR_NO_MEM; + } + + switch (cfg->qrcode_ecc_level) { + case ESP_QRCODE_ECC_LOW: + ecc_lvl = qrcodegen_Ecc_LOW; + break; + case ESP_QRCODE_ECC_MED: + ecc_lvl = qrcodegen_Ecc_MEDIUM; + break; + case ESP_QRCODE_ECC_QUART: + ecc_lvl = qrcodegen_Ecc_QUARTILE; + break; + case ESP_QRCODE_ECC_HIGH: + ecc_lvl = qrcodegen_Ecc_HIGH; + break; + default: + ecc_lvl = qrcodegen_Ecc_LOW; + break; + } + + ESP_LOGI(TAG, "Encoding below text with ECC LVL %d & QR Code Version %d", + ecc_lvl, cfg->max_qrcode_version); + ESP_LOGI(TAG, "%s", text); + // Make and print the QR Code symbol + bool ok = qrcodegen_encodeText(text, tempbuf, qrcode, ecc_lvl, + qrcodegen_VERSION_MIN, cfg->max_qrcode_version, + qrcodegen_Mask_AUTO, true); + if (ok && cfg->display_func) { + cfg->display_func((esp_qrcode_handle_t)qrcode); + err = ESP_OK; + } + + free(qrcode); + free(tempbuf); + return err; +} diff --git a/RainMaker_Table-Lights/managed_components/espressif__qrcode/esp_qrcode_wrapper.c b/RainMaker_Table-Lights/managed_components/espressif__qrcode/esp_qrcode_wrapper.c new file mode 100644 index 000000000..fb40c4fe7 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__qrcode/esp_qrcode_wrapper.c @@ -0,0 +1,21 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include "qrcodegen.h" +#include "qrcode.h" + +int esp_qrcode_get_size(esp_qrcode_handle_t qrcode) +{ + return qrcodegen_getSize(qrcode); +} + +bool esp_qrcode_get_module(esp_qrcode_handle_t qrcode, int x, int y) +{ + return qrcodegen_getModule(qrcode, x, y); +} diff --git a/RainMaker_Table-Lights/managed_components/espressif__qrcode/idf_component.yml b/RainMaker_Table-Lights/managed_components/espressif__qrcode/idf_component.yml new file mode 100644 index 000000000..6e714a58b --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__qrcode/idf_component.yml @@ -0,0 +1,3 @@ +description: QR Code generator +url: https://github.com/espressif/idf-extra-components/tree/master/qrcode +version: 0.1.0~2 diff --git a/RainMaker_Table-Lights/managed_components/espressif__qrcode/include/qrcode.h b/RainMaker_Table-Lights/managed_components/espressif__qrcode/include/qrcode.h new file mode 100644 index 000000000..4957a21e9 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__qrcode/include/qrcode.h @@ -0,0 +1,97 @@ +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief QR Code handle used by the display function + */ +typedef const uint8_t *esp_qrcode_handle_t; + +/** + * @brief QR Code configuration options + */ +typedef struct { + void (*display_func)(esp_qrcode_handle_t qrcode); /**< Function called for displaying the QR Code after encoding is complete */ + int max_qrcode_version; /**< Max QR Code Version to be used. Range: 2 - 40 */ + int qrcode_ecc_level; /**< Error Correction Level for QR Code */ +} esp_qrcode_config_t; + +/** + * @brief Error Correction Level in a QR Code Symbol + */ +enum { + ESP_QRCODE_ECC_LOW, /**< QR Code Error Tolerance of 7% */ + ESP_QRCODE_ECC_MED, /**< QR Code Error Tolerance of 15% */ + ESP_QRCODE_ECC_QUART, /**< QR Code Error Tolerance of 25% */ + ESP_QRCODE_ECC_HIGH /**< QR Code Error Tolerance of 30% */ +}; + +/** + * @brief Encodes the given string into a QR Code and calls the display function + * + * @attention 1. Can successfully encode a UTF-8 string of up to 2953 bytes or an alphanumeric + * string of up to 4296 characters or any digit string of up to 7089 characters + * + * @param cfg Configuration used for QR Code encoding. + * @param text String to encode into a QR Code. + * + * @return + * - ESP_OK: succeed + * - ESP_FAIL: Failed to encode string into a QR Code + * - ESP_ERR_NO_MEM: Failed to allocate buffer for given max_qrcode_version + */ +esp_err_t esp_qrcode_generate(esp_qrcode_config_t *cfg, const char *text); + +/** + * @brief Displays QR Code on the console + * + * @param qrcode QR Code handle used by the display function. + */ +void esp_qrcode_print_console(esp_qrcode_handle_t qrcode); + +/** + * @brief Returns the side length of the given QR Code + * + * @param qrcode QR Code handle used by the display function. + * + * @return + * - val[21, 177]: Side length of QR Code + */ +int esp_qrcode_get_size(esp_qrcode_handle_t qrcode); + +/** + * @brief Returns the Pixel value for the given coordinates + * False indicates White and True indicates Black + * + * @attention 1. Coordinates for top left corner are (x=0, y=0) + * @attention 2. For out of bound coordinates false (White) is returned + * + * @param qrcode QR Code handle used by the display function. + * @param x X-Coordinate of QR Code module + * @param y Y-Coordinate of QR Code module + * + * @return + * - true: (x, y) Pixel is Black + * - false: (x, y) Pixel is White + */ +bool esp_qrcode_get_module(esp_qrcode_handle_t qrcode, int x, int y); + +#define ESP_QRCODE_CONFIG_DEFAULT() (esp_qrcode_config_t) { \ + .display_func = esp_qrcode_print_console, \ + .max_qrcode_version = 10, \ + .qrcode_ecc_level = ESP_QRCODE_ECC_LOW, \ +} + +#ifdef __cplusplus +} +#endif diff --git a/RainMaker_Table-Lights/managed_components/espressif__qrcode/qrcodegen.c b/RainMaker_Table-Lights/managed_components/espressif__qrcode/qrcodegen.c new file mode 100644 index 000000000..b97d14a72 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__qrcode/qrcodegen.c @@ -0,0 +1,1124 @@ +/* + * QR Code generator library (C) + * + * Copyright (c) Project Nayuki. (MIT License) + * https://www.nayuki.io/page/qr-code-generator-library + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * - The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * - The Software is provided "as is", without warranty of any kind, express or + * implied, including but not limited to the warranties of merchantability, + * fitness for a particular purpose and noninfringement. In no event shall the + * authors or copyright holders be liable for any claim, damages or other + * liability, whether in an action of contract, tort or otherwise, arising from, + * out of or in connection with the Software or the use or other dealings in the + * Software. + */ + +#include +#include +#include +#include +#include "qrcodegen.h" + +#ifndef QRCODEGEN_TEST +#define testable static // Keep functions private +#else +#define testable // Expose private functions +#endif + + +/*---- Forward declarations for private functions ----*/ + +// Regarding all public and private functions defined in this source file: +// - They require all pointer/array arguments to be not null unless the array length is zero. +// - They only read input scalar/array arguments, write to output pointer/array +// arguments, and return scalar values; they are "pure" functions. +// - They don't read mutable global variables or write to any global variables. +// - They don't perform I/O, read the clock, print to console, etc. +// - They allocate a small and constant amount of stack memory. +// - They don't allocate or free any memory on the heap. +// - They don't recurse or mutually recurse. All the code +// could be inlined into the top-level public functions. +// - They run in at most quadratic time with respect to input arguments. +// Most functions run in linear time, and some in constant time. +// There are no unbounded loops or non-obvious termination conditions. +// - They are completely thread-safe if the caller does not give the +// same writable buffer to concurrent calls to these functions. + +testable void appendBitsToBuffer(unsigned int val, int numBits, uint8_t buffer[], int *bitLen); + +testable void addEccAndInterleave(uint8_t data[], int version, enum qrcodegen_Ecc ecl, uint8_t result[]); +testable int getNumDataCodewords(int version, enum qrcodegen_Ecc ecl); +testable int getNumRawDataModules(int ver); + +testable void reedSolomonComputeDivisor(int degree, uint8_t result[]); +testable void reedSolomonComputeRemainder(const uint8_t data[], int dataLen, + const uint8_t generator[], int degree, uint8_t result[]); +testable uint8_t reedSolomonMultiply(uint8_t x, uint8_t y); + +testable void initializeFunctionModules(int version, uint8_t qrcode[]); +static void drawWhiteFunctionModules(uint8_t qrcode[], int version); +static void drawFormatBits(enum qrcodegen_Ecc ecl, enum qrcodegen_Mask mask, uint8_t qrcode[]); +testable int getAlignmentPatternPositions(int version, uint8_t result[7]); +static void fillRectangle(int left, int top, int width, int height, uint8_t qrcode[]); + +static void drawCodewords(const uint8_t data[], int dataLen, uint8_t qrcode[]); +static void applyMask(const uint8_t functionModules[], uint8_t qrcode[], enum qrcodegen_Mask mask); +static long getPenaltyScore(const uint8_t qrcode[]); +static int finderPenaltyCountPatterns(const int runHistory[7], int qrsize); +static int finderPenaltyTerminateAndCount(bool currentRunColor, int currentRunLength, int runHistory[7], int qrsize); +static void finderPenaltyAddHistory(int currentRunLength, int runHistory[7]); + +testable bool getModule(const uint8_t qrcode[], int x, int y); +testable void setModule(uint8_t qrcode[], int x, int y, bool isBlack); +testable void setModuleBounded(uint8_t qrcode[], int x, int y, bool isBlack); +static bool getBit(int x, int i); + +testable int calcSegmentBitLength(enum qrcodegen_Mode mode, size_t numChars); +testable int getTotalBits(const struct qrcodegen_Segment segs[], size_t len, int version); +static int numCharCountBits(enum qrcodegen_Mode mode, int version); + + + +/*---- Private tables of constants ----*/ + +// The set of all legal characters in alphanumeric mode, where each character +// value maps to the index in the string. For checking text and encoding segments. +static const char *ALPHANUMERIC_CHARSET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:"; + +// For generating error correction codes. +testable const int8_t ECC_CODEWORDS_PER_BLOCK[4][41] = { + // Version: (note that index 0 is for padding, and is set to an illegal value) + //0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 Error correction level + {-1, 7, 10, 15, 20, 26, 18, 20, 24, 30, 18, 20, 24, 26, 30, 22, 24, 28, 30, 28, 28, 28, 28, 30, 30, 26, 28, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30}, // Low + {-1, 10, 16, 26, 18, 24, 16, 18, 22, 22, 26, 30, 22, 22, 24, 24, 28, 28, 26, 26, 26, 26, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28}, // Medium + {-1, 13, 22, 18, 26, 18, 24, 18, 22, 20, 24, 28, 26, 24, 20, 30, 24, 28, 28, 26, 30, 28, 30, 30, 30, 30, 28, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30}, // Quartile + {-1, 17, 28, 22, 16, 22, 28, 26, 26, 24, 28, 24, 28, 22, 24, 24, 30, 28, 28, 26, 28, 30, 24, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30}, // High +}; + +#define qrcodegen_REED_SOLOMON_DEGREE_MAX 30 // Based on the table above + +// For generating error correction codes. +testable const int8_t NUM_ERROR_CORRECTION_BLOCKS[4][41] = { + // Version: (note that index 0 is for padding, and is set to an illegal value) + //0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40 Error correction level + {-1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 4, 4, 4, 4, 4, 6, 6, 6, 6, 7, 8, 8, 9, 9, 10, 12, 12, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, 21, 22, 24, 25}, // Low + {-1, 1, 1, 1, 2, 2, 4, 4, 4, 5, 5, 5, 8, 9, 9, 10, 10, 11, 13, 14, 16, 17, 17, 18, 20, 21, 23, 25, 26, 28, 29, 31, 33, 35, 37, 38, 40, 43, 45, 47, 49}, // Medium + {-1, 1, 1, 2, 2, 4, 4, 6, 6, 8, 8, 8, 10, 12, 16, 12, 17, 16, 18, 21, 20, 23, 23, 25, 27, 29, 34, 34, 35, 38, 40, 43, 45, 48, 51, 53, 56, 59, 62, 65, 68}, // Quartile + {-1, 1, 1, 2, 4, 4, 4, 5, 6, 8, 8, 11, 11, 16, 16, 18, 16, 19, 21, 25, 25, 25, 34, 30, 32, 35, 37, 40, 42, 45, 48, 51, 54, 57, 60, 63, 66, 70, 74, 77, 81}, // High +}; + +// For automatic mask pattern selection. +static const int PENALTY_N1 = 3; +static const int PENALTY_N2 = 3; +static const int PENALTY_N3 = 40; +static const int PENALTY_N4 = 10; + + + +/*---- High-level QR Code encoding functions ----*/ + +// Public function - see documentation comment in header file. +bool qrcodegen_encodeText(const char *text, uint8_t tempBuffer[], uint8_t qrcode[], + enum qrcodegen_Ecc ecl, int minVersion, int maxVersion, enum qrcodegen_Mask mask, bool boostEcl) +{ + + size_t textLen = strlen(text); + if (textLen == 0) { + return qrcodegen_encodeSegmentsAdvanced(NULL, 0, ecl, minVersion, maxVersion, mask, boostEcl, tempBuffer, qrcode); + } + size_t bufLen = (size_t)qrcodegen_BUFFER_LEN_FOR_VERSION(maxVersion); + + struct qrcodegen_Segment seg; + if (qrcodegen_isNumeric(text)) { + if (qrcodegen_calcSegmentBufferSize(qrcodegen_Mode_NUMERIC, textLen) > bufLen) { + goto fail; + } + seg = qrcodegen_makeNumeric(text, tempBuffer); + } else if (qrcodegen_isAlphanumeric(text)) { + if (qrcodegen_calcSegmentBufferSize(qrcodegen_Mode_ALPHANUMERIC, textLen) > bufLen) { + goto fail; + } + seg = qrcodegen_makeAlphanumeric(text, tempBuffer); + } else { + if (textLen > bufLen) { + goto fail; + } + for (size_t i = 0; i < textLen; i++) { + tempBuffer[i] = (uint8_t)text[i]; + } + seg.mode = qrcodegen_Mode_BYTE; + seg.bitLength = calcSegmentBitLength(seg.mode, textLen); + if (seg.bitLength == -1) { + goto fail; + } + seg.numChars = (int)textLen; + seg.data = tempBuffer; + } + return qrcodegen_encodeSegmentsAdvanced(&seg, 1, ecl, minVersion, maxVersion, mask, boostEcl, tempBuffer, qrcode); + +fail: + qrcode[0] = 0; // Set size to invalid value for safety + return false; +} + + +// Public function - see documentation comment in header file. +bool qrcodegen_encodeBinary(uint8_t dataAndTemp[], size_t dataLen, uint8_t qrcode[], + enum qrcodegen_Ecc ecl, int minVersion, int maxVersion, enum qrcodegen_Mask mask, bool boostEcl) +{ + + struct qrcodegen_Segment seg; + seg.mode = qrcodegen_Mode_BYTE; + seg.bitLength = calcSegmentBitLength(seg.mode, dataLen); + if (seg.bitLength == -1) { + qrcode[0] = 0; // Set size to invalid value for safety + return false; + } + seg.numChars = (int)dataLen; + seg.data = dataAndTemp; + return qrcodegen_encodeSegmentsAdvanced(&seg, 1, ecl, minVersion, maxVersion, mask, boostEcl, dataAndTemp, qrcode); +} + + +// Appends the given number of low-order bits of the given value to the given byte-based +// bit buffer, increasing the bit length. Requires 0 <= numBits <= 16 and val < 2^numBits. +testable void appendBitsToBuffer(unsigned int val, int numBits, uint8_t buffer[], int *bitLen) +{ + assert(0 <= numBits && numBits <= 16 && (unsigned long)val >> numBits == 0); + for (int i = numBits - 1; i >= 0; i--, (*bitLen)++) { + buffer[*bitLen >> 3] |= ((val >> i) & 1) << (7 - (*bitLen & 7)); + } +} + + + +/*---- Low-level QR Code encoding functions ----*/ + +// Public function - see documentation comment in header file. +bool qrcodegen_encodeSegments(const struct qrcodegen_Segment segs[], size_t len, + enum qrcodegen_Ecc ecl, uint8_t tempBuffer[], uint8_t qrcode[]) +{ + return qrcodegen_encodeSegmentsAdvanced(segs, len, ecl, + qrcodegen_VERSION_MIN, qrcodegen_VERSION_MAX, qrcodegen_Mask_AUTO, true, tempBuffer, qrcode); +} + + +// Public function - see documentation comment in header file. +bool qrcodegen_encodeSegmentsAdvanced(const struct qrcodegen_Segment segs[], size_t len, enum qrcodegen_Ecc ecl, + int minVersion, int maxVersion, enum qrcodegen_Mask mask, bool boostEcl, uint8_t tempBuffer[], uint8_t qrcode[]) +{ + assert(segs != NULL || len == 0); + assert(qrcodegen_VERSION_MIN <= minVersion && minVersion <= maxVersion && maxVersion <= qrcodegen_VERSION_MAX); + assert(0 <= (int)ecl && (int)ecl <= 3 && -1 <= (int)mask && (int)mask <= 7); + + // Find the minimal version number to use + int version, dataUsedBits; + for (version = minVersion; ; version++) { + int dataCapacityBits = getNumDataCodewords(version, ecl) * 8; // Number of data bits available + dataUsedBits = getTotalBits(segs, len, version); + if (dataUsedBits != -1 && dataUsedBits <= dataCapacityBits) { + break; // This version number is found to be suitable + } + if (version >= maxVersion) { // All versions in the range could not fit the given data + qrcode[0] = 0; // Set size to invalid value for safety + return false; + } + } + assert(dataUsedBits != -1); + + // Increase the error correction level while the data still fits in the current version number + for (int i = (int)qrcodegen_Ecc_MEDIUM; i <= (int)qrcodegen_Ecc_HIGH; i++) { // From low to high + if (boostEcl && dataUsedBits <= getNumDataCodewords(version, (enum qrcodegen_Ecc)i) * 8) { + ecl = (enum qrcodegen_Ecc)i; + } + } + + // Concatenate all segments to create the data bit string + memset(qrcode, 0, (size_t)qrcodegen_BUFFER_LEN_FOR_VERSION(version) * sizeof(qrcode[0])); + int bitLen = 0; + for (size_t i = 0; i < len; i++) { + const struct qrcodegen_Segment *seg = &segs[i]; + appendBitsToBuffer((unsigned int)seg->mode, 4, qrcode, &bitLen); + appendBitsToBuffer((unsigned int)seg->numChars, numCharCountBits(seg->mode, version), qrcode, &bitLen); + for (int j = 0; j < seg->bitLength; j++) { + int bit = (seg->data[j >> 3] >> (7 - (j & 7))) & 1; + appendBitsToBuffer((unsigned int)bit, 1, qrcode, &bitLen); + } + } + assert(bitLen == dataUsedBits); + + // Add terminator and pad up to a byte if applicable + int dataCapacityBits = getNumDataCodewords(version, ecl) * 8; + assert(bitLen <= dataCapacityBits); + int terminatorBits = dataCapacityBits - bitLen; + if (terminatorBits > 4) { + terminatorBits = 4; + } + appendBitsToBuffer(0, terminatorBits, qrcode, &bitLen); + appendBitsToBuffer(0, (8 - bitLen % 8) % 8, qrcode, &bitLen); + assert(bitLen % 8 == 0); + + // Pad with alternating bytes until data capacity is reached + for (uint8_t padByte = 0xEC; bitLen < dataCapacityBits; padByte ^= 0xEC ^ 0x11) { + appendBitsToBuffer(padByte, 8, qrcode, &bitLen); + } + + // Draw function and data codeword modules + addEccAndInterleave(qrcode, version, ecl, tempBuffer); + initializeFunctionModules(version, qrcode); + drawCodewords(tempBuffer, getNumRawDataModules(version) / 8, qrcode); + drawWhiteFunctionModules(qrcode, version); + initializeFunctionModules(version, tempBuffer); + + // Handle masking + if (mask == qrcodegen_Mask_AUTO) { // Automatically choose best mask + long minPenalty = LONG_MAX; + for (int i = 0; i < 8; i++) { + enum qrcodegen_Mask msk = (enum qrcodegen_Mask)i; + applyMask(tempBuffer, qrcode, msk); + drawFormatBits(ecl, msk, qrcode); + long penalty = getPenaltyScore(qrcode); + if (penalty < minPenalty) { + mask = msk; + minPenalty = penalty; + } + applyMask(tempBuffer, qrcode, msk); // Undoes the mask due to XOR + } + } + assert(0 <= (int)mask && (int)mask <= 7); + applyMask(tempBuffer, qrcode, mask); + drawFormatBits(ecl, mask, qrcode); + return true; +} + + + +/*---- Error correction code generation functions ----*/ + +// Appends error correction bytes to each block of the given data array, then interleaves +// bytes from the blocks and stores them in the result array. data[0 : dataLen] contains +// the input data. data[dataLen : rawCodewords] is used as a temporary work area and will +// be clobbered by this function. The final answer is stored in result[0 : rawCodewords]. +testable void addEccAndInterleave(uint8_t data[], int version, enum qrcodegen_Ecc ecl, uint8_t result[]) +{ + // Calculate parameter numbers + assert(0 <= (int)ecl && (int)ecl < 4 && qrcodegen_VERSION_MIN <= version && version <= qrcodegen_VERSION_MAX); + int numBlocks = NUM_ERROR_CORRECTION_BLOCKS[(int)ecl][version]; + int blockEccLen = ECC_CODEWORDS_PER_BLOCK [(int)ecl][version]; + int rawCodewords = getNumRawDataModules(version) / 8; + int dataLen = getNumDataCodewords(version, ecl); + int numShortBlocks = numBlocks - rawCodewords % numBlocks; + int shortBlockDataLen = rawCodewords / numBlocks - blockEccLen; + + // Split data into blocks, calculate ECC, and interleave + // (not concatenate) the bytes into a single sequence + uint8_t rsdiv[qrcodegen_REED_SOLOMON_DEGREE_MAX]; + reedSolomonComputeDivisor(blockEccLen, rsdiv); + const uint8_t *dat = data; + for (int i = 0; i < numBlocks; i++) { + int datLen = shortBlockDataLen + (i < numShortBlocks ? 0 : 1); + uint8_t *ecc = &data[dataLen]; // Temporary storage + reedSolomonComputeRemainder(dat, datLen, rsdiv, blockEccLen, ecc); + for (int j = 0, k = i; j < datLen; j++, k += numBlocks) { // Copy data + if (j == shortBlockDataLen) { + k -= numShortBlocks; + } + result[k] = dat[j]; + } + for (int j = 0, k = dataLen + i; j < blockEccLen; j++, k += numBlocks) { // Copy ECC + result[k] = ecc[j]; + } + dat += datLen; + } +} + + +// Returns the number of 8-bit codewords that can be used for storing data (not ECC), +// for the given version number and error correction level. The result is in the range [9, 2956]. +testable int getNumDataCodewords(int version, enum qrcodegen_Ecc ecl) +{ + int v = version, e = (int)ecl; + assert(0 <= e && e < 4); + return getNumRawDataModules(v) / 8 + - ECC_CODEWORDS_PER_BLOCK [e][v] + * NUM_ERROR_CORRECTION_BLOCKS[e][v]; +} + + +// Returns the number of data bits that can be stored in a QR Code of the given version number, after +// all function modules are excluded. This includes remainder bits, so it might not be a multiple of 8. +// The result is in the range [208, 29648]. This could be implemented as a 40-entry lookup table. +testable int getNumRawDataModules(int ver) +{ + assert(qrcodegen_VERSION_MIN <= ver && ver <= qrcodegen_VERSION_MAX); + int result = (16 * ver + 128) * ver + 64; + if (ver >= 2) { + int numAlign = ver / 7 + 2; + result -= (25 * numAlign - 10) * numAlign - 55; + if (ver >= 7) { + result -= 36; + } + } + assert(208 <= result && result <= 29648); + return result; +} + + + +/*---- Reed-Solomon ECC generator functions ----*/ + +// Computes a Reed-Solomon ECC generator polynomial for the given degree, storing in result[0 : degree]. +// This could be implemented as a lookup table over all possible parameter values, instead of as an algorithm. +testable void reedSolomonComputeDivisor(int degree, uint8_t result[]) +{ + assert(1 <= degree && degree <= qrcodegen_REED_SOLOMON_DEGREE_MAX); + // Polynomial coefficients are stored from highest to lowest power, excluding the leading term which is always 1. + // For example the polynomial x^3 + 255x^2 + 8x + 93 is stored as the uint8 array {255, 8, 93}. + memset(result, 0, (size_t)degree * sizeof(result[0])); + result[degree - 1] = 1; // Start off with the monomial x^0 + + // Compute the product polynomial (x - r^0) * (x - r^1) * (x - r^2) * ... * (x - r^{degree-1}), + // drop the highest monomial term which is always 1x^degree. + // Note that r = 0x02, which is a generator element of this field GF(2^8/0x11D). + uint8_t root = 1; + for (int i = 0; i < degree; i++) { + // Multiply the current product by (x - r^i) + for (int j = 0; j < degree; j++) { + result[j] = reedSolomonMultiply(result[j], root); + if (j + 1 < degree) { + result[j] ^= result[j + 1]; + } + } + root = reedSolomonMultiply(root, 0x02); + } +} + + +// Computes the Reed-Solomon error correction codeword for the given data and divisor polynomials. +// The remainder when data[0 : dataLen] is divided by divisor[0 : degree] is stored in result[0 : degree]. +// All polynomials are in big endian, and the generator has an implicit leading 1 term. +testable void reedSolomonComputeRemainder(const uint8_t data[], int dataLen, + const uint8_t generator[], int degree, uint8_t result[]) +{ + assert(1 <= degree && degree <= qrcodegen_REED_SOLOMON_DEGREE_MAX); + memset(result, 0, (size_t)degree * sizeof(result[0])); + for (int i = 0; i < dataLen; i++) { // Polynomial division + uint8_t factor = data[i] ^ result[0]; + memmove(&result[0], &result[1], (size_t)(degree - 1) * sizeof(result[0])); + result[degree - 1] = 0; + for (int j = 0; j < degree; j++) { + result[j] ^= reedSolomonMultiply(generator[j], factor); + } + } +} + +#undef qrcodegen_REED_SOLOMON_DEGREE_MAX + + +// Returns the product of the two given field elements modulo GF(2^8/0x11D). +// All inputs are valid. This could be implemented as a 256*256 lookup table. +testable uint8_t reedSolomonMultiply(uint8_t x, uint8_t y) +{ + // Russian peasant multiplication + uint8_t z = 0; + for (int i = 7; i >= 0; i--) { + z = (uint8_t)((z << 1) ^ ((z >> 7) * 0x11D)); + z ^= ((y >> i) & 1) * x; + } + return z; +} + + + +/*---- Drawing function modules ----*/ + +// Clears the given QR Code grid with white modules for the given +// version's size, then marks every function module as black. +testable void initializeFunctionModules(int version, uint8_t qrcode[]) +{ + // Initialize QR Code + int qrsize = version * 4 + 17; + memset(qrcode, 0, (size_t)((qrsize * qrsize + 7) / 8 + 1) * sizeof(qrcode[0])); + qrcode[0] = (uint8_t)qrsize; + + // Fill horizontal and vertical timing patterns + fillRectangle(6, 0, 1, qrsize, qrcode); + fillRectangle(0, 6, qrsize, 1, qrcode); + + // Fill 3 finder patterns (all corners except bottom right) and format bits + fillRectangle(0, 0, 9, 9, qrcode); + fillRectangle(qrsize - 8, 0, 8, 9, qrcode); + fillRectangle(0, qrsize - 8, 9, 8, qrcode); + + // Fill numerous alignment patterns + uint8_t alignPatPos[7]; + int numAlign = getAlignmentPatternPositions(version, alignPatPos); + for (int i = 0; i < numAlign; i++) { + for (int j = 0; j < numAlign; j++) { + // Don't draw on the three finder corners + if (!((i == 0 && j == 0) || (i == 0 && j == numAlign - 1) || (i == numAlign - 1 && j == 0))) { + fillRectangle(alignPatPos[i] - 2, alignPatPos[j] - 2, 5, 5, qrcode); + } + } + } + + // Fill version blocks + if (version >= 7) { + fillRectangle(qrsize - 11, 0, 3, 6, qrcode); + fillRectangle(0, qrsize - 11, 6, 3, qrcode); + } +} + + +// Draws white function modules and possibly some black modules onto the given QR Code, without changing +// non-function modules. This does not draw the format bits. This requires all function modules to be previously +// marked black (namely by initializeFunctionModules()), because this may skip redrawing black function modules. +static void drawWhiteFunctionModules(uint8_t qrcode[], int version) +{ + // Draw horizontal and vertical timing patterns + int qrsize = qrcodegen_getSize(qrcode); + for (int i = 7; i < qrsize - 7; i += 2) { + setModule(qrcode, 6, i, false); + setModule(qrcode, i, 6, false); + } + + // Draw 3 finder patterns (all corners except bottom right; overwrites some timing modules) + for (int dy = -4; dy <= 4; dy++) { + for (int dx = -4; dx <= 4; dx++) { + int dist = abs(dx); + if (abs(dy) > dist) { + dist = abs(dy); + } + if (dist == 2 || dist == 4) { + setModuleBounded(qrcode, 3 + dx, 3 + dy, false); + setModuleBounded(qrcode, qrsize - 4 + dx, 3 + dy, false); + setModuleBounded(qrcode, 3 + dx, qrsize - 4 + dy, false); + } + } + } + + // Draw numerous alignment patterns + uint8_t alignPatPos[7]; + int numAlign = getAlignmentPatternPositions(version, alignPatPos); + for (int i = 0; i < numAlign; i++) { + for (int j = 0; j < numAlign; j++) { + if ((i == 0 && j == 0) || (i == 0 && j == numAlign - 1) || (i == numAlign - 1 && j == 0)) { + continue; // Don't draw on the three finder corners + } + for (int dy = -1; dy <= 1; dy++) { + for (int dx = -1; dx <= 1; dx++) { + setModule(qrcode, alignPatPos[i] + dx, alignPatPos[j] + dy, dx == 0 && dy == 0); + } + } + } + } + + // Draw version blocks + if (version >= 7) { + // Calculate error correction code and pack bits + int rem = version; // version is uint6, in the range [7, 40] + for (int i = 0; i < 12; i++) { + rem = (rem << 1) ^ ((rem >> 11) * 0x1F25); + } + long bits = (long)version << 12 | rem; // uint18 + assert(bits >> 18 == 0); + + // Draw two copies + for (int i = 0; i < 6; i++) { + for (int j = 0; j < 3; j++) { + int k = qrsize - 11 + j; + setModule(qrcode, k, i, (bits & 1) != 0); + setModule(qrcode, i, k, (bits & 1) != 0); + bits >>= 1; + } + } + } +} + + +// Draws two copies of the format bits (with its own error correction code) based +// on the given mask and error correction level. This always draws all modules of +// the format bits, unlike drawWhiteFunctionModules() which might skip black modules. +static void drawFormatBits(enum qrcodegen_Ecc ecl, enum qrcodegen_Mask mask, uint8_t qrcode[]) +{ + // Calculate error correction code and pack bits + assert(0 <= (int)mask && (int)mask <= 7); + static const int table[] = {1, 0, 3, 2}; + int data = table[(int)ecl] << 3 | (int)mask; // errCorrLvl is uint2, mask is uint3 + int rem = data; + for (int i = 0; i < 10; i++) { + rem = (rem << 1) ^ ((rem >> 9) * 0x537); + } + int bits = (data << 10 | rem) ^ 0x5412; // uint15 + assert(bits >> 15 == 0); + + // Draw first copy + for (int i = 0; i <= 5; i++) { + setModule(qrcode, 8, i, getBit(bits, i)); + } + setModule(qrcode, 8, 7, getBit(bits, 6)); + setModule(qrcode, 8, 8, getBit(bits, 7)); + setModule(qrcode, 7, 8, getBit(bits, 8)); + for (int i = 9; i < 15; i++) { + setModule(qrcode, 14 - i, 8, getBit(bits, i)); + } + + // Draw second copy + int qrsize = qrcodegen_getSize(qrcode); + for (int i = 0; i < 8; i++) { + setModule(qrcode, qrsize - 1 - i, 8, getBit(bits, i)); + } + for (int i = 8; i < 15; i++) { + setModule(qrcode, 8, qrsize - 15 + i, getBit(bits, i)); + } + setModule(qrcode, 8, qrsize - 8, true); // Always black +} + + +// Calculates and stores an ascending list of positions of alignment patterns +// for this version number, returning the length of the list (in the range [0,7]). +// Each position is in the range [0,177), and are used on both the x and y axes. +// This could be implemented as lookup table of 40 variable-length lists of unsigned bytes. +testable int getAlignmentPatternPositions(int version, uint8_t result[7]) +{ + if (version == 1) { + return 0; + } + int numAlign = version / 7 + 2; + int step = (version == 32) ? 26 : + (version * 4 + numAlign * 2 + 1) / (numAlign * 2 - 2) * 2; + for (int i = numAlign - 1, pos = version * 4 + 10; i >= 1; i--, pos -= step) { + result[i] = (uint8_t)pos; + } + result[0] = 6; + return numAlign; +} + + +// Sets every pixel in the range [left : left + width] * [top : top + height] to black. +static void fillRectangle(int left, int top, int width, int height, uint8_t qrcode[]) +{ + for (int dy = 0; dy < height; dy++) { + for (int dx = 0; dx < width; dx++) { + setModule(qrcode, left + dx, top + dy, true); + } + } +} + + + +/*---- Drawing data modules and masking ----*/ + +// Draws the raw codewords (including data and ECC) onto the given QR Code. This requires the initial state of +// the QR Code to be black at function modules and white at codeword modules (including unused remainder bits). +static void drawCodewords(const uint8_t data[], int dataLen, uint8_t qrcode[]) +{ + int qrsize = qrcodegen_getSize(qrcode); + int i = 0; // Bit index into the data + // Do the funny zigzag scan + for (int right = qrsize - 1; right >= 1; right -= 2) { // Index of right column in each column pair + if (right == 6) { + right = 5; + } + for (int vert = 0; vert < qrsize; vert++) { // Vertical counter + for (int j = 0; j < 2; j++) { + int x = right - j; // Actual x coordinate + bool upward = ((right + 1) & 2) == 0; + int y = upward ? qrsize - 1 - vert : vert; // Actual y coordinate + if (!getModule(qrcode, x, y) && i < dataLen * 8) { + bool black = getBit(data[i >> 3], 7 - (i & 7)); + setModule(qrcode, x, y, black); + i++; + } + // If this QR Code has any remainder bits (0 to 7), they were assigned as + // 0/false/white by the constructor and are left unchanged by this method + } + } + } + assert(i == dataLen * 8); +} + + +// XORs the codeword modules in this QR Code with the given mask pattern. +// The function modules must be marked and the codeword bits must be drawn +// before masking. Due to the arithmetic of XOR, calling applyMask() with +// the same mask value a second time will undo the mask. A final well-formed +// QR Code needs exactly one (not zero, two, etc.) mask applied. +static void applyMask(const uint8_t functionModules[], uint8_t qrcode[], enum qrcodegen_Mask mask) +{ + assert(0 <= (int)mask && (int)mask <= 7); // Disallows qrcodegen_Mask_AUTO + int qrsize = qrcodegen_getSize(qrcode); + for (int y = 0; y < qrsize; y++) { + for (int x = 0; x < qrsize; x++) { + if (getModule(functionModules, x, y)) { + continue; + } + bool invert; + switch ((int)mask) { + case 0: invert = (x + y) % 2 == 0; break; + case 1: invert = y % 2 == 0; break; + case 2: invert = x % 3 == 0; break; + case 3: invert = (x + y) % 3 == 0; break; + case 4: invert = (x / 3 + y / 2) % 2 == 0; break; + case 5: invert = x * y % 2 + x * y % 3 == 0; break; + case 6: invert = (x * y % 2 + x * y % 3) % 2 == 0; break; + case 7: invert = ((x + y) % 2 + x * y % 3) % 2 == 0; break; + default: assert(false); return; + } + bool val = getModule(qrcode, x, y); + setModule(qrcode, x, y, val ^ invert); + } + } +} + + +// Calculates and returns the penalty score based on state of the given QR Code's current modules. +// This is used by the automatic mask choice algorithm to find the mask pattern that yields the lowest score. +static long getPenaltyScore(const uint8_t qrcode[]) +{ + int qrsize = qrcodegen_getSize(qrcode); + long result = 0; + + // Adjacent modules in row having same color, and finder-like patterns + for (int y = 0; y < qrsize; y++) { + bool runColor = false; + int runX = 0; + int runHistory[7] = {0}; + int padRun = qrsize; // Add white border to initial run + for (int x = 0; x < qrsize; x++) { + if (getModule(qrcode, x, y) == runColor) { + runX++; + if (runX == 5) { + result += PENALTY_N1; + } else if (runX > 5) { + result++; + } + } else { + finderPenaltyAddHistory(runX + padRun, runHistory); + padRun = 0; + if (!runColor) { + result += finderPenaltyCountPatterns(runHistory, qrsize) * PENALTY_N3; + } + runColor = getModule(qrcode, x, y); + runX = 1; + } + } + result += finderPenaltyTerminateAndCount(runColor, runX + padRun, runHistory, qrsize) * PENALTY_N3; + } + // Adjacent modules in column having same color, and finder-like patterns + for (int x = 0; x < qrsize; x++) { + bool runColor = false; + int runY = 0; + int runHistory[7] = {0}; + int padRun = qrsize; // Add white border to initial run + for (int y = 0; y < qrsize; y++) { + if (getModule(qrcode, x, y) == runColor) { + runY++; + if (runY == 5) { + result += PENALTY_N1; + } else if (runY > 5) { + result++; + } + } else { + finderPenaltyAddHistory(runY + padRun, runHistory); + padRun = 0; + if (!runColor) { + result += finderPenaltyCountPatterns(runHistory, qrsize) * PENALTY_N3; + } + runColor = getModule(qrcode, x, y); + runY = 1; + } + } + result += finderPenaltyTerminateAndCount(runColor, runY + padRun, runHistory, qrsize) * PENALTY_N3; + } + + // 2*2 blocks of modules having same color + for (int y = 0; y < qrsize - 1; y++) { + for (int x = 0; x < qrsize - 1; x++) { + bool color = getModule(qrcode, x, y); + if ( color == getModule(qrcode, x + 1, y) && + color == getModule(qrcode, x, y + 1) && + color == getModule(qrcode, x + 1, y + 1)) { + result += PENALTY_N2; + } + } + } + + // Balance of black and white modules + int black = 0; + for (int y = 0; y < qrsize; y++) { + for (int x = 0; x < qrsize; x++) { + if (getModule(qrcode, x, y)) { + black++; + } + } + } + int total = qrsize * qrsize; // Note that size is odd, so black/total != 1/2 + // Compute the smallest integer k >= 0 such that (45-5k)% <= black/total <= (55+5k)% + int k = (int)((labs(black * 20L - total * 10L) + total - 1) / total) - 1; + result += k * PENALTY_N4; + return result; +} + + +// Can only be called immediately after a white run is added, and +// returns either 0, 1, or 2. A helper function for getPenaltyScore(). +static int finderPenaltyCountPatterns(const int runHistory[7], int qrsize) +{ + int n = runHistory[1]; + assert(n <= qrsize * 3); + bool core = n > 0 && runHistory[2] == n && runHistory[3] == n * 3 && runHistory[4] == n && runHistory[5] == n; + // The maximum QR Code size is 177, hence the black run length n <= 177. + // Arithmetic is promoted to int, so n*4 will not overflow. + return (core && runHistory[0] >= n * 4 && runHistory[6] >= n ? 1 : 0) + + (core && runHistory[6] >= n * 4 && runHistory[0] >= n ? 1 : 0); +} + + +// Must be called at the end of a line (row or column) of modules. A helper function for getPenaltyScore(). +static int finderPenaltyTerminateAndCount(bool currentRunColor, int currentRunLength, int runHistory[7], int qrsize) +{ + if (currentRunColor) { // Terminate black run + finderPenaltyAddHistory(currentRunLength, runHistory); + currentRunLength = 0; + } + currentRunLength += qrsize; // Add white border to final run + finderPenaltyAddHistory(currentRunLength, runHistory); + return finderPenaltyCountPatterns(runHistory, qrsize); +} + + +// Pushes the given value to the front and drops the last value. A helper function for getPenaltyScore(). +static void finderPenaltyAddHistory(int currentRunLength, int runHistory[7]) +{ + memmove(&runHistory[1], &runHistory[0], 6 * sizeof(runHistory[0])); + runHistory[0] = currentRunLength; +} + + + +/*---- Basic QR Code information ----*/ + +// Public function - see documentation comment in header file. +int qrcodegen_getSize(const uint8_t qrcode[]) +{ + assert(qrcode != NULL); + int result = qrcode[0]; + assert((qrcodegen_VERSION_MIN * 4 + 17) <= result + && result <= (qrcodegen_VERSION_MAX * 4 + 17)); + return result; +} + + +// Public function - see documentation comment in header file. +bool qrcodegen_getModule(const uint8_t qrcode[], int x, int y) +{ + assert(qrcode != NULL); + int qrsize = qrcode[0]; + return (0 <= x && x < qrsize && 0 <= y && y < qrsize) && getModule(qrcode, x, y); +} + + +// Gets the module at the given coordinates, which must be in bounds. +testable bool getModule(const uint8_t qrcode[], int x, int y) +{ + int qrsize = qrcode[0]; + assert(21 <= qrsize && qrsize <= 177 && 0 <= x && x < qrsize && 0 <= y && y < qrsize); + int index = y * qrsize + x; + return getBit(qrcode[(index >> 3) + 1], index & 7); +} + + +// Sets the module at the given coordinates, which must be in bounds. +testable void setModule(uint8_t qrcode[], int x, int y, bool isBlack) +{ + int qrsize = qrcode[0]; + assert(21 <= qrsize && qrsize <= 177 && 0 <= x && x < qrsize && 0 <= y && y < qrsize); + int index = y * qrsize + x; + int bitIndex = index & 7; + int byteIndex = (index >> 3) + 1; + if (isBlack) { + qrcode[byteIndex] |= 1 << bitIndex; + } else { + qrcode[byteIndex] &= (1 << bitIndex) ^ 0xFF; + } +} + + +// Sets the module at the given coordinates, doing nothing if out of bounds. +testable void setModuleBounded(uint8_t qrcode[], int x, int y, bool isBlack) +{ + int qrsize = qrcode[0]; + if (0 <= x && x < qrsize && 0 <= y && y < qrsize) { + setModule(qrcode, x, y, isBlack); + } +} + + +// Returns true iff the i'th bit of x is set to 1. Requires x >= 0 and 0 <= i <= 14. +static bool getBit(int x, int i) +{ + return ((x >> i) & 1) != 0; +} + + + +/*---- Segment handling ----*/ + +// Public function - see documentation comment in header file. +bool qrcodegen_isAlphanumeric(const char *text) +{ + assert(text != NULL); + for (; *text != '\0'; text++) { + if (strchr(ALPHANUMERIC_CHARSET, *text) == NULL) { + return false; + } + } + return true; +} + + +// Public function - see documentation comment in header file. +bool qrcodegen_isNumeric(const char *text) +{ + assert(text != NULL); + for (; *text != '\0'; text++) { + if (*text < '0' || *text > '9') { + return false; + } + } + return true; +} + + +// Public function - see documentation comment in header file. +size_t qrcodegen_calcSegmentBufferSize(enum qrcodegen_Mode mode, size_t numChars) +{ + int temp = calcSegmentBitLength(mode, numChars); + if (temp == -1) { + return SIZE_MAX; + } + assert(0 <= temp && temp <= INT16_MAX); + return ((size_t)temp + 7) / 8; +} + + +// Returns the number of data bits needed to represent a segment +// containing the given number of characters using the given mode. Notes: +// - Returns -1 on failure, i.e. numChars > INT16_MAX or +// the number of needed bits exceeds INT16_MAX (i.e. 32767). +// - Otherwise, all valid results are in the range [0, INT16_MAX]. +// - For byte mode, numChars measures the number of bytes, not Unicode code points. +// - For ECI mode, numChars must be 0, and the worst-case number of bits is returned. +// An actual ECI segment can have shorter data. For non-ECI modes, the result is exact. +testable int calcSegmentBitLength(enum qrcodegen_Mode mode, size_t numChars) +{ + // All calculations are designed to avoid overflow on all platforms + if (numChars > (unsigned int)INT16_MAX) { + return -1; + } + long result = (long)numChars; + if (mode == qrcodegen_Mode_NUMERIC) { + result = (result * 10 + 2) / 3; // ceil(10/3 * n) + } else if (mode == qrcodegen_Mode_ALPHANUMERIC) { + result = (result * 11 + 1) / 2; // ceil(11/2 * n) + } else if (mode == qrcodegen_Mode_BYTE) { + result *= 8; + } else if (mode == qrcodegen_Mode_KANJI) { + result *= 13; + } else if (mode == qrcodegen_Mode_ECI && numChars == 0) { + result = 3 * 8; + } else { // Invalid argument + assert(false); + return -1; + } + assert(result >= 0); + if (result > INT16_MAX) { + return -1; + } + return (int)result; +} + + +// Public function - see documentation comment in header file. +struct qrcodegen_Segment qrcodegen_makeBytes(const uint8_t data[], size_t len, uint8_t buf[]) +{ + assert(data != NULL || len == 0); + struct qrcodegen_Segment result; + result.mode = qrcodegen_Mode_BYTE; + result.bitLength = calcSegmentBitLength(result.mode, len); + assert(result.bitLength != -1); + result.numChars = (int)len; + if (len > 0) { + memcpy(buf, data, len * sizeof(buf[0])); + } + result.data = buf; + return result; +} + + +// Public function - see documentation comment in header file. +struct qrcodegen_Segment qrcodegen_makeNumeric(const char *digits, uint8_t buf[]) +{ + assert(digits != NULL); + struct qrcodegen_Segment result; + size_t len = strlen(digits); + result.mode = qrcodegen_Mode_NUMERIC; + int bitLen = calcSegmentBitLength(result.mode, len); + assert(bitLen != -1); + result.numChars = (int)len; + if (bitLen > 0) { + memset(buf, 0, ((size_t)bitLen + 7) / 8 * sizeof(buf[0])); + } + result.bitLength = 0; + + unsigned int accumData = 0; + int accumCount = 0; + for (; *digits != '\0'; digits++) { + char c = *digits; + assert('0' <= c && c <= '9'); + accumData = accumData * 10 + (unsigned int)(c - '0'); + accumCount++; + if (accumCount == 3) { + appendBitsToBuffer(accumData, 10, buf, &result.bitLength); + accumData = 0; + accumCount = 0; + } + } + if (accumCount > 0) { // 1 or 2 digits remaining + appendBitsToBuffer(accumData, accumCount * 3 + 1, buf, &result.bitLength); + } + assert(result.bitLength == bitLen); + result.data = buf; + return result; +} + + +// Public function - see documentation comment in header file. +struct qrcodegen_Segment qrcodegen_makeAlphanumeric(const char *text, uint8_t buf[]) +{ + assert(text != NULL); + struct qrcodegen_Segment result; + size_t len = strlen(text); + result.mode = qrcodegen_Mode_ALPHANUMERIC; + int bitLen = calcSegmentBitLength(result.mode, len); + assert(bitLen != -1); + result.numChars = (int)len; + if (bitLen > 0) { + memset(buf, 0, ((size_t)bitLen + 7) / 8 * sizeof(buf[0])); + } + result.bitLength = 0; + + unsigned int accumData = 0; + int accumCount = 0; + for (; *text != '\0'; text++) { + const char *temp = strchr(ALPHANUMERIC_CHARSET, *text); + assert(temp != NULL); + accumData = accumData * 45 + (unsigned int)(temp - ALPHANUMERIC_CHARSET); + accumCount++; + if (accumCount == 2) { + appendBitsToBuffer(accumData, 11, buf, &result.bitLength); + accumData = 0; + accumCount = 0; + } + } + if (accumCount > 0) { // 1 character remaining + appendBitsToBuffer(accumData, 6, buf, &result.bitLength); + } + assert(result.bitLength == bitLen); + result.data = buf; + return result; +} + + +// Public function - see documentation comment in header file. +struct qrcodegen_Segment qrcodegen_makeEci(long assignVal, uint8_t buf[]) +{ + struct qrcodegen_Segment result; + result.mode = qrcodegen_Mode_ECI; + result.numChars = 0; + result.bitLength = 0; + if (assignVal < 0) { + assert(false); + } else if (assignVal < (1 << 7)) { + memset(buf, 0, 1 * sizeof(buf[0])); + appendBitsToBuffer((unsigned int)assignVal, 8, buf, &result.bitLength); + } else if (assignVal < (1 << 14)) { + memset(buf, 0, 2 * sizeof(buf[0])); + appendBitsToBuffer(2, 2, buf, &result.bitLength); + appendBitsToBuffer((unsigned int)assignVal, 14, buf, &result.bitLength); + } else if (assignVal < 1000000L) { + memset(buf, 0, 3 * sizeof(buf[0])); + appendBitsToBuffer(6, 3, buf, &result.bitLength); + appendBitsToBuffer((unsigned int)(assignVal >> 10), 11, buf, &result.bitLength); + appendBitsToBuffer((unsigned int)(assignVal & 0x3FF), 10, buf, &result.bitLength); + } else { + assert(false); + } + result.data = buf; + return result; +} + + +// Calculates the number of bits needed to encode the given segments at the given version. +// Returns a non-negative number if successful. Otherwise returns -1 if a segment has too +// many characters to fit its length field, or the total bits exceeds INT16_MAX. +testable int getTotalBits(const struct qrcodegen_Segment segs[], size_t len, int version) +{ + assert(segs != NULL || len == 0); + long result = 0; + for (size_t i = 0; i < len; i++) { + int numChars = segs[i].numChars; + int bitLength = segs[i].bitLength; + assert(0 <= numChars && numChars <= INT16_MAX); + assert(0 <= bitLength && bitLength <= INT16_MAX); + int ccbits = numCharCountBits(segs[i].mode, version); + assert(0 <= ccbits && ccbits <= 16); + if (numChars >= (1L << ccbits)) { + return -1; // The segment's length doesn't fit the field's bit width + } + result += 4L + ccbits + bitLength; + if (result > INT16_MAX) { + return -1; // The sum might overflow an int type + } + } + assert(0 <= result && result <= INT16_MAX); + return (int)result; +} + + +// Returns the bit width of the character count field for a segment in the given mode +// in a QR Code at the given version number. The result is in the range [0, 16]. +static int numCharCountBits(enum qrcodegen_Mode mode, int version) +{ + assert(qrcodegen_VERSION_MIN <= version && version <= qrcodegen_VERSION_MAX); + int i = (version + 7) / 17; + switch (mode) { + case qrcodegen_Mode_NUMERIC : { + static const int temp[] = {10, 12, 14}; + return temp[i]; + } + case qrcodegen_Mode_ALPHANUMERIC: { + static const int temp[] = { 9, 11, 13}; + return temp[i]; + } + case qrcodegen_Mode_BYTE : { + static const int temp[] = { 8, 16, 16}; + return temp[i]; + } + case qrcodegen_Mode_KANJI : { + static const int temp[] = { 8, 10, 12}; + return temp[i]; + } + case qrcodegen_Mode_ECI : return 0; + default: assert(false); return -1; // Dummy value + } +} diff --git a/RainMaker_Table-Lights/managed_components/espressif__qrcode/qrcodegen.h b/RainMaker_Table-Lights/managed_components/espressif__qrcode/qrcodegen.h new file mode 100644 index 000000000..835b56efd --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__qrcode/qrcodegen.h @@ -0,0 +1,311 @@ +/* + * QR Code generator library (C) + * + * Copyright (c) Project Nayuki. (MIT License) + * https://www.nayuki.io/page/qr-code-generator-library + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * - The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * - The Software is provided "as is", without warranty of any kind, express or + * implied, including but not limited to the warranties of merchantability, + * fitness for a particular purpose and noninfringement. In no event shall the + * authors or copyright holders be liable for any claim, damages or other + * liability, whether in an action of contract, tort or otherwise, arising from, + * out of or in connection with the Software or the use or other dealings in the + * Software. + */ + +#pragma once + +#include +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* + * This library creates QR Code symbols, which is a type of two-dimension barcode. + * Invented by Denso Wave and described in the ISO/IEC 18004 standard. + * A QR Code structure is an immutable square grid of black and white cells. + * The library provides functions to create a QR Code from text or binary data. + * The library covers the QR Code Model 2 specification, supporting all versions (sizes) + * from 1 to 40, all 4 error correction levels, and 4 character encoding modes. + * + * Ways to create a QR Code object: + * - High level: Take the payload data and call qrcodegen_encodeText() or qrcodegen_encodeBinary(). + * - Low level: Custom-make the list of segments and call + * qrcodegen_encodeSegments() or qrcodegen_encodeSegmentsAdvanced(). + * (Note that all ways require supplying the desired error correction level and various byte buffers.) + */ + + +/*---- Enum and struct types----*/ + +/* + * The error correction level in a QR Code symbol. + */ +enum qrcodegen_Ecc { + // Must be declared in ascending order of error protection + // so that an internal qrcodegen function works properly + qrcodegen_Ecc_LOW = 0, // The QR Code can tolerate about 7% erroneous codewords + qrcodegen_Ecc_MEDIUM, // The QR Code can tolerate about 15% erroneous codewords + qrcodegen_Ecc_QUARTILE, // The QR Code can tolerate about 25% erroneous codewords + qrcodegen_Ecc_HIGH, // The QR Code can tolerate about 30% erroneous codewords +}; + + +/* + * The mask pattern used in a QR Code symbol. + */ +enum qrcodegen_Mask { + // A special value to tell the QR Code encoder to + // automatically select an appropriate mask pattern + qrcodegen_Mask_AUTO = -1, + // The eight actual mask patterns + qrcodegen_Mask_0 = 0, + qrcodegen_Mask_1, + qrcodegen_Mask_2, + qrcodegen_Mask_3, + qrcodegen_Mask_4, + qrcodegen_Mask_5, + qrcodegen_Mask_6, + qrcodegen_Mask_7, +}; + + +/* + * Describes how a segment's data bits are interpreted. + */ +enum qrcodegen_Mode { + qrcodegen_Mode_NUMERIC = 0x1, + qrcodegen_Mode_ALPHANUMERIC = 0x2, + qrcodegen_Mode_BYTE = 0x4, + qrcodegen_Mode_KANJI = 0x8, + qrcodegen_Mode_ECI = 0x7, +}; + + +/* + * A segment of character/binary/control data in a QR Code symbol. + * The mid-level way to create a segment is to take the payload data + * and call a factory function such as qrcodegen_makeNumeric(). + * The low-level way to create a segment is to custom-make the bit buffer + * and initialize a qrcodegen_Segment struct with appropriate values. + * Even in the most favorable conditions, a QR Code can only hold 7089 characters of data. + * Any segment longer than this is meaningless for the purpose of generating QR Codes. + * Moreover, the maximum allowed bit length is 32767 because + * the largest QR Code (version 40) has 31329 modules. + */ +struct qrcodegen_Segment { + // The mode indicator of this segment. + enum qrcodegen_Mode mode; + + // The length of this segment's unencoded data. Measured in characters for + // numeric/alphanumeric/kanji mode, bytes for byte mode, and 0 for ECI mode. + // Always zero or positive. Not the same as the data's bit length. + int numChars; + + // The data bits of this segment, packed in bitwise big endian. + // Can be null if the bit length is zero. + uint8_t *data; + + // The number of valid data bits used in the buffer. Requires + // 0 <= bitLength <= 32767, and bitLength <= (capacity of data array) * 8. + // The character count (numChars) must agree with the mode and the bit buffer length. + int bitLength; +}; + + + +/*---- Macro constants and functions ----*/ + +#define qrcodegen_VERSION_MIN 1 // The minimum version number supported in the QR Code Model 2 standard +#define qrcodegen_VERSION_MAX 40 // The maximum version number supported in the QR Code Model 2 standard + +// Calculates the number of bytes needed to store any QR Code up to and including the given version number, +// as a compile-time constant. For example, 'uint8_t buffer[qrcodegen_BUFFER_LEN_FOR_VERSION(25)];' +// can store any single QR Code from version 1 to 25 (inclusive). The result fits in an int (or int16). +// Requires qrcodegen_VERSION_MIN <= n <= qrcodegen_VERSION_MAX. +#define qrcodegen_BUFFER_LEN_FOR_VERSION(n) ((((n) * 4 + 17) * ((n) * 4 + 17) + 7) / 8 + 1) + +// The worst-case number of bytes needed to store one QR Code, up to and including +// version 40. This value equals 3918, which is just under 4 kilobytes. +// Use this more convenient value to avoid calculating tighter memory bounds for buffers. +#define qrcodegen_BUFFER_LEN_MAX qrcodegen_BUFFER_LEN_FOR_VERSION(qrcodegen_VERSION_MAX) + + + +/*---- Functions (high level) to generate QR Codes ----*/ + +/* + * Encodes the given text string to a QR Code, returning true if encoding succeeded. + * If the data is too long to fit in any version in the given range + * at the given ECC level, then false is returned. + * - The input text must be encoded in UTF-8 and contain no NULs. + * - The variables ecl and mask must correspond to enum constant values. + * - Requires 1 <= minVersion <= maxVersion <= 40. + * - The arrays tempBuffer and qrcode must each have a length + * of at least qrcodegen_BUFFER_LEN_FOR_VERSION(maxVersion). + * - After the function returns, tempBuffer contains no useful data. + * - If successful, the resulting QR Code may use numeric, + * alphanumeric, or byte mode to encode the text. + * - In the most optimistic case, a QR Code at version 40 with low ECC + * can hold any UTF-8 string up to 2953 bytes, or any alphanumeric string + * up to 4296 characters, or any digit string up to 7089 characters. + * These numbers represent the hard upper limit of the QR Code standard. + * - Please consult the QR Code specification for information on + * data capacities per version, ECC level, and text encoding mode. + */ +bool qrcodegen_encodeText(const char *text, uint8_t tempBuffer[], uint8_t qrcode[], + enum qrcodegen_Ecc ecl, int minVersion, int maxVersion, enum qrcodegen_Mask mask, bool boostEcl); + + +/* + * Encodes the given binary data to a QR Code, returning true if encoding succeeded. + * If the data is too long to fit in any version in the given range + * at the given ECC level, then false is returned. + * - The input array range dataAndTemp[0 : dataLen] should normally be + * valid UTF-8 text, but is not required by the QR Code standard. + * - The variables ecl and mask must correspond to enum constant values. + * - Requires 1 <= minVersion <= maxVersion <= 40. + * - The arrays dataAndTemp and qrcode must each have a length + * of at least qrcodegen_BUFFER_LEN_FOR_VERSION(maxVersion). + * - After the function returns, the contents of dataAndTemp may have changed, + * and does not represent useful data anymore. + * - If successful, the resulting QR Code will use byte mode to encode the data. + * - In the most optimistic case, a QR Code at version 40 with low ECC can hold any byte + * sequence up to length 2953. This is the hard upper limit of the QR Code standard. + * - Please consult the QR Code specification for information on + * data capacities per version, ECC level, and text encoding mode. + */ +bool qrcodegen_encodeBinary(uint8_t dataAndTemp[], size_t dataLen, uint8_t qrcode[], + enum qrcodegen_Ecc ecl, int minVersion, int maxVersion, enum qrcodegen_Mask mask, bool boostEcl); + + +/*---- Functions (low level) to generate QR Codes ----*/ + +/* + * Renders a QR Code representing the given segments at the given error correction level. + * The smallest possible QR Code version is automatically chosen for the output. Returns true if + * QR Code creation succeeded, or false if the data is too long to fit in any version. The ECC level + * of the result may be higher than the ecl argument if it can be done without increasing the version. + * This function allows the user to create a custom sequence of segments that switches + * between modes (such as alphanumeric and byte) to encode text in less space. + * This is a low-level API; the high-level API is qrcodegen_encodeText() and qrcodegen_encodeBinary(). + * To save memory, the segments' data buffers can alias/overlap tempBuffer, and will + * result in them being clobbered, but the QR Code output will still be correct. + * But the qrcode array must not overlap tempBuffer or any segment's data buffer. + */ +bool qrcodegen_encodeSegments(const struct qrcodegen_Segment segs[], size_t len, + enum qrcodegen_Ecc ecl, uint8_t tempBuffer[], uint8_t qrcode[]); + + +/* + * Renders a QR Code representing the given segments with the given encoding parameters. + * Returns true if QR Code creation succeeded, or false if the data is too long to fit in the range of versions. + * The smallest possible QR Code version within the given range is automatically + * chosen for the output. Iff boostEcl is true, then the ECC level of the result + * may be higher than the ecl argument if it can be done without increasing the + * version. The mask is either between qrcodegen_Mask_0 to 7 to force that mask, or + * qrcodegen_Mask_AUTO to automatically choose an appropriate mask (which may be slow). + * This function allows the user to create a custom sequence of segments that switches + * between modes (such as alphanumeric and byte) to encode text in less space. + * This is a low-level API; the high-level API is qrcodegen_encodeText() and qrcodegen_encodeBinary(). + * To save memory, the segments' data buffers can alias/overlap tempBuffer, and will + * result in them being clobbered, but the QR Code output will still be correct. + * But the qrcode array must not overlap tempBuffer or any segment's data buffer. + */ +bool qrcodegen_encodeSegmentsAdvanced(const struct qrcodegen_Segment segs[], size_t len, enum qrcodegen_Ecc ecl, + int minVersion, int maxVersion, enum qrcodegen_Mask mask, bool boostEcl, uint8_t tempBuffer[], uint8_t qrcode[]); + + +/* + * Tests whether the given string can be encoded as a segment in alphanumeric mode. + * A string is encodable iff each character is in the following set: 0 to 9, A to Z + * (uppercase only), space, dollar, percent, asterisk, plus, hyphen, period, slash, colon. + */ +bool qrcodegen_isAlphanumeric(const char *text); + + +/* + * Tests whether the given string can be encoded as a segment in numeric mode. + * A string is encodable iff each character is in the range 0 to 9. + */ +bool qrcodegen_isNumeric(const char *text); + + +/* + * Returns the number of bytes (uint8_t) needed for the data buffer of a segment + * containing the given number of characters using the given mode. Notes: + * - Returns SIZE_MAX on failure, i.e. numChars > INT16_MAX or + * the number of needed bits exceeds INT16_MAX (i.e. 32767). + * - Otherwise, all valid results are in the range [0, ceil(INT16_MAX / 8)], i.e. at most 4096. + * - It is okay for the user to allocate more bytes for the buffer than needed. + * - For byte mode, numChars measures the number of bytes, not Unicode code points. + * - For ECI mode, numChars must be 0, and the worst-case number of bytes is returned. + * An actual ECI segment can have shorter data. For non-ECI modes, the result is exact. + */ +size_t qrcodegen_calcSegmentBufferSize(enum qrcodegen_Mode mode, size_t numChars); + + +/* + * Returns a segment representing the given binary data encoded in + * byte mode. All input byte arrays are acceptable. Any text string + * can be converted to UTF-8 bytes and encoded as a byte mode segment. + */ +struct qrcodegen_Segment qrcodegen_makeBytes(const uint8_t data[], size_t len, uint8_t buf[]); + + +/* + * Returns a segment representing the given string of decimal digits encoded in numeric mode. + */ +struct qrcodegen_Segment qrcodegen_makeNumeric(const char *digits, uint8_t buf[]); + + +/* + * Returns a segment representing the given text string encoded in alphanumeric mode. + * The characters allowed are: 0 to 9, A to Z (uppercase only), space, + * dollar, percent, asterisk, plus, hyphen, period, slash, colon. + */ +struct qrcodegen_Segment qrcodegen_makeAlphanumeric(const char *text, uint8_t buf[]); + + +/* + * Returns a segment representing an Extended Channel Interpretation + * (ECI) designator with the given assignment value. + */ +struct qrcodegen_Segment qrcodegen_makeEci(long assignVal, uint8_t buf[]); + + +/*---- Functions to extract raw data from QR Codes ----*/ + +/* + * Returns the side length of the given QR Code, assuming that encoding succeeded. + * The result is in the range [21, 177]. Note that the length of the array buffer + * is related to the side length - every 'uint8_t qrcode[]' must have length at least + * qrcodegen_BUFFER_LEN_FOR_VERSION(version), which equals ceil(size^2 / 8 + 1). + */ +int qrcodegen_getSize(const uint8_t qrcode[]); + + +/* + * Returns the color of the module (pixel) at the given coordinates, which is false + * for white or true for black. The top left corner has the coordinates (x=0, y=0). + * If the given coordinates are out of bounds, then false (white) is returned. + */ +bool qrcodegen_getModule(const uint8_t qrcode[], int x, int y); + + +#ifdef __cplusplus +} +#endif diff --git a/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/.component_hash b/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/.component_hash new file mode 100644 index 000000000..b903c0c8b --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/.component_hash @@ -0,0 +1 @@ +f1208cd1951f9308fd838d7af12de3522206cc77079f268629cd74bf9c6daea7 \ No newline at end of file diff --git a/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/CHECKSUMS.json b/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/CHECKSUMS.json new file mode 100644 index 000000000..629b35c4a --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/CHECKSUMS.json @@ -0,0 +1 @@ +{"version": "1.0", "algorithm": "sha256", "created_at": "2025-06-26T07:31:22.467519+00:00", "files": [{"path": "CMakeLists.txt", "size": 848, "hash": "b00eda8fa0b15720d0758b88b3ae9770237c3b7da038b8d78c653c570131c5ba"}, {"path": "Kconfig", "size": 7021, "hash": "e716589409507dd2dcc1d3fd0c8316e385caa9caff947f14414b89620d19b450"}, {"path": "LICENSE", "size": 11357, "hash": "c71d239df91726fc519c6eb72d318ec65820627232b2f796219e87dcf35d0ab4"}, {"path": "README.md", "size": 263, "hash": "31328ea0d3ba737dbfbb385f1ebdedc541d449e2e2c6e9553b4ba56af71d1bfe"}, {"path": "component.mk", "size": 139, "hash": "57d1101c6f6fd426ffb1846e170291b9dc87e5cdc29c2ea278dd1e8195ad74e5"}, {"path": "idf_component.yml", "size": 276, "hash": "fc80c605f58728f9c04d039b6c0a8e89bd92789dd5a99b9f6a90d59edd856480"}, {"path": "include/esp_rmaker_cmd_resp.h", "size": 6118, "hash": "4bb88f84c416b7429fce3312106232c38928d49d6b65e9bf64dbe03aa1e4431b"}, {"path": "include/esp_rmaker_common_console.h", "size": 857, "hash": "599ef7942735d160033e656a4d52311e77679c1b0c2a6bb7b0b14343d38da09a"}, {"path": "include/esp_rmaker_common_events.h", "size": 2436, "hash": "765ba1d5b6da5ec37a1e82a2e611967b4e23faf7990e2f61d5ae4a6f540b0a2b"}, {"path": "include/esp_rmaker_factory.h", "size": 2282, "hash": "568ca9d7c3edbb03a4bc4e804b77b8e713a56881fe46b55b50ec44de13d4897c"}, {"path": "include/esp_rmaker_mqtt_glue.h", "size": 5905, "hash": "ef066abca71027201eac6929553f4ee2f2370f47ce9ebf7362f30e0a3f976041"}, {"path": "include/esp_rmaker_utils.h", "size": 8082, "hash": "be2d6ea67d15ca89b5058618bae08442bb5d1e0a2a065cdb7a68b00754852519"}, {"path": "include/esp_rmaker_work_queue.h", "size": 2500, "hash": "2e54bb695f87523487f996351a2d11affc66f6920c37c73ae010a5a51b6eda3d"}, {"path": "src/cmd_resp.c", "size": 15074, "hash": "2551281636d6fd28e148ed8027dafd565f276d3155b34f8e45e5f80b4a814b4e"}, {"path": "src/create_APN3_PPI_string.c", "size": 8140, "hash": "eab27b5eb8ac03bb4c01022dd5e05038d1a0fd2a560dfffbcaf3eaa1846773e1"}, {"path": "src/factory.c", "size": 4465, "hash": "57c2bc0447c5ec76322955ad2e34ad17c60a27e0fb9702117053f60d09288f1a"}, {"path": "src/time.c", "size": 8817, "hash": "9c19e7613bf6c1cdc0db7a9369f2e9bf439f820306cac905a08b2af0f9014fe4"}, {"path": "src/timezone.c", "size": 21030, "hash": "2440efd33980593b4714dfa1eda7178db8494340bed2c9a8558e8d90875c12f4"}, {"path": "src/utils.c", "size": 5880, "hash": "e0ea46be44ef4a7ce99c43b5e95d6c0adc6b0ee1e702928cb3948172fd02266f"}, {"path": "src/work_queue.c", "size": 4814, "hash": "a8933f1a0a7da3d485c61da97536c819c85f372beb12f4a74f4db4e43673a0e9"}, {"path": "src/console/rmaker_common_cmds.c", "size": 11294, "hash": "f6dde3b130c4142d989d3d807b2a38e96cfc23a1423fd4e9cc184321707a7348"}, {"path": "src/console/rmaker_console.c", "size": 3205, "hash": "27df9d970a8f0b540eb01612e49804122bc3007e56842c9a540aef6fa9c514f1"}, {"path": "src/console/rmaker_console_internal.h", "size": 180, "hash": "8b837bc20258325abaf863c1e9cb3fb5560e3d97a213ec9596ec393cb6251ddd"}, {"path": "src/esp-mqtt/esp-mqtt-glue.c", "size": 24400, "hash": "82f051c4d1acc361ed4581ceb8ed315f79e66eb86b291ddf37fbd2cf6b2b1f7d"}]} \ No newline at end of file diff --git a/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/CMakeLists.txt b/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/CMakeLists.txt new file mode 100644 index 000000000..7212fb09a --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/CMakeLists.txt @@ -0,0 +1,23 @@ +set(srcs "src/work_queue.c" "src/factory.c" "src/time.c" "src/timezone.c" "src/utils.c" + "src/cmd_resp.c" "src/console/rmaker_common_cmds.c" "src/console/rmaker_console.c") + +set(priv_req mqtt nvs_flash console nvs_flash esp_wifi driver) +set(requires esp_event) + +# esp_timer component was introduced in v4.2 +if("${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}" VERSION_GREATER "4.1") + list(APPEND priv_req esp_timer) +endif() + +#if(CONFIG_ESP_RMAKER_LIB_ESP_MQTT) + list(APPEND srcs "src/esp-mqtt/esp-mqtt-glue.c") +#endif() +if(CONFIG_ESP_RMAKER_MQTT_SEND_USERNAME) + list(APPEND srcs "src/create_APN3_PPI_string.c") +endif() + +idf_component_register(SRCS ${srcs} + INCLUDE_DIRS "include" + PRIV_INCLUDE_DIRS + REQUIRES ${requires} + PRIV_REQUIRES ${priv_req}) diff --git a/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/Kconfig b/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/Kconfig new file mode 100644 index 000000000..4d109b889 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/Kconfig @@ -0,0 +1,180 @@ +menu "ESP RainMaker Common" + + choice ESP_RMAKER_MQTT_GLUE_LIB + bool "MQTT Library" + default ESP_RMAKER_LIB_ESP_MQTT + help + MQTT Library to be used + + config ESP_RMAKER_LIB_ESP_MQTT + bool "ESP-MQTT" + config ESP_RMAKER_LIB_AWS_IOT + bool "AWS-IOT" + endchoice + + config ESP_RMAKER_MQTT_GLUE_LIB + int + default 1 if ESP_RMAKER_LIB_ESP_MQTT + default 2 if ESP_RMAKER_LIB_AWS_IOT + + choice ESP_RMAKER_MQTT_PORT + bool "MQTT Port" + default ESP_RMAKER_MQTT_PORT_443 + help + ESP RainMaker MQTT Broker can be connected to either on Port 8883 or port 443. + Port 443 is recommended as it is generally not blocked by any firewalls, + since it is standard HTTPS port. + + config ESP_RMAKER_MQTT_PORT_443 + bool "443" + config ESP_RMAKER_MQTT_PORT_8883 + bool "8883" + endchoice + + config ESP_RMAKER_MQTT_PORT + int + default 1 if ESP_RMAKER_MQTT_PORT_443 + default 2 if ESP_RMAKER_MQTT_PORT_8883 + + config ESP_RMAKER_MQTT_PERSISTENT_SESSION + bool "Use Persisent MQTT sessions" + default n + help + Use persistent MQTT sessions. This improves reliability as QOS1 messages missed + out due to some network issue are received after the MQTT reconnects. The broker + caches messages for a period of upto 1 hour. However, a side-effect of this is that + messages can be received at unexpected time. Enable this option only if it suits + your use case. Please read MQTT specs to understand more about persistent sessions + and the cleanSession flag. + + config ESP_RMAKER_MQTT_SEND_USERNAME + bool "Send MQTT Username" + default y + help + Send a Username during MQTT Connect. This is generally required only for tracking + the MQTT client types, platform, SDK, etc. in AWS. + + config ESP_RMAKER_MQTT_PRODUCT_NAME + string "Product Name" + depends on ESP_RMAKER_MQTT_SEND_USERNAME + default "RMDev" + help + Approved AWS product name. Please get in touch with your Espressif/AWS representative for more info. + + config ESP_RMAKER_MQTT_PRODUCT_VERSION + string "Product Version" + depends on ESP_RMAKER_MQTT_SEND_USERNAME + default "1x0" + help + Approved AWS product version. Please get in touch with your Espressif/AWS representative for more info. + + config ESP_RMAKER_MQTT_PRODUCT_SKU + string "Product SKU" + depends on ESP_RMAKER_MQTT_SEND_USERNAME + default "EX00" + help + Product SKU. Please get in touch with your Espressif/AWS representative for more info. + + config ESP_RMAKER_MQTT_USE_CERT_BUNDLE + bool "Use Certificate Bundle" + default y + help + Use Certificate Bundle for server authentication. Enabling this is recommended to safeguard + against any changes in the server certificates in future. This has an impact on the binary + size as well as heap requirement. + + config ESP_RMAKER_MAX_MQTT_SUBSCRIPTIONS + int "Maximum number of MQTT Subscriptions" + default 10 + help + This value controls the maximum number of topics that the device can subscribe to. + + config ESP_RMAKER_MQTT_KEEP_ALIVE_INTERVAL + int "MQTT Keep Alive Internal" + default 120 + range 30 1200 + help + MQTT Keep Alive Interval. Note that it can take upto 1.5x of keep alive interval for a device + to be reported by offline by the MQTT Broker. Change this only if required. + + choice ESP_RMAKER_NETWORK_PROTOCOL_TYPE + prompt "ESP RainMaker Network Type" + default ESP_RMAKER_NETWORK_OVER_WIFI + help + Network protocol type over which the ESP RainMaker will run. + + config ESP_RMAKER_NETWORK_OVER_WIFI + depends on ESP_WIFI_ENABLED || ESP32_WIFI_ENABLED || ESP_WIFI_REMOTE_ENABLED + bool "ESP RainMaker over Wi-Fi" + + config ESP_RMAKER_NETWORK_OVER_THREAD + depends on OPENTHREAD_ENABLED + bool "ESP RainMaker over Thread" + endchoice + + config ESP_RMAKER_WORK_QUEUE_TASK_STACK + int "ESP RainMaker Work Queue Task stack" + default 5120 + help + Stack size for the ESP RainMaker Work Queue Task. + + config ESP_RMAKER_WORK_QUEUE_TASK_PRIORITY + int "ESP RainMaker Work Queue Task priority" + default 5 + help + Priority for the ESP RainMaker Work Queue Task. Not recommended to be changed + unless you really need it. + + config ESP_RMAKER_FACTORY_PARTITION_NAME + string "ESP RainMaker Factory Partition Name" + default "fctry" + help + Factory NVS Partition name which will have the MQTT connectivity credentials. + + config ESP_RMAKER_FACTORY_NAMESPACE + string "ESP RainMaker Factory Namespace" + default "rmaker_creds" + help + Namespace in the Factory NVS Partition name which will have the MQTT + connectivity credentials. + + config ESP_RMAKER_ENCRYPT_FACTORY_PARTITION + bool "Encrypt Rainmaker Factory partition" + default false + depends on NVS_ENCRYPTION + help + Enable this option if the factory partition is pre-encrypted before flashing and the encryption keys + are flashed in partition with subtype nvs_keys specified by CONFIG_ESP_RMAKER_FACTORY_NVS_KEYS_PARTITION_NAME. + If an unencrypted factory partition is flashed, the device would not be able to read its data and + the partition would be considered empty. + If nvs encryption keys are not flashed onto device, they would be auto-generated and any previous data + in nvs/factory partition would become invalid. + + config ESP_RMAKER_FACTORY_NVS_KEYS_PARTITION_NAME + string "ESP Rainmaker Factory NVS keys partition label" + default "nvs_key" + depends on ESP_RMAKER_ENCRYPT_FACTORY_PARTITION + help + Label of the partition of subtype "nvs_keys" used for encrypting/decrypting Rainmaker factory partition. + + config ESP_RMAKER_DEF_TIMEZONE + string "Default Timezone" + default "Asia/Shanghai" + help + Default Timezone to use. Eg. "Asia/Shanghai", "America/Los_Angeles". + Check documentation for complete list of valid values. This value + will be used only if no timezone is set using the C APIs. + + config ESP_RMAKER_SNTP_SERVER_NAME + string "ESP RainMaker SNTP Server Name" + default "pool.ntp.org" + help + Default SNTP Server which is used for time synchronization. + + config ESP_RMAKER_MAX_COMMANDS + int "Maximum commands supported for command-response" + default 10 + help + Maximum number of commands supported by the command-response framework + +endmenu diff --git a/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/LICENSE b/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/LICENSE new file mode 100644 index 000000000..261eeb9e9 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/README.md b/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/README.md new file mode 100644 index 000000000..0db26c836 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/README.md @@ -0,0 +1,9 @@ +# ESP RainMaker Common modules + +This component consists of some common modules used by ESP RainMaker and ESP RainMaker Diagnostics repos. +Currently, it consists of +- MQTT glue layer +- Timing APIs (SNTP helpers, timezone, etc.) +- Factory NVS helpers +- Work Queue + diff --git a/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/component.mk b/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/component.mk new file mode 100644 index 000000000..978b48b4d --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/component.mk @@ -0,0 +1,5 @@ +COMPONENT_ADD_INCLUDEDIRS := include +COMPONENT_SRCDIRS := src +ifdef CONFIG_ESP_RMAKER_LIB_ESP_MQTT +COMPONENT_SRCDIRS += src/esp-mqtt +endif diff --git a/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/idf_component.yml b/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/idf_component.yml new file mode 100644 index 000000000..693ffd0cb --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/idf_component.yml @@ -0,0 +1,7 @@ +description: ESP RainMaker firmware agent Common component +repository: git://github.com/espressif/esp-rainmaker-common.git +repository_info: + commit_sha: 7e3c935adc9ee38528d7eb945cda9ff9d1042078 + path: . +url: https://github.com/espressif/esp-rainmaker-common +version: 1.4.11 diff --git a/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/include/esp_rmaker_cmd_resp.h b/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/include/esp_rmaker_cmd_resp.h new file mode 100644 index 000000000..74e937dc4 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/include/esp_rmaker_cmd_resp.h @@ -0,0 +1,184 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* Super Admin User Flag*/ +#define ESP_RMAKER_USER_ROLE_SUPER_ADMIN (1 << 0) + +/** Primary User Flag */ +#define ESP_RMAKER_USER_ROLE_PRIMARY_USER (1 << 1) + +/** Secondary User Flag */ +#define ESP_RMAKER_USER_ROLE_SECONDARY_USER (1 << 2) + + +/** RainMaker Command Response TLV8 Types */ +typedef enum { + /** Request Id : Variable length string, max 32 characters*/ + ESP_RMAKER_TLV_TYPE_REQ_ID = 1, + /** User Role : 1 byte */ + ESP_RMAKER_TLV_TYPE_USER_ROLE, + /** Status : 1 byte */ + ESP_RMAKER_TLV_TYPE_STATUS, + /** Timestamp : TBD */ + ESP_RMAKER_TLV_TYPE_TIMESTAMP, + /** Command : 2 bytes*/ + ESP_RMAKER_TLV_TYPE_CMD, + /** Data : Variable length */ + ESP_RMAKER_TLV_TYPE_DATA +} esp_rmaker_tlv_type_t; + +/* RainMaker Command Response Status */ +typedef enum { + /** Success */ + ESP_RMAKER_CMD_STATUS_SUCCESS = 0, + /** Generic Failure */ + ESP_RMAKER_CMD_STATUS_FAILED, + /** Invalid Command */ + ESP_RMAKER_CMD_STATUS_CMD_INVALID, + /** Authentication Failed */ + ESP_RMAKER_CMD_STATUS_AUTH_FAIL, + /** Command not found */ + ESP_RMAKER_CMD_STATUS_NOT_FOUND, + /** Last status value */ + ESP_RMAKER_CMD_STATUS_MAX, +} esp_rmaker_cmd_status_t; + +#define REQ_ID_LEN 32 +typedef struct { + /** Command id */ + uint16_t cmd; + /** Request id */ + char req_id[REQ_ID_LEN]; + /** User Role */ + uint8_t user_role; +} esp_rmaker_cmd_ctx_t; + +typedef enum { + /** Standard command: Set Parameters */ + ESP_RMAKER_CMD_TYPE_SET_PARAMS = 1, + /** Last Standard command */ + ESP_RMAKER_CMD_STANDARD_LAST = 0xfff, + /** Custom commands can start from here */ + ESP_RMAKER_CMD_CUSTOM_START = 0x1000 +} esp_rmaker_cmd_t; + +/** Command Response Handler + * + * If any command data is received from any of the supported transports (which are outside the scope of this core framework), + * this function should be called to handle it and fill in the response. + * + * @param[in] input Pointer to input data. + * @param[in] input_len data len. + * @param[in] output Pointer to output data which should be set by the handler. + * @param[out] output_len Length of output generated. + * + * @return ESP_OK on success. + * @return error on failure. + */ +esp_err_t esp_rmaker_cmd_response_handler(const void *input, size_t input_len, void **output, size_t *output_len); + +/** Prototype for Command Handler + * + * The handler to be invoked when a given command is received. + * + * @param[in] in_data Pointer to input data. + * @param[in] in_len data len. + * @param[in] out_data Pointer to output data which should be set by the handler. + * @param[out] out_len Length of output generated. + * @param[in] ctx Command Context. + * @param[in] priv Private data, if specified while registering command. + * + * @return ESP_OK on success. + * @return error on failure. + */ +typedef esp_err_t (*esp_rmaker_cmd_handler_t)(const void *in_data, size_t in_len, void **out_data, size_t *out_len, esp_rmaker_cmd_ctx_t *ctx, void *priv); + +/** Register a new command + * + * @param[in] cmd Command Identifier. Custom commands should start beyond ESP_RMAKER_CMD_STANDARD_LAST + * @param[in] access User Access for the command. Can be an OR of the various user role flags like ESP_RMAKER_USER_ROLE_SUPER_ADMIN, + * ESP_RMAKER_USER_ROLE_PRIMARY_USER and ESP_RMAKER_USER_ROLE_SECONDARY_USER + * @param[in] handler The handler to be invoked when the given command is received. + * @param[in] free_on_return Flag to indicate of the framework should free the output after it has been sent as response. + * @param[in] priv Optional private data to be passed to the handler. + * + * @return ESP_OK on success. + * @return error on failure. + */ +esp_err_t esp_rmaker_cmd_register(uint16_t cmd, uint8_t access, esp_rmaker_cmd_handler_t handler, bool free_on_return, void *priv); + +/** De-register a command + * + * @param[in] cmd Command Identifier. Custom commands should start beyond ESP_RMAKER_CMD_STANDARD_LAST + * + * @return ESP_OK on success. + * @return error on failure. + */ +esp_err_t esp_rmaker_cmd_deregister(uint16_t cmd); + +/* Prepare an empty command response + * + * This can be used to populate the request to be sent to get all pending commands + * + * @param[in] out_data Pointer to output data. This function will allocate memory and set this pointer + * accordingly. + * @param[out] out_len Length of output generated. + * + * @return ESP_OK on success. + * @return error on failure. + */ + esp_err_t esp_rmaker_cmd_prepare_empty_response(void **output, size_t *output_len); + +/** Prototype for Command sending function (TESTING only) + * + * @param[in] data Pointer to the data to be sent. + * @param[in] data_len Size of data to be sent. + * @param[in] priv Private data, if applicable. + * + * @return ESP_OK on success. + * @return error on failure. + */ +typedef esp_err_t (*esp_rmaker_cmd_send_t)(const void *data, size_t data_len, void *priv); + +/** Send Test command (TESTING only) + * + * @param[in] req_id NULL terminated request id of max 32 characters. + * @param[in] role User Role flag. + * @param[in] cmd Command Identifier. + * @param[in] data Pointer to data for the command. + * @param[in] data_size Size of the data. + * @param[in] cmd_send Transport specific function to send the command data. + * @param[in] priv Private data (if any) to be sent to cmd_send. + * + * @return ESP_OK on success. + * @return error on failure. + */ +esp_err_t esp_rmaker_cmd_resp_test_send(const char *req_id, uint8_t role, uint16_t cmd, const void *data, size_t data_size, esp_rmaker_cmd_send_t cmd_send, void *priv); + +/** Parse response (TESTING only) + * + * @param[in] response Pointer to the response received + * @param[in] response_len Length of the response + * @param[in] priv Private data, if any. Can be NULL. + * + * @return ESP_OK on success. + * @return error on failure. + */ +esp_err_t esp_rmaker_cmd_resp_parse_response(const void *response, size_t response_len, void *priv); +#ifdef __cplusplus +} +#endif diff --git a/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/include/esp_rmaker_common_console.h b/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/include/esp_rmaker_common_console.h new file mode 100644 index 000000000..55825a8c5 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/include/esp_rmaker_common_console.h @@ -0,0 +1,47 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** + * @brief Initialize console + * + * Initializes serial console and adds basic commands. + * + * @return ESP_OK on success. + * @return error in case of failures. + */ +esp_err_t esp_rmaker_common_console_init(void); + +/* Reference for adding custom console commands: +#include + +static int command_console_handler(int argc, char *argv[]) +{ + // Command code here +} + +static void register_console_command() +{ + const esp_console_cmd_t cmd = { + .command = "", + .help = "", + .func = &command_console_handler, + }; + ESP_ERROR_CHECK(esp_console_cmd_register(&cmd)); +} +*/ + +#ifdef __cplusplus +} +#endif diff --git a/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/include/esp_rmaker_common_events.h b/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/include/esp_rmaker_common_events.h new file mode 100644 index 000000000..b77f8a3d1 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/include/esp_rmaker_common_events.h @@ -0,0 +1,60 @@ +// Copyright 2021 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. +#pragma once +#include +#include +#ifdef __cplusplus +extern "C" +{ +#endif + +/** ESP RainMaker Common Event Base */ +ESP_EVENT_DECLARE_BASE(RMAKER_COMMON_EVENT); + +typedef enum { + /** Node reboot has been triggered. The associated event data is the time in seconds + * (type: uint8_t) after which the node will reboot. Note that this time may not be + * accurate as the events are received asynchronously.*/ + RMAKER_EVENT_REBOOT, + /** Wi-Fi credentials reset. Triggered after calling esp_rmaker_wifi_reset() */ + RMAKER_EVENT_WIFI_RESET, + /** Node reset to factory defaults. Triggered after calling esp_rmaker_factory_reset() */ + RMAKER_EVENT_FACTORY_RESET, + /** Connected to MQTT Broker */ + RMAKER_MQTT_EVENT_CONNECTED, + /** Disconnected from MQTT Broker */ + RMAKER_MQTT_EVENT_DISCONNECTED, + /** MQTT message published successfully. + * Event data will contain the message ID (integer) of published message. + */ + RMAKER_MQTT_EVENT_PUBLISHED, + /** POSIX Timezone Changed. Associated data would be NULL terminated POSIX Timezone + * Eg. "PST8PDT,M3.2.0,M11.1.0" */ + RMAKER_EVENT_TZ_POSIX_CHANGED, + /** Timezone Changed. Associated data would be NULL terminated Timezone. + * Eg. "America/Los_Angeles" + * Note that whenever this event is received, the RMAKER_EVENT_TZ_POSIX_CHANGED event + * will also be received, but not necessarily vice versa. + */ + RMAKER_EVENT_TZ_CHANGED, + /** + * MQTT message deleted from the outbox if the message couldn't have been sent and acknowledged. + * Event data will contain the message ID (integer) of deleted message. + * Valid only if CONFIG_MQTT_REPORT_DELETED_MESSAGES is enabled. + */ + RMAKER_MQTT_EVENT_MSG_DELETED, +} esp_rmaker_common_event_t; +#ifdef __cplusplus +} +#endif diff --git a/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/include/esp_rmaker_factory.h b/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/include/esp_rmaker_factory.h new file mode 100644 index 000000000..cea7489b4 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/include/esp_rmaker_factory.h @@ -0,0 +1,73 @@ +// Copyright 2021 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. +#pragma once +#include +#include +#include +#ifdef __cplusplus +extern "C" +{ +#endif + +/** Initialize Factory NVS + * + * This initializes the Factory NVS partition which will store data + * that should not be cleared even after a reset to factory. + * + * @return ESP_OK on success. + * @return error on failure. + */ +esp_err_t esp_rmaker_factory_init(void); + +/** Get value from factory NVS + * + * This will search for the specified key in the Factory NVS partition, + * allocate the required memory to hold it, copy the value and return + * the pointer to it. It is responsibility of the caller to free the + * memory when the value is no more required. + * + * @param[in] key The key of the value to be read from factory NVS. + * + * @return pointer to the value on success. + * @return NULL on failure. + */ +void *esp_rmaker_factory_get(const char *key); + +/** Get size of value from factory NVS + * + * This will search for the specified key in the Factory NVS partition, + * and return the size of the value associated with the key. + * + * @param[in] key The key of the value to be read from factory NVS. + * + * @return size of the value on success. + * @return 0 on failure. + */ +size_t esp_rmaker_factory_get_size(const char *key); + +/** Set a value in factory NVS + * + * This will write the value for the specified key into factory NVS. + * + * @param[in] key The key for the value to be set in factory NVS. + * @param[in] value Pointer to the value. + * @param[in] len Length of the value. + * + * @return ESP_OK on success. + * @return error on failure. + */ +esp_err_t esp_rmaker_factory_set(const char *key, void *value, size_t len); +#ifdef __cplusplus +} +#endif diff --git a/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/include/esp_rmaker_mqtt_glue.h b/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/include/esp_rmaker_mqtt_glue.h new file mode 100644 index 000000000..20f1a9aa3 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/include/esp_rmaker_mqtt_glue.h @@ -0,0 +1,177 @@ +// Copyright 2021 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. + +#pragma once + +#include +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +#define RMAKER_MQTT_QOS0 0 +#define RMAKER_MQTT_QOS1 1 + +/** MQTT Connection parameters */ +typedef struct { + /** MQTT Host */ + char *mqtt_host; + /** Client ID */ + char *client_id; + /** Client Certificate in DER format or NULL-terminated PEM format */ + char *client_cert; + /** Client Certificate length */ + size_t client_cert_len; + /** Client Key in DER format or NULL-terminated PEM format */ + char *client_key; + /** Client Key length */ + size_t client_key_len; + /** Server Certificate in DER format or NULL-terminated PEM format */ + char *server_cert; + /** Server Certificate length */ + size_t server_cert_len; + /** Pointer for digital signature peripheral context */ + void *ds_data; +} esp_rmaker_mqtt_conn_params_t; + +/** MQTT Get Connection Parameters function prototype + * + * @return Pointer to \ref esp_rmaker_mqtt_conn_params_t on success. + * @return NULL on failure. + */ +typedef esp_rmaker_mqtt_conn_params_t *(*esp_rmaker_mqtt_get_conn_params_t)(void); + +/** MQTT Subscribe callback prototype + * + * @param[in] topic Topic on which the message was received + * @param[in] payload Data received in the message + * @param[in] payload_len Length of the data + * @param[in] priv_data The private data passed during subscription + */ +typedef void (*esp_rmaker_mqtt_subscribe_cb_t)(const char *topic, void *payload, size_t payload_len, void *priv_data); + +/** MQTT Init function prototype + * + * @param[in] conn_params The MQTT connection parameters. If NULL is passed, it should internally use the + * \ref esp_rmaker_mqtt_get_conn_params call if registered. + * + * @return ESP_OK on success. + * @return error in case of any error. + */ +typedef esp_err_t (*esp_rmaker_mqtt_init_t)(esp_rmaker_mqtt_conn_params_t *conn_params); + +/** MQTT Deinit function prototype + * + * Call this function after MQTT has disconnected. + */ +typedef void (*esp_rmaker_mqtt_deinit_t)(void); + +/** MQTT Connect function prototype + * + * Starts the connection attempts to the MQTT broker. + * This should ideally be called after successful network connection. + * + * @return ESP_OK on success. + * @return error in case of any error. + */ +typedef esp_err_t (*esp_rmaker_mqtt_connect_t)(void); + +/** MQTT Disconnect function prototype + * + * Disconnects from the MQTT broker. + * + * @return ESP_OK on success. + * @return error in case of any error. + */ +typedef esp_err_t (*esp_rmaker_mqtt_disconnect_t)(void); + +/** MQTT Publish Message function prototype + * + * @param[in] topic The MQTT topic on which the message should be published. + * @param[in] data Data to be published. + * @param[in] data_len Length of the data. + * @param[in] qos Quality of service for the message. + * @param[out] msg_id If a non NULL pointer is passed, the id of the published message will be returned in this. + * + * @return ESP_OK on success. + * @return error in case of any error. + */ +typedef esp_err_t (*esp_rmaker_mqtt_publish_t)(const char *topic, void *data, size_t data_len, uint8_t qos, int *msg_id); + +/** MQTT Subscribe function prototype + * + * @param[in] topic The topic to be subscribed to. + * @param[in] cb The callback to be invoked when a message is received on the given topic. + * @param[in] qos Quality of service for the subscription. + * @param[in] priv_data Optional private data to be passed to the callback. + * + * @return ESP_OK on success. + * @return error in case of any error. + */ +typedef esp_err_t (*esp_rmaker_mqtt_subscribe_t)(const char *topic, esp_rmaker_mqtt_subscribe_cb_t cb, uint8_t qos, void *priv_data); + +/** MQTT Unsubscribe function prototype + * + * @param[in] topic Topic from which to unsubscribe. + * + * @return ESP_OK on success. + * @return error in case of any error. + */ +typedef esp_err_t (*esp_rmaker_mqtt_unsubscribe_t)(const char *topic); + +/** MQTT configuration */ +typedef struct { + /** Flag to indicate if the MQTT config setup is done */ + bool setup_done; + /** Pointer to the Get MQTT params function. */ + esp_rmaker_mqtt_get_conn_params_t get_conn_params; + /** Pointer to MQTT Init function. */ + esp_rmaker_mqtt_init_t init; + /** Pointer to MQTT Deinit function. */ + esp_rmaker_mqtt_deinit_t deinit; + /** Pointer to MQTT Connect function. */ + esp_rmaker_mqtt_connect_t connect; + /** Pointer to MQTQ Disconnect function */ + esp_rmaker_mqtt_disconnect_t disconnect; + /** Pointer to MQTT Publish function */ + esp_rmaker_mqtt_publish_t publish; + /** Pointer to MQTT Subscribe function */ + esp_rmaker_mqtt_subscribe_t subscribe; + /** Pointer to MQTT Unsubscribe function */ + esp_rmaker_mqtt_unsubscribe_t unsubscribe; +} esp_rmaker_mqtt_config_t; + +/** Setup MQTT Glue + * + * This function initializes MQTT glue layer with all the default functions. + * + * @param[out] mqtt_config Pointer to an allocated MQTT configuration structure. + * + * @return ESP_OK on success. + * @return error in case of any error. + */ +esp_err_t esp_rmaker_mqtt_glue_setup(esp_rmaker_mqtt_config_t *mqtt_config); + +/* Get the ESP AWS PPI String + * + * @return pointer to a NULL terminated PPI string on success. + * @return NULL in case of any error. + */ +const char *esp_get_aws_ppi(void); +#ifdef __cplusplus +} +#endif diff --git a/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/include/esp_rmaker_utils.h b/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/include/esp_rmaker_utils.h new file mode 100644 index 000000000..bf20be7a8 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/include/esp_rmaker_utils.h @@ -0,0 +1,212 @@ +// Copyright 2021 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. +#pragma once +#include +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 4, 0) +#include +#else +#include +#endif + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +#if ((CONFIG_SPIRAM || CONFIG_SPIRAM_SUPPORT) && \ + (CONFIG_SPIRAM_USE_CAPS_ALLOC || CONFIG_SPIRAM_USE_MALLOC)) +#define MEM_ALLOC_EXTRAM(size) heap_caps_malloc_prefer(size, 2, MALLOC_CAP_DEFAULT | MALLOC_CAP_SPIRAM, MALLOC_CAP_DEFAULT | MALLOC_CAP_INTERNAL) +#define MEM_CALLOC_EXTRAM(num, size) heap_caps_calloc_prefer(num, size, 2, MALLOC_CAP_DEFAULT | MALLOC_CAP_SPIRAM, MALLOC_CAP_DEFAULT | MALLOC_CAP_INTERNAL) +#define MEM_REALLOC_EXTRAM(ptr, size) heap_caps_realloc_prefer(ptr, size, 2, MALLOC_CAP_DEFAULT | MALLOC_CAP_SPIRAM, MALLOC_CAP_DEFAULT | MALLOC_CAP_INTERNAL) +#else +#define MEM_ALLOC_EXTRAM(size) malloc(size) +#define MEM_CALLOC_EXTRAM(num, size) calloc(num, size) +#define MEM_REALLOC_EXTRAM(ptr, size) realloc(ptr, size) +#endif + +typedef struct esp_rmaker_time_config { + /** If not specified, then 'CONFIG_ESP_RMAKER_SNTP_SERVER_NAME' is used as the SNTP server. */ + char *sntp_server_name; + /** Optional callback to invoke, whenever time is synchronised. This will be called + * periodically as per the SNTP polling interval (which is 60min by default). + * If kept NULL, the default callback will be invoked, which will just print the + * current local time. + */ + sntp_sync_time_cb_t sync_time_cb; +} esp_rmaker_time_config_t; + +/** Reboot the device after a delay + * + * This API just starts a reboot timer and returns immediately. + * The actual reboot is trigerred asynchronously in the timer callback. + * This is useful if you want to reboot after a delay, to allow other tasks to finish + * their operations (Eg. MQTT publish to indicate OTA success). The \ref RMAKER_EVENT_REBOOT + * event is triggered when the reboot timer is started. + * + * @param[in] seconds Time in seconds after which the device should reboot. + * + * @return ESP_OK on success. + * @return error on failure. + */ +esp_err_t esp_rmaker_reboot(int8_t seconds); + +/** Reset Wi-Fi credentials and (optionally) reboot + * + * This will reset just the Wi-Fi credentials and (optionally) trigger a reboot. + * This is useful when you want to keep all the entries in NVS memory + * intact, but just change the Wi-Fi credentials. The \ref RMAKER_EVENT_WIFI_RESET + * event is triggered when this API is called. The actual reset will happen after a + * delay if reset_seconds is not zero. + * + * @note This reset and reboot operations will happen asynchronously depending + * on the values passed to the API. + * + * @param[in] reset_seconds Time in seconds after which the reset should get triggered. + * This will help other modules take some actions before the device actually resets. + * If set to zero, the operation would be performed immediately. + * @param[in] reboot_seconds Time in seconds after which the device should reboot. If set + * to negative value, the device will not reboot at all. + * + * @return ESP_OK on success. + * @return error on failure. + */ +esp_err_t esp_rmaker_wifi_reset(int8_t reset_seconds, int8_t reboot_seconds); + +/** Reset to factory defaults and reboot + * + * This will clear entire NVS partition and (optionally) trigger a reboot. + * The \ref RMAKER_EVENT_FACTORY_RESET event is triggered when this API is called. + * The actual reset will happen after a delay if reset_seconds is not zero. + * + * @note This reset and reboot operations will happen asynchronously depending + * on the values passed to the API. + * + * @param[in] reset_seconds Time in seconds after which the reset should get triggered. + * This will help other modules take some actions before the device actually resets. + * If set to zero, the operation would be performed immediately. + * @param[in] reboot_seconds Time in seconds after which the device should reboot. If set + * to negative value, the device will not reboot at all. + * + * @return ESP_OK on success. + * @return error on failure. + */ +esp_err_t esp_rmaker_factory_reset(int8_t reset_seconds, int8_t reboot_seconds); + +/** Initialize time synchronization + * + * This API initializes SNTP for time synchronization. + * + * @param[in] config Configuration to be used for SNTP time synchronization. The default configuration is used if NULL is passed. + * + * @return ESP_OK on success + * @return error on failure + */ +esp_err_t esp_rmaker_time_sync_init(esp_rmaker_time_config_t *config); + +/** Check if current time is updated + * + * This API checks if the current system time is updated against the reference time of 1-Jan-2019. + * + * @return true if time is updated + * @return false if time is not updated + */ +bool esp_rmaker_time_check(void); + +/** Wait for time synchronization + * + * This API waits for the system time to be updated against the reference time of 1-Jan-2019. + * This is a blocking call. + * + * @param[in] ticks_to_wait Number of ticks to wait for time synchronization. Accepted values: 0 to portMAX_DELAY. + * + * @return ESP_OK on success + * @return error on failure + */ +esp_err_t esp_rmaker_time_wait_for_sync(uint32_t ticks_to_wait); + +/** Set POSIX timezone + * + * Set the timezone (TZ environment variable) as per the POSIX format + * specified in the [GNU libc documentation](https://www.gnu.org/software/libc/manual/html_node/TZ-Variable.html). + * Eg. For China: "CST-8" + * For US Pacific Time (including daylight saving information): "PST8PDT,M3.2.0,M11.1.0" + * + * @param[in] tz_posix NULL terminated TZ POSIX string + * + * @return ESP_OK on success + * @return error on failure + */ +esp_err_t esp_rmaker_time_set_timezone_posix(const char *tz_posix); + +/** Set timezone location string + * + * Set the timezone as a user friendly location string. + * Check [here](https://rainmaker.espressif.com/docs/time-service.html) for a list of valid values. + * + * Eg. For China: "Asia/Shanghai" + * For US Pacific Time: "America/Los_Angeles" + * + * @note Setting timezone using this API internally also sets the POSIX timezone string. + * + * @param[in] tz NULL terminated Timezone location string + * + * @return ESP_OK on success + * @return error on failure + */ +esp_err_t esp_rmaker_time_set_timezone(const char *tz); + +/** Get the current POSIX timezone + * + * This fetches the current timezone in POSIX format, read from NVS. + * + * @return Pointer to a NULL terminated POSIX timezone string on success. + * Freeing this is the responsibility of the caller. + * @return NULL on failure. + */ +char *esp_rmaker_time_get_timezone_posix(void); + +/** Get the current timezone + * + * This fetches the current timezone in POSIX format, read from NVS. + * + * @return Pointer to a NULL terminated timezone string on success. + * Freeing this is the responsibility of the caller. + * @return NULL on failure. + */ +char *esp_rmaker_time_get_timezone(void); + +/** Get printable local time string + * + * Get a printable local time string, with information of timezone and Daylight Saving. + * Eg. "Tue Sep 1 09:04:38 2020 -0400[EDT], DST: Yes" + * "Tue Sep 1 21:04:04 2020 +0800[CST], DST: No" + * + * + * @param[out] buf Pointer to a pre-allocated buffer into which the time string will + * be populated. + * @param[in] buf_len Length of the above buffer. + * + * @return ESP_OK on success + * @return error on failure + */ +esp_err_t esp_rmaker_get_local_time_str(char *buf, size_t buf_len); + +#ifdef __cplusplus +} +#endif diff --git a/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/include/esp_rmaker_work_queue.h b/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/include/esp_rmaker_work_queue.h new file mode 100644 index 000000000..0e696d468 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/include/esp_rmaker_work_queue.h @@ -0,0 +1,82 @@ +// Copyright 2021 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. +#pragma once +#include +#include +#include +#ifdef __cplusplus +extern "C" +{ +#endif +/** Prototype for ESP RainMaker Work Queue Function + * + * @param[in] priv_data The private data associated with the work function. + */ +typedef void (*esp_rmaker_work_fn_t)(void *priv_data); + +/** Initializes the Work Queue + * + * This initializes the work queue, which is basically a mechanism to run + * tasks in the context of a dedicated thread. You can start queueing tasks + * after this, but they will get executed only after calling + * esp_rmaker_work_queue_start(). + * + * @return ESP_OK on success. + * @return error in case of failure. + */ +esp_err_t esp_rmaker_work_queue_init(void); + +/** De-initialize the Work Queue + * + * This de-initializes the work queue. Note that the work queue needs to + * be stopped using esp_rmaker_work_queue_stop() before calling this. + * + * @return ESP_OK on success. + * @return error in case of failure. + */ +esp_err_t esp_rmaker_work_queue_deinit(void); + +/** Start the Work Queue + * + * This starts the Work Queue thread which then starts executing the tasks queued. + * + * @return ESP_OK on success. + * @return error in case of failure. + */ +esp_err_t esp_rmaker_work_queue_start(void); + +/** Stop the Work Queue + * + * This stops a running Work Queue. + * + * @return ESP_OK on success. + * @return error in case of failure. + */ +esp_err_t esp_rmaker_work_queue_stop(void); + +/** Queue execution of a function in the Work Queue's context + * + * This API queues a work function for execution in the Work Queue Task's context. + * + * @param[in] work_fn The Work function to be queued. + * @param[in] priv_data Private data to be passed to the work function. + * + * @return ESP_OK on success. + * @return error in case of failure. + */ +esp_err_t esp_rmaker_work_queue_add_task(esp_rmaker_work_fn_t work_fn, void *priv_data); + +#ifdef __cplusplus +} +#endif diff --git a/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/src/cmd_resp.c b/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/src/cmd_resp.c new file mode 100644 index 000000000..997b3ada9 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/src/cmd_resp.c @@ -0,0 +1,429 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include + +#define RMAKER_MAX_CMD CONFIG_ESP_RMAKER_MAX_COMMANDS + +static const char *TAG = "esp_rmaker_common_cmd_resp"; + +typedef struct { + uint16_t cmd; + uint8_t access; + bool free_on_return; + esp_rmaker_cmd_handler_t handler; + void *priv; +} esp_rmaker_cmd_info_t; + +typedef struct { + uint8_t *bufptr; + int bufsize; + int curlen; +} esp_rmaker_tlv_data_t; + +static esp_rmaker_cmd_info_t *esp_rmaker_cmd_list[RMAKER_MAX_CMD]; + +/* Get uint16 from Little Endian data buffer */ +static uint16_t get_u16_le(const void *val_ptr) +{ + const uint8_t *p = (const uint8_t *) val_ptr; + uint16_t val; + + val = (uint16_t)p[0]; + val |= (uint16_t)p[1] << 8; + + return val; +} + +/* Put uint16 in Little Endian ordering into data buffer */ +static void put_u16_le(void *val_ptr, const uint16_t val) +{ + uint8_t *p = (uint8_t *) val_ptr; + + p[0] = (uint8_t)val & 0xff; + p[1] = (uint8_t)(val >> 8) & 0xff; +} + +/* Initialise TLV Data */ +static void esp_rmaker_tlv_data_init(esp_rmaker_tlv_data_t *tlv_data, uint8_t *buf, int buf_size) +{ + tlv_data->bufptr = buf; + tlv_data->bufsize = buf_size; + tlv_data->curlen = 0; +} + +/* Get length of data, for given type. + * + * Returns length of data on success and -1 if the TLV was not found + */ +static int esp_rmaker_get_tlv_length(const uint8_t *buf, int buflen, uint8_t type) +{ + if (!buf ) { + return -1; + } + int curlen = 0; + int val_len = 0; + bool found = false; + while (buflen > 0) { + if (buf[curlen] == type) { + uint8_t len = buf[curlen + 1]; + if ((buflen - len) < 2) { + return -1; + } + val_len += len; + if (len < 255) { + return val_len; + } else { + found = true; + } + + } else if (found) { + return val_len; + } + + /* buf[curlen +1] will give the Length */ + buflen -= (2 + buf[curlen + 1]); + curlen += (2 + buf[curlen + 1]); + } + if (found) { + return val_len; + } + return -1; +} + +/* Get the value for the given type. + * + * Returns length of data on success and -1 if the TLV was not found + */ +static int esp_rmaker_get_value_from_tlv(const uint8_t *buf, int buflen, uint8_t type, void *val, int val_size) +{ + if (!buf || !val) { + return -1; + } + int curlen = 0; + int val_len = 0; + bool found = false; + while (buflen > 0) { + if (buf[curlen] == type) { + uint8_t len = buf[curlen + 1]; + if ((val_size < len) || ((buflen - len) < 2)) { + return -1; + } + memcpy(val + val_len, &buf[curlen + 2], len); + val_len += len; + val_size -= len; + if (len < 255) { + return val_len; + } else { + found = true; + } + + } else if (found) { + return val_len; + } + + /* buf[curlen +1] will give the Length */ + buflen -= (2 + buf[curlen + 1]); + curlen += (2 + buf[curlen + 1]); + } + if (found) { + return val_len; + } + return -1; +} + +/* Add a TLV to the TLV buffer */ +static int esp_rmaker_add_tlv(esp_rmaker_tlv_data_t *tlv_data, uint8_t type, int len, const void *val) +{ + if (!tlv_data->bufptr || ((len + 2) > (tlv_data->bufsize - tlv_data->curlen))) { + return -1; + } + if (len > 0 && val == NULL) { + return -1; + } + uint8_t *buf_ptr = (uint8_t *)val; + int orig_len = tlv_data->curlen; + do { + tlv_data->bufptr[tlv_data->curlen++] = type; + int tmp_len; + if (len > 255) { + tmp_len = 255; + } else { + tmp_len = len; + } + tlv_data->bufptr[tlv_data->curlen++] = tmp_len; + memcpy(&tlv_data->bufptr[tlv_data->curlen], buf_ptr, tmp_len); + tlv_data->curlen += tmp_len; + buf_ptr += tmp_len; + len -= tmp_len; + } while (len); + return tlv_data->curlen - orig_len; +} + +/* Get user role string from flag. Useful for printing */ +const char *esp_rmaker_get_user_role_string(uint8_t user_role) +{ + switch (user_role) { + case ESP_RMAKER_USER_ROLE_SUPER_ADMIN: + return "Admin"; + case ESP_RMAKER_USER_ROLE_PRIMARY_USER: + return "Primary"; + case ESP_RMAKER_USER_ROLE_SECONDARY_USER: + return "Secondary"; + default: + return "Invalid Role"; + } +} + +/* Prepare the response TLV8 which includes + * + * Request Id + * Status + * Command Id + * Response Data + */ +static esp_err_t esp_rmaker_cmd_prepare_response(esp_rmaker_cmd_ctx_t *cmd_ctx, uint8_t status, void *response, size_t response_size, void **output, size_t *output_len) +{ + size_t publish_size = response_size + 100; /* +100 for rest of metadata. TODO: Do exact calculation */ + void *publish_data = MEM_CALLOC_EXTRAM(1, publish_size); + if (!publish_data) { + ESP_LOGE(TAG, "Failed to allocate buffer of size %d for response.", response_size + 100); + return ESP_ERR_NO_MEM; + } + esp_rmaker_tlv_data_t tlv_data; + esp_rmaker_tlv_data_init(&tlv_data, publish_data, publish_size); + if (strlen(cmd_ctx->req_id)) { + esp_rmaker_add_tlv(&tlv_data, ESP_RMAKER_TLV_TYPE_REQ_ID, strlen(cmd_ctx->req_id), cmd_ctx->req_id); + } + esp_rmaker_add_tlv(&tlv_data, ESP_RMAKER_TLV_TYPE_STATUS, sizeof(status), &status); + uint8_t cmd_buf[2]; + put_u16_le(cmd_buf, cmd_ctx->cmd); + esp_rmaker_add_tlv(&tlv_data, ESP_RMAKER_TLV_TYPE_CMD, sizeof(cmd_buf), cmd_buf); + if (response != NULL && response_size != 0) { + esp_rmaker_add_tlv(&tlv_data, ESP_RMAKER_TLV_TYPE_DATA, response_size, response); + } + ESP_LOGD(TAG, "Generated response of size %d for cmd %d", tlv_data.curlen, cmd_ctx->cmd); + *output = publish_data; + *output_len = tlv_data.curlen; + return ESP_OK; +} + +esp_err_t esp_rmaker_cmd_prepare_empty_response(void **output, size_t *output_len) +{ + size_t publish_size = 6; /* unit16 cmd = 0 (4 bytes in TLV), req_id = empty (2 bytes) */ + void *publish_data = MEM_CALLOC_EXTRAM(1, publish_size); + if (!publish_data) { + return ESP_ERR_NO_MEM; + } + esp_rmaker_tlv_data_t tlv_data; + esp_rmaker_tlv_data_init(&tlv_data, publish_data, publish_size); + esp_rmaker_add_tlv(&tlv_data, ESP_RMAKER_TLV_TYPE_REQ_ID, 0, NULL); + uint8_t cmd_buf[2]; + put_u16_le(cmd_buf, 0); + esp_rmaker_add_tlv(&tlv_data, ESP_RMAKER_TLV_TYPE_CMD, sizeof(cmd_buf), cmd_buf); + *output = publish_data; + *output_len = tlv_data.curlen; + ESP_LOGD(TAG, "Generated empty response for requesting pending commands."); + return ESP_OK; +} + +/* Register a new command with its handler + */ +esp_err_t esp_rmaker_cmd_register(uint16_t cmd, uint8_t access, esp_rmaker_cmd_handler_t handler, bool free_on_return, void *priv) +{ + int i; + for (i = 0; i < RMAKER_MAX_CMD; i++) { + if (esp_rmaker_cmd_list[i] && (esp_rmaker_cmd_list[i]->cmd == cmd)) { + ESP_LOGE(TAG, "Handler for command %d already exists.", cmd); + return ESP_FAIL; + } + } + for (i = 0; i < RMAKER_MAX_CMD; i++) { + if (!esp_rmaker_cmd_list[i]) { + esp_rmaker_cmd_info_t *cmd_info = calloc(1, sizeof(esp_rmaker_cmd_info_t)); + if (!cmd_info) { + ESP_LOGE(TAG, "Could not allocate memory for cmd %d", cmd); + return ESP_ERR_NO_MEM; + } + cmd_info->cmd = cmd; + cmd_info->access = access; + cmd_info->free_on_return = free_on_return; + cmd_info->handler = handler; + cmd_info->priv = priv; + esp_rmaker_cmd_list[i] = cmd_info; + ESP_LOGI(TAG, "Registered command %d", cmd); + return ESP_OK; + } + } + ESP_LOGE(TAG, "No space to add command %d", cmd); + return ESP_ERR_NO_MEM; +} + +/* Find the command infor for given command + * + * Returns pointer to the info if found and NULL on error + */ +static esp_rmaker_cmd_info_t *esp_rmaker_get_cmd_info(uint16_t cmd) +{ + int i; + for (i = 0; i < RMAKER_MAX_CMD; i++) { + if (esp_rmaker_cmd_list[i] && (esp_rmaker_cmd_list[i]->cmd == cmd)) { + ESP_LOGI(TAG, "Handler found for command %d.", cmd); + return esp_rmaker_cmd_list[i]; + } + } + ESP_LOGE(TAG, "No handler found for command %d.", cmd); + return NULL; +} + +/* De-register given command */ +esp_err_t esp_rmaker_cmd_deregister(uint16_t cmd) +{ + int i; + for (i = 0; i < RMAKER_MAX_CMD; i++) { + if (esp_rmaker_cmd_list[i] && (esp_rmaker_cmd_list[i]->cmd == cmd)) { + free(esp_rmaker_cmd_list[i]); + esp_rmaker_cmd_list[i] = NULL; + return ESP_OK; + } + } + ESP_LOGE(TAG, "Cannot unregister command %d as it wasn't registered.", cmd); + return ESP_ERR_INVALID_ARG; +} + +/* Main command response handling function. + * + * It parses the rceived data to find the command and other metadata and + * prepares the response to be sent + */ +esp_err_t esp_rmaker_cmd_response_handler(const void *input, size_t input_len, void **output, size_t *output_len) +{ + esp_rmaker_cmd_ctx_t cmd_ctx = {0}; + + /* Read request id, user role and command, since these are mandatory fields */ + esp_rmaker_get_value_from_tlv(input, input_len, ESP_RMAKER_TLV_TYPE_REQ_ID, &cmd_ctx.req_id, sizeof(cmd_ctx.req_id)); + esp_rmaker_get_value_from_tlv(input, input_len, ESP_RMAKER_TLV_TYPE_USER_ROLE, &cmd_ctx.user_role, sizeof(cmd_ctx.user_role)); + uint8_t cmd_buf[2] = {0}; + esp_rmaker_get_value_from_tlv(input, input_len, ESP_RMAKER_TLV_TYPE_CMD, cmd_buf, sizeof(cmd_buf)); + cmd_ctx.cmd = get_u16_le(cmd_buf); + + if (strlen(cmd_ctx.req_id) == 0 || cmd_ctx.user_role == 0 || cmd_ctx.cmd == 0) { + ESP_LOGE(TAG, "Request id, user role or command id cannot be 0"); + return esp_rmaker_cmd_prepare_response(&cmd_ctx, ESP_RMAKER_CMD_STATUS_CMD_INVALID, NULL, 0, output, output_len); + } + ESP_LOGI(TAG, "Got Req. Id: %s, Role = %s, Cmd = %d", cmd_ctx.req_id, + esp_rmaker_get_user_role_string(cmd_ctx.user_role), cmd_ctx.cmd); + + /* Search for the command info and handle it if found */ + esp_rmaker_cmd_info_t *cmd_info = esp_rmaker_get_cmd_info(cmd_ctx.cmd); + if (cmd_info) { + if (cmd_info->access & cmd_ctx.user_role) { + void *data = NULL; + int data_size = esp_rmaker_get_tlv_length(input, input_len, ESP_RMAKER_TLV_TYPE_DATA); + if (data_size > 0) { + /* TODO: If data size < 255, can just use the pointer to input */ + data = MEM_CALLOC_EXTRAM(1, data_size); + if (!data) { + ESP_LOGE(TAG, "Failed to allocate buffer of size %d for data.", data_size); + return ESP_ERR_NO_MEM; + } + esp_rmaker_get_value_from_tlv(input, input_len, ESP_RMAKER_TLV_TYPE_DATA, data, data_size); + } else { + /* It is not mandatory to have data for a given command. So, just throwing a warning */ + ESP_LOGW(TAG, "No data received for the command."); + data_size = 0; + } + void *response; + size_t response_size = 0; + esp_err_t err = cmd_info->handler(data, data_size, &response, &response_size, &cmd_ctx, cmd_info->priv); + if (err == ESP_OK) { + err = esp_rmaker_cmd_prepare_response(&cmd_ctx, ESP_RMAKER_CMD_STATUS_SUCCESS, response, response_size, output, output_len); + } else { + err = esp_rmaker_cmd_prepare_response(&cmd_ctx, ESP_RMAKER_CMD_STATUS_FAILED, NULL, 0, output, output_len); + } + if (response && cmd_info->free_on_return) { + ESP_LOGI(TAG, "Freeing response buffer."); + free(response); + } + return err; + } else { + return esp_rmaker_cmd_prepare_response(&cmd_ctx, ESP_RMAKER_CMD_STATUS_AUTH_FAIL, NULL, 0, output, output_len); + } + } + return esp_rmaker_cmd_prepare_response(&cmd_ctx, ESP_RMAKER_CMD_STATUS_NOT_FOUND, NULL, 0, output, output_len); +} + +/****************************************** Testing Functions ******************************************/ +static const char *cmd_status[] = { + [ESP_RMAKER_CMD_STATUS_SUCCESS] = "Success", + [ESP_RMAKER_CMD_STATUS_FAILED] = "Fail", + [ESP_RMAKER_CMD_STATUS_CMD_INVALID] = "Invalid command data", + [ESP_RMAKER_CMD_STATUS_AUTH_FAIL] = "Auth fail", + [ESP_RMAKER_CMD_STATUS_NOT_FOUND] = "Command not found", +}; + +/* Send test command */ +esp_err_t esp_rmaker_cmd_resp_test_send(const char *req_id, uint8_t role, uint16_t cmd, const void *data, + size_t data_size, esp_rmaker_cmd_send_t cmd_send, void *priv_data) +{ + if (!cmd_send) { + ESP_LOGE(TAG, "No callback to trigger the command."); + return ESP_ERR_INVALID_ARG; + } + uint8_t cmd_data[200]; + esp_rmaker_tlv_data_t tlv_data; + esp_rmaker_tlv_data_init(&tlv_data, cmd_data, sizeof(cmd_data)); + if (req_id) { + esp_rmaker_add_tlv(&tlv_data, ESP_RMAKER_TLV_TYPE_REQ_ID, strlen(req_id), req_id); + } + esp_rmaker_add_tlv(&tlv_data, ESP_RMAKER_TLV_TYPE_USER_ROLE, sizeof(role), &role); + uint8_t cmd_buf[2]; + put_u16_le(cmd_buf, cmd); + esp_rmaker_add_tlv(&tlv_data, ESP_RMAKER_TLV_TYPE_CMD, sizeof(cmd_buf), cmd_buf); + if (data != NULL && data_size != 0) { + esp_rmaker_add_tlv(&tlv_data, ESP_RMAKER_TLV_TYPE_DATA, data_size, data); + } + ESP_LOGI(TAG, "Sending command of size %d for cmd %d", tlv_data.curlen, cmd); + return cmd_send(cmd_data, tlv_data.curlen, priv_data); +} + +/* Parse response */ +esp_err_t esp_rmaker_cmd_resp_parse_response(const void *response, size_t response_len, void *priv_data) +{ + if (!response) { + ESP_LOGE(TAG, "NULL response. Cannot parse."); + return ESP_ERR_INVALID_ARG; + } + char req_id[REQ_ID_LEN] = {0}; + if (esp_rmaker_get_value_from_tlv(response, response_len, ESP_RMAKER_TLV_TYPE_REQ_ID, req_id, sizeof(req_id)) > 0) { + ESP_LOGI(TAG, "RESP: Request Id: %s", req_id); + } + + uint16_t cmd; + uint8_t cmd_buf[2]; + if (esp_rmaker_get_value_from_tlv(response, response_len, ESP_RMAKER_TLV_TYPE_CMD, cmd_buf, sizeof(cmd_buf)) > 0) { + cmd = get_u16_le(cmd_buf); + ESP_LOGI(TAG, "RESP: Command: %" PRIu16, cmd); + } + + uint8_t status; + if (esp_rmaker_get_value_from_tlv(response, response_len, ESP_RMAKER_TLV_TYPE_STATUS, &status, sizeof(status)) > 0) { + ESP_LOGI(TAG, "RESP: Status: %" PRIu8 ": %s", status, cmd_status[status]); + } + + char resp_data[200]; + int resp_size = esp_rmaker_get_value_from_tlv(response, response_len, ESP_RMAKER_TLV_TYPE_DATA, resp_data, sizeof(resp_data)); + if (resp_size > 0) { + resp_data[resp_size] = 0; + ESP_LOGI(TAG, "RESP: Data: %s", resp_data); + } + return ESP_OK; +} diff --git a/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/src/console/rmaker_common_cmds.c b/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/src/console/rmaker_common_cmds.c new file mode 100644 index 000000000..ee538fc76 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/src/console/rmaker_common_cmds.c @@ -0,0 +1,359 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_HEAP_TRACING +#include +#endif + +#include + + +#include "rmaker_console_internal.h" + +static const char *TAG = "esp_rmaker_commands"; + +static int reboot_cli_handler(int argc, char *argv[]) +{ + /* Just to go to the next line */ + printf("\n"); + esp_restart(); + return 0; +} + +static int up_time_cli_handler(int argc, char *argv[]) +{ + printf("%s: Uptime of the device: %lld milliseconds\n", TAG, esp_timer_get_time() / 1000); + return 0; +} + +static int task_dump_cli_handler(int argc, char *argv[]) +{ +#ifndef CONFIG_FREERTOS_USE_TRACE_FACILITY + printf("%s: To use this utility enable: Component config --> FreeRTOS --> Enable FreeRTOS trace facility\n", TAG); +#else + int num_of_tasks = uxTaskGetNumberOfTasks(); + TaskStatus_t *task_array = MEM_CALLOC_EXTRAM(num_of_tasks, sizeof(TaskStatus_t)); + if (!task_array) { + ESP_LOGE(TAG, "Memory allocation for task list failed."); + return -1; + } + num_of_tasks = uxTaskGetSystemState(task_array, num_of_tasks, NULL); + printf("%s: \tName\tNumber\tPriority\tStackWaterMark\n", TAG); + for (int i = 0; i < num_of_tasks; i++) { + printf("%16s\t%d\t%d\t%" PRIu32 "\n", + task_array[i].pcTaskName, + task_array[i].xTaskNumber, + task_array[i].uxCurrentPriority, + task_array[i].usStackHighWaterMark); + } + free(task_array); +#endif + return 0; +} + +static int cpu_dump_cli_handler(int argc, char *argv[]) +{ +#ifndef CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS + printf("%s: To use this utility enable: Component config --> FreeRTOS --> Enable FreeRTOS to collect run time stats\n", TAG); +#else + char *buf = MEM_CALLOC_EXTRAM(1, 2 * 1024); + if (!buf) { + ESP_LOGE(TAG, "Memory allocation for cpu dump failed."); + return -1; + } + vTaskGetRunTimeStats(buf); + printf("%s: Run Time Stats:\n%s\n", TAG, buf); + free(buf); +#endif + return 0; +} + +static int mem_dump_cli_handler(int argc, char *argv[]) +{ + printf("\tDescription\tInternal\tSPIRAM\n"); + printf("Current Free Memory\t%d\t\t%d\n", + heap_caps_get_free_size(MALLOC_CAP_8BIT) - heap_caps_get_free_size(MALLOC_CAP_SPIRAM), + heap_caps_get_free_size(MALLOC_CAP_SPIRAM)); + printf("Largest Free Block\t%d\t\t%d\n", + heap_caps_get_largest_free_block(MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL), + heap_caps_get_largest_free_block(MALLOC_CAP_SPIRAM)); + printf("Min. Ever Free Size\t%d\t\t%d\n", + heap_caps_get_minimum_free_size(MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL), + heap_caps_get_minimum_free_size(MALLOC_CAP_SPIRAM)); + return 0; +} + +static int sock_dump_cli_handler(int argc, char *argv[]) +{ +#if LWIP_IPV4 + int i, ret, used_sockets = 0; + + struct sockaddr_in local_sock, peer_sock; + socklen_t local_sock_len = sizeof(struct sockaddr_in), peer_sock_len = sizeof(struct sockaddr_in); + char local_ip_addr[16], peer_ip_addr[16]; + unsigned int local_port, peer_port; + + int sock_type; + socklen_t sock_type_len; + +#define TOTAL_NUM_SOCKETS MEMP_NUM_NETCONN + printf("sock_fd\tprotocol\tlocal_addr\t\tpeer_addr\n"); + for (i = LWIP_SOCKET_OFFSET; i < LWIP_SOCKET_OFFSET + TOTAL_NUM_SOCKETS; i++) { + memset(&local_sock, 0, sizeof(struct sockaddr_in)); + memset(&peer_sock, 0, sizeof(struct sockaddr_in)); + local_sock_len = sizeof(struct sockaddr); + peer_sock_len = sizeof(struct sockaddr); + memset(local_ip_addr, 0, sizeof(local_ip_addr)); + memset(peer_ip_addr, 0, sizeof(peer_ip_addr)); + local_port = 0; + peer_port = 0; + sock_type = 0; + sock_type_len = sizeof(int); + + ret = getsockname(i, (struct sockaddr *)&local_sock, &local_sock_len); + if (ret >= 0) { + used_sockets++; + inet_ntop(AF_INET, &local_sock.sin_addr, local_ip_addr, sizeof(local_ip_addr)); + local_port = ntohs(local_sock.sin_port); + getsockopt(i, SOL_SOCKET, SO_TYPE, &sock_type, &sock_type_len); + printf("%d\t%d:%s\t%16s:%d", i, sock_type, sock_type == SOCK_STREAM ? "tcp" : sock_type == SOCK_DGRAM ? "udp" : "raw", local_ip_addr, local_port); + + ret = getpeername(i, (struct sockaddr *)&peer_sock, &peer_sock_len); + if (ret >= 0) { + inet_ntop(AF_INET, &peer_sock.sin_addr, peer_ip_addr, sizeof(peer_ip_addr)); + peer_port = ntohs(peer_sock.sin_port); + printf("\t%16s:%d", peer_ip_addr, peer_port); + } + printf("\n"); + } + } + printf("Remaining sockets: %d\n", TOTAL_NUM_SOCKETS - used_sockets); +#else + printf("%s: To use this utility enable: Component config --> LWIP --> Enable IPv4 \n", TAG); +#endif /* LWIP_IPV4 */ + return 0; +} + +#ifdef CONFIG_HEAP_TRACING +static int heap_trace_records; +static heap_trace_record_t *heap_trace_records_buf; +static int cli_heap_trace_start() +{ + if (!heap_trace_records_buf) { + // this buffer is required to be in internal + heap_trace_records_buf = malloc(heap_trace_records * sizeof(heap_trace_record_t)); + if (!heap_trace_records_buf) { + printf("%s: Failed to allocate records buffer\n", TAG); + return -1; + } + if (heap_trace_init_standalone(heap_trace_records_buf, heap_trace_records) != ESP_OK) { + printf("%s: Failed to initialise tracing\n", TAG); + goto error1; + } + } + if (heap_trace_start(HEAP_TRACE_LEAKS) != ESP_OK) { + printf("%s: Failed to start heap trace\n", TAG); + goto error2; + } + return 0; +error2: + heap_trace_init_standalone(NULL, 0); +error1: + free(heap_trace_records_buf); + heap_trace_records_buf = NULL; + return -1; +} + +static int cli_heap_trace_stop() +{ + if (!heap_trace_records_buf) { + printf("%s: Tracing not started?\n", TAG); + return 0; + } + heap_trace_stop(); + heap_trace_dump(); + heap_trace_init_standalone(NULL, 0); + free(heap_trace_records_buf); + heap_trace_records_buf = NULL; + return 0; +} +#endif + +static int heap_trace_cli_handler(int argc, char *argv[]) +{ + int ret = 0; +#ifndef CONFIG_HEAP_TRACING + printf("%s: To use this utility enable: Component config --> Heap memory debugging --> Enable heap tracing\n", TAG); +#else + if (argc < 2) { + printf("%s: Incorrect arguments\n", TAG); + return -1; + } + if (strcmp(argv[1], "start") == 0) { +#define DEFAULT_HEAP_TRACE_RECORDS 200 + if (argc != 3) { + heap_trace_records = DEFAULT_HEAP_TRACE_RECORDS; + } else { + heap_trace_records = atoi(argv[2]); + } + printf("%s: Using a buffer to trace %d records\n", TAG, heap_trace_records); + ret = cli_heap_trace_start(); + } else if (strcmp(argv[1], "stop") == 0) { + ret = cli_heap_trace_stop(); + } else { + printf("%s: Invalid argument:%s:\n", TAG, argv[1]); + ret = -1; + } +#endif + return ret; +} + +static int register_generic_debug_commands() +{ + const esp_console_cmd_t debug_commands[] = { + { + .command = "reboot", + .help = "", + .func = reboot_cli_handler, + }, + { + .command = "up-time", + .help = "Get the device up time in milliseconds.", + .func = up_time_cli_handler, + }, + { + .command = "mem-dump", + .help = "Get the available memory.", + .func = mem_dump_cli_handler, + }, + { + .command = "task-dump", + .help = "Get the list of all the running tasks.", + .func = task_dump_cli_handler, + }, + { + .command = "cpu-dump", + .help = "Get the CPU utilisation by all the runninng tasks.", + .func = cpu_dump_cli_handler, + }, + { + .command = "sock-dump", + .help = "Get the list of all the active sockets.", + .func = sock_dump_cli_handler, + }, + { + .command = "heap-trace", + .help = "Start or stop heap tracing. Usage: heap-trace ", + .func = heap_trace_cli_handler, + }, + }; + + int cmds_num = sizeof(debug_commands) / sizeof(esp_console_cmd_t); + int i; + for (i = 0; i < cmds_num; i++) { + ESP_LOGI(TAG, "Registering command: %s", debug_commands[i].command); + esp_console_cmd_register(&debug_commands[i]); + } + return 0; +} + +static int reset_to_factory_handler(int argc, char** argv) +{ +#define RESET_DELAY 2 +#define REBOOT_DELAY 2 + printf("%s: Resetting to Factory Defaults...\n", TAG); + esp_rmaker_factory_reset(RESET_DELAY, REBOOT_DELAY); + return ESP_OK; +} + +static void register_reset_to_factory() +{ + const esp_console_cmd_t cmd = { + .command = "reset-to-factory", + .help = "Reset the board to factory defaults", + .func = &reset_to_factory_handler, + }; + ESP_LOGI(TAG, "Registering command: %s", cmd.command); + esp_console_cmd_register(&cmd); +} + +static int local_time_cli_handler(int argc, char *argv[]) +{ + char local_time[64]; + if (esp_rmaker_get_local_time_str(local_time, sizeof(local_time)) == ESP_OK) { + printf("%s: Current local time: %s\n", TAG, local_time); + } else { + printf("%s: Current local time (truncated): %s\n", TAG, local_time); + } + return ESP_OK; +} + +static int tz_set_cli_handler(int argc, char *argv[]) +{ + if (argc < 2) { + printf("%s: Invalid Usage.\n", TAG); + return ESP_ERR_INVALID_ARG; + } + if (strcmp(argv[1], "posix") == 0) { + if (argv[2]) { + esp_rmaker_time_set_timezone_posix(argv[2]); + } else { + printf("%s: Invalid Usage.\n", TAG); + return ESP_ERR_INVALID_ARG; + } + } else { + esp_rmaker_time_set_timezone(argv[1]); + } + return ESP_OK; +} + +static void register_time_commands() +{ + const esp_console_cmd_t local_time_cmd = { + .command = "local-time", + .help = "Get the local time of device.", + .func = &local_time_cli_handler, + }; + ESP_LOGI(TAG, "Registering command: %s", local_time_cmd.command); + esp_console_cmd_register(&local_time_cmd); + + const esp_console_cmd_t tz_set_cmd = { + .command = "tz-set", + .help = "Set Timezone. Usage: tz-set [posix] .", + .func = &tz_set_cli_handler, + }; + ESP_LOGI(TAG, "Registering command: %s", tz_set_cmd.command); + esp_console_cmd_register(&tz_set_cmd); +} + +void esp_rmaker_common_register_commands() +{ + static bool registered = false; + if (registered) { + ESP_LOGI(TAG, "Skipping already registered commands"); + return; + } + register_generic_debug_commands(); + register_reset_to_factory(); + register_time_commands(); + registered = true; +} diff --git a/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/src/console/rmaker_console.c b/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/src/console/rmaker_console.c new file mode 100644 index 000000000..b51f81be6 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/src/console/rmaker_console.c @@ -0,0 +1,117 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "rmaker_console_internal.h" + +static const char *TAG = "esp_rmaker_console"; +static int stop; + +static void scli_task(void *arg) +{ + int uart_num = 0; + uint8_t linebuf[256]; + int i, cmd_ret; + esp_err_t ret; + QueueHandle_t uart_queue; + uart_event_t event; + bool first_done = false; + + ESP_LOGI(TAG, "Initialising UART on port %d", uart_num); + 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); + esp_console_register_help_command(); + + while (!stop) { + if (first_done) { + uart_write_bytes(uart_num, "\n>> ", 4); + } else { + first_done = true; + } + memset(linebuf, 0, sizeof(linebuf)); + i = 0; + do { + ret = xQueueReceive(uart_queue, (void * )&event, (TickType_t)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'; + /* Just to go to the next line */ + printf("\n"); + ret = esp_console_run((char *) linebuf, &cmd_ret); + if (cmd_ret != 0) { + printf("%s: Console command failed with error: %d\n", TAG, cmd_ret); + cmd_ret = 0; + } + if (ret < 0) { + printf("%s: Console dispatcher error\n", TAG); + break; + } + } + ESP_LOGE(TAG, "Stopped CLI"); + vTaskDelete(NULL); +} + +static esp_err_t scli_init() +{ + static bool cli_started = false; + if (cli_started) { + return ESP_OK; + } +#define SCLI_STACK_SIZE 4096 + if (xTaskCreate(&scli_task, "console_task", SCLI_STACK_SIZE, NULL, 3, NULL) != pdPASS) { + ESP_LOGE(TAG, "Couldn't create thread"); + return ESP_ERR_NO_MEM; + } + cli_started = true; + return ESP_OK; +} + +esp_err_t esp_rmaker_common_console_init() +{ + esp_err_t ret = scli_init(); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "Couldn't initialise console"); + return ret; + } + + esp_rmaker_common_register_commands(); + return ESP_OK; +} diff --git a/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/src/console/rmaker_console_internal.h b/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/src/console/rmaker_console_internal.h new file mode 100644 index 000000000..942a7e0d5 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/src/console/rmaker_console_internal.h @@ -0,0 +1,9 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +void esp_rmaker_common_register_commands(void); diff --git a/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/src/create_APN3_PPI_string.c b/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/src/create_APN3_PPI_string.c new file mode 100644 index 000000000..ca2074a5d --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/src/create_APN3_PPI_string.c @@ -0,0 +1,246 @@ +/* + * APN3 PPI string generator - sample code + * + * NOTE: All code is provided as sample code for informational purposes only, and should not be used for any testing or production workloads. + * All code is provided “as is” and AWS expressly disclaims all warranties, including, without limitation: any implied warranties of + * noninfringement, merchantability, or fitness for a particular purpose; any warranty that operation of the code will be error-free + * or free of harmful components; or any warranty arising out of any course of dealing or usage of trade. In no event shall AWS or + * any of its affiliates be liable for any damages arising out of the use of this code, including, without limitation, any direct, + * indirect, special, incidental or consequential damages. + */ +#include +#include +#include +#include +#include +#ifdef CONFIG_ESP_RMAKER_NETWORK_OVER_THREAD +#include +#endif + +static const char *TAG = "aws_ppi"; + +#define PPI_STRING_GEN_VERSION 0.4 +#define MAX_PPI_STRING_LEN 64 +#define MAX_LEN_FIELDS_1_2_3 37 /* max length of fields ProductName + ProductUID + ProductVersion */ + +#define PPI_PREFIX_1 "?" +#define PPI_PREFIX_1_ALT "&" + +#define PPI_PREFIX_2 "Platform=APN3|" +#define PPI_RESERVED "A0|" /* reserved for AWS use */ + +#define PPI_PLATFORM_AWS "AZ|" +#define PPI_PLATFORM_RAINMAKER "RM|" +#define PPI_PLATFORM PPI_PLATFORM_RAINMAKER + +#define PPI_SILICON_SKU_CODE CONFIG_ESP_RMAKER_MQTT_PRODUCT_SKU +#define PPI_PRODUCT_NAME CONFIG_ESP_RMAKER_MQTT_PRODUCT_NAME +#define PPI_PRODUCT_VERSION CONFIG_ESP_RMAKER_MQTT_PRODUCT_VERSION + +#define PPI_SEPARATOR_CHAR '|' +#define PPI_SEPARATOR "|" + +#define PPI_FIXED_PART PPI_PREFIX_1 PPI_PREFIX_2 PPI_RESERVED PPI_PLATFORM PPI_SILICON_SKU_CODE PPI_SEPARATOR PPI_PRODUCT_NAME PPI_SEPARATOR PPI_PRODUCT_VERSION PPI_SEPARATOR + +#define VALID 1 +#define INVALID 0 + +/* + * platform_get_product_name is a stub function to be customized for each platform. + * It must return a pointer to the product name string. + * Can use a #define instead of a function in most cases. + */ +char __attribute__((weak)) *platform_get_product_name() +{ + return(PPI_PRODUCT_NAME); +} + +/* + * platform_get_product_UID is a stub function to be customized for each platform. + * It must return a pointer to the product UID string. + */ +char __attribute__((weak)) *platform_get_product_UID() +{ + static char mac_str[13]; +#if defined(CONFIG_ESP_RMAKER_NETWORK_OVER_WIFI) + uint8_t eth_mac[6]; + esp_err_t err = esp_wifi_get_mac(WIFI_IF_STA, eth_mac); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Could not fetch MAC address. Please initialise Wi-Fi first"); + return NULL; + } + snprintf(mac_str, sizeof(mac_str), "%02X%02X%02X%02X%02X%02X", + eth_mac[0], eth_mac[1], eth_mac[2], eth_mac[3], eth_mac[4], eth_mac[5]); +#elif defined(CONFIG_ESP_RMAKER_NETWORK_OVER_THREAD) /* CONFIG_ESP_RMAKER_NETWORK_OVER_WIFI */ + uint8_t base_mac[6]; + esp_err_t err = esp_read_mac(base_mac, ESP_MAC_BASE); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Could not fetch base mac"); + return NULL; + } + snprintf(mac_str, sizeof(mac_str), "%02X%02X%02X%02X%02X%02X", + base_mac[0], base_mac[1], base_mac[2], base_mac[3], base_mac[4], base_mac[5]); +#endif /* CONFIG_ESP_RMAKER_NETWORK_OVER_THREAD */ + return mac_str; +} + +/* + * platform_get_product_version is a stub function to be customized for each platform. + * It must return a pointer to the product version string. + * Can use a #define instead of a function in most cases. + */ +char __attribute__((weak)) *platform_get_product_version() +{ + return(PPI_PRODUCT_VERSION); +} + +/* + * platform_get_silicom_sku_code is a stub function to be customized for each platform. + * It must return a pointer to a valid Silicon SKU code. + * Can use a #define instead of a function in most cases. + */ +char __attribute__((weak)) *platform_get_silicon_sku_code() +{ + return(PPI_SILICON_SKU_CODE); +} + +/* + * validate_sku_code takes as input the 4 character SKU code and validates it. + * + * Returns + * VALID if valid, else INVALID + */ +int validate_sku_code(char *silicon_sku_code) +{ + int retval = INVALID; + + typedef struct sku_item_t { + /* entry in sku code lookup table */ + char *skucode; /* code corresponding to sku name */ + } sku_item; + + static sku_item skutable[] = + { + /* + * codes for partner 1 + */ + { "ES00" }, /* Older Default */ + { "EX00" }, /* Default */ + { "EX01" }, /* ESP32-C3, including 8685 */ + { "EX02" }, /* ESP32-C2, including 8684 */ + { "EX03" }, /* ESP32-S3 */ + { "EX04" }, /* ESP32 */ + { "EX05" }, /* ESP32-C5 */ + { "EX06" }, /* ESP32-S2 */ + /* + * add new entries above in any order + */ + { NULL } /* this must be the last entry */ + }; + + /* + * linear search for a matching silicon sku code entry + */ + for (sku_item *p = skutable; p->skucode != NULL; p++) + { + if (strcmp(p->skucode, silicon_sku_code) == 0) + { /* found match */ + retval = VALID; + break; + } + } + return (retval); +} + +/* + * validate_platform_inputs + * + * Returns + * VALID if inputs are valid, INVALID otherwise + */ +int validate_platform_inputs(char *product_name, char *product_uid, char *product_version, char *silicon_sku_code) +{ + int retval = INVALID; + + if ( (strlen(product_name) + strlen(product_uid) + strlen(product_version)) <= MAX_LEN_FIELDS_1_2_3) + { /* field 1,2,3 length check passed */ + + if (validate_sku_code(silicon_sku_code) == VALID) + { + retval = VALID; + } + else + { /* invalid sku code */ + ESP_LOGE(TAG, "Error: Invalid sku code"); + } + } + else + { /* invalid string length */ + ESP_LOGE(TAG, "Error: Invalid field(s) length"); + } + return(retval); +} + +/* + * create_APN_PPI_string creates the string that must be passed in the UserName field of the MQTT Connect + * packet as required by the IAP Module Incentive program. Details are given in the APN3 IoT Acceleration + * Module Incentive Program Guide-Tech- document. + * + * Inputs: + * product_name = pointer to a string holding the product name. + * product_uid = pointer to a string holding the product UID (unique id) + * product_version = version number of the product. + * silicon_sku_code = pointer to a string holding a valid SKU code as specified in the guide. + * + * Return values + * NULL if there is an error and the PPI string could not be generated, otherwise the PPI string is returned. + */ +char * create_APN_PPI_string(char *product_name, char *product_uid, char *product_version, char *silicon_sku_code) +{ + char *retval = NULL; + static char ppistring[MAX_PPI_STRING_LEN + 1]; + + + ESP_LOGD(TAG, "PPI string generator v%2.1f", PPI_STRING_GEN_VERSION); + + /* + * Validate inputs + */ + if (validate_platform_inputs(product_name, product_uid, product_version, silicon_sku_code)) + { /* valid inputs - build the string */ + snprintf(ppistring, sizeof(ppistring),"%s%s%s%s%s%s%s%s%s%s%s", + PPI_PREFIX_1, PPI_PREFIX_2, PPI_RESERVED, PPI_PLATFORM, silicon_sku_code, + PPI_SEPARATOR, product_name, PPI_SEPARATOR, product_version, PPI_SEPARATOR, + product_uid); + retval = ppistring; + } + else + { /* error - some inputs are not valid */ + ESP_LOGE(TAG, "Error: Some inputs are not valid"); + } + return(retval); +} + + +/* + * main - setup values for your platform and invoke string generator. + */ +const char __attribute__((weak)) *esp_get_aws_ppi(void) +{ + char *ppistring = NULL; + + ppistring = create_APN_PPI_string( platform_get_product_name(), + platform_get_product_UID(), + platform_get_product_version(), + platform_get_silicon_sku_code() ); + + if (ppistring != NULL) + { + ESP_LOGD(TAG, "PPI inputs pass all checks. String value is shown below:\n\n%s", ppistring); + } + else + { /* error */ + ESP_LOGE(TAG, "Error creating PPI string"); + } + return ppistring; +} diff --git a/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/src/esp-mqtt/esp-mqtt-glue.c b/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/src/esp-mqtt/esp-mqtt-glue.c new file mode 100644 index 000000000..a86ffd4d4 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/src/esp-mqtt/esp-mqtt-glue.c @@ -0,0 +1,655 @@ +// Copyright 2021 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. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 1, 0) +// Features supported in 4.1+ + +#ifdef CONFIG_ESP_RMAKER_MQTT_PORT_443 +#define ESP_RMAKER_MQTT_USE_PORT_443 +#endif + +#else + +#ifdef CONFIG_ESP_RMAKER_MQTT_PORT_443 +#warning "Certificate Bundle not supported below IDF v4.4. Using provided certificate instead." +#endif + +#endif /* !IDF4.1 */ + +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 4, 0) +// Features supported in 4.4+ + +#ifdef CONFIG_ESP_RMAKER_MQTT_USE_CERT_BUNDLE +#define ESP_RMAKER_MQTT_USE_CERT_BUNDLE +#include +#endif + +#else + +#ifdef CONFIG_ESP_RMAKER_MQTT_USE_CERT_BUNDLE +#warning "Certificate Bundle not supported below 4.4. Using provided certificate instead." +#endif + +#endif /* !IDF4.4 */ + +static const char *TAG = "esp_mqtt_glue"; + +#define MAX_MQTT_SUBSCRIPTIONS CONFIG_ESP_RMAKER_MAX_MQTT_SUBSCRIPTIONS + +/* Subscription states for tracking subscription lifecycle */ +typedef enum { + MQTT_SUB_STATE_NONE = 0, /* Not subscribed */ + MQTT_SUB_STATE_REQUESTED, /* Subscription request sent, waiting for SUBACK */ + MQTT_SUB_STATE_ACKNOWLEDGED, /* SUBACK received, subscription active */ + MQTT_SUB_STATE_FAILED /* Subscription failed */ +} mqtt_subscription_state_t; + +typedef struct { + char *topic; + esp_rmaker_mqtt_subscribe_cb_t cb; + void *priv; + mqtt_subscription_state_t state; + int msg_id; /* Message ID from last subscribe request */ + uint8_t qos; /* QoS level for this subscription */ +} esp_mqtt_glue_subscription_t; + +typedef struct { + esp_mqtt_client_handle_t mqtt_client; + esp_rmaker_mqtt_conn_params_t *conn_params; + esp_mqtt_glue_subscription_t *subscriptions[MAX_MQTT_SUBSCRIPTIONS]; +} esp_mqtt_glue_data_t; +esp_mqtt_glue_data_t *mqtt_data; + +typedef struct { + char *data; + char *topic; +} esp_mqtt_glue_long_data_t; + +static void esp_mqtt_glue_deinit(void); + +/* Helper function to reset all subscription states */ +static void esp_mqtt_glue_reset_subscription_states(void) +{ + for (int i = 0; i < MAX_MQTT_SUBSCRIPTIONS; i++) { + if (mqtt_data->subscriptions[i]) { + mqtt_data->subscriptions[i]->state = MQTT_SUB_STATE_NONE; + } + } +} + +static void esp_mqtt_glue_subscribe_callback(const char *topic, int topic_len, const char *data, int data_len) +{ + esp_mqtt_glue_subscription_t **subscriptions = mqtt_data->subscriptions; + int i; + for (i = 0; i < MAX_MQTT_SUBSCRIPTIONS; i++) { + if (subscriptions[i]) { + if ((strncmp(topic, subscriptions[i]->topic, topic_len) == 0) + && (topic_len == strlen(subscriptions[i]->topic))) { + subscriptions[i]->cb(subscriptions[i]->topic, (void *)data, data_len, subscriptions[i]->priv); + } + } + } +} + +/* + * Compatibility wrapper for ESP-IDF v5.1.2+ esp_mqtt_client_subscribe macro issue + * The _Generic macro doesn't handle const char* topic type properly in older versions + * esp_mqtt_client_subscribe_single was introduced in ESP-IDF v5.1.2 to fix this + * See: https://github.com/espressif/esp-idf/issues/13414 + */ +static inline int _esp_mqtt_client_subscribe(esp_mqtt_client_handle_t client, const char *topic, int qos) +{ +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 1, 2) + return esp_mqtt_client_subscribe_single(client, topic, qos); +#else + return esp_mqtt_client_subscribe(client, topic, qos); +#endif +} + +static esp_err_t esp_mqtt_glue_subscribe(const char *topic, esp_rmaker_mqtt_subscribe_cb_t cb, uint8_t qos, void *priv_data) +{ + if (!mqtt_data || !topic || !cb) { + return ESP_FAIL; + } + + esp_mqtt_glue_subscription_t *existing_entry = NULL; + bool topic_has_active_subscription = false; + int empty_slot = -1; + + /* Single pass: gather all the info we need */ + for (int i = 0; i < MAX_MQTT_SUBSCRIPTIONS; i++) { + if (mqtt_data->subscriptions[i]) { + if (strcmp(topic, mqtt_data->subscriptions[i]->topic) == 0) { + /* Same topic found */ + if (cb == mqtt_data->subscriptions[i]->cb) { + /* Same callback too - this is an update */ + existing_entry = mqtt_data->subscriptions[i]; + } + /* Check if this topic has an active subscription */ + if (mqtt_data->subscriptions[i]->state == MQTT_SUB_STATE_ACKNOWLEDGED) { + topic_has_active_subscription = true; + } + } + } else if (empty_slot == -1) { + empty_slot = i; + } + } + + /* Handle existing entry (same topic + same callback) */ + if (existing_entry) { + existing_entry->priv = priv_data; + + bool need_resubscribe = false; + + if (existing_entry->state != MQTT_SUB_STATE_ACKNOWLEDGED) { + /* Not acknowledged yet, need to re-subscribe */ + need_resubscribe = true; + } else if (existing_entry->qos < qos) { + /* QoS upgrade needed, re-subscribe */ + need_resubscribe = true; + ESP_LOGD(TAG, "QoS upgrade requested for topic: %s (%d->%d)", topic, existing_entry->qos, qos); + } + + if (need_resubscribe) { + int ret = _esp_mqtt_client_subscribe(mqtt_data->mqtt_client, topic, qos); + if (ret >= 0) { + existing_entry->msg_id = ret; + existing_entry->state = MQTT_SUB_STATE_REQUESTED; + existing_entry->qos = qos; + ESP_LOGD(TAG, "Re-subscribing to topic: %s (msg_id: %d, QoS: %d)", topic, ret, qos); + } else { + existing_entry->state = MQTT_SUB_STATE_FAILED; + ESP_LOGW(TAG, "Failed to re-subscribe to topic: %s", topic); + } + } + return ESP_OK; + } + + /* Need to create new entry */ + if (empty_slot == -1) { + ESP_LOGE(TAG, "No space for new subscription to topic: %s", topic); + return ESP_FAIL; + } + + /* Create and populate new subscription */ + esp_mqtt_glue_subscription_t *subscription = calloc(1, sizeof(esp_mqtt_glue_subscription_t)); + if (!subscription) { + ESP_LOGE(TAG, "Failed to allocate memory for subscription"); + return ESP_FAIL; + } + + subscription->topic = strdup(topic); + if (!subscription->topic) { + free(subscription); + ESP_LOGE(TAG, "Failed to allocate memory for topic string"); + return ESP_FAIL; + } + + subscription->priv = priv_data; + subscription->cb = cb; + subscription->qos = qos; + subscription->state = topic_has_active_subscription ? MQTT_SUB_STATE_ACKNOWLEDGED : MQTT_SUB_STATE_NONE; + + /* Add to database first */ + mqtt_data->subscriptions[empty_slot] = subscription; + + /* Send MQTT subscribe only if needed */ + if (!topic_has_active_subscription) { + int ret = _esp_mqtt_client_subscribe(mqtt_data->mqtt_client, topic, qos); + if (ret >= 0) { + subscription->msg_id = ret; + subscription->state = MQTT_SUB_STATE_REQUESTED; + ESP_LOGD(TAG, "Subscribed to topic: %s (msg_id: %d)", topic, ret); + } else { + subscription->state = MQTT_SUB_STATE_FAILED; + ESP_LOGW(TAG, "MQTT subscribe failed for topic: %s, keeping in DB for retry", topic); + } + } else { + ESP_LOGD(TAG, "Added callback for already-subscribed topic: %s", topic); + } + + return ESP_OK; +} + +static void unsubscribe_helper(esp_mqtt_glue_subscription_t **subscription) +{ + if (subscription && *subscription) { + /* Only send MQTT unsubscribe if this is the last subscription for this topic */ + bool other_subscription_exists = false; + for (int i = 0; i < MAX_MQTT_SUBSCRIPTIONS; i++) { + if (mqtt_data->subscriptions[i] && + mqtt_data->subscriptions[i] != *subscription && + strcmp(mqtt_data->subscriptions[i]->topic, (*subscription)->topic) == 0) { + other_subscription_exists = true; + break; + } + } + + if (!other_subscription_exists) { + if (esp_mqtt_client_unsubscribe(mqtt_data->mqtt_client, (*subscription)->topic) < 0) { + ESP_LOGW(TAG, "Could not unsubscribe from topic: %s", (*subscription)->topic); + } else { + ESP_LOGD(TAG, "Unsubscribed from topic: %s", (*subscription)->topic); + } + } else { + ESP_LOGD(TAG, "Not unsubscribing from topic %s - other callbacks still exist", (*subscription)->topic); + } + + free((*subscription)->topic); + free(*subscription); + *subscription = NULL; + } +} + +static esp_err_t esp_mqtt_glue_unsubscribe(const char *topic) +{ + if (!mqtt_data || !topic) { + return ESP_FAIL; + } + esp_mqtt_glue_subscription_t **subscriptions = mqtt_data->subscriptions; + int i; + for (i = 0; i < MAX_MQTT_SUBSCRIPTIONS; i++) { + if (subscriptions[i]) { + if (strncmp(topic, subscriptions[i]->topic, strlen(topic)) == 0) { + unsubscribe_helper(&subscriptions[i]); + return ESP_OK; + } + } + } + return ESP_FAIL; +} + +static esp_err_t esp_mqtt_glue_publish(const char *topic, void *data, size_t data_len, uint8_t qos, int *msg_id) +{ + if (!mqtt_data || !topic || !data) { + return ESP_FAIL; + } + ESP_LOGD(TAG, "Publishing to %s", topic); + int ret = esp_mqtt_client_publish(mqtt_data->mqtt_client, topic, data, data_len, qos, 0); + if (ret < 0) { + ESP_LOGE(TAG, "MQTT Publish failed"); + return ESP_FAIL; + } + if (msg_id) { + *msg_id = ret; + } + return ESP_OK; +} + +static esp_mqtt_glue_long_data_t *esp_mqtt_glue_free_long_data(esp_mqtt_glue_long_data_t *long_data) +{ + if (long_data) { + if (long_data->topic) { + free(long_data->topic); + } + if (long_data->data) { + free(long_data->data); + } + free(long_data); + } + return NULL; +} + +static esp_mqtt_glue_long_data_t *esp_mqtt_glue_manage_long_data(esp_mqtt_glue_long_data_t *long_data, + esp_mqtt_event_handle_t event) +{ + if (event->topic) { + /* This is new data. Free any earlier data, if present. */ + esp_mqtt_glue_free_long_data(long_data); + long_data = calloc(1, sizeof(esp_mqtt_glue_long_data_t)); + if (!long_data) { + ESP_LOGE(TAG, "Could not allocate memory for esp_mqtt_glue_long_data_t"); + return NULL; + } + long_data->data = MEM_CALLOC_EXTRAM(1, event->total_data_len); + if (!long_data->data) { + ESP_LOGE(TAG, "Could not allocate %d bytes for received data.", event->total_data_len); + return esp_mqtt_glue_free_long_data(long_data); + } + long_data->topic = strndup(event->topic, event->topic_len); + if (!long_data->topic) { + ESP_LOGE(TAG, "Could not allocate %d bytes for received topic.", event->topic_len); + return esp_mqtt_glue_free_long_data(long_data); + } + } + if (long_data) { + memcpy(long_data->data + event->current_data_offset, event->data, event->data_len); + + if ((event->current_data_offset + event->data_len) == event->total_data_len) { + esp_mqtt_glue_subscribe_callback(long_data->topic, strlen(long_data->topic), + long_data->data, event->total_data_len); + return esp_mqtt_glue_free_long_data(long_data); + } + } + return long_data; +} + +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0) +static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data) +#else +static esp_err_t mqtt_event_handler(esp_mqtt_event_handle_t event) +#endif +{ +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0) + esp_mqtt_event_handle_t event = event_data; +#else + uint32_t event_id = event->event_id; +#endif + + switch (event_id) { + case MQTT_EVENT_CONNECTED: + ESP_LOGI(TAG, "MQTT Connected"); + /* Reset all subscription states on reconnection */ + esp_mqtt_glue_reset_subscription_states(); + + /* Re-subscribe to unique topics only */ + for (int i = 0; i < MAX_MQTT_SUBSCRIPTIONS; i++) { + if (!mqtt_data->subscriptions[i]) continue; + + /* Skip if we already processed this topic */ + bool topic_already_processed = false; + for (int j = 0; j < i; j++) { + if (mqtt_data->subscriptions[j] && + strcmp(mqtt_data->subscriptions[i]->topic, mqtt_data->subscriptions[j]->topic) == 0) { + topic_already_processed = true; + break; + } + } + if (topic_already_processed) continue; + + /* Find highest QoS for this topic */ + uint8_t max_qos = mqtt_data->subscriptions[i]->qos; + for (int j = i + 1; j < MAX_MQTT_SUBSCRIPTIONS; j++) { + if (mqtt_data->subscriptions[j] && + strcmp(mqtt_data->subscriptions[i]->topic, mqtt_data->subscriptions[j]->topic) == 0 && + mqtt_data->subscriptions[j]->qos > max_qos) { + max_qos = mqtt_data->subscriptions[j]->qos; + } + } + + /* Subscribe once with highest QoS */ + int ret = _esp_mqtt_client_subscribe(event->client, mqtt_data->subscriptions[i]->topic, max_qos); + mqtt_subscription_state_t new_state = (ret >= 0) ? MQTT_SUB_STATE_REQUESTED : MQTT_SUB_STATE_FAILED; + + /* Update all subscriptions for this topic */ + for (int j = i; j < MAX_MQTT_SUBSCRIPTIONS; j++) { + if (mqtt_data->subscriptions[j] && + strcmp(mqtt_data->subscriptions[i]->topic, mqtt_data->subscriptions[j]->topic) == 0) { + mqtt_data->subscriptions[j]->msg_id = (ret >= 0) ? ret : -1; + mqtt_data->subscriptions[j]->state = new_state; + } + } + + if (ret >= 0) { + ESP_LOGD(TAG, "Reconnect: Subscribed to %s (msg_id: %d, QoS: %d)", + mqtt_data->subscriptions[i]->topic, ret, max_qos); + } else { + ESP_LOGW(TAG, "Reconnect: Failed to subscribe to %s", mqtt_data->subscriptions[i]->topic); + } + } + esp_event_post(RMAKER_COMMON_EVENT, RMAKER_MQTT_EVENT_CONNECTED, NULL, 0, portMAX_DELAY); + break; + case MQTT_EVENT_DISCONNECTED: + ESP_LOGW(TAG, "MQTT Disconnected. Will try reconnecting in a while..."); + /* Mark all subscriptions as disconnected - they'll need re-acknowledgment */ + esp_mqtt_glue_reset_subscription_states(); + esp_event_post(RMAKER_COMMON_EVENT, RMAKER_MQTT_EVENT_DISCONNECTED, NULL, 0, portMAX_DELAY); + break; + + case MQTT_EVENT_SUBSCRIBED: + ESP_LOGD(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id); + /* Mark matching subscriptions as acknowledged */ + for (int i = 0; i < MAX_MQTT_SUBSCRIPTIONS; i++) { + if (mqtt_data->subscriptions[i] && + mqtt_data->subscriptions[i]->msg_id == event->msg_id) { + mqtt_data->subscriptions[i]->state = MQTT_SUB_STATE_ACKNOWLEDGED; + ESP_LOGD(TAG, "Subscription acknowledged for topic: %s", mqtt_data->subscriptions[i]->topic); + } + } + break; + case MQTT_EVENT_UNSUBSCRIBED: + ESP_LOGD(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id); + break; + case MQTT_EVENT_PUBLISHED: + ESP_LOGD(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id); + esp_event_post(RMAKER_COMMON_EVENT, RMAKER_MQTT_EVENT_PUBLISHED, &event->msg_id, sizeof(event->msg_id), portMAX_DELAY); + break; +#ifdef CONFIG_MQTT_REPORT_DELETED_MESSAGES + case MQTT_EVENT_DELETED: + ESP_LOGD(TAG, "MQTT_EVENT_DELETED, msg_id=%d", event->msg_id); + esp_event_post(RMAKER_COMMON_EVENT, RMAKER_MQTT_EVENT_MSG_DELETED, &event->msg_id, sizeof(event->msg_id), portMAX_DELAY); + break; +#endif /* CONFIG_MQTT_REPORT_DELETED_MESSAGES */ + case MQTT_EVENT_DATA: { + ESP_LOGD(TAG, "MQTT_EVENT_DATA"); + static esp_mqtt_glue_long_data_t *long_data; + /* Topic can be NULL, for data longer than the MQTT buffer */ + if (event->topic) { + ESP_LOGD(TAG, "TOPIC=%.*s\r\n", event->topic_len, event->topic); + } + ESP_LOGD(TAG, "DATA=%.*s\r\n", event->data_len, event->data); + if (event->data_len == event->total_data_len) { + /* If long_data still exists, it means there was some issue getting the + * long data, and so, it needs to be freed up. + */ + if (long_data) { + long_data = esp_mqtt_glue_free_long_data(long_data); + } + esp_mqtt_glue_subscribe_callback(event->topic, event->topic_len, event->data, event->data_len); + } else { + long_data = esp_mqtt_glue_manage_long_data(long_data, event); + } + break; + } + case MQTT_EVENT_ERROR: + ESP_LOGE(TAG, "MQTT_EVENT_ERROR"); + break; + default: + ESP_LOGD(TAG, "Other event id:%d", event->event_id); + break; + } +#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 0, 0) + return ESP_OK; +#endif +} + +static esp_err_t esp_mqtt_glue_connect(void) +{ + if (!mqtt_data) { + return ESP_FAIL; + } + ESP_LOGI(TAG, "Connecting to %s", mqtt_data->conn_params->mqtt_host); + esp_err_t ret = esp_mqtt_client_start(mqtt_data->mqtt_client); + if (ret != ESP_OK) { + ESP_LOGE(TAG, "esp_mqtt_client_start() failed with err = %d", ret); + return ret; + } + return ESP_OK; +} + +static void esp_mqtt_glue_unsubscribe_all(void) +{ + if (!mqtt_data) { + return; + } + int i; + for (i = 0; i < MAX_MQTT_SUBSCRIPTIONS; i++) { + if (mqtt_data->subscriptions[i]) { + unsubscribe_helper(&(mqtt_data->subscriptions[i])); + } + } +} + +static esp_err_t esp_mqtt_glue_disconnect(void) +{ + if (!mqtt_data) { + return ESP_FAIL; + } + esp_mqtt_glue_unsubscribe_all(); + esp_err_t err = esp_mqtt_client_stop(mqtt_data->mqtt_client); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to disconnect from MQTT"); + } else { + ESP_LOGI(TAG, "MQTT Disconnected."); + } + return err; +} +#ifdef ESP_RMAKER_MQTT_USE_PORT_443 +static const char *alpn_protocols[] = { "x-amzn-mqtt-ca", NULL }; +#endif /* ESP_RMAKER_MQTT_USE_PORT_443 */ +static esp_err_t esp_mqtt_glue_init(esp_rmaker_mqtt_conn_params_t *conn_params) +{ +#ifdef CONFIG_ESP_RMAKER_MQTT_SEND_USERNAME + const char *username = esp_get_aws_ppi(); + ESP_LOGI(TAG, "AWS PPI: %s", username); +#endif + if (mqtt_data) { + ESP_LOGE(TAG, "MQTT already initialized"); + return ESP_OK; + } + if (!conn_params) { + ESP_LOGE(TAG, "Connection params are mandatory for esp_mqtt_glue_init"); + return ESP_FAIL; + } + ESP_LOGI(TAG, "Initialising MQTT"); + mqtt_data = calloc(1, sizeof(esp_mqtt_glue_data_t)); + if (!mqtt_data) { + ESP_LOGE(TAG, "Failed to allocate memory for esp_mqtt_glue_data_t"); + return ESP_ERR_NO_MEM; + } + mqtt_data->conn_params = conn_params; + +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0) + const esp_mqtt_client_config_t mqtt_client_cfg = { + .broker = { + .address = { + .hostname = conn_params->mqtt_host, +#ifdef ESP_RMAKER_MQTT_USE_PORT_443 + .port = 443, +#else + .port = 8883, +#endif + .transport = MQTT_TRANSPORT_OVER_SSL, + }, + .verification = { +#ifdef ESP_RMAKER_MQTT_USE_PORT_443 + .alpn_protos = alpn_protocols, +#endif +#ifdef ESP_RMAKER_MQTT_USE_CERT_BUNDLE + .crt_bundle_attach = esp_crt_bundle_attach, +#else + .certificate = (const char *)conn_params->server_cert, + .certificate_len = conn_params->server_cert_len, +#endif + } + }, + .credentials = { +#ifdef CONFIG_ESP_RMAKER_MQTT_SEND_USERNAME + .username = username, +#endif + .client_id = (const char *)conn_params->client_id, + .authentication = { + .certificate = (const char *)conn_params->client_cert, + .certificate_len = conn_params->client_cert_len, + .key = (const char *)conn_params->client_key, + .key_len = conn_params->client_key_len, + .ds_data = conn_params->ds_data + }, + }, + .session = { + .keepalive = CONFIG_ESP_RMAKER_MQTT_KEEP_ALIVE_INTERVAL, +#ifdef CONFIG_ESP_RMAKER_MQTT_PERSISTENT_SESSION + .disable_clean_session = 1, +#endif /* CONFIG_ESP_RMAKER_MQTT_PERSISTENT_SESSION */ + }, + }; +#else + const esp_mqtt_client_config_t mqtt_client_cfg = { + .host = conn_params->mqtt_host, +#ifdef ESP_RMAKER_MQTT_USE_PORT_443 + .port = 443, + .alpn_protos = alpn_protocols, +#else + .port = 8883, +#endif /* !ESP_RMAKER_MQTT_USE_PORT_443 */ +#ifdef ESP_RMAKER_MQTT_USE_CERT_BUNDLE + .crt_bundle_attach = esp_crt_bundle_attach, +#else + .cert_pem = (const char *)conn_params->server_cert, + .cert_len = conn_params->server_cert_len, +#endif + .client_cert_pem = (const char *)conn_params->client_cert, + .client_cert_len = conn_params->client_cert_len, + .client_key_pem = (const char *)conn_params->client_key, + .client_key_len = conn_params->client_key_len, + .client_id = (const char *)conn_params->client_id, + .keepalive = CONFIG_ESP_RMAKER_MQTT_KEEP_ALIVE_INTERVAL, + .event_handle = mqtt_event_handler, + .transport = MQTT_TRANSPORT_OVER_SSL, +#ifdef CONFIG_ESP_RMAKER_MQTT_PERSISTENT_SESSION + .disable_clean_session = 1, +#endif /* CONFIG_ESP_RMAKER_MQTT_PERSISTENT_SESSION */ +#ifdef CONFIG_ESP_RMAKER_MQTT_SEND_USERNAME + .username = username, +#endif + }; +#endif + mqtt_data->mqtt_client = esp_mqtt_client_init(&mqtt_client_cfg); + if (!mqtt_data->mqtt_client) { + ESP_LOGE(TAG, "esp_mqtt_client_init failed"); + esp_mqtt_glue_deinit(); + return ESP_FAIL; + } +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0) + esp_mqtt_client_register_event(mqtt_data->mqtt_client , ESP_EVENT_ANY_ID, mqtt_event_handler, NULL); +#endif + return ESP_OK; +} + +static void esp_mqtt_glue_deinit(void) +{ + esp_mqtt_glue_unsubscribe_all(); + if (mqtt_data && mqtt_data->mqtt_client) { + esp_mqtt_client_destroy(mqtt_data->mqtt_client); + } + if (mqtt_data) { + free(mqtt_data); + mqtt_data = NULL; + } +} + +esp_err_t esp_rmaker_mqtt_glue_setup(esp_rmaker_mqtt_config_t *mqtt_config) +{ + mqtt_config->init = esp_mqtt_glue_init; + mqtt_config->deinit = esp_mqtt_glue_deinit; + mqtt_config->connect = esp_mqtt_glue_connect; + mqtt_config->disconnect = esp_mqtt_glue_disconnect; + mqtt_config->publish = esp_mqtt_glue_publish; + mqtt_config->subscribe = esp_mqtt_glue_subscribe; + mqtt_config->unsubscribe = esp_mqtt_glue_unsubscribe; + mqtt_config->setup_done = true; + return ESP_OK; +} diff --git a/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/src/factory.c b/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/src/factory.c new file mode 100644 index 000000000..c7a3ba354 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/src/factory.c @@ -0,0 +1,120 @@ +// Copyright 2021 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. +#include +#include +#include +#include +#include +#include + +static const char *TAG = "esp_rmaker_fctry"; + +#define RMAKER_FACTORY_NAMESPACE CONFIG_ESP_RMAKER_FACTORY_NAMESPACE +#define RMAKER_FACTORY_PART CONFIG_ESP_RMAKER_FACTORY_PARTITION_NAME + +esp_err_t esp_rmaker_factory_init(void) +{ + static bool esp_rmaker_storage_init_done; + if (esp_rmaker_storage_init_done) { + ESP_LOGW(TAG, "ESP RainMaker Storage already initialized"); + return ESP_OK; + } + esp_err_t err = ESP_OK; +#ifdef CONFIG_ESP_RMAKER_ENCRYPT_FACTORY_PARTITION + const char *nvs_keys_partition_name = CONFIG_ESP_RMAKER_FACTORY_NVS_KEYS_PARTITION_NAME; + if (strlen(nvs_keys_partition_name) == 0) { + nvs_keys_partition_name = NULL; + } + ESP_LOGI(TAG, "Initialising factory partition in secure mode."); + const esp_partition_t* key_part = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_NVS_KEYS, nvs_keys_partition_name); + if (!key_part) { + ESP_LOGE(TAG, "Partition with subtype nvs_keys not found"); + return ESP_FAIL; + } + nvs_sec_cfg_t cfg = {}; + err = nvs_flash_read_security_cfg(key_part, &cfg); + if (err != ESP_OK) { + ESP_LOGE(TAG, "Failed to read NVS security cfg: 0x%x", err); + return err; + } + err = nvs_flash_secure_init_partition(RMAKER_FACTORY_PART, &cfg); +#else + err = nvs_flash_init_partition(RMAKER_FACTORY_PART); +#endif + if (err != ESP_OK) { + ESP_LOGE(TAG, "NVS Flash init failed"); + } else { + esp_rmaker_storage_init_done = true; + } + return err; +} + +void *esp_rmaker_factory_get(const char *key) +{ + nvs_handle handle; + esp_err_t err; + if ((err = nvs_open_from_partition(RMAKER_FACTORY_PART, RMAKER_FACTORY_NAMESPACE, + NVS_READONLY, &handle)) != ESP_OK) { + ESP_LOGD(TAG, "NVS open for %s %s %s failed with error %d", RMAKER_FACTORY_PART, RMAKER_FACTORY_NAMESPACE, key, err); + return NULL; + } + size_t required_size = 0; + if ((err = nvs_get_blob(handle, key, NULL, &required_size)) != ESP_OK) { + ESP_LOGD(TAG, "Failed to read key %s with error %d size %d", key, err, required_size); + nvs_close(handle); + return NULL; + } + void *value = MEM_CALLOC_EXTRAM(required_size + 1, 1); /* + 1 for NULL termination */ + if (value) { + nvs_get_blob(handle, key, value, &required_size); + } + nvs_close(handle); + return value; +} + +size_t esp_rmaker_factory_get_size(const char *key) +{ + nvs_handle handle; + esp_err_t err; + if ((err = nvs_open_from_partition(RMAKER_FACTORY_PART, RMAKER_FACTORY_NAMESPACE, + NVS_READONLY, &handle)) != ESP_OK) { + ESP_LOGD(TAG, "NVS open for %s %s %s failed with error %d", RMAKER_FACTORY_PART, RMAKER_FACTORY_NAMESPACE, key, err); + return 0; + } + size_t required_size = 0; + if ((err = nvs_get_blob(handle, key, NULL, &required_size)) != ESP_OK) { + ESP_LOGD(TAG, "Failed to read key %s with error %d size %d", key, err, required_size); + } + nvs_close(handle); + return required_size; +} + +esp_err_t esp_rmaker_factory_set(const char *key, void *value, size_t len) +{ + nvs_handle handle; + esp_err_t err; + if ((err = nvs_open_from_partition(RMAKER_FACTORY_PART, RMAKER_FACTORY_NAMESPACE, + NVS_READWRITE, &handle)) != ESP_OK) { + ESP_LOGE(TAG, "NVS open failed with error %d", err); + return ESP_FAIL; + } + if ((err = nvs_set_blob(handle, key, value, len)) != ESP_OK) { + ESP_LOGE(TAG, "Failed to write key %s with error %d size %d", key, err, len); + nvs_close(handle); + return ESP_FAIL; + } + nvs_commit(handle); + nvs_close(handle); + return ESP_OK; +} diff --git a/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/src/time.c b/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/src/time.c new file mode 100644 index 000000000..363a50cbc --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/src/time.c @@ -0,0 +1,277 @@ +// Copyright 2021 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. + +#include +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 1, 0) +#include +#else +#include +#endif + +#include +#include +#include +#include +#include +#include +#include + +static const char *TAG = "esp_rmaker_time"; + +#define ESP_RMAKER_NVS_PART_NAME "nvs" + +#define ESP_RMAKER_NVS_TIME_NAMESPACE "rmaker_time" +#define ESP_RMAKER_TZ_POSIX_NVS_NAME "tz_posix" +#define ESP_RMAKER_TZ_NVS_NAME "tz" + +#define REF_TIME 1546300800 /* 01-Jan-2019 00:00:00 */ +static bool init_done = false; +extern const char *esp_rmaker_tz_db_get_posix_str(const char *name); + +#define ESP_RMAKER_DEF_TZ CONFIG_ESP_RMAKER_DEF_TIMEZONE + +int esp_setenv(const char *name, const char *value, int rewrite) +{ +/* IDF version lower than v4.4.3 not support parse bracket POSIX TZ in newlib. + Wrap setenv function to convert bracket POSIX TZ, such as <+08>-8 to TZ-08 */ +#if ESP_IDF_VERSION <= ESP_IDF_VERSION_VAL(4, 4, 3) +#define ESP_TZNAME_MIN 3 +#define ESP_TZNAME_MAX 10 + if (value) { + const char *tzenv = value; + if (*tzenv == '<') { + ++ tzenv; + char tzname[ESP_TZNAME_MIN + 1] = {0}; + char real_value[6] = {0}; + int n = 0; + if (sscanf(tzenv, "%10[-+0-9A-Za-z]%n", tzname, &n) <= 0 || n < ESP_TZNAME_MIN || n > ESP_TZNAME_MAX || '>' != tzenv[n]) { + ESP_LOGW(TAG, "Failed to convert Posix TZ %s", value); + goto exit; + } + tzname[0] = (tzname[0] == '-') ? '+' : '-'; + sprintf(real_value, "TZ%s", tzname); + ESP_LOGI(TAG, "Real Posix TZ is %s", real_value); + return setenv(name, real_value, rewrite); + } + } +exit: +#endif + return setenv(name, value, rewrite); +} + +esp_err_t esp_rmaker_get_local_time_str(char *buf, size_t buf_len) +{ + struct tm timeinfo; + char strftime_buf[64]; + time_t now; + time(&now); + localtime_r(&now, &timeinfo); + strftime(strftime_buf, sizeof(strftime_buf), "%c %z[%Z]", &timeinfo); + size_t print_size = snprintf(buf, buf_len, "%s, DST: %s", strftime_buf, timeinfo.tm_isdst ? "Yes" : "No"); + if (print_size >= buf_len) { + ESP_LOGE(TAG, "Buffer size %d insufficient for localtime string. Required size: %d", buf_len, print_size); + return ESP_ERR_INVALID_ARG; + } + return ESP_OK; +} + +static esp_err_t esp_rmaker_print_current_time(void) +{ + char local_time[64]; + if (esp_rmaker_get_local_time_str(local_time, sizeof(local_time)) == ESP_OK) { + if (esp_rmaker_time_check() == false) { + ESP_LOGI(TAG, "Time not synchronised yet."); + } + ESP_LOGI(TAG, "The current time is: %s.", local_time); + return ESP_OK; + } + return ESP_FAIL; +} + +static char *__esp_rmaker_time_get_nvs(const char *key) +{ + char *val = NULL; + nvs_handle handle; + esp_err_t err = nvs_open_from_partition(ESP_RMAKER_NVS_PART_NAME, ESP_RMAKER_NVS_TIME_NAMESPACE, NVS_READONLY, &handle); + if (err != ESP_OK) { + return NULL; + } + size_t len = 0; + if ((err = nvs_get_blob(handle, key, NULL, &len)) == ESP_OK) { + val = MEM_CALLOC_EXTRAM(1, len + 1); /* +1 for NULL termination */ + if (val) { + nvs_get_blob(handle, key, val, &len); + } + } + nvs_close(handle); + return val; + +} + +static esp_err_t __esp_rmaker_time_set_nvs(const char *key, const char *val) +{ + nvs_handle handle; + esp_err_t err = nvs_open_from_partition(ESP_RMAKER_NVS_PART_NAME, ESP_RMAKER_NVS_TIME_NAMESPACE, NVS_READWRITE, &handle); + if (err != ESP_OK) { + return err; + } + err = nvs_set_blob(handle, key, val, strlen(val)); + nvs_commit(handle); + nvs_close(handle); + return err; +} + +char *esp_rmaker_time_get_timezone_posix(void) +{ + return __esp_rmaker_time_get_nvs(ESP_RMAKER_TZ_POSIX_NVS_NAME); +} + +char *esp_rmaker_time_get_timezone(void) +{ + return __esp_rmaker_time_get_nvs(ESP_RMAKER_TZ_NVS_NAME); +} + +esp_err_t esp_rmaker_time_set_timezone_posix(const char *tz_posix) +{ + esp_err_t err = __esp_rmaker_time_set_nvs(ESP_RMAKER_TZ_POSIX_NVS_NAME, tz_posix); + if (err == ESP_OK) { + esp_setenv("TZ", tz_posix, 1); + tzset(); + esp_event_post(RMAKER_COMMON_EVENT, RMAKER_EVENT_TZ_POSIX_CHANGED, + (void *)tz_posix, strlen(tz_posix) + 1, portMAX_DELAY); + esp_rmaker_print_current_time(); + } + return err; +} + +esp_err_t esp_rmaker_time_set_timezone(const char *tz) +{ + const char *tz_posix = esp_rmaker_tz_db_get_posix_str(tz); + if (!tz_posix) { + return ESP_ERR_INVALID_ARG; + } + esp_err_t err = esp_rmaker_time_set_timezone_posix(tz_posix); + if (err == ESP_OK) { + esp_event_post(RMAKER_COMMON_EVENT, RMAKER_EVENT_TZ_CHANGED, (void *)tz, + strlen(tz) + 1, portMAX_DELAY); + err = __esp_rmaker_time_set_nvs(ESP_RMAKER_TZ_NVS_NAME, tz); + } + return err; +} + +esp_err_t esp_rmaker_timezone_enable(void) +{ + char *tz_posix = esp_rmaker_time_get_timezone_posix(); + if (tz_posix) { + esp_setenv("TZ", tz_posix, 1); + tzset(); + free(tz_posix); + } else { + if (strlen(ESP_RMAKER_DEF_TZ) > 0) { + const char *tz_def = esp_rmaker_tz_db_get_posix_str(ESP_RMAKER_DEF_TZ); + if (tz_def) { + esp_setenv("TZ", tz_def, 1); + tzset(); + return ESP_OK; + } else { + ESP_LOGE(TAG, "Invalid Timezone %s specified.", ESP_RMAKER_DEF_TZ); + return ESP_ERR_INVALID_ARG; + } + } + } + return ESP_OK; +} +static void esp_rmaker_time_sync_cb(struct timeval *tv) +{ + ESP_LOGI(TAG, "SNTP Synchronised."); + esp_rmaker_print_current_time(); +} + +esp_err_t esp_rmaker_time_sync_init(esp_rmaker_time_config_t *config) +{ +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 1, 0) + if (esp_sntp_enabled()) { +#else + if (sntp_enabled()) { +#endif + ESP_LOGI(TAG, "SNTP already initialized."); + init_done = true; + return ESP_OK; + } + char *sntp_server_name; + if (!config || !config->sntp_server_name) { + sntp_server_name = CONFIG_ESP_RMAKER_SNTP_SERVER_NAME; + } else { + sntp_server_name = config->sntp_server_name; + } + ESP_LOGI(TAG, "Initializing SNTP. Using the SNTP server: %s", sntp_server_name); +#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 1, 0) + esp_sntp_setoperatingmode(SNTP_OPMODE_POLL); + esp_sntp_setservername(0, sntp_server_name); + esp_sntp_init(); +#else + sntp_setoperatingmode(SNTP_OPMODE_POLL); + sntp_setservername(0, sntp_server_name); + sntp_init(); +#endif + if (config && config->sync_time_cb) { + sntp_set_time_sync_notification_cb(config->sync_time_cb); + } else { + sntp_set_time_sync_notification_cb(esp_rmaker_time_sync_cb); + } + esp_rmaker_timezone_enable(); + init_done = true; + return ESP_OK; +} + +bool esp_rmaker_time_check(void) +{ + time_t now; + time(&now); + if (now > REF_TIME) { + return true; + } + return false; +} + +#define DEFAULT_TICKS (2000 / portTICK_PERIOD_MS) /* 2 seconds in ticks */ + +esp_err_t esp_rmaker_time_wait_for_sync(uint32_t ticks_to_wait) +{ + if (!init_done) { + ESP_LOGW(TAG, "Time sync not initialized using 'esp_rmaker_time_sync_init'"); + } + ESP_LOGW(TAG, "Waiting for time to be synchronized. This may take time."); + uint32_t ticks_remaining = ticks_to_wait; + uint32_t ticks = DEFAULT_TICKS; + while (ticks_remaining > 0) { + if (esp_rmaker_time_check() == true) { + break; + } + ESP_LOGD(TAG, "Time not synchronized yet. Retrying..."); + ticks = ticks_remaining < DEFAULT_TICKS ? ticks_remaining : DEFAULT_TICKS; + ticks_remaining -= ticks; + vTaskDelay(ticks); + } + + /* Check if ticks_to_wait expired and time is not synchronized yet. */ + if (esp_rmaker_time_check() == false) { + ESP_LOGE(TAG, "Time not synchronized within the provided ticks: %" PRIu32, ticks_to_wait); + return ESP_FAIL; + } + + /* Get current time */ + esp_rmaker_print_current_time(); + return ESP_OK; +} diff --git a/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/src/timezone.c b/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/src/timezone.c new file mode 100644 index 000000000..e69eed1c1 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/src/timezone.c @@ -0,0 +1,516 @@ +// MIT License +// +// Copyright (c) 2020 Nayar Systems +// Copyright (c) 2020 Jacob Lambert +// Copyright 2021 Espressif Systems (Shanghai) PTE LTD +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +// Original code taken from: https://github.com/jdlambert/micro_tz_db +// which was forked from https://github.com/nayarsystems/posix_tz_db + +#include + +typedef struct { + const char *name; + const char *posix_str; +} esp_rmaker_tz_db_pair_t; + +static const esp_rmaker_tz_db_pair_t esp_rmaker_tz_db_tzs[] = { + {"Africa/Abidjan", "GMT0"}, + {"Africa/Accra", "GMT0"}, + {"Africa/Addis_Ababa", "EAT-3"}, + {"Africa/Algiers", "CET-1"}, + {"Africa/Asmara", "EAT-3"}, + {"Africa/Bamako", "GMT0"}, + {"Africa/Bangui", "WAT-1"}, + {"Africa/Banjul", "GMT0"}, + {"Africa/Bissau", "GMT0"}, + {"Africa/Blantyre", "CAT-2"}, + {"Africa/Brazzaville", "WAT-1"}, + {"Africa/Bujumbura", "CAT-2"}, + {"Africa/Cairo", "EET-2"}, + {"Africa/Casablanca", "<+01>-1"}, + {"Africa/Ceuta", "CET-1CEST,M3.5.0,M10.5.0/3"}, + {"Africa/Conakry", "GMT0"}, + {"Africa/Dakar", "GMT0"}, + {"Africa/Dar_es_Salaam", "EAT-3"}, + {"Africa/Djibouti", "EAT-3"}, + {"Africa/Douala", "WAT-1"}, + {"Africa/El_Aaiun", "<+01>-1"}, + {"Africa/Freetown", "GMT0"}, + {"Africa/Gaborone", "CAT-2"}, + {"Africa/Harare", "CAT-2"}, + {"Africa/Johannesburg", "SAST-2"}, + {"Africa/Juba", "EAT-3"}, + {"Africa/Kampala", "EAT-3"}, + {"Africa/Khartoum", "CAT-2"}, + {"Africa/Kigali", "CAT-2"}, + {"Africa/Kinshasa", "WAT-1"}, + {"Africa/Lagos", "WAT-1"}, + {"Africa/Libreville", "WAT-1"}, + {"Africa/Lome", "GMT0"}, + {"Africa/Luanda", "WAT-1"}, + {"Africa/Lubumbashi", "CAT-2"}, + {"Africa/Lusaka", "CAT-2"}, + {"Africa/Malabo", "WAT-1"}, + {"Africa/Maputo", "CAT-2"}, + {"Africa/Maseru", "SAST-2"}, + {"Africa/Mbabane", "SAST-2"}, + {"Africa/Mogadishu", "EAT-3"}, + {"Africa/Monrovia", "GMT0"}, + {"Africa/Nairobi", "EAT-3"}, + {"Africa/Ndjamena", "WAT-1"}, + {"Africa/Niamey", "WAT-1"}, + {"Africa/Nouakchott", "GMT0"}, + {"Africa/Ouagadougou", "GMT0"}, + {"Africa/Porto-Novo", "WAT-1"}, + {"Africa/Sao_Tome", "GMT0"}, + {"Africa/Tripoli", "EET-2"}, + {"Africa/Tunis", "CET-1"}, + {"Africa/Windhoek", "CAT-2"}, + {"America/Adak", "HST10HDT,M3.2.0,M11.1.0"}, + {"America/Anchorage", "AKST9AKDT,M3.2.0,M11.1.0"}, + {"America/Anguilla", "AST4"}, + {"America/Antigua", "AST4"}, + {"America/Araguaina", "<-03>3"}, + {"America/Argentina/Buenos_Aires", "<-03>3"}, + {"America/Argentina/Catamarca", "<-03>3"}, + {"America/Argentina/Cordoba", "<-03>3"}, + {"America/Argentina/Jujuy", "<-03>3"}, + {"America/Argentina/La_Rioja", "<-03>3"}, + {"America/Argentina/Mendoza", "<-03>3"}, + {"America/Argentina/Rio_Gallegos", "<-03>3"}, + {"America/Argentina/Salta", "<-03>3"}, + {"America/Argentina/San_Juan", "<-03>3"}, + {"America/Argentina/San_Luis", "<-03>3"}, + {"America/Argentina/Tucuman", "<-03>3"}, + {"America/Argentina/Ushuaia", "<-03>3"}, + {"America/Aruba", "AST4"}, + {"America/Asuncion", "<-04>4<-03>,M10.1.0/0,M3.4.0/0"}, + {"America/Atikokan", "EST5"}, + {"America/Bahia", "<-03>3"}, + {"America/Bahia_Banderas", "CST6CDT,M4.1.0,M10.5.0"}, + {"America/Barbados", "AST4"}, + {"America/Belem", "<-03>3"}, + {"America/Belize", "CST6"}, + {"America/Blanc-Sablon", "AST4"}, + {"America/Boa_Vista", "<-04>4"}, + {"America/Bogota", "<-05>5"}, + {"America/Boise", "MST7MDT,M3.2.0,M11.1.0"}, + {"America/Cambridge_Bay", "MST7MDT,M3.2.0,M11.1.0"}, + {"America/Campo_Grande", "<-04>4"}, + {"America/Cancun", "EST5"}, + {"America/Caracas", "<-04>4"}, + {"America/Cayenne", "<-03>3"}, + {"America/Cayman", "EST5"}, + {"America/Chicago", "CST6CDT,M3.2.0,M11.1.0"}, + {"America/Chihuahua", "MST7MDT,M4.1.0,M10.5.0"}, + {"America/Costa_Rica", "CST6"}, + {"America/Creston", "MST7"}, + {"America/Cuiaba", "<-04>4"}, + {"America/Curacao", "AST4"}, + {"America/Danmarkshavn", "GMT0"}, + {"America/Dawson", "MST7"}, + {"America/Dawson_Creek", "MST7"}, + {"America/Denver", "MST7MDT,M3.2.0,M11.1.0"}, + {"America/Detroit", "EST5EDT,M3.2.0,M11.1.0"}, + {"America/Dominica", "AST4"}, + {"America/Edmonton", "MST7MDT,M3.2.0,M11.1.0"}, + {"America/Eirunepe", "<-05>5"}, + {"America/El_Salvador", "CST6"}, + {"America/Fortaleza", "<-03>3"}, + {"America/Fort_Nelson", "MST7"}, + {"America/Glace_Bay", "AST4ADT,M3.2.0,M11.1.0"}, + {"America/Godthab", "<-03>3<-02>,M3.5.0/-2,M10.5.0/-1"}, + {"America/Goose_Bay", "AST4ADT,M3.2.0,M11.1.0"}, + {"America/Grand_Turk", "EST5EDT,M3.2.0,M11.1.0"}, + {"America/Grenada", "AST4"}, + {"America/Guadeloupe", "AST4"}, + {"America/Guatemala", "CST6"}, + {"America/Guayaquil", "<-05>5"}, + {"America/Guyana", "<-04>4"}, + {"America/Halifax", "AST4ADT,M3.2.0,M11.1.0"}, + {"America/Havana", "CST5CDT,M3.2.0/0,M11.1.0/1"}, + {"America/Hermosillo", "MST7"}, + {"America/Indiana/Indianapolis", "EST5EDT,M3.2.0,M11.1.0"}, + {"America/Indiana/Knox", "CST6CDT,M3.2.0,M11.1.0"}, + {"America/Indiana/Marengo", "EST5EDT,M3.2.0,M11.1.0"}, + {"America/Indiana/Petersburg", "EST5EDT,M3.2.0,M11.1.0"}, + {"America/Indiana/Tell_City", "CST6CDT,M3.2.0,M11.1.0"}, + {"America/Indiana/Vevay", "EST5EDT,M3.2.0,M11.1.0"}, + {"America/Indiana/Vincennes", "EST5EDT,M3.2.0,M11.1.0"}, + {"America/Indiana/Winamac", "EST5EDT,M3.2.0,M11.1.0"}, + {"America/Inuvik", "MST7MDT,M3.2.0,M11.1.0"}, + {"America/Iqaluit", "EST5EDT,M3.2.0,M11.1.0"}, + {"America/Jamaica", "EST5"}, + {"America/Juneau", "AKST9AKDT,M3.2.0,M11.1.0"}, + {"America/Kentucky/Louisville", "EST5EDT,M3.2.0,M11.1.0"}, + {"America/Kentucky/Monticello", "EST5EDT,M3.2.0,M11.1.0"}, + {"America/Kralendijk", "AST4"}, + {"America/La_Paz", "<-04>4"}, + {"America/Lima", "<-05>5"}, + {"America/Los_Angeles", "PST8PDT,M3.2.0,M11.1.0"}, + {"America/Lower_Princes", "AST4"}, + {"America/Maceio", "<-03>3"}, + {"America/Managua", "CST6"}, + {"America/Manaus", "<-04>4"}, + {"America/Marigot", "AST4"}, + {"America/Martinique", "AST4"}, + {"America/Matamoros", "CST6CDT,M3.2.0,M11.1.0"}, + {"America/Mazatlan", "MST7MDT,M4.1.0,M10.5.0"}, + {"America/Menominee", "CST6CDT,M3.2.0,M11.1.0"}, + {"America/Merida", "CST6CDT,M4.1.0,M10.5.0"}, + {"America/Metlakatla", "AKST9AKDT,M3.2.0,M11.1.0"}, + {"America/Mexico_City", "CST6CDT,M4.1.0,M10.5.0"}, + {"America/Miquelon", "<-03>3<-02>,M3.2.0,M11.1.0"}, + {"America/Moncton", "AST4ADT,M3.2.0,M11.1.0"}, + {"America/Monterrey", "CST6CDT,M4.1.0,M10.5.0"}, + {"America/Montevideo", "<-03>3"}, + {"America/Montreal", "EST5EDT,M3.2.0,M11.1.0"}, + {"America/Montserrat", "AST4"}, + {"America/Nassau", "EST5EDT,M3.2.0,M11.1.0"}, + {"America/New_York", "EST5EDT,M3.2.0,M11.1.0"}, + {"America/Nipigon", "EST5EDT,M3.2.0,M11.1.0"}, + {"America/Nome", "AKST9AKDT,M3.2.0,M11.1.0"}, + {"America/Noronha", "<-02>2"}, + {"America/North_Dakota/Beulah", "CST6CDT,M3.2.0,M11.1.0"}, + {"America/North_Dakota/Center", "CST6CDT,M3.2.0,M11.1.0"}, + {"America/North_Dakota/New_Salem", "CST6CDT,M3.2.0,M11.1.0"}, + {"America/Ojinaga", "MST7MDT,M3.2.0,M11.1.0"}, + {"America/Panama", "EST5"}, + {"America/Pangnirtung", "EST5EDT,M3.2.0,M11.1.0"}, + {"America/Paramaribo", "<-03>3"}, + {"America/Phoenix", "MST7"}, + {"America/Port-au-Prince", "EST5EDT,M3.2.0,M11.1.0"}, + {"America/Port_of_Spain", "AST4"}, + {"America/Porto_Velho", "<-04>4"}, + {"America/Puerto_Rico", "AST4"}, + {"America/Punta_Arenas", "<-03>3"}, + {"America/Rainy_River", "CST6CDT,M3.2.0,M11.1.0"}, + {"America/Rankin_Inlet", "CST6CDT,M3.2.0,M11.1.0"}, + {"America/Recife", "<-03>3"}, + {"America/Regina", "CST6"}, + {"America/Resolute", "CST6CDT,M3.2.0,M11.1.0"}, + {"America/Rio_Branco", "<-05>5"}, + {"America/Santarem", "<-03>3"}, + {"America/Santiago", "<-04>4<-03>,M9.1.6/24,M4.1.6/24"}, + {"America/Santo_Domingo", "AST4"}, + {"America/Sao_Paulo", "<-03>3"}, + {"America/Scoresbysund", "<-01>1<+00>,M3.5.0/0,M10.5.0/1"}, + {"America/Sitka", "AKST9AKDT,M3.2.0,M11.1.0"}, + {"America/St_Barthelemy", "AST4"}, + {"America/St_Johns", "NST3:30NDT,M3.2.0,M11.1.0"}, + {"America/St_Kitts", "AST4"}, + {"America/St_Lucia", "AST4"}, + {"America/St_Thomas", "AST4"}, + {"America/St_Vincent", "AST4"}, + {"America/Swift_Current", "CST6"}, + {"America/Tegucigalpa", "CST6"}, + {"America/Thule", "AST4ADT,M3.2.0,M11.1.0"}, + {"America/Thunder_Bay", "EST5EDT,M3.2.0,M11.1.0"}, + {"America/Tijuana", "PST8PDT,M3.2.0,M11.1.0"}, + {"America/Toronto", "EST5EDT,M3.2.0,M11.1.0"}, + {"America/Tortola", "AST4"}, + {"America/Vancouver", "PST8PDT,M3.2.0,M11.1.0"}, + {"America/Whitehorse", "MST7"}, + {"America/Winnipeg", "CST6CDT,M3.2.0,M11.1.0"}, + {"America/Yakutat", "AKST9AKDT,M3.2.0,M11.1.0"}, + {"America/Yellowknife", "MST7MDT,M3.2.0,M11.1.0"}, + {"Antarctica/Casey", "<+08>-8"}, + {"Antarctica/Davis", "<+07>-7"}, + {"Antarctica/DumontDUrville", "<+10>-10"}, + {"Antarctica/Macquarie", "<+11>-11"}, + {"Antarctica/Mawson", "<+05>-5"}, + {"Antarctica/McMurdo", "NZST-12NZDT,M9.5.0,M4.1.0/3"}, + {"Antarctica/Palmer", "<-03>3"}, + {"Antarctica/Rothera", "<-03>3"}, + {"Antarctica/Syowa", "<+03>-3"}, + {"Antarctica/Troll", "<+00>0<+02>-2,M3.5.0/1,M10.5.0/3"}, + {"Antarctica/Vostok", "<+06>-6"}, + {"Arctic/Longyearbyen", "CET-1CEST,M3.5.0,M10.5.0/3"}, + {"Asia/Aden", "<+03>-3"}, + {"Asia/Almaty", "<+06>-6"}, + {"Asia/Amman", "EET-2EEST,M3.5.4/24,M10.5.5/1"}, + {"Asia/Anadyr", "<+12>-12"}, + {"Asia/Aqtau", "<+05>-5"}, + {"Asia/Aqtobe", "<+05>-5"}, + {"Asia/Ashgabat", "<+05>-5"}, + {"Asia/Atyrau", "<+05>-5"}, + {"Asia/Baghdad", "<+03>-3"}, + {"Asia/Bahrain", "<+03>-3"}, + {"Asia/Baku", "<+04>-4"}, + {"Asia/Bangkok", "<+07>-7"}, + {"Asia/Barnaul", "<+07>-7"}, + {"Asia/Beirut", "EET-2EEST,M3.5.0/0,M10.5.0/0"}, + {"Asia/Bishkek", "<+06>-6"}, + {"Asia/Brunei", "<+08>-8"}, + {"Asia/Chita", "<+09>-9"}, + {"Asia/Choibalsan", "<+08>-8"}, + {"Asia/Colombo", "<+0530>-5:30"}, + {"Asia/Damascus", "EET-2EEST,M3.5.5/0,M10.5.5/0"}, + {"Asia/Dhaka", "<+06>-6"}, + {"Asia/Dili", "<+09>-9"}, + {"Asia/Dubai", "<+04>-4"}, + {"Asia/Dushanbe", "<+05>-5"}, + {"Asia/Famagusta", "EET-2EEST,M3.5.0/3,M10.5.0/4"}, + {"Asia/Gaza", "EET-2EEST,M3.5.5/0,M10.5.6/1"}, + {"Asia/Hebron", "EET-2EEST,M3.5.5/0,M10.5.6/1"}, + {"Asia/Ho_Chi_Minh", "<+07>-7"}, + {"Asia/Hong_Kong", "HKT-8"}, + {"Asia/Hovd", "<+07>-7"}, + {"Asia/Irkutsk", "<+08>-8"}, + {"Asia/Jakarta", "WIB-7"}, + {"Asia/Jayapura", "WIT-9"}, + {"Asia/Jerusalem", "IST-2IDT,M3.4.4/26,M10.5.0"}, + {"Asia/Kabul", "<+0430>-4:30"}, + {"Asia/Kamchatka", "<+12>-12"}, + {"Asia/Karachi", "PKT-5"}, + {"Asia/Kathmandu", "<+0545>-5:45"}, + {"Asia/Khandyga", "<+09>-9"}, + {"Asia/Kolkata", "IST-5:30"}, + {"Asia/Krasnoyarsk", "<+07>-7"}, + {"Asia/Kuala_Lumpur", "<+08>-8"}, + {"Asia/Kuching", "<+08>-8"}, + {"Asia/Kuwait", "<+03>-3"}, + {"Asia/Macau", "CST-8"}, + {"Asia/Magadan", "<+11>-11"}, + {"Asia/Makassar", "WITA-8"}, + {"Asia/Manila", "PST-8"}, + {"Asia/Muscat", "<+04>-4"}, + {"Asia/Nicosia", "EET-2EEST,M3.5.0/3,M10.5.0/4"}, + {"Asia/Novokuznetsk", "<+07>-7"}, + {"Asia/Novosibirsk", "<+07>-7"}, + {"Asia/Omsk", "<+06>-6"}, + {"Asia/Oral", "<+05>-5"}, + {"Asia/Phnom_Penh", "<+07>-7"}, + {"Asia/Pontianak", "WIB-7"}, + {"Asia/Pyongyang", "KST-9"}, + {"Asia/Qatar", "<+03>-3"}, + {"Asia/Qyzylorda", "<+05>-5"}, + {"Asia/Riyadh", "<+03>-3"}, + {"Asia/Sakhalin", "<+11>-11"}, + {"Asia/Samarkand", "<+05>-5"}, + {"Asia/Seoul", "KST-9"}, + {"Asia/Shanghai", "CST-8"}, + {"Asia/Singapore", "<+08>-8"}, + {"Asia/Srednekolymsk", "<+11>-11"}, + {"Asia/Taipei", "CST-8"}, + {"Asia/Tashkent", "<+05>-5"}, + {"Asia/Tbilisi", "<+04>-4"}, + {"Asia/Tehran", "<+0330>-3:30<+0430>,J79/24,J263/24"}, + {"Asia/Thimphu", "<+06>-6"}, + {"Asia/Tokyo", "JST-9"}, + {"Asia/Tomsk", "<+07>-7"}, + {"Asia/Ulaanbaatar", "<+08>-8"}, + {"Asia/Urumqi", "<+06>-6"}, + {"Asia/Ust-Nera", "<+10>-10"}, + {"Asia/Vientiane", "<+07>-7"}, + {"Asia/Vladivostok", "<+10>-10"}, + {"Asia/Yakutsk", "<+09>-9"}, + {"Asia/Yangon", "<+0630>-6:30"}, + {"Asia/Yekaterinburg", "<+05>-5"}, + {"Asia/Yerevan", "<+04>-4"}, + {"Atlantic/Azores", "<-01>1<+00>,M3.5.0/0,M10.5.0/1"}, + {"Atlantic/Bermuda", "AST4ADT,M3.2.0,M11.1.0"}, + {"Atlantic/Canary", "WET0WEST,M3.5.0/1,M10.5.0"}, + {"Atlantic/Cape_Verde", "<-01>1"}, + {"Atlantic/Faroe", "WET0WEST,M3.5.0/1,M10.5.0"}, + {"Atlantic/Madeira", "WET0WEST,M3.5.0/1,M10.5.0"}, + {"Atlantic/Reykjavik", "GMT0"}, + {"Atlantic/South_Georgia", "<-02>2"}, + {"Atlantic/Stanley", "<-03>3"}, + {"Atlantic/St_Helena", "GMT0"}, + {"Australia/Adelaide", "ACST-9:30ACDT,M10.1.0,M4.1.0/3"}, + {"Australia/Brisbane", "AEST-10"}, + {"Australia/Broken_Hill", "ACST-9:30ACDT,M10.1.0,M4.1.0/3"}, + {"Australia/Currie", "AEST-10AEDT,M10.1.0,M4.1.0/3"}, + {"Australia/Darwin", "ACST-9:30"}, + {"Australia/Eucla", "<+0845>-8:45"}, + {"Australia/Hobart", "AEST-10AEDT,M10.1.0,M4.1.0/3"}, + {"Australia/Lindeman", "AEST-10"}, + {"Australia/Lord_Howe", "<+1030>-10:30<+11>-11,M10.1.0,M4.1.0"}, + {"Australia/Melbourne", "AEST-10AEDT,M10.1.0,M4.1.0/3"}, + {"Australia/Perth", "AWST-8"}, + {"Australia/Sydney", "AEST-10AEDT,M10.1.0,M4.1.0/3"}, + {"Europe/Amsterdam", "CET-1CEST,M3.5.0,M10.5.0/3"}, + {"Europe/Andorra", "CET-1CEST,M3.5.0,M10.5.0/3"}, + {"Europe/Astrakhan", "<+04>-4"}, + {"Europe/Athens", "EET-2EEST,M3.5.0/3,M10.5.0/4"}, + {"Europe/Belgrade", "CET-1CEST,M3.5.0,M10.5.0/3"}, + {"Europe/Berlin", "CET-1CEST,M3.5.0,M10.5.0/3"}, + {"Europe/Bratislava", "CET-1CEST,M3.5.0,M10.5.0/3"}, + {"Europe/Brussels", "CET-1CEST,M3.5.0,M10.5.0/3"}, + {"Europe/Bucharest", "EET-2EEST,M3.5.0/3,M10.5.0/4"}, + {"Europe/Budapest", "CET-1CEST,M3.5.0,M10.5.0/3"}, + {"Europe/Busingen", "CET-1CEST,M3.5.0,M10.5.0/3"}, + {"Europe/Chisinau", "EET-2EEST,M3.5.0,M10.5.0/3"}, + {"Europe/Copenhagen", "CET-1CEST,M3.5.0,M10.5.0/3"}, + {"Europe/Dublin", "IST-1GMT0,M10.5.0,M3.5.0/1"}, + {"Europe/Gibraltar", "CET-1CEST,M3.5.0,M10.5.0/3"}, + {"Europe/Guernsey", "GMT0BST,M3.5.0/1,M10.5.0"}, + {"Europe/Helsinki", "EET-2EEST,M3.5.0/3,M10.5.0/4"}, + {"Europe/Isle_of_Man", "GMT0BST,M3.5.0/1,M10.5.0"}, + {"Europe/Istanbul", "<+03>-3"}, + {"Europe/Jersey", "GMT0BST,M3.5.0/1,M10.5.0"}, + {"Europe/Kaliningrad", "EET-2"}, + {"Europe/Kiev", "EET-2EEST,M3.5.0/3,M10.5.0/4"}, + {"Europe/Kirov", "<+03>-3"}, + {"Europe/Lisbon", "WET0WEST,M3.5.0/1,M10.5.0"}, + {"Europe/Ljubljana", "CET-1CEST,M3.5.0,M10.5.0/3"}, + {"Europe/London", "GMT0BST,M3.5.0/1,M10.5.0"}, + {"Europe/Luxembourg", "CET-1CEST,M3.5.0,M10.5.0/3"}, + {"Europe/Madrid", "CET-1CEST,M3.5.0,M10.5.0/3"}, + {"Europe/Malta", "CET-1CEST,M3.5.0,M10.5.0/3"}, + {"Europe/Mariehamn", "EET-2EEST,M3.5.0/3,M10.5.0/4"}, + {"Europe/Minsk", "<+03>-3"}, + {"Europe/Monaco", "CET-1CEST,M3.5.0,M10.5.0/3"}, + {"Europe/Moscow", "MSK-3"}, + {"Europe/Oslo", "CET-1CEST,M3.5.0,M10.5.0/3"}, + {"Europe/Paris", "CET-1CEST,M3.5.0,M10.5.0/3"}, + {"Europe/Podgorica", "CET-1CEST,M3.5.0,M10.5.0/3"}, + {"Europe/Prague", "CET-1CEST,M3.5.0,M10.5.0/3"}, + {"Europe/Riga", "EET-2EEST,M3.5.0/3,M10.5.0/4"}, + {"Europe/Rome", "CET-1CEST,M3.5.0,M10.5.0/3"}, + {"Europe/Samara", "<+04>-4"}, + {"Europe/San_Marino", "CET-1CEST,M3.5.0,M10.5.0/3"}, + {"Europe/Sarajevo", "CET-1CEST,M3.5.0,M10.5.0/3"}, + {"Europe/Saratov", "<+04>-4"}, + {"Europe/Simferopol", "MSK-3"}, + {"Europe/Skopje", "CET-1CEST,M3.5.0,M10.5.0/3"}, + {"Europe/Sofia", "EET-2EEST,M3.5.0/3,M10.5.0/4"}, + {"Europe/Stockholm", "CET-1CEST,M3.5.0,M10.5.0/3"}, + {"Europe/Tallinn", "EET-2EEST,M3.5.0/3,M10.5.0/4"}, + {"Europe/Tirane", "CET-1CEST,M3.5.0,M10.5.0/3"}, + {"Europe/Ulyanovsk", "<+04>-4"}, + {"Europe/Uzhgorod", "EET-2EEST,M3.5.0/3,M10.5.0/4"}, + {"Europe/Vaduz", "CET-1CEST,M3.5.0,M10.5.0/3"}, + {"Europe/Vatican", "CET-1CEST,M3.5.0,M10.5.0/3"}, + {"Europe/Vienna", "CET-1CEST,M3.5.0,M10.5.0/3"}, + {"Europe/Vilnius", "EET-2EEST,M3.5.0/3,M10.5.0/4"}, + {"Europe/Volgograd", "<+04>-4"}, + {"Europe/Warsaw", "CET-1CEST,M3.5.0,M10.5.0/3"}, + {"Europe/Zagreb", "CET-1CEST,M3.5.0,M10.5.0/3"}, + {"Europe/Zaporozhye", "EET-2EEST,M3.5.0/3,M10.5.0/4"}, + {"Europe/Zurich", "CET-1CEST,M3.5.0,M10.5.0/3"}, + {"Indian/Antananarivo", "EAT-3"}, + {"Indian/Chagos", "<+06>-6"}, + {"Indian/Christmas", "<+07>-7"}, + {"Indian/Cocos", "<+0630>-6:30"}, + {"Indian/Comoro", "EAT-3"}, + {"Indian/Kerguelen", "<+05>-5"}, + {"Indian/Mahe", "<+04>-4"}, + {"Indian/Maldives", "<+05>-5"}, + {"Indian/Mauritius", "<+04>-4"}, + {"Indian/Mayotte", "EAT-3"}, + {"Indian/Reunion", "<+04>-4"}, + {"Pacific/Apia", "<+13>-13<+14>,M9.5.0/3,M4.1.0/4"}, + {"Pacific/Auckland", "NZST-12NZDT,M9.5.0,M4.1.0/3"}, + {"Pacific/Bougainville", "<+11>-11"}, + {"Pacific/Chatham", "<+1245>-12:45<+1345>,M9.5.0/2:45,M4.1.0/3:45"}, + {"Pacific/Chuuk", "<+10>-10"}, + {"Pacific/Easter", "<-06>6<-05>,M9.1.6/22,M4.1.6/22"}, + {"Pacific/Efate", "<+11>-11"}, + {"Pacific/Enderbury", "<+13>-13"}, + {"Pacific/Fakaofo", "<+13>-13"}, + {"Pacific/Fiji", "<+12>-12<+13>,M11.2.0,M1.2.3/99"}, + {"Pacific/Funafuti", "<+12>-12"}, + {"Pacific/Galapagos", "<-06>6"}, + {"Pacific/Gambier", "<-09>9"}, + {"Pacific/Guadalcanal", "<+11>-11"}, + {"Pacific/Guam", "ChST-10"}, + {"Pacific/Honolulu", "HST10"}, + {"Pacific/Kiritimati", "<+14>-14"}, + {"Pacific/Kosrae", "<+11>-11"}, + {"Pacific/Kwajalein", "<+12>-12"}, + {"Pacific/Majuro", "<+12>-12"}, + {"Pacific/Marquesas", "<-0930>9:30"}, + {"Pacific/Midway", "SST11"}, + {"Pacific/Nauru", "<+12>-12"}, + {"Pacific/Niue", "<-11>11"}, + {"Pacific/Norfolk", "<+11>-11<+12>,M10.1.0,M4.1.0/3"}, + {"Pacific/Noumea", "<+11>-11"}, + {"Pacific/Pago_Pago", "SST11"}, + {"Pacific/Palau", "<+09>-9"}, + {"Pacific/Pitcairn", "<-08>8"}, + {"Pacific/Pohnpei", "<+11>-11"}, + {"Pacific/Port_Moresby", "<+10>-10"}, + {"Pacific/Rarotonga", "<-10>10"}, + {"Pacific/Saipan", "ChST-10"}, + {"Pacific/Tahiti", "<-10>10"}, + {"Pacific/Tarawa", "<+12>-12"}, + {"Pacific/Tongatapu", "<+13>-13"}, + {"Pacific/Wake", "<+12>-12"}, + {"Pacific/Wallis", "<+12>-12"} +}; + +static char lower(char start) { + if ('A' <= start && start <= 'Z') { + return start - 'A' + 'a'; + } + return start; +} + +/** + * Basically strcmp, but accounting for spaces that have become underscores + * @param[in] target - the 0-terminated string on the left hand side of the comparison + * @param[in] other - the 0-terminated string on the right hand side of the comparison + * @return > 0 if target comes before other alphabetically, + * ==0 if they're the same, + * < 0 if other comes before target alphabetically + * (we don't expect NULL arguments, but, -1 if either is NULL) + **/ +static int tz_name_cmp(const char * target, const char * other) +{ + if (!target || !other) { + return -1; + } + + while (*target) { + if (lower(*target) != lower(*other)) { + break; + } + do { + target++; + } while (*target == '_'); + do { + other++; + } while (*other == '_'); + } + + return lower(*target) - lower(*other); +} + +const char *esp_rmaker_tz_db_get_posix_str(const char *name) +{ + int lo = 0, hi = sizeof(esp_rmaker_tz_db_tzs) / sizeof(esp_rmaker_tz_db_pair_t); + while (lo < hi) { + int mid = (lo + hi) / 2; + esp_rmaker_tz_db_pair_t mid_pair = esp_rmaker_tz_db_tzs[mid]; + int comparison = tz_name_cmp(name, mid_pair.name); + if (comparison == 0) { + return mid_pair.posix_str; + } else if (comparison < 0) { + hi = mid; + } else { + lo = mid + 1; + } + } + return NULL; +} diff --git a/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/src/utils.c b/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/src/utils.c new file mode 100644 index 000000000..6576ac493 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/src/utils.c @@ -0,0 +1,177 @@ +// Copyright 2021 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. +#include +#include +#include +#include +#include +#include +#include + +ESP_EVENT_DEFINE_BASE(RMAKER_COMMON_EVENT); + +static TimerHandle_t reboot_timer; +static TimerHandle_t reset_timer; + +static void esp_rmaker_reboot_cb(TimerHandle_t handle) +{ + xTimerDelete(reboot_timer, 10); + reboot_timer = NULL; + esp_restart(); +} + +esp_err_t esp_rmaker_reboot(int8_t seconds) +{ + /* If specified time is 0, reboot immediately */ + if (seconds == 0) { + esp_event_post(RMAKER_COMMON_EVENT, RMAKER_EVENT_REBOOT, &seconds, sizeof(seconds), portMAX_DELAY); + esp_restart(); + return ESP_OK; + } else if (reboot_timer) { + /* If reboot timer already exists, it means that a reboot operation is already in progress. + * So, just return an error from here. + */ + return ESP_FAIL; + } + reboot_timer = xTimerCreate("rmaker_reboot_tm", (seconds * 1000) / portTICK_PERIOD_MS, + pdFALSE, NULL, esp_rmaker_reboot_cb); + if (reboot_timer) { + if (xTimerStart(reboot_timer, 10) != pdTRUE) { + xTimerDelete(reboot_timer, 10); + reboot_timer = NULL; + return ESP_FAIL; + } + } else { + return ESP_ERR_NO_MEM; + } + esp_event_post(RMAKER_COMMON_EVENT, RMAKER_EVENT_REBOOT, &seconds, sizeof(seconds), portMAX_DELAY); + return ESP_OK; +} + +#ifdef CONFIG_ESP_RMAKER_NETWORK_OVER_WIFI +static esp_err_t __esp_rmaker_wifi_reset(int8_t reboot_seconds) +{ + esp_wifi_restore(); + if (reboot_seconds >= 0) { + esp_rmaker_reboot(reboot_seconds); + } + return ESP_OK; +} +#endif /* CONFIG_ESP_RMAKER_NETWORK_OVER_WIFI */ + +static esp_err_t __esp_rmaker_factory_reset(int8_t reboot_seconds) +{ + nvs_flash_deinit(); + nvs_flash_erase(); +#ifdef CONFIG_ESP_RMAKER_NETWORK_OVER_WIFI + esp_wifi_restore(); +#endif /* CONFIG_ESP_RMAKER_NETWORK_OVER_WIFI */ + if (reboot_seconds >= 0) { + esp_rmaker_reboot(reboot_seconds); + } + return ESP_OK; +} + +#ifdef CONFIG_ESP_RMAKER_NETWORK_OVER_WIFI +static void esp_rmaker_wifi_reset_cb(TimerHandle_t handle) +{ + /* (Hack) Using the timer id as reboot seconds */ + int8_t *reboot_seconds = (int8_t *)pvTimerGetTimerID(handle); + if (reboot_seconds) { + __esp_rmaker_wifi_reset((int8_t)*reboot_seconds); + free(reboot_seconds); + } else { + __esp_rmaker_wifi_reset(0); + } + xTimerDelete(reset_timer, 10); + reset_timer = NULL; +} +#endif /* CONFIG_ESP_RMAKER_NETWORK_OVER_WIFI */ + +static void esp_rmaker_factory_reset_cb(TimerHandle_t handle) +{ + /* (Hack) Using the timer id as reboot seconds */ + int8_t *reboot_seconds = (int8_t *)pvTimerGetTimerID(handle); + if (reboot_seconds) { + __esp_rmaker_factory_reset((int8_t)*reboot_seconds); + free(reboot_seconds); + } else { + __esp_rmaker_factory_reset(0); + } + xTimerDelete(reset_timer, 10); + reset_timer = NULL; +} + +static esp_err_t esp_rmaker_start_reset_timer(int8_t reset_seconds, int8_t reboot_seconds, TimerCallbackFunction_t cb) +{ + /* If reset timer already exists, it means that a reset operation is already in progress. + * So, just return an error from here. + */ + if (reset_timer) { + return ESP_FAIL; + } + /* (Hack) Passing the reboot delay as timer id */ + int8_t *reboot_delay = calloc(1, sizeof(int8_t)); + if (reboot_delay) { + *reboot_delay = reboot_seconds; + } + reset_timer = xTimerCreate("rmaker_reset_tm", (reset_seconds * 1000) / portTICK_PERIOD_MS, + pdFALSE, (void *)reboot_delay, cb); + if (reset_timer) { + if (xTimerStart(reset_timer, 10) != pdTRUE) { + xTimerDelete(reset_timer, 10); + reset_timer = NULL; + return ESP_FAIL; + } + } else { + return ESP_ERR_NO_MEM; + } + return ESP_OK; +} + +esp_err_t esp_rmaker_wifi_reset(int8_t reset_seconds, int8_t reboot_seconds) +{ +#ifdef CONFIG_ESP_RMAKER_NETWORK_OVER_WIFI + esp_err_t err = ESP_FAIL; + /* If reset time is 0, just do it right away */ + if (reset_seconds == 0) { + err = __esp_rmaker_wifi_reset(reboot_seconds); + } else { + /* Else start a timer so that the task gets performed after the specified delay */ + err = esp_rmaker_start_reset_timer(reset_seconds, reboot_seconds, esp_rmaker_wifi_reset_cb); + } + if (err == ESP_OK) { + esp_event_post(RMAKER_COMMON_EVENT, RMAKER_EVENT_WIFI_RESET, NULL, 0, portMAX_DELAY); + } + return ESP_OK; +#else + return ESP_ERR_NOT_SUPPORTED; +#endif /* CONFIG_ESP_RMAKER_NETWORK_OVER_WIFI */ +} + +esp_err_t esp_rmaker_factory_reset(int8_t reset_seconds, int8_t reboot_seconds) +{ + esp_err_t err = ESP_FAIL; + /* If reset time is 0, just do it right away */ + if (reset_seconds == 0) { + err = __esp_rmaker_factory_reset(reboot_seconds); + } else { + /* Else start a timer so that the task gets performed after the specified delay */ + err = esp_rmaker_start_reset_timer(reset_seconds, reboot_seconds, esp_rmaker_factory_reset_cb); + } + if (err == ESP_OK) { + esp_event_post(RMAKER_COMMON_EVENT, RMAKER_EVENT_FACTORY_RESET, NULL, 0, portMAX_DELAY); + } + return ESP_OK; +} diff --git a/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/src/work_queue.c b/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/src/work_queue.c new file mode 100644 index 000000000..f00a7cb03 --- /dev/null +++ b/RainMaker_Table-Lights/managed_components/espressif__rmaker_common/src/work_queue.c @@ -0,0 +1,148 @@ +// Copyright 2021 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. + +#include +#include +#include +#include +#include + +#include + +#define ESP_RMAKER_TASK_QUEUE_SIZE 8 +#define ESP_RMAKER_TASK_STACK CONFIG_ESP_RMAKER_WORK_QUEUE_TASK_STACK +#define ESP_RMAKER_TASK_PRIORITY CONFIG_ESP_RMAKER_WORK_QUEUE_TASK_PRIORITY + +static const char *TAG = "esp_rmaker_work_queue"; + +typedef enum { + WORK_QUEUE_STATE_DEINIT = 0, + WORK_QUEUE_STATE_INIT_DONE, + WORK_QUEUE_STATE_RUNNING, + WORK_QUEUE_STATE_STOP_REQUESTED, +} esp_rmaker_work_queue_state_t; + +typedef struct { + esp_rmaker_work_fn_t work_fn; + void *priv_data; +} esp_rmaker_work_queue_entry_t; + +static QueueHandle_t work_queue; +static esp_rmaker_work_queue_state_t queue_state; + +static void esp_rmaker_handle_work_queue(void) +{ + esp_rmaker_work_queue_entry_t work_queue_entry; + /* 2 sec delay to prevent spinning */ + BaseType_t ret = xQueueReceive(work_queue, &work_queue_entry, 2000 / portTICK_PERIOD_MS); + while (ret == pdTRUE) { + work_queue_entry.work_fn(work_queue_entry.priv_data); + ret = xQueueReceive(work_queue, &work_queue_entry, 0); + } +} + +static void esp_rmaker_work_queue_task(void *param) +{ + ESP_LOGI(TAG, "RainMaker Work Queue task started."); + while (queue_state != WORK_QUEUE_STATE_STOP_REQUESTED) { + esp_rmaker_handle_work_queue(); + } + ESP_LOGI(TAG, "Stopping Work Queue task"); + queue_state = WORK_QUEUE_STATE_INIT_DONE; + vTaskDelete(NULL); +} + +esp_err_t esp_rmaker_work_queue_add_task(esp_rmaker_work_fn_t work_fn, void *priv_data) +{ + if (!work_queue) { + ESP_LOGE(TAG, "Cannot enqueue function as Work Queue hasn't been created."); + return ESP_ERR_INVALID_STATE; + } + esp_rmaker_work_queue_entry_t work_queue_entry = { + .work_fn = work_fn, + .priv_data = priv_data, + }; + if (xQueueSend(work_queue, &work_queue_entry, 0) == pdTRUE) { + return ESP_OK; + } + return ESP_FAIL; +} + +esp_err_t esp_rmaker_work_queue_init(void) +{ + if (queue_state != WORK_QUEUE_STATE_DEINIT) { + ESP_LOGW(TAG, "Work Queue already initialiased/started."); + return ESP_OK; + } + work_queue = xQueueCreate(ESP_RMAKER_TASK_QUEUE_SIZE, sizeof(esp_rmaker_work_queue_entry_t)); + if (!work_queue) { + ESP_LOGE(TAG, "Failed to create Work Queue."); + return ESP_FAIL; + } + ESP_LOGI(TAG, "Work Queue created."); + queue_state = WORK_QUEUE_STATE_INIT_DONE; + return ESP_OK; +} + +esp_err_t esp_rmaker_work_queue_deinit(void) +{ + if (queue_state != WORK_QUEUE_STATE_STOP_REQUESTED) { + esp_rmaker_work_queue_stop(); + } + + while (queue_state == WORK_QUEUE_STATE_STOP_REQUESTED) { + ESP_LOGI(TAG, "Waiting for esp_rmaker_work_queue being stopped..."); + vTaskDelay(2000 / portTICK_PERIOD_MS); + } + + if (queue_state == WORK_QUEUE_STATE_DEINIT) { + return ESP_OK; + } else if (queue_state != WORK_QUEUE_STATE_INIT_DONE) { + ESP_LOGE(TAG, "Cannot deinitialize Work Queue as the task is still running."); + return ESP_ERR_INVALID_STATE; + } else { + vQueueDelete(work_queue); + work_queue = NULL; + queue_state = WORK_QUEUE_STATE_DEINIT; + } + ESP_LOGI(TAG, "esp_rmaker_work_queue was successfully deinitialized"); + return ESP_OK; +} + +esp_err_t esp_rmaker_work_queue_start(void) +{ + if (queue_state == WORK_QUEUE_STATE_RUNNING) { + ESP_LOGW(TAG, "Work Queue already started."); + return ESP_OK; + } + if (queue_state != WORK_QUEUE_STATE_INIT_DONE) { + ESP_LOGE(TAG, "Failed to start Work Queue as it wasn't initialized."); + return ESP_ERR_INVALID_STATE; + } + if (xTaskCreate(&esp_rmaker_work_queue_task, "rmaker_queue_task", ESP_RMAKER_TASK_STACK, + NULL, ESP_RMAKER_TASK_PRIORITY, NULL) != pdPASS) { + ESP_LOGE(TAG, "Couldn't create RainMaker work queue task"); + return ESP_FAIL; + } + queue_state = WORK_QUEUE_STATE_RUNNING; + return ESP_OK; +} + +esp_err_t esp_rmaker_work_queue_stop(void) +{ + if (queue_state == WORK_QUEUE_STATE_RUNNING) { + queue_state = WORK_QUEUE_STATE_STOP_REQUESTED; + } + return ESP_OK; +} diff --git a/RainMaker_Table-Lights/sdkconfig b/RainMaker_Table-Lights/sdkconfig new file mode 100644 index 000000000..1928de823 --- /dev/null +++ b/RainMaker_Table-Lights/sdkconfig @@ -0,0 +1,2623 @@ +# +# Automatically generated file. DO NOT EDIT. +# Espressif IoT Development Framework (ESP-IDF) 5.4.1 Project Configuration +# +CONFIG_SOC_ADC_SUPPORTED=y +CONFIG_SOC_DEDICATED_GPIO_SUPPORTED=y +CONFIG_SOC_UART_SUPPORTED=y +CONFIG_SOC_GDMA_SUPPORTED=y +CONFIG_SOC_AHB_GDMA_SUPPORTED=y +CONFIG_SOC_GPTIMER_SUPPORTED=y +CONFIG_SOC_TWAI_SUPPORTED=y +CONFIG_SOC_BT_SUPPORTED=y +CONFIG_SOC_ASYNC_MEMCPY_SUPPORTED=y +CONFIG_SOC_USB_SERIAL_JTAG_SUPPORTED=y +CONFIG_SOC_TEMP_SENSOR_SUPPORTED=y +CONFIG_SOC_XT_WDT_SUPPORTED=y +CONFIG_SOC_PHY_SUPPORTED=y +CONFIG_SOC_WIFI_SUPPORTED=y +CONFIG_SOC_SUPPORTS_SECURE_DL_MODE=y +CONFIG_SOC_EFUSE_KEY_PURPOSE_FIELD=y +CONFIG_SOC_EFUSE_HAS_EFUSE_RST_BUG=y +CONFIG_SOC_EFUSE_SUPPORTED=y +CONFIG_SOC_RTC_FAST_MEM_SUPPORTED=y +CONFIG_SOC_RTC_MEM_SUPPORTED=y +CONFIG_SOC_I2S_SUPPORTED=y +CONFIG_SOC_RMT_SUPPORTED=y +CONFIG_SOC_SDM_SUPPORTED=y +CONFIG_SOC_GPSPI_SUPPORTED=y +CONFIG_SOC_LEDC_SUPPORTED=y +CONFIG_SOC_I2C_SUPPORTED=y +CONFIG_SOC_SYSTIMER_SUPPORTED=y +CONFIG_SOC_SUPPORT_COEXISTENCE=y +CONFIG_SOC_AES_SUPPORTED=y +CONFIG_SOC_MPI_SUPPORTED=y +CONFIG_SOC_SHA_SUPPORTED=y +CONFIG_SOC_HMAC_SUPPORTED=y +CONFIG_SOC_DIG_SIGN_SUPPORTED=y +CONFIG_SOC_FLASH_ENC_SUPPORTED=y +CONFIG_SOC_SECURE_BOOT_SUPPORTED=y +CONFIG_SOC_MEMPROT_SUPPORTED=y +CONFIG_SOC_BOD_SUPPORTED=y +CONFIG_SOC_CLK_TREE_SUPPORTED=y +CONFIG_SOC_ASSIST_DEBUG_SUPPORTED=y +CONFIG_SOC_WDT_SUPPORTED=y +CONFIG_SOC_SPI_FLASH_SUPPORTED=y +CONFIG_SOC_RNG_SUPPORTED=y +CONFIG_SOC_LIGHT_SLEEP_SUPPORTED=y +CONFIG_SOC_DEEP_SLEEP_SUPPORTED=y +CONFIG_SOC_LP_PERIPH_SHARE_INTERRUPT=y +CONFIG_SOC_PM_SUPPORTED=y +CONFIG_SOC_XTAL_SUPPORT_40M=y +CONFIG_SOC_AES_SUPPORT_DMA=y +CONFIG_SOC_AES_GDMA=y +CONFIG_SOC_AES_SUPPORT_AES_128=y +CONFIG_SOC_AES_SUPPORT_AES_256=y +CONFIG_SOC_ADC_DIG_CTRL_SUPPORTED=y +CONFIG_SOC_ADC_ARBITER_SUPPORTED=y +CONFIG_SOC_ADC_DIG_IIR_FILTER_SUPPORTED=y +CONFIG_SOC_ADC_MONITOR_SUPPORTED=y +CONFIG_SOC_ADC_DMA_SUPPORTED=y +CONFIG_SOC_ADC_PERIPH_NUM=2 +CONFIG_SOC_ADC_MAX_CHANNEL_NUM=5 +CONFIG_SOC_ADC_ATTEN_NUM=4 +CONFIG_SOC_ADC_DIGI_CONTROLLER_NUM=1 +CONFIG_SOC_ADC_PATT_LEN_MAX=8 +CONFIG_SOC_ADC_DIGI_MIN_BITWIDTH=12 +CONFIG_SOC_ADC_DIGI_MAX_BITWIDTH=12 +CONFIG_SOC_ADC_DIGI_RESULT_BYTES=4 +CONFIG_SOC_ADC_DIGI_DATA_BYTES_PER_CONV=4 +CONFIG_SOC_ADC_DIGI_IIR_FILTER_NUM=2 +CONFIG_SOC_ADC_DIGI_MONITOR_NUM=2 +CONFIG_SOC_ADC_SAMPLE_FREQ_THRES_HIGH=83333 +CONFIG_SOC_ADC_SAMPLE_FREQ_THRES_LOW=611 +CONFIG_SOC_ADC_RTC_MIN_BITWIDTH=12 +CONFIG_SOC_ADC_RTC_MAX_BITWIDTH=12 +CONFIG_SOC_ADC_CALIBRATION_V1_SUPPORTED=y +CONFIG_SOC_ADC_SELF_HW_CALI_SUPPORTED=y +CONFIG_SOC_ADC_SHARED_POWER=y +CONFIG_SOC_APB_BACKUP_DMA=y +CONFIG_SOC_BROWNOUT_RESET_SUPPORTED=y +CONFIG_SOC_SHARED_IDCACHE_SUPPORTED=y +CONFIG_SOC_CACHE_MEMORY_IBANK_SIZE=0x4000 +CONFIG_SOC_CPU_CORES_NUM=1 +CONFIG_SOC_CPU_INTR_NUM=32 +CONFIG_SOC_CPU_HAS_FLEXIBLE_INTC=y +CONFIG_SOC_CPU_HAS_CSR_PC=y +CONFIG_SOC_CPU_BREAKPOINTS_NUM=8 +CONFIG_SOC_CPU_WATCHPOINTS_NUM=8 +CONFIG_SOC_CPU_WATCHPOINT_MAX_REGION_SIZE=0x80000000 +CONFIG_SOC_DS_SIGNATURE_MAX_BIT_LEN=3072 +CONFIG_SOC_DS_KEY_PARAM_MD_IV_LENGTH=16 +CONFIG_SOC_DS_KEY_CHECK_MAX_WAIT_US=1100 +CONFIG_SOC_AHB_GDMA_VERSION=1 +CONFIG_SOC_GDMA_NUM_GROUPS_MAX=1 +CONFIG_SOC_GDMA_PAIRS_PER_GROUP_MAX=3 +CONFIG_SOC_GPIO_PORT=1 +CONFIG_SOC_GPIO_PIN_COUNT=22 +CONFIG_SOC_GPIO_SUPPORT_PIN_GLITCH_FILTER=y +CONFIG_SOC_GPIO_FILTER_CLK_SUPPORT_APB=y +CONFIG_SOC_GPIO_SUPPORT_FORCE_HOLD=y +CONFIG_SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP=y +CONFIG_SOC_GPIO_IN_RANGE_MAX=21 +CONFIG_SOC_GPIO_OUT_RANGE_MAX=21 +CONFIG_SOC_GPIO_DEEP_SLEEP_WAKE_VALID_GPIO_MASK=0 +CONFIG_SOC_GPIO_DEEP_SLEEP_WAKE_SUPPORTED_PIN_CNT=6 +CONFIG_SOC_GPIO_VALID_DIGITAL_IO_PAD_MASK=0x00000000003FFFC0 +CONFIG_SOC_GPIO_CLOCKOUT_BY_GPIO_MATRIX=y +CONFIG_SOC_GPIO_CLOCKOUT_CHANNEL_NUM=3 +CONFIG_SOC_GPIO_SUPPORT_HOLD_IO_IN_DSLP=y +CONFIG_SOC_DEDIC_GPIO_OUT_CHANNELS_NUM=8 +CONFIG_SOC_DEDIC_GPIO_IN_CHANNELS_NUM=8 +CONFIG_SOC_DEDIC_PERIPH_ALWAYS_ENABLE=y +CONFIG_SOC_I2C_NUM=1 +CONFIG_SOC_HP_I2C_NUM=1 +CONFIG_SOC_I2C_FIFO_LEN=32 +CONFIG_SOC_I2C_CMD_REG_NUM=8 +CONFIG_SOC_I2C_SUPPORT_SLAVE=y +CONFIG_SOC_I2C_SUPPORT_HW_CLR_BUS=y +CONFIG_SOC_I2C_SUPPORT_XTAL=y +CONFIG_SOC_I2C_SUPPORT_RTC=y +CONFIG_SOC_I2C_SUPPORT_10BIT_ADDR=y +CONFIG_SOC_I2C_SLAVE_SUPPORT_BROADCAST=y +CONFIG_SOC_I2C_SLAVE_CAN_GET_STRETCH_CAUSE=y +CONFIG_SOC_I2C_SLAVE_SUPPORT_I2CRAM_ACCESS=y +CONFIG_SOC_I2S_NUM=1 +CONFIG_SOC_I2S_HW_VERSION_2=y +CONFIG_SOC_I2S_SUPPORTS_XTAL=y +CONFIG_SOC_I2S_SUPPORTS_PLL_F160M=y +CONFIG_SOC_I2S_SUPPORTS_PCM=y +CONFIG_SOC_I2S_SUPPORTS_PDM=y +CONFIG_SOC_I2S_SUPPORTS_PDM_TX=y +CONFIG_SOC_I2S_PDM_MAX_TX_LINES=2 +CONFIG_SOC_I2S_SUPPORTS_TDM=y +CONFIG_SOC_LEDC_SUPPORT_APB_CLOCK=y +CONFIG_SOC_LEDC_SUPPORT_XTAL_CLOCK=y +CONFIG_SOC_LEDC_TIMER_NUM=4 +CONFIG_SOC_LEDC_CHANNEL_NUM=6 +CONFIG_SOC_LEDC_TIMER_BIT_WIDTH=14 +CONFIG_SOC_LEDC_SUPPORT_FADE_STOP=y +CONFIG_SOC_MMU_LINEAR_ADDRESS_REGION_NUM=1 +CONFIG_SOC_MMU_PERIPH_NUM=1 +CONFIG_SOC_MPU_MIN_REGION_SIZE=0x20000000 +CONFIG_SOC_MPU_REGIONS_MAX_NUM=8 +CONFIG_SOC_RMT_GROUPS=1 +CONFIG_SOC_RMT_TX_CANDIDATES_PER_GROUP=2 +CONFIG_SOC_RMT_RX_CANDIDATES_PER_GROUP=2 +CONFIG_SOC_RMT_CHANNELS_PER_GROUP=4 +CONFIG_SOC_RMT_MEM_WORDS_PER_CHANNEL=48 +CONFIG_SOC_RMT_SUPPORT_RX_PINGPONG=y +CONFIG_SOC_RMT_SUPPORT_RX_DEMODULATION=y +CONFIG_SOC_RMT_SUPPORT_TX_ASYNC_STOP=y +CONFIG_SOC_RMT_SUPPORT_TX_LOOP_COUNT=y +CONFIG_SOC_RMT_SUPPORT_TX_SYNCHRO=y +CONFIG_SOC_RMT_SUPPORT_TX_CARRIER_DATA_ONLY=y +CONFIG_SOC_RMT_SUPPORT_XTAL=y +CONFIG_SOC_RMT_SUPPORT_APB=y +CONFIG_SOC_RMT_SUPPORT_RC_FAST=y +CONFIG_SOC_RTC_CNTL_CPU_PD_DMA_BUS_WIDTH=128 +CONFIG_SOC_RTC_CNTL_CPU_PD_REG_FILE_NUM=108 +CONFIG_SOC_SLEEP_SYSTIMER_STALL_WORKAROUND=y +CONFIG_SOC_SLEEP_TGWDT_STOP_WORKAROUND=y +CONFIG_SOC_RTCIO_PIN_COUNT=0 +CONFIG_SOC_MPI_MEM_BLOCKS_NUM=4 +CONFIG_SOC_MPI_OPERATIONS_NUM=3 +CONFIG_SOC_RSA_MAX_BIT_LEN=3072 +CONFIG_SOC_SHA_DMA_MAX_BUFFER_SIZE=3968 +CONFIG_SOC_SHA_SUPPORT_DMA=y +CONFIG_SOC_SHA_SUPPORT_RESUME=y +CONFIG_SOC_SHA_GDMA=y +CONFIG_SOC_SHA_SUPPORT_SHA1=y +CONFIG_SOC_SHA_SUPPORT_SHA224=y +CONFIG_SOC_SHA_SUPPORT_SHA256=y +CONFIG_SOC_SDM_GROUPS=1 +CONFIG_SOC_SDM_CHANNELS_PER_GROUP=4 +CONFIG_SOC_SDM_CLK_SUPPORT_APB=y +CONFIG_SOC_SPI_PERIPH_NUM=2 +CONFIG_SOC_SPI_MAX_CS_NUM=6 +CONFIG_SOC_SPI_MAXIMUM_BUFFER_SIZE=64 +CONFIG_SOC_SPI_SUPPORT_DDRCLK=y +CONFIG_SOC_SPI_SLAVE_SUPPORT_SEG_TRANS=y +CONFIG_SOC_SPI_SUPPORT_CD_SIG=y +CONFIG_SOC_SPI_SUPPORT_CONTINUOUS_TRANS=y +CONFIG_SOC_SPI_SUPPORT_SLAVE_HD_VER2=y +CONFIG_SOC_SPI_SUPPORT_CLK_APB=y +CONFIG_SOC_SPI_SUPPORT_CLK_XTAL=y +CONFIG_SOC_SPI_PERIPH_SUPPORT_CONTROL_DUMMY_OUT=y +CONFIG_SOC_SPI_SCT_SUPPORTED=y +CONFIG_SOC_SPI_SCT_REG_NUM=14 +CONFIG_SOC_SPI_SCT_BUFFER_NUM_MAX=y +CONFIG_SOC_SPI_SCT_CONF_BITLEN_MAX=0x3FFFA +CONFIG_SOC_MEMSPI_IS_INDEPENDENT=y +CONFIG_SOC_SPI_MAX_PRE_DIVIDER=16 +CONFIG_SOC_SPI_MEM_SUPPORT_AUTO_WAIT_IDLE=y +CONFIG_SOC_SPI_MEM_SUPPORT_AUTO_SUSPEND=y +CONFIG_SOC_SPI_MEM_SUPPORT_AUTO_RESUME=y +CONFIG_SOC_SPI_MEM_SUPPORT_IDLE_INTR=y +CONFIG_SOC_SPI_MEM_SUPPORT_SW_SUSPEND=y +CONFIG_SOC_SPI_MEM_SUPPORT_CHECK_SUS=y +CONFIG_SOC_SPI_MEM_SUPPORT_CONFIG_GPIO_BY_EFUSE=y +CONFIG_SOC_SPI_MEM_SUPPORT_WRAP=y +CONFIG_SOC_MEMSPI_SRC_FREQ_80M_SUPPORTED=y +CONFIG_SOC_MEMSPI_SRC_FREQ_40M_SUPPORTED=y +CONFIG_SOC_MEMSPI_SRC_FREQ_26M_SUPPORTED=y +CONFIG_SOC_MEMSPI_SRC_FREQ_20M_SUPPORTED=y +CONFIG_SOC_SYSTIMER_COUNTER_NUM=2 +CONFIG_SOC_SYSTIMER_ALARM_NUM=3 +CONFIG_SOC_SYSTIMER_BIT_WIDTH_LO=32 +CONFIG_SOC_SYSTIMER_BIT_WIDTH_HI=20 +CONFIG_SOC_SYSTIMER_FIXED_DIVIDER=y +CONFIG_SOC_SYSTIMER_INT_LEVEL=y +CONFIG_SOC_SYSTIMER_ALARM_MISS_COMPENSATE=y +CONFIG_SOC_TIMER_GROUPS=2 +CONFIG_SOC_TIMER_GROUP_TIMERS_PER_GROUP=1 +CONFIG_SOC_TIMER_GROUP_COUNTER_BIT_WIDTH=54 +CONFIG_SOC_TIMER_GROUP_SUPPORT_XTAL=y +CONFIG_SOC_TIMER_GROUP_SUPPORT_APB=y +CONFIG_SOC_TIMER_GROUP_TOTAL_TIMERS=2 +CONFIG_SOC_LP_TIMER_BIT_WIDTH_LO=32 +CONFIG_SOC_LP_TIMER_BIT_WIDTH_HI=16 +CONFIG_SOC_MWDT_SUPPORT_XTAL=y +CONFIG_SOC_TWAI_CONTROLLER_NUM=1 +CONFIG_SOC_TWAI_CLK_SUPPORT_APB=y +CONFIG_SOC_TWAI_BRP_MIN=2 +CONFIG_SOC_TWAI_BRP_MAX=16384 +CONFIG_SOC_TWAI_SUPPORTS_RX_STATUS=y +CONFIG_SOC_EFUSE_DIS_DOWNLOAD_ICACHE=y +CONFIG_SOC_EFUSE_DIS_PAD_JTAG=y +CONFIG_SOC_EFUSE_DIS_USB_JTAG=y +CONFIG_SOC_EFUSE_DIS_DIRECT_BOOT=y +CONFIG_SOC_EFUSE_SOFT_DIS_JTAG=y +CONFIG_SOC_EFUSE_DIS_ICACHE=y +CONFIG_SOC_EFUSE_BLOCK9_KEY_PURPOSE_QUIRK=y +CONFIG_SOC_SECURE_BOOT_V2_RSA=y +CONFIG_SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS=3 +CONFIG_SOC_EFUSE_REVOKE_BOOT_KEY_DIGESTS=y +CONFIG_SOC_SUPPORT_SECURE_BOOT_REVOKE_KEY=y +CONFIG_SOC_FLASH_ENCRYPTED_XTS_AES_BLOCK_MAX=32 +CONFIG_SOC_FLASH_ENCRYPTION_XTS_AES=y +CONFIG_SOC_FLASH_ENCRYPTION_XTS_AES_128=y +CONFIG_SOC_MEMPROT_CPU_PREFETCH_PAD_SIZE=16 +CONFIG_SOC_MEMPROT_MEM_ALIGN_SIZE=512 +CONFIG_SOC_UART_NUM=2 +CONFIG_SOC_UART_HP_NUM=2 +CONFIG_SOC_UART_FIFO_LEN=128 +CONFIG_SOC_UART_BITRATE_MAX=5000000 +CONFIG_SOC_UART_SUPPORT_APB_CLK=y +CONFIG_SOC_UART_SUPPORT_RTC_CLK=y +CONFIG_SOC_UART_SUPPORT_XTAL_CLK=y +CONFIG_SOC_UART_SUPPORT_WAKEUP_INT=y +CONFIG_SOC_UART_SUPPORT_FSM_TX_WAIT_SEND=y +CONFIG_SOC_COEX_HW_PTI=y +CONFIG_SOC_PHY_DIG_REGS_MEM_SIZE=21 +CONFIG_SOC_MAC_BB_PD_MEM_SIZE=192 +CONFIG_SOC_WIFI_LIGHT_SLEEP_CLK_WIDTH=12 +CONFIG_SOC_PM_SUPPORT_WIFI_WAKEUP=y +CONFIG_SOC_PM_SUPPORT_BT_WAKEUP=y +CONFIG_SOC_PM_SUPPORT_CPU_PD=y +CONFIG_SOC_PM_SUPPORT_WIFI_PD=y +CONFIG_SOC_PM_SUPPORT_BT_PD=y +CONFIG_SOC_PM_SUPPORT_RC_FAST_PD=y +CONFIG_SOC_PM_SUPPORT_VDDSDIO_PD=y +CONFIG_SOC_PM_SUPPORT_MAC_BB_PD=y +CONFIG_SOC_PM_CPU_RETENTION_BY_RTCCNTL=y +CONFIG_SOC_PM_MODEM_RETENTION_BY_BACKUPDMA=y +CONFIG_SOC_PM_MODEM_PD_BY_SW=y +CONFIG_SOC_CLK_RC_FAST_D256_SUPPORTED=y +CONFIG_SOC_RTC_SLOW_CLK_SUPPORT_RC_FAST_D256=y +CONFIG_SOC_CLK_RC_FAST_SUPPORT_CALIBRATION=y +CONFIG_SOC_CLK_XTAL32K_SUPPORTED=y +CONFIG_SOC_TEMPERATURE_SENSOR_SUPPORT_FAST_RC=y +CONFIG_SOC_TEMPERATURE_SENSOR_SUPPORT_XTAL=y +CONFIG_SOC_WIFI_HW_TSF=y +CONFIG_SOC_WIFI_FTM_SUPPORT=y +CONFIG_SOC_WIFI_GCMP_SUPPORT=y +CONFIG_SOC_WIFI_WAPI_SUPPORT=y +CONFIG_SOC_WIFI_CSI_SUPPORT=y +CONFIG_SOC_WIFI_MESH_SUPPORT=y +CONFIG_SOC_WIFI_SUPPORT_VARIABLE_BEACON_WINDOW=y +CONFIG_SOC_WIFI_PHY_NEEDS_USB_WORKAROUND=y +CONFIG_SOC_BLE_SUPPORTED=y +CONFIG_SOC_BLE_MESH_SUPPORTED=y +CONFIG_SOC_BLE_50_SUPPORTED=y +CONFIG_SOC_BLE_DEVICE_PRIVACY_SUPPORTED=y +CONFIG_SOC_BLUFI_SUPPORTED=y +CONFIG_SOC_PHY_COMBO_MODULE=y +CONFIG_IDF_CMAKE=y +CONFIG_IDF_TOOLCHAIN="gcc" +CONFIG_IDF_TOOLCHAIN_GCC=y +CONFIG_IDF_TARGET_ARCH_RISCV=y +CONFIG_IDF_TARGET_ARCH="riscv" +CONFIG_IDF_TARGET="esp32c3" +CONFIG_IDF_INIT_VERSION="5.4.1" +CONFIG_IDF_TARGET_ESP32C3=y +CONFIG_IDF_FIRMWARE_CHIP_ID=0x0005 + +# +# Build type +# +CONFIG_APP_BUILD_TYPE_APP_2NDBOOT=y +# CONFIG_APP_BUILD_TYPE_RAM is not set +CONFIG_APP_BUILD_GENERATE_BINARIES=y +CONFIG_APP_BUILD_BOOTLOADER=y +CONFIG_APP_BUILD_USE_FLASH_SECTIONS=y +# CONFIG_APP_REPRODUCIBLE_BUILD is not set +# CONFIG_APP_NO_BLOBS is not set +# end of Build type + +# +# Bootloader config +# + +# +# Bootloader manager +# +CONFIG_BOOTLOADER_COMPILE_TIME_DATE=y +CONFIG_BOOTLOADER_PROJECT_VER=1 +# end of Bootloader manager + +CONFIG_BOOTLOADER_OFFSET_IN_FLASH=0x0 +CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y +# CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_DEBUG is not set +# CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_PERF is not set +# CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_NONE is not set + +# +# Log +# +# CONFIG_BOOTLOADER_LOG_LEVEL_NONE is not set +# CONFIG_BOOTLOADER_LOG_LEVEL_ERROR is not set +# CONFIG_BOOTLOADER_LOG_LEVEL_WARN is not set +CONFIG_BOOTLOADER_LOG_LEVEL_INFO=y +# CONFIG_BOOTLOADER_LOG_LEVEL_DEBUG is not set +# CONFIG_BOOTLOADER_LOG_LEVEL_VERBOSE is not set +CONFIG_BOOTLOADER_LOG_LEVEL=3 + +# +# Format +# +# CONFIG_BOOTLOADER_LOG_COLORS is not set +CONFIG_BOOTLOADER_LOG_TIMESTAMP_SOURCE_CPU_TICKS=y +# end of Format +# end of Log + +# +# Serial Flash Configurations +# +# CONFIG_BOOTLOADER_FLASH_DC_AWARE is not set +CONFIG_BOOTLOADER_FLASH_XMC_SUPPORT=y +# end of Serial Flash Configurations + +# CONFIG_BOOTLOADER_FACTORY_RESET is not set +# CONFIG_BOOTLOADER_APP_TEST is not set +CONFIG_BOOTLOADER_REGION_PROTECTION_ENABLE=y +CONFIG_BOOTLOADER_WDT_ENABLE=y +# CONFIG_BOOTLOADER_WDT_DISABLE_IN_USER_CODE is not set +CONFIG_BOOTLOADER_WDT_TIME_MS=9000 +CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE=y +# CONFIG_BOOTLOADER_APP_ANTI_ROLLBACK is not set +# CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP is not set +# CONFIG_BOOTLOADER_SKIP_VALIDATE_ON_POWER_ON is not set +# CONFIG_BOOTLOADER_SKIP_VALIDATE_ALWAYS is not set +CONFIG_BOOTLOADER_RESERVE_RTC_SIZE=0 +# CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC is not set +# end of Bootloader config + +# +# Security features +# +CONFIG_SECURE_BOOT_V2_RSA_SUPPORTED=y +CONFIG_SECURE_BOOT_V2_PREFERRED=y +# CONFIG_SECURE_SIGNED_APPS_NO_SECURE_BOOT is not set +# CONFIG_SECURE_BOOT is not set +# CONFIG_SECURE_FLASH_ENC_ENABLED is not set +CONFIG_SECURE_ROM_DL_MODE_ENABLED=y +# end of Security features + +# +# Application manager +# +CONFIG_APP_COMPILE_TIME_DATE=y +# CONFIG_APP_EXCLUDE_PROJECT_VER_VAR is not set +# CONFIG_APP_EXCLUDE_PROJECT_NAME_VAR is not set +# CONFIG_APP_PROJECT_VER_FROM_CONFIG is not set +CONFIG_APP_RETRIEVE_LEN_ELF_SHA=9 +# end of Application manager + +CONFIG_ESP_ROM_HAS_CRC_LE=y +CONFIG_ESP_ROM_HAS_CRC_BE=y +CONFIG_ESP_ROM_HAS_MZ_CRC32=y +CONFIG_ESP_ROM_HAS_JPEG_DECODE=y +CONFIG_ESP_ROM_UART_CLK_IS_XTAL=y +CONFIG_ESP_ROM_USB_SERIAL_DEVICE_NUM=3 +CONFIG_ESP_ROM_HAS_RETARGETABLE_LOCKING=y +CONFIG_ESP_ROM_HAS_ERASE_0_REGION_BUG=y +CONFIG_ESP_ROM_HAS_ENCRYPTED_WRITES_USING_LEGACY_DRV=y +CONFIG_ESP_ROM_GET_CLK_FREQ=y +CONFIG_ESP_ROM_NEEDS_SWSETUP_WORKAROUND=y +CONFIG_ESP_ROM_HAS_LAYOUT_TABLE=y +CONFIG_ESP_ROM_HAS_SPI_FLASH=y +CONFIG_ESP_ROM_HAS_ETS_PRINTF_BUG=y +CONFIG_ESP_ROM_HAS_NEWLIB=y +CONFIG_ESP_ROM_HAS_NEWLIB_NANO_FORMAT=y +CONFIG_ESP_ROM_HAS_NEWLIB_32BIT_TIME=y +CONFIG_ESP_ROM_NEEDS_SET_CACHE_MMU_SIZE=y +CONFIG_ESP_ROM_RAM_APP_NEEDS_MMU_INIT=y +CONFIG_ESP_ROM_HAS_SW_FLOAT=y +CONFIG_ESP_ROM_USB_OTG_NUM=-1 +CONFIG_ESP_ROM_HAS_VERSION=y +CONFIG_ESP_ROM_SUPPORT_DEEP_SLEEP_WAKEUP_STUB=y + +# +# Boot ROM Behavior +# +CONFIG_BOOT_ROM_LOG_ALWAYS_ON=y +# CONFIG_BOOT_ROM_LOG_ALWAYS_OFF is not set +# CONFIG_BOOT_ROM_LOG_ON_GPIO_HIGH is not set +# CONFIG_BOOT_ROM_LOG_ON_GPIO_LOW is not set +# end of Boot ROM Behavior + +# +# Serial flasher config +# +# CONFIG_ESPTOOLPY_NO_STUB is not set +# CONFIG_ESPTOOLPY_FLASHMODE_QIO is not set +# CONFIG_ESPTOOLPY_FLASHMODE_QOUT is not set +CONFIG_ESPTOOLPY_FLASHMODE_DIO=y +# CONFIG_ESPTOOLPY_FLASHMODE_DOUT is not set +CONFIG_ESPTOOLPY_FLASH_SAMPLE_MODE_STR=y +CONFIG_ESPTOOLPY_FLASHMODE="dio" +CONFIG_ESPTOOLPY_FLASHFREQ_80M=y +# CONFIG_ESPTOOLPY_FLASHFREQ_40M is not set +# CONFIG_ESPTOOLPY_FLASHFREQ_26M is not set +# CONFIG_ESPTOOLPY_FLASHFREQ_20M is not set +CONFIG_ESPTOOLPY_FLASHFREQ="80m" +# CONFIG_ESPTOOLPY_FLASHSIZE_1MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_2MB is not set +CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y +# CONFIG_ESPTOOLPY_FLASHSIZE_8MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_16MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_32MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_64MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_128MB is not set +CONFIG_ESPTOOLPY_FLASHSIZE="4MB" +# CONFIG_ESPTOOLPY_HEADER_FLASHSIZE_UPDATE is not set +CONFIG_ESPTOOLPY_BEFORE_RESET=y +# CONFIG_ESPTOOLPY_BEFORE_NORESET is not set +CONFIG_ESPTOOLPY_BEFORE="default_reset" +CONFIG_ESPTOOLPY_AFTER_RESET=y +# CONFIG_ESPTOOLPY_AFTER_NORESET is not set +CONFIG_ESPTOOLPY_AFTER="hard_reset" +CONFIG_ESPTOOLPY_MONITOR_BAUD=115200 +# end of Serial flasher config + +# +# Partition Table +# +# CONFIG_PARTITION_TABLE_SINGLE_APP is not set +# CONFIG_PARTITION_TABLE_SINGLE_APP_LARGE is not set +# CONFIG_PARTITION_TABLE_TWO_OTA is not set +# CONFIG_PARTITION_TABLE_TWO_OTA_LARGE is not set +CONFIG_PARTITION_TABLE_CUSTOM=y +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions_4mb_optimised.csv" +CONFIG_PARTITION_TABLE_FILENAME="partitions_4mb_optimised.csv" +CONFIG_PARTITION_TABLE_OFFSET=0xc000 +CONFIG_PARTITION_TABLE_MD5=y +# end of Partition Table + +# +# Example Configuration +# +CONFIG_EXAMPLE_BOARD_BUTTON_GPIO=9 +# end of Example Configuration + +# +# ESP RainMaker App Wi-Fi Provisioning +# +CONFIG_APP_NETWORK_PROV_SHOW_QR=y +CONFIG_APP_NETWORK_PROV_MAX_POP_MISMATCH=5 +# CONFIG_APP_NETWORK_PROV_TRANSPORT_SOFTAP is not set +CONFIG_APP_NETWORK_PROV_TRANSPORT_BLE=y +CONFIG_APP_NETWORK_PROV_TRANSPORT=2 +CONFIG_APP_NETWORK_RESET_PROV_ON_FAILURE=y +CONFIG_APP_NETWORK_PROV_MAX_RETRY_CNT=5 +# CONFIG_APP_NETWORK_SHOW_DEMO_INTRO_TEXT is not set +CONFIG_APP_NETWORK_PROV_TIMEOUT_PERIOD=30 +CONFIG_APP_NETWORK_PROV_NAME_PREFIX="PROV" +CONFIG_APP_WIFI_PROV_COMPAT=y +# end of ESP RainMaker App Wi-Fi Provisioning + +# +# ESP RainMaker Config +# +# CONFIG_ESP_RMAKER_NO_CLAIM is not set +CONFIG_ESP_RMAKER_SELF_CLAIM=y +# CONFIG_ESP_RMAKER_ASSISTED_CLAIM is not set +CONFIG_ESP_RMAKER_USE_NVS=y +CONFIG_ESP_RMAKER_CLAIM_TYPE=1 +CONFIG_ESP_RMAKER_CLAIM_SERVICE_BASE_URL="https://esp-claiming.rainmaker.espressif.com" +# CONFIG_ESP_RMAKER_READ_MQTT_HOST_FROM_CONFIG is not set +# CONFIG_ESP_RMAKER_READ_NODE_ID_FROM_CERT_CN is not set +CONFIG_ESP_RMAKER_MQTT_HOST="a1p72mufdu6064-ats.iot.us-east-1.amazonaws.com" +CONFIG_ESP_RMAKER_MQTT_USE_BASIC_INGEST_TOPICS=y +CONFIG_ESP_RMAKER_MQTT_ENABLE_BUDGETING=y +CONFIG_ESP_RMAKER_MQTT_DEFAULT_BUDGET=100 +CONFIG_ESP_RMAKER_MQTT_MAX_BUDGET=1024 +CONFIG_ESP_RMAKER_MQTT_BUDGET_REVIVE_PERIOD=5 +CONFIG_ESP_RMAKER_MQTT_BUDGET_REVIVE_COUNT=1 +CONFIG_ESP_RMAKER_MAX_PARAM_DATA_SIZE=1024 +# CONFIG_ESP_RMAKER_DISABLE_USER_MAPPING_PROV is not set +CONFIG_ESP_RMAKER_USER_ID_CHECK=y +# CONFIG_RMAKER_NAME_PARAM_CB is not set +CONFIG_ESP_RMAKER_LOCAL_CTRL_FEATURE_ENABLE=y +CONFIG_ESP_RMAKER_LOCAL_CTRL_AUTO_ENABLE=y +CONFIG_ESP_RMAKER_LOCAL_CTRL_HTTP_PORT=8080 +CONFIG_ESP_RMAKER_LOCAL_CTRL_STACK_SIZE=6144 +# CONFIG_ESP_RMAKER_LOCAL_CTRL_SECURITY_0 is not set +CONFIG_ESP_RMAKER_LOCAL_CTRL_SECURITY_1=y +CONFIG_ESP_RMAKER_LOCAL_CTRL_SECURITY=1 +CONFIG_ESP_RMAKER_CONSOLE_UART_NUM_0=y +# CONFIG_ESP_RMAKER_CONSOLE_UART_NUM_1 is not set +CONFIG_ESP_RMAKER_CONSOLE_UART_NUM=0 +CONFIG_ESP_RMAKER_USE_CERT_BUNDLE=y + +# +# ESP RainMaker OTA Config +# +CONFIG_ESP_RMAKER_OTA_AUTOFETCH=y +CONFIG_ESP_RMAKER_OTA_AUTOFETCH_PERIOD=0 +# CONFIG_ESP_RMAKER_SKIP_COMMON_NAME_CHECK is not set +# CONFIG_ESP_RMAKER_SKIP_VERSION_CHECK is not set +# CONFIG_ESP_RMAKER_SKIP_SECURE_VERSION_CHECK is not set +# CONFIG_ESP_RMAKER_SKIP_PROJECT_NAME_CHECK is not set +CONFIG_ESP_RMAKER_OTA_HTTP_RX_BUFFER_SIZE=1024 +CONFIG_ESP_RMAKER_OTA_ROLLBACK_WAIT_PERIOD=90 +# CONFIG_ESP_RMAKER_OTA_DISABLE_AUTO_REBOOT is not set +CONFIG_ESP_RMAKER_OTA_TIME_SUPPORT=y +# CONFIG_ESP_RMAKER_OTA_PROGRESS_SUPPORT is not set +CONFIG_ESP_RMAKER_OTA_MAX_RETRIES=3 +CONFIG_ESP_RMAKER_OTA_RETRY_DELAY_MINUTES=5 +# end of ESP RainMaker OTA Config + +# +# ESP RainMaker Scheduling +# +CONFIG_ESP_RMAKER_SCHEDULING_MAX_SCHEDULES=10 +# end of ESP RainMaker Scheduling + +# +# ESP RainMaker Scenes +# +CONFIG_ESP_RMAKER_SCENES_MAX_SCENES=10 +# CONFIG_ESP_RMAKER_SCENES_DEACTIVATE_SUPPORT is not set +# end of ESP RainMaker Scenes + +# +# ESP RainMaker Command-Response +# +CONFIG_ESP_RMAKER_CMD_RESP_ENABLE=y +# CONFIG_ESP_RMAKER_CMD_RESP_TEST_ENABLE is not set +# end of ESP RainMaker Command-Response + +CONFIG_ESP_RMAKER_USING_NETWORK_PROV=y +# end of ESP RainMaker Config + +# +# Compiler options +# +CONFIG_COMPILER_OPTIMIZATION_DEBUG=y +# CONFIG_COMPILER_OPTIMIZATION_SIZE is not set +# CONFIG_COMPILER_OPTIMIZATION_PERF is not set +# CONFIG_COMPILER_OPTIMIZATION_NONE is not set +CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE=y +# CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT is not set +# CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE is not set +CONFIG_COMPILER_ASSERT_NDEBUG_EVALUATE=y +CONFIG_COMPILER_FLOAT_LIB_FROM_GCCLIB=y +CONFIG_COMPILER_OPTIMIZATION_ASSERTION_LEVEL=2 +# CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT is not set +CONFIG_COMPILER_HIDE_PATHS_MACROS=y +# CONFIG_COMPILER_CXX_EXCEPTIONS is not set +# CONFIG_COMPILER_CXX_RTTI is not set +CONFIG_COMPILER_STACK_CHECK_MODE_NONE=y +# CONFIG_COMPILER_STACK_CHECK_MODE_NORM is not set +# CONFIG_COMPILER_STACK_CHECK_MODE_STRONG is not set +# CONFIG_COMPILER_STACK_CHECK_MODE_ALL is not set +# CONFIG_COMPILER_NO_MERGE_CONSTANTS is not set +# CONFIG_COMPILER_WARN_WRITE_STRINGS is not set +# CONFIG_COMPILER_SAVE_RESTORE_LIBCALLS is not set +CONFIG_COMPILER_DISABLE_DEFAULT_ERRORS=y +# CONFIG_COMPILER_DISABLE_GCC12_WARNINGS is not set +# CONFIG_COMPILER_DISABLE_GCC13_WARNINGS is not set +# CONFIG_COMPILER_DISABLE_GCC14_WARNINGS is not set +# CONFIG_COMPILER_DUMP_RTL_FILES is not set +CONFIG_COMPILER_RT_LIB_GCCLIB=y +CONFIG_COMPILER_RT_LIB_NAME="gcc" +CONFIG_COMPILER_ORPHAN_SECTIONS_WARNING=y +# CONFIG_COMPILER_ORPHAN_SECTIONS_PLACE is not set +# CONFIG_COMPILER_STATIC_ANALYZER is not set +# end of Compiler options + +# +# Component config +# + +# +# Application Level Tracing +# +# CONFIG_APPTRACE_DEST_JTAG is not set +CONFIG_APPTRACE_DEST_NONE=y +# CONFIG_APPTRACE_DEST_UART1 is not set +# CONFIG_APPTRACE_DEST_USB_CDC is not set +CONFIG_APPTRACE_DEST_UART_NONE=y +CONFIG_APPTRACE_UART_TASK_PRIO=1 +CONFIG_APPTRACE_LOCK_ENABLE=y +# end of Application Level Tracing + +# +# Bluetooth +# +CONFIG_BT_ENABLED=y +# CONFIG_BT_BLUEDROID_ENABLED is not set +CONFIG_BT_NIMBLE_ENABLED=y +# CONFIG_BT_CONTROLLER_ONLY is not set +CONFIG_BT_CONTROLLER_ENABLED=y +# CONFIG_BT_CONTROLLER_DISABLED is not set + +# +# NimBLE Options +# +CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_INTERNAL=y +# CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_DEFAULT is not set +# CONFIG_BT_NIMBLE_LOG_LEVEL_NONE is not set +# CONFIG_BT_NIMBLE_LOG_LEVEL_ERROR is not set +# CONFIG_BT_NIMBLE_LOG_LEVEL_WARNING is not set +CONFIG_BT_NIMBLE_LOG_LEVEL_INFO=y +# CONFIG_BT_NIMBLE_LOG_LEVEL_DEBUG is not set +CONFIG_BT_NIMBLE_LOG_LEVEL=1 +CONFIG_BT_NIMBLE_MAX_CONNECTIONS=3 +CONFIG_BT_NIMBLE_MAX_BONDS=3 +CONFIG_BT_NIMBLE_MAX_CCCDS=8 +CONFIG_BT_NIMBLE_L2CAP_COC_MAX_NUM=0 +CONFIG_BT_NIMBLE_PINNED_TO_CORE=0 +CONFIG_BT_NIMBLE_HOST_TASK_STACK_SIZE=4096 +CONFIG_BT_NIMBLE_ROLE_CENTRAL=y +CONFIG_BT_NIMBLE_ROLE_PERIPHERAL=y +CONFIG_BT_NIMBLE_ROLE_BROADCASTER=y +CONFIG_BT_NIMBLE_ROLE_OBSERVER=y +# CONFIG_BT_NIMBLE_NVS_PERSIST is not set +# CONFIG_BT_NIMBLE_SMP_ID_RESET is not set +CONFIG_BT_NIMBLE_SECURITY_ENABLE=y +CONFIG_BT_NIMBLE_SM_LEGACY=y +CONFIG_BT_NIMBLE_SM_SC=y +# CONFIG_BT_NIMBLE_SM_SC_DEBUG_KEYS is not set +CONFIG_BT_NIMBLE_LL_CFG_FEAT_LE_ENCRYPTION=y +CONFIG_BT_NIMBLE_SM_LVL=0 +CONFIG_BT_NIMBLE_SM_SC_ONLY=0 +# CONFIG_BT_NIMBLE_DEBUG is not set +# CONFIG_BT_NIMBLE_DYNAMIC_SERVICE is not set +CONFIG_BT_NIMBLE_SVC_GAP_DEVICE_NAME="nimble" +CONFIG_BT_NIMBLE_GAP_DEVICE_NAME_MAX_LEN=31 +CONFIG_BT_NIMBLE_ATT_PREFERRED_MTU=256 +CONFIG_BT_NIMBLE_SVC_GAP_APPEARANCE=0 + +# +# Memory Settings +# +CONFIG_BT_NIMBLE_MSYS_1_BLOCK_COUNT=12 +CONFIG_BT_NIMBLE_MSYS_1_BLOCK_SIZE=256 +CONFIG_BT_NIMBLE_MSYS_2_BLOCK_COUNT=24 +CONFIG_BT_NIMBLE_MSYS_2_BLOCK_SIZE=320 +CONFIG_BT_NIMBLE_TRANSPORT_ACL_FROM_LL_COUNT=24 +CONFIG_BT_NIMBLE_TRANSPORT_ACL_SIZE=255 +CONFIG_BT_NIMBLE_TRANSPORT_EVT_SIZE=70 +CONFIG_BT_NIMBLE_TRANSPORT_EVT_COUNT=30 +CONFIG_BT_NIMBLE_TRANSPORT_EVT_DISCARD_COUNT=8 +CONFIG_BT_NIMBLE_L2CAP_COC_SDU_BUFF_COUNT=1 +# end of Memory Settings + +CONFIG_BT_NIMBLE_GATT_MAX_PROCS=4 +# CONFIG_BT_NIMBLE_HS_FLOW_CTRL is not set +CONFIG_BT_NIMBLE_RPA_TIMEOUT=900 +# CONFIG_BT_NIMBLE_MESH is not set +CONFIG_BT_NIMBLE_CRYPTO_STACK_MBEDTLS=y +CONFIG_BT_NIMBLE_HS_STOP_TIMEOUT_MS=2000 +CONFIG_BT_NIMBLE_ENABLE_CONN_REATTEMPT=y +CONFIG_BT_NIMBLE_MAX_CONN_REATTEMPT=3 +CONFIG_BT_NIMBLE_50_FEATURE_SUPPORT=y +CONFIG_BT_NIMBLE_LL_CFG_FEAT_LE_2M_PHY=y +CONFIG_BT_NIMBLE_LL_CFG_FEAT_LE_CODED_PHY=y +# CONFIG_BT_NIMBLE_EXT_ADV is not set +CONFIG_BT_NIMBLE_EXT_SCAN=y +CONFIG_BT_NIMBLE_ENABLE_PERIODIC_SYNC=y +CONFIG_BT_NIMBLE_MAX_PERIODIC_SYNCS=0 +# CONFIG_BT_NIMBLE_GATT_CACHING is not set +CONFIG_BT_NIMBLE_WHITELIST_SIZE=12 +# CONFIG_BT_NIMBLE_TEST_THROUGHPUT_TEST is not set +# CONFIG_BT_NIMBLE_BLUFI_ENABLE is not set +CONFIG_BT_NIMBLE_USE_ESP_TIMER=y +CONFIG_BT_NIMBLE_LEGACY_VHCI_ENABLE=y +# CONFIG_BT_NIMBLE_BLE_GATT_BLOB_TRANSFER is not set + +# +# GAP Service +# + +# +# GAP Appearance write permissions +# +# CONFIG_BT_NIMBLE_SVC_GAP_APPEAR_WRITE is not set +# end of GAP Appearance write permissions + +CONFIG_BT_NIMBLE_SVC_GAP_APPEAR_WRITE_PERM=0 +CONFIG_BT_NIMBLE_SVC_GAP_APPEAR_WRITE_PERM_ENC=0 +CONFIG_BT_NIMBLE_SVC_GAP_APPEAR_WRITE_PERM_ATHN=0 +CONFIG_BT_NIMBLE_SVC_GAP_APPEAR_WRITE_PERM_ATHR=0 +CONFIG_BT_NIMBLE_SVC_GAP_CAR_CHAR_NOT_SUPP=y +# CONFIG_BT_NIMBLE_SVC_GAP_CAR_NOT_SUPP is not set +# CONFIG_BT_NIMBLE_SVC_GAP_CAR_SUPP is not set +CONFIG_BT_NIMBLE_SVC_GAP_CENT_ADDR_RESOLUTION=-1 + +# +# GAP device name write permissions +# +# CONFIG_BT_NIMBLE_SVC_GAP_NAME_WRITE is not set +# end of GAP device name write permissions + +CONFIG_BT_NIMBLE_SVC_GAP_NAME_WRITE_PERM=0 +CONFIG_BT_NIMBLE_SVC_GAP_NAME_WRITE_PERM_ENC=0 +CONFIG_BT_NIMBLE_SVC_GAP_NAME_WRITE_PERM_AUTHEN=0 +CONFIG_BT_NIMBLE_SVC_GAP_NAME_WRITE_PERM_AUTHOR=0 +CONFIG_BT_NIMBLE_SVC_GAP_PPCP_MAX_CONN_INTERVAL=0 +CONFIG_BT_NIMBLE_SVC_GAP_PPCP_MIN_CONN_INTERVAL=0 +CONFIG_BT_NIMBLE_SVC_GAP_PPCP_SLAVE_LATENCY=0 +CONFIG_BT_NIMBLE_SVC_GAP_PPCP_SUPERVISION_TMO=0 +# CONFIG_BT_NIMBLE_SVC_GAP_GATT_SECURITY_LEVEL is not set +# end of GAP Service + +# +# BLE Services +# +# CONFIG_BT_NIMBLE_HID_SERVICE is not set +# CONFIG_BT_NIMBLE_SVC_BAS_BATTERY_LEVEL_NOTIFY is not set + +# +# Device Information Service +# +# CONFIG_BT_NIMBLE_SVC_DIS_MANUFACTURER_NAME is not set +# CONFIG_BT_NIMBLE_SVC_DIS_SERIAL_NUMBER is not set +# CONFIG_BT_NIMBLE_SVC_DIS_HARDWARE_REVISION is not set +# CONFIG_BT_NIMBLE_SVC_DIS_FIRMWARE_REVISION is not set +# CONFIG_BT_NIMBLE_SVC_DIS_SOFTWARE_REVISION is not set +# CONFIG_BT_NIMBLE_SVC_DIS_SYSTEM_ID is not set +# CONFIG_BT_NIMBLE_SVC_DIS_PNP_ID is not set +# CONFIG_BT_NIMBLE_SVC_DIS_INCLUDED is not set +# end of Device Information Service +# end of BLE Services + +# CONFIG_BT_NIMBLE_VS_SUPPORT is not set +# CONFIG_BT_NIMBLE_ENC_ADV_DATA is not set +# CONFIG_BT_NIMBLE_HIGH_DUTY_ADV_ITVL is not set +# CONFIG_BT_NIMBLE_HOST_ALLOW_CONNECT_WITH_SCAN is not set +# CONFIG_BT_NIMBLE_HOST_QUEUE_CONG_CHECK is not set +# CONFIG_BT_NIMBLE_GATTC_PROC_PREEMPTION_PROTECT is not set + +# +# Host-controller Transport +# +CONFIG_UART_HW_FLOWCTRL_DISABLE=y +# CONFIG_UART_HW_FLOWCTRL_CTS_RTS is not set +CONFIG_BT_NIMBLE_HCI_UART_FLOW_CTRL=0 +CONFIG_BT_NIMBLE_HCI_UART_RTS_PIN=19 +CONFIG_BT_NIMBLE_HCI_UART_CTS_PIN=23 +# end of Host-controller Transport + +CONFIG_BT_NIMBLE_EATT_CHAN_NUM=0 +# CONFIG_BT_NIMBLE_SUBRATE is not set +# end of NimBLE Options + +# +# Controller Options +# +CONFIG_BT_CTRL_MODE_EFF=1 +CONFIG_BT_CTRL_BLE_MAX_ACT=6 +CONFIG_BT_CTRL_BLE_MAX_ACT_EFF=6 +CONFIG_BT_CTRL_BLE_STATIC_ACL_TX_BUF_NB=0 +CONFIG_BT_CTRL_PINNED_TO_CORE=0 +CONFIG_BT_CTRL_HCI_MODE_VHCI=y +# CONFIG_BT_CTRL_HCI_MODE_UART_H4 is not set +CONFIG_BT_CTRL_HCI_TL=1 +CONFIG_BT_CTRL_ADV_DUP_FILT_MAX=30 +CONFIG_BT_BLE_CCA_MODE_NONE=y +# CONFIG_BT_BLE_CCA_MODE_HW is not set +# CONFIG_BT_BLE_CCA_MODE_SW is not set +CONFIG_BT_BLE_CCA_MODE=0 +CONFIG_BT_CTRL_HW_CCA_VAL=20 +CONFIG_BT_CTRL_HW_CCA_EFF=0 +CONFIG_BT_CTRL_CE_LENGTH_TYPE_ORIG=y +# CONFIG_BT_CTRL_CE_LENGTH_TYPE_CE is not set +# CONFIG_BT_CTRL_CE_LENGTH_TYPE_SD is not set +CONFIG_BT_CTRL_CE_LENGTH_TYPE_EFF=0 +CONFIG_BT_CTRL_TX_ANTENNA_INDEX_0=y +# CONFIG_BT_CTRL_TX_ANTENNA_INDEX_1 is not set +CONFIG_BT_CTRL_TX_ANTENNA_INDEX_EFF=0 +CONFIG_BT_CTRL_RX_ANTENNA_INDEX_0=y +# CONFIG_BT_CTRL_RX_ANTENNA_INDEX_1 is not set +CONFIG_BT_CTRL_RX_ANTENNA_INDEX_EFF=0 +# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N24 is not set +# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N21 is not set +# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N18 is not set +# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N15 is not set +# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N12 is not set +# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N9 is not set +# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N6 is not set +# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N3 is not set +# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_N0 is not set +# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P3 is not set +# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P6 is not set +CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P9=y +# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P12 is not set +# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P15 is not set +# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P18 is not set +# CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_P20 is not set +CONFIG_BT_CTRL_DFT_TX_POWER_LEVEL_EFF=11 +CONFIG_BT_CTRL_BLE_ADV_REPORT_FLOW_CTRL_SUPP=y +CONFIG_BT_CTRL_BLE_ADV_REPORT_FLOW_CTRL_NUM=100 +CONFIG_BT_CTRL_BLE_ADV_REPORT_DISCARD_THRSHOLD=20 +CONFIG_BT_CTRL_BLE_SCAN_DUPL=y +CONFIG_BT_CTRL_SCAN_DUPL_TYPE_DEVICE=y +# CONFIG_BT_CTRL_SCAN_DUPL_TYPE_DATA is not set +# CONFIG_BT_CTRL_SCAN_DUPL_TYPE_DATA_DEVICE is not set +CONFIG_BT_CTRL_SCAN_DUPL_TYPE=0 +CONFIG_BT_CTRL_SCAN_DUPL_CACHE_SIZE=100 +CONFIG_BT_CTRL_DUPL_SCAN_CACHE_REFRESH_PERIOD=0 +# CONFIG_BT_CTRL_BLE_MESH_SCAN_DUPL_EN is not set +# CONFIG_BT_CTRL_COEX_PHY_CODED_TX_RX_TLIM_EN is not set +CONFIG_BT_CTRL_COEX_PHY_CODED_TX_RX_TLIM_DIS=y +CONFIG_BT_CTRL_COEX_PHY_CODED_TX_RX_TLIM_EFF=0 + +# +# MODEM SLEEP Options +# +# CONFIG_BT_CTRL_MODEM_SLEEP is not set +# end of MODEM SLEEP Options + +CONFIG_BT_CTRL_SLEEP_MODE_EFF=0 +CONFIG_BT_CTRL_SLEEP_CLOCK_EFF=0 +CONFIG_BT_CTRL_HCI_TL_EFF=1 +# CONFIG_BT_CTRL_AGC_RECORRECT_EN is not set +# CONFIG_BT_CTRL_SCAN_BACKOFF_UPPERLIMITMAX is not set +# CONFIG_BT_BLE_ADV_DATA_LENGTH_ZERO_AUX is not set +CONFIG_BT_CTRL_CHAN_ASS_EN=y +CONFIG_BT_CTRL_LE_PING_EN=y + +# +# BLE disconnects when Instant Passed (0x28) occurs +# +# CONFIG_BT_CTRL_BLE_LLCP_CONN_UPDATE is not set +# CONFIG_BT_CTRL_BLE_LLCP_CHAN_MAP_UPDATE is not set +# CONFIG_BT_CTRL_BLE_LLCP_PHY_UPDATE is not set +# end of BLE disconnects when Instant Passed (0x28) occurs + +# CONFIG_BT_CTRL_RUN_IN_FLASH_ONLY is not set +# CONFIG_BT_CTRL_CHECK_CONNECT_IND_ACCESS_ADDRESS is not set +# end of Controller Options + +# +# Common Options +# +CONFIG_BT_ALARM_MAX_NUM=50 +# CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED is not set +# end of Common Options + +# CONFIG_BT_HCI_LOG_DEBUG_EN is not set +# end of Bluetooth + +# CONFIG_BLE_MESH is not set + +# +# Console Library +# +# CONFIG_CONSOLE_SORTED_HELP is not set +# end of Console Library + +# +# Driver Configurations +# + +# +# TWAI Configuration +# +# CONFIG_TWAI_ISR_IN_IRAM is not set +CONFIG_TWAI_ERRATA_FIX_LISTEN_ONLY_DOM=y +# end of TWAI Configuration + +# +# Legacy ADC Driver Configuration +# +# CONFIG_ADC_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_ADC_SKIP_LEGACY_CONFLICT_CHECK is not set + +# +# Legacy ADC Calibration Configuration +# +# CONFIG_ADC_CALI_SUPPRESS_DEPRECATE_WARN is not set +# end of Legacy ADC Calibration Configuration +# end of Legacy ADC Driver Configuration + +# +# Legacy Timer Group Driver Configurations +# +# CONFIG_GPTIMER_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_GPTIMER_SKIP_LEGACY_CONFLICT_CHECK is not set +# end of Legacy Timer Group Driver Configurations + +# +# Legacy RMT Driver Configurations +# +# CONFIG_RMT_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_RMT_SKIP_LEGACY_CONFLICT_CHECK is not set +# end of Legacy RMT Driver Configurations + +# +# Legacy I2S Driver Configurations +# +# CONFIG_I2S_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_I2S_SKIP_LEGACY_CONFLICT_CHECK is not set +# end of Legacy I2S Driver Configurations + +# +# Legacy SDM Driver Configurations +# +# CONFIG_SDM_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_SDM_SKIP_LEGACY_CONFLICT_CHECK is not set +# end of Legacy SDM Driver Configurations + +# +# Legacy Temperature Sensor Driver Configurations +# +# CONFIG_TEMP_SENSOR_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_TEMP_SENSOR_SKIP_LEGACY_CONFLICT_CHECK is not set +# end of Legacy Temperature Sensor Driver Configurations +# end of Driver Configurations + +# +# eFuse Bit Manager +# +# CONFIG_EFUSE_CUSTOM_TABLE is not set +# CONFIG_EFUSE_VIRTUAL is not set +CONFIG_EFUSE_MAX_BLK_LEN=256 +# end of eFuse Bit Manager + +# +# ESP-TLS +# +CONFIG_ESP_TLS_USING_MBEDTLS=y +CONFIG_ESP_TLS_USE_DS_PERIPHERAL=y +# CONFIG_ESP_TLS_CLIENT_SESSION_TICKETS is not set +# CONFIG_ESP_TLS_SERVER_SESSION_TICKETS is not set +# CONFIG_ESP_TLS_SERVER_CERT_SELECT_HOOK is not set +# CONFIG_ESP_TLS_SERVER_MIN_AUTH_MODE_OPTIONAL is not set +# CONFIG_ESP_TLS_PSK_VERIFICATION is not set +# CONFIG_ESP_TLS_INSECURE is not set +# end of ESP-TLS + +# +# ADC and ADC Calibration +# +# CONFIG_ADC_ONESHOT_CTRL_FUNC_IN_IRAM is not set +# CONFIG_ADC_CONTINUOUS_ISR_IRAM_SAFE is not set +# CONFIG_ADC_CONTINUOUS_FORCE_USE_ADC2_ON_C3_S3 is not set +# CONFIG_ADC_ONESHOT_FORCE_USE_ADC2_ON_C3 is not set +# CONFIG_ADC_ENABLE_DEBUG_LOG is not set +# end of ADC and ADC Calibration + +# +# Wireless Coexistence +# +CONFIG_ESP_COEX_ENABLED=y +CONFIG_ESP_COEX_SW_COEXIST_ENABLE=y +# CONFIG_ESP_COEX_POWER_MANAGEMENT is not set +# CONFIG_ESP_COEX_GPIO_DEBUG is not set +# end of Wireless Coexistence + +# +# Common ESP-related +# +CONFIG_ESP_ERR_TO_NAME_LOOKUP=y +# end of Common ESP-related + +# +# ESP-Driver:GPIO Configurations +# +# CONFIG_GPIO_CTRL_FUNC_IN_IRAM is not set +# end of ESP-Driver:GPIO Configurations + +# +# ESP-Driver:GPTimer Configurations +# +CONFIG_GPTIMER_ISR_HANDLER_IN_IRAM=y +# CONFIG_GPTIMER_CTRL_FUNC_IN_IRAM is not set +# CONFIG_GPTIMER_ISR_IRAM_SAFE is not set +# CONFIG_GPTIMER_ENABLE_DEBUG_LOG is not set +# end of ESP-Driver:GPTimer Configurations + +# +# ESP-Driver:I2C Configurations +# +# CONFIG_I2C_ISR_IRAM_SAFE is not set +# CONFIG_I2C_ENABLE_DEBUG_LOG is not set +# CONFIG_I2C_ENABLE_SLAVE_DRIVER_VERSION_2 is not set +# end of ESP-Driver:I2C Configurations + +# +# ESP-Driver:I2S Configurations +# +# CONFIG_I2S_ISR_IRAM_SAFE is not set +# CONFIG_I2S_ENABLE_DEBUG_LOG is not set +# end of ESP-Driver:I2S Configurations + +# +# ESP-Driver:LEDC Configurations +# +# CONFIG_LEDC_CTRL_FUNC_IN_IRAM is not set +# end of ESP-Driver:LEDC Configurations + +# +# ESP-Driver:RMT Configurations +# +# CONFIG_RMT_ISR_IRAM_SAFE is not set +# CONFIG_RMT_RECV_FUNC_IN_IRAM is not set +# CONFIG_RMT_ENABLE_DEBUG_LOG is not set +# end of ESP-Driver:RMT Configurations + +# +# ESP-Driver:Sigma Delta Modulator Configurations +# +# CONFIG_SDM_CTRL_FUNC_IN_IRAM is not set +# CONFIG_SDM_ENABLE_DEBUG_LOG is not set +# end of ESP-Driver:Sigma Delta Modulator Configurations + +# +# ESP-Driver:SPI Configurations +# +# CONFIG_SPI_MASTER_IN_IRAM is not set +CONFIG_SPI_MASTER_ISR_IN_IRAM=y +# CONFIG_SPI_SLAVE_IN_IRAM is not set +CONFIG_SPI_SLAVE_ISR_IN_IRAM=y +# end of ESP-Driver:SPI Configurations + +# +# ESP-Driver:Temperature Sensor Configurations +# +# CONFIG_TEMP_SENSOR_ENABLE_DEBUG_LOG is not set +# end of ESP-Driver:Temperature Sensor Configurations + +# +# ESP-Driver:UART Configurations +# +# CONFIG_UART_ISR_IN_IRAM is not set +# end of ESP-Driver:UART Configurations + +# +# ESP-Driver:USB Serial/JTAG Configuration +# +CONFIG_USJ_ENABLE_USB_SERIAL_JTAG=y +# end of ESP-Driver:USB Serial/JTAG Configuration + +# +# Ethernet +# +CONFIG_ETH_ENABLED=y +CONFIG_ETH_USE_SPI_ETHERNET=y +# CONFIG_ETH_SPI_ETHERNET_DM9051 is not set +# CONFIG_ETH_SPI_ETHERNET_W5500 is not set +# CONFIG_ETH_SPI_ETHERNET_KSZ8851SNL is not set +# CONFIG_ETH_USE_OPENETH is not set +# CONFIG_ETH_TRANSMIT_MUTEX is not set +# end of Ethernet + +# +# Event Loop Library +# +# CONFIG_ESP_EVENT_LOOP_PROFILING is not set +CONFIG_ESP_EVENT_POST_FROM_ISR=y +CONFIG_ESP_EVENT_POST_FROM_IRAM_ISR=y +# end of Event Loop Library + +# +# GDB Stub +# +CONFIG_ESP_GDBSTUB_ENABLED=y +# CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME is not set +CONFIG_ESP_GDBSTUB_SUPPORT_TASKS=y +CONFIG_ESP_GDBSTUB_MAX_TASKS=32 +# end of GDB Stub + +# +# ESP HID +# +CONFIG_ESPHID_TASK_SIZE_BT=2048 +CONFIG_ESPHID_TASK_SIZE_BLE=4096 +# end of ESP HID + +# +# ESP HTTP client +# +CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS=y +# CONFIG_ESP_HTTP_CLIENT_ENABLE_BASIC_AUTH is not set +# CONFIG_ESP_HTTP_CLIENT_ENABLE_DIGEST_AUTH is not set +# CONFIG_ESP_HTTP_CLIENT_ENABLE_CUSTOM_TRANSPORT is not set +CONFIG_ESP_HTTP_CLIENT_EVENT_POST_TIMEOUT=2000 +# end of ESP HTTP client + +# +# HTTP Server +# +CONFIG_HTTPD_MAX_REQ_HDR_LEN=512 +CONFIG_HTTPD_MAX_URI_LEN=512 +CONFIG_HTTPD_ERR_RESP_NO_DELAY=y +CONFIG_HTTPD_PURGE_BUF_LEN=32 +# CONFIG_HTTPD_LOG_PURGE_DATA is not set +# CONFIG_HTTPD_WS_SUPPORT is not set +# CONFIG_HTTPD_QUEUE_WORK_BLOCKING is not set +CONFIG_HTTPD_SERVER_EVENT_POST_TIMEOUT=2000 +# end of HTTP Server + +# +# ESP HTTPS OTA +# +# CONFIG_ESP_HTTPS_OTA_DECRYPT_CB is not set +# CONFIG_ESP_HTTPS_OTA_ALLOW_HTTP is not set +CONFIG_ESP_HTTPS_OTA_EVENT_POST_TIMEOUT=2000 +# end of ESP HTTPS OTA + +# +# ESP HTTPS server +# +CONFIG_ESP_HTTPS_SERVER_ENABLE=y +CONFIG_ESP_HTTPS_SERVER_EVENT_POST_TIMEOUT=2000 +# end of ESP HTTPS server + +# +# Hardware Settings +# + +# +# Chip revision +# +# CONFIG_ESP32C3_REV_MIN_0 is not set +# CONFIG_ESP32C3_REV_MIN_1 is not set +# CONFIG_ESP32C3_REV_MIN_2 is not set +CONFIG_ESP32C3_REV_MIN_3=y +# CONFIG_ESP32C3_REV_MIN_4 is not set +# CONFIG_ESP32C3_REV_MIN_101 is not set +CONFIG_ESP32C3_REV_MIN_FULL=3 +CONFIG_ESP_REV_MIN_FULL=3 + +# +# Maximum Supported ESP32-C3 Revision (Rev v1.99) +# +CONFIG_ESP32C3_REV_MAX_FULL=199 +CONFIG_ESP_REV_MAX_FULL=199 +CONFIG_ESP_EFUSE_BLOCK_REV_MIN_FULL=0 +CONFIG_ESP_EFUSE_BLOCK_REV_MAX_FULL=199 + +# +# Maximum Supported ESP32-C3 eFuse Block Revision (eFuse Block Rev v1.99) +# +# end of Chip revision + +# +# MAC Config +# +CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_STA=y +CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_AP=y +CONFIG_ESP_MAC_ADDR_UNIVERSE_BT=y +CONFIG_ESP_MAC_ADDR_UNIVERSE_ETH=y +CONFIG_ESP_MAC_UNIVERSAL_MAC_ADDRESSES_FOUR=y +CONFIG_ESP_MAC_UNIVERSAL_MAC_ADDRESSES=4 +# CONFIG_ESP32C3_UNIVERSAL_MAC_ADDRESSES_TWO is not set +CONFIG_ESP32C3_UNIVERSAL_MAC_ADDRESSES_FOUR=y +CONFIG_ESP32C3_UNIVERSAL_MAC_ADDRESSES=4 +# CONFIG_ESP_MAC_USE_CUSTOM_MAC_AS_BASE_MAC is not set +# end of MAC Config + +# +# Sleep Config +# +# CONFIG_ESP_SLEEP_POWER_DOWN_FLASH is not set +CONFIG_ESP_SLEEP_FLASH_LEAKAGE_WORKAROUND=y +# CONFIG_ESP_SLEEP_MSPI_NEED_ALL_IO_PU is not set +CONFIG_ESP_SLEEP_GPIO_RESET_WORKAROUND=y +CONFIG_ESP_SLEEP_WAIT_FLASH_READY_EXTRA_DELAY=0 +# CONFIG_ESP_SLEEP_CACHE_SAFE_ASSERTION is not set +# CONFIG_ESP_SLEEP_DEBUG is not set +CONFIG_ESP_SLEEP_GPIO_ENABLE_INTERNAL_RESISTORS=y +# end of Sleep Config + +# +# RTC Clock Config +# +CONFIG_RTC_CLK_SRC_INT_RC=y +# CONFIG_RTC_CLK_SRC_EXT_CRYS is not set +# CONFIG_RTC_CLK_SRC_EXT_OSC is not set +# CONFIG_RTC_CLK_SRC_INT_8MD256 is not set +CONFIG_RTC_CLK_CAL_CYCLES=1024 +# end of RTC Clock Config + +# +# Peripheral Control +# +CONFIG_PERIPH_CTRL_FUNC_IN_IRAM=y +# end of Peripheral Control + +# +# GDMA Configurations +# +CONFIG_GDMA_CTRL_FUNC_IN_IRAM=y +# CONFIG_GDMA_ISR_IRAM_SAFE is not set +# CONFIG_GDMA_ENABLE_DEBUG_LOG is not set +# end of GDMA Configurations + +# +# Main XTAL Config +# +CONFIG_XTAL_FREQ_40=y +CONFIG_XTAL_FREQ=40 +# end of Main XTAL Config + +CONFIG_ESP_SPI_BUS_LOCK_ISR_FUNCS_IN_IRAM=y +# end of Hardware Settings + +# +# ESP-Driver:LCD Controller Configurations +# +# CONFIG_LCD_ENABLE_DEBUG_LOG is not set +# end of ESP-Driver:LCD Controller Configurations + +# +# ESP-MM: Memory Management Configurations +# +# end of ESP-MM: Memory Management Configurations + +# +# ESP NETIF Adapter +# +CONFIG_ESP_NETIF_IP_LOST_TIMER_INTERVAL=120 +# CONFIG_ESP_NETIF_PROVIDE_CUSTOM_IMPLEMENTATION is not set +CONFIG_ESP_NETIF_TCPIP_LWIP=y +# CONFIG_ESP_NETIF_LOOPBACK is not set +CONFIG_ESP_NETIF_USES_TCPIP_WITH_BSD_API=y +CONFIG_ESP_NETIF_REPORT_DATA_TRAFFIC=y +# CONFIG_ESP_NETIF_RECEIVE_REPORT_ERRORS is not set +# CONFIG_ESP_NETIF_L2_TAP is not set +# CONFIG_ESP_NETIF_BRIDGE_EN is not set +# CONFIG_ESP_NETIF_SET_DNS_PER_DEFAULT_NETIF is not set +# end of ESP NETIF Adapter + +# +# Partition API Configuration +# +# end of Partition API Configuration + +# +# PHY +# +CONFIG_ESP_PHY_ENABLED=y +CONFIG_ESP_PHY_CALIBRATION_AND_DATA_STORAGE=y +# CONFIG_ESP_PHY_INIT_DATA_IN_PARTITION is not set +CONFIG_ESP_PHY_MAX_WIFI_TX_POWER=20 +CONFIG_ESP_PHY_MAX_TX_POWER=20 +# CONFIG_ESP_PHY_REDUCE_TX_POWER is not set +CONFIG_ESP_PHY_ENABLE_USB=y +# CONFIG_ESP_PHY_ENABLE_CERT_TEST is not set +CONFIG_ESP_PHY_RF_CAL_PARTIAL=y +# CONFIG_ESP_PHY_RF_CAL_NONE is not set +# CONFIG_ESP_PHY_RF_CAL_FULL is not set +CONFIG_ESP_PHY_CALIBRATION_MODE=0 +# CONFIG_ESP_PHY_PLL_TRACK_DEBUG is not set +# CONFIG_ESP_PHY_RECORD_USED_TIME is not set +# end of PHY + +# +# Power Management +# +# CONFIG_PM_ENABLE is not set +# CONFIG_PM_SLP_IRAM_OPT is not set +CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP=y +# end of Power Management + +# +# ESP PSRAM +# + +# +# ESP Ringbuf +# +# CONFIG_RINGBUF_PLACE_FUNCTIONS_INTO_FLASH is not set +# end of ESP Ringbuf + +# +# ESP Security Specific +# +# end of ESP Security Specific + +# +# ESP System Settings +# +# CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_80 is not set +CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_160=y +CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ=160 +# CONFIG_ESP_SYSTEM_PANIC_PRINT_HALT is not set +CONFIG_ESP_SYSTEM_PANIC_PRINT_REBOOT=y +# CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT is not set +# CONFIG_ESP_SYSTEM_PANIC_GDBSTUB is not set +CONFIG_ESP_SYSTEM_PANIC_REBOOT_DELAY_SECONDS=0 +CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE=y +CONFIG_ESP_SYSTEM_RTC_FAST_MEM_AS_HEAP_DEPCHECK=y +CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP=y +# CONFIG_ESP_SYSTEM_USE_EH_FRAME is not set + +# +# Memory protection +# +CONFIG_ESP_SYSTEM_MEMPROT_FEATURE=y +CONFIG_ESP_SYSTEM_MEMPROT_FEATURE_LOCK=y +# end of Memory protection + +CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE=32 +CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=2304 +CONFIG_ESP_MAIN_TASK_STACK_SIZE=3584 +CONFIG_ESP_MAIN_TASK_AFFINITY_CPU0=y +# CONFIG_ESP_MAIN_TASK_AFFINITY_NO_AFFINITY is not set +CONFIG_ESP_MAIN_TASK_AFFINITY=0x0 +CONFIG_ESP_MINIMAL_SHARED_STACK_SIZE=2048 +CONFIG_ESP_CONSOLE_UART_DEFAULT=y +# CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG is not set +# CONFIG_ESP_CONSOLE_UART_CUSTOM is not set +# CONFIG_ESP_CONSOLE_NONE is not set +# CONFIG_ESP_CONSOLE_SECONDARY_NONE is not set +CONFIG_ESP_CONSOLE_SECONDARY_USB_SERIAL_JTAG=y +CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG_ENABLED=y +CONFIG_ESP_CONSOLE_UART=y +CONFIG_ESP_CONSOLE_UART_NUM=0 +CONFIG_ESP_CONSOLE_ROM_SERIAL_PORT_NUM=0 +CONFIG_ESP_CONSOLE_UART_BAUDRATE=115200 +CONFIG_ESP_INT_WDT=y +CONFIG_ESP_INT_WDT_TIMEOUT_MS=300 +CONFIG_ESP_TASK_WDT_EN=y +CONFIG_ESP_TASK_WDT_INIT=y +# CONFIG_ESP_TASK_WDT_PANIC is not set +CONFIG_ESP_TASK_WDT_TIMEOUT_S=5 +CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0=y +# CONFIG_ESP_PANIC_HANDLER_IRAM is not set +# CONFIG_ESP_DEBUG_STUBS_ENABLE is not set +CONFIG_ESP_DEBUG_OCDAWARE=y +CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL_4=y + +# +# Brownout Detector +# +CONFIG_ESP_BROWNOUT_DET=y +CONFIG_ESP_BROWNOUT_DET_LVL_SEL_7=y +# CONFIG_ESP_BROWNOUT_DET_LVL_SEL_6 is not set +# CONFIG_ESP_BROWNOUT_DET_LVL_SEL_5 is not set +# CONFIG_ESP_BROWNOUT_DET_LVL_SEL_4 is not set +# CONFIG_ESP_BROWNOUT_DET_LVL_SEL_3 is not set +# CONFIG_ESP_BROWNOUT_DET_LVL_SEL_2 is not set +CONFIG_ESP_BROWNOUT_DET_LVL=7 +# end of Brownout Detector + +CONFIG_ESP_SYSTEM_BROWNOUT_INTR=y +CONFIG_ESP_SYSTEM_HW_STACK_GUARD=y +CONFIG_ESP_SYSTEM_HW_PC_RECORD=y +# end of ESP System Settings + +# +# IPC (Inter-Processor Call) +# +CONFIG_ESP_IPC_TASK_STACK_SIZE=1024 +# end of IPC (Inter-Processor Call) + +# +# ESP Timer (High Resolution Timer) +# +# CONFIG_ESP_TIMER_PROFILING is not set +CONFIG_ESP_TIME_FUNCS_USE_RTC_TIMER=y +CONFIG_ESP_TIME_FUNCS_USE_ESP_TIMER=y +CONFIG_ESP_TIMER_TASK_STACK_SIZE=3584 +CONFIG_ESP_TIMER_INTERRUPT_LEVEL=1 +# CONFIG_ESP_TIMER_SHOW_EXPERIMENTAL is not set +CONFIG_ESP_TIMER_TASK_AFFINITY=0x0 +CONFIG_ESP_TIMER_TASK_AFFINITY_CPU0=y +CONFIG_ESP_TIMER_ISR_AFFINITY_CPU0=y +# CONFIG_ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD is not set +CONFIG_ESP_TIMER_IMPL_SYSTIMER=y +# end of ESP Timer (High Resolution Timer) + +# +# Wi-Fi +# +CONFIG_ESP_WIFI_ENABLED=y +CONFIG_ESP_WIFI_STATIC_RX_BUFFER_NUM=10 +CONFIG_ESP_WIFI_DYNAMIC_RX_BUFFER_NUM=32 +# CONFIG_ESP_WIFI_STATIC_TX_BUFFER is not set +CONFIG_ESP_WIFI_DYNAMIC_TX_BUFFER=y +CONFIG_ESP_WIFI_TX_BUFFER_TYPE=1 +CONFIG_ESP_WIFI_DYNAMIC_TX_BUFFER_NUM=32 +CONFIG_ESP_WIFI_STATIC_RX_MGMT_BUFFER=y +# CONFIG_ESP_WIFI_DYNAMIC_RX_MGMT_BUFFER is not set +CONFIG_ESP_WIFI_DYNAMIC_RX_MGMT_BUF=0 +CONFIG_ESP_WIFI_RX_MGMT_BUF_NUM_DEF=5 +# CONFIG_ESP_WIFI_CSI_ENABLED is not set +CONFIG_ESP_WIFI_AMPDU_TX_ENABLED=y +CONFIG_ESP_WIFI_TX_BA_WIN=6 +CONFIG_ESP_WIFI_AMPDU_RX_ENABLED=y +CONFIG_ESP_WIFI_RX_BA_WIN=6 +CONFIG_ESP_WIFI_NVS_ENABLED=y +CONFIG_ESP_WIFI_SOFTAP_BEACON_MAX_LEN=752 +CONFIG_ESP_WIFI_MGMT_SBUF_NUM=32 +CONFIG_ESP_WIFI_IRAM_OPT=y +# CONFIG_ESP_WIFI_EXTRA_IRAM_OPT is not set +CONFIG_ESP_WIFI_RX_IRAM_OPT=y +CONFIG_ESP_WIFI_ENABLE_WPA3_SAE=y +CONFIG_ESP_WIFI_ENABLE_SAE_PK=y +CONFIG_ESP_WIFI_SOFTAP_SAE_SUPPORT=y +CONFIG_ESP_WIFI_ENABLE_WPA3_OWE_STA=y +# CONFIG_ESP_WIFI_SLP_IRAM_OPT is not set +CONFIG_ESP_WIFI_SLP_DEFAULT_MIN_ACTIVE_TIME=50 +CONFIG_ESP_WIFI_SLP_DEFAULT_MAX_ACTIVE_TIME=10 +CONFIG_ESP_WIFI_SLP_DEFAULT_WAIT_BROADCAST_DATA_TIME=15 +# CONFIG_ESP_WIFI_FTM_ENABLE is not set +CONFIG_ESP_WIFI_STA_DISCONNECTED_PM_ENABLE=y +# CONFIG_ESP_WIFI_GCMP_SUPPORT is not set +CONFIG_ESP_WIFI_GMAC_SUPPORT=y +CONFIG_ESP_WIFI_SOFTAP_SUPPORT=y +# CONFIG_ESP_WIFI_SLP_BEACON_LOST_OPT is not set +CONFIG_ESP_WIFI_ESPNOW_MAX_ENCRYPT_NUM=7 +CONFIG_ESP_WIFI_MBEDTLS_CRYPTO=y +CONFIG_ESP_WIFI_MBEDTLS_TLS_CLIENT=y +# CONFIG_ESP_WIFI_WAPI_PSK is not set +# CONFIG_ESP_WIFI_SUITE_B_192 is not set +# CONFIG_ESP_WIFI_11KV_SUPPORT is not set +# CONFIG_ESP_WIFI_MBO_SUPPORT is not set +# CONFIG_ESP_WIFI_DPP_SUPPORT is not set +# CONFIG_ESP_WIFI_11R_SUPPORT is not set +# CONFIG_ESP_WIFI_WPS_SOFTAP_REGISTRAR is not set + +# +# WPS Configuration Options +# +# CONFIG_ESP_WIFI_WPS_STRICT is not set +# CONFIG_ESP_WIFI_WPS_PASSPHRASE is not set +# end of WPS Configuration Options + +# CONFIG_ESP_WIFI_DEBUG_PRINT is not set +# CONFIG_ESP_WIFI_TESTING_OPTIONS is not set +CONFIG_ESP_WIFI_ENTERPRISE_SUPPORT=y +# CONFIG_ESP_WIFI_ENT_FREE_DYNAMIC_BUFFER is not set +# end of Wi-Fi + +# +# Core dump +# +# CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH is not set +# CONFIG_ESP_COREDUMP_ENABLE_TO_UART is not set +CONFIG_ESP_COREDUMP_ENABLE_TO_NONE=y +# end of Core dump + +# +# FAT Filesystem support +# +CONFIG_FATFS_VOLUME_COUNT=2 +CONFIG_FATFS_LFN_NONE=y +# CONFIG_FATFS_LFN_HEAP is not set +# CONFIG_FATFS_LFN_STACK is not set +# CONFIG_FATFS_SECTOR_512 is not set +CONFIG_FATFS_SECTOR_4096=y +# CONFIG_FATFS_CODEPAGE_DYNAMIC is not set +CONFIG_FATFS_CODEPAGE_437=y +# CONFIG_FATFS_CODEPAGE_720 is not set +# CONFIG_FATFS_CODEPAGE_737 is not set +# CONFIG_FATFS_CODEPAGE_771 is not set +# CONFIG_FATFS_CODEPAGE_775 is not set +# CONFIG_FATFS_CODEPAGE_850 is not set +# CONFIG_FATFS_CODEPAGE_852 is not set +# CONFIG_FATFS_CODEPAGE_855 is not set +# CONFIG_FATFS_CODEPAGE_857 is not set +# CONFIG_FATFS_CODEPAGE_860 is not set +# CONFIG_FATFS_CODEPAGE_861 is not set +# CONFIG_FATFS_CODEPAGE_862 is not set +# CONFIG_FATFS_CODEPAGE_863 is not set +# CONFIG_FATFS_CODEPAGE_864 is not set +# CONFIG_FATFS_CODEPAGE_865 is not set +# CONFIG_FATFS_CODEPAGE_866 is not set +# CONFIG_FATFS_CODEPAGE_869 is not set +# CONFIG_FATFS_CODEPAGE_932 is not set +# CONFIG_FATFS_CODEPAGE_936 is not set +# CONFIG_FATFS_CODEPAGE_949 is not set +# CONFIG_FATFS_CODEPAGE_950 is not set +CONFIG_FATFS_CODEPAGE=437 +CONFIG_FATFS_FS_LOCK=0 +CONFIG_FATFS_TIMEOUT_MS=10000 +CONFIG_FATFS_PER_FILE_CACHE=y +# CONFIG_FATFS_USE_FASTSEEK is not set +CONFIG_FATFS_USE_STRFUNC_NONE=y +# CONFIG_FATFS_USE_STRFUNC_WITHOUT_CRLF_CONV is not set +# CONFIG_FATFS_USE_STRFUNC_WITH_CRLF_CONV is not set +CONFIG_FATFS_VFS_FSTAT_BLKSIZE=0 +# CONFIG_FATFS_IMMEDIATE_FSYNC is not set +# CONFIG_FATFS_USE_LABEL is not set +CONFIG_FATFS_LINK_LOCK=y +# end of FAT Filesystem support + +# +# FreeRTOS +# + +# +# Kernel +# +# CONFIG_FREERTOS_SMP is not set +CONFIG_FREERTOS_UNICORE=y +CONFIG_FREERTOS_HZ=100 +CONFIG_FREERTOS_OPTIMIZED_SCHEDULER=y +# CONFIG_FREERTOS_CHECK_STACKOVERFLOW_NONE is not set +# CONFIG_FREERTOS_CHECK_STACKOVERFLOW_PTRVAL is not set +CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY=y +CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS=1 +CONFIG_FREERTOS_IDLE_TASK_STACKSIZE=1536 +# CONFIG_FREERTOS_USE_IDLE_HOOK is not set +# CONFIG_FREERTOS_USE_TICK_HOOK is not set +CONFIG_FREERTOS_MAX_TASK_NAME_LEN=16 +# CONFIG_FREERTOS_ENABLE_BACKWARD_COMPATIBILITY is not set +CONFIG_FREERTOS_USE_TIMERS=y +CONFIG_FREERTOS_TIMER_SERVICE_TASK_NAME="Tmr Svc" +# CONFIG_FREERTOS_TIMER_TASK_AFFINITY_CPU0 is not set +CONFIG_FREERTOS_TIMER_TASK_NO_AFFINITY=y +CONFIG_FREERTOS_TIMER_SERVICE_TASK_CORE_AFFINITY=0x7FFFFFFF +CONFIG_FREERTOS_TIMER_TASK_PRIORITY=1 +CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=3120 +CONFIG_FREERTOS_TIMER_QUEUE_LENGTH=10 +CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE=0 +CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES=1 +# CONFIG_FREERTOS_USE_TRACE_FACILITY is not set +# CONFIG_FREERTOS_USE_LIST_DATA_INTEGRITY_CHECK_BYTES is not set +# CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS is not set +# CONFIG_FREERTOS_USE_APPLICATION_TASK_TAG is not set +# end of Kernel + +# +# Port +# +CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER=y +# CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK is not set +CONFIG_FREERTOS_TLSP_DELETION_CALLBACKS=y +# CONFIG_FREERTOS_TASK_PRE_DELETION_HOOK is not set +# CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP is not set +CONFIG_FREERTOS_CHECK_MUTEX_GIVEN_BY_OWNER=y +CONFIG_FREERTOS_ISR_STACKSIZE=1536 +CONFIG_FREERTOS_INTERRUPT_BACKTRACE=y +CONFIG_FREERTOS_TICK_SUPPORT_SYSTIMER=y +CONFIG_FREERTOS_CORETIMER_SYSTIMER_LVL1=y +# CONFIG_FREERTOS_CORETIMER_SYSTIMER_LVL3 is not set +CONFIG_FREERTOS_SYSTICK_USES_SYSTIMER=y +# CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH is not set +# CONFIG_FREERTOS_CHECK_PORT_CRITICAL_COMPLIANCE is not set +# end of Port + +# +# Extra +# +# end of Extra + +CONFIG_FREERTOS_PORT=y +CONFIG_FREERTOS_NO_AFFINITY=0x7FFFFFFF +CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION=y +CONFIG_FREERTOS_DEBUG_OCDAWARE=y +CONFIG_FREERTOS_ENABLE_TASK_SNAPSHOT=y +CONFIG_FREERTOS_PLACE_SNAPSHOT_FUNS_INTO_FLASH=y +CONFIG_FREERTOS_NUMBER_OF_CORES=1 +# end of FreeRTOS + +# +# Hardware Abstraction Layer (HAL) and Low Level (LL) +# +CONFIG_HAL_ASSERTION_EQUALS_SYSTEM=y +# CONFIG_HAL_ASSERTION_DISABLE is not set +# CONFIG_HAL_ASSERTION_SILENT is not set +# CONFIG_HAL_ASSERTION_ENABLE is not set +CONFIG_HAL_DEFAULT_ASSERTION_LEVEL=2 +CONFIG_HAL_SPI_MASTER_FUNC_IN_IRAM=y +CONFIG_HAL_SPI_SLAVE_FUNC_IN_IRAM=y +# end of Hardware Abstraction Layer (HAL) and Low Level (LL) + +# +# Heap memory debugging +# +CONFIG_HEAP_POISONING_DISABLED=y +# CONFIG_HEAP_POISONING_LIGHT is not set +# CONFIG_HEAP_POISONING_COMPREHENSIVE is not set +CONFIG_HEAP_TRACING_OFF=y +# CONFIG_HEAP_TRACING_STANDALONE is not set +# CONFIG_HEAP_TRACING_TOHOST is not set +# CONFIG_HEAP_USE_HOOKS is not set +# CONFIG_HEAP_TASK_TRACKING is not set +# CONFIG_HEAP_ABORT_WHEN_ALLOCATION_FAILS is not set +# CONFIG_HEAP_PLACE_FUNCTION_INTO_FLASH is not set +# end of Heap memory debugging + +# +# Log +# + +# +# Log Level +# +# CONFIG_LOG_DEFAULT_LEVEL_NONE is not set +# CONFIG_LOG_DEFAULT_LEVEL_ERROR is not set +# CONFIG_LOG_DEFAULT_LEVEL_WARN is not set +CONFIG_LOG_DEFAULT_LEVEL_INFO=y +# CONFIG_LOG_DEFAULT_LEVEL_DEBUG is not set +# CONFIG_LOG_DEFAULT_LEVEL_VERBOSE is not set +CONFIG_LOG_DEFAULT_LEVEL=3 +CONFIG_LOG_MAXIMUM_EQUALS_DEFAULT=y +# CONFIG_LOG_MAXIMUM_LEVEL_DEBUG is not set +# CONFIG_LOG_MAXIMUM_LEVEL_VERBOSE is not set +CONFIG_LOG_MAXIMUM_LEVEL=3 + +# +# Level Settings +# +# CONFIG_LOG_MASTER_LEVEL is not set +CONFIG_LOG_DYNAMIC_LEVEL_CONTROL=y +# CONFIG_LOG_TAG_LEVEL_IMPL_NONE is not set +# CONFIG_LOG_TAG_LEVEL_IMPL_LINKED_LIST is not set +CONFIG_LOG_TAG_LEVEL_IMPL_CACHE_AND_LINKED_LIST=y +# CONFIG_LOG_TAG_LEVEL_CACHE_ARRAY is not set +CONFIG_LOG_TAG_LEVEL_CACHE_BINARY_MIN_HEAP=y +CONFIG_LOG_TAG_LEVEL_IMPL_CACHE_SIZE=31 +# end of Level Settings +# end of Log Level + +# +# Format +# +# CONFIG_LOG_COLORS is not set +CONFIG_LOG_TIMESTAMP_SOURCE_RTOS=y +# CONFIG_LOG_TIMESTAMP_SOURCE_SYSTEM is not set +# end of Format +# end of Log + +# +# LWIP +# +CONFIG_LWIP_ENABLE=y +CONFIG_LWIP_LOCAL_HOSTNAME="espressif" +# CONFIG_LWIP_NETIF_API is not set +CONFIG_LWIP_TCPIP_TASK_PRIO=18 +# CONFIG_LWIP_TCPIP_CORE_LOCKING is not set +# CONFIG_LWIP_CHECK_THREAD_SAFETY is not set +CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES=y +# CONFIG_LWIP_L2_TO_L3_COPY is not set +# CONFIG_LWIP_IRAM_OPTIMIZATION is not set +# CONFIG_LWIP_EXTRA_IRAM_OPTIMIZATION is not set +CONFIG_LWIP_TIMERS_ONDEMAND=y +CONFIG_LWIP_ND6=y +# CONFIG_LWIP_FORCE_ROUTER_FORWARDING is not set +CONFIG_LWIP_MAX_SOCKETS=10 +# CONFIG_LWIP_USE_ONLY_LWIP_SELECT is not set +# CONFIG_LWIP_SO_LINGER is not set +CONFIG_LWIP_SO_REUSE=y +CONFIG_LWIP_SO_REUSE_RXTOALL=y +# CONFIG_LWIP_SO_RCVBUF is not set +# CONFIG_LWIP_NETBUF_RECVINFO is not set +CONFIG_LWIP_IP_DEFAULT_TTL=64 +CONFIG_LWIP_IP4_FRAG=y +CONFIG_LWIP_IP6_FRAG=y +# CONFIG_LWIP_IP4_REASSEMBLY is not set +# CONFIG_LWIP_IP6_REASSEMBLY is not set +CONFIG_LWIP_IP_REASS_MAX_PBUFS=10 +# CONFIG_LWIP_IP_FORWARD is not set +# CONFIG_LWIP_STATS is not set +CONFIG_LWIP_ESP_GRATUITOUS_ARP=y +CONFIG_LWIP_GARP_TMR_INTERVAL=60 +CONFIG_LWIP_ESP_MLDV6_REPORT=y +CONFIG_LWIP_MLDV6_TMR_INTERVAL=40 +CONFIG_LWIP_TCPIP_RECVMBOX_SIZE=32 +CONFIG_LWIP_DHCP_DOES_ARP_CHECK=y +# CONFIG_LWIP_DHCP_DOES_ACD_CHECK is not set +# CONFIG_LWIP_DHCP_DOES_NOT_CHECK_OFFERED_IP is not set +# CONFIG_LWIP_DHCP_DISABLE_CLIENT_ID is not set +CONFIG_LWIP_DHCP_DISABLE_VENDOR_CLASS_ID=y +# CONFIG_LWIP_DHCP_RESTORE_LAST_IP is not set +CONFIG_LWIP_DHCP_OPTIONS_LEN=68 +CONFIG_LWIP_NUM_NETIF_CLIENT_DATA=0 +CONFIG_LWIP_DHCP_COARSE_TIMER_SECS=1 + +# +# DHCP server +# +CONFIG_LWIP_DHCPS=y +CONFIG_LWIP_DHCPS_LEASE_UNIT=60 +CONFIG_LWIP_DHCPS_MAX_STATION_NUM=8 +CONFIG_LWIP_DHCPS_STATIC_ENTRIES=y +CONFIG_LWIP_DHCPS_ADD_DNS=y +# end of DHCP server + +# CONFIG_LWIP_AUTOIP is not set +CONFIG_LWIP_IPV4=y +CONFIG_LWIP_IPV6=y +# CONFIG_LWIP_IPV6_AUTOCONFIG is not set +CONFIG_LWIP_IPV6_NUM_ADDRESSES=3 +# CONFIG_LWIP_IPV6_FORWARD is not set +# CONFIG_LWIP_NETIF_STATUS_CALLBACK is not set +CONFIG_LWIP_NETIF_LOOPBACK=y +CONFIG_LWIP_LOOPBACK_MAX_PBUFS=8 + +# +# TCP +# +CONFIG_LWIP_MAX_ACTIVE_TCP=16 +CONFIG_LWIP_MAX_LISTENING_TCP=16 +CONFIG_LWIP_TCP_HIGH_SPEED_RETRANSMISSION=y +CONFIG_LWIP_TCP_MAXRTX=12 +CONFIG_LWIP_TCP_SYNMAXRTX=12 +CONFIG_LWIP_TCP_MSS=1440 +CONFIG_LWIP_TCP_TMR_INTERVAL=250 +CONFIG_LWIP_TCP_MSL=60000 +CONFIG_LWIP_TCP_FIN_WAIT_TIMEOUT=20000 +CONFIG_LWIP_TCP_SND_BUF_DEFAULT=5760 +CONFIG_LWIP_TCP_WND_DEFAULT=5760 +CONFIG_LWIP_TCP_RECVMBOX_SIZE=6 +CONFIG_LWIP_TCP_ACCEPTMBOX_SIZE=6 +CONFIG_LWIP_TCP_QUEUE_OOSEQ=y +CONFIG_LWIP_TCP_OOSEQ_TIMEOUT=6 +CONFIG_LWIP_TCP_OOSEQ_MAX_PBUFS=4 +# CONFIG_LWIP_TCP_SACK_OUT is not set +CONFIG_LWIP_TCP_OVERSIZE_MSS=y +# CONFIG_LWIP_TCP_OVERSIZE_QUARTER_MSS is not set +# CONFIG_LWIP_TCP_OVERSIZE_DISABLE is not set +CONFIG_LWIP_TCP_RTO_TIME=1500 +# end of TCP + +# +# UDP +# +CONFIG_LWIP_MAX_UDP_PCBS=16 +CONFIG_LWIP_UDP_RECVMBOX_SIZE=6 +# end of UDP + +# +# Checksums +# +# CONFIG_LWIP_CHECKSUM_CHECK_IP is not set +# CONFIG_LWIP_CHECKSUM_CHECK_UDP is not set +CONFIG_LWIP_CHECKSUM_CHECK_ICMP=y +# end of Checksums + +CONFIG_LWIP_TCPIP_TASK_STACK_SIZE=3072 +CONFIG_LWIP_TCPIP_TASK_AFFINITY_NO_AFFINITY=y +# CONFIG_LWIP_TCPIP_TASK_AFFINITY_CPU0 is not set +CONFIG_LWIP_TCPIP_TASK_AFFINITY=0x7FFFFFFF +CONFIG_LWIP_IPV6_MEMP_NUM_ND6_QUEUE=3 +CONFIG_LWIP_IPV6_ND6_NUM_NEIGHBORS=5 +CONFIG_LWIP_IPV6_ND6_NUM_PREFIXES=5 +CONFIG_LWIP_IPV6_ND6_NUM_ROUTERS=3 +CONFIG_LWIP_IPV6_ND6_NUM_DESTINATIONS=10 +# CONFIG_LWIP_PPP_SUPPORT is not set +# CONFIG_LWIP_SLIP_SUPPORT is not set + +# +# ICMP +# +CONFIG_LWIP_ICMP=y +# CONFIG_LWIP_MULTICAST_PING is not set +# CONFIG_LWIP_BROADCAST_PING is not set +# end of ICMP + +# +# LWIP RAW API +# +CONFIG_LWIP_MAX_RAW_PCBS=16 +# end of LWIP RAW API + +# +# SNTP +# +CONFIG_LWIP_SNTP_MAX_SERVERS=1 +# CONFIG_LWIP_DHCP_GET_NTP_SRV is not set +CONFIG_LWIP_SNTP_UPDATE_DELAY=3600000 +CONFIG_LWIP_SNTP_STARTUP_DELAY=y +CONFIG_LWIP_SNTP_MAXIMUM_STARTUP_DELAY=5000 +# end of SNTP + +# +# DNS +# +CONFIG_LWIP_DNS_MAX_HOST_IP=1 +CONFIG_LWIP_DNS_MAX_SERVERS=3 +# CONFIG_LWIP_FALLBACK_DNS_SERVER_SUPPORT is not set +# CONFIG_LWIP_DNS_SETSERVER_WITH_NETIF is not set +# end of DNS + +CONFIG_LWIP_BRIDGEIF_MAX_PORTS=7 +CONFIG_LWIP_ESP_LWIP_ASSERT=y + +# +# Hooks +# +# CONFIG_LWIP_HOOK_TCP_ISN_NONE is not set +CONFIG_LWIP_HOOK_TCP_ISN_DEFAULT=y +# CONFIG_LWIP_HOOK_TCP_ISN_CUSTOM is not set +CONFIG_LWIP_HOOK_IP6_ROUTE_NONE=y +# CONFIG_LWIP_HOOK_IP6_ROUTE_DEFAULT is not set +# CONFIG_LWIP_HOOK_IP6_ROUTE_CUSTOM is not set +CONFIG_LWIP_HOOK_ND6_GET_GW_NONE=y +# CONFIG_LWIP_HOOK_ND6_GET_GW_DEFAULT is not set +# CONFIG_LWIP_HOOK_ND6_GET_GW_CUSTOM is not set +CONFIG_LWIP_HOOK_IP6_SELECT_SRC_ADDR_NONE=y +# CONFIG_LWIP_HOOK_IP6_SELECT_SRC_ADDR_DEFAULT is not set +# CONFIG_LWIP_HOOK_IP6_SELECT_SRC_ADDR_CUSTOM is not set +CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_NONE=y +# CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_DEFAULT is not set +# CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_CUSTOM is not set +CONFIG_LWIP_HOOK_DNS_EXT_RESOLVE_NONE=y +# CONFIG_LWIP_HOOK_DNS_EXT_RESOLVE_CUSTOM is not set +# CONFIG_LWIP_HOOK_IP6_INPUT_NONE is not set +CONFIG_LWIP_HOOK_IP6_INPUT_DEFAULT=y +# CONFIG_LWIP_HOOK_IP6_INPUT_CUSTOM is not set +# end of Hooks + +# CONFIG_LWIP_DEBUG is not set +# end of LWIP + +# +# mbedTLS +# +CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y +# CONFIG_MBEDTLS_DEFAULT_MEM_ALLOC is not set +# CONFIG_MBEDTLS_CUSTOM_MEM_ALLOC is not set +CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN=y +CONFIG_MBEDTLS_SSL_IN_CONTENT_LEN=16384 +CONFIG_MBEDTLS_SSL_OUT_CONTENT_LEN=4096 +CONFIG_MBEDTLS_DYNAMIC_BUFFER=y +CONFIG_MBEDTLS_DYNAMIC_FREE_CONFIG_DATA=y +CONFIG_MBEDTLS_DYNAMIC_FREE_CA_CERT=y +# CONFIG_MBEDTLS_DEBUG is not set + +# +# mbedTLS v3.x related +# +# CONFIG_MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH is not set +# CONFIG_MBEDTLS_X509_TRUSTED_CERT_CALLBACK is not set +# CONFIG_MBEDTLS_SSL_CONTEXT_SERIALIZATION is not set +CONFIG_MBEDTLS_SSL_KEEP_PEER_CERTIFICATE=y +CONFIG_MBEDTLS_PKCS7_C=y +# end of mbedTLS v3.x related + +# +# Certificate Bundle +# +CONFIG_MBEDTLS_CERTIFICATE_BUNDLE=y +# CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_FULL is not set +CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_CMN=y +# CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_NONE is not set +# CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE is not set +# CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEPRECATED_LIST is not set +CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_MAX_CERTS=200 +# end of Certificate Bundle + +# CONFIG_MBEDTLS_ECP_RESTARTABLE is not set +CONFIG_MBEDTLS_CMAC_C=y +CONFIG_MBEDTLS_HARDWARE_AES=y +CONFIG_MBEDTLS_AES_USE_INTERRUPT=y +CONFIG_MBEDTLS_AES_INTERRUPT_LEVEL=0 +CONFIG_MBEDTLS_GCM_SUPPORT_NON_AES_CIPHER=y +CONFIG_MBEDTLS_HARDWARE_MPI=y +CONFIG_MBEDTLS_LARGE_KEY_SOFTWARE_MPI=y +CONFIG_MBEDTLS_MPI_USE_INTERRUPT=y +CONFIG_MBEDTLS_MPI_INTERRUPT_LEVEL=0 +CONFIG_MBEDTLS_HARDWARE_SHA=y +CONFIG_MBEDTLS_ROM_MD5=y +# CONFIG_MBEDTLS_ATCA_HW_ECDSA_SIGN is not set +# CONFIG_MBEDTLS_ATCA_HW_ECDSA_VERIFY is not set +CONFIG_MBEDTLS_HAVE_TIME=y +# CONFIG_MBEDTLS_PLATFORM_TIME_ALT is not set +# CONFIG_MBEDTLS_HAVE_TIME_DATE is not set +CONFIG_MBEDTLS_ECDSA_DETERMINISTIC=y +CONFIG_MBEDTLS_SHA512_C=y +# CONFIG_MBEDTLS_SHA3_C is not set +CONFIG_MBEDTLS_TLS_SERVER_AND_CLIENT=y +# CONFIG_MBEDTLS_TLS_SERVER_ONLY is not set +# CONFIG_MBEDTLS_TLS_CLIENT_ONLY is not set +# CONFIG_MBEDTLS_TLS_DISABLED is not set +CONFIG_MBEDTLS_TLS_SERVER=y +CONFIG_MBEDTLS_TLS_CLIENT=y +CONFIG_MBEDTLS_TLS_ENABLED=y + +# +# TLS Key Exchange Methods +# +# CONFIG_MBEDTLS_PSK_MODES is not set +CONFIG_MBEDTLS_KEY_EXCHANGE_RSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_RSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_RSA=y +# end of TLS Key Exchange Methods + +CONFIG_MBEDTLS_SSL_RENEGOTIATION=y +CONFIG_MBEDTLS_SSL_PROTO_TLS1_2=y +# CONFIG_MBEDTLS_SSL_PROTO_GMTSSL1_1 is not set +# CONFIG_MBEDTLS_SSL_PROTO_DTLS is not set +CONFIG_MBEDTLS_SSL_ALPN=y +CONFIG_MBEDTLS_CLIENT_SSL_SESSION_TICKETS=y +CONFIG_MBEDTLS_SERVER_SSL_SESSION_TICKETS=y + +# +# Symmetric Ciphers +# +CONFIG_MBEDTLS_AES_C=y +# CONFIG_MBEDTLS_CAMELLIA_C is not set +# CONFIG_MBEDTLS_DES_C is not set +# CONFIG_MBEDTLS_BLOWFISH_C is not set +# CONFIG_MBEDTLS_XTEA_C is not set +CONFIG_MBEDTLS_CCM_C=y +CONFIG_MBEDTLS_GCM_C=y +# CONFIG_MBEDTLS_NIST_KW_C is not set +# end of Symmetric Ciphers + +# CONFIG_MBEDTLS_RIPEMD160_C is not set + +# +# Certificates +# +CONFIG_MBEDTLS_PEM_PARSE_C=y +CONFIG_MBEDTLS_PEM_WRITE_C=y +CONFIG_MBEDTLS_X509_CRL_PARSE_C=y +CONFIG_MBEDTLS_X509_CSR_PARSE_C=y +# end of Certificates + +CONFIG_MBEDTLS_ECP_C=y +CONFIG_MBEDTLS_PK_PARSE_EC_EXTENDED=y +CONFIG_MBEDTLS_PK_PARSE_EC_COMPRESSED=y +# CONFIG_MBEDTLS_DHM_C is not set +CONFIG_MBEDTLS_ECDH_C=y +CONFIG_MBEDTLS_ECDSA_C=y +# CONFIG_MBEDTLS_ECJPAKE_C is not set +CONFIG_MBEDTLS_ECP_DP_SECP192R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP224R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP384R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP521R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP192K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP224K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP256K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP256R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP384R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP512R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_CURVE25519_ENABLED=y +CONFIG_MBEDTLS_ECP_NIST_OPTIM=y +# CONFIG_MBEDTLS_ECP_FIXED_POINT_OPTIM is not set +# CONFIG_MBEDTLS_POLY1305_C is not set +# CONFIG_MBEDTLS_CHACHA20_C is not set +# CONFIG_MBEDTLS_HKDF_C is not set +# CONFIG_MBEDTLS_THREADING_C is not set +CONFIG_MBEDTLS_ERROR_STRINGS=y +CONFIG_MBEDTLS_FS_IO=y +# end of mbedTLS + +# +# ESP-MQTT Configurations +# +CONFIG_MQTT_PROTOCOL_311=y +# CONFIG_MQTT_PROTOCOL_5 is not set +CONFIG_MQTT_TRANSPORT_SSL=y +CONFIG_MQTT_TRANSPORT_WEBSOCKET=y +CONFIG_MQTT_TRANSPORT_WEBSOCKET_SECURE=y +# CONFIG_MQTT_MSG_ID_INCREMENTAL is not set +# CONFIG_MQTT_SKIP_PUBLISH_IF_DISCONNECTED is not set +# CONFIG_MQTT_REPORT_DELETED_MESSAGES is not set +# CONFIG_MQTT_USE_CUSTOM_CONFIG is not set +# CONFIG_MQTT_TASK_CORE_SELECTION_ENABLED is not set +# CONFIG_MQTT_CUSTOM_OUTBOX is not set +# end of ESP-MQTT Configurations + +# +# Newlib +# +CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF=y +# CONFIG_NEWLIB_STDOUT_LINE_ENDING_LF is not set +# CONFIG_NEWLIB_STDOUT_LINE_ENDING_CR is not set +# CONFIG_NEWLIB_STDIN_LINE_ENDING_CRLF is not set +# CONFIG_NEWLIB_STDIN_LINE_ENDING_LF is not set +CONFIG_NEWLIB_STDIN_LINE_ENDING_CR=y +# CONFIG_NEWLIB_NANO_FORMAT is not set +CONFIG_NEWLIB_TIME_SYSCALL_USE_RTC_HRT=y +# CONFIG_NEWLIB_TIME_SYSCALL_USE_RTC is not set +# CONFIG_NEWLIB_TIME_SYSCALL_USE_HRT is not set +# CONFIG_NEWLIB_TIME_SYSCALL_USE_NONE is not set +# end of Newlib + +# +# NVS +# +# CONFIG_NVS_ENCRYPTION is not set +# CONFIG_NVS_ASSERT_ERROR_CHECK is not set +# CONFIG_NVS_LEGACY_DUP_KEYS_COMPATIBILITY is not set +# end of NVS + +# +# OpenThread +# +# CONFIG_OPENTHREAD_ENABLED is not set + +# +# OpenThread Spinel +# +# CONFIG_OPENTHREAD_SPINEL_ONLY is not set +# end of OpenThread Spinel +# end of OpenThread + +# +# Protocomm +# +CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_0=y +CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_1=y +CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_2=y +CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_PATCH_VERSION=y +# end of Protocomm + +# +# PThreads +# +CONFIG_PTHREAD_TASK_PRIO_DEFAULT=5 +CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT=3072 +CONFIG_PTHREAD_STACK_MIN=768 +CONFIG_PTHREAD_TASK_CORE_DEFAULT=-1 +CONFIG_PTHREAD_TASK_NAME_DEFAULT="pthread" +# end of PThreads + +# +# MMU Config +# +CONFIG_MMU_PAGE_SIZE_64KB=y +CONFIG_MMU_PAGE_MODE="64KB" +CONFIG_MMU_PAGE_SIZE=0x10000 +# end of MMU Config + +# +# Main Flash configuration +# + +# +# SPI Flash behavior when brownout +# +CONFIG_SPI_FLASH_BROWNOUT_RESET_XMC=y +CONFIG_SPI_FLASH_BROWNOUT_RESET=y +# end of SPI Flash behavior when brownout + +# +# Optional and Experimental Features (READ DOCS FIRST) +# + +# +# Features here require specific hardware (READ DOCS FIRST!) +# +# CONFIG_SPI_FLASH_AUTO_SUSPEND is not set +CONFIG_SPI_FLASH_SUSPEND_TSUS_VAL_US=50 +# CONFIG_SPI_FLASH_FORCE_ENABLE_XMC_C_SUSPEND is not set +# end of Optional and Experimental Features (READ DOCS FIRST) +# end of Main Flash configuration + +# +# SPI Flash driver +# +# CONFIG_SPI_FLASH_VERIFY_WRITE is not set +# CONFIG_SPI_FLASH_ENABLE_COUNTERS is not set +CONFIG_SPI_FLASH_ROM_DRIVER_PATCH=y +# CONFIG_SPI_FLASH_ROM_IMPL is not set +CONFIG_SPI_FLASH_DANGEROUS_WRITE_ABORTS=y +# CONFIG_SPI_FLASH_DANGEROUS_WRITE_FAILS is not set +# CONFIG_SPI_FLASH_DANGEROUS_WRITE_ALLOWED is not set +# CONFIG_SPI_FLASH_BYPASS_BLOCK_ERASE is not set +CONFIG_SPI_FLASH_YIELD_DURING_ERASE=y +CONFIG_SPI_FLASH_ERASE_YIELD_DURATION_MS=20 +CONFIG_SPI_FLASH_ERASE_YIELD_TICKS=1 +CONFIG_SPI_FLASH_WRITE_CHUNK_SIZE=8192 +# CONFIG_SPI_FLASH_SIZE_OVERRIDE is not set +# CONFIG_SPI_FLASH_CHECK_ERASE_TIMEOUT_DISABLED is not set +# CONFIG_SPI_FLASH_OVERRIDE_CHIP_DRIVER_LIST is not set + +# +# Auto-detect flash chips +# +CONFIG_SPI_FLASH_VENDOR_XMC_SUPPORTED=y +CONFIG_SPI_FLASH_VENDOR_GD_SUPPORTED=y +CONFIG_SPI_FLASH_VENDOR_ISSI_SUPPORTED=y +CONFIG_SPI_FLASH_VENDOR_MXIC_SUPPORTED=y +CONFIG_SPI_FLASH_VENDOR_WINBOND_SUPPORTED=y +CONFIG_SPI_FLASH_VENDOR_BOYA_SUPPORTED=y +CONFIG_SPI_FLASH_VENDOR_TH_SUPPORTED=y +CONFIG_SPI_FLASH_SUPPORT_ISSI_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_MXIC_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_GD_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_WINBOND_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_BOYA_CHIP=y +CONFIG_SPI_FLASH_SUPPORT_TH_CHIP=y +# end of Auto-detect flash chips + +CONFIG_SPI_FLASH_ENABLE_ENCRYPTED_READ_WRITE=y +# end of SPI Flash driver + +# +# SPIFFS Configuration +# +CONFIG_SPIFFS_MAX_PARTITIONS=3 + +# +# SPIFFS Cache Configuration +# +CONFIG_SPIFFS_CACHE=y +CONFIG_SPIFFS_CACHE_WR=y +# CONFIG_SPIFFS_CACHE_STATS is not set +# end of SPIFFS Cache Configuration + +CONFIG_SPIFFS_PAGE_CHECK=y +CONFIG_SPIFFS_GC_MAX_RUNS=10 +# CONFIG_SPIFFS_GC_STATS is not set +CONFIG_SPIFFS_PAGE_SIZE=256 +CONFIG_SPIFFS_OBJ_NAME_LEN=32 +# CONFIG_SPIFFS_FOLLOW_SYMLINKS is not set +CONFIG_SPIFFS_USE_MAGIC=y +CONFIG_SPIFFS_USE_MAGIC_LENGTH=y +CONFIG_SPIFFS_META_LENGTH=4 +CONFIG_SPIFFS_USE_MTIME=y + +# +# Debug Configuration +# +# CONFIG_SPIFFS_DBG is not set +# CONFIG_SPIFFS_API_DBG is not set +# CONFIG_SPIFFS_GC_DBG is not set +# CONFIG_SPIFFS_CACHE_DBG is not set +# CONFIG_SPIFFS_CHECK_DBG is not set +# CONFIG_SPIFFS_TEST_VISUALISATION is not set +# end of Debug Configuration +# end of SPIFFS Configuration + +# +# TCP Transport +# + +# +# Websocket +# +CONFIG_WS_TRANSPORT=y +CONFIG_WS_BUFFER_SIZE=1024 +# CONFIG_WS_DYNAMIC_BUFFER is not set +# end of Websocket +# end of TCP Transport + +# +# Unity unit testing library +# +CONFIG_UNITY_ENABLE_FLOAT=y +CONFIG_UNITY_ENABLE_DOUBLE=y +# CONFIG_UNITY_ENABLE_64BIT is not set +# CONFIG_UNITY_ENABLE_COLOR is not set +CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=y +# CONFIG_UNITY_ENABLE_FIXTURE is not set +# CONFIG_UNITY_ENABLE_BACKTRACE_ON_FAIL is not set +# end of Unity unit testing library + +# +# Virtual file system +# +CONFIG_VFS_SUPPORT_IO=y +CONFIG_VFS_SUPPORT_DIR=y +CONFIG_VFS_SUPPORT_SELECT=y +CONFIG_VFS_SUPPRESS_SELECT_DEBUG_OUTPUT=y +# CONFIG_VFS_SELECT_IN_RAM is not set +CONFIG_VFS_SUPPORT_TERMIOS=y +CONFIG_VFS_MAX_COUNT=8 + +# +# Host File System I/O (Semihosting) +# +CONFIG_VFS_SEMIHOSTFS_MAX_MOUNT_POINTS=1 +# end of Host File System I/O (Semihosting) + +CONFIG_VFS_INITIALIZE_DEV_NULL=y +# end of Virtual file system + +# +# Wear Levelling +# +# CONFIG_WL_SECTOR_SIZE_512 is not set +CONFIG_WL_SECTOR_SIZE_4096=y +CONFIG_WL_SECTOR_SIZE=4096 +# end of Wear Levelling + +# +# Wi-Fi Provisioning Manager +# +CONFIG_WIFI_PROV_SCAN_MAX_ENTRIES=16 +CONFIG_WIFI_PROV_AUTOSTOP_TIMEOUT=30 +# CONFIG_WIFI_PROV_BLE_BONDING is not set +CONFIG_WIFI_PROV_BLE_SEC_CONN=y +# CONFIG_WIFI_PROV_BLE_FORCE_ENCRYPTION is not set +# CONFIG_WIFI_PROV_BLE_NOTIFY is not set +# CONFIG_WIFI_PROV_KEEP_BLE_ON_AFTER_PROV is not set +CONFIG_WIFI_PROV_STA_ALL_CHANNEL_SCAN=y +# CONFIG_WIFI_PROV_STA_FAST_SCAN is not set +# end of Wi-Fi Provisioning Manager + +# +# GPIO Button +# +CONFIG_IO_GLITCH_FILTER_TIME_MS=50 +# end of GPIO Button + +# +# WS2812 RGB LED +# +CONFIG_WS2812_LED_ENABLE=y +CONFIG_WS2812_LED_GPIO=8 +# end of WS2812 RGB LED + +# +# ESP serial flasher +# +CONFIG_SERIAL_FLASHER_MD5_ENABLED=y +CONFIG_SERIAL_FLASHER_INTERFACE_UART=y +# CONFIG_SERIAL_FLASHER_INTERFACE_SPI is not set +# CONFIG_SERIAL_FLASHER_INTERFACE_USB is not set +# CONFIG_SERIAL_FLASHER_INTERFACE_SDIO is not set +CONFIG_SERIAL_FLASHER_RESET_HOLD_TIME_MS=100 +CONFIG_SERIAL_FLASHER_BOOT_HOLD_TIME_MS=50 +# CONFIG_SERIAL_FLASHER_DEBUG_TRACE is not set +CONFIG_SERIAL_FLASHER_WRITE_BLOCK_RETRIES=3 +# CONFIG_SERIAL_FLASHER_RESET_INVERT is not set +# CONFIG_SERIAL_FLASHER_BOOT_INVERT is not set +# end of ESP serial flasher + +# +# Diagnostics data store +# +CONFIG_DIAG_DATA_STORE_RTC=y +# CONFIG_DIAG_DATA_STORE_FLASH is not set +# CONFIG_DIAG_DATA_STORE_DBG_PRINTS is not set +CONFIG_DIAG_DATA_STORE_REPORTING_WATERMARK_PERCENT=80 + +# +# RTC Store +# +CONFIG_RTC_STORE_DATA_SIZE=6144 +CONFIG_RTC_STORE_CRITICAL_DATA_SIZE=4096 +# end of RTC Store +# end of Diagnostics data store + +# +# Diagnostics +# +CONFIG_DIAG_LOG_MSG_ARG_FORMAT_TLV=y +# CONFIG_DIAG_LOG_MSG_ARG_FORMAT_STRING is not set +CONFIG_DIAG_LOG_MSG_ARG_MAX_SIZE=64 +CONFIG_DIAG_LOG_DROP_WIFI_LOGS=y +# CONFIG_DIAG_ENABLE_WRAP_LOG_FUNCTIONS is not set +CONFIG_DIAG_ENABLE_METRICS=y +CONFIG_DIAG_METRICS_MAX_COUNT=20 +CONFIG_DIAG_ENABLE_HEAP_METRICS=y +CONFIG_DIAG_HEAP_POLLING_INTERVAL=30 +CONFIG_DIAG_ENABLE_WIFI_METRICS=y +CONFIG_DIAG_WIFI_POLLING_INTERVAL=30 +CONFIG_DIAG_ENABLE_VARIABLES=y +CONFIG_DIAG_VARIABLES_MAX_COUNT=20 +CONFIG_DIAG_ENABLE_NETWORK_VARIABLES=y +# CONFIG_DIAG_MORE_NETWORK_VARS is not set +# CONFIG_DIAG_USE_EXTERNAL_LOG_WRAP is not set +# end of Diagnostics + +# +# ESP Insights +# +# CONFIG_ESP_INSIGHTS_ENABLED is not set +CONFIG_ESP_INSIGHTS_TRANSPORT_MQTT=y +# CONFIG_ESP_INSIGHTS_TRANSPORT_HTTPS is not set +CONFIG_ESP_INSIGHTS_CLOUD_POST_MIN_INTERVAL_SEC=60 +CONFIG_ESP_INSIGHTS_CLOUD_POST_MAX_INTERVAL_SEC=240 +CONFIG_ESP_INSIGHTS_META_VERSION_10=y +# end of ESP Insights + +# +# OpenThread RCP Update +# +# CONFIG_AUTO_UPDATE_RCP is not set +# CONFIG_CREATE_OTA_IMAGE_WITH_RCP_FW is not set +# end of OpenThread RCP Update + +# +# ESP Secure Cert Manager +# +CONFIG_ESP_SECURE_CERT_DS_PERIPHERAL=y +# CONFIG_ESP_SECURE_CERT_SUPPORT_LEGACY_FORMATS is not set +# end of ESP Secure Cert Manager + +# +# jsmn +# +# CONFIG_JSMN_PARENT_LINKS is not set +# CONFIG_JSMN_STRICT is not set +# CONFIG_JSMN_STATIC is not set +# end of jsmn + +# +# mDNS +# +CONFIG_MDNS_MAX_INTERFACES=3 +CONFIG_MDNS_MAX_SERVICES=10 +CONFIG_MDNS_TASK_PRIORITY=1 +CONFIG_MDNS_ACTION_QUEUE_LEN=16 +CONFIG_MDNS_TASK_STACK_SIZE=4096 +# CONFIG_MDNS_TASK_AFFINITY_NO_AFFINITY is not set +CONFIG_MDNS_TASK_AFFINITY_CPU0=y +CONFIG_MDNS_TASK_AFFINITY=0x0 + +# +# MDNS Memory Configuration +# +CONFIG_MDNS_TASK_CREATE_FROM_INTERNAL=y +CONFIG_MDNS_MEMORY_ALLOC_INTERNAL=y +# CONFIG_MDNS_MEMORY_CUSTOM_IMPL is not set +# end of MDNS Memory Configuration + +CONFIG_MDNS_SERVICE_ADD_TIMEOUT_MS=2000 +CONFIG_MDNS_TIMER_PERIOD_MS=100 +# CONFIG_MDNS_NETWORKING_SOCKET is not set +# CONFIG_MDNS_SKIP_SUPPRESSING_OWN_QUERIES is not set +# CONFIG_MDNS_ENABLE_DEBUG_PRINTS is not set +CONFIG_MDNS_ENABLE_CONSOLE_CLI=y +# CONFIG_MDNS_RESPOND_REVERSE_QUERIES is not set +CONFIG_MDNS_MULTIPLE_INSTANCE=y + +# +# MDNS Predefined interfaces +# +CONFIG_MDNS_PREDEF_NETIF_STA=y +CONFIG_MDNS_PREDEF_NETIF_AP=y +CONFIG_MDNS_PREDEF_NETIF_ETH=y +# end of MDNS Predefined interfaces +# end of mDNS + +# +# Network Provisioning Manager +# +CONFIG_NETWORK_PROV_NETWORK_TYPE_WIFI=y +CONFIG_NETWORK_PROV_SCAN_MAX_ENTRIES=16 +CONFIG_NETWORK_PROV_AUTOSTOP_TIMEOUT=30 +# CONFIG_NETWORK_PROV_BLE_BONDING is not set +CONFIG_NETWORK_PROV_BLE_SEC_CONN=y +# CONFIG_NETWORK_PROV_BLE_FORCE_ENCRYPTION is not set +# CONFIG_NETWORK_PROV_KEEP_BLE_ON_AFTER_PROV is not set +CONFIG_NETWORK_PROV_WIFI_STA_ALL_CHANNEL_SCAN=y +# CONFIG_NETWORK_PROV_WIFI_STA_FAST_SCAN is not set +# end of Network Provisioning Manager + +# +# ESP RainMaker Common +# +CONFIG_ESP_RMAKER_LIB_ESP_MQTT=y +# CONFIG_ESP_RMAKER_LIB_AWS_IOT is not set +CONFIG_ESP_RMAKER_MQTT_GLUE_LIB=1 +CONFIG_ESP_RMAKER_MQTT_PORT_443=y +# CONFIG_ESP_RMAKER_MQTT_PORT_8883 is not set +CONFIG_ESP_RMAKER_MQTT_PORT=1 +# CONFIG_ESP_RMAKER_MQTT_PERSISTENT_SESSION is not set +CONFIG_ESP_RMAKER_MQTT_SEND_USERNAME=y +CONFIG_ESP_RMAKER_MQTT_PRODUCT_NAME="RMDev" +CONFIG_ESP_RMAKER_MQTT_PRODUCT_VERSION="1x0" +CONFIG_ESP_RMAKER_MQTT_PRODUCT_SKU="EX00" +CONFIG_ESP_RMAKER_MQTT_USE_CERT_BUNDLE=y +CONFIG_ESP_RMAKER_MAX_MQTT_SUBSCRIPTIONS=10 +CONFIG_ESP_RMAKER_MQTT_KEEP_ALIVE_INTERVAL=120 +CONFIG_ESP_RMAKER_NETWORK_OVER_WIFI=y +CONFIG_ESP_RMAKER_WORK_QUEUE_TASK_STACK=5120 +CONFIG_ESP_RMAKER_WORK_QUEUE_TASK_PRIORITY=5 +CONFIG_ESP_RMAKER_FACTORY_PARTITION_NAME="fctry" +CONFIG_ESP_RMAKER_FACTORY_NAMESPACE="rmaker_creds" +CONFIG_ESP_RMAKER_DEF_TIMEZONE="Asia/Shanghai" +CONFIG_ESP_RMAKER_SNTP_SERVER_NAME="pool.ntp.org" +CONFIG_ESP_RMAKER_MAX_COMMANDS=10 +# end of ESP RainMaker Common +# end of Component config + +# CONFIG_IDF_EXPERIMENTAL_FEATURES is not set + +# Deprecated options for backward compatibility +# CONFIG_APP_BUILD_TYPE_ELF_RAM is not set +# CONFIG_NO_BLOBS is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_NONE is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_ERROR is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_WARN is not set +CONFIG_LOG_BOOTLOADER_LEVEL_INFO=y +# CONFIG_LOG_BOOTLOADER_LEVEL_DEBUG is not set +# CONFIG_LOG_BOOTLOADER_LEVEL_VERBOSE is not set +CONFIG_LOG_BOOTLOADER_LEVEL=3 +CONFIG_APP_ROLLBACK_ENABLE=y +# CONFIG_APP_ANTI_ROLLBACK is not set +# CONFIG_FLASH_ENCRYPTION_ENABLED is not set +# CONFIG_FLASHMODE_QIO is not set +# CONFIG_FLASHMODE_QOUT is not set +CONFIG_FLASHMODE_DIO=y +# CONFIG_FLASHMODE_DOUT is not set +CONFIG_MONITOR_BAUD=115200 +CONFIG_APP_WIFI_PROV_SHOW_QR=y +CONFIG_APP_WIFI_PROV_MAX_POP_MISMATCH=5 +# CONFIG_APP_WIFI_PROV_TRANSPORT_SOFTAP is not set +CONFIG_APP_WIFI_PROV_TRANSPORT_BLE=y +CONFIG_APP_WIFI_PROV_TRANSPORT=2 +CONFIG_APP_WIFI_RESET_PROV_ON_FAILURE=y +# CONFIG_APP_WIFI_SHOW_DEMO_INTRO_TEXT is not set +CONFIG_APP_WIFI_PROV_TIMEOUT_PERIOD=30 +CONFIG_APP_WIFI_PROV_NAME_PREFIX="PROV" +CONFIG_ESP_RMAKER_LOCAL_CTRL_ENABLE=y +CONFIG_OPTIMIZATION_LEVEL_DEBUG=y +CONFIG_COMPILER_OPTIMIZATION_LEVEL_DEBUG=y +CONFIG_COMPILER_OPTIMIZATION_DEFAULT=y +# CONFIG_OPTIMIZATION_LEVEL_RELEASE is not set +# CONFIG_COMPILER_OPTIMIZATION_LEVEL_RELEASE is not set +CONFIG_OPTIMIZATION_ASSERTIONS_ENABLED=y +# CONFIG_OPTIMIZATION_ASSERTIONS_SILENT is not set +# CONFIG_OPTIMIZATION_ASSERTIONS_DISABLED is not set +CONFIG_OPTIMIZATION_ASSERTION_LEVEL=2 +# CONFIG_CXX_EXCEPTIONS is not set +CONFIG_STACK_CHECK_NONE=y +# CONFIG_STACK_CHECK_NORM is not set +# CONFIG_STACK_CHECK_STRONG is not set +# CONFIG_STACK_CHECK_ALL is not set +# CONFIG_WARN_WRITE_STRINGS is not set +# CONFIG_ESP32_APPTRACE_DEST_TRAX is not set +CONFIG_ESP32_APPTRACE_DEST_NONE=y +CONFIG_ESP32_APPTRACE_LOCK_ENABLE=y +# CONFIG_BLUEDROID_ENABLED is not set +CONFIG_NIMBLE_ENABLED=y +CONFIG_NIMBLE_MEM_ALLOC_MODE_INTERNAL=y +# CONFIG_NIMBLE_MEM_ALLOC_MODE_DEFAULT is not set +CONFIG_NIMBLE_MAX_CONNECTIONS=3 +CONFIG_NIMBLE_MAX_BONDS=3 +CONFIG_NIMBLE_MAX_CCCDS=8 +CONFIG_NIMBLE_L2CAP_COC_MAX_NUM=0 +CONFIG_NIMBLE_PINNED_TO_CORE=0 +CONFIG_NIMBLE_TASK_STACK_SIZE=4096 +CONFIG_BT_NIMBLE_TASK_STACK_SIZE=4096 +CONFIG_NIMBLE_ROLE_CENTRAL=y +CONFIG_NIMBLE_ROLE_PERIPHERAL=y +CONFIG_NIMBLE_ROLE_BROADCASTER=y +CONFIG_NIMBLE_ROLE_OBSERVER=y +# CONFIG_NIMBLE_NVS_PERSIST is not set +CONFIG_NIMBLE_SM_LEGACY=y +CONFIG_NIMBLE_SM_SC=y +# CONFIG_NIMBLE_SM_SC_DEBUG_KEYS is not set +CONFIG_BT_NIMBLE_SM_SC_LVL=0 +# CONFIG_NIMBLE_DEBUG is not set +CONFIG_NIMBLE_SVC_GAP_DEVICE_NAME="nimble" +CONFIG_NIMBLE_GAP_DEVICE_NAME_MAX_LEN=31 +CONFIG_NIMBLE_ATT_PREFERRED_MTU=256 +CONFIG_NIMBLE_SVC_GAP_APPEARANCE=0 +CONFIG_BT_NIMBLE_MSYS1_BLOCK_COUNT=12 +CONFIG_BT_NIMBLE_ACL_BUF_COUNT=24 +CONFIG_BT_NIMBLE_ACL_BUF_SIZE=255 +CONFIG_BT_NIMBLE_HCI_EVT_BUF_SIZE=70 +CONFIG_BT_NIMBLE_HCI_EVT_HI_BUF_COUNT=30 +CONFIG_BT_NIMBLE_HCI_EVT_LO_BUF_COUNT=8 +# CONFIG_NIMBLE_HS_FLOW_CTRL is not set +CONFIG_NIMBLE_RPA_TIMEOUT=900 +# CONFIG_NIMBLE_MESH is not set +CONFIG_NIMBLE_CRYPTO_STACK_MBEDTLS=y +# CONFIG_BT_NIMBLE_COEX_PHY_CODED_TX_RX_TLIM_EN is not set +CONFIG_BT_NIMBLE_COEX_PHY_CODED_TX_RX_TLIM_DIS=y +CONFIG_SW_COEXIST_ENABLE=y +CONFIG_ESP32_WIFI_SW_COEXIST_ENABLE=y +CONFIG_ESP_WIFI_SW_COEXIST_ENABLE=y +# CONFIG_EVENT_LOOP_PROFILING is not set +CONFIG_POST_EVENTS_FROM_ISR=y +CONFIG_POST_EVENTS_FROM_IRAM_ISR=y +CONFIG_GDBSTUB_SUPPORT_TASKS=y +CONFIG_GDBSTUB_MAX_TASKS=32 +# CONFIG_OTA_ALLOW_HTTP is not set +# CONFIG_ESP_SYSTEM_PD_FLASH is not set +CONFIG_ESP32C3_LIGHTSLEEP_GPIO_RESET_WORKAROUND=y +CONFIG_ESP32C3_RTC_CLK_SRC_INT_RC=y +# CONFIG_ESP32C3_RTC_CLK_SRC_EXT_CRYS is not set +# CONFIG_ESP32C3_RTC_CLK_SRC_EXT_OSC is not set +# CONFIG_ESP32C3_RTC_CLK_SRC_INT_8MD256 is not set +CONFIG_ESP32C3_RTC_CLK_CAL_CYCLES=1024 +CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE=y +# CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION is not set +CONFIG_ESP32_PHY_MAX_WIFI_TX_POWER=20 +CONFIG_ESP32_PHY_MAX_TX_POWER=20 +# CONFIG_REDUCE_PHY_TX_POWER is not set +# CONFIG_ESP32_REDUCE_PHY_TX_POWER is not set +CONFIG_ESP_SYSTEM_PM_POWER_DOWN_CPU=y +# CONFIG_ESP32C3_DEFAULT_CPU_FREQ_80 is not set +CONFIG_ESP32C3_DEFAULT_CPU_FREQ_160=y +CONFIG_ESP32C3_DEFAULT_CPU_FREQ_MHZ=160 +CONFIG_ESP32C3_MEMPROT_FEATURE=y +CONFIG_ESP32C3_MEMPROT_FEATURE_LOCK=y +CONFIG_SYSTEM_EVENT_QUEUE_SIZE=32 +CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE=2304 +CONFIG_MAIN_TASK_STACK_SIZE=3584 +CONFIG_CONSOLE_UART_DEFAULT=y +# CONFIG_CONSOLE_UART_CUSTOM is not set +# CONFIG_CONSOLE_UART_NONE is not set +# CONFIG_ESP_CONSOLE_UART_NONE is not set +CONFIG_CONSOLE_UART=y +CONFIG_CONSOLE_UART_NUM=0 +CONFIG_CONSOLE_UART_BAUDRATE=115200 +CONFIG_INT_WDT=y +CONFIG_INT_WDT_TIMEOUT_MS=300 +CONFIG_TASK_WDT=y +CONFIG_ESP_TASK_WDT=y +# CONFIG_TASK_WDT_PANIC is not set +CONFIG_TASK_WDT_TIMEOUT_S=5 +CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU0=y +# CONFIG_ESP32_DEBUG_STUBS_ENABLE is not set +CONFIG_ESP32C3_DEBUG_OCDAWARE=y +CONFIG_BROWNOUT_DET=y +CONFIG_ESP32C3_BROWNOUT_DET=y +CONFIG_BROWNOUT_DET_LVL_SEL_7=y +CONFIG_ESP32C3_BROWNOUT_DET_LVL_SEL_7=y +# CONFIG_BROWNOUT_DET_LVL_SEL_6 is not set +# CONFIG_ESP32C3_BROWNOUT_DET_LVL_SEL_6 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_5 is not set +# CONFIG_ESP32C3_BROWNOUT_DET_LVL_SEL_5 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_4 is not set +# CONFIG_ESP32C3_BROWNOUT_DET_LVL_SEL_4 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_3 is not set +# CONFIG_ESP32C3_BROWNOUT_DET_LVL_SEL_3 is not set +# CONFIG_BROWNOUT_DET_LVL_SEL_2 is not set +# CONFIG_ESP32C3_BROWNOUT_DET_LVL_SEL_2 is not set +CONFIG_BROWNOUT_DET_LVL=7 +CONFIG_ESP32C3_BROWNOUT_DET_LVL=7 +CONFIG_IPC_TASK_STACK_SIZE=1024 +CONFIG_TIMER_TASK_STACK_SIZE=3584 +CONFIG_ESP32_WIFI_ENABLED=y +CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=10 +CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=32 +# CONFIG_ESP32_WIFI_STATIC_TX_BUFFER is not set +CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER=y +CONFIG_ESP32_WIFI_TX_BUFFER_TYPE=1 +CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM=32 +# CONFIG_ESP32_WIFI_CSI_ENABLED is not set +CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED=y +CONFIG_ESP32_WIFI_TX_BA_WIN=6 +CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=y +CONFIG_ESP32_WIFI_RX_BA_WIN=6 +CONFIG_ESP32_WIFI_NVS_ENABLED=y +CONFIG_ESP32_WIFI_SOFTAP_BEACON_MAX_LEN=752 +CONFIG_ESP32_WIFI_MGMT_SBUF_NUM=32 +CONFIG_ESP32_WIFI_IRAM_OPT=y +CONFIG_ESP32_WIFI_RX_IRAM_OPT=y +CONFIG_ESP32_WIFI_ENABLE_WPA3_SAE=y +CONFIG_ESP32_WIFI_ENABLE_WPA3_OWE_STA=y +CONFIG_WPA_MBEDTLS_CRYPTO=y +CONFIG_WPA_MBEDTLS_TLS_CLIENT=y +# CONFIG_WPA_WAPI_PSK is not set +# CONFIG_WPA_SUITE_B_192 is not set +# CONFIG_WPA_11KV_SUPPORT is not set +# CONFIG_WPA_MBO_SUPPORT is not set +# CONFIG_WPA_DPP_SUPPORT is not set +# CONFIG_WPA_11R_SUPPORT is not set +# CONFIG_WPA_WPS_SOFTAP_REGISTRAR is not set +# CONFIG_WPA_WPS_STRICT is not set +# CONFIG_WPA_DEBUG_PRINT is not set +# CONFIG_WPA_TESTING_OPTIONS is not set +# CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH is not set +# CONFIG_ESP32_ENABLE_COREDUMP_TO_UART is not set +CONFIG_ESP32_ENABLE_COREDUMP_TO_NONE=y +CONFIG_TIMER_TASK_PRIORITY=1 +CONFIG_TIMER_TASK_STACK_DEPTH=3120 +CONFIG_TIMER_QUEUE_LENGTH=10 +# CONFIG_ENABLE_STATIC_TASK_CLEAN_UP_HOOK is not set +# CONFIG_HAL_ASSERTION_SILIENT is not set +# CONFIG_L2_TO_L3_COPY is not set +CONFIG_ESP_GRATUITOUS_ARP=y +CONFIG_GARP_TMR_INTERVAL=60 +CONFIG_TCPIP_RECVMBOX_SIZE=32 +CONFIG_TCP_MAXRTX=12 +CONFIG_TCP_SYNMAXRTX=12 +CONFIG_TCP_MSS=1440 +CONFIG_TCP_MSL=60000 +CONFIG_TCP_SND_BUF_DEFAULT=5760 +CONFIG_TCP_WND_DEFAULT=5760 +CONFIG_TCP_RECVMBOX_SIZE=6 +CONFIG_TCP_QUEUE_OOSEQ=y +CONFIG_TCP_OVERSIZE_MSS=y +# CONFIG_TCP_OVERSIZE_QUARTER_MSS is not set +# CONFIG_TCP_OVERSIZE_DISABLE is not set +CONFIG_UDP_RECVMBOX_SIZE=6 +CONFIG_TCPIP_TASK_STACK_SIZE=3072 +CONFIG_TCPIP_TASK_AFFINITY_NO_AFFINITY=y +# CONFIG_TCPIP_TASK_AFFINITY_CPU0 is not set +CONFIG_TCPIP_TASK_AFFINITY=0x7FFFFFFF +# CONFIG_PPP_SUPPORT is not set +CONFIG_ESP32C3_TIME_SYSCALL_USE_RTC_SYSTIMER=y +# CONFIG_ESP32C3_TIME_SYSCALL_USE_RTC is not set +# CONFIG_ESP32C3_TIME_SYSCALL_USE_SYSTIMER is not set +# CONFIG_ESP32C3_TIME_SYSCALL_USE_NONE is not set +CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT=5 +CONFIG_ESP32_PTHREAD_TASK_STACK_SIZE_DEFAULT=3072 +CONFIG_ESP32_PTHREAD_STACK_MIN=768 +CONFIG_ESP32_PTHREAD_TASK_CORE_DEFAULT=-1 +CONFIG_ESP32_PTHREAD_TASK_NAME_DEFAULT="pthread" +CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ABORTS=y +# CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_FAILS is not set +# CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ALLOWED is not set +CONFIG_SUPPRESS_SELECT_DEBUG_OUTPUT=y +CONFIG_SUPPORT_TERMIOS=y +CONFIG_SEMIHOSTFS_MAX_MOUNT_POINTS=1 +# End of deprecated options