forked from espressif/esp-idf
Compare commits
440 Commits
v4.1-beta1
...
v4.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5ef1b39002 | ||
|
|
bd72a9ab2b | ||
|
|
f1b651af7e | ||
|
|
550ed39ea3 | ||
|
|
95083233c5 | ||
|
|
ceeee9036c | ||
|
|
be13513378 | ||
|
|
36edd91060 | ||
|
|
b3b7fcf51c | ||
|
|
103503ba56 | ||
|
|
50b5b3184e | ||
|
|
69ce0cea68 | ||
|
|
77fd8095e0 | ||
|
|
839893cfce | ||
|
|
5cf858bee3 | ||
|
|
f5a7c9635f | ||
|
|
1ecd5ab91d | ||
|
|
9c9b64ee17 | ||
|
|
0116d5d096 | ||
|
|
6db66c96d6 | ||
|
|
8d54933e10 | ||
|
|
b1e907ccf1 | ||
|
|
370aa39045 | ||
|
|
9b19b21073 | ||
|
|
88baff4cbb | ||
|
|
4ea2935b1a | ||
|
|
a1cd7d0ef5 | ||
|
|
113721f8fc | ||
|
|
5cc9ef901e | ||
|
|
ea8fae9ded | ||
|
|
9d38b0ab9b | ||
|
|
faaf08c441 | ||
|
|
f9e22b627e | ||
|
|
b6e2163e5e | ||
|
|
aceb46efc2 | ||
|
|
56accfe4c4 | ||
|
|
7ab2ffb45f | ||
|
|
6cbc7dc2cd | ||
|
|
c735e7edf5 | ||
|
|
f31a804c1e | ||
|
|
d168611bbf | ||
|
|
b85f877817 | ||
|
|
6ae54e7fd2 | ||
|
|
dd99fc77cb | ||
|
|
4daa605bd3 | ||
|
|
97f10f6509 | ||
|
|
ee70736a03 | ||
|
|
9e55345c43 | ||
|
|
6b66850dc1 | ||
|
|
e0e391dce3 | ||
|
|
0a1919abff | ||
|
|
c5bbe87425 | ||
|
|
5e52e5f6f5 | ||
|
|
f82010fa6a | ||
|
|
08e7bce4ea | ||
|
|
a945ae8a9d | ||
|
|
b33828e254 | ||
|
|
ae64d9e738 | ||
|
|
6861f7d5d8 | ||
|
|
c5a6fc9c7e | ||
|
|
3b8b057894 | ||
|
|
e69ee31e1a | ||
|
|
846a2f95f4 | ||
|
|
74623ac9d5 | ||
|
|
37c155c359 | ||
|
|
194a3b09dc | ||
|
|
1b8905e544 | ||
|
|
d0093c7675 | ||
|
|
de6f21936f | ||
|
|
46486a863c | ||
|
|
29bc65e719 | ||
|
|
7de0c391ac | ||
|
|
326b42560d | ||
|
|
6f768b74e4 | ||
|
|
aa6481837f | ||
|
|
bd3caffdcd | ||
|
|
a5b4fda207 | ||
|
|
7070fea6e4 | ||
|
|
d35226c656 | ||
|
|
7cdc2f2b81 | ||
|
|
50319bb03c | ||
|
|
0ea6d39686 | ||
|
|
298f23c958 | ||
|
|
1e12199832 | ||
|
|
36a66a7243 | ||
|
|
4eec4fbc99 | ||
|
|
b00f38f91c | ||
|
|
3c6b1b4c0a | ||
|
|
2c531d5bb3 | ||
|
|
69895387ee | ||
|
|
7708bf6158 | ||
|
|
10f3d92f6c | ||
|
|
5fb93a14ae | ||
|
|
63592b667c | ||
|
|
ba06ecf96d | ||
|
|
8793aab0e3 | ||
|
|
d32ee233af | ||
|
|
049402ae8d | ||
|
|
977d98cb6d | ||
|
|
983a4be42e | ||
|
|
0c87b1c12d | ||
|
|
5ea193115b | ||
|
|
6971cdbad5 | ||
|
|
0af793f6ef | ||
|
|
e1ce31483d | ||
|
|
55b56a1557 | ||
|
|
2f73d76768 | ||
|
|
63c8dd2981 | ||
|
|
a02a782ee9 | ||
|
|
0c06be9bcd | ||
|
|
d3921346a9 | ||
|
|
c3d33f4232 | ||
|
|
ad4dfed632 | ||
|
|
7d3d56ff9a | ||
|
|
edb84c19dd | ||
|
|
3b89497b39 | ||
|
|
841aba8948 | ||
|
|
84b51781c8 | ||
|
|
58f0a94cdf | ||
|
|
3cfd7eebd1 | ||
|
|
4775176d7f | ||
|
|
eeff638c97 | ||
|
|
ca01e8698f | ||
|
|
db7e28b8c7 | ||
|
|
13537ce279 | ||
|
|
cc187a43b3 | ||
|
|
b4588f7d92 | ||
|
|
59b313fdcf | ||
|
|
74056dea91 | ||
|
|
2eadacbf29 | ||
|
|
3c32f5a726 | ||
|
|
55cd9206d5 | ||
|
|
80412dfbb8 | ||
|
|
502a2aed2a | ||
|
|
d075bcab98 | ||
|
|
88f6e2b60d | ||
|
|
e789d85e69 | ||
|
|
eb8f6f942a | ||
|
|
715cb64288 | ||
|
|
52fa4c7f96 | ||
|
|
f02d095ff1 | ||
|
|
ab73b3fd8e | ||
|
|
dc4cd3ae7c | ||
|
|
3db186d5d1 | ||
|
|
db3d03f9ac | ||
|
|
4a42368603 | ||
|
|
db0897705f | ||
|
|
276cbb69f3 | ||
|
|
c973bea7d1 | ||
|
|
6191429df5 | ||
|
|
5a1848a5a6 | ||
|
|
e9d4659175 | ||
|
|
0266ad95d7 | ||
|
|
19163393a9 | ||
|
|
9d587eb8fd | ||
|
|
32e20304a7 | ||
|
|
1cfeb8be7f | ||
|
|
222ac1dd60 | ||
|
|
63dae58176 | ||
|
|
e07023b9c7 | ||
|
|
ddae67f50f | ||
|
|
c595429db0 | ||
|
|
b929611d5d | ||
|
|
e9f64eb1c3 | ||
|
|
56c1646e2a | ||
|
|
204553ec6c | ||
|
|
87141efd1e | ||
|
|
260d6f83b7 | ||
|
|
8860c1b94c | ||
|
|
31b164ccb1 | ||
|
|
c96ce01d87 | ||
|
|
97f72da56e | ||
|
|
3e93b8fed9 | ||
|
|
295a9eea82 | ||
|
|
06d445759a | ||
|
|
b1efdd5eb1 | ||
|
|
42ccb7277f | ||
|
|
cffbc32253 | ||
|
|
8f5564af84 | ||
|
|
6a6bac2c62 | ||
|
|
526f253b2e | ||
|
|
2f40c4449f | ||
|
|
8ab29292ab | ||
|
|
9af8947e55 | ||
|
|
800cb0fff8 | ||
|
|
362e8e0a1f | ||
|
|
de648753b0 | ||
|
|
aed5dc63b7 | ||
|
|
21c5be311c | ||
|
|
0a41241e10 | ||
|
|
e3472c1c99 | ||
|
|
175109d196 | ||
|
|
61d376109c | ||
|
|
fd4b6fd47e | ||
|
|
b348b55d1e | ||
|
|
82a5b05948 | ||
|
|
95718d9ef9 | ||
|
|
33c0ddce40 | ||
|
|
bf4b513e83 | ||
|
|
91fff8c897 | ||
|
|
7ea60199a6 | ||
|
|
2b84b673bf | ||
|
|
c2e24e306f | ||
|
|
a85459e245 | ||
|
|
a0434371b0 | ||
|
|
1717c2face | ||
|
|
ee0f8adaed | ||
|
|
949e7c6f85 | ||
|
|
f14cdd5d3a | ||
|
|
15daee9a0f | ||
|
|
de85de7c51 | ||
|
|
27ae9d3e2c | ||
|
|
7db21de3b3 | ||
|
|
cec0f25484 | ||
|
|
f232b07e4e | ||
|
|
78b13034ef | ||
|
|
099bf88b2e | ||
|
|
466d450b4b | ||
|
|
a742255f8e | ||
|
|
dd89b2dc0d | ||
|
|
654a3913eb | ||
|
|
fefa9b7fe9 | ||
|
|
547fd926a9 | ||
|
|
d6cbfc7f19 | ||
|
|
61405472e4 | ||
|
|
541d8aef37 | ||
|
|
f9bfc83295 | ||
|
|
3fa198b8a2 | ||
|
|
9778b163b1 | ||
|
|
e006d21419 | ||
|
|
4214179de1 | ||
|
|
5c98ff015e | ||
|
|
b56c7d9066 | ||
|
|
d67e764ef6 | ||
|
|
1554fd3d8a | ||
|
|
0cd5e28bce | ||
|
|
c1cd396b95 | ||
|
|
f7a2bfc873 | ||
|
|
4b1cbe87b3 | ||
|
|
8b2291a718 | ||
|
|
fca4124f70 | ||
|
|
d35d765395 | ||
|
|
94092a148c | ||
|
|
68e8a7e0ba | ||
|
|
62ac50f9d7 | ||
|
|
fefd52f093 | ||
|
|
7c379f8a65 | ||
|
|
fca858dd58 | ||
|
|
c28828d255 | ||
|
|
d595793caa | ||
|
|
67eef52822 | ||
|
|
6f7acf6a21 | ||
|
|
df96c73471 | ||
|
|
3ceb5b3718 | ||
|
|
d51bd36142 | ||
|
|
bd01c359bd | ||
|
|
c5cb44d813 | ||
|
|
43d8950682 | ||
|
|
d4e700e744 | ||
|
|
ddaa9d4523 | ||
|
|
fadbfdadf4 | ||
|
|
58044063dd | ||
|
|
67f9448e71 | ||
|
|
5b516b107a | ||
|
|
6366c20858 | ||
|
|
27ec86cd8e | ||
|
|
3b3050b09f | ||
|
|
69c8d9211f | ||
|
|
6254bf443e | ||
|
|
198953df8f | ||
|
|
87fa7af6b7 | ||
|
|
e558b2237d | ||
|
|
eb5bafeb65 | ||
|
|
9a389162ab | ||
|
|
e6fc2a7bc8 | ||
|
|
2fb9cad1b4 | ||
|
|
13ef9cf4bc | ||
|
|
1229590a2c | ||
|
|
7d934dafb8 | ||
|
|
6c9864ce86 | ||
|
|
4952b3baed | ||
|
|
ee234472c1 | ||
|
|
c50952ebaf | ||
|
|
20085a0fcd | ||
|
|
19449289d0 | ||
|
|
f5645cc9d8 | ||
|
|
0c92ca5175 | ||
|
|
a41bcacf31 | ||
|
|
f4243de752 | ||
|
|
e9c6f119de | ||
|
|
1ea008d22e | ||
|
|
585d53dfa8 | ||
|
|
1f480f4570 | ||
|
|
d10ad9a4b1 | ||
|
|
0effd9b257 | ||
|
|
0c4e55e3bd | ||
|
|
a2a71fc68f | ||
|
|
ae063d96c2 | ||
|
|
3948065c24 | ||
|
|
33eab40f2a | ||
|
|
f59ef5e6ef | ||
|
|
b7ae3ff9bd | ||
|
|
a2a89fb95d | ||
|
|
ffe0cca423 | ||
|
|
b3410b9210 | ||
|
|
b08b0f0949 | ||
|
|
f646cdd6a8 | ||
|
|
445f727e7a | ||
|
|
e1562311bf | ||
|
|
afc1362ea6 | ||
|
|
5a09cfe70a | ||
|
|
858f4745fd | ||
|
|
d880672076 | ||
|
|
90a8945930 | ||
|
|
34b9e6c677 | ||
|
|
1ac44aa202 | ||
|
|
7053737110 | ||
|
|
acb92c225f | ||
|
|
072d01da2f | ||
|
|
87d68ebb98 | ||
|
|
89f7e62011 | ||
|
|
4fe18a9258 | ||
|
|
51c32997b1 | ||
|
|
40af109144 | ||
|
|
ec5c123ef7 | ||
|
|
4573688862 | ||
|
|
cd301cc324 | ||
|
|
9a1c5a903f | ||
|
|
655e201b1c | ||
|
|
5e09d473c7 | ||
|
|
bf7f40007a | ||
|
|
a2c55e2c37 | ||
|
|
4b59f7e2c7 | ||
|
|
716298f8e3 | ||
|
|
38060c0b58 | ||
|
|
3c01f68a78 | ||
|
|
a5bf353e3f | ||
|
|
51b7247033 | ||
|
|
52dcf1c180 | ||
|
|
26379f7d3e | ||
|
|
8dc421c7e1 | ||
|
|
79590d2e21 | ||
|
|
c17d55eb9b | ||
|
|
7c34711c07 | ||
|
|
cf8dd62fc4 | ||
|
|
f96d28172b | ||
|
|
f538b63458 | ||
|
|
6c7895fbac | ||
|
|
a8494b68e1 | ||
|
|
8367bc4571 | ||
|
|
374e9b32d4 | ||
|
|
7fdc9571ba | ||
|
|
f9f42a9d90 | ||
|
|
820ed5c7f1 | ||
|
|
69147fc4ec | ||
|
|
88f8f91d40 | ||
|
|
06337f1034 | ||
|
|
40f66c3117 | ||
|
|
db1111ef79 | ||
|
|
dbaf0f1e93 | ||
|
|
906280e767 | ||
|
|
55abe2eba8 | ||
|
|
fbe215f3c0 | ||
|
|
6e0b8af978 | ||
|
|
b8fe1fdf27 | ||
|
|
355a210a38 | ||
|
|
5c4f7948d4 | ||
|
|
bc81db3676 | ||
|
|
737215c50f | ||
|
|
2925b5f42b | ||
|
|
cc95d14d80 | ||
|
|
1717232f11 | ||
|
|
98742664e8 | ||
|
|
2aba19e00d | ||
|
|
9f024df9e5 | ||
|
|
af3c81b68a | ||
|
|
bac92d579f | ||
|
|
b445b59c5e | ||
|
|
9b31a2e7f9 | ||
|
|
71ffae5d6e | ||
|
|
c092f9b881 | ||
|
|
582a493739 | ||
|
|
2976f5daea | ||
|
|
4414e829de | ||
|
|
e4704e0875 | ||
|
|
f5fc735711 | ||
|
|
7815cd9ff4 | ||
|
|
da113cdfa8 | ||
|
|
48e6195506 | ||
|
|
1cdea40bba | ||
|
|
3d462d7d81 | ||
|
|
aa6347339c | ||
|
|
8488f292c2 | ||
|
|
6431a5e185 | ||
|
|
27b28c0249 | ||
|
|
b29bc240a7 | ||
|
|
940e87c0da | ||
|
|
60eaca9637 | ||
|
|
e01333514d | ||
|
|
f0519c674f | ||
|
|
de9186b908 | ||
|
|
5cd45a6d80 | ||
|
|
1fa6db757d | ||
|
|
7f84669054 | ||
|
|
e82ac041cd | ||
|
|
47f9c0e301 | ||
|
|
d09a43fc1e | ||
|
|
a003bcde29 | ||
|
|
492065463d | ||
|
|
85c15812c9 | ||
|
|
ba43902fb8 | ||
|
|
eda9d8ffa8 | ||
|
|
f4c84ea2b2 | ||
|
|
fefd64fa83 | ||
|
|
70b1ab76e8 | ||
|
|
6bc77d79a6 | ||
|
|
4c09dc6270 | ||
|
|
570653bc7b | ||
|
|
2241dda536 | ||
|
|
a559d55379 | ||
|
|
c99eac2f0b | ||
|
|
a1764ec5b0 | ||
|
|
5ce7ec848c | ||
|
|
15cdd2859a | ||
|
|
a0abb4dfdc | ||
|
|
f5b678f7ba | ||
|
|
1af819d19b | ||
|
|
408d1d9f93 | ||
|
|
5f2d918437 | ||
|
|
32756b165e | ||
|
|
74b299c4c7 | ||
|
|
27e9cb785a | ||
|
|
60fed38c0f | ||
|
|
425486223e | ||
|
|
d6026823fa | ||
|
|
c57ba38d67 | ||
|
|
250e219279 | ||
|
|
23c5770156 | ||
|
|
4c668ff3d3 | ||
|
|
4a623798f1 |
@@ -120,8 +120,17 @@ before_script:
|
||||
dependencies: []
|
||||
before_script:
|
||||
- *apply_bot_filter
|
||||
- $IDF_PATH/tools/idf_tools.py install-python-env
|
||||
# On macOS, these tools need to be installed
|
||||
- $IDF_PATH/tools/idf_tools.py --non-interactive install cmake ninja
|
||||
# This adds tools (compilers) and the version-specific Python environment to PATH
|
||||
- *setup_tools_unless_target_test
|
||||
# Install packages required by CI scripts into IDF Python environment
|
||||
- pip install -r $IDF_PATH/tools/ci/python_packages/ttfw_idf/requirements.txt
|
||||
- source tools/ci/configure_ci_environment.sh
|
||||
# Part of tools/ci/setup_python.sh; we don't use pyenv on macOS, so can't run the rest of the script.
|
||||
- export PYTHONPATH="$IDF_PATH/tools:$IDF_PATH/tools/ci/python_packages:$PYTHONPATH"
|
||||
- *fetch_submodules
|
||||
|
||||
include:
|
||||
- '/tools/ci/config/pre_check.yml'
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
project(esp-idf C CXX ASM)
|
||||
|
||||
if(CMAKE_CURRENT_LIST_DIR STREQUAL CMAKE_SOURCE_DIR)
|
||||
message(FATAL_ERROR "Current directory '${CMAKE_CURRENT_LIST_DIR}' is not buildable. "
|
||||
"Change directories to one of the example projects in '${CMAKE_CURRENT_LIST_DIR}/examples' and try "
|
||||
"again.")
|
||||
endif()
|
||||
|
||||
unset(compile_options)
|
||||
unset(c_compile_options)
|
||||
unset(cxx_compile_options)
|
||||
@@ -10,15 +16,31 @@ unset(link_options)
|
||||
# Add the following build specifications here, since these seem to be dependent
|
||||
# on config values on the root Kconfig.
|
||||
|
||||
if(CONFIG_COMPILER_OPTIMIZATION_SIZE)
|
||||
list(APPEND compile_options "-Os")
|
||||
list(APPEND compile_options "-freorder-blocks")
|
||||
elseif(CONFIG_COMPILER_OPTIMIZATION_DEFAULT)
|
||||
list(APPEND compile_options "-Og")
|
||||
elseif(CONFIG_COMPILER_OPTIMIZATION_NONE)
|
||||
list(APPEND compile_options "-O0")
|
||||
elseif(CONFIG_COMPILER_OPTIMIZATION_PERF)
|
||||
list(APPEND compile_options "-O2")
|
||||
if(NOT BOOTLOADER_BUILD)
|
||||
|
||||
if(CONFIG_COMPILER_OPTIMIZATION_SIZE)
|
||||
list(APPEND compile_options "-Os")
|
||||
list(APPEND compile_options "-freorder-blocks")
|
||||
elseif(CONFIG_COMPILER_OPTIMIZATION_DEFAULT)
|
||||
list(APPEND compile_options "-Og")
|
||||
elseif(CONFIG_COMPILER_OPTIMIZATION_NONE)
|
||||
list(APPEND compile_options "-O0")
|
||||
elseif(CONFIG_COMPILER_OPTIMIZATION_PERF)
|
||||
list(APPEND compile_options "-O2")
|
||||
endif()
|
||||
|
||||
else() # BOOTLOADER_BUILD
|
||||
|
||||
if(CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE)
|
||||
list(APPEND compile_options "-Os")
|
||||
list(APPEND compile_options "-freorder-blocks")
|
||||
elseif(CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_DEBUG)
|
||||
list(APPEND compile_options "-Og")
|
||||
elseif(CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_NONE)
|
||||
list(APPEND compile_options "-O0")
|
||||
elseif(CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_PERF)
|
||||
list(APPEND compile_options "-O2")
|
||||
endif()
|
||||
|
||||
endif()
|
||||
|
||||
|
||||
5
Kconfig
5
Kconfig
@@ -171,7 +171,7 @@ mainmenu "Espressif IoT Development Framework Configuration"
|
||||
prompt "Optimization Level"
|
||||
default COMPILER_OPTIMIZATION_DEFAULT
|
||||
help
|
||||
This option sets compiler optimization level (gcc -O argument).
|
||||
This option sets compiler optimization level (gcc -O argument) for the app.
|
||||
|
||||
- The "Default" setting will add the -0g flag to CFLAGS.
|
||||
- The "Size" setting will add the -0s flag to CFLAGS.
|
||||
@@ -189,6 +189,9 @@ mainmenu "Espressif IoT Development Framework Configuration"
|
||||
|
||||
Note that custom optimization levels may be unsupported.
|
||||
|
||||
Compiler optimization for the IDF bootloader is set separately,
|
||||
see the BOOTLOADER_COMPILER_OPTIMIZATION setting.
|
||||
|
||||
config COMPILER_OPTIMIZATION_DEFAULT
|
||||
bool "Debug (-Og)"
|
||||
config COMPILER_OPTIMIZATION_SIZE
|
||||
|
||||
@@ -39,4 +39,4 @@ target_compile_options(${COMPONENT_LIB} PRIVATE "-fno-profile-arcs" "-fno-test-c
|
||||
|
||||
# Force app_trace to also appear later than gcov in link line
|
||||
idf_component_get_property(app_trace app_trace COMPONENT_LIB)
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE $<TARGET_FILE:${app_trace}> gcov $<TARGET_FILE:${app_trace}> ${LIBC})
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE $<TARGET_FILE:${app_trace}> gcov $<TARGET_FILE:${app_trace}> c)
|
||||
|
||||
@@ -22,4 +22,14 @@ menu "Application manager"
|
||||
The PROJECT_NAME variable from the build system will not affect the firmware image.
|
||||
This value will not be contained in the esp_app_desc structure.
|
||||
|
||||
config APP_RETRIEVE_LEN_ELF_SHA
|
||||
int "The length of APP ELF SHA is stored in RAM(chars)"
|
||||
default 16
|
||||
range 8 64
|
||||
help
|
||||
At startup, the app will read this many hex characters from the embedded APP ELF SHA-256 hash value
|
||||
and store it in static RAM. This ensures the app ELF SHA-256 value is always available
|
||||
if it needs to be printed by the panic handler code.
|
||||
Changing this value will change the size of a static buffer, in bytes.
|
||||
|
||||
endmenu # "Application manager"
|
||||
|
||||
@@ -72,13 +72,35 @@ static inline char IRAM_ATTR to_hex_digit(unsigned val)
|
||||
return (val < 10) ? ('0' + val) : ('a' + val - 10);
|
||||
}
|
||||
|
||||
__attribute__((constructor)) void esp_ota_init_app_elf_sha256(void)
|
||||
{
|
||||
esp_ota_get_app_elf_sha256(NULL, 0);
|
||||
}
|
||||
|
||||
/* The esp_app_desc.app_elf_sha256 should be possible to print in panic handler during cache is disabled.
|
||||
* But because the cache is disabled the reading esp_app_desc.app_elf_sha256 is not right and
|
||||
* can lead to a complete lock-up of the CPU.
|
||||
* For this reason we do a reading of esp_app_desc.app_elf_sha256 while start up in esp_ota_init_app_elf_sha256()
|
||||
* and keep it in the static s_app_elf_sha256 value.
|
||||
*/
|
||||
int IRAM_ATTR esp_ota_get_app_elf_sha256(char* dst, size_t size)
|
||||
{
|
||||
size_t n = MIN((size - 1) / 2, sizeof(esp_app_desc.app_elf_sha256));
|
||||
const uint8_t* src = esp_app_desc.app_elf_sha256;
|
||||
static char s_app_elf_sha256[CONFIG_APP_RETRIEVE_LEN_ELF_SHA / 2];
|
||||
static bool first_call = true;
|
||||
if (first_call) {
|
||||
first_call = false;
|
||||
const uint8_t* src = esp_app_desc.app_elf_sha256;
|
||||
for (size_t i = 0; i < sizeof(s_app_elf_sha256); ++i) {
|
||||
s_app_elf_sha256[i] = src[i];
|
||||
}
|
||||
}
|
||||
if (dst == NULL || size == 0) {
|
||||
return 0;
|
||||
}
|
||||
size_t n = MIN((size - 1) / 2, sizeof(s_app_elf_sha256));
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
dst[2*i] = to_hex_digit(src[i] >> 4);
|
||||
dst[2*i + 1] = to_hex_digit(src[i] & 0xf);
|
||||
dst[2*i] = to_hex_digit(s_app_elf_sha256[i] >> 4);
|
||||
dst[2*i + 1] = to_hex_digit(s_app_elf_sha256[i] & 0xf);
|
||||
}
|
||||
dst[2*n] = 0;
|
||||
return 2*n + 1;
|
||||
|
||||
@@ -157,7 +157,8 @@ esp_err_t esp_ota_begin(const esp_partition_t *partition, size_t image_size, esp
|
||||
if ((image_size == 0) || (image_size == OTA_SIZE_UNKNOWN)) {
|
||||
ret = esp_partition_erase_range(partition, 0, partition->size);
|
||||
} else {
|
||||
ret = esp_partition_erase_range(partition, 0, (image_size / SPI_FLASH_SEC_SIZE + 1) * SPI_FLASH_SEC_SIZE);
|
||||
const int aligned_erase_size = (image_size + SPI_FLASH_SEC_SIZE - 1) & ~(SPI_FLASH_SEC_SIZE - 1);
|
||||
ret = esp_partition_erase_range(partition, 0, aligned_erase_size);
|
||||
}
|
||||
|
||||
if (ret != ESP_OK) {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
TEST_CASE("esp_ota_get_app_elf_sha256 test", "[esp_app_desc]")
|
||||
{
|
||||
const int sha256_hex_len = 64;
|
||||
const int sha256_hex_len = CONFIG_APP_RETRIEVE_LEN_ELF_SHA;
|
||||
char dst[sha256_hex_len + 2];
|
||||
const char fill = 0xcc;
|
||||
int res;
|
||||
|
||||
@@ -6,7 +6,7 @@ if(BOOTLOADER_BUILD OR NOT CONFIG_APP_BUILD_BOOTLOADER)
|
||||
endif()
|
||||
|
||||
# When secure boot is enabled, do not flash bootloader along with invocation of `idf.py flash`
|
||||
if(NOT CONFIG_SECURE_BOOT_ENABLED)
|
||||
if(NOT CONFIG_SECURE_BOOT)
|
||||
set(flash_bootloader FLASH_IN_PROJECT)
|
||||
endif()
|
||||
|
||||
|
||||
@@ -1,4 +1,29 @@
|
||||
menu "Bootloader config"
|
||||
|
||||
choice BOOTLOADER_COMPILER_OPTIMIZATION
|
||||
prompt "Bootloader optimization Level"
|
||||
default BOOTLOADER_COMPILER_OPTIMIZATION_SIZE
|
||||
help
|
||||
This option sets compiler optimization level (gcc -O argument)
|
||||
for the bootloader.
|
||||
|
||||
- The default "Size" setting will add the -0s flag to CFLAGS.
|
||||
- The "Debug" setting will add the -Og flag to CFLAGS.
|
||||
- The "Performance" setting will add the -O2 flag to CFLAGS.
|
||||
- The "None" setting will add the -O0 flag to CFLAGS.
|
||||
|
||||
Note that custom optimization levels may be unsupported.
|
||||
|
||||
config BOOTLOADER_COMPILER_OPTIMIZATION_SIZE
|
||||
bool "Size (-Os)"
|
||||
config BOOTLOADER_COMPILER_OPTIMIZATION_DEBUG
|
||||
bool "Debug (-Og)"
|
||||
config BOOTLOADER_COMPILER_OPTIMIZATION_PERF
|
||||
bool "Optimize for performance (-O2)"
|
||||
config BOOTLOADER_COMPILER_OPTIMIZATION_NONE
|
||||
bool "Debug without optimization (-O0)"
|
||||
endchoice
|
||||
|
||||
choice BOOTLOADER_LOG_LEVEL
|
||||
bool "Bootloader log verbosity"
|
||||
default BOOTLOADER_LOG_LEVEL_INFO
|
||||
@@ -224,7 +249,7 @@ menu "Bootloader config"
|
||||
|
||||
config BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP
|
||||
bool "Skip image validation when exiting deep sleep"
|
||||
depends on (SECURE_BOOT_ENABLED && SECURE_BOOT_INSECURE) || !SECURE_BOOT_ENABLED
|
||||
depends on (SECURE_BOOT && SECURE_BOOT_INSECURE) || !SECURE_BOOT
|
||||
default n
|
||||
help
|
||||
This option disables the normal validation of an image coming out of
|
||||
@@ -279,12 +304,12 @@ menu "Security features"
|
||||
config SECURE_SIGNED_ON_BOOT
|
||||
bool
|
||||
default y
|
||||
depends on SECURE_BOOT_ENABLED || SECURE_SIGNED_ON_BOOT_NO_SECURE_BOOT
|
||||
depends on SECURE_BOOT || SECURE_SIGNED_ON_BOOT_NO_SECURE_BOOT
|
||||
|
||||
config SECURE_SIGNED_ON_UPDATE
|
||||
bool
|
||||
default y
|
||||
depends on SECURE_BOOT_ENABLED || SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT
|
||||
depends on SECURE_BOOT || SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT
|
||||
|
||||
config SECURE_SIGNED_APPS
|
||||
bool
|
||||
@@ -298,8 +323,7 @@ menu "Security features"
|
||||
|
||||
config SECURE_SIGNED_APPS_NO_SECURE_BOOT
|
||||
bool "Require signed app images"
|
||||
default n
|
||||
depends on !SECURE_BOOT_ENABLED
|
||||
depends on !SECURE_BOOT
|
||||
help
|
||||
Require apps to be signed to verify their integrity.
|
||||
|
||||
@@ -308,6 +332,35 @@ menu "Security features"
|
||||
against remote network access, but not physical access. Compared to using hardware Secure Boot this option
|
||||
is much simpler to implement.
|
||||
|
||||
choice SECURE_SIGNED_APPS_SCHEME
|
||||
bool "App Signing Scheme"
|
||||
depends on SECURE_BOOT || SECURE_SIGNED_APPS_NO_SECURE_BOOT
|
||||
default SECURE_SIGNED_APPS_ECDSA_SCHEME if SECURE_BOOT_V1_ENABLED
|
||||
default SECURE_SIGNED_APPS_RSA_SCHEME if SECURE_BOOT_V2_ENABLED
|
||||
help
|
||||
Select the Secure App signing scheme. Depends on the Chip Revision.
|
||||
There are two options:
|
||||
1. ECDSA based secure boot scheme. (Only choice for Secure Boot V1)
|
||||
Supported in ESP32 and ESP32-ECO3.
|
||||
2. The RSA based secure boot scheme. (Only choice for Secure Boot V2)
|
||||
Supported in ESP32-ECO3. (ESP32 Chip Revision 3 onwards)
|
||||
|
||||
config SECURE_SIGNED_APPS_ECDSA_SCHEME
|
||||
bool "ECDSA"
|
||||
depends on IDF_TARGET_ESP32 && (SECURE_SIGNED_APPS_NO_SECURE_BOOT || SECURE_BOOT_V1_ENABLED)
|
||||
help
|
||||
Embeds the ECDSA public key in the bootloader and signs the application with an ECDSA key.
|
||||
|
||||
Refer to the documentation before enabling.
|
||||
|
||||
config SECURE_SIGNED_APPS_RSA_SCHEME
|
||||
bool "RSA"
|
||||
depends on ESP32_REV_MIN_3 && SECURE_BOOT_V2_ENABLED
|
||||
help
|
||||
Appends the RSA-3072 based Signature block to the application.
|
||||
Refer to <Secure Boot Version 2 documentation link> before enabling.
|
||||
endchoice
|
||||
|
||||
config SECURE_SIGNED_ON_BOOT_NO_SECURE_BOOT
|
||||
bool "Bootloader verifies app signatures"
|
||||
default n
|
||||
@@ -334,23 +387,48 @@ menu "Security features"
|
||||
If hardware secure boot is not enabled, this option still adds significant security against network-based
|
||||
attackers by preventing spoofing of OTA updates.
|
||||
|
||||
config SECURE_BOOT_ENABLED
|
||||
bool "Enable hardware secure boot in bootloader (READ DOCS FIRST)"
|
||||
config SECURE_BOOT
|
||||
bool "Enable hardware Secure Boot in bootloader (READ DOCS FIRST)"
|
||||
default n
|
||||
help
|
||||
Build a bootloader which enables secure boot on first boot.
|
||||
Build a bootloader which enables Secure Boot on first boot.
|
||||
|
||||
Once enabled, secure boot will not boot a modified bootloader. The bootloader will only load a partition
|
||||
Once enabled, Secure Boot will not boot a modified bootloader. The bootloader will only load a partition
|
||||
table or boot an app if the data has a verified digital signature. There are implications for reflashing
|
||||
updated apps once secure boot is enabled.
|
||||
|
||||
When enabling secure boot, JTAG and ROM BASIC Interpreter are permanently disabled by default.
|
||||
|
||||
Refer to https://docs.espressif.com/projects/esp-idf/en/latest/security/secure-boot.html before enabling.
|
||||
choice SECURE_BOOT_VERSION
|
||||
bool "Select secure boot version"
|
||||
default SECURE_BOOT_V2_ENABLED if ESP32_REV_MIN_3
|
||||
depends on SECURE_BOOT
|
||||
help
|
||||
Select the Secure Boot Version. Depends on the Chip Revision.
|
||||
Secure Boot V2 is the new RSA based secure boot scheme.
|
||||
Supported in ESP32-ECO3. (ESP32 Chip Revision 3 onwards)
|
||||
Secure Boot V1 is the AES based secure boot scheme.
|
||||
Supported in ESP32 and ESP32-ECO3.
|
||||
|
||||
config SECURE_BOOT_V1_ENABLED
|
||||
bool "Enable Secure Boot version 1"
|
||||
depends on IDF_TARGET_ESP32
|
||||
help
|
||||
Build a bootloader which enables secure boot version 1 on first boot.
|
||||
Refer to the Secure Boot section of the ESP-IDF Programmer's Guide for this version before enabling.
|
||||
|
||||
config SECURE_BOOT_V2_ENABLED
|
||||
bool "Enable Secure Boot version 2"
|
||||
depends on ESP32_REV_MIN_3
|
||||
help
|
||||
Build a bootloader which enables Secure Boot version 2 on first boot.
|
||||
Refer to Secure Boot V2 section of the ESP-IDF Programmer's Guide for this version before enabling.
|
||||
|
||||
endchoice
|
||||
|
||||
choice SECURE_BOOTLOADER_MODE
|
||||
bool "Secure bootloader mode"
|
||||
depends on SECURE_BOOT_ENABLED
|
||||
depends on SECURE_BOOT_V1_ENABLED
|
||||
default SECURE_BOOTLOADER_ONE_TIME_FLASH
|
||||
|
||||
config SECURE_BOOTLOADER_ONE_TIME_FLASH
|
||||
@@ -385,7 +463,8 @@ menu "Security features"
|
||||
If enabled (default), these binary files are signed as part of the build process. The file named in
|
||||
"Secure boot private signing key" will be used to sign the image.
|
||||
|
||||
If disabled, unsigned app/partition data will be built. They must be signed manually using espsecure.py
|
||||
If disabled, unsigned app/partition data will be built. They must be signed manually using espsecure.py.
|
||||
Version 1 to enable ECDSA Based Secure Boot and Version 2 to enable RSA based Secure Boot.
|
||||
(for example, on a remote signing server.)
|
||||
|
||||
config SECURE_BOOT_SIGNING_KEY
|
||||
@@ -395,28 +474,32 @@ menu "Security features"
|
||||
help
|
||||
Path to the key file used to sign app images.
|
||||
|
||||
Key file is an ECDSA private key (NIST256p curve) in PEM format.
|
||||
Key file is an ECDSA private key (NIST256p curve) in PEM format for Secure Boot V1.
|
||||
Key file is an RSA private key in PEM format for Secure Boot V2.
|
||||
|
||||
Path is evaluated relative to the project directory.
|
||||
|
||||
You can generate a new signing key by running the following command:
|
||||
espsecure.py generate_signing_key secure_boot_signing_key.pem
|
||||
|
||||
See https://docs.espressif.com/projects/esp-idf/en/latest/security/secure-boot.html for details.
|
||||
See the Secure Boot section of the ESP-IDF Programmer's Guide for this version for details.
|
||||
|
||||
config SECURE_BOOT_VERIFICATION_KEY
|
||||
string "Secure boot public signature verification key"
|
||||
depends on SECURE_SIGNED_APPS && !SECURE_BOOT_BUILD_SIGNED_BINARIES
|
||||
depends on SECURE_SIGNED_APPS && !SECURE_BOOT_BUILD_SIGNED_BINARIES && !SECURE_SIGNED_APPS_RSA_SCHEME
|
||||
default "signature_verification_key.bin"
|
||||
help
|
||||
Path to a public key file used to verify signed images. This key is compiled into the bootloader and/or
|
||||
Path to a public key file used to verify signed images.
|
||||
Secure Boot V1: This ECDSA public key is compiled into the bootloader and/or
|
||||
app, to verify app images.
|
||||
Secure Boot V2: This RSA public key is compiled into the signature block at
|
||||
the end of the bootloader/app.
|
||||
|
||||
Key file is in raw binary format, and can be extracted from a
|
||||
PEM formatted private key using the espsecure.py
|
||||
extract_public_key command.
|
||||
|
||||
Refer to https://docs.espressif.com/projects/esp-idf/en/latest/security/secure-boot.html before enabling.
|
||||
Refer to the Secure Boot section of the ESP-IDF Programmer's Guide for this version before enabling.
|
||||
|
||||
choice SECURE_BOOTLOADER_KEY_ENCODING
|
||||
bool "Hardware Key Encoding"
|
||||
@@ -443,7 +526,7 @@ menu "Security features"
|
||||
|
||||
config SECURE_BOOT_INSECURE
|
||||
bool "Allow potentially insecure options"
|
||||
depends on SECURE_BOOT_ENABLED
|
||||
depends on SECURE_BOOT
|
||||
default N
|
||||
help
|
||||
You can disable some of the default protections offered by secure boot, in order to enable testing or a
|
||||
@@ -451,7 +534,7 @@ menu "Security features"
|
||||
|
||||
Only enable these options if you are very sure.
|
||||
|
||||
Refer to https://docs.espressif.com/projects/esp-idf/en/latest/security/secure-boot.html before enabling.
|
||||
Refer to the Secure Boot section of the ESP-IDF Programmer's Guide for this version before enabling.
|
||||
|
||||
config SECURE_FLASH_ENC_ENABLED
|
||||
bool "Enable flash encryption on boot (READ DOCS FIRST)"
|
||||
@@ -495,7 +578,7 @@ menu "Security features"
|
||||
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 the Secure Boot section of the ESP-IDF Programmer's Guide for this version and
|
||||
https://docs.espressif.com/projects/esp-idf/en/latest/security/flash-encryption.html for details.
|
||||
|
||||
config SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT
|
||||
@@ -557,6 +640,18 @@ menu "Security features"
|
||||
image to this length. It is generally not recommended to set this option, unless you have a legacy
|
||||
partitioning scheme which doesn't support 64KB aligned partition lengths.
|
||||
|
||||
config SECURE_BOOT_V2_ALLOW_EFUSE_RD_DIS
|
||||
bool "Allow additional read protecting of efuses"
|
||||
depends on SECURE_BOOT_INSECURE && SECURE_BOOT_V2_ENABLED
|
||||
help
|
||||
If not set (default, recommended), on first boot the bootloader will burn the WR_DIS_RD_DIS
|
||||
efuse when Secure Boot is enabled. This prevents any more efuses from being read protected.
|
||||
|
||||
If this option is set, it will remain possible to write the EFUSE_RD_DIS efuse field after Secure
|
||||
Boot is enabled. This may allow an attacker to read-protect the BLK2 efuse holding the public
|
||||
key digest, causing an immediate denial of service and possibly allowing an additional fault
|
||||
injection attack to bypass the signature protection.
|
||||
|
||||
config SECURE_FLASH_UART_BOOTLOADER_ALLOW_ENC
|
||||
bool "Leave UART bootloader encryption enabled"
|
||||
depends on SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT
|
||||
|
||||
@@ -45,7 +45,7 @@ clean: bootloader-clean
|
||||
bootloader-list-components:
|
||||
$(BOOTLOADER_MAKE) list-components
|
||||
|
||||
ifndef CONFIG_SECURE_BOOT_ENABLED
|
||||
ifndef CONFIG_SECURE_BOOT
|
||||
# If secure boot disabled, bootloader flashing is integrated
|
||||
# with 'make flash' and no warnings are printed.
|
||||
|
||||
@@ -115,13 +115,35 @@ $(BOOTLOADER_DIGEST_BIN): $(BOOTLOADER_BIN) $(SECURE_BOOTLOADER_KEY) | check_pyt
|
||||
@echo "DIGEST $(notdir $@)"
|
||||
$(ESPSECUREPY) digest_secure_bootloader -k $(SECURE_BOOTLOADER_KEY) -o $@ $<
|
||||
|
||||
else # CONFIG_SECURE_BOOT_ENABLED && !CONFIG_SECURE_BOOTLOADER_REFLASHABLE && !CONFIG_SECURE_BOOTLOADER_ONE_TIME_FLASH
|
||||
else ifdef CONFIG_SECURE_BOOT_V2_ENABLED
|
||||
BOOTLOADER_SIGNED_BIN := $(BOOTLOADER_BUILD_DIR)/bootloader-signed.bin
|
||||
ifdef CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES
|
||||
bootloader: $(BOOTLOADER_BIN) $(SDKCONFIG_MAKEFILE) | check_python_dependencies
|
||||
$(ESPSECUREPY) sign_data --keyfile $(SECURE_BOOT_SIGNING_KEY) --version 2 \
|
||||
-o $(BOOTLOADER_SIGNED_BIN) $(BOOTLOADER_BIN)
|
||||
else
|
||||
bootloader: $(BOOTLOADER_BIN) $(SDKCONFIG_MAKEFILE) | check_python_dependencies
|
||||
@echo "Bootloader not signed. Sign the bootloader before flashing."
|
||||
@echo "To sign the bootloader, you can use this command:"
|
||||
@echo "espsecure.py sign_data --keyfile SECURE_BOOT_SIGNING_KEY --version 2 $(BOOTLOADER_BIN)"
|
||||
endif
|
||||
@echo $(SEPARATOR)
|
||||
@echo "Use the following command to flash the bootloader:"
|
||||
ifdef CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES
|
||||
@echo "$(ESPTOOLPY_WRITE_FLASH) $(BOOTLOADER_OFFSET) $(BOOTLOADER_SIGNED_BIN)"
|
||||
else
|
||||
@echo "$(ESPTOOLPY_WRITE_FLASH) $(BOOTLOADER_OFFSET) $(BOOTLOADER_BIN)"
|
||||
endif
|
||||
@echo $(SEPARATOR)
|
||||
|
||||
else # CONFIG_SECURE_BOOT && !CONFIG_SECURE_BOOTLOADER_REFLASHABLE \
|
||||
&& !CONFIG_SECURE_BOOTLOADER_ONE_TIME_FLASH && !CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME
|
||||
bootloader:
|
||||
@echo "Invalid bootloader target: bad sdkconfig?"
|
||||
@exit 1
|
||||
endif
|
||||
|
||||
ifndef CONFIG_SECURE_BOOT_ENABLED
|
||||
ifndef CONFIG_SECURE_BOOT
|
||||
# don't build bootloader by default if secure boot is enabled
|
||||
all_binaries: $(BOOTLOADER_BIN)
|
||||
endif
|
||||
@@ -131,3 +153,8 @@ bootloader-clean: $(SDKCONFIG_MAKEFILE)
|
||||
ifdef CONFIG_SECURE_BOOTLOADER_REFLASHABLE
|
||||
rm -f $(SECURE_BOOTLOADER_KEY) $(BOOTLOADER_DIGEST_BIN)
|
||||
endif
|
||||
ifdef CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME
|
||||
ifdef CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES
|
||||
rm -f $(BOOTLOADER_SIGNED_BIN)
|
||||
endif
|
||||
endif
|
||||
@@ -19,8 +19,8 @@ set(bootloader_binary_files
|
||||
|
||||
idf_build_get_property(project_dir PROJECT_DIR)
|
||||
|
||||
# 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.
|
||||
# There are some additional processing when CONFIG_SECURE_SIGNED_APPS. This happens
|
||||
# when either CONFIG_SECURE_BOOT_V1_ENABLED or CONFIG_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.
|
||||
#
|
||||
@@ -29,7 +29,13 @@ idf_build_get_property(project_dir PROJECT_DIR)
|
||||
if(CONFIG_SECURE_SIGNED_APPS)
|
||||
add_custom_target(gen_secure_boot_keys)
|
||||
|
||||
if(CONFIG_SECURE_BOOT_ENABLED)
|
||||
if(CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME)
|
||||
set(secure_apps_signing_scheme "1")
|
||||
elseif(CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME)
|
||||
set(secure_apps_signing_scheme "2")
|
||||
endif()
|
||||
|
||||
if(CONFIG_SECURE_BOOT_V1_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))
|
||||
@@ -60,7 +66,8 @@ if(CONFIG_SECURE_SIGNED_APPS)
|
||||
# (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}")
|
||||
"\tespsecure.py generate_signing_key --version ${secure_apps_signing_scheme} \
|
||||
${CONFIG_SECURE_BOOT_SIGNING_KEY}")
|
||||
else()
|
||||
add_custom_target(gen_secure_boot_signing_key)
|
||||
endif()
|
||||
@@ -70,7 +77,7 @@ if(CONFIG_SECURE_SIGNED_APPS)
|
||||
set(ver_key_arg)
|
||||
|
||||
add_dependencies(gen_secure_boot_keys gen_secure_boot_signing_key)
|
||||
else()
|
||||
elseif(CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME)
|
||||
|
||||
get_filename_component(secure_boot_verification_key
|
||||
${CONFIG_SECURE_BOOT_VERIFICATION_KEY}
|
||||
@@ -83,7 +90,7 @@ if(CONFIG_SECURE_SIGNED_APPS)
|
||||
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.")
|
||||
"\tSee docs/security/secure-boot-v1.rst for details.")
|
||||
else()
|
||||
add_custom_target(gen_secure_boot_verification_key)
|
||||
endif()
|
||||
|
||||
@@ -20,3 +20,6 @@ CONFIG_FLASH_ENCRYPTION_INSECURE CONFIG_SECURE_FLASH_
|
||||
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_CACHE CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_CACHE
|
||||
|
||||
# Secure Boot Scheme
|
||||
CONFIG_SECURE_BOOT_ENABLED CONFIG_SECURE_BOOT_V1_ENABLED
|
||||
|
||||
@@ -83,6 +83,39 @@ if(CONFIG_SECURE_BOOTLOADER_REFLASHABLE)
|
||||
add_custom_target (gen_bootloader_digest_bin ALL DEPENDS "${bootloader_digest_bin}")
|
||||
endif()
|
||||
|
||||
if(CONFIG_SECURE_BOOT_V2_ENABLED)
|
||||
if(CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES)
|
||||
get_filename_component(secure_boot_signing_key
|
||||
"${SECURE_BOOT_SIGNING_KEY}" ABSOLUTE BASE_DIR "${project_dir}")
|
||||
|
||||
if(NOT EXISTS "${secure_boot_signing_key}")
|
||||
message(FATAL_ERROR
|
||||
"Secure Boot Signing Key Not found."
|
||||
"\nGenerate the Secure Boot V2 RSA-PSS 3072 Key."
|
||||
"\nTo generate one, you can use this command:"
|
||||
"\n\t${espsecurepy} generate_signing_key --version 2 ${SECURE_BOOT_SIGNING_KEY}")
|
||||
endif()
|
||||
|
||||
set(bootloader_unsigned_bin "bootloader-unsigned.bin")
|
||||
add_custom_command(OUTPUT ".signed_bin_timestamp"
|
||||
COMMAND cp "${CMAKE_BINARY_DIR}/${PROJECT_BIN}" "${CMAKE_BINARY_DIR}/${bootloader_unsigned_bin}"
|
||||
COMMAND ${ESPSECUREPY} sign_data --version 2 --keyfile "${secure_boot_signing_key}"
|
||||
-o "${CMAKE_BINARY_DIR}/${PROJECT_BIN}" "${CMAKE_BINARY_DIR}/${bootloader_unsigned_bin}"
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "Generated signed binary image ${build_dir}/${PROJECT_BIN}"
|
||||
"from ${CMAKE_BINARY_DIR}/${bootloader_unsigned_bin}"
|
||||
COMMAND ${CMAKE_COMMAND} -E md5sum "${CMAKE_BINARY_DIR}/${PROJECT_BIN}" > "${CMAKE_BINARY_DIR}/.signed_bin_timestamp"
|
||||
DEPENDS "${build_dir}/.bin_timestamp"
|
||||
VERBATIM
|
||||
COMMENT "Generated the signed Bootloader")
|
||||
else()
|
||||
add_custom_command(OUTPUT ".signed_bin_timestamp"
|
||||
VERBATIM
|
||||
COMMENT "Bootloader generated but not signed")
|
||||
endif()
|
||||
|
||||
add_custom_target (gen_signed_bootloader ALL DEPENDS "${build_dir}/.signed_bin_timestamp")
|
||||
endif()
|
||||
|
||||
if(CONFIG_SECURE_BOOTLOADER_ONE_TIME_FLASH)
|
||||
add_custom_command(TARGET bootloader.elf POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E echo
|
||||
@@ -126,4 +159,18 @@ elseif(CONFIG_SECURE_BOOTLOADER_REFLASHABLE)
|
||||
"* Not recommended to re-use the same secure boot keyfile on multiple production devices."
|
||||
DEPENDS gen_secure_bootloader_key gen_bootloader_digest_bin
|
||||
VERBATIM)
|
||||
elseif(CONFIG_SECURE_BOOT_V2_ENABLED)
|
||||
add_custom_command(TARGET bootloader.elf POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E echo
|
||||
"=============================================================================="
|
||||
COMMAND ${CMAKE_COMMAND} -E echo
|
||||
"Bootloader built. Secure boot enabled, so bootloader not flashed automatically."
|
||||
COMMAND ${CMAKE_COMMAND} -E echo
|
||||
"Secure boot enabled, so bootloader not flashed automatically."
|
||||
COMMAND ${CMAKE_COMMAND} -E echo
|
||||
"\t${esptoolpy_write_flash} ${BOOTLOADER_OFFSET} ${CMAKE_BINARY_DIR}/bootloader.bin"
|
||||
COMMAND ${CMAKE_COMMAND} -E echo
|
||||
"=============================================================================="
|
||||
DEPENDS gen_signed_bootloader
|
||||
VERBATIM)
|
||||
endif()
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
# only compile the "micro-ecc/uECC.c" source file
|
||||
idf_component_register(SRCS "micro-ecc/uECC.c"
|
||||
INCLUDE_DIRS micro-ecc)
|
||||
# only compile the "uECC_verify_antifault.c" file which includes the "micro-ecc/uECC.c" source file
|
||||
idf_component_register(SRCS "uECC_verify_antifault.c"
|
||||
INCLUDE_DIRS . micro-ecc)
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
# only compile the micro-ecc/uECC.c source file
|
||||
# (SRCDIRS is needed so build system can find the source file)
|
||||
COMPONENT_SRCDIRS := micro-ecc
|
||||
COMPONENT_OBJS := micro-ecc/uECC.o
|
||||
# only compile the "uECC_verify_antifault.c" file which includes the "micro-ecc/uECC.c" source file
|
||||
COMPONENT_SRCDIRS := .
|
||||
|
||||
COMPONENT_ADD_INCLUDEDIRS := micro-ecc
|
||||
COMPONENT_ADD_INCLUDEDIRS := . micro-ecc
|
||||
|
||||
COMPONENT_SUBMODULES := micro-ecc
|
||||
|
||||
@@ -0,0 +1,141 @@
|
||||
/* Copyright 2014, Kenneth MacKay. Licensed under the BSD 2-clause license.
|
||||
|
||||
Modifications Copyright 2020, Espressif Systems (Shanghai) PTE LTD. Licensed under the BSD
|
||||
2-clause license.
|
||||
*/
|
||||
|
||||
/* uECC_verify() calls a number of static functions form here and
|
||||
uses other definitions, so we just build that whole source file here and then append
|
||||
our modified version uECC_verify_antifault(). */
|
||||
#include "micro-ecc/uECC.c"
|
||||
|
||||
/* Version of uECC_verify() which also copies message_hash into verified_hash,
|
||||
but only if the signature is valid. Does this in an FI resistant way.
|
||||
*/
|
||||
int uECC_verify_antifault(const uint8_t *public_key,
|
||||
const uint8_t *message_hash,
|
||||
unsigned hash_size,
|
||||
const uint8_t *signature,
|
||||
uECC_Curve curve,
|
||||
uint8_t *verified_hash) {
|
||||
uECC_word_t u1[uECC_MAX_WORDS], u2[uECC_MAX_WORDS];
|
||||
uECC_word_t z[uECC_MAX_WORDS];
|
||||
uECC_word_t sum[uECC_MAX_WORDS * 2];
|
||||
uECC_word_t rx[uECC_MAX_WORDS];
|
||||
uECC_word_t ry[uECC_MAX_WORDS];
|
||||
uECC_word_t tx[uECC_MAX_WORDS];
|
||||
uECC_word_t ty[uECC_MAX_WORDS];
|
||||
uECC_word_t tz[uECC_MAX_WORDS];
|
||||
const uECC_word_t *points[4];
|
||||
const uECC_word_t *point;
|
||||
bitcount_t num_bits;
|
||||
bitcount_t i;
|
||||
#if uECC_VLI_NATIVE_LITTLE_ENDIAN
|
||||
uECC_word_t *_public = (uECC_word_t *)public_key;
|
||||
#else
|
||||
uECC_word_t _public[uECC_MAX_WORDS * 2];
|
||||
#endif
|
||||
uECC_word_t r[uECC_MAX_WORDS], s[uECC_MAX_WORDS];
|
||||
wordcount_t num_words = curve->num_words;
|
||||
wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits);
|
||||
|
||||
rx[num_n_words - 1] = 0;
|
||||
r[num_n_words - 1] = 0;
|
||||
s[num_n_words - 1] = 0;
|
||||
|
||||
#if uECC_VLI_NATIVE_LITTLE_ENDIAN
|
||||
bcopy((uint8_t *) r, signature, curve->num_bytes);
|
||||
bcopy((uint8_t *) s, signature + curve->num_bytes, curve->num_bytes);
|
||||
#else
|
||||
uECC_vli_bytesToNative(_public, public_key, curve->num_bytes);
|
||||
uECC_vli_bytesToNative(
|
||||
_public + num_words, public_key + curve->num_bytes, curve->num_bytes);
|
||||
uECC_vli_bytesToNative(r, signature, curve->num_bytes);
|
||||
uECC_vli_bytesToNative(s, signature + curve->num_bytes, curve->num_bytes);
|
||||
#endif
|
||||
|
||||
/* r, s must not be 0. */
|
||||
if (uECC_vli_isZero(r, num_words) || uECC_vli_isZero(s, num_words)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* r, s must be < n. */
|
||||
if (uECC_vli_cmp(curve->n, r, num_n_words) != 1 ||
|
||||
uECC_vli_cmp(curve->n, s, num_n_words) != 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Calculate u1 and u2. */
|
||||
uECC_vli_modInv(z, s, curve->n, num_n_words); /* z = 1/s */
|
||||
u1[num_n_words - 1] = 0;
|
||||
bits2int(u1, message_hash, hash_size, curve);
|
||||
uECC_vli_modMult(u1, u1, z, curve->n, num_n_words); /* u1 = e/s */
|
||||
uECC_vli_modMult(u2, r, z, curve->n, num_n_words); /* u2 = r/s */
|
||||
|
||||
/* Calculate sum = G + Q. */
|
||||
uECC_vli_set(sum, _public, num_words);
|
||||
uECC_vli_set(sum + num_words, _public + num_words, num_words);
|
||||
uECC_vli_set(tx, curve->G, num_words);
|
||||
uECC_vli_set(ty, curve->G + num_words, num_words);
|
||||
uECC_vli_modSub(z, sum, tx, curve->p, num_words); /* z = x2 - x1 */
|
||||
XYcZ_add(tx, ty, sum, sum + num_words, curve);
|
||||
uECC_vli_modInv(z, z, curve->p, num_words); /* z = 1/z */
|
||||
apply_z(sum, sum + num_words, z, curve);
|
||||
|
||||
/* Use Shamir's trick to calculate u1*G + u2*Q */
|
||||
points[0] = 0;
|
||||
points[1] = curve->G;
|
||||
points[2] = _public;
|
||||
points[3] = sum;
|
||||
num_bits = smax(uECC_vli_numBits(u1, num_n_words),
|
||||
uECC_vli_numBits(u2, num_n_words));
|
||||
|
||||
point = points[(!!uECC_vli_testBit(u1, num_bits - 1)) |
|
||||
((!!uECC_vli_testBit(u2, num_bits - 1)) << 1)];
|
||||
uECC_vli_set(rx, point, num_words);
|
||||
uECC_vli_set(ry, point + num_words, num_words);
|
||||
uECC_vli_clear(z, num_words);
|
||||
z[0] = 1;
|
||||
|
||||
for (i = num_bits - 2; i >= 0; --i) {
|
||||
uECC_word_t index;
|
||||
curve->double_jacobian(rx, ry, z, curve);
|
||||
|
||||
index = (!!uECC_vli_testBit(u1, i)) | ((!!uECC_vli_testBit(u2, i)) << 1);
|
||||
point = points[index];
|
||||
if (point) {
|
||||
uECC_vli_set(tx, point, num_words);
|
||||
uECC_vli_set(ty, point + num_words, num_words);
|
||||
apply_z(tx, ty, z, curve);
|
||||
uECC_vli_modSub(tz, rx, tx, curve->p, num_words); /* Z = x2 - x1 */
|
||||
XYcZ_add(tx, ty, rx, ry, curve);
|
||||
uECC_vli_modMult_fast(z, z, tz, curve);
|
||||
}
|
||||
}
|
||||
|
||||
uECC_vli_modInv(z, z, curve->p, num_words); /* Z = 1/Z */
|
||||
apply_z(rx, ry, z, curve);
|
||||
|
||||
/* v = x1 (mod n) */
|
||||
if (uECC_vli_cmp(curve->n, rx, num_n_words) != 1) {
|
||||
uECC_vli_sub(rx, rx, curve->n, num_n_words);
|
||||
}
|
||||
|
||||
/* Anti-FI addition. Copy message_hash into verified_hash, but do it in a
|
||||
way that it will only happen if v == r (ie, rx == r)
|
||||
*/
|
||||
const uECC_word_t *mhash_words = (const uECC_word_t *)message_hash;
|
||||
uECC_word_t *vhash_words = (uECC_word_t *)verified_hash;
|
||||
unsigned hash_words = hash_size / sizeof(uECC_word_t);
|
||||
for (int w = 0; w < hash_words; w++) {
|
||||
/* note: using curve->num_words here to encourage compiler to re-read this variable */
|
||||
vhash_words[w] = mhash_words[w] ^ rx[w % curve->num_words] ^ r[w % curve->num_words];
|
||||
}
|
||||
/* Curve may be longer than hash, in which case keep reading the rest of the bytes */
|
||||
for (int w = hash_words; w < curve->num_words; w++) {
|
||||
vhash_words[w % hash_words] |= rx[w] ^ r[w];
|
||||
}
|
||||
|
||||
/* Accept only if v == r. */
|
||||
return (int)(uECC_vli_equal(rx, r, num_words));
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
/* Copyright 2014, Kenneth MacKay. Licensed under the BSD 2-clause license.
|
||||
|
||||
Modifications Copyright 2020, Espressif Systems (Shanghai) PTE LTD. Licensed under the BSD
|
||||
2-clause license.
|
||||
*/
|
||||
#pragma once
|
||||
#include "uECC.h"
|
||||
|
||||
/* Version uECC_verify() that also copies message_hash to verified_hash
|
||||
if the signature is valid, and does it in a way that is harder to attack
|
||||
with fault injection.
|
||||
*/
|
||||
int uECC_verify_antifault(const uint8_t *public_key,
|
||||
const uint8_t *message_hash,
|
||||
unsigned hash_size,
|
||||
const uint8_t *signature,
|
||||
uECC_Curve curve,
|
||||
uint8_t *verified_hash);
|
||||
@@ -17,6 +17,9 @@ ifdef CONFIG_IDF_TARGET_ESP32
|
||||
ifndef CONFIG_SPI_FLASH_ROM_DRIVER_PATCH
|
||||
LINKER_SCRIPTS += $(IDF_PATH)/components/esp_rom/$(IDF_TARGET)/ld/$(IDF_TARGET).rom.spiflash.ld
|
||||
endif
|
||||
ifdef CONFIG_ESP32_REV_MIN_3
|
||||
LINKER_SCRIPTS += $(IDF_PATH)/components/esp_rom/$(IDF_TARGET)/ld/$(IDF_TARGET).rom.eco3.ld
|
||||
endif
|
||||
endif
|
||||
|
||||
COMPONENT_ADD_LDFLAGS += -L $(COMPONENT_PATH) $(addprefix -T ,$(LINKER_SCRIPTS))
|
||||
|
||||
@@ -76,6 +76,7 @@ SECTIONS
|
||||
.dram0.bss (NOLOAD) :
|
||||
{
|
||||
. = ALIGN (8);
|
||||
_dram_start = ABSOLUTE(.);
|
||||
_bss_start = ABSOLUTE(.);
|
||||
*(.dynsbss)
|
||||
*(.sbss)
|
||||
@@ -152,6 +153,7 @@ SECTIONS
|
||||
*(.gnu.linkonce.lit4.*)
|
||||
_lit4_end = ABSOLUTE(.);
|
||||
. = ALIGN(4);
|
||||
_dram_end = ABSOLUTE(.);
|
||||
} >dram_seg
|
||||
|
||||
.iram.text :
|
||||
|
||||
@@ -68,6 +68,7 @@ SECTIONS
|
||||
.dram0.bss (NOLOAD) :
|
||||
{
|
||||
. = ALIGN (8);
|
||||
_dram_start = ABSOLUTE(.);
|
||||
_bss_start = ABSOLUTE(.);
|
||||
*(.dynsbss)
|
||||
*(.sbss)
|
||||
@@ -144,7 +145,7 @@ SECTIONS
|
||||
*(.gnu.linkonce.lit4.*)
|
||||
_lit4_end = ABSOLUTE(.);
|
||||
. = ALIGN(4);
|
||||
_heap_start = ABSOLUTE(.);
|
||||
_dram_end = ABSOLUTE(.);
|
||||
} >dram_seg
|
||||
|
||||
.iram.text :
|
||||
|
||||
@@ -20,22 +20,34 @@ if(BOOTLOADER_BUILD)
|
||||
set(include_dirs "include" "include_bootloader")
|
||||
set(priv_requires micro-ecc spi_flash efuse)
|
||||
list(APPEND srcs
|
||||
"src/bootloader_init.c"
|
||||
"src/${IDF_TARGET}/bootloader_sha.c"
|
||||
"src/${IDF_TARGET}/flash_encrypt.c"
|
||||
"src/${IDF_TARGET}/secure_boot_signatures.c"
|
||||
"src/${IDF_TARGET}/secure_boot.c"
|
||||
"src/${IDF_TARGET}/bootloader_${IDF_TARGET}.c"
|
||||
)
|
||||
"src/bootloader_init.c"
|
||||
"src/${IDF_TARGET}/bootloader_sha.c"
|
||||
"src/${IDF_TARGET}/flash_encrypt.c"
|
||||
"src/${IDF_TARGET}/bootloader_${IDF_TARGET}.c"
|
||||
)
|
||||
else()
|
||||
list(APPEND srcs
|
||||
"src/idf/bootloader_sha.c"
|
||||
"src/idf/secure_boot_signatures.c")
|
||||
"src/idf/bootloader_sha.c")
|
||||
set(include_dirs "include")
|
||||
set(priv_include_dirs "include_bootloader")
|
||||
set(priv_requires spi_flash mbedtls efuse)
|
||||
endif()
|
||||
|
||||
if(CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME OR CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME)
|
||||
if(BOOTLOADER_BUILD)
|
||||
list(APPEND srcs
|
||||
"src/${IDF_TARGET}/secure_boot_signatures.c")
|
||||
else()
|
||||
list(APPEND srcs
|
||||
"src/idf/secure_boot_signatures.c")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(CONFIG_SECURE_BOOT AND BOOTLOADER_BUILD)
|
||||
list(APPEND srcs
|
||||
"src/${IDF_TARGET}/secure_boot.c")
|
||||
endif()
|
||||
|
||||
set(requires soc) #unfortunately the header directly uses SOC registers
|
||||
|
||||
idf_component_register(SRCS "${srcs}"
|
||||
@@ -44,7 +56,7 @@ idf_component_register(SRCS "${srcs}"
|
||||
REQUIRES "${requires}"
|
||||
PRIV_REQUIRES "${priv_requires}")
|
||||
|
||||
if(CONFIG_SECURE_SIGNED_APPS)
|
||||
if(CONFIG_SECURE_SIGNED_APPS AND (CONFIG_SECURE_BOOT_V1_ENABLED OR CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME))
|
||||
if(BOOTLOADER_BUILD)
|
||||
# Whether CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES or not, we need verification key to embed
|
||||
# in the library.
|
||||
|
||||
@@ -22,11 +22,23 @@ endif
|
||||
COMPONENT_OBJEXCLUDE += src/bootloader_flash_config_esp32s2beta.o \
|
||||
src/bootloader_efuse_esp32s2beta.o
|
||||
|
||||
ifndef CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME
|
||||
ifndef CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME
|
||||
COMPONENT_OBJEXCLUDE += src/$(IDF_TARGET)/secure_boot_signatures.o \
|
||||
src/idf/secure_boot_signatures.o
|
||||
endif
|
||||
endif
|
||||
|
||||
ifndef CONFIG_SECURE_BOOT
|
||||
COMPONENT_OBJEXCLUDE += src/$(IDF_TARGET)/secure_boot.o
|
||||
endif
|
||||
|
||||
#
|
||||
# Secure boot signing key support
|
||||
#
|
||||
ifdef CONFIG_SECURE_SIGNED_APPS
|
||||
|
||||
ifdef CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME
|
||||
# this path is created relative to the component build directory
|
||||
SECURE_BOOT_VERIFICATION_KEY := $(abspath signature_verification_key.bin)
|
||||
|
||||
@@ -41,7 +53,7 @@ ORIG_SECURE_BOOT_VERIFICATION_KEY := $(call resolvepath,$(call dequote,$(CONFIG_
|
||||
$(ORIG_SECURE_BOOT_VERIFICATION_KEY):
|
||||
@echo "Secure boot verification public key '$@' missing."
|
||||
@echo "This can be extracted from the private signing key, see"
|
||||
@echo "docs/security/secure-boot.rst for details."
|
||||
@echo "docs/security/secure-boot-v1.rst for details."
|
||||
exit 1
|
||||
|
||||
# copy it into the build dir, so the secure boot verification key has
|
||||
@@ -55,4 +67,5 @@ COMPONENT_EXTRA_CLEAN += $(SECURE_BOOT_VERIFICATION_KEY)
|
||||
|
||||
COMPONENT_EMBED_FILES := $(SECURE_BOOT_VERIFICATION_KEY)
|
||||
|
||||
endif #CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME
|
||||
endif #CONFIG_SECURE_SIGNED_APPS
|
||||
|
||||
@@ -16,13 +16,18 @@
|
||||
#include <stdbool.h>
|
||||
#include <esp_err.h>
|
||||
#include "soc/efuse_periph.h"
|
||||
#include "esp_image_format.h"
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#if CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
#include "esp32s2beta/rom/efuse.h"
|
||||
#else
|
||||
#include "esp32/rom/secure_boot.h"
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SECURE_BOOT_ENABLED
|
||||
typedef struct ets_secure_boot_signature ets_secure_boot_signature_t;
|
||||
|
||||
#ifdef CONFIG_SECURE_BOOT_V1_ENABLED
|
||||
#if !defined(CONFIG_SECURE_SIGNED_ON_BOOT) || !defined(CONFIG_SECURE_SIGNED_ON_UPDATE) || !defined(CONFIG_SECURE_SIGNED_APPS)
|
||||
#error "internal sdkconfig error, secure boot should always enable all signature options"
|
||||
#endif
|
||||
@@ -47,16 +52,23 @@ extern "C" {
|
||||
static inline bool esp_secure_boot_enabled(void)
|
||||
{
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
return REG_READ(EFUSE_BLK0_RDATA6_REG) & EFUSE_RD_ABS_DONE_0;
|
||||
#ifdef CONFIG_SECURE_BOOT_V1_ENABLED
|
||||
return REG_READ(EFUSE_BLK0_RDATA6_REG) & EFUSE_RD_ABS_DONE_0;
|
||||
#elif CONFIG_SECURE_BOOT_V2_ENABLED
|
||||
return ets_use_secure_boot_v2();
|
||||
#endif
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
return ets_efuse_secure_boot_enabled();
|
||||
#endif
|
||||
return false; /* Secure Boot not enabled in menuconfig */
|
||||
}
|
||||
|
||||
/** @brief Generate secure digest from bootloader image
|
||||
*
|
||||
* @important This function is intended to be called from bootloader code only.
|
||||
*
|
||||
* This function is only used in the context of the Secure Boot V1 scheme.
|
||||
*
|
||||
* If secure boot is not yet enabled for bootloader, this will:
|
||||
* 1) generate the secure boot key and burn it on EFUSE
|
||||
* (without enabling R/W protection)
|
||||
@@ -73,18 +85,17 @@ static inline bool esp_secure_boot_enabled(void)
|
||||
*/
|
||||
esp_err_t esp_secure_boot_generate_digest(void);
|
||||
|
||||
/** @brief Enable secure boot if it is not already enabled.
|
||||
/** @brief Enable secure boot V1 if it is not already enabled.
|
||||
*
|
||||
* @important If this function succeeds, secure boot is permanently
|
||||
* @important If this function succeeds, secure boot V1 is permanently
|
||||
* enabled on the chip via efuse.
|
||||
*
|
||||
* @important This function is intended to be called from bootloader code only.
|
||||
*
|
||||
* @important This will enable r/w protection of secure boot key on EFUSE,
|
||||
* therefore it is to be ensured that esp_secure_boot_generate_digest()
|
||||
* is called before this
|
||||
*
|
||||
* If secure boot is not yet enabled for bootloader, this will
|
||||
* @important In case of Secure Boot V1, this will enable r/w protection
|
||||
* of secure boot key on EFUSE, therefore it is to be ensured that
|
||||
* esp_secure_boot_generate_digest() is called before this .If secure boot is not
|
||||
* yet enabled for bootloader, this will
|
||||
* 1) enable R/W protection of secure boot key on EFUSE
|
||||
* 2) enable secure boot by blowing the EFUSE_RD_ABS_DONE_0 efuse.
|
||||
*
|
||||
@@ -100,35 +111,97 @@ esp_err_t esp_secure_boot_generate_digest(void);
|
||||
*/
|
||||
esp_err_t esp_secure_boot_permanently_enable(void);
|
||||
|
||||
/** @brief Verify the secure boot signature (determinstic ECDSA w/ SHA256) appended to some binary data in flash.
|
||||
/** @brief Enables secure boot V2 if it is not already enabled.
|
||||
*
|
||||
* Public key is compiled into the calling program. See docs/security/secure-boot.rst for details.
|
||||
* @important If this function succeeds, secure boot V2 is permanently
|
||||
* enabled on the chip via efuse.
|
||||
*
|
||||
* @important This function is intended to be called from bootloader code only.
|
||||
*
|
||||
* @important In case of Secure Boot V2, this will enable write protection
|
||||
* of secure boot key on EFUSE in BLK2. .If secure boot is not
|
||||
* yet enabled for bootloader, this will
|
||||
* 1) enable W protection of secure boot key on EFUSE
|
||||
* 2) enable secure boot by blowing the EFUSE_RD_ABS_DONE_1 efuse.
|
||||
*
|
||||
* This function does not verify secure boot of the bootloader (the
|
||||
* ROM bootloader does this.)
|
||||
*
|
||||
* @param image_data Image metadata of the application to be loaded.
|
||||
*
|
||||
* Will fail if efuses have been part-burned in a way that indicates
|
||||
* secure boot should not or could not be correctly enabled.
|
||||
*
|
||||
* @return ESP_ERR_INVALID_STATE if efuse state doesn't allow
|
||||
* secure boot to be enabled cleanly. ESP_OK if secure boot
|
||||
* is enabled on this chip from now on.
|
||||
*/
|
||||
esp_err_t esp_secure_boot_v2_permanently_enable(const esp_image_metadata_t *image_data);
|
||||
|
||||
/** @brief Verify the secure boot signature appended to some binary data in flash.
|
||||
*
|
||||
* For ECDSA Scheme (Secure Boot V1) - deterministic ECDSA w/ SHA256 image
|
||||
* For RSA Scheme (Secure Boot V2) - RSA-PSS Verification of the SHA-256 image
|
||||
*
|
||||
* Public key is compiled into the calling program in the ECDSA Scheme.
|
||||
* See the apt docs/security/secure-boot-v1.rst or docs/security/secure-boot-v2.rst for details.
|
||||
*
|
||||
* @param src_addr Starting offset of the data in flash.
|
||||
* @param length Length of data in bytes. Signature is appended -after- length bytes.
|
||||
*
|
||||
* If flash encryption is enabled, the image will be transparently decrypted while being verified.
|
||||
*
|
||||
* @note This function doesn't have any fault injection resistance so should not be called
|
||||
* during a secure boot itself (but can be called when verifying an update, etc.)
|
||||
*
|
||||
* @return ESP_OK if signature is valid, ESP_ERR_INVALID_STATE if
|
||||
* signature fails, ESP_FAIL for other failures (ie can't read flash).
|
||||
*/
|
||||
esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length);
|
||||
|
||||
/** @brief Verify the secure boot signature block (deterministic ECDSA w/ SHA256) based on the SHA256 hash of some data.
|
||||
*
|
||||
* Similar to esp_secure_boot_verify_signature(), but can be used when the digest is precalculated.
|
||||
* @param sig_block Pointer to signature block data
|
||||
* @param image_digest Pointer to 32 byte buffer holding SHA-256 hash.
|
||||
*
|
||||
*/
|
||||
|
||||
/** @brief Secure boot verification block, on-flash data format. */
|
||||
typedef struct {
|
||||
uint32_t version;
|
||||
uint8_t signature[64];
|
||||
} esp_secure_boot_sig_block_t;
|
||||
|
||||
esp_err_t esp_secure_boot_verify_signature_block(const esp_secure_boot_sig_block_t *sig_block, const uint8_t *image_digest);
|
||||
/** @brief Verify the ECDSA secure boot signature block for Secure Boot V1.
|
||||
*
|
||||
* Calculates Deterministic ECDSA w/ SHA256 based on the SHA256 hash of the image. ECDSA signature
|
||||
* verification must be enabled in project configuration to use this function.
|
||||
*
|
||||
* Similar to esp_secure_boot_verify_signature(), but can be used when the digest is precalculated.
|
||||
* @param sig_block Pointer to ECDSA signature block data
|
||||
* @param image_digest Pointer to 32 byte buffer holding SHA-256 hash.
|
||||
* @param verified_digest Pointer to 32 byte buffer that will receive verified digest if verification completes. (Used during bootloader implementation only, result is invalid otherwise.)
|
||||
*
|
||||
*/
|
||||
esp_err_t esp_secure_boot_verify_ecdsa_signature_block(const esp_secure_boot_sig_block_t *sig_block, const uint8_t *image_digest, uint8_t *verified_digest);
|
||||
|
||||
|
||||
/** @brief Verify the RSA secure boot signature block for Secure Boot V2.
|
||||
*
|
||||
* Performs RSA-PSS Verification of the SHA-256 image based on the public key
|
||||
* in the signature block, compared against the public key digest stored in efuse.
|
||||
*
|
||||
* Similar to esp_secure_boot_verify_signature(), but can be used when the digest is precalculated.
|
||||
* @param sig_block Pointer to RSA signature block data
|
||||
* @param image_digest Pointer to 32 byte buffer holding SHA-256 hash.
|
||||
* @param verified_digest Pointer to 32 byte buffer that will receive verified digest if verification completes. (Used during bootloader implementation only, result is invalid otherwise.)
|
||||
*
|
||||
*/
|
||||
esp_err_t esp_secure_boot_verify_rsa_signature_block(const ets_secure_boot_signature_t *sig_block, const uint8_t *image_digest, uint8_t *verified_digest);
|
||||
|
||||
/** @brief Legacy ECDSA verification function
|
||||
*
|
||||
* @note Deprecated, call either esp_secure_boot_verify_ecdsa_signature_block() or esp_secure_boot_verify_rsa_signature_block() instead.
|
||||
*
|
||||
* @param sig_block Pointer to ECDSA signature block data
|
||||
* @param image_digest Pointer to 32 byte buffer holding SHA-256 hash.
|
||||
*/
|
||||
esp_err_t esp_secure_boot_verify_signature_block(const esp_secure_boot_sig_block_t *sig_block, const uint8_t *image_digest)
|
||||
__attribute__((deprecated("use esp_secure_boot_verify_ecdsa_signature_block instead")));
|
||||
|
||||
|
||||
#define FLASH_OFFS_SECURE_BOOT_IV_DIGEST 0
|
||||
|
||||
|
||||
@@ -18,9 +18,11 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <esp_err.h>
|
||||
#include <esp_spi_flash.h> /* including in bootloader for error values */
|
||||
|
||||
#define FLASH_SECTOR_SIZE 0x1000
|
||||
#define FLASH_BLOCK_SIZE 0x10000
|
||||
#define MMAP_ALIGNED_MASK 0x0000FFFF
|
||||
|
||||
/* Provide a Flash API for bootloader_support code,
|
||||
that can be used from bootloader or app code.
|
||||
|
||||
@@ -108,3 +108,17 @@ esp_err_t bootloader_sha256_hex_to_str(char *out_str, const uint8_t *in_array_he
|
||||
* @param label Label to print at beginning of log line.
|
||||
*/
|
||||
void bootloader_debug_buffer(const void *buffer, size_t length, const char *label);
|
||||
|
||||
/** @brief Generates the digest of the data between offset & offset+length.
|
||||
*
|
||||
* This function should be used when the size of the data is larger than 3.2MB.
|
||||
* The MMU capacity is 3.2MB (50 pages - 64KB each). This function generates the SHA-256
|
||||
* of the data in chunks of 3.2MB, considering the MMU capacity.
|
||||
*
|
||||
* @param[in] flash_offset Offset of the data in flash.
|
||||
* @param[in] len Length of data in bytes.
|
||||
* @param[out] digest Pointer to buffer where the digest is written, if ESP_OK is returned.
|
||||
*
|
||||
* @return ESP_OK if secure boot digest is generated successfully.
|
||||
*/
|
||||
esp_err_t bootloader_sha256_flash_contents(uint32_t flash_offset, uint32_t len, uint8_t *digest);
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
|
||||
#include <bootloader_flash.h>
|
||||
#include <esp_log.h>
|
||||
#include <esp_spi_flash.h> /* including in bootloader for error values */
|
||||
#include <esp_flash_encrypt.h>
|
||||
#if CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
#include "esp32s2beta/rom/spi_flash.h"
|
||||
|
||||
@@ -62,6 +62,7 @@ void IRAM_ATTR bootloader_flash_clock_config(const esp_image_header_t* pfhdr)
|
||||
break;
|
||||
}
|
||||
esp_rom_spiflash_config_clk(spi_clk_div, 0);
|
||||
esp_rom_spiflash_config_clk(spi_clk_div, 1);
|
||||
}
|
||||
|
||||
void IRAM_ATTR bootloader_flash_gpio_config(const esp_image_header_t* pfhdr)
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_attr.h"
|
||||
#include "esp_log.h"
|
||||
#include "bootloader_init.h"
|
||||
#include "bootloader_flash.h"
|
||||
@@ -30,7 +31,7 @@
|
||||
|
||||
static const char *TAG = "boot";
|
||||
|
||||
esp_image_header_t bootloader_image_hdr;
|
||||
esp_image_header_t WORD_ALIGNED_ATTR bootloader_image_hdr;
|
||||
|
||||
void bootloader_clear_bss_section(void)
|
||||
{
|
||||
|
||||
@@ -555,11 +555,19 @@ static void load_image(const esp_image_metadata_t *image_data)
|
||||
* then Step 6 enables secure boot.
|
||||
*/
|
||||
|
||||
#if defined(CONFIG_SECURE_BOOT_ENABLED) || defined(CONFIG_SECURE_FLASH_ENC_ENABLED)
|
||||
#if defined(CONFIG_SECURE_BOOT) || defined(CONFIG_SECURE_FLASH_ENC_ENABLED)
|
||||
esp_err_t err;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SECURE_BOOT_ENABLED
|
||||
#ifdef CONFIG_SECURE_BOOT_V2_ENABLED
|
||||
err = esp_secure_boot_v2_permanently_enable(image_data);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Secure Boot v2 failed (%d)", err);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SECURE_BOOT_V1_ENABLED
|
||||
/* Steps 1 & 2 (see above for full description):
|
||||
* 1) Generate secure boot EFUSE key
|
||||
* 2) Compute digest of plaintext bootloader
|
||||
@@ -586,7 +594,7 @@ static void load_image(const esp_image_metadata_t *image_data)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SECURE_BOOT_ENABLED
|
||||
#ifdef CONFIG_SECURE_BOOT_V1_ENABLED
|
||||
/* Step 6 (see above for full description):
|
||||
* 6) Burn EFUSE to enable secure boot
|
||||
*/
|
||||
@@ -816,3 +824,37 @@ void bootloader_debug_buffer(const void *buffer, size_t length, const char *labe
|
||||
ESP_LOGD(TAG, "%s: %s", label, hexbuf);
|
||||
#endif
|
||||
}
|
||||
|
||||
esp_err_t bootloader_sha256_flash_contents(uint32_t flash_offset, uint32_t len, uint8_t *digest)
|
||||
{
|
||||
if (digest == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
/* Handling firmware images larger than MMU capacity */
|
||||
uint32_t mmu_free_pages_count = bootloader_mmap_get_free_pages();
|
||||
bootloader_sha256_handle_t sha_handle = NULL;
|
||||
|
||||
sha_handle = bootloader_sha256_start();
|
||||
if (sha_handle == NULL) {
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
while (len > 0) {
|
||||
uint32_t mmu_page_offset = ((flash_offset & MMAP_ALIGNED_MASK) != 0) ? 1 : 0; /* Skip 1st MMU Page if it is already populated */
|
||||
uint32_t partial_image_len = MIN(len, ((mmu_free_pages_count - mmu_page_offset) * SPI_FLASH_MMU_PAGE_SIZE)); /* Read the image that fits in the free MMU pages */
|
||||
|
||||
const void * image = bootloader_mmap(flash_offset, partial_image_len);
|
||||
if (image == NULL) {
|
||||
bootloader_sha256_finish(sha_handle, NULL);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
bootloader_sha256_data(sha_handle, image, partial_image_len);
|
||||
bootloader_munmap(image);
|
||||
|
||||
flash_offset += partial_image_len;
|
||||
len -= partial_image_len;
|
||||
}
|
||||
bootloader_sha256_finish(sha_handle, digest);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@@ -73,6 +73,10 @@ esp_err_t esp_flash_encrypt_check_and_update(void)
|
||||
|
||||
static esp_err_t initialise_flash_encryption(void)
|
||||
{
|
||||
uint32_t new_wdata0 = 0;
|
||||
uint32_t new_wdata5 = 0;
|
||||
uint32_t new_wdata6 = 0;
|
||||
|
||||
uint32_t coding_scheme = REG_GET_FIELD(EFUSE_BLK0_RDATA6_REG, EFUSE_CODING_SCHEME);
|
||||
if (coding_scheme != EFUSE_CODING_SCHEME_VAL_NONE && coding_scheme != EFUSE_CODING_SCHEME_VAL_34) {
|
||||
ESP_LOGE(TAG, "Unknown/unsupported CODING_SCHEME value 0x%x", coding_scheme);
|
||||
@@ -97,11 +101,10 @@ static esp_err_t initialise_flash_encryption(void)
|
||||
&& REG_READ(EFUSE_BLK1_RDATA7_REG) == 0) {
|
||||
ESP_LOGI(TAG, "Generating new flash encryption key...");
|
||||
esp_efuse_write_random_key(EFUSE_BLK1_WDATA0_REG);
|
||||
esp_efuse_burn_new_values();
|
||||
// defer efuse programming step to the end
|
||||
|
||||
ESP_LOGI(TAG, "Read & write protecting new key...");
|
||||
REG_WRITE(EFUSE_BLK0_WDATA0_REG, EFUSE_WR_DIS_BLK1 | EFUSE_RD_DIS_BLK1);
|
||||
esp_efuse_burn_new_values();
|
||||
new_wdata0 |= EFUSE_WR_DIS_BLK1 | EFUSE_RD_DIS_BLK1;
|
||||
} else {
|
||||
|
||||
if(!(efuse_key_read_protected && efuse_key_write_protected)) {
|
||||
@@ -122,34 +125,36 @@ static esp_err_t initialise_flash_encryption(void)
|
||||
operation does nothing. Please note this is not recommended!
|
||||
*/
|
||||
ESP_LOGI(TAG, "Setting CRYPT_CONFIG efuse to 0xF");
|
||||
REG_WRITE(EFUSE_BLK0_WDATA5_REG, EFUSE_FLASH_CRYPT_CONFIG_M);
|
||||
esp_efuse_burn_new_values();
|
||||
new_wdata5 |= EFUSE_FLASH_CRYPT_CONFIG_M;
|
||||
|
||||
uint32_t new_wdata6 = 0;
|
||||
#ifndef CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_ENC
|
||||
ESP_LOGI(TAG, "Disable UART bootloader encryption...");
|
||||
new_wdata6 |= EFUSE_DISABLE_DL_ENCRYPT;
|
||||
#else
|
||||
ESP_LOGW(TAG, "Not disabling UART bootloader encryption");
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_DEC
|
||||
ESP_LOGI(TAG, "Disable UART bootloader decryption...");
|
||||
new_wdata6 |= EFUSE_DISABLE_DL_DECRYPT;
|
||||
#else
|
||||
ESP_LOGW(TAG, "Not disabling UART bootloader decryption - SECURITY COMPROMISED");
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_CACHE
|
||||
ESP_LOGI(TAG, "Disable UART bootloader MMU cache...");
|
||||
new_wdata6 |= EFUSE_DISABLE_DL_CACHE;
|
||||
#else
|
||||
ESP_LOGW(TAG, "Not disabling UART bootloader MMU cache - SECURITY COMPROMISED");
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_SECURE_BOOT_ALLOW_JTAG
|
||||
ESP_LOGI(TAG, "Disable JTAG...");
|
||||
new_wdata6 |= EFUSE_RD_DISABLE_JTAG;
|
||||
#else
|
||||
ESP_LOGW(TAG, "Not disabling JTAG - SECURITY COMPROMISED");
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_SECURE_BOOT_ALLOW_ROM_BASIC
|
||||
ESP_LOGI(TAG, "Disable ROM BASIC interpreter fallback...");
|
||||
new_wdata6 |= EFUSE_RD_CONSOLE_DEBUG_DISABLE;
|
||||
@@ -157,10 +162,16 @@ static esp_err_t initialise_flash_encryption(void)
|
||||
ESP_LOGW(TAG, "Not disabling ROM BASIC fallback - SECURITY COMPROMISED");
|
||||
#endif
|
||||
|
||||
if (new_wdata6 != 0) {
|
||||
REG_WRITE(EFUSE_BLK0_WDATA6_REG, new_wdata6);
|
||||
esp_efuse_burn_new_values();
|
||||
}
|
||||
#if defined(CONFIG_SECURE_BOOT_V2_ENABLED) && !defined(CONFIG_SECURE_BOOT_V2_ALLOW_EFUSE_RD_DIS)
|
||||
// This bit is set when enabling Secure Boot V2, but we can't enable it until this later point in the first boot
|
||||
// otherwise the Flash Encryption key cannot be read protected
|
||||
new_wdata0 |= EFUSE_WR_DIS_RD_DIS;
|
||||
#endif
|
||||
|
||||
REG_WRITE(EFUSE_BLK0_WDATA0_REG, new_wdata0);
|
||||
REG_WRITE(EFUSE_BLK0_WDATA5_REG, new_wdata5);
|
||||
REG_WRITE(EFUSE_BLK0_WDATA6_REG, new_wdata6);
|
||||
esp_efuse_burn_new_values();
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
@@ -210,16 +221,19 @@ static esp_err_t encrypt_flash_contents(uint32_t flash_crypt_cnt, bool flash_cry
|
||||
|
||||
ESP_LOGD(TAG, "All flash regions checked for encryption pass");
|
||||
|
||||
uint32_t new_flash_crypt_cnt;
|
||||
#ifdef CONFIG_SECURE_FLASH_ENCRYPTION_MODE_RELEASE
|
||||
// Go straight to max, permanently enabled
|
||||
ESP_LOGI(TAG, "Setting FLASH_CRYPT_CNT for permanent encryption");
|
||||
new_flash_crypt_cnt = EFUSE_FLASH_CRYPT_CNT;
|
||||
#else
|
||||
/* Set least significant 0-bit in flash_crypt_cnt */
|
||||
int ffs_inv = __builtin_ffs((~flash_crypt_cnt) & EFUSE_RD_FLASH_CRYPT_CNT);
|
||||
/* 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));
|
||||
new_flash_crypt_cnt = flash_crypt_cnt + (1 << (ffs_inv - 1));
|
||||
#endif
|
||||
ESP_LOGD(TAG, "FLASH_CRYPT_CNT 0x%x -> 0x%x", 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();
|
||||
@@ -236,13 +250,24 @@ static esp_err_t encrypt_bootloader(void)
|
||||
/* Check for plaintext bootloader (verification will fail if it's already encrypted) */
|
||||
if (esp_image_verify_bootloader(&image_length) == ESP_OK) {
|
||||
ESP_LOGD(TAG, "bootloader is plaintext. Encrypting...");
|
||||
|
||||
#if CONFIG_SECURE_BOOT_V2_ENABLED
|
||||
// Account for the signature sector after the bootloader
|
||||
image_length = (image_length + FLASH_SECTOR_SIZE - 1) & ~(FLASH_SECTOR_SIZE - 1);
|
||||
image_length += FLASH_SECTOR_SIZE;
|
||||
if (ESP_BOOTLOADER_OFFSET + image_length > ESP_PARTITION_TABLE_OFFSET) {
|
||||
ESP_LOGE(TAG, "Bootloader is too large to fit Secure Boot V2 signature sector and partition table (configured offset 0x%x)", ESP_PARTITION_TABLE_OFFSET);
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
#endif // CONFIG_SECURE_BOOT_V2_ENABLED
|
||||
|
||||
err = esp_flash_encrypt_region(ESP_BOOTLOADER_OFFSET, image_length);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to encrypt bootloader in place: 0x%x", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SECURE_BOOT_ENABLED
|
||||
#ifdef CONFIG_SECURE_BOOT_V1_ENABLED
|
||||
/* If secure boot is enabled and bootloader was plaintext, also
|
||||
* need to encrypt secure boot IV+digest.
|
||||
*/
|
||||
@@ -355,4 +380,4 @@ esp_err_t esp_flash_encrypt_region(uint32_t src_addr, size_t data_length)
|
||||
flash_failed:
|
||||
ESP_LOGE(TAG, "flash operation failed: 0x%x", err);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,10 +20,12 @@
|
||||
|
||||
#include "esp32/rom/cache.h"
|
||||
#include "esp32/rom/ets_sys.h"
|
||||
#include "esp32/rom/secure_boot.h"
|
||||
#include "esp32/rom/crc.h"
|
||||
|
||||
#include "soc/efuse_periph.h"
|
||||
#include "soc/rtc_periph.h"
|
||||
#include "bootloader_sha.h"
|
||||
#include "bootloader_utility.h"
|
||||
|
||||
#include "sdkconfig.h"
|
||||
|
||||
@@ -38,8 +40,8 @@
|
||||
* from the bootloader code.
|
||||
*/
|
||||
|
||||
static const char* TAG = "secure_boot";
|
||||
|
||||
#ifdef CONFIG_SECURE_BOOT_V1_ENABLED
|
||||
static const char *TAG = "secure_boot_v1";
|
||||
/**
|
||||
* @function : secure_boot_generate
|
||||
* @description: generate boot digest (aka "abstract") & iv
|
||||
@@ -94,12 +96,6 @@ static bool secure_boot_generate(uint32_t image_len){
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Burn values written to the efuse write registers */
|
||||
static inline void burn_efuses(void)
|
||||
{
|
||||
esp_efuse_burn_new_values();
|
||||
}
|
||||
|
||||
esp_err_t esp_secure_boot_generate_digest(void)
|
||||
{
|
||||
esp_err_t err;
|
||||
@@ -139,7 +135,7 @@ esp_err_t esp_secure_boot_generate_digest(void)
|
||||
&& REG_READ(EFUSE_BLK2_RDATA7_REG) == 0) {
|
||||
ESP_LOGI(TAG, "Generating new secure boot key...");
|
||||
esp_efuse_write_random_key(EFUSE_BLK2_WDATA0_REG);
|
||||
burn_efuses();
|
||||
esp_efuse_burn_new_values();
|
||||
} else {
|
||||
ESP_LOGW(TAG, "Using pre-loaded secure boot key in EFUSE block 2");
|
||||
}
|
||||
@@ -162,6 +158,9 @@ esp_err_t esp_secure_boot_generate_digest(void)
|
||||
|
||||
esp_err_t esp_secure_boot_permanently_enable(void)
|
||||
{
|
||||
uint32_t new_wdata0 = 0;
|
||||
uint32_t new_wdata6 = 0;
|
||||
|
||||
if (esp_secure_boot_enabled()) {
|
||||
ESP_LOGI(TAG, "bootloader secure boot is already enabled, continuing..");
|
||||
return ESP_OK;
|
||||
@@ -173,8 +172,7 @@ esp_err_t esp_secure_boot_permanently_enable(void)
|
||||
if (efuse_key_read_protected == false
|
||||
&& efuse_key_write_protected == false) {
|
||||
ESP_LOGI(TAG, "Read & write protecting new key...");
|
||||
REG_WRITE(EFUSE_BLK0_WDATA0_REG, EFUSE_WR_DIS_BLK2 | EFUSE_RD_DIS_BLK2);
|
||||
burn_efuses();
|
||||
new_wdata0 = EFUSE_WR_DIS_BLK2 | EFUSE_RD_DIS_BLK2;
|
||||
efuse_key_read_protected = true;
|
||||
efuse_key_write_protected = true;
|
||||
}
|
||||
@@ -191,7 +189,7 @@ esp_err_t esp_secure_boot_permanently_enable(void)
|
||||
ESP_LOGI(TAG, "blowing secure boot efuse...");
|
||||
ESP_LOGD(TAG, "before updating, EFUSE_BLK0_RDATA6 %x", REG_READ(EFUSE_BLK0_RDATA6_REG));
|
||||
|
||||
uint32_t new_wdata6 = EFUSE_RD_ABS_DONE_0;
|
||||
new_wdata6 |= EFUSE_RD_ABS_DONE_0;
|
||||
|
||||
#ifndef CONFIG_SECURE_BOOT_ALLOW_JTAG
|
||||
ESP_LOGI(TAG, "Disable JTAG...");
|
||||
@@ -207,8 +205,9 @@ esp_err_t esp_secure_boot_permanently_enable(void)
|
||||
ESP_LOGW(TAG, "Not disabling ROM BASIC fallback - SECURITY COMPROMISED");
|
||||
#endif
|
||||
|
||||
REG_WRITE(EFUSE_BLK0_WDATA0_REG, new_wdata0);
|
||||
REG_WRITE(EFUSE_BLK0_WDATA6_REG, new_wdata6);
|
||||
burn_efuses();
|
||||
esp_efuse_burn_new_values();
|
||||
uint32_t after = REG_READ(EFUSE_BLK0_RDATA6_REG);
|
||||
ESP_LOGD(TAG, "after updating, EFUSE_BLK0_RDATA6 %x", after);
|
||||
if (after & EFUSE_RD_ABS_DONE_0) {
|
||||
@@ -219,3 +218,208 @@ esp_err_t esp_secure_boot_permanently_enable(void)
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
}
|
||||
#elif CONFIG_SECURE_BOOT_V2_ENABLED
|
||||
|
||||
#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
|
||||
static const char *TAG = "secure_boot_v2";
|
||||
|
||||
#define SIG_BLOCK_MAGIC_BYTE 0xe7
|
||||
#define CRC_SIGN_BLOCK_LEN 1196
|
||||
#define SIG_BLOCK_PADDING 4096
|
||||
|
||||
#define DIGEST_LEN 32
|
||||
|
||||
static esp_err_t validate_signature_block(const ets_secure_boot_signature_t *sig_block, uint8_t *digest)
|
||||
{
|
||||
uint32_t crc = crc32_le(0, (uint8_t *)sig_block, CRC_SIGN_BLOCK_LEN);
|
||||
if (sig_block->block[0].magic_byte == SIG_BLOCK_MAGIC_BYTE && sig_block->block[0].block_crc == crc && !memcmp(digest, sig_block->block[0].image_digest, DIGEST_LEN)) {
|
||||
ESP_LOGI(TAG, "valid signature block found");
|
||||
return ESP_OK;
|
||||
}
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
static esp_err_t secure_boot_v2_digest_generate(uint32_t flash_offset, uint32_t flash_size, uint8_t *public_key_digest)
|
||||
{
|
||||
esp_err_t ret = ESP_FAIL;
|
||||
|
||||
uint8_t image_digest[DIGEST_LEN] = {0};
|
||||
size_t sig_block_addr = flash_offset + ALIGN_UP(flash_size, FLASH_SECTOR_SIZE);
|
||||
ret = bootloader_sha256_flash_contents(flash_offset, sig_block_addr - flash_offset, image_digest);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "error generating image digest, %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG, "reading signature block");
|
||||
const ets_secure_boot_signature_t *sig_block = bootloader_mmap(sig_block_addr, sizeof(ets_secure_boot_signature_t));
|
||||
if (sig_block == NULL) {
|
||||
ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", sig_block_addr, sizeof(ets_secure_boot_signature_t));
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Validating Signature block */
|
||||
ret = validate_signature_block(sig_block, image_digest);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "signature block (address 0x%x) validation failed %d", sig_block_addr, ret);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Verifying Signature block */
|
||||
uint8_t verified_digest[DIGEST_LEN] = {0};
|
||||
|
||||
/* Generating the SHA of the public key components in the signature block */
|
||||
bootloader_sha256_handle_t sig_block_sha;
|
||||
sig_block_sha = bootloader_sha256_start();
|
||||
bootloader_sha256_data(sig_block_sha, &sig_block->block[0].key, sizeof(sig_block->block[0].key));
|
||||
bootloader_sha256_finish(sig_block_sha, public_key_digest);
|
||||
|
||||
secure_boot_v2_status_t error;
|
||||
error = ets_secure_boot_verify_signature(sig_block, image_digest, public_key_digest, verified_digest);
|
||||
if (error != SBV2_SUCCESS) {
|
||||
ESP_LOGE(TAG, "secure boot v2 verification failed %d", error);
|
||||
ret = ESP_FAIL;
|
||||
goto done;
|
||||
} else {
|
||||
ret = ESP_OK;
|
||||
}
|
||||
|
||||
done:
|
||||
bootloader_munmap(sig_block);
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t esp_secure_boot_v2_permanently_enable(const esp_image_metadata_t *image_data)
|
||||
{
|
||||
uint32_t new_wdata0 = 0;
|
||||
uint32_t new_wdata6 = 0;
|
||||
|
||||
ESP_LOGI(TAG, "enabling secure boot v2...");
|
||||
esp_err_t ret;
|
||||
if (esp_secure_boot_enabled()) {
|
||||
ESP_LOGI(TAG, "secure boot v2 is already enabled. Continuing..");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
uint32_t coding_scheme = REG_GET_FIELD(EFUSE_BLK0_RDATA6_REG, EFUSE_CODING_SCHEME);
|
||||
if (coding_scheme != EFUSE_CODING_SCHEME_VAL_NONE) {
|
||||
ESP_LOGE(TAG, "No coding schemes are supported in secure boot v2.(Detected scheme: 0x%x)", coding_scheme);
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
/* Verify the bootloader */
|
||||
esp_image_metadata_t bootloader_data = { 0 };
|
||||
ret = esp_image_verify_bootloader_data(&bootloader_data);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "bootloader image appears invalid! error %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint8_t boot_pub_key_digest[DIGEST_LEN];
|
||||
uint32_t dis_reg = REG_READ(EFUSE_BLK0_RDATA0_REG);
|
||||
bool efuse_key_read_protected = dis_reg & EFUSE_RD_DIS_BLK2;
|
||||
bool efuse_key_write_protected = dis_reg & EFUSE_WR_DIS_BLK2;
|
||||
if (efuse_key_write_protected == false
|
||||
&& efuse_key_read_protected == false
|
||||
&& REG_READ(EFUSE_BLK2_RDATA0_REG) == 0
|
||||
&& REG_READ(EFUSE_BLK2_RDATA1_REG) == 0
|
||||
&& REG_READ(EFUSE_BLK2_RDATA2_REG) == 0
|
||||
&& REG_READ(EFUSE_BLK2_RDATA3_REG) == 0
|
||||
&& REG_READ(EFUSE_BLK2_RDATA4_REG) == 0
|
||||
&& REG_READ(EFUSE_BLK2_RDATA5_REG) == 0
|
||||
&& REG_READ(EFUSE_BLK2_RDATA6_REG) == 0
|
||||
&& REG_READ(EFUSE_BLK2_RDATA7_REG) == 0) {
|
||||
/* Verifies the signature block appended to the image matches with the signature block of the app to be loaded */
|
||||
ret = secure_boot_v2_digest_generate(bootloader_data.start_addr, bootloader_data.image_len - SIG_BLOCK_PADDING, boot_pub_key_digest);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Public key digest generation failed");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Burning public key hash to efuse.");
|
||||
uint32_t *boot_public_key_digest_ptr = (uint32_t *) boot_pub_key_digest;
|
||||
for (int i = 0; i < 8 ; i++) {
|
||||
REG_WRITE(EFUSE_BLK2_WDATA0_REG + 4 * i, boot_public_key_digest_ptr[i]);
|
||||
ESP_LOGD(TAG, "EFUSE_BLKx_WDATA%d_REG = 0x%08x", i, boot_public_key_digest_ptr[i]);
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Write protecting public key digest...");
|
||||
new_wdata0 |= EFUSE_WR_DIS_BLK2;
|
||||
efuse_key_write_protected = true;
|
||||
efuse_key_read_protected = false;
|
||||
} else {
|
||||
ESP_LOGW(TAG, "Using pre-loaded secure boot v2 public key digest in EFUSE block 2");
|
||||
}
|
||||
|
||||
uint8_t app_pub_key_digest[DIGEST_LEN];
|
||||
ret = secure_boot_v2_digest_generate(image_data->start_addr, image_data->image_len - SIG_BLOCK_PADDING, app_pub_key_digest);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Application signature block is invalid.");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Confirming if the public key in the bootloader's signature block matches with the one in the application's signature block */
|
||||
if (memcmp(boot_pub_key_digest, app_pub_key_digest, DIGEST_LEN) != 0) {
|
||||
ESP_LOGE(TAG, "Application not signed with a valid private key.");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
if (efuse_key_read_protected) {
|
||||
ESP_LOGE(TAG, "Efuse BLK2 (public key digest) is read protected. Refusing to blow secure boot efuse.");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
if (!efuse_key_write_protected) {
|
||||
ESP_LOGE(TAG, "Efuse BLK2 (public key digest) is not write protected. Refusing to blow secure boot efuse.");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "blowing secure boot efuse...");
|
||||
ESP_LOGD(TAG, "before updating, EFUSE_BLK0_RDATA6 %x", REG_READ(EFUSE_BLK0_RDATA6_REG));
|
||||
|
||||
new_wdata6 |= EFUSE_RD_ABS_DONE_1;
|
||||
|
||||
#ifndef CONFIG_SECURE_BOOT_ALLOW_JTAG
|
||||
ESP_LOGI(TAG, "Disable JTAG...");
|
||||
new_wdata6 |= EFUSE_RD_DISABLE_JTAG;
|
||||
#else
|
||||
ESP_LOGW(TAG, "Not disabling JTAG - SECURITY COMPROMISED");
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_SECURE_BOOT_ALLOW_ROM_BASIC
|
||||
ESP_LOGI(TAG, "Disable ROM BASIC interpreter fallback...");
|
||||
new_wdata6 |= EFUSE_RD_CONSOLE_DEBUG_DISABLE;
|
||||
#else
|
||||
ESP_LOGW(TAG, "Not disabling ROM BASIC fallback - SECURITY COMPROMISED");
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_SECURE_BOOT_V2_ALLOW_EFUSE_RD_DIS
|
||||
bool rd_dis_now = true;
|
||||
#ifdef CONFIG_SECURE_FLASH_ENC_ENABLED
|
||||
/* If flash encryption is not enabled yet then don't read-disable efuses yet, do it later in the boot
|
||||
when Flash Encryption is being enabled */
|
||||
rd_dis_now = esp_flash_encryption_enabled();
|
||||
#endif
|
||||
if (rd_dis_now) {
|
||||
ESP_LOGI(TAG, "Prevent read disabling of additional efuses...");
|
||||
new_wdata0 |= EFUSE_WR_DIS_RD_DIS;
|
||||
}
|
||||
#else
|
||||
ESP_LOGW(TAG, "Allowing read disabling of additional efuses - SECURITY COMPROMISED");
|
||||
#endif
|
||||
|
||||
REG_WRITE(EFUSE_BLK0_WDATA0_REG, new_wdata0);
|
||||
REG_WRITE(EFUSE_BLK0_WDATA6_REG, new_wdata6);
|
||||
esp_efuse_burn_new_values();
|
||||
uint32_t after = REG_READ(EFUSE_BLK0_RDATA6_REG);
|
||||
ESP_LOGD(TAG, "after updating, EFUSE_BLK0_RDATA0 0x%08x EFUSE_BLK0_RDATA6 0x%08x",
|
||||
REG_READ(EFUSE_BLK0_RDATA0_REG), after);
|
||||
if (after & EFUSE_RD_ABS_DONE_1) {
|
||||
ESP_LOGI(TAG, "secure boot v2 is now enabled.");
|
||||
return ESP_OK;
|
||||
} else {
|
||||
ESP_LOGE(TAG, " secure boot v2 not enabled, EFUSE_RD_ABS_DONE_1 is probably write protected!");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // CONFIG_SECURE_BOOT_V2_ENABLED
|
||||
|
||||
@@ -15,62 +15,40 @@
|
||||
|
||||
#include "bootloader_flash.h"
|
||||
#include "bootloader_sha.h"
|
||||
#include "bootloader_utility.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_image_format.h"
|
||||
#include "esp_secure_boot.h"
|
||||
#include "esp_spi_flash.h"
|
||||
#include "esp_fault.h"
|
||||
#include "esp32/rom/sha.h"
|
||||
#include "uECC.h"
|
||||
#include "uECC_verify_antifault.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <string.h>
|
||||
|
||||
static const char *TAG = "secure_boot";
|
||||
#define DIGEST_LEN 32
|
||||
|
||||
#ifdef CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME
|
||||
extern const uint8_t signature_verification_key_start[] asm("_binary_signature_verification_key_bin_start");
|
||||
extern const uint8_t signature_verification_key_end[] asm("_binary_signature_verification_key_bin_end");
|
||||
|
||||
#define SIGNATURE_VERIFICATION_KEYLEN 64
|
||||
|
||||
#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)
|
||||
{
|
||||
uint8_t digest[DIGEST_LEN];
|
||||
const uint8_t *data;
|
||||
uint8_t verified_digest[DIGEST_LEN] = { 0 }; /* ignored in this function */
|
||||
const esp_secure_boot_sig_block_t *sigblock;
|
||||
|
||||
ESP_LOGD(TAG, "verifying signature src_addr 0x%x length 0x%x", src_addr, length);
|
||||
|
||||
bootloader_sha256_handle_t handle = bootloader_sha256_start();
|
||||
|
||||
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;
|
||||
}
|
||||
bootloader_sha256_data(handle, data, data_len);
|
||||
bootloader_munmap(data);
|
||||
|
||||
data_addr += data_len;
|
||||
data_len_remain -= data_len;
|
||||
esp_err_t err = bootloader_sha256_flash_contents(src_addr, length, digest);
|
||||
if (err != ESP_OK) {
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Done! Get the digest */
|
||||
bootloader_sha256_finish(handle, digest);
|
||||
|
||||
// Map the signature block
|
||||
sigblock = (const esp_secure_boot_sig_block_t *) bootloader_mmap(src_addr + length, sizeof(esp_secure_boot_sig_block_t));
|
||||
if(!sigblock) {
|
||||
@@ -78,7 +56,7 @@ esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length)
|
||||
return ESP_FAIL;
|
||||
}
|
||||
// Verify the signature
|
||||
esp_err_t err = esp_secure_boot_verify_signature_block(sigblock, digest);
|
||||
err = esp_secure_boot_verify_ecdsa_signature_block(sigblock, digest, verified_digest);
|
||||
// Unmap
|
||||
bootloader_munmap(sigblock);
|
||||
|
||||
@@ -86,6 +64,12 @@ esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length)
|
||||
}
|
||||
|
||||
esp_err_t esp_secure_boot_verify_signature_block(const esp_secure_boot_sig_block_t *sig_block, const uint8_t *image_digest)
|
||||
{
|
||||
uint8_t verified_digest[DIGEST_LEN] = { 0 };
|
||||
return esp_secure_boot_verify_ecdsa_signature_block(sig_block, image_digest, verified_digest);
|
||||
}
|
||||
|
||||
esp_err_t esp_secure_boot_verify_ecdsa_signature_block(const esp_secure_boot_sig_block_t *sig_block, const uint8_t *image_digest, uint8_t *verified_digest)
|
||||
{
|
||||
ptrdiff_t keylen;
|
||||
|
||||
@@ -103,11 +87,98 @@ esp_err_t esp_secure_boot_verify_signature_block(const esp_secure_boot_sig_block
|
||||
ESP_LOGD(TAG, "Verifying secure boot signature");
|
||||
|
||||
bool is_valid;
|
||||
is_valid = uECC_verify(signature_verification_key_start,
|
||||
is_valid = uECC_verify_antifault(signature_verification_key_start,
|
||||
image_digest,
|
||||
DIGEST_LEN,
|
||||
sig_block->signature,
|
||||
uECC_secp256r1());
|
||||
uECC_secp256r1(),
|
||||
verified_digest);
|
||||
ESP_LOGD(TAG, "Verification result %d", is_valid);
|
||||
|
||||
return is_valid ? ESP_OK : ESP_ERR_IMAGE_INVALID;
|
||||
}
|
||||
|
||||
#elif CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME
|
||||
#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
|
||||
|
||||
esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length)
|
||||
{
|
||||
uint8_t digest[DIGEST_LEN] = {0};
|
||||
uint8_t verified_digest[DIGEST_LEN] = {0}; // ignored in this function
|
||||
const uint8_t *data;
|
||||
|
||||
/* Padding to round off the input to the nearest 4k boundary */
|
||||
int padded_length = ALIGN_UP(length, FLASH_SECTOR_SIZE);
|
||||
ESP_LOGD(TAG, "verifying src_addr 0x%x length", src_addr, padded_length);
|
||||
|
||||
data = bootloader_mmap(src_addr, padded_length + sizeof(ets_secure_boot_signature_t));
|
||||
if (data == NULL) {
|
||||
ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", src_addr, padded_length);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
/* Calculate digest of main image */
|
||||
esp_err_t err = bootloader_sha256_flash_contents(src_addr, padded_length, digest);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Digest calculation failed 0x%x, 0x%x", src_addr, padded_length);
|
||||
bootloader_munmap(data);
|
||||
return err;
|
||||
}
|
||||
|
||||
const ets_secure_boot_signature_t *sig_block = (const ets_secure_boot_signature_t *)(data + padded_length);
|
||||
err = esp_secure_boot_verify_rsa_signature_block(sig_block, digest, verified_digest);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Secure Boot V2 verification failed.");
|
||||
}
|
||||
|
||||
bootloader_munmap(data);
|
||||
return err;
|
||||
}
|
||||
|
||||
esp_err_t esp_secure_boot_verify_rsa_signature_block(const ets_secure_boot_signature_t *sig_block, const uint8_t *image_digest, uint8_t *verified_digest)
|
||||
{
|
||||
secure_boot_v2_status_t r;
|
||||
uint8_t efuse_trusted_digest[DIGEST_LEN] = {0}, sig_block_trusted_digest[DIGEST_LEN] = {0};
|
||||
|
||||
memcpy(efuse_trusted_digest, (uint8_t *)EFUSE_BLK2_RDATA0_REG, DIGEST_LEN); /* EFUSE_BLK2_RDATA0_REG - Stores the Secure Boot Public Key Digest */
|
||||
|
||||
if (!ets_use_secure_boot_v2()) {
|
||||
ESP_LOGI(TAG, "Secure Boot eFuse bit(ABS_DONE_1) not yet programmed.");
|
||||
|
||||
/* Generating the SHA of the public key components in the signature block */
|
||||
bootloader_sha256_handle_t sig_block_sha;
|
||||
sig_block_sha = bootloader_sha256_start();
|
||||
bootloader_sha256_data(sig_block_sha, &sig_block->block[0].key, sizeof(sig_block->block[0].key));
|
||||
bootloader_sha256_finish(sig_block_sha, (unsigned char *)sig_block_trusted_digest);
|
||||
|
||||
#if CONFIG_SECURE_BOOT_V2_ENABLED
|
||||
if (memcmp(efuse_trusted_digest, sig_block_trusted_digest, DIGEST_LEN) != 0) {
|
||||
/* Most likely explanation for this is that BLK2 is empty, and we're going to burn it
|
||||
after we verify that the signature is valid. However, if BLK2 is not empty then we need to
|
||||
fail here.
|
||||
*/
|
||||
bool all_zeroes = true;
|
||||
for (int i = 0; i < DIGEST_LEN; i++) {
|
||||
all_zeroes = all_zeroes && (efuse_trusted_digest[i] == 0);
|
||||
}
|
||||
if (!all_zeroes) {
|
||||
ESP_LOGE(TAG, "Different public key digest burned to eFuse BLK2");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
}
|
||||
|
||||
ESP_FAULT_ASSERT(!ets_use_secure_boot_v2());
|
||||
#endif
|
||||
|
||||
memcpy(efuse_trusted_digest, sig_block_trusted_digest, DIGEST_LEN);
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Verifying with RSA-PSS...");
|
||||
r = ets_secure_boot_verify_signature(sig_block, image_digest, efuse_trusted_digest, verified_digest);
|
||||
if (r != SBV2_SUCCESS) {
|
||||
ESP_LOGE(TAG, "Secure Boot V2 verification failed.");
|
||||
}
|
||||
|
||||
return (r == SBV2_SUCCESS) ? ESP_OK : ESP_ERR_IMAGE_INVALID;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
#include "esp_log.h"
|
||||
#include "esp32s2beta/rom/secure_boot.h"
|
||||
|
||||
#define TAG "secure_boot"
|
||||
static const char *TAG = "secure_boot";
|
||||
|
||||
esp_err_t esp_secure_boot_permanently_enable(void)
|
||||
{
|
||||
|
||||
@@ -27,6 +27,7 @@ esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length)
|
||||
{
|
||||
ets_secure_boot_key_digests_t trusted_keys = { 0 };
|
||||
uint8_t digest[DIGEST_LEN];
|
||||
uint8_t verified_digest[DIGEST_LEN] = { 0 }; /* Note: this function doesn't do any anti-FI checks on this buffer */
|
||||
const uint8_t *data;
|
||||
|
||||
ESP_LOGD(TAG, "verifying signature src_addr 0x%x length 0x%x", src_addr, length);
|
||||
@@ -37,7 +38,7 @@ esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length)
|
||||
}
|
||||
|
||||
data = bootloader_mmap(src_addr, length + sizeof(struct ets_secure_boot_sig_block));
|
||||
if(data == NULL) {
|
||||
if (data == NULL) {
|
||||
ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", src_addr, length+sizeof(ets_secure_boot_signature_t));
|
||||
return ESP_FAIL;
|
||||
}
|
||||
@@ -57,36 +58,25 @@ esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length)
|
||||
if (r == ETS_OK) {
|
||||
const ets_secure_boot_signature_t *sig = (const ets_secure_boot_signature_t *)(data + length);
|
||||
// TODO: calling this function in IDF app context is unsafe
|
||||
r = ets_secure_boot_verify_signature(sig, digest, &trusted_keys);
|
||||
r = ets_secure_boot_verify_signature(sig, digest, &trusted_keys, verified_digest);
|
||||
}
|
||||
bootloader_munmap(data);
|
||||
|
||||
return (r == ETS_OK) ? ESP_OK : ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_err_t esp_secure_boot_verify_signature_block(uint32_t sig_block_flash_offs, const uint8_t *image_digest)
|
||||
esp_err_t esp_secure_boot_verify_rsa_signature_block(const ets_secure_boot_signature_t *sig_block, const uint8_t *image_digest, uint8_t *verified_digest)
|
||||
{
|
||||
ets_secure_boot_key_digests_t trusted_keys;
|
||||
|
||||
assert(sig_block_flash_offs % 4096 == 0); // TODO: enforce this in a better way
|
||||
|
||||
const ets_secure_boot_signature_t *sig = bootloader_mmap(sig_block_flash_offs, sizeof(ets_secure_boot_signature_t));
|
||||
|
||||
if (sig == NULL) {
|
||||
ESP_LOGE(TAG, "Failed to mmap data at offset 0x%x", sig_block_flash_offs);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
int r = ets_secure_boot_read_key_digests(&trusted_keys);
|
||||
if (r != 0) {
|
||||
ESP_LOGE(TAG, "No trusted key digests were found in efuse!");
|
||||
} else {
|
||||
ESP_LOGD(TAG, "Verifying with RSA-PSS...");
|
||||
// TODO: calling this function in IDF app context is unsafe
|
||||
r = ets_secure_boot_verify_signature(sig, image_digest, &trusted_keys);
|
||||
r = ets_secure_boot_verify_signature(sig_block, image_digest, &trusted_keys, verified_digest);
|
||||
}
|
||||
|
||||
bootloader_munmap(sig);
|
||||
|
||||
return (r == 0) ? ESP_OK : ESP_ERR_IMAGE_INVALID;
|
||||
}
|
||||
|
||||
@@ -16,13 +16,16 @@
|
||||
#include <soc/cpu.h>
|
||||
#include <bootloader_utility.h>
|
||||
#include <esp_secure_boot.h>
|
||||
#include <esp_fault.h>
|
||||
#include <esp_log.h>
|
||||
#include <esp_attr.h>
|
||||
#include <esp_spi_flash.h>
|
||||
#include <bootloader_flash.h>
|
||||
#include <bootloader_random.h>
|
||||
#include <bootloader_sha.h>
|
||||
#include "bootloader_util.h"
|
||||
#include "bootloader_common.h"
|
||||
#include "soc/soc_memory_layout.h"
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#include <esp32/rom/rtc.h>
|
||||
#include <esp32/rom/secure_boot.h>
|
||||
@@ -37,11 +40,11 @@
|
||||
*/
|
||||
#ifdef BOOTLOADER_BUILD
|
||||
#ifdef CONFIG_SECURE_SIGNED_ON_BOOT
|
||||
#define SECURE_BOOT_CHECK_SIGNATURE
|
||||
#define SECURE_BOOT_CHECK_SIGNATURE 1
|
||||
#endif
|
||||
#else /* !BOOTLOADER_BUILD */
|
||||
#ifdef CONFIG_SECURE_SIGNED_ON_UPDATE
|
||||
#define SECURE_BOOT_CHECK_SIGNATURE
|
||||
#define SECURE_BOOT_CHECK_SIGNATURE 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -55,18 +58,12 @@ static const char *TAG = "esp_image";
|
||||
/* Headroom to ensure between stack SP (at time of checking) and data loaded from flash */
|
||||
#define STACK_LOAD_HEADROOM 32768
|
||||
|
||||
/* Mmap source address mask */
|
||||
#define MMAP_ALIGNED_MASK 0x0000FFFF
|
||||
|
||||
#ifdef BOOTLOADER_BUILD
|
||||
/* 64 bits of random data to obfuscate loaded RAM with, until verification is complete
|
||||
(Means loaded code isn't executable until after the secure boot check.)
|
||||
*/
|
||||
static uint32_t ram_obfs_value[2];
|
||||
|
||||
/* Range of IRAM used by the loader, defined in ld script */
|
||||
extern int _loader_text_start;
|
||||
extern int _loader_text_end;
|
||||
#endif
|
||||
|
||||
/* Return true if load_addr is an address the bootloader should load into */
|
||||
@@ -97,7 +94,7 @@ static esp_err_t verify_segment_header(int index, const esp_image_segment_header
|
||||
|
||||
static esp_err_t verify_checksum(bootloader_sha256_handle_t sha_handle, uint32_t checksum_word, esp_image_metadata_t *data);
|
||||
|
||||
static esp_err_t __attribute__((unused)) verify_secure_boot_signature(bootloader_sha256_handle_t sha_handle, esp_image_metadata_t *data);
|
||||
static esp_err_t __attribute__((unused)) verify_secure_boot_signature(bootloader_sha256_handle_t sha_handle, esp_image_metadata_t *data, uint8_t *image_digest, uint8_t *verified_digest);
|
||||
static esp_err_t __attribute__((unused)) verify_simple_hash(bootloader_sha256_handle_t sha_handle, esp_image_metadata_t *data);
|
||||
|
||||
static esp_err_t image_load(esp_image_load_mode_t mode, const esp_partition_pos_t *part, esp_image_metadata_t *data)
|
||||
@@ -115,6 +112,11 @@ static esp_err_t image_load(esp_image_load_mode_t mode, const esp_partition_pos_
|
||||
uint32_t checksum_word = ESP_ROM_CHECKSUM_INITIAL;
|
||||
uint32_t *checksum = NULL;
|
||||
bootloader_sha256_handle_t sha_handle = NULL;
|
||||
#if SECURE_BOOT_CHECK_SIGNATURE
|
||||
/* used for anti-FI checks */
|
||||
uint8_t image_digest[HASH_LEN] = { [ 0 ... 31] = 0xEE };
|
||||
uint8_t verified_digest[HASH_LEN] = { [ 0 ... 31 ] = 0x01 };
|
||||
#endif
|
||||
|
||||
if (data == NULL || part == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
@@ -172,6 +174,7 @@ static esp_err_t image_load(esp_image_load_mode_t mode, const esp_partition_pos_
|
||||
for (int i = 0; i < data->image.segment_count; i++) {
|
||||
esp_image_segment_header_t *header = &data->segments[i];
|
||||
ESP_LOGV(TAG, "loading segment header %d at offset 0x%x", i, next_addr);
|
||||
|
||||
err = process_segment(i, next_addr, header, silent, do_load, sha_handle, checksum);
|
||||
if (err != ESP_OK) {
|
||||
goto err;
|
||||
@@ -197,14 +200,14 @@ static esp_err_t image_load(esp_image_load_mode_t mode, const esp_partition_pos_
|
||||
}
|
||||
}
|
||||
|
||||
/* For secure boot on ESP32, we don't calculate SHA or verify signautre on bootloaders.
|
||||
For ESP32S2, we do verify signature on botoloaders which includes the SHA calculation.
|
||||
/* For secure boot V1 on ESP32, we don't calculate SHA or verify signature on bootloaders.
|
||||
For Secure Boot V2, we do verify signature on bootloader which includes the SHA calculation.
|
||||
|
||||
(For non-secure boot, we don't verify any SHA-256 hash appended to the bootloader because
|
||||
esptool.py may have rewritten the header - rely on esptool.py having verified the bootloader at flashing time, instead.)
|
||||
*/
|
||||
bool verify_sha;
|
||||
#if defined(CONFIG_SECURE_BOOT_ENABLED) && defined(CONFIG_IDF_TARGET_ESP32S2BETA)
|
||||
#if CONFIG_SECURE_BOOT_V2_ENABLED
|
||||
verify_sha = true;
|
||||
#else // ESP32, or ESP32S2 without secure boot enabled
|
||||
verify_sha = (data->start_addr != ESP_BOOTLOADER_OFFSET);
|
||||
@@ -217,7 +220,7 @@ static esp_err_t image_load(esp_image_load_mode_t mode, const esp_partition_pos_
|
||||
|
||||
#ifdef SECURE_BOOT_CHECK_SIGNATURE
|
||||
// secure boot images have a signature appended
|
||||
err = verify_secure_boot_signature(sha_handle, data);
|
||||
err = verify_secure_boot_signature(sha_handle, data, image_digest, verified_digest);
|
||||
#else
|
||||
// No secure boot, but SHA-256 can be appended for basic corruption detection
|
||||
if (sha_handle != NULL && !esp_cpu_in_ocd_debug_mode()) {
|
||||
@@ -250,7 +253,28 @@ static esp_err_t image_load(esp_image_load_mode_t mode, const esp_partition_pos_
|
||||
}
|
||||
|
||||
#ifdef BOOTLOADER_BUILD
|
||||
if (do_load && ram_obfs_value[0] != 0 && ram_obfs_value[1] != 0) { // Need to deobfuscate RAM
|
||||
|
||||
#ifdef SECURE_BOOT_CHECK_SIGNATURE
|
||||
/* If signature was checked in bootloader build, verified_digest should equal image_digest
|
||||
|
||||
This is to detect any fault injection that caused signature verification to not complete normally.
|
||||
|
||||
Any attack which bypasses this check should be of limited use as the RAM contents are still obfuscated, therefore we do the check
|
||||
immediately before we deobfuscate.
|
||||
|
||||
Note: the conditions for making this check are the same as for setting verify_sha above, but on ESP32 SB V1 we move the test for
|
||||
"only verify signature in bootloader" into the macro so it's tested multiple times.
|
||||
*/
|
||||
#if CONFIG_SECURE_BOOT_V2_ENABLED
|
||||
ESP_FAULT_ASSERT(memcmp(image_digest, verified_digest, HASH_LEN) == 0);
|
||||
#else // Secure Boot V1 on ESP32, only verify signatures for apps not bootloaders
|
||||
ESP_FAULT_ASSERT(data->start_addr == ESP_BOOTLOADER_OFFSET || memcmp(image_digest, verified_digest, HASH_LEN) == 0);
|
||||
#endif
|
||||
|
||||
#endif // SECURE_BOOT_CHECK_SIGNATURE
|
||||
|
||||
// Deobfuscate RAM
|
||||
if (do_load && ram_obfs_value[0] != 0 && ram_obfs_value[1] != 0) {
|
||||
for (int i = 0; i < data->image.segment_count; i++) {
|
||||
uint32_t load_addr = data->segments[i].load_addr;
|
||||
if (should_load(load_addr)) {
|
||||
@@ -336,6 +360,127 @@ static esp_err_t verify_image_header(uint32_t src_addr, const esp_image_header_t
|
||||
return err;
|
||||
}
|
||||
|
||||
#ifdef BOOTLOADER_BUILD
|
||||
/* Check the region load_addr - load_end doesn't overlap any memory used by the bootloader, registers, or other invalid memory
|
||||
*/
|
||||
static bool verify_load_addresses(int segment_index, intptr_t load_addr, intptr_t load_end, bool print_error, bool no_recurse)
|
||||
{
|
||||
/* Addresses of static data and the "loader" section of bootloader IRAM, all defined in ld script */
|
||||
const char *reason = NULL;
|
||||
extern int _dram_start, _dram_end, _loader_text_start, _loader_text_end;
|
||||
void *load_addr_p = (void *)load_addr;
|
||||
void *load_end_p = (void *)load_end;
|
||||
|
||||
if (load_end == load_addr) {
|
||||
return true; // zero-length segments are fine
|
||||
}
|
||||
assert(load_end > load_addr); // data_len<16MB is checked in verify_segment_header() which is called before this, so this should always be true
|
||||
|
||||
if (esp_ptr_in_dram(load_addr_p) && esp_ptr_in_dram(load_end_p)) { /* Writing to DRAM */
|
||||
/* Check if we're clobbering the stack */
|
||||
intptr_t sp = (intptr_t)get_sp();
|
||||
if (bootloader_util_regions_overlap(sp - STACK_LOAD_HEADROOM, SOC_ROM_STACK_START,
|
||||
load_addr, load_end)) {
|
||||
reason = "overlaps bootloader stack";
|
||||
goto invalid;
|
||||
}
|
||||
|
||||
/* Check if we're clobbering static data
|
||||
|
||||
(_dram_start.._dram_end includes bss, data, rodata sections in DRAM)
|
||||
*/
|
||||
if (bootloader_util_regions_overlap((intptr_t)&_dram_start, (intptr_t)&_dram_end, load_addr, load_end)) {
|
||||
reason = "overlaps bootloader data";
|
||||
goto invalid;
|
||||
}
|
||||
|
||||
/* LAST DRAM CHECK (recursive): for D/IRAM, check the equivalent IRAM addresses if needed
|
||||
|
||||
Allow for the possibility that even though both pointers are IRAM, only part of the region is in a D/IRAM
|
||||
section. In which case we recurse to check the part which falls in D/IRAM.
|
||||
|
||||
Note: We start with SOC_DIRAM_DRAM_LOW/HIGH and convert that address to IRAM to account for any reversing of word order
|
||||
(chip-specific).
|
||||
*/
|
||||
if (!no_recurse && bootloader_util_regions_overlap(SOC_DIRAM_DRAM_LOW, SOC_DIRAM_DRAM_HIGH, load_addr, load_end)) {
|
||||
intptr_t iram_load_addr, iram_load_end;
|
||||
|
||||
if (esp_ptr_in_diram_dram(load_addr_p)) {
|
||||
iram_load_addr = (intptr_t)esp_ptr_diram_dram_to_iram(load_addr_p);
|
||||
} else {
|
||||
iram_load_addr = (intptr_t)esp_ptr_diram_dram_to_iram((void *)SOC_DIRAM_DRAM_LOW);
|
||||
}
|
||||
|
||||
if (esp_ptr_in_diram_dram(load_end_p)) {
|
||||
iram_load_end = (intptr_t)esp_ptr_diram_dram_to_iram(load_end_p);
|
||||
} else {
|
||||
iram_load_end = (intptr_t)esp_ptr_diram_dram_to_iram((void *)SOC_DIRAM_DRAM_HIGH);
|
||||
}
|
||||
|
||||
if (iram_load_end < iram_load_addr) {
|
||||
return verify_load_addresses(segment_index, iram_load_end, iram_load_addr, print_error, true);
|
||||
} else {
|
||||
return verify_load_addresses(segment_index, iram_load_addr, iram_load_end, print_error, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (esp_ptr_in_iram(load_addr_p) && esp_ptr_in_iram(load_end_p)) { /* Writing to IRAM */
|
||||
/* Check for overlap of 'loader' section of IRAM */
|
||||
if (bootloader_util_regions_overlap((intptr_t)&_loader_text_start, (intptr_t)&_loader_text_end,
|
||||
load_addr, load_end)) {
|
||||
reason = "overlaps loader IRAM";
|
||||
goto invalid;
|
||||
}
|
||||
|
||||
/* LAST IRAM CHECK (recursive): for D/IRAM, check the equivalent DRAM address if needed
|
||||
|
||||
Allow for the possibility that even though both pointers are IRAM, only part of the region is in a D/IRAM
|
||||
section. In which case we recurse to check the part which falls in D/IRAM.
|
||||
Note: We start with SOC_DIRAM_IRAM_LOW/HIGH and convert that address to DRAM to account for any reversing of word order
|
||||
(chip-specific).
|
||||
*/
|
||||
if (!no_recurse && bootloader_util_regions_overlap(SOC_DIRAM_IRAM_LOW, SOC_DIRAM_IRAM_HIGH, load_addr, load_end)) {
|
||||
intptr_t dram_load_addr, dram_load_end;
|
||||
|
||||
if (esp_ptr_in_diram_iram(load_addr_p)) {
|
||||
dram_load_addr = (intptr_t)esp_ptr_diram_iram_to_dram(load_addr_p);
|
||||
} else {
|
||||
dram_load_addr = (intptr_t)esp_ptr_diram_iram_to_dram((void *)SOC_DIRAM_IRAM_LOW);
|
||||
}
|
||||
|
||||
if (esp_ptr_in_diram_iram(load_end_p)) {
|
||||
dram_load_end = (intptr_t)esp_ptr_diram_iram_to_dram(load_end_p);
|
||||
} else {
|
||||
dram_load_end = (intptr_t)esp_ptr_diram_iram_to_dram((void *)SOC_DIRAM_IRAM_HIGH);
|
||||
}
|
||||
|
||||
if (dram_load_end < dram_load_addr) {
|
||||
return verify_load_addresses(segment_index, dram_load_end, dram_load_addr, print_error, true);
|
||||
} else {
|
||||
return verify_load_addresses(segment_index, dram_load_addr, dram_load_end, print_error, true);
|
||||
}
|
||||
}
|
||||
/* Sections entirely in RTC memory won't overlap with a vanilla bootloader but are valid load addresses, thus skipping them from the check */
|
||||
} else if (esp_ptr_in_rtc_iram_fast(load_addr_p) && esp_ptr_in_rtc_iram_fast(load_end_p)){
|
||||
return true;
|
||||
} else if (esp_ptr_in_rtc_dram_fast(load_addr_p) && esp_ptr_in_rtc_dram_fast(load_end_p)){
|
||||
return true;
|
||||
} else if (esp_ptr_in_rtc_slow(load_addr_p) && esp_ptr_in_rtc_slow(load_end_p)) {
|
||||
return true;
|
||||
} else { /* Not a DRAM or an IRAM or RTC Fast IRAM, RTC Fast DRAM or RTC Slow address */
|
||||
reason = "bad load address range";
|
||||
goto invalid;
|
||||
}
|
||||
return true;
|
||||
|
||||
invalid:
|
||||
if (print_error) {
|
||||
ESP_LOGE(TAG, "Segment %d 0x%08x-0x%08x invalid: %s", segment_index, load_addr, load_end, reason);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif // BOOTLOADER_BUILD
|
||||
|
||||
static esp_err_t process_segment(int index, uint32_t flash_addr, esp_image_segment_header_t *header, bool silent, bool do_load, bootloader_sha256_handle_t sha_handle, uint32_t *checksum)
|
||||
{
|
||||
esp_err_t err;
|
||||
@@ -378,34 +523,9 @@ static esp_err_t process_segment(int index, uint32_t flash_addr, esp_image_segme
|
||||
|
||||
#ifdef BOOTLOADER_BUILD
|
||||
/* Before loading segment, check it doesn't clobber bootloader RAM. */
|
||||
if (do_load) {
|
||||
const intptr_t load_end = load_addr + data_len;
|
||||
if (load_end < (intptr_t) SOC_DRAM_HIGH) {
|
||||
/* Writing to DRAM */
|
||||
intptr_t sp = (intptr_t)get_sp();
|
||||
if (load_end > sp - STACK_LOAD_HEADROOM) {
|
||||
/* Bootloader .data/.rodata/.bss is above the stack, so this
|
||||
* also checks that we aren't overwriting these segments.
|
||||
*
|
||||
* TODO: This assumes specific arrangement of sections we have
|
||||
* in the ESP32. Rewrite this in a generic way to support other
|
||||
* layouts.
|
||||
*/
|
||||
ESP_LOGE(TAG, "Segment %d end address 0x%08x too high (bootloader stack 0x%08x limit 0x%08x)",
|
||||
index, load_end, sp, sp - STACK_LOAD_HEADROOM);
|
||||
return ESP_ERR_IMAGE_INVALID;
|
||||
}
|
||||
} else {
|
||||
/* Writing to IRAM */
|
||||
const intptr_t loader_iram_start = (intptr_t) &_loader_text_start;
|
||||
const intptr_t loader_iram_end = (intptr_t) &_loader_text_end;
|
||||
|
||||
if (bootloader_util_regions_overlap(loader_iram_start, loader_iram_end,
|
||||
load_addr, load_end)) {
|
||||
ESP_LOGE(TAG, "Segment %d (0x%08x-0x%08x) overlaps bootloader IRAM (0x%08x-0x%08x)",
|
||||
index, load_addr, load_end, loader_iram_start, loader_iram_end);
|
||||
return ESP_ERR_IMAGE_INVALID;
|
||||
}
|
||||
if (do_load && data_len > 0) {
|
||||
if (!verify_load_addresses(index, load_addr, load_addr + data_len, true, false)) {
|
||||
return ESP_ERR_IMAGE_INVALID;
|
||||
}
|
||||
}
|
||||
#endif // BOOTLOADER_BUILD
|
||||
@@ -415,6 +535,10 @@ static esp_err_t process_segment(int index, uint32_t flash_addr, esp_image_segme
|
||||
|
||||
int32_t data_len_remain = data_len;
|
||||
while (data_len_remain > 0) {
|
||||
#if SECURE_BOOT_CHECK_SIGNATURE && defined(BOOTLOADER_BUILD)
|
||||
/* Double check the address verification done above */
|
||||
ESP_FAULT_ASSERT(!do_load || verify_load_addresses(0, load_addr, load_addr + data_len_remain, false, false));
|
||||
#endif
|
||||
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. */
|
||||
data_len = MIN(data_len_remain, ((free_page_count - offset_page) * SPI_FLASH_MMU_PAGE_SIZE));
|
||||
@@ -440,7 +564,7 @@ static esp_err_t process_segment_data(intptr_t load_addr, uint32_t data_addr, ui
|
||||
{
|
||||
// If we are not loading, and the checksum is empty, skip processing this
|
||||
// segment for data
|
||||
if(!do_load && checksum == NULL) {
|
||||
if (!do_load && checksum == NULL) {
|
||||
ESP_LOGD(TAG, "skipping checksum for segment");
|
||||
return ESP_OK;
|
||||
}
|
||||
@@ -599,7 +723,7 @@ static esp_err_t verify_checksum(bootloader_sha256_handle_t sha_handle, uint32_t
|
||||
length = (length + 15) & ~15; // Pad to next full 16 byte block
|
||||
|
||||
// Verify checksum
|
||||
uint8_t buf[16];
|
||||
WORD_ALIGNED_ATTR uint8_t buf[16];
|
||||
esp_err_t err = bootloader_flash_read(data->start_addr + unpadded_length, buf, length - unpadded_length, true);
|
||||
uint8_t calc = buf[length - unpadded_length - 1];
|
||||
uint8_t checksum = (checksum_word >> 24)
|
||||
@@ -623,9 +747,9 @@ static esp_err_t verify_checksum(bootloader_sha256_handle_t sha_handle, uint32_t
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t verify_secure_boot_signature(bootloader_sha256_handle_t sha_handle, esp_image_metadata_t *data)
|
||||
static esp_err_t verify_secure_boot_signature(bootloader_sha256_handle_t sha_handle, esp_image_metadata_t *data, uint8_t *image_digest, uint8_t *verified_digest)
|
||||
{
|
||||
uint8_t image_hash[HASH_LEN] = { 0 };
|
||||
#ifdef SECURE_BOOT_CHECK_SIGNATURE
|
||||
uint32_t end = data->start_addr + data->image_len;
|
||||
|
||||
ESP_LOGI(TAG, "Verifying image signature...");
|
||||
@@ -638,25 +762,36 @@ static esp_err_t verify_secure_boot_signature(bootloader_sha256_handle_t sha_han
|
||||
bootloader_munmap(simple_hash);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
// Pad to 4096 byte sector boundary
|
||||
if (end % FLASH_SECTOR_SIZE != 0) {
|
||||
uint32_t pad_len = FLASH_SECTOR_SIZE - (end % FLASH_SECTOR_SIZE);
|
||||
const void *padding = bootloader_mmap(end, pad_len);
|
||||
bootloader_sha256_data(sha_handle, padding, pad_len);
|
||||
#if CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME
|
||||
// End of the image needs to be padded all the way to a 4KB boundary, after the simple hash
|
||||
// (for apps they are usually already padded due to --secure-pad-v2, only a problem if this option was not used.)
|
||||
uint32_t padded_end = (end + FLASH_SECTOR_SIZE - 1) & ~(FLASH_SECTOR_SIZE-1);
|
||||
if (padded_end > end) {
|
||||
const void *padding = bootloader_mmap(end, padded_end - end);
|
||||
bootloader_sha256_data(sha_handle, padding, padded_end - end);
|
||||
bootloader_munmap(padding);
|
||||
end += pad_len;
|
||||
end = padded_end;
|
||||
}
|
||||
#endif
|
||||
|
||||
bootloader_sha256_finish(sha_handle, image_hash);
|
||||
bootloader_sha256_finish(sha_handle, image_digest);
|
||||
|
||||
// Log the hash for debugging
|
||||
bootloader_debug_buffer(image_hash, HASH_LEN, "Calculated secure boot hash");
|
||||
bootloader_debug_buffer(image_digest, HASH_LEN, "Calculated secure boot hash");
|
||||
|
||||
// Use hash to verify signature block
|
||||
const esp_secure_boot_sig_block_t *sig_block = bootloader_mmap(data->start_addr + data->image_len, sizeof(esp_secure_boot_sig_block_t));
|
||||
esp_err_t err = esp_secure_boot_verify_signature_block(sig_block, image_hash);
|
||||
esp_err_t err = ESP_ERR_IMAGE_INVALID;
|
||||
const void *sig_block;
|
||||
#ifdef CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME
|
||||
ESP_FAULT_ASSERT(memcmp(image_digest, verified_digest, HASH_LEN) != 0); /* sanity check that these values start differently */
|
||||
sig_block = bootloader_mmap(data->start_addr + data->image_len, sizeof(esp_secure_boot_sig_block_t));
|
||||
err = esp_secure_boot_verify_ecdsa_signature_block(sig_block, image_digest, verified_digest);
|
||||
#elif CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME
|
||||
ESP_FAULT_ASSERT(memcmp(image_digest, verified_digest, HASH_LEN) != 0); /* sanity check that these values start differently */
|
||||
sig_block = bootloader_mmap(end, sizeof(ets_secure_boot_signature_t));
|
||||
err = esp_secure_boot_verify_rsa_signature_block(sig_block, image_digest, verified_digest);
|
||||
#endif
|
||||
|
||||
bootloader_munmap(sig_block);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Secure boot signature verification failed");
|
||||
@@ -677,11 +812,12 @@ static esp_err_t verify_secure_boot_signature(bootloader_sha256_handle_t sha_han
|
||||
return ESP_ERR_IMAGE_INVALID;
|
||||
}
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
#if CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME
|
||||
// Adjust image length result to include the appended signature
|
||||
data->image_len = end - data->start_addr + sizeof(ets_secure_boot_signature_t);
|
||||
#endif
|
||||
|
||||
#endif // SECURE_BOOT_CHECK_SIGNATURE
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -31,16 +31,16 @@ void esp_flash_encryption_init_checks()
|
||||
// FLASH_CRYPT_CNT *must* be write protected. This will have happened automatically
|
||||
// if bootloader is IDF V4.0 or newer but may not have happened for previous ESP-IDF bootloaders.
|
||||
#ifdef CONFIG_SECURE_FLASH_ENCRYPTION_MODE_RELEASE
|
||||
#ifdef CONFIG_SECURE_BOOT_ENABLED
|
||||
#ifdef CONFIG_SECURE_BOOT
|
||||
if (esp_secure_boot_enabled() && esp_flash_encryption_enabled()) {
|
||||
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_EARLY_LOGE(TAG, "Flash encryption & Secure Boot together requires FLASH_CRYPT_CNT efuse to be write protected. Fixing now...");
|
||||
ESP_LOGE(TAG, "Flash encryption & Secure Boot together requires FLASH_CRYPT_CNT efuse to be write protected. Fixing now...");
|
||||
esp_flash_write_protect_crypt_cnt();
|
||||
}
|
||||
}
|
||||
#endif // CONFIG_SECURE_BOOT_ENABLED
|
||||
#endif // CONFIG_SECURE_BOOT
|
||||
#endif // CONFIG_SECURE_FLASH_ENCRYPTION_MODE_RELEASE
|
||||
|
||||
// Second check is to print a warning or error if the current running flash encryption mode
|
||||
@@ -48,13 +48,13 @@ void esp_flash_encryption_init_checks()
|
||||
mode = esp_get_flash_encryption_mode();
|
||||
if (mode == ESP_FLASH_ENC_MODE_DEVELOPMENT) {
|
||||
#ifdef CONFIG_SECURE_FLASH_ENCRYPTION_MODE_RELEASE
|
||||
ESP_EARLY_LOGE(TAG, "Flash encryption settings error: app is configured for RELEASE but efuses are set for DEVELOPMENT");
|
||||
ESP_EARLY_LOGE(TAG, "Mismatch found in security options in bootloader menuconfig and efuse settings. Device is not secure.");
|
||||
ESP_LOGE(TAG, "Flash encryption settings error: app is configured for RELEASE but efuses are set for DEVELOPMENT");
|
||||
ESP_LOGE(TAG, "Mismatch found in security options in bootloader menuconfig and efuse settings. Device is not secure.");
|
||||
#else
|
||||
ESP_EARLY_LOGW(TAG, "Flash encryption mode is DEVELOPMENT (not secure)");
|
||||
ESP_LOGW(TAG, "Flash encryption mode is DEVELOPMENT (not secure)");
|
||||
#endif
|
||||
} else if (mode == ESP_FLASH_ENC_MODE_RELEASE) {
|
||||
ESP_EARLY_LOGI(TAG, "Flash encryption mode is RELEASE");
|
||||
ESP_LOGI(TAG, "Flash encryption mode is RELEASE");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#include "bootloader_sha.h"
|
||||
#include "bootloader_flash.h"
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
@@ -15,46 +15,55 @@
|
||||
|
||||
#include "bootloader_flash.h"
|
||||
#include "bootloader_sha.h"
|
||||
#include "bootloader_utility.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_image_format.h"
|
||||
#include "esp_secure_boot.h"
|
||||
#include "mbedtls/sha256.h"
|
||||
#include "mbedtls/x509.h"
|
||||
#include "mbedtls/md.h"
|
||||
#include "mbedtls/platform.h"
|
||||
#include "mbedtls/entropy.h"
|
||||
#include "mbedtls/ctr_drbg.h"
|
||||
#include <string.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
static const char *TAG = "secure_boot";
|
||||
#define DIGEST_LEN 32
|
||||
|
||||
#ifdef CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME
|
||||
static const char *TAG = "secure_boot_v1";
|
||||
|
||||
extern const uint8_t signature_verification_key_start[] asm("_binary_signature_verification_key_bin_start");
|
||||
extern const uint8_t signature_verification_key_end[] asm("_binary_signature_verification_key_bin_end");
|
||||
|
||||
#define SIGNATURE_VERIFICATION_KEYLEN 64
|
||||
|
||||
#define DIGEST_LEN 32
|
||||
|
||||
esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length)
|
||||
{
|
||||
uint8_t digest[DIGEST_LEN];
|
||||
const uint8_t *data;
|
||||
uint8_t verified_digest[DIGEST_LEN];
|
||||
const esp_secure_boot_sig_block_t *sigblock;
|
||||
|
||||
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));
|
||||
if (data == NULL) {
|
||||
ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", src_addr, length + sizeof(esp_secure_boot_sig_block_t));
|
||||
return ESP_FAIL;
|
||||
esp_err_t err = bootloader_sha256_flash_contents(src_addr, length, digest);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Digest calculation failed 0x%x, 0x%x", src_addr, length);
|
||||
return err;
|
||||
}
|
||||
|
||||
// Calculate digest of main image
|
||||
mbedtls_sha256_ret(data, length, digest, 0);
|
||||
|
||||
// Map the signature block and verify the signature
|
||||
sigblock = (const esp_secure_boot_sig_block_t *)(data + length);
|
||||
esp_err_t err = esp_secure_boot_verify_signature_block(sigblock, digest);
|
||||
bootloader_munmap(data);
|
||||
sigblock = (const esp_secure_boot_sig_block_t *)bootloader_mmap(src_addr + length, sizeof(esp_secure_boot_sig_block_t));
|
||||
if (sigblock == NULL) {
|
||||
ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", src_addr + length, sizeof(esp_secure_boot_sig_block_t));
|
||||
return ESP_FAIL;
|
||||
}
|
||||
err = esp_secure_boot_verify_ecdsa_signature_block(sigblock, digest, verified_digest);
|
||||
bootloader_munmap(sigblock);
|
||||
return err;
|
||||
}
|
||||
|
||||
esp_err_t esp_secure_boot_verify_signature_block(const esp_secure_boot_sig_block_t *sig_block, const uint8_t *image_digest)
|
||||
esp_err_t esp_secure_boot_verify_ecdsa_signature_block(const esp_secure_boot_sig_block_t *sig_block, const uint8_t *image_digest, uint8_t *verified_digest)
|
||||
{
|
||||
#if !(defined(CONFIG_MBEDTLS_ECDSA_C) && defined(CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED))
|
||||
ESP_LOGE(TAG, "Signature verification requires ECDSA & SECP256R1 curve enabled");
|
||||
@@ -62,6 +71,9 @@ esp_err_t esp_secure_boot_verify_signature_block(const esp_secure_boot_sig_block
|
||||
#else
|
||||
ptrdiff_t keylen;
|
||||
|
||||
/* Note: in IDF app image verification we don't add any fault injection resistance, boot-time checks only */
|
||||
memset(verified_digest, 0, DIGEST_LEN);
|
||||
|
||||
keylen = signature_verification_key_end - signature_verification_key_start;
|
||||
if (keylen != SIGNATURE_VERIFICATION_KEYLEN) {
|
||||
ESP_LOGE(TAG, "Embedded public verification key has wrong length %d", keylen);
|
||||
@@ -123,3 +135,147 @@ cleanup:
|
||||
return ret == 0 ? ESP_OK : ESP_ERR_IMAGE_INVALID;
|
||||
#endif // CONFIG_MBEDTLS_ECDSA_C && CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED
|
||||
}
|
||||
|
||||
#elif CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME
|
||||
|
||||
static const char *TAG = "secure_boot_v2";
|
||||
#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
|
||||
#define RSA_KEY_SIZE 384 /* RSA 3072 Bits */
|
||||
|
||||
esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length)
|
||||
{
|
||||
uint8_t digest[DIGEST_LEN] = {0};
|
||||
uint8_t verified_digest[DIGEST_LEN] = {0};
|
||||
|
||||
/* Rounding off length to the upper 4k boundary */
|
||||
uint32_t padded_length = ALIGN_UP(length, FLASH_SECTOR_SIZE);
|
||||
ESP_LOGD(TAG, "verifying signature src_addr 0x%x length 0x%x", src_addr, length);
|
||||
|
||||
esp_err_t err = bootloader_sha256_flash_contents(src_addr, padded_length, digest);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Digest calculation failed 0x%x, 0x%x", src_addr, padded_length);
|
||||
return err;
|
||||
}
|
||||
|
||||
const ets_secure_boot_signature_t *sig_block = bootloader_mmap(src_addr + padded_length, sizeof(ets_secure_boot_signature_t));
|
||||
if (sig_block == NULL) {
|
||||
ESP_LOGE(TAG, "Failed to mmap data at offset 0x%x", src_addr + padded_length);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
err = esp_secure_boot_verify_rsa_signature_block(sig_block, digest, verified_digest);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Secure Boot V2 verification failed.");
|
||||
}
|
||||
bootloader_munmap(sig_block);
|
||||
return err;
|
||||
}
|
||||
|
||||
esp_err_t esp_secure_boot_verify_rsa_signature_block(const ets_secure_boot_signature_t *sig_block, const uint8_t *image_digest, uint8_t *verified_digest)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
#if CONFIG_SECURE_BOOT_V2_ENABLED /* Verify key against efuse block */
|
||||
uint8_t efuse_trusted_digest[DIGEST_LEN] = {0}, sig_block_trusted_digest[DIGEST_LEN] = {0};
|
||||
memcpy(efuse_trusted_digest, (uint8_t *) EFUSE_BLK2_RDATA0_REG, sizeof(efuse_trusted_digest));
|
||||
|
||||
/* Note: in IDF verification we don't add any fault injection resistance, as we don't expect this to be called
|
||||
during boot-time verification. */
|
||||
memset(verified_digest, 0, DIGEST_LEN);
|
||||
|
||||
/* Generating the SHA of the public key components in the signature block */
|
||||
bootloader_sha256_handle_t sig_block_sha;
|
||||
sig_block_sha = bootloader_sha256_start();
|
||||
bootloader_sha256_data(sig_block_sha, &sig_block->block[0].key, sizeof(sig_block->block[0].key));
|
||||
bootloader_sha256_finish(sig_block_sha, (unsigned char *)sig_block_trusted_digest);
|
||||
|
||||
if (memcmp(efuse_trusted_digest, sig_block_trusted_digest, DIGEST_LEN) != 0) {
|
||||
const uint8_t zeroes[DIGEST_LEN] = {0};
|
||||
/* Can't continue if secure boot is enabled, OR if a different digest is already written in efuse BLK2
|
||||
|
||||
(If BLK2 is empty and Secure Boot is disabled then we assume that it will be enabled later.)
|
||||
*/
|
||||
if (esp_secure_boot_enabled() || memcmp(efuse_trusted_digest, zeroes, DIGEST_LEN) != 0) {
|
||||
ESP_LOGE(TAG, "Public key digest in eFuse BLK2 and the signature block don't match.");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
ESP_LOGI(TAG, "Verifying with RSA-PSS...");
|
||||
int ret = 0;
|
||||
mbedtls_rsa_context pk;
|
||||
mbedtls_entropy_context entropy;
|
||||
mbedtls_ctr_drbg_context ctr_drbg;
|
||||
unsigned char *sig_be = calloc(1, RSA_KEY_SIZE);
|
||||
unsigned char *buf = calloc(1, RSA_KEY_SIZE);
|
||||
if (sig_be == NULL || buf == NULL) {
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
mbedtls_entropy_init(&entropy);
|
||||
mbedtls_ctr_drbg_init(&ctr_drbg);
|
||||
ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, NULL, 0);
|
||||
if (ret != 0) {
|
||||
ESP_LOGE(TAG, "mbedtls_ctr_drbg_seed returned -0x%04x\n", ret);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
for (i = 0; i < SECURE_BOOT_NUM_BLOCKS; i++) {
|
||||
const mbedtls_mpi N = { .s = 1,
|
||||
.n = sizeof(sig_block->block[i].key.n)/sizeof(mbedtls_mpi_uint),
|
||||
.p = (void *)sig_block->block[i].key.n,
|
||||
};
|
||||
const mbedtls_mpi e = { .s = 1,
|
||||
.n = sizeof(sig_block->block[i].key.e)/sizeof(mbedtls_mpi_uint), // 1
|
||||
.p = (void *)&sig_block->block[i].key.e,
|
||||
};
|
||||
mbedtls_rsa_init(&pk, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA256);
|
||||
ret = mbedtls_rsa_import(&pk, &N, NULL, NULL, NULL, &e);
|
||||
if (ret != 0) {
|
||||
ESP_LOGE(TAG, "Failed mbedtls_rsa_import, err: %d", ret);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ret = mbedtls_rsa_complete(&pk);
|
||||
if (ret != 0) {
|
||||
ESP_LOGE(TAG, "Failed mbedtls_rsa_complete, err: %d", ret);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ret = mbedtls_rsa_check_pubkey(&pk);
|
||||
if (ret != 0) {
|
||||
ESP_LOGI(TAG, "Key is not an RSA key -%0x", -ret);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Signature needs to be byte swapped into BE representation */
|
||||
for (int j = 0; j < RSA_KEY_SIZE; j++) {
|
||||
sig_be[RSA_KEY_SIZE- j - 1] = sig_block->block[i].signature[j];
|
||||
}
|
||||
|
||||
ret = mbedtls_rsa_public( &pk, sig_be, buf);
|
||||
if (ret != 0) {
|
||||
ESP_LOGE(TAG, "mbedtls_rsa_public failed, err: %d", ret);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ret = mbedtls_rsa_rsassa_pss_verify( &pk, mbedtls_ctr_drbg_random, &ctr_drbg, MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_SHA256, 32,
|
||||
sig_block->block[i].image_digest, sig_be);
|
||||
if (ret != 0) {
|
||||
ESP_LOGE(TAG, "Failed mbedtls_rsa_rsassa_pss_verify, err: %d", ret);
|
||||
} else {
|
||||
ESP_LOGI(TAG, "Signature verified successfully!");
|
||||
}
|
||||
exit:
|
||||
mbedtls_rsa_free(&pk);
|
||||
if (ret == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
free(sig_be);
|
||||
free(buf);
|
||||
return (!ret) ? ESP_OK : ESP_ERR_IMAGE_INVALID;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -323,7 +323,8 @@ if(CONFIG_BT_ENABLED)
|
||||
"esp_ble_mesh/api/models/include"
|
||||
"esp_ble_mesh/api")
|
||||
|
||||
list(APPEND srcs "esp_ble_mesh/api/core/esp_ble_mesh_common_api.c"
|
||||
list(APPEND srcs "esp_ble_mesh/api/core/esp_ble_mesh_ble_api.c"
|
||||
"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"
|
||||
@@ -347,6 +348,8 @@ if(CONFIG_BT_ENABLED)
|
||||
"esp_ble_mesh/mesh_common/mesh_buf.c"
|
||||
"esp_ble_mesh/mesh_common/mesh_common.c"
|
||||
"esp_ble_mesh/mesh_common/mesh_kernel.c"
|
||||
"esp_ble_mesh/mesh_common/mesh_mutex.c"
|
||||
"esp_ble_mesh/mesh_common/mesh_timer.c"
|
||||
"esp_ble_mesh/mesh_common/mesh_util.c"
|
||||
"esp_ble_mesh/mesh_core/storage/settings_nvs.c"
|
||||
"esp_ble_mesh/mesh_core/access.c"
|
||||
|
||||
@@ -90,7 +90,7 @@ do{\
|
||||
} while(0)
|
||||
|
||||
#define OSI_FUNCS_TIME_BLOCKING 0xffffffff
|
||||
#define OSI_VERSION 0x00010001
|
||||
#define OSI_VERSION 0x00010002
|
||||
#define OSI_MAGIC_VALUE 0xFADEBEAD
|
||||
|
||||
/* SPIRAM Configuration */
|
||||
@@ -167,6 +167,8 @@ struct osi_funcs_t {
|
||||
void (* _btdm_sleep_exit_phase1)(void); /* called from ISR */
|
||||
void (* _btdm_sleep_exit_phase2)(void); /* called from ISR */
|
||||
void (* _btdm_sleep_exit_phase3)(void); /* called from task */
|
||||
bool (* _coex_bt_wakeup_request)(void);
|
||||
void (* _coex_bt_wakeup_request_end)(void);
|
||||
int (* _coex_bt_request)(uint32_t event, uint32_t latency, uint32_t duration);
|
||||
int (* _coex_bt_release)(uint32_t event);
|
||||
int (* _coex_register_bt_cb)(coex_func_cb_t cb);
|
||||
@@ -282,6 +284,8 @@ static void btdm_sleep_enter_phase1_wrapper(uint32_t lpcycles);
|
||||
static void btdm_sleep_enter_phase2_wrapper(void);
|
||||
static void IRAM_ATTR btdm_sleep_exit_phase1_wrapper(void);
|
||||
static void btdm_sleep_exit_phase3_wrapper(void);
|
||||
static bool coex_bt_wakeup_request(void);
|
||||
static void coex_bt_wakeup_request_end(void);
|
||||
|
||||
/* Local variable definition
|
||||
***************************************************************************
|
||||
@@ -329,6 +333,8 @@ static const struct osi_funcs_t osi_funcs_ro = {
|
||||
._btdm_sleep_exit_phase1 = btdm_sleep_exit_phase1_wrapper,
|
||||
._btdm_sleep_exit_phase2 = NULL,
|
||||
._btdm_sleep_exit_phase3 = btdm_sleep_exit_phase3_wrapper,
|
||||
._coex_bt_wakeup_request = coex_bt_wakeup_request,
|
||||
._coex_bt_wakeup_request_end = coex_bt_wakeup_request_end,
|
||||
._coex_bt_request = coex_bt_request_wrapper,
|
||||
._coex_bt_release = coex_bt_release_wrapper,
|
||||
._coex_register_bt_cb = coex_register_bt_cb_wrapper,
|
||||
@@ -889,13 +895,24 @@ static void IRAM_ATTR btdm_slp_tmr_callback(void *arg)
|
||||
}
|
||||
#endif
|
||||
|
||||
bool esp_vhci_host_check_send_available(void)
|
||||
{
|
||||
return API_vhci_host_check_send_available();
|
||||
}
|
||||
#define BTDM_ASYNC_WAKEUP_REQ_HCI 0
|
||||
#define BTDM_ASYNC_WAKEUP_REQ_COEX 1
|
||||
#define BTDM_ASYNC_WAKEUP_REQMAX 2
|
||||
|
||||
void esp_vhci_host_send_packet(uint8_t *data, uint16_t len)
|
||||
static bool async_wakeup_request(int event)
|
||||
{
|
||||
bool request_lock = false;
|
||||
switch (event) {
|
||||
case BTDM_ASYNC_WAKEUP_REQ_HCI:
|
||||
request_lock = true;
|
||||
break;
|
||||
case BTDM_ASYNC_WAKEUP_REQ_COEX:
|
||||
request_lock = false;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool do_wakeup_request = false;
|
||||
|
||||
if (!btdm_power_state_active()) {
|
||||
@@ -906,13 +923,57 @@ void esp_vhci_host_send_packet(uint8_t *data, uint16_t len)
|
||||
esp_timer_stop(s_btdm_slp_tmr);
|
||||
#endif
|
||||
do_wakeup_request = true;
|
||||
btdm_wakeup_request(true);
|
||||
btdm_wakeup_request(request_lock);
|
||||
}
|
||||
|
||||
return do_wakeup_request;
|
||||
}
|
||||
|
||||
static void async_wakeup_request_end(int event)
|
||||
{
|
||||
bool request_lock = false;
|
||||
switch (event) {
|
||||
case BTDM_ASYNC_WAKEUP_REQ_HCI:
|
||||
request_lock = true;
|
||||
break;
|
||||
case BTDM_ASYNC_WAKEUP_REQ_COEX:
|
||||
request_lock = false;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if (request_lock) {
|
||||
btdm_wakeup_request_end();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static bool coex_bt_wakeup_request(void)
|
||||
{
|
||||
return async_wakeup_request(BTDM_ASYNC_WAKEUP_REQ_COEX);
|
||||
}
|
||||
|
||||
static void coex_bt_wakeup_request_end(void)
|
||||
{
|
||||
async_wakeup_request_end(BTDM_ASYNC_WAKEUP_REQ_COEX);
|
||||
return;
|
||||
}
|
||||
|
||||
bool esp_vhci_host_check_send_available(void)
|
||||
{
|
||||
return API_vhci_host_check_send_available();
|
||||
}
|
||||
|
||||
void esp_vhci_host_send_packet(uint8_t *data, uint16_t len)
|
||||
{
|
||||
bool do_wakeup_request = async_wakeup_request(BTDM_ASYNC_WAKEUP_REQ_HCI);
|
||||
|
||||
API_vhci_host_send_packet(data, len);
|
||||
|
||||
if (do_wakeup_request) {
|
||||
btdm_wakeup_request_end();
|
||||
async_wakeup_request_end(BTDM_ASYNC_WAKEUP_REQ_HCI);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -972,7 +1033,7 @@ static esp_err_t try_heap_caps_add_region(intptr_t start, intptr_t end)
|
||||
esp_err_t esp_bt_controller_mem_release(esp_bt_mode_t mode)
|
||||
{
|
||||
bool update = true;
|
||||
intptr_t mem_start, mem_end;
|
||||
intptr_t mem_start=(intptr_t) NULL, mem_end=(intptr_t) NULL;
|
||||
|
||||
if (btdm_controller_status != ESP_BT_CONTROLLER_STATUS_IDLE) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
|
||||
Submodule components/bt/controller/lib updated: f7e14284a3...238fc047f2
@@ -9,8 +9,8 @@ if BLE_MESH
|
||||
config BLE_MESH_USE_DUPLICATE_SCAN
|
||||
bool "Support Duplicate Scan in BLE Mesh"
|
||||
depends on BT_BLUEDROID_ENABLED
|
||||
select BLE_SCAN_DUPLICATE
|
||||
select BLE_MESH_SCAN_DUPLICATE_EN
|
||||
select BTDM_BLE_SCAN_DUPL
|
||||
select BTDM_BLE_MESH_SCAN_DUPL_EN
|
||||
default y
|
||||
help
|
||||
Enable this option to allow using specific duplicate scan filter
|
||||
@@ -56,7 +56,7 @@ if BLE_MESH
|
||||
|
||||
config BLE_MESH_WAIT_FOR_PROV_MAX_DEV_NUM
|
||||
int "Maximum number of unprovisioned devices that can be added to device queue"
|
||||
default 20
|
||||
default 10
|
||||
range 1 100
|
||||
help
|
||||
This option specifies how many unprovisioned devices can be added to device
|
||||
@@ -64,20 +64,9 @@ if BLE_MESH
|
||||
queue in the bottom layer which is used to store unprovisioned device
|
||||
information (e.g. Device UUID, address).
|
||||
|
||||
config BLE_MESH_MAX_STORED_NODES
|
||||
int "Maximum number of nodes whose information can be stored"
|
||||
default 20
|
||||
range BLE_MESH_MAX_PROV_NODES 1000
|
||||
help
|
||||
This option specifies the maximum number of nodes whose information can be
|
||||
stored by a Provisioner in its upper layer.
|
||||
Users can change this value according to the number of nodes whose information
|
||||
(e.g. Device UUID, unicast address, element number) are going to be stored by
|
||||
a Provisioner. And the nodes include the provisioned ones and user-added ones.
|
||||
|
||||
config BLE_MESH_MAX_PROV_NODES
|
||||
int "Maximum number of devices that can be provisioned by Provisioner"
|
||||
default 20
|
||||
default 10
|
||||
range 1 1000
|
||||
help
|
||||
This option specifies how many devices can be provisioned by a Provisioner.
|
||||
@@ -296,6 +285,29 @@ if BLE_MESH
|
||||
introduce message replay attacks and system security will be in a
|
||||
vulnerable state.
|
||||
|
||||
config BLE_MESH_SETTINGS_BACKWARD_COMPATIBILITY
|
||||
bool "A specific option for settings backward compatibility"
|
||||
depends on BLE_MESH_NODE
|
||||
default n
|
||||
help
|
||||
This option is created to solve the issue of failure in recovering
|
||||
node information after mesh stack updates. In the old version mesh
|
||||
stack, there is no key of "mesh/role" in nvs. In the new version
|
||||
mesh stack, key of "mesh/role" is added in nvs, recovering node
|
||||
information needs to check "mesh/role" key in nvs and implements
|
||||
selective recovery of mesh node information. Therefore, there may
|
||||
be failure in recovering node information during node restarting
|
||||
after OTA.
|
||||
|
||||
The new version mesh stack adds the option of "mesh/role" because
|
||||
we have added the support of storing Provisioner information, while
|
||||
the old version only supports storing node information.
|
||||
|
||||
If users are updating their nodes from old version to new version,
|
||||
we recommend enabling this option, so that system could set the flag
|
||||
in advance before recovering node information and make sure the node
|
||||
information recovering could work as expected.
|
||||
|
||||
endif # if BLE_MESH_SETTINGS
|
||||
|
||||
config BLE_MESH_SUBNET_COUNT
|
||||
@@ -348,6 +360,11 @@ if BLE_MESH
|
||||
The replay protection list is used to prevent a node from replay attack,
|
||||
which will store the source address and sequence number of the received
|
||||
mesh messages.
|
||||
For Provisioner, the replay protection list size should not be smaller than
|
||||
the maximum number of nodes whose information can be stored. And the element
|
||||
number of each node should also be taken into consideration. For example, if
|
||||
Provisioner can provision up to 20 nodes and each node contains two elements,
|
||||
then the replay protection list size of Provisioner should be at least 40.
|
||||
|
||||
config BLE_MESH_MSG_CACHE_SIZE
|
||||
int "Network message cache size"
|
||||
@@ -372,6 +389,24 @@ if BLE_MESH
|
||||
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_SUPPORT_BLE_ADV
|
||||
bool "Support sending normal BLE advertising packets"
|
||||
default n
|
||||
help
|
||||
When selected, users can send normal BLE advertising packets
|
||||
with specific API.
|
||||
|
||||
if BLE_MESH_SUPPORT_BLE_ADV
|
||||
|
||||
config BLE_MESH_BLE_ADV_BUF_COUNT
|
||||
int "Number of advertising buffers for BLE advertising packets"
|
||||
default 3
|
||||
range 1 255
|
||||
help
|
||||
Number of advertising buffers for BLE packets available.
|
||||
|
||||
endif # BLE_MESH_SUPPORT_BLE_ADV
|
||||
|
||||
config BLE_MESH_IVU_DIVIDER
|
||||
int "Divider for IV Update state refresh timer"
|
||||
default 4
|
||||
@@ -794,9 +829,9 @@ if BLE_MESH
|
||||
Enable support for Generic Default Transition Time client model.
|
||||
|
||||
config BLE_MESH_GENERIC_POWER_ONOFF_CLI
|
||||
bool "Generic Power Onoff Client Model"
|
||||
bool "Generic Power OnOff Client Model"
|
||||
help
|
||||
Enable support for Generic Power Onoff client model.
|
||||
Enable support for Generic Power OnOff client model.
|
||||
|
||||
config BLE_MESH_GENERIC_POWER_LEVEL_CLI
|
||||
bool "Generic Power Level Client Model"
|
||||
@@ -882,6 +917,26 @@ if BLE_MESH
|
||||
This option adds extra self-tests which are run every time BLE Mesh
|
||||
networking is initialized.
|
||||
|
||||
if BLE_MESH_SELF_TEST
|
||||
|
||||
config BLE_MESH_TEST_AUTO_ENTER_NETWORK
|
||||
bool "Unprovisioned device enters mesh network automatically"
|
||||
default y
|
||||
help
|
||||
With this option enabled, an unprovisioned device can automatically
|
||||
enters mesh network using a specific test function without the pro-
|
||||
visioning procedure. And on the Provisioner side, a test function
|
||||
needs to be invoked to add the node information into the mesh stack.
|
||||
|
||||
config BLE_MESH_TEST_USE_WHITE_LIST
|
||||
bool "Use white list to filter mesh advertising packets"
|
||||
default n
|
||||
help
|
||||
With this option enabled, users can use white list to filter mesh
|
||||
advertising packets while scanning.
|
||||
|
||||
endif # BLE_MESH_SELF_TEST
|
||||
|
||||
config BLE_MESH_SHELL
|
||||
bool "Enable BLE Mesh shell"
|
||||
default n
|
||||
|
||||
73
components/bt/esp_ble_mesh/api/core/esp_ble_mesh_ble_api.c
Normal file
73
components/bt/esp_ble_mesh/api/core/esp_ble_mesh_ble_api.c
Normal file
@@ -0,0 +1,73 @@
|
||||
// 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 <string.h>
|
||||
|
||||
#include "btc/btc_manage.h"
|
||||
|
||||
#include "esp_err.h"
|
||||
|
||||
#include "btc_ble_mesh_prov.h"
|
||||
#include "esp_ble_mesh_defs.h"
|
||||
|
||||
#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV
|
||||
|
||||
esp_err_t esp_ble_mesh_start_ble_advertising(const esp_ble_mesh_ble_adv_param_t *param,
|
||||
const esp_ble_mesh_ble_adv_data_t *data)
|
||||
{
|
||||
btc_ble_mesh_prov_args_t arg = {0};
|
||||
btc_msg_t msg = {0};
|
||||
|
||||
if (param == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_PROV;
|
||||
msg.act = BTC_BLE_MESH_ACT_START_BLE_ADVERTISING;
|
||||
|
||||
memcpy(&arg.start_ble_advertising.param, param, sizeof(esp_ble_mesh_ble_adv_param_t));
|
||||
if (data) {
|
||||
memcpy(&arg.start_ble_advertising.data, data, sizeof(esp_ble_mesh_ble_adv_data_t));
|
||||
}
|
||||
|
||||
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_stop_ble_advertising(uint8_t index)
|
||||
{
|
||||
btc_ble_mesh_prov_args_t arg = {0};
|
||||
btc_msg_t msg = {0};
|
||||
|
||||
if (index >= CONFIG_BLE_MESH_BLE_ADV_BUF_COUNT) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_PROV;
|
||||
msg.act = BTC_BLE_MESH_ACT_STOP_BLE_ADVERTISING;
|
||||
|
||||
arg.stop_ble_advertising.index = 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_SUPPORT_BLE_ADV */
|
||||
@@ -17,8 +17,6 @@
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/semphr.h"
|
||||
|
||||
#include "btc/btc_manage.h"
|
||||
|
||||
#include "esp_err.h"
|
||||
|
||||
#include "btc_ble_mesh_prov.h"
|
||||
@@ -73,10 +71,22 @@ esp_err_t esp_ble_mesh_init(esp_ble_mesh_prov_t *prov, esp_ble_mesh_comp_t *comp
|
||||
|
||||
esp_err_t esp_ble_mesh_deinit(esp_ble_mesh_deinit_param_t *param)
|
||||
{
|
||||
btc_ble_mesh_prov_args_t arg = {0};
|
||||
btc_msg_t msg = {0};
|
||||
|
||||
if (param == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
return btc_ble_mesh_deinit(param);
|
||||
ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
|
||||
|
||||
arg.mesh_deinit.param.erase_flash = param->erase_flash;
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_PROV;
|
||||
msg.act = BTC_BLE_MESH_ACT_DEINIT_MESH;
|
||||
|
||||
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL)
|
||||
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
|
||||
}
|
||||
|
||||
|
||||
@@ -14,8 +14,6 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "btc/btc_manage.h"
|
||||
|
||||
#include "esp_err.h"
|
||||
|
||||
#include "btc_ble_mesh_prov.h"
|
||||
@@ -44,6 +42,9 @@ uint16_t *esp_ble_mesh_is_model_subscribed_to_group(esp_ble_mesh_model_t *model,
|
||||
|
||||
esp_ble_mesh_elem_t *esp_ble_mesh_find_element(uint16_t element_addr)
|
||||
{
|
||||
if (!ESP_BLE_MESH_ADDR_IS_UNICAST(element_addr)) {
|
||||
return NULL;
|
||||
}
|
||||
return btc_ble_mesh_elem_find(element_addr);
|
||||
}
|
||||
|
||||
|
||||
@@ -14,8 +14,6 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "btc/btc_manage.h"
|
||||
|
||||
#include "esp_err.h"
|
||||
|
||||
#include "btc_ble_mesh_prov.h"
|
||||
|
||||
@@ -15,8 +15,6 @@
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "btc/btc_manage.h"
|
||||
|
||||
#include "esp_err.h"
|
||||
|
||||
#include "btc_ble_mesh_prov.h"
|
||||
@@ -71,9 +69,9 @@ static esp_err_t ble_mesh_model_send_msg(esp_ble_mesh_model_t *model,
|
||||
}
|
||||
|
||||
if (act == BTC_BLE_MESH_ACT_MODEL_PUBLISH) {
|
||||
mic_len = 4;
|
||||
mic_len = ESP_BLE_MESH_MIC_SHORT;
|
||||
} else {
|
||||
mic_len = ctx->send_rel ? 8 : 4;
|
||||
mic_len = ctx->send_rel ? ESP_BLE_MESH_MIC_LONG : ESP_BLE_MESH_MIC_SHORT;
|
||||
}
|
||||
|
||||
if (op_len + length + mic_len > MIN(ESP_BLE_MESH_SDU_MAX_LEN, ESP_BLE_MESH_TX_SDU_MAX)) {
|
||||
@@ -268,7 +266,8 @@ esp_err_t esp_ble_mesh_provisioner_set_node_name(uint16_t index, const char *nam
|
||||
|
||||
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));
|
||||
strncpy(arg.set_node_name.name, name, ESP_BLE_MESH_NODE_NAME_MAX_LEN);
|
||||
|
||||
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL)
|
||||
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
|
||||
}
|
||||
|
||||
@@ -15,8 +15,6 @@
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "btc/btc_manage.h"
|
||||
|
||||
#include "esp_err.h"
|
||||
|
||||
#include "btc_ble_mesh_prov.h"
|
||||
@@ -118,7 +116,7 @@ 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) {
|
||||
if (!string || strlen(string) > ESP_BLE_MESH_PROV_INPUT_OOB_MAX_LEN) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
@@ -128,7 +126,8 @@ esp_err_t esp_ble_mesh_node_input_string(const char *string)
|
||||
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));
|
||||
strncpy(arg.input_string.string, string,
|
||||
MIN(strlen(string), sizeof(arg.input_string.string)));
|
||||
|
||||
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL)
|
||||
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
|
||||
@@ -150,7 +149,8 @@ esp_err_t esp_ble_mesh_set_unprovisioned_device_name(const char *name)
|
||||
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));
|
||||
strncpy(arg.set_device_name.name, name, ESP_BLE_MESH_DEVICE_NAME_MAX_LEN);
|
||||
|
||||
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL)
|
||||
== BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
|
||||
}
|
||||
@@ -185,7 +185,8 @@ esp_err_t esp_ble_mesh_provisioner_input_string(const char *string, uint8_t link
|
||||
btc_ble_mesh_prov_args_t arg = {0};
|
||||
btc_msg_t msg = {0};
|
||||
|
||||
if (!string || link_idx >= MAX_PROV_LINK_IDX) {
|
||||
if (!string || strlen(string) > ESP_BLE_MESH_PROV_OUTPUT_OOB_MAX_LEN ||
|
||||
link_idx >= MAX_PROV_LINK_IDX) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
@@ -196,7 +197,8 @@ esp_err_t esp_ble_mesh_provisioner_input_string(const char *string, uint8_t link
|
||||
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));
|
||||
strncpy(arg.provisioner_input_str.string, string,
|
||||
MIN(strlen(string), sizeof(arg.provisioner_input_str.string)));
|
||||
arg.provisioner_input_str.link_idx = link_idx;
|
||||
|
||||
return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_mesh_prov_args_t), NULL)
|
||||
@@ -350,6 +352,10 @@ esp_err_t esp_ble_mesh_provisioner_set_dev_uuid_match(const uint8_t *match_val,
|
||||
btc_ble_mesh_prov_args_t arg = {0};
|
||||
btc_msg_t msg = {0};
|
||||
|
||||
if (match_len + offset > ESP_BLE_MESH_OCTET16_LEN) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
ESP_BLE_HOST_STATUS_CHECK(ESP_BLE_HOST_STATUS_ENABLED);
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
@@ -446,7 +452,8 @@ esp_err_t esp_ble_mesh_set_fast_prov_info(esp_ble_mesh_fast_prov_info_t *fast_pr
|
||||
btc_ble_mesh_prov_args_t arg = {0};
|
||||
btc_msg_t msg = {0};
|
||||
|
||||
if (fast_prov_info == NULL) {
|
||||
if (fast_prov_info == NULL || (fast_prov_info->offset +
|
||||
fast_prov_info->match_len > ESP_BLE_MESH_OCTET16_LEN)) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,8 +15,6 @@
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "btc/btc_manage.h"
|
||||
|
||||
#include "esp_err.h"
|
||||
|
||||
#include "btc_ble_mesh_prov.h"
|
||||
|
||||
@@ -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.
|
||||
|
||||
#ifndef _ESP_BLE_MESH_BLE_API_H_
|
||||
#define _ESP_BLE_MESH_BLE_API_H_
|
||||
|
||||
#include "esp_ble_mesh_defs.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief This function is called to start BLE advertising with the corresponding data
|
||||
* and parameters while BLE Mesh is working at the same time.
|
||||
*
|
||||
* @note 1. When this function is called, the BLE advertising packet will be posted to
|
||||
* the BLE mesh adv queue in the mesh stack and waited to be sent.
|
||||
* 2. In the BLE advertising parameters, the "duration" means the time used for
|
||||
* sending the BLE advertising packet each time, it shall not be smaller than the
|
||||
* advertising interval. When the packet is sent successfully, it will be posted
|
||||
* to the adv queue again after the "period" time if the "count" is bigger than 0.
|
||||
* The "count" means how many durations the packet will be sent after it is sent
|
||||
* successfully for the first time. And if the "count" is set to 0xFFFF, which
|
||||
* means the packet will be sent infinitely.
|
||||
* 3. The "priority" means the priority of BLE advertising packet compared with
|
||||
* BLE Mesh packets. Currently two options (i.e. low/high) are provided. If the
|
||||
* "priority" is high, the BLE advertising packet will be posted to the front of
|
||||
* adv queue. Otherwise it will be posted to the back of adv queue.
|
||||
*
|
||||
* @param[in] param: Pointer to the BLE advertising parameters
|
||||
* @param[in] data: Pointer to the BLE advertising data and scan response data
|
||||
*
|
||||
* @return ESP_OK on success or error code otherwise.
|
||||
*
|
||||
*/
|
||||
esp_err_t esp_ble_mesh_start_ble_advertising(const esp_ble_mesh_ble_adv_param_t *param,
|
||||
const esp_ble_mesh_ble_adv_data_t *data);
|
||||
|
||||
/**
|
||||
* @brief This function is called to stop BLE advertising with the corresponding index.
|
||||
*
|
||||
* @param[in] index: Index of BLE advertising
|
||||
*
|
||||
* @return ESP_OK on success or error code otherwise.
|
||||
*
|
||||
*/
|
||||
esp_err_t esp_ble_mesh_stop_ble_advertising(uint8_t index);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _ESP_BLE_MESH_BLE_API_H_ */
|
||||
@@ -17,6 +17,10 @@
|
||||
|
||||
#include "esp_ble_mesh_defs.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Initialize BLE Mesh module.
|
||||
* This API initializes provisioning capabilities and composition data information.
|
||||
@@ -46,4 +50,8 @@ esp_err_t esp_ble_mesh_init(esp_ble_mesh_prov_t *prov, esp_ble_mesh_comp_t *comp
|
||||
*/
|
||||
esp_err_t esp_ble_mesh_deinit(esp_ble_mesh_deinit_param_t *param);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _ESP_BLE_MESH_COMMON_API_H_ */
|
||||
|
||||
@@ -17,6 +17,10 @@
|
||||
|
||||
#include "esp_ble_mesh_defs.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Get the model publish period, the unit is ms.
|
||||
*
|
||||
@@ -104,4 +108,8 @@ esp_ble_mesh_model_t *esp_ble_mesh_find_sig_model(const esp_ble_mesh_elem_t *ele
|
||||
*/
|
||||
const esp_ble_mesh_comp_t *esp_ble_mesh_get_composition_data(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _ESP_BLE_MESH_LOCAL_DATA_OPERATION_API_H_ */
|
||||
|
||||
@@ -17,6 +17,10 @@
|
||||
|
||||
#include "esp_ble_mesh_defs.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enable BLE Mesh device LPN functionality.
|
||||
*
|
||||
@@ -58,4 +62,8 @@ esp_err_t esp_ble_mesh_lpn_disable(bool force);
|
||||
*/
|
||||
esp_err_t esp_ble_mesh_lpn_poll(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _ESP_BLE_MESH_LOW_POWER_API_H_ */
|
||||
|
||||
@@ -17,6 +17,10 @@
|
||||
|
||||
#include "esp_ble_mesh_defs.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @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);
|
||||
@@ -381,4 +385,8 @@ uint16_t esp_ble_mesh_provisioner_get_prov_node_count(void);
|
||||
*/
|
||||
const uint8_t *esp_ble_mesh_get_fast_prov_app_key(uint16_t net_idx, uint16_t app_idx);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _ESP_BLE_MESH_NETWORKING_API_H_ */
|
||||
|
||||
@@ -17,6 +17,10 @@
|
||||
|
||||
#include "esp_ble_mesh_defs.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @brief: event, event code of provisioning events; param, parameters of provisioning events */
|
||||
typedef void (* esp_ble_mesh_prov_cb_t)(esp_ble_mesh_prov_cb_event_t event,
|
||||
esp_ble_mesh_prov_cb_param_t *param);
|
||||
@@ -367,4 +371,8 @@ esp_err_t esp_ble_mesh_set_fast_prov_info(esp_ble_mesh_fast_prov_info_t *fast_pr
|
||||
*/
|
||||
esp_err_t esp_ble_mesh_set_fast_prov_action(esp_ble_mesh_fast_prov_action_t action);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _ESP_BLE_MESH_PROVISIONING_API_H_ */
|
||||
|
||||
@@ -17,6 +17,10 @@
|
||||
|
||||
#include "esp_ble_mesh_defs.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Enable advertising with Node Identity.
|
||||
*
|
||||
@@ -114,5 +118,9 @@ esp_err_t esp_ble_mesh_proxy_client_add_filter_addr(uint8_t conn_handle,
|
||||
esp_err_t esp_ble_mesh_proxy_client_remove_filter_addr(uint8_t conn_handle,
|
||||
uint16_t net_idx, uint16_t *addr, uint16_t addr_num);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _ESP_BLE_MESH_PROXY_API_H_ */
|
||||
|
||||
|
||||
@@ -31,9 +31,19 @@
|
||||
#define ESP_BLE_HOST_STATUS_CHECK(status) do {} while (0)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*!< The maximum length of a BLE Mesh message, including Opcode, Payload and TransMIC */
|
||||
#define ESP_BLE_MESH_SDU_MAX_LEN 384
|
||||
|
||||
/*!< Length of a short Mesh MIC. */
|
||||
#define ESP_BLE_MESH_MIC_SHORT 4
|
||||
|
||||
/*!< Length of a long Mesh MIC. */
|
||||
#define ESP_BLE_MESH_MIC_LONG 8
|
||||
|
||||
/*!< The maximum length of a BLE Mesh provisioned node name */
|
||||
#define ESP_BLE_MESH_NODE_NAME_MAX_LEN 31
|
||||
|
||||
@@ -238,6 +248,15 @@ typedef enum {
|
||||
ESP_BLE_MESH_PROV_OOB_ON_DEV = BIT(15),
|
||||
} esp_ble_mesh_prov_oob_info_t;
|
||||
|
||||
/*!< Maximum length of value used by Static OOB authentication */
|
||||
#define ESP_BLE_MESH_PROV_STATIC_OOB_MAX_LEN 16
|
||||
|
||||
/*!< Maximum length of string used by Output OOB authentication */
|
||||
#define ESP_BLE_MESH_PROV_OUTPUT_OOB_MAX_LEN 8
|
||||
|
||||
/*!< Maximum length of string used by Output OOB authentication */
|
||||
#define ESP_BLE_MESH_PROV_INPUT_OOB_MAX_LEN 8
|
||||
|
||||
/*!< Macros used to define message opcode */
|
||||
#define ESP_BLE_MESH_MODEL_OP_1(b0) (b0)
|
||||
#define ESP_BLE_MESH_MODEL_OP_2(b0, b1) (((b0) << 8) | (b1))
|
||||
@@ -356,7 +375,8 @@ typedef struct {
|
||||
|
||||
uint16_t publish_addr; /*!< Publish Address. */
|
||||
uint16_t app_idx:12, /*!< Publish AppKey Index. */
|
||||
cred:1; /*!< Friendship Credentials Flag. */
|
||||
cred:1, /*!< Friendship Credentials Flag. */
|
||||
send_rel:1; /*!< Force reliable sending (segment acks) */
|
||||
|
||||
uint8_t ttl; /*!< Publish Time to Live. */
|
||||
uint8_t retransmit; /*!< Retransmit Count & Interval Steps. */
|
||||
@@ -380,11 +400,11 @@ typedef struct {
|
||||
/** Callback used to update publish message. Initialized by the stack. */
|
||||
esp_ble_mesh_cb_t update;
|
||||
|
||||
/** Role of the device that is going to publish messages */
|
||||
uint8_t dev_role;
|
||||
|
||||
/** Publish Period Timer. Initialized by the stack. */
|
||||
struct k_delayed_work timer;
|
||||
|
||||
/** Role of the device that is going to publish messages */
|
||||
uint8_t dev_role;
|
||||
} esp_ble_mesh_model_pub_t;
|
||||
|
||||
/** @def ESP_BLE_MESH_MODEL_PUB_DEFINE
|
||||
@@ -693,7 +713,7 @@ typedef struct {
|
||||
uint8_t dev_key[16]; /*!< Node device key */
|
||||
|
||||
/* Additional information */
|
||||
char name[ESP_BLE_MESH_NODE_NAME_MAX_LEN]; /*!< Node name */
|
||||
char name[ESP_BLE_MESH_NODE_NAME_MAX_LEN + 1]; /*!< Node name */
|
||||
uint16_t comp_length; /*!< Length of Composition Data */
|
||||
uint8_t *comp_data; /*!< Value of Composition Data */
|
||||
} __attribute__((packed)) esp_ble_mesh_node_t;
|
||||
@@ -725,6 +745,36 @@ typedef enum {
|
||||
PROXY_FILTER_BLACKLIST,
|
||||
} esp_ble_mesh_proxy_filter_type_t;
|
||||
|
||||
/** Count for sending BLE advertising packet infinitely */
|
||||
#define ESP_BLE_MESH_BLE_ADV_INFINITE 0xFFFF
|
||||
|
||||
/*!< This enum value is the priority of BLE advertising packet */
|
||||
typedef enum {
|
||||
ESP_BLE_MESH_BLE_ADV_PRIO_LOW,
|
||||
ESP_BLE_MESH_BLE_ADV_PRIO_HIGH,
|
||||
} esp_ble_mesh_ble_adv_priority_t;
|
||||
|
||||
/** Context of BLE advertising parameters. */
|
||||
typedef struct {
|
||||
uint16_t interval; /*!< BLE advertising interval */
|
||||
uint8_t adv_type; /*!< BLE advertising type */
|
||||
uint8_t own_addr_type; /*!< Own address type */
|
||||
uint8_t peer_addr_type; /*!< Peer address type */
|
||||
uint8_t peer_addr[BD_ADDR_LEN]; /*!< Peer address */
|
||||
uint16_t duration; /*!< Duration is milliseconds */
|
||||
uint16_t period; /*!< Period in milliseconds */
|
||||
uint16_t count; /*!< Number of advertising duration */
|
||||
uint8_t priority:2; /*!< Priority of BLE advertising packet */
|
||||
} esp_ble_mesh_ble_adv_param_t;
|
||||
|
||||
/** Context of BLE advertising data. */
|
||||
typedef struct {
|
||||
uint8_t adv_data_len; /*!< Advertising data length */
|
||||
uint8_t adv_data[31]; /*!< Advertising data */
|
||||
uint8_t scan_rsp_data_len; /*!< Scan response data length */
|
||||
uint8_t scan_rsp_data[31]; /*!< Scan response data */
|
||||
} esp_ble_mesh_ble_adv_data_t;
|
||||
|
||||
/*!< This enum value is the event of node/provisioner/fast provisioning */
|
||||
typedef enum {
|
||||
ESP_BLE_MESH_PROV_REGISTER_COMP_EVT, /*!< Initialize BLE Mesh provisioning capabilities and internal data information completion event */
|
||||
@@ -792,6 +842,9 @@ typedef enum {
|
||||
ESP_BLE_MESH_PROXY_CLIENT_SET_FILTER_TYPE_COMP_EVT, /*!< Proxy Client set filter type completion event */
|
||||
ESP_BLE_MESH_PROXY_CLIENT_ADD_FILTER_ADDR_COMP_EVT, /*!< Proxy Client add filter address completion event */
|
||||
ESP_BLE_MESH_PROXY_CLIENT_REMOVE_FILTER_ADDR_COMP_EVT, /*!< Proxy Client remove filter address completion event */
|
||||
ESP_BLE_MESH_START_BLE_ADVERTISING_COMP_EVT, /*!< Start BLE advertising completion event */
|
||||
ESP_BLE_MESH_STOP_BLE_ADVERTISING_COMP_EVT, /*!< Stop BLE advertising completion event */
|
||||
ESP_BLE_MESH_DEINIT_MESH_COMP_EVT, /*!< De-initialize BLE Mesh stack completion event */
|
||||
ESP_BLE_MESH_PROV_EVT_MAX,
|
||||
} esp_ble_mesh_prov_cb_event_t;
|
||||
|
||||
@@ -911,12 +964,12 @@ typedef union {
|
||||
* @brief ESP_BLE_MESH_PROVISIONER_RECV_UNPROV_ADV_PKT_EVT
|
||||
*/
|
||||
struct ble_mesh_provisioner_recv_unprov_adv_pkt_param {
|
||||
uint8_t dev_uuid[16]; /*!< Device UUID of the unprovisoned device */
|
||||
esp_ble_mesh_bd_addr_t addr; /*!< Device address of the unprovisoned device */
|
||||
uint8_t dev_uuid[16]; /*!< Device UUID of the unprovisioned device */
|
||||
esp_ble_mesh_bd_addr_t addr; /*!< Device address of the unprovisioned device */
|
||||
esp_ble_mesh_addr_type_t addr_type; /*!< Device address type */
|
||||
uint16_t oob_info; /*!< OOB Info of the unprovisoned device */
|
||||
uint8_t adv_type; /*!< Avertising type of the unprovisoned device */
|
||||
esp_ble_mesh_prov_bearer_t bearer; /*!< Bearer of the unprovisoned device */
|
||||
uint16_t oob_info; /*!< OOB Info of the unprovisioned device */
|
||||
uint8_t adv_type; /*!< Avertising type of the unprovisioned device */
|
||||
esp_ble_mesh_prov_bearer_t bearer; /*!< Bearer of the unprovisioned device */
|
||||
int8_t rssi; /*!< RSSI of the received advertising packet */
|
||||
} provisioner_recv_unprov_adv_pkt; /*!< Event parameter of ESP_BLE_MESH_PROVISIONER_RECV_UNPROV_ADV_PKT_EVT */
|
||||
/**
|
||||
@@ -1164,7 +1217,7 @@ typedef union {
|
||||
* @brief ESP_BLE_MESH_FRIEND_FRIENDSHIP_ESTABLISH_EVT
|
||||
*/
|
||||
struct ble_mesh_friend_friendship_establish_param {
|
||||
uint16_t lpn_addr; /*!< Low Power Node unciast address */
|
||||
uint16_t lpn_addr; /*!< Low Power Node unicast address */
|
||||
} frnd_friendship_establish; /*!< Event parameter of ESP_BLE_MESH_FRIEND_FRIENDSHIP_ESTABLISH_EVT */
|
||||
/**
|
||||
* @brief ESP_BLE_MESH_FRIEND_FRIENDSHIP_TERMINATE_EVT
|
||||
@@ -1259,6 +1312,26 @@ typedef union {
|
||||
uint8_t conn_handle; /*!< Proxy connection handle */
|
||||
uint16_t net_idx; /*!< Corresponding NetKey Index */
|
||||
} proxy_client_remove_filter_addr_comp; /*!< Event parameter of ESP_BLE_MESH_PROXY_CLIENT_REMOVE_FILTER_ADDR_COMP_EVT */
|
||||
/**
|
||||
* @brief ESP_BLE_MESH_START_BLE_ADVERTISING_COMP_EVT
|
||||
*/
|
||||
struct ble_mesh_start_ble_advertising_comp_param {
|
||||
int err_code; /*!< Indicate the result of starting BLE advertising */
|
||||
uint8_t index; /*!< Index of the BLE advertising */
|
||||
} start_ble_advertising_comp; /*!< Event parameter of ESP_BLE_MESH_START_BLE_ADVERTISING_COMP_EVT */
|
||||
/**
|
||||
* @brief ESP_BLE_MESH_STOP_BLE_ADVERTISING_COMP_EVT
|
||||
*/
|
||||
struct ble_mesh_stop_ble_advertising_comp_param {
|
||||
int err_code; /*!< Indicate the result of stopping BLE advertising */
|
||||
uint8_t index; /*!< Index of the BLE advertising */
|
||||
} stop_ble_advertising_comp; /*!< Event parameter of ESP_BLE_MESH_STOP_BLE_ADVERTISING_COMP_EVT */
|
||||
/**
|
||||
* @brief ESP_BLE_MESH_DEINIT_MESH_COMP_EVT
|
||||
*/
|
||||
struct ble_mesh_deinit_mesh_comp_param {
|
||||
int err_code; /*!< Indicate the result of BLE Mesh deinitialization */
|
||||
} deinit_mesh_comp; /*!< Event parameter of ESP_BLE_MESH_DEINIT_MESH_COMP_EVT */
|
||||
} esp_ble_mesh_prov_cb_param_t;
|
||||
|
||||
/**
|
||||
@@ -1365,7 +1438,7 @@ typedef uint32_t esp_ble_mesh_opcode_config_client_set_t;
|
||||
#define ESP_BLE_MESH_MODEL_OP_RELAY_SET ESP_BLE_MESH_MODEL_OP_2(0x80, 0x27) /*!< Config Relay Set */
|
||||
#define ESP_BLE_MESH_MODEL_OP_MODEL_PUB_SET ESP_BLE_MESH_MODEL_OP_1(0x03) /*!< Config Model Publication Set */
|
||||
#define ESP_BLE_MESH_MODEL_OP_MODEL_SUB_ADD ESP_BLE_MESH_MODEL_OP_2(0x80, 0x1B) /*!< Config Model Subscription Add */
|
||||
#define ESP_BLE_MESH_MODEL_OP_MODEL_SUB_VIRTUAL_ADDR_ADD ESP_BLE_MESH_MODEL_OP_2(0x80, 0x20) /*!< Config Model Subscription Vritual Address Add */
|
||||
#define ESP_BLE_MESH_MODEL_OP_MODEL_SUB_VIRTUAL_ADDR_ADD ESP_BLE_MESH_MODEL_OP_2(0x80, 0x20) /*!< Config Model Subscription Virtual Address Add */
|
||||
#define ESP_BLE_MESH_MODEL_OP_MODEL_SUB_DELETE ESP_BLE_MESH_MODEL_OP_2(0x80, 0x1C) /*!< Config Model Subscription Delete */
|
||||
#define ESP_BLE_MESH_MODEL_OP_MODEL_SUB_VIRTUAL_ADDR_DELETE ESP_BLE_MESH_MODEL_OP_2(0x80, 0x21) /*!< Config Model Subscription Virtual Address Delete */
|
||||
#define ESP_BLE_MESH_MODEL_OP_MODEL_SUB_OVERWRITE ESP_BLE_MESH_MODEL_OP_2(0x80, 0x1E) /*!< Config Model Subscription Overwrite */
|
||||
@@ -1798,7 +1871,7 @@ typedef struct {
|
||||
esp_ble_mesh_model_t *model; /*!< Pointer to the client model. Initialized by the stack. */
|
||||
int op_pair_size; /*!< Size of the op_pair */
|
||||
const esp_ble_mesh_client_op_pair_t *op_pair; /*!< Table containing get/set message opcode and corresponding status message opcode */
|
||||
uint32_t publish_status; /*!< Callback used to handle the received unsoliciated message. Initialized by the stack. */
|
||||
uint32_t publish_status; /*!< Callback used to handle the received unsolicited message. Initialized by the stack. */
|
||||
void *internal_data; /*!< Pointer to the internal data of client model */
|
||||
uint8_t msg_role; /*!< Role of the device (Node/Provisioner) that is going to send messages */
|
||||
} esp_ble_mesh_client_t;
|
||||
@@ -1852,7 +1925,7 @@ typedef struct {
|
||||
typedef struct {
|
||||
uint8_t tid; /*!< Transaction number of the last message */
|
||||
uint16_t src; /*!< Source address of the last message */
|
||||
uint16_t dst; /*!< Destination address of the last messgae */
|
||||
uint16_t dst; /*!< Destination address of the last message */
|
||||
int64_t timestamp; /*!< Time when the last message is received */
|
||||
} esp_ble_mesh_last_msg_info_t;
|
||||
|
||||
@@ -1965,7 +2038,7 @@ typedef union {
|
||||
* @brief ESP_BLE_MESH_MODEL_OPERATION_EVT
|
||||
*/
|
||||
struct ble_mesh_model_operation_evt_param {
|
||||
uint32_t opcode; /*!< Opcode of the recieved message */
|
||||
uint32_t opcode; /*!< Opcode of the received message */
|
||||
esp_ble_mesh_model_t *model; /*!< Pointer to the model which receives the message */
|
||||
esp_ble_mesh_msg_ctx_t *ctx; /*!< Pointer to the context of the received message */
|
||||
uint16_t length; /*!< Length of the received message */
|
||||
@@ -1991,7 +2064,7 @@ typedef union {
|
||||
* @brief ESP_BLE_MESH_CLIENT_MODEL_RECV_PUBLISH_MSG_EVT
|
||||
*/
|
||||
struct ble_mesh_mod_recv_publish_msg_param {
|
||||
uint32_t opcode; /*!< Opcode of the unsoliciated received message */
|
||||
uint32_t opcode; /*!< Opcode of the unsolicited received message */
|
||||
esp_ble_mesh_model_t *model; /*!< Pointer to the model which receives the message */
|
||||
esp_ble_mesh_msg_ctx_t *ctx; /*!< Pointer to the context of the message */
|
||||
uint16_t length; /*!< Length of the received message */
|
||||
@@ -2021,4 +2094,8 @@ typedef union {
|
||||
} server_model_update_state; /*!< Event parameter of ESP_BLE_MESH_SERVER_MODEL_UPDATE_STATE_COMP_EVT */
|
||||
} esp_ble_mesh_model_cb_param_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _ESP_BLE_MESH_DEFS_H_ */
|
||||
|
||||
@@ -17,6 +17,10 @@
|
||||
|
||||
#include "esp_ble_mesh_defs.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @def ESP_BLE_MESH_MODEL_CFG_SRV
|
||||
*
|
||||
* @brief Define a new Config Server Model.
|
||||
@@ -814,5 +818,9 @@ esp_err_t esp_ble_mesh_config_client_get_state(esp_ble_mesh_client_common_param_
|
||||
esp_err_t esp_ble_mesh_config_client_set_state(esp_ble_mesh_client_common_param_t *params,
|
||||
esp_ble_mesh_cfg_client_set_state_t *set_state);
|
||||
|
||||
#endif /** _ESP_BLE_MESH_CONFIG_MODEL_API_H_ */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _ESP_BLE_MESH_CONFIG_MODEL_API_H_ */
|
||||
|
||||
|
||||
@@ -21,6 +21,10 @@
|
||||
|
||||
#include "esp_ble_mesh_defs.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @def ESP_BLE_MESH_MODEL_GEN_ONOFF_CLI
|
||||
*
|
||||
* @brief Define a new Generic OnOff Client Model.
|
||||
@@ -256,7 +260,7 @@ typedef struct {
|
||||
/** Parameters of Generic Admin Property Set. */
|
||||
typedef struct {
|
||||
uint16_t property_id; /*!< Property ID identifying a Generic Admin Property */
|
||||
uint8_t user_access; /*!< Enumeration indicating user accessn */
|
||||
uint8_t user_access; /*!< Enumeration indicating user access */
|
||||
struct net_buf_simple *property_value; /*!< Raw value for the Admin Property */
|
||||
} esp_ble_mesh_gen_admin_property_set_t;
|
||||
|
||||
@@ -1293,5 +1297,9 @@ typedef void (* esp_ble_mesh_generic_server_cb_t)(esp_ble_mesh_generic_server_cb
|
||||
*/
|
||||
esp_err_t esp_ble_mesh_register_generic_server_callback(esp_ble_mesh_generic_server_cb_t callback);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _ESP_BLE_MESH_GENERIC_MODEL_API_H_ */
|
||||
|
||||
|
||||
@@ -17,6 +17,10 @@
|
||||
|
||||
#include "esp_ble_mesh_defs.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @def ESP_BLE_MESH_MODEL_HEALTH_SRV
|
||||
*
|
||||
* @brief Define a new Health Server Model.
|
||||
@@ -403,4 +407,8 @@ esp_err_t esp_ble_mesh_health_client_set_state(esp_ble_mesh_client_common_param_
|
||||
*/
|
||||
esp_err_t esp_ble_mesh_health_server_fault_update(esp_ble_mesh_elem_t *element);
|
||||
|
||||
#endif /** _ESP_BLE_MESH_HEALTH_MODEL_API_H_ */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _ESP_BLE_MESH_HEALTH_MODEL_API_H_ */
|
||||
|
||||
@@ -21,6 +21,10 @@
|
||||
|
||||
#include "esp_ble_mesh_defs.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @def ESP_BLE_MESH_MODEL_LIGHT_LIGHTNESS_CLI
|
||||
*
|
||||
* @brief Define a new Light Lightness Client Model.
|
||||
@@ -1061,7 +1065,7 @@ typedef struct {
|
||||
* Occupancy state upon receiving a Sensor Status message from an
|
||||
* occupancy sensor.
|
||||
*/
|
||||
uint32_t time_occupancy_delay; /*!< The value of Light LC Time Occupany Delay state */
|
||||
uint32_t time_occupancy_delay; /*!< The value of Light LC Time Occupancy Delay state */
|
||||
/**
|
||||
* A timing state that determines the time the controlled lights fade
|
||||
* to the level determined by the Light LC Lightness On state.
|
||||
@@ -1341,7 +1345,7 @@ typedef struct {
|
||||
|
||||
/** Parameter of Light LC Occupancy Mode state change event */
|
||||
typedef struct {
|
||||
uint8_t mode; /*!< The value of Light LC Occupany Mode state */
|
||||
uint8_t mode; /*!< The value of Light LC Occupancy Mode state */
|
||||
} esp_ble_mesh_state_change_light_lc_om_set_t;
|
||||
|
||||
/** Parameter of Light LC Light OnOff state change event */
|
||||
@@ -1671,5 +1675,9 @@ typedef void (* esp_ble_mesh_lighting_server_cb_t)(esp_ble_mesh_lighting_server_
|
||||
*/
|
||||
esp_err_t esp_ble_mesh_register_lighting_server_callback(esp_ble_mesh_lighting_server_cb_t callback);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _ESP_BLE_MESH_LIGHTING_MODEL_API_H_ */
|
||||
|
||||
|
||||
@@ -21,6 +21,10 @@
|
||||
|
||||
#include "esp_ble_mesh_defs.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @def ESP_BLE_MESH_MODEL_SENSOR_CLI
|
||||
*
|
||||
* @brief Define a new Sensor Client Model.
|
||||
@@ -345,6 +349,91 @@ esp_err_t esp_ble_mesh_sensor_client_set_state(esp_ble_mesh_client_common_param_
|
||||
*/
|
||||
#define ESP_BLE_MESH_SENSOR_DATA_ZERO_LEN 0x7F
|
||||
|
||||
/** @def ESP_BLE_MESH_GET_SENSOR_DATA_FORMAT
|
||||
*
|
||||
* @brief Get format of the sensor data.
|
||||
*
|
||||
* @note Multiple sensor data may be concatenated. Make sure the _data pointer is
|
||||
* updated before getting the format of the corresponding sensor data.
|
||||
*
|
||||
* @param _data Pointer to the start of the sensor data.
|
||||
*
|
||||
* @return Format of the sensor data.
|
||||
*/
|
||||
#define ESP_BLE_MESH_GET_SENSOR_DATA_FORMAT(_data) (((_data)[0]) & BIT_MASK(1))
|
||||
|
||||
/** @def ESP_BLE_MESH_GET_SENSOR_DATA_LENGTH
|
||||
*
|
||||
* @brief Get length of the sensor data.
|
||||
*
|
||||
* @note Multiple sensor data may be concatenated. Make sure the _data pointer is
|
||||
* updated before getting the length of the corresponding sensor data.
|
||||
*
|
||||
* @param _data Pointer to the start of the sensor data.
|
||||
* @param _fmt Format of the sensor data.
|
||||
*
|
||||
* @return Length (zero-based) of the sensor data.
|
||||
*/
|
||||
#define ESP_BLE_MESH_GET_SENSOR_DATA_LENGTH(_data, _fmt) \
|
||||
(((_fmt) == ESP_BLE_MESH_SENSOR_DATA_FORMAT_A) ? ((((_data)[0]) >> 1) & BIT_MASK(4)) : ((((_data)[0]) >> 1) & BIT_MASK(7)))
|
||||
|
||||
/** @def ESP_BLE_MESH_GET_SENSOR_DATA_PROPERTY_ID
|
||||
*
|
||||
* @brief Get Sensor Property ID of the sensor data.
|
||||
*
|
||||
* @note Multiple sensor data may be concatenated. Make sure the _data pointer is
|
||||
* updated before getting Sensor Property ID of the corresponding sensor data.
|
||||
*
|
||||
* @param _data Pointer to the start of the sensor data.
|
||||
* @param _fmt Format of the sensor data.
|
||||
*
|
||||
* @return Sensor Property ID of the sensor data.
|
||||
*/
|
||||
#define ESP_BLE_MESH_GET_SENSOR_DATA_PROPERTY_ID(_data, _fmt) \
|
||||
(((_fmt) == ESP_BLE_MESH_SENSOR_DATA_FORMAT_A) ? ((((_data)[1]) << 3) | (((_data)[0]) >> 5)) : ((((_data)[2]) << 8) | ((_data)[1])))
|
||||
|
||||
/** @def ESP_BLE_MESH_SENSOR_DATA_FORMAT_A_MPID
|
||||
*
|
||||
* @brief Generate a MPID value for sensor data with Format A.
|
||||
*
|
||||
* @note 1. The Format field is 0b0 and indicates that Format A is used.
|
||||
* 2. The Length field is a 1-based uint4 value (valid range 0x0–0xF,
|
||||
* representing range of 1–16).
|
||||
* 3. The Property ID is an 11-bit bit field representing 11 LSb of a Property ID.
|
||||
* 4. This format may be used for Property Values that are not longer than 16
|
||||
* octets and for Property IDs less than 0x0800.
|
||||
*
|
||||
* @param _len Length of Sensor Raw value.
|
||||
* @param _id Sensor Property ID.
|
||||
*
|
||||
* @return 2-octet MPID value for sensor data with Format A.
|
||||
*
|
||||
*/
|
||||
#define ESP_BLE_MESH_SENSOR_DATA_FORMAT_A_MPID(_len, _id) \
|
||||
((((_id) & BIT_MASK(11)) << 5) | (((_len) & BIT_MASK(4)) << 1) | ESP_BLE_MESH_SENSOR_DATA_FORMAT_A)
|
||||
|
||||
/** @def ESP_BLE_MESH_SENSOR_DATA_FORMAT_B_MPID
|
||||
*
|
||||
* @brief Generate a MPID value for sensor data with Format B.
|
||||
*
|
||||
* @note 1. The Format field is 0b1 and indicates Format B is used.
|
||||
* 2. The Length field is a 1-based uint7 value (valid range 0x0–0x7F, representing
|
||||
* range of 1–127). The value 0x7F represents a length of zero.
|
||||
* 3. The Property ID is a 16-bit bit field representing a Property ID.
|
||||
* 4. This format may be used for Property Values not longer than 128 octets and for
|
||||
* any Property IDs. Property values longer than 128 octets are not supported by
|
||||
* the Sensor Status message.
|
||||
* 5. Exclude the generated 1-octet value, the 2-octet Sensor Property ID
|
||||
*
|
||||
* @param _len Length of Sensor Raw value.
|
||||
* @param _id Sensor Property ID.
|
||||
*
|
||||
* @return 3-octet MPID value for sensor data with Format B.
|
||||
*
|
||||
*/
|
||||
#define ESP_BLE_MESH_SENSOR_DATA_FORMAT_B_MPID(_len, _id) \
|
||||
(((_id) << 8) | (((_len) & BIT_MASK(7)) << 1) | ESP_BLE_MESH_SENSOR_DATA_FORMAT_B)
|
||||
|
||||
/** This enum value is value of Sensor Sampling Function */
|
||||
enum esp_ble_mesh_sensor_sample_func {
|
||||
ESP_BLE_MESH_SAMPLE_FUNC_UNSPECIFIED,
|
||||
@@ -523,7 +612,7 @@ typedef struct {
|
||||
typedef struct {
|
||||
bool op_en; /*!< Indicate if optional parameters are included */
|
||||
uint16_t property_id; /*!< Property identifying a sensor */
|
||||
struct net_buf_simple *raw_value; /*!< Raw value containg X1 and X2 (optional) */
|
||||
struct net_buf_simple *raw_value; /*!< Raw value containing X1 and X2 (optional) */
|
||||
} esp_ble_mesh_server_recv_sensor_series_get_t;
|
||||
|
||||
/**
|
||||
@@ -621,6 +710,10 @@ typedef void (* esp_ble_mesh_sensor_server_cb_t)(esp_ble_mesh_sensor_server_cb_e
|
||||
*/
|
||||
esp_err_t esp_ble_mesh_register_sensor_server_callback(esp_ble_mesh_sensor_server_cb_t callback);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _ESP_BLE_MESH_SENSOR_MODEL_API_H_ */
|
||||
|
||||
|
||||
|
||||
@@ -21,6 +21,10 @@
|
||||
|
||||
#include "esp_ble_mesh_defs.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @def ESP_BLE_MESH_MODEL_TIME_CLI
|
||||
*
|
||||
* @brief Define a new Time Client Model.
|
||||
@@ -434,11 +438,11 @@ esp_err_t esp_ble_mesh_time_scene_client_set_state(esp_ble_mesh_client_common_pa
|
||||
#define ESP_BLE_MESH_UNKNOWN_TAI_ZONE_CHANGE 0x0000000000 /*!< Unknown TAI of Zone Change */
|
||||
#define ESP_BLE_MESH_UNKNOWN_TAI_DELTA_CHANGE 0x0000000000 /*!< Unknown TAI of Delta Change */
|
||||
|
||||
#define ESP_BLE_MESH_TAI_UTC_DELAT_MAX_VALUE 0x7FFF /*!< Maximum TAI-UTC Delta value */
|
||||
#define ESP_BLE_MESH_TAI_UTC_DELTA_MAX_VALUE 0x7FFF /*!< Maximum TAI-UTC Delta value */
|
||||
|
||||
#define ESP_BLE_MESH_TAI_SECONDS_LEN 0x05 /*!< Length of TAI Seconds */
|
||||
#define ESP_BLE_MESH_TAI_OF_ZONE_CHANGE_LEN 0x05 /*!< Length of TAI of Zone Change */
|
||||
#define ESP_BLE_MESH_TAI_OF_DELAT_CHANGE_LEN 0x05 /*!< Length of TAI of Delta Change */
|
||||
#define ESP_BLE_MESH_TAI_OF_DELTA_CHANGE_LEN 0x05 /*!< Length of TAI of Delta Change */
|
||||
|
||||
#define ESP_BLE_MESH_INVALID_SCENE_NUMBER 0x0000 /*!< Invalid Scene Number */
|
||||
#define ESP_BLE_MESH_SCENE_NUMBER_LEN 0x02 /*!< Length of the Scene Number */
|
||||
@@ -908,5 +912,9 @@ typedef void (* esp_ble_mesh_time_scene_server_cb_t)(esp_ble_mesh_time_scene_ser
|
||||
*/
|
||||
esp_err_t esp_ble_mesh_register_time_scene_server_callback(esp_ble_mesh_time_scene_server_cb_t callback);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _ESP_BLE_MESH_TIME_SCENE_MODEL_API_H_ */
|
||||
|
||||
|
||||
@@ -15,11 +15,9 @@
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "foundation.h"
|
||||
#include "mesh_common.h"
|
||||
#include "cfg_cli.h"
|
||||
|
||||
#include "btc_ble_mesh_config_model.h"
|
||||
#include "foundation.h"
|
||||
#include "cfg_cli.h"
|
||||
#include "esp_ble_mesh_config_model_api.h"
|
||||
|
||||
#define CID_NVAL 0xffff
|
||||
|
||||
@@ -15,10 +15,8 @@
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "mesh_common.h"
|
||||
#include "generic_client.h"
|
||||
|
||||
#include "btc_ble_mesh_generic_model.h"
|
||||
#include "generic_client.h"
|
||||
#include "esp_ble_mesh_generic_model_api.h"
|
||||
|
||||
/* Generic Client Models related functions */
|
||||
|
||||
@@ -15,13 +15,11 @@
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "btc_ble_mesh_health_model.h"
|
||||
#include "foundation.h"
|
||||
#include "mesh_common.h"
|
||||
#include "health_srv.h"
|
||||
#include "health_cli.h"
|
||||
|
||||
#include "btc_ble_mesh_health_model.h"
|
||||
#include "esp_ble_mesh_defs.h"
|
||||
#include "esp_ble_mesh_health_model_api.h"
|
||||
|
||||
extern s32_t health_msg_timeout;
|
||||
|
||||
|
||||
@@ -15,10 +15,8 @@
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "mesh_common.h"
|
||||
#include "lighting_client.h"
|
||||
|
||||
#include "btc_ble_mesh_lighting_model.h"
|
||||
#include "lighting_client.h"
|
||||
#include "esp_ble_mesh_lighting_model_api.h"
|
||||
|
||||
/* Lighting Client Models related functions */
|
||||
|
||||
@@ -15,9 +15,16 @@
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "btc_ble_mesh_prov.h"
|
||||
#include "btc_ble_mesh_config_model.h"
|
||||
#include "btc_ble_mesh_health_model.h"
|
||||
#include "btc_ble_mesh_generic_model.h"
|
||||
#include "btc_ble_mesh_time_scene_model.h"
|
||||
#include "btc_ble_mesh_sensor_model.h"
|
||||
#include "btc_ble_mesh_lighting_model.h"
|
||||
|
||||
#include "adv.h"
|
||||
#include "mesh_kernel.h"
|
||||
#include "mesh_proxy.h"
|
||||
#include "mesh.h"
|
||||
#include "access.h"
|
||||
@@ -38,15 +45,6 @@
|
||||
#include "client_common.h"
|
||||
#include "state_binding.h"
|
||||
|
||||
#include "btc_ble_mesh_prov.h"
|
||||
#include "btc_ble_mesh_config_model.h"
|
||||
#include "btc_ble_mesh_health_model.h"
|
||||
#include "btc_ble_mesh_generic_model.h"
|
||||
#include "btc_ble_mesh_time_scene_model.h"
|
||||
#include "btc_ble_mesh_sensor_model.h"
|
||||
#include "btc_ble_mesh_lighting_model.h"
|
||||
|
||||
#include "esp_ble_mesh_defs.h"
|
||||
#include "esp_ble_mesh_common_api.h"
|
||||
#include "esp_ble_mesh_provisioning_api.h"
|
||||
#include "esp_ble_mesh_networking_api.h"
|
||||
@@ -559,7 +557,8 @@ static int btc_ble_mesh_output_string_cb(const char *str)
|
||||
|
||||
BT_DBG("%s", __func__);
|
||||
|
||||
strncpy(mesh_param.node_prov_output_str.string, str, strlen(str));
|
||||
strncpy(mesh_param.node_prov_output_str.string, str,
|
||||
MIN(strlen(str), sizeof(mesh_param.node_prov_output_str.string)));
|
||||
|
||||
ret = btc_ble_mesh_prov_callback(&mesh_param, ESP_BLE_MESH_NODE_PROV_OUTPUT_STRING_EVT);
|
||||
return (ret == BT_STATUS_SUCCESS) ? 0 : -1;
|
||||
@@ -934,11 +933,6 @@ static void btc_ble_mesh_proxy_client_filter_status_recv_cb(u8_t conn_handle,
|
||||
}
|
||||
#endif /* CONFIG_BLE_MESH_GATT_PROXY_CLIENT */
|
||||
|
||||
int btc_ble_mesh_deinit(esp_ble_mesh_deinit_param_t *param)
|
||||
{
|
||||
return bt_mesh_deinit((struct bt_mesh_deinit_param *)param);
|
||||
}
|
||||
|
||||
int btc_ble_mesh_client_model_init(esp_ble_mesh_model_t *model)
|
||||
{
|
||||
__ASSERT(model && model->op, "%s, Invalid parameter", __func__);
|
||||
@@ -998,7 +992,7 @@ const esp_ble_mesh_comp_t *btc_ble_mesh_comp_get(void)
|
||||
|
||||
u16_t btc_ble_mesh_provisioner_get_prov_node_count(void)
|
||||
{
|
||||
return bt_mesh_provisioner_get_prov_node_count();
|
||||
return bt_mesh_provisioner_get_node_count();
|
||||
}
|
||||
|
||||
/* Configuration Models */
|
||||
@@ -1577,7 +1571,7 @@ void btc_ble_mesh_prov_call_handler(btc_msg_t *msg)
|
||||
break;
|
||||
case BTC_BLE_MESH_ACT_NODE_RESET:
|
||||
BT_DBG("%s, BTC_BLE_MESH_ACT_NODE_RESET", __func__);
|
||||
bt_mesh_reset();
|
||||
bt_mesh_node_reset();
|
||||
return;
|
||||
case BTC_BLE_MESH_ACT_SET_OOB_PUB_KEY:
|
||||
act = ESP_BLE_MESH_NODE_PROV_SET_OOB_PUB_KEY_COMP_EVT;
|
||||
@@ -1787,7 +1781,7 @@ void btc_ble_mesh_prov_call_handler(btc_msg_t *msg)
|
||||
act = ESP_BLE_MESH_PROVISIONER_DELETE_NODE_WITH_ADDR_COMP_EVT;
|
||||
param.provisioner_delete_node_with_addr_comp.unicast_addr = arg->delete_node_with_addr.unicast_addr;
|
||||
param.provisioner_delete_node_with_addr_comp.err_code =
|
||||
bt_mesh_provisioner_delete_node_with_addr(arg->delete_node_with_addr.unicast_addr);
|
||||
bt_mesh_provisioner_delete_node_with_node_addr(arg->delete_node_with_addr.unicast_addr);
|
||||
break;
|
||||
#endif /* CONFIG_BLE_MESH_PROVISIONER */
|
||||
#if CONFIG_BLE_MESH_FAST_PROV
|
||||
@@ -1884,6 +1878,30 @@ void btc_ble_mesh_prov_call_handler(btc_msg_t *msg)
|
||||
break;
|
||||
}
|
||||
#endif /* CONFIG_BLE_MESH_GATT_PROXY_CLIENT */
|
||||
#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV
|
||||
case BTC_BLE_MESH_ACT_START_BLE_ADVERTISING: {
|
||||
struct bt_mesh_ble_adv_param *set = (struct bt_mesh_ble_adv_param *)&arg->start_ble_advertising.param;
|
||||
struct bt_mesh_ble_adv_data *data = NULL;
|
||||
if (arg->start_ble_advertising.data.adv_data_len ||
|
||||
arg->start_ble_advertising.data.scan_rsp_data_len) {
|
||||
data = (struct bt_mesh_ble_adv_data *)&arg->start_ble_advertising.data;
|
||||
}
|
||||
act = ESP_BLE_MESH_START_BLE_ADVERTISING_COMP_EVT;
|
||||
param.start_ble_advertising_comp.err_code =
|
||||
bt_mesh_start_ble_advertising(set, data, ¶m.start_ble_advertising_comp.index);
|
||||
break;
|
||||
}
|
||||
case BTC_BLE_MESH_ACT_STOP_BLE_ADVERTISING:
|
||||
act = ESP_BLE_MESH_STOP_BLE_ADVERTISING_COMP_EVT;
|
||||
param.stop_ble_advertising_comp.index = arg->stop_ble_advertising.index;
|
||||
param.stop_ble_advertising_comp.err_code =
|
||||
bt_mesh_stop_ble_advertising(arg->stop_ble_advertising.index);
|
||||
break;
|
||||
#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */
|
||||
case BTC_BLE_MESH_ACT_DEINIT_MESH:
|
||||
act = ESP_BLE_MESH_DEINIT_MESH_COMP_EVT;
|
||||
param.deinit_mesh_comp.err_code = bt_mesh_deinit((struct bt_mesh_deinit_param *)&arg->mesh_deinit.param);
|
||||
break;
|
||||
default:
|
||||
BT_WARN("%s, Invalid msg->act %d", __func__, msg->act);
|
||||
return;
|
||||
@@ -1944,8 +1962,8 @@ void btc_ble_mesh_model_call_handler(btc_msg_t *msg)
|
||||
break;
|
||||
}
|
||||
case BTC_BLE_MESH_ACT_SERVER_MODEL_SEND: {
|
||||
/* arg->model_send.length contains opcode & message, 4 is used for TransMIC */
|
||||
struct net_buf_simple *buf = bt_mesh_alloc_buf(arg->model_send.length + 4);
|
||||
/* arg->model_send.length contains opcode & payload, plus extra 4-bytes TransMIC */
|
||||
struct net_buf_simple *buf = bt_mesh_alloc_buf(arg->model_send.length + BLE_MESH_MIC_SHORT);
|
||||
if (!buf) {
|
||||
BT_ERR("%s, Failed to allocate memory", __func__);
|
||||
break;
|
||||
@@ -1962,8 +1980,8 @@ void btc_ble_mesh_model_call_handler(btc_msg_t *msg)
|
||||
}
|
||||
case BTC_BLE_MESH_ACT_CLIENT_MODEL_SEND: {
|
||||
bt_mesh_role_param_t common = {0};
|
||||
/* arg->model_send.length contains opcode & message, 4 is used for TransMIC */
|
||||
struct net_buf_simple *buf = bt_mesh_alloc_buf(arg->model_send.length + 4);
|
||||
/* arg->model_send.length contains opcode & message, plus extra 4-bytes TransMIC */
|
||||
struct net_buf_simple *buf = bt_mesh_alloc_buf(arg->model_send.length + BLE_MESH_MIC_SHORT);
|
||||
if (!buf) {
|
||||
BT_ERR("%s, Failed to allocate memory", __func__);
|
||||
break;
|
||||
|
||||
@@ -15,10 +15,8 @@
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "mesh_common.h"
|
||||
#include "sensor_client.h"
|
||||
|
||||
#include "btc_ble_mesh_sensor_model.h"
|
||||
#include "sensor_client.h"
|
||||
#include "esp_ble_mesh_sensor_model_api.h"
|
||||
|
||||
/* Sensor Client Models related functions */
|
||||
|
||||
@@ -15,10 +15,8 @@
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "mesh_common.h"
|
||||
#include "time_scene_client.h"
|
||||
|
||||
#include "btc_ble_mesh_time_scene_model.h"
|
||||
#include "time_scene_client.h"
|
||||
#include "esp_ble_mesh_time_scene_model_api.h"
|
||||
|
||||
/* Time and Scenes Client Models related functions */
|
||||
|
||||
@@ -18,6 +18,10 @@
|
||||
#include "btc/btc_manage.h"
|
||||
#include "esp_ble_mesh_config_model_api.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
BTC_BLE_MESH_ACT_CONFIG_CLIENT_GET_STATE,
|
||||
BTC_BLE_MESH_ACT_CONFIG_CLIENT_SET_STATE,
|
||||
@@ -71,4 +75,8 @@ void bt_mesh_config_server_cb_evt_to_btc(u8_t evt_type,
|
||||
struct bt_mesh_msg_ctx *ctx,
|
||||
const u8_t *val, size_t len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _BTC_BLE_MESH_CONFIG_MODEL_H_ */
|
||||
|
||||
@@ -18,6 +18,10 @@
|
||||
#include "btc/btc_manage.h"
|
||||
#include "esp_ble_mesh_generic_model_api.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
BTC_BLE_MESH_ACT_GENERIC_CLIENT_GET_STATE,
|
||||
BTC_BLE_MESH_ACT_GENERIC_CLIENT_SET_STATE,
|
||||
@@ -73,4 +77,8 @@ void bt_mesh_generic_server_cb_evt_to_btc(u8_t evt_type,
|
||||
|
||||
void btc_ble_mesh_generic_server_cb_handler(btc_msg_t *msg);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _BTC_BLE_MESH_GENERIC_MODEL_H_ */
|
||||
|
||||
@@ -18,6 +18,10 @@
|
||||
#include "btc/btc_manage.h"
|
||||
#include "esp_ble_mesh_health_model_api.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
BTC_BLE_MESH_ACT_HEALTH_CLIENT_GET_STATE,
|
||||
BTC_BLE_MESH_ACT_HEALTH_CLIENT_SET_STATE,
|
||||
@@ -84,4 +88,8 @@ void btc_ble_mesh_health_server_attention_on(struct bt_mesh_model *model, u8_t t
|
||||
|
||||
void btc_ble_mesh_health_server_attention_off(struct bt_mesh_model *model);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _BTC_BLE_MESH_HEALTH_MODEL_H_ */
|
||||
|
||||
@@ -18,6 +18,10 @@
|
||||
#include "btc/btc_manage.h"
|
||||
#include "esp_ble_mesh_lighting_model_api.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
BTC_BLE_MESH_ACT_LIGHTING_CLIENT_GET_STATE,
|
||||
BTC_BLE_MESH_ACT_LIGHTING_CLIENT_SET_STATE,
|
||||
@@ -74,5 +78,9 @@ void bt_mesh_lighting_server_cb_evt_to_btc(u8_t evt_type,
|
||||
|
||||
void btc_ble_mesh_lighting_server_cb_handler(btc_msg_t *msg);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _BTC_BLE_MESH_LIGHTING_MODEL_H_ */
|
||||
|
||||
|
||||
@@ -16,10 +16,15 @@
|
||||
#define _BTC_BLE_MESH_PROV_H_
|
||||
|
||||
#include "btc/btc_manage.h"
|
||||
#include "mesh_byteorder.h"
|
||||
#include "mesh_main.h"
|
||||
#include "provisioner_prov.h"
|
||||
#include "esp_ble_mesh_defs.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
BTC_BLE_MESH_ACT_MESH_INIT = 0,
|
||||
BTC_BLE_MESH_ACT_PROV_ENABLE,
|
||||
@@ -63,6 +68,9 @@ typedef enum {
|
||||
BTC_BLE_MESH_ACT_PROXY_CLIENT_SET_FILTER_TYPE,
|
||||
BTC_BLE_MESH_ACT_PROXY_CLIENT_ADD_FILTER_ADDR,
|
||||
BTC_BLE_MESH_ACT_PROXY_CLIENT_REMOVE_FILTER_ADDR,
|
||||
BTC_BLE_MESH_ACT_START_BLE_ADVERTISING,
|
||||
BTC_BLE_MESH_ACT_STOP_BLE_ADVERTISING,
|
||||
BTC_BLE_MESH_ACT_DEINIT_MESH,
|
||||
} btc_ble_mesh_prov_act_t;
|
||||
|
||||
typedef enum {
|
||||
@@ -96,7 +104,7 @@ typedef union {
|
||||
char string[8];
|
||||
} input_string;
|
||||
struct ble_mesh_set_device_name_args {
|
||||
char name[ESP_BLE_MESH_DEVICE_NAME_MAX_LEN];
|
||||
char name[ESP_BLE_MESH_DEVICE_NAME_MAX_LEN + 1];
|
||||
} set_device_name;
|
||||
struct ble_mesh_provisioner_read_oob_pub_key_args {
|
||||
uint8_t link_idx;
|
||||
@@ -150,7 +158,7 @@ typedef union {
|
||||
} set_primary_elem_addr;
|
||||
struct ble_mesh_provisioner_set_node_name_args {
|
||||
uint16_t index;
|
||||
char name[ESP_BLE_MESH_NODE_NAME_MAX_LEN];
|
||||
char name[ESP_BLE_MESH_NODE_NAME_MAX_LEN + 1];
|
||||
} set_node_name;
|
||||
struct ble_mesh_provisioner_add_local_app_key_args {
|
||||
uint8_t app_key[16];
|
||||
@@ -234,6 +242,16 @@ typedef union {
|
||||
uint16_t addr_num;
|
||||
uint16_t *addr;
|
||||
} proxy_client_remove_filter_addr;
|
||||
struct ble_mesh_start_ble_advertising_args {
|
||||
esp_ble_mesh_ble_adv_param_t param;
|
||||
esp_ble_mesh_ble_adv_data_t data;
|
||||
} start_ble_advertising;
|
||||
struct ble_mesh_stop_ble_advertising_args {
|
||||
uint8_t index;
|
||||
} stop_ble_advertising;
|
||||
struct ble_mesh_deinit_args {
|
||||
esp_ble_mesh_deinit_param_t param;
|
||||
} mesh_deinit;
|
||||
} btc_ble_mesh_prov_args_t;
|
||||
|
||||
typedef union {
|
||||
@@ -266,8 +284,6 @@ esp_ble_mesh_node_t *btc_ble_mesh_provisioner_get_node_with_uuid(const uint8_t u
|
||||
|
||||
esp_ble_mesh_node_t *btc_ble_mesh_provisioner_get_node_with_addr(uint16_t unicast_addr);
|
||||
|
||||
int btc_ble_mesh_deinit(esp_ble_mesh_deinit_param_t *param);
|
||||
|
||||
int btc_ble_mesh_client_model_init(esp_ble_mesh_model_t *model);
|
||||
|
||||
int btc_ble_mesh_client_model_deinit(esp_ble_mesh_model_t *model);
|
||||
@@ -298,4 +314,8 @@ void btc_ble_mesh_model_cb_handler(btc_msg_t *msg);
|
||||
void btc_ble_mesh_prov_call_handler(btc_msg_t *msg);
|
||||
void btc_ble_mesh_prov_cb_handler(btc_msg_t *msg);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _BTC_BLE_MESH_PROV_H_ */
|
||||
|
||||
@@ -18,6 +18,10 @@
|
||||
#include "btc/btc_manage.h"
|
||||
#include "esp_ble_mesh_sensor_model_api.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
BTC_BLE_MESH_ACT_SENSOR_CLIENT_GET_STATE,
|
||||
BTC_BLE_MESH_ACT_SENSOR_CLIENT_SET_STATE,
|
||||
@@ -73,5 +77,9 @@ void bt_mesh_sensor_server_cb_evt_to_btc(u8_t evt_type,
|
||||
|
||||
void btc_ble_mesh_sensor_server_cb_handler(btc_msg_t *msg);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _BTC_BLE_MESH_SENSOR_MODEL_H_ */
|
||||
|
||||
|
||||
@@ -18,6 +18,10 @@
|
||||
#include "btc/btc_manage.h"
|
||||
#include "esp_ble_mesh_time_scene_model_api.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
BTC_BLE_MESH_ACT_TIME_SCENE_CLIENT_GET_STATE,
|
||||
BTC_BLE_MESH_ACT_TIME_SCENE_CLIENT_SET_STATE,
|
||||
@@ -74,5 +78,9 @@ void bt_mesh_time_scene_server_cb_evt_to_btc(u8_t evt_type,
|
||||
|
||||
void btc_ble_mesh_time_scene_server_cb_handler(btc_msg_t *msg);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _BTC_BLE_MESH_TIME_SCENE_MODEL_H_ */
|
||||
|
||||
|
||||
@@ -11,7 +11,9 @@
|
||||
#ifndef _BLE_MESH_BUF_H_
|
||||
#define _BLE_MESH_BUF_H_
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#include "mesh_slist.h"
|
||||
#include "mesh_compiler.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -241,6 +243,30 @@ void net_buf_simple_add_le16(struct net_buf_simple *buf, u16_t val);
|
||||
*/
|
||||
void net_buf_simple_add_be16(struct net_buf_simple *buf, u16_t val);
|
||||
|
||||
/**
|
||||
* @brief Add 24-bit value at the end of the buffer
|
||||
*
|
||||
* Adds 24-bit value in little endian format at the end of buffer.
|
||||
* Increments the data length of a buffer to account for more data
|
||||
* at the end.
|
||||
*
|
||||
* @param buf Buffer to update.
|
||||
* @param val 24-bit value to be added.
|
||||
*/
|
||||
void net_buf_simple_add_le24(struct net_buf_simple *buf, u32_t val);
|
||||
|
||||
/**
|
||||
* @brief Add 24-bit value at the end of the buffer
|
||||
*
|
||||
* Adds 24-bit value in big endian format at the end of buffer.
|
||||
* Increments the data length of a buffer to account for more data
|
||||
* at the end.
|
||||
*
|
||||
* @param buf Buffer to update.
|
||||
* @param val 24-bit value to be added.
|
||||
*/
|
||||
void net_buf_simple_add_be24(struct net_buf_simple *buf, u32_t val);
|
||||
|
||||
/**
|
||||
* @brief Add 32-bit value at the end of the buffer
|
||||
*
|
||||
@@ -265,6 +291,54 @@ void net_buf_simple_add_le32(struct net_buf_simple *buf, u32_t val);
|
||||
*/
|
||||
void net_buf_simple_add_be32(struct net_buf_simple *buf, u32_t val);
|
||||
|
||||
/**
|
||||
* @brief Add 48-bit value at the end of the buffer
|
||||
*
|
||||
* Adds 48-bit value in little endian format at the end of buffer.
|
||||
* Increments the data length of a buffer to account for more data
|
||||
* at the end.
|
||||
*
|
||||
* @param buf Buffer to update.
|
||||
* @param val 48-bit value to be added.
|
||||
*/
|
||||
void net_buf_simple_add_le48(struct net_buf_simple *buf, u64_t val);
|
||||
|
||||
/**
|
||||
* @brief Add 48-bit value at the end of the buffer
|
||||
*
|
||||
* Adds 48-bit value in big endian format at the end of buffer.
|
||||
* Increments the data length of a buffer to account for more data
|
||||
* at the end.
|
||||
*
|
||||
* @param buf Buffer to update.
|
||||
* @param val 48-bit value to be added.
|
||||
*/
|
||||
void net_buf_simple_add_be48(struct net_buf_simple *buf, u64_t val);
|
||||
|
||||
/**
|
||||
* @brief Add 64-bit value at the end of the buffer
|
||||
*
|
||||
* Adds 64-bit value in little endian format at the end of buffer.
|
||||
* Increments the data length of a buffer to account for more data
|
||||
* at the end.
|
||||
*
|
||||
* @param buf Buffer to update.
|
||||
* @param val 64-bit value to be added.
|
||||
*/
|
||||
void net_buf_simple_add_le64(struct net_buf_simple *buf, u64_t val);
|
||||
|
||||
/**
|
||||
* @brief Add 64-bit value at the end of the buffer
|
||||
*
|
||||
* Adds 64-bit value in big endian format at the end of buffer.
|
||||
* Increments the data length of a buffer to account for more data
|
||||
* at the end.
|
||||
*
|
||||
* @param buf Buffer to update.
|
||||
* @param val 64-bit value to be added.
|
||||
*/
|
||||
void net_buf_simple_add_be64(struct net_buf_simple *buf, u64_t val);
|
||||
|
||||
/**
|
||||
* @brief Push data to the beginning of the buffer.
|
||||
*
|
||||
@@ -310,6 +384,94 @@ void net_buf_simple_push_be16(struct net_buf_simple *buf, u16_t val);
|
||||
*/
|
||||
void net_buf_simple_push_u8(struct net_buf_simple *buf, u8_t val);
|
||||
|
||||
/**
|
||||
* @brief Push 24-bit value to the beginning of the buffer
|
||||
*
|
||||
* Adds 24-bit value in little endian format to the beginning of the
|
||||
* buffer.
|
||||
*
|
||||
* @param buf Buffer to update.
|
||||
* @param val 24-bit value to be pushed to the buffer.
|
||||
*/
|
||||
void net_buf_simple_push_le24(struct net_buf_simple *buf, u32_t val);
|
||||
|
||||
/**
|
||||
* @brief Push 24-bit value to the beginning of the buffer
|
||||
*
|
||||
* Adds 24-bit value in big endian format to the beginning of the
|
||||
* buffer.
|
||||
*
|
||||
* @param buf Buffer to update.
|
||||
* @param val 24-bit value to be pushed to the buffer.
|
||||
*/
|
||||
void net_buf_simple_push_be24(struct net_buf_simple *buf, u32_t val);
|
||||
|
||||
/**
|
||||
* @brief Push 32-bit value to the beginning of the buffer
|
||||
*
|
||||
* Adds 32-bit value in little endian format to the beginning of the
|
||||
* buffer.
|
||||
*
|
||||
* @param buf Buffer to update.
|
||||
* @param val 32-bit value to be pushed to the buffer.
|
||||
*/
|
||||
void net_buf_simple_push_le32(struct net_buf_simple *buf, u32_t val);
|
||||
|
||||
/**
|
||||
* @brief Push 32-bit value to the beginning of the buffer
|
||||
*
|
||||
* Adds 32-bit value in big endian format to the beginning of the
|
||||
* buffer.
|
||||
*
|
||||
* @param buf Buffer to update.
|
||||
* @param val 32-bit value to be pushed to the buffer.
|
||||
*/
|
||||
void net_buf_simple_push_be32(struct net_buf_simple *buf, u32_t val);
|
||||
|
||||
/**
|
||||
* @brief Push 48-bit value to the beginning of the buffer
|
||||
*
|
||||
* Adds 48-bit value in little endian format to the beginning of the
|
||||
* buffer.
|
||||
*
|
||||
* @param buf Buffer to update.
|
||||
* @param val 48-bit value to be pushed to the buffer.
|
||||
*/
|
||||
void net_buf_simple_push_le48(struct net_buf_simple *buf, u64_t val);
|
||||
|
||||
/**
|
||||
* @brief Push 48-bit value to the beginning of the buffer
|
||||
*
|
||||
* Adds 48-bit value in big endian format to the beginning of the
|
||||
* buffer.
|
||||
*
|
||||
* @param buf Buffer to update.
|
||||
* @param val 48-bit value to be pushed to the buffer.
|
||||
*/
|
||||
void net_buf_simple_push_be48(struct net_buf_simple *buf, u64_t val);
|
||||
|
||||
/**
|
||||
* @brief Push 64-bit value to the beginning of the buffer
|
||||
*
|
||||
* Adds 64-bit value in little endian format to the beginning of the
|
||||
* buffer.
|
||||
*
|
||||
* @param buf Buffer to update.
|
||||
* @param val 64-bit value to be pushed to the buffer.
|
||||
*/
|
||||
void net_buf_simple_push_le64(struct net_buf_simple *buf, u64_t val);
|
||||
|
||||
/**
|
||||
* @brief Push 64-bit value to the beginning of the buffer
|
||||
*
|
||||
* Adds 64-bit value in big endian format to the beginning of the
|
||||
* buffer.
|
||||
*
|
||||
* @param buf Buffer to update.
|
||||
* @param val 64-bit value to be pushed to the buffer.
|
||||
*/
|
||||
void net_buf_simple_push_be64(struct net_buf_simple *buf, u64_t val);
|
||||
|
||||
/**
|
||||
* @brief Remove data from the beginning of the buffer.
|
||||
*
|
||||
@@ -372,6 +534,30 @@ u16_t net_buf_simple_pull_le16(struct net_buf_simple *buf);
|
||||
*/
|
||||
u16_t net_buf_simple_pull_be16(struct net_buf_simple *buf);
|
||||
|
||||
/**
|
||||
* @brief Remove and convert 24 bits from the beginning of the buffer.
|
||||
*
|
||||
* Same idea as with net_buf_simple_pull(), but a helper for operating
|
||||
* on 24-bit little endian data.
|
||||
*
|
||||
* @param buf A valid pointer on a buffer.
|
||||
*
|
||||
* @return 24-bit value converted from little endian to host endian.
|
||||
*/
|
||||
u32_t net_buf_simple_pull_le24(struct net_buf_simple *buf);
|
||||
|
||||
/**
|
||||
* @brief Remove and convert 24 bits from the beginning of the buffer.
|
||||
*
|
||||
* Same idea as with net_buf_simple_pull(), but a helper for operating
|
||||
* on 24-bit big endian data.
|
||||
*
|
||||
* @param buf A valid pointer on a buffer.
|
||||
*
|
||||
* @return 24-bit value converted from big endian to host endian.
|
||||
*/
|
||||
u32_t net_buf_simple_pull_be24(struct net_buf_simple *buf);
|
||||
|
||||
/**
|
||||
* @brief Remove and convert 32 bits from the beginning of the buffer.
|
||||
*
|
||||
@@ -396,6 +582,54 @@ u32_t net_buf_simple_pull_le32(struct net_buf_simple *buf);
|
||||
*/
|
||||
u32_t net_buf_simple_pull_be32(struct net_buf_simple *buf);
|
||||
|
||||
/**
|
||||
* @brief Remove and convert 48 bits from the beginning of the buffer.
|
||||
*
|
||||
* Same idea as with net_buf_simple_pull(), but a helper for operating
|
||||
* on 48-bit little endian data.
|
||||
*
|
||||
* @param buf A valid pointer on a buffer.
|
||||
*
|
||||
* @return 48-bit value converted from little endian to host endian.
|
||||
*/
|
||||
u64_t net_buf_simple_pull_le48(struct net_buf_simple *buf);
|
||||
|
||||
/**
|
||||
* @brief Remove and convert 48 bits from the beginning of the buffer.
|
||||
*
|
||||
* Same idea as with net_buf_simple_pull(), but a helper for operating
|
||||
* on 48-bit big endian data.
|
||||
*
|
||||
* @param buf A valid pointer on a buffer.
|
||||
*
|
||||
* @return 48-bit value converted from big endian to host endian.
|
||||
*/
|
||||
u64_t net_buf_simple_pull_be48(struct net_buf_simple *buf);
|
||||
|
||||
/**
|
||||
* @brief Remove and convert 64 bits from the beginning of the buffer.
|
||||
*
|
||||
* Same idea as with net_buf_simple_pull(), but a helper for operating
|
||||
* on 64-bit little endian data.
|
||||
*
|
||||
* @param buf A valid pointer on a buffer.
|
||||
*
|
||||
* @return 64-bit value converted from little endian to host endian.
|
||||
*/
|
||||
u64_t net_buf_simple_pull_le64(struct net_buf_simple *buf);
|
||||
|
||||
/**
|
||||
* @brief Remove and convert 64 bits from the beginning of the buffer.
|
||||
*
|
||||
* Same idea as with net_buf_simple_pull(), but a helper for operating
|
||||
* on 64-bit big endian data.
|
||||
*
|
||||
* @param buf A valid pointer on a buffer.
|
||||
*
|
||||
* @return 64-bit value converted from big endian to host endian.
|
||||
*/
|
||||
u64_t net_buf_simple_pull_be64(struct net_buf_simple *buf);
|
||||
|
||||
/**
|
||||
* @brief Get the tail pointer for a buffer.
|
||||
*
|
||||
@@ -882,6 +1116,32 @@ static inline void *net_buf_user_data(struct net_buf *buf)
|
||||
*/
|
||||
#define net_buf_add_be16(buf, val) net_buf_simple_add_be16(&(buf)->b, val)
|
||||
|
||||
/**
|
||||
* @def net_buf_add_le24
|
||||
* @brief Add 24-bit value at the end of the buffer
|
||||
*
|
||||
* Adds 24-bit value in little endian format at the end of buffer.
|
||||
* Increments the data length of a buffer to account for more data
|
||||
* at the end.
|
||||
*
|
||||
* @param buf Buffer to update.
|
||||
* @param val 24-bit value to be added.
|
||||
*/
|
||||
#define net_buf_add_le24(buf, val) net_buf_simple_add_le24(&(buf)->b, val)
|
||||
|
||||
/**
|
||||
* @def net_buf_add_be24
|
||||
* @brief Add 24-bit value at the end of the buffer
|
||||
*
|
||||
* Adds 24-bit value in big endian format at the end of buffer.
|
||||
* Increments the data length of a buffer to account for more data
|
||||
* at the end.
|
||||
*
|
||||
* @param buf Buffer to update.
|
||||
* @param val 24-bit value to be added.
|
||||
*/
|
||||
#define net_buf_add_be24(buf, val) net_buf_simple_add_be24(&(buf)->b, val)
|
||||
|
||||
/**
|
||||
* @def net_buf_add_le32
|
||||
* @brief Add 32-bit value at the end of the buffer
|
||||
@@ -908,6 +1168,58 @@ static inline void *net_buf_user_data(struct net_buf *buf)
|
||||
*/
|
||||
#define net_buf_add_be32(buf, val) net_buf_simple_add_be32(&(buf)->b, val)
|
||||
|
||||
/**
|
||||
* @def net_buf_add_le48
|
||||
* @brief Add 48-bit value at the end of the buffer
|
||||
*
|
||||
* Adds 48-bit value in little endian format at the end of buffer.
|
||||
* Increments the data length of a buffer to account for more data
|
||||
* at the end.
|
||||
*
|
||||
* @param buf Buffer to update.
|
||||
* @param val 48-bit value to be added.
|
||||
*/
|
||||
#define net_buf_add_le48(buf, val) net_buf_simple_add_le48(&(buf)->b, val)
|
||||
|
||||
/**
|
||||
* @def net_buf_add_be48
|
||||
* @brief Add 48-bit value at the end of the buffer
|
||||
*
|
||||
* Adds 48-bit value in big endian format at the end of buffer.
|
||||
* Increments the data length of a buffer to account for more data
|
||||
* at the end.
|
||||
*
|
||||
* @param buf Buffer to update.
|
||||
* @param val 48-bit value to be added.
|
||||
*/
|
||||
#define net_buf_add_be48(buf, val) net_buf_simple_add_be48(&(buf)->b, val)
|
||||
|
||||
/**
|
||||
* @def net_buf_add_le64
|
||||
* @brief Add 64-bit value at the end of the buffer
|
||||
*
|
||||
* Adds 64-bit value in little endian format at the end of buffer.
|
||||
* Increments the data length of a buffer to account for more data
|
||||
* at the end.
|
||||
*
|
||||
* @param buf Buffer to update.
|
||||
* @param val 64-bit value to be added.
|
||||
*/
|
||||
#define net_buf_add_le64(buf, val) net_buf_simple_add_le64(&(buf)->b, val)
|
||||
|
||||
/**
|
||||
* @def net_buf_add_be64
|
||||
* @brief Add 64-bit value at the end of the buffer
|
||||
*
|
||||
* Adds 64-bit value in big endian format at the end of buffer.
|
||||
* Increments the data length of a buffer to account for more data
|
||||
* at the end.
|
||||
*
|
||||
* @param buf Buffer to update.
|
||||
* @param val 64-bit value to be added.
|
||||
*/
|
||||
#define net_buf_add_be64(buf, val) net_buf_simple_add_be64(&(buf)->b, val)
|
||||
|
||||
/**
|
||||
* @def net_buf_push
|
||||
* @brief Push data to the beginning of the buffer.
|
||||
@@ -957,6 +1269,102 @@ static inline void *net_buf_user_data(struct net_buf *buf)
|
||||
*/
|
||||
#define net_buf_push_u8(buf, val) net_buf_simple_push_u8(&(buf)->b, val)
|
||||
|
||||
/**
|
||||
* @def net_buf_push_le24
|
||||
* @brief Push 24-bit value to the beginning of the buffer
|
||||
*
|
||||
* Adds 24-bit value in little endian format to the beginning of the
|
||||
* buffer.
|
||||
*
|
||||
* @param buf Buffer to update.
|
||||
* @param val 24-bit value to be pushed to the buffer.
|
||||
*/
|
||||
#define net_buf_push_le24(buf, val) net_buf_simple_push_le24(&(buf)->b, val)
|
||||
|
||||
/**
|
||||
* @def net_buf_push_be24
|
||||
* @brief Push 24-bit value to the beginning of the buffer
|
||||
*
|
||||
* Adds 24-bit value in little endian format to the beginning of the
|
||||
* buffer.
|
||||
*
|
||||
* @param buf Buffer to update.
|
||||
* @param val 24-bit value to be pushed to the buffer.
|
||||
*/
|
||||
#define net_buf_push_be24(buf, val) net_buf_simple_push_be24(&(buf)->b, val)
|
||||
|
||||
/**
|
||||
* @def net_buf_push_le32
|
||||
* @brief Push 32-bit value to the beginning of the buffer
|
||||
*
|
||||
* Adds 32-bit value in little endian format to the beginning of the
|
||||
* buffer.
|
||||
*
|
||||
* @param buf Buffer to update.
|
||||
* @param val 32-bit value to be pushed to the buffer.
|
||||
*/
|
||||
#define net_buf_push_le32(buf, val) net_buf_simple_push_le32(&(buf)->b, val)
|
||||
|
||||
/**
|
||||
* @def net_buf_push_be32
|
||||
* @brief Push 32-bit value to the beginning of the buffer
|
||||
*
|
||||
* Adds 32-bit value in little endian format to the beginning of the
|
||||
* buffer.
|
||||
*
|
||||
* @param buf Buffer to update.
|
||||
* @param val 32-bit value to be pushed to the buffer.
|
||||
*/
|
||||
#define net_buf_push_be32(buf, val) net_buf_simple_push_be32(&(buf)->b, val)
|
||||
|
||||
/**
|
||||
* @def net_buf_push_le48
|
||||
* @brief Push 48-bit value to the beginning of the buffer
|
||||
*
|
||||
* Adds 48-bit value in little endian format to the beginning of the
|
||||
* buffer.
|
||||
*
|
||||
* @param buf Buffer to update.
|
||||
* @param val 48-bit value to be pushed to the buffer.
|
||||
*/
|
||||
#define net_buf_push_le48(buf, val) net_buf_simple_push_le48(&(buf)->b, val)
|
||||
|
||||
/**
|
||||
* @def net_buf_push_be48
|
||||
* @brief Push 48-bit value to the beginning of the buffer
|
||||
*
|
||||
* Adds 48-bit value in little endian format to the beginning of the
|
||||
* buffer.
|
||||
*
|
||||
* @param buf Buffer to update.
|
||||
* @param val 48-bit value to be pushed to the buffer.
|
||||
*/
|
||||
#define net_buf_push_be48(buf, val) net_buf_simple_push_be48(&(buf)->b, val)
|
||||
|
||||
/**
|
||||
* @def net_buf_push_le64
|
||||
* @brief Push 64-bit value to the beginning of the buffer
|
||||
*
|
||||
* Adds 64-bit value in little endian format to the beginning of the
|
||||
* buffer.
|
||||
*
|
||||
* @param buf Buffer to update.
|
||||
* @param val 64-bit value to be pushed to the buffer.
|
||||
*/
|
||||
#define net_buf_push_le64(buf, val) net_buf_simple_push_le64(&(buf)->b, val)
|
||||
|
||||
/**
|
||||
* @def net_buf_push_be64
|
||||
* @brief Push 64-bit value to the beginning of the buffer
|
||||
*
|
||||
* Adds 64-bit value in little endian format to the beginning of the
|
||||
* buffer.
|
||||
*
|
||||
* @param buf Buffer to update.
|
||||
* @param val 64-bit value to be pushed to the buffer.
|
||||
*/
|
||||
#define net_buf_push_be64(buf, val) net_buf_simple_push_be64(&(buf)->b, val)
|
||||
|
||||
/**
|
||||
* @def net_buf_pull
|
||||
* @brief Remove data from the beginning of the buffer.
|
||||
@@ -1024,6 +1432,32 @@ static inline void *net_buf_user_data(struct net_buf *buf)
|
||||
*/
|
||||
#define net_buf_pull_be16(buf) net_buf_simple_pull_be16(&(buf)->b)
|
||||
|
||||
/**
|
||||
* @def net_buf_pull_le24
|
||||
* @brief Remove and convert 24 bits from the beginning of the buffer.
|
||||
*
|
||||
* Same idea as with net_buf_pull(), but a helper for operating on
|
||||
* 24-bit little endian data.
|
||||
*
|
||||
* @param buf A valid pointer on a buffer.
|
||||
*
|
||||
* @return 24-bit value converted from little endian to host endian.
|
||||
*/
|
||||
#define net_buf_pull_le24(buf) net_buf_simple_pull_le24(&(buf)->b)
|
||||
|
||||
/**
|
||||
* @def net_buf_pull_be24
|
||||
* @brief Remove and convert 24 bits from the beginning of the buffer.
|
||||
*
|
||||
* Same idea as with net_buf_pull(), but a helper for operating on
|
||||
* 24-bit big endian data.
|
||||
*
|
||||
* @param buf A valid pointer on a buffer.
|
||||
*
|
||||
* @return 24-bit value converted from big endian to host endian.
|
||||
*/
|
||||
#define net_buf_pull_be24(buf) net_buf_simple_pull_be24(&(buf)->b)
|
||||
|
||||
/**
|
||||
* @def net_buf_pull_le32
|
||||
* @brief Remove and convert 32 bits from the beginning of the buffer.
|
||||
@@ -1050,6 +1484,58 @@ static inline void *net_buf_user_data(struct net_buf *buf)
|
||||
*/
|
||||
#define net_buf_pull_be32(buf) net_buf_simple_pull_be32(&(buf)->b)
|
||||
|
||||
/**
|
||||
* @def net_buf_pull_le48
|
||||
* @brief Remove and convert 48 bits from the beginning of the buffer.
|
||||
*
|
||||
* Same idea as with net_buf_pull(), but a helper for operating on
|
||||
* 48-bit little endian data.
|
||||
*
|
||||
* @param buf A valid pointer on a buffer.
|
||||
*
|
||||
* @return 48-bit value converted from little endian to host endian.
|
||||
*/
|
||||
#define net_buf_pull_le48(buf) net_buf_simple_pull_le48(&(buf)->b)
|
||||
|
||||
/**
|
||||
* @def net_buf_pull_be48
|
||||
* @brief Remove and convert 48 bits from the beginning of the buffer.
|
||||
*
|
||||
* Same idea as with net_buf_pull(), but a helper for operating on
|
||||
* 48-bit big endian data.
|
||||
*
|
||||
* @param buf A valid pointer on a buffer
|
||||
*
|
||||
* @return 48-bit value converted from big endian to host endian.
|
||||
*/
|
||||
#define net_buf_pull_be48(buf) net_buf_simple_pull_be48(&(buf)->b)
|
||||
|
||||
/**
|
||||
* @def net_buf_pull_le64
|
||||
* @brief Remove and convert 64 bits from the beginning of the buffer.
|
||||
*
|
||||
* Same idea as with net_buf_pull(), but a helper for operating on
|
||||
* 64-bit little endian data.
|
||||
*
|
||||
* @param buf A valid pointer on a buffer.
|
||||
*
|
||||
* @return 64-bit value converted from little endian to host endian.
|
||||
*/
|
||||
#define net_buf_pull_le64(buf) net_buf_simple_pull_le64(&(buf)->b)
|
||||
|
||||
/**
|
||||
* @def net_buf_pull_be64
|
||||
* @brief Remove and convert 64 bits from the beginning of the buffer.
|
||||
*
|
||||
* Same idea as with net_buf_pull(), but a helper for operating on
|
||||
* 64-bit big endian data.
|
||||
*
|
||||
* @param buf A valid pointer on a buffer
|
||||
*
|
||||
* @return 64-bit value converted from big endian to host endian.
|
||||
*/
|
||||
#define net_buf_pull_be64(buf) net_buf_simple_pull_be64(&(buf)->b)
|
||||
|
||||
/**
|
||||
* @def net_buf_tailroom
|
||||
* @brief Check buffer tailroom.
|
||||
|
||||
599
components/bt/esp_ble_mesh/mesh_common/include/mesh_byteorder.h
Normal file
599
components/bt/esp_ble_mesh/mesh_common/include/mesh_byteorder.h
Normal file
@@ -0,0 +1,599 @@
|
||||
/*
|
||||
* Copyright (c) 2015-2016, Intel Corporation.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef _BLE_MESH_BYTEORDER_H_
|
||||
#define _BLE_MESH_BYTEORDER_H_
|
||||
|
||||
#include "mesh_types.h"
|
||||
#include "mesh_trace.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Internal helpers only used by the sys_* APIs further below */
|
||||
#ifndef __bswap_16
|
||||
#define __bswap_16(x) ((u16_t) ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8)))
|
||||
#endif
|
||||
|
||||
#ifndef __bswap_24
|
||||
#define __bswap_24(x) ((u32_t) ((((x) >> 16) & 0xff) | \
|
||||
(((x)) & 0xff00) | \
|
||||
(((x) & 0xff) << 16)))
|
||||
#endif
|
||||
|
||||
#ifndef __bswap_32
|
||||
#define __bswap_32(x) ((u32_t) ((((x) >> 24) & 0xff) | \
|
||||
(((x) >> 8) & 0xff00) | \
|
||||
(((x) & 0xff00) << 8) | \
|
||||
(((x) & 0xff) << 24)))
|
||||
#endif
|
||||
|
||||
#ifndef __bswap_48
|
||||
#define __bswap_48(x) ((u64_t) ((((x) >> 40) & 0xff) | \
|
||||
(((x) >> 24) & 0xff00) | \
|
||||
(((x) >> 8) & 0xff0000) | \
|
||||
(((x) & 0xff0000) << 8) | \
|
||||
(((x) & 0xff00) << 24) | \
|
||||
(((x) & 0xff) << 40)))
|
||||
#endif
|
||||
|
||||
#ifndef __bswap_64
|
||||
#define __bswap_64(x) ((u64_t) ((((x) >> 56) & 0xff) | \
|
||||
(((x) >> 40) & 0xff00) | \
|
||||
(((x) >> 24) & 0xff0000) | \
|
||||
(((x) >> 8) & 0xff000000) | \
|
||||
(((x) & 0xff000000) << 8) | \
|
||||
(((x) & 0xff0000) << 24) | \
|
||||
(((x) & 0xff00) << 40) | \
|
||||
(((x) & 0xff) << 56)))
|
||||
#endif
|
||||
|
||||
/** @def sys_le16_to_cpu
|
||||
* @brief Convert 16-bit integer from little-endian to host endianness.
|
||||
*
|
||||
* @param val 16-bit integer in little-endian format.
|
||||
*
|
||||
* @return 16-bit integer in host endianness.
|
||||
*/
|
||||
|
||||
/** @def sys_cpu_to_le16
|
||||
* @brief Convert 16-bit integer from host endianness to little-endian.
|
||||
*
|
||||
* @param val 16-bit integer in host endianness.
|
||||
*
|
||||
* @return 16-bit integer in little-endian format.
|
||||
*/
|
||||
|
||||
/** @def sys_le24_to_cpu
|
||||
* @brief Convert 24-bit integer from little-endian to host endianness.
|
||||
*
|
||||
* @param val 24-bit integer in little-endian format.
|
||||
*
|
||||
* @return 24-bit integer in host endianness.
|
||||
*/
|
||||
|
||||
/** @def sys_cpu_to_le24
|
||||
* @brief Convert 24-bit integer from host endianness to little-endian.
|
||||
*
|
||||
* @param val 24-bit integer in host endianness.
|
||||
*
|
||||
* @return 24-bit integer in little-endian format.
|
||||
*/
|
||||
|
||||
/** @def sys_le32_to_cpu
|
||||
* @brief Convert 32-bit integer from little-endian to host endianness.
|
||||
*
|
||||
* @param val 32-bit integer in little-endian format.
|
||||
*
|
||||
* @return 32-bit integer in host endianness.
|
||||
*/
|
||||
|
||||
/** @def sys_cpu_to_le32
|
||||
* @brief Convert 32-bit integer from host endianness to little-endian.
|
||||
*
|
||||
* @param val 32-bit integer in host endianness.
|
||||
*
|
||||
* @return 32-bit integer in little-endian format.
|
||||
*/
|
||||
|
||||
/** @def sys_le48_to_cpu
|
||||
* @brief Convert 48-bit integer from little-endian to host endianness.
|
||||
*
|
||||
* @param val 48-bit integer in little-endian format.
|
||||
*
|
||||
* @return 48-bit integer in host endianness.
|
||||
*/
|
||||
|
||||
/** @def sys_cpu_to_le48
|
||||
* @brief Convert 48-bit integer from host endianness to little-endian.
|
||||
*
|
||||
* @param val 48-bit integer in host endianness.
|
||||
*
|
||||
* @return 48-bit integer in little-endian format.
|
||||
*/
|
||||
|
||||
/** @def sys_be16_to_cpu
|
||||
* @brief Convert 16-bit integer from big-endian to host endianness.
|
||||
*
|
||||
* @param val 16-bit integer in big-endian format.
|
||||
*
|
||||
* @return 16-bit integer in host endianness.
|
||||
*/
|
||||
|
||||
/** @def sys_cpu_to_be16
|
||||
* @brief Convert 16-bit integer from host endianness to big-endian.
|
||||
*
|
||||
* @param val 16-bit integer in host endianness.
|
||||
*
|
||||
* @return 16-bit integer in big-endian format.
|
||||
*/
|
||||
|
||||
/** @def sys_be24_to_cpu
|
||||
* @brief Convert 24-bit integer from big-endian to host endianness.
|
||||
*
|
||||
* @param val 24-bit integer in big-endian format.
|
||||
*
|
||||
* @return 24-bit integer in host endianness.
|
||||
*/
|
||||
|
||||
/** @def sys_cpu_to_be24
|
||||
* @brief Convert 24-bit integer from host endianness to big-endian.
|
||||
*
|
||||
* @param val 24-bit integer in host endianness.
|
||||
*
|
||||
* @return 24-bit integer in big-endian format.
|
||||
*/
|
||||
|
||||
/** @def sys_be32_to_cpu
|
||||
* @brief Convert 32-bit integer from big-endian to host endianness.
|
||||
*
|
||||
* @param val 32-bit integer in big-endian format.
|
||||
*
|
||||
* @return 32-bit integer in host endianness.
|
||||
*/
|
||||
|
||||
/** @def sys_cpu_to_be32
|
||||
* @brief Convert 32-bit integer from host endianness to big-endian.
|
||||
*
|
||||
* @param val 32-bit integer in host endianness.
|
||||
*
|
||||
* @return 32-bit integer in big-endian format.
|
||||
*/
|
||||
|
||||
/** @def sys_be48_to_cpu
|
||||
* @brief Convert 48-bit integer from big-endian to host endianness.
|
||||
*
|
||||
* @param val 48-bit integer in big-endian format.
|
||||
*
|
||||
* @return 48-bit integer in host endianness.
|
||||
*/
|
||||
|
||||
/** @def sys_cpu_to_be48
|
||||
* @brief Convert 48-bit integer from host endianness to big-endian.
|
||||
*
|
||||
* @param val 48-bit integer in host endianness.
|
||||
*
|
||||
* @return 48-bit integer in big-endian format.
|
||||
*/
|
||||
|
||||
#ifndef sys_le16_to_cpu
|
||||
#define sys_le16_to_cpu(val) (val)
|
||||
#endif
|
||||
#ifndef sys_cpu_to_le16
|
||||
#define sys_cpu_to_le16(val) (val)
|
||||
#endif
|
||||
#ifndef sys_le24_to_cpu
|
||||
#define sys_le24_to_cpu(val) (val)
|
||||
#endif
|
||||
#ifndef sys_cpu_to_le24
|
||||
#define sys_cpu_to_le24(val) (val)
|
||||
#endif
|
||||
#ifndef sys_le32_to_cpu
|
||||
#define sys_le32_to_cpu(val) (val)
|
||||
#endif
|
||||
#ifndef sys_cpu_to_le32
|
||||
#define sys_cpu_to_le32(val) (val)
|
||||
#endif
|
||||
#ifndef sys_le48_to_cpu
|
||||
#define sys_le48_to_cpu(val) (val)
|
||||
#endif
|
||||
#ifndef sys_cpu_to_le48
|
||||
#define sys_cpu_to_le48(val) (val)
|
||||
#endif
|
||||
#ifndef sys_le64_to_cpu
|
||||
#define sys_le64_to_cpu(val) (val)
|
||||
#endif
|
||||
#ifndef sys_cpu_to_le64
|
||||
#define sys_cpu_to_le64(val) (val)
|
||||
#endif
|
||||
#ifndef sys_be16_to_cpu
|
||||
#define sys_be16_to_cpu(val) __bswap_16(val)
|
||||
#endif
|
||||
#ifndef sys_cpu_to_be16
|
||||
#define sys_cpu_to_be16(val) __bswap_16(val)
|
||||
#endif
|
||||
#ifndef sys_be24_to_cpu
|
||||
#define sys_be24_to_cpu(val) __bswap_24(val)
|
||||
#endif
|
||||
#ifndef sys_cpu_to_be24
|
||||
#define sys_cpu_to_be24(val) __bswap_24(val)
|
||||
#endif
|
||||
#ifndef sys_be32_to_cpu
|
||||
#define sys_be32_to_cpu(val) __bswap_32(val)
|
||||
#endif
|
||||
#ifndef sys_cpu_to_be32
|
||||
#define sys_cpu_to_be32(val) __bswap_32(val)
|
||||
#endif
|
||||
#ifndef sys_be48_to_cpu
|
||||
#define sys_be48_to_cpu(val) __bswap_48(val)
|
||||
#endif
|
||||
#ifndef sys_cpu_to_be48
|
||||
#define sys_cpu_to_be48(val) __bswap_48(val)
|
||||
#endif
|
||||
#ifndef sys_be64_to_cpu
|
||||
#define sys_be64_to_cpu(val) __bswap_64(val)
|
||||
#endif
|
||||
#ifndef sys_cpu_to_be64
|
||||
#define sys_cpu_to_be64(val) __bswap_64(val)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Put a 16-bit integer as big-endian to arbitrary location.
|
||||
*
|
||||
* Put a 16-bit integer, originally in host endianness, to a
|
||||
* potentially unaligned memory location in big-endian format.
|
||||
*
|
||||
* @param val 16-bit integer in host endianness.
|
||||
* @param dst Destination memory address to store the result.
|
||||
*/
|
||||
static inline void sys_put_be16(u16_t val, u8_t dst[2])
|
||||
{
|
||||
dst[0] = val >> 8;
|
||||
dst[1] = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Put a 24-bit integer as big-endian to arbitrary location.
|
||||
*
|
||||
* Put a 24-bit integer, originally in host endianness, to a
|
||||
* potentially unaligned memory location in big-endian format.
|
||||
*
|
||||
* @param val 24-bit integer in host endianness.
|
||||
* @param dst Destination memory address to store the result.
|
||||
*/
|
||||
static inline void sys_put_be24(u32_t val, u8_t dst[3])
|
||||
{
|
||||
dst[0] = val >> 16;
|
||||
sys_put_be16(val, &dst[1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Put a 32-bit integer as big-endian to arbitrary location.
|
||||
*
|
||||
* Put a 32-bit integer, originally in host endianness, to a
|
||||
* potentially unaligned memory location in big-endian format.
|
||||
*
|
||||
* @param val 32-bit integer in host endianness.
|
||||
* @param dst Destination memory address to store the result.
|
||||
*/
|
||||
static inline void sys_put_be32(u32_t val, u8_t dst[4])
|
||||
{
|
||||
sys_put_be16(val >> 16, dst);
|
||||
sys_put_be16(val, &dst[2]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Put a 48-bit integer as big-endian to arbitrary location.
|
||||
*
|
||||
* Put a 48-bit integer, originally in host endianness, to a
|
||||
* potentially unaligned memory location in big-endian format.
|
||||
*
|
||||
* @param val 48-bit integer in host endianness.
|
||||
* @param dst Destination memory address to store the result.
|
||||
*/
|
||||
static inline void sys_put_be48(u64_t val, u8_t dst[6])
|
||||
{
|
||||
sys_put_be16(val >> 32, dst);
|
||||
sys_put_be32(val, &dst[2]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Put a 64-bit integer as big-endian to arbitrary location.
|
||||
*
|
||||
* Put a 64-bit integer, originally in host endianness, to a
|
||||
* potentially unaligned memory location in big-endian format.
|
||||
*
|
||||
* @param val 64-bit integer in host endianness.
|
||||
* @param dst Destination memory address to store the result.
|
||||
*/
|
||||
static inline void sys_put_be64(u64_t val, u8_t dst[8])
|
||||
{
|
||||
sys_put_be32(val >> 32, dst);
|
||||
sys_put_be32(val, &dst[4]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Put a 16-bit integer as little-endian to arbitrary location.
|
||||
*
|
||||
* Put a 16-bit integer, originally in host endianness, to a
|
||||
* potentially unaligned memory location in little-endian format.
|
||||
*
|
||||
* @param val 16-bit integer in host endianness.
|
||||
* @param dst Destination memory address to store the result.
|
||||
*/
|
||||
static inline void sys_put_le16(u16_t val, u8_t dst[2])
|
||||
{
|
||||
dst[0] = val;
|
||||
dst[1] = val >> 8;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Put a 24-bit integer as little-endian to arbitrary location.
|
||||
*
|
||||
* Put a 24-bit integer, originally in host endianness, to a
|
||||
* potentially unaligned memory location in littel-endian format.
|
||||
*
|
||||
* @param val 24-bit integer in host endianness.
|
||||
* @param dst Destination memory address to store the result.
|
||||
*/
|
||||
static inline void sys_put_le24(u32_t val, u8_t dst[3])
|
||||
{
|
||||
sys_put_le16(val, dst);
|
||||
dst[2] = val >> 16;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Put a 32-bit integer as little-endian to arbitrary location.
|
||||
*
|
||||
* Put a 32-bit integer, originally in host endianness, to a
|
||||
* potentially unaligned memory location in little-endian format.
|
||||
*
|
||||
* @param val 32-bit integer in host endianness.
|
||||
* @param dst Destination memory address to store the result.
|
||||
*/
|
||||
static inline void sys_put_le32(u32_t val, u8_t dst[4])
|
||||
{
|
||||
sys_put_le16(val, dst);
|
||||
sys_put_le16(val >> 16, &dst[2]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Put a 48-bit integer as little-endian to arbitrary location.
|
||||
*
|
||||
* Put a 48-bit integer, originally in host endianness, to a
|
||||
* potentially unaligned memory location in little-endian format.
|
||||
*
|
||||
* @param val 48-bit integer in host endianness.
|
||||
* @param dst Destination memory address to store the result.
|
||||
*/
|
||||
static inline void sys_put_le48(u64_t val, u8_t dst[6])
|
||||
{
|
||||
sys_put_le32(val, dst);
|
||||
sys_put_le16(val >> 32, &dst[4]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Put a 64-bit integer as little-endian to arbitrary location.
|
||||
*
|
||||
* Put a 64-bit integer, originally in host endianness, to a
|
||||
* potentially unaligned memory location in little-endian format.
|
||||
*
|
||||
* @param val 64-bit integer in host endianness.
|
||||
* @param dst Destination memory address to store the result.
|
||||
*/
|
||||
static inline void sys_put_le64(u64_t val, u8_t dst[8])
|
||||
{
|
||||
sys_put_le32(val, dst);
|
||||
sys_put_le32(val >> 32, &dst[4]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get a 16-bit integer stored in big-endian format.
|
||||
*
|
||||
* Get a 16-bit integer, stored in big-endian format in a potentially
|
||||
* unaligned memory location, and convert it to the host endianness.
|
||||
*
|
||||
* @param src Location of the big-endian 16-bit integer to get.
|
||||
*
|
||||
* @return 16-bit integer in host endianness.
|
||||
*/
|
||||
static inline u16_t sys_get_be16(const u8_t src[2])
|
||||
{
|
||||
return ((u16_t)src[0] << 8) | src[1];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get a 24-bit integer stored in big-endian format.
|
||||
*
|
||||
* Get a 24-bit integer, stored in big-endian format in a potentially
|
||||
* unaligned memory location, and convert it to the host endianness.
|
||||
*
|
||||
* @param src Location of the big-endian 24-bit integer to get.
|
||||
*
|
||||
* @return 24-bit integer in host endianness.
|
||||
*/
|
||||
static inline u32_t sys_get_be24(const u8_t src[3])
|
||||
{
|
||||
return ((u32_t)src[0] << 16) | sys_get_be16(&src[1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get a 32-bit integer stored in big-endian format.
|
||||
*
|
||||
* Get a 32-bit integer, stored in big-endian format in a potentially
|
||||
* unaligned memory location, and convert it to the host endianness.
|
||||
*
|
||||
* @param src Location of the big-endian 32-bit integer to get.
|
||||
*
|
||||
* @return 32-bit integer in host endianness.
|
||||
*/
|
||||
static inline u32_t sys_get_be32(const u8_t src[4])
|
||||
{
|
||||
return ((u32_t)sys_get_be16(&src[0]) << 16) | sys_get_be16(&src[2]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get a 48-bit integer stored in big-endian format.
|
||||
*
|
||||
* Get a 48-bit integer, stored in big-endian format in a potentially
|
||||
* unaligned memory location, and convert it to the host endianness.
|
||||
*
|
||||
* @param src Location of the big-endian 48-bit integer to get.
|
||||
*
|
||||
* @return 48-bit integer in host endianness.
|
||||
*/
|
||||
static inline u64_t sys_get_be48(const u8_t src[6])
|
||||
{
|
||||
return ((u64_t)sys_get_be32(&src[0]) << 32) | sys_get_be16(&src[4]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get a 64-bit integer stored in big-endian format.
|
||||
*
|
||||
* Get a 64-bit integer, stored in big-endian format in a potentially
|
||||
* unaligned memory location, and convert it to the host endianness.
|
||||
*
|
||||
* @param src Location of the big-endian 64-bit integer to get.
|
||||
*
|
||||
* @return 64-bit integer in host endianness.
|
||||
*/
|
||||
static inline u64_t sys_get_be64(const u8_t src[8])
|
||||
{
|
||||
return ((u64_t)sys_get_be32(&src[0]) << 32) | sys_get_be32(&src[4]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get a 16-bit integer stored in little-endian format.
|
||||
*
|
||||
* Get a 16-bit integer, stored in little-endian format in a potentially
|
||||
* unaligned memory location, and convert it to the host endianness.
|
||||
*
|
||||
* @param src Location of the little-endian 16-bit integer to get.
|
||||
*
|
||||
* @return 16-bit integer in host endianness.
|
||||
*/
|
||||
static inline u16_t sys_get_le16(const u8_t src[2])
|
||||
{
|
||||
return ((u16_t)src[1] << 8) | src[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get a 24-bit integer stored in big-endian format.
|
||||
*
|
||||
* Get a 24-bit integer, stored in big-endian format in a potentially
|
||||
* unaligned memory location, and convert it to the host endianness.
|
||||
*
|
||||
* @param src Location of the big-endian 24-bit integer to get.
|
||||
*
|
||||
* @return 24-bit integer in host endianness.
|
||||
*/
|
||||
static inline u32_t sys_get_le24(const u8_t src[3])
|
||||
{
|
||||
return ((u32_t)src[2] << 16) | sys_get_le16(&src[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get a 32-bit integer stored in little-endian format.
|
||||
*
|
||||
* Get a 32-bit integer, stored in little-endian format in a potentially
|
||||
* unaligned memory location, and convert it to the host endianness.
|
||||
*
|
||||
* @param src Location of the little-endian 32-bit integer to get.
|
||||
*
|
||||
* @return 32-bit integer in host endianness.
|
||||
*/
|
||||
static inline u32_t sys_get_le32(const u8_t src[4])
|
||||
{
|
||||
return ((u32_t)sys_get_le16(&src[2]) << 16) | sys_get_le16(&src[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get a 48-bit integer stored in little-endian format.
|
||||
*
|
||||
* Get a 48-bit integer, stored in little-endian format in a potentially
|
||||
* unaligned memory location, and convert it to the host endianness.
|
||||
*
|
||||
* @param src Location of the little-endian 48-bit integer to get.
|
||||
*
|
||||
* @return 48-bit integer in host endianness.
|
||||
*/
|
||||
static inline u64_t sys_get_le48(const u8_t src[6])
|
||||
{
|
||||
return ((u64_t)sys_get_le32(&src[2]) << 32) | sys_get_le16(&src[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get a 64-bit integer stored in little-endian format.
|
||||
*
|
||||
* Get a 64-bit integer, stored in little-endian format in a potentially
|
||||
* unaligned memory location, and convert it to the host endianness.
|
||||
*
|
||||
* @param src Location of the little-endian 64-bit integer to get.
|
||||
*
|
||||
* @return 64-bit integer in host endianness.
|
||||
*/
|
||||
static inline u64_t sys_get_le64(const u8_t src[8])
|
||||
{
|
||||
return ((u64_t)sys_get_le32(&src[4]) << 32) | sys_get_le32(&src[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Swap one buffer content into another
|
||||
*
|
||||
* Copy the content of src buffer into dst buffer in reversed order,
|
||||
* i.e.: src[n] will be put in dst[end-n]
|
||||
* Where n is an index and 'end' the last index in both arrays.
|
||||
* The 2 memory pointers must be pointing to different areas, and have
|
||||
* a minimum size of given length.
|
||||
*
|
||||
* @param dst A valid pointer on a memory area where to copy the data in
|
||||
* @param src A valid pointer on a memory area where to copy the data from
|
||||
* @param length Size of both dst and src memory areas
|
||||
*/
|
||||
static inline void sys_memcpy_swap(void *dst, const void *src, size_t length)
|
||||
{
|
||||
u8_t *pdst = (u8_t *)dst;
|
||||
const u8_t *psrc = (const u8_t *)src;
|
||||
|
||||
__ASSERT(((psrc < pdst && (psrc + length) <= pdst) ||
|
||||
(psrc > pdst && (pdst + length) <= psrc)),
|
||||
"Source and destination buffers must not overlap");
|
||||
|
||||
psrc += length - 1;
|
||||
|
||||
for (; length > 0; length--) {
|
||||
*pdst++ = *psrc--;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Swap buffer content
|
||||
*
|
||||
* In-place memory swap, where final content will be reversed.
|
||||
* I.e.: buf[n] will be put in buf[end-n]
|
||||
* Where n is an index and 'end' the last index of buf.
|
||||
*
|
||||
* @param buf A valid pointer on a memory area to swap
|
||||
* @param length Size of buf memory area
|
||||
*/
|
||||
static inline void sys_mem_swap(void *buf, size_t length)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < (length / 2); i++) {
|
||||
u8_t tmp = ((u8_t *)buf)[i];
|
||||
|
||||
((u8_t *)buf)[i] = ((u8_t *)buf)[length - 1 - i];
|
||||
((u8_t *)buf)[length - 1 - i] = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _BLE_MESH_BYTEORDER_H_ */
|
||||
@@ -22,15 +22,18 @@
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "freertos/semphr.h"
|
||||
|
||||
#include "esp_heap_caps.h"
|
||||
|
||||
#include "mesh_byteorder.h"
|
||||
#include "mesh_ffs.h"
|
||||
#include "mesh_trace.h"
|
||||
#include "mesh_mutex.h"
|
||||
#include "mesh_access.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if CONFIG_BLE_MESH_ALLOC_FROM_PSRAM_FIRST
|
||||
#define bt_mesh_malloc(size) heap_caps_malloc_prefer(size, 2, MALLOC_CAP_DEFAULT|MALLOC_CAP_SPIRAM, MALLOC_CAP_DEFAULT|MALLOC_CAP_INTERNAL)
|
||||
#define bt_mesh_calloc(size) heap_caps_calloc_prefer(1, size, 2, MALLOC_CAP_DEFAULT|MALLOC_CAP_SPIRAM, MALLOC_CAP_DEFAULT|MALLOC_CAP_INTERNAL)
|
||||
@@ -72,19 +75,8 @@ void bt_mesh_free_buf(struct net_buf_simple *buf);
|
||||
*/
|
||||
u8_t bt_mesh_get_device_role(struct bt_mesh_model *model, bool srv_send);
|
||||
|
||||
typedef struct {
|
||||
SemaphoreHandle_t mutex;
|
||||
#if CONFIG_SPIRAM_USE_MALLOC
|
||||
StaticQueue_t *buffer;
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
} bt_mesh_mutex_t;
|
||||
|
||||
void bt_mesh_mutex_create(bt_mesh_mutex_t *mutex);
|
||||
|
||||
void bt_mesh_mutex_free(bt_mesh_mutex_t *mutex);
|
||||
|
||||
void bt_mesh_mutex_lock(bt_mesh_mutex_t *mutex);
|
||||
|
||||
void bt_mesh_mutex_unlock(bt_mesh_mutex_t *mutex);
|
||||
|
||||
#endif /* _BLE_MESH_COMMON_H_ */
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2014,2017 Wind River Systems, Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef _BLE_MESH_COMPILER_H_
|
||||
#define _BLE_MESH_COMPILER_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define ___in_section(a, b, c)
|
||||
|
||||
#define __in_section(a, b, c) ___in_section(a, b, c)
|
||||
|
||||
#define __in_section_unique(seg) ___in_section(seg, __FILE__, __COUNTER__)
|
||||
|
||||
#ifndef __packed
|
||||
#define __packed __attribute__((__packed__))
|
||||
#endif
|
||||
|
||||
#ifndef __aligned
|
||||
#define __aligned(x) __attribute__((__aligned__(x)))
|
||||
#endif
|
||||
|
||||
#ifndef __used
|
||||
#define __used __attribute__((__used__))
|
||||
#endif
|
||||
|
||||
#ifndef ARG_UNUSED
|
||||
#define ARG_UNUSED(x) (void)(x)
|
||||
#endif
|
||||
|
||||
#ifndef popcount
|
||||
#define popcount(x) __builtin_popcount(x)
|
||||
#endif
|
||||
|
||||
#ifndef ALWAYS_INLINE
|
||||
#define ALWAYS_INLINE inline __attribute__((always_inline))
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* This is meant to be used in conjunction with __in_section() and similar
|
||||
* where scattered structure instances are concatened together by the linker
|
||||
* and walked by the code at run time just like a contiguous array of such
|
||||
* structures.
|
||||
*
|
||||
* Assemblers and linkers may insert alignment padding by default whose
|
||||
* size is larger than the natural alignment for those structures when
|
||||
* gathering various section segments together, messing up the array walk.
|
||||
* To prevent this, we need to provide an explicit alignment not to rely
|
||||
* on the default that might just work by luck.
|
||||
*
|
||||
* Alignment statements in linker scripts are not sufficient as
|
||||
* the assembler may add padding by itself to each segment when switching
|
||||
* between sections within the same file even if it merges many such segments
|
||||
* into a single section in the end.
|
||||
*/
|
||||
#ifndef Z_DECL_ALIGN
|
||||
#define Z_DECL_ALIGN(type) __aligned(__alignof(type)) type
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Convenience helper combining __in_section() and Z_DECL_ALIGN().
|
||||
* The section name is the struct type prepended with an underscore.
|
||||
* The subsection is "static" and the subsubsection is the variable name.
|
||||
*/
|
||||
#ifndef Z_STRUCT_SECTION_ITERABLE
|
||||
#define Z_STRUCT_SECTION_ITERABLE(struct_type, name) \
|
||||
Z_DECL_ALIGN(struct struct_type) name
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _BLE_MESH_COMPILER_H_ */
|
||||
60
components/bt/esp_ble_mesh/mesh_common/include/mesh_ffs.h
Normal file
60
components/bt/esp_ble_mesh/mesh_common/include/mesh_ffs.h
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Wind River Systems, Inc.
|
||||
* Copyright (c) 2017, Oticon A/S
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef _BLE_MESH_FFS_H_
|
||||
#define _BLE_MESH_FFS_H_
|
||||
|
||||
#include "mesh_types.h"
|
||||
#include "mesh_compiler.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief find most significant bit set in a 32-bit word
|
||||
*
|
||||
* This routine finds the first bit set starting from the most significant bit
|
||||
* in the argument passed in and returns the index of that bit. Bits are
|
||||
* numbered starting at 1 from the least significant bit. A return value of
|
||||
* zero indicates that the value passed is zero.
|
||||
*
|
||||
* @return most significant bit set, 0 if @a op is 0
|
||||
*/
|
||||
|
||||
static ALWAYS_INLINE unsigned int find_msb_set(u32_t op)
|
||||
{
|
||||
if (op == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 32 - __builtin_clz(op);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief find least significant bit set in a 32-bit word
|
||||
*
|
||||
* This routine finds the first bit set starting from the least significant bit
|
||||
* in the argument passed in and returns the index of that bit. Bits are
|
||||
* numbered starting at 1 from the least significant bit. A return value of
|
||||
* zero indicates that the value passed is zero.
|
||||
*
|
||||
* @return least significant bit set, 0 if @a op is 0
|
||||
*/
|
||||
|
||||
static ALWAYS_INLINE unsigned int find_lsb_set(u32_t op)
|
||||
{
|
||||
return __builtin_ffs(op);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _BLE_MESH_FFS_H_ */
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Wind River Systems, Inc.
|
||||
* Additional Copyright (c) 2018 Espressif Systems (Shanghai) PTE LTD
|
||||
* Additional Copyright (c) 2020 Espressif Systems (Shanghai) PTE LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -8,249 +8,34 @@
|
||||
#ifndef _BLE_MESH_KERNEL_H_
|
||||
#define _BLE_MESH_KERNEL_H_
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "freertos/semphr.h"
|
||||
|
||||
#include "mesh_types.h"
|
||||
#include "mesh_slist.h"
|
||||
#include "mesh_atomic.h"
|
||||
|
||||
/* number of nsec per usec */
|
||||
#define NSEC_PER_USEC 1000
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* number of microseconds per millisecond */
|
||||
#define USEC_PER_MSEC 1000
|
||||
#ifdef CONFIG_BT_BLUEDROID_ENABLED
|
||||
#ifdef CONFIG_BT_BLUEDROID_PINNED_TO_CORE
|
||||
#define BLE_MESH_ADV_TASK_CORE (CONFIG_BT_BLUEDROID_PINNED_TO_CORE < portNUM_PROCESSORS ? CONFIG_BT_BLUEDROID_PINNED_TO_CORE : tskNO_AFFINITY)
|
||||
#else
|
||||
#define BLE_MESH_ADV_TASK_CORE (0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* number of milliseconds per second */
|
||||
#define MSEC_PER_SEC 1000
|
||||
#ifdef CONFIG_BT_NIMBLE_ENABLED
|
||||
#ifdef CONFIG_BT_NIMBLE_PINNED_TO_CORE
|
||||
#define BLE_MESH_ADV_TASK_CORE (CONFIG_BT_NIMBLE_PINNED_TO_CORE < portNUM_PROCESSORS ? CONFIG_BT_NIMBLE_PINNED_TO_CORE : tskNO_AFFINITY)
|
||||
#else
|
||||
#define BLE_MESH_ADV_TASK_CORE (0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* number of microseconds per second */
|
||||
#define USEC_PER_SEC ((USEC_PER_MSEC) * (MSEC_PER_SEC))
|
||||
|
||||
/* number of nanoseconds per second */
|
||||
#define NSEC_PER_SEC ((NSEC_PER_USEC) * (USEC_PER_MSEC) * (MSEC_PER_SEC))
|
||||
|
||||
/* timeout is not in use */
|
||||
#define _INACTIVE (-1)
|
||||
|
||||
struct k_work;
|
||||
|
||||
/**
|
||||
* @typedef k_work_handler_t
|
||||
* @brief Work item handler function type.
|
||||
*
|
||||
* A work item's handler function is executed by a workqueue's thread
|
||||
* when the work item is processed by the workqueue.
|
||||
*
|
||||
* @param work Address of the work item.
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
typedef void (*k_work_handler_t)(struct k_work *work);
|
||||
|
||||
struct k_work {
|
||||
void *_reserved;
|
||||
k_work_handler_t handler;
|
||||
int index;
|
||||
};
|
||||
|
||||
#define _K_WORK_INITIALIZER(work_handler) \
|
||||
{ \
|
||||
._reserved = NULL, \
|
||||
.handler = work_handler, \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Generate null timeout delay.
|
||||
*
|
||||
* This macro generates a timeout delay that that instructs a kernel API
|
||||
* not to wait if the requested operation cannot be performed immediately.
|
||||
*
|
||||
* @return Timeout delay value.
|
||||
*/
|
||||
#define K_NO_WAIT 0
|
||||
|
||||
/**
|
||||
* @brief Generate timeout delay from milliseconds.
|
||||
*
|
||||
* This macro generates a timeout delay that that instructs a kernel API
|
||||
* to wait up to @a ms milliseconds to perform the requested operation.
|
||||
*
|
||||
* @param ms Duration in milliseconds.
|
||||
*
|
||||
* @return Timeout delay value.
|
||||
*/
|
||||
#define K_MSEC(ms) (ms)
|
||||
|
||||
/**
|
||||
* @brief Generate timeout delay from seconds.
|
||||
*
|
||||
* This macro generates a timeout delay that that instructs a kernel API
|
||||
* to wait up to @a s seconds to perform the requested operation.
|
||||
*
|
||||
* @param s Duration in seconds.
|
||||
*
|
||||
* @return Timeout delay value.
|
||||
*/
|
||||
#define K_SECONDS(s) K_MSEC((s) * MSEC_PER_SEC)
|
||||
|
||||
/**
|
||||
* @brief Generate timeout delay from minutes.
|
||||
*
|
||||
* This macro generates a timeout delay that that instructs a kernel API
|
||||
* to wait up to @a m minutes to perform the requested operation.
|
||||
*
|
||||
* @param m Duration in minutes.
|
||||
*
|
||||
* @return Timeout delay value.
|
||||
*/
|
||||
#define K_MINUTES(m) K_SECONDS((m) * 60)
|
||||
|
||||
/**
|
||||
* @brief Generate timeout delay from hours.
|
||||
*
|
||||
* This macro generates a timeout delay that that instructs a kernel API
|
||||
* to wait up to @a h hours to perform the requested operation.
|
||||
*
|
||||
* @param h Duration in hours.
|
||||
*
|
||||
* @return Timeout delay value.
|
||||
*/
|
||||
#define K_HOURS(h) K_MINUTES((h) * 60)
|
||||
|
||||
/**
|
||||
* @brief Generate infinite timeout delay.
|
||||
*
|
||||
* This macro generates a timeout delay that that instructs a kernel API
|
||||
* to wait as long as necessary to perform the requested operation.
|
||||
*
|
||||
* @return Timeout delay value.
|
||||
*/
|
||||
#define K_FOREVER (-1)
|
||||
|
||||
/**
|
||||
* @brief Get system uptime (32-bit version).
|
||||
*
|
||||
* This routine returns the lower 32-bits of the elapsed time since the system
|
||||
* booted, in milliseconds.
|
||||
*
|
||||
* This routine can be more efficient than k_uptime_get(), as it reduces the
|
||||
* need for interrupt locking and 64-bit math. However, the 32-bit result
|
||||
* cannot hold a system uptime time larger than approximately 50 days, so the
|
||||
* caller must handle possible rollovers.
|
||||
*
|
||||
* @return Current uptime.
|
||||
*/
|
||||
u32_t k_uptime_get_32(void);
|
||||
|
||||
struct k_delayed_work {
|
||||
struct k_work work;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Submit a delayed work item to the system workqueue.
|
||||
*
|
||||
* This routine schedules work item @a work to be processed by the system
|
||||
* workqueue after a delay of @a delay milliseconds. The routine initiates
|
||||
* an asynchronous countdown for the work item and then returns to the caller.
|
||||
* Only when the countdown completes is the work item actually submitted to
|
||||
* the workqueue and becomes pending.
|
||||
*
|
||||
* Submitting a previously submitted delayed work item that is still
|
||||
* counting down cancels the existing submission and restarts the countdown
|
||||
* using the new delay. If the work item is currently pending on the
|
||||
* workqueue's queue because the countdown has completed it is too late to
|
||||
* resubmit the item, and resubmission fails without impacting the work item.
|
||||
* If the work item has already been processed, or is currently being processed,
|
||||
* its work is considered complete and the work item can be resubmitted.
|
||||
*
|
||||
* @warning
|
||||
* Work items submitted to the system workqueue should avoid using handlers
|
||||
* that block or yield since this may prevent the system workqueue from
|
||||
* processing other work items in a timely manner.
|
||||
*
|
||||
* @note Can be called by ISRs.
|
||||
*
|
||||
* @param work Address of delayed work item.
|
||||
* @param delay Delay before submitting the work item (in milliseconds).
|
||||
*
|
||||
* @retval 0 Work item countdown started.
|
||||
* @retval -EINPROGRESS Work item is already pending.
|
||||
* @retval -EINVAL Work item is being processed or has completed its work.
|
||||
* @retval -EADDRINUSE Work item is pending on a different workqueue.
|
||||
*/
|
||||
int k_delayed_work_submit(struct k_delayed_work *work, s32_t delay);
|
||||
|
||||
int k_delayed_work_submit_periodic(struct k_delayed_work *work, s32_t period);
|
||||
|
||||
/**
|
||||
* @brief Get time remaining before a delayed work gets scheduled.
|
||||
*
|
||||
* This routine computes the (approximate) time remaining before a
|
||||
* delayed work gets executed. If the delayed work is not waiting to be
|
||||
* scheduled, it returns zero.
|
||||
*
|
||||
* @param work Delayed work item.
|
||||
*
|
||||
* @return Remaining time (in milliseconds).
|
||||
*/
|
||||
s32_t k_delayed_work_remaining_get(struct k_delayed_work *work);
|
||||
|
||||
/**
|
||||
* @brief Submit a work item to the system workqueue.
|
||||
*
|
||||
* This routine submits work item @a work to be processed by the system
|
||||
* workqueue. If the work item is already pending in the workqueue's queue
|
||||
* as a result of an earlier submission, this routine has no effect on the
|
||||
* work item. If the work item has already been processed, or is currently
|
||||
* being processed, its work is considered complete and the work item can be
|
||||
* resubmitted.
|
||||
*
|
||||
* @warning
|
||||
* Work items submitted to the system workqueue should avoid using handlers
|
||||
* that block or yield since this may prevent the system workqueue from
|
||||
* processing other work items in a timely manner.
|
||||
*
|
||||
* @note Can be called by ISRs.
|
||||
*
|
||||
* @param work Address of work item.
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
static inline void k_work_submit(struct k_work *work)
|
||||
{
|
||||
if (work && work->handler) {
|
||||
work->handler(work);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize a work item.
|
||||
*
|
||||
* This routine initializes a workqueue work item, prior to its first use.
|
||||
*
|
||||
* @param work Address of work item.
|
||||
* @param handler Function to invoke each time work item is processed.
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
static inline void k_work_init(struct k_work *work, k_work_handler_t handler)
|
||||
{
|
||||
work->handler = handler;
|
||||
}
|
||||
|
||||
int k_delayed_work_cancel(struct k_delayed_work *work);
|
||||
|
||||
int k_delayed_work_free(struct k_delayed_work *work);
|
||||
|
||||
void k_delayed_work_init(struct k_delayed_work *work, k_work_handler_t handler);
|
||||
|
||||
/**
|
||||
* @brief Get system uptime.
|
||||
*
|
||||
* This routine returns the elapsed time since the system booted,
|
||||
* in milliseconds.
|
||||
*
|
||||
* @return Current uptime.
|
||||
*/
|
||||
s64_t k_uptime_get(void);
|
||||
#define BLE_MESH_ADV_TASK_STACK_SIZE 3072
|
||||
|
||||
/**
|
||||
* @brief Put the current thread to sleep.
|
||||
@@ -264,17 +49,9 @@ s64_t k_uptime_get(void);
|
||||
*/
|
||||
void k_sleep(s32_t duration);
|
||||
|
||||
void bt_mesh_list_lock(void);
|
||||
void bt_mesh_list_unlock(void);
|
||||
|
||||
void bt_mesh_buf_lock(void);
|
||||
void bt_mesh_buf_unlock(void);
|
||||
|
||||
void bt_mesh_atomic_lock(void);
|
||||
void bt_mesh_atomic_unlock(void);
|
||||
|
||||
void bt_mesh_k_init(void);
|
||||
void bt_mesh_k_deinit(void);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _BLE_MESH_KERNEL_H_ */
|
||||
|
||||
|
||||
58
components/bt/esp_ble_mesh/mesh_common/include/mesh_mutex.h
Normal file
58
components/bt/esp_ble_mesh/mesh_common/include/mesh_mutex.h
Normal file
@@ -0,0 +1,58 @@
|
||||
// Copyright 2017-2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef _BLE_MESH_MUTEX_H_
|
||||
#define _BLE_MESH_MUTEX_H_
|
||||
|
||||
#include "mesh_kernel.h"
|
||||
#include "mesh_slist.h"
|
||||
#include "mesh_atomic.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
SemaphoreHandle_t mutex;
|
||||
#if CONFIG_SPIRAM_USE_MALLOC
|
||||
StaticQueue_t *buffer;
|
||||
#endif
|
||||
} bt_mesh_mutex_t;
|
||||
|
||||
void bt_mesh_mutex_create(bt_mesh_mutex_t *mutex);
|
||||
void bt_mesh_mutex_free(bt_mesh_mutex_t *mutex);
|
||||
void bt_mesh_mutex_lock(bt_mesh_mutex_t *mutex);
|
||||
void bt_mesh_mutex_unlock(bt_mesh_mutex_t *mutex);
|
||||
|
||||
void bt_mesh_alarm_lock(void);
|
||||
void bt_mesh_alarm_unlock(void);
|
||||
|
||||
void bt_mesh_list_lock(void);
|
||||
void bt_mesh_list_unlock(void);
|
||||
|
||||
void bt_mesh_buf_lock(void);
|
||||
void bt_mesh_buf_unlock(void);
|
||||
|
||||
void bt_mesh_atomic_lock(void);
|
||||
void bt_mesh_atomic_unlock(void);
|
||||
|
||||
void bt_mesh_mutex_init(void);
|
||||
void bt_mesh_mutex_deinit(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _BLE_MESH_MUTEX_H_ */
|
||||
|
||||
267
components/bt/esp_ble_mesh/mesh_common/include/mesh_timer.h
Normal file
267
components/bt/esp_ble_mesh/mesh_common/include/mesh_timer.h
Normal file
@@ -0,0 +1,267 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Wind River Systems, Inc.
|
||||
* Additional Copyright (c) 2018 Espressif Systems (Shanghai) PTE LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef _BLE_MESH_TIMER_H_
|
||||
#define _BLE_MESH_TIMER_H_
|
||||
|
||||
#include "mesh_types.h"
|
||||
#include "mesh_slist.h"
|
||||
#include "mesh_atomic.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* number of nsec per usec */
|
||||
#define NSEC_PER_USEC 1000
|
||||
|
||||
/* number of microseconds per millisecond */
|
||||
#define USEC_PER_MSEC 1000
|
||||
|
||||
/* number of milliseconds per second */
|
||||
#define MSEC_PER_SEC 1000
|
||||
|
||||
/* number of microseconds per second */
|
||||
#define USEC_PER_SEC ((USEC_PER_MSEC) * (MSEC_PER_SEC))
|
||||
|
||||
/* number of nanoseconds per second */
|
||||
#define NSEC_PER_SEC ((NSEC_PER_USEC) * (USEC_PER_MSEC) * (MSEC_PER_SEC))
|
||||
|
||||
/* timeout is not in use */
|
||||
#define _INACTIVE (-1)
|
||||
|
||||
struct k_work;
|
||||
|
||||
/**
|
||||
* @typedef k_work_handler_t
|
||||
* @brief Work item handler function type.
|
||||
*
|
||||
* A work item's handler function is executed by a workqueue's thread
|
||||
* when the work item is processed by the workqueue.
|
||||
*
|
||||
* @param work Address of the work item.
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
typedef void (*k_work_handler_t)(struct k_work *work);
|
||||
|
||||
struct k_work {
|
||||
void *_reserved;
|
||||
k_work_handler_t handler;
|
||||
int index;
|
||||
};
|
||||
|
||||
#define _K_WORK_INITIALIZER(work_handler) \
|
||||
{ \
|
||||
._reserved = NULL, \
|
||||
.handler = work_handler, \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Generate null timeout delay.
|
||||
*
|
||||
* This macro generates a timeout delay that that instructs a kernel API
|
||||
* not to wait if the requested operation cannot be performed immediately.
|
||||
*
|
||||
* @return Timeout delay value.
|
||||
*/
|
||||
#define K_NO_WAIT 0
|
||||
|
||||
/**
|
||||
* @brief Generate timeout delay from milliseconds.
|
||||
*
|
||||
* This macro generates a timeout delay that that instructs a kernel API
|
||||
* to wait up to @a ms milliseconds to perform the requested operation.
|
||||
*
|
||||
* @param ms Duration in milliseconds.
|
||||
*
|
||||
* @return Timeout delay value.
|
||||
*/
|
||||
#define K_MSEC(ms) (ms)
|
||||
|
||||
/**
|
||||
* @brief Generate timeout delay from seconds.
|
||||
*
|
||||
* This macro generates a timeout delay that that instructs a kernel API
|
||||
* to wait up to @a s seconds to perform the requested operation.
|
||||
*
|
||||
* @param s Duration in seconds.
|
||||
*
|
||||
* @return Timeout delay value.
|
||||
*/
|
||||
#define K_SECONDS(s) K_MSEC((s) * MSEC_PER_SEC)
|
||||
|
||||
/**
|
||||
* @brief Generate timeout delay from minutes.
|
||||
*
|
||||
* This macro generates a timeout delay that that instructs a kernel API
|
||||
* to wait up to @a m minutes to perform the requested operation.
|
||||
*
|
||||
* @param m Duration in minutes.
|
||||
*
|
||||
* @return Timeout delay value.
|
||||
*/
|
||||
#define K_MINUTES(m) K_SECONDS((m) * 60)
|
||||
|
||||
/**
|
||||
* @brief Generate timeout delay from hours.
|
||||
*
|
||||
* This macro generates a timeout delay that that instructs a kernel API
|
||||
* to wait up to @a h hours to perform the requested operation.
|
||||
*
|
||||
* @param h Duration in hours.
|
||||
*
|
||||
* @return Timeout delay value.
|
||||
*/
|
||||
#define K_HOURS(h) K_MINUTES((h) * 60)
|
||||
|
||||
/**
|
||||
* @brief Generate infinite timeout delay.
|
||||
*
|
||||
* This macro generates a timeout delay that that instructs a kernel API
|
||||
* to wait as long as necessary to perform the requested operation.
|
||||
*
|
||||
* @return Timeout delay value.
|
||||
*/
|
||||
#define K_FOREVER (-1)
|
||||
|
||||
/**
|
||||
* @brief Get system uptime (32-bit version).
|
||||
*
|
||||
* This routine returns the lower 32-bits of the elapsed time since the system
|
||||
* booted, in milliseconds.
|
||||
*
|
||||
* This routine can be more efficient than k_uptime_get(), as it reduces the
|
||||
* need for interrupt locking and 64-bit math. However, the 32-bit result
|
||||
* cannot hold a system uptime time larger than approximately 50 days, so the
|
||||
* caller must handle possible rollovers.
|
||||
*
|
||||
* @return Current uptime.
|
||||
*/
|
||||
u32_t k_uptime_get_32(void);
|
||||
|
||||
struct k_delayed_work {
|
||||
struct k_work work;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Submit a delayed work item to the system workqueue.
|
||||
*
|
||||
* This routine schedules work item @a work to be processed by the system
|
||||
* workqueue after a delay of @a delay milliseconds. The routine initiates
|
||||
* an asynchronous countdown for the work item and then returns to the caller.
|
||||
* Only when the countdown completes is the work item actually submitted to
|
||||
* the workqueue and becomes pending.
|
||||
*
|
||||
* Submitting a previously submitted delayed work item that is still
|
||||
* counting down cancels the existing submission and restarts the countdown
|
||||
* using the new delay. If the work item is currently pending on the
|
||||
* workqueue's queue because the countdown has completed it is too late to
|
||||
* resubmit the item, and resubmission fails without impacting the work item.
|
||||
* If the work item has already been processed, or is currently being processed,
|
||||
* its work is considered complete and the work item can be resubmitted.
|
||||
*
|
||||
* @warning
|
||||
* Work items submitted to the system workqueue should avoid using handlers
|
||||
* that block or yield since this may prevent the system workqueue from
|
||||
* processing other work items in a timely manner.
|
||||
*
|
||||
* @note Can be called by ISRs.
|
||||
*
|
||||
* @param work Address of delayed work item.
|
||||
* @param delay Delay before submitting the work item (in milliseconds).
|
||||
*
|
||||
* @retval 0 Work item countdown started.
|
||||
* @retval -EINPROGRESS Work item is already pending.
|
||||
* @retval -EINVAL Work item is being processed or has completed its work.
|
||||
* @retval -EADDRINUSE Work item is pending on a different workqueue.
|
||||
*/
|
||||
int k_delayed_work_submit(struct k_delayed_work *work, s32_t delay);
|
||||
|
||||
int k_delayed_work_submit_periodic(struct k_delayed_work *work, s32_t period);
|
||||
|
||||
/**
|
||||
* @brief Get time remaining before a delayed work gets scheduled.
|
||||
*
|
||||
* This routine computes the (approximate) time remaining before a
|
||||
* delayed work gets executed. If the delayed work is not waiting to be
|
||||
* scheduled, it returns zero.
|
||||
*
|
||||
* @param work Delayed work item.
|
||||
*
|
||||
* @return Remaining time (in milliseconds).
|
||||
*/
|
||||
s32_t k_delayed_work_remaining_get(struct k_delayed_work *work);
|
||||
|
||||
/**
|
||||
* @brief Submit a work item to the system workqueue.
|
||||
*
|
||||
* This routine submits work item @a work to be processed by the system
|
||||
* workqueue. If the work item is already pending in the workqueue's queue
|
||||
* as a result of an earlier submission, this routine has no effect on the
|
||||
* work item. If the work item has already been processed, or is currently
|
||||
* being processed, its work is considered complete and the work item can be
|
||||
* resubmitted.
|
||||
*
|
||||
* @warning
|
||||
* Work items submitted to the system workqueue should avoid using handlers
|
||||
* that block or yield since this may prevent the system workqueue from
|
||||
* processing other work items in a timely manner.
|
||||
*
|
||||
* @note Can be called by ISRs.
|
||||
*
|
||||
* @param work Address of work item.
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
static inline void k_work_submit(struct k_work *work)
|
||||
{
|
||||
if (work && work->handler) {
|
||||
work->handler(work);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize a work item.
|
||||
*
|
||||
* This routine initializes a workqueue work item, prior to its first use.
|
||||
*
|
||||
* @param work Address of work item.
|
||||
* @param handler Function to invoke each time work item is processed.
|
||||
*
|
||||
* @return N/A
|
||||
*/
|
||||
static inline void k_work_init(struct k_work *work, k_work_handler_t handler)
|
||||
{
|
||||
work->handler = handler;
|
||||
}
|
||||
|
||||
int k_delayed_work_cancel(struct k_delayed_work *work);
|
||||
|
||||
int k_delayed_work_free(struct k_delayed_work *work);
|
||||
|
||||
int k_delayed_work_init(struct k_delayed_work *work, k_work_handler_t handler);
|
||||
|
||||
/**
|
||||
* @brief Get system uptime.
|
||||
*
|
||||
* This routine returns the elapsed time since the system booted,
|
||||
* in milliseconds.
|
||||
*
|
||||
* @return Current uptime.
|
||||
*/
|
||||
s64_t k_uptime_get(void);
|
||||
|
||||
void bt_mesh_timer_init(void);
|
||||
void bt_mesh_timer_deinit(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _BLE_MESH_TIMER_H_ */
|
||||
|
||||
@@ -10,6 +10,11 @@
|
||||
#define _BLE_MESH_TRACE_H_
|
||||
|
||||
#include "esp_log.h"
|
||||
#include "mesh_util.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Define common tracing for all */
|
||||
#ifndef LOG_LEVEL_ERROR
|
||||
@@ -52,10 +57,6 @@
|
||||
#define BLE_MESH_LOG_LOCAL_LEVEL_MAPPING LOG_LOCAL_LEVEL
|
||||
#endif
|
||||
|
||||
#ifndef MAX
|
||||
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
||||
#endif /* MAX(a, b) */
|
||||
|
||||
#define BLE_MESH_LOG_LEVEL_CHECK(LAYER, LEVEL) (MAX(LAYER##_LOG_LEVEL, BLE_MESH_LOG_LOCAL_LEVEL_MAPPING) >= LOG_LEVEL_##LEVEL)
|
||||
|
||||
#define BLE_MESH_PRINT_E(tag, format, ...) {esp_log_write(ESP_LOG_ERROR, tag, LOG_FORMAT(E, format), esp_log_timestamp(), tag, ##__VA_ARGS__); }
|
||||
@@ -127,4 +128,8 @@
|
||||
#define NET_BUF_SIMPLE_ASSERT(cond)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _BLE_MESH_TRACE_H_ */
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -39,6 +40,14 @@ typedef int bt_mesh_atomic_t;
|
||||
#define true 1
|
||||
#endif
|
||||
|
||||
#ifndef PRIu64
|
||||
#define PRIu64 "llu"
|
||||
#endif
|
||||
|
||||
#ifndef PRIx64
|
||||
#define PRIx64 "llx"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -15,9 +15,7 @@
|
||||
#define _BLE_MESH_UTIL_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include "soc/soc.h"
|
||||
#include "mesh_types.h"
|
||||
#include "mesh_trace.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -26,87 +24,99 @@ extern "C" {
|
||||
/* Helper to pass a int as a pointer or vice-versa.
|
||||
* Those are available for 32 bits architectures:
|
||||
*/
|
||||
#ifndef POINTER_TO_UINT
|
||||
#define POINTER_TO_UINT(x) ((u32_t) (x))
|
||||
#endif
|
||||
#ifndef UINT_TO_POINTER
|
||||
#define UINT_TO_POINTER(x) ((void *) (x))
|
||||
#endif
|
||||
#ifndef POINTER_TO_INT
|
||||
#define POINTER_TO_INT(x) ((s32_t) (x))
|
||||
#endif
|
||||
#ifndef INT_TO_POINTER
|
||||
#define INT_TO_POINTER(x) ((void *) (x))
|
||||
#endif
|
||||
|
||||
/* Evaluates to 0 if cond is true-ish; compile error otherwise */
|
||||
#ifndef ZERO_OR_COMPILE_ERROR
|
||||
#define ZERO_OR_COMPILE_ERROR(cond) ((int) sizeof(char[1 - 2 * !(cond)]) - 1)
|
||||
#endif
|
||||
|
||||
/* Evaluates to 0 if array is an array; compile error if not array (e.g.
|
||||
* pointer)
|
||||
*/
|
||||
#define IS_ARRAY(array) \
|
||||
ZERO_OR_COMPILE_ERROR( \
|
||||
!__builtin_types_compatible_p(__typeof__(array), \
|
||||
__typeof__(&(array)[0])))
|
||||
#ifndef IS_ARRAY
|
||||
#define IS_ARRAY(array) \
|
||||
ZERO_OR_COMPILE_ERROR( \
|
||||
!__builtin_types_compatible_p(__typeof__(array), \
|
||||
__typeof__(&(array)[0])))
|
||||
#endif
|
||||
|
||||
/* Evaluates to number of elements in an array; compile error if not
|
||||
* an array (e.g. pointer)
|
||||
*/
|
||||
#define ARRAY_SIZE(array) \
|
||||
((unsigned long) (IS_ARRAY(array) + \
|
||||
(sizeof(array) / sizeof((array)[0]))))
|
||||
#ifndef ARRAY_SIZE
|
||||
#define ARRAY_SIZE(array) \
|
||||
((unsigned long) (IS_ARRAY(array) + \
|
||||
(sizeof(array) / sizeof((array)[0]))))
|
||||
#endif
|
||||
|
||||
/* Evaluates to 1 if ptr is part of array, 0 otherwise; compile error if
|
||||
* "array" argument is not an array (e.g. "ptr" and "array" mixed up)
|
||||
*/
|
||||
#ifndef PART_OF_ARRAY
|
||||
#define PART_OF_ARRAY(array, ptr) \
|
||||
((ptr) && ((ptr) >= &array[0] && (ptr) < &array[ARRAY_SIZE(array)]))
|
||||
((ptr) && ((ptr) >= &array[0] && (ptr) < &array[ARRAY_SIZE(array)]))
|
||||
#endif
|
||||
|
||||
#ifndef CONTAINER_OF
|
||||
#define CONTAINER_OF(ptr, type, field) \
|
||||
((type *)(((char *)(ptr)) - offsetof(type, field)))
|
||||
((type *)(((char *)(ptr)) - offsetof(type, field)))
|
||||
#endif
|
||||
|
||||
/* round "x" up/down to next multiple of "align" (which must be a power of 2) */
|
||||
#define ROUND_UP(x, align) \
|
||||
(((unsigned long)(x) + ((unsigned long)align - 1)) & \
|
||||
~((unsigned long)align - 1))
|
||||
#ifndef ROUND_UP
|
||||
#define ROUND_UP(x, align) \
|
||||
(((unsigned long)(x) + ((unsigned long)align - 1)) & \
|
||||
~((unsigned long)align - 1))
|
||||
#endif
|
||||
|
||||
#ifndef ROUND_DOWN
|
||||
#define ROUND_DOWN(x, align) ((unsigned long)(x) & ~((unsigned long)align - 1))
|
||||
#endif
|
||||
|
||||
/* round up/down to the next word boundary */
|
||||
#ifndef WB_UP
|
||||
#define WB_UP(x) ROUND_UP(x, sizeof(void *))
|
||||
#endif
|
||||
|
||||
#ifndef WB_DN
|
||||
#define WB_DN(x) ROUND_DOWN(x, sizeof(void *))
|
||||
#endif
|
||||
|
||||
#ifndef ceiling_fraction
|
||||
#define ceiling_fraction(numerator, divider) \
|
||||
(((numerator) + ((divider) - 1)) / (divider))
|
||||
|
||||
/* Internal helpers only used by the sys_* APIs further below */
|
||||
#ifndef __bswap_16
|
||||
#define __bswap_16(x) ((u16_t) ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8)))
|
||||
(((numerator) + ((divider) - 1)) / (divider))
|
||||
#endif
|
||||
|
||||
#ifndef __bswap_32
|
||||
#define __bswap_32(x) ((u32_t) ((((x) >> 24) & 0xff) | \
|
||||
(((x) >> 8) & 0xff00) | \
|
||||
(((x) & 0xff00) << 8) | \
|
||||
(((x) & 0xff) << 24)))
|
||||
#ifndef CHECKIF
|
||||
#define CHECKIF(expr) if (expr)
|
||||
#endif
|
||||
|
||||
#ifndef __bswap_64
|
||||
#define __bswap_64(x) ((u64_t) ((((x) >> 56) & 0xff) | \
|
||||
(((x) >> 40) & 0xff00) | \
|
||||
(((x) >> 24) & 0xff0000) | \
|
||||
(((x) >> 8) & 0xff000000) | \
|
||||
(((x) & 0xff000000) << 8) | \
|
||||
(((x) & 0xff0000) << 24) | \
|
||||
(((x) & 0xff00) << 40) | \
|
||||
(((x) & 0xff) << 56)))
|
||||
#endif
|
||||
|
||||
#define sys_le16_to_cpu(val) (val)
|
||||
#define sys_cpu_to_le16(val) (val)
|
||||
#define sys_be16_to_cpu(val) __bswap_16(val)
|
||||
#define sys_cpu_to_be16(val) __bswap_16(val)
|
||||
#define sys_le32_to_cpu(val) (val)
|
||||
#define sys_cpu_to_le32(val) (val)
|
||||
#define sys_le64_to_cpu(val) (val)
|
||||
#define sys_cpu_to_le64(val) (val)
|
||||
#define sys_be32_to_cpu(val) __bswap_32(val)
|
||||
#define sys_cpu_to_be32(val) __bswap_32(val)
|
||||
#define sys_be64_to_cpu(val) __bswap_64(val)
|
||||
#define sys_cpu_to_be64(val) __bswap_64(val)
|
||||
|
||||
/** @brief Return larger value of two provided expressions.
|
||||
*
|
||||
* @note Arguments are evaluated twice. See Z_MAX for GCC only, single
|
||||
* evaluation version.
|
||||
*/
|
||||
#ifndef MAX
|
||||
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
/** @brief Return smaller value of two provided expressions.
|
||||
*
|
||||
* @note Arguments are evaluated twice. See Z_MIN for GCC only, single
|
||||
* evaluation version.
|
||||
*/
|
||||
#ifndef MIN
|
||||
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
|
||||
#endif
|
||||
@@ -140,14 +150,14 @@ extern "C" {
|
||||
* value to be e.g. a literal "1" at expansion time in the next macro,
|
||||
* not "(1)", etc... Standard recursive expansion does not work.
|
||||
*/
|
||||
#define IS_ENABLED(config_macro) _IS_ENABLED1(config_macro)
|
||||
#define IS_ENABLED(config_macro) Z_IS_ENABLED1(config_macro)
|
||||
|
||||
/* Now stick on a "_XXXX" prefix, it will now be "_XXXX1" if config_macro
|
||||
* is "1", or just "_XXXX" if it's undefined.
|
||||
* ENABLED: _IS_ENABLED2(_XXXX1)
|
||||
* DISABLED _IS_ENABLED2(_XXXX)
|
||||
* ENABLED: Z_IS_ENABLED2(_XXXX1)
|
||||
* DISABLED Z_IS_ENABLED2(_XXXX)
|
||||
*/
|
||||
#define _IS_ENABLED1(config_macro) _IS_ENABLED2(_XXXX##config_macro)
|
||||
#define Z_IS_ENABLED1(config_macro) Z_IS_ENABLED2(_XXXX##config_macro)
|
||||
|
||||
/* Here's the core trick, we map "_XXXX1" to "_YYYY," (i.e. a string
|
||||
* with a trailing comma), so it has the effect of making this a
|
||||
@@ -161,221 +171,20 @@ extern "C" {
|
||||
/* Then we append an extra argument to fool the gcc preprocessor into
|
||||
* accepting it as a varargs macro.
|
||||
* arg1 arg2 arg3
|
||||
* ENABLED: _IS_ENABLED3(_YYYY, 1, 0)
|
||||
* DISABLED _IS_ENABLED3(_XXXX 1, 0)
|
||||
* ENABLED: Z_IS_ENABLED3(_YYYY, 1, 0)
|
||||
* DISABLED Z_IS_ENABLED3(_XXXX 1, 0)
|
||||
*/
|
||||
#define _IS_ENABLED2(one_or_two_args) _IS_ENABLED3(one_or_two_args 1, 0)
|
||||
#define Z_IS_ENABLED2(one_or_two_args) Z_IS_ENABLED3(one_or_two_args true, false)
|
||||
|
||||
/* And our second argument is thus now cooked to be 1 in the case
|
||||
* where the value is defined to 1, and 0 if not:
|
||||
*/
|
||||
#define _IS_ENABLED3(ignore_this, val, ...) val
|
||||
|
||||
/* ESP Toolchain doesn't support section */
|
||||
#define ___in_section(a, b, c)
|
||||
#define __in_section(a, b, c) ___in_section(a, b, c)
|
||||
|
||||
#define __in_section_unique(seg) ___in_section(seg, __FILE__, __COUNTER__)
|
||||
|
||||
#define popcount(x) __builtin_popcount(x)
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief find most significant bit set in a 32-bit word
|
||||
*
|
||||
* This routine finds the first bit set starting from the most significant bit
|
||||
* in the argument passed in and returns the index of that bit. Bits are
|
||||
* numbered starting at 1 from the least significant bit. A return value of
|
||||
* zero indicates that the value passed is zero.
|
||||
*
|
||||
* @return most significant bit set, 0 if @a op is 0
|
||||
*/
|
||||
|
||||
#if defined(__GNUC__)
|
||||
static inline unsigned int find_msb_set(u32_t op)
|
||||
{
|
||||
if (!op) {
|
||||
return 0;
|
||||
}
|
||||
return 32 - __builtin_clz(op);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief find least significant bit set in a 32-bit word
|
||||
*
|
||||
* This routine finds the first bit set starting from the least significant bit
|
||||
* in the argument passed in and returns the index of that bit. Bits are
|
||||
* numbered starting at 1 from the least significant bit. A return value of
|
||||
* zero indicates that the value passed is zero.
|
||||
*
|
||||
* @return least significant bit set, 0 if @a op is 0
|
||||
*/
|
||||
|
||||
#if defined(__GNUC__)
|
||||
static inline unsigned int find_lsb_set(u32_t op)
|
||||
{
|
||||
return __builtin_ffs(op);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Put a 16-bit integer as big-endian to arbitrary location.
|
||||
*
|
||||
* Put a 16-bit integer, originally in host endianness, to a
|
||||
* potentially unaligned memory location in big-endian format.
|
||||
*
|
||||
* @param val 16-bit integer in host endianness.
|
||||
* @param dst Destination memory address to store the result.
|
||||
*/
|
||||
static inline void sys_put_be16(u16_t val, u8_t dst[2])
|
||||
{
|
||||
dst[0] = val >> 8;
|
||||
dst[1] = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Put a 32-bit integer as big-endian to arbitrary location.
|
||||
*
|
||||
* Put a 32-bit integer, originally in host endianness, to a
|
||||
* potentially unaligned memory location in big-endian format.
|
||||
*
|
||||
* @param val 32-bit integer in host endianness.
|
||||
* @param dst Destination memory address to store the result.
|
||||
*/
|
||||
static inline void sys_put_be32(u32_t val, u8_t dst[4])
|
||||
{
|
||||
sys_put_be16(val >> 16, dst);
|
||||
sys_put_be16(val, &dst[2]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Put a 16-bit integer as little-endian to arbitrary location.
|
||||
*
|
||||
* Put a 16-bit integer, originally in host endianness, to a
|
||||
* potentially unaligned memory location in little-endian format.
|
||||
*
|
||||
* @param val 16-bit integer in host endianness.
|
||||
* @param dst Destination memory address to store the result.
|
||||
*/
|
||||
static inline void sys_put_le16(u16_t val, u8_t dst[2])
|
||||
{
|
||||
dst[0] = val;
|
||||
dst[1] = val >> 8;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Put a 32-bit integer as little-endian to arbitrary location.
|
||||
*
|
||||
* Put a 32-bit integer, originally in host endianness, to a
|
||||
* potentially unaligned memory location in little-endian format.
|
||||
*
|
||||
* @param val 32-bit integer in host endianness.
|
||||
* @param dst Destination memory address to store the result.
|
||||
*/
|
||||
static inline void sys_put_le32(u32_t val, u8_t dst[4])
|
||||
{
|
||||
sys_put_le16(val, dst);
|
||||
sys_put_le16(val >> 16, &dst[2]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Put a 64-bit integer as little-endian to arbitrary location.
|
||||
*
|
||||
* Put a 64-bit integer, originally in host endianness, to a
|
||||
* potentially unaligned memory location in little-endian format.
|
||||
*
|
||||
* @param val 64-bit integer in host endianness.
|
||||
* @param dst Destination memory address to store the result.
|
||||
*/
|
||||
static inline void sys_put_le64(u64_t val, u8_t dst[8])
|
||||
{
|
||||
sys_put_le32(val, dst);
|
||||
sys_put_le32(val >> 32, &dst[4]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get a 16-bit integer stored in big-endian format.
|
||||
*
|
||||
* Get a 16-bit integer, stored in big-endian format in a potentially
|
||||
* unaligned memory location, and convert it to the host endianness.
|
||||
*
|
||||
* @param src Location of the big-endian 16-bit integer to get.
|
||||
*
|
||||
* @return 16-bit integer in host endianness.
|
||||
*/
|
||||
static inline u16_t sys_get_be16(const u8_t src[2])
|
||||
{
|
||||
return ((u16_t)src[0] << 8) | src[1];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get a 32-bit integer stored in big-endian format.
|
||||
*
|
||||
* Get a 32-bit integer, stored in big-endian format in a potentially
|
||||
* unaligned memory location, and convert it to the host endianness.
|
||||
*
|
||||
* @param src Location of the big-endian 32-bit integer to get.
|
||||
*
|
||||
* @return 32-bit integer in host endianness.
|
||||
*/
|
||||
static inline u32_t sys_get_be32(const u8_t src[4])
|
||||
{
|
||||
return ((u32_t)sys_get_be16(&src[0]) << 16) | sys_get_be16(&src[2]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get a 16-bit integer stored in little-endian format.
|
||||
*
|
||||
* Get a 16-bit integer, stored in little-endian format in a potentially
|
||||
* unaligned memory location, and convert it to the host endianness.
|
||||
*
|
||||
* @param src Location of the little-endian 16-bit integer to get.
|
||||
*
|
||||
* @return 16-bit integer in host endianness.
|
||||
*/
|
||||
static inline u16_t sys_get_le16(const u8_t src[2])
|
||||
{
|
||||
return ((u16_t)src[1] << 8) | src[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get a 32-bit integer stored in little-endian format.
|
||||
*
|
||||
* Get a 32-bit integer, stored in little-endian format in a potentially
|
||||
* unaligned memory location, and convert it to the host endianness.
|
||||
*
|
||||
* @param src Location of the little-endian 32-bit integer to get.
|
||||
*
|
||||
* @return 32-bit integer in host endianness.
|
||||
*/
|
||||
static inline u32_t sys_get_le32(const u8_t src[4])
|
||||
{
|
||||
return ((u32_t)sys_get_le16(&src[2]) << 16) | sys_get_le16(&src[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get a 64-bit integer stored in little-endian format.
|
||||
*
|
||||
* Get a 64-bit integer, stored in little-endian format in a potentially
|
||||
* unaligned memory location, and convert it to the host endianness.
|
||||
*
|
||||
* @param src Location of the little-endian 64-bit integer to get.
|
||||
*
|
||||
* @return 64-bit integer in host endianness.
|
||||
*/
|
||||
static inline u64_t sys_get_le64(const u8_t src[8])
|
||||
{
|
||||
return ((u64_t)sys_get_le32(&src[4]) << 32) | sys_get_le32(&src[0]);
|
||||
}
|
||||
#define Z_IS_ENABLED3(ignore_this, val, ...) val
|
||||
|
||||
const char *bt_hex(const void *buf, size_t len);
|
||||
|
||||
void mem_rcopy(u8_t *dst, u8_t const *src, u16_t len);
|
||||
|
||||
void _set(void *to, uint8_t val, unsigned int len);
|
||||
|
||||
unsigned int _copy(uint8_t *to, unsigned int to_len,
|
||||
const uint8_t *from, unsigned int from_len);
|
||||
|
||||
@@ -385,57 +194,6 @@ uint8_t _double_byte(uint8_t a);
|
||||
|
||||
int _compare(const uint8_t *a, const uint8_t *b, size_t size);
|
||||
|
||||
/**
|
||||
* @brief Swap one buffer content into another
|
||||
*
|
||||
* Copy the content of src buffer into dst buffer in reversed order,
|
||||
* i.e.: src[n] will be put in dst[end-n]
|
||||
* Where n is an index and 'end' the last index in both arrays.
|
||||
* The 2 memory pointers must be pointing to different areas, and have
|
||||
* a minimum size of given length.
|
||||
*
|
||||
* @param dst A valid pointer on a memory area where to copy the data in
|
||||
* @param src A valid pointer on a memory area where to copy the data from
|
||||
* @param length Size of both dst and src memory areas
|
||||
*/
|
||||
static inline void sys_memcpy_swap(void *dst, const void *src, size_t length)
|
||||
{
|
||||
u8_t *pdst = (u8_t *)dst;
|
||||
const u8_t *psrc = (const u8_t *)src;
|
||||
|
||||
__ASSERT(((psrc < pdst && (psrc + length) <= pdst) ||
|
||||
(psrc > pdst && (pdst + length) <= psrc)),
|
||||
"Source and destination buffers must not overlap");
|
||||
|
||||
psrc += length - 1;
|
||||
|
||||
for (; length > 0; length--) {
|
||||
*pdst++ = *psrc--;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Swap buffer content
|
||||
*
|
||||
* In-place memory swap, where final content will be reversed.
|
||||
* I.e.: buf[n] will be put in buf[end-n]
|
||||
* Where n is an index and 'end' the last index of buf.
|
||||
*
|
||||
* @param buf A valid pointer on a memory area to swap
|
||||
* @param length Size of buf memory area
|
||||
*/
|
||||
static inline void sys_mem_swap(void *buf, size_t length)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < (length / 2); i++) {
|
||||
u8_t tmp = ((u8_t *)buf)[i];
|
||||
|
||||
((u8_t *)buf)[i] = ((u8_t *)buf)[length - 1 - i];
|
||||
((u8_t *)buf)[length - 1 - i] = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
*/
|
||||
|
||||
#include "mesh_atomic.h"
|
||||
#include "mesh_kernel.h"
|
||||
#include "mesh_mutex.h"
|
||||
|
||||
#ifndef CONFIG_ATOMIC_OPERATIONS_BUILTIN
|
||||
|
||||
|
||||
@@ -6,10 +6,7 @@
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "mesh_buf.h"
|
||||
#include "mesh_trace.h"
|
||||
#include "mesh_kernel.h"
|
||||
#include "mesh_common.h"
|
||||
|
||||
int net_buf_id(struct net_buf *buf)
|
||||
{
|
||||
@@ -72,32 +69,70 @@ void net_buf_simple_add_le16(struct net_buf_simple *buf, u16_t val)
|
||||
{
|
||||
NET_BUF_SIMPLE_DBG("buf %p val %u", buf, val);
|
||||
|
||||
val = sys_cpu_to_le16(val);
|
||||
memcpy(net_buf_simple_add(buf, sizeof(val)), &val, sizeof(val));
|
||||
sys_put_le16(val, net_buf_simple_add(buf, sizeof(val)));
|
||||
}
|
||||
|
||||
void net_buf_simple_add_be16(struct net_buf_simple *buf, u16_t val)
|
||||
{
|
||||
NET_BUF_SIMPLE_DBG("buf %p val %u", buf, val);
|
||||
|
||||
val = sys_cpu_to_be16(val);
|
||||
memcpy(net_buf_simple_add(buf, sizeof(val)), &val, sizeof(val));
|
||||
sys_put_be16(val, net_buf_simple_add(buf, sizeof(val)));
|
||||
}
|
||||
|
||||
void net_buf_simple_add_le24(struct net_buf_simple *buf, u32_t val)
|
||||
{
|
||||
NET_BUF_SIMPLE_DBG("buf %p val %u", buf, val);
|
||||
|
||||
sys_put_le24(val, net_buf_simple_add(buf, 3));
|
||||
}
|
||||
|
||||
void net_buf_simple_add_be24(struct net_buf_simple *buf, u32_t val)
|
||||
{
|
||||
NET_BUF_SIMPLE_DBG("buf %p val %u", buf, val);
|
||||
|
||||
sys_put_be24(val, net_buf_simple_add(buf, 3));
|
||||
}
|
||||
|
||||
void net_buf_simple_add_le32(struct net_buf_simple *buf, u32_t val)
|
||||
{
|
||||
NET_BUF_SIMPLE_DBG("buf %p val %u", buf, val);
|
||||
|
||||
val = sys_cpu_to_le32(val);
|
||||
memcpy(net_buf_simple_add(buf, sizeof(val)), &val, sizeof(val));
|
||||
sys_put_le32(val, net_buf_simple_add(buf, sizeof(val)));
|
||||
}
|
||||
|
||||
void net_buf_simple_add_be32(struct net_buf_simple *buf, u32_t val)
|
||||
{
|
||||
NET_BUF_SIMPLE_DBG("buf %p val %u", buf, val);
|
||||
|
||||
val = sys_cpu_to_be32(val);
|
||||
memcpy(net_buf_simple_add(buf, sizeof(val)), &val, sizeof(val));
|
||||
sys_put_be32(val, net_buf_simple_add(buf, sizeof(val)));
|
||||
}
|
||||
|
||||
void net_buf_simple_add_le48(struct net_buf_simple *buf, u64_t val)
|
||||
{
|
||||
NET_BUF_SIMPLE_DBG("buf %p val %" PRIu64, buf, val);
|
||||
|
||||
sys_put_le48(val, net_buf_simple_add(buf, 6));
|
||||
}
|
||||
|
||||
void net_buf_simple_add_be48(struct net_buf_simple *buf, u64_t val)
|
||||
{
|
||||
NET_BUF_SIMPLE_DBG("buf %p val %" PRIu64, buf, val);
|
||||
|
||||
sys_put_be48(val, net_buf_simple_add(buf, 6));
|
||||
}
|
||||
|
||||
void net_buf_simple_add_le64(struct net_buf_simple *buf, u64_t val)
|
||||
{
|
||||
NET_BUF_SIMPLE_DBG("buf %p val %" PRIu64, buf, val);
|
||||
|
||||
sys_put_le64(val, net_buf_simple_add(buf, sizeof(val)));
|
||||
}
|
||||
|
||||
void net_buf_simple_add_be64(struct net_buf_simple *buf, u64_t val)
|
||||
{
|
||||
NET_BUF_SIMPLE_DBG("buf %p val %" PRIu64, buf, val);
|
||||
|
||||
sys_put_be64(val, net_buf_simple_add(buf, sizeof(val)));
|
||||
}
|
||||
|
||||
void *net_buf_simple_push(struct net_buf_simple *buf, size_t len)
|
||||
@@ -115,16 +150,14 @@ void net_buf_simple_push_le16(struct net_buf_simple *buf, u16_t val)
|
||||
{
|
||||
NET_BUF_SIMPLE_DBG("buf %p val %u", buf, val);
|
||||
|
||||
val = sys_cpu_to_le16(val);
|
||||
memcpy(net_buf_simple_push(buf, sizeof(val)), &val, sizeof(val));
|
||||
sys_put_le16(val, net_buf_simple_push(buf, sizeof(val)));
|
||||
}
|
||||
|
||||
void net_buf_simple_push_be16(struct net_buf_simple *buf, u16_t val)
|
||||
{
|
||||
NET_BUF_SIMPLE_DBG("buf %p val %u", buf, val);
|
||||
|
||||
val = sys_cpu_to_be16(val);
|
||||
memcpy(net_buf_simple_push(buf, sizeof(val)), &val, sizeof(val));
|
||||
sys_put_be16(val, net_buf_simple_push(buf, sizeof(val)));
|
||||
}
|
||||
|
||||
void net_buf_simple_push_u8(struct net_buf_simple *buf, u8_t val)
|
||||
@@ -134,6 +167,62 @@ void net_buf_simple_push_u8(struct net_buf_simple *buf, u8_t val)
|
||||
*data = val;
|
||||
}
|
||||
|
||||
void net_buf_simple_push_le24(struct net_buf_simple *buf, u32_t val)
|
||||
{
|
||||
NET_BUF_SIMPLE_DBG("buf %p val %u", buf, val);
|
||||
|
||||
sys_put_le24(val, net_buf_simple_push(buf, 3));
|
||||
}
|
||||
|
||||
void net_buf_simple_push_be24(struct net_buf_simple *buf, u32_t val)
|
||||
{
|
||||
NET_BUF_SIMPLE_DBG("buf %p val %u", buf, val);
|
||||
|
||||
sys_put_be24(val, net_buf_simple_push(buf, 3));
|
||||
}
|
||||
|
||||
void net_buf_simple_push_le32(struct net_buf_simple *buf, u32_t val)
|
||||
{
|
||||
NET_BUF_SIMPLE_DBG("buf %p val %u", buf, val);
|
||||
|
||||
sys_put_le32(val, net_buf_simple_push(buf, sizeof(val)));
|
||||
}
|
||||
|
||||
void net_buf_simple_push_be32(struct net_buf_simple *buf, u32_t val)
|
||||
{
|
||||
NET_BUF_SIMPLE_DBG("buf %p val %u", buf, val);
|
||||
|
||||
sys_put_be32(val, net_buf_simple_push(buf, sizeof(val)));
|
||||
}
|
||||
|
||||
void net_buf_simple_push_le48(struct net_buf_simple *buf, u64_t val)
|
||||
{
|
||||
NET_BUF_SIMPLE_DBG("buf %p val %" PRIu64, buf, val);
|
||||
|
||||
sys_put_le48(val, net_buf_simple_push(buf, 6));
|
||||
}
|
||||
|
||||
void net_buf_simple_push_be48(struct net_buf_simple *buf, u64_t val)
|
||||
{
|
||||
NET_BUF_SIMPLE_DBG("buf %p val %" PRIu64, buf, val);
|
||||
|
||||
sys_put_be48(val, net_buf_simple_push(buf, 6));
|
||||
}
|
||||
|
||||
void net_buf_simple_push_le64(struct net_buf_simple *buf, u64_t val)
|
||||
{
|
||||
NET_BUF_SIMPLE_DBG("buf %p val %" PRIu64, buf, val);
|
||||
|
||||
sys_put_le64(val, net_buf_simple_push(buf, sizeof(val)));
|
||||
}
|
||||
|
||||
void net_buf_simple_push_be64(struct net_buf_simple *buf, u64_t val)
|
||||
{
|
||||
NET_BUF_SIMPLE_DBG("buf %p val %" PRIu64, buf, val);
|
||||
|
||||
sys_put_be64(val, net_buf_simple_push(buf, sizeof(val)));
|
||||
}
|
||||
|
||||
void *net_buf_simple_pull(struct net_buf_simple *buf, size_t len)
|
||||
{
|
||||
NET_BUF_SIMPLE_DBG("buf %p len %u", buf, len);
|
||||
@@ -188,6 +277,30 @@ u16_t net_buf_simple_pull_be16(struct net_buf_simple *buf)
|
||||
return sys_be16_to_cpu(val);
|
||||
}
|
||||
|
||||
u32_t net_buf_simple_pull_le24(struct net_buf_simple *buf)
|
||||
{
|
||||
struct uint24 {
|
||||
u32_t u24:24;
|
||||
} __packed val;
|
||||
|
||||
val = UNALIGNED_GET((struct uint24 *)buf->data);
|
||||
net_buf_simple_pull(buf, sizeof(val));
|
||||
|
||||
return sys_le24_to_cpu(val.u24);
|
||||
}
|
||||
|
||||
u32_t net_buf_simple_pull_be24(struct net_buf_simple *buf)
|
||||
{
|
||||
struct uint24 {
|
||||
u32_t u24:24;
|
||||
} __packed val;
|
||||
|
||||
val = UNALIGNED_GET((struct uint24 *)buf->data);
|
||||
net_buf_simple_pull(buf, sizeof(val));
|
||||
|
||||
return sys_be24_to_cpu(val.u24);
|
||||
}
|
||||
|
||||
u32_t net_buf_simple_pull_le32(struct net_buf_simple *buf)
|
||||
{
|
||||
u32_t val = 0U;
|
||||
@@ -208,6 +321,50 @@ u32_t net_buf_simple_pull_be32(struct net_buf_simple *buf)
|
||||
return sys_be32_to_cpu(val);
|
||||
}
|
||||
|
||||
u64_t net_buf_simple_pull_le48(struct net_buf_simple *buf)
|
||||
{
|
||||
struct uint48 {
|
||||
u64_t u48:48;
|
||||
} __packed val;
|
||||
|
||||
val = UNALIGNED_GET((struct uint48 *)buf->data);
|
||||
net_buf_simple_pull(buf, sizeof(val));
|
||||
|
||||
return sys_le48_to_cpu(val.u48);
|
||||
}
|
||||
|
||||
u64_t net_buf_simple_pull_be48(struct net_buf_simple *buf)
|
||||
{
|
||||
struct uint48 {
|
||||
u64_t u48:48;
|
||||
} __packed val;
|
||||
|
||||
val = UNALIGNED_GET((struct uint48 *)buf->data);
|
||||
net_buf_simple_pull(buf, sizeof(val));
|
||||
|
||||
return sys_be48_to_cpu(val.u48);
|
||||
}
|
||||
|
||||
u64_t net_buf_simple_pull_le64(struct net_buf_simple *buf)
|
||||
{
|
||||
u64_t val;
|
||||
|
||||
val = UNALIGNED_GET((u64_t *)buf->data);
|
||||
net_buf_simple_pull(buf, sizeof(val));
|
||||
|
||||
return sys_le64_to_cpu(val);
|
||||
}
|
||||
|
||||
u64_t net_buf_simple_pull_be64(struct net_buf_simple *buf)
|
||||
{
|
||||
u64_t val;
|
||||
|
||||
val = UNALIGNED_GET((u64_t *)buf->data);
|
||||
net_buf_simple_pull(buf, sizeof(val));
|
||||
|
||||
return sys_be64_to_cpu(val);
|
||||
}
|
||||
|
||||
size_t net_buf_simple_headroom(struct net_buf_simple *buf)
|
||||
{
|
||||
return buf->data - buf->__buf;
|
||||
|
||||
@@ -65,62 +65,3 @@ u8_t bt_mesh_get_device_role(struct bt_mesh_model *model, bool srv_send)
|
||||
|
||||
return client->msg_role;
|
||||
}
|
||||
|
||||
void bt_mesh_mutex_create(bt_mesh_mutex_t *mutex)
|
||||
{
|
||||
if (!mutex) {
|
||||
BT_ERR("%s, Invalid mutex", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
#if CONFIG_SPIRAM_USE_MALLOC
|
||||
mutex->buffer = heap_caps_calloc(1, sizeof(StaticQueue_t), MALLOC_CAP_DEFAULT|MALLOC_CAP_SPIRAM);
|
||||
__ASSERT(mutex->buffer, "%s, Failed to create queue buffer", __func__);
|
||||
mutex->mutex = xSemaphoreCreateMutexStatic(mutex->buffer);
|
||||
__ASSERT(mutex->mutex, "%s, Failed to create static mutex", __func__);
|
||||
#else
|
||||
mutex->mutex = xSemaphoreCreateMutex();
|
||||
__ASSERT(mutex->mutex, "%s, Failed to create mutex", __func__);
|
||||
#endif
|
||||
}
|
||||
|
||||
void bt_mesh_mutex_free(bt_mesh_mutex_t *mutex)
|
||||
{
|
||||
if (!mutex) {
|
||||
BT_ERR("%s, Invalid mutex", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mutex->mutex) {
|
||||
vSemaphoreDelete(mutex->mutex);
|
||||
mutex->mutex = NULL;
|
||||
#if CONFIG_SPIRAM_USE_MALLOC
|
||||
heap_caps_free(mutex->buffer);
|
||||
mutex->buffer = NULL;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void bt_mesh_mutex_lock(bt_mesh_mutex_t *mutex)
|
||||
{
|
||||
if (!mutex) {
|
||||
BT_ERR("%s, Invalid mutex", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mutex->mutex) {
|
||||
xSemaphoreTake(mutex->mutex, portMAX_DELAY);
|
||||
}
|
||||
}
|
||||
|
||||
void bt_mesh_mutex_unlock(bt_mesh_mutex_t *mutex)
|
||||
{
|
||||
if (!mutex) {
|
||||
BT_ERR("%s, Invalid mutex", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mutex->mutex) {
|
||||
xSemaphoreGive(mutex->mutex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,293 +1,14 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Intel Corporation
|
||||
* Copyright (c) 2016 Wind River Systems, Inc.
|
||||
* Additional Copyright (c) 2018 Espressif Systems (Shanghai) PTE LTD
|
||||
* Additional Copyright (c) 2020 Espressif Systems (Shanghai) PTE LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include "osi/hash_map.h"
|
||||
#include "osi/alarm.h"
|
||||
#include "osi/hash_functions.h"
|
||||
|
||||
#include "mesh_common.h"
|
||||
#include "provisioner_prov.h"
|
||||
|
||||
static bt_mesh_mutex_t bm_alarm_lock;
|
||||
static bt_mesh_mutex_t bm_list_lock;
|
||||
static bt_mesh_mutex_t bm_buf_lock;
|
||||
static bt_mesh_mutex_t bm_atomic_lock;
|
||||
static hash_map_t *bm_alarm_hash_map;
|
||||
static const size_t BLE_MESH_GENERAL_ALARM_HASH_MAP_SIZE = 20 + CONFIG_BLE_MESH_PBA_SAME_TIME + \
|
||||
CONFIG_BLE_MESH_PBG_SAME_TIME;
|
||||
|
||||
typedef struct alarm_t {
|
||||
/* timer id point to here */
|
||||
esp_timer_handle_t alarm_hdl;
|
||||
osi_alarm_callback_t cb;
|
||||
void *cb_data;
|
||||
int64_t deadline_us;
|
||||
} osi_alarm_t;
|
||||
|
||||
static void bt_mesh_alarm_mutex_new(void)
|
||||
{
|
||||
if (!bm_alarm_lock.mutex) {
|
||||
bt_mesh_mutex_create(&bm_alarm_lock);
|
||||
}
|
||||
}
|
||||
|
||||
static void bt_mesh_alarm_mutex_free(void)
|
||||
{
|
||||
bt_mesh_mutex_free(&bm_alarm_lock);
|
||||
}
|
||||
|
||||
static void bt_mesh_alarm_lock(void)
|
||||
{
|
||||
bt_mesh_mutex_lock(&bm_alarm_lock);
|
||||
}
|
||||
|
||||
static void bt_mesh_alarm_unlock(void)
|
||||
{
|
||||
bt_mesh_mutex_unlock(&bm_alarm_lock);
|
||||
}
|
||||
|
||||
static void bt_mesh_list_mutex_new(void)
|
||||
{
|
||||
if (!bm_list_lock.mutex) {
|
||||
bt_mesh_mutex_create(&bm_list_lock);
|
||||
}
|
||||
}
|
||||
|
||||
static void bt_mesh_list_mutex_free(void)
|
||||
{
|
||||
bt_mesh_mutex_free(&bm_list_lock);
|
||||
}
|
||||
|
||||
void bt_mesh_list_lock(void)
|
||||
{
|
||||
bt_mesh_mutex_lock(&bm_list_lock);
|
||||
}
|
||||
|
||||
void bt_mesh_list_unlock(void)
|
||||
{
|
||||
bt_mesh_mutex_unlock(&bm_list_lock);
|
||||
}
|
||||
|
||||
static void bt_mesh_buf_mutex_new(void)
|
||||
{
|
||||
if (!bm_buf_lock.mutex) {
|
||||
bt_mesh_mutex_create(&bm_buf_lock);
|
||||
}
|
||||
}
|
||||
|
||||
static void bt_mesh_buf_mutex_free(void)
|
||||
{
|
||||
bt_mesh_mutex_free(&bm_buf_lock);
|
||||
}
|
||||
|
||||
void bt_mesh_buf_lock(void)
|
||||
{
|
||||
bt_mesh_mutex_lock(&bm_buf_lock);
|
||||
}
|
||||
|
||||
void bt_mesh_buf_unlock(void)
|
||||
{
|
||||
bt_mesh_mutex_unlock(&bm_buf_lock);
|
||||
}
|
||||
|
||||
static void bt_mesh_atomic_mutex_new(void)
|
||||
{
|
||||
if (!bm_atomic_lock.mutex) {
|
||||
bt_mesh_mutex_create(&bm_atomic_lock);
|
||||
}
|
||||
}
|
||||
|
||||
static void bt_mesh_atomic_mutex_free(void)
|
||||
{
|
||||
bt_mesh_mutex_free(&bm_atomic_lock);
|
||||
}
|
||||
|
||||
void bt_mesh_atomic_lock(void)
|
||||
{
|
||||
bt_mesh_mutex_lock(&bm_atomic_lock);
|
||||
}
|
||||
|
||||
void bt_mesh_atomic_unlock(void)
|
||||
{
|
||||
bt_mesh_mutex_unlock(&bm_atomic_lock);
|
||||
}
|
||||
|
||||
s64_t k_uptime_get(void)
|
||||
{
|
||||
/** k_uptime_get_32 is in in milliseconds,
|
||||
* but esp_timer_get_time is in microseconds
|
||||
*/
|
||||
return (esp_timer_get_time() / 1000);
|
||||
}
|
||||
|
||||
u32_t k_uptime_get_32(void)
|
||||
{
|
||||
/** k_uptime_get_32 is in in milliseconds,
|
||||
* but esp_timer_get_time is in microseconds
|
||||
*/
|
||||
return (u32_t)(esp_timer_get_time() / 1000);
|
||||
}
|
||||
#include "mesh_kernel.h"
|
||||
|
||||
void k_sleep(s32_t duration)
|
||||
{
|
||||
vTaskDelay(duration / portTICK_PERIOD_MS);
|
||||
return;
|
||||
}
|
||||
|
||||
void bt_mesh_k_init(void)
|
||||
{
|
||||
bt_mesh_alarm_mutex_new();
|
||||
bt_mesh_list_mutex_new();
|
||||
bt_mesh_buf_mutex_new();
|
||||
bt_mesh_atomic_mutex_new();
|
||||
bm_alarm_hash_map = hash_map_new(BLE_MESH_GENERAL_ALARM_HASH_MAP_SIZE,
|
||||
hash_function_pointer, NULL,
|
||||
(data_free_fn)osi_alarm_free, NULL);
|
||||
__ASSERT(bm_alarm_hash_map, "%s, Failed to create hash map", __func__);
|
||||
}
|
||||
|
||||
void bt_mesh_k_deinit(void)
|
||||
{
|
||||
bt_mesh_alarm_mutex_free();
|
||||
bt_mesh_list_mutex_free();
|
||||
bt_mesh_buf_mutex_free();
|
||||
bt_mesh_atomic_mutex_free();
|
||||
if (bm_alarm_hash_map) {
|
||||
hash_map_free(bm_alarm_hash_map);
|
||||
bm_alarm_hash_map = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void k_delayed_work_init(struct k_delayed_work *work, k_work_handler_t handler)
|
||||
{
|
||||
osi_alarm_t *alarm = NULL;
|
||||
|
||||
if (!work || !bm_alarm_hash_map) {
|
||||
BT_ERR("%s, Invalid parameter", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
k_work_init(&work->work, handler);
|
||||
|
||||
bt_mesh_alarm_lock();
|
||||
if (!hash_map_has_key(bm_alarm_hash_map, (void *)work)) {
|
||||
alarm = osi_alarm_new("bt_mesh", (osi_alarm_callback_t)handler, (void *)&work->work, 0);
|
||||
if (alarm == NULL) {
|
||||
BT_ERR("%s, Unable to create alarm", __func__);
|
||||
bt_mesh_alarm_unlock();
|
||||
return;
|
||||
}
|
||||
if (!hash_map_set(bm_alarm_hash_map, work, (void *)alarm)) {
|
||||
BT_ERR("%s Unable to add the timer to hash map.", __func__);
|
||||
}
|
||||
}
|
||||
bt_mesh_alarm_unlock();
|
||||
|
||||
alarm = hash_map_get(bm_alarm_hash_map, work);
|
||||
if (alarm == NULL) {
|
||||
BT_WARN("%s, Unable to find expected alarm in hash map", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
// Just init the work timer only, don't start it.
|
||||
osi_alarm_cancel(alarm);
|
||||
return;
|
||||
}
|
||||
|
||||
int k_delayed_work_submit(struct k_delayed_work *work, s32_t delay)
|
||||
{
|
||||
if (!work || !bm_alarm_hash_map) {
|
||||
BT_ERR("%s, Invalid parameter", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
osi_alarm_t *alarm = hash_map_get(bm_alarm_hash_map, (void *)work);
|
||||
if (alarm == NULL) {
|
||||
BT_WARN("%s, Unable to find expected alarm in hash map", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
// Cancel the alarm first, before start the alarm.
|
||||
osi_alarm_cancel(alarm);
|
||||
osi_alarm_set(alarm, delay);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int k_delayed_work_submit_periodic(struct k_delayed_work *work, s32_t period)
|
||||
{
|
||||
if (!work || !bm_alarm_hash_map) {
|
||||
BT_ERR("%s, Invalid parameter", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
osi_alarm_t *alarm = hash_map_get(bm_alarm_hash_map, (void *)work);
|
||||
if (alarm == NULL) {
|
||||
BT_WARN("%s, Unable to find expected alarm in hash map", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Cancel the alarm first before starting it. */
|
||||
osi_alarm_cancel(alarm);
|
||||
osi_alarm_set_periodic(alarm, period);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int k_delayed_work_cancel(struct k_delayed_work *work)
|
||||
{
|
||||
if (!work || !bm_alarm_hash_map) {
|
||||
BT_ERR("%s, Invalid parameter", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
osi_alarm_t *alarm = hash_map_get(bm_alarm_hash_map, (void *)work);
|
||||
if (alarm == NULL) {
|
||||
BT_WARN("%s, Unable to find expected alarm in hash map", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
osi_alarm_cancel(alarm);
|
||||
alarm->deadline_us = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int k_delayed_work_free(struct k_delayed_work *work)
|
||||
{
|
||||
if (!work || !bm_alarm_hash_map) {
|
||||
BT_ERR("%s, Invalid parameter", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
osi_alarm_t *alarm = hash_map_get(bm_alarm_hash_map, work);
|
||||
if (alarm == NULL) {
|
||||
BT_WARN("%s Unable to find expected alarm in hash map", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
osi_alarm_cancel(alarm);
|
||||
hash_map_erase(bm_alarm_hash_map, work);
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32_t k_delayed_work_remaining_get(struct k_delayed_work *work)
|
||||
{
|
||||
if (!work || !bm_alarm_hash_map) {
|
||||
BT_ERR("%s, Invalid parameter", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
osi_alarm_t *alarm = hash_map_get(bm_alarm_hash_map, (void *)work);
|
||||
if (alarm == NULL) {
|
||||
BT_WARN("%s Unable to find expected alarm in hash map", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return osi_alarm_get_remaining_ms(alarm);
|
||||
}
|
||||
|
||||
183
components/bt/esp_ble_mesh/mesh_common/mesh_mutex.c
Normal file
183
components/bt/esp_ble_mesh/mesh_common/mesh_mutex.c
Normal file
@@ -0,0 +1,183 @@
|
||||
// Copyright 2017-2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "mesh_common.h"
|
||||
|
||||
static bt_mesh_mutex_t alarm_lock;
|
||||
static bt_mesh_mutex_t list_lock;
|
||||
static bt_mesh_mutex_t buf_lock;
|
||||
static bt_mesh_mutex_t atomic_lock;
|
||||
|
||||
void bt_mesh_mutex_create(bt_mesh_mutex_t *mutex)
|
||||
{
|
||||
if (!mutex) {
|
||||
BT_ERR("%s, Invalid mutex", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
#if CONFIG_SPIRAM_USE_MALLOC
|
||||
mutex->buffer = heap_caps_calloc(1, sizeof(StaticQueue_t), MALLOC_CAP_DEFAULT|MALLOC_CAP_SPIRAM);
|
||||
__ASSERT(mutex->buffer, "%s, Failed to create queue buffer", __func__);
|
||||
mutex->mutex = xSemaphoreCreateMutexStatic(mutex->buffer);
|
||||
__ASSERT(mutex->mutex, "%s, Failed to create static mutex", __func__);
|
||||
#else
|
||||
mutex->mutex = xSemaphoreCreateMutex();
|
||||
__ASSERT(mutex->mutex, "%s, Failed to create mutex", __func__);
|
||||
#endif
|
||||
}
|
||||
|
||||
void bt_mesh_mutex_free(bt_mesh_mutex_t *mutex)
|
||||
{
|
||||
if (!mutex) {
|
||||
BT_ERR("%s, Invalid mutex", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mutex->mutex) {
|
||||
vSemaphoreDelete(mutex->mutex);
|
||||
mutex->mutex = NULL;
|
||||
#if CONFIG_SPIRAM_USE_MALLOC
|
||||
heap_caps_free(mutex->buffer);
|
||||
mutex->buffer = NULL;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void bt_mesh_mutex_lock(bt_mesh_mutex_t *mutex)
|
||||
{
|
||||
if (!mutex) {
|
||||
BT_ERR("%s, Invalid mutex", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mutex->mutex) {
|
||||
xSemaphoreTake(mutex->mutex, portMAX_DELAY);
|
||||
}
|
||||
}
|
||||
|
||||
void bt_mesh_mutex_unlock(bt_mesh_mutex_t *mutex)
|
||||
{
|
||||
if (!mutex) {
|
||||
BT_ERR("%s, Invalid mutex", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mutex->mutex) {
|
||||
xSemaphoreGive(mutex->mutex);
|
||||
}
|
||||
}
|
||||
|
||||
static void bt_mesh_alarm_mutex_new(void)
|
||||
{
|
||||
if (!alarm_lock.mutex) {
|
||||
bt_mesh_mutex_create(&alarm_lock);
|
||||
}
|
||||
}
|
||||
|
||||
static void bt_mesh_alarm_mutex_free(void)
|
||||
{
|
||||
bt_mesh_mutex_free(&alarm_lock);
|
||||
}
|
||||
|
||||
void bt_mesh_alarm_lock(void)
|
||||
{
|
||||
bt_mesh_mutex_lock(&alarm_lock);
|
||||
}
|
||||
|
||||
void bt_mesh_alarm_unlock(void)
|
||||
{
|
||||
bt_mesh_mutex_unlock(&alarm_lock);
|
||||
}
|
||||
|
||||
static void bt_mesh_list_mutex_new(void)
|
||||
{
|
||||
if (!list_lock.mutex) {
|
||||
bt_mesh_mutex_create(&list_lock);
|
||||
}
|
||||
}
|
||||
|
||||
static void bt_mesh_list_mutex_free(void)
|
||||
{
|
||||
bt_mesh_mutex_free(&list_lock);
|
||||
}
|
||||
|
||||
void bt_mesh_list_lock(void)
|
||||
{
|
||||
bt_mesh_mutex_lock(&list_lock);
|
||||
}
|
||||
|
||||
void bt_mesh_list_unlock(void)
|
||||
{
|
||||
bt_mesh_mutex_unlock(&list_lock);
|
||||
}
|
||||
|
||||
static void bt_mesh_buf_mutex_new(void)
|
||||
{
|
||||
if (!buf_lock.mutex) {
|
||||
bt_mesh_mutex_create(&buf_lock);
|
||||
}
|
||||
}
|
||||
|
||||
static void bt_mesh_buf_mutex_free(void)
|
||||
{
|
||||
bt_mesh_mutex_free(&buf_lock);
|
||||
}
|
||||
|
||||
void bt_mesh_buf_lock(void)
|
||||
{
|
||||
bt_mesh_mutex_lock(&buf_lock);
|
||||
}
|
||||
|
||||
void bt_mesh_buf_unlock(void)
|
||||
{
|
||||
bt_mesh_mutex_unlock(&buf_lock);
|
||||
}
|
||||
|
||||
static void bt_mesh_atomic_mutex_new(void)
|
||||
{
|
||||
if (!atomic_lock.mutex) {
|
||||
bt_mesh_mutex_create(&atomic_lock);
|
||||
}
|
||||
}
|
||||
|
||||
static void bt_mesh_atomic_mutex_free(void)
|
||||
{
|
||||
bt_mesh_mutex_free(&atomic_lock);
|
||||
}
|
||||
|
||||
void bt_mesh_atomic_lock(void)
|
||||
{
|
||||
bt_mesh_mutex_lock(&atomic_lock);
|
||||
}
|
||||
|
||||
void bt_mesh_atomic_unlock(void)
|
||||
{
|
||||
bt_mesh_mutex_unlock(&atomic_lock);
|
||||
}
|
||||
|
||||
void bt_mesh_mutex_init(void)
|
||||
{
|
||||
bt_mesh_alarm_mutex_new();
|
||||
bt_mesh_list_mutex_new();
|
||||
bt_mesh_buf_mutex_new();
|
||||
bt_mesh_atomic_mutex_new();
|
||||
}
|
||||
|
||||
void bt_mesh_mutex_deinit(void)
|
||||
{
|
||||
bt_mesh_alarm_mutex_free();
|
||||
bt_mesh_list_mutex_free();
|
||||
bt_mesh_buf_mutex_free();
|
||||
bt_mesh_atomic_mutex_free();
|
||||
}
|
||||
207
components/bt/esp_ble_mesh/mesh_common/mesh_timer.c
Normal file
207
components/bt/esp_ble_mesh/mesh_common/mesh_timer.c
Normal file
@@ -0,0 +1,207 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Intel Corporation
|
||||
* Copyright (c) 2016 Wind River Systems, Inc.
|
||||
* Additional Copyright (c) 2018 Espressif Systems (Shanghai) PTE LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include "osi/hash_map.h"
|
||||
#include "osi/alarm.h"
|
||||
#include "osi/hash_functions.h"
|
||||
|
||||
#include "mesh_common.h"
|
||||
#include "provisioner_prov.h"
|
||||
|
||||
static hash_map_t *bm_alarm_hash_map;
|
||||
static const size_t BLE_MESH_GENERAL_ALARM_HASH_MAP_SIZE = 20 + CONFIG_BLE_MESH_PBA_SAME_TIME + \
|
||||
CONFIG_BLE_MESH_PBG_SAME_TIME;
|
||||
|
||||
typedef struct alarm_t {
|
||||
/* timer id point to here */
|
||||
esp_timer_handle_t alarm_hdl;
|
||||
osi_alarm_callback_t cb;
|
||||
void *cb_data;
|
||||
int64_t deadline_us;
|
||||
} osi_alarm_t;
|
||||
|
||||
s64_t k_uptime_get(void)
|
||||
{
|
||||
/** k_uptime_get_32 is in in milliseconds,
|
||||
* but esp_timer_get_time is in microseconds
|
||||
*/
|
||||
return (esp_timer_get_time() / 1000);
|
||||
}
|
||||
|
||||
u32_t k_uptime_get_32(void)
|
||||
{
|
||||
/** k_uptime_get_32 is in in milliseconds,
|
||||
* but esp_timer_get_time is in microseconds
|
||||
*/
|
||||
return (u32_t)(esp_timer_get_time() / 1000);
|
||||
}
|
||||
|
||||
void bt_mesh_timer_init(void)
|
||||
{
|
||||
bm_alarm_hash_map = hash_map_new(BLE_MESH_GENERAL_ALARM_HASH_MAP_SIZE,
|
||||
hash_function_pointer, NULL,
|
||||
(data_free_fn)osi_alarm_free, NULL);
|
||||
__ASSERT(bm_alarm_hash_map, "%s, Failed to create hash map", __func__);
|
||||
}
|
||||
|
||||
void bt_mesh_timer_deinit(void)
|
||||
{
|
||||
if (bm_alarm_hash_map) {
|
||||
hash_map_free(bm_alarm_hash_map);
|
||||
bm_alarm_hash_map = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int k_delayed_work_init(struct k_delayed_work *work, k_work_handler_t handler)
|
||||
{
|
||||
osi_alarm_t *alarm = NULL;
|
||||
|
||||
if (!work || !bm_alarm_hash_map) {
|
||||
BT_ERR("%s, Invalid parameter", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
k_work_init(&work->work, handler);
|
||||
|
||||
bt_mesh_alarm_lock();
|
||||
if (!hash_map_has_key(bm_alarm_hash_map, (void *)work)) {
|
||||
alarm = osi_alarm_new("bt_mesh", (osi_alarm_callback_t)handler, (void *)&work->work, 0);
|
||||
if (alarm == NULL) {
|
||||
BT_ERR("%s, Alarm not created", __func__);
|
||||
bt_mesh_alarm_unlock();
|
||||
return -EIO;
|
||||
}
|
||||
if (!hash_map_set(bm_alarm_hash_map, work, (void *)alarm)) {
|
||||
BT_ERR("%s, Alarm not set", __func__);
|
||||
bt_mesh_alarm_unlock();
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
|
||||
alarm = hash_map_get(bm_alarm_hash_map, work);
|
||||
if (alarm == NULL) {
|
||||
BT_ERR("%s, Alarm not found", __func__);
|
||||
bt_mesh_alarm_unlock();
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
// Just init the work timer only, don't start it.
|
||||
osi_alarm_cancel(alarm);
|
||||
bt_mesh_alarm_unlock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int k_delayed_work_submit(struct k_delayed_work *work, s32_t delay)
|
||||
{
|
||||
if (!work || !bm_alarm_hash_map) {
|
||||
BT_ERR("%s, Invalid parameter", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
bt_mesh_alarm_lock();
|
||||
osi_alarm_t *alarm = hash_map_get(bm_alarm_hash_map, (void *)work);
|
||||
if (alarm == NULL) {
|
||||
BT_WARN("%s, Alarm not found", __func__);
|
||||
bt_mesh_alarm_unlock();
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
// Cancel the alarm first, before start the alarm.
|
||||
osi_alarm_cancel(alarm);
|
||||
osi_alarm_set(alarm, delay);
|
||||
bt_mesh_alarm_unlock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int k_delayed_work_submit_periodic(struct k_delayed_work *work, s32_t period)
|
||||
{
|
||||
if (!work || !bm_alarm_hash_map) {
|
||||
BT_ERR("%s, Invalid parameter", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
bt_mesh_alarm_lock();
|
||||
osi_alarm_t *alarm = hash_map_get(bm_alarm_hash_map, (void *)work);
|
||||
if (alarm == NULL) {
|
||||
BT_WARN("%s, Alarm not found", __func__);
|
||||
bt_mesh_alarm_unlock();
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Cancel the alarm first before starting it. */
|
||||
osi_alarm_cancel(alarm);
|
||||
osi_alarm_set_periodic(alarm, period);
|
||||
bt_mesh_alarm_unlock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int k_delayed_work_cancel(struct k_delayed_work *work)
|
||||
{
|
||||
if (!work || !bm_alarm_hash_map) {
|
||||
BT_ERR("%s, Invalid parameter", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
bt_mesh_alarm_lock();
|
||||
osi_alarm_t *alarm = hash_map_get(bm_alarm_hash_map, (void *)work);
|
||||
if (alarm == NULL) {
|
||||
BT_WARN("%s, Alarm not found", __func__);
|
||||
bt_mesh_alarm_unlock();
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
osi_alarm_cancel(alarm);
|
||||
alarm->deadline_us = 0;
|
||||
bt_mesh_alarm_unlock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int k_delayed_work_free(struct k_delayed_work *work)
|
||||
{
|
||||
if (!work || !bm_alarm_hash_map) {
|
||||
BT_ERR("%s, Invalid parameter", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
bt_mesh_alarm_lock();
|
||||
osi_alarm_t *alarm = hash_map_get(bm_alarm_hash_map, work);
|
||||
if (alarm == NULL) {
|
||||
BT_WARN("%s, Alarm not found", __func__);
|
||||
bt_mesh_alarm_unlock();
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
osi_alarm_cancel(alarm);
|
||||
hash_map_erase(bm_alarm_hash_map, work);
|
||||
bt_mesh_alarm_unlock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32_t k_delayed_work_remaining_get(struct k_delayed_work *work)
|
||||
{
|
||||
s32_t time = 0;
|
||||
|
||||
if (!work || !bm_alarm_hash_map) {
|
||||
BT_ERR("%s, Invalid parameter", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bt_mesh_alarm_lock();
|
||||
osi_alarm_t *alarm = hash_map_get(bm_alarm_hash_map, (void *)work);
|
||||
if (alarm == NULL) {
|
||||
BT_WARN("%s, Alarm not found", __func__);
|
||||
bt_mesh_alarm_unlock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
time = osi_alarm_get_remaining_ms(alarm);
|
||||
bt_mesh_alarm_unlock();
|
||||
return time;
|
||||
}
|
||||
@@ -396,18 +396,22 @@ static int publish_retransmit(struct bt_mesh_model *mod)
|
||||
};
|
||||
int err = 0;
|
||||
|
||||
key = bt_mesh_app_key_find(pub->key);
|
||||
key = bt_mesh_tx_appkey_get(pub->dev_role, pub->key);
|
||||
if (!key) {
|
||||
BT_ERR("%s, Failed to find AppKey", __func__);
|
||||
return -EADDRNOTAVAIL;
|
||||
}
|
||||
|
||||
tx.sub = bt_mesh_subnet_get(key->net_idx);
|
||||
tx.sub = bt_mesh_tx_netkey_get(pub->dev_role, key->net_idx);
|
||||
if (!tx.sub) {
|
||||
BT_ERR("%s, Failed to get subnet", __func__);
|
||||
return -EADDRNOTAVAIL;
|
||||
}
|
||||
|
||||
ctx.net_idx = key->net_idx;
|
||||
ctx.app_idx = key->app_idx;
|
||||
|
||||
sdu = bt_mesh_alloc_buf(pub->msg->len + 4);
|
||||
sdu = bt_mesh_alloc_buf(pub->msg->len + BLE_MESH_MIC_SHORT);
|
||||
if (!sdu) {
|
||||
BT_ERR("%s, Failed to allocate memory", __func__);
|
||||
return -ENOMEM;
|
||||
@@ -423,6 +427,14 @@ static int publish_retransmit(struct bt_mesh_model *mod)
|
||||
return err;
|
||||
}
|
||||
|
||||
static void publish_retransmit_end(int err, struct bt_mesh_model_pub *pub)
|
||||
{
|
||||
/* Cancel all retransmits for this publish attempt */
|
||||
pub->count = 0U;
|
||||
/* Make sure the publish timer gets reset */
|
||||
publish_sent(err, pub->mod);
|
||||
}
|
||||
|
||||
static void mod_publish(struct k_work *work)
|
||||
{
|
||||
struct bt_mesh_model_pub *pub = CONTAINER_OF(work,
|
||||
@@ -464,7 +476,10 @@ static void mod_publish(struct k_work *work)
|
||||
*/
|
||||
err = pub->update(pub->mod);
|
||||
if (err) {
|
||||
BT_ERR("%s, Failed to update publication message", __func__);
|
||||
/* Cancel this publish attempt. */
|
||||
BT_ERR("Update failed, skipping publish (err %d)", err);
|
||||
pub->period_start = k_uptime_get_32();
|
||||
publish_retransmit_end(err, pub);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -612,7 +627,7 @@ void bt_mesh_comp_provision(u16_t addr)
|
||||
|
||||
dev_primary_addr = addr;
|
||||
|
||||
BT_INFO("addr 0x%04x elem_count %u", addr, dev_comp->elem_count);
|
||||
BT_INFO("Primary address 0x%04x, element count %u", addr, dev_comp->elem_count);
|
||||
|
||||
for (i = 0; i < dev_comp->elem_count; i++) {
|
||||
struct bt_mesh_elem *elem = &dev_comp->elem[i];
|
||||
@@ -782,6 +797,10 @@ static int get_opcode(struct net_buf_simple *buf, u32_t *opcode)
|
||||
}
|
||||
|
||||
*opcode = net_buf_simple_pull_u8(buf) << 16;
|
||||
/* Using LE for the CID since the model layer is defined as
|
||||
* little-endian in the mesh spec and using BT_MESH_MODEL_OP_3
|
||||
* will declare the opcode in this way.
|
||||
*/
|
||||
*opcode |= net_buf_simple_pull_le16(buf);
|
||||
return 0;
|
||||
}
|
||||
@@ -823,7 +842,7 @@ void bt_mesh_model_recv(struct bt_mesh_net_rx *rx, struct net_buf_simple *buf)
|
||||
return;
|
||||
}
|
||||
|
||||
BT_INFO("OpCode 0x%08x", opcode);
|
||||
BT_DBG("OpCode 0x%08x", opcode);
|
||||
|
||||
for (i = 0; i < dev_comp->elem_count; i++) {
|
||||
struct bt_mesh_elem *elem = &dev_comp->elem[i];
|
||||
@@ -906,6 +925,10 @@ void bt_mesh_model_msg_init(struct net_buf_simple *msg, u32_t opcode)
|
||||
break;
|
||||
case 3:
|
||||
net_buf_simple_add_u8(msg, ((opcode >> 16) & 0xff));
|
||||
/* Using LE for the CID since the model layer is defined as
|
||||
* little-endian in the mesh spec and using BT_MESH_MODEL_OP_3
|
||||
* will declare the opcode in this way.
|
||||
*/
|
||||
net_buf_simple_add_le16(msg, opcode & 0xffff);
|
||||
break;
|
||||
default:
|
||||
@@ -944,8 +967,8 @@ static int model_send(struct bt_mesh_model *model,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
BT_INFO("net_idx 0x%04x app_idx 0x%04x dst 0x%04x", tx->ctx->net_idx,
|
||||
tx->ctx->app_idx, tx->ctx->addr);
|
||||
BT_INFO("app_idx 0x%04x src 0x%04x dst 0x%04x",
|
||||
tx->ctx->app_idx, tx->src, tx->ctx->addr);
|
||||
BT_INFO("len %u: %s", msg->len, bt_hex(msg->data, msg->len));
|
||||
|
||||
if (!ready_to_send(role, tx->ctx->addr)) {
|
||||
@@ -953,12 +976,12 @@ static int model_send(struct bt_mesh_model *model,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (net_buf_simple_tailroom(msg) < 4) {
|
||||
if (net_buf_simple_tailroom(msg) < BLE_MESH_MIC_SHORT) {
|
||||
BT_ERR("%s, Not enough tailroom for TransMIC", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (msg->len > MIN(BLE_MESH_TX_SDU_MAX, BLE_MESH_SDU_MAX_LEN) - 4) {
|
||||
if (msg->len > MIN(BLE_MESH_TX_SDU_MAX, BLE_MESH_SDU_MAX_LEN) - BLE_MESH_MIC_SHORT) {
|
||||
BT_ERR("%s, Too big message", __func__);
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
@@ -1009,7 +1032,9 @@ int bt_mesh_model_publish(struct bt_mesh_model *model)
|
||||
struct bt_mesh_model_pub *pub = model->pub;
|
||||
struct bt_mesh_app_key *key = NULL;
|
||||
struct net_buf_simple *sdu = NULL;
|
||||
struct bt_mesh_msg_ctx ctx = {0};
|
||||
struct bt_mesh_msg_ctx ctx = {
|
||||
.model = model,
|
||||
};
|
||||
struct bt_mesh_net_tx tx = {
|
||||
.sub = NULL,
|
||||
.ctx = &ctx,
|
||||
@@ -1036,7 +1061,7 @@ int bt_mesh_model_publish(struct bt_mesh_model *model)
|
||||
return -EADDRNOTAVAIL;
|
||||
}
|
||||
|
||||
if (pub->msg->len + 4 > MIN(BLE_MESH_TX_SDU_MAX, BLE_MESH_SDU_MAX_LEN)) {
|
||||
if (pub->msg->len + BLE_MESH_MIC_SHORT > MIN(BLE_MESH_TX_SDU_MAX, BLE_MESH_SDU_MAX_LEN)) {
|
||||
BT_ERR("%s, Message does not fit maximum SDU size", __func__);
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
@@ -1047,6 +1072,7 @@ int bt_mesh_model_publish(struct bt_mesh_model *model)
|
||||
}
|
||||
|
||||
ctx.addr = pub->addr;
|
||||
ctx.send_rel = pub->send_rel;
|
||||
ctx.send_ttl = pub->ttl;
|
||||
ctx.net_idx = key->net_idx;
|
||||
ctx.app_idx = key->app_idx;
|
||||
@@ -1065,7 +1091,7 @@ int bt_mesh_model_publish(struct bt_mesh_model *model)
|
||||
BT_INFO("Publish Retransmit Count %u Interval %ums", pub->count,
|
||||
BLE_MESH_PUB_TRANSMIT_INT(pub->retransmit));
|
||||
|
||||
sdu = bt_mesh_alloc_buf(pub->msg->len + 4);
|
||||
sdu = bt_mesh_alloc_buf(pub->msg->len + BLE_MESH_MIC_SHORT);
|
||||
if (!sdu) {
|
||||
BT_ERR("%s, Failed to allocate memory", __func__);
|
||||
return -ENOMEM;
|
||||
@@ -1075,10 +1101,7 @@ int bt_mesh_model_publish(struct bt_mesh_model *model)
|
||||
|
||||
err = model_send(model, &tx, true, sdu, &pub_sent_cb, model);
|
||||
if (err) {
|
||||
/* Don't try retransmissions for this publish attempt */
|
||||
pub->count = 0U;
|
||||
/* Make sure the publish timer gets reset */
|
||||
publish_sent(err, model);
|
||||
publish_retransmit_end(err, pub);
|
||||
}
|
||||
|
||||
bt_mesh_free_buf(sdu);
|
||||
|
||||
@@ -11,6 +11,10 @@
|
||||
|
||||
#include "net.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* bt_mesh_model.flags */
|
||||
enum {
|
||||
BLE_MESH_MOD_BIND_PENDING = BIT(0),
|
||||
@@ -74,4 +78,8 @@ size_t bt_mesh_rx_appkey_size(void);
|
||||
|
||||
struct bt_mesh_app_key *bt_mesh_rx_appkey_get(size_t index);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _ACCESS_H_ */
|
||||
|
||||
@@ -11,16 +11,12 @@
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "freertos/task.h"
|
||||
|
||||
#include "osi/thread.h"
|
||||
|
||||
#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BLE_MESH_DEBUG_ADV)
|
||||
|
||||
#include "mesh_kernel.h"
|
||||
#include "mesh.h"
|
||||
#include "mesh_hci.h"
|
||||
#include "mesh_common.h"
|
||||
#include "adv.h"
|
||||
#include "beacon.h"
|
||||
#include "prov.h"
|
||||
@@ -32,6 +28,8 @@
|
||||
|
||||
/* Convert from ms to 0.625ms units */
|
||||
#define ADV_SCAN_UNIT(_ms) ((_ms) * 8 / 5)
|
||||
/* Convert from 0.625ms units to interval(ms) */
|
||||
#define ADV_SCAN_INT(val) ((val) * 5 / 8)
|
||||
|
||||
/* Window and Interval are equal for continuous scanning */
|
||||
#define MESH_SCAN_INTERVAL 0x20
|
||||
@@ -73,7 +71,11 @@ struct bt_mesh_queue {
|
||||
|
||||
static struct bt_mesh_queue xBleMeshQueue;
|
||||
/* We reserve one queue for bt_mesh_adv_update() */
|
||||
#define BLE_MESH_QUEUE_SIZE (CONFIG_BLE_MESH_ADV_BUF_COUNT + 1)
|
||||
#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV
|
||||
#define BLE_MESH_QUEUE_SIZE (CONFIG_BLE_MESH_ADV_BUF_COUNT + CONFIG_BLE_MESH_BLE_ADV_BUF_COUNT + 1)
|
||||
#else
|
||||
#define BLE_MESH_QUEUE_SIZE (CONFIG_BLE_MESH_ADV_BUF_COUNT + 1)
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_BLE_MESH_RELAY_ADV_BUF)
|
||||
NET_BUF_POOL_DEFINE(relay_adv_buf_pool, CONFIG_BLE_MESH_RELAY_ADV_BUF_COUNT,
|
||||
@@ -93,6 +95,30 @@ static QueueSetHandle_t xBleMeshQueueSet;
|
||||
static bool ignore_relay_packet(u32_t timestamp);
|
||||
#endif /* defined(CONFIG_BLE_MESH_RELAY_ADV_BUF) */
|
||||
|
||||
#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV
|
||||
/* length + advertising data + length + scan response data */
|
||||
NET_BUF_POOL_DEFINE(ble_adv_buf_pool, CONFIG_BLE_MESH_BLE_ADV_BUF_COUNT,
|
||||
((BLE_MESH_ADV_DATA_SIZE + 3) << 1), BLE_MESH_ADV_USER_DATA_SIZE, NULL);
|
||||
|
||||
static struct bt_mesh_adv ble_adv_pool[CONFIG_BLE_MESH_BLE_ADV_BUF_COUNT];
|
||||
|
||||
enum {
|
||||
TIMER_INIT, /* Resend timer is initialized */
|
||||
NUM_FLAGS,
|
||||
};
|
||||
|
||||
static struct ble_adv_tx {
|
||||
struct bt_mesh_ble_adv_param param;
|
||||
struct net_buf *buf;
|
||||
struct k_delayed_work resend;
|
||||
BLE_MESH_ATOMIC_DEFINE(flags, NUM_FLAGS);
|
||||
} ble_adv_tx[CONFIG_BLE_MESH_BLE_ADV_BUF_COUNT];
|
||||
|
||||
#define SEND_BLE_ADV_INFINITE 0xFFFF
|
||||
|
||||
static void bt_mesh_ble_adv_deinit(void);
|
||||
#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */
|
||||
|
||||
struct bt_mesh_adv_task {
|
||||
TaskHandle_t handle;
|
||||
#if CONFIG_SPIRAM_USE_MALLOC
|
||||
@@ -136,28 +162,63 @@ static inline int adv_send(struct net_buf *buf)
|
||||
struct bt_mesh_adv_data ad = {0};
|
||||
int err = 0;
|
||||
|
||||
adv_int = MAX(adv_int_min,
|
||||
BLE_MESH_TRANSMIT_INT(BLE_MESH_ADV(buf)->xmit));
|
||||
duration = (BLE_MESH_TRANSMIT_COUNT(BLE_MESH_ADV(buf)->xmit) + 1) *
|
||||
(adv_int + 10);
|
||||
|
||||
BT_DBG("type %u len %u: %s", BLE_MESH_ADV(buf)->type,
|
||||
buf->len, bt_hex(buf->data, buf->len));
|
||||
BT_DBG("count %u interval %ums duration %ums",
|
||||
BLE_MESH_TRANSMIT_COUNT(BLE_MESH_ADV(buf)->xmit) + 1, adv_int,
|
||||
duration);
|
||||
buf->len, bt_hex(buf->data, buf->len));
|
||||
|
||||
ad.type = adv_type[BLE_MESH_ADV(buf)->type];
|
||||
ad.data_len = buf->len;
|
||||
ad.data = buf->data;
|
||||
#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV
|
||||
if (BLE_MESH_ADV(buf)->type != BLE_MESH_ADV_BLE) {
|
||||
#endif
|
||||
adv_int = MAX(adv_int_min,
|
||||
BLE_MESH_TRANSMIT_INT(BLE_MESH_ADV(buf)->xmit));
|
||||
duration = (BLE_MESH_TRANSMIT_COUNT(BLE_MESH_ADV(buf)->xmit) + 1) *
|
||||
(adv_int + 10);
|
||||
|
||||
param.options = 0U;
|
||||
param.interval_min = ADV_SCAN_UNIT(adv_int);
|
||||
param.interval_max = param.interval_min;
|
||||
BT_DBG("count %u interval %ums duration %ums",
|
||||
BLE_MESH_TRANSMIT_COUNT(BLE_MESH_ADV(buf)->xmit) + 1, adv_int,
|
||||
duration);
|
||||
|
||||
bt_mesh_adv_buf_ref_debug(__func__, buf, 4U, BLE_MESH_BUF_REF_SMALL);
|
||||
ad.type = adv_type[BLE_MESH_ADV(buf)->type];
|
||||
ad.data_len = buf->len;
|
||||
ad.data = buf->data;
|
||||
|
||||
param.options = 0U;
|
||||
param.interval_min = ADV_SCAN_UNIT(adv_int);
|
||||
param.interval_max = param.interval_min;
|
||||
|
||||
bt_mesh_adv_buf_ref_debug(__func__, buf, 4U, BLE_MESH_BUF_REF_SMALL);
|
||||
|
||||
err = bt_le_adv_start(¶m, &ad, 1, NULL, 0);
|
||||
#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV
|
||||
} else {
|
||||
struct bt_mesh_ble_adv_data data = {0};
|
||||
struct ble_adv_tx *tx = cb_data;
|
||||
|
||||
if (tx == NULL) {
|
||||
BT_ERR("%s, Invalid adv user data", __func__);
|
||||
net_buf_unref(buf);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
BT_DBG("interval %dms, duration %dms, period %dms, count %d",
|
||||
ADV_SCAN_INT(tx->param.interval), tx->param.duration,
|
||||
tx->param.period, tx->param.count);
|
||||
|
||||
data.adv_data_len = tx->buf->data[0];
|
||||
if (data.adv_data_len) {
|
||||
memcpy(data.adv_data, tx->buf->data + 1, data.adv_data_len);
|
||||
}
|
||||
data.scan_rsp_data_len = tx->buf->data[data.adv_data_len + 1];
|
||||
if (data.scan_rsp_data_len) {
|
||||
memcpy(data.scan_rsp_data, tx->buf->data + data.adv_data_len + 2, data.scan_rsp_data_len);
|
||||
}
|
||||
duration = tx->param.duration;
|
||||
|
||||
bt_mesh_adv_buf_ref_debug(__func__, buf, 3U, BLE_MESH_BUF_REF_SMALL);
|
||||
|
||||
err = bt_mesh_ble_adv_start(&tx->param, &data);
|
||||
}
|
||||
#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */
|
||||
|
||||
err = bt_le_adv_start(¶m, &ad, 1, NULL, 0);
|
||||
net_buf_unref(buf);
|
||||
adv_send_start(duration, err, cb, cb_data);
|
||||
if (err) {
|
||||
@@ -329,8 +390,8 @@ void bt_mesh_unref_buf_from_pool(struct net_buf_pool *pool)
|
||||
struct net_buf *buf = &pool->__bufs[i];
|
||||
if (buf->ref > 1U) {
|
||||
buf->ref = 1U;
|
||||
net_buf_unref(buf);
|
||||
}
|
||||
net_buf_unref(buf);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -372,13 +433,16 @@ static void bt_mesh_unref_buf(bt_mesh_msg_t *msg)
|
||||
if (msg->arg) {
|
||||
buf = (struct net_buf *)msg->arg;
|
||||
BLE_MESH_ADV(buf)->busy = 0U;
|
||||
if (buf->ref > 1U) {
|
||||
buf->ref = 1U;
|
||||
}
|
||||
net_buf_unref(buf);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void bt_mesh_task_post(bt_mesh_msg_t *msg, uint32_t timeout)
|
||||
static void bt_mesh_task_post(bt_mesh_msg_t *msg, uint32_t timeout, bool front)
|
||||
{
|
||||
BT_DBG("%s", __func__);
|
||||
|
||||
@@ -387,9 +451,16 @@ static void bt_mesh_task_post(bt_mesh_msg_t *msg, uint32_t timeout)
|
||||
return;
|
||||
}
|
||||
|
||||
if (xQueueSend(xBleMeshQueue.queue, msg, timeout) != pdTRUE) {
|
||||
BT_ERR("%s, Failed to send item to queue", __func__);
|
||||
bt_mesh_unref_buf(msg);
|
||||
if (front) {
|
||||
if (xQueueSendToFront(xBleMeshQueue.queue, msg, timeout) != pdTRUE) {
|
||||
BT_ERR("%s, Failed to send item to queue front", __func__);
|
||||
bt_mesh_unref_buf(msg);
|
||||
}
|
||||
} else {
|
||||
if (xQueueSend(xBleMeshQueue.queue, msg, timeout) != pdTRUE) {
|
||||
BT_ERR("%s, Failed to send item to queue back", __func__);
|
||||
bt_mesh_unref_buf(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -410,7 +481,7 @@ void bt_mesh_adv_send(struct net_buf *buf, const struct bt_mesh_send_cb *cb,
|
||||
bt_mesh_adv_buf_ref_debug(__func__, buf, 3U, BLE_MESH_BUF_REF_SMALL);
|
||||
|
||||
msg.arg = (void *)net_buf_ref(buf);
|
||||
bt_mesh_task_post(&msg, portMAX_DELAY);
|
||||
bt_mesh_task_post(&msg, portMAX_DELAY, false);
|
||||
}
|
||||
|
||||
void bt_mesh_adv_update(void)
|
||||
@@ -422,7 +493,7 @@ void bt_mesh_adv_update(void)
|
||||
|
||||
BT_DBG("%s", __func__);
|
||||
|
||||
bt_mesh_task_post(&msg, K_NO_WAIT);
|
||||
bt_mesh_task_post(&msg, K_NO_WAIT, false);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BLE_MESH_RELAY_ADV_BUF)
|
||||
@@ -543,7 +614,7 @@ static bool bt_mesh_is_adv_flags_valid(struct net_buf_simple *buf)
|
||||
|
||||
BT_DBG("Received adv pkt with flags: 0x%02x", flags);
|
||||
|
||||
/* Flags context will not be checked curently */
|
||||
/* Flags context will not be checked currently */
|
||||
((void) flags);
|
||||
|
||||
return true;
|
||||
@@ -770,7 +841,7 @@ void bt_mesh_adv_init(void)
|
||||
__ASSERT(adv_task.stack, "%s, Failed to create adv thread stack", __func__);
|
||||
adv_task.handle = xTaskCreateStaticPinnedToCore(adv_thread, "BLE_Mesh_ADV_Task", BLE_MESH_ADV_TASK_STACK_SIZE, NULL,
|
||||
configMAX_PRIORITIES - 5, adv_task.stack, adv_task.task, BLE_MESH_ADV_TASK_CORE);
|
||||
__ASSERT(adv_task.stack, "%s, Failed to create static adv thread stack", __func__);
|
||||
__ASSERT(adv_task.handle, "%s, Failed to create static adv thread", __func__);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -780,6 +851,15 @@ void bt_mesh_adv_deinit(void)
|
||||
return;
|
||||
}
|
||||
|
||||
vTaskDelete(adv_task.handle);
|
||||
adv_task.handle = NULL;
|
||||
#if CONFIG_SPIRAM_USE_MALLOC
|
||||
heap_caps_free(adv_task.stack);
|
||||
adv_task.stack = NULL;
|
||||
heap_caps_free(adv_task.task);
|
||||
adv_task.task = NULL;
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_BLE_MESH_RELAY_ADV_BUF)
|
||||
xQueueRemoveFromSet(xBleMeshQueue.queue, xBleMeshQueueSet);
|
||||
xQueueRemoveFromSet(xBleMeshRelayQueue.queue, xBleMeshQueueSet);
|
||||
@@ -812,15 +892,8 @@ void bt_mesh_adv_deinit(void)
|
||||
bt_mesh_unref_buf_from_pool(&adv_buf_pool);
|
||||
memset(adv_pool, 0, sizeof(adv_pool));
|
||||
|
||||
vTaskDelete(adv_task.handle);
|
||||
adv_task.handle = NULL;
|
||||
#if CONFIG_SPIRAM_USE_MALLOC
|
||||
heap_caps_free(adv_task.stack);
|
||||
adv_task.stack = NULL;
|
||||
/* Delay certain period for free adv_task.task */
|
||||
vTaskDelay(10 / portTICK_PERIOD_MS);
|
||||
heap_caps_free(adv_task.task);
|
||||
adv_task.task = NULL;
|
||||
#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV
|
||||
bt_mesh_ble_adv_deinit();
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -836,7 +909,8 @@ int bt_mesh_scan_enable(void)
|
||||
.filter_dup = BLE_MESH_SCAN_FILTER_DUP_DISABLE,
|
||||
#endif
|
||||
.interval = MESH_SCAN_INTERVAL,
|
||||
.window = MESH_SCAN_WINDOW
|
||||
.window = MESH_SCAN_WINDOW,
|
||||
.scan_fil_policy = BLE_MESH_SP_ADV_ALL,
|
||||
};
|
||||
|
||||
BT_DBG("%s", __func__);
|
||||
@@ -864,3 +938,286 @@ int bt_mesh_scan_disable(void)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if CONFIG_BLE_MESH_TEST_USE_WHITE_LIST
|
||||
int bt_mesh_scan_with_wl_enable(void)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
struct bt_mesh_scan_param scan_param = {
|
||||
.type = BLE_MESH_SCAN_PASSIVE,
|
||||
#if defined(CONFIG_BLE_MESH_USE_DUPLICATE_SCAN)
|
||||
.filter_dup = BLE_MESH_SCAN_FILTER_DUP_ENABLE,
|
||||
#else
|
||||
.filter_dup = BLE_MESH_SCAN_FILTER_DUP_DISABLE,
|
||||
#endif
|
||||
.interval = MESH_SCAN_INTERVAL,
|
||||
.window = MESH_SCAN_WINDOW,
|
||||
.scan_fil_policy = BLE_MESH_SP_ADV_WL,
|
||||
};
|
||||
|
||||
BT_DBG("%s", __func__);
|
||||
|
||||
err = bt_le_scan_start(&scan_param, bt_mesh_scan_cb);
|
||||
if (err) {
|
||||
BT_ERR("starting scan failed (err %d)", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_BLE_MESH_TEST_USE_WHITE_LIST */
|
||||
|
||||
#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV
|
||||
static struct bt_mesh_adv *ble_adv_alloc(int id)
|
||||
{
|
||||
return &ble_adv_pool[id];
|
||||
}
|
||||
|
||||
static struct net_buf *bt_mesh_ble_adv_create(enum bt_mesh_adv_type type, u8_t xmit, s32_t timeout)
|
||||
{
|
||||
return bt_mesh_adv_create_from_pool(&ble_adv_buf_pool, ble_adv_alloc, type,
|
||||
xmit, timeout);
|
||||
}
|
||||
|
||||
static void bt_mesh_ble_adv_send(struct net_buf *buf, const struct bt_mesh_send_cb *cb,
|
||||
void *cb_data, bool front)
|
||||
{
|
||||
bt_mesh_msg_t msg = {
|
||||
.relay = false,
|
||||
};
|
||||
|
||||
BT_DBG("type 0x%02x len %u: %s", BLE_MESH_ADV(buf)->type, buf->len,
|
||||
bt_hex(buf->data, buf->len));
|
||||
|
||||
BLE_MESH_ADV(buf)->cb = cb;
|
||||
BLE_MESH_ADV(buf)->cb_data = cb_data;
|
||||
BLE_MESH_ADV(buf)->busy = 1U;
|
||||
|
||||
bt_mesh_adv_buf_ref_debug(__func__, buf, 3U, BLE_MESH_BUF_REF_SMALL);
|
||||
|
||||
msg.arg = (void *)net_buf_ref(buf);
|
||||
bt_mesh_task_post(&msg, portMAX_DELAY, front);
|
||||
}
|
||||
|
||||
static void ble_adv_tx_reset(struct ble_adv_tx *tx, bool unref)
|
||||
{
|
||||
if (tx->buf == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (bt_mesh_atomic_test_bit(tx->flags, TIMER_INIT)) {
|
||||
k_delayed_work_free(&tx->resend);
|
||||
}
|
||||
bt_mesh_atomic_set(tx->flags, 0);
|
||||
memset(&tx->param, 0, sizeof(tx->param));
|
||||
BLE_MESH_ADV(tx->buf)->busy = 0U;
|
||||
if (unref) {
|
||||
net_buf_unref(tx->buf);
|
||||
}
|
||||
tx->buf = NULL;
|
||||
}
|
||||
|
||||
static void ble_adv_send_start(u16_t duration, int err, void *cb_data)
|
||||
{
|
||||
struct ble_adv_tx *tx = cb_data;
|
||||
|
||||
BT_DBG("%s, duration %d, err %d", __func__, duration, err);
|
||||
|
||||
/* If failed to send BLE adv packet, and param->count is not 0
|
||||
* which means the timer has been initialized, here we need to
|
||||
* free the timer.
|
||||
*/
|
||||
if (err) {
|
||||
ble_adv_tx_reset(tx, true);
|
||||
}
|
||||
}
|
||||
|
||||
static void ble_adv_send_end(int err, void *cb_data)
|
||||
{
|
||||
struct ble_adv_tx *tx = cb_data;
|
||||
|
||||
BT_DBG("%s, err %d", __func__, err);
|
||||
|
||||
if (err) {
|
||||
ble_adv_tx_reset(tx, true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (tx->param.count) {
|
||||
if (tx->param.period) {
|
||||
k_delayed_work_submit(&tx->resend, tx->param.period);
|
||||
} else {
|
||||
k_work_submit(&tx->resend.work);
|
||||
}
|
||||
} else {
|
||||
ble_adv_tx_reset(tx, true);
|
||||
}
|
||||
}
|
||||
|
||||
static struct bt_mesh_send_cb ble_adv_send_cb = {
|
||||
.start = ble_adv_send_start,
|
||||
.end = ble_adv_send_end,
|
||||
};
|
||||
|
||||
static void ble_adv_resend(struct k_work *work)
|
||||
{
|
||||
struct ble_adv_tx *tx = CONTAINER_OF(work, struct ble_adv_tx, resend.work);
|
||||
bool front = false;
|
||||
|
||||
if (tx->buf == NULL) {
|
||||
/* The advertising has been cancelled */
|
||||
return;
|
||||
}
|
||||
|
||||
front = (tx->param.priority == BLE_MESH_BLE_ADV_PRIO_HIGH) ? true : false;
|
||||
bt_mesh_ble_adv_send(tx->buf, &ble_adv_send_cb, tx, front);
|
||||
|
||||
if (tx->param.count == SEND_BLE_ADV_INFINITE) {
|
||||
/* Send the BLE advertising packet infinitely */
|
||||
return;
|
||||
}
|
||||
|
||||
if (tx->param.count > 0U) {
|
||||
tx->param.count--;
|
||||
}
|
||||
}
|
||||
|
||||
int bt_mesh_start_ble_advertising(const struct bt_mesh_ble_adv_param *param,
|
||||
const struct bt_mesh_ble_adv_data *data, u8_t *index)
|
||||
{
|
||||
struct ble_adv_tx *tx = NULL;
|
||||
struct net_buf *buf = NULL;
|
||||
bool front = false;
|
||||
|
||||
if (param == NULL || index == NULL) {
|
||||
BT_ERR("%s, Invalid parameter", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (param->adv_type != BLE_MESH_ADV_DIRECT_IND &&
|
||||
(param->interval < 0x20 || param->interval > 0x4000)) {
|
||||
BT_ERR("%s, Invalid adv interval 0x%04x", __func__, param->interval);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (param->adv_type > BLE_MESH_ADV_DIRECT_IND_LOW_DUTY) {
|
||||
BT_ERR("%s, Invalid adv type 0x%02x", __func__, param->adv_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (param->own_addr_type > BLE_MESH_ADDR_RANDOM_ID) {
|
||||
BT_ERR("%s, Invalid own addr type 0x%02x", __func__, param->own_addr_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((param->own_addr_type == BLE_MESH_ADDR_PUBLIC_ID ||
|
||||
param->own_addr_type == BLE_MESH_ADDR_RANDOM_ID ||
|
||||
param->adv_type == BLE_MESH_ADV_DIRECT_IND ||
|
||||
param->adv_type == BLE_MESH_ADV_DIRECT_IND_LOW_DUTY) &&
|
||||
param->peer_addr_type > BLE_MESH_ADDR_RANDOM) {
|
||||
BT_ERR("%s, Invalid peer addr type 0x%02x", __func__, param->peer_addr_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (data && (data->adv_data_len > 31 || data->scan_rsp_data_len > 31)) {
|
||||
BT_ERR("%s, Invalid adv data length, %d %d", __func__,
|
||||
data->adv_data_len, data->scan_rsp_data_len);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (param->priority > BLE_MESH_BLE_ADV_PRIO_HIGH) {
|
||||
BT_ERR("%s, Invalid adv priority %d", __func__, param->priority);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (param->duration < ADV_SCAN_INT(param->interval)) {
|
||||
BT_ERR("%s, Too small duration %dms", __func__, param->duration);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
buf = bt_mesh_ble_adv_create(BLE_MESH_ADV_BLE, 0U, K_NO_WAIT);
|
||||
if (!buf) {
|
||||
BT_ERR("%s, Unable to allocate buffer", __func__);
|
||||
return -ENOBUFS;
|
||||
}
|
||||
|
||||
/* Set advertising data and scan response data */
|
||||
memset(buf->data, 0, buf->size);
|
||||
if (data) {
|
||||
net_buf_add_u8(buf, data->adv_data_len);
|
||||
if (data->adv_data_len) {
|
||||
net_buf_add_mem(buf, data->adv_data, data->adv_data_len);
|
||||
}
|
||||
net_buf_add_u8(buf, data->scan_rsp_data_len);
|
||||
if (data->scan_rsp_data_len) {
|
||||
net_buf_add_mem(buf, data->scan_rsp_data, data->scan_rsp_data_len);
|
||||
}
|
||||
}
|
||||
|
||||
*index = net_buf_id(buf);
|
||||
tx = &ble_adv_tx[*index];
|
||||
tx->buf = buf;
|
||||
memcpy(&tx->param, param, sizeof(tx->param));
|
||||
|
||||
front = (tx->param.priority == BLE_MESH_BLE_ADV_PRIO_HIGH) ? true : false;
|
||||
bt_mesh_ble_adv_send(buf, &ble_adv_send_cb, tx, front);
|
||||
if (param->count) {
|
||||
if (k_delayed_work_init(&tx->resend, ble_adv_resend)) {
|
||||
/* If failed to create a timer, the BLE adv packet will be
|
||||
* sent only once. Just give a warning here, and since the
|
||||
* BLE adv packet can be sent, return 0 here.
|
||||
*/
|
||||
BT_WARN("Send BLE adv packet only once");
|
||||
tx->param.count = 0;
|
||||
net_buf_unref(buf);
|
||||
return 0;
|
||||
}
|
||||
bt_mesh_atomic_set_bit(tx->flags, TIMER_INIT);
|
||||
} else {
|
||||
/* Send the BLE advertising packet only once */
|
||||
net_buf_unref(buf);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bt_mesh_stop_ble_advertising(u8_t index)
|
||||
{
|
||||
struct ble_adv_tx *tx = NULL;
|
||||
bool unref = true;
|
||||
|
||||
if (index >= ARRAY_SIZE(ble_adv_tx)) {
|
||||
BT_ERR("%s, Invalid index %d", __func__, index);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
tx = &ble_adv_tx[index];
|
||||
|
||||
if (tx->buf == NULL) {
|
||||
BT_WARN("%s, Already stopped, index %d", __func__, index);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* busy 1, ref 1; busy 1, ref 2;
|
||||
* busy 0, ref 0; busy 0, ref 1;
|
||||
*/
|
||||
if (BLE_MESH_ADV(tx->buf)->busy == 1U &&
|
||||
tx->buf->ref == 1U) {
|
||||
unref = false;
|
||||
}
|
||||
ble_adv_tx_reset(tx, unref);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void bt_mesh_ble_adv_deinit(void)
|
||||
{
|
||||
for (int i = 0; i < ARRAY_SIZE(ble_adv_tx); i++) {
|
||||
struct ble_adv_tx *tx = &ble_adv_tx[i];
|
||||
ble_adv_tx_reset(tx, false);
|
||||
}
|
||||
bt_mesh_unref_buf_from_pool(&ble_adv_buf_pool);
|
||||
memset(ble_adv_pool, 0, sizeof(ble_adv_pool));
|
||||
}
|
||||
#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */
|
||||
|
||||
@@ -13,6 +13,10 @@
|
||||
#include "mesh_access.h"
|
||||
#include "mesh_bearer_adapt.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Maximum advertising data payload for a single data type */
|
||||
#define BLE_MESH_ADV_DATA_SIZE 29
|
||||
|
||||
@@ -34,6 +38,7 @@ enum bt_mesh_adv_type {
|
||||
BLE_MESH_ADV_DATA,
|
||||
BLE_MESH_ADV_BEACON,
|
||||
BLE_MESH_ADV_URI,
|
||||
BLE_MESH_ADV_BLE,
|
||||
};
|
||||
|
||||
typedef void (*bt_mesh_adv_func_t)(struct net_buf *buf, u16_t duration,
|
||||
@@ -43,14 +48,9 @@ struct bt_mesh_adv {
|
||||
const struct bt_mesh_send_cb *cb;
|
||||
void *cb_data;
|
||||
|
||||
u8_t type: 2,
|
||||
busy: 1;
|
||||
u8_t type:3,
|
||||
busy:1;
|
||||
u8_t xmit;
|
||||
|
||||
/* For transport layer segment sending */
|
||||
struct {
|
||||
u8_t attempts;
|
||||
} seg;
|
||||
};
|
||||
|
||||
typedef struct bt_mesh_adv *(*bt_mesh_adv_alloc_t)(int id);
|
||||
@@ -97,4 +97,17 @@ int bt_mesh_scan_enable(void);
|
||||
|
||||
int bt_mesh_scan_disable(void);
|
||||
|
||||
int bt_mesh_scan_with_wl_enable(void);
|
||||
|
||||
#if CONFIG_BLE_MESH_SUPPORT_BLE_ADV
|
||||
int bt_mesh_start_ble_advertising(const struct bt_mesh_ble_adv_param *param,
|
||||
const struct bt_mesh_ble_adv_data *data, u8_t *index);
|
||||
|
||||
int bt_mesh_stop_ble_advertising(u8_t index);
|
||||
#endif /* CONFIG_BLE_MESH_SUPPORT_BLE_ADV */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _ADV_H_ */
|
||||
|
||||
@@ -102,10 +102,10 @@ void bt_mesh_beacon_create(struct bt_mesh_subnet *sub,
|
||||
|
||||
net_buf_simple_add_mem(buf, sub->auth, 8);
|
||||
|
||||
BT_INFO("net_idx 0x%04x flags 0x%02x NetID %s", sub->net_idx,
|
||||
flags, bt_hex(keys->net_id, 8));
|
||||
BT_INFO("IV Index 0x%08x Auth %s", bt_mesh.iv_index,
|
||||
bt_hex(sub->auth, 8));
|
||||
BT_INFO("net_idx 0x%03x iv_index 0x%08x flags 0x%02x",
|
||||
sub->net_idx, bt_mesh.iv_index, flags);
|
||||
BT_DBG("NetID %s Auth %s", bt_hex(keys->net_id, 8),
|
||||
bt_hex(sub->auth, 8));
|
||||
}
|
||||
|
||||
/* If the interval has passed or is within 5 seconds from now send a beacon */
|
||||
@@ -269,7 +269,7 @@ static bool ready_to_send(void)
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BLE_MESH_PROVISIONER) && bt_mesh_is_provisioner_en()) {
|
||||
if (bt_mesh_provisioner_get_all_node_count()) {
|
||||
if (bt_mesh_provisioner_get_node_count()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -357,8 +357,8 @@ static void secure_beacon_recv(struct net_buf_simple *buf)
|
||||
goto update_stats;
|
||||
}
|
||||
|
||||
BT_INFO("net_idx 0x%04x iv_index 0x%08x, current iv_index 0x%08x",
|
||||
sub->net_idx, iv_index, bt_mesh.iv_index);
|
||||
BT_INFO("net_idx 0x%03x iv_index 0x%08x current iv_index 0x%08x",
|
||||
sub->net_idx, iv_index, bt_mesh.iv_index);
|
||||
|
||||
if (bt_mesh_atomic_test_bit(bt_mesh.flags, BLE_MESH_IVU_INITIATOR) &&
|
||||
(bt_mesh_atomic_test_bit(bt_mesh.flags, BLE_MESH_IVU_IN_PROGRESS) ==
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user