Merge branch 'master' into feature/esp32s2beta_update

This commit is contained in:
Angus Gratton 2019-08-08 13:44:24 +10:00 committed by Angus Gratton
commit 24d26fccde
2414 changed files with 160787 additions and 45783 deletions

15
.flake8
View file

@ -140,15 +140,16 @@ exclude =
.git, .git,
__pycache__, __pycache__,
# submodules # submodules
components/esptool_py/esptool,
components/bootloader/subproject/components/micro-ecc/micro-ecc, components/bootloader/subproject/components/micro-ecc/micro-ecc,
components/nghttp/nghttp2, components/esptool_py/esptool,
components/libsodium/libsodium,
components/json/cJSON,
components/mbedtls/mbedtls,
components/expat/expat, components/expat/expat,
components/json/cJSON,
components/libsodium/libsodium,
components/mbedtls/mbedtls,
components/nghttp/nghttp2,
components/bt/host/nimble/nimble,
components/unity/unity, components/unity/unity,
examples/build_system/cmake/import_lib/main/lib/tinyxml2 examples/build_system/cmake/import_lib/main/lib/tinyxml2,
# other third-party libraries # other third-party libraries
tools/kconfig_new/kconfiglib.py, tools/kconfig_new/kconfiglib.py,
# autogenerated scripts # autogenerated scripts
@ -156,6 +157,8 @@ exclude =
components/protocomm/python/sec0_pb2.py, components/protocomm/python/sec0_pb2.py,
components/protocomm/python/sec1_pb2.py, components/protocomm/python/sec1_pb2.py,
components/protocomm/python/session_pb2.py, components/protocomm/python/session_pb2.py,
components/wifi_provisioning/python/wifi_scan_pb2.py,
components/wifi_provisioning/python/wifi_config_pb2.py, components/wifi_provisioning/python/wifi_config_pb2.py,
components/wifi_provisioning/python/wifi_constants_pb2.py, components/wifi_provisioning/python/wifi_constants_pb2.py,
components/esp_local_ctrl/python/esp_local_ctrl_pb2.py,
examples/provisioning/custom_config/components/custom_provisioning/python/custom_config_pb2.py, examples/provisioning/custom_config/components/custom_provisioning/python/custom_config_pb2.py,

7
.gitignore vendored
View file

@ -58,13 +58,6 @@ TEST_LOGS
coverage.info coverage.info
coverage_report/ coverage_report/
# Windows tools installer build
tools/windows/tool_setup/.*
tools/windows/tool_setup/input
tools/windows/tool_setup/dl
tools/windows/tool_setup/keys
tools/windows/tool_setup/Output
test_multi_heap_host test_multi_heap_host
# VS Code Settings # VS Code Settings

File diff suppressed because it is too large Load diff

50
.gitmodules vendored
View file

@ -1,71 +1,81 @@
#
# All the relative URL paths are intended to be GitHub ones
# For Espressif's public projects please use '../../espressif/proj', not a '../proj'
#
[submodule "components/esptool_py/esptool"] [submodule "components/esptool_py/esptool"]
path = components/esptool_py/esptool path = components/esptool_py/esptool
url = https://github.com/espressif/esptool.git url = ../../espressif/esptool.git
[submodule "components/bt/lib"] [submodule "components/bt/controller/lib"]
path = components/bt/lib path = components/bt/controller/lib
url = https://github.com/espressif/esp32-bt-lib.git url = ../../espressif/esp32-bt-lib.git
[submodule "components/bootloader/subproject/components/micro-ecc/micro-ecc"] [submodule "components/bootloader/subproject/components/micro-ecc/micro-ecc"]
path = components/bootloader/subproject/components/micro-ecc/micro-ecc path = components/bootloader/subproject/components/micro-ecc/micro-ecc
url = https://github.com/kmackay/micro-ecc.git url = ../../kmackay/micro-ecc.git
[submodule "components/coap/libcoap"] [submodule "components/coap/libcoap"]
path = components/coap/libcoap path = components/coap/libcoap
url = https://github.com/obgm/libcoap.git url = ../../obgm/libcoap.git
[submodule "components/nghttp/nghttp2"] [submodule "components/nghttp/nghttp2"]
path = components/nghttp/nghttp2 path = components/nghttp/nghttp2
url = https://github.com/nghttp2/nghttp2.git url = ../../nghttp2/nghttp2.git
[submodule "components/libsodium/libsodium"] [submodule "components/libsodium/libsodium"]
path = components/libsodium/libsodium path = components/libsodium/libsodium
url = https://github.com/jedisct1/libsodium.git url = ../../jedisct1/libsodium.git
[submodule "components/spiffs/spiffs"] [submodule "components/spiffs/spiffs"]
path = components/spiffs/spiffs path = components/spiffs/spiffs
url = https://github.com/pellepl/spiffs.git url = ../../pellepl/spiffs.git
[submodule "components/json/cJSON"] [submodule "components/json/cJSON"]
path = components/json/cJSON path = components/json/cJSON
url = https://github.com/DaveGamble/cJSON.git url = ../../DaveGamble/cJSON.git
[submodule "components/mbedtls/mbedtls"] [submodule "components/mbedtls/mbedtls"]
path = components/mbedtls/mbedtls path = components/mbedtls/mbedtls
url = https://github.com/espressif/mbedtls.git url = ../../espressif/mbedtls.git
[submodule "components/asio/asio"] [submodule "components/asio/asio"]
path = components/asio/asio path = components/asio/asio
url = https://github.com/espressif/asio.git url = ../../espressif/asio.git
[submodule "components/expat/expat"] [submodule "components/expat/expat"]
path = components/expat/expat path = components/expat/expat
url = https://github.com/libexpat/libexpat.git url = ../../libexpat/libexpat.git
[submodule "components/lwip/lwip"] [submodule "components/lwip/lwip"]
path = components/lwip/lwip path = components/lwip/lwip
url = https://github.com/espressif/esp-lwip.git url = ../../espressif/esp-lwip.git
[submodule "components/mqtt/esp-mqtt"] [submodule "components/mqtt/esp-mqtt"]
path = components/mqtt/esp-mqtt path = components/mqtt/esp-mqtt
url = https://github.com/espressif/esp-mqtt.git url = ../../espressif/esp-mqtt.git
[submodule "components/protobuf-c/protobuf-c"] [submodule "components/protobuf-c/protobuf-c"]
path = components/protobuf-c/protobuf-c path = components/protobuf-c/protobuf-c
url = https://github.com/protobuf-c/protobuf-c url = ../../protobuf-c/protobuf-c.git
[submodule "components/unity/unity"] [submodule "components/unity/unity"]
path = components/unity/unity path = components/unity/unity
url = https://github.com/ThrowTheSwitch/Unity url = ../../ThrowTheSwitch/Unity.git
[submodule "examples/build_system/cmake/import_lib/main/lib/tinyxml2"] [submodule "examples/build_system/cmake/import_lib/main/lib/tinyxml2"]
path = examples/build_system/cmake/import_lib/main/lib/tinyxml2 path = examples/build_system/cmake/import_lib/main/lib/tinyxml2
url = https://github.com/leethomason/tinyxml2 url = ../../leethomason/tinyxml2.git
[submodule "components/esp_wifi/lib_esp32"] [submodule "components/esp_wifi/lib_esp32"]
path = components/esp_wifi/lib_esp32 path = components/esp_wifi/lib_esp32
url = https://github.com/espressif/esp32-wifi-lib.git url = ../../espressif/esp32-wifi-lib.git
[submodule "components/esp_wifi/lib_esp32s2beta"] [submodule "components/esp_wifi/lib_esp32s2beta"]
path = components/esp_wifi/lib_esp32s2beta path = components/esp_wifi/lib_esp32s2beta
url = https://github.com/espressif/esp32-wifi-lib.git url = ../../espressif/esp32-wifi-lib.git
[submodule "components/bt/host/nimble/nimble"]
path = components/bt/host/nimble/nimble
url = ../../espressif/esp-nimble.git

View file

@ -7,7 +7,6 @@ version: 2
# Optionally build your docs in additional formats such as PDF and ePub # Optionally build your docs in additional formats such as PDF and ePub
formats: formats:
- htmlzip
- pdf - pdf
# Optionally set the version of Python and requirements required to build your docs # Optionally set the version of Python and requirements required to build your docs

View file

@ -11,6 +11,7 @@ unset(compile_definitions)
if(CONFIG_COMPILER_OPTIMIZATION_LEVEL_RELEASE) if(CONFIG_COMPILER_OPTIMIZATION_LEVEL_RELEASE)
list(APPEND compile_options "-Os") list(APPEND compile_options "-Os")
list(APPEND compile_options "-freorder-blocks")
else() else()
list(APPEND compile_options "-Og") list(APPEND compile_options "-Og")
endif() endif()
@ -70,39 +71,13 @@ foreach(component_target ${build_component_targets})
set(COMPONENT_NAME ${_name}) set(COMPONENT_NAME ${_name})
set(COMPONENT_DIR ${dir}) set(COMPONENT_DIR ${dir})
set(COMPONENT_ALIAS ${alias}) set(COMPONENT_ALIAS ${alias})
set(COMPONENT_PATH ${dir}) # also deprecated, see comment in previous loop set(COMPONENT_PATH ${dir}) # for backward compatibility only, COMPONENT_DIR is preferred
idf_build_get_property(build_prefix __PREFIX) idf_build_get_property(build_prefix __PREFIX)
set(__idf_component_context 1) set(__idf_component_context 1)
if(NOT prefix STREQUAL build_prefix) if(NOT prefix STREQUAL build_prefix)
add_subdirectory(${dir} ${prefix}_${_name} EXCLUDE_FROM_ALL) add_subdirectory(${dir} ${prefix}_${_name})
else() else()
add_subdirectory(${dir} ${_name} EXCLUDE_FROM_ALL) add_subdirectory(${dir} ${_name})
endif() endif()
set(__idf_component_context 0) set(__idf_component_context 0)
endforeach() endforeach()
# Establish dependencies between components
idf_build_get_property(build_components BUILD_COMPONENTS)
foreach(build_component ${build_components})
__component_get_target(component_target ${build_component})
__component_get_property(component_lib ${component_target} COMPONENT_LIB)
__component_get_property(reqs ${component_target} __REQUIRES)
foreach(req ${reqs})
__component_get_property(req_lib ${req} COMPONENT_LIB)
if(TARGET ${req_lib})
set_property(TARGET ${component_lib} APPEND PROPERTY INTERFACE_LINK_LIBRARIES ${req_lib})
endif()
endforeach()
get_property(type TARGET ${component_lib} PROPERTY TYPE)
if(type STREQUAL STATIC_LIBRARY)
__component_get_property(reqs ${component_target} __REQUIRES)
__component_get_property(priv_reqs ${component_target} __PRIV_REQUIRES)
foreach(req ${reqs} ${priv_reqs})
__component_get_property(req_lib ${req} COMPONENT_LIB)
if(TARGET ${req_lib})
set_property(TARGET ${component_lib} APPEND PROPERTY LINK_LIBRARIES ${req_lib})
endif()
endforeach()
endif()
endforeach()

View file

@ -56,11 +56,11 @@ mainmenu "Espressif IoT Development Framework Configuration"
The executable name/path that is used to run python. On some systems Python 2.x The executable name/path that is used to run python. On some systems Python 2.x
may need to be invoked as python2. may need to be invoked as python2.
(Note: This option is used with the GNU Make build system only, not idf.py (Note: This option is used with the legacy GNU Make build system only.)
or CMake-based builds.)
config SDK_MAKE_WARN_UNDEFINED_VARIABLES config SDK_MAKE_WARN_UNDEFINED_VARIABLES
bool "'make' warns on undefined variables" bool "'make' warns on undefined variables"
depends on !IDF_CMAKE
default "y" default "y"
help help
Adds --warn-undefined-variables to MAKEFLAGS. This causes make to Adds --warn-undefined-variables to MAKEFLAGS. This causes make to
@ -70,6 +70,8 @@ mainmenu "Espressif IoT Development Framework Configuration"
or otherwise missing, but it can be unwanted if you have Makefiles which or otherwise missing, but it can be unwanted if you have Makefiles which
depend on undefined variables expanding to an empty string. depend on undefined variables expanding to an empty string.
(Note: this option is used with the legacy GNU Make build system only.)
endmenu # SDK tool configuration endmenu # SDK tool configuration
source "$COMPONENT_KCONFIGS_PROJBUILD" source "$COMPONENT_KCONFIGS_PROJBUILD"

View file

@ -13,6 +13,14 @@ See setup guides for detailed instructions to set up the ESP-IDF:
* [Getting Started Guide for the stable ESP-IDF version](https://docs.espressif.com/projects/esp-idf/en/stable/get-started/) * [Getting Started Guide for the stable ESP-IDF version](https://docs.espressif.com/projects/esp-idf/en/stable/get-started/)
* [Getting Started Guide for the latest (master branch) ESP-IDF version](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/) * [Getting Started Guide for the latest (master branch) ESP-IDF version](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/)
### Non-GitHub forks
ESP-IDF uses relative locations as its submodules URLs ([.gitmodules](.gitmodules)). So they link to GitHub.
If ESP-IDF is forked to a Git repository which is not on GitHub, you will need to run the script
[tools/set-submodules-to-github.sh](tools/set-submodules-to-github.sh) after git clone.
The script sets absolute URLs for all submodules, allowing `git submodule update --init --recursive` to complete.
If cloning ESP-IDF from GitHub, this step is not needed.
## Finding a Project ## Finding a Project
As well as the [esp-idf-template](https://github.com/espressif/esp-idf-template) project mentioned in Getting Started, ESP-IDF comes with some example projects in the [examples](examples) directory. As well as the [esp-idf-template](https://github.com/espressif/esp-idf-template) project mentioned in Getting Started, ESP-IDF comes with some example projects in the [examples](examples) directory.
@ -25,9 +33,17 @@ To start your own project based on an example, copy the example project director
See the Getting Started guide links above for a detailed setup guide. This is a quick reference for common commands when working with ESP-IDF projects: See the Getting Started guide links above for a detailed setup guide. This is a quick reference for common commands when working with ESP-IDF projects:
## Setup Build Environment
(See Getting Started guide for a full list of required steps with details.)
* Install host build dependencies mentioned in Getting Started guide.
* Add `tools/` directory to the PATH
* Run `python -m pip install requirements.txt` to install Python dependencies
## Configuring the Project ## Configuring the Project
`make menuconfig` `idf.py menuconfig`
* Opens a text-based configuration menu for the project. * Opens a text-based configuration menu for the project.
* Use up & down arrow keys to navigate the menu. * Use up & down arrow keys to navigate the menu.
@ -41,76 +57,48 @@ Once done configuring, press Escape multiple times to exit and say "Yes" to save
## Compiling the Project ## Compiling the Project
`make -j4 all` `idf.py build`
... will compile app, bootloader and generate a partition table based on the config. ... will compile app, bootloader and generate a partition table based on the config.
NOTE: The `-j4` option causes `make` to run 4 parallel jobs. This is much faster than the default single job. The recommended number to pass to this option is `-j(number of CPUs + 1)`.
## Flashing the Project ## Flashing the Project
When the build finishes, it will print a command line to use esptool.py to flash the chip. However you can also do this automatically by running: When the build finishes, it will print a command line to use esptool.py to flash the chip. However you can also do this automatically by running:
`make -j4 flash` `idf.py -p PORT flash`
This will flash the entire project (app, bootloader and partition table) to a new chip. The settings for serial port flashing can be configured with `make menuconfig`. Replace PORT with the name of your serial port (like `COM3` on Windows, `/dev/ttyUSB0` on Linux, or `/dev/cu.usbserial-X` on MacOS. If the `-p` option is left out, `idf.py flash` will try to flash the first available serial port.
You don't need to run `make all` before running `make flash`, `make flash` will automatically rebuild anything which needs it. This will flash the entire project (app, bootloader and partition table) to a new chip. The settings for serial port flashing can be configured with `idf.py menuconfig`.
You don't need to run `idf.py build` before running `idf.py flash`, `idf.py flash` will automatically rebuild anything which needs it.
## Viewing Serial Output ## Viewing Serial Output
The `make monitor` target uses the [idf_monitor tool](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/idf-monitor.html) to display serial output from the ESP32. idf_monitor also has a range of features to decode crash output and interact with the device. [Check the documentation page for details](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/idf-monitor.html). The `idf.py monitor` target uses the [idf_monitor tool](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/idf-monitor.html) to display serial output from the ESP32. idf_monitor also has a range of features to decode crash output and interact with the device. [Check the documentation page for details](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/idf-monitor.html).
Exit the monitor by typing Ctrl-]. Exit the monitor by typing Ctrl-].
To build, flash and monitor output in one pass, you can run: To build, flash and monitor output in one pass, you can run:
`make -j4 flash monitor` `idf.py flash monitor`
## Compiling & Flashing Only the App ## Compiling & Flashing Only the App
After the initial flash, you may just want to build and flash just your app, not the bootloader and partition table: After the initial flash, you may just want to build and flash just your app, not the bootloader and partition table:
* `make app` - build just the app. * `idf.py app` - build just the app.
* `make app-flash` - flash just the app. * `idf.py app-flash` - flash just the app.
`make app-flash` will automatically rebuild the app if any source files have changed. `idf.py app-flash` will automatically rebuild the app if any source files have changed.
(In normal development there's no downside to reflashing the bootloader and partition table each time, if they haven't changed.) (In normal development there's no downside to reflashing the bootloader and partition table each time, if they haven't changed.)
## Parallel Builds
ESP-IDF supports compiling multiple files in parallel, so all of the above commands can be run as `make -jN` where `N` is the number of parallel make processes to run (generally N should be equal to the number of CPU cores in your system, plus one.)
Multiple make functions can be combined into one. For example: to build the app & bootloader using 5 jobs in parallel, then flash everything, and then display serial output from the ESP32 run:
```
make -j5 flash monitor
```
## The Partition Table
Once you've compiled your project, the "build" directory will contain a binary file with a name like "my_app.bin". This is an ESP32 image binary that can be loaded by the bootloader.
A single ESP32's flash can contain multiple apps, as well as many different kinds of data (calibration data, filesystems, parameter storage, etc). For this reason a partition table is flashed to offset 0x8000 in the flash.
Each entry in the partition table has a name (label), type (app, data, or something else), subtype and the offset in flash where the partition is loaded.
The simplest way to use the partition table is to `make menuconfig` and choose one of the simple predefined partition tables:
* "Single factory app, no OTA"
* "Factory app, two OTA definitions"
In both cases the factory app is flashed at offset 0x10000. If you `make partition_table` then it will print a summary of the partition table.
For more details about partition tables and how to create custom variations, view the [`docs/en/api-guides/partition-tables.rst`](docs/en/api-guides/partition-tables.rst) file.
## Erasing Flash ## Erasing Flash
The `make flash` target does not erase the entire flash contents. However it is sometimes useful to set the device back to a totally erased state, particularly when making partition table changes or OTA app updates. To erase the entire flash, run `make erase_flash`. The `idf.py flash` target does not erase the entire flash contents. However it is sometimes useful to set the device back to a totally erased state, particularly when making partition table changes or OTA app updates. To erase the entire flash, run `idf.py erase_flash`.
This can be combined with other targets, ie `make erase_flash flash` will erase everything and then re-flash the new app, bootloader and partition table. This can be combined with other targets, ie `idf.py -p PORT erase_flash flash` will erase everything and then re-flash the new app, bootloader and partition table.
# Resources # Resources

View file

@ -9,8 +9,7 @@
if [ -z ${IDF_PATH} ]; then if [ -z ${IDF_PATH} ]; then
echo "IDF_PATH must be set before including this script." echo "IDF_PATH must be set before including this script."
else else
IDF_ADD_PATHS_EXTRAS= IDF_ADD_PATHS_EXTRAS="${IDF_PATH}/components/esptool_py/esptool"
IDF_ADD_PATHS_EXTRAS="${IDF_ADD_PATHS_EXTRAS}:${IDF_PATH}/components/esptool_py/esptool"
IDF_ADD_PATHS_EXTRAS="${IDF_ADD_PATHS_EXTRAS}:${IDF_PATH}/components/espcoredump" IDF_ADD_PATHS_EXTRAS="${IDF_ADD_PATHS_EXTRAS}:${IDF_PATH}/components/espcoredump"
IDF_ADD_PATHS_EXTRAS="${IDF_ADD_PATHS_EXTRAS}:${IDF_PATH}/components/partition_table/" IDF_ADD_PATHS_EXTRAS="${IDF_ADD_PATHS_EXTRAS}:${IDF_PATH}/components/partition_table/"
IDF_ADD_PATHS_EXTRAS="${IDF_ADD_PATHS_EXTRAS}:${IDF_PATH}/tools/" IDF_ADD_PATHS_EXTRAS="${IDF_ADD_PATHS_EXTRAS}:${IDF_PATH}/tools/"

View file

@ -1,16 +1,19 @@
set(COMPONENT_SRCS "app_trace.c" set(srcs
"app_trace.c"
"app_trace_util.c" "app_trace_util.c"
"host_file_io.c" "host_file_io.c"
"gcov/gcov_rtio.c") "gcov/gcov_rtio.c")
set(COMPONENT_ADD_INCLUDEDIRS "include")
set(include_dirs "include")
if(CONFIG_SYSVIEW_ENABLE) if(CONFIG_SYSVIEW_ENABLE)
list(APPEND COMPONENT_ADD_INCLUDEDIRS list(APPEND include_dirs
sys_view/Config sys_view/Config
sys_view/SEGGER sys_view/SEGGER
sys_view/Sample/OS) sys_view/Sample/OS)
list(APPEND COMPONENT_SRCS "sys_view/SEGGER/SEGGER_SYSVIEW.c" list(APPEND srcs
"sys_view/SEGGER/SEGGER_SYSVIEW.c"
"sys_view/Sample/Config/SEGGER_SYSVIEW_Config_FreeRTOS.c" "sys_view/Sample/Config/SEGGER_SYSVIEW_Config_FreeRTOS.c"
"sys_view/Sample/OS/SEGGER_SYSVIEW_FreeRTOS.c" "sys_view/Sample/OS/SEGGER_SYSVIEW_FreeRTOS.c"
"sys_view/esp32/SEGGER_RTT_esp32.c" "sys_view/esp32/SEGGER_RTT_esp32.c"
@ -19,16 +22,15 @@ if(CONFIG_SYSVIEW_ENABLE)
endif() endif()
if(CONFIG_HEAP_TRACING_TOHOST) if(CONFIG_HEAP_TRACING_TOHOST)
list(APPEND COMPONENT_SRCS "heap_trace_tohost.c") list(APPEND srcs "heap_trace_tohost.c")
endif() endif()
set(COMPONENT_REQUIRES) idf_component_register(SRCS "${srcs}"
set(COMPONENT_PRIV_REQUIRES heap soc) INCLUDE_DIRS "${include_dirs}"
set(COMPONENT_ADD_LDFRAGMENTS linker.lf) PRIV_REQUIRES soc
LDFRAGMENTS linker.lf)
register_component()
# disable --coverage for this component, as it is used as transport # disable --coverage for this component, as it is used as transport
# for gcov # for gcov
target_compile_options(${COMPONENT_LIB} PRIVATE "-fno-profile-arcs" "-fno-test-coverage") target_compile_options(${COMPONENT_LIB} PRIVATE "-fno-profile-arcs" "-fno-test-coverage")
target_link_libraries(${COMPONENT_LIB} gcov ${LIBC} ${LIBM} gcc) target_link_libraries(${COMPONENT_LIB} PUBLIC gcov ${LIBC} ${LIBM} gcc)

View file

@ -0,0 +1,23 @@
# idf_create_lcov_report
#
# Create coverage report.
function(idf_create_coverage_report report_dir)
set(gcov_tool ${CONFIG_SDK_TOOLPREFIX}gcov)
idf_build_get_property(project_name PROJECT_NAME)
add_custom_target(lcov-report
COMMENT "Generating coverage report in: ${report_dir}"
COMMAND ${CMAKE_COMMAND} -E echo "Using gcov: ${gcov_tool}"
COMMAND ${CMAKE_COMMAND} -E make_directory ${report_dir}/html
COMMAND lcov --gcov-tool ${gcov_tool} -c -d ${CMAKE_CURRENT_BINARY_DIR} -o ${report_dir}/${project_name}.info
COMMAND genhtml -o ${report_dir}/html ${report_dir}/${project_name}.info)
endfunction()
# idf_clean_coverage_report
#
# Clean coverage report.
function(idf_clean_coverage_report report_dir)
add_custom_target(cov-data-clean
COMMENT "Clean coverage report in: ${report_dir}"
COMMAND ${CMAKE_COMMAND} -E remove_directory ${report_dir})
endfunction()

View file

@ -1,6 +1,3 @@
set(COMPONENT_SRCDIRS ".") idf_component_register(SRC_DIRS "."
set(COMPONENT_ADD_INCLUDEDIRS ".") INCLUDE_DIRS "."
REQUIRES unity)
set(COMPONENT_REQUIRES unity)
register_component()

View file

@ -1,15 +1,11 @@
set(COMPONENT_SRCS "esp_ota_ops.c" idf_component_register(SRCS "esp_ota_ops.c"
"esp_app_desc.c") "esp_app_desc.c"
set(COMPONENT_ADD_INCLUDEDIRS "include") INCLUDE_DIRS "include"
REQUIRES spi_flash partition_table bootloader_support)
set(COMPONENT_REQUIRES spi_flash partition_table bootloader_support)
set(COMPONENT_PRIV_REQUIRES)
register_component()
# esp_app_desc structure is added as an undefined symbol because otherwise the # esp_app_desc structure is added as an undefined symbol because otherwise the
# linker will ignore this structure as it has no other files depending on it. # linker will ignore this structure as it has no other files depending on it.
target_link_libraries(${COMPONENT_LIB} "-u esp_app_desc") target_link_libraries(${COMPONENT_LIB} INTERFACE "-u esp_app_desc")
# cut PROJECT_VER and PROJECT_NAME to required 32 characters. # cut PROJECT_VER and PROJECT_NAME to required 32 characters.
idf_build_get_property(project_ver PROJECT_VER) idf_build_get_property(project_ver PROJECT_VER)
@ -34,21 +30,27 @@ if(NOT BOOTLOADER_BUILD)
idf_build_get_property(idf_path IDF_PATH) idf_build_get_property(idf_path IDF_PATH)
idf_build_get_property(python PYTHON) idf_build_get_property(python PYTHON)
add_custom_command(OUTPUT ${blank_otadata_file} add_custom_command(OUTPUT ${blank_otadata_file}
COMMAND ${python} ${idf_path}/components/partition_table/parttool.py COMMAND ${python} ${idf_path}/components/partition_table/gen_empty_partition.py
--partition-type data --partition-subtype ota -q ${otadata_size} ${blank_otadata_file})
--partition-table-file ${PARTITION_CSV_PATH} generate_blank_partition_file
--output ${blank_otadata_file})
add_custom_target(blank_ota_data ALL DEPENDS ${blank_otadata_file}) add_custom_target(blank_ota_data ALL DEPENDS ${blank_otadata_file})
add_dependencies(app blank_ota_data) add_dependencies(flash blank_ota_data)
set(otatool_py ${python} ${COMPONENT_DIR}/otatool.py) set(otatool_py ${python} ${COMPONENT_DIR}/otatool.py)
set(esptool_args --esptool-args before=${CONFIG_ESPTOOLPY_BEFORE} after=${CONFIG_ESPTOOLPY_AFTER})
add_custom_target(read_otadata DEPENDS "${PARTITION_CSV_PATH}" add_custom_target(read_otadata DEPENDS "${PARTITION_CSV_PATH}"
COMMAND ${otatool_py} --partition-table-file ${PARTITION_CSV_PATH} read_otadata) COMMAND ${otatool_py} ${esptool_args}
--partition-table-file ${PARTITION_CSV_PATH}
--partition-table-offset ${PARTITION_TABLE_OFFSET}
read_otadata)
add_custom_target(erase_otadata DEPENDS "${PARTITION_CSV_PATH}" add_custom_target(erase_otadata DEPENDS "${PARTITION_CSV_PATH}"
COMMAND ${otatool_py} --partition-table-file ${PARTITION_CSV_PATH} erase_otadata) COMMAND ${otatool_py} ${esptool_args}
--partition-table-file ${PARTITION_CSV_PATH}
--partition-table-offset ${PARTITION_TABLE_OFFSET}
erase_otadata)
esptool_py_flash_project_args(otadata ${otadata_offset} "${blank_otadata_file}" FLASH_IN_PROJECT) esptool_py_flash_project_args(otadata ${otadata_offset} "${blank_otadata_file}" FLASH_IN_PROJECT)
endif() endif()

View file

@ -17,8 +17,7 @@ endif
$(BLANK_OTA_DATA_FILE): partition_table_get_info $(PARTITION_TABLE_CSV_PATH) | check_python_dependencies $(BLANK_OTA_DATA_FILE): partition_table_get_info $(PARTITION_TABLE_CSV_PATH) | check_python_dependencies
$(shell if [ "$(OTA_DATA_OFFSET)" != "" ] && [ "$(OTA_DATA_SIZE)" != "" ]; then \ $(shell if [ "$(OTA_DATA_OFFSET)" != "" ] && [ "$(OTA_DATA_SIZE)" != "" ]; then \
$(PARTTOOL_PY) --partition-type data --partition-subtype ota --partition-table-file $(PARTITION_TABLE_CSV_PATH) \ $(PYTHON) $(IDF_PATH)/components/partition_table/gen_empty_partition.py $(OTA_DATA_SIZE) $(BLANK_OTA_DATA_FILE); \
-q generate_blank_partition_file --output $(BLANK_OTA_DATA_FILE); \
fi; ) fi; )
$(eval BLANK_OTA_DATA_FILE = $(shell if [ "$(OTA_DATA_OFFSET)" != "" ] && [ "$(OTA_DATA_SIZE)" != "" ]; then \ $(eval BLANK_OTA_DATA_FILE = $(shell if [ "$(OTA_DATA_OFFSET)" != "" ] && [ "$(OTA_DATA_SIZE)" != "" ]; then \
echo $(BLANK_OTA_DATA_FILE); else echo " "; fi) ) echo $(BLANK_OTA_DATA_FILE); else echo " "; fi) )
@ -29,17 +28,26 @@ blank_ota_data: $(BLANK_OTA_DATA_FILE)
# expand to empty values. # expand to empty values.
ESPTOOL_ALL_FLASH_ARGS += $(OTA_DATA_OFFSET) $(BLANK_OTA_DATA_FILE) ESPTOOL_ALL_FLASH_ARGS += $(OTA_DATA_OFFSET) $(BLANK_OTA_DATA_FILE)
ESPTOOL_ARGS := --esptool-args port=$(CONFIG_ESPTOOLPY_PORT) baud=$(CONFIG_ESPTOOLPY_BAUD) before=$(CONFIG_ESPTOOLPY_BEFORE) after=$(CONFIG_ESPTOOLPY_AFTER)
erase_otadata: $(PARTITION_TABLE_CSV_PATH) partition_table_get_info | check_python_dependencies erase_otadata: $(PARTITION_TABLE_CSV_PATH) partition_table_get_info | check_python_dependencies
$(OTATOOL_PY) --partition-table-file $(PARTITION_TABLE_CSV_PATH) erase_otadata $(OTATOOL_PY) $(ESPTOOL_ARGS) --partition-table-file $(PARTITION_TABLE_CSV_PATH) \
--partition-table-offset $(PARTITION_TABLE_OFFSET) \
erase_otadata
read_otadata: $(PARTITION_TABLE_CSV_PATH) partition_table_get_info | check_python_dependencies read_otadata: $(PARTITION_TABLE_CSV_PATH) partition_table_get_info | check_python_dependencies
$(OTATOOL_PY) --partition-table-file $(PARTITION_TABLE_CSV_PATH) read_otadata $(OTATOOL_PY) $(ESPTOOL_ARGS) --partition-table-file $(PARTITION_TABLE_CSV_PATH) \
--partition-table-offset $(partition_table_offset) \
read_otadata
erase_ota: erase_otadata erase_ota: erase_otadata
@echo "WARNING: erase_ota is deprecated. Use erase_otadata instead." @echo "WARNING: erase_ota is deprecated. Use erase_otadata instead."
all: blank_ota_data all: blank_ota_data
flash: blank_ota_data flash: blank_ota_data
ifdef CONFIG_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT
encrypted-flash: blank_ota_data
endif
TMP_DEFINES := $(BUILD_DIR_BASE)/app_update/tmp_cppflags.txt TMP_DEFINES := $(BUILD_DIR_BASE)/app_update/tmp_cppflags.txt
export TMP_DEFINES export TMP_DEFINES

View file

@ -21,16 +21,20 @@ import argparse
import os import os
import sys import sys
import binascii import binascii
import subprocess
import tempfile import tempfile
import collections import collections
import struct import struct
__version__ = '1.0' try:
from parttool import PartitionName, PartitionType, ParttoolTarget, PARTITION_TABLE_OFFSET
except ImportError:
COMPONENTS_PATH = os.path.expandvars(os.path.join("$IDF_PATH", "components"))
PARTTOOL_DIR = os.path.join(COMPONENTS_PATH, "partition_table")
IDF_COMPONENTS_PATH = os.path.expandvars(os.path.join("$IDF_PATH", "components")) sys.path.append(PARTTOOL_DIR)
from parttool import PartitionName, PartitionType, ParttoolTarget, PARTITION_TABLE_OFFSET
PARTTOOL_PY = os.path.join(IDF_COMPONENTS_PATH, "partition_table", "parttool.py") __version__ = '2.0'
SPI_FLASH_SEC_SIZE = 0x2000 SPI_FLASH_SEC_SIZE = 0x2000
@ -42,121 +46,72 @@ def status(msg):
print(msg) print(msg)
def _invoke_parttool(parttool_args, args, output=False, partition=None): class OtatoolTarget():
invoke_args = []
if partition: OTADATA_PARTITION = PartitionType("data", "ota")
invoke_args += [sys.executable, PARTTOOL_PY] + partition
else:
invoke_args += [sys.executable, PARTTOOL_PY, "--partition-type", "data", "--partition-subtype", "ota"]
if quiet: def __init__(self, port=None, baud=None, partition_table_offset=PARTITION_TABLE_OFFSET, partition_table_file=None,
invoke_args += ["-q"] spi_flash_sec_size=SPI_FLASH_SEC_SIZE, esptool_args=[], esptool_write_args=[],
esptool_read_args=[], esptool_erase_args=[]):
if args.port != "": self.target = ParttoolTarget(port, baud, partition_table_offset, partition_table_file, esptool_args,
invoke_args += ["--port", args.port] esptool_write_args, esptool_read_args, esptool_erase_args)
self.spi_flash_sec_size = spi_flash_sec_size
if args.partition_table_file:
invoke_args += ["--partition-table-file", args.partition_table_file]
if args.partition_table_offset:
invoke_args += ["--partition-table-offset", args.partition_table_offset]
invoke_args += parttool_args
if output:
return subprocess.check_output(invoke_args)
else:
return subprocess.check_call(invoke_args)
def _get_otadata_contents(args, check=True):
global quiet
if check:
check_args = ["get_partition_info", "--info", "offset", "size"]
quiet = True
output = _invoke_parttool(check_args, args, True).split(b" ")
quiet = args.quiet
if not output:
raise RuntimeError("No ota_data partition found")
with tempfile.NamedTemporaryFile(delete=False) as f:
f_name = f.name
temp_file = tempfile.NamedTemporaryFile(delete=False)
temp_file.close()
try: try:
invoke_args = ["read_partition", "--output", f_name] self.target.read_partition(OtatoolTarget.OTADATA_PARTITION, temp_file.name)
_invoke_parttool(invoke_args, args) with open(temp_file.name, "rb") as f:
with open(f_name, "rb") as f: self.otadata = f.read()
contents = f.read() except Exception:
self.otadata = None
finally: finally:
os.unlink(f_name) os.unlink(temp_file.name)
return contents def _check_otadata_partition(self):
if not self.otadata:
raise Exception("No otadata partition found")
def erase_otadata(self):
self._check_otadata_partition()
self.target.erase_partition(OtatoolTarget.OTADATA_PARTITION)
def _get_otadata_status(otadata_contents): def _get_otadata_info(self):
status = [] info = []
otadata_status = collections.namedtuple("otadata_status", "seq crc") otadata_info = collections.namedtuple("otadata_info", "seq crc")
for i in range(2): for i in range(2):
start = i * (SPI_FLASH_SEC_SIZE >> 1) start = i * (self.spi_flash_sec_size >> 1)
seq = bytearray(otadata_contents[start:start + 4]) seq = bytearray(self.otadata[start:start + 4])
crc = bytearray(otadata_contents[start + 28:start + 32]) crc = bytearray(self.otadata[start + 28:start + 32])
seq = struct.unpack('>I', seq) seq = struct.unpack('>I', seq)
crc = struct.unpack('>I', crc) crc = struct.unpack('>I', crc)
status.append(otadata_status(seq[0], crc[0])) info.append(otadata_info(seq[0], crc[0]))
return status return info
def _get_partition_id_from_ota_id(self, ota_id):
if isinstance(ota_id, int):
return PartitionType("app", "ota_" + str(ota_id))
else:
return PartitionName(ota_id)
def read_otadata(args): def switch_ota_partition(self, ota_id):
status("Reading ota_data partition contents...") self._check_otadata_partition()
otadata_info = _get_otadata_contents(args)
otadata_info = _get_otadata_status(otadata_info)
print(otadata_info) sys.path.append(PARTTOOL_DIR)
print("\t\t{:11}\t{:8s}|\t{:8s}\t{:8s}".format("OTA_SEQ", "CRC", "OTA_SEQ", "CRC"))
print("Firmware: 0x{:8x} \t 0x{:8x} |\t0x{:8x} \t 0x{:8x}".format(otadata_info[0].seq, otadata_info[0].crc,
otadata_info[1].seq, otadata_info[1].crc))
def erase_otadata(args):
status("Erasing ota_data partition contents...")
_invoke_parttool(["erase_partition"], args)
status("Erased ota_data partition contents")
def switch_otadata(args):
sys.path.append(os.path.join(IDF_COMPONENTS_PATH, "partition_table"))
import gen_esp32part as gen import gen_esp32part as gen
with tempfile.NamedTemporaryFile(delete=False) as f: def is_otadata_info_valid(status):
f_name = f.name
try:
def is_otadata_status_valid(status):
seq = status.seq % (1 << 32) seq = status.seq % (1 << 32)
crc = hex(binascii.crc32(struct.pack("I", seq), 0xFFFFFFFF) % (1 << 32)) crc = hex(binascii.crc32(struct.pack("I", seq), 0xFFFFFFFF) % (1 << 32))
return seq < (int('0xFFFFFFFF', 16) % (1 << 32)) and status.crc == crc return seq < (int('0xFFFFFFFF', 16) % (1 << 32)) and status.crc == crc
status("Looking for ota app partitions...") partition_table = self.target.partition_table
# In order to get the number of ota app partitions, we need the partition table
partition_table = None
invoke_args = ["get_partition_info", "--table", f_name]
_invoke_parttool(invoke_args, args)
partition_table = open(f_name, "rb").read()
partition_table = gen.PartitionTable.from_binary(partition_table)
ota_partitions = list() ota_partitions = list()
@ -171,39 +126,36 @@ def switch_otadata(args):
ota_partitions = sorted(ota_partitions, key=lambda p: p.subtype) ota_partitions = sorted(ota_partitions, key=lambda p: p.subtype)
if not ota_partitions: if not ota_partitions:
raise RuntimeError("No ota app partitions found") raise Exception("No ota app partitions found")
status("Verifying partition to switch to exists...")
# Look for the app partition to switch to # Look for the app partition to switch to
ota_partition_next = None ota_partition_next = None
try: try:
if args.name: if isinstance(ota_id, int):
ota_partition_next = filter(lambda p: p.name == args.name, ota_partitions) ota_partition_next = filter(lambda p: p.subtype - gen.MIN_PARTITION_SUBTYPE_APP_OTA == ota_id, ota_partitions)
else: else:
ota_partition_next = filter(lambda p: p.subtype - gen.MIN_PARTITION_SUBTYPE_APP_OTA == args.slot, ota_partitions) ota_partition_next = filter(lambda p: p.name == ota_id, ota_partitions)
ota_partition_next = list(ota_partition_next)[0] ota_partition_next = list(ota_partition_next)[0]
except IndexError: except IndexError:
raise RuntimeError("Partition to switch to not found") raise Exception("Partition to switch to not found")
otadata_contents = _get_otadata_contents(args) otadata_info = self._get_otadata_info()
otadata_status = _get_otadata_status(otadata_contents)
# Find the copy to base the computation for ota sequence number on # Find the copy to base the computation for ota sequence number on
otadata_compute_base = -1 otadata_compute_base = -1
# Both are valid, take the max as computation base # Both are valid, take the max as computation base
if is_otadata_status_valid(otadata_status[0]) and is_otadata_status_valid(otadata_status[1]): if is_otadata_info_valid(otadata_info[0]) and is_otadata_info_valid(otadata_info[1]):
if otadata_status[0].seq >= otadata_status[1].seq: if otadata_info[0].seq >= otadata_info[1].seq:
otadata_compute_base = 0 otadata_compute_base = 0
else: else:
otadata_compute_base = 1 otadata_compute_base = 1
# Only one copy is valid, use that # Only one copy is valid, use that
elif is_otadata_status_valid(otadata_status[0]): elif is_otadata_info_valid(otadata_info[0]):
otadata_compute_base = 0 otadata_compute_base = 0
elif is_otadata_status_valid(otadata_status[1]): elif is_otadata_info_valid(otadata_info[1]):
otadata_compute_base = 1 otadata_compute_base = 1
# Both are invalid (could be initial state - all 0xFF's) # Both are invalid (could be initial state - all 0xFF's)
else: else:
@ -216,7 +168,7 @@ def switch_otadata(args):
# Find the next ota sequence number # Find the next ota sequence number
if otadata_compute_base == 0 or otadata_compute_base == 1: if otadata_compute_base == 0 or otadata_compute_base == 1:
base_seq = otadata_status[otadata_compute_base].seq % (1 << 32) base_seq = otadata_info[otadata_compute_base].seq % (1 << 32)
i = 0 i = 0
while base_seq > target_seq % ota_partitions_num + i * ota_partitions_num: while base_seq > target_seq % ota_partitions_num + i * ota_partitions_num:
@ -231,10 +183,14 @@ def switch_otadata(args):
ota_seq_crc_next = binascii.crc32(ota_seq_next, 0xFFFFFFFF) % (1 << 32) ota_seq_crc_next = binascii.crc32(ota_seq_next, 0xFFFFFFFF) % (1 << 32)
ota_seq_crc_next = struct.pack("I", ota_seq_crc_next) ota_seq_crc_next = struct.pack("I", ota_seq_crc_next)
with open(f_name, "wb") as otadata_next_file: temp_file = tempfile.NamedTemporaryFile(delete=False)
start = (1 if otadata_compute_base == 0 else 0) * (SPI_FLASH_SEC_SIZE >> 1) temp_file.close()
otadata_next_file.write(otadata_contents) try:
with open(temp_file.name, "wb") as otadata_next_file:
start = (1 if otadata_compute_base == 0 else 0) * (self.spi_flash_sec_size >> 1)
otadata_next_file.write(self.otadata)
otadata_next_file.seek(start) otadata_next_file.seek(start)
otadata_next_file.write(ota_seq_next) otadata_next_file.write(ota_seq_next)
@ -244,34 +200,51 @@ def switch_otadata(args):
otadata_next_file.flush() otadata_next_file.flush()
_invoke_parttool(["write_partition", "--input", f_name], args) self.target.write_partition(OtatoolTarget.OTADATA_PARTITION, temp_file.name)
status("Updated ota_data partition")
finally: finally:
os.unlink(f_name) os.unlink(temp_file.name)
def read_ota_partition(self, ota_id, output):
self.target.read_partition(self._get_partition_id_from_ota_id(ota_id), output)
def write_ota_partition(self, ota_id, input):
self.target.write_partition(self._get_partition_id_from_ota_id(ota_id), input)
def erase_ota_partition(self, ota_id):
self.target.erase_partition(self._get_partition_id_from_ota_id(ota_id))
def _get_partition_specifier(args): def _read_otadata(target):
if args.name: target._check_otadata_partition()
return ["--partition-name", args.name]
else: otadata_info = target._get_otadata_info()
return ["--partition-type", "app", "--partition-subtype", "ota_" + str(args.slot)]
print(" {:8s} \t {:8s} | \t {:8s} \t {:8s}".format("OTA_SEQ", "CRC", "OTA_SEQ", "CRC"))
print("Firmware: 0x{:8x} \t0x{:8x} | \t0x{:8x} \t 0x{:8x}".format(otadata_info[0].seq, otadata_info[0].crc,
otadata_info[1].seq, otadata_info[1].crc))
def read_ota_partition(args): def _erase_otadata(target):
invoke_args = ["read_partition", "--output", args.output] target.erase_otadata()
_invoke_parttool(invoke_args, args, partition=_get_partition_specifier(args)) status("Erased ota_data partition contents")
status("Read ota partition contents to file {}".format(args.output))
def write_ota_partition(args): def _switch_ota_partition(target, ota_id):
invoke_args = ["write_partition", "--input", args.input] target.switch_ota_partition(ota_id)
_invoke_parttool(invoke_args, args, partition=_get_partition_specifier(args))
status("Written contents of file {} to ota partition".format(args.input))
def erase_ota_partition(args): def _read_ota_partition(target, ota_id, output):
invoke_args = ["erase_partition"] target.read_ota_partition(ota_id, output)
_invoke_parttool(invoke_args, args, partition=_get_partition_specifier(args)) status("Read ota partition contents to file {}".format(output))
def _write_ota_partition(target, ota_id, input):
target.write_ota_partition(ota_id, input)
status("Written contents of file {} to ota partition".format(input))
def _erase_ota_partition(target, ota_id):
target.erase_ota_partition(ota_id)
status("Erased contents of ota partition") status("Erased contents of ota partition")
@ -281,20 +254,29 @@ def main():
parser = argparse.ArgumentParser("ESP-IDF OTA Partitions Tool") parser = argparse.ArgumentParser("ESP-IDF OTA Partitions Tool")
parser.add_argument("--quiet", "-q", help="suppress stderr messages", action="store_true") parser.add_argument("--quiet", "-q", help="suppress stderr messages", action="store_true")
parser.add_argument("--esptool-args", help="additional main arguments for esptool", nargs="+")
parser.add_argument("--esptool-write-args", help="additional subcommand arguments for esptool write_flash", nargs="+")
parser.add_argument("--esptool-read-args", help="additional subcommand arguments for esptool read_flash", nargs="+")
parser.add_argument("--esptool-erase-args", help="additional subcommand arguments for esptool erase_region", nargs="+")
# There are two possible sources for the partition table: a device attached to the host # There are two possible sources for the partition table: a device attached to the host
# or a partition table CSV/binary file. These sources are mutually exclusive. # or a partition table CSV/binary file. These sources are mutually exclusive.
partition_table_info_source_args = parser.add_mutually_exclusive_group() parser.add_argument("--port", "-p", help="port where the device to read the partition table from is attached")
partition_table_info_source_args.add_argument("--port", "-p", help="port where the device to read the partition table from is attached", default="") parser.add_argument("--baud", "-b", help="baudrate to use", type=int)
partition_table_info_source_args.add_argument("--partition-table-file", "-f", help="file (CSV/binary) to read the partition table from", default="")
parser.add_argument("--partition-table-offset", "-o", help="offset to read the partition table from", default="0x8000") parser.add_argument("--partition-table-offset", "-o", help="offset to read the partition table from", type=str)
parser.add_argument("--partition-table-file", "-f", help="file (CSV/binary) to read the partition table from; \
overrides device attached to specified port as the partition table source when defined")
subparsers = parser.add_subparsers(dest="operation", help="run otatool -h for additional help") subparsers = parser.add_subparsers(dest="operation", help="run otatool -h for additional help")
spi_flash_sec_size = argparse.ArgumentParser(add_help=False)
spi_flash_sec_size.add_argument("--spi-flash-sec-size", help="value of SPI_FLASH_SEC_SIZE macro", type=str)
# Specify the supported operations # Specify the supported operations
subparsers.add_parser("read_otadata", help="read otadata partition") subparsers.add_parser("read_otadata", help="read otadata partition", parents=[spi_flash_sec_size])
subparsers.add_parser("erase_otadata", help="erase otadata partition") subparsers.add_parser("erase_otadata", help="erase otadata partition")
slot_or_name_parser = argparse.ArgumentParser(add_help=False) slot_or_name_parser = argparse.ArgumentParser(add_help=False)
@ -302,7 +284,7 @@ def main():
slot_or_name_parser_args.add_argument("--slot", help="slot number of the ota partition", type=int) slot_or_name_parser_args.add_argument("--slot", help="slot number of the ota partition", type=int)
slot_or_name_parser_args.add_argument("--name", help="name of the ota partition") slot_or_name_parser_args.add_argument("--name", help="name of the ota partition")
subparsers.add_parser("switch_otadata", help="switch otadata partition", parents=[slot_or_name_parser]) subparsers.add_parser("switch_ota_partition", help="switch otadata partition", parents=[slot_or_name_parser, spi_flash_sec_size])
read_ota_partition_subparser = subparsers.add_parser("read_ota_partition", help="read contents of an ota partition", parents=[slot_or_name_parser]) read_ota_partition_subparser = subparsers.add_parser("read_ota_partition", help="read contents of an ota partition", parents=[slot_or_name_parser])
read_ota_partition_subparser.add_argument("--output", help="file to write the contents of the ota partition to") read_ota_partition_subparser.add_argument("--output", help="file to write the contents of the ota partition to")
@ -322,17 +304,84 @@ def main():
parser.print_help() parser.print_help()
sys.exit(1) sys.exit(1)
# Else execute the operation target_args = {}
operation_func = globals()[args.operation]
if args.port:
target_args["port"] = args.port
if args.partition_table_file:
target_args["partition_table_file"] = args.partition_table_file
if args.partition_table_offset:
target_args["partition_table_offset"] = int(args.partition_table_offset, 0)
try:
if args.spi_flash_sec_size:
target_args["spi_flash_sec_size"] = int(args.spi_flash_sec_size, 0)
except AttributeError:
pass
if args.esptool_args:
target_args["esptool_args"] = args.esptool_args
if args.esptool_write_args:
target_args["esptool_write_args"] = args.esptool_write_args
if args.esptool_read_args:
target_args["esptool_read_args"] = args.esptool_read_args
if args.esptool_erase_args:
target_args["esptool_erase_args"] = args.esptool_erase_args
if args.baud:
target_args["baud"] = args.baud
target = OtatoolTarget(**target_args)
# Create the operation table and execute the operation
common_args = {'target':target}
ota_id = []
try:
if args.name is not None:
ota_id = ["name"]
else:
if args.slot is not None:
ota_id = ["slot"]
except AttributeError:
pass
otatool_ops = {
'read_otadata':(_read_otadata, []),
'erase_otadata':(_erase_otadata, []),
'switch_ota_partition':(_switch_ota_partition, ota_id),
'read_ota_partition':(_read_ota_partition, ["output"] + ota_id),
'write_ota_partition':(_write_ota_partition, ["input"] + ota_id),
'erase_ota_partition':(_erase_ota_partition, ota_id)
}
(op, op_args) = otatool_ops[args.operation]
for op_arg in op_args:
common_args.update({op_arg:vars(args)[op_arg]})
try:
common_args['ota_id'] = common_args.pop('name')
except KeyError:
try:
common_args['ota_id'] = common_args.pop('slot')
except KeyError:
pass
if quiet: if quiet:
# If exceptions occur, suppress and exit quietly # If exceptions occur, suppress and exit quietly
try: try:
operation_func(args) op(**common_args)
except Exception: except Exception:
sys.exit(2) sys.exit(2)
else: else:
operation_func(args) op(**common_args)
if __name__ == '__main__': if __name__ == '__main__':

View file

@ -1,6 +1,3 @@
set(COMPONENT_SRCDIRS ".") idf_component_register(SRC_DIRS "."
set(COMPONENT_ADD_INCLUDEDIRS ".") INCLUDE_DIRS "."
REQUIRES unity test_utils app_update bootloader_support nvs_flash)
set(COMPONENT_REQUIRES unity test_utils app_update bootloader_support nvs_flash)
register_component()

View file

@ -296,7 +296,7 @@ static void test_flow1(void)
// 3 Stage: run OTA0 -> check it -> copy OTA0 to OTA1 -> reboot --//-- // 3 Stage: run OTA0 -> check it -> copy OTA0 to OTA1 -> reboot --//--
// 4 Stage: run OTA1 -> check it -> copy OTA1 to OTA0 -> reboot --//-- // 4 Stage: run OTA1 -> check it -> copy OTA1 to OTA0 -> reboot --//--
// 5 Stage: run OTA0 -> check it -> erase OTA_DATA for next tests -> PASS // 5 Stage: run OTA0 -> check it -> erase OTA_DATA for next tests -> PASS
TEST_CASE_MULTIPLE_STAGES("Switching between factory, OTA0, OTA1, OTA0", "[app_update][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET]", start_test, test_flow1, test_flow1, test_flow1, test_flow1); TEST_CASE_MULTIPLE_STAGES("Switching between factory, OTA0, OTA1, OTA0", "[app_update][timeout=90][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET]", start_test, test_flow1, test_flow1, test_flow1, test_flow1);
static void test_flow2(void) static void test_flow2(void)
{ {
@ -333,7 +333,7 @@ static void test_flow2(void)
// 2 Stage: run factory -> check it -> copy factory to OTA0 -> reboot --//-- // 2 Stage: run factory -> check it -> copy factory to OTA0 -> reboot --//--
// 3 Stage: run OTA0 -> check it -> corrupt ota data -> reboot --//-- // 3 Stage: run OTA0 -> check it -> corrupt ota data -> reboot --//--
// 4 Stage: run factory -> check it -> erase OTA_DATA for next tests -> PASS // 4 Stage: run factory -> check it -> erase OTA_DATA for next tests -> PASS
TEST_CASE_MULTIPLE_STAGES("Switching between factory, OTA0, corrupt ota_sec1, factory", "[app_update][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET]", start_test, test_flow2, test_flow2, test_flow2); TEST_CASE_MULTIPLE_STAGES("Switching between factory, OTA0, corrupt ota_sec1, factory", "[app_update][timeout=90][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET]", start_test, test_flow2, test_flow2, test_flow2);
static void test_flow3(void) static void test_flow3(void)
{ {
@ -377,7 +377,7 @@ static void test_flow3(void)
// 3 Stage: run OTA0 -> check it -> copy OTA0 to OTA1 -> reboot --//-- // 3 Stage: run OTA0 -> check it -> copy OTA0 to OTA1 -> reboot --//--
// 3 Stage: run OTA1 -> check it -> corrupt ota sector2 -> reboot --//-- // 3 Stage: run OTA1 -> check it -> corrupt ota sector2 -> reboot --//--
// 4 Stage: run OTA0 -> check it -> erase OTA_DATA for next tests -> PASS // 4 Stage: run OTA0 -> check it -> erase OTA_DATA for next tests -> PASS
TEST_CASE_MULTIPLE_STAGES("Switching between factory, OTA0, OTA1, currupt ota_sec2, OTA0", "[app_update][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET]", start_test, test_flow3, test_flow3, test_flow3, test_flow3); TEST_CASE_MULTIPLE_STAGES("Switching between factory, OTA0, OTA1, currupt ota_sec2, OTA0", "[app_update][timeout=90][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET]", start_test, test_flow3, test_flow3, test_flow3, test_flow3);
#ifdef CONFIG_BOOTLOADER_FACTORY_RESET #ifdef CONFIG_BOOTLOADER_FACTORY_RESET
#define STORAGE_NAMESPACE "update_ota" #define STORAGE_NAMESPACE "update_ota"
@ -444,7 +444,7 @@ static void test_flow4(void)
// 2 Stage: run factory -> check it -> copy factory to OTA0 -> reboot --//-- // 2 Stage: run factory -> check it -> copy factory to OTA0 -> reboot --//--
// 3 Stage: run OTA0 -> check it -> set_pin_factory_reset -> reboot --//-- // 3 Stage: run OTA0 -> check it -> set_pin_factory_reset -> reboot --//--
// 4 Stage: run factory -> check it -> erase OTA_DATA for next tests -> PASS // 4 Stage: run factory -> check it -> erase OTA_DATA for next tests -> PASS
TEST_CASE_MULTIPLE_STAGES("Switching between factory, OTA0, sets pin_factory_reset, factory", "[app_update][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET]", start_test, test_flow4, test_flow4, test_flow4); TEST_CASE_MULTIPLE_STAGES("Switching between factory, OTA0, sets pin_factory_reset, factory", "[app_update][timeout=90][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET]", start_test, test_flow4, test_flow4, test_flow4);
#endif #endif
#ifdef CONFIG_BOOTLOADER_APP_TEST #ifdef CONFIG_BOOTLOADER_APP_TEST
@ -487,7 +487,7 @@ static void test_flow5(void)
// 2 Stage: run factory -> check it -> copy factory to Test and set pin_test_app -> reboot --//-- // 2 Stage: run factory -> check it -> copy factory to Test and set pin_test_app -> reboot --//--
// 3 Stage: run test -> check it -> reset pin_test_app -> reboot --//-- // 3 Stage: run test -> check it -> reset pin_test_app -> reboot --//--
// 4 Stage: run factory -> check it -> erase OTA_DATA for next tests -> PASS // 4 Stage: run factory -> check it -> erase OTA_DATA for next tests -> PASS
TEST_CASE_MULTIPLE_STAGES("Switching between factory, test, factory", "[app_update][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET]", start_test, test_flow5, test_flow5, test_flow5); TEST_CASE_MULTIPLE_STAGES("Switching between factory, test, factory", "[app_update][timeout=90][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET]", start_test, test_flow5, test_flow5, test_flow5);
#endif #endif
static const esp_partition_t* app_update(void) static const esp_partition_t* app_update(void)
@ -581,7 +581,7 @@ static void test_rollback1_1(void)
// 3 Stage: run OTA0 -> check it -> esp_ota_mark_app_valid_cancel_rollback() -> reboot --//-- // 3 Stage: run OTA0 -> check it -> esp_ota_mark_app_valid_cancel_rollback() -> reboot --//--
// 4 Stage: run OTA0 -> check it -> esp_ota_mark_app_invalid_rollback_and_reboot() -> reboot // 4 Stage: run OTA0 -> check it -> esp_ota_mark_app_invalid_rollback_and_reboot() -> reboot
// 5 Stage: run factory -> check it -> erase OTA_DATA for next tests -> PASS // 5 Stage: run factory -> check it -> erase OTA_DATA for next tests -> PASS
TEST_CASE_MULTIPLE_STAGES("Test rollback. factory, OTA0, OTA0, rollback -> factory", "[app_update][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET, SW_CPU_RESET]", start_test, test_rollback1, test_rollback1, test_rollback1, test_rollback1_1); TEST_CASE_MULTIPLE_STAGES("Test rollback. factory, OTA0, OTA0, rollback -> factory", "[app_update][timeout=90][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET, SW_CPU_RESET]", start_test, test_rollback1, test_rollback1, test_rollback1, test_rollback1_1);
static void test_rollback2(void) static void test_rollback2(void)
{ {
@ -679,7 +679,7 @@ static void test_rollback2_1(void)
// 3 Stage: run OTA0 -> check it -> esp_ota_mark_app_valid_cancel_rollback(), copy to next app slot -> reboot --//-- // 3 Stage: run OTA0 -> check it -> esp_ota_mark_app_valid_cancel_rollback(), copy to next app slot -> reboot --//--
// 4 Stage: run OTA1 -> check it -> PENDING_VERIFY/esp_ota_mark_app_invalid_rollback_and_reboot() -> reboot // 4 Stage: run OTA1 -> check it -> PENDING_VERIFY/esp_ota_mark_app_invalid_rollback_and_reboot() -> reboot
// 5 Stage: run OTA0(rollback) -> check it -> erase OTA_DATA for next tests -> PASS // 5 Stage: run OTA0(rollback) -> check it -> erase OTA_DATA for next tests -> PASS
TEST_CASE_MULTIPLE_STAGES("Test rollback. factory, OTA0, OTA1, rollback -> OTA0", "[app_update][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET, SW_CPU_RESET]", start_test, test_rollback2, test_rollback2, test_rollback2, test_rollback2_1); TEST_CASE_MULTIPLE_STAGES("Test rollback. factory, OTA0, OTA1, rollback -> OTA0", "[app_update][timeout=90][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET, SW_CPU_RESET]", start_test, test_rollback2, test_rollback2, test_rollback2, test_rollback2_1);
static void test_erase_last_app_flow(void) static void test_erase_last_app_flow(void)
{ {
@ -730,4 +730,4 @@ static void test_erase_last_app_rollback(void)
// 3 Stage: run OTA0 -> check it -> copy factory to OTA1 -> reboot --//-- // 3 Stage: run OTA0 -> check it -> copy factory to OTA1 -> reboot --//--
// 4 Stage: run OTA1 -> check it -> erase OTA0 and rollback -> reboot // 4 Stage: run OTA1 -> check it -> erase OTA0 and rollback -> reboot
// 5 Stage: run factory -> check it -> erase OTA_DATA for next tests -> PASS // 5 Stage: run factory -> check it -> erase OTA_DATA for next tests -> PASS
TEST_CASE_MULTIPLE_STAGES("Test erase_last_boot_app_partition. factory, OTA1, OTA0, factory", "[app_update][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET, SW_CPU_RESET]", start_test, test_erase_last_app_flow, test_erase_last_app_flow, test_erase_last_app_flow, test_erase_last_app_rollback); TEST_CASE_MULTIPLE_STAGES("Test erase_last_boot_app_partition. factory, OTA1, OTA0, factory", "[app_update][timeout=90][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET, SW_CPU_RESET]", start_test, test_erase_last_app_flow, test_erase_last_app_flow, test_erase_last_app_flow, test_erase_last_app_rollback);

View file

@ -1,6 +1,3 @@
set(COMPONENT_ADD_INCLUDEDIRS asio/asio/include port/include) idf_component_register(SRCS "asio/asio/src/asio.cpp"
set(COMPONENT_SRCS "asio/asio/src/asio.cpp") INCLUDE_DIRS "asio/asio/include" "port/include"
REQUIRES lwip)
set(COMPONENT_REQUIRES lwip)
register_component()

View file

@ -1,14 +1,21 @@
register_component() idf_component_register(PRIV_REQUIRES partition_table)
# Do not generate flash file when building bootloader or is in early expansion of the build # Do not generate flash file when building bootloader or is in early expansion of the build
if(BOOTLOADER_BUILD) if(BOOTLOADER_BUILD)
return() return()
endif() endif()
# When secure boot is enabled, do not flash bootloader along with invocation of `idf.py flash`
if(NOT CONFIG_SECURE_BOOT_ENABLED)
set(flash_bootloader FLASH_IN_PROJECT)
endif()
# Set values used in flash_bootloader_args.in and generate flash file # Set values used in flash_bootloader_args.in and generate flash file
# for bootloader # for bootloader
set(BOOTLOADER_OFFSET 0x1000) esptool_py_flash_project_args(bootloader 0x1000
esptool_py_flash_project_args(bootloader ${BOOTLOADER_OFFSET}
${BOOTLOADER_BUILD_DIR}/bootloader.bin ${BOOTLOADER_BUILD_DIR}/bootloader.bin
FLASH_IN_PROJECT ${flash_bootloader}
FLASH_FILE_TEMPLATE flash_bootloader_args.in) FLASH_FILE_TEMPLATE flash_bootloader_args.in)
esptool_py_custom_target(bootloader-flash bootloader "bootloader")
add_dependencies(bootloader partition_table)

View file

@ -409,7 +409,8 @@ menu "Security features"
Note: After first boot, the system will be permanently encrypted. Re-flashing an encrypted Note: After first boot, the system will be permanently encrypted. Re-flashing an encrypted
system is complicated and not always possible. system is complicated and not always possible.
Read https://docs.espressif.com/projects/esp-idf/en/latest/security/flash-encryption.html before enabling. Read https://docs.espressif.com/projects/esp-idf/en/latest/security/flash-encryption.html
before enabling.
choice SECURE_FLASH_ENCRYPTION_KEYSIZE choice SECURE_FLASH_ENCRYPTION_KEYSIZE
bool "Size of generated AES-XTS key" bool "Size of generated AES-XTS key"
@ -431,31 +432,40 @@ menu "Security features"
bool "AES-256 (512-bit key)" bool "AES-256 (512-bit key)"
endchoice endchoice
config SECURE_FLASH_ENC_INSECURE choice SECURE_FLASH_ENCRYPTION_MODE
bool "Allow potentially insecure options" bool "Enable usage mode"
depends on SECURE_FLASH_ENC_ENABLED depends on SECURE_FLASH_ENC_ENABLED
default N default SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT
help help
You can disable some of the default protections offered by flash encryption, in order to enable testing or By default Development mode is enabled which allows UART bootloader to perform flash encryption operations
a custom combination of security features.
Only enable these options if you are very sure. Select Release mode only for production or manufacturing. Once enabled you can not reflash using UART
bootloader
Refer to https://docs.espressif.com/projects/esp-idf/en/latest/security/secure-boot.html and Refer to https://docs.espressif.com/projects/esp-idf/en/latest/security/secure-boot.html and
https://docs.espressif.com/projects/esp-idf/en/latest/security/flash-encryption.html for details. https://docs.espressif.com/projects/esp-idf/en/latest/security/flash-encryption.html for details.
config SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT
bool "Development(NOT SECURE)"
select SECURE_FLASH_UART_BOOTLOADER_ALLOW_ENC
config SECURE_FLASH_ENCRYPTION_MODE_RELEASE
bool "Release"
endchoice
menu "Potentially insecure options" menu "Potentially insecure options"
visible if SECURE_FLASH_ENC_INSECURE || SECURE_BOOT_INSECURE visible if SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT || SECURE_BOOT_INSECURE
# NOTE: Options in this menu NEED to have SECURE_BOOT_INSECURE # NOTE: Options in this menu NEED to have SECURE_BOOT_INSECURE
# and/or SECURE_FLASH_ENC_INSECURE in "depends on", as the menu # and/or SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT in "depends on", as the menu
# itself doesn't enable/disable its children (if it's not set, # itself doesn't enable/disable its children (if it's not set,
# it's possible for the insecure menu to be disabled but the insecure option # it's possible for the insecure menu to be disabled but the insecure option
# to remain on which is very bad.) # to remain on which is very bad.)
config SECURE_BOOT_ALLOW_ROM_BASIC config SECURE_BOOT_ALLOW_ROM_BASIC
bool "Leave ROM BASIC Interpreter available on reset" bool "Leave ROM BASIC Interpreter available on reset"
depends on SECURE_BOOT_INSECURE || SECURE_FLASH_ENC_INSECURE depends on SECURE_BOOT_INSECURE || SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT
default N default N
help help
By default, the BASIC ROM Console starts on reset if no valid bootloader is By default, the BASIC ROM Console starts on reset if no valid bootloader is
@ -469,7 +479,7 @@ menu "Security features"
config SECURE_BOOT_ALLOW_JTAG config SECURE_BOOT_ALLOW_JTAG
bool "Allow JTAG Debugging" bool "Allow JTAG Debugging"
depends on SECURE_BOOT_INSECURE || SECURE_FLASH_ENC_INSECURE depends on SECURE_BOOT_INSECURE || SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT
default N default N
help help
If not set (default), the bootloader will permanently disable JTAG (across entire chip) on first boot If not set (default), the bootloader will permanently disable JTAG (across entire chip) on first boot
@ -496,7 +506,7 @@ menu "Security features"
config SECURE_FLASH_UART_BOOTLOADER_ALLOW_ENC config SECURE_FLASH_UART_BOOTLOADER_ALLOW_ENC
bool "Leave UART bootloader encryption enabled" bool "Leave UART bootloader encryption enabled"
depends on SECURE_FLASH_ENC_INSECURE depends on SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT
default N default N
help help
If not set (default), the bootloader will permanently disable UART bootloader encryption access on If not set (default), the bootloader will permanently disable UART bootloader encryption access on
@ -506,7 +516,7 @@ menu "Security features"
config SECURE_FLASH_UART_BOOTLOADER_ALLOW_DEC config SECURE_FLASH_UART_BOOTLOADER_ALLOW_DEC
bool "Leave UART bootloader decryption enabled" bool "Leave UART bootloader decryption enabled"
depends on SECURE_FLASH_ENC_INSECURE depends on SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT
default N default N
help help
If not set (default), the bootloader will permanently disable UART bootloader decryption access on If not set (default), the bootloader will permanently disable UART bootloader decryption access on
@ -517,7 +527,7 @@ menu "Security features"
config SECURE_FLASH_UART_BOOTLOADER_ALLOW_CACHE config SECURE_FLASH_UART_BOOTLOADER_ALLOW_CACHE
bool "Leave UART bootloader flash cache enabled" bool "Leave UART bootloader flash cache enabled"
depends on SECURE_FLASH_ENC_INSECURE depends on SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT
default N default N
help help
If not set (default), the bootloader will permanently disable UART bootloader flash cache access on If not set (default), the bootloader will permanently disable UART bootloader flash cache access on
@ -527,3 +537,4 @@ menu "Security features"
endmenu # Potentially Insecure endmenu # Potentially Insecure
endmenu # Security features endmenu # Security features

View file

@ -1,4 +1,4 @@
--flash_mode ${ESPFLASHMODE} --flash_mode ${ESPFLASHMODE}
--flash_size ${ESPFLASHSIZE} --flash_size ${ESPFLASHSIZE}
--flash_freq ${ESPFLASHFREQ} --flash_freq ${ESPFLASHFREQ}
${BOOTLOADER_OFFSET} bootloader/bootloader.bin ${OFFSET} ${IMAGE}

View file

@ -1,32 +1,10 @@
# Do not generate flash file when building bootloader or is in early expansion of the build set(BOOTLOADER_OFFSET 0x1000)
# Do not generate flash file when building bootloader
if(BOOTLOADER_BUILD) if(BOOTLOADER_BUILD)
return() return()
endif() endif()
idf_build_get_property(project_dir PROJECT_DIR)
# This is for tracking the top level project path
if(BOOTLOADER_BUILD)
set(main_project_path "${CMAKE_BINARY_DIR}/../..")
else()
set(main_project_path "${project_dir}")
endif()
get_filename_component(secure_boot_signing_key
"${CONFIG_SECURE_BOOT_SIGNING_KEY}"
ABSOLUTE BASE_DIR "${main_project_path}")
if(NOT EXISTS ${secure_boot_signing_key})
# If the signing key is not found, create a phony gen_secure_boot_signing_key target that
# fails the build. fail_at_build_time also touches CMakeCache.txt to cause a cmake run next time
# (to pick up a new signing key if one exists, etc.)
fail_at_build_time(gen_secure_boot_signing_key
"Secure Boot Signing Key ${CONFIG_SECURE_BOOT_SIGNING_KEY} does not exist. Generate using:"
"\tespsecure.py generate_signing_key ${CONFIG_SECURE_BOOT_SIGNING_KEY}")
else()
add_custom_target(gen_secure_boot_signing_key)
endif()
# Glue to build the bootloader subproject binary as an external # Glue to build the bootloader subproject binary as an external
# cmake project under this one # cmake project under this one
# #
@ -39,37 +17,104 @@ set(bootloader_binary_files
"${BOOTLOADER_BUILD_DIR}/bootloader.map" "${BOOTLOADER_BUILD_DIR}/bootloader.map"
) )
# These additional files may get generated idf_build_get_property(project_dir PROJECT_DIR)
if(CONFIG_SECURE_BOOTLOADER_REFLASHABLE)
# There are some additional processing when CONFIG_CONFIG_SECURE_SIGNED_APPS. This happens
# when either CONFIG_SECURE_BOOT_ENABLED or SECURE_BOOT_BUILD_SIGNED_BINARIES.
# For both cases, the user either sets binaries to be signed during build or not
# using CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES.
#
# Regardless, pass the main project's keys (signing/verification) to the bootloader subproject
# via config.
if(CONFIG_SECURE_SIGNED_APPS)
add_custom_target(gen_secure_boot_keys)
if(CONFIG_SECURE_BOOT_ENABLED)
# Check that the configuration is sane
if((CONFIG_SECURE_BOOTLOADER_REFLASHABLE AND CONFIG_SECURE_BOOTLOADER_ONE_TIME_FLASH) OR
(NOT CONFIG_SECURE_BOOTLOADER_REFLASHABLE AND NOT CONFIG_SECURE_BOOTLOADER_ONE_TIME_FLASH))
fail_at_build_time(bootloader "Invalid bootloader target: bad sdkconfig?")
endif()
if(CONFIG_SECURE_BOOTLOADER_REFLASHABLE)
set(bootloader_binary_files set(bootloader_binary_files
${bootloader_binary_files} ${bootloader_binary_files}
"${BOOTLOADER_BUILD_DIR}/bootloader-reflash-digest.bin" "${BOOTLOADER_BUILD_DIR}/bootloader-reflash-digest.bin"
"${BOOTLOADER_BUILD_DIR}/secure-bootloader-key-192.bin" "${BOOTLOADER_BUILD_DIR}/secure-bootloader-key-192.bin"
"${BOOTLOADER_BUILD_DIR}/secure-bootloader-key-256.bin" "${BOOTLOADER_BUILD_DIR}/secure-bootloader-key-256.bin"
) )
endif()
endif()
# Since keys are usually given relative to main project dir, get the absolute paths to the keys
# for use by the bootloader subproject. Replace the values in config with these absolute paths,
# so that bootloader subproject does not need to assume main project dir to obtain path to the keys.
if(CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES)
get_filename_component(secure_boot_signing_key
"${CONFIG_SECURE_BOOT_SIGNING_KEY}"
ABSOLUTE BASE_DIR "${project_dir}")
if(NOT EXISTS ${secure_boot_signing_key})
# If the signing key is not found, create a phony gen_secure_boot_signing_key target that
# fails the build. fail_at_build_time causes a cmake run next time
# (to pick up a new signing key if one exists, etc.)
fail_at_build_time(gen_secure_boot_signing_key
"Secure Boot Signing Key ${CONFIG_SECURE_BOOT_SIGNING_KEY} does not exist. Generate using:"
"\tespsecure.py generate_signing_key ${CONFIG_SECURE_BOOT_SIGNING_KEY}")
else()
add_custom_target(gen_secure_boot_signing_key)
endif()
set(SECURE_BOOT_SIGNING_KEY ${secure_boot_signing_key}) # needed by some other components
set(sign_key_arg "-DSECURE_BOOT_SIGNING_KEY=${secure_boot_signing_key}")
add_dependencies(gen_secure_boot_keys gen_secure_boot_signing_key)
else()
get_filename_component(secure_boot_verification_key
${CONFIG_SECURE_BOOT_VERIFICATION_KEY}
ABSOLUTE BASE_DIR "${project_dir}")
if(NOT EXISTS ${secure_boot_verification_key})
# If the verification key is not found, create a phony gen_secure_boot_verification_key target that
# fails the build. fail_at_build_time causes a cmake run next time
# (to pick up a new verification key if one exists, etc.)
fail_at_build_time(gen_secure_boot_verification_key
"Secure Boot Verification Public Key ${CONFIG_SECURE_BOOT_VERIFICATION_KEY} does not exist."
"\tThis can be extracted from the private signing key."
"\tSee docs/security/secure-boot.rst for details.")
else()
add_custom_target(gen_secure_boot_verification_key)
endif()
set(ver_key_arg "-DSECURE_BOOT_VERIFICATION_KEY=${secure_boot_verification_key}")
add_dependencies(gen_secure_boot_keys gen_secure_boot_verification_key)
endif()
endif() endif()
if((NOT CONFIG_SECURE_BOOT_ENABLED) OR idf_build_get_property(idf_path IDF_PATH)
CONFIG_SECURE_BOOTLOADER_REFLASHABLE OR idf_build_get_property(idf_target IDF_TARGET)
CONFIG_SECURE_BOOTLOADER_ONE_TIME_FLASH) idf_build_get_property(sdkconfig SDKCONFIG)
idf_build_get_property(idf_path IDF_PATH)
idf_build_get_property(sdkconfig SDKCONFIG) externalproject_add(bootloader
idf_build_get_property(idf_target IDF_TARGET)
externalproject_add(bootloader
# TODO: support overriding the bootloader in COMPONENT_PATHS
SOURCE_DIR "${CMAKE_CURRENT_LIST_DIR}/subproject" SOURCE_DIR "${CMAKE_CURRENT_LIST_DIR}/subproject"
BINARY_DIR "${BOOTLOADER_BUILD_DIR}" BINARY_DIR "${BOOTLOADER_BUILD_DIR}"
CMAKE_ARGS -DSDKCONFIG=${sdkconfig} -DIDF_PATH=${idf_path} -DIDF_TARGET=${idf_target} CMAKE_ARGS -DSDKCONFIG=${sdkconfig} -DIDF_PATH=${idf_path} -DIDF_TARGET=${idf_target}
-DSECURE_BOOT_SIGNING_KEY=${secure_boot_signing_key}
-DPYTHON_DEPS_CHECKED=1 -DPYTHON_DEPS_CHECKED=1
-DEXTRA_COMPONENT_DIRS=${CMAKE_CURRENT_LIST_DIR} -DEXTRA_COMPONENT_DIRS=${CMAKE_CURRENT_LIST_DIR}
${sign_key_arg} ${ver_key_arg}
# LEGACY_INCLUDE_COMMON_HEADERS has to be passed in via cache variable since
# the bootloader common component requirements depends on this and
# config variables are not available before project() call.
-DLEGACY_INCLUDE_COMMON_HEADERS=${CONFIG_LEGACY_INCLUDE_COMMON_HEADERS}
INSTALL_COMMAND "" INSTALL_COMMAND ""
BUILD_ALWAYS 1 # no easy way around this... BUILD_ALWAYS 1 # no easy way around this...
BUILD_BYPRODUCTS ${bootloader_binary_files} BUILD_BYPRODUCTS ${bootloader_binary_files}
DEPENDS gen_secure_boot_signing_key
) )
else()
fail_at_build_time(bootloader "Invalid bootloader target: bad sdkconfig?") if(CONFIG_SECURE_SIGNED_APPS)
add_dependencies(bootloader gen_secure_boot_keys)
endif() endif()
# this is a hack due to an (annoying) shortcoming in cmake, it can't # this is a hack due to an (annoying) shortcoming in cmake, it can't

View file

@ -16,7 +16,7 @@ CONFIG_APP_SECURE_VERSION_SIZE_EFUSE_FIELD CONFIG_BOOTLOADER_AP
CONFIG_EFUSE_SECURE_VERSION_EMULATE CONFIG_BOOTLOADER_EFUSE_SECURE_VERSION_EMULATE CONFIG_EFUSE_SECURE_VERSION_EMULATE CONFIG_BOOTLOADER_EFUSE_SECURE_VERSION_EMULATE
CONFIG_FLASH_ENCRYPTION_ENABLED CONFIG_SECURE_FLASH_ENC_ENABLED CONFIG_FLASH_ENCRYPTION_ENABLED CONFIG_SECURE_FLASH_ENC_ENABLED
CONFIG_FLASH_ENCRYPTION_INSECURE CONFIG_SECURE_FLASH_ENC_INSECURE CONFIG_FLASH_ENCRYPTION_INSECURE CONFIG_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT
CONFIG_FLASH_ENCRYPTION_UART_BOOTLOADER_ALLOW_ENCRYPT CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_ENC CONFIG_FLASH_ENCRYPTION_UART_BOOTLOADER_ALLOW_ENCRYPT CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_ENC
CONFIG_FLASH_ENCRYPTION_UART_BOOTLOADER_ALLOW_DECRYPT CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_DEC CONFIG_FLASH_ENCRYPTION_UART_BOOTLOADER_ALLOW_DECRYPT CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_DEC
CONFIG_FLASH_ENCRYPTION_UART_BOOTLOADER_ALLOW_CACHE CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_CACHE CONFIG_FLASH_ENCRYPTION_UART_BOOTLOADER_ALLOW_CACHE CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_CACHE

View file

@ -19,7 +19,7 @@ set(COMPONENTS bootloader esptool_py partition_table soc bootloader_support log
set(BOOTLOADER_BUILD 1) set(BOOTLOADER_BUILD 1)
include("${IDF_PATH}/tools/cmake/project.cmake") include("${IDF_PATH}/tools/cmake/project.cmake")
set(common_req log esp_rom esp_common xtensa) set(common_req log esp_rom esp_common xtensa)
if (CONFIG_LEGACY_INCLUDE_COMMON_HEADERS) if(LEGACY_INCLUDE_COMMON_HEADERS)
list(APPEND common_req soc) list(APPEND common_req soc)
endif() endif()
idf_build_set_property(__COMPONENT_REQUIRES_COMMON "${common_req}") idf_build_set_property(__COMPONENT_REQUIRES_COMMON "${common_req}")
@ -29,8 +29,6 @@ project(bootloader)
idf_build_set_property(COMPILE_DEFINITIONS "-DBOOTLOADER_BUILD=1" APPEND) idf_build_set_property(COMPILE_DEFINITIONS "-DBOOTLOADER_BUILD=1" APPEND)
idf_build_set_property(COMPILE_OPTIONS "-fno-stack-protector" APPEND) idf_build_set_property(COMPILE_OPTIONS "-fno-stack-protector" APPEND)
set(secure_boot_signing_key ${SECURE_BOOT_SIGNING_KEY})
string(REPLACE ";" " " espsecurepy "${ESPSECUREPY}") string(REPLACE ";" " " espsecurepy "${ESPSECUREPY}")
string(REPLACE ";" " " espefusepy "${ESPEFUSEPY}") string(REPLACE ";" " " espefusepy "${ESPEFUSEPY}")
set(esptoolpy_write_flash "${ESPTOOLPY_WRITE_FLASH_STR}") set(esptoolpy_write_flash "${ESPTOOLPY_WRITE_FLASH_STR}")
@ -53,7 +51,7 @@ if(CONFIG_SECURE_BOOTLOADER_REFLASHABLE)
add_custom_command(OUTPUT "${secure_bootloader_key}" add_custom_command(OUTPUT "${secure_bootloader_key}"
COMMAND ${ESPSECUREPY} digest_private_key COMMAND ${ESPSECUREPY} digest_private_key
--keylen "${key_digest_len}" --keylen "${key_digest_len}"
--keyfile "${secure_boot_signing_key}" --keyfile "${SECURE_BOOT_SIGNING_KEY}"
"${secure_bootloader_key}" "${secure_bootloader_key}"
VERBATIM) VERBATIM)
@ -67,7 +65,7 @@ if(CONFIG_SECURE_BOOTLOADER_REFLASHABLE)
"\nTo generate one, you can use this command:" "\nTo generate one, you can use this command:"
"\n\t${espsecurepy} generate_flash_encryption_key ${secure_bootloader_key}" "\n\t${espsecurepy} generate_flash_encryption_key ${secure_bootloader_key}"
"\nIf a signing key is present, then instead use:" "\nIf a signing key is present, then instead use:"
"\n\t${ESPSECUREPY} digest_private_key " "\n\t${espsecurepy} digest_private_key "
"--keylen (192/256) --keyfile KEYFILE " "--keylen (192/256) --keyfile KEYFILE "
"${secure_bootloader_key}") "${secure_bootloader_key}")
endif() endif()
@ -78,14 +76,14 @@ if(CONFIG_SECURE_BOOTLOADER_REFLASHABLE)
COMMAND ${CMAKE_COMMAND} -E echo "DIGEST ${bootloader_digest_bin}" COMMAND ${CMAKE_COMMAND} -E echo "DIGEST ${bootloader_digest_bin}"
COMMAND ${ESPSECUREPY} digest_secure_bootloader --keyfile "${secure_bootloader_key}" COMMAND ${ESPSECUREPY} digest_secure_bootloader --keyfile "${secure_bootloader_key}"
-o "${bootloader_digest_bin}" "${CMAKE_BINARY_DIR}/bootloader.bin" -o "${bootloader_digest_bin}" "${CMAKE_BINARY_DIR}/bootloader.bin"
DEPENDS gen_secure_bootloader_key "${CMAKE_BINARY_DIR}/bootloader.bin" DEPENDS gen_secure_bootloader_key gen_project_binary
VERBATIM) VERBATIM)
add_custom_target (gen_bootloader_digest_bin ALL DEPENDS "${bootloader_digest_bin}") add_custom_target (gen_bootloader_digest_bin ALL DEPENDS "${bootloader_digest_bin}")
endif() endif()
if(CONFIG_SECURE_BOOTLOADER_ONE_TIME_FLASH) if(CONFIG_SECURE_BOOTLOADER_ONE_TIME_FLASH)
add_custom_command(TARGET bootloader POST_BUILD add_custom_command(TARGET bootloader.elf POST_BUILD
COMMAND ${CMAKE_COMMAND} -E echo COMMAND ${CMAKE_COMMAND} -E echo
"==============================================================================" "=============================================================================="
COMMAND ${CMAKE_COMMAND} -E echo COMMAND ${CMAKE_COMMAND} -E echo
@ -97,9 +95,8 @@ if(CONFIG_SECURE_BOOTLOADER_ONE_TIME_FLASH)
COMMAND ${CMAKE_COMMAND} -E echo COMMAND ${CMAKE_COMMAND} -E echo
"* IMPORTANT: After first boot, BOOTLOADER CANNOT BE RE-FLASHED on same device" "* IMPORTANT: After first boot, BOOTLOADER CANNOT BE RE-FLASHED on same device"
VERBATIM) VERBATIM)
elseif(CONFIG_SECURE_BOOTLOADER_REFLASHABLE) elseif(CONFIG_SECURE_BOOTLOADER_REFLASHABLE)
add_custom_command(TARGET bootloader POST_BUILD add_custom_command(TARGET bootloader.elf POST_BUILD
COMMAND ${CMAKE_COMMAND} -E echo COMMAND ${CMAKE_COMMAND} -E echo
"==============================================================================" "=============================================================================="
COMMAND ${CMAKE_COMMAND} -E echo COMMAND ${CMAKE_COMMAND} -E echo

View file

@ -1,4 +1,3 @@
# only compile the "micro-ecc/uECC.c" source file # only compile the "micro-ecc/uECC.c" source file
set(COMPONENT_SRCS "micro-ecc/uECC.c") idf_component_register(SRCS "micro-ecc/uECC.c"
set(COMPONENT_ADD_INCLUDEDIRS micro-ecc) INCLUDE_DIRS micro-ecc)
register_component()

View file

@ -5,4 +5,5 @@ idf_build_get_property(target IDF_TARGET)
set(scripts "ld/${target}/bootloader.ld" set(scripts "ld/${target}/bootloader.ld"
"ld/${target}/bootloader.rom.ld") "ld/${target}/bootloader.rom.ld")
target_linker_script(${COMPONENT_LIB} "${scripts}") target_linker_script(${COMPONENT_LIB} INTERFACE "${scripts}")

View file

@ -1,64 +1,70 @@
set(COMPONENT_SRCS "src/bootloader_clock.c" set(srcs
"src/bootloader_clock.c"
"src/bootloader_common.c" "src/bootloader_common.c"
"src/bootloader_flash.c" "src/bootloader_flash.c"
"src/bootloader_random.c" "src/bootloader_random.c"
"src/bootloader_utility.c" "src/bootloader_utility.c"
"src/esp_image_format.c" "src/esp_image_format.c"
"src/flash_encrypt.c"
"src/flash_partitions.c" "src/flash_partitions.c"
"src/flash_qio_mode.c") "src/flash_qio_mode.c"
"src/${IDF_TARGET}/bootloader_flash_config_${IDF_TARGET}.c"
)
if(BOOTLOADER_BUILD) if(BOOTLOADER_BUILD)
set(COMPONENT_ADD_INCLUDEDIRS "include include_bootloader") set(include_dirs "include" "include_bootloader")
set(COMPONENT_REQUIRES spi_flash soc) #unfortunately the header directly uses SOC registers set(priv_requires micro-ecc spi_flash efuse)
set(COMPONENT_PRIV_REQUIRES micro-ecc efuse) list(APPEND srcs
list(APPEND COMPONENT_SRCS "src/bootloader_init.c" "src/bootloader_init.c"
"src/${IDF_TARGET}/bootloader_sha.c" "src/${IDF_TARGET}/bootloader_sha.c"
"src/${IDF_TARGET}/flash_encrypt.c" "src/${IDF_TARGET}/flash_encrypt.c"
"src/${IDF_TARGET}/secure_boot_signatures.c" "src/${IDF_TARGET}/secure_boot_signatures.c"
"src/${IDF_TARGET}/secure_boot.c" "src/${IDF_TARGET}/secure_boot.c"
"src/${IDF_TARGET}/bootloader_${IDF_TARGET}.c" "src/${IDF_TARGET}/bootloader_${IDF_TARGET}.c"
"src/${IDF_TARGET}/bootloader_clock_${IDF_TARGET}.c") "src/${IDF_TARGET}/bootloader_clock_${IDF_TARGET}.c"
)
else()
list(APPEND srcs
"src/idf/bootloader_sha.c"
"src/idf/secure_boot_signatures.c")
set(include_dirs "include")
set(priv_include_dirs "include_bootloader")
set(priv_requires spi_flash mbedtls efuse)
endif()
if(CONFIG_SECURE_SIGNED_APPS) set(requires soc) #unfortunately the header directly uses SOC registers
idf_component_register(SRCS "${srcs}"
INCLUDE_DIRS "${include_dirs}"
PRIV_INCLUDE_DIRS "${priv_include_dirs}"
REQUIRES "${requires}"
PRIV_REQUIRES "${priv_requires}")
if(BOOTLOADER_BUILD AND CONFIG_SECURE_SIGNED_APPS)
# Whether CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES or not, we need verification key to embed
# in the library.
if(CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES)
# We generate the key from the signing key. The signing key is passed from the main project.
get_filename_component(secure_boot_signing_key
"${SECURE_BOOT_SIGNING_KEY}"
ABSOLUTE BASE_DIR "${project_dir}")
get_filename_component(secure_boot_verification_key get_filename_component(secure_boot_verification_key
"signature_verification_key.bin" "signature_verification_key.bin"
ABSOLUTE BASE_DIR "${CMAKE_BINARY_DIR}") ABSOLUTE BASE_DIR "${CMAKE_CURRENT_BINARY_DIR}")
if(CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES)
add_custom_command(OUTPUT "${secure_boot_verification_key}" add_custom_command(OUTPUT "${secure_boot_verification_key}"
COMMAND ${ESPSECUREPY} COMMAND ${ESPSECUREPY}
extract_public_key --keyfile "${secure_boot_signing_key}" extract_public_key --keyfile "${secure_boot_signing_key}"
"${secure_boot_verification_key}" "${secure_boot_verification_key}"
DEPENDS gen_secure_boot_signing_key
VERBATIM) VERBATIM)
else() else()
get_filename_component(orig_secure_boot_verification_key # We expect to 'inherit' the verification key passed from main project.
"${CONFIG_SECURE_BOOT_VERIFICATION_KEY}" get_filename_component(secure_boot_verification_key
ABSOLUTE BASE_DIR "${main_project_path}") ${SECURE_BOOT_VERIFICATION_KEY}
if(NOT EXISTS ${orig_secure_boot_verification_key}) ABSOLUTE BASE_DIR "${project_dir}")
message(FATAL_ERROR
"Secure Boot Verification Public Key ${CONFIG_SECURE_BOOT_VERIFICATION_KEY} does not exist."
"\nThis can be extracted from the private signing key."
"\nSee docs/security/secure-boot.rst for details.")
endif() endif()
add_custom_command(OUTPUT "${secure_boot_verification_key}" target_add_binary_data(${COMPONENT_LIB} "${secure_boot_verification_key}" "BINARY")
COMMAND ${CMAKE_COMMAND} -E copy "${orig_secure_boot_verification_key}"
"${secure_boot_verification_key}"
DEPENDS "${orig_secure_boot_verification_key}"
VERBATIM)
endif()
set(COMPONENT_EMBED_FILES "${secure_boot_verification_key}")
set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES
"${secure_boot_verification_key}") "${secure_boot_verification_key}")
endif()
else()
list(APPEND COMPONENT_SRCS "src/idf/bootloader_sha.c"
"src/idf/secure_boot_signatures.c")
set(COMPONENT_ADD_INCLUDEDIRS "include")
set(COMPONENT_PRIV_INCLUDEDIRS "include_bootloader")
set(COMPONENT_REQUIRES mbedtls soc) #unfortunately the header directly uses SOC registers
set(COMPONENT_PRIV_REQUIRES spi_flash efuse)
endif() endif()
register_component()

View file

@ -14,6 +14,10 @@
#pragma once #pragma once
#ifdef __cplusplus
extern "C" {
#endif
/** @brief Configure clocks for early boot /** @brief Configure clocks for early boot
* *
* Called by bootloader, or by the app if the bootloader version is old (pre v2.1). * Called by bootloader, or by the app if the bootloader version is old (pre v2.1).
@ -23,3 +27,8 @@ void bootloader_clock_configure(void);
/** @brief Return the rated maximum frequency of this chip /** @brief Return the rated maximum frequency of this chip
*/ */
int bootloader_clock_get_rated_freq_mhz(void); int bootloader_clock_get_rated_freq_mhz(void);
#ifdef __cplusplus
}
#endif

View file

@ -16,6 +16,10 @@
#include "esp_flash_partitions.h" #include "esp_flash_partitions.h"
#include "esp_image_format.h" #include "esp_image_format.h"
#ifdef __cplusplus
extern "C" {
#endif
/// Type of hold a GPIO in low state /// Type of hold a GPIO in low state
typedef enum { typedef enum {
GPIO_LONG_HOLD = 1, /*!< The long hold GPIO */ GPIO_LONG_HOLD = 1, /*!< The long hold GPIO */
@ -148,3 +152,7 @@ esp_err_t bootloader_common_get_partition_description(const esp_partition_pos_t
* @brief Configure VDDSDIO, call this API to rise VDDSDIO to 1.9V when VDDSDIO regulator is enabled as 1.8V mode. * @brief Configure VDDSDIO, call this API to rise VDDSDIO to 1.9V when VDDSDIO regulator is enabled as 1.8V mode.
*/ */
void bootloader_common_vddsdio_configure(); void bootloader_common_vddsdio_configure();
#ifdef __cplusplus
}
#endif

View file

@ -0,0 +1,71 @@
// Copyright 2018 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 "esp_image_format.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Update the flash id in g_rom_flashchip(global esp_rom_spiflash_chip_t structure).
*
* @return None
*/
void bootloader_flash_update_id();
/**
* @brief Set the flash CS setup and hold time.
*
* @note CS setup time is recomemded to be 1.5T, and CS hold time is recommended to be 2.5T.
* cs_setup = 1, cs_setup_time = 0; cs_hold = 1, cs_hold_time = 1.
*
* @return None
*/
void bootloader_flash_cs_timing_config();
/**
* @brief Configure SPI flash clock.
*
* @note This function only set clock frequency for SPI0.
*
* @param pfhdr Pointer to App image header, from where to fetch flash settings.
*
* @return None
*/
void bootloader_flash_clock_config(const esp_image_header_t* pfhdr);
/**
* @brief Configure SPI flash gpio, include the IO matrix and drive strength configuration.
*
* @param pfhdr Pointer to App image header, from where to fetch flash settings.
*
* @return None
*/
void bootloader_flash_gpio_config(const esp_image_header_t* pfhdr);
/**
* @brief Configure SPI flash read dummy based on different mode and frequency.
*
* @param pfhdr Pointer to App image header, from where to fetch flash settings.
*
* @return None
*/
void bootloader_flash_dummy_config(const esp_image_header_t* pfhdr);
#ifdef __cplusplus
}
#endif

View file

@ -16,6 +16,10 @@
#include <stddef.h> #include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
/** /**
* @brief Enable early entropy source for RNG * @brief Enable early entropy source for RNG
* *
@ -47,3 +51,7 @@ void bootloader_random_disable(void);
* @param length This many bytes of random data will be copied to buffer * @param length This many bytes of random data will be copied to buffer
*/ */
void bootloader_fill_random(void *buffer, size_t length); void bootloader_fill_random(void *buffer, size_t length);
#ifdef __cplusplus
}
#endif

View file

@ -16,6 +16,10 @@
#include <stddef.h> #include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
/** /**
* @brief Check if half-open intervals overlap * @brief Check if half-open intervals overlap
* *
@ -29,6 +33,11 @@ static inline bool bootloader_util_regions_overlap(
const intptr_t start1, const intptr_t end1, const intptr_t start1, const intptr_t end1,
const intptr_t start2, const intptr_t end2) const intptr_t start2, const intptr_t end2)
{ {
return (end1 > start2 && end2 > start1) || assert(end1>start1);
!(end1 <= start2 || end2 <= start1); assert(end2>start2);
return (end1 > start2 && end2 > start1);
} }
#ifdef __cplusplus
}
#endif

View file

@ -0,0 +1,109 @@
// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
/**
* @brief SPI flash mode, used in esp_image_header_t
*/
typedef enum {
ESP_IMAGE_SPI_MODE_QIO, /*!< SPI mode QIO */
ESP_IMAGE_SPI_MODE_QOUT, /*!< SPI mode QOUT */
ESP_IMAGE_SPI_MODE_DIO, /*!< SPI mode DIO */
ESP_IMAGE_SPI_MODE_DOUT, /*!< SPI mode DOUT */
ESP_IMAGE_SPI_MODE_FAST_READ, /*!< SPI mode FAST_READ */
ESP_IMAGE_SPI_MODE_SLOW_READ /*!< SPI mode SLOW_READ */
} esp_image_spi_mode_t;
/**
* @brief SPI flash clock frequency
*/
typedef enum {
ESP_IMAGE_SPI_SPEED_40M, /*!< SPI clock frequency 40 MHz */
ESP_IMAGE_SPI_SPEED_26M, /*!< SPI clock frequency 26 MHz */
ESP_IMAGE_SPI_SPEED_20M, /*!< SPI clock frequency 20 MHz */
ESP_IMAGE_SPI_SPEED_80M = 0xF /*!< SPI clock frequency 80 MHz */
} esp_image_spi_freq_t;
/**
* @brief Supported SPI flash sizes
*/
typedef enum {
ESP_IMAGE_FLASH_SIZE_1MB = 0, /*!< SPI flash size 1 MB */
ESP_IMAGE_FLASH_SIZE_2MB, /*!< SPI flash size 2 MB */
ESP_IMAGE_FLASH_SIZE_4MB, /*!< SPI flash size 4 MB */
ESP_IMAGE_FLASH_SIZE_8MB, /*!< SPI flash size 8 MB */
ESP_IMAGE_FLASH_SIZE_16MB, /*!< SPI flash size 16 MB */
ESP_IMAGE_FLASH_SIZE_MAX /*!< SPI flash size MAX */
} esp_image_flash_size_t;
#define ESP_IMAGE_HEADER_MAGIC 0xE9 /*!< The magic word for the esp_image_header_t structure. */
/**
* @brief Main header of binary image
*/
typedef struct {
uint8_t magic; /*!< Magic word ESP_IMAGE_HEADER_MAGIC */
uint8_t segment_count; /*!< Count of memory segments */
uint8_t spi_mode; /*!< flash read mode (esp_image_spi_mode_t as uint8_t) */
uint8_t spi_speed: 4; /*!< flash frequency (esp_image_spi_freq_t as uint8_t) */
uint8_t spi_size: 4; /*!< flash chip size (esp_image_flash_size_t as uint8_t) */
uint32_t entry_addr; /*!< Entry address */
uint8_t wp_pin; /*!< WP pin when SPI pins set via efuse (read by ROM bootloader,
* the IDF bootloader uses software to configure the WP
* pin and sets this field to 0xEE=disabled) */
uint8_t spi_pin_drv[3]; /*!< Drive settings for the SPI flash pins (read by ROM bootloader) */
uint8_t reserved[11]; /*!< Reserved bytes in ESP32 additional header space, currently unused */
uint8_t hash_appended; /*!< If 1, a SHA256 digest "simple hash" (of the entire image) is appended after the checksum.
* Included in image length. This digest
* is separate to secure boot and only used for detecting corruption.
* For secure boot signed images, the signature
* is appended after this (and the simple hash is included in the signed data). */
} __attribute__((packed)) esp_image_header_t;
/** @cond */
_Static_assert(sizeof(esp_image_header_t) == 24, "binary image header should be 24 bytes");
/** @endcond */
/**
* @brief Header of binary image segment
*/
typedef struct {
uint32_t load_addr; /*!< Address of segment */
uint32_t data_len; /*!< Length of data */
} esp_image_segment_header_t;
#define ESP_IMAGE_MAX_SEGMENTS 16 /*!< Max count of segments in the image. */
#define ESP_APP_DESC_MAGIC_WORD 0xABCD5432 /*!< The magic word for the esp_app_desc structure that is in DROM. */
/**
* @brief Description about application.
*/
typedef struct {
uint32_t magic_word; /*!< Magic word ESP_APP_DESC_MAGIC_WORD */
uint32_t secure_version; /*!< Secure version */
uint32_t reserv1[2]; /*!< reserv1 */
char version[32]; /*!< Application version */
char project_name[32]; /*!< Project name */
char time[16]; /*!< Compile time */
char date[16]; /*!< Compile date*/
char idf_ver[32]; /*!< Version IDF */
uint8_t app_elf_sha256[32]; /*!< sha256 of elf file */
uint32_t reserv2[20]; /*!< reserv2 */
} esp_app_desc_t;
/** @cond */
_Static_assert(sizeof(esp_app_desc_t) == 256, "esp_app_desc_t should be 256 bytes");
/** @endcond */

View file

@ -11,8 +11,7 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#ifndef __ESP32_FLASH_ENCRYPT_H #pragma once
#define __ESP32_FLASH_ENCRYPT_H
#include <stdbool.h> #include <stdbool.h>
#include "esp_attr.h" #include "esp_attr.h"
@ -23,6 +22,18 @@
#include "soc/efuse_periph.h" #include "soc/efuse_periph.h"
#include "sdkconfig.h" #include "sdkconfig.h"
#ifdef __cplusplus
extern "C" {
#endif
/* @brief Flash encryption mode based on efuse values
*/
typedef enum {
ESP_FLASH_ENC_MODE_DISABLED, // flash encryption is not enabled (flash crypt cnt=0)
ESP_FLASH_ENC_MODE_DEVELOPMENT, // flash encryption is enabled but for Development (reflash over UART allowed)
ESP_FLASH_ENC_MODE_RELEASE // flash encryption is enabled for Release (reflash over UART disabled)
} esp_flash_enc_mode_t;
/** /**
* @file esp_partition.h * @file esp_partition.h
* @brief Support functions for flash encryption features * @brief Support functions for flash encryption features
@ -117,8 +128,18 @@ esp_err_t esp_flash_encrypt_region(uint32_t src_addr, size_t data_length);
* is enabled but secure boot is not used. This should protect against * is enabled but secure boot is not used. This should protect against
* serial re-flashing of an unauthorised code in absence of secure boot. * serial re-flashing of an unauthorised code in absence of secure boot.
* *
* @return
*/ */
void esp_flash_write_protect_crypt_cnt(); void esp_flash_write_protect_crypt_cnt();
/** @brief Return the flash encryption mode
*
* The API is called during boot process but can also be called by
* application to check the current flash encryption mode of ESP32
*
* @return
*/
esp_flash_enc_mode_t esp_get_flash_encryption_mode();
#ifdef __cplusplus
}
#endif #endif

View file

@ -103,6 +103,17 @@ inline static __attribute__((deprecated)) esp_err_t esp_partition_table_basic_ve
{ {
return esp_partition_table_verify(partition_table, log_errors, num_partitions); return esp_partition_table_verify(partition_table, log_errors, num_partitions);
} }
/**
* Check whether the region on the main flash is safe to write.
*
* @param addr Start address of the region
* @param size Size of the region
*
* @return true if the region is safe to write, otherwise false.
*/
bool esp_partition_main_flash_region_safe(size_t addr, size_t size);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View file

@ -16,6 +16,11 @@
#include <stdbool.h> #include <stdbool.h>
#include <esp_err.h> #include <esp_err.h>
#include "esp_flash_partitions.h" #include "esp_flash_partitions.h"
#include "esp_app_format.h"
#ifdef __cplusplus
extern "C" {
#endif
#define ESP_ERR_IMAGE_BASE 0x2000 #define ESP_ERR_IMAGE_BASE 0x2000
#define ESP_ERR_IMAGE_FLASH_FAIL (ESP_ERR_IMAGE_BASE + 1) #define ESP_ERR_IMAGE_FLASH_FAIL (ESP_ERR_IMAGE_BASE + 1)
@ -25,91 +30,8 @@
Can be compiled as part of app or bootloader code. Can be compiled as part of app or bootloader code.
*/ */
/* SPI flash mode, used in esp_image_header_t */
typedef enum {
ESP_IMAGE_SPI_MODE_QIO,
ESP_IMAGE_SPI_MODE_QOUT,
ESP_IMAGE_SPI_MODE_DIO,
ESP_IMAGE_SPI_MODE_DOUT,
ESP_IMAGE_SPI_MODE_FAST_READ,
ESP_IMAGE_SPI_MODE_SLOW_READ
} esp_image_spi_mode_t;
/* SPI flash clock frequency */
typedef enum {
ESP_IMAGE_SPI_SPEED_40M,
ESP_IMAGE_SPI_SPEED_26M,
ESP_IMAGE_SPI_SPEED_20M,
ESP_IMAGE_SPI_SPEED_80M = 0xF
} esp_image_spi_freq_t;
/* Supported SPI flash sizes */
typedef enum {
ESP_IMAGE_FLASH_SIZE_1MB = 0,
ESP_IMAGE_FLASH_SIZE_2MB,
ESP_IMAGE_FLASH_SIZE_4MB,
ESP_IMAGE_FLASH_SIZE_8MB,
ESP_IMAGE_FLASH_SIZE_16MB,
ESP_IMAGE_FLASH_SIZE_MAX
} esp_image_flash_size_t;
#define ESP_IMAGE_HEADER_MAGIC 0xE9
/* Main header of binary image */
typedef struct {
uint8_t magic;
uint8_t segment_count;
/* flash read mode (esp_image_spi_mode_t as uint8_t) */
uint8_t spi_mode;
/* flash frequency (esp_image_spi_freq_t as uint8_t) */
uint8_t spi_speed: 4;
/* flash chip size (esp_image_flash_size_t as uint8_t) */
uint8_t spi_size: 4;
uint32_t entry_addr;
/* WP pin when SPI pins set via efuse (read by ROM bootloader, the IDF bootloader uses software to configure the WP
* pin and sets this field to 0xEE=disabled) */
uint8_t wp_pin;
/* Drive settings for the SPI flash pins (read by ROM bootloader) */
uint8_t spi_pin_drv[3];
/* Reserved bytes in ESP32 additional header space, currently unused */
uint8_t reserved[11];
/* If 1, a SHA256 digest "simple hash" (of the entire image) is appended after the checksum. Included in image length. This digest
* is separate to secure boot and only used for detecting corruption. For secure boot signed images, the signature
* is appended after this (and the simple hash is included in the signed data). */
uint8_t hash_appended;
} __attribute__((packed)) esp_image_header_t;
_Static_assert(sizeof(esp_image_header_t) == 24, "binary image header should be 24 bytes");
#define ESP_IMAGE_HASH_LEN 32 /* Length of the appended SHA-256 digest */ #define ESP_IMAGE_HASH_LEN 32 /* Length of the appended SHA-256 digest */
/* Header of binary image segment */
typedef struct {
uint32_t load_addr;
uint32_t data_len;
} esp_image_segment_header_t;
#define ESP_APP_DESC_MAGIC_WORD 0xABCD5432 /*!< The magic word for the esp_app_desc structure that is in DROM. */
/**
* @brief Description about application.
*/
typedef struct {
uint32_t magic_word; /*!< Magic word ESP_APP_DESC_MAGIC_WORD */
uint32_t secure_version; /*!< Secure version */
uint32_t reserv1[2]; /*!< --- */
char version[32]; /*!< Application version */
char project_name[32]; /*!< Project name */
char time[16]; /*!< Compile time */
char date[16]; /*!< Compile date*/
char idf_ver[32]; /*!< Version IDF */
uint8_t app_elf_sha256[32]; /*!< sha256 of elf file */
uint32_t reserv2[20]; /*!< --- */
} esp_app_desc_t;
_Static_assert(sizeof(esp_app_desc_t) == 256, "esp_app_desc_t should be 256 bytes");
#define ESP_IMAGE_MAX_SEGMENTS 16
/* Structure to hold on-flash image metadata */ /* Structure to hold on-flash image metadata */
typedef struct { typedef struct {
uint32_t start_addr; /* Start address of image */ uint32_t start_addr; /* Start address of image */
@ -240,3 +162,7 @@ typedef struct {
uint32_t irom_load_addr; uint32_t irom_load_addr;
uint32_t irom_size; uint32_t irom_size;
} esp_image_flash_mapping_t; } esp_image_flash_mapping_t;
#ifdef __cplusplus
}
#endif

View file

@ -138,7 +138,6 @@ typedef struct {
uint8_t digest[64]; uint8_t digest[64];
} esp_secure_boot_iv_digest_t; } esp_secure_boot_iv_digest_t;
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View file

@ -30,6 +30,13 @@
bootloader_support components only. bootloader_support components only.
*/ */
/**
* @brief Get number of free pages
*
* @return Number of free pages
*/
uint32_t bootloader_mmap_get_free_pages();
/** /**
* @brief Map a region of flash to data memory * @brief Map a region of flash to data memory
* *

View file

@ -28,6 +28,11 @@ static const char *TAG = "bootloader_mmap";
static spi_flash_mmap_handle_t map; static spi_flash_mmap_handle_t map;
uint32_t bootloader_mmap_get_free_pages()
{
return spi_flash_mmap_get_free_pages(SPI_FLASH_MMAP_DATA);
}
const void *bootloader_mmap(uint32_t src_addr, uint32_t size) const void *bootloader_mmap(uint32_t src_addr, uint32_t size)
{ {
if (map) { if (map) {
@ -104,6 +109,7 @@ static const char *TAG = "bootloader_flash";
#define MMU_BLOCK0_VADDR SOC_DROM_LOW #define MMU_BLOCK0_VADDR SOC_DROM_LOW
#define MMU_SIZE (0x320000) #define MMU_SIZE (0x320000)
#define MMU_BLOCK50_VADDR (MMU_BLOCK0_VADDR + MMU_SIZE) #define MMU_BLOCK50_VADDR (MMU_BLOCK0_VADDR + MMU_SIZE)
#define FLASH_READ_VADDR MMU_BLOCK50_VADDR
#elif CONFIG_IDF_TARGET_ESP32S2BETA #elif CONFIG_IDF_TARGET_ESP32S2BETA
/* Use first 63 blocks in MMU for bootloader_mmap, /* Use first 63 blocks in MMU for bootloader_mmap,
63th block for bootloader_flash_read 63th block for bootloader_flash_read
@ -111,13 +117,25 @@ static const char *TAG = "bootloader_flash";
#define MMU_BLOCK0_VADDR SOC_DROM_LOW #define MMU_BLOCK0_VADDR SOC_DROM_LOW
#define MMU_SIZE (0x3f0000) #define MMU_SIZE (0x3f0000)
#define MMU_BLOCK63_VADDR (MMU_BLOCK0_VADDR + MMU_SIZE) #define MMU_BLOCK63_VADDR (MMU_BLOCK0_VADDR + MMU_SIZE)
#define FLASH_READ_VADDR MMU_BLOCK63_VADDR
#endif #endif
#define MMU_FREE_PAGES (MMU_SIZE / FLASH_BLOCK_SIZE)
static bool mapped; static bool mapped;
// Current bootloader mapping (ab)used for bootloader_read() // Current bootloader mapping (ab)used for bootloader_read()
static uint32_t current_read_mapping = UINT32_MAX; static uint32_t current_read_mapping = UINT32_MAX;
uint32_t bootloader_mmap_get_free_pages()
{
/**
* Allow mapping up to 50 of the 51 available MMU blocks (last one used for reads)
* Since, bootloader_mmap function below assumes it to be 0x320000 (50 pages), we can safely do this.
*/
return MMU_FREE_PAGES;
}
const void *bootloader_mmap(uint32_t src_addr, uint32_t size) const void *bootloader_mmap(uint32_t src_addr, uint32_t size)
{ {
if (mapped) { if (mapped) {
@ -235,9 +253,9 @@ static esp_err_t bootloader_flash_read_allow_decrypt(size_t src_addr, void *dest
#endif #endif
ESP_LOGD(TAG, "mmu set block paddr=0x%08x (was 0x%08x)", map_at, current_read_mapping); ESP_LOGD(TAG, "mmu set block paddr=0x%08x (was 0x%08x)", map_at, current_read_mapping);
#if CONFIG_IDF_TARGET_ESP32 #if CONFIG_IDF_TARGET_ESP32
int e = cache_flash_mmu_set(0, 0, MMU_BLOCK50_VADDR, map_at, 64, 1); int e = cache_flash_mmu_set(0, 0, FLASH_READ_VADDR, map_at, 64, 1);
#elif CONFIG_IDF_TARGET_ESP32S2BETA #elif CONFIG_IDF_TARGET_ESP32S2BETA
int e = Cache_Ibus_MMU_Set(DPORT_MMU_ACCESS_FLASH, MMU_BLOCK63_VADDR, map_at, 64, 1, 0); int e = Cache_Ibus_MMU_Set(DPORT_MMU_ACCESS_FLASH, FLASH_READ_VADDR, map_at, 64, 1, 0);
#endif #endif
if (e != 0) { if (e != 0) {
ESP_LOGE(TAG, "cache_flash_mmu_set failed: %d\n", e); ESP_LOGE(TAG, "cache_flash_mmu_set failed: %d\n", e);
@ -255,11 +273,7 @@ static esp_err_t bootloader_flash_read_allow_decrypt(size_t src_addr, void *dest
Cache_Resume_ICache(autoload); Cache_Resume_ICache(autoload);
#endif #endif
} }
#if CONFIG_IDF_TARGET_ESP32 map_ptr = (uint32_t *)(FLASH_READ_VADDR + (word_src - map_at));
map_ptr = (uint32_t *)(MMU_BLOCK50_VADDR + (word_src - map_at));
#elif CONFIG_IDF_TARGET_ESP32S2BETA
map_ptr = (uint32_t *)(MMU_BLOCK63_VADDR + (word_src - map_at));
#endif
dest_words[word] = *map_ptr; dest_words[word] = *map_ptr;
} }
return ESP_OK; return ESP_OK;

View file

@ -70,6 +70,7 @@
#include "bootloader_common.h" #include "bootloader_common.h"
#include "bootloader_clock.h" #include "bootloader_clock.h"
#include "bootloader_common.h" #include "bootloader_common.h"
#include "bootloader_flash_config.h"
#include "flash_qio_mode.h" #include "flash_qio_mode.h"
@ -83,7 +84,7 @@ static const char *TAG = "boot";
static esp_err_t bootloader_main(); static esp_err_t bootloader_main();
static void print_flash_info(const esp_image_header_t *pfhdr); static void print_flash_info(const esp_image_header_t *pfhdr);
static void update_flash_config(const esp_image_header_t *pfhdr); static void update_flash_config(const esp_image_header_t *pfhdr);
static void flash_gpio_configure(const esp_image_header_t *pfhdr); static void bootloader_init_flash_configure(const esp_image_header_t* pfhdr);
static void uart_console_configure(void); static void uart_console_configure(void);
static void wdt_reset_check(void); static void wdt_reset_check(void);
@ -169,7 +170,7 @@ static esp_err_t bootloader_main()
ESP_LOGE(TAG, "failed to load bootloader header!"); ESP_LOGE(TAG, "failed to load bootloader header!");
return ESP_FAIL; return ESP_FAIL;
} }
flash_gpio_configure(&fhdr); bootloader_init_flash_configure(&fhdr);
#ifdef CONFIG_IDF_TARGET_ESP32 #ifdef CONFIG_IDF_TARGET_ESP32
int rated_freq = bootloader_clock_get_rated_freq_mhz(); int rated_freq = bootloader_clock_get_rated_freq_mhz();
@ -358,134 +359,11 @@ static void print_flash_info(const esp_image_header_t *phdr)
#endif #endif
} }
#if CONFIG_IDF_TARGET_ESP32 static void IRAM_ATTR bootloader_init_flash_configure(const esp_image_header_t* pfhdr)
#define FLASH_CLK_IO 6
#define FLASH_CS_IO 11
#define FLASH_SPIQ_IO 7
#define FLASH_SPID_IO 8
#define FLASH_SPIWP_IO 10
#define FLASH_SPIHD_IO 9
#endif
#if CONFIG_IDF_TARGET_ESP32
#define FLASH_IO_MATRIX_DUMMY_40M 1
#define FLASH_IO_MATRIX_DUMMY_80M 2
#elif CONFIG_IDF_TARGET_ESP32S2BETA
#define FLASH_IO_MATRIX_DUMMY_40M 0
#define FLASH_IO_MATRIX_DUMMY_80M 0
#endif
#define FLASH_IO_DRIVE_GD_WITH_1V8PSRAM 3
/*
* Bootloader reads SPI configuration from bin header, so that
* the burning configuration can be different with compiling configuration.
*/
static void IRAM_ATTR flash_gpio_configure(const esp_image_header_t *pfhdr)
{ {
int spi_cache_dummy = 0; bootloader_flash_gpio_config(pfhdr);
int drv = 2; bootloader_flash_dummy_config(pfhdr);
switch (pfhdr->spi_mode) { bootloader_flash_cs_timing_config();
case ESP_IMAGE_SPI_MODE_QIO:
spi_cache_dummy = SPI0_R_DIO_DUMMY_CYCLELEN;
break;
case ESP_IMAGE_SPI_MODE_DIO:
spi_cache_dummy = SPI0_R_DIO_DUMMY_CYCLELEN; //qio 3
break;
case ESP_IMAGE_SPI_MODE_QOUT:
case ESP_IMAGE_SPI_MODE_DOUT:
default:
spi_cache_dummy = SPI0_R_FAST_DUMMY_CYCLELEN;
break;
}
/* dummy_len_plus values defined in ROM for SPI flash configuration */
extern uint8_t g_rom_spiflash_dummy_len_plus[];
switch (pfhdr->spi_speed) {
case ESP_IMAGE_SPI_SPEED_80M:
g_rom_spiflash_dummy_len_plus[0] = FLASH_IO_MATRIX_DUMMY_80M;
g_rom_spiflash_dummy_len_plus[1] = FLASH_IO_MATRIX_DUMMY_80M;
#if CONFIG_IDF_TARGET_ESP32
SET_PERI_REG_BITS(SPI_USER1_REG(0), SPI_USR_DUMMY_CYCLELEN_V, spi_cache_dummy + FLASH_IO_MATRIX_DUMMY_80M,
SPI_USR_DUMMY_CYCLELEN_S); //DUMMY
#elif CONFIG_IDF_TARGET_ESP32S2BETA
SET_PERI_REG_BITS(SPI_MEM_USER1_REG(0), SPI_MEM_USR_DUMMY_CYCLELEN_V, spi_cache_dummy + FLASH_IO_MATRIX_DUMMY_80M,
SPI_MEM_USR_DUMMY_CYCLELEN_S); //DUMMY
#endif
drv = 3;
break;
case ESP_IMAGE_SPI_SPEED_40M:
g_rom_spiflash_dummy_len_plus[0] = FLASH_IO_MATRIX_DUMMY_40M;
g_rom_spiflash_dummy_len_plus[1] = FLASH_IO_MATRIX_DUMMY_40M;
#if CONFIG_IDF_TARGET_ESP32
SET_PERI_REG_BITS(SPI_USER1_REG(0), SPI_USR_DUMMY_CYCLELEN_V, spi_cache_dummy + FLASH_IO_MATRIX_DUMMY_40M,
SPI_USR_DUMMY_CYCLELEN_S); //DUMMY
#elif CONFIG_IDF_TARGET_ESP32S2BETA
SET_PERI_REG_BITS(SPI_MEM_USER1_REG(0), SPI_MEM_USR_DUMMY_CYCLELEN_V, spi_cache_dummy + FLASH_IO_MATRIX_DUMMY_40M,
SPI_MEM_USR_DUMMY_CYCLELEN_S); //DUMMY
#endif
break;
default:
break;
}
#if CONFIG_IDF_TARGET_ESP32
uint32_t chip_ver = REG_GET_FIELD(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_VER_PKG);
uint32_t pkg_ver = chip_ver & 0x7;
if (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32D2WDQ5) {
// For ESP32D2WD the SPI pins are already configured
// flash clock signal should come from IO MUX.
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK);
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, drv, FUN_DRV_S);
} else if (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD2) {
// For ESP32PICOD2 the SPI pins are already configured
// flash clock signal should come from IO MUX.
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK);
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, drv, FUN_DRV_S);
} else if (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD4) {
// For ESP32PICOD4 the SPI pins are already configured
// flash clock signal should come from IO MUX.
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK);
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, drv, FUN_DRV_S);
} else {
const uint32_t spiconfig = ets_efuse_get_spiconfig();
if (spiconfig == EFUSE_SPICONFIG_SPI_DEFAULTS) {
gpio_matrix_out(FLASH_CS_IO, SPICS0_OUT_IDX, 0, 0);
gpio_matrix_out(FLASH_SPIQ_IO, SPIQ_OUT_IDX, 0, 0);
gpio_matrix_in(FLASH_SPIQ_IO, SPIQ_IN_IDX, 0);
gpio_matrix_out(FLASH_SPID_IO, SPID_OUT_IDX, 0, 0);
gpio_matrix_in(FLASH_SPID_IO, SPID_IN_IDX, 0);
gpio_matrix_out(FLASH_SPIWP_IO, SPIWP_OUT_IDX, 0, 0);
gpio_matrix_in(FLASH_SPIWP_IO, SPIWP_IN_IDX, 0);
gpio_matrix_out(FLASH_SPIHD_IO, SPIHD_OUT_IDX, 0, 0);
gpio_matrix_in(FLASH_SPIHD_IO, SPIHD_IN_IDX, 0);
//select pin function gpio
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA0_U, PIN_FUNC_GPIO);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA1_U, PIN_FUNC_GPIO);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA2_U, PIN_FUNC_GPIO);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA3_U, PIN_FUNC_GPIO);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CMD_U, PIN_FUNC_GPIO);
// flash clock signal should come from IO MUX.
// set drive ability for clock
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK);
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, drv, FUN_DRV_S);
#if CONFIG_SPIRAM_TYPE_ESPPSRAM32
uint32_t flash_id = g_rom_flashchip.device_id;
if (flash_id == FLASH_ID_GD25LQ32C) {
// Set drive ability for 1.8v flash in 80Mhz.
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_DATA0_U, FUN_DRV, 3, FUN_DRV_S);
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_DATA1_U, FUN_DRV, 3, FUN_DRV_S);
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_DATA2_U, FUN_DRV, 3, FUN_DRV_S);
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_DATA3_U, FUN_DRV, 3, FUN_DRV_S);
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CMD_U, FUN_DRV, 3, FUN_DRV_S);
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, 3, FUN_DRV_S);
}
#endif
}
}
#elif CONFIG_IDF_TARGET_ESP32S2BETA
bootloader_configure_spi_pins(drv);
#endif
} }
static void uart_console_configure(void) static void uart_console_configure(void)

View file

@ -0,0 +1,165 @@
// Copyright 2018 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 <stdbool.h>
#include <assert.h>
#include "string.h"
#include "sdkconfig.h"
#include "esp_err.h"
#include "esp_log.h"
#include "esp32/rom/gpio.h"
#include "esp32/rom/spi_flash.h"
#include "esp32/rom/efuse.h"
#include "soc/gpio_periph.h"
#include "soc/efuse_reg.h"
#include "soc/spi_reg.h"
#include "soc/spi_caps.h"
#include "flash_qio_mode.h"
#include "bootloader_flash_config.h"
void bootloader_flash_update_id()
{
g_rom_flashchip.device_id = bootloader_read_flash_id();
}
void IRAM_ATTR bootloader_flash_cs_timing_config()
{
SET_PERI_REG_MASK(SPI_USER_REG(0), SPI_CS_HOLD_M | SPI_CS_SETUP_M);
SET_PERI_REG_BITS(SPI_CTRL2_REG(0), SPI_HOLD_TIME_V, 1, SPI_HOLD_TIME_S);
SET_PERI_REG_BITS(SPI_CTRL2_REG(0), SPI_SETUP_TIME_V, 0, SPI_SETUP_TIME_S);
SET_PERI_REG_MASK(SPI_USER_REG(1), SPI_CS_HOLD_M | SPI_CS_SETUP_M);
SET_PERI_REG_BITS(SPI_CTRL2_REG(1), SPI_HOLD_TIME_V, 1, SPI_HOLD_TIME_S);
SET_PERI_REG_BITS(SPI_CTRL2_REG(1), SPI_SETUP_TIME_V, 0, SPI_SETUP_TIME_S);
}
void IRAM_ATTR bootloader_flash_clock_config(const esp_image_header_t* pfhdr)
{
uint32_t spi_clk_div = 0;
switch (pfhdr->spi_speed) {
case ESP_IMAGE_SPI_SPEED_80M:
spi_clk_div = 1;
break;
case ESP_IMAGE_SPI_SPEED_40M:
spi_clk_div = 2;
break;
case ESP_IMAGE_SPI_SPEED_26M:
spi_clk_div = 3;
break;
case ESP_IMAGE_SPI_SPEED_20M:
spi_clk_div = 4;
break;
default:
break;
}
esp_rom_spiflash_config_clk(spi_clk_div, 0);
}
void IRAM_ATTR bootloader_flash_gpio_config(const esp_image_header_t* pfhdr)
{
uint32_t drv = 2;
if (pfhdr->spi_speed == ESP_IMAGE_SPI_SPEED_80M) {
drv = 3;
}
uint32_t chip_ver = REG_GET_FIELD(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_VER_PKG);
uint32_t pkg_ver = chip_ver & 0x7;
if (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32D2WDQ5) {
// For ESP32D2WD the SPI pins are already configured
// flash clock signal should come from IO MUX.
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK);
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, drv, FUN_DRV_S);
} else if (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD2) {
// For ESP32PICOD2 the SPI pins are already configured
// flash clock signal should come from IO MUX.
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK);
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, drv, FUN_DRV_S);
} else if (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD4) {
// For ESP32PICOD4 the SPI pins are already configured
// flash clock signal should come from IO MUX.
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK);
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, drv, FUN_DRV_S);
} else {
const uint32_t spiconfig = ets_efuse_get_spiconfig();
if (spiconfig == EFUSE_SPICONFIG_SPI_DEFAULTS) {
gpio_matrix_out(SPI_IOMUX_PIN_NUM_CS, SPICS0_OUT_IDX, 0, 0);
gpio_matrix_out(SPI_IOMUX_PIN_NUM_MISO, SPIQ_OUT_IDX, 0, 0);
gpio_matrix_in(SPI_IOMUX_PIN_NUM_MISO, SPIQ_IN_IDX, 0);
gpio_matrix_out(SPI_IOMUX_PIN_NUM_MOSI, SPID_OUT_IDX, 0, 0);
gpio_matrix_in(SPI_IOMUX_PIN_NUM_MOSI, SPID_IN_IDX, 0);
gpio_matrix_out(SPI_IOMUX_PIN_NUM_WP, SPIWP_OUT_IDX, 0, 0);
gpio_matrix_in(SPI_IOMUX_PIN_NUM_WP, SPIWP_IN_IDX, 0);
gpio_matrix_out(SPI_IOMUX_PIN_NUM_HD, SPIHD_OUT_IDX, 0, 0);
gpio_matrix_in(SPI_IOMUX_PIN_NUM_HD, SPIHD_IN_IDX, 0);
//select pin function gpio
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA0_U, PIN_FUNC_GPIO);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA1_U, PIN_FUNC_GPIO);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA2_U, PIN_FUNC_GPIO);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA3_U, PIN_FUNC_GPIO);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CMD_U, PIN_FUNC_GPIO);
// flash clock signal should come from IO MUX.
// set drive ability for clock
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK);
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, drv, FUN_DRV_S);
uint32_t flash_id = g_rom_flashchip.device_id;
if (flash_id == FLASH_ID_GD25LQ32C) {
// Set drive ability for 1.8v flash in 80Mhz.
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_DATA0_U, FUN_DRV, 3, FUN_DRV_S);
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_DATA1_U, FUN_DRV, 3, FUN_DRV_S);
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_DATA2_U, FUN_DRV, 3, FUN_DRV_S);
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_DATA3_U, FUN_DRV, 3, FUN_DRV_S);
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CMD_U, FUN_DRV, 3, FUN_DRV_S);
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, 3, FUN_DRV_S);
}
}
}
}
void IRAM_ATTR bootloader_flash_dummy_config(const esp_image_header_t* pfhdr)
{
int spi_cache_dummy = 0;
uint32_t modebit = READ_PERI_REG(SPI_CTRL_REG(0));
if (modebit & SPI_FASTRD_MODE) {
if (modebit & SPI_FREAD_QIO) { //SPI mode is QIO
spi_cache_dummy = SPI0_R_QIO_DUMMY_CYCLELEN;
} else if (modebit & SPI_FREAD_DIO) { //SPI mode is DIO
spi_cache_dummy = SPI0_R_DIO_DUMMY_CYCLELEN;
SET_PERI_REG_BITS(SPI_USER1_REG(0), SPI_USR_ADDR_BITLEN_V, SPI0_R_DIO_ADDR_BITSLEN, SPI_USR_ADDR_BITLEN_S);
} else if(modebit & (SPI_FREAD_QUAD | SPI_FREAD_DUAL)) { //SPI mode is QOUT or DIO
spi_cache_dummy = SPI0_R_FAST_DUMMY_CYCLELEN;
}
}
extern uint8_t g_rom_spiflash_dummy_len_plus[];
switch (pfhdr->spi_speed) {
case ESP_IMAGE_SPI_SPEED_80M:
g_rom_spiflash_dummy_len_plus[0] = ESP_ROM_SPIFLASH_DUMMY_LEN_PLUS_80M;
g_rom_spiflash_dummy_len_plus[1] = ESP_ROM_SPIFLASH_DUMMY_LEN_PLUS_80M;
break;
case ESP_IMAGE_SPI_SPEED_40M:
g_rom_spiflash_dummy_len_plus[0] = ESP_ROM_SPIFLASH_DUMMY_LEN_PLUS_40M;
g_rom_spiflash_dummy_len_plus[1] = ESP_ROM_SPIFLASH_DUMMY_LEN_PLUS_40M;
break;
case ESP_IMAGE_SPI_SPEED_26M:
case ESP_IMAGE_SPI_SPEED_20M:
g_rom_spiflash_dummy_len_plus[0] = ESP_ROM_SPIFLASH_DUMMY_LEN_PLUS_20M;
g_rom_spiflash_dummy_len_plus[1] = ESP_ROM_SPIFLASH_DUMMY_LEN_PLUS_20M;
break;
default:
break;
}
SET_PERI_REG_BITS(SPI_USER1_REG(0), SPI_USR_DUMMY_CYCLELEN_V, spi_cache_dummy + g_rom_spiflash_dummy_len_plus[0],
SPI_USR_DUMMY_CYCLELEN_S);
}

View file

@ -27,6 +27,12 @@
#include "esp32/rom/cache.h" #include "esp32/rom/cache.h"
#include "esp32/rom/spi_flash.h" /* TODO: Remove this */ #include "esp32/rom/spi_flash.h" /* TODO: Remove this */
/* This file implements FLASH ENCRYPTION related APIs to perform
* various operations such as programming necessary flash encryption
* eFuses, detect whether flash encryption is enabled (by reading eFuse)
* and if required encrypt the partitions in flash memory
*/
static const char *TAG = "flash_encrypt"; static const char *TAG = "flash_encrypt";
/* Static functions for stages of flash encryption */ /* Static functions for stages of flash encryption */
@ -203,7 +209,13 @@ static esp_err_t encrypt_flash_contents(uint32_t flash_crypt_cnt, bool flash_cry
/* ffs_inv shouldn't be zero, as zero implies flash_crypt_cnt == EFUSE_RD_FLASH_CRYPT_CNT (0x7F) */ /* ffs_inv shouldn't be zero, as zero implies flash_crypt_cnt == EFUSE_RD_FLASH_CRYPT_CNT (0x7F) */
uint32_t new_flash_crypt_cnt = flash_crypt_cnt + (1 << (ffs_inv - 1)); uint32_t new_flash_crypt_cnt = flash_crypt_cnt + (1 << (ffs_inv - 1));
ESP_LOGD(TAG, "FLASH_CRYPT_CNT 0x%x -> 0x%x", flash_crypt_cnt, new_flash_crypt_cnt); ESP_LOGD(TAG, "FLASH_CRYPT_CNT 0x%x -> 0x%x", flash_crypt_cnt, new_flash_crypt_cnt);
REG_SET_FIELD(EFUSE_BLK0_WDATA0_REG, EFUSE_FLASH_CRYPT_CNT, new_flash_crypt_cnt); uint32_t wdata0_reg = ((new_flash_crypt_cnt & EFUSE_FLASH_CRYPT_CNT) << EFUSE_FLASH_CRYPT_CNT_S);
#ifdef CONFIG_SECURE_FLASH_ENCRYPTION_MODE_RELEASE
ESP_LOGI(TAG, "Write protecting FLASH_CRYPT_CNT eFuse");
wdata0_reg |= EFUSE_WR_DIS_FLASH_CRYPT_CNT;
#endif
REG_WRITE(EFUSE_BLK0_WDATA0_REG, wdata0_reg);
esp_efuse_burn_new_values(); esp_efuse_burn_new_values();
ESP_LOGI(TAG, "Flash encryption completed"); ESP_LOGI(TAG, "Flash encryption completed");
@ -338,13 +350,3 @@ esp_err_t esp_flash_encrypt_region(uint32_t src_addr, size_t data_length)
ESP_LOGE(TAG, "flash operation failed: 0x%x", err); ESP_LOGE(TAG, "flash operation failed: 0x%x", err);
return err; return err;
} }
void esp_flash_write_protect_crypt_cnt()
{
uint32_t efuse_blk0 = REG_READ(EFUSE_BLK0_RDATA0_REG);
bool flash_crypt_wr_dis = efuse_blk0 & EFUSE_WR_DIS_FLASH_CRYPT_CNT;
if(!flash_crypt_wr_dis) {
REG_WRITE(EFUSE_BLK0_WDATA0_REG, EFUSE_WR_DIS_FLASH_CRYPT_CNT);
esp_efuse_burn_new_values();
}
}

View file

@ -21,7 +21,7 @@
#include "esp32/rom/sha.h" #include "esp32/rom/sha.h"
#include "uECC.h" #include "uECC.h"
typedef SHA_CTX sha_context; #include <sys/param.h>
static const char *TAG = "secure_boot"; static const char *TAG = "secure_boot";
@ -32,6 +32,9 @@ extern const uint8_t signature_verification_key_end[] asm("_binary_signature_ver
#define DIGEST_LEN 32 #define DIGEST_LEN 32
/* Mmap source address mask */
#define MMAP_ALIGNED_MASK 0x0000FFFF
esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length) esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length)
{ {
uint8_t digest[DIGEST_LEN]; uint8_t digest[DIGEST_LEN];
@ -40,21 +43,44 @@ esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length)
ESP_LOGD(TAG, "verifying signature src_addr 0x%x length 0x%x", src_addr, length); ESP_LOGD(TAG, "verifying signature src_addr 0x%x length 0x%x", src_addr, length);
data = bootloader_mmap(src_addr, length + sizeof(esp_secure_boot_sig_block_t)); bootloader_sha256_handle_t handle = bootloader_sha256_start();
if (data == NULL) {
ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", src_addr, length + sizeof(esp_secure_boot_sig_block_t)); uint32_t free_page_count = bootloader_mmap_get_free_pages();
ESP_LOGD(TAG, "free data page_count 0x%08x", free_page_count);
int32_t data_len_remain = length;
uint32_t data_addr = src_addr;
while (data_len_remain > 0) {
uint32_t offset_page = ((data_addr & MMAP_ALIGNED_MASK) != 0) ? 1 : 0;
/* Data we could map in case we are not aligned to PAGE boundary is one page size lesser. */
uint32_t data_len = MIN(data_len_remain, ((free_page_count - offset_page) * SPI_FLASH_MMU_PAGE_SIZE));
data = (const uint8_t *) bootloader_mmap(data_addr, data_len);
if(!data) {
ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", data_addr, data_len);
bootloader_sha256_finish(handle, NULL);
return ESP_FAIL; return ESP_FAIL;
} }
bootloader_sha256_data(handle, data, data_len);
bootloader_munmap(data);
// Calculate digest of main image data_addr += data_len;
bootloader_sha256_handle_t handle = bootloader_sha256_start(); data_len_remain -= data_len;
bootloader_sha256_data(handle, data, length); }
/* Done! Get the digest */
bootloader_sha256_finish(handle, digest); bootloader_sha256_finish(handle, digest);
// Map the signature block and verify the signature // Map the signature block
sigblock = (const esp_secure_boot_sig_block_t *)(data + length); sigblock = (const esp_secure_boot_sig_block_t *) bootloader_mmap(src_addr + length, sizeof(esp_secure_boot_sig_block_t));
if(!sigblock) {
ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", src_addr + length, sizeof(esp_secure_boot_sig_block_t));
return ESP_FAIL;
}
// Verify the signature
esp_err_t err = esp_secure_boot_verify_signature_block(sigblock, digest); esp_err_t err = esp_secure_boot_verify_signature_block(sigblock, digest);
bootloader_munmap(data); // Unmap
bootloader_munmap(sigblock);
return err; return err;
} }

View file

@ -0,0 +1,109 @@
// Copyright 2019 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <stdbool.h>
#include <assert.h>
#include "string.h"
#include "sdkconfig.h"
#include "esp_err.h"
#include "esp_log.h"
#include "esp32/rom/gpio.h"
#include "esp32/rom/spi_flash.h"
#include "esp32/rom/efuse.h"
#include "soc/gpio_periph.h"
#include "soc/efuse_reg.h"
#include "soc/spi_reg.h"
#include "soc/spi_caps.h"
#include "flash_qio_mode.h"
#include "bootloader_flash_config.h"
void bootloader_flash_update_id()
{
g_rom_flashchip.device_id = bootloader_read_flash_id();
}
void IRAM_ATTR bootloader_flash_cs_timing_config()
{
SET_PERI_REG_MASK(SPI_USER_REG(0), SPI_CS_HOLD_M | SPI_CS_SETUP_M);
SET_PERI_REG_BITS(SPI_CTRL2_REG(0), SPI_HOLD_TIME_V, 1, SPI_HOLD_TIME_S);
SET_PERI_REG_BITS(SPI_CTRL2_REG(0), SPI_SETUP_TIME_V, 0, SPI_SETUP_TIME_S);
SET_PERI_REG_MASK(SPI_USER_REG(1), SPI_CS_HOLD_M | SPI_CS_SETUP_M);
SET_PERI_REG_BITS(SPI_CTRL2_REG(1), SPI_HOLD_TIME_V, 1, SPI_HOLD_TIME_S);
SET_PERI_REG_BITS(SPI_CTRL2_REG(1), SPI_SETUP_TIME_V, 0, SPI_SETUP_TIME_S);
}
void IRAM_ATTR bootloader_flash_clock_config(const esp_image_header_t* pfhdr)
{
uint32_t spi_clk_div = 0;
switch (pfhdr->spi_speed) {
case ESP_IMAGE_SPI_SPEED_80M:
spi_clk_div = 1;
break;
case ESP_IMAGE_SPI_SPEED_40M:
spi_clk_div = 2;
break;
case ESP_IMAGE_SPI_SPEED_26M:
spi_clk_div = 3;
break;
case ESP_IMAGE_SPI_SPEED_20M:
spi_clk_div = 4;
break;
default:
break;
}
esp_rom_spiflash_config_clk(spi_clk_div, 0);
}
void IRAM_ATTR bootloader_flash_gpio_config(const esp_image_header_t* pfhdr)
{
}
void IRAM_ATTR bootloader_flash_dummy_config(const esp_image_header_t* pfhdr)
{
int spi_cache_dummy = 0;
uint32_t modebit = READ_PERI_REG(SPI_CTRL_REG(0));
if (modebit & SPI_FASTRD_MODE) {
if (modebit & SPI_FREAD_QIO) { //SPI mode is QIO
spi_cache_dummy = SPI0_R_QIO_DUMMY_CYCLELEN;
} else if (modebit & SPI_FREAD_DIO) { //SPI mode is DIO
spi_cache_dummy = SPI0_R_DIO_DUMMY_CYCLELEN;
SET_PERI_REG_BITS(SPI_USER1_REG(0), SPI_USR_ADDR_BITLEN_V, SPI0_R_DIO_ADDR_BITSLEN, SPI_USR_ADDR_BITLEN_S);
} else if(modebit & (SPI_FREAD_QUAD | SPI_FREAD_DUAL)) { //SPI mode is QOUT or DIO
spi_cache_dummy = SPI0_R_FAST_DUMMY_CYCLELEN;
}
}
extern uint8_t g_rom_spiflash_dummy_len_plus[];
switch (pfhdr->spi_speed) {
case ESP_IMAGE_SPI_SPEED_80M:
g_rom_spiflash_dummy_len_plus[0] = ESP_ROM_SPIFLASH_DUMMY_LEN_PLUS_80M;
g_rom_spiflash_dummy_len_plus[1] = ESP_ROM_SPIFLASH_DUMMY_LEN_PLUS_80M;
break;
case ESP_IMAGE_SPI_SPEED_40M:
g_rom_spiflash_dummy_len_plus[0] = ESP_ROM_SPIFLASH_DUMMY_LEN_PLUS_40M;
g_rom_spiflash_dummy_len_plus[1] = ESP_ROM_SPIFLASH_DUMMY_LEN_PLUS_40M;
break;
case ESP_IMAGE_SPI_SPEED_26M:
case ESP_IMAGE_SPI_SPEED_20M:
g_rom_spiflash_dummy_len_plus[0] = ESP_ROM_SPIFLASH_DUMMY_LEN_PLUS_20M;
g_rom_spiflash_dummy_len_plus[1] = ESP_ROM_SPIFLASH_DUMMY_LEN_PLUS_20M;
break;
default:
break;
}
SET_PERI_REG_BITS(SPI_MEM_USER1_REG(0), SPI_MEM_USR_DUMMY_CYCLELEN_V, spi_cache_dummy + FLASH_IO_MATRIX_DUMMY_80M,
SPI_MEM_USR_DUMMY_CYCLELEN_S); //DUMMY
}

View file

@ -380,24 +380,22 @@ static esp_err_t process_segment(int index, uint32_t flash_addr, esp_image_segme
} }
#endif // BOOTLOADER_BUILD #endif // BOOTLOADER_BUILD
#ifndef BOOTLOADER_BUILD uint32_t free_page_count = bootloader_mmap_get_free_pages();
uint32_t free_page_count = spi_flash_mmap_get_free_pages(SPI_FLASH_MMAP_DATA);
ESP_LOGD(TAG, "free data page_count 0x%08x", free_page_count); ESP_LOGD(TAG, "free data page_count 0x%08x", free_page_count);
uint32_t offset_page = 0;
while (data_len >= free_page_count * SPI_FLASH_MMU_PAGE_SIZE) { int32_t data_len_remain = data_len;
offset_page = ((data_addr & MMAP_ALIGNED_MASK) != 0) ? 1 : 0; while (data_len_remain > 0) {
err = process_segment_data(load_addr, data_addr, (free_page_count - offset_page) * SPI_FLASH_MMU_PAGE_SIZE, do_load, sha_handle, checksum); uint32_t offset_page = ((data_addr & MMAP_ALIGNED_MASK) != 0) ? 1 : 0;
if (err != ESP_OK) { /* Data we could map in case we are not aligned to PAGE boundary is one page size lesser. */
return err; data_len = MIN(data_len_remain, ((free_page_count - offset_page) * SPI_FLASH_MMU_PAGE_SIZE));
}
data_addr += (free_page_count - offset_page) * SPI_FLASH_MMU_PAGE_SIZE;
data_len -= (free_page_count - offset_page) * SPI_FLASH_MMU_PAGE_SIZE;
}
#endif
err = process_segment_data(load_addr, data_addr, data_len, do_load, sha_handle, checksum); err = process_segment_data(load_addr, data_addr, data_len, do_load, sha_handle, checksum);
if (err != ESP_OK) { if (err != ESP_OK) {
return err; return err;
} }
data_addr += data_len;
data_len_remain -= data_len;
}
return ESP_OK; return ESP_OK;
err: err:

View file

@ -0,0 +1,52 @@
// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <strings.h>
#include "esp_efuse.h"
#include "esp_efuse_table.h"
#include "esp_flash_encrypt.h"
void esp_flash_write_protect_crypt_cnt()
{
uint8_t flash_crypt_cnt_wr_dis = 0;
esp_efuse_read_field_blob(ESP_EFUSE_WR_DIS_FLASH_CRYPT_CNT, &flash_crypt_cnt_wr_dis, 1);
if (!flash_crypt_cnt_wr_dis) {
esp_efuse_write_field_cnt(ESP_EFUSE_WR_DIS_FLASH_CRYPT_CNT, 1);
}
}
esp_flash_enc_mode_t esp_get_flash_encryption_mode()
{
uint8_t efuse_flash_crypt_cnt_wr_protected = 0;
uint8_t dis_dl_enc = 0, dis_dl_dec = 0, dis_dl_cache = 0;
esp_flash_enc_mode_t mode = ESP_FLASH_ENC_MODE_DEVELOPMENT;
if (esp_flash_encryption_enabled()) {
/* Check if FLASH CRYPT CNT is write protected */
esp_efuse_read_field_blob(ESP_EFUSE_WR_DIS_FLASH_CRYPT_CNT, &efuse_flash_crypt_cnt_wr_protected, 1);
if (efuse_flash_crypt_cnt_wr_protected) {
esp_efuse_read_field_blob(ESP_EFUSE_DISABLE_DL_CACHE, &dis_dl_cache, 1);
esp_efuse_read_field_blob(ESP_EFUSE_DISABLE_DL_ENCRYPT, &dis_dl_enc, 1);
esp_efuse_read_field_blob(ESP_EFUSE_DISABLE_DL_DECRYPT, &dis_dl_dec, 1);
/* Check if DISABLE_DL_DECRYPT, DISABLE_DL_ENCRYPT & DISABLE_DL_CACHE are set */
if ( dis_dl_cache && dis_dl_enc && dis_dl_dec ) {
mode = ESP_FLASH_ENC_MODE_RELEASE;
}
}
} else {
mode = ESP_FLASH_ENC_MODE_DISABLED;
}
return mode;
}

View file

@ -1,6 +1,3 @@
set(COMPONENT_SRCDIRS ".") idf_component_register(SRC_DIRS "."
set(COMPONENT_ADD_INCLUDEDIRS ".") INCLUDE_DIRS "."
REQUIRES unity bootloader_support app_update)
set(COMPONENT_REQUIRES unity bootloader_support app_update)
register_component()

View file

@ -1,300 +1,510 @@
if(CONFIG_BT_ENABLED) if(CONFIG_BT_ENABLED)
set(COMPONENT_SRCS "bt.c") set(srcs "controller/bt.c")
set(COMPONENT_ADD_INCLUDEDIRS include) set(include_dirs include
common/osi/include)
list(APPEND priv_include_dirs
common/btc/include
common/include)
list(APPEND srcs "common/btc/core/btc_alarm.c"
"common/btc/core/btc_manage.c"
"common/btc/core/btc_task.c"
"common/osi/alarm.c"
"common/osi/allocator.c"
"common/osi/buffer.c"
"common/osi/config.c"
"common/osi/fixed_queue.c"
"common/osi/future.c"
"common/osi/hash_functions.c"
"common/osi/hash_map.c"
"common/osi/list.c"
"common/osi/mutex.c"
"common/osi/thread.c"
"common/osi/osi.c"
"common/osi/semaphore.c")
if(CONFIG_BT_BLUEDROID_ENABLED) if(CONFIG_BT_BLUEDROID_ENABLED)
list(APPEND COMPONENT_PRIV_INCLUDEDIRS list(APPEND priv_include_dirs
bluedroid/bta/include host/bluedroid/bta/include
bluedroid/bta/ar/include host/bluedroid/bta/ar/include
bluedroid/bta/av/include host/bluedroid/bta/av/include
bluedroid/bta/dm/include host/bluedroid/bta/dm/include
bluedroid/bta/gatt/include host/bluedroid/bta/gatt/include
bluedroid/bta/hf_client/include host/bluedroid/bta/hf_client/include
bluedroid/bta/hh/include host/bluedroid/bta/hh/include
bluedroid/bta/jv/include host/bluedroid/bta/jv/include
bluedroid/bta/sdp/include host/bluedroid/bta/sdp/include
bluedroid/bta/sys/include host/bluedroid/bta/sys/include
bluedroid/device/include host/bluedroid/device/include
bluedroid/hci/include host/bluedroid/hci/include
bluedroid/osi/include host/bluedroid/external/sbc/decoder/include
bluedroid/external/sbc/decoder/include host/bluedroid/external/sbc/encoder/include
bluedroid/external/sbc/encoder/include host/bluedroid/external/sbc/plc/include
bluedroid/external/sbc/plc/include host/bluedroid/btc/profile/esp/blufi/include
bluedroid/btc/profile/esp/blufi/include host/bluedroid/btc/profile/esp/include
bluedroid/btc/profile/esp/include host/bluedroid/btc/profile/std/a2dp/include
bluedroid/btc/profile/std/a2dp/include host/bluedroid/btc/profile/std/include
bluedroid/btc/profile/std/include host/bluedroid/btc/include
bluedroid/btc/include host/bluedroid/stack/btm/include
bluedroid/stack/btm/include host/bluedroid/stack/gap/include
bluedroid/stack/gap/include host/bluedroid/stack/gatt/include
bluedroid/stack/gatt/include host/bluedroid/stack/l2cap/include
bluedroid/stack/l2cap/include host/bluedroid/stack/sdp/include
bluedroid/stack/sdp/include host/bluedroid/stack/smp/include
bluedroid/stack/smp/include host/bluedroid/stack/avct/include
bluedroid/stack/avct/include host/bluedroid/stack/avrc/include
bluedroid/stack/avrc/include host/bluedroid/stack/avdt/include
bluedroid/stack/avdt/include host/bluedroid/stack/a2dp/include
bluedroid/stack/a2dp/include host/bluedroid/stack/rfcomm/include
bluedroid/stack/rfcomm/include host/bluedroid/stack/include
bluedroid/stack/include host/bluedroid/common/include)
bluedroid/common/include)
list(APPEND COMPONENT_ADD_INCLUDEDIRS bluedroid/api/include/api) list(APPEND include_dirs host/bluedroid/api/include/api)
list(APPEND COMPONENT_SRCS "bluedroid/api/esp_a2dp_api.c" list(APPEND srcs "host/bluedroid/api/esp_a2dp_api.c"
"bluedroid/api/esp_avrc_api.c" "host/bluedroid/api/esp_avrc_api.c"
"bluedroid/api/esp_blufi_api.c" "host/bluedroid/api/esp_blufi_api.c"
"bluedroid/api/esp_bt_device.c" "host/bluedroid/api/esp_bt_device.c"
"bluedroid/api/esp_bt_main.c" "host/bluedroid/api/esp_bt_main.c"
"bluedroid/api/esp_gap_ble_api.c" "host/bluedroid/api/esp_gap_ble_api.c"
"bluedroid/api/esp_gap_bt_api.c" "host/bluedroid/api/esp_gap_bt_api.c"
"bluedroid/api/esp_gatt_common_api.c" "host/bluedroid/api/esp_gatt_common_api.c"
"bluedroid/api/esp_gattc_api.c" "host/bluedroid/api/esp_gattc_api.c"
"bluedroid/api/esp_gatts_api.c" "host/bluedroid/api/esp_gatts_api.c"
"bluedroid/api/esp_hf_client_api.c" "host/bluedroid/api/esp_hf_client_api.c"
"bluedroid/api/esp_spp_api.c" "host/bluedroid/api/esp_spp_api.c"
"bluedroid/bta/ar/bta_ar.c" "host/bluedroid/bta/ar/bta_ar.c"
"bluedroid/bta/av/bta_av_aact.c" "host/bluedroid/bta/av/bta_av_aact.c"
"bluedroid/bta/av/bta_av_act.c" "host/bluedroid/bta/av/bta_av_act.c"
"bluedroid/bta/av/bta_av_api.c" "host/bluedroid/bta/av/bta_av_api.c"
"bluedroid/bta/av/bta_av_cfg.c" "host/bluedroid/bta/av/bta_av_cfg.c"
"bluedroid/bta/av/bta_av_ci.c" "host/bluedroid/bta/av/bta_av_ci.c"
"bluedroid/bta/av/bta_av_main.c" "host/bluedroid/bta/av/bta_av_main.c"
"bluedroid/bta/av/bta_av_sbc.c" "host/bluedroid/bta/av/bta_av_sbc.c"
"bluedroid/bta/av/bta_av_ssm.c" "host/bluedroid/bta/av/bta_av_ssm.c"
"bluedroid/bta/dm/bta_dm_act.c" "host/bluedroid/bta/dm/bta_dm_act.c"
"bluedroid/bta/dm/bta_dm_api.c" "host/bluedroid/bta/dm/bta_dm_api.c"
"bluedroid/bta/dm/bta_dm_cfg.c" "host/bluedroid/bta/dm/bta_dm_cfg.c"
"bluedroid/bta/dm/bta_dm_ci.c" "host/bluedroid/bta/dm/bta_dm_ci.c"
"bluedroid/bta/dm/bta_dm_co.c" "host/bluedroid/bta/dm/bta_dm_co.c"
"bluedroid/bta/dm/bta_dm_main.c" "host/bluedroid/bta/dm/bta_dm_main.c"
"bluedroid/bta/dm/bta_dm_pm.c" "host/bluedroid/bta/dm/bta_dm_pm.c"
"bluedroid/bta/dm/bta_dm_sco.c" "host/bluedroid/bta/dm/bta_dm_sco.c"
"bluedroid/bta/gatt/bta_gatt_common.c" "host/bluedroid/bta/gatt/bta_gatt_common.c"
"bluedroid/bta/gatt/bta_gattc_act.c" "host/bluedroid/bta/gatt/bta_gattc_act.c"
"bluedroid/bta/gatt/bta_gattc_api.c" "host/bluedroid/bta/gatt/bta_gattc_api.c"
"bluedroid/bta/gatt/bta_gattc_cache.c" "host/bluedroid/bta/gatt/bta_gattc_cache.c"
"bluedroid/bta/gatt/bta_gattc_ci.c" "host/bluedroid/bta/gatt/bta_gattc_ci.c"
"bluedroid/bta/gatt/bta_gattc_co.c" "host/bluedroid/bta/gatt/bta_gattc_co.c"
"bluedroid/bta/gatt/bta_gattc_main.c" "host/bluedroid/bta/gatt/bta_gattc_main.c"
"bluedroid/bta/gatt/bta_gattc_utils.c" "host/bluedroid/bta/gatt/bta_gattc_utils.c"
"bluedroid/bta/gatt/bta_gatts_act.c" "host/bluedroid/bta/gatt/bta_gatts_act.c"
"bluedroid/bta/gatt/bta_gatts_api.c" "host/bluedroid/bta/gatt/bta_gatts_api.c"
"bluedroid/bta/gatt/bta_gatts_co.c" "host/bluedroid/bta/gatt/bta_gatts_co.c"
"bluedroid/bta/gatt/bta_gatts_main.c" "host/bluedroid/bta/gatt/bta_gatts_main.c"
"bluedroid/bta/gatt/bta_gatts_utils.c" "host/bluedroid/bta/gatt/bta_gatts_utils.c"
"bluedroid/bta/hh/bta_hh_act.c" "host/bluedroid/bta/hh/bta_hh_act.c"
"bluedroid/bta/hh/bta_hh_api.c" "host/bluedroid/bta/hh/bta_hh_api.c"
"bluedroid/bta/hh/bta_hh_cfg.c" "host/bluedroid/bta/hh/bta_hh_cfg.c"
"bluedroid/bta/hh/bta_hh_le.c" "host/bluedroid/bta/hh/bta_hh_le.c"
"bluedroid/bta/hh/bta_hh_main.c" "host/bluedroid/bta/hh/bta_hh_main.c"
"bluedroid/bta/hh/bta_hh_utils.c" "host/bluedroid/bta/hh/bta_hh_utils.c"
"bluedroid/bta/jv/bta_jv_act.c" "host/bluedroid/bta/jv/bta_jv_act.c"
"bluedroid/bta/jv/bta_jv_api.c" "host/bluedroid/bta/jv/bta_jv_api.c"
"bluedroid/bta/jv/bta_jv_cfg.c" "host/bluedroid/bta/jv/bta_jv_cfg.c"
"bluedroid/bta/jv/bta_jv_main.c" "host/bluedroid/bta/jv/bta_jv_main.c"
"bluedroid/bta/hf_client/bta_hf_client_act.c" "host/bluedroid/bta/hf_client/bta_hf_client_act.c"
"bluedroid/bta/hf_client/bta_hf_client_api.c" "host/bluedroid/bta/hf_client/bta_hf_client_api.c"
"bluedroid/bta/hf_client/bta_hf_client_at.c" "host/bluedroid/bta/hf_client/bta_hf_client_at.c"
"bluedroid/bta/hf_client/bta_hf_client_cmd.c" "host/bluedroid/bta/hf_client/bta_hf_client_cmd.c"
"bluedroid/bta/hf_client/bta_hf_client_main.c" "host/bluedroid/bta/hf_client/bta_hf_client_main.c"
"bluedroid/bta/hf_client/bta_hf_client_rfc.c" "host/bluedroid/bta/hf_client/bta_hf_client_rfc.c"
"bluedroid/bta/hf_client/bta_hf_client_sco.c" "host/bluedroid/bta/hf_client/bta_hf_client_sco.c"
"bluedroid/bta/hf_client/bta_hf_client_sdp.c" "host/bluedroid/bta/hf_client/bta_hf_client_sdp.c"
"bluedroid/bta/sdp/bta_sdp.c" "host/bluedroid/bta/sdp/bta_sdp.c"
"bluedroid/bta/sdp/bta_sdp_act.c" "host/bluedroid/bta/sdp/bta_sdp_act.c"
"bluedroid/bta/sdp/bta_sdp_api.c" "host/bluedroid/bta/sdp/bta_sdp_api.c"
"bluedroid/bta/sdp/bta_sdp_cfg.c" "host/bluedroid/bta/sdp/bta_sdp_cfg.c"
"bluedroid/bta/sys/bta_sys_conn.c" "host/bluedroid/bta/sys/bta_sys_conn.c"
"bluedroid/bta/sys/bta_sys_main.c" "host/bluedroid/bta/sys/bta_sys_main.c"
"bluedroid/bta/sys/utl.c" "host/bluedroid/bta/sys/utl.c"
"bluedroid/btc/core/btc_alarm.c" "host/bluedroid/btc/core/btc_ble_storage.c"
"bluedroid/btc/core/btc_ble_storage.c" "host/bluedroid/btc/core/btc_config.c"
"bluedroid/btc/core/btc_config.c" "host/bluedroid/btc/core/btc_dev.c"
"bluedroid/btc/core/btc_dev.c" "host/bluedroid/btc/core/btc_dm.c"
"bluedroid/btc/core/btc_dm.c" "host/bluedroid/btc/core/btc_main.c"
"bluedroid/btc/core/btc_main.c" "host/bluedroid/btc/core/btc_profile_queue.c"
"bluedroid/btc/core/btc_manage.c" "host/bluedroid/btc/core/btc_sec.c"
"bluedroid/btc/core/btc_profile_queue.c" "host/bluedroid/btc/core/btc_sm.c"
"bluedroid/btc/core/btc_sec.c" "host/bluedroid/btc/core/btc_storage.c"
"bluedroid/btc/core/btc_sm.c" "host/bluedroid/btc/core/btc_util.c"
"bluedroid/btc/core/btc_storage.c" "host/bluedroid/btc/profile/esp/blufi/blufi_prf.c"
"bluedroid/btc/core/btc_task.c" "host/bluedroid/btc/profile/esp/blufi/blufi_protocol.c"
"bluedroid/btc/core/btc_util.c" "host/bluedroid/btc/profile/std/a2dp/bta_av_co.c"
"bluedroid/btc/profile/esp/blufi/blufi_prf.c" "host/bluedroid/btc/profile/std/a2dp/btc_a2dp.c"
"bluedroid/btc/profile/esp/blufi/blufi_protocol.c" "host/bluedroid/btc/profile/std/a2dp/btc_a2dp_control.c"
"bluedroid/btc/profile/std/a2dp/bta_av_co.c" "host/bluedroid/btc/profile/std/a2dp/btc_a2dp_sink.c"
"bluedroid/btc/profile/std/a2dp/btc_a2dp.c" "host/bluedroid/btc/profile/std/a2dp/btc_a2dp_source.c"
"bluedroid/btc/profile/std/a2dp/btc_a2dp_control.c" "host/bluedroid/btc/profile/std/a2dp/btc_av.c"
"bluedroid/btc/profile/std/a2dp/btc_a2dp_sink.c" "host/bluedroid/btc/profile/std/avrc/btc_avrc.c"
"bluedroid/btc/profile/std/a2dp/btc_a2dp_source.c" "host/bluedroid/btc/profile/std/avrc/bta_avrc_co.c"
"bluedroid/btc/profile/std/a2dp/btc_av.c" "host/bluedroid/btc/profile/std/hf_client/btc_hf_client.c"
"bluedroid/btc/profile/std/avrc/btc_avrc.c" "host/bluedroid/btc/profile/std/hf_client/bta_hf_client_co.c"
"bluedroid/btc/profile/std/avrc/bta_avrc_co.c" "host/bluedroid/btc/profile/std/gap/btc_gap_ble.c"
"bluedroid/btc/profile/std/hf_client/btc_hf_client.c" "host/bluedroid/btc/profile/std/gap/btc_gap_bt.c"
"bluedroid/btc/profile/std/hf_client/bta_hf_client_co.c" "host/bluedroid/btc/profile/std/gap/bta_gap_bt_co.c"
"bluedroid/btc/profile/std/gap/btc_gap_ble.c" "host/bluedroid/btc/profile/std/gatt/btc_gatt_common.c"
"bluedroid/btc/profile/std/gap/btc_gap_bt.c" "host/bluedroid/btc/profile/std/gatt/btc_gatt_util.c"
"bluedroid/btc/profile/std/gatt/btc_gatt_common.c" "host/bluedroid/btc/profile/std/gatt/btc_gattc.c"
"bluedroid/btc/profile/std/gatt/btc_gatt_util.c" "host/bluedroid/btc/profile/std/gatt/btc_gatts.c"
"bluedroid/btc/profile/std/gatt/btc_gattc.c" "host/bluedroid/btc/profile/std/spp/btc_spp.c"
"bluedroid/btc/profile/std/gatt/btc_gatts.c" "host/bluedroid/device/bdaddr.c"
"bluedroid/btc/profile/std/spp/btc_spp.c" "host/bluedroid/device/controller.c"
"bluedroid/device/bdaddr.c" "host/bluedroid/device/interop.c"
"bluedroid/device/controller.c" "host/bluedroid/external/sbc/decoder/srce/alloc.c"
"bluedroid/device/interop.c" "host/bluedroid/external/sbc/decoder/srce/bitalloc-sbc.c"
"bluedroid/external/sbc/decoder/srce/alloc.c" "host/bluedroid/external/sbc/decoder/srce/bitalloc.c"
"bluedroid/external/sbc/decoder/srce/bitalloc-sbc.c" "host/bluedroid/external/sbc/decoder/srce/bitstream-decode.c"
"bluedroid/external/sbc/decoder/srce/bitalloc.c" "host/bluedroid/external/sbc/decoder/srce/decoder-oina.c"
"bluedroid/external/sbc/decoder/srce/bitstream-decode.c" "host/bluedroid/external/sbc/decoder/srce/decoder-private.c"
"bluedroid/external/sbc/decoder/srce/decoder-oina.c" "host/bluedroid/external/sbc/decoder/srce/decoder-sbc.c"
"bluedroid/external/sbc/decoder/srce/decoder-private.c" "host/bluedroid/external/sbc/decoder/srce/dequant.c"
"bluedroid/external/sbc/decoder/srce/decoder-sbc.c" "host/bluedroid/external/sbc/decoder/srce/framing-sbc.c"
"bluedroid/external/sbc/decoder/srce/dequant.c" "host/bluedroid/external/sbc/decoder/srce/framing.c"
"bluedroid/external/sbc/decoder/srce/framing-sbc.c" "host/bluedroid/external/sbc/decoder/srce/oi_codec_version.c"
"bluedroid/external/sbc/decoder/srce/framing.c" "host/bluedroid/external/sbc/decoder/srce/synthesis-8-generated.c"
"bluedroid/external/sbc/decoder/srce/oi_codec_version.c" "host/bluedroid/external/sbc/decoder/srce/synthesis-dct8.c"
"bluedroid/external/sbc/decoder/srce/synthesis-8-generated.c" "host/bluedroid/external/sbc/decoder/srce/synthesis-sbc.c"
"bluedroid/external/sbc/decoder/srce/synthesis-dct8.c" "host/bluedroid/external/sbc/encoder/srce/sbc_analysis.c"
"bluedroid/external/sbc/decoder/srce/synthesis-sbc.c" "host/bluedroid/external/sbc/encoder/srce/sbc_dct.c"
"bluedroid/external/sbc/encoder/srce/sbc_analysis.c" "host/bluedroid/external/sbc/encoder/srce/sbc_dct_coeffs.c"
"bluedroid/external/sbc/encoder/srce/sbc_dct.c" "host/bluedroid/external/sbc/encoder/srce/sbc_enc_bit_alloc_mono.c"
"bluedroid/external/sbc/encoder/srce/sbc_dct_coeffs.c" "host/bluedroid/external/sbc/encoder/srce/sbc_enc_bit_alloc_ste.c"
"bluedroid/external/sbc/encoder/srce/sbc_enc_bit_alloc_mono.c" "host/bluedroid/external/sbc/encoder/srce/sbc_enc_coeffs.c"
"bluedroid/external/sbc/encoder/srce/sbc_enc_bit_alloc_ste.c" "host/bluedroid/external/sbc/encoder/srce/sbc_encoder.c"
"bluedroid/external/sbc/encoder/srce/sbc_enc_coeffs.c" "host/bluedroid/external/sbc/encoder/srce/sbc_packing.c"
"bluedroid/external/sbc/encoder/srce/sbc_encoder.c" "host/bluedroid/external/sbc/plc/sbc_plc.c"
"bluedroid/external/sbc/encoder/srce/sbc_packing.c" "host/bluedroid/hci/hci_audio.c"
"bluedroid/external/sbc/plc/sbc_plc.c" "host/bluedroid/hci/hci_hal_h4.c"
"bluedroid/hci/hci_audio.c" "host/bluedroid/hci/hci_layer.c"
"bluedroid/hci/hci_hal_h4.c" "host/bluedroid/hci/hci_packet_factory.c"
"bluedroid/hci/hci_layer.c" "host/bluedroid/hci/hci_packet_parser.c"
"bluedroid/hci/hci_packet_factory.c" "host/bluedroid/hci/packet_fragmenter.c"
"bluedroid/hci/hci_packet_parser.c" "host/bluedroid/main/bte_init.c"
"bluedroid/hci/packet_fragmenter.c" "host/bluedroid/main/bte_main.c"
"bluedroid/main/bte_init.c" "host/bluedroid/stack/a2dp/a2d_api.c"
"bluedroid/main/bte_main.c" "host/bluedroid/stack/a2dp/a2d_sbc.c"
"bluedroid/osi/alarm.c" "host/bluedroid/stack/avct/avct_api.c"
"bluedroid/osi/allocator.c" "host/bluedroid/stack/avct/avct_ccb.c"
"bluedroid/osi/buffer.c" "host/bluedroid/stack/avct/avct_l2c.c"
"bluedroid/osi/config.c" "host/bluedroid/stack/avct/avct_lcb.c"
"bluedroid/osi/fixed_queue.c" "host/bluedroid/stack/avct/avct_lcb_act.c"
"bluedroid/osi/future.c" "host/bluedroid/stack/avdt/avdt_ad.c"
"bluedroid/osi/hash_functions.c" "host/bluedroid/stack/avdt/avdt_api.c"
"bluedroid/osi/hash_map.c" "host/bluedroid/stack/avdt/avdt_ccb.c"
"bluedroid/osi/list.c" "host/bluedroid/stack/avdt/avdt_ccb_act.c"
"bluedroid/osi/mutex.c" "host/bluedroid/stack/avdt/avdt_l2c.c"
"bluedroid/osi/osi.c" "host/bluedroid/stack/avdt/avdt_msg.c"
"bluedroid/osi/semaphore.c" "host/bluedroid/stack/avdt/avdt_scb.c"
"bluedroid/stack/a2dp/a2d_api.c" "host/bluedroid/stack/avdt/avdt_scb_act.c"
"bluedroid/stack/a2dp/a2d_sbc.c" "host/bluedroid/stack/avrc/avrc_api.c"
"bluedroid/stack/avct/avct_api.c" "host/bluedroid/stack/avrc/avrc_bld_ct.c"
"bluedroid/stack/avct/avct_ccb.c" "host/bluedroid/stack/avrc/avrc_bld_tg.c"
"bluedroid/stack/avct/avct_l2c.c" "host/bluedroid/stack/avrc/avrc_opt.c"
"bluedroid/stack/avct/avct_lcb.c" "host/bluedroid/stack/avrc/avrc_pars_ct.c"
"bluedroid/stack/avct/avct_lcb_act.c" "host/bluedroid/stack/avrc/avrc_pars_tg.c"
"bluedroid/stack/avdt/avdt_ad.c" "host/bluedroid/stack/avrc/avrc_sdp.c"
"bluedroid/stack/avdt/avdt_api.c" "host/bluedroid/stack/avrc/avrc_utils.c"
"bluedroid/stack/avdt/avdt_ccb.c" "host/bluedroid/stack/btm/btm_acl.c"
"bluedroid/stack/avdt/avdt_ccb_act.c" "host/bluedroid/stack/btm/btm_ble.c"
"bluedroid/stack/avdt/avdt_l2c.c" "host/bluedroid/stack/btm/btm_ble_addr.c"
"bluedroid/stack/avdt/avdt_msg.c" "host/bluedroid/stack/btm/btm_ble_adv_filter.c"
"bluedroid/stack/avdt/avdt_scb.c" "host/bluedroid/stack/btm/btm_ble_batchscan.c"
"bluedroid/stack/avdt/avdt_scb_act.c" "host/bluedroid/stack/btm/btm_ble_bgconn.c"
"bluedroid/stack/avrc/avrc_api.c" "host/bluedroid/stack/btm/btm_ble_cont_energy.c"
"bluedroid/stack/avrc/avrc_bld_ct.c" "host/bluedroid/stack/btm/btm_ble_gap.c"
"bluedroid/stack/avrc/avrc_bld_tg.c" "host/bluedroid/stack/btm/btm_ble_multi_adv.c"
"bluedroid/stack/avrc/avrc_opt.c" "host/bluedroid/stack/btm/btm_ble_privacy.c"
"bluedroid/stack/avrc/avrc_pars_ct.c" "host/bluedroid/stack/btm/btm_dev.c"
"bluedroid/stack/avrc/avrc_pars_tg.c" "host/bluedroid/stack/btm/btm_devctl.c"
"bluedroid/stack/avrc/avrc_sdp.c" "host/bluedroid/stack/btm/btm_inq.c"
"bluedroid/stack/avrc/avrc_utils.c" "host/bluedroid/stack/btm/btm_main.c"
"bluedroid/stack/btm/btm_acl.c" "host/bluedroid/stack/btm/btm_pm.c"
"bluedroid/stack/btm/btm_ble.c" "host/bluedroid/stack/btm/btm_sco.c"
"bluedroid/stack/btm/btm_ble_addr.c" "host/bluedroid/stack/btm/btm_sec.c"
"bluedroid/stack/btm/btm_ble_adv_filter.c" "host/bluedroid/stack/btu/btu_hcif.c"
"bluedroid/stack/btm/btm_ble_batchscan.c" "host/bluedroid/stack/btu/btu_init.c"
"bluedroid/stack/btm/btm_ble_bgconn.c" "host/bluedroid/stack/btu/btu_task.c"
"bluedroid/stack/btm/btm_ble_cont_energy.c" "host/bluedroid/stack/gap/gap_api.c"
"bluedroid/stack/btm/btm_ble_gap.c" "host/bluedroid/stack/gap/gap_ble.c"
"bluedroid/stack/btm/btm_ble_multi_adv.c" "host/bluedroid/stack/gap/gap_conn.c"
"bluedroid/stack/btm/btm_ble_privacy.c" "host/bluedroid/stack/gap/gap_utils.c"
"bluedroid/stack/btm/btm_dev.c" "host/bluedroid/stack/gatt/att_protocol.c"
"bluedroid/stack/btm/btm_devctl.c" "host/bluedroid/stack/gatt/gatt_api.c"
"bluedroid/stack/btm/btm_inq.c" "host/bluedroid/stack/gatt/gatt_attr.c"
"bluedroid/stack/btm/btm_main.c" "host/bluedroid/stack/gatt/gatt_auth.c"
"bluedroid/stack/btm/btm_pm.c" "host/bluedroid/stack/gatt/gatt_cl.c"
"bluedroid/stack/btm/btm_sco.c" "host/bluedroid/stack/gatt/gatt_db.c"
"bluedroid/stack/btm/btm_sec.c" "host/bluedroid/stack/gatt/gatt_main.c"
"bluedroid/stack/btu/btu_hcif.c" "host/bluedroid/stack/gatt/gatt_sr.c"
"bluedroid/stack/btu/btu_init.c" "host/bluedroid/stack/gatt/gatt_utils.c"
"bluedroid/stack/btu/btu_task.c" "host/bluedroid/stack/hcic/hciblecmds.c"
"bluedroid/stack/gap/gap_api.c" "host/bluedroid/stack/hcic/hcicmds.c"
"bluedroid/stack/gap/gap_ble.c" "host/bluedroid/stack/l2cap/l2c_api.c"
"bluedroid/stack/gap/gap_conn.c" "host/bluedroid/stack/l2cap/l2c_ble.c"
"bluedroid/stack/gap/gap_utils.c" "host/bluedroid/stack/l2cap/l2c_csm.c"
"bluedroid/stack/gatt/att_protocol.c" "host/bluedroid/stack/l2cap/l2c_fcr.c"
"bluedroid/stack/gatt/gatt_api.c" "host/bluedroid/stack/l2cap/l2c_link.c"
"bluedroid/stack/gatt/gatt_attr.c" "host/bluedroid/stack/l2cap/l2c_main.c"
"bluedroid/stack/gatt/gatt_auth.c" "host/bluedroid/stack/l2cap/l2c_ucd.c"
"bluedroid/stack/gatt/gatt_cl.c" "host/bluedroid/stack/l2cap/l2c_utils.c"
"bluedroid/stack/gatt/gatt_db.c" "host/bluedroid/stack/l2cap/l2cap_client.c"
"bluedroid/stack/gatt/gatt_main.c" "host/bluedroid/stack/rfcomm/port_api.c"
"bluedroid/stack/gatt/gatt_sr.c" "host/bluedroid/stack/rfcomm/port_rfc.c"
"bluedroid/stack/gatt/gatt_utils.c" "host/bluedroid/stack/rfcomm/port_utils.c"
"bluedroid/stack/hcic/hciblecmds.c" "host/bluedroid/stack/rfcomm/rfc_l2cap_if.c"
"bluedroid/stack/hcic/hcicmds.c" "host/bluedroid/stack/rfcomm/rfc_mx_fsm.c"
"bluedroid/stack/l2cap/l2c_api.c" "host/bluedroid/stack/rfcomm/rfc_port_fsm.c"
"bluedroid/stack/l2cap/l2c_ble.c" "host/bluedroid/stack/rfcomm/rfc_port_if.c"
"bluedroid/stack/l2cap/l2c_csm.c" "host/bluedroid/stack/rfcomm/rfc_ts_frames.c"
"bluedroid/stack/l2cap/l2c_fcr.c" "host/bluedroid/stack/rfcomm/rfc_utils.c"
"bluedroid/stack/l2cap/l2c_link.c" "host/bluedroid/stack/sdp/sdp_api.c"
"bluedroid/stack/l2cap/l2c_main.c" "host/bluedroid/stack/sdp/sdp_db.c"
"bluedroid/stack/l2cap/l2c_ucd.c" "host/bluedroid/stack/sdp/sdp_discovery.c"
"bluedroid/stack/l2cap/l2c_utils.c" "host/bluedroid/stack/sdp/sdp_main.c"
"bluedroid/stack/l2cap/l2cap_client.c" "host/bluedroid/stack/sdp/sdp_server.c"
"bluedroid/stack/rfcomm/port_api.c" "host/bluedroid/stack/sdp/sdp_utils.c"
"bluedroid/stack/rfcomm/port_rfc.c" "host/bluedroid/stack/smp/aes.c"
"bluedroid/stack/rfcomm/port_utils.c" "host/bluedroid/stack/smp/p_256_curvepara.c"
"bluedroid/stack/rfcomm/rfc_l2cap_if.c" "host/bluedroid/stack/smp/p_256_ecc_pp.c"
"bluedroid/stack/rfcomm/rfc_mx_fsm.c" "host/bluedroid/stack/smp/p_256_multprecision.c"
"bluedroid/stack/rfcomm/rfc_port_fsm.c" "host/bluedroid/stack/smp/smp_act.c"
"bluedroid/stack/rfcomm/rfc_port_if.c" "host/bluedroid/stack/smp/smp_api.c"
"bluedroid/stack/rfcomm/rfc_ts_frames.c" "host/bluedroid/stack/smp/smp_br_main.c"
"bluedroid/stack/rfcomm/rfc_utils.c" "host/bluedroid/stack/smp/smp_cmac.c"
"bluedroid/stack/sdp/sdp_api.c" "host/bluedroid/stack/smp/smp_keys.c"
"bluedroid/stack/sdp/sdp_db.c" "host/bluedroid/stack/smp/smp_l2c.c"
"bluedroid/stack/sdp/sdp_discovery.c" "host/bluedroid/stack/smp/smp_main.c"
"bluedroid/stack/sdp/sdp_main.c" "host/bluedroid/stack/smp/smp_utils.c")
"bluedroid/stack/sdp/sdp_server.c" endif()
"bluedroid/stack/sdp/sdp_utils.c"
"bluedroid/stack/smp/aes.c" if(CONFIG_BLE_MESH)
"bluedroid/stack/smp/p_256_curvepara.c" list(APPEND include_dirs
"bluedroid/stack/smp/p_256_ecc_pp.c" "esp_ble_mesh/mesh_core"
"bluedroid/stack/smp/p_256_multprecision.c" "esp_ble_mesh/mesh_core/include"
"bluedroid/stack/smp/smp_act.c" "esp_ble_mesh/mesh_core/settings"
"bluedroid/stack/smp/smp_api.c" "esp_ble_mesh/btc/include"
"bluedroid/stack/smp/smp_br_main.c" "esp_ble_mesh/mesh_models/include"
"bluedroid/stack/smp/smp_cmac.c" "esp_ble_mesh/api/core/include"
"bluedroid/stack/smp/smp_keys.c" "esp_ble_mesh/api/models/include"
"bluedroid/stack/smp/smp_l2c.c" "esp_ble_mesh/api")
"bluedroid/stack/smp/smp_main.c"
"bluedroid/stack/smp/smp_utils.c") list(APPEND srcs "esp_ble_mesh/api/core/esp_ble_mesh_common_api.c"
"esp_ble_mesh/api/core/esp_ble_mesh_local_data_operation_api.c"
"esp_ble_mesh/api/core/esp_ble_mesh_low_power_api.c"
"esp_ble_mesh/api/core/esp_ble_mesh_networking_api.c"
"esp_ble_mesh/api/core/esp_ble_mesh_provisioning_api.c"
"esp_ble_mesh/api/core/esp_ble_mesh_proxy_api.c"
"esp_ble_mesh/api/models/esp_ble_mesh_config_model_api.c"
"esp_ble_mesh/api/models/esp_ble_mesh_generic_model_api.c"
"esp_ble_mesh/api/models/esp_ble_mesh_health_model_api.c"
"esp_ble_mesh/api/models/esp_ble_mesh_lighting_model_api.c"
"esp_ble_mesh/api/models/esp_ble_mesh_sensor_model_api.c"
"esp_ble_mesh/api/models/esp_ble_mesh_time_scene_model_api.c"
"esp_ble_mesh/btc/btc_ble_mesh_config_model.c"
"esp_ble_mesh/btc/btc_ble_mesh_generic_model.c"
"esp_ble_mesh/btc/btc_ble_mesh_health_model.c"
"esp_ble_mesh/btc/btc_ble_mesh_lighting_model.c"
"esp_ble_mesh/btc/btc_ble_mesh_prov.c"
"esp_ble_mesh/btc/btc_ble_mesh_sensor_model.c"
"esp_ble_mesh/btc/btc_ble_mesh_time_scene_model.c"
"esp_ble_mesh/mesh_core/settings/settings_nvs.c"
"esp_ble_mesh/mesh_core/access.c"
"esp_ble_mesh/mesh_core/adv.c"
"esp_ble_mesh/mesh_core/beacon.c"
"esp_ble_mesh/mesh_core/cfg_cli.c"
"esp_ble_mesh/mesh_core/cfg_srv.c"
"esp_ble_mesh/mesh_core/crypto.c"
"esp_ble_mesh/mesh_core/friend.c"
"esp_ble_mesh/mesh_core/health_cli.c"
"esp_ble_mesh/mesh_core/health_srv.c"
"esp_ble_mesh/mesh_core/lpn.c"
"esp_ble_mesh/mesh_core/mesh_aes_encrypt.c"
"esp_ble_mesh/mesh_core/mesh_atomic.c"
"esp_ble_mesh/mesh_core/mesh_bearer_adapt.c"
"esp_ble_mesh/mesh_core/mesh_buf.c"
"esp_ble_mesh/mesh_core/mesh_hci.c"
"esp_ble_mesh/mesh_core/mesh_kernel.c"
"esp_ble_mesh/mesh_core/mesh_main.c"
"esp_ble_mesh/mesh_core/mesh_util.c"
"esp_ble_mesh/mesh_core/net.c"
"esp_ble_mesh/mesh_core/prov.c"
"esp_ble_mesh/mesh_core/provisioner_beacon.c"
"esp_ble_mesh/mesh_core/provisioner_main.c"
"esp_ble_mesh/mesh_core/provisioner_prov.c"
"esp_ble_mesh/mesh_core/provisioner_proxy.c"
"esp_ble_mesh/mesh_core/proxy.c"
"esp_ble_mesh/mesh_core/settings.c"
"esp_ble_mesh/mesh_core/test.c"
"esp_ble_mesh/mesh_core/transport.c"
"esp_ble_mesh/mesh_models/generic_client.c"
"esp_ble_mesh/mesh_models/lighting_client.c"
"esp_ble_mesh/mesh_models/mesh_common.c"
"esp_ble_mesh/mesh_models/model_common.c"
"esp_ble_mesh/mesh_models/sensor_client.c"
"esp_ble_mesh/mesh_models/time_scene_client.c")
endif()
if(CONFIG_BT_NIMBLE_ENABLED)
list(APPEND include_dirs
host/nimble/nimble/porting/nimble/include
host/nimble/port/include
host/nimble/nimble/nimble/include
host/nimble/nimble/nimble/host/include
host/nimble/nimble/nimble/host/services/ans/include
host/nimble/nimble/nimble/host/services/bas/include
host/nimble/nimble/nimble/host/services/gap/include
host/nimble/nimble/nimble/host/services/gatt/include
host/nimble/nimble/nimble/host/services/ias/include
host/nimble/nimble/nimble/host/services/lls/include
host/nimble/nimble/nimble/host/services/tps/include
host/nimble/nimble/nimble/host/util/include
host/nimble/nimble/nimble/host/store/ram/include
host/nimble/nimble/nimble/host/store/config/include
host/nimble/nimble/porting/npl/freertos/include
host/nimble/nimble/ext/tinycrypt/include
host/nimble/esp-hci/include)
list(APPEND srcs "host/nimble/nimble/ext/tinycrypt/src/utils.c"
"host/nimble/nimble/ext/tinycrypt/src/sha256.c"
"host/nimble/nimble/ext/tinycrypt/src/ecc.c"
"host/nimble/nimble/ext/tinycrypt/src/ctr_prng.c"
"host/nimble/nimble/ext/tinycrypt/src/ctr_mode.c"
"host/nimble/nimble/ext/tinycrypt/src/aes_decrypt.c"
"host/nimble/nimble/ext/tinycrypt/src/aes_encrypt.c"
"host/nimble/nimble/ext/tinycrypt/src/ccm_mode.c"
"host/nimble/nimble/ext/tinycrypt/src/ecc_dsa.c"
"host/nimble/nimble/ext/tinycrypt/src/cmac_mode.c"
"host/nimble/nimble/ext/tinycrypt/src/ecc_dh.c"
"host/nimble/nimble/ext/tinycrypt/src/hmac_prng.c"
"host/nimble/nimble/ext/tinycrypt/src/ecc_platform_specific.c"
"host/nimble/nimble/ext/tinycrypt/src/hmac.c"
"host/nimble/nimble/ext/tinycrypt/src/cbc_mode.c"
"host/nimble/nimble/nimble/host/util/src/addr.c"
"host/nimble/nimble/nimble/host/services/gatt/src/ble_svc_gatt.c"
"host/nimble/nimble/nimble/host/services/tps/src/ble_svc_tps.c"
"host/nimble/nimble/nimble/host/services/ias/src/ble_svc_ias.c"
"host/nimble/nimble/nimble/host/services/ans/src/ble_svc_ans.c"
"host/nimble/nimble/nimble/host/services/gap/src/ble_svc_gap.c"
"host/nimble/nimble/nimble/host/services/bas/src/ble_svc_bas.c"
"host/nimble/nimble/nimble/host/services/lls/src/ble_svc_lls.c"
"host/nimble/nimble/nimble/host/src/ble_hs_conn.c"
"host/nimble/nimble/nimble/host/src/ble_store_util.c"
"host/nimble/nimble/nimble/host/src/ble_sm.c"
"host/nimble/nimble/nimble/host/src/ble_hs_shutdown.c"
"host/nimble/nimble/nimble/host/src/ble_l2cap_sig_cmd.c"
"host/nimble/nimble/nimble/host/src/ble_hs_hci_cmd.c"
"host/nimble/nimble/nimble/host/src/ble_hs_id.c"
"host/nimble/nimble/nimble/host/src/ble_att_svr.c"
"host/nimble/nimble/nimble/host/src/ble_gatts_lcl.c"
"host/nimble/nimble/nimble/host/src/ble_ibeacon.c"
"host/nimble/nimble/nimble/host/src/ble_hs_atomic.c"
"host/nimble/nimble/nimble/host/src/ble_sm_alg.c"
"host/nimble/nimble/nimble/host/src/ble_hs_stop.c"
"host/nimble/nimble/nimble/host/src/ble_hs.c"
"host/nimble/nimble/nimble/host/src/ble_hs_hci_evt.c"
"host/nimble/nimble/nimble/host/src/ble_hs_dbg.c"
"host/nimble/nimble/nimble/host/src/ble_hs_mqueue.c"
"host/nimble/nimble/nimble/host/src/ble_att.c"
"host/nimble/nimble/nimble/host/src/ble_gattc.c"
"host/nimble/nimble/nimble/host/src/ble_store.c"
"host/nimble/nimble/nimble/host/src/ble_sm_lgcy.c"
"host/nimble/nimble/nimble/host/src/ble_hs_cfg.c"
"host/nimble/nimble/nimble/host/src/ble_monitor.c"
"host/nimble/nimble/nimble/host/src/ble_att_clt.c"
"host/nimble/nimble/nimble/host/src/ble_l2cap_coc.c"
"host/nimble/nimble/nimble/host/src/ble_hs_mbuf.c"
"host/nimble/nimble/nimble/host/src/ble_att_cmd.c"
"host/nimble/nimble/nimble/host/src/ble_hs_log.c"
"host/nimble/nimble/nimble/host/src/ble_eddystone.c"
"host/nimble/nimble/nimble/host/src/ble_hs_startup.c"
"host/nimble/nimble/nimble/host/src/ble_l2cap_sig.c"
"host/nimble/nimble/nimble/host/src/ble_gap.c"
"host/nimble/nimble/nimble/host/src/ble_sm_cmd.c"
"host/nimble/nimble/nimble/host/src/ble_uuid.c"
"host/nimble/nimble/nimble/host/src/ble_hs_pvcy.c"
"host/nimble/nimble/nimble/host/src/ble_hs_flow.c"
"host/nimble/nimble/nimble/host/src/ble_l2cap.c"
"host/nimble/nimble/nimble/host/src/ble_sm_sc.c"
"host/nimble/nimble/nimble/host/src/ble_hs_misc.c"
"host/nimble/nimble/nimble/host/src/ble_gatts.c"
"host/nimble/nimble/nimble/host/src/ble_hs_adv.c"
"host/nimble/nimble/nimble/host/src/ble_hs_hci.c"
"host/nimble/nimble/nimble/host/src/ble_hs_hci_util.c"
"host/nimble/nimble/nimble/host/store/ram/src/ble_store_ram.c"
"host/nimble/nimble/nimble/host/store/config/src/ble_store_config.c"
"host/nimble/nimble/nimble/host/store/config/src/ble_store_nvs.c"
"host/nimble/nimble/nimble/src/ble_util.c"
"host/nimble/nimble/porting/npl/freertos/src/nimble_port_freertos.c"
"host/nimble/nimble/porting/npl/freertos/src/npl_os_freertos.c"
"host/nimble/nimble/porting/nimble/src/endian.c"
"host/nimble/nimble/porting/nimble/src/os_cputime_pwr2.c"
"host/nimble/nimble/porting/nimble/src/hal_timer.c"
"host/nimble/nimble/porting/nimble/src/os_mempool.c"
"host/nimble/nimble/porting/nimble/src/os_msys_init.c"
"host/nimble/nimble/porting/nimble/src/nimble_port.c"
"host/nimble/nimble/porting/nimble/src/mem.c"
"host/nimble/nimble/porting/nimble/src/os_mbuf.c"
"host/nimble/nimble/porting/nimble/src/os_cputime.c"
"host/nimble/esp-hci/src/esp_nimble_hci.c")
if(CONFIG_BT_NIMBLE_MESH)
list(APPEND include_dirs
host/nimble/nimble/nimble/host/mesh/include)
list(APPEND srcs "host/nimble/nimble/nimble/host/mesh/src/shell.c"
"host/nimble/nimble/nimble/host/mesh/src/friend.c"
"host/nimble/nimble/nimble/host/mesh/src/crypto.c"
"host/nimble/nimble/nimble/host/mesh/src/settings.c"
"host/nimble/nimble/nimble/host/mesh/src/adv.c"
"host/nimble/nimble/nimble/host/mesh/src/model_srv.c"
"host/nimble/nimble/nimble/host/mesh/src/beacon.c"
"host/nimble/nimble/nimble/host/mesh/src/glue.c"
"host/nimble/nimble/nimble/host/mesh/src/model_cli.c"
"host/nimble/nimble/nimble/host/mesh/src/transport.c"
"host/nimble/nimble/nimble/host/mesh/src/prov.c"
"host/nimble/nimble/nimble/host/mesh/src/mesh.c"
"host/nimble/nimble/nimble/host/mesh/src/access.c"
"host/nimble/nimble/nimble/host/mesh/src/cfg_srv.c"
"host/nimble/nimble/nimble/host/mesh/src/cfg_cli.c"
"host/nimble/nimble/nimble/host/mesh/src/light_model.c"
"host/nimble/nimble/nimble/host/mesh/src/health_cli.c"
"host/nimble/nimble/nimble/host/mesh/src/lpn.c"
"host/nimble/nimble/nimble/host/mesh/src/proxy.c"
"host/nimble/nimble/nimble/host/mesh/src/health_srv.c"
"host/nimble/nimble/nimble/host/mesh/src/testing.c"
"host/nimble/nimble/nimble/host/mesh/src/net.c")
endif()
endif() endif()
endif() endif()
# requirements can't depend on config # requirements can't depend on config
set(COMPONENT_PRIV_REQUIRES nvs_flash soc) idf_component_register(SRCS "${srcs}"
INCLUDE_DIRS "${include_dirs}"
register_component() PRIV_INCLUDE_DIRS "${priv_include_dirs}"
REQUIRES nvs_flash soc)
if(CONFIG_BT_ENABLED) if(CONFIG_BT_ENABLED)
if(GCC_NOT_5_2_0) if(GCC_NOT_5_2_0)
target_compile_options(${COMPONENT_LIB} PRIVATE -Wno-implicit-fallthrough -Wno-unused-const-variable) target_compile_options(${COMPONENT_LIB} PRIVATE -Wno-implicit-fallthrough -Wno-unused-const-variable)
endif() endif()
target_link_libraries(${COMPONENT_LIB} "-L${CMAKE_CURRENT_LIST_DIR}/lib") target_link_libraries(${COMPONENT_LIB} INTERFACE "-L${CMAKE_CURRENT_LIST_DIR}/controller/lib")
target_link_libraries(${COMPONENT_LIB} btdm_app) target_link_libraries(${COMPONENT_LIB} PUBLIC btdm_app)
endif() endif()

File diff suppressed because it is too large Load diff

View file

@ -1,199 +0,0 @@
// Copyright 2015-2016 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 <stdlib.h>
#include <string.h>
#include "common/bt_target.h"
#include "btc/btc_task.h"
#include "common/bt_trace.h"
#include "osi/thread.h"
#include "common/bt_defs.h"
#include "osi/allocator.h"
#include "btc/btc_main.h"
#include "btc/btc_dev.h"
#include "btc_gatts.h"
#include "btc_gattc.h"
#include "btc_gatt_common.h"
#include "btc_gap_ble.h"
#include "btc_blufi_prf.h"
#include "btc/btc_dm.h"
#include "btc/btc_alarm.h"
#include "bta/bta_gatt_api.h"
#if CONFIG_BT_CLASSIC_ENABLED
#include "btc/btc_profile_queue.h"
#if (BTC_GAP_BT_INCLUDED == TRUE)
#include "btc_gap_bt.h"
#endif /* BTC_GAP_BT_INCLUDED == TRUE */
#if BTC_AV_INCLUDED
#include "btc_av.h"
#include "btc_avrc.h"
#endif /* #if BTC_AV_INCLUDED */
#if CONFIG_BT_SPP_ENABLED
#include "btc_spp.h"
#endif /* #if CONFIG_BT_SPP_ENABLED */
#if BTC_HF_CLIENT_INCLUDED
#include "btc_hf_client.h"
#endif /* #if BTC_HF_CLIENT_INCLUDED */
#endif /* #if CONFIG_BT_CLASSIC_ENABLED */
static xTaskHandle xBtcTaskHandle = NULL;
static xQueueHandle xBtcQueue = 0;
static btc_func_t profile_tab[BTC_PID_NUM] = {
[BTC_PID_MAIN_INIT] = {btc_main_call_handler, NULL },
[BTC_PID_DEV] = {btc_dev_call_handler, NULL },
#if (GATTS_INCLUDED == TRUE)
[BTC_PID_GATTS] = {btc_gatts_call_handler, btc_gatts_cb_handler },
#endif ///GATTS_INCLUDED == TRUE
#if (GATTC_INCLUDED == TRUE)
[BTC_PID_GATTC] = {btc_gattc_call_handler, btc_gattc_cb_handler },
#endif ///GATTC_INCLUDED == TRUE
#if (GATTS_INCLUDED == TRUE || GATTC_INCLUDED == TRUE)
[BTC_PID_GATT_COMMON] = {btc_gatt_com_call_handler, NULL },
#endif //GATTC_INCLUDED == TRUE || GATTS_INCLUDED == TRUE
[BTC_PID_GAP_BLE] = {btc_gap_ble_call_handler, btc_gap_ble_cb_handler },
[BTC_PID_BLE_HID] = {NULL, NULL},
[BTC_PID_SPPLIKE] = {NULL, NULL},
#if (GATTS_INCLUDED == TRUE)
[BTC_PID_BLUFI] = {btc_blufi_call_handler, btc_blufi_cb_handler },
#endif ///GATTS_INCLUDED == TRUE
[BTC_PID_DM_SEC] = {NULL, btc_dm_sec_cb_handler },
[BTC_PID_ALARM] = {btc_alarm_handler, NULL },
#if CONFIG_BT_CLASSIC_ENABLED
#if (BTC_GAP_BT_INCLUDED == TRUE)
[BTC_PID_GAP_BT] = {btc_gap_bt_call_handler, btc_gap_bt_cb_handler },
#endif /* (BTC_GAP_BT_INCLUDED == TRUE) */
[BTC_PID_PRF_QUE] = {btc_profile_queue_handler, NULL },
#if BTC_AV_INCLUDED
[BTC_PID_A2DP] = {btc_a2dp_call_handler, btc_a2dp_cb_handler },
[BTC_PID_AVRC_CT] = {btc_avrc_ct_call_handler, NULL },
[BTC_PID_AVRC_TG] = {btc_avrc_tg_call_handler, NULL },
#endif /* #if BTC_AV_INCLUDED */
#if CONFIG_BT_SPP_ENABLED
[BTC_PID_SPP] = {btc_spp_call_handler, btc_spp_cb_handler },
#endif /* #if CONFIG_BT_SPP_ENABLED */
#if BTC_HF_CLIENT_INCLUDED
[BTC_PID_HF_CLIENT] = {btc_hf_client_call_handler, btc_hf_client_cb_handler},
#endif /* #if BTC_HF_CLIENT_INCLUDED */
#endif /* #if CONFIG_BT_CLASSIC_ENABLED */
};
/*****************************************************************************
**
** Function btc_task
**
** Description Process profile Task Thread.
******************************************************************************/
static void btc_task(void *arg)
{
btc_msg_t msg;
for (;;) {
if (pdTRUE == xQueueReceive(xBtcQueue, &msg, (portTickType)portMAX_DELAY)) {
BTC_TRACE_DEBUG("%s msg %u %u %u %p\n", __func__, msg.sig, msg.pid, msg.act, msg.arg);
switch (msg.sig) {
case BTC_SIG_API_CALL:
profile_tab[msg.pid].btc_call(&msg);
break;
case BTC_SIG_API_CB:
profile_tab[msg.pid].btc_cb(&msg);
break;
default:
break;
}
if (msg.arg) {
osi_free(msg.arg);
}
}
}
}
static bt_status_t btc_task_post(btc_msg_t *msg, task_post_t timeout)
{
if (msg == NULL) {
return BT_STATUS_PARM_INVALID;
}
if (xQueueSend(xBtcQueue, msg, timeout) != pdTRUE) {
BTC_TRACE_ERROR("Btc Post failed\n");
return BT_STATUS_BUSY;
}
return BT_STATUS_SUCCESS;
}
bt_status_t btc_transfer_context(btc_msg_t *msg, void *arg, int arg_len, btc_arg_deep_copy_t copy_func)
{
btc_msg_t lmsg;
if (msg == NULL) {
return BT_STATUS_PARM_INVALID;
}
BTC_TRACE_DEBUG("%s msg %u %u %u %p\n", __func__, msg->sig, msg->pid, msg->act, arg);
memcpy(&lmsg, msg, sizeof(btc_msg_t));
if (arg) {
lmsg.arg = (void *)osi_malloc(arg_len);
if (lmsg.arg == NULL) {
return BT_STATUS_NOMEM;
}
memset(lmsg.arg, 0x00, arg_len); //important, avoid arg which have no length
memcpy(lmsg.arg, arg, arg_len);
if (copy_func) {
copy_func(&lmsg, lmsg.arg, arg);
}
} else {
lmsg.arg = NULL;
}
return btc_task_post(&lmsg, TASK_POST_BLOCKING);
}
int btc_init(void)
{
xBtcQueue = xQueueCreate(BTC_TASK_QUEUE_LEN, sizeof(btc_msg_t));
xTaskCreatePinnedToCore(btc_task, "Btc_task", BTC_TASK_STACK_SIZE, NULL, BTC_TASK_PRIO, &xBtcTaskHandle, BTC_TASK_PINNED_TO_CORE);
if (xBtcTaskHandle == NULL || xBtcQueue == 0){
return BT_STATUS_NOMEM;
}
btc_gap_callback_init();
#if SCAN_QUEUE_CONGEST_CHECK
btc_adv_list_init();
#endif
/* TODO: initial the profile_tab */
return BT_STATUS_SUCCESS;
}
void btc_deinit(void)
{
vTaskDelete(xBtcTaskHandle);
vQueueDelete(xBtcQueue);
#if SCAN_QUEUE_CONGEST_CHECK
btc_adv_list_deinit();
#endif
xBtcTaskHandle = NULL;
xBtcQueue = 0;
}
bool btc_check_queue_is_congest(void)
{
UBaseType_t wait_size = uxQueueMessagesWaiting(xBtcQueue);
if(wait_size >= QUEUE_CONGEST_SIZE) {
return true;
}
return false;
}

View file

@ -1,552 +0,0 @@
/******************************************************************************
*
* Copyright (C) 2014 Google, Inc.
*
* 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 <stdbool.h>
#include "common/bt_target.h"
#include "common/bt_trace.h"
#include "device/bdaddr.h"
#include "stack/bt_types.h"
#include "device/controller.h"
#include "device/event_mask.h"
#include "stack/hcimsgs.h"
#include "hci/hci_layer.h"
#include "hci/hci_packet_factory.h"
#include "hci/hci_packet_parser.h"
#include "stack/btm_ble_api.h"
#include "device/version.h"
#include "osi/future.h"
const bt_event_mask_t BLE_EVENT_MASK = { "\x00\x00\x00\x00\x00\x00\x06\x7f" };
#if (BLE_INCLUDED)
const bt_event_mask_t CLASSIC_EVENT_MASK = { HCI_DUMO_EVENT_MASK_EXT };
#else
const bt_event_mask_t CLASSIC_EVENT_MASK = { HCI_LISBON_EVENT_MASK_EXT };
#endif
// TODO(zachoverflow): factor out into common module
const uint8_t SCO_HOST_BUFFER_SIZE = 0xff;
#define HCI_SUPPORTED_COMMANDS_ARRAY_SIZE 64
#define MAX_FEATURES_CLASSIC_PAGE_COUNT 3
#define BLE_SUPPORTED_STATES_SIZE 8
#define BLE_SUPPORTED_FEATURES_SIZE 8
static const hci_t *hci;
static const hci_packet_factory_t *packet_factory;
static const hci_packet_parser_t *packet_parser;
static bt_bdaddr_t address;
static bt_version_t bt_version;
static uint8_t supported_commands[HCI_SUPPORTED_COMMANDS_ARRAY_SIZE];
static bt_device_features_t features_classic[MAX_FEATURES_CLASSIC_PAGE_COUNT];
static uint8_t last_features_classic_page_index;
static uint16_t acl_data_size_classic;
static uint16_t acl_data_size_ble;
static uint16_t acl_buffer_count_classic;
static uint8_t acl_buffer_count_ble;
static uint8_t sco_data_size;
static uint16_t sco_buffer_count;
static uint8_t ble_white_list_size;
static uint8_t ble_resolving_list_max_size;
static uint8_t ble_supported_states[BLE_SUPPORTED_STATES_SIZE];
static bt_device_features_t features_ble;
static uint16_t ble_suggested_default_data_length;
static uint16_t ble_suggested_default_data_txtime;
static bool readable;
static bool ble_supported;
static bool simple_pairing_supported;
static bool secure_connections_supported;
#define AWAIT_COMMAND(command) future_await(hci->transmit_command_futured(command))
// Module lifecycle functions
static void start_up(void)
{
BT_HDR *response;
// Send the initial reset command
response = AWAIT_COMMAND(packet_factory->make_reset());
packet_parser->parse_generic_command_complete(response);
// Request the classic buffer size next
response = AWAIT_COMMAND(packet_factory->make_read_buffer_size());
packet_parser->parse_read_buffer_size_response(
response, &acl_data_size_classic, &acl_buffer_count_classic,
&sco_data_size, &sco_buffer_count);
#if (C2H_FLOW_CONTROL_INCLUDED == TRUE)
// Enable controller to host flow control
response = AWAIT_COMMAND(packet_factory->make_set_c2h_flow_control(HCI_HOST_FLOW_CTRL_ACL_ON));
packet_parser->parse_generic_command_complete(response);
#endif ///C2H_FLOW_CONTROL_INCLUDED == TRUE
#if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE)
// Enable adv flow control
response = AWAIT_COMMAND(packet_factory->make_set_adv_report_flow_control(HCI_HOST_FLOW_CTRL_ADV_REPORT_ON, (uint16_t)BLE_ADV_REPORT_FLOW_CONTROL_NUM, (uint16_t)BLE_ADV_REPORT_DISCARD_THRSHOLD));
packet_parser->parse_generic_command_complete(response);
#endif
// Tell the controller about our buffer sizes and buffer counts next
// TODO(zachoverflow): factor this out. eww l2cap contamination. And why just a hardcoded 10?
response = AWAIT_COMMAND(
packet_factory->make_host_buffer_size(
L2CAP_MTU_SIZE,
SCO_HOST_BUFFER_SIZE,
L2CAP_HOST_FC_ACL_BUFS,
10
)
);
packet_parser->parse_generic_command_complete(response);
// Read the local version info off the controller next, including
// information such as manufacturer and supported HCI version
response = AWAIT_COMMAND(packet_factory->make_read_local_version_info());
packet_parser->parse_read_local_version_info_response(response, &bt_version);
// Read the bluetooth address off the controller next
response = AWAIT_COMMAND(packet_factory->make_read_bd_addr());
packet_parser->parse_read_bd_addr_response(response, &address);
// Request the controller's supported commands next
response = AWAIT_COMMAND(packet_factory->make_read_local_supported_commands());
packet_parser->parse_read_local_supported_commands_response(
response,
supported_commands,
HCI_SUPPORTED_COMMANDS_ARRAY_SIZE
);
// Read page 0 of the controller features next
uint8_t page_number = 0;
response = AWAIT_COMMAND(packet_factory->make_read_local_extended_features(page_number));
packet_parser->parse_read_local_extended_features_response(
response,
&page_number,
&last_features_classic_page_index,
features_classic,
MAX_FEATURES_CLASSIC_PAGE_COUNT
);
assert(page_number == 0);
page_number++;
// Inform the controller what page 0 features we support, based on what
// it told us it supports. We need to do this first before we request the
// next page, because the controller's response for page 1 may be
// dependent on what we configure from page 0
#if (BT_SSP_INCLUDED == TRUE)
simple_pairing_supported = HCI_SIMPLE_PAIRING_SUPPORTED(features_classic[0].as_array);
#else
simple_pairing_supported = false;
#endif
if (simple_pairing_supported) {
response = AWAIT_COMMAND(packet_factory->make_write_simple_pairing_mode(HCI_SP_MODE_ENABLED));
packet_parser->parse_generic_command_complete(response);
}
#if (BLE_INCLUDED == TRUE)
if (HCI_LE_SPT_SUPPORTED(features_classic[0].as_array)) {
uint8_t simultaneous_le_host = HCI_SIMUL_LE_BREDR_SUPPORTED(features_classic[0].as_array) ? BTM_BLE_SIMULTANEOUS_HOST : 0;
response = AWAIT_COMMAND(
packet_factory->make_ble_write_host_support(BTM_BLE_HOST_SUPPORT, simultaneous_le_host)
);
packet_parser->parse_generic_command_complete(response);
}
#endif
// Done telling the controller about what page 0 features we support
// Request the remaining feature pages
while (page_number <= last_features_classic_page_index &&
page_number < MAX_FEATURES_CLASSIC_PAGE_COUNT) {
response = AWAIT_COMMAND(packet_factory->make_read_local_extended_features(page_number));
packet_parser->parse_read_local_extended_features_response(
response,
&page_number,
&last_features_classic_page_index,
features_classic,
MAX_FEATURES_CLASSIC_PAGE_COUNT
);
page_number++;
}
#if (SC_MODE_INCLUDED == TRUE)
secure_connections_supported = HCI_SC_CTRLR_SUPPORTED(features_classic[2].as_array);
if (secure_connections_supported) {
response = AWAIT_COMMAND(packet_factory->make_write_secure_connections_host_support(HCI_SC_MODE_ENABLED));
packet_parser->parse_generic_command_complete(response);
}
#endif
#if (BLE_INCLUDED == TRUE)
ble_supported = last_features_classic_page_index >= 1 && HCI_LE_HOST_SUPPORTED(features_classic[1].as_array);
if (ble_supported) {
// Request the ble white list size next
response = AWAIT_COMMAND(packet_factory->make_ble_read_white_list_size());
packet_parser->parse_ble_read_white_list_size_response(response, &ble_white_list_size);
// Request the ble buffer size next
response = AWAIT_COMMAND(packet_factory->make_ble_read_buffer_size());
packet_parser->parse_ble_read_buffer_size_response(
response,
&acl_data_size_ble,
&acl_buffer_count_ble
);
// Response of 0 indicates ble has the same buffer size as classic
if (acl_data_size_ble == 0) {
acl_data_size_ble = acl_data_size_classic;
}
// Request the ble supported states next
response = AWAIT_COMMAND(packet_factory->make_ble_read_supported_states());
packet_parser->parse_ble_read_supported_states_response(
response,
ble_supported_states,
sizeof(ble_supported_states)
);
// Request the ble supported features next
response = AWAIT_COMMAND(packet_factory->make_ble_read_local_supported_features());
packet_parser->parse_ble_read_local_supported_features_response(
response,
&features_ble
);
if (HCI_LE_ENHANCED_PRIVACY_SUPPORTED(features_ble.as_array)) {
response = AWAIT_COMMAND(packet_factory->make_ble_read_resolving_list_size());
packet_parser->parse_ble_read_resolving_list_size_response(
response,
&ble_resolving_list_max_size);
}
if (HCI_LE_DATA_LEN_EXT_SUPPORTED(features_ble.as_array)) {
/* set default tx data length to MAX 251 */
response = AWAIT_COMMAND(packet_factory->make_ble_write_suggested_default_data_length(BTM_BLE_DATA_SIZE_MAX, BTM_BLE_DATA_TX_TIME_MAX));
packet_parser->parse_generic_command_complete(response);
response = AWAIT_COMMAND(packet_factory->make_ble_read_suggested_default_data_length());
packet_parser->parse_ble_read_suggested_default_data_length_response(
response,
&ble_suggested_default_data_length,
&ble_suggested_default_data_txtime);
}
// Set the ble event mask next
response = AWAIT_COMMAND(packet_factory->make_ble_set_event_mask(&BLE_EVENT_MASK));
packet_parser->parse_generic_command_complete(response);
}
#endif
response = AWAIT_COMMAND(packet_factory->make_set_event_mask(&CLASSIC_EVENT_MASK));
packet_parser->parse_generic_command_complete(response);
#if (BTM_SCO_HCI_INCLUDED == TRUE)
response = AWAIT_COMMAND(packet_factory->make_write_sync_flow_control_enable(1));
packet_parser->parse_generic_command_complete(response);
response = AWAIT_COMMAND(packet_factory->make_write_default_erroneous_data_report(1));
packet_parser->parse_generic_command_complete(response);
#endif
readable = true;
// return future_new_immediate(FUTURE_SUCCESS);
return;
}
static void shut_down(void)
{
readable = false;
}
static bool get_is_ready(void)
{
return readable;
}
static const bt_bdaddr_t *get_address(void)
{
assert(readable);
return &address;
}
static const bt_version_t *get_bt_version(void)
{
assert(readable);
return &bt_version;
}
// TODO(zachoverflow): hide inside, move decoder inside too
static const bt_device_features_t *get_features_classic(int index)
{
assert(readable);
assert(index < MAX_FEATURES_CLASSIC_PAGE_COUNT);
return &features_classic[index];
}
static uint8_t get_last_features_classic_index(void)
{
assert(readable);
return last_features_classic_page_index;
}
static const bt_device_features_t *get_features_ble(void)
{
assert(readable);
assert(ble_supported);
return &features_ble;
}
static const uint8_t *get_ble_supported_states(void)
{
assert(readable);
assert(ble_supported);
return ble_supported_states;
}
static bool supports_simple_pairing(void)
{
assert(readable);
return simple_pairing_supported;
}
static bool supports_secure_connections(void)
{
assert(readable);
return secure_connections_supported;
}
static bool supports_simultaneous_le_bredr(void)
{
assert(readable);
return HCI_SIMUL_LE_BREDR_SUPPORTED(features_classic[0].as_array);
}
static bool supports_reading_remote_extended_features(void)
{
assert(readable);
return HCI_READ_REMOTE_EXT_FEATURES_SUPPORTED(supported_commands);
}
static bool supports_interlaced_inquiry_scan(void)
{
assert(readable);
return HCI_LMP_INTERLACED_INQ_SCAN_SUPPORTED(features_classic[0].as_array);
}
static bool supports_rssi_with_inquiry_results(void)
{
assert(readable);
return HCI_LMP_INQ_RSSI_SUPPORTED(features_classic[0].as_array);
}
static bool supports_extended_inquiry_response(void)
{
assert(readable);
return HCI_EXT_INQ_RSP_SUPPORTED(features_classic[0].as_array);
}
static bool supports_master_slave_role_switch(void)
{
assert(readable);
return HCI_SWITCH_SUPPORTED(features_classic[0].as_array);
}
static bool supports_ble(void)
{
assert(readable);
return ble_supported;
}
static bool supports_ble_privacy(void)
{
assert(readable);
assert(ble_supported);
return HCI_LE_ENHANCED_PRIVACY_SUPPORTED(features_ble.as_array);
}
static bool supports_ble_packet_extension(void)
{
assert(readable);
assert(ble_supported);
return HCI_LE_DATA_LEN_EXT_SUPPORTED(features_ble.as_array);
}
static bool supports_ble_connection_parameters_request(void)
{
assert(readable);
assert(ble_supported);
return HCI_LE_CONN_PARAM_REQ_SUPPORTED(features_ble.as_array);
}
static uint16_t get_acl_data_size_classic(void)
{
assert(readable);
return acl_data_size_classic;
}
static uint16_t get_acl_data_size_ble(void)
{
assert(readable);
assert(ble_supported);
return acl_data_size_ble;
}
static uint16_t get_acl_packet_size_classic(void)
{
assert(readable);
return acl_data_size_classic + HCI_DATA_PREAMBLE_SIZE;
}
static uint16_t get_acl_packet_size_ble(void)
{
assert(readable);
return acl_data_size_ble + HCI_DATA_PREAMBLE_SIZE;
}
static uint16_t get_ble_suggested_default_data_length(void)
{
assert(readable);
assert(ble_supported);
return ble_suggested_default_data_length;
}
static uint16_t get_ble_suggested_default_data_txtime(void)
{
assert(readable);
assert(ble_supported);
return ble_suggested_default_data_txtime;
}
static uint16_t get_acl_buffer_count_classic(void)
{
assert(readable);
return acl_buffer_count_classic;
}
static uint8_t get_acl_buffer_count_ble(void)
{
assert(readable);
assert(ble_supported);
return acl_buffer_count_ble;
}
static uint8_t get_ble_white_list_size(void)
{
assert(readable);
assert(ble_supported);
return ble_white_list_size;
}
static uint8_t get_ble_resolving_list_max_size(void)
{
assert(readable);
assert(ble_supported);
return ble_resolving_list_max_size;
}
static void set_ble_resolving_list_max_size(int resolving_list_max_size)
{
assert(readable);
assert(ble_supported);
ble_resolving_list_max_size = resolving_list_max_size;
}
#if (BTM_SCO_HCI_INCLUDED == TRUE)
static uint8_t get_sco_data_size(void)
{
assert(readable);
return sco_data_size;
}
static uint8_t get_sco_buffer_count(void)
{
assert(readable);
return sco_buffer_count;
}
#endif /* (BTM_SCO_HCI_INCLUDED == TRUE) */
static const controller_t interface = {
start_up,
shut_down,
get_is_ready,
get_address,
get_bt_version,
get_features_classic,
get_last_features_classic_index,
get_features_ble,
get_ble_supported_states,
supports_simple_pairing,
supports_secure_connections,
supports_simultaneous_le_bredr,
supports_reading_remote_extended_features,
supports_interlaced_inquiry_scan,
supports_rssi_with_inquiry_results,
supports_extended_inquiry_response,
supports_master_slave_role_switch,
supports_ble,
supports_ble_packet_extension,
supports_ble_connection_parameters_request,
supports_ble_privacy,
get_acl_data_size_classic,
get_acl_data_size_ble,
get_acl_packet_size_classic,
get_acl_packet_size_ble,
get_ble_suggested_default_data_length,
get_ble_suggested_default_data_txtime,
get_acl_buffer_count_classic,
get_acl_buffer_count_ble,
get_ble_white_list_size,
get_ble_resolving_list_max_size,
set_ble_resolving_list_max_size,
#if (BTM_SCO_HCI_INCLUDED == TRUE)
get_sco_data_size,
get_sco_buffer_count,
#endif /* (BTM_SCO_HCI_INCLUDED == TRUE) */
};
const controller_t *controller_get_interface()
{
static bool loaded = false;
if (!loaded) {
loaded = true;
hci = hci_layer_get_interface();
packet_factory = hci_packet_factory_get_interface();
packet_parser = hci_packet_parser_get_interface();
}
return &interface;
}

View file

@ -1,115 +0,0 @@
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef __THREAD_H__
#define __THREAD_H__
#include "freertos/xtensa_api.h"
#include "freertos/FreeRTOSConfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"
#include "freertos/task.h"
#include "esp_task.h"
#include "common/bt_defs.h"
#define portBASE_TYPE int
struct bt_task_evt {
uint32_t sig; //task sig
void *par; //point to task param
void *cb; //point to function cb
void *arg; //point to function arg
};
typedef struct bt_task_evt BtTaskEvt_t;
typedef bt_status_t (* BtTaskCb_t)(void *arg);
typedef enum {
SIG_HCI_HAL_RECV_PACKET = 0,
SIG_HCI_HAL_NUM,
} SIG_HCI_HAL_t;
typedef enum {
SIG_HCI_HOST_SEND_AVAILABLE = 0,
SIG_HCI_HOST_NUM,
} SIG_HCI_HOST_t;
typedef enum {
SIG_BTU_START_UP = 0,
SIG_BTU_HCI_MSG,
SIG_BTU_BTA_MSG,
SIG_BTU_BTA_ALARM,
SIG_BTU_GENERAL_ALARM,
SIG_BTU_ONESHOT_ALARM,
SIG_BTU_L2CAP_ALARM,
SIG_BTU_NUM,
} SIG_BTU_t;
#define TASK_PINNED_TO_CORE (CONFIG_BT_BLUEDROID_PINNED_TO_CORE < portNUM_PROCESSORS ? CONFIG_BT_BLUEDROID_PINNED_TO_CORE : tskNO_AFFINITY)
#define HCI_HOST_TASK_PINNED_TO_CORE (TASK_PINNED_TO_CORE)
#define HCI_HOST_TASK_STACK_SIZE (2048 + BT_TASK_EXTRA_STACK_SIZE)
#define HCI_HOST_TASK_PRIO (configMAX_PRIORITIES - 3)
#define HCI_HOST_TASK_NAME "hciHostT"
#define HCI_HOST_QUEUE_LEN 40
#define HCI_H4_TASK_PINNED_TO_CORE (TASK_PINNED_TO_CORE)
#define HCI_H4_TASK_STACK_SIZE (2048 + BT_TASK_EXTRA_STACK_SIZE)
#define HCI_H4_TASK_PRIO (configMAX_PRIORITIES - 4)
#define HCI_H4_TASK_NAME "hciH4T"
#define HCI_H4_QUEUE_LEN 1
#define BTU_TASK_PINNED_TO_CORE (TASK_PINNED_TO_CORE)
#define BTU_TASK_STACK_SIZE (CONFIG_BT_BTU_TASK_STACK_SIZE + BT_TASK_EXTRA_STACK_SIZE)
#define BTU_TASK_PRIO (configMAX_PRIORITIES - 5)
#define BTU_TASK_NAME "btuT"
#define BTU_QUEUE_LEN 50
#define BTC_TASK_PINNED_TO_CORE (TASK_PINNED_TO_CORE)
#define BTC_TASK_STACK_SIZE (CONFIG_BT_BTC_TASK_STACK_SIZE + BT_TASK_EXTRA_STACK_SIZE) //by menuconfig
#define BTC_TASK_NAME "btcT"
#define BTC_TASK_PRIO (configMAX_PRIORITIES - 6)
#define BTC_TASK_QUEUE_LEN 60
#define BTC_A2DP_SINK_TASK_PINNED_TO_CORE (TASK_PINNED_TO_CORE)
#define BTC_A2DP_SINK_TASK_STACK_SIZE (CONFIG_BT_A2DP_SINK_TASK_STACK_SIZE + BT_TASK_EXTRA_STACK_SIZE) // by menuconfig
#define BTC_A2DP_SINK_TASK_NAME "BtA2dSinkT"
#define BTC_A2DP_SINK_TASK_PRIO (configMAX_PRIORITIES - 3)
#define BTC_A2DP_SINK_DATA_QUEUE_LEN (3)
#define BTC_A2DP_SINK_CTRL_QUEUE_LEN (5)
#define BTC_A2DP_SINK_TASK_QUEUE_SET_LEN (BTC_A2DP_SINK_DATA_QUEUE_LEN + BTC_A2DP_SINK_CTRL_QUEUE_LEN)
#define BTC_A2DP_SOURCE_TASK_PINNED_TO_CORE (TASK_PINNED_TO_CORE)
#define BTC_A2DP_SOURCE_TASK_STACK_SIZE (CONFIG_BT_A2DP_SOURCE_TASK_STACK_SIZE + BT_TASK_EXTRA_STACK_SIZE) // by menuconfig
#define BTC_A2DP_SOURCE_TASK_NAME "BtA2dSourceT"
#define BTC_A2DP_SOURCE_TASK_PRIO (configMAX_PRIORITIES - 3)
#define BTC_A2DP_SOURCE_DATA_QUEUE_LEN (1)
#define BTC_A2DP_SOURCE_CTRL_QUEUE_LEN (5)
#define BTC_A2DP_SOURCE_TASK_QUEUE_SET_LEN (BTC_A2DP_SOURCE_DATA_QUEUE_LEN + BTC_A2DP_SOURCE_CTRL_QUEUE_LEN)
#define TASK_POST_NON_BLOCKING (0)
#define TASK_POST_BLOCKING (portMAX_DELAY)
typedef uint32_t task_post_t; /* Timeout of task post return, unit TICK */
typedef enum {
TASK_POST_SUCCESS = 0,
TASK_POST_FAIL,
} task_post_status_t;
task_post_status_t btu_task_post(uint32_t sig, void *param, task_post_t timeout);
task_post_status_t hci_host_task_post(task_post_t timeout);
task_post_status_t hci_hal_h4_task_post(task_post_t timeout);
#endif /* __THREAD_H__ */

View file

@ -14,6 +14,7 @@
#include "btc/btc_task.h" #include "btc/btc_task.h"
#include "btc/btc_alarm.h" #include "btc/btc_alarm.h"
#include "esp_log.h"
void btc_alarm_handler(btc_msg_t *msg) void btc_alarm_handler(btc_msg_t *msg)
{ {

View file

@ -14,12 +14,13 @@
#include "btc/btc_task.h" #include "btc/btc_task.h"
#include "common/bt_trace.h"
#include "osi/thread.h" #include "osi/thread.h"
#include "esp_bt_defs.h"
#include "esp_gatt_defs.h"
static void *btc_profile_cb_tab[BTC_PID_NUM] = {}; #if BTC_DYNAMIC_MEMORY == FALSE
void *btc_profile_cb_tab[BTC_PID_NUM] = {};
#else
void **btc_profile_cb_tab;
#endif
void esp_profile_cb_reset(void) void esp_profile_cb_reset(void)
{ {

View file

@ -0,0 +1,368 @@
// Copyright 2015-2016 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 <stdlib.h>
#include <string.h>
#include "btc/btc_task.h"
#include "osi/thread.h"
#include "esp_log.h"
#include "bt_common.h"
#include "osi/allocator.h"
#ifdef CONFIG_BT_BLUEDROID_ENABLED
#include "common/bt_target.h"
#include "btc/btc_main.h"
#include "btc/btc_manage.h"
#include "btc/btc_dev.h"
#include "btc_gatts.h"
#include "btc_gattc.h"
#include "btc_gatt_common.h"
#include "btc_gap_ble.h"
#include "btc_blufi_prf.h"
#include "blufi_int.h"
#include "btc/btc_dm.h"
#include "btc/btc_alarm.h"
#include "bta/bta_gatt_api.h"
#if CLASSIC_BT_INCLUDED
#include "btc/btc_profile_queue.h"
#if (BTC_GAP_BT_INCLUDED == TRUE)
#include "btc_gap_bt.h"
#endif /* BTC_GAP_BT_INCLUDED == TRUE */
#if BTC_AV_INCLUDED
#include "btc_av.h"
#include "btc_avrc.h"
#include "btc_av_co.h"
#endif /* #if BTC_AV_INCLUDED */
#if (BTC_SPP_INCLUDED == TRUE)
#include "btc_spp.h"
#endif /* #if (BTC_SPP_INCLUDED == TRUE) */
#if BTC_HF_CLIENT_INCLUDED
#include "btc_hf_client.h"
#endif /* #if BTC_HF_CLIENT_INCLUDED */
#endif /* #if CLASSIC_BT_INCLUDED */
#endif
#if CONFIG_BLE_MESH
#include "btc_ble_mesh_prov.h"
#include "btc_ble_mesh_health_model.h"
#include "btc_ble_mesh_config_model.h"
#include "btc_ble_mesh_generic_model.h"
#include "btc_ble_mesh_lighting_model.h"
#include "btc_ble_mesh_sensor_model.h"
#include "btc_ble_mesh_time_scene_model.h"
#endif /* #if CONFIG_BLE_MESH */
#define BTC_TASK_PINNED_TO_CORE (TASK_PINNED_TO_CORE)
#define BTC_TASK_STACK_SIZE (BT_BTC_TASK_STACK_SIZE + BT_TASK_EXTRA_STACK_SIZE) //by menuconfig
#define BTC_TASK_NAME "btcT"
#define BTC_TASK_PRIO (BT_TASK_MAX_PRIORITIES - 6)
osi_thread_t *btc_thread;
static const btc_func_t profile_tab[BTC_PID_NUM] = {
#ifdef CONFIG_BT_BLUEDROID_ENABLED
[BTC_PID_MAIN_INIT] = {btc_main_call_handler, NULL },
[BTC_PID_DEV] = {btc_dev_call_handler, NULL },
#if (GATTS_INCLUDED == TRUE)
[BTC_PID_GATTS] = {btc_gatts_call_handler, btc_gatts_cb_handler },
#endif ///GATTS_INCLUDED == TRUE
#if (GATTC_INCLUDED == TRUE)
[BTC_PID_GATTC] = {btc_gattc_call_handler, btc_gattc_cb_handler },
#endif ///GATTC_INCLUDED == TRUE
#if (GATTS_INCLUDED == TRUE || GATTC_INCLUDED == TRUE)
[BTC_PID_GATT_COMMON] = {btc_gatt_com_call_handler, NULL },
#endif //GATTC_INCLUDED == TRUE || GATTS_INCLUDED == TRUE
#if (BLE_INCLUDED == TRUE)
[BTC_PID_GAP_BLE] = {btc_gap_ble_call_handler, btc_gap_ble_cb_handler },
#else
[BTC_PID_GAP_BLE] = {NULL, NULL},
#endif ///BLE_INCLUDED == TRUE
[BTC_PID_BLE_HID] = {NULL, NULL},
[BTC_PID_SPPLIKE] = {NULL, NULL},
#if (GATTS_INCLUDED == TRUE)
[BTC_PID_BLUFI] = {btc_blufi_call_handler, btc_blufi_cb_handler },
#endif ///GATTS_INCLUDED == TRUE
[BTC_PID_DM_SEC] = {NULL, btc_dm_sec_cb_handler },
[BTC_PID_ALARM] = {btc_alarm_handler, NULL },
#if CLASSIC_BT_INCLUDED
#if (BTC_GAP_BT_INCLUDED == TRUE)
[BTC_PID_GAP_BT] = {btc_gap_bt_call_handler, btc_gap_bt_cb_handler },
#endif /* (BTC_GAP_BT_INCLUDED == TRUE) */
[BTC_PID_PRF_QUE] = {btc_profile_queue_handler, NULL },
#if BTC_AV_INCLUDED
[BTC_PID_A2DP] = {btc_a2dp_call_handler, btc_a2dp_cb_handler },
[BTC_PID_AVRC_CT] = {btc_avrc_ct_call_handler, NULL },
[BTC_PID_AVRC_TG] = {btc_avrc_tg_call_handler, NULL },
#endif /* #if BTC_AV_INCLUDED */
#if (BTC_SPP_INCLUDED == TRUE)
[BTC_PID_SPP] = {btc_spp_call_handler, btc_spp_cb_handler },
#endif /* #if (BTC_SPP_INCLUDED == TRUE) */
#if BTC_HF_CLIENT_INCLUDED
[BTC_PID_HF_CLIENT] = {btc_hf_client_call_handler, btc_hf_client_cb_handler},
#endif /* #if BTC_HF_CLIENT_INCLUDED */
#endif /* #if CLASSIC_BT_INCLUDED */
#endif
#if CONFIG_BLE_MESH
[BTC_PID_PROV] = {btc_mesh_prov_call_handler, btc_mesh_prov_cb_handler},
[BTC_PID_MODEL] = {btc_mesh_model_call_handler, btc_mesh_model_cb_handler},
[BTC_PID_HEALTH_CLIENT] = {btc_mesh_health_client_call_handler, btc_mesh_health_client_cb_handler},
[BTC_PID_HEALTH_SERVER] = {btc_mesh_health_server_call_handler, btc_mesh_health_server_cb_handler},
[BTC_PID_CFG_CLIENT] = {btc_mesh_cfg_client_call_handler, btc_mesh_cfg_client_cb_handler},
[BTC_PID_CFG_SERVER] = {NULL , btc_mesh_cfg_server_cb_handler},
[BTC_PID_GENERIC_CLIENT] = {btc_mesh_generic_client_call_handler, btc_mesh_generic_client_cb_handler},
[BTC_PID_LIGHT_CLIENT] = {btc_mesh_light_client_call_handler, btc_mesh_light_client_cb_handler},
[BTC_PID_SENSOR_CLIENT] = {btc_mesh_sensor_client_call_handler, btc_mesh_sensor_client_cb_handler},
[BTC_PID_TIME_SCENE_CLIENT] = {btc_mesh_time_scene_client_call_handler, btc_mesh_time_scene_client_cb_handler},
#endif /* #if CONFIG_BLE_MESH */
};
/*****************************************************************************
**
** Function btc_task
**
** Description Process profile Task Thread.
******************************************************************************/
static void btc_thread_handler(void *arg)
{
btc_msg_t *msg = (btc_msg_t *)arg;
BTC_TRACE_DEBUG("%s msg %u %u %u %p\n", __func__, msg->sig, msg->pid, msg->act, msg->arg);
switch (msg->sig) {
case BTC_SIG_API_CALL:
profile_tab[msg->pid].btc_call(msg);
break;
case BTC_SIG_API_CB:
profile_tab[msg->pid].btc_cb(msg);
break;
default:
break;
}
if (msg->arg) {
osi_free(msg->arg);
}
osi_free(msg);
}
static bt_status_t btc_task_post(btc_msg_t *msg, uint32_t timeout)
{
btc_msg_t *lmsg;
lmsg = (btc_msg_t *)osi_malloc(sizeof(btc_msg_t));
if (lmsg == NULL) {
return BT_STATUS_NOMEM;
}
memcpy(lmsg, msg, sizeof(btc_msg_t));
if (osi_thread_post(btc_thread, btc_thread_handler, lmsg, 0, timeout) == false) {
return BT_STATUS_BUSY;
}
return BT_STATUS_SUCCESS;
}
bt_status_t btc_transfer_context(btc_msg_t *msg, void *arg, int arg_len, btc_arg_deep_copy_t copy_func)
{
btc_msg_t lmsg;
if (msg == NULL) {
return BT_STATUS_PARM_INVALID;
}
BTC_TRACE_DEBUG("%s msg %u %u %u %p\n", __func__, msg->sig, msg->pid, msg->act, arg);
memcpy(&lmsg, msg, sizeof(btc_msg_t));
if (arg) {
lmsg.arg = (void *)osi_malloc(arg_len);
if (lmsg.arg == NULL) {
return BT_STATUS_NOMEM;
}
memset(lmsg.arg, 0x00, arg_len); //important, avoid arg which have no length
memcpy(lmsg.arg, arg, arg_len);
if (copy_func) {
copy_func(&lmsg, lmsg.arg, arg);
}
} else {
lmsg.arg = NULL;
}
return btc_task_post(&lmsg, OSI_THREAD_MAX_TIMEOUT);
}
#if BTC_DYNAMIC_MEMORY
static void btc_deinit_mem(void) {
if (btc_dm_cb_ptr) {
osi_free(btc_dm_cb_ptr);
btc_dm_cb_ptr = NULL;
}
if (btc_profile_cb_tab) {
osi_free(btc_profile_cb_tab);
btc_profile_cb_tab = NULL;
}
#if (BLE_INCLUDED == TRUE)
if (gl_bta_adv_data_ptr) {
osi_free(gl_bta_adv_data_ptr);
gl_bta_adv_data_ptr = NULL;
}
if (gl_bta_scan_rsp_data_ptr) {
osi_free(gl_bta_scan_rsp_data_ptr);
gl_bta_scan_rsp_data_ptr = NULL;
}
#endif ///BLE_INCLUDED == TRUE
#if GATTS_INCLUDED == TRUE && GATT_DYNAMIC_MEMORY == TRUE
if (btc_creat_tab_env_ptr) {
osi_free(btc_creat_tab_env_ptr);
btc_creat_tab_env_ptr = NULL;
}
if (blufi_env_ptr) {
osi_free(blufi_env_ptr);
blufi_env_ptr = NULL;
}
#endif
#if BTC_HF_CLIENT_INCLUDED == TRUE && HFP_DYNAMIC_MEMORY == TRUE
if (hf_client_local_param_ptr) {
osi_free(hf_client_local_param_ptr);
hf_client_local_param_ptr = NULL;
}
#endif
#if BTC_AV_INCLUDED == TRUE && AVRC_DYNAMIC_MEMORY == TRUE
if (btc_rc_cb_ptr) {
osi_free(btc_rc_cb_ptr);
btc_rc_cb_ptr = NULL;
}
if (bta_av_co_cb_ptr) {
osi_free(bta_av_co_cb_ptr);
bta_av_co_cb_ptr = NULL;
}
#endif
}
static bt_status_t btc_init_mem(void) {
if ((btc_dm_cb_ptr = (btc_dm_cb_t *)osi_malloc(sizeof(btc_dm_cb_t))) == NULL) {
goto error_exit;
}
memset((void *)btc_dm_cb_ptr, 0, sizeof(btc_dm_cb_t));
if ((btc_profile_cb_tab = (void **)osi_malloc(sizeof(void *) * BTC_PID_NUM)) == NULL) {
goto error_exit;
}
memset((void *)btc_profile_cb_tab, 0, sizeof(void *) * BTC_PID_NUM);
#if (BLE_INCLUDED == TRUE)
if ((gl_bta_adv_data_ptr = (tBTA_BLE_ADV_DATA *)osi_malloc(sizeof(tBTA_BLE_ADV_DATA))) == NULL) {
goto error_exit;
}
memset((void *)gl_bta_adv_data_ptr, 0, sizeof(tBTA_BLE_ADV_DATA));
if ((gl_bta_scan_rsp_data_ptr = (tBTA_BLE_ADV_DATA *)osi_malloc(sizeof(tBTA_BLE_ADV_DATA))) == NULL) {
goto error_exit;
}
memset((void *)gl_bta_scan_rsp_data_ptr, 0, sizeof(tBTA_BLE_ADV_DATA));
#endif ///BLE_INCLUDED == TRUE
#if GATTS_INCLUDED == TRUE && GATT_DYNAMIC_MEMORY == TRUE
if ((btc_creat_tab_env_ptr = (esp_btc_creat_tab_t *)osi_malloc(sizeof(esp_btc_creat_tab_t))) == NULL) {
goto error_exit;
}
memset((void *)btc_creat_tab_env_ptr, 0, sizeof(esp_btc_creat_tab_t));
if ((blufi_env_ptr = (tBLUFI_ENV *)osi_malloc(sizeof(tBLUFI_ENV))) == NULL) {
goto error_exit;
}
memset((void *)blufi_env_ptr, 0, sizeof(tBLUFI_ENV));
#endif
#if BTC_HF_CLIENT_INCLUDED == TRUE && HFP_DYNAMIC_MEMORY == TRUE
if ((hf_client_local_param_ptr = (hf_client_local_param_t *)osi_malloc(sizeof(hf_client_local_param_t))) == NULL) {
goto error_exit;
}
memset((void *)hf_client_local_param_ptr, 0, sizeof(hf_client_local_param_t));
#endif
#if BTC_AV_INCLUDED == TRUE && AVRC_DYNAMIC_MEMORY == TRUE
if ((btc_rc_cb_ptr = (btc_rc_cb_t *)osi_malloc(sizeof(btc_rc_cb_t))) == NULL) {
goto error_exit;
}
memset((void *)btc_rc_cb_ptr, 0, sizeof(btc_rc_cb_t));
if ((bta_av_co_cb_ptr = (tBTA_AV_CO_CB *)osi_malloc(sizeof(tBTA_AV_CO_CB))) == NULL) {
goto error_exit;
}
memset((void *)bta_av_co_cb_ptr, 0, sizeof(tBTA_AV_CO_CB));
#endif
return BT_STATUS_SUCCESS;
error_exit:;
btc_deinit_mem();
return BT_STATUS_NOMEM;
}
#endif ///BTC_DYNAMIC_MEMORY
int btc_init(void)
{
btc_thread = osi_thread_create("BTC_TASK", BTC_TASK_STACK_SIZE, BTC_TASK_PRIO, BTC_TASK_PINNED_TO_CORE, 3);
if (btc_thread == NULL) {
return BT_STATUS_NOMEM;
}
#if BTC_DYNAMIC_MEMORY
if (btc_init_mem() != BT_STATUS_SUCCESS){
return BT_STATUS_NOMEM;
}
#endif
#if (BLE_INCLUDED == TRUE)
btc_gap_callback_init();
#endif ///BLE_INCLUDED == TRUE
#if SCAN_QUEUE_CONGEST_CHECK
btc_adv_list_init();
#endif
/* TODO: initial the profile_tab */
return BT_STATUS_SUCCESS;
}
void btc_deinit(void)
{
#if BTC_DYNAMIC_MEMORY
btc_deinit_mem();
#endif
osi_thread_free(btc_thread);
btc_thread = NULL;
#if SCAN_QUEUE_CONGEST_CHECK
btc_adv_list_deinit();
#endif
}
bool btc_check_queue_is_congest(void)
{
if (osi_thread_queue_wait_size(btc_thread, 0) >= BT_QUEUE_CONGEST_SIZE) {
return true;
}
return false;
}

View file

@ -19,6 +19,11 @@
#include "btc/btc_task.h" #include "btc/btc_task.h"
#include "esp_bt_defs.h" #include "esp_bt_defs.h"
#if BTC_DYNAMIC_MEMORY == FALSE
extern void *btc_profile_cb_tab[BTC_PID_NUM];
#else
extern void **btc_profile_cb_tab;
#endif
/* reset gatt callback table */ /* reset gatt callback table */
void esp_profile_cb_reset(void); void esp_profile_cb_reset(void);

View file

@ -16,10 +16,13 @@
#define __BTC_TASK_H__ #define __BTC_TASK_H__
#include <stdint.h> #include <stdint.h>
#include "common/bt_target.h" #include "bt_common.h"
#include "common/bt_defs.h"
#include "osi/thread.h" #include "osi/thread.h"
#if CONFIG_BT_BLUEDROID_ENABLED
#include "common/bt_target.h"
#endif
typedef struct btc_msg { typedef struct btc_msg {
uint8_t sig; //event signal uint8_t sig; //event signal
uint8_t aid; //application id uint8_t aid; //application id
@ -53,17 +56,29 @@ typedef enum {
BTC_PID_BLUFI, BTC_PID_BLUFI,
BTC_PID_DM_SEC, BTC_PID_DM_SEC,
BTC_PID_ALARM, BTC_PID_ALARM,
#if CONFIG_BT_CLASSIC_ENABLED #if (CLASSIC_BT_INCLUDED == TRUE)
BTC_PID_GAP_BT, BTC_PID_GAP_BT,
BTC_PID_PRF_QUE, BTC_PID_PRF_QUE,
BTC_PID_A2DP, BTC_PID_A2DP,
BTC_PID_AVRC_CT, BTC_PID_AVRC_CT,
BTC_PID_AVRC_TG, BTC_PID_AVRC_TG,
BTC_PID_SPP, BTC_PID_SPP,
#if BTC_HF_CLIENT_INCLUDED #if (BTC_HF_CLIENT_INCLUDED == TRUE)
BTC_PID_HF_CLIENT, BTC_PID_HF_CLIENT,
#endif /* BTC_HF_CLIENT_INCLUDED */ #endif /* BTC_HF_CLIENT_INCLUDED */
#endif /* CONFIG_BT_CLASSIC_ENABLED */ #endif /* CLASSIC_BT_INCLUDED */
#if CONFIG_BLE_MESH
BTC_PID_PROV,
BTC_PID_MODEL,
BTC_PID_HEALTH_CLIENT,
BTC_PID_HEALTH_SERVER,
BTC_PID_CFG_CLIENT,
BTC_PID_CFG_SERVER,
BTC_PID_GENERIC_CLIENT,
BTC_PID_LIGHT_CLIENT,
BTC_PID_SENSOR_CLIENT,
BTC_PID_TIME_SCENE_CLIENT,
#endif /* CONFIG_BLE_MESH */
BTC_PID_NUM, BTC_PID_NUM,
} btc_pid_t; //btc profile id } btc_pid_t; //btc profile id

View file

@ -0,0 +1,158 @@
// Copyright 2019 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef _BT_COMMON_H_
#define _BT_COMMON_H_
#include "bt_user_config.h"
#include "esp_log.h"
#ifndef FALSE
#define FALSE false
#endif
#ifndef TRUE
#define TRUE true
#endif
#ifndef BT_QUEUE_CONGEST_SIZE
#define BT_QUEUE_CONGEST_SIZE 40
#endif
#define BTC_INITIAL_TRACE_LEVEL UC_BT_LOG_BTC_TRACE_LEVEL
#define OSI_INITIAL_TRACE_LEVEL UC_BT_LOG_OSI_TRACE_LEVEL
#if UC_BT_BLE_DYNAMIC_ENV_MEMORY
#define BT_BLE_DYNAMIC_ENV_MEMORY TRUE
#define BTC_DYNAMIC_MEMORY TRUE
#else
#define BT_BLE_DYNAMIC_ENV_MEMORY FALSE
#define BTC_DYNAMIC_MEMORY FALSE
#endif
#ifndef BT_BLE_DYNAMIC_ENV_MEMORY
#define BT_BLE_DYNAMIC_ENV_MEMORY FALSE
#endif
/* OS Configuration from User config (eg: sdkconfig) */
#define TASK_PINNED_TO_CORE UC_TASK_PINNED_TO_CORE
#define BT_TASK_MAX_PRIORITIES configMAX_PRIORITIES
#define BT_BTC_TASK_STACK_SIZE UC_BTC_TASK_STACK_SIZE
/* Define trace levels */
#define BT_TRACE_LEVEL_NONE UC_TRACE_LEVEL_NONE /* No trace messages to be generated */
#define BT_TRACE_LEVEL_ERROR UC_TRACE_LEVEL_ERROR /* Error condition trace messages */
#define BT_TRACE_LEVEL_WARNING UC_TRACE_LEVEL_WARNING /* Warning condition trace messages */
#define BT_TRACE_LEVEL_API UC_TRACE_LEVEL_API /* API traces */
#define BT_TRACE_LEVEL_EVENT UC_TRACE_LEVEL_EVENT /* Debug messages for events */
#define BT_TRACE_LEVEL_DEBUG UC_TRACE_LEVEL_DEBUG /* Full debug messages */
#define BT_TRACE_LEVEL_VERBOSE UC_TRACE_LEVEL_VERBOSE /* Verbose debug messages */
#define MAX_TRACE_LEVEL UC_TRACE_LEVEL_VERBOSE
#ifndef LOG_LOCAL_LEVEL
#ifndef BOOTLOADER_BUILD
#define LOG_LOCAL_LEVEL UC_LOG_DEFAULT_LEVEL
#else
#define LOG_LOCAL_LEVEL UC_BOOTLOADER_LOG_LEVEL
#endif
#endif
// Mapping between ESP_LOG_LEVEL and BT_TRACE_LEVEL
#if (LOG_LOCAL_LEVEL >= 4)
#define LOG_LOCAL_LEVEL_MAPPING (LOG_LOCAL_LEVEL+1)
#else
#define LOG_LOCAL_LEVEL_MAPPING LOG_LOCAL_LEVEL
#endif
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define BT_LOG_LEVEL_CHECK(LAYER, LEVEL) (MAX(LAYER##_INITIAL_TRACE_LEVEL, LOG_LOCAL_LEVEL_MAPPING) >= BT_TRACE_LEVEL_##LEVEL)
#define BT_PRINT_E(tag, format, ...) {esp_log_write(ESP_LOG_ERROR, tag, LOG_FORMAT(E, format), esp_log_timestamp(), tag, ##__VA_ARGS__); }
#define BT_PRINT_W(tag, format, ...) {esp_log_write(ESP_LOG_WARN, tag, LOG_FORMAT(W, format), esp_log_timestamp(), tag, ##__VA_ARGS__); }
#define BT_PRINT_I(tag, format, ...) {esp_log_write(ESP_LOG_INFO, tag, LOG_FORMAT(I, format), esp_log_timestamp(), tag, ##__VA_ARGS__); }
#define BT_PRINT_D(tag, format, ...) {esp_log_write(ESP_LOG_DEBUG, tag, LOG_FORMAT(D, format), esp_log_timestamp(), tag, ##__VA_ARGS__); }
#define BT_PRINT_V(tag, format, ...) {esp_log_write(ESP_LOG_VERBOSE, tag, LOG_FORMAT(V, format), esp_log_timestamp(), tag, ##__VA_ARGS__); }
#ifndef assert
#define assert(x) do { if (!(x)) BT_PRINT_E("BT", "bt host error %s %u\n", __FILE__, __LINE__); } while (0)
#endif
#if !UC_BT_STACK_NO_LOG
/* define traces for BTC */
#define BTC_TRACE_ERROR(fmt, args...) {if (BTC_INITIAL_TRACE_LEVEL >= BT_TRACE_LEVEL_ERROR && BT_LOG_LEVEL_CHECK(BTC, ERROR)) BT_PRINT_E("BT_BTC", fmt, ## args);}
#define BTC_TRACE_WARNING(fmt, args...) {if (BTC_INITIAL_TRACE_LEVEL >= BT_TRACE_LEVEL_WARNING && BT_LOG_LEVEL_CHECK(BTC, WARNING)) BT_PRINT_W("BT_BTC", fmt, ## args);}
#define BTC_TRACE_API(fmt, args...) {if (BTC_INITIAL_TRACE_LEVEL >= BT_TRACE_LEVEL_API && BT_LOG_LEVEL_CHECK(BTC,API)) BT_PRINT_I("BT_BTC", fmt, ## args);}
#define BTC_TRACE_EVENT(fmt, args...) {if (BTC_INITIAL_TRACE_LEVEL >= BT_TRACE_LEVEL_EVENT && BT_LOG_LEVEL_CHECK(BTC,EVENT)) BT_PRINT_D("BT_BTC", fmt, ## args);}
#define BTC_TRACE_DEBUG(fmt, args...) {if (BTC_INITIAL_TRACE_LEVEL >= BT_TRACE_LEVEL_DEBUG && BT_LOG_LEVEL_CHECK(BTC,DEBUG)) BT_PRINT_D("BT_BTC", fmt, ## args);}
#define BTC_TRACE_VERBOSE(fmt, args...) {if (BTC_INITIAL_TRACE_LEVEL >= BT_TRACE_LEVEL_VERBOSE && BT_LOG_LEVEL_CHECK(BTC,VERBOSE)) BT_PRINT_V("BT_BTC", fmt, ## args);}
/* define traces for OSI */
#define OSI_TRACE_ERROR(fmt, args...) {if (OSI_INITIAL_TRACE_LEVEL >= BT_TRACE_LEVEL_ERROR && BT_LOG_LEVEL_CHECK(OSI, ERROR)) BT_PRINT_E("BT_OSI", fmt, ## args);}
#define OSI_TRACE_WARNING(fmt, args...) {if (OSI_INITIAL_TRACE_LEVEL >= BT_TRACE_LEVEL_WARNING && BT_LOG_LEVEL_CHECK(OSI, WARNING)) BT_PRINT_W("BT_OSI", fmt, ## args);}
#define OSI_TRACE_API(fmt, args...) {if (OSI_INITIAL_TRACE_LEVEL >= BT_TRACE_LEVEL_API && BT_LOG_LEVEL_CHECK(OSI,API)) BT_PRINT_I("BT_OSI", fmt, ## args);}
#define OSI_TRACE_EVENT(fmt, args...) {if (OSI_INITIAL_TRACE_LEVEL >= BT_TRACE_LEVEL_EVENT && BT_LOG_LEVEL_CHECK(OSI,EVENT)) BT_PRINT_D("BT_OSI", fmt, ## args);}
#define OSI_TRACE_DEBUG(fmt, args...) {if (OSI_INITIAL_TRACE_LEVEL >= BT_TRACE_LEVEL_DEBUG && BT_LOG_LEVEL_CHECK(OSI,DEBUG)) BT_PRINT_D("BT_OSI", fmt, ## args);}
#define OSI_TRACE_VERBOSE(fmt, args...) {if (OSI_INITIAL_TRACE_LEVEL >= BT_TRACE_LEVEL_VERBOSE && BT_LOG_LEVEL_CHECK(OSI,VERBOSE)) BT_PRINT_V("BT_OSI", fmt, ## args);}
#else
/* define traces for BTC */
#define BTC_TRACE_ERROR(fmt, args...)
#define BTC_TRACE_WARNING(fmt, args...)
#define BTC_TRACE_API(fmt, args...)
#define BTC_TRACE_EVENT(fmt, args...)
#define BTC_TRACE_DEBUG(fmt, args...)
#define BTC_TRACE_VERBOSE(fmt, args...)
/* define traces for OSI */
#define OSI_TRACE_ERROR(fmt, args...)
#define OSI_TRACE_WARNING(fmt, args...)
#define OSI_TRACE_API(fmt, args...)
#define OSI_TRACE_EVENT(fmt, args...)
#define OSI_TRACE_DEBUG(fmt, args...)
#define OSI_TRACE_VERBOSE(fmt, args...)
#endif
/** Bluetooth Error Status */
/** We need to build on this */
/* relate to ESP_BT_STATUS_xxx in esp_bt_defs.h */
typedef enum {
BT_STATUS_SUCCESS = 0,
BT_STATUS_FAIL,
BT_STATUS_NOT_READY,
BT_STATUS_NOMEM,
BT_STATUS_BUSY,
BT_STATUS_DONE, /* request already completed */
BT_STATUS_UNSUPPORTED,
BT_STATUS_PARM_INVALID,
BT_STATUS_UNHANDLED,
BT_STATUS_AUTH_FAILURE,
BT_STATUS_RMT_DEV_DOWN,
BT_STATUS_AUTH_REJECTED,
BT_STATUS_INVALID_STATIC_RAND_ADDR,
BT_STATUS_PENDING,
BT_STATUS_UNACCEPT_CONN_INTERVAL,
BT_STATUS_PARAM_OUT_OF_RANGE,
BT_STATUS_TIMEOUT,
BT_STATUS_MEMORY_FULL,
BT_STATUS_EIR_TOO_LARGE,
} bt_status_t;
#endif /* _BT_COMMON_H_ */

View file

@ -0,0 +1,83 @@
// Copyright 2019 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef __BT_USER_CONFIG_H__
#define __BT_USER_CONFIG_H__
#include "sdkconfig.h"
#define UC_TRACE_LEVEL_NONE 0 /* No trace messages to be generated */
#define UC_TRACE_LEVEL_ERROR 1 /* Error condition trace messages */
#define UC_TRACE_LEVEL_WARNING 2 /* Warning condition trace messages */
#define UC_TRACE_LEVEL_API 3 /* API traces */
#define UC_TRACE_LEVEL_EVENT 4 /* Debug messages for events */
#define UC_TRACE_LEVEL_DEBUG 5 /* Full debug messages */
#define UC_TRACE_LEVEL_VERBOSE 6 /* Verbose debug messages */
//DYNAMIC ENV ALLOCATOR
#ifdef CONFIG_BT_BLE_DYNAMIC_ENV_MEMORY
#define UC_BT_BLE_DYNAMIC_ENV_MEMORY CONFIG_BT_BLE_DYNAMIC_ENV_MEMORY
#else
#define UC_BT_BLE_DYNAMIC_ENV_MEMORY FALSE
#endif
#ifdef CONFIG_BT_STACK_NO_LOG
#define UC_BT_STACK_NO_LOG CONFIG_BT_STACK_NO_LOG
#else
#define UC_BT_STACK_NO_LOG FALSE
#endif
/**********************************************************
* Thread/Task reference
**********************************************************/
#ifdef CONFIG_BLUEDROID_PINNED_TO_CORE
#define UC_TASK_PINNED_TO_CORE (CONFIG_BLUEDROID_PINNED_TO_CORE < portNUM_PROCESSORS ? CONFIG_BLUEDROID_PINNED_TO_CORE : tskNO_AFFINITY)
#else
#define UC_TASK_PINNED_TO_CORE (0)
#endif
#ifdef CONFIG_BTC_TASK_STACK_SIZE
#define UC_BTC_TASK_STACK_SIZE CONFIG_BTC_TASK_STACK_SIZE
#else
#define UC_BTC_TASK_STACK_SIZE 3072
#endif
/**********************************************************
* Trace reference
**********************************************************/
#ifdef CONFIG_LOG_DEFAULT_LEVEL
#define UC_LOG_DEFAULT_LEVEL CONFIG_LOG_DEFAULT_LEVEL
#else
#define UC_LOG_DEFAULT_LEVEL 3
#endif
#ifdef CONFIG_BOOTLOADER_LOG_LEVEL
#define UC_BOOTLOADER_LOG_LEVEL CONFIG_BOOTLOADER_LOG_LEVEL
#else
#define UC_BOOTLOADER_LOG_LEVEL 3
#endif
#ifdef CONFIG_BT_LOG_BTC_TRACE_LEVEL
#define UC_BT_LOG_BTC_TRACE_LEVEL CONFIG_BT_LOG_BTC_TRACE_LEVEL
#else
#define UC_BT_LOG_BTC_TRACE_LEVEL UC_TRACE_LEVEL_WARNING
#endif
#ifdef CONFIG_BT_LOG_OSI_TRACE_LEVEL
#define UC_BT_LOG_OSI_TRACE_LEVEL CONFIG_BT_LOG_OSI_TRACE_LEVEL
#else
#define UC_BT_LOG_OSI_TRACE_LEVEL UC_TRACE_LEVEL_WARNING
#endif
#endif /* __BT_USER_CONFIG_H__ */

View file

@ -18,8 +18,6 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <stdbool.h> #include <stdbool.h>
#include "common/bt_defs.h"
#include "common/bt_trace.h"
#include "osi/alarm.h" #include "osi/alarm.h"
#include "osi/allocator.h" #include "osi/allocator.h"
#include "osi/list.h" #include "osi/list.h"
@ -27,6 +25,7 @@
#include "btc/btc_task.h" #include "btc/btc_task.h"
#include "btc/btc_alarm.h" #include "btc/btc_alarm.h"
#include "osi/mutex.h" #include "osi/mutex.h"
#include "bt_common.h"
typedef struct alarm_t { typedef struct alarm_t {
/* timer id point to here */ /* timer id point to here */
@ -44,7 +43,11 @@ enum {
static osi_mutex_t alarm_mutex; static osi_mutex_t alarm_mutex;
static int alarm_state; static int alarm_state;
#if (BT_BLE_DYNAMIC_ENV_MEMORY == FALSE)
static struct alarm_t alarm_cbs[ALARM_CBS_NUM]; static struct alarm_t alarm_cbs[ALARM_CBS_NUM];
#else
static struct alarm_t *alarm_cbs;
#endif
static osi_alarm_err_t alarm_free(osi_alarm_t *alarm); static osi_alarm_err_t alarm_free(osi_alarm_t *alarm);
static osi_alarm_err_t alarm_set(osi_alarm_t *alarm, period_ms_t timeout, bool is_periodic); static osi_alarm_err_t alarm_set(osi_alarm_t *alarm, period_ms_t timeout, bool is_periodic);
@ -78,7 +81,14 @@ void osi_alarm_init(void)
OSI_TRACE_WARNING("%s, invalid state %d\n", __func__, alarm_state); OSI_TRACE_WARNING("%s, invalid state %d\n", __func__, alarm_state);
goto end; goto end;
} }
memset(alarm_cbs, 0x00, sizeof(alarm_cbs)); #if (BT_BLE_DYNAMIC_ENV_MEMORY == TRUE)
if ((alarm_cbs = (osi_alarm_t *)osi_malloc(sizeof(osi_alarm_t) * ALARM_CBS_NUM)) == NULL) {
OSI_TRACE_ERROR("%s, malloc failed\n", __func__);
goto end;
}
#endif
memset(alarm_cbs, 0x00, sizeof(osi_alarm_t) * ALARM_CBS_NUM);
alarm_state = ALARM_STATE_OPEN; alarm_state = ALARM_STATE_OPEN;
end: end:
@ -100,6 +110,12 @@ void osi_alarm_deinit(void)
alarm_free(&alarm_cbs[i]); alarm_free(&alarm_cbs[i]);
} }
} }
#if (BT_BLE_DYNAMIC_ENV_MEMORY == TRUE)
osi_free(alarm_cbs);
alarm_cbs = NULL;
#endif
alarm_state = ALARM_STATE_IDLE; alarm_state = ALARM_STATE_IDLE;
end: end:
@ -251,12 +267,12 @@ end:
osi_alarm_err_t osi_alarm_set(osi_alarm_t *alarm, period_ms_t timeout) osi_alarm_err_t osi_alarm_set(osi_alarm_t *alarm, period_ms_t timeout)
{ {
return alarm_set(alarm, timeout, false); return alarm_set(alarm, timeout, FALSE);
} }
osi_alarm_err_t osi_alarm_set_periodic(osi_alarm_t *alarm, period_ms_t period) osi_alarm_err_t osi_alarm_set_periodic(osi_alarm_t *alarm, period_ms_t period)
{ {
return alarm_set(alarm, period, true); return alarm_set(alarm, period, TRUE);
} }
osi_alarm_err_t osi_alarm_cancel(osi_alarm_t *alarm) osi_alarm_err_t osi_alarm_cancel(osi_alarm_t *alarm)

View file

@ -18,13 +18,14 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "common/bt_defs.h" #include "bt_common.h"
#include "osi/allocator.h" #include "osi/allocator.h"
extern void *pvPortZalloc(size_t size); extern void *pvPortZalloc(size_t size);
extern void vPortFree(void *pv); extern void vPortFree(void *pv);
#ifdef CONFIG_BT_BLUEDROID_MEM_DEBUG
#if HEAP_MEMORY_DEBUG
#define OSI_MEM_DBG_INFO_MAX 1024*3 #define OSI_MEM_DBG_INFO_MAX 1024*3
typedef struct { typedef struct {
@ -35,8 +36,16 @@ typedef struct {
} osi_mem_dbg_info_t; } osi_mem_dbg_info_t;
static uint32_t mem_dbg_count = 0; static uint32_t mem_dbg_count = 0;
static uint32_t mem_dbg_count2 = 0;
static osi_mem_dbg_info_t mem_dbg_info[OSI_MEM_DBG_INFO_MAX]; static osi_mem_dbg_info_t mem_dbg_info[OSI_MEM_DBG_INFO_MAX];
static uint32_t mem_dbg_current_size = 0;
static uint32_t mem_dbg_max_size = 0;
#define OSI_MEM_DBG_MAX_SECTION_NUM 5
typedef struct {
bool used;
uint32_t max_size;
} osi_mem_dbg_max_size_section_t;
static osi_mem_dbg_max_size_section_t mem_dbg_max_size_section[OSI_MEM_DBG_MAX_SECTION_NUM];
void osi_mem_dbg_init(void) void osi_mem_dbg_init(void)
{ {
@ -49,7 +58,13 @@ void osi_mem_dbg_init(void)
mem_dbg_info[i].line = 0; mem_dbg_info[i].line = 0;
} }
mem_dbg_count = 0; mem_dbg_count = 0;
mem_dbg_count2 = 0; mem_dbg_current_size = 0;
mem_dbg_max_size = 0;
for (i = 0; i < OSI_MEM_DBG_MAX_SECTION_NUM; i++){
mem_dbg_max_size_section[i].used = false;
mem_dbg_max_size_section[i].max_size = 0;
}
} }
void osi_mem_dbg_record(void *p, int size, const char *func, int line) void osi_mem_dbg_record(void *p, int size, const char *func, int line)
@ -75,6 +90,19 @@ void osi_mem_dbg_record(void *p, int size, const char *func, int line)
if (i >= OSI_MEM_DBG_INFO_MAX) { if (i >= OSI_MEM_DBG_INFO_MAX) {
OSI_TRACE_ERROR("%s full %s %d !!\n", __func__, func, line); OSI_TRACE_ERROR("%s full %s %d !!\n", __func__, func, line);
} }
mem_dbg_current_size += size;
if(mem_dbg_max_size < mem_dbg_current_size) {
mem_dbg_max_size = mem_dbg_current_size;
}
for (i = 0; i < OSI_MEM_DBG_MAX_SECTION_NUM; i++){
if (mem_dbg_max_size_section[i].used) {
if(mem_dbg_max_size_section[i].max_size < mem_dbg_current_size) {
mem_dbg_max_size_section[i].max_size = mem_dbg_current_size;
}
}
}
} }
void osi_mem_dbg_clean(void *p, const char *func, int line) void osi_mem_dbg_clean(void *p, const char *func, int line)
@ -88,6 +116,7 @@ void osi_mem_dbg_clean(void *p, const char *func, int line)
for (i = 0; i < OSI_MEM_DBG_INFO_MAX; i++) { for (i = 0; i < OSI_MEM_DBG_INFO_MAX; i++) {
if (mem_dbg_info[i].p == p) { if (mem_dbg_info[i].p == p) {
mem_dbg_current_size -= mem_dbg_info[i].size;
mem_dbg_info[i].p = NULL; mem_dbg_info[i].p = NULL;
mem_dbg_info[i].size = 0; mem_dbg_info[i].size = 0;
mem_dbg_info[i].func = NULL; mem_dbg_info[i].func = NULL;
@ -112,6 +141,60 @@ void osi_mem_dbg_show(void)
} }
} }
OSI_TRACE_ERROR("--> count %d\n", mem_dbg_count); OSI_TRACE_ERROR("--> count %d\n", mem_dbg_count);
OSI_TRACE_ERROR("--> size %dB\n--> max size %dB\n", mem_dbg_current_size, mem_dbg_max_size);
}
uint32_t osi_mem_dbg_get_max_size(void)
{
return mem_dbg_max_size;
}
uint32_t osi_mem_dbg_get_current_size(void)
{
return mem_dbg_current_size;
}
void osi_men_dbg_set_section_start(uint8_t index)
{
if (index >= OSI_MEM_DBG_MAX_SECTION_NUM) {
OSI_TRACE_ERROR("Then range of index should be between 0 and %d, current index is %d.\n",
OSI_MEM_DBG_MAX_SECTION_NUM - 1, index);
return;
}
if (mem_dbg_max_size_section[index].used) {
OSI_TRACE_WARNING("This index(%d) has been started, restart it.\n", index);
}
mem_dbg_max_size_section[index].used = true;
mem_dbg_max_size_section[index].max_size = mem_dbg_current_size;
}
void osi_men_dbg_set_section_end(uint8_t index)
{
if (index >= OSI_MEM_DBG_MAX_SECTION_NUM) {
OSI_TRACE_ERROR("Then range of index should be between 0 and %d, current index is %d.\n",
OSI_MEM_DBG_MAX_SECTION_NUM - 1, index);
return;
}
if (!mem_dbg_max_size_section[index].used) {
OSI_TRACE_ERROR("This index(%d) has not been started.\n", index);
return;
}
mem_dbg_max_size_section[index].used = false;
}
uint32_t osi_mem_dbg_get_max_size_section(uint8_t index)
{
if (index >= OSI_MEM_DBG_MAX_SECTION_NUM){
OSI_TRACE_ERROR("Then range of index should be between 0 and %d, current index is %d.\n",
OSI_MEM_DBG_MAX_SECTION_NUM - 1, index);
return 0;
}
return mem_dbg_max_size_section[index].max_size;
} }
#endif #endif
@ -130,47 +213,47 @@ char *osi_strdup(const char *str)
void *osi_malloc_func(size_t size) void *osi_malloc_func(size_t size)
{ {
#ifdef CONFIG_BT_BLUEDROID_MEM_DEBUG #if HEAP_MEMORY_DEBUG
void *p; void *p;
#if CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST #if HEAP_ALLOCATION_FROM_SPIRAM_FIRST
p = heap_caps_malloc_prefer(size, 2, MALLOC_CAP_DEFAULT|MALLOC_CAP_SPIRAM, MALLOC_CAP_DEFAULT|MALLOC_CAP_INTERNAL); p = heap_caps_malloc_prefer(size, 2, MALLOC_CAP_DEFAULT|MALLOC_CAP_SPIRAM, MALLOC_CAP_DEFAULT|MALLOC_CAP_INTERNAL);
#else #else
p = malloc(size); p = malloc(size);
#endif /* #if CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST */ #endif /* #if HEAP_ALLOCATION_FROM_SPIRAM_FIRST */
osi_mem_dbg_record(p, size, __func__, __LINE__); osi_mem_dbg_record(p, size, __func__, __LINE__);
return p; return p;
#else #else
#if CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST #if HEAP_ALLOCATION_FROM_SPIRAM_FIRST
return heap_caps_malloc_prefer(size, 2, MALLOC_CAP_DEFAULT|MALLOC_CAP_SPIRAM, MALLOC_CAP_DEFAULT|MALLOC_CAP_INTERNAL); return heap_caps_malloc_prefer(size, 2, MALLOC_CAP_DEFAULT|MALLOC_CAP_SPIRAM, MALLOC_CAP_DEFAULT|MALLOC_CAP_INTERNAL);
#else #else
return malloc(size); return malloc(size);
#endif /* #if CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST */ #endif /* #if HEAP_ALLOCATION_FROM_SPIRAM_FIRST */
#endif /* #ifdef CONFIG_BT_BLUEDROID_MEM_DEBUG */ #endif /* #if HEAP_MEMORY_DEBUG */
} }
void *osi_calloc_func(size_t size) void *osi_calloc_func(size_t size)
{ {
#ifdef CONFIG_BT_BLUEDROID_MEM_DEBUG #if HEAP_MEMORY_DEBUG
void *p; void *p;
#if CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST #if HEAP_ALLOCATION_FROM_SPIRAM_FIRST
p = heap_caps_calloc_prefer(1, size, 2, MALLOC_CAP_DEFAULT|MALLOC_CAP_SPIRAM, MALLOC_CAP_DEFAULT|MALLOC_CAP_INTERNAL); p = heap_caps_calloc_prefer(1, size, 2, MALLOC_CAP_DEFAULT|MALLOC_CAP_SPIRAM, MALLOC_CAP_DEFAULT|MALLOC_CAP_INTERNAL);
#else #else
p = calloc(1, size); p = calloc(1, size);
#endif /* #if CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST */ #endif /* #if HEAP_ALLOCATION_FROM_SPIRAM_FIRST */
osi_mem_dbg_record(p, size, __func__, __LINE__); osi_mem_dbg_record(p, size, __func__, __LINE__);
return p; return p;
#else #else
#if CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST #if HEAP_ALLOCATION_FROM_SPIRAM_FIRST
return heap_caps_calloc_prefer(1, size, 2, MALLOC_CAP_DEFAULT|MALLOC_CAP_SPIRAM, MALLOC_CAP_DEFAULT|MALLOC_CAP_INTERNAL); return heap_caps_calloc_prefer(1, size, 2, MALLOC_CAP_DEFAULT|MALLOC_CAP_SPIRAM, MALLOC_CAP_DEFAULT|MALLOC_CAP_INTERNAL);
#else #else
return calloc(1, size); return calloc(1, size);
#endif /* #if CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST */ #endif /* #if HEAP_ALLOCATION_FROM_SPIRAM_FIRST */
#endif /* #ifdef CONFIG_BT_BLUEDROID_MEM_DEBUG */ #endif /* #if HEAP_MEMORY_DEBUG */
} }
void osi_free_func(void *ptr) void osi_free_func(void *ptr)
{ {
#ifdef CONFIG_BT_BLUEDROID_MEM_DEBUG #if HEAP_MEMORY_DEBUG
osi_mem_dbg_clean(ptr, __func__, __LINE__); osi_mem_dbg_clean(ptr, __func__, __LINE__);
#endif #endif
free(ptr); free(ptr);

View file

@ -16,11 +16,9 @@
* *
******************************************************************************/ ******************************************************************************/
#include <stdint.h> #include <stdint.h>
#include "common/bt_trace.h" #include "bt_common.h"
#include "osi/allocator.h" #include "osi/allocator.h"
#include "osi/buffer.h" #include "osi/buffer.h"
#include "common/bt_defs.h"
#include "common/bt_trace.h"
struct buffer_t { struct buffer_t {
buffer_t *root; buffer_t *root;

View file

@ -23,10 +23,10 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "bt_common.h"
#include "osi/allocator.h" #include "osi/allocator.h"
#include "osi/config.h" #include "osi/config.h"
#include "osi/list.h" #include "osi/list.h"
#include "common/bt_trace.h"
#define CONFIG_FILE_MAX_SIZE (1536)//1.5k #define CONFIG_FILE_MAX_SIZE (1536)//1.5k
#define CONFIG_FILE_DEFAULE_LENGTH (2048) #define CONFIG_FILE_DEFAULE_LENGTH (2048)
@ -440,8 +440,9 @@ bool config_save(const config_t *config, const char *filename)
goto error; goto error;
} }
}else { }else {
uint count = (w_cnt_total / CONFIG_FILE_MAX_SIZE); int count = (w_cnt_total / CONFIG_FILE_MAX_SIZE);
for (int i = 0; i <= count; i++) assert(count <= 0xFF);
for (uint8_t i = 0; i <= count; i++)
{ {
snprintf(keyname, keyname_bufsz, "%s%d", CONFIG_KEY, i); snprintf(keyname, keyname_bufsz, "%s%d", CONFIG_KEY, i);
if (i == count) { if (i == count) {

View file

@ -16,12 +16,10 @@
* *
******************************************************************************/ ******************************************************************************/
#include "common/bt_defs.h"
#include "osi/allocator.h" #include "osi/allocator.h"
#include "osi/fixed_queue.h" #include "osi/fixed_queue.h"
#include "osi/list.h" #include "osi/list.h"
#include "osi/osi.h" #include "osi/osi.h"
#include "common/bt_trace.h"
#include "osi/mutex.h" #include "osi/mutex.h"
#include "osi/semaphore.h" #include "osi/semaphore.h"
@ -129,45 +127,12 @@ size_t fixed_queue_capacity(fixed_queue_t *queue)
return queue->capacity; return queue->capacity;
} }
void fixed_queue_enqueue(fixed_queue_t *queue, void *data) bool fixed_queue_enqueue(fixed_queue_t *queue, void *data, uint32_t timeout)
{ {
assert(queue != NULL); assert(queue != NULL);
assert(data != NULL); assert(data != NULL);
osi_sem_take(&queue->enqueue_sem, OSI_SEM_MAX_TIMEOUT); if (osi_sem_take(&queue->enqueue_sem, timeout) != 0) {
osi_mutex_lock(&queue->lock, OSI_MUTEX_MAX_TIMEOUT);
list_append(queue->list, data);
osi_mutex_unlock(&queue->lock);
osi_sem_give(&queue->dequeue_sem);
}
void *fixed_queue_dequeue(fixed_queue_t *queue)
{
void *ret = NULL;
assert(queue != NULL);
osi_sem_take(&queue->dequeue_sem, OSI_SEM_MAX_TIMEOUT);
osi_mutex_lock(&queue->lock, OSI_MUTEX_MAX_TIMEOUT);
ret = list_front(queue->list);
list_remove(queue->list, ret);
osi_mutex_unlock(&queue->lock);
osi_sem_give(&queue->enqueue_sem);
return ret;
}
bool fixed_queue_try_enqueue(fixed_queue_t *queue, void *data)
{
assert(queue != NULL);
assert(data != NULL);
if (osi_sem_take(&queue->enqueue_sem, 0) != 0) {
return false; return false;
} }
@ -181,15 +146,13 @@ bool fixed_queue_try_enqueue(fixed_queue_t *queue, void *data)
return true; return true;
} }
void *fixed_queue_try_dequeue(fixed_queue_t *queue) void *fixed_queue_dequeue(fixed_queue_t *queue, uint32_t timeout)
{ {
void *ret = NULL; void *ret = NULL;
if (queue == NULL) { assert(queue != NULL);
return NULL;
}
if (osi_sem_take(queue->dequeue_sem, 0) != 0) { if (osi_sem_take(queue->dequeue_sem, timeout) != 0) {
return NULL; return NULL;
} }

View file

@ -16,8 +16,7 @@
* *
******************************************************************************/ ******************************************************************************/
#include "common/bt_trace.h" #include "bt_common.h"
#include "osi/allocator.h" #include "osi/allocator.h"
#include "osi/future.h" #include "osi/future.h"
#include "osi/osi.h" #include "osi/osi.h"

View file

@ -16,8 +16,7 @@
* *
******************************************************************************/ ******************************************************************************/
#include "common/bt_defs.h" #include "bt_common.h"
#include "common/bt_trace.h"
#include "osi/list.h" #include "osi/list.h"
#include "osi/hash_map.h" #include "osi/hash_map.h"
#include "osi/allocator.h" #include "osi/allocator.h"

View file

@ -22,7 +22,6 @@
#include <stddef.h> #include <stddef.h>
#include <stdlib.h> #include <stdlib.h>
#include "esp_heap_caps.h" #include "esp_heap_caps.h"
#include "sdkconfig.h"
char *osi_strdup(const char *str); char *osi_strdup(const char *str);
@ -30,14 +29,19 @@ void *osi_malloc_func(size_t size);
void *osi_calloc_func(size_t size); void *osi_calloc_func(size_t size);
void osi_free_func(void *ptr); void osi_free_func(void *ptr);
#ifdef CONFIG_BT_BLUEDROID_MEM_DEBUG #if HEAP_MEMORY_DEBUG
void osi_mem_dbg_init(void); void osi_mem_dbg_init(void);
void osi_mem_dbg_record(void *p, int size, const char *func, int line); void osi_mem_dbg_record(void *p, int size, const char *func, int line);
void osi_mem_dbg_clean(void *p, const char *func, int line); void osi_mem_dbg_clean(void *p, const char *func, int line);
void osi_mem_dbg_show(void); void osi_mem_dbg_show(void);
uint32_t osi_mem_dbg_get_max_size(void);
uint32_t osi_mem_dbg_get_current_size(void);
void osi_men_dbg_set_section_start(uint8_t index);
void osi_men_dbg_set_section_end(uint8_t index);
uint32_t osi_mem_dbg_get_max_size_section(uint8_t index);
#if CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST #if HEAP_ALLOCATION_FROM_SPIRAM_FIRST
#define osi_malloc(size) \ #define osi_malloc(size) \
({ \ ({ \
void *p; \ void *p; \
@ -76,7 +80,7 @@ void osi_mem_dbg_show(void);
(void *)p; \ (void *)p; \
}) })
#endif /* #if CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST */ #endif /* #if HEAP_ALLOCATION_FROM_SPIRAM_FIRST */
#if 0 #if 0
@ -84,11 +88,11 @@ void osi_mem_dbg_show(void);
do { \ do { \
void *p; \ void *p; \
\ \
#if CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST \ #if HEAP_ALLOCATION_FROM_SPIRAM_FIRST \
p = heap_caps_malloc_prefer(size, 2, MALLOC_CAP_DEFAULT|MALLOC_CAP_SPIRAM, MALLOC_CAP_DEFAULT|MALLOC_CAP_INTERNAL); \ p = heap_caps_malloc_prefer(size, 2, MALLOC_CAP_DEFAULT|MALLOC_CAP_SPIRAM, MALLOC_CAP_DEFAULT|MALLOC_CAP_INTERNAL); \
#else \ #else \
p = malloc((size)); \ p = malloc((size)); \
#endif /* #if CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST */ \ #endif /* #if HEAP_ALLOCATION_FROM_SPIRAM_FIRST */ \
osi_mem_dbg_record(p, size, __func__, __LINE__); \ osi_mem_dbg_record(p, size, __func__, __LINE__); \
(void *)p; \ (void *)p; \
}while(0) }while(0)
@ -97,13 +101,13 @@ do { \
do { \ do { \
void *p; \ void *p; \
\ \
#if CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST \ #if HEAP_ALLOCATION_FROM_SPIRAM_FIRST \
p = heap_caps_calloc_prefer(1, size, 2, \ p = heap_caps_calloc_prefer(1, size, 2, \
MALLOC_CAP_DEFAULT|MALLOC_CAP_SPIRAM, \ MALLOC_CAP_DEFAULT|MALLOC_CAP_SPIRAM, \
MALLOC_CAP_DEFAULT|MALLOC_CAP_INTERNAL); \ MALLOC_CAP_DEFAULT|MALLOC_CAP_INTERNAL); \
#else \ #else \
p = calloc(1, (size)); \ p = calloc(1, (size)); \
#endif /* #if CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST */ \ #endif /* #if HEAP_ALLOCATION_FROM_SPIRAM_FIRST */ \
osi_mem_dbg_record(p, size, __func__, __LINE__); \ osi_mem_dbg_record(p, size, __func__, __LINE__); \
(void *)p; \ (void *)p; \
} while(0) } while(0)
@ -118,16 +122,16 @@ do { \
#else #else
#if CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST #if HEAP_ALLOCATION_FROM_SPIRAM_FIRST
#define osi_malloc(size) heap_caps_malloc_prefer(size, 2, MALLOC_CAP_DEFAULT|MALLOC_CAP_SPIRAM, MALLOC_CAP_DEFAULT|MALLOC_CAP_INTERNAL) #define osi_malloc(size) heap_caps_malloc_prefer(size, 2, MALLOC_CAP_DEFAULT|MALLOC_CAP_SPIRAM, MALLOC_CAP_DEFAULT|MALLOC_CAP_INTERNAL)
#define osi_calloc(size) heap_caps_calloc_prefer(1, size, 2, MALLOC_CAP_DEFAULT|MALLOC_CAP_SPIRAM, MALLOC_CAP_DEFAULT|MALLOC_CAP_INTERNAL) #define osi_calloc(size) heap_caps_calloc_prefer(1, size, 2, MALLOC_CAP_DEFAULT|MALLOC_CAP_SPIRAM, MALLOC_CAP_DEFAULT|MALLOC_CAP_INTERNAL)
#else #else
#define osi_malloc(size) malloc((size)) #define osi_malloc(size) malloc((size))
#define osi_calloc(size) calloc(1, (size)) #define osi_calloc(size) calloc(1, (size))
#endif /* #if CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST */ #endif /* #if HEAP_ALLOCATION_FROM_SPIRAM_FIRST */
#define osi_free(p) free((p)) #define osi_free(p) free((p))
#endif /* CONFIG_BT_BLUEDROID_MEM_DEBUG */ #endif /* HEAP_MEMORY_DEBUG */
#define FREE_AND_RESET(a) \ #define FREE_AND_RESET(a) \
do { \ do { \

View file

@ -21,11 +21,14 @@
#include <stdbool.h> #include <stdbool.h>
#include "osi/list.h" #include "osi/list.h"
#include "osi/semaphore.h"
#ifndef QUEUE_SIZE_MAX #ifndef QUEUE_SIZE_MAX
#define QUEUE_SIZE_MAX 254 #define QUEUE_SIZE_MAX 254
#endif #endif
#define FIXED_QUEUE_MAX_TIMEOUT OSI_SEM_MAX_TIMEOUT
struct fixed_queue_t; struct fixed_queue_t;
typedef struct fixed_queue_t fixed_queue_t; typedef struct fixed_queue_t fixed_queue_t;
@ -56,27 +59,14 @@ size_t fixed_queue_length(fixed_queue_t *queue);
// not be NULL. // not be NULL.
size_t fixed_queue_capacity(fixed_queue_t *queue); size_t fixed_queue_capacity(fixed_queue_t *queue);
// Enqueues the given |data| into the |queue|. The caller will be blocked // Enqueues the given |data| into the |queue|. The caller will be blocked or immediately return or wait for timeout according to the parameter timeout.
// if nore more space is available in the queue. Neither |queue| nor |data| // If enqueue failed, it will return false, otherwise return true
// may be NULL. bool fixed_queue_enqueue(fixed_queue_t *queue, void *data, uint32_t timeout);
void fixed_queue_enqueue(fixed_queue_t *queue, void *data);
// Dequeues the next element from |queue|. If the queue is currently empty, // Dequeues the next element from |queue|. If the queue is currently empty,
// this function will block the caller until an item is enqueued. This // this function will block the caller until an item is enqueued or immediately return or wait for timeout according to the parameter timeout.
// function will never return NULL. |queue| may not be NULL. // If dequeue failed, it will return NULL, otherwise return a point.
void *fixed_queue_dequeue(fixed_queue_t *queue); void *fixed_queue_dequeue(fixed_queue_t *queue, uint32_t timeout);
// Tries to enqueue |data| into the |queue|. This function will never block
// the caller. If the queue capacity would be exceeded by adding one more
// element, this function returns false immediately. Otherwise, this function
// returns true. Neither |queue| nor |data| may be NULL.
bool fixed_queue_try_enqueue(fixed_queue_t *queue, void *data);
// Tries to dequeue an element from |queue|. This function will never block
// the caller. If the queue is empty, this function returns NULL immediately.
// Otherwise, the next element in the queue is returned. |queue| may not be
// NULL.
void *fixed_queue_try_dequeue(fixed_queue_t *queue);
// Returns the first element from |queue|, if present, without dequeuing it. // Returns the first element from |queue|, if present, without dequeuing it.
// This function will never block the caller. Returns NULL if there are no // This function will never block the caller. Returns NULL if there are no

View file

@ -23,9 +23,9 @@
#include "freertos/task.h" #include "freertos/task.h"
#include "freertos/queue.h" #include "freertos/queue.h"
#include "freertos/semphr.h" #include "freertos/semphr.h"
#include "osi/semaphore.h"
#define OSI_MUTEX_MAX_TIMEOUT OSI_SEM_MAX_TIMEOUT
#define OSI_MUTEX_MAX_TIMEOUT 0xffffffffUL
#define osi_mutex_valid( x ) ( ( ( *x ) == NULL) ? pdFALSE : pdTRUE ) #define osi_mutex_valid( x ) ( ( ( *x ) == NULL) ? pdFALSE : pdTRUE )
#define osi_mutex_set_invalid( x ) ( ( *x ) = NULL ) #define osi_mutex_set_invalid( x ) ( ( *x ) = NULL )

View file

@ -0,0 +1,92 @@
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef __THREAD_H__
#define __THREAD_H__
#include "freertos/xtensa_api.h"
#include "freertos/FreeRTOSConfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"
#include "freertos/task.h"
#include "osi/semaphore.h"
#include "esp_task.h"
#include "bt_common.h"
#define portBASE_TYPE int
#define OSI_THREAD_MAX_TIMEOUT OSI_SEM_MAX_TIMEOUT
struct osi_thread;
typedef struct osi_thread osi_thread_t;
typedef void (*osi_thread_func_t)(void *context);
typedef enum {
OSI_THREAD_CORE_0 = 0,
OSI_THREAD_CORE_1,
OSI_THREAD_CORE_AFFINITY,
} osi_thread_core_t;
/*
* brief: Create a thread or task
* param name: thread name
* param stack_size: thread stack size
* param priority: thread priority
* param core: the CPU core which this thread run, OSI_THREAD_CORE_AFFINITY means unspecific CPU core
* param work_queue_num: speicify queue number, the queue[0] has highest priority, and the priority is decrease by index
* return : if create successfully, return thread handler; otherwise return NULL.
*/
osi_thread_t *osi_thread_create(const char *name, size_t stack_size, int priority, osi_thread_core_t core, uint8_t work_queue_num);
/*
* brief: Destroy a thread or task
* param thread: point of thread handler
*/
void osi_thread_free(osi_thread_t *thread);
/*
* brief: Post an msg to a thread and told the thread call the function
* param thread: point of thread handler
* param func: callback function that called by target thread
* param context: argument of callback function
* param queue_idx: the queue which the msg send to
* param timeout: post timeout, OSI_THREAD_MAX_TIMEOUT means blocking forever, 0 means never blocking, others means block millisecond
* return : if post successfully, return true, otherwise return false
*/
bool osi_thread_post(osi_thread_t *thread, osi_thread_func_t func, void *context, int queue_idx, uint32_t timeout);
/*
* brief: Set the priority of thread
* param thread: point of thread handler
* param priority: priority
* return : if set successfully, return true, otherwise return false
*/
bool osi_thread_set_priority(osi_thread_t *thread, int priority);
/* brief: Get thread name
* param thread: point of thread handler
* return: constant point of thread name
*/
const char *osi_thread_name(osi_thread_t *thread);
/* brief: Get the size of the specified queue
* param thread: point of thread handler
* param wq_idx: the queue index of the thread
* return: queue size
*/
int osi_thread_queue_wait_size(osi_thread_t *thread, int wq_idx);
#endif /* __THREAD_H__ */

View file

@ -1,6 +1,5 @@
#include "common/bt_defs.h" #include "bt_common.h"
#include "osi/allocator.h" #include "osi/allocator.h"
#include "osi/list.h" #include "osi/list.h"
#include "osi/osi.h" #include "osi/osi.h"

View file

@ -0,0 +1,278 @@
/******************************************************************************
*
* Copyright (C) 2014 Google, Inc.
*
* 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 <string.h>
#include "osi/allocator.h"
#include "osi/fixed_queue.h"
#include "osi/semaphore.h"
#include "osi/thread.h"
struct osi_thread {
void *thread_handle; /*!< Store the thread object */
int thread_id; /*!< May for some OS, such as Linux */
bool stop;
uint8_t work_queue_num; /*!< Work queue number */
fixed_queue_t **work_queues; /*!< Point to queue array, and the priority inverse array index */
osi_sem_t work_sem;
osi_sem_t stop_sem;
};
struct osi_thread_start_arg {
osi_thread_t *thread;
osi_sem_t start_sem;
int error;
};
typedef struct {
osi_thread_func_t func;
void *context;
} work_item_t;
static const size_t DEFAULT_WORK_QUEUE_CAPACITY = 100;
static void osi_thread_run(void *arg)
{
struct osi_thread_start_arg *start = (struct osi_thread_start_arg *)arg;
osi_thread_t *thread = start->thread;
osi_sem_give(&start->start_sem);
while (1) {
int idx = 0;
osi_sem_take(&thread->work_sem, OSI_SEM_MAX_TIMEOUT);
if (thread->stop) {
break;
}
while (!thread->stop && idx < thread->work_queue_num) {
work_item_t *item = fixed_queue_dequeue(thread->work_queues[idx], 0);
if (item) {
item->func(item->context);
osi_free(item);
idx = 0;
continue;
} else {
idx++;
}
}
}
thread->thread_handle = NULL;
osi_sem_give(&thread->stop_sem);
vTaskDelete(NULL);
}
static int osi_thread_join(osi_thread_t *thread, uint32_t wait_ms)
{
assert(thread != NULL);
return osi_sem_take(&thread->stop_sem, wait_ms);
}
static void osi_thread_stop(osi_thread_t *thread)
{
int ret;
assert(thread != NULL);
//stop the thread
thread->stop = true;
osi_sem_give(&thread->work_sem);
//join
ret = osi_thread_join(thread, 1000); //wait 1000ms
//if join failed, delete the task here
if (ret != 0 && thread->thread_handle) {
vTaskDelete(thread->thread_handle);
}
}
//in linux, the stack_size, priority and core may not be set here, the code will be ignore the arguments
osi_thread_t *osi_thread_create(const char *name, size_t stack_size, int priority, osi_thread_core_t core, uint8_t work_queue_num)
{
int ret;
osi_thread_t *thread;
struct osi_thread_start_arg start_arg = {0};
if (stack_size <= 0 ||
core < OSI_THREAD_CORE_0 || core > OSI_THREAD_CORE_AFFINITY ||
work_queue_num <= 0) {
return NULL;
}
thread = (osi_thread_t *)osi_malloc(sizeof(osi_thread_t));
if (thread == NULL) {
goto _err;
}
thread->stop = false;
thread->work_queue_num = work_queue_num;
thread->work_queues = (fixed_queue_t **)osi_malloc(sizeof(fixed_queue_t *) * work_queue_num);
if (thread->work_queues == NULL) {
goto _err;
}
for (int i = 0; i < thread->work_queue_num; i++) {
thread->work_queues[i] = fixed_queue_new(DEFAULT_WORK_QUEUE_CAPACITY);
if (thread->work_queues[i] == NULL) {
goto _err;
}
}
ret = osi_sem_new(&thread->work_sem, 1, 0);
if (ret != 0) {
goto _err;
}
ret = osi_sem_new(&thread->stop_sem, 1, 0);
if (ret != 0) {
goto _err;
}
start_arg.thread = thread;
ret = osi_sem_new(&start_arg.start_sem, 1, 0);
if (ret != 0) {
goto _err;
}
if (xTaskCreatePinnedToCore(osi_thread_run, name, stack_size, &start_arg, priority, &thread->thread_handle, core) != pdPASS) {
goto _err;
}
osi_sem_take(&start_arg.start_sem, OSI_SEM_MAX_TIMEOUT);
osi_sem_free(&start_arg.start_sem);
return thread;
_err:
if (thread) {
if (start_arg.start_sem) {
osi_sem_free(&start_arg.start_sem);
}
if (thread->thread_handle) {
vTaskDelete(thread->thread_handle);
}
for (int i = 0; i < thread->work_queue_num; i++) {
if (thread->work_queues[i]) {
fixed_queue_free(thread->work_queues[i], osi_free_func);
}
}
if (thread->work_queues) {
osi_free(thread->work_queues);
}
if (thread->work_sem) {
osi_sem_free(&thread->work_sem);
}
if (thread->stop_sem) {
osi_sem_free(&thread->stop_sem);
}
osi_free(thread);
}
return NULL;
}
void osi_thread_free(osi_thread_t *thread)
{
if (!thread)
return;
osi_thread_stop(thread);
for (int i = 0; i < thread->work_queue_num; i++) {
if (thread->work_queues[i]) {
fixed_queue_free(thread->work_queues[i], osi_free_func);
}
}
if (thread->work_queues) {
osi_free(thread->work_queues);
}
if (thread->work_sem) {
osi_sem_free(&thread->work_sem);
}
if (thread->stop_sem) {
osi_sem_free(&thread->stop_sem);
}
osi_free(thread);
}
bool osi_thread_post(osi_thread_t *thread, osi_thread_func_t func, void *context, int queue_idx, uint32_t timeout)
{
assert(thread != NULL);
assert(func != NULL);
if (queue_idx >= thread->work_queue_num) {
return false;
}
work_item_t *item = (work_item_t *)osi_malloc(sizeof(work_item_t));
if (item == NULL) {
return false;
}
item->func = func;
item->context = context;
if (fixed_queue_enqueue(thread->work_queues[queue_idx], item, timeout) == false) {
osi_free(item);
return false;
}
osi_sem_give(&thread->work_sem);
return true;
}
bool osi_thread_set_priority(osi_thread_t *thread, int priority)
{
assert(thread != NULL);
vTaskPrioritySet(thread->thread_handle, priority);
return true;
}
const char *osi_thread_name(osi_thread_t *thread)
{
assert(thread != NULL);
return pcTaskGetTaskName(thread->thread_handle);
}
int osi_thread_queue_wait_size(osi_thread_t *thread, int wq_idx)
{
if (wq_idx < 0 || wq_idx >= thread->work_queue_num) {
return -1;
}
return fixed_queue_length(thread->work_queues[wq_idx]);
}

View file

@ -3,130 +3,196 @@
# #
ifdef CONFIG_BT_ENABLED ifdef CONFIG_BT_ENABLED
COMPONENT_SRCDIRS := . COMPONENT_SRCDIRS := controller
COMPONENT_ADD_INCLUDEDIRS := include COMPONENT_ADD_INCLUDEDIRS := include
LIBS := btdm_app LIBS := btdm_app
COMPONENT_ADD_LDFLAGS := -lbt -L $(COMPONENT_PATH)/lib \ COMPONENT_ADD_LDFLAGS := -lbt -L $(COMPONENT_PATH)/controller/lib \
$(addprefix -l,$(LIBS)) $(addprefix -l,$(LIBS))
# re-link program if BT binary libs change # re-link program if BT binary libs change
COMPONENT_ADD_LINKER_DEPS := $(patsubst %,$(COMPONENT_PATH)/lib/lib%.a,$(LIBS)) COMPONENT_ADD_LINKER_DEPS := $(patsubst %,$(COMPONENT_PATH)/controller/lib/lib%.a,$(LIBS))
COMPONENT_SUBMODULES += lib COMPONENT_SUBMODULES += controller/lib
ifeq ($(GCC_NOT_5_2_0), 1) ifeq ($(GCC_NOT_5_2_0), 1)
# TODO: annotate fallthroughs in Bluedroid code with comments # TODO: annotate fallthroughs in Bluedroid code with comments
CFLAGS += -Wno-implicit-fallthrough CFLAGS += -Wno-implicit-fallthrough
endif endif
endif
ifdef CONFIG_BT_BLUEDROID_ENABLED ifdef CONFIG_BT_BLUEDROID_ENABLED
COMPONENT_PRIV_INCLUDEDIRS += bluedroid/bta/include \ COMPONENT_PRIV_INCLUDEDIRS += host/bluedroid/bta/include \
bluedroid/bta/ar/include \ host/bluedroid/bta/ar/include \
bluedroid/bta/av/include \ host/bluedroid/bta/av/include \
bluedroid/bta/hf_client/include \ host/bluedroid/bta/hf_client/include \
bluedroid/bta/dm/include \ host/bluedroid/bta/dm/include \
bluedroid/bta/gatt/include \ host/bluedroid/bta/gatt/include \
bluedroid/bta/hh/include \ host/bluedroid/bta/hh/include \
bluedroid/bta/jv/include \ host/bluedroid/bta/jv/include \
bluedroid/bta/sdp/include \ host/bluedroid/bta/sdp/include \
bluedroid/bta/sys/include \ host/bluedroid/bta/sys/include \
bluedroid/btcore/include \ host/bluedroid/device/include \
bluedroid/device/include \ host/bluedroid/gki/include \
bluedroid/gki/include \ host/bluedroid/hci/include \
bluedroid/hci/include \ host/bluedroid/utils/include \
bluedroid/osi/include \ host/bluedroid/external/sbc/decoder/include \
bluedroid/utils/include \ host/bluedroid/external/sbc/encoder/include \
bluedroid/external/sbc/decoder/include \ host/bluedroid/external/sbc/plc/include \
bluedroid/external/sbc/encoder/include \ host/bluedroid/btc/profile/esp/blufi/include \
bluedroid/external/sbc/plc/include \ host/bluedroid/btc/profile/esp/include \
bluedroid/btc/core/include \ host/bluedroid/btc/profile/std/gatt/include \
bluedroid/btc/profile/esp/blufi/include \ host/bluedroid/btc/profile/std/gap/include \
bluedroid/btc/profile/esp/include \ host/bluedroid/btc/profile/std/a2dp/include \
bluedroid/btc/profile/std/gatt/include \ host/bluedroid/btc/profile/std/include \
bluedroid/btc/profile/std/gap/include \ host/bluedroid/btc/include \
bluedroid/btc/profile/std/a2dp/include \ host/bluedroid/btif/include \
bluedroid/btc/profile/std/include \ host/bluedroid/stack/btm/include \
bluedroid/btc/include \ host/bluedroid/stack/btu/include \
bluedroid/btif/include \ host/bluedroid/stack/gap/include \
bluedroid/stack/btm/include \ host/bluedroid/stack/gatt/include \
bluedroid/stack/btu/include \ host/bluedroid/stack/hcic/include \
bluedroid/stack/gap/include \ host/bluedroid/stack/l2cap/include \
bluedroid/stack/gatt/include \ host/bluedroid/stack/sdp/include \
bluedroid/stack/hcic/include \ host/bluedroid/stack/smp/include \
bluedroid/stack/l2cap/include \ host/bluedroid/stack/avct/include \
bluedroid/stack/sdp/include \ host/bluedroid/stack/avrc/include \
bluedroid/stack/smp/include \ host/bluedroid/stack/avdt/include \
bluedroid/stack/avct/include \ host/bluedroid/stack/a2dp/include \
bluedroid/stack/avrc/include \ host/bluedroid/stack/rfcomm/include \
bluedroid/stack/avdt/include \ host/bluedroid/stack/include \
bluedroid/stack/a2dp/include \ host/bluedroid/utils/include \
bluedroid/stack/rfcomm/include \ host/bluedroid/common/include
bluedroid/stack/include \
bluedroid/utils/include \
bluedroid/common/include
COMPONENT_ADD_INCLUDEDIRS += bluedroid/api/include/api COMPONENT_ADD_INCLUDEDIRS += host/bluedroid/api/include/api \
common/osi/include
COMPONENT_SRCDIRS += host/bluedroid/bta/dm \
host/bluedroid/bta/gatt \
host/bluedroid/bta/hh \
host/bluedroid/bta/sdp \
host/bluedroid/bta/av \
host/bluedroid/bta/ar \
host/bluedroid/bta/sys \
host/bluedroid/bta/jv \
host/bluedroid/bta/hf_client \
host/bluedroid/bta \
host/bluedroid/btif \
host/bluedroid/device \
host/bluedroid/gki \
host/bluedroid/hci \
host/bluedroid/main \
host/bluedroid/external/sbc/decoder/srce \
host/bluedroid/external/sbc/encoder/srce \
host/bluedroid/external/sbc/plc \
host/bluedroid/btc/core \
host/bluedroid/btc/profile/esp/blufi \
host/bluedroid/btc/profile/std/gap \
host/bluedroid/btc/profile/std/gatt \
host/bluedroid/btc/profile/std/a2dp \
host/bluedroid/btc/profile/std/avrc \
host/bluedroid/btc/profile/std/spp \
host/bluedroid/btc/profile/std/hf_client \
host/bluedroid/btc/profile \
host/bluedroid/stack/btm \
host/bluedroid/stack/btu \
host/bluedroid/stack/gap \
host/bluedroid/stack/gatt \
host/bluedroid/stack/hcic \
host/bluedroid/stack/include \
host/bluedroid/stack/l2cap \
host/bluedroid/stack/sdp \
host/bluedroid/stack/smp \
host/bluedroid/stack/avct \
host/bluedroid/stack/avrc \
host/bluedroid/stack/avdt \
host/bluedroid/stack/a2dp \
host/bluedroid/stack/rfcomm \
host/bluedroid/stack \
host/bluedroid/utils \
host/bluedroid/api \
host/bluedroid
COMPONENT_SRCDIRS += bluedroid/bta/dm \
bluedroid/bta/gatt \
bluedroid/bta/hh \
bluedroid/bta/sdp \
bluedroid/bta/av \
bluedroid/bta/ar \
bluedroid/bta/sys \
bluedroid/bta/jv \
bluedroid/bta/hf_client \
bluedroid/bta \
bluedroid/btcore \
bluedroid/btif \
bluedroid/device \
bluedroid/gki \
bluedroid/hci \
bluedroid/main \
bluedroid/osi \
bluedroid/external/sbc/decoder/srce \
bluedroid/external/sbc/encoder/srce \
bluedroid/external/sbc/plc \
bluedroid/btc/core \
bluedroid/btc/profile/esp/blufi \
bluedroid/btc/profile/std/gap \
bluedroid/btc/profile/std/gatt \
bluedroid/btc/profile/std/a2dp \
bluedroid/btc/profile/std/avrc \
bluedroid/btc/profile/std/spp \
bluedroid/btc/profile/std/hf_client \
bluedroid/btc/profile \
bluedroid/stack/btm \
bluedroid/stack/btu \
bluedroid/stack/gap \
bluedroid/stack/gatt \
bluedroid/stack/hcic \
bluedroid/stack/include \
bluedroid/stack/l2cap \
bluedroid/stack/sdp \
bluedroid/stack/smp \
bluedroid/stack/avct \
bluedroid/stack/avrc \
bluedroid/stack/avdt \
bluedroid/stack/a2dp \
bluedroid/stack/rfcomm \
bluedroid/stack \
bluedroid/utils \
bluedroid/api \
bluedroid
ifeq ($(GCC_NOT_5_2_0), 1) ifeq ($(GCC_NOT_5_2_0), 1)
bluedroid/bta/sdp/bta_sdp_act.o: CFLAGS += -Wno-unused-const-variable host/bluedroid/bta/sdp/bta_sdp_act.o: CFLAGS += -Wno-unused-const-variable
bluedroid/btc/core/btc_config.o: CFLAGS += -Wno-unused-const-variable host/bluedroid/btc/core/btc_config.o: CFLAGS += -Wno-unused-const-variable
bluedroid/stack/btm/btm_sec.o: CFLAGS += -Wno-unused-const-variable host/bluedroid/stack/btm/btm_sec.o: CFLAGS += -Wno-unused-const-variable
bluedroid/stack/smp/smp_keys.o: CFLAGS += -Wno-unused-const-variable host/bluedroid/stack/smp/smp_keys.o: CFLAGS += -Wno-unused-const-variable
endif
COMPONENT_PRIV_INCLUDEDIRS += common/btc/include \
common/include
COMPONENT_SRCDIRS += common/osi \
common/btc/core
endif
ifdef CONFIG_BLE_MESH
COMPONENT_ADD_INCLUDEDIRS += esp_ble_mesh/mesh_core \
esp_ble_mesh/mesh_core/include \
esp_ble_mesh/mesh_core/settings \
esp_ble_mesh/btc/include \
esp_ble_mesh/mesh_models/include \
esp_ble_mesh/api/core/include \
esp_ble_mesh/api/models/include \
esp_ble_mesh/api
COMPONENT_SRCDIRS += esp_ble_mesh/mesh_core \
esp_ble_mesh/mesh_core/settings \
esp_ble_mesh/btc \
esp_ble_mesh/mesh_models \
esp_ble_mesh/api/core \
esp_ble_mesh/api/models
endif
ifdef CONFIG_BT_NIMBLE_ENABLED
COMPONENT_ADD_INCLUDEDIRS += host/nimble/nimble/nimble/include \
host/nimble/nimble/nimble/host/include \
host/nimble/nimble/porting/nimble/include \
host/nimble/nimble/porting/npl/freertos/include \
host/nimble/nimble/nimble/host/services/ans/include \
host/nimble/nimble/nimble/host/services/bas/include \
host/nimble/nimble/nimble/host/services/gap/include \
host/nimble/nimble/nimble/host/services/gatt/include \
host/nimble/nimble/nimble/host/services/ias/include \
host/nimble/nimble/nimble/host/services/lls/include \
host/nimble/nimble/nimble/host/services/tps/include \
host/nimble/nimble/nimble/host/util/include \
host/nimble/nimble/nimble/host/store/ram/include \
host/nimble/nimble/nimble/host/store/config/include \
host/nimble/nimble/ext/tinycrypt/include \
host/nimble/esp-hci/include \
host/nimble/port/include
COMPONENT_SRCDIRS += host/nimble/nimble/nimble/host/src \
host/nimble/nimble/porting/nimble/src \
host/nimble/nimble/porting/npl/freertos/src \
host/nimble/nimble/ext/tinycrypt/src \
host/nimble/nimble/nimble/host/services/ans/src \
host/nimble/nimble/nimble/host/services/bas/src \
host/nimble/nimble/nimble/host/services/gap/src \
host/nimble/nimble/nimble/host/services/gatt/src \
host/nimble/nimble/nimble/host/services/ias/src \
host/nimble/nimble/nimble/host/services/lls/src \
host/nimble/nimble/nimble/host/services/tps/src \
host/nimble/nimble/nimble/host/util/src \
host/nimble/nimble/nimble/host/store/ram/src \
host/nimble/nimble/nimble/host/store/config/src \
host/nimble/esp-hci/src
COMPONENT_OBJEXCLUDE += host/nimble/nimble/nimble/host/store/config/src/ble_store_config_conf.o
ifdef CONFIG_BT_NIMBLE_MESH
COMPONENT_ADD_INCLUDEDIRS += host/nimble/nimble/nimble/host/mesh/include
COMPONENT_SRCDIRS += host/nimble/nimble/nimble/host/mesh/src
endif
endif endif
endif endif

View file

@ -234,10 +234,14 @@ extern uint32_t _data_end_btdm_rom;
extern uint32_t _bt_bss_start; extern uint32_t _bt_bss_start;
extern uint32_t _bt_bss_end; extern uint32_t _bt_bss_end;
extern uint32_t _nimble_bss_start;
extern uint32_t _nimble_bss_end;
extern uint32_t _btdm_bss_start; extern uint32_t _btdm_bss_start;
extern uint32_t _btdm_bss_end; extern uint32_t _btdm_bss_end;
extern uint32_t _bt_data_start; extern uint32_t _bt_data_start;
extern uint32_t _bt_data_end; extern uint32_t _bt_data_end;
extern uint32_t _nimble_data_start;
extern uint32_t _nimble_data_end;
extern uint32_t _btdm_data_start; extern uint32_t _btdm_data_start;
extern uint32_t _btdm_data_end; extern uint32_t _btdm_data_end;
@ -1045,6 +1049,19 @@ esp_err_t esp_bt_mem_release(esp_bt_mode_t mode)
ESP_LOGD(BTDM_LOG_TAG, "Release BT Data [0x%08x] - [0x%08x]", mem_start, mem_end); ESP_LOGD(BTDM_LOG_TAG, "Release BT Data [0x%08x] - [0x%08x]", mem_start, mem_end);
ESP_ERROR_CHECK(try_heap_caps_add_region(mem_start, mem_end)); ESP_ERROR_CHECK(try_heap_caps_add_region(mem_start, mem_end));
} }
mem_start = (intptr_t)&_nimble_bss_start;
mem_end = (intptr_t)&_nimble_bss_end;
if (mem_start != mem_end) {
ESP_LOGD(BTDM_LOG_TAG, "Release NimBLE BSS [0x%08x] - [0x%08x]", mem_start, mem_end);
ESP_ERROR_CHECK(try_heap_caps_add_region(mem_start, mem_end));
}
mem_start = (intptr_t)&_nimble_data_start;
mem_end = (intptr_t)&_nimble_data_end;
if (mem_start != mem_end) {
ESP_LOGD(BTDM_LOG_TAG, "Release NimBLE Data [0x%08x] - [0x%08x]", mem_start, mem_end);
ESP_ERROR_CHECK(try_heap_caps_add_region(mem_start, mem_end));
}
} }
return ESP_OK; return ESP_OK;
} }

@ -0,0 +1 @@
Subproject commit cc2fd1177d97f1a4b9e0d819035ddf52ba77079d

View file

@ -0,0 +1,803 @@
if BLE_MESH
config BLE_MESH_HCI_5_0
bool "Support sending 20ms non-connectable adv packets"
default y
help
It is a temporary solution and needs further modifications.
config BLE_MESH_USE_DUPLICATE_SCAN
bool "Support Duplicate Scan in BLE Mesh"
select BLE_SCAN_DUPLICATE
select BLE_MESH_SCAN_DUPLICATE_EN
default y
help
Enable this option to allow using specific duplicate scan filter
in BLE Mesh, and Scan Duplicate Type must be set to 0x02.
config BLE_MESH_FAST_PROV
bool "Enable BLE Mesh Fast Provisioning"
select BLE_MESH_NODE
select BLE_MESH_PROVISIONER
select BLE_MESH_PB_ADV
default n
help
Enable this option to allow BLE Mesh fast provisioning solution to be used.
config BLE_MESH_NODE
bool "Support for BLE Mesh Node"
help
Enable the device to be provisioned into a node.
config BLE_MESH_PROVISIONER
bool "Support for BLE Mesh Provisioner"
help
Enable the device to be a provisioner.
if BLE_MESH_PROVISIONER
config BLE_MESH_WAIT_FOR_PROV_MAX_DEV_NUM
int "Maximum number of unprovisioned devices that can be added to device queue"
default 20
range 1 100
help
This option specifies how may unprovisioned devices can be added to device
queue for provisioning.
config BLE_MESH_MAX_STORED_NODES
int "Maximum number of nodes whose information can be stored"
default 20
range 1 1000
help
This option specifies the maximum number of nodes whose information can be
stored by a provisioner in its upper layer.
config BLE_MESH_MAX_PROV_NODES
int "Maximum number of devices that can be provisioned by provisioner"
default 20
range 1 100
help
This option specifies how many devices can be provisioned by provisioner.
if BLE_MESH_PB_ADV
config BLE_MESH_PBA_SAME_TIME
int "Maximum number of PB-ADV running at the same time by provisioner"
default 2
range 1 10
help
This option specifies how many devices can be provisioned at the same
time using PB-ADV.
endif # BLE_MESH_PB_ADV
if BLE_MESH_PB_GATT
config BLE_MESH_PBG_SAME_TIME
int "Maximum number of PB-GATT running at the same time by provisioner"
default 1
range 1 5
help
This option specifies how many devices can be provisioned at the same
time using PB-GATT.
endif # BLE_MESH_PB_GATT
config BLE_MESH_PROVISIONER_SUBNET_COUNT
int "Maximum number of mesh subnets that can be created by provisioner"
default 3
range 1 4096
help
This option specifies how many subnets per network a provisioner can create.
config BLE_MESH_PROVISIONER_APP_KEY_COUNT
int "Maximum number of application keys that can be owned by provisioner"
default 9
range 1 4096
help
This option specifies how many application keys the provisioner can have.
endif # BLE_MESH_PROVISIONER
# Virtual option enabled whenever Generic Provisioning layer is needed
config BLE_MESH_PROV
bool "BLE Mesh Provisioning support"
default y
help
Enable this option to support BLE Mesh Provisioning functionality. For
BLE Mesh, this option should be always enabled.
config BLE_MESH_PB_ADV
bool "Provisioning support using the advertising bearer (PB-ADV)"
select BLE_MESH_PROV
default y
help
Enable this option to allow the device to be provisioned over the
advertising bearer.
config BLE_MESH_PB_GATT
bool "Provisioning support using GATT (PB-GATT)"
select BLE_MESH_PROXY
select BLE_MESH_PROV
help
Enable this option to allow the device to be provisioned over GATT.
# Virtual option enabled whenever any Proxy protocol is needed
config BLE_MESH_PROXY
bool "BLE Mesh Proxy protocol support"
default y
help
Enable this option to support BLE Mesh Proxy protocol used by PB-GATT
and other proxy pdu transmission.
config BLE_MESH_GATT_PROXY
bool "BLE Mesh GATT Proxy Service"
select BLE_MESH_PROXY
help
This option enables support for Mesh GATT Proxy Service, i.e. the
ability to act as a proxy between a Mesh GATT Client and a Mesh network.
config BLE_MESH_NODE_ID_TIMEOUT
int "Node Identity advertising timeout"
depends on BLE_MESH_GATT_PROXY
range 1 60
default 60
help
This option determines for how long the local node advertises using
Node Identity. The given value is in seconds. The specification limits
this to 60 seconds and lists it as the recommended value as well.
So leaving the default value is the safest option.
if BLE_MESH_PROXY
config BLE_MESH_PROXY_FILTER_SIZE
int "Maximum number of filter entries per Proxy Client"
default 1
default 3 if BLE_MESH_GATT_PROXY
range 1 32767
help
This option specifies how many Proxy Filter entries the local node supports.
endif # BLE_MESH_PROXY
config BLE_MESH_NET_BUF_POOL_USAGE
bool "BLE Mesh net buffer pool usage tracking"
default y
help
Enable BLE Mesh net buffer pool tracking.
config BLE_MESH_SETTINGS
bool "Store BLE Mesh Node configuration persistently"
default n
help
When selected, the BLE Mesh stack will take care of storing/restoring the
BLE Mesh configuration persistently in flash. Currently this only supports
storing BLE Mesh node configuration.
if BLE_MESH_SETTINGS
config BLE_MESH_STORE_TIMEOUT
int "Delay (in seconds) before storing anything persistently"
range 0 1000000
default 0
help
This value defines in seconds how soon any pending changes are actually
written into persistent storage (flash) after a change occurs.
config BLE_MESH_SEQ_STORE_RATE
int "How often the sequence number gets updated in storage"
range 0 1000000
default 128
help
This value defines how often the local sequence number gets updated in
persistent storage (i.e. flash). e.g. a value of 100 means that the
sequence number will be stored to flash on every 100th increment.
If the node sends messages very frequently a higher value makes more
sense, whereas if the node sends infrequently a value as low as 0
(update storage for every increment) can make sense. When the stack
gets initialized it will add sequence number to the last stored one,
so that it starts off with a value that's guaranteed to be larger than
the last one used before power off.
config BLE_MESH_RPL_STORE_TIMEOUT
int "Minimum frequency that the RPL gets updated in storage"
range 0 1000000
default 5
help
This value defines in seconds how soon the RPL(Replay Protection List)
gets written to persistent storage after a change occurs. If the node
receives messages frequently, then a large value is recommended. If the
node receives messages rarely, then the value can be as low as 0 (which
means the PRL is written into the storage immediately).
Note that if the node operates in a security-sensitive case, and there is
a risk of sudden power-off, then a value of 0 is strongly recommended.
Otherwise, a power loss before RPL being written into the storage may
introduce message replay attacks and system security will be in a
vulnerable state.
endif # if BLE_MESH_SETTINGS
config BLE_MESH_SUBNET_COUNT
int "Maximum number of mesh subnets per network"
default 3
range 1 4096
help
This option specifies how many subnets a Mesh network can have at the same time.
config BLE_MESH_APP_KEY_COUNT
int "Maximum number of application keys per network"
default 3
range 1 4096
help
This option specifies how many application keys the device can store per network.
config BLE_MESH_MODEL_KEY_COUNT
int "Maximum number of application keys per model"
default 3
range 1 4096
help
This option specifies the maximum number of application keys to which each model
can be bound.
config BLE_MESH_MODEL_GROUP_COUNT
int "Maximum number of group address subscriptions per model"
default 3
range 1 4096
help
This option specifies the maximum number of addresses to which each model can
be subscribed.
config BLE_MESH_LABEL_COUNT
int "Maximum number of Label UUIDs used for Virtual Addresses"
default 3
range 0 4096
help
This option specifies how many Label UUIDs can be stored.
config BLE_MESH_CRPL
int "Maximum capacity of the replay protection list"
default 10
range 2 65535
help
This option specifies the maximum capacity of the replay protection list.
It is similar to Network message cache size, but has a different purpose.
config BLE_MESH_MSG_CACHE_SIZE
int "Network message cache size"
default 10
range 2 65535
help
Number of messages that are cached for the network. This helps prevent
unnecessary decryption operations and unnecessary relays. This option
is similar to Replay protection list, but has a different purpose.
config BLE_MESH_ADV_BUF_COUNT
int "Number of advertising buffers"
default 60
range 6 256
help
Number of advertising buffers available. The transport layer reserves
ADV_BUF_COUNT - 3 buffers for outgoing segments. The maximum outgoing
SDU size is 12 times this value (out of which 4 or 8 bytes are used
for the Transport Layer MIC). For example, 5 segments means the maximum
SDU size is 60 bytes, which leaves 56 bytes for application layer data
using a 4-byte MIC, or 52 bytes using an 8-byte MIC.
config BLE_MESH_IVU_DIVIDER
int "Divider for IV Update state refresh timer"
default 4
range 2 96
help
When the IV Update state enters Normal operation or IV Update
in Progress, we need to keep track of how many hours has passed
in the state, since the specification requires us to remain in
the state at least for 96 hours (Update in Progress has an
additional upper limit of 144 hours).
In order to fulfill the above requirement, even if the node might
be powered off once in a while, we need to store persistently
how many hours the node has been in the state. This doesn't
necessarily need to happen every hour (thanks to the flexible
duration range). The exact cadence will depend a lot on the
ways that the node will be used and what kind of power source it
has.
Since there is no single optimal answer, this configuration
option allows specifying a divider, i.e. how many intervals
the 96 hour minimum gets split into. After each interval the
duration that the node has been in the current state gets
stored to flash. E.g. the default value of 4 means that the
state is saved every 24 hours (96 / 4).
config BLE_MESH_TX_SEG_MSG_COUNT
int "Maximum number of simultaneous outgoing segmented messages"
default 1
range 1 BLE_MESH_ADV_BUF_COUNT
help
Maximum number of simultaneous outgoing multi-segment and/or reliable messages.
config BLE_MESH_RX_SEG_MSG_COUNT
int "Maximum number of simultaneous incoming segmented messages"
default 1
range 1 255
help
Maximum number of simultaneous incoming multi-segment and/or reliable messages.
config BLE_MESH_RX_SDU_MAX
int "Maximum incoming Upper Transport Access PDU length"
default 384
range 36 384
help
Maximum incoming Upper Transport Access PDU length. Leave this to the default
value, unless you really need to optimize memory usage.
config BLE_MESH_TX_SEG_MAX
int "Maximum number of segments in outgoing messages"
default 20
range 2 32
help
Maximum number of segments supported for outgoing messages.
This value should typically be fine-tuned based on what
models the local node supports, i.e. what's the largest
message payload that the node needs to be able to send.
This value affects memory and call stack consumption, which
is why the default is lower than the maximum that the
specification would allow (32 segments).
The maximum outgoing SDU size is 12 times this number (out of
which 4 or 8 bytes is used for the Transport Layer MIC). For
example, 5 segments means the maximum SDU size is 60 bytes,
which leaves 56 bytes for application layer data using a
4-byte MIC and 52 bytes using an 8-byte MIC.
Be sure to specify a sufficient number of advertising buffers
when setting this option to a higher value. There must be at
least three more advertising buffers (BLE_MESH_ADV_BUF_COUNT)
as there are outgoing segments.
config BLE_MESH_RELAY
bool "Relay support"
help
Support for acting as a Mesh Relay Node.
config BLE_MESH_LOW_POWER
bool "Support for Low Power features"
help
Enable this option to operate as a Low Power Node.
if BLE_MESH_LOW_POWER
config BLE_MESH_LPN_ESTABLISHMENT
bool "Perform Friendship establishment using low power"
default y
help
Perform the Friendship establishment using low power with the help of a
reduced scan duty cycle. The downside of this is that the node may miss
out on messages intended for it until it has successfully set up Friendship
with a Friend node.
config BLE_MESH_LPN_AUTO
bool "Automatically start looking for Friend nodes once provisioned"
default y
help
Once provisioned, automatically enable LPN functionality and start looking
for Friend nodes. If this option is disabled LPN mode needs to be manually
enabled by calling bt_mesh_lpn_set(true).
config BLE_MESH_LPN_AUTO_TIMEOUT
int "Time from last received message before going to LPN mode"
default 15
range 0 3600
depends on BLE_MESH_LPN_AUTO
help
Time in seconds from the last received message, that the node waits out
before starting to look for Friend nodes.
config BLE_MESH_LPN_RETRY_TIMEOUT
int "Retry timeout for Friend requests"
default 8
range 1 3600
help
Time in seconds between Friend Requests, if a previous Friend Request did
not yield any acceptable Friend Offers.
config BLE_MESH_LPN_RSSI_FACTOR
int "RSSIFactor, used in Friend Offer Delay calculation"
range 0 3
default 0
help
The contribution of the RSSI, measured by the Friend node, used in Friend
Offer Delay calculations. 0 = 1, 1 = 1.5, 2 = 2, 3 = 2.5.
config BLE_MESH_LPN_RECV_WIN_FACTOR
int "ReceiveWindowFactor, used in Friend Offer Delay calculation"
range 0 3
default 0
help
The contribution of the supported Receive Window used in Friend Offer
Delay calculations. 0 = 1, 1 = 1.5, 2 = 2, 3 = 2.5.
config BLE_MESH_LPN_MIN_QUEUE_SIZE
int "Minimum size of the acceptable friend queue (MinQueueSizeLog)"
range 1 7
default 1
help
The MinQueueSizeLog field is defined as log_2(N), where N is the minimum
number of maximum size Lower Transport PDUs that the Friend node can store
in its Friend Queue. As an example, MinQueueSizeLog value 1 gives N = 2,
and value 7 gives N = 128.
config BLE_MESH_LPN_RECV_DELAY
int "Receive delay requested by the local node"
range 10 255
default 100
help
The ReceiveDelay is the time between the Low Power node sending a
request and listening for a response. This delay allows the Friend
node time to prepare the response. The value is in units of milliseconds.
config BLE_MESH_LPN_POLL_TIMEOUT
int "The value of the PollTimeout timer"
range 10 244735
default 300
help
PollTimeout timer is used to measure time between two consecutive
requests sent by a Low Power node. If no requests are received
the Friend node before the PollTimeout timer expires, then the
friendship is considered terminated. The value is in units of 100
milliseconds, so e.g. a value of 300 means 30 seconds.
config BLE_MESH_LPN_INIT_POLL_TIMEOUT
int "The starting value of the PollTimeout timer"
range 10 BLE_MESH_LPN_POLL_TIMEOUT
default BLE_MESH_LPN_POLL_TIMEOUT
help
The initial value of the PollTimeout timer when Friendship is to be
established for the first time. After this, the timeout gradually
grows toward the actual PollTimeout, doubling in value for each iteration.
The value is in units of 100 milliseconds, so e.g. a value of 300 means
30 seconds.
config BLE_MESH_LPN_SCAN_LATENCY
int "Latency for enabling scanning"
range 0 50
default 10
help
Latency (in milliseconds) is the time it takes to enable scanning. In
practice, it means how much time in advance of the Receive Window, the
request to enable scanning is made.
config BLE_MESH_LPN_GROUPS
int "Number of groups the LPN can subscribe to"
range 0 16384
default 8
help
Maximum number of groups to which the LPN can subscribe.
endif # BLE_MESH_LOW_POWER
config BLE_MESH_FRIEND
bool "Support for acting as a Friend Node"
help
Enable this option to be able to act as a Friend Node.
if BLE_MESH_FRIEND
config BLE_MESH_FRIEND_RECV_WIN
int "Friend Receive Window"
range 1 255
default 255
help
Receive Window in milliseconds supported by the Friend node.
config BLE_MESH_FRIEND_QUEUE_SIZE
int "Minimum number of buffers supported per Friend Queue"
range 2 65536
default 16
help
Minimum number of buffers available to be stored for each local Friend Queue.
config BLE_MESH_FRIEND_SUB_LIST_SIZE
int "Friend Subscription List Size"
range 0 1023
default 3
help
Size of the Subscription List that can be supported by a Friend node for a
Low Power node.
config BLE_MESH_FRIEND_LPN_COUNT
int "Number of supported LPN nodes"
range 1 1000
default 2
help
Number of Low Power Nodes with which a Friend can have Friendship simultaneously.
config BLE_MESH_FRIEND_SEG_RX
int "Number of incomplete segment lists per LPN"
range 1 1000
default 1
help
Number of incomplete segment lists tracked for each Friends' LPN.
In other words, this determines from how many elements can segmented
messages destined for the Friend queue be received simultaneously.
endif # BLE_MESH_FRIEND
config BLE_MESH_NO_LOG
bool "Disable BLE Mesh debug logs (minimize bin size)"
depends on BLE_MESH
default n
help
Select this to save the BLE Mesh related rodata code size.
menu "BLE Mesh STACK DEBUG LOG LEVEL"
depends on BLE_MESH && !BLE_MESH_NO_LOG
choice BLE_MESH_STACK_TRACE_LEVEL
prompt "BLE_MESH_STACK"
default BLE_MESH_TRACE_LEVEL_WARNING
depends on BLE_MESH && !BLE_MESH_NO_LOG
help
Define BLE Mesh trace level for BLE Mesh stack.
config BLE_MESH_TRACE_LEVEL_NONE
bool "NONE"
config BLE_MESH_TRACE_LEVEL_ERROR
bool "ERROR"
config BLE_MESH_TRACE_LEVEL_WARNING
bool "WARNING"
config BLE_MESH_TRACE_LEVEL_INFO
bool "INFO"
config BLE_MESH_TRACE_LEVEL_DEBUG
bool "DEBUG"
config BLE_MESH_TRACE_LEVEL_VERBOSE
bool "VERBOSE"
endchoice
config BLE_MESH_STACK_TRACE_LEVEL
int
depends on BLE_MESH
default 0 if BLE_MESH_TRACE_LEVEL_NONE
default 1 if BLE_MESH_TRACE_LEVEL_ERROR
default 2 if BLE_MESH_TRACE_LEVEL_WARNING
default 3 if BLE_MESH_TRACE_LEVEL_INFO
default 4 if BLE_MESH_TRACE_LEVEL_DEBUG
default 5 if BLE_MESH_TRACE_LEVEL_VERBOSE
default 2
endmenu #BLE Mesh DEBUG LOG LEVEL
menu "BLE Mesh NET BUF DEBUG LOG LEVEL"
depends on BLE_MESH && !BLE_MESH_NO_LOG
choice BLE_MESH_NET_BUF_TRACE_LEVEL
prompt "BLE_MESH_NET_BUF"
default BLE_MESH_NET_BUF_TRACE_LEVEL_WARNING
depends on BLE_MESH && !BLE_MESH_NO_LOG
help
Define BLE Mesh trace level for BLE Mesh net buffer.
config BLE_MESH_NET_BUF_TRACE_LEVEL_NONE
bool "NONE"
config BLE_MESH_NET_BUF_TRACE_LEVEL_ERROR
bool "ERROR"
config BLE_MESH_NET_BUF_TRACE_LEVEL_WARNING
bool "WARNING"
config BLE_MESH_NET_BUF_TRACE_LEVEL_INFO
bool "INFO"
config BLE_MESH_NET_BUF_TRACE_LEVEL_DEBUG
bool "DEBUG"
config BLE_MESH_NET_BUF_TRACE_LEVEL_VERBOSE
bool "VERBOSE"
endchoice
config BLE_MESH_NET_BUF_TRACE_LEVEL
int
depends on BLE_MESH
default 0 if BLE_MESH_NET_BUF_TRACE_LEVEL_NONE
default 1 if BLE_MESH_NET_BUF_TRACE_LEVEL_ERROR
default 2 if BLE_MESH_NET_BUF_TRACE_LEVEL_WARNING
default 3 if BLE_MESH_NET_BUF_TRACE_LEVEL_INFO
default 4 if BLE_MESH_NET_BUF_TRACE_LEVEL_DEBUG
default 5 if BLE_MESH_NET_BUF_TRACE_LEVEL_VERBOSE
default 2
endmenu #BLE Mesh NET BUF DEBUG LOG LEVEL
config BLE_MESH_IRQ_LOCK
bool "Used the IRQ lock instead of task lock"
help
To improve the real-time requirements of bt controller in BLE Mesh,
task lock is used to replace IRQ lock.
config BLE_MESH_CLIENT_MSG_TIMEOUT
int "Timeout(ms) for client message response"
range 100 1200000
default 4000
help
Timeout value used by the node to get response of the acknowledged
message which is sent by the client model.
menu "Support for BLE Mesh Client Models"
config BLE_MESH_CFG_CLI
bool "Configuration Client Model"
help
Enable support for Configuration client model.
config BLE_MESH_HEALTH_CLI
bool "Health Client Model"
help
Enable support for Health client model.
config BLE_MESH_GENERIC_ONOFF_CLI
bool "Generic OnOff Client Model"
help
Enable support for Generic OnOff client model.
config BLE_MESH_GENERIC_LEVEL_CLI
bool "Generic Level Client Model"
help
Enable support for Generic Level client model.
config BLE_MESH_GENERIC_DEF_TRANS_TIME_CLI
bool "Generic Default Transition Time Client Model"
help
Enable support for Generic Default Transition Time client model.
config BLE_MESH_GENERIC_POWER_ONOFF_CLI
bool "Generic Power Onoff Client Model"
help
Enable support for Generic Power Onoff client model.
config BLE_MESH_GENERIC_POWER_LEVEL_CLI
bool "Generic Power Level Client Model"
help
Enable support for Generic Power Level client model.
config BLE_MESH_GENERIC_BATTERY_CLI
bool "Generic Battery Client Model"
help
Enable support for Generic Battery client model.
config BLE_MESH_GENERIC_LOCATION_CLI
bool "Generic Location Client Model"
help
Enable support for Generic Location client model.
config BLE_MESH_GENERIC_PROPERTY_CLI
bool "Generic Property Client Model"
help
Enable support for Generic Property client model.
config BLE_MESH_SENSOR_CLI
bool "Sensor Client Model"
help
Enable support for Sensor client model.
config BLE_MESH_TIME_CLI
bool "Time Client Model"
help
Enable support for Time client model.
config BLE_MESH_SCENE_CLI
bool "Scene Client Model"
help
Enable support for Scene client model.
config BLE_MESH_SCHEDULER_CLI
bool "Scheduler Client Model"
help
Enable support for Scheduler client model.
config BLE_MESH_LIGHT_LIGHTNESS_CLI
bool "Light Lightness Client Model"
help
Enable support for Light Lightness client model.
config BLE_MESH_LIGHT_CTL_CLI
bool "Light CTL Client Model"
help
Enable support for Light CTL client model.
config BLE_MESH_LIGHT_HSL_CLI
bool "Light HSL Client Model"
help
Enable support for Light HSL client model.
config BLE_MESH_LIGHT_XYL_CLI
bool "Light XYL Client Model"
help
Enable support for Light XYL client model.
config BLE_MESH_LIGHT_LC_CLI
bool "Light LC Client Model"
help
Enable support for Light LC client model.
endmenu
config BLE_MESH_IV_UPDATE_TEST
bool "Test the IV Update Procedure"
default n
help
This option removes the 96 hour limit of the IV Update Procedure and
lets the state to be changed at any time.
menu "BLE Mesh specific test option"
config BLE_MESH_SELF_TEST
bool "Perform BLE Mesh self-tests"
default n
help
This option adds extra self-tests which are run every time BLE Mesh
networking is initialized.
config BLE_MESH_SHELL
bool "Enable BLE Mesh shell"
default n
help
Activate shell module that provides BLE Mesh commands to the console.
config BLE_MESH_DEBUG
bool "Enable BLE Mesh debug logs"
default n
help
Enable debug logs for the BLE Mesh functionality.
if BLE_MESH_DEBUG
config BLE_MESH_DEBUG_NET
bool "Network layer debug"
help
Enable Network layer debug logs for the BLE Mesh functionality.
config BLE_MESH_DEBUG_TRANS
bool "Transport layer debug"
help
Enable Transport layer debug logs for the BLE Mesh functionality.
config BLE_MESH_DEBUG_BEACON
bool "Beacon debug"
help
Enable Beacon-related debug logs for the BLE Mesh functionality.
config BLE_MESH_DEBUG_CRYPTO
bool "Crypto debug"
help
Enable cryptographic debug logs for the BLE Mesh functionality.
config BLE_MESH_DEBUG_PROV
bool "Provisioning debug"
help
Enable Provisioning debug logs for the BLE Mesh functionality.
config BLE_MESH_DEBUG_ACCESS
bool "Access layer debug"
help
Enable Access layer debug logs for the BLE Mesh functionality.
config BLE_MESH_DEBUG_MODEL
bool "Foundation model debug"
help
Enable Foundation Models debug logs for the BLE Mesh functionality.
config BLE_MESH_DEBUG_ADV
bool "Advertising debug"
help
Enable advertising debug logs for the BLE Mesh functionality.
config BLE_MESH_DEBUG_LOW_POWER
bool "Low Power debug"
help
Enable Low Power debug logs for the BLE Mesh functionality.
config BLE_MESH_DEBUG_FRIEND
bool "Friend debug"
help
Enable Friend debug logs for the BLE Mesh functionality.
config BLE_MESH_DEBUG_PROXY
bool "Proxy debug"
depends on BLE_MESH_PROXY
help
Enable Proxy protocol debug logs for the BLE Mesh functionality.
endif # BLE_MESH_DEBUG
endmenu
endif # BLE_MESH

View file

@ -0,0 +1,70 @@
// Copyright 2017-2019 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <stdint.h>
#include "freertos/FreeRTOS.h"
#include "freertos/semphr.h"
#include "btc/btc_task.h"
#include "btc/btc_manage.h"
#include "esp_err.h"
#include "esp_bt_defs.h"
#include "esp_bt_main.h"
#include "btc_ble_mesh_prov.h"
#include "esp_ble_mesh_defs.h"
esp_err_t esp_ble_mesh_init(esp_ble_mesh_prov_t *prov, esp_ble_mesh_comp_t *comp)
{
btc_ble_mesh_prov_args_t arg = {0};
SemaphoreHandle_t semaphore = NULL;
btc_msg_t msg = {0};
if (prov == NULL || comp == NULL) {
return ESP_ERR_INVALID_ARG;
}
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
// Create a semaphore
if ((semaphore = xSemaphoreCreateCounting(1, 0)) == NULL) {
LOG_ERROR("%s, Failed to allocate memory for the semaphore", __func__);
return ESP_ERR_NO_MEM;
}
arg.mesh_init.prov = prov;
arg.mesh_init.comp = comp;
/* Transport semaphore pointer to BTC layer, and will give the semaphore in the BTC task */
arg.mesh_init.semaphore = semaphore;
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_PROV;
msg.act = BTC_BLE_MESH_ACT_MESH_INIT;
if (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL) != BT_STATUS_SUCCESS) {
vSemaphoreDelete(semaphore);
LOG_ERROR("%s, BLE Mesh initialise failed", __func__);
return ESP_FAIL;
}
/* Take the Semaphore, wait BLE Mesh initialization to finish. */
xSemaphoreTake(semaphore, portMAX_DELAY);
/* Don't forget to delete the semaphore at the end. */
vSemaphoreDelete(semaphore);
return ESP_OK;
}

View file

@ -0,0 +1,80 @@
// Copyright 2017-2019 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <stdint.h>
#include <errno.h>
#include "btc/btc_task.h"
#include "btc/btc_manage.h"
#include "esp_err.h"
#include "esp_bt_defs.h"
#include "esp_bt_main.h"
#include "btc_ble_mesh_prov.h"
#include "esp_ble_mesh_defs.h"
int32_t esp_ble_mesh_get_model_publish_period(esp_ble_mesh_model_t *model)
{
if (model == NULL) {
return 0;
}
return btc_ble_mesh_model_pub_period_get(model);
}
uint16_t esp_ble_mesh_get_primary_element_address(void)
{
return btc_ble_mesh_get_primary_addr();
}
uint16_t *esp_ble_mesh_is_model_subscribed_to_group(esp_ble_mesh_model_t *model, uint16_t group_addr)
{
if (model == NULL) {
return NULL;
}
return btc_ble_mesh_model_find_group(model, group_addr);
}
esp_ble_mesh_elem_t *esp_ble_mesh_find_element(uint16_t element_addr)
{
return btc_ble_mesh_elem_find(element_addr);
}
uint8_t esp_ble_mesh_get_element_count(void)
{
return btc_ble_mesh_elem_count();
}
esp_ble_mesh_model_t *esp_ble_mesh_find_vendor_model(const esp_ble_mesh_elem_t *element,
uint16_t company_id, uint16_t model_id)
{
if (element == NULL) {
return NULL;
}
return btc_ble_mesh_model_find_vnd(element, company_id, model_id);
}
esp_ble_mesh_model_t *esp_ble_mesh_find_sig_model(const esp_ble_mesh_elem_t *element, uint16_t model_id)
{
if (element == NULL) {
return NULL;
}
return btc_ble_mesh_model_find(element, model_id);
}
const esp_ble_mesh_comp_t *esp_ble_mesh_get_composition_data(void)
{
return btc_ble_mesh_comp_get();
}

View file

@ -0,0 +1,26 @@
// Copyright 2017-2019 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <stdint.h>
#include "btc/btc_task.h"
#include "btc/btc_manage.h"
#include "esp_err.h"
#include "esp_bt_defs.h"
#include "esp_bt_main.h"
#include "btc_ble_mesh_prov.h"
#include "esp_ble_mesh_defs.h"

View file

@ -0,0 +1,338 @@
// Copyright 2017-2019 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <stdint.h>
#include <errno.h>
#include "btc/btc_task.h"
#include "btc/btc_manage.h"
#include "esp_err.h"
#include "esp_bt_defs.h"
#include "esp_bt_main.h"
#include "btc_ble_mesh_prov.h"
#include "esp_ble_mesh_networking_api.h"
#define ESP_BLE_MESH_TX_SDU_MAX ((CONFIG_BLE_MESH_ADV_BUF_COUNT - 3) * 12)
static esp_err_t ble_mesh_send_msg(esp_ble_mesh_model_t *model,
esp_ble_mesh_msg_ctx_t *ctx,
uint32_t opcode,
btc_ble_mesh_model_act_t act,
uint16_t length, uint8_t *data,
int32_t msg_timeout, bool need_rsp,
esp_ble_mesh_dev_role_t device_role)
{
btc_ble_mesh_model_args_t arg = {0};
uint8_t op_len = 0, mic_len = 0;
uint8_t *msg_data = NULL;
btc_msg_t msg = {0};
esp_err_t status;
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
if (device_role > ROLE_FAST_PROV) {
return ESP_ERR_INVALID_ARG;
}
/* When data is NULL, it is mandatory to set length to 0 to prevent users from misinterpreting parameters. */
if (data == NULL) {
length = 0;
}
if (opcode < 0x100) {
op_len = 1;
} else if (opcode < 0x10000) {
op_len = 2;
} else {
op_len = 3;
}
if (act == BTC_BLE_MESH_ACT_MODEL_PUBLISH) {
if (op_len + length > model->pub->msg->size) {
LOG_ERROR("%s, Model publication msg size %d is too small", __func__, model->pub->msg->size);
return ESP_ERR_INVALID_ARG;
}
}
if (act == BTC_BLE_MESH_ACT_MODEL_PUBLISH) {
mic_len = 4;
} else {
mic_len = ctx->send_rel ? 8 : 4;
}
if (op_len + length + mic_len > MIN(ESP_BLE_MESH_SDU_MAX_LEN, ESP_BLE_MESH_TX_SDU_MAX)) {
LOG_ERROR("%s, Data length %d is too large", __func__, length);
return ESP_ERR_INVALID_ARG;
}
if (act == BTC_BLE_MESH_ACT_MODEL_PUBLISH) {
bt_mesh_model_msg_init(model->pub->msg, opcode);
net_buf_simple_add_mem(model->pub->msg, data, length);
} else {
msg_data = (uint8_t *)osi_malloc(op_len + length);
if (msg_data == NULL) {
return ESP_ERR_NO_MEM;
}
esp_ble_mesh_model_msg_opcode_init(msg_data, opcode);
memcpy(msg_data + op_len, data, length);
}
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_MODEL;
msg.act = act;
if (act == BTC_BLE_MESH_ACT_MODEL_PUBLISH) {
arg.model_publish.model = model;
arg.model_publish.device_role = device_role;
} else {
arg.model_send.model = model;
arg.model_send.ctx = ctx;
arg.model_send.need_rsp = need_rsp;
arg.model_send.opcode = opcode;
arg.model_send.length = op_len + length;
arg.model_send.data = msg_data;
arg.model_send.device_role = device_role;
arg.model_send.msg_timeout = msg_timeout;
}
status = (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_model_args_t), btc_ble_mesh_prov_arg_deep_copy)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
osi_free(msg_data);
return status;
}
esp_err_t esp_ble_mesh_register_custom_model_callback(esp_ble_mesh_model_cb_t callback)
{
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
return (btc_profile_cb_set(BTC_PID_MODEL, callback) == 0 ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_model_msg_opcode_init(uint8_t *data, uint32_t opcode)
{
uint16_t val;
if (data == NULL) {
return ESP_ERR_INVALID_ARG;
}
if (opcode < 0x100) {
/* 1-byte OpCode */
data[0] = opcode & 0xff;
return ESP_OK;
}
if (opcode < 0x10000) {
/* 2-byte OpCode, big endian */
val = sys_cpu_to_be16 (opcode);
memcpy(data, &val, 2);
return ESP_OK;
}
/* 3-byte OpCode, note that little endian for the least 2 bytes(Company ID) of opcode */
data[0] = (opcode >> 16) & 0xff;
val = sys_cpu_to_le16(opcode & 0xffff);
memcpy(&data[1], &val, 2);
return ESP_OK;
}
esp_err_t esp_ble_mesh_client_model_init(esp_ble_mesh_model_t *model)
{
if (model == NULL) {
return ESP_ERR_INVALID_ARG;
}
return btc_ble_mesh_client_init(model);
}
esp_err_t esp_ble_mesh_server_model_send_msg(esp_ble_mesh_model_t *model,
esp_ble_mesh_msg_ctx_t *ctx, uint32_t opcode,
uint16_t length, uint8_t *data)
{
if (!model || !ctx) {
return ESP_ERR_INVALID_ARG;
}
return ble_mesh_send_msg(model, ctx, opcode, BTC_BLE_MESH_ACT_SERVER_MODEL_SEND,
length, data, 0, false, ROLE_NODE);
}
esp_err_t esp_ble_mesh_client_model_send_msg(esp_ble_mesh_model_t *model,
esp_ble_mesh_msg_ctx_t *ctx, uint32_t opcode,
uint16_t length, uint8_t *data, int32_t msg_timeout,
bool need_rsp, esp_ble_mesh_dev_role_t device_role)
{
if (!model || !ctx) {
return ESP_ERR_INVALID_ARG;
}
return ble_mesh_send_msg(model, ctx, opcode, BTC_BLE_MESH_ACT_CLIENT_MODEL_SEND,
length, data, msg_timeout, need_rsp, device_role);
}
esp_err_t esp_ble_mesh_model_publish(esp_ble_mesh_model_t *model, uint32_t opcode,
uint16_t length, uint8_t *data,
esp_ble_mesh_dev_role_t device_role)
{
if (!model || !model->pub || !model->pub->msg) {
return ESP_ERR_INVALID_ARG;
}
return ble_mesh_send_msg(model, NULL, opcode, BTC_BLE_MESH_ACT_MODEL_PUBLISH,
length, data, 0, false, device_role);
}
esp_err_t esp_ble_mesh_node_local_reset(void)
{
btc_msg_t msg = {0};
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_PROV;
msg.act = BTC_BLE_MESH_ACT_NODE_RESET;
return (btc_transfer_context(&msg, NULL, 0, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
#if (CONFIG_BLE_MESH_PROVISIONER)
esp_err_t esp_ble_mesh_provisioner_set_node_name(int index, const char *name)
{
btc_ble_mesh_prov_args_t arg = {0};
btc_msg_t msg = {0};
if (!name || (strlen(name) > ESP_BLE_MESH_NODE_NAME_MAX_LEN)) {
return ESP_ERR_INVALID_ARG;
}
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_PROV;
msg.act = BTC_BLE_MESH_ACT_PROVISIONER_SET_NODE_NAME;
arg.set_node_name.index = index;
memset(arg.set_node_name.name, 0, sizeof(arg.set_node_name.name));
memcpy(arg.set_node_name.name, name, strlen(name));
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
const char *esp_ble_mesh_provisioner_get_node_name(int index)
{
return bt_mesh_provisioner_get_node_name(index);
}
int esp_ble_mesh_provisioner_get_node_index(const char *name)
{
if (!name || (strlen(name) > ESP_BLE_MESH_NODE_NAME_MAX_LEN)) {
return -EINVAL;
}
return bt_mesh_provisioner_get_node_index(name);
}
esp_err_t esp_ble_mesh_provisioner_add_local_app_key(const uint8_t app_key[16],
uint16_t net_idx, uint16_t app_idx)
{
btc_ble_mesh_prov_args_t arg = {0};
btc_msg_t msg = {0};
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_PROV;
msg.act = BTC_BLE_MESH_ACT_PROVISIONER_SET_LOCAL_APP_KEY;
arg.add_local_app_key.net_idx = net_idx;
arg.add_local_app_key.app_idx = app_idx;
if (app_key) {
memcpy(arg.add_local_app_key.app_key, app_key, 16);
} else {
bzero(arg.add_local_app_key.app_key, 16);
}
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
const uint8_t *esp_ble_mesh_provisioner_get_local_app_key(uint16_t net_idx, uint16_t app_idx)
{
return bt_mesh_provisioner_local_app_key_get(net_idx, app_idx);
}
esp_err_t esp_ble_mesh_provisioner_bind_app_key_to_local_model(uint16_t element_addr, uint16_t app_idx,
uint16_t model_id, uint16_t company_id)
{
btc_ble_mesh_prov_args_t arg = {0};
btc_msg_t msg = {0};
if (!ESP_BLE_MESH_ADDR_IS_UNICAST(element_addr)) {
return ESP_ERR_INVALID_ARG;
}
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_PROV;
msg.act = BTC_BLE_MESH_ACT_PROVISIONER_BIND_LOCAL_MOD_APP;
arg.local_mod_app_bind.elem_addr = element_addr;
arg.local_mod_app_bind.app_idx = app_idx;
arg.local_mod_app_bind.model_id = model_id;
arg.local_mod_app_bind.cid = company_id;
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_provisioner_add_local_net_key(const uint8_t net_key[16], uint16_t net_idx)
{
btc_ble_mesh_prov_args_t arg = {0};
btc_msg_t msg = {0};
if (net_idx == ESP_BLE_MESH_KEY_PRIMARY) {
return ESP_ERR_INVALID_ARG;
}
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_PROV;
msg.act = BTC_BLE_MESH_ACT_PROVISIONER_ADD_LOCAL_NET_KEY;
arg.add_local_net_key.net_idx = net_idx;
if (net_key) {
memcpy(arg.add_local_net_key.net_key, net_key, 16);
} else {
bzero(arg.add_local_net_key.net_key, 16);
}
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
const uint8_t *esp_ble_mesh_provisioner_get_local_net_key(uint16_t net_idx)
{
return bt_mesh_provisioner_local_net_key_get(net_idx);
}
#endif /* CONFIG_BLE_MESH_PROVISIONER */
#if (CONFIG_BLE_MESH_FAST_PROV)
const uint8_t *esp_ble_mesh_get_fast_prov_app_key(uint16_t net_idx, uint16_t app_idx)
{
return bt_mesh_get_fast_prov_app_key(net_idx, app_idx);
}
#endif /* CONFIG_BLE_MESH_FAST_PROV */

View file

@ -0,0 +1,423 @@
// Copyright 2017-2019 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <stdint.h>
#include "btc/btc_task.h"
#include "btc/btc_manage.h"
#include "esp_err.h"
#include "esp_bt_defs.h"
#include "esp_bt_main.h"
#include "btc_ble_mesh_prov.h"
#include "esp_ble_mesh_provisioning_api.h"
#define MAX_PROV_LINK_IDX (CONFIG_BLE_MESH_PBA_SAME_TIME + CONFIG_BLE_MESH_PBG_SAME_TIME)
#define MAX_OOB_INPUT_NUM 0x5F5E0FF /* Decimal: 99999999 */
esp_err_t esp_ble_mesh_register_prov_callback(esp_ble_mesh_prov_cb_t callback)
{
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
return (btc_profile_cb_set(BTC_PID_PROV, callback) == 0 ? ESP_OK : ESP_FAIL);
}
bool esp_ble_mesh_node_is_provisioned(void)
{
return bt_mesh_is_provisioned();
}
esp_err_t esp_ble_mesh_node_prov_enable(esp_ble_mesh_prov_bearer_t bearers)
{
btc_ble_mesh_prov_args_t arg = {0};
btc_msg_t msg = {0};
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_PROV;
msg.act = BTC_BLE_MESH_ACT_PROV_ENABLE;
arg.node_prov_enable.bearers = bearers;
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_node_prov_disable(esp_ble_mesh_prov_bearer_t bearers)
{
btc_ble_mesh_prov_args_t arg = {0};
btc_msg_t msg = {0};
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_PROV;
msg.act = BTC_BLE_MESH_ACT_PROV_DISABLE;
arg.node_prov_disable.bearers = bearers;
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_node_set_oob_pub_key(uint8_t pub_key_x[32], uint8_t pub_key_y[32],
uint8_t private_key[32])
{
btc_ble_mesh_prov_args_t arg = {0};
btc_msg_t msg = {0};
if (!pub_key_x || !pub_key_y || !private_key) {
return ESP_ERR_INVALID_ARG;
}
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_PROV;
msg.act = BTC_BLE_MESH_ACT_SET_OOB_PUB_KEY;
memcpy(arg.set_oob_pub_key.pub_key_x, pub_key_x, 32);
memcpy(arg.set_oob_pub_key.pub_key_y, pub_key_y, 32);
memcpy(arg.set_oob_pub_key.private_key, private_key, 32);
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_node_input_number(uint32_t number)
{
btc_ble_mesh_prov_args_t arg = {0};
btc_msg_t msg = {0};
if (number > MAX_OOB_INPUT_NUM) {
return ESP_ERR_INVALID_ARG;
}
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_PROV;
msg.act = BTC_BLE_MESH_ACT_INPUT_NUMBER;
arg.input_number.number = number;
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_node_input_string(const char *string)
{
btc_ble_mesh_prov_args_t arg = {0};
btc_msg_t msg = {0};
if (!string) {
return ESP_ERR_INVALID_ARG;
}
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_PROV;
msg.act = BTC_BLE_MESH_ACT_INPUT_STRING;
memset(arg.input_string.string, 0, sizeof(arg.input_string.string));
strncpy(arg.input_string.string, string, strlen(string));
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_set_unprovisioned_device_name(const char *name)
{
btc_ble_mesh_prov_args_t arg = {0};
btc_msg_t msg = {0};
if (!name || strlen(name) > ESP_BLE_MESH_DEVICE_NAME_MAX_LEN) {
return ESP_ERR_INVALID_ARG;
}
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_PROV;
msg.act = BTC_BLE_MESH_ACT_SET_DEVICE_NAME;
memset(arg.set_device_name.name, 0, sizeof(arg.set_device_name.name));
memcpy(arg.set_device_name.name, name, strlen(name));
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
#if (CONFIG_BLE_MESH_PROVISIONER)
esp_err_t esp_ble_mesh_provisioner_read_oob_pub_key(uint8_t link_idx, uint8_t pub_key_x[32],
uint8_t pub_key_y[32])
{
btc_ble_mesh_prov_args_t arg = {0};
btc_msg_t msg = {0};
if (!pub_key_x || !pub_key_y || link_idx >= MAX_PROV_LINK_IDX) {
return ESP_ERR_INVALID_ARG;
}
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_PROV;
msg.act = BTC_BLE_MESH_ACT_PROVISIONER_READ_OOB_PUB_KEY;
arg.provisioner_read_oob_pub_key.link_idx = link_idx;
memcpy(arg.provisioner_read_oob_pub_key.pub_key_x, pub_key_x, 32);
memcpy(arg.provisioner_read_oob_pub_key.pub_key_y, pub_key_y, 32);
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_provisioner_input_string(const char *string, uint8_t link_idx)
{
btc_ble_mesh_prov_args_t arg = {0};
btc_msg_t msg = {0};
if (!string || link_idx >= MAX_PROV_LINK_IDX) {
return ESP_ERR_INVALID_ARG;
}
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_PROV;
msg.act = BTC_BLE_MESH_ACT_PROVISIONER_INPUT_STR;
memset(arg.provisioner_input_str.string, 0, sizeof(arg.provisioner_input_str.string));
strncpy(arg.provisioner_input_str.string, string, strlen(string));
arg.provisioner_input_str.link_idx = link_idx;
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_provisioner_input_number(uint32_t number, uint8_t link_idx)
{
btc_ble_mesh_prov_args_t arg = {0};
btc_msg_t msg = {0};
if (number > MAX_OOB_INPUT_NUM || link_idx >= MAX_PROV_LINK_IDX) {
return ESP_ERR_INVALID_ARG;
}
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_PROV;
msg.act = BTC_BLE_MESH_ACT_PROVISIONER_INPUT_NUM;
arg.provisioner_input_num.number = number;
arg.provisioner_input_num.link_idx = link_idx;
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_provisioner_prov_enable(esp_ble_mesh_prov_bearer_t bearers)
{
btc_ble_mesh_prov_args_t arg = {0};
btc_msg_t msg = {0};
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_PROV;
msg.act = BTC_BLE_MESH_ACT_PROVISIONER_ENABLE;
arg.provisioner_enable.bearers = bearers;
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_provisioner_prov_disable(esp_ble_mesh_prov_bearer_t bearers)
{
btc_ble_mesh_prov_args_t arg = {0};
btc_msg_t msg = {0};
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_PROV;
msg.act = BTC_BLE_MESH_ACT_PROVISIONER_DISABLE;
arg.provisioner_disable.bearers = bearers;
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_provisioner_add_unprov_dev(esp_ble_mesh_unprov_dev_add_t *add_dev,
esp_ble_mesh_dev_add_flag_t flags)
{
btc_ble_mesh_prov_args_t arg = {0};
btc_msg_t msg = {0};
if (add_dev == NULL) {
return ESP_ERR_INVALID_ARG;
}
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_PROV;
msg.act = BTC_BLE_MESH_ACT_PROVISIONER_DEV_ADD;
arg.provisioner_dev_add.add_dev.addr_type = add_dev->addr_type;
arg.provisioner_dev_add.add_dev.oob_info = add_dev->oob_info;
arg.provisioner_dev_add.add_dev.bearer = add_dev->bearer;
memcpy(arg.provisioner_dev_add.add_dev.addr, add_dev->addr, sizeof(esp_bd_addr_t));
memcpy(arg.provisioner_dev_add.add_dev.uuid, add_dev->uuid, 16);
arg.provisioner_dev_add.flags = flags;
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_provisioner_delete_dev(esp_ble_mesh_device_delete_t *del_dev)
{
uint8_t val = DEL_DEV_ADDR_FLAG | DEL_DEV_UUID_FLAG;
btc_ble_mesh_prov_args_t arg = {0};
btc_msg_t msg = {0};
if (del_dev == NULL || (__builtin_popcount(del_dev->flag & val) != 1)) {
return ESP_ERR_INVALID_ARG;
}
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_PROV;
msg.act = BTC_BLE_MESH_ACT_PROVISIONER_DEV_DEL;
arg.provisioner_dev_del.del_dev.flag = del_dev->flag;
if (del_dev->flag & DEL_DEV_ADDR_FLAG) {
arg.provisioner_dev_del.del_dev.addr_type = del_dev->addr_type;
memcpy(arg.provisioner_dev_del.del_dev.addr, del_dev->addr, sizeof(esp_bd_addr_t));
} else if (del_dev->flag & DEL_DEV_UUID_FLAG) {
memcpy(arg.provisioner_dev_del.del_dev.uuid, del_dev->uuid, 16);
}
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_provisioner_set_dev_uuid_match(const uint8_t *match_val, uint8_t match_len,
uint8_t offset, bool prov_after_match)
{
btc_ble_mesh_prov_args_t arg = {0};
btc_msg_t msg = {0};
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_PROV;
msg.act = BTC_BLE_MESH_ACT_PROVISIONER_SET_DEV_UUID_MATCH;
if (match_len && match_val) {
memcpy(arg.set_dev_uuid_match.match_val, match_val, match_len);
}
arg.set_dev_uuid_match.match_len = match_len;
arg.set_dev_uuid_match.offset = offset;
arg.set_dev_uuid_match.prov_after_match = prov_after_match;
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_provisioner_set_prov_data_info(esp_ble_mesh_prov_data_info_t *prov_data_info)
{
uint8_t val = PROV_DATA_NET_IDX_FLAG | PROV_DATA_FLAGS_FLAG | PROV_DATA_IV_INDEX_FLAG;
btc_ble_mesh_prov_args_t arg = {0};
btc_msg_t msg = {0};
if (prov_data_info == NULL || (__builtin_popcount(prov_data_info->flag & val) != 1)) {
return ESP_ERR_INVALID_ARG;
}
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_PROV;
msg.act = BTC_BLE_MESH_ACT_PROVISIONER_SET_PROV_DATA_INFO;
arg.set_prov_data_info.prov_data.flag = prov_data_info->flag;
if (prov_data_info->flag & PROV_DATA_NET_IDX_FLAG) {
arg.set_prov_data_info.prov_data.net_idx = prov_data_info->net_idx;
} else if (prov_data_info->flag & PROV_DATA_FLAGS_FLAG) {
arg.set_prov_data_info.prov_data.flags = prov_data_info->flags;
} else if (prov_data_info->flag & PROV_DATA_IV_INDEX_FLAG) {
arg.set_prov_data_info.prov_data.iv_index = prov_data_info->iv_index;
}
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
#endif /* CONFIG_BLE_MESH_PROVISIONER */
/* The following APIs are for fast provisioning */
#if (CONFIG_BLE_MESH_FAST_PROV)
esp_err_t esp_ble_mesh_set_fast_prov_info(esp_ble_mesh_fast_prov_info_t *fast_prov_info)
{
btc_ble_mesh_prov_args_t arg = {0};
btc_msg_t msg = {0};
if (fast_prov_info == NULL) {
return ESP_ERR_INVALID_ARG;
}
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_PROV;
msg.act = BTC_BLE_MESH_ACT_SET_FAST_PROV_INFO;
arg.set_fast_prov_info.unicast_min = fast_prov_info->unicast_min;
arg.set_fast_prov_info.unicast_max = fast_prov_info->unicast_max;
arg.set_fast_prov_info.net_idx = fast_prov_info->net_idx;
arg.set_fast_prov_info.flags = fast_prov_info->flags;
arg.set_fast_prov_info.iv_index = fast_prov_info->iv_index;
arg.set_fast_prov_info.offset = fast_prov_info->offset;
arg.set_fast_prov_info.match_len = fast_prov_info->match_len;
if (fast_prov_info->match_len && fast_prov_info->match_val) {
memcpy(arg.set_fast_prov_info.match_val, fast_prov_info->match_val, fast_prov_info->match_len);
}
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_set_fast_prov_action(esp_ble_mesh_fast_prov_action_t action)
{
btc_ble_mesh_prov_args_t arg = {0};
btc_msg_t msg = {0};
if (action >= FAST_PROV_ACT_MAX) {
return ESP_ERR_INVALID_ARG;
}
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_PROV;
msg.act = BTC_BLE_MESH_ACT_SET_FAST_PROV_ACTION;
arg.set_fast_prov_action.action = action;
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL)
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
#endif /* CONFIG_BLE_MESH_FAST_PROV */

View file

@ -0,0 +1,65 @@
// Copyright 2017-2019 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <stdint.h>
#include "btc/btc_task.h"
#include "btc/btc_manage.h"
#include "esp_err.h"
#include "esp_bt_defs.h"
#include "esp_bt_main.h"
#include "btc_ble_mesh_prov.h"
#include "esp_ble_mesh_defs.h"
esp_err_t esp_ble_mesh_proxy_identity_enable(void)
{
btc_msg_t msg = {0};
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_PROV;
msg.act = BTC_BLE_MESH_ACT_PROXY_IDENTITY_ENABLE;
return (btc_transfer_context(&msg, NULL, 0, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_proxy_gatt_enable(void)
{
btc_msg_t msg = {0};
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_PROV;
msg.act = BTC_BLE_MESH_ACT_PROXY_GATT_ENABLE;
return (btc_transfer_context(&msg, NULL, 0, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}
esp_err_t esp_ble_mesh_proxy_gatt_disable(void)
{
btc_msg_t msg = {0};
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_PROV;
msg.act = BTC_BLE_MESH_ACT_PROXY_GATT_DISABLE;
return (btc_transfer_context(&msg, NULL, 0, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}

View file

@ -0,0 +1,37 @@
// Copyright 2017-2019 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef _ESP_BLE_MESH_COMMON_API_H_
#define _ESP_BLE_MESH_COMMON_API_H_
#include "esp_ble_mesh_defs.h"
/**
* @brief Initialize BLE Mesh module.
* This API initializes provisioning capabilities and composition data information.
*
* @note After calling this API, the device needs to call esp_ble_mesh_prov_enable()
* to enable provisioning functionality again.
*
* @param[in] prov: Pointer to the device provisioning capabilities. This pointer must
* remain valid during the lifetime of the BLE Mesh device.
* @param[in] comp: Pointer to the device composition data information. This pointer
* must remain valid during the lifetime of the BLE Mesh device.
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_init(esp_ble_mesh_prov_t *prov, esp_ble_mesh_comp_t *comp);
#endif /* _ESP_BLE_MESH_COMMON_API_H_ */

View file

@ -0,0 +1,107 @@
// Copyright 2017-2019 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef _ESP_BLE_MESH_LOCAL_DATA_OPERATION_API_H_
#define _ESP_BLE_MESH_LOCAL_DATA_OPERATION_API_H_
#include "esp_ble_mesh_defs.h"
/**
* @brief Get the model publish period, the unit is ms.
*
* @param[in] model: Model instance pointer.
*
* @return Publish period value on success, 0 or (negative) error code from errno.h on failure.
*
*/
int32_t esp_ble_mesh_get_model_publish_period(esp_ble_mesh_model_t *model);
/**
* @brief Get the address of the primary element.
*
* @return Address of the primary element on success, or
* ESP_BLE_MESH_ADDR_UNASSIGNED on failure which means the device has not been provisioned.
*
*/
uint16_t esp_ble_mesh_get_primary_element_address(void);
/**
* @brief Check if the model has subscribed to the given group address.
* Note: E.g., once a status message is received and the destination address
* is a group address, the model uses this API to check if it is successfully subscribed
* to the given group address.
*
* @param[in] model: Pointer to the model.
* @param[in] group_addr: Group address.
*
* @return Pointer to the group address within the Subscription List of the model on success, or
* NULL on failure which means the model has not subscribed to the given group address.
* Note: With the pointer to the group address returned, you can reset the group address
* to 0x0000 in order to unsubscribe the model from the group.
*
*/
uint16_t *esp_ble_mesh_is_model_subscribed_to_group(esp_ble_mesh_model_t *model, uint16_t group_addr);
/**
* @brief Find the BLE Mesh element pointer via the element address.
*
* @param[in] element_addr: Element address.
*
* @return Pointer to the element on success, or NULL on failure.
*
*/
esp_ble_mesh_elem_t *esp_ble_mesh_find_element(uint16_t element_addr);
/**
* @brief Get the number of elements that have been registered.
*
* @return Number of elements.
*
*/
uint8_t esp_ble_mesh_get_element_count(void);
/**
* @brief Find the Vendor specific model with the given element,
* the company ID and the Vendor Model ID.
*
* @param[in] element: Element to which the model belongs.
* @param[in] company_id: A 16-bit company identifier assigned by the Bluetooth SIG.
* @param[in] model_id: A 16-bit vendor-assigned model identifier.
*
* @return Pointer to the Vendor Model on success, or NULL on failure which means the Vendor Model is not found.
*
*/
esp_ble_mesh_model_t *esp_ble_mesh_find_vendor_model(const esp_ble_mesh_elem_t *element,
uint16_t company_id, uint16_t model_id);
/**
* @brief Find the SIG model with the given element and Model id.
*
* @param[in] element: Element to which the model belongs.
* @param[in] model_id: SIG model identifier.
*
* @return Pointer to the SIG Model on success, or NULL on failure which means the SIG Model is not found.
*
*/
esp_ble_mesh_model_t *esp_ble_mesh_find_sig_model(const esp_ble_mesh_elem_t *element, uint16_t model_id);
/**
* @brief Get the Composition data which has been registered.
*
* @return Pointer to the Composition data on success, or NULL on failure which means the Composition data is not initialized.
*
*/
const esp_ble_mesh_comp_t *esp_ble_mesh_get_composition_data(void);
#endif /* _ESP_BLE_MESH_LOCAL_DATA_OPERATION_API_H_ */

View file

@ -0,0 +1,20 @@
// Copyright 2017-2019 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef _ESP_BLE_MESH_LOW_POWER_API_H_
#define _ESP_BLE_MESH_LOW_POWER_API_H_
#include "esp_ble_mesh_defs.h"
#endif /* _ESP_BLE_MESH_LOW_POWER_API_H_ */

View file

@ -0,0 +1,265 @@
// Copyright 2017-2019 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef _ESP_BLE_MESH_NETWORKING_API_H_
#define _ESP_BLE_MESH_NETWORKING_API_H_
#include "esp_ble_mesh_defs.h"
/** @brief: event, event code of user-defined model events; param, parameters of user-defined model events */
typedef void (* esp_ble_mesh_model_cb_t)(esp_ble_mesh_model_cb_event_t event,
esp_ble_mesh_model_cb_param_t *param);
/**
* @brief Register BLE Mesh callback for user-defined models' operations.
* This callback can report the following events generated for the user-defined models:
* - Call back the messages received by user-defined client and server models to the
* application layer;
* - If users call esp_ble_mesh_server/client_model_send, this callback notifies the
* application layer of the send_complete event;
* - If user-defined client model sends a message that requires response, and the response
* message is received after the timer expires, the response message will be reported
* to the application layer as published by a peer device;
* - If the user-defined client model fails to receive the response message during a specified
* period of time, a timeout event will be reported to the application layer.
*
* @note The client models (i.e. Config Client model, Health Client model, Generic
* Client models, Sensor Client model, Scene Client model and Lighting Client models)
* that have been realized internally have their specific register functions.
* For example, esp_ble_mesh_register_config_client_callback is the register
* function for Config Client Model.
*
* @param[in] callback: Pointer to the callback function.
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_register_custom_model_callback(esp_ble_mesh_model_cb_t callback);
/**
* @brief Add the message opcode to the beginning of the model message
* before sending or publishing the model message.
*
* @note This API is only used to set the opcode of the message.
*
* @param[in] data: Pointer to the message data.
* @param[in] opcode: The message opcode.
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_model_msg_opcode_init(uint8_t *data, uint32_t opcode);
/**
* @brief Initialize the user-defined client model. All user-defined client models
* shall call this function to initialize the client model internal data.
* Node: Before calling this API, the op_pair_size and op_pair variabled within
* the user_data(defined using esp_ble_mesh_client_t_) of the client model
* need to be initialized.
*
* @param[in] model: BLE Mesh Client model to which the message belongs.
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_client_model_init(esp_ble_mesh_model_t *model);
/**
* @brief Send server model messages(such as server model status messages).
*
* @param[in] model: BLE Mesh Server Model to which the message belongs.
* @param[in] ctx: Message context, includes keys, TTL, etc.
* @param[in] opcode: Message opcode.
* @param[in] length: Message length (exclude the message opcode).
* @param[in] data: Parameters of Access Payload (exclude the message opcode) to be sent.
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_server_model_send_msg(esp_ble_mesh_model_t *model,
esp_ble_mesh_msg_ctx_t *ctx, uint32_t opcode,
uint16_t length, uint8_t *data);
/**
* @brief Send client model message (such as model get, set, etc).
*
* @param[in] model: BLE Mesh Client Model to which the message belongs.
* @param[in] ctx: Message context, includes keys, TTL, etc.
* @param[in] opcode: Message opcode.
* @param[in] length: Message length (exclude the message opcode).
* @param[in] data: Parameters of the Access Payload (exclude the message opcode) to be sent.
* @param[in] msg_timeout: Time to get response to the message (in milliseconds).
* @param[in] need_rsp: TRUE if the opcode requires the peer device to reply, FALSE otherwise.
* @param[in] device_role: Role of the device (Node/Provisioner) that sends the message.
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_client_model_send_msg(esp_ble_mesh_model_t *model,
esp_ble_mesh_msg_ctx_t *ctx, uint32_t opcode,
uint16_t length, uint8_t *data, int32_t msg_timeout,
bool need_rsp, esp_ble_mesh_dev_role_t device_role);
/**
* @brief Send a model publication message.
*
* @note Before calling this function, the user needs to ensure that the model
* publication message (@ref esp_ble_mesh_model_pub_t.msg) contains a valid
* message to be sent. And if users want to update the publishing message,
* this API should be called in ESP_BLE_MESH_MODEL_PUBLISH_UPDATE_EVT
* with the message updated.
*
*
* @param[in] model: Mesh (client) Model publishing the message.
* @param[in] opcode: Message opcode.
* @param[in] length: Message length (exclude the message opcode).
* @param[in] data: Parameters of the Access Payload (exclude the message opcode) to be sent.
* @param[in] device_role: Role of the device (node/provisioner) publishing the message of the type esp_ble_mesh_dev_role_t.
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_model_publish(esp_ble_mesh_model_t *model, uint32_t opcode,
uint16_t length, uint8_t *data,
esp_ble_mesh_dev_role_t device_role);
/**
* @brief Reset the provisioning procedure of the local BLE Mesh node.
*
* @note All provisioning information in this node will be deleted and the node
* needs to be reprovisioned. The API function esp_ble_mesh_node_prov_enable()
* needs to be called to start a new provisioning procedure.
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_node_local_reset(void);
/**
* @brief This function is called to set the node (provisioned device) name.
*
* @param[in] index: Index of the node in the node queue.
* @param[in] name: Name (end by '\0') to be set for the node.
*
* @note index is obtained from the parameters of ESP_BLE_MESH_PROVISIONER_PROV_COMPLETE_EVT.
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_provisioner_set_node_name(int index, const char *name);
/**
* @brief This function is called to get the node (provisioned device) name.
*
* @param[in] index: Index of the node in the node queue.
*
* @note index is obtained from the parameters of ESP_BLE_MESH_PROVISIONER_PROV_COMPLETE_EVT.
*
* @return Node name on success, or NULL on failure.
*
*/
const char *esp_ble_mesh_provisioner_get_node_name(int index);
/**
* @brief This function is called to get the node (provisioned device) index.
*
* @param[in] name: Name of the node (end by '\0').
*
* @return Node index on success, or (negative) error code from errno.h on failure.
*
*/
int esp_ble_mesh_provisioner_get_node_index(const char *name);
/**
* @brief This function is called to set the app key for the local BLE Mesh stack.
*
* @param[in] app_key: The app key to be set for the local BLE Mesh stack.
* @param[in] net_idx: The network key index.
* @param[in] app_idx: The app key index.
*
* @note app_key: If set to NULL, app_key will be generated internally.
* net_idx: Should be an existing one.
* app_idx: If it is going to be generated internally, it should be set to
* 0xFFFF, and the new app_idx will be reported via an event.
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_provisioner_add_local_app_key(const uint8_t app_key[16], uint16_t net_idx, uint16_t app_idx);
/**
* @brief This function is called by Provisioner to get the local app key value.
*
* @param[in] net_idx: Network key index.
* @param[in] app_idx: Application key index.
*
* @return App key on success, or NULL on failure.
*
*/
const uint8_t *esp_ble_mesh_provisioner_get_local_app_key(uint16_t net_idx, uint16_t app_idx);
/**
* @brief This function is called by Provisioner to bind own model with proper app key.
*
* @param[in] element_addr: Provisioner local element address
* @param[in] app_idx: Provisioner local appkey index
* @param[in] model_id: Provisioner local model id
* @param[in] company_id: Provisioner local company id
*
* @note company_id: If going to bind app_key with local vendor model, company_id
* should be set to 0xFFFF.
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_provisioner_bind_app_key_to_local_model(uint16_t element_addr, uint16_t app_idx,
uint16_t model_id, uint16_t company_id);
/**
* @brief This function is called by Provisioner to add local network key.
*
* @param[in] net_key: The network key to be added to the Provisioner local BLE Mesh stack.
* @param[in] net_idx: The network key index.
*
* @note net_key: If set to NULL, net_key will be generated internally.
* net_idx: If it is going to be generated internally, it should be set to
* 0xFFFF, and the new net_idx will be reported via an event.
*
* @return ESP_OK on success or error code otherwise.
*
*/
esp_err_t esp_ble_mesh_provisioner_add_local_net_key(const uint8_t net_key[16], uint16_t net_idx);
/**
* @brief This function is called by Provisioner to get the local network key value.
*
* @param[in] net_idx: Network key index.
*
* @return Network key on success, or NULL on failure.
*
*/
const uint8_t *esp_ble_mesh_provisioner_get_local_net_key(uint16_t net_idx);
/**
* @brief This function is called to get fast provisioning application key.
*
* @param[in] net_idx: Network key index.
* @param[in] app_idx: Application key index.
*
* @return Application key on success, or NULL on failure.
*
*/
const uint8_t *esp_ble_mesh_get_fast_prov_app_key(uint16_t net_idx, uint16_t app_idx);
#endif /* _ESP_BLE_MESH_NETWORKING_API_H_ */

Some files were not shown because too many files have changed in this diff Show more