forked from espressif/esp-idf
Compare commits
385 Commits
v4.3-beta2
...
v4.3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c9646ff0be | ||
|
|
88c2b69c68 | ||
|
|
94a54d574b | ||
|
|
a560a506f2 | ||
|
|
1967e53f4a | ||
|
|
98c20ce417 | ||
|
|
9e2ce84a9a | ||
|
|
4de9ba152a | ||
|
|
415418cf0e | ||
|
|
a573cfe58a | ||
|
|
7d1fe0b553 | ||
|
|
f2f6acd6a6 | ||
|
|
e66fec955e | ||
|
|
a9a8fd03b6 | ||
|
|
8efb2bb1ed | ||
|
|
c270a9f0b9 | ||
|
|
6be10fab09 | ||
|
|
aa33c43644 | ||
|
|
2b19bd0c2f | ||
|
|
de0063164d | ||
|
|
acb05c21d9 | ||
|
|
93aee41c29 | ||
|
|
798aab5097 | ||
|
|
4db80bcc78 | ||
|
|
e97ddd80b7 | ||
|
|
2647288d32 | ||
|
|
a75a988c98 | ||
|
|
f00db86668 | ||
|
|
c7a10f9293 | ||
|
|
7095159a4c | ||
|
|
2644f793bd | ||
|
|
848f931e06 | ||
|
|
d5e2a482c3 | ||
|
|
410a0a5f5a | ||
|
|
7478d96228 | ||
|
|
644e653293 | ||
|
|
53956cf8ad | ||
|
|
effee74b2f | ||
|
|
08c5b89096 | ||
|
|
e6f96717ff | ||
|
|
db49804f65 | ||
|
|
ed76cc4dd4 | ||
|
|
d51ed40487 | ||
|
|
31b142cf93 | ||
|
|
d95e2c63ca | ||
|
|
cdec9f3659 | ||
|
|
02e742271d | ||
|
|
5ec69efafa | ||
|
|
42657a7464 | ||
|
|
f16ec53183 | ||
|
|
3299a19c2f | ||
|
|
a3ae9ae482 | ||
|
|
a6b169f91e | ||
|
|
deeb517b72 | ||
|
|
874b470379 | ||
|
|
38aa99d63d | ||
|
|
a37c20b417 | ||
|
|
fd5d6db71e | ||
|
|
1957025f4a | ||
|
|
6d2bdfc5f5 | ||
|
|
d651e4e073 | ||
|
|
5fc3c0ca91 | ||
|
|
2e64d234c4 | ||
|
|
229fab87a5 | ||
|
|
e45be4dd4a | ||
|
|
f6d96f33bb | ||
|
|
228f875ada | ||
|
|
997c07c2ee | ||
|
|
dca229df07 | ||
|
|
788312a009 | ||
|
|
6c9005e11b | ||
|
|
d30ec8c94e | ||
|
|
658a0acdbe | ||
|
|
2ecc8fad50 | ||
|
|
467c7af33e | ||
|
|
6121046090 | ||
|
|
4c113a0c0c | ||
|
|
ad759ee5a7 | ||
|
|
24af403dac | ||
|
|
469bb082d7 | ||
|
|
80e381e511 | ||
|
|
847273d0fb | ||
|
|
6d32eec165 | ||
|
|
6dc067dda7 | ||
|
|
0ddf00c6e1 | ||
|
|
8c6705ded5 | ||
|
|
a480a00237 | ||
|
|
2f603a56a7 | ||
|
|
2bffeb7265 | ||
|
|
9c872b1851 | ||
|
|
b2c18de9b3 | ||
|
|
f684bd10f5 | ||
|
|
9da031e0c3 | ||
|
|
64de7ee38c | ||
|
|
52d9d466fb | ||
|
|
a4a7e7b3e9 | ||
|
|
fbc6f27e81 | ||
|
|
31c396c127 | ||
|
|
a87f5c6c02 | ||
|
|
20993109e8 | ||
|
|
6c38cc736a | ||
|
|
193b60afcf | ||
|
|
e4d84804c1 | ||
|
|
e4ebaca693 | ||
|
|
3f358236f0 | ||
|
|
ba1ce2ebd0 | ||
|
|
aad1f7abde | ||
|
|
29ad86ed5b | ||
|
|
dede31cd83 | ||
|
|
d592a9863b | ||
|
|
f89f5b7f75 | ||
|
|
07291fdd27 | ||
|
|
00801c8044 | ||
|
|
b8e31efcac | ||
|
|
819ac7f847 | ||
|
|
46ab19818a | ||
|
|
b9038d045e | ||
|
|
ae72870d43 | ||
|
|
4d1aaed682 | ||
|
|
6059ef26fb | ||
|
|
5fa34f6a30 | ||
|
|
56a3845986 | ||
|
|
2c153af57a | ||
|
|
18d7d9497a | ||
|
|
38db3d9507 | ||
|
|
42ae0166d7 | ||
|
|
eff7fd9052 | ||
|
|
275743ab1c | ||
|
|
8a39b5237d | ||
|
|
5e9aa539ea | ||
|
|
6f3b1a0554 | ||
|
|
d0e0f80bd0 | ||
|
|
ecb01b28c4 | ||
|
|
1b82e9604c | ||
|
|
26139daaf5 | ||
|
|
f9831301ce | ||
|
|
cfb84d3381 | ||
|
|
952e47d45d | ||
|
|
ed6a0c324c | ||
|
|
c6ca4e3e88 | ||
|
|
999f648a35 | ||
|
|
9bf4d44235 | ||
|
|
50e3f9f66c | ||
|
|
613201c24d | ||
|
|
1166bc5680 | ||
|
|
02170d815e | ||
|
|
6e06d323b1 | ||
|
|
d7a793f406 | ||
|
|
85e0728700 | ||
|
|
3fb1165e4e | ||
|
|
34140d2a00 | ||
|
|
face9518b2 | ||
|
|
5f1887b3ca | ||
|
|
d8c4ab482b | ||
|
|
94ed8f8606 | ||
|
|
cdcb85fd70 | ||
|
|
a67793e9fc | ||
|
|
182c2eda48 | ||
|
|
1d218485ec | ||
|
|
257047c073 | ||
|
|
83358061df | ||
|
|
47e4386953 | ||
|
|
60bf9d30b2 | ||
|
|
e8282fb5c5 | ||
|
|
5a5327e77e | ||
|
|
5580d578bd | ||
|
|
759e4340a9 | ||
|
|
949a3cd61a | ||
|
|
ac9bd8bcc4 | ||
|
|
e45ce5c058 | ||
|
|
44b81cb280 | ||
|
|
b24671e935 | ||
|
|
d41781099a | ||
|
|
6403a229eb | ||
|
|
98ad8cc2e3 | ||
|
|
afc2f9b5d3 | ||
|
|
f2e222a8f8 | ||
|
|
bdce35c3d7 | ||
|
|
7d7ad29d5a | ||
|
|
905293a6c9 | ||
|
|
6587ff6110 | ||
|
|
991d0b8c31 | ||
|
|
2290d0385e | ||
|
|
4f04f48a70 | ||
|
|
2a7df3bcd8 | ||
|
|
67b09d3db5 | ||
|
|
5717f8f2fb | ||
|
|
fe2f3bfe1e | ||
|
|
e2af75b5e4 | ||
|
|
a17b57b062 | ||
|
|
df0c1a1285 | ||
|
|
662b6bb48a | ||
|
|
3d0a386c10 | ||
|
|
9ed4e06dd2 | ||
|
|
ededfb47b9 | ||
|
|
6f47a4e0a6 | ||
|
|
2335e5026f | ||
|
|
2bd0e9371a | ||
|
|
fead8b8a06 | ||
|
|
e9cf9e2978 | ||
|
|
6463dd9630 | ||
|
|
c9f1b55287 | ||
|
|
e16ec9a574 | ||
|
|
a7994b1a42 | ||
|
|
c725aa3ec1 | ||
|
|
3687ae989b | ||
|
|
16cf160d57 | ||
|
|
58160d46c6 | ||
|
|
776906dc84 | ||
|
|
891a17ea62 | ||
|
|
bd03a0e66a | ||
|
|
eab4e6fedd | ||
|
|
03d504dbb2 | ||
|
|
8e8737c128 | ||
|
|
3a5d9d9431 | ||
|
|
693aaef039 | ||
|
|
7703fcbd8d | ||
|
|
9a7deae742 | ||
|
|
84dc42c4b0 | ||
|
|
d7e680828a | ||
|
|
da47503c14 | ||
|
|
e490fdafbe | ||
|
|
94e3141a32 | ||
|
|
fd34406960 | ||
|
|
4544b709e5 | ||
|
|
a95c1c302d | ||
|
|
1ef91c72e2 | ||
|
|
90696dad89 | ||
|
|
e310fb1393 | ||
|
|
71de11e89d | ||
|
|
bda9e1fda7 | ||
|
|
97df333a3b | ||
|
|
6dfff2fdbd | ||
|
|
2ed3e8b344 | ||
|
|
58a7d9f239 | ||
|
|
e4dd9053c2 | ||
|
|
ff5e0d0d38 | ||
|
|
03b0540bc6 | ||
|
|
17e30c9e89 | ||
|
|
00cfcde385 | ||
|
|
0839fd08dd | ||
|
|
626964beae | ||
|
|
220f3d2198 | ||
|
|
904933745b | ||
|
|
ea4a8d5e4f | ||
|
|
10cce6b74a | ||
|
|
e36e433519 | ||
|
|
76ff1724b3 | ||
|
|
9f1ae278e0 | ||
|
|
54908d3a42 | ||
|
|
19b90e8ba9 | ||
|
|
a5e27d73a5 | ||
|
|
1e6a6ffa0d | ||
|
|
dbf2a64adb | ||
|
|
11970e65a1 | ||
|
|
3b8c7bdf0b | ||
|
|
670b057b04 | ||
|
|
ae3b4819da | ||
|
|
b0684e8b3c | ||
|
|
322cba0bf0 | ||
|
|
f5c6595cb4 | ||
|
|
02de1a8071 | ||
|
|
e9e2b68587 | ||
|
|
73d40cb813 | ||
|
|
bf6ddf2557 | ||
|
|
d761226f36 | ||
|
|
5036ec363b | ||
|
|
c724236623 | ||
|
|
f7034e7767 | ||
|
|
7e75d7f748 | ||
|
|
e5437afa7f | ||
|
|
319eecc793 | ||
|
|
d17923151b | ||
|
|
0a0b3bb23f | ||
|
|
2a5cf2c3e0 | ||
|
|
ae15a0cab8 | ||
|
|
0c7f286a87 | ||
|
|
3e26049a05 | ||
|
|
dece3abd9c | ||
|
|
1af5bc2f7d | ||
|
|
278cfc2047 | ||
|
|
1790aa6bc6 | ||
|
|
b75a5fd03a | ||
|
|
cbf2858450 | ||
|
|
868c96c59f | ||
|
|
60d5dcb000 | ||
|
|
62787fc277 | ||
|
|
9e97133481 | ||
|
|
c9087c205b | ||
|
|
736b87db6d | ||
|
|
c2eaa3d844 | ||
|
|
2a715c811b | ||
|
|
17aa9c5ec4 | ||
|
|
c93211db62 | ||
|
|
be56456add | ||
|
|
413bbe4de4 | ||
|
|
4906779d50 | ||
|
|
7d5d57ec03 | ||
|
|
67a1858bb1 | ||
|
|
fb9de62f74 | ||
|
|
f48346f22f | ||
|
|
79ce133ed7 | ||
|
|
a59a5cb2cc | ||
|
|
2d26c24e3a | ||
|
|
2792c333bc | ||
|
|
7c5e920c37 | ||
|
|
d4ac30a978 | ||
|
|
2596c7e2cc | ||
|
|
e6b7c933d5 | ||
|
|
8fe99aff96 | ||
|
|
4866027391 | ||
|
|
a6ed4611a2 | ||
|
|
d457641f90 | ||
|
|
1509264f2e | ||
|
|
271b84f5b6 | ||
|
|
f1be501271 | ||
|
|
ea20966c29 | ||
|
|
f25c996b06 | ||
|
|
745bb2123f | ||
|
|
143bb1edf4 | ||
|
|
f1737a630d | ||
|
|
83087f15fa | ||
|
|
a9d1d44d4d | ||
|
|
72b27f1782 | ||
|
|
8e482c9423 | ||
|
|
1fb45977fa | ||
|
|
257728feab | ||
|
|
26d362040e | ||
|
|
f6a794cf51 | ||
|
|
974db3016b | ||
|
|
9c4c377f2d | ||
|
|
e6b8bc6ecb | ||
|
|
718f296587 | ||
|
|
6c74618bff | ||
|
|
974f345316 | ||
|
|
f2ca74b139 | ||
|
|
ac8ea9e9e5 | ||
|
|
48890daab1 | ||
|
|
f1aabb2894 | ||
|
|
cc8ef3660a | ||
|
|
67402f035f | ||
|
|
7dd5568cb7 | ||
|
|
f00d7ee9d0 | ||
|
|
dba5597edf | ||
|
|
5019a6571e | ||
|
|
4f8d784753 | ||
|
|
a697377871 | ||
|
|
6ceee165b5 | ||
|
|
4a20f68f5c | ||
|
|
8ec0ffe751 | ||
|
|
5d0ce8b52f | ||
|
|
2313683b58 | ||
|
|
c41822dc7c | ||
|
|
21909d7823 | ||
|
|
651a939643 | ||
|
|
3bf9d389ef | ||
|
|
6238c49479 | ||
|
|
fe1126cccb | ||
|
|
4725249385 | ||
|
|
6cfef8ce93 | ||
|
|
a643ea9432 | ||
|
|
f54dfe2912 | ||
|
|
c2ba180de3 | ||
|
|
d6f76f8a5f | ||
|
|
1d778c941c | ||
|
|
87b613fd2f | ||
|
|
f5f7d21c83 | ||
|
|
502a819757 | ||
|
|
802a01c0b7 | ||
|
|
a479ee30c9 | ||
|
|
46e85ed021 | ||
|
|
0862fe815b | ||
|
|
918875424e | ||
|
|
5490c0a243 | ||
|
|
a71d9cc466 | ||
|
|
c75a8b11bb | ||
|
|
9c884b3ba9 | ||
|
|
9a2d251912 | ||
|
|
d92ac450a2 | ||
|
|
113bf479a4 | ||
|
|
fd93c475b6 | ||
|
|
27c72a4105 | ||
|
|
5c8b1d6ab8 | ||
|
|
f3be9976b9 | ||
|
|
6638b81f8e |
17
.github/workflows/release_zips.yml
vendored
Normal file
17
.github/workflows/release_zips.yml
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
name: Create zip file with recursive source clone for release
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- v*
|
||||
|
||||
jobs:
|
||||
release_zips:
|
||||
name: Create release zip file
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: Create a recursive clone source zip
|
||||
uses: espressif/github-actions/release_zips@master
|
||||
env:
|
||||
RELEASE_PROJECT_NAME: ESP-IDF
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
8
.gitmodules
vendored
8
.gitmodules
vendored
@@ -7,8 +7,8 @@
|
||||
path = components/esptool_py/esptool
|
||||
url = ../../espressif/esptool.git
|
||||
|
||||
[submodule "components/bt/controller/lib"]
|
||||
path = components/bt/controller/lib
|
||||
[submodule "components/bt/controller/lib_esp32"]
|
||||
path = components/bt/controller/lib_esp32
|
||||
url = ../../espressif/esp32-bt-lib.git
|
||||
|
||||
[submodule "components/bootloader/subproject/components/micro-ecc/micro-ecc"]
|
||||
@@ -90,3 +90,7 @@
|
||||
[submodule "components/cmock/CMock"]
|
||||
path = components/cmock/CMock
|
||||
url = ../../ThrowTheSwitch/CMock.git
|
||||
|
||||
[submodule "components/bt/controller/lib_esp32c3_family"]
|
||||
path = components/bt/controller/lib_esp32c3_family
|
||||
url = ../../espressif/esp32c3-bt-lib.git
|
||||
|
||||
@@ -9,7 +9,7 @@ entries:
|
||||
SEGGER_SYSVIEW_Config_FreeRTOS (noflash)
|
||||
SEGGER_SYSVIEW_FreeRTOS (noflash)
|
||||
|
||||
[mapping:driver]
|
||||
[mapping:app_trace_driver]
|
||||
archive: libdriver.a
|
||||
entries:
|
||||
if SYSVIEW_TS_SOURCE_TIMER_00 = y || SYSVIEW_TS_SOURCE_TIMER_01 = y
|
||||
|
||||
@@ -41,16 +41,6 @@
|
||||
#include "esp_efuse.h"
|
||||
#include "esp_attr.h"
|
||||
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
#include "esp32/rom/crc.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
#include "esp32s2/rom/crc.h"
|
||||
#include "esp32s2/rom/secure_boot.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||
#include "esp32c3/rom/crc.h"
|
||||
#include "esp32c3/rom/secure_boot.h"
|
||||
#endif
|
||||
|
||||
#define SUB_TYPE_ID(i) (i & 0x0F)
|
||||
|
||||
/* Partial_data is word aligned so no reallocation is necessary for encrypted flash write */
|
||||
|
||||
@@ -424,7 +424,7 @@ menu "Security features"
|
||||
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)
|
||||
Supported in ESP32-ECO3 (ESP32 Chip Revision 3 onwards), ESP32-S2, ESP32-C3, ESP32-S3.
|
||||
|
||||
config SECURE_SIGNED_APPS_ECDSA_SCHEME
|
||||
bool "ECDSA"
|
||||
@@ -436,7 +436,7 @@ menu "Security features"
|
||||
|
||||
config SECURE_SIGNED_APPS_RSA_SCHEME
|
||||
bool "RSA"
|
||||
depends on SECURE_BOOT_SUPPORTS_RSA && SECURE_BOOT_V2_ENABLED
|
||||
depends on SECURE_BOOT_SUPPORTS_RSA && (SECURE_SIGNED_APPS_NO_SECURE_BOOT || 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.
|
||||
@@ -445,7 +445,7 @@ menu "Security features"
|
||||
config SECURE_SIGNED_ON_BOOT_NO_SECURE_BOOT
|
||||
bool "Bootloader verifies app signatures"
|
||||
default n
|
||||
depends on SECURE_SIGNED_APPS_NO_SECURE_BOOT
|
||||
depends on SECURE_SIGNED_APPS_NO_SECURE_BOOT && SECURE_SIGNED_APPS_ECDSA_SCHEME
|
||||
help
|
||||
If this option is set, the bootloader will be compiled with code to verify that an app is signed before
|
||||
booting it.
|
||||
@@ -471,7 +471,7 @@ menu "Security features"
|
||||
config SECURE_BOOT
|
||||
bool "Enable hardware Secure Boot in bootloader (READ DOCS FIRST)"
|
||||
default n
|
||||
depends on !IDF_TARGET_ESP32C3 # IDF-2647
|
||||
depends on IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 || ESP32C3_REV_MIN_3
|
||||
help
|
||||
Build a bootloader which enables Secure Boot on first boot.
|
||||
|
||||
@@ -488,7 +488,7 @@ menu "Security features"
|
||||
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)
|
||||
Supported in ESP32-ECO3 (ESP32 Chip Revision 3 onwards), ESP32-S2, ESP32-C3 ECO3.
|
||||
Secure Boot V1 is the AES based secure boot scheme.
|
||||
Supported in ESP32 and ESP32-ECO3.
|
||||
|
||||
@@ -502,8 +502,6 @@ menu "Security features"
|
||||
config SECURE_BOOT_V2_ENABLED
|
||||
bool "Enable Secure Boot version 2"
|
||||
depends on SECURE_BOOT_SUPPORTS_RSA
|
||||
select SECURE_ENABLE_SECURE_ROM_DL_MODE if !IDF_TARGET_ESP32 && !SECURE_INSECURE_ALLOW_DL_MODE && !SECURE_DISABLE_ROM_DL_MODE # NOERROR
|
||||
select SECURE_DISABLE_ROM_DL_MODE if ESP32_REV_MIN_3 && !SECURE_INSECURE_ALLOW_DL_MODE
|
||||
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.
|
||||
@@ -672,8 +670,6 @@ menu "Security features"
|
||||
|
||||
config SECURE_FLASH_ENCRYPTION_MODE_RELEASE
|
||||
bool "Release"
|
||||
select SECURE_ENABLE_SECURE_ROM_DL_MODE if SECURE_TARGET_HAS_SECURE_ROM_DL_MODE && !SECURE_DISABLE_ROM_DL_MODE # NOERROR
|
||||
|
||||
endchoice
|
||||
|
||||
menu "Potentially insecure options"
|
||||
@@ -738,19 +734,6 @@ menu "Security features"
|
||||
key digest, causing an immediate denial of service and possibly allowing an additional fault
|
||||
injection attack to bypass the signature protection.
|
||||
|
||||
config SECURE_INSECURE_ALLOW_DL_MODE
|
||||
bool "Don't automatically restrict UART download mode"
|
||||
depends on SECURE_BOOT_INSECURE && SECURE_BOOT_V2_ENABLED
|
||||
default N
|
||||
help
|
||||
By default, enabling either flash encryption in release mode or secure boot will automatically
|
||||
disable UART download mode on ESP32 ECO3, or enable secure download mode on newer chips.
|
||||
This is recommended to reduce the attack surface of the chip.
|
||||
|
||||
To allow the full UART download mode to stay enabled, enable this option and ensure
|
||||
the options SECURE_DISABLE_ROM_DL_MODE and SECURE_ENABLE_SECURE_ROM_DL_MODE are disabled as applicable.
|
||||
This is not recommended.
|
||||
|
||||
config SECURE_FLASH_UART_BOOTLOADER_ALLOW_ENC
|
||||
bool "Leave UART bootloader encryption enabled"
|
||||
depends on SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT
|
||||
@@ -798,47 +781,58 @@ menu "Security features"
|
||||
|
||||
endmenu # Potentially Insecure
|
||||
|
||||
config SECURE_DISABLE_ROM_DL_MODE
|
||||
bool "Permanently disable ROM Download Mode"
|
||||
choice SECURE_UART_ROM_DL_MODE
|
||||
bool "UART ROM download mode"
|
||||
default SECURE_ENABLE_SECURE_ROM_DL_MODE if SECURE_TARGET_HAS_SECURE_ROM_DL_MODE && !SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT # NOERROR
|
||||
default SECURE_INSECURE_ALLOW_DL_MODE
|
||||
depends on SECURE_BOOT_V2_ENABLED || SECURE_FLASH_ENC_ENABLED
|
||||
depends on !IDF_TARGET_ESP32 || ESP32_REV_MIN_3
|
||||
default n
|
||||
help
|
||||
If set, during startup the app will burn an eFuse bit to permanently disable the UART ROM
|
||||
Download Mode. This prevents any future use of esptool.py, espefuse.py and similar tools.
|
||||
|
||||
Once disabled, if the SoC is booted with strapping pins set for ROM Download Mode
|
||||
then an error is printed instead.
|
||||
config SECURE_DISABLE_ROM_DL_MODE
|
||||
bool "UART ROM download mode (Permanently disabled (recommended))"
|
||||
help
|
||||
If set, during startup the app will burn an eFuse bit to permanently disable the UART ROM
|
||||
Download Mode. This prevents any future use of esptool.py, espefuse.py and similar tools.
|
||||
|
||||
It is recommended to enable this option in any production application where Flash
|
||||
Encryption and/or Secure Boot is enabled and access to Download Mode is not required.
|
||||
Once disabled, if the SoC is booted with strapping pins set for ROM Download Mode
|
||||
then an error is printed instead.
|
||||
|
||||
It is also possible to permanently disable Download Mode by calling
|
||||
esp_efuse_disable_rom_download_mode() at runtime.
|
||||
It is recommended to enable this option in any production application where Flash
|
||||
Encryption and/or Secure Boot is enabled and access to Download Mode is not required.
|
||||
|
||||
config SECURE_ENABLE_SECURE_ROM_DL_MODE
|
||||
bool "Permanently switch to ROM UART Secure Download mode"
|
||||
depends on SECURE_TARGET_HAS_SECURE_ROM_DL_MODE && !SECURE_DISABLE_ROM_DL_MODE
|
||||
select ESPTOOLPY_NO_STUB
|
||||
help
|
||||
If set, during startup the app will burn an eFuse bit to permanently switch the UART ROM
|
||||
Download Mode into a separate Secure Download mode. This option can only work if
|
||||
Download Mode is not already disabled by eFuse.
|
||||
It is also possible to permanently disable Download Mode by calling
|
||||
esp_efuse_disable_rom_download_mode() at runtime.
|
||||
|
||||
Secure Download mode limits the use of Download Mode functions to simple flash read,
|
||||
write and erase operations, plus a command to return a summary of currently enabled
|
||||
security features.
|
||||
config SECURE_ENABLE_SECURE_ROM_DL_MODE
|
||||
bool "UART ROM download mode (Permanently switch to Secure mode (recommended))"
|
||||
depends on SECURE_TARGET_HAS_SECURE_ROM_DL_MODE
|
||||
select ESPTOOLPY_NO_STUB
|
||||
help
|
||||
If set, during startup the app will burn an eFuse bit to permanently switch the UART ROM
|
||||
Download Mode into a separate Secure Download mode. This option can only work if
|
||||
Download Mode is not already disabled by eFuse.
|
||||
|
||||
Secure Download mode is not compatible with the esptool.py flasher stub feature,
|
||||
espefuse.py, read/writing memory or registers, encrypted download, or any other
|
||||
features that interact with unsupported Download Mode commands.
|
||||
Secure Download mode limits the use of Download Mode functions to simple flash read,
|
||||
write and erase operations, plus a command to return a summary of currently enabled
|
||||
security features.
|
||||
|
||||
Secure Download mode should be enabled in any application where Flash Encryption
|
||||
and/or Secure Boot is enabled. Disabling this option does not immediately cancel
|
||||
the benefits of the security features, but it increases the potential "attack
|
||||
surface" for an attacker to try and bypass them with a successful physical attack.
|
||||
Secure Download mode is not compatible with the esptool.py flasher stub feature,
|
||||
espefuse.py, read/writing memory or registers, encrypted download, or any other
|
||||
features that interact with unsupported Download Mode commands.
|
||||
|
||||
It is also possible to enable secure download mode at runtime by calling
|
||||
esp_efuse_enable_rom_secure_download_mode()
|
||||
Secure Download mode should be enabled in any application where Flash Encryption
|
||||
and/or Secure Boot is enabled. Disabling this option does not immediately cancel
|
||||
the benefits of the security features, but it increases the potential "attack
|
||||
surface" for an attacker to try and bypass them with a successful physical attack.
|
||||
|
||||
It is also possible to enable secure download mode at runtime by calling
|
||||
esp_efuse_enable_rom_secure_download_mode()
|
||||
|
||||
config SECURE_INSECURE_ALLOW_DL_MODE
|
||||
bool "UART ROM download mode (Enabled (not recommended))"
|
||||
help
|
||||
This is a potentially insecure option.
|
||||
Enabling this option will allow the full UART download mode to stay enabled.
|
||||
This option SHOULD NOT BE ENABLED for production use cases.
|
||||
endchoice
|
||||
endmenu # Security features
|
||||
|
||||
@@ -17,6 +17,8 @@ CONFIG_SECURE_BOOT_SIGNING_KEY ?=
|
||||
SECURE_BOOT_SIGNING_KEY=$(abspath $(call dequote,$(CONFIG_SECURE_BOOT_SIGNING_KEY)))
|
||||
export SECURE_BOOT_SIGNING_KEY # used by bootloader_support component
|
||||
|
||||
BOOTLOADER_SIGNED_BIN ?=
|
||||
|
||||
# Has a matching value in bootloader_support esp_flash_partitions.h
|
||||
BOOTLOADER_OFFSET := 0x1000
|
||||
|
||||
|
||||
@@ -28,10 +28,11 @@ set(COMPONENTS
|
||||
micro-ecc
|
||||
main
|
||||
efuse
|
||||
esp_system)
|
||||
esp_system
|
||||
newlib)
|
||||
set(BOOTLOADER_BUILD 1)
|
||||
include("${IDF_PATH}/tools/cmake/project.cmake")
|
||||
set(common_req log esp_rom esp_common esp_hw_support hal)
|
||||
set(common_req log esp_rom esp_common esp_hw_support hal newlib)
|
||||
if(LEGACY_INCLUDE_COMMON_HEADERS)
|
||||
list(APPEND common_req soc hal)
|
||||
endif()
|
||||
@@ -53,6 +54,9 @@ string(REPLACE ";" " " esptoolpy_write_flash
|
||||
string(REPLACE ";" " " espsecurepy "${ESPSECUREPY}")
|
||||
string(REPLACE ";" " " espefusepy "${ESPEFUSEPY}")
|
||||
|
||||
# Suppress warning: "Manually-specified variables were not used by the project: SECURE_BOOT_SIGNING_KEY"
|
||||
set(ignore_signing_key "${SECURE_BOOT_SIGNING_KEY}")
|
||||
|
||||
if(CONFIG_SECURE_BOOTLOADER_REFLASHABLE)
|
||||
if(CONFIG_SECURE_BOOTLOADER_KEY_ENCODING_192BIT)
|
||||
set(key_digest_len 192)
|
||||
|
||||
@@ -8,7 +8,7 @@ endif
|
||||
|
||||
PROJECT_NAME := bootloader
|
||||
|
||||
COMPONENTS := esp_hw_support esptool_py bootloader_support log spi_flash micro-ecc soc main efuse esp_rom hal
|
||||
COMPONENTS := esp_hw_support esptool_py bootloader_support log spi_flash micro-ecc soc main efuse esp_rom hal xtensa
|
||||
|
||||
# Clear C and CXX from top level project
|
||||
CFLAGS =
|
||||
|
||||
@@ -52,7 +52,7 @@ SECTIONS
|
||||
*libbootloader_support.a:flash_encrypt.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:flash_partitions.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:secure_boot.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:secure_boot_signatures.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:secure_boot_signatures_bootloader.*(.literal .text .literal.* .text.*)
|
||||
*libmicro-ecc.a:*.*(.literal .text .literal.* .text.*)
|
||||
*libspi_flash.a:*.*(.literal .text .literal.* .text.*)
|
||||
*libhal.a:wdt_hal_iram.*(.literal .text .literal.* .text.*)
|
||||
@@ -167,6 +167,14 @@ SECTIONS
|
||||
*(.fini.literal)
|
||||
*(.fini)
|
||||
*(.gnu.version)
|
||||
|
||||
/** CPU will try to prefetch up to 16 bytes of
|
||||
* of instructions. This means that any configuration (e.g. MMU, PMS) must allow
|
||||
* safe access to up to 16 bytes after the last real instruction, add
|
||||
* dummy bytes to ensure this
|
||||
*/
|
||||
. += 16;
|
||||
|
||||
_text_end = ABSOLUTE(.);
|
||||
_etext = .;
|
||||
} > iram_seg
|
||||
|
||||
@@ -40,7 +40,7 @@ SECTIONS
|
||||
*libbootloader_support.a:flash_encrypt.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:flash_partitions.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:secure_boot.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:secure_boot_signatures.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:secure_boot_signatures_bootloader.*(.literal .text .literal.* .text.*)
|
||||
*libmicro-ecc.a:*.*(.literal .text .literal.* .text.*)
|
||||
*libspi_flash.a:*.*(.literal .text .literal.* .text.*)
|
||||
*libhal.a:wdt_hal_iram.*(.literal .text .literal.* .text.*)
|
||||
@@ -156,6 +156,14 @@ SECTIONS
|
||||
*(.fini.literal)
|
||||
*(.fini)
|
||||
*(.gnu.version)
|
||||
|
||||
/** CPU will try to prefetch up to 16 bytes of
|
||||
* of instructions. This means that any configuration (e.g. MMU, PMS) must allow
|
||||
* safe access to up to 16 bytes after the last real instruction, add
|
||||
* dummy bytes to ensure this
|
||||
*/
|
||||
. += 16;
|
||||
|
||||
_text_end = ABSOLUTE(.);
|
||||
_etext = .;
|
||||
} > iram_seg
|
||||
|
||||
@@ -39,7 +39,7 @@ SECTIONS
|
||||
*libbootloader_support.a:flash_encrypt.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:flash_partitions.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:secure_boot.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:secure_boot_signatures.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:secure_boot_signatures_bootloader.*(.literal .text .literal.* .text.*)
|
||||
*libmicro-ecc.a:*.*(.literal .text .literal.* .text.*)
|
||||
*libspi_flash.a:*.*(.literal .text .literal.* .text.*)
|
||||
*libhal.a:wdt_hal_iram.*(.literal .text .literal.* .text.*)
|
||||
@@ -155,6 +155,14 @@ SECTIONS
|
||||
*(.fini.literal)
|
||||
*(.fini)
|
||||
*(.gnu.version)
|
||||
|
||||
/** CPU will try to prefetch up to 16 bytes of
|
||||
* of instructions. This means that any configuration (e.g. MMU, PMS) must allow
|
||||
* safe access to up to 16 bytes after the last real instruction, add
|
||||
* dummy bytes to ensure this
|
||||
*/
|
||||
. += 16;
|
||||
|
||||
_text_end = ABSOLUTE(.);
|
||||
_etext = .;
|
||||
} > iram_seg
|
||||
|
||||
@@ -40,7 +40,7 @@ SECTIONS
|
||||
*libbootloader_support.a:flash_encrypt.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:flash_partitions.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:secure_boot.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:secure_boot_signatures.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:secure_boot_signatures_bootloader.*(.literal .text .literal.* .text.*)
|
||||
*libmicro-ecc.a:*.*(.literal .text .literal.* .text.*)
|
||||
*libspi_flash.a:*.*(.literal .text .literal.* .text.*)
|
||||
*libhal.a:wdt_hal_iram.*(.literal .text .literal.* .text.*)
|
||||
@@ -156,6 +156,14 @@ SECTIONS
|
||||
*(.fini.literal)
|
||||
*(.fini)
|
||||
*(.gnu.version)
|
||||
|
||||
/** CPU will try to prefetch up to 16 bytes of
|
||||
* of instructions. This means that any configuration (e.g. MMU, PMS) must allow
|
||||
* safe access to up to 16 bytes after the last real instruction, add
|
||||
* dummy bytes to ensure this
|
||||
*/
|
||||
. += 16;
|
||||
|
||||
_text_end = ABSOLUTE(.);
|
||||
_etext = .;
|
||||
} > iram_seg
|
||||
|
||||
@@ -9,6 +9,7 @@ set(srcs
|
||||
"src/bootloader_utility.c"
|
||||
"src/esp_image_format.c"
|
||||
"src/flash_encrypt.c"
|
||||
"src/secure_boot.c"
|
||||
"src/flash_partitions.c"
|
||||
"src/flash_qio_mode.c"
|
||||
"src/bootloader_flash_config_${IDF_TARGET}.c"
|
||||
@@ -34,16 +35,28 @@ else()
|
||||
"src/idf/bootloader_sha.c")
|
||||
set(include_dirs "include")
|
||||
set(priv_include_dirs "include_bootloader")
|
||||
set(priv_requires spi_flash mbedtls efuse)
|
||||
set(priv_requires spi_flash mbedtls efuse app_update)
|
||||
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")
|
||||
if(BOOTLOADER_BUILD)
|
||||
if(CONFIG_SECURE_SIGNED_ON_BOOT)
|
||||
if(CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME)
|
||||
list(APPEND srcs "src/secure_boot_v1/secure_boot_signatures_bootloader.c")
|
||||
endif()
|
||||
|
||||
if(CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME)
|
||||
list(APPEND srcs "src/secure_boot_v2/secure_boot_signatures_bootloader.c")
|
||||
endif()
|
||||
endif()
|
||||
else()
|
||||
if(CONFIG_SECURE_SIGNED_ON_UPDATE)
|
||||
if(CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME)
|
||||
list(APPEND srcs "src/secure_boot_v1/secure_boot_signatures_app.c")
|
||||
endif()
|
||||
|
||||
if(CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME)
|
||||
list(APPEND srcs "src/secure_boot_v2/secure_boot_signatures_app.c")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
@@ -7,7 +7,9 @@ else
|
||||
COMPONENT_PRIV_INCLUDEDIRS := include_bootloader
|
||||
endif
|
||||
|
||||
COMPONENT_SRCDIRS := src
|
||||
COMPONENT_SRCDIRS := src \
|
||||
src/secure_boot_v2 \
|
||||
src/secure_boot_v1
|
||||
|
||||
ifndef IS_BOOTLOADER_BUILD
|
||||
COMPONENT_SRCDIRS += src/idf # idf sub-directory contains platform agnostic IDF versions
|
||||
@@ -33,12 +35,27 @@ COMPONENT_OBJEXCLUDE += src/bootloader_flash_config_esp32s2.o \
|
||||
src/bootloader_random_esp32s3.o \
|
||||
src/bootloader_random_esp32c3.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
|
||||
ifdef IS_BOOTLOADER_BUILD
|
||||
ifndef CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME
|
||||
COMPONENT_OBJEXCLUDE += src/secure_boot_v1/secure_boot_signatures_bootloader.o
|
||||
endif
|
||||
|
||||
ifndef CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME
|
||||
COMPONENT_OBJEXCLUDE += src/secure_boot_v2/secure_boot_signatures_bootloader.o
|
||||
endif
|
||||
COMPONENT_OBJEXCLUDE += src/secure_boot_v1/secure_boot_signatures_app.o \
|
||||
src/secure_boot_v2/secure_boot_signatures_app.o
|
||||
else
|
||||
ifndef CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME
|
||||
COMPONENT_OBJEXCLUDE += src/secure_boot_v1/secure_boot_signatures_app.o
|
||||
endif
|
||||
|
||||
ifndef CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME
|
||||
COMPONENT_OBJEXCLUDE += src/secure_boot_v2/secure_boot_signatures_app.o
|
||||
endif
|
||||
COMPONENT_OBJEXCLUDE += src/secure_boot_v1/secure_boot_signatures_bootloader.o \
|
||||
src/secure_boot_v2/secure_boot_signatures_bootloader.o
|
||||
endif # IS_BOOTLOADER_BUILD
|
||||
|
||||
ifndef CONFIG_SECURE_BOOT
|
||||
COMPONENT_OBJEXCLUDE += src/$(IDF_TARGET)/secure_boot.o
|
||||
|
||||
@@ -106,6 +106,20 @@ _Static_assert(sizeof(rtc_retain_mem_t) <= ESP_BOOTLOADER_RESERVE_RTC, "Reserved
|
||||
*/
|
||||
esp_err_t esp_image_verify(esp_image_load_mode_t mode, const esp_partition_pos_t *part, esp_image_metadata_t *data);
|
||||
|
||||
/**
|
||||
* @brief Get metadata of app
|
||||
*
|
||||
* If encryption is enabled, data will be transparently decrypted.
|
||||
*
|
||||
* @param part Partition to load the app from.
|
||||
* @param[out] metadata Pointer to the image metadata structure which is be filled in by this function.
|
||||
* Fields will all be initialised by this function.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK if filling of metadata was successful
|
||||
*/
|
||||
esp_err_t esp_image_get_metadata(const esp_partition_pos_t *part, esp_image_metadata_t *metadata);
|
||||
|
||||
/**
|
||||
* @brief Verify and load an app image (available only in space of bootloader).
|
||||
*
|
||||
|
||||
@@ -19,17 +19,22 @@
|
||||
#include "esp_image_format.h"
|
||||
#include "esp_rom_efuse.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_rom_crc.h"
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#include "esp32/rom/efuse.h"
|
||||
#include "esp32/rom/secure_boot.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
#include "esp32s2/rom/efuse.h"
|
||||
#include "esp32s2/rom/secure_boot.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||
#include "esp32c3/rom/efuse.h"
|
||||
#include "esp32c3/rom/secure_boot.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||
#include "esp32s3/rom/efuse.h"
|
||||
#include "esp32s3/rom/secure_boot.h"
|
||||
#endif
|
||||
|
||||
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"
|
||||
@@ -45,6 +50,8 @@ extern "C" {
|
||||
Can be compiled as part of app or bootloader code.
|
||||
*/
|
||||
|
||||
#define ESP_SECURE_BOOT_DIGEST_LEN 32
|
||||
|
||||
/** @brief Is secure boot currently enabled in hardware?
|
||||
*
|
||||
* This means that the ROM bootloader code will only boot
|
||||
@@ -181,6 +188,16 @@ typedef struct {
|
||||
*/
|
||||
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 !CONFIG_IDF_TARGET_ESP32 || CONFIG_ESP32_REV_MIN_3
|
||||
/**
|
||||
* @brief Structure to hold public key digests calculated from the signature blocks of a single image.
|
||||
*
|
||||
* Each image can have one or more signature blocks (up to SECURE_BOOT_NUM_BLOCKS). Each signature block includes a public key.
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t key_digests[SECURE_BOOT_NUM_BLOCKS][ESP_SECURE_BOOT_DIGEST_LEN]; /* SHA of the public key components in the signature block */
|
||||
unsigned num_digests; /* Number of valid digests, starting at index 0 */
|
||||
} esp_image_sig_public_key_digests_t;
|
||||
|
||||
/** @brief Verify the RSA secure boot signature block for Secure Boot V2.
|
||||
*
|
||||
@@ -194,6 +211,7 @@ esp_err_t esp_secure_boot_verify_ecdsa_signature_block(const esp_secure_boot_sig
|
||||
*
|
||||
*/
|
||||
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);
|
||||
#endif // !CONFIG_IDF_TARGET_ESP32 || CONFIG_ESP32_REV_MIN_3
|
||||
|
||||
/** @brief Legacy ECDSA verification function
|
||||
*
|
||||
@@ -214,6 +232,45 @@ typedef struct {
|
||||
uint8_t digest[64];
|
||||
} esp_secure_boot_iv_digest_t;
|
||||
|
||||
/** @brief Check the secure boot V2 during startup
|
||||
*
|
||||
* @note This function is called automatically during app startup,
|
||||
* it doesn't need to be called from the app.
|
||||
*
|
||||
* Verifies the secure boot config during startup:
|
||||
*
|
||||
* - Correct any insecure secure boot settings
|
||||
*/
|
||||
void esp_secure_boot_init_checks(void);
|
||||
|
||||
#if !BOOTLOADER_BUILD && CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME
|
||||
|
||||
/** @brief Scan the current running app for signature blocks
|
||||
*
|
||||
* @note This function doesn't verify that the signatures are valid or the
|
||||
* corresponding public keys are trusted, it only reads the number of signature
|
||||
* blocks present and optionally calculates the digests of the public keys
|
||||
* provided in the signature blocks.
|
||||
*
|
||||
* @param digest_public_keys If true, the key_digests fields in the
|
||||
* public_key_digests structure will be filled with the digests of the public
|
||||
* key provided in each signature block. Note that if Secure Boot V2 is enabled,
|
||||
* each public key will only be trusted if the same digest is also present in
|
||||
* eFuse (but this is not checked by this function).
|
||||
*
|
||||
* @param public_key_digests[out] Structure is initialized with the num_digests
|
||||
* field set to the number of signatures found. If digest_public_keys is set,
|
||||
* the public key digests are also calculated and stored here.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK - At least one signature was found
|
||||
* - ESP_ERR_NOT_FOUND - No signatures were found, num_digests value will be zero
|
||||
* - ESP_FAIL - An error occured trying to read the signature blocks from flash
|
||||
*/
|
||||
esp_err_t esp_secure_boot_get_signature_blocks_for_running_app(bool digest_public_keys, esp_image_sig_public_key_digests_t *public_key_digests);
|
||||
|
||||
#endif // !BOOTLOADER_BUILD && CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include "soc/gpio_periph.h"
|
||||
#include "soc/rtc.h"
|
||||
#include "soc/efuse_reg.h"
|
||||
#include "soc/soc_memory_layout.h"
|
||||
#include "hal/gpio_ll.h"
|
||||
#include "esp_image_format.h"
|
||||
#include "bootloader_sha.h"
|
||||
@@ -76,7 +77,9 @@ esp_err_t bootloader_common_check_chip_validity(const esp_image_header_t* img_hd
|
||||
}
|
||||
uint8_t revision = bootloader_common_get_chip_revision();
|
||||
if (revision < img_hdr->min_chip_rev) {
|
||||
ESP_LOGE(TAG, "can't run on lower chip revision, expected %d, found %d", revision, img_hdr->min_chip_rev);
|
||||
/* To fix this error, please update mininum supported chip revision from configuration,
|
||||
* located in TARGET (e.g. ESP32) specific options under "Component config" menu */
|
||||
ESP_LOGE(TAG, "This chip is revision %d but the application is configured for minimum revision %d. Can't run.", revision, img_hdr->min_chip_rev);
|
||||
err = ESP_FAIL;
|
||||
} else if (revision != img_hdr->min_chip_rev) {
|
||||
#ifdef BOOTLOADER_BUILD
|
||||
@@ -138,7 +141,18 @@ esp_err_t bootloader_common_get_partition_description(const esp_partition_pos_t
|
||||
|
||||
#if defined( CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP ) || defined( CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC )
|
||||
|
||||
rtc_retain_mem_t *const rtc_retain_mem = (rtc_retain_mem_t *)(SOC_RTC_DRAM_HIGH - sizeof(rtc_retain_mem_t));
|
||||
#define RTC_RETAIN_MEM_ADDR (SOC_RTC_DRAM_HIGH - sizeof(rtc_retain_mem_t))
|
||||
|
||||
rtc_retain_mem_t *const rtc_retain_mem = (rtc_retain_mem_t *)RTC_RETAIN_MEM_ADDR;
|
||||
|
||||
#if !IS_BOOTLOADER_BUILD
|
||||
/* The app needs to be told this memory is reserved, important if configured to use RTC memory as heap.
|
||||
|
||||
Note that keeping this macro here only works when other symbols in this file are referenced by the app, as
|
||||
this feature is otherwise 100% part of the bootloader. However this seems to happen in all apps.
|
||||
*/
|
||||
SOC_RESERVE_MEMORY_REGION(RTC_RETAIN_MEM_ADDR, RTC_RETAIN_MEM_ADDR + sizeof(rtc_retain_mem_t), rtc_retain_mem);
|
||||
#endif
|
||||
|
||||
static bool check_rtc_retain_mem(void)
|
||||
{
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "soc/gpio_sig_map.h"
|
||||
#include "soc/rtc.h"
|
||||
#include "hal/clk_gate_ll.h"
|
||||
#include "hal/gpio_hal.h"
|
||||
#if CONFIG_IDF_TARGET_ESP32S2
|
||||
#include "esp32s2/rom/usb/cdc_acm.h"
|
||||
#include "esp32s2/rom/usb/usb_common.h"
|
||||
@@ -69,8 +70,8 @@ void bootloader_console_init(void)
|
||||
uart_tx_gpio != UART_NUM_0_TXD_DIRECT_GPIO_NUM ||
|
||||
uart_rx_gpio != UART_NUM_0_RXD_DIRECT_GPIO_NUM) {
|
||||
// Change default UART pins back to GPIOs
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, PIN_FUNC_GPIO);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, PIN_FUNC_GPIO);
|
||||
gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_U0RXD_U, PIN_FUNC_GPIO);
|
||||
gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_U0TXD_U, PIN_FUNC_GPIO);
|
||||
// Route GPIO signals to/from pins
|
||||
const uint32_t tx_idx = uart_periph_signal[uart_num].tx_sig;
|
||||
const uint32_t rx_idx = uart_periph_signal[uart_num].rx_sig;
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "soc/spi_reg.h"
|
||||
#include "soc/soc_caps.h"
|
||||
#include "soc/soc_pins.h"
|
||||
#include "hal/gpio_hal.h"
|
||||
#include "flash_qio_mode.h"
|
||||
#include "bootloader_common.h"
|
||||
#include "bootloader_flash_config.h"
|
||||
@@ -87,7 +88,7 @@ void IRAM_ATTR bootloader_flash_gpio_config(const esp_image_header_t* pfhdr)
|
||||
pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOV302) {
|
||||
// For ESP32D2WD or ESP32-PICO series,the SPI pins are already configured
|
||||
// flash clock signal should come from IO MUX.
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK);
|
||||
gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK);
|
||||
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, drv, FUN_DRV_S);
|
||||
} else {
|
||||
const uint32_t spiconfig = esp_rom_efuse_get_flash_gpio_info();
|
||||
@@ -102,14 +103,14 @@ void IRAM_ATTR bootloader_flash_gpio_config(const esp_image_header_t* pfhdr)
|
||||
esp_rom_gpio_connect_out_signal(SPI_IOMUX_PIN_NUM_HD, SPIHD_OUT_IDX, 0, 0);
|
||||
esp_rom_gpio_connect_in_signal(SPI_IOMUX_PIN_NUM_HD, SPIHD_IN_IDX, 0);
|
||||
//select pin function gpio
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA0_U, PIN_FUNC_GPIO);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA1_U, PIN_FUNC_GPIO);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA2_U, PIN_FUNC_GPIO);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA3_U, PIN_FUNC_GPIO);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CMD_U, PIN_FUNC_GPIO);
|
||||
gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_SD_DATA0_U, PIN_FUNC_GPIO);
|
||||
gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_SD_DATA1_U, PIN_FUNC_GPIO);
|
||||
gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_SD_DATA2_U, PIN_FUNC_GPIO);
|
||||
gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_SD_DATA3_U, PIN_FUNC_GPIO);
|
||||
gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_SD_CMD_U, PIN_FUNC_GPIO);
|
||||
// flash clock signal should come from IO MUX.
|
||||
// set drive ability for clock
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK);
|
||||
gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK);
|
||||
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, drv, FUN_DRV_S);
|
||||
|
||||
uint32_t flash_id = g_rom_flashchip.device_id;
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
#include "soc/efuse_reg.h"
|
||||
#include "soc/spi_reg.h"
|
||||
#include "soc/spi_mem_reg.h"
|
||||
#include "soc/spi_caps.h"
|
||||
#include "soc/soc_caps.h"
|
||||
#include "flash_qio_mode.h"
|
||||
#include "bootloader_flash_config.h"
|
||||
#include "bootloader_common.h"
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "soc/io_mux_reg.h"
|
||||
#include "soc/rtc.h"
|
||||
#include "soc/spi_periph.h"
|
||||
#include "hal/gpio_hal.h"
|
||||
|
||||
#include "esp32/rom/cache.h"
|
||||
#include "esp_rom_gpio.h"
|
||||
@@ -61,7 +62,7 @@ void bootloader_configure_spi_pins(int drv)
|
||||
pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOV302) {
|
||||
// For ESP32D2WD or ESP32-PICO series,the SPI pins are already configured
|
||||
// flash clock signal should come from IO MUX.
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK);
|
||||
gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK);
|
||||
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, drv, FUN_DRV_S);
|
||||
} else {
|
||||
const uint32_t spiconfig = esp_rom_efuse_get_flash_gpio_info();
|
||||
@@ -76,14 +77,14 @@ void bootloader_configure_spi_pins(int drv)
|
||||
esp_rom_gpio_connect_out_signal(FLASH_SPIHD_IO, SPIHD_OUT_IDX, 0, 0);
|
||||
esp_rom_gpio_connect_in_signal(FLASH_SPIHD_IO, SPIHD_IN_IDX, 0);
|
||||
//select pin function gpio
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA0_U, PIN_FUNC_GPIO);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA1_U, PIN_FUNC_GPIO);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA2_U, PIN_FUNC_GPIO);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA3_U, PIN_FUNC_GPIO);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CMD_U, PIN_FUNC_GPIO);
|
||||
gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_SD_DATA0_U, PIN_FUNC_GPIO);
|
||||
gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_SD_DATA1_U, PIN_FUNC_GPIO);
|
||||
gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_SD_DATA2_U, PIN_FUNC_GPIO);
|
||||
gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_SD_DATA3_U, PIN_FUNC_GPIO);
|
||||
gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_SD_CMD_U, PIN_FUNC_GPIO);
|
||||
// flash clock signal should come from IO MUX.
|
||||
// set drive ability for clock
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK);
|
||||
gpio_hal_iomux_func_sel(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK);
|
||||
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, drv, FUN_DRV_S);
|
||||
|
||||
#if CONFIG_SPIRAM_TYPE_ESPPSRAM32 || CONFIG_SPIRAM_TYPE_ESPPSRAM64
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
#include "esp_log.h"
|
||||
|
||||
#include "esp32/rom/cache.h"
|
||||
#include "esp_rom_crc.h"
|
||||
|
||||
#include "soc/efuse_periph.h"
|
||||
#include "soc/rtc_periph.h"
|
||||
@@ -223,16 +222,12 @@ esp_err_t esp_secure_boot_permanently_enable(void)
|
||||
#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 = esp_rom_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)) {
|
||||
if (sig_block->block[0].magic_byte == ETS_SECURE_BOOT_V2_SIGNATURE_MAGIC
|
||||
&& sig_block->block[0].block_crc == crc
|
||||
&& !memcmp(digest, sig_block->block[0].image_digest, ESP_SECURE_BOOT_DIGEST_LEN)) {
|
||||
ESP_LOGI(TAG, "valid signature block found");
|
||||
return ESP_OK;
|
||||
}
|
||||
@@ -243,7 +238,7 @@ static esp_err_t secure_boot_v2_digest_generate(uint32_t flash_offset, uint32_t
|
||||
{
|
||||
esp_err_t ret = ESP_FAIL;
|
||||
|
||||
uint8_t image_digest[DIGEST_LEN] = {0};
|
||||
uint8_t image_digest[ESP_SECURE_BOOT_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) {
|
||||
@@ -266,7 +261,7 @@ static esp_err_t secure_boot_v2_digest_generate(uint32_t flash_offset, uint32_t
|
||||
}
|
||||
|
||||
/* Verifying Signature block */
|
||||
uint8_t verified_digest[DIGEST_LEN] = {0};
|
||||
uint8_t verified_digest[ESP_SECURE_BOOT_DIGEST_LEN] = {0};
|
||||
|
||||
/* Generating the SHA of the public key components in the signature block */
|
||||
bootloader_sha256_handle_t sig_block_sha;
|
||||
@@ -318,7 +313,7 @@ esp_err_t esp_secure_boot_v2_permanently_enable(const esp_image_metadata_t *imag
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint8_t boot_pub_key_digest[DIGEST_LEN];
|
||||
uint8_t boot_pub_key_digest[ESP_SECURE_BOOT_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;
|
||||
@@ -350,7 +345,7 @@ esp_err_t esp_secure_boot_v2_permanently_enable(const esp_image_metadata_t *imag
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Burning public key hash to efuse.");
|
||||
ret = esp_efuse_write_block(EFUSE_BLK2, boot_pub_key_digest, 0, (DIGEST_LEN * 8));
|
||||
ret = esp_efuse_write_block(EFUSE_BLK2, boot_pub_key_digest, 0, (ESP_SECURE_BOOT_DIGEST_LEN * 8));
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Writing public key hash to efuse failed.");
|
||||
return ret;
|
||||
@@ -366,7 +361,7 @@ esp_err_t esp_secure_boot_v2_permanently_enable(const esp_image_metadata_t *imag
|
||||
efuse_blk2_digest[5] = efuse_blk2_r5;
|
||||
efuse_blk2_digest[6] = efuse_blk2_r6;
|
||||
efuse_blk2_digest[7] = efuse_blk2_r7;
|
||||
memcpy(boot_pub_key_digest, efuse_blk2_digest, DIGEST_LEN);
|
||||
memcpy(boot_pub_key_digest, efuse_blk2_digest, ESP_SECURE_BOOT_DIGEST_LEN);
|
||||
ESP_LOGW(TAG, "Using pre-loaded secure boot v2 public key digest in EFUSE block 2");
|
||||
}
|
||||
|
||||
@@ -380,7 +375,7 @@ esp_err_t esp_secure_boot_v2_permanently_enable(const esp_image_metadata_t *imag
|
||||
efuse_key_write_protected = true;
|
||||
}
|
||||
|
||||
uint8_t app_pub_key_digest[DIGEST_LEN];
|
||||
uint8_t app_pub_key_digest[ESP_SECURE_BOOT_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.");
|
||||
@@ -388,7 +383,7 @@ esp_err_t esp_secure_boot_v2_permanently_enable(const esp_image_metadata_t *imag
|
||||
}
|
||||
|
||||
/* 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) {
|
||||
if (memcmp(boot_pub_key_digest, app_pub_key_digest, ESP_SECURE_BOOT_DIGEST_LEN) != 0) {
|
||||
ESP_LOGE(TAG, "Application not signed with a valid private key.");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
@@ -1,184 +0,0 @@
|
||||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#include "bootloader_flash_priv.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_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
|
||||
|
||||
esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length)
|
||||
{
|
||||
uint8_t digest[DIGEST_LEN];
|
||||
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);
|
||||
|
||||
esp_err_t err = bootloader_sha256_flash_contents(src_addr, length, digest);
|
||||
if (err != ESP_OK) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// 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) {
|
||||
ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", src_addr + length, sizeof(esp_secure_boot_sig_block_t));
|
||||
return ESP_FAIL;
|
||||
}
|
||||
// Verify the signature
|
||||
err = esp_secure_boot_verify_ecdsa_signature_block(sigblock, digest, verified_digest);
|
||||
// Unmap
|
||||
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)
|
||||
{
|
||||
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;
|
||||
|
||||
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);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
if (sig_block->version != 0) {
|
||||
ESP_LOGE(TAG, "image has invalid signature version field 0x%08x", sig_block->version);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG, "Verifying secure boot signature");
|
||||
|
||||
bool is_valid;
|
||||
is_valid = uECC_verify_antifault(signature_verification_key_start,
|
||||
image_digest,
|
||||
DIGEST_LEN,
|
||||
sig_block->signature,
|
||||
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
|
||||
@@ -264,24 +264,33 @@ static void bootloader_super_wdt_auto_feed(void)
|
||||
|
||||
static inline void bootloader_hardware_init(void)
|
||||
{
|
||||
// TODO ESP32-C3 IDF-2452
|
||||
REGI2C_WRITE_MASK(I2C_ULP, I2C_ULP_IR_FORCE_XPD_IPH, 1);
|
||||
REGI2C_WRITE_MASK(I2C_BIAS, I2C_BIAS_DREG_1P1_PVT, 12);
|
||||
// This check is always included in the bootloader so it can
|
||||
// print the minimum revision error message later in the boot
|
||||
if (bootloader_common_get_chip_revision() < 3) {
|
||||
REGI2C_WRITE_MASK(I2C_ULP, I2C_ULP_IR_FORCE_XPD_IPH, 1);
|
||||
REGI2C_WRITE_MASK(I2C_BIAS, I2C_BIAS_DREG_1P1_PVT, 12);
|
||||
}
|
||||
}
|
||||
|
||||
/* There happend clock glitch reset for some chip when testing wifi[BIT0] and brownout reset when chip startup[BIT1].
|
||||
* But super_watch_dog_reset function is ok, so open it[BIT2].
|
||||
* Whether this api will deleted or not depends on analog design & test result when ECO chip come back.
|
||||
*/
|
||||
static inline void bootloader_glitch_reset_disable(void)
|
||||
{
|
||||
// TODO ESP32-C3 IDF-2453
|
||||
REG_SET_FIELD(RTC_CNTL_FIB_SEL_REG, RTC_CNTL_FIB_SEL, BIT2);
|
||||
/*
|
||||
For origin chip & ECO1: only support swt reset;
|
||||
For ECO2: fix brownout reset bug, support swt & brownout reset;
|
||||
For ECO3: fix clock glitch reset bug, support all reset, include: swt & brownout & clock glitch reset.
|
||||
*/
|
||||
uint8_t chip_version = bootloader_common_get_chip_revision();
|
||||
if (chip_version < 2) {
|
||||
REG_SET_FIELD(RTC_CNTL_FIB_SEL_REG, RTC_CNTL_FIB_SEL, RTC_CNTL_FIB_SUPER_WDT_RST);
|
||||
} else if (chip_version == 2) {
|
||||
REG_SET_FIELD(RTC_CNTL_FIB_SEL_REG, RTC_CNTL_FIB_SEL, RTC_CNTL_FIB_SUPER_WDT_RST | RTC_CNTL_FIB_BOR_RST);
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t bootloader_init(void)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
|
||||
bootloader_hardware_init();
|
||||
bootloader_glitch_reset_disable();
|
||||
bootloader_super_wdt_auto_feed();
|
||||
|
||||
@@ -31,17 +31,11 @@
|
||||
static const char *TAG = "secure_boot_v2";
|
||||
#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
|
||||
|
||||
#define SIG_BLOCK_MAGIC_BYTE 0xe7
|
||||
#define CRC_SIGN_BLOCK_LEN 1196
|
||||
#define SIG_BLOCK_PADDING 4096
|
||||
|
||||
#define DIGEST_LEN 32
|
||||
|
||||
/* A signature block is valid when it has correct magic byte, crc and image digest. */
|
||||
static esp_err_t validate_signature_block(const ets_secure_boot_sig_block_t *block, int block_num, const uint8_t *image_digest)
|
||||
{
|
||||
uint32_t crc = esp_rom_crc32_le(0, (uint8_t *)block, CRC_SIGN_BLOCK_LEN);
|
||||
if (block->magic_byte != SIG_BLOCK_MAGIC_BYTE) {
|
||||
if (block->magic_byte != ETS_SECURE_BOOT_V2_SIGNATURE_MAGIC) {
|
||||
// All signature blocks have been parsed, no new signature block present.
|
||||
ESP_LOGD(TAG, "Signature block(%d) invalid/absent.", block_num);
|
||||
return ESP_FAIL;
|
||||
@@ -50,7 +44,7 @@ static esp_err_t validate_signature_block(const ets_secure_boot_sig_block_t *blo
|
||||
ESP_LOGE(TAG, "Magic byte correct but incorrect crc.");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
if (memcmp(image_digest, block->image_digest, DIGEST_LEN)) {
|
||||
if (memcmp(image_digest, block->image_digest, ESP_SECURE_BOOT_DIGEST_LEN)) {
|
||||
ESP_LOGE(TAG, "Magic byte & CRC correct but incorrect image digest.");
|
||||
return ESP_FAIL;
|
||||
} else {
|
||||
@@ -61,19 +55,6 @@ static esp_err_t validate_signature_block(const ets_secure_boot_sig_block_t *blo
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
/* Structure to hold public key digests calculated from the signature blocks of a single image.
|
||||
|
||||
Each image can have one or more signature blocks (up to SECURE_BOOT_NUM_BLOCKS). Each signature block
|
||||
includes a public key.
|
||||
|
||||
Different to the ROM ets_secure_boot_key_digests_t structure which holds pointers to eFuse data with digests,
|
||||
in this data structure the digest data is included.
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t key_digests[SECURE_BOOT_NUM_BLOCKS][DIGEST_LEN];
|
||||
unsigned num_digests; /* Number of valid digests, starting at index 0 */
|
||||
} image_sig_public_key_digests_t;
|
||||
|
||||
/* Generates the public key digests of the valid public keys in an image's
|
||||
signature block, verifies each signature, and stores the key digests in the
|
||||
public_key_digests structure.
|
||||
@@ -89,16 +70,16 @@ typedef struct {
|
||||
@return - ESP_OK if no signatures failed to verify, or if no valid signature blocks are found at all.
|
||||
- ESP_FAIL if there's a valid signature block that doesn't verify using the included public key (unexpected!)
|
||||
*/
|
||||
static esp_err_t s_calculate_image_public_key_digests(uint32_t flash_offset, uint32_t flash_size, image_sig_public_key_digests_t *public_key_digests)
|
||||
static esp_err_t s_calculate_image_public_key_digests(uint32_t flash_offset, uint32_t flash_size, esp_image_sig_public_key_digests_t *public_key_digests)
|
||||
{
|
||||
esp_err_t ret;
|
||||
uint8_t image_digest[DIGEST_LEN] = {0};
|
||||
uint8_t __attribute__((aligned(4))) key_digest[DIGEST_LEN] = {0};
|
||||
uint8_t image_digest[ESP_SECURE_BOOT_DIGEST_LEN] = {0};
|
||||
uint8_t __attribute__((aligned(4))) key_digest[ESP_SECURE_BOOT_DIGEST_LEN] = {0};
|
||||
size_t sig_block_addr = flash_offset + ALIGN_UP(flash_size, FLASH_SECTOR_SIZE);
|
||||
|
||||
ESP_LOGD(TAG, "calculating public key digests for sig blocks of image offset 0x%x (sig block offset 0x%x)", flash_offset, sig_block_addr);
|
||||
|
||||
bzero(public_key_digests, sizeof(image_sig_public_key_digests_t));
|
||||
bzero(public_key_digests, sizeof(esp_image_sig_public_key_digests_t));
|
||||
|
||||
ret = bootloader_sha256_flash_contents(flash_offset, sig_block_addr - flash_offset, image_digest);
|
||||
if (ret != ESP_OK) {
|
||||
@@ -129,7 +110,7 @@ static esp_err_t s_calculate_image_public_key_digests(uint32_t flash_offset, uin
|
||||
bootloader_sha256_finish(sig_block_sha, key_digest);
|
||||
|
||||
// Check we can verify the image using this signature and this key
|
||||
uint8_t temp_verified_digest[DIGEST_LEN];
|
||||
uint8_t temp_verified_digest[ESP_SECURE_BOOT_DIGEST_LEN];
|
||||
bool verified = ets_rsa_pss_verify(&block->key, block->signature, image_digest, temp_verified_digest);
|
||||
|
||||
if (!verified) {
|
||||
@@ -142,7 +123,7 @@ static esp_err_t s_calculate_image_public_key_digests(uint32_t flash_offset, uin
|
||||
}
|
||||
ESP_LOGD(TAG, "Signature block (%d) is verified", i);
|
||||
/* Copy the key digest to the buffer provided by the caller */
|
||||
memcpy((void *)public_key_digests->key_digests[i], key_digest, DIGEST_LEN);
|
||||
memcpy((void *)public_key_digests->key_digests[i], key_digest, ESP_SECURE_BOOT_DIGEST_LEN);
|
||||
public_key_digests->num_digests++;
|
||||
}
|
||||
|
||||
@@ -173,8 +154,8 @@ static esp_err_t check_and_generate_secure_boot_keys(const esp_image_metadata_t
|
||||
ESP_LOGI(TAG, "Secure boot digests %s", has_secure_boot_digest ? "already present":"absent, generating..");
|
||||
|
||||
if (!has_secure_boot_digest) {
|
||||
image_sig_public_key_digests_t boot_key_digests = {0};
|
||||
image_sig_public_key_digests_t app_key_digests = {0};
|
||||
esp_image_sig_public_key_digests_t boot_key_digests = {0};
|
||||
esp_image_sig_public_key_digests_t app_key_digests = {0};
|
||||
|
||||
/* Generate the bootloader public key digests */
|
||||
ret = s_calculate_image_public_key_digests(bootloader_data.start_addr, bootloader_data.image_len - SIG_BLOCK_PADDING, &boot_key_digests);
|
||||
@@ -234,7 +215,7 @@ static esp_err_t check_and_generate_secure_boot_keys(const esp_image_metadata_t
|
||||
}
|
||||
|
||||
for (int j = 0; j < app_key_digests.num_digests; j++) {
|
||||
if (!memcmp(boot_key_digests.key_digests[i], app_key_digests.key_digests[j], DIGEST_LEN)) {
|
||||
if (!memcmp(boot_key_digests.key_digests[i], app_key_digests.key_digests[j], ESP_SECURE_BOOT_DIGEST_LEN)) {
|
||||
ESP_LOGI(TAG, "Application key(%d) matches with bootloader key(%d).", j, i);
|
||||
match = true;
|
||||
}
|
||||
|
||||
@@ -1,94 +0,0 @@
|
||||
// Copyright 2015-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 "sdkconfig.h"
|
||||
|
||||
#include <string.h>
|
||||
#include "esp_fault.h"
|
||||
#include "bootloader_flash_priv.h"
|
||||
#include "bootloader_sha.h"
|
||||
#include "bootloader_utility.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_image_format.h"
|
||||
#include "esp_secure_boot.h"
|
||||
#include "esp32c3/rom/secure_boot.h"
|
||||
|
||||
static const char* TAG = "secure_boot";
|
||||
|
||||
#define DIGEST_LEN 32
|
||||
#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];
|
||||
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);
|
||||
|
||||
/* 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, length + sizeof(struct ets_secure_boot_sig_block));
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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 = (const ets_secure_boot_signature_t *)(data + length);
|
||||
int r = esp_secure_boot_verify_rsa_signature_block(sig, digest, verified_digest);
|
||||
bootloader_munmap(data);
|
||||
|
||||
return (r == ETS_OK) ? ESP_OK : ESP_FAIL;
|
||||
}
|
||||
|
||||
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;
|
||||
ets_secure_boot_key_digests_t trusted_key_copies[2];
|
||||
ETS_STATUS r;
|
||||
ets_secure_boot_status_t sb_result;
|
||||
|
||||
memset(&trusted_keys, 0, sizeof(ets_secure_boot_key_digests_t));
|
||||
memset(trusted_key_copies, 0, 2 * sizeof(ets_secure_boot_key_digests_t));
|
||||
|
||||
if (!esp_secure_boot_enabled()) {
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
r = ets_secure_boot_read_key_digests(&trusted_keys);
|
||||
if (r != ETS_OK) {
|
||||
ESP_LOGI(TAG, "Could not read secure boot digests!");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
// Create the copies for FI checks (assuming result is ETS_OK, if it's not then it'll fail the fault check anyhow)
|
||||
ets_secure_boot_read_key_digests(&trusted_key_copies[0]);
|
||||
ets_secure_boot_read_key_digests(&trusted_key_copies[1]);
|
||||
ESP_FAULT_ASSERT(memcmp(&trusted_keys, &trusted_key_copies[0], sizeof(ets_secure_boot_key_digests_t)) == 0);
|
||||
ESP_FAULT_ASSERT(memcmp(&trusted_keys, &trusted_key_copies[1], sizeof(ets_secure_boot_key_digests_t)) == 0);
|
||||
|
||||
ESP_LOGI(TAG, "Verifying with RSA-PSS boot...");
|
||||
sb_result = ets_secure_boot_verify_signature(sig_block, image_digest, &trusted_keys, verified_digest);
|
||||
return (sb_result == SB_SUCCESS) ? ESP_OK : ESP_FAIL;
|
||||
}
|
||||
@@ -31,17 +31,11 @@
|
||||
static const char *TAG = "secure_boot_v2";
|
||||
#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
|
||||
|
||||
#define SIG_BLOCK_MAGIC_BYTE 0xe7
|
||||
#define CRC_SIGN_BLOCK_LEN 1196
|
||||
#define SIG_BLOCK_PADDING 4096
|
||||
|
||||
#define DIGEST_LEN 32
|
||||
|
||||
/* A signature block is valid when it has correct magic byte, crc and image digest. */
|
||||
static esp_err_t validate_signature_block(const ets_secure_boot_sig_block_t *block, int block_num, const uint8_t *image_digest)
|
||||
{
|
||||
uint32_t crc = esp_rom_crc32_le(0, (uint8_t *)block, CRC_SIGN_BLOCK_LEN);
|
||||
if (block->magic_byte != SIG_BLOCK_MAGIC_BYTE) {
|
||||
if (block->magic_byte != ETS_SECURE_BOOT_V2_SIGNATURE_MAGIC) {
|
||||
// All signature blocks have been parsed, no new signature block present.
|
||||
ESP_LOGD(TAG, "Signature block(%d) invalid/absent.", block_num);
|
||||
return ESP_FAIL;
|
||||
@@ -50,7 +44,7 @@ static esp_err_t validate_signature_block(const ets_secure_boot_sig_block_t *blo
|
||||
ESP_LOGE(TAG, "Magic byte correct but incorrect crc.");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
if (memcmp(image_digest, block->image_digest, DIGEST_LEN)) {
|
||||
if (memcmp(image_digest, block->image_digest, ESP_SECURE_BOOT_DIGEST_LEN)) {
|
||||
ESP_LOGE(TAG, "Magic byte & CRC correct but incorrect image digest.");
|
||||
return ESP_FAIL;
|
||||
} else {
|
||||
@@ -61,19 +55,6 @@ static esp_err_t validate_signature_block(const ets_secure_boot_sig_block_t *blo
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
/* Structure to hold public key digests calculated from the signature blocks of a single image.
|
||||
|
||||
Each image can have one or more signature blocks (up to SECURE_BOOT_NUM_BLOCKS). Each signature block
|
||||
includes a public key.
|
||||
|
||||
Different to the ROM ets_secure_boot_key_digests_t structure which holds pointers to eFuse data with digests,
|
||||
in this data structure the digest data is included.
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t key_digests[SECURE_BOOT_NUM_BLOCKS][DIGEST_LEN];
|
||||
unsigned num_digests; /* Number of valid digests, starting at index 0 */
|
||||
} image_sig_public_key_digests_t;
|
||||
|
||||
/* Generates the public key digests of the valid public keys in an image's
|
||||
signature block, verifies each signature, and stores the key digests in the
|
||||
public_key_digests structure.
|
||||
@@ -89,16 +70,16 @@ typedef struct {
|
||||
@return - ESP_OK if no signatures failed to verify, or if no valid signature blocks are found at all.
|
||||
- ESP_FAIL if there's a valid signature block that doesn't verify using the included public key (unexpected!)
|
||||
*/
|
||||
static esp_err_t s_calculate_image_public_key_digests(uint32_t flash_offset, uint32_t flash_size, image_sig_public_key_digests_t *public_key_digests)
|
||||
static esp_err_t s_calculate_image_public_key_digests(uint32_t flash_offset, uint32_t flash_size, esp_image_sig_public_key_digests_t *public_key_digests)
|
||||
{
|
||||
esp_err_t ret;
|
||||
uint8_t image_digest[DIGEST_LEN] = {0};
|
||||
uint8_t __attribute__((aligned(4))) key_digest[DIGEST_LEN] = {0};
|
||||
uint8_t image_digest[ESP_SECURE_BOOT_DIGEST_LEN] = {0};
|
||||
uint8_t __attribute__((aligned(4))) key_digest[ESP_SECURE_BOOT_DIGEST_LEN] = {0};
|
||||
size_t sig_block_addr = flash_offset + ALIGN_UP(flash_size, FLASH_SECTOR_SIZE);
|
||||
|
||||
ESP_LOGD(TAG, "calculating public key digests for sig blocks of image offset 0x%x (sig block offset 0x%x)", flash_offset, sig_block_addr);
|
||||
|
||||
bzero(public_key_digests, sizeof(image_sig_public_key_digests_t));
|
||||
bzero(public_key_digests, sizeof(esp_image_sig_public_key_digests_t));
|
||||
|
||||
ret = bootloader_sha256_flash_contents(flash_offset, sig_block_addr - flash_offset, image_digest);
|
||||
if (ret != ESP_OK) {
|
||||
@@ -129,7 +110,7 @@ static esp_err_t s_calculate_image_public_key_digests(uint32_t flash_offset, uin
|
||||
bootloader_sha256_finish(sig_block_sha, key_digest);
|
||||
|
||||
// Check we can verify the image using this signature and this key
|
||||
uint8_t temp_verified_digest[DIGEST_LEN];
|
||||
uint8_t temp_verified_digest[ESP_SECURE_BOOT_DIGEST_LEN];
|
||||
bool verified = ets_rsa_pss_verify(&block->key, block->signature, image_digest, temp_verified_digest);
|
||||
|
||||
if (!verified) {
|
||||
@@ -142,7 +123,7 @@ static esp_err_t s_calculate_image_public_key_digests(uint32_t flash_offset, uin
|
||||
}
|
||||
ESP_LOGD(TAG, "Signature block (%d) is verified", i);
|
||||
/* Copy the key digest to the buffer provided by the caller */
|
||||
memcpy((void *)public_key_digests->key_digests[i], key_digest, DIGEST_LEN);
|
||||
memcpy((void *)public_key_digests->key_digests[i], key_digest, ESP_SECURE_BOOT_DIGEST_LEN);
|
||||
public_key_digests->num_digests++;
|
||||
}
|
||||
|
||||
@@ -173,8 +154,8 @@ static esp_err_t check_and_generate_secure_boot_keys(const esp_image_metadata_t
|
||||
ESP_LOGI(TAG, "Secure boot digests %s", has_secure_boot_digest ? "already present":"absent, generating..");
|
||||
|
||||
if (!has_secure_boot_digest) {
|
||||
image_sig_public_key_digests_t boot_key_digests = {0};
|
||||
image_sig_public_key_digests_t app_key_digests = {0};
|
||||
esp_image_sig_public_key_digests_t boot_key_digests = {0};
|
||||
esp_image_sig_public_key_digests_t app_key_digests = {0};
|
||||
|
||||
/* Generate the bootloader public key digests */
|
||||
ret = s_calculate_image_public_key_digests(bootloader_data.start_addr, bootloader_data.image_len - SIG_BLOCK_PADDING, &boot_key_digests);
|
||||
@@ -234,7 +215,7 @@ static esp_err_t check_and_generate_secure_boot_keys(const esp_image_metadata_t
|
||||
}
|
||||
|
||||
for (int j = 0; j < app_key_digests.num_digests; j++) {
|
||||
if (!memcmp(boot_key_digests.key_digests[i], app_key_digests.key_digests[j], DIGEST_LEN)) {
|
||||
if (!memcmp(boot_key_digests.key_digests[i], app_key_digests.key_digests[j], ESP_SECURE_BOOT_DIGEST_LEN)) {
|
||||
ESP_LOGI(TAG, "Application key(%d) matches with bootloader key(%d).", j, i);
|
||||
match = true;
|
||||
}
|
||||
|
||||
@@ -1,93 +0,0 @@
|
||||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#include <string.h>
|
||||
#include "esp_fault.h"
|
||||
#include "bootloader_flash_priv.h"
|
||||
#include "bootloader_sha.h"
|
||||
#include "bootloader_utility.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_image_format.h"
|
||||
#include "esp_secure_boot.h"
|
||||
#include "esp32s2/rom/secure_boot.h"
|
||||
|
||||
static const char* TAG = "secure_boot";
|
||||
|
||||
#define DIGEST_LEN 32
|
||||
#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];
|
||||
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);
|
||||
|
||||
/* 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, length + sizeof(struct ets_secure_boot_sig_block));
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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 = (const ets_secure_boot_signature_t *)(data + length);
|
||||
int r = esp_secure_boot_verify_rsa_signature_block(sig, digest, verified_digest);
|
||||
bootloader_munmap(data);
|
||||
|
||||
return (r == ETS_OK) ? ESP_OK : ESP_FAIL;
|
||||
}
|
||||
|
||||
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;
|
||||
ets_secure_boot_key_digests_t trusted_key_copies[2];
|
||||
ETS_STATUS r;
|
||||
ets_secure_boot_status_t sb_result;
|
||||
|
||||
memset(&trusted_keys, 0, sizeof(ets_secure_boot_key_digests_t));
|
||||
memset(trusted_key_copies, 0, 2 * sizeof(ets_secure_boot_key_digests_t));
|
||||
|
||||
if (!esp_secure_boot_enabled()) {
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
r = ets_secure_boot_read_key_digests(&trusted_keys);
|
||||
if (r != ETS_OK) {
|
||||
ESP_LOGI(TAG, "Could not read secure boot digests!");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
// Create the copies for FI checks (assuming result is ETS_OK, if it's not then it'll fail the fault check anyhow)
|
||||
ets_secure_boot_read_key_digests(&trusted_key_copies[0]);
|
||||
ets_secure_boot_read_key_digests(&trusted_key_copies[1]);
|
||||
ESP_FAULT_ASSERT(memcmp(&trusted_keys, &trusted_key_copies[0], sizeof(ets_secure_boot_key_digests_t)) == 0);
|
||||
ESP_FAULT_ASSERT(memcmp(&trusted_keys, &trusted_key_copies[1], sizeof(ets_secure_boot_key_digests_t)) == 0);
|
||||
|
||||
ESP_LOGI(TAG, "Verifying with RSA-PSS boot...");
|
||||
sb_result = ets_secure_boot_verify_signature(sig_block, image_digest, &trusted_keys, verified_digest);
|
||||
return (sb_result == SB_SUCCESS) ? ESP_OK : ESP_FAIL;
|
||||
}
|
||||
@@ -31,17 +31,11 @@
|
||||
static const char *TAG = "secure_boot_v2";
|
||||
#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
|
||||
|
||||
#define SIG_BLOCK_MAGIC_BYTE 0xe7
|
||||
#define CRC_SIGN_BLOCK_LEN 1196
|
||||
#define SIG_BLOCK_PADDING 4096
|
||||
|
||||
#define DIGEST_LEN 32
|
||||
|
||||
/* A signature block is valid when it has correct magic byte, crc and image digest. */
|
||||
static esp_err_t validate_signature_block(const ets_secure_boot_sig_block_t *block, int block_num, const uint8_t *image_digest)
|
||||
{
|
||||
uint32_t crc = esp_rom_crc32_le(0, (uint8_t *)block, CRC_SIGN_BLOCK_LEN);
|
||||
if (block->magic_byte != SIG_BLOCK_MAGIC_BYTE) {
|
||||
if (block->magic_byte != ETS_SECURE_BOOT_V2_SIGNATURE_MAGIC) {
|
||||
// All signature blocks have been parsed, no new signature block present.
|
||||
ESP_LOGD(TAG, "Signature block(%d) invalid/absent.", block_num);
|
||||
return ESP_FAIL;
|
||||
@@ -50,7 +44,7 @@ static esp_err_t validate_signature_block(const ets_secure_boot_sig_block_t *blo
|
||||
ESP_LOGE(TAG, "Magic byte correct but incorrect crc.");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
if (memcmp(image_digest, block->image_digest, DIGEST_LEN)) {
|
||||
if (memcmp(image_digest, block->image_digest, ESP_SECURE_BOOT_DIGEST_LEN)) {
|
||||
ESP_LOGE(TAG, "Magic byte & CRC correct but incorrect image digest.");
|
||||
return ESP_FAIL;
|
||||
} else {
|
||||
@@ -61,19 +55,6 @@ static esp_err_t validate_signature_block(const ets_secure_boot_sig_block_t *blo
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
/* Structure to hold public key digests calculated from the signature blocks of a single image.
|
||||
|
||||
Each image can have one or more signature blocks (up to SECURE_BOOT_NUM_BLOCKS). Each signature block
|
||||
includes a public key.
|
||||
|
||||
Different to the ROM ets_secure_boot_key_digests_t structure which holds pointers to eFuse data with digests,
|
||||
in this data structure the digest data is included.
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t key_digests[SECURE_BOOT_NUM_BLOCKS][DIGEST_LEN];
|
||||
unsigned num_digests; /* Number of valid digests, starting at index 0 */
|
||||
} image_sig_public_key_digests_t;
|
||||
|
||||
/* Generates the public key digests of the valid public keys in an image's
|
||||
signature block, verifies each signature, and stores the key digests in the
|
||||
public_key_digests structure.
|
||||
@@ -89,16 +70,16 @@ typedef struct {
|
||||
@return - ESP_OK if no signatures failed to verify, or if no valid signature blocks are found at all.
|
||||
- ESP_FAIL if there's a valid signature block that doesn't verify using the included public key (unexpected!)
|
||||
*/
|
||||
static esp_err_t s_calculate_image_public_key_digests(uint32_t flash_offset, uint32_t flash_size, image_sig_public_key_digests_t *public_key_digests)
|
||||
static esp_err_t s_calculate_image_public_key_digests(uint32_t flash_offset, uint32_t flash_size, esp_image_sig_public_key_digests_t *public_key_digests)
|
||||
{
|
||||
esp_err_t ret;
|
||||
uint8_t image_digest[DIGEST_LEN] = {0};
|
||||
uint8_t __attribute__((aligned(4))) key_digest[DIGEST_LEN] = {0};
|
||||
uint8_t image_digest[ESP_SECURE_BOOT_DIGEST_LEN] = {0};
|
||||
uint8_t __attribute__((aligned(4))) key_digest[ESP_SECURE_BOOT_DIGEST_LEN] = {0};
|
||||
size_t sig_block_addr = flash_offset + ALIGN_UP(flash_size, FLASH_SECTOR_SIZE);
|
||||
|
||||
ESP_LOGD(TAG, "calculating public key digests for sig blocks of image offset 0x%x (sig block offset 0x%x)", flash_offset, sig_block_addr);
|
||||
|
||||
bzero(public_key_digests, sizeof(image_sig_public_key_digests_t));
|
||||
bzero(public_key_digests, sizeof(esp_image_sig_public_key_digests_t));
|
||||
|
||||
ret = bootloader_sha256_flash_contents(flash_offset, sig_block_addr - flash_offset, image_digest);
|
||||
if (ret != ESP_OK) {
|
||||
@@ -129,7 +110,7 @@ static esp_err_t s_calculate_image_public_key_digests(uint32_t flash_offset, uin
|
||||
bootloader_sha256_finish(sig_block_sha, key_digest);
|
||||
|
||||
// Check we can verify the image using this signature and this key
|
||||
uint8_t temp_verified_digest[DIGEST_LEN];
|
||||
uint8_t temp_verified_digest[ESP_SECURE_BOOT_DIGEST_LEN];
|
||||
bool verified = ets_rsa_pss_verify(&block->key, block->signature, image_digest, temp_verified_digest);
|
||||
|
||||
if (!verified) {
|
||||
@@ -142,7 +123,7 @@ static esp_err_t s_calculate_image_public_key_digests(uint32_t flash_offset, uin
|
||||
}
|
||||
ESP_LOGD(TAG, "Signature block (%d) is verified", i);
|
||||
/* Copy the key digest to the buffer provided by the caller */
|
||||
memcpy((void *)public_key_digests->key_digests[i], key_digest, DIGEST_LEN);
|
||||
memcpy((void *)public_key_digests->key_digests[i], key_digest, ESP_SECURE_BOOT_DIGEST_LEN);
|
||||
public_key_digests->num_digests++;
|
||||
}
|
||||
|
||||
@@ -173,8 +154,8 @@ static esp_err_t check_and_generate_secure_boot_keys(const esp_image_metadata_t
|
||||
ESP_LOGI(TAG, "Secure boot digests %s", has_secure_boot_digest ? "already present":"absent, generating..");
|
||||
|
||||
if (!has_secure_boot_digest) {
|
||||
image_sig_public_key_digests_t boot_key_digests = {0};
|
||||
image_sig_public_key_digests_t app_key_digests = {0};
|
||||
esp_image_sig_public_key_digests_t boot_key_digests = {0};
|
||||
esp_image_sig_public_key_digests_t app_key_digests = {0};
|
||||
|
||||
/* Generate the bootloader public key digests */
|
||||
ret = s_calculate_image_public_key_digests(bootloader_data.start_addr, bootloader_data.image_len - SIG_BLOCK_PADDING, &boot_key_digests);
|
||||
@@ -234,7 +215,7 @@ static esp_err_t check_and_generate_secure_boot_keys(const esp_image_metadata_t
|
||||
}
|
||||
|
||||
for (int j = 0; j < app_key_digests.num_digests; j++) {
|
||||
if (!memcmp(boot_key_digests.key_digests[i], app_key_digests.key_digests[j], DIGEST_LEN)) {
|
||||
if (!memcmp(boot_key_digests.key_digests[i], app_key_digests.key_digests[j], ESP_SECURE_BOOT_DIGEST_LEN)) {
|
||||
ESP_LOGI(TAG, "Application key(%d) matches with bootloader key(%d).", j, i);
|
||||
match = true;
|
||||
}
|
||||
|
||||
@@ -1,93 +0,0 @@
|
||||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <string.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_fault.h"
|
||||
#include "bootloader_flash_priv.h"
|
||||
#include "bootloader_sha.h"
|
||||
#include "bootloader_utility.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_image_format.h"
|
||||
#include "esp_secure_boot.h"
|
||||
#include "esp32s3/rom/secure_boot.h"
|
||||
|
||||
static const char* TAG = "secure_boot";
|
||||
|
||||
#define DIGEST_LEN 32
|
||||
#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];
|
||||
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);
|
||||
|
||||
/* 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, length + sizeof(struct ets_secure_boot_sig_block));
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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 = (const ets_secure_boot_signature_t *)(data + length);
|
||||
int r = esp_secure_boot_verify_rsa_signature_block(sig, digest, verified_digest);
|
||||
bootloader_munmap(data);
|
||||
|
||||
return (r == ETS_OK) ? ESP_OK : ESP_FAIL;
|
||||
}
|
||||
|
||||
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;
|
||||
ets_secure_boot_key_digests_t trusted_key_copies[2];
|
||||
ETS_STATUS r;
|
||||
ets_secure_boot_status_t sb_result;
|
||||
|
||||
memset(&trusted_keys, 0, sizeof(ets_secure_boot_key_digests_t));
|
||||
memset(trusted_key_copies, 0, 2 * sizeof(ets_secure_boot_key_digests_t));
|
||||
|
||||
if (!esp_secure_boot_enabled()) {
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
r = ets_secure_boot_read_key_digests(&trusted_keys);
|
||||
if (r != ETS_OK) {
|
||||
ESP_LOGI(TAG, "Could not read secure boot digests!");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
// Create the copies for FI checks (assuming result is ETS_OK, if it's not then it'll fail the fault check anyhow)
|
||||
ets_secure_boot_read_key_digests(&trusted_key_copies[0]);
|
||||
ets_secure_boot_read_key_digests(&trusted_key_copies[1]);
|
||||
ESP_FAULT_ASSERT(memcmp(&trusted_keys, &trusted_key_copies[0], sizeof(ets_secure_boot_key_digests_t)) == 0);
|
||||
ESP_FAULT_ASSERT(memcmp(&trusted_keys, &trusted_key_copies[1], sizeof(ets_secure_boot_key_digests_t)) == 0);
|
||||
|
||||
ESP_LOGI(TAG, "Verifying with RSA-PSS boot...");
|
||||
sb_result = ets_secure_boot_verify_signature(sig_block, image_digest, &trusted_keys, verified_digest);
|
||||
return (sb_result == SB_SUCCESS) ? ESP_OK : ESP_FAIL;
|
||||
}
|
||||
@@ -361,6 +361,45 @@ esp_err_t esp_image_verify(esp_image_load_mode_t mode, const esp_partition_pos_t
|
||||
return image_load(mode, part, data);
|
||||
}
|
||||
|
||||
esp_err_t esp_image_get_metadata(const esp_partition_pos_t *part, esp_image_metadata_t *metadata)
|
||||
{
|
||||
if (metadata == NULL || part == NULL || part->size > SIXTEEN_MB) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
memset(metadata, 0, sizeof(esp_image_metadata_t));
|
||||
metadata->start_addr = part->offset;
|
||||
|
||||
esp_err_t err = bootloader_flash_read(metadata->start_addr, &metadata->image, sizeof(esp_image_header_t), true);
|
||||
if (err != ESP_OK) {
|
||||
return err;
|
||||
}
|
||||
uint32_t next_addr = metadata->start_addr + sizeof(esp_image_header_t);
|
||||
for (int i = 0; i < metadata->image.segment_count; i++) {
|
||||
esp_image_segment_header_t *header = &metadata->segments[i];
|
||||
err = process_segment(i, next_addr, header, true, false, NULL, NULL);
|
||||
if (err != ESP_OK) {
|
||||
return err;
|
||||
}
|
||||
next_addr += sizeof(esp_image_segment_header_t);
|
||||
metadata->segment_data[i] = next_addr;
|
||||
next_addr += header->data_len;
|
||||
}
|
||||
metadata->image_len = next_addr - metadata->start_addr;
|
||||
|
||||
// checksum
|
||||
uint32_t unpadded_length = metadata->image_len;
|
||||
uint32_t length = unpadded_length + 1; // Add a byte for the checksum
|
||||
length = (length + 15) & ~15; // Pad to next full 16 byte block
|
||||
if (metadata->image.hash_appended) {
|
||||
// Account for the hash in the total image length
|
||||
length += HASH_LEN;
|
||||
}
|
||||
metadata->image_len = length;
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t verify_image_header(uint32_t src_addr, const esp_image_header_t *image, bool silent)
|
||||
{
|
||||
esp_err_t err = ESP_OK;
|
||||
@@ -821,18 +860,18 @@ static esp_err_t verify_secure_boot_signature(bootloader_sha256_handle_t sha_han
|
||||
|
||||
// Use hash to verify signature block
|
||||
esp_err_t err = ESP_ERR_IMAGE_INVALID;
|
||||
#if defined(CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME) || defined(CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME)
|
||||
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 */
|
||||
#ifdef CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME
|
||||
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 */
|
||||
#else
|
||||
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);
|
||||
#endif // CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME or CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Secure boot signature verification failed");
|
||||
|
||||
|
||||
@@ -1,339 +0,0 @@
|
||||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#include "bootloader_flash_priv.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>
|
||||
#include "esp_secure_boot.h"
|
||||
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32S2
|
||||
#include <esp32s2/rom/secure_boot.h>
|
||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||
#include <esp32c3/rom/secure_boot.h>
|
||||
#endif
|
||||
|
||||
#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
|
||||
|
||||
esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length)
|
||||
{
|
||||
uint8_t digest[DIGEST_LEN];
|
||||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// Map the signature block and verify the signature
|
||||
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_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");
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
#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);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
if (sig_block->version != 0) {
|
||||
ESP_LOGE(TAG, "image has invalid signature version field 0x%08x", sig_block->version);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG, "Verifying secure boot signature");
|
||||
|
||||
int ret;
|
||||
mbedtls_mpi r, s;
|
||||
|
||||
mbedtls_mpi_init(&r);
|
||||
mbedtls_mpi_init(&s);
|
||||
|
||||
/* Extract r and s components from RAW ECDSA signature of 64 bytes */
|
||||
#define ECDSA_INTEGER_LEN 32
|
||||
ret = mbedtls_mpi_read_binary(&r, &sig_block->signature[0], ECDSA_INTEGER_LEN);
|
||||
if (ret != 0) {
|
||||
ESP_LOGE(TAG, "Failed mbedtls_mpi_read_binary(1), err:%d", ret);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
ret = mbedtls_mpi_read_binary(&s, &sig_block->signature[ECDSA_INTEGER_LEN], ECDSA_INTEGER_LEN);
|
||||
if (ret != 0) {
|
||||
ESP_LOGE(TAG, "Failed mbedtls_mpi_read_binary(2), err:%d", ret);
|
||||
mbedtls_mpi_free(&r);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
/* Initialise ECDSA context */
|
||||
mbedtls_ecdsa_context ecdsa_context;
|
||||
mbedtls_ecdsa_init(&ecdsa_context);
|
||||
|
||||
mbedtls_ecp_group_load(&ecdsa_context.grp, MBEDTLS_ECP_DP_SECP256R1);
|
||||
size_t plen = mbedtls_mpi_size(&ecdsa_context.grp.P);
|
||||
if (keylen != 2 * plen) {
|
||||
ESP_LOGE(TAG, "Incorrect ECDSA key length %d", keylen);
|
||||
ret = ESP_FAIL;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Extract X and Y components from ECDSA public key */
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ecdsa_context.Q.X, signature_verification_key_start, plen));
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ecdsa_context.Q.Y, signature_verification_key_start + plen, plen));
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&ecdsa_context.Q.Z, 1));
|
||||
|
||||
ret = mbedtls_ecdsa_verify(&ecdsa_context.grp, image_digest, DIGEST_LEN, &ecdsa_context.Q, &r, &s);
|
||||
ESP_LOGD(TAG, "Verification result %d", ret);
|
||||
|
||||
cleanup:
|
||||
mbedtls_mpi_free(&r);
|
||||
mbedtls_mpi_free(&s);
|
||||
mbedtls_ecdsa_free(&ecdsa_context);
|
||||
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 */
|
||||
|
||||
#if SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS > 1
|
||||
inline static bool digest_matches(const void *trusted, const void *computed)
|
||||
{
|
||||
if (trusted == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 'trusted' is probably a pointer to read-only efuse registers,
|
||||
// which only support word reads. memcmp() cannot be guaranteed
|
||||
// to do word reads, so we make a local copy here (we know that
|
||||
// memcpy() will do word operations if it can).
|
||||
uint8_t __attribute__((aligned(4))) trusted_local[ETS_DIGEST_LEN];
|
||||
uint8_t __attribute__((aligned(4))) computed_local[ETS_DIGEST_LEN];
|
||||
|
||||
memcpy(trusted_local, trusted, ETS_DIGEST_LEN);
|
||||
memcpy(computed_local, computed, ETS_DIGEST_LEN);
|
||||
return memcmp(trusted_local, computed_local, ETS_DIGEST_LEN) == 0;
|
||||
}
|
||||
#endif /* SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS > 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};
|
||||
|
||||
/* 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)
|
||||
{
|
||||
uint8_t i = 0;
|
||||
#if CONFIG_SECURE_BOOT_V2_ENABLED /* Verify key against efuse block */
|
||||
uint8_t sig_block_key_digest[SECURE_BOOT_NUM_BLOCKS][DIGEST_LEN] = {0};
|
||||
|
||||
/* 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 */
|
||||
for (i = 0; i < SECURE_BOOT_NUM_BLOCKS; i++) {
|
||||
bootloader_sha256_handle_t sig_block_sha;
|
||||
sig_block_sha = bootloader_sha256_start();
|
||||
bootloader_sha256_data(sig_block_sha, &sig_block->block[i].key, sizeof(sig_block->block[i].key));
|
||||
bootloader_sha256_finish(sig_block_sha, (unsigned char *)sig_block_key_digest[i]);
|
||||
}
|
||||
|
||||
#if SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS == 1
|
||||
uint8_t efuse_trusted_digest[DIGEST_LEN] = {0};
|
||||
memcpy(efuse_trusted_digest, (uint8_t *) EFUSE_BLK2_RDATA0_REG, sizeof(efuse_trusted_digest));
|
||||
|
||||
if (memcmp(efuse_trusted_digest, sig_block_key_digest[0], 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;
|
||||
}
|
||||
}
|
||||
#elif SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS > 1
|
||||
bool match = false;
|
||||
ets_secure_boot_key_digests_t efuse_trusted_digest;
|
||||
ETS_STATUS r;
|
||||
r = ets_secure_boot_read_key_digests(&efuse_trusted_digest);
|
||||
if (r != 0) {
|
||||
ESP_LOGI(TAG, "Could not read secure boot digests!");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
#endif /* SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS */
|
||||
#endif /* CONFIG_SECURE_BOOT_V2_ENABLED */
|
||||
|
||||
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++) {
|
||||
#if SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS > 1
|
||||
for (uint8_t j = 0; j < SECURE_BOOT_NUM_BLOCKS; j++) {
|
||||
if (digest_matches(efuse_trusted_digest.key_digests[j], sig_block_key_digest[i])) {
|
||||
ESP_LOGI(TAG, "eFuse key matches(%d) matches the application key(%d).", j, i);
|
||||
match = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (match == false) {
|
||||
continue; // Skip the public keys whose digests don't match.
|
||||
}
|
||||
# endif // SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS > 1
|
||||
|
||||
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, DIGEST_LEN,
|
||||
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);
|
||||
#if SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS == 1
|
||||
return (ret != 0) ? ESP_ERR_IMAGE_INVALID: ESP_OK;
|
||||
#elif SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS > 1
|
||||
return (ret != 0 || match == false) ? ESP_ERR_IMAGE_INVALID: ESP_OK;
|
||||
#endif /* CONFIG_IDF_TARGET_ESP32 */
|
||||
}
|
||||
#endif
|
||||
57
components/bootloader_support/src/secure_boot.c
Normal file
57
components/bootloader_support/src/secure_boot.c
Normal file
@@ -0,0 +1,57 @@
|
||||
// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <strings.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_efuse.h"
|
||||
#include "esp_efuse_table.h"
|
||||
#include "esp_secure_boot.h"
|
||||
|
||||
#ifndef BOOTLOADER_BUILD
|
||||
static __attribute__((unused)) const char *TAG = "secure_boot";
|
||||
|
||||
#if CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME && CONFIG_SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT
|
||||
|
||||
static void rsa_check_signature_on_update_check(void)
|
||||
{
|
||||
// We rely on the keys used to sign this app to verify the next app on OTA, so make sure there is at
|
||||
// least one to avoid a stuck firmware
|
||||
esp_image_sig_public_key_digests_t digests = { 0 };
|
||||
|
||||
esp_err_t err = esp_secure_boot_get_signature_blocks_for_running_app(false, &digests);
|
||||
|
||||
if (err != ESP_OK || digests.num_digests == 0) {
|
||||
ESP_LOGE(TAG, "This app is not signed, but check signature on update is enabled in config. It won't be possible to verify any update.");
|
||||
abort();
|
||||
}
|
||||
#if CONFIG_SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT && SECURE_BOOT_NUM_BLOCKS > 1
|
||||
if (digests.num_digests > 1) {
|
||||
ESP_LOGW(TAG, "App has %d signatures. Only the first position of signature blocks is used to verify any update", digests.num_digests);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif // CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME && CONFIG_SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT
|
||||
|
||||
void esp_secure_boot_init_checks(void)
|
||||
{
|
||||
|
||||
|
||||
|
||||
#if CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME && CONFIG_SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT
|
||||
rsa_check_signature_on_update_check();
|
||||
#endif // CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME && CONFIG_SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT
|
||||
|
||||
}
|
||||
#endif // not BOOTLOADER_BUILD
|
||||
@@ -0,0 +1,136 @@
|
||||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#include "bootloader_flash_priv.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>
|
||||
|
||||
#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
|
||||
|
||||
esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length)
|
||||
{
|
||||
uint8_t digest[ESP_SECURE_BOOT_DIGEST_LEN];
|
||||
uint8_t verified_digest[ESP_SECURE_BOOT_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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// Map the signature block and verify the signature
|
||||
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_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");
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
#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, ESP_SECURE_BOOT_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);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
if (sig_block->version != 0) {
|
||||
ESP_LOGE(TAG, "image has invalid signature version field 0x%08x", sig_block->version);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG, "Verifying secure boot signature");
|
||||
|
||||
int ret;
|
||||
mbedtls_mpi r, s;
|
||||
|
||||
mbedtls_mpi_init(&r);
|
||||
mbedtls_mpi_init(&s);
|
||||
|
||||
/* Extract r and s components from RAW ECDSA signature of 64 bytes */
|
||||
#define ECDSA_INTEGER_LEN 32
|
||||
ret = mbedtls_mpi_read_binary(&r, &sig_block->signature[0], ECDSA_INTEGER_LEN);
|
||||
if (ret != 0) {
|
||||
ESP_LOGE(TAG, "Failed mbedtls_mpi_read_binary(1), err:%d", ret);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
ret = mbedtls_mpi_read_binary(&s, &sig_block->signature[ECDSA_INTEGER_LEN], ECDSA_INTEGER_LEN);
|
||||
if (ret != 0) {
|
||||
ESP_LOGE(TAG, "Failed mbedtls_mpi_read_binary(2), err:%d", ret);
|
||||
mbedtls_mpi_free(&r);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
/* Initialise ECDSA context */
|
||||
mbedtls_ecdsa_context ecdsa_context;
|
||||
mbedtls_ecdsa_init(&ecdsa_context);
|
||||
|
||||
mbedtls_ecp_group_load(&ecdsa_context.grp, MBEDTLS_ECP_DP_SECP256R1);
|
||||
size_t plen = mbedtls_mpi_size(&ecdsa_context.grp.P);
|
||||
if (keylen != 2 * plen) {
|
||||
ESP_LOGE(TAG, "Incorrect ECDSA key length %d", keylen);
|
||||
ret = ESP_FAIL;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* Extract X and Y components from ECDSA public key */
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ecdsa_context.Q.X, signature_verification_key_start, plen));
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ecdsa_context.Q.Y, signature_verification_key_start + plen, plen));
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&ecdsa_context.Q.Z, 1));
|
||||
|
||||
ret = mbedtls_ecdsa_verify(&ecdsa_context.grp, image_digest, ESP_SECURE_BOOT_DIGEST_LEN, &ecdsa_context.Q, &r, &s);
|
||||
ESP_LOGD(TAG, "Verification result %d", ret);
|
||||
|
||||
cleanup:
|
||||
mbedtls_mpi_free(&r);
|
||||
mbedtls_mpi_free(&s);
|
||||
mbedtls_ecdsa_free(&ecdsa_context);
|
||||
return ret == 0 ? ESP_OK : ESP_ERR_IMAGE_INVALID;
|
||||
#endif // CONFIG_MBEDTLS_ECDSA_C && CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED
|
||||
}
|
||||
#endif // CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME
|
||||
@@ -0,0 +1,100 @@
|
||||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#include "bootloader_flash_priv.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_verify_antifault.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <string.h>
|
||||
|
||||
static const char *TAG = "secure_boot";
|
||||
|
||||
#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
|
||||
|
||||
esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length)
|
||||
{
|
||||
uint8_t digest[ESP_SECURE_BOOT_DIGEST_LEN];
|
||||
uint8_t verified_digest[ESP_SECURE_BOOT_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);
|
||||
|
||||
esp_err_t err = bootloader_sha256_flash_contents(src_addr, length, digest);
|
||||
if (err != ESP_OK) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// 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) {
|
||||
ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", src_addr + length, sizeof(esp_secure_boot_sig_block_t));
|
||||
return ESP_FAIL;
|
||||
}
|
||||
// Verify the signature
|
||||
err = esp_secure_boot_verify_ecdsa_signature_block(sigblock, digest, verified_digest);
|
||||
// Unmap
|
||||
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)
|
||||
{
|
||||
uint8_t verified_digest[ESP_SECURE_BOOT_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;
|
||||
|
||||
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);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
if (sig_block->version != 0) {
|
||||
ESP_LOGE(TAG, "image has invalid signature version field 0x%08x", sig_block->version);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG, "Verifying secure boot signature");
|
||||
|
||||
bool is_valid;
|
||||
is_valid = uECC_verify_antifault(signature_verification_key_start,
|
||||
image_digest,
|
||||
ESP_SECURE_BOOT_DIGEST_LEN,
|
||||
sig_block->signature,
|
||||
uECC_secp256r1(),
|
||||
verified_digest);
|
||||
ESP_LOGD(TAG, "Verification result %d", is_valid);
|
||||
|
||||
return is_valid ? ESP_OK : ESP_ERR_IMAGE_INVALID;
|
||||
}
|
||||
|
||||
#endif // CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME
|
||||
@@ -0,0 +1,294 @@
|
||||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#include "bootloader_flash_priv.h"
|
||||
#include "bootloader_sha.h"
|
||||
#include "bootloader_utility.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_image_format.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>
|
||||
#include "esp_secure_boot.h"
|
||||
#include "esp_ota_ops.h"
|
||||
|
||||
// Secure boot V2 for app
|
||||
|
||||
_Static_assert(SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS == SECURE_BOOT_NUM_BLOCKS,
|
||||
"Parts of this code rely on the max number of signatures appended to an image"
|
||||
"being the same as the max number of trusted keys.");
|
||||
|
||||
#if CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME || CONFIG_SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT
|
||||
|
||||
static const char *TAG = "secure_boot_v2";
|
||||
#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
|
||||
|
||||
/* A signature block is valid when it has correct magic byte, crc. */
|
||||
static esp_err_t validate_signature_block(const ets_secure_boot_sig_block_t *block)
|
||||
{
|
||||
if (block->magic_byte != ETS_SECURE_BOOT_V2_SIGNATURE_MAGIC
|
||||
|| block->block_crc != esp_rom_crc32_le(0, (uint8_t *)block, CRC_SIGN_BLOCK_LEN)) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_secure_boot_get_signature_blocks_for_running_app(bool digest_public_keys, esp_image_sig_public_key_digests_t *public_key_digests)
|
||||
{
|
||||
esp_image_metadata_t metadata;
|
||||
const esp_partition_t* running_app_part = esp_ota_get_running_partition();
|
||||
if (running_app_part == NULL) {
|
||||
ESP_LOGE(TAG, "Cannot get running partition");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
const esp_partition_pos_t part_pos = {
|
||||
.offset = running_app_part->address,
|
||||
.size = running_app_part->size,
|
||||
};
|
||||
esp_err_t err = esp_image_get_metadata(&part_pos, &metadata);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Error reading metadata from running app (err=0x%x)", err);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
memset(public_key_digests, 0, sizeof(esp_image_sig_public_key_digests_t));
|
||||
|
||||
// Generating the SHA of the public key components in the signature block
|
||||
|
||||
// metadata.image_len doesn't include any padding to start of the signature sector, so pad it here
|
||||
size_t sig_block_addr = metadata.start_addr + ALIGN_UP(metadata.image_len, FLASH_SECTOR_SIZE);
|
||||
ESP_LOGD(TAG, "reading signatures for app address 0x%x sig block address 0x%x", part_pos.offset, sig_block_addr);
|
||||
for (unsigned i = 0; i < SECURE_BOOT_NUM_BLOCKS; i++) {
|
||||
ets_secure_boot_sig_block_t block;
|
||||
size_t addr = sig_block_addr + sizeof(ets_secure_boot_sig_block_t) * i;
|
||||
esp_err_t err = bootloader_flash_read(addr, &block, sizeof(ets_secure_boot_sig_block_t), true);
|
||||
if (err == ESP_OK) {
|
||||
if (validate_signature_block(&block) == ESP_OK) {
|
||||
if (digest_public_keys) {
|
||||
bootloader_sha256_handle_t sig_block_sha = bootloader_sha256_start();
|
||||
bootloader_sha256_data(sig_block_sha, &block.key, sizeof(block.key));
|
||||
bootloader_sha256_finish(sig_block_sha, public_key_digests->key_digests[i]);
|
||||
}
|
||||
public_key_digests->num_digests++;
|
||||
}
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Secure boot sign blocks cannot be read from a running app (err=0x%x)", err);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
}
|
||||
if (public_key_digests->num_digests > 0) {
|
||||
return ESP_OK;
|
||||
}
|
||||
ESP_LOGE(TAG, "No signatures were found for the running app");
|
||||
return ESP_ERR_NOT_FOUND;
|
||||
}
|
||||
|
||||
static esp_err_t get_secure_boot_key_digests(esp_image_sig_public_key_digests_t *public_key_digests)
|
||||
{
|
||||
#ifdef CONFIG_SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT
|
||||
// Gets key digests from running app
|
||||
ESP_LOGI(TAG, "Take trusted digest key(s) from running app");
|
||||
return esp_secure_boot_get_signature_blocks_for_running_app(true, public_key_digests);
|
||||
#elif CONFIG_SECURE_BOOT_V2_ENABLED
|
||||
ESP_LOGI(TAG, "Take trusted digest key(s) from eFuse block(s)");
|
||||
#if SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS > 1
|
||||
// Read key digests from efuse
|
||||
ets_secure_boot_key_digests_t efuse_trusted;
|
||||
if (ets_secure_boot_read_key_digests(&efuse_trusted) == ETS_OK) {
|
||||
for (unsigned i = 0; i < SECURE_BOOT_NUM_BLOCKS; i++) {
|
||||
if (efuse_trusted.key_digests[i] != NULL) {
|
||||
memcpy(public_key_digests->key_digests[i], (uint8_t *)efuse_trusted.key_digests[i], ESP_SECURE_BOOT_DIGEST_LEN);
|
||||
public_key_digests->num_digests++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (public_key_digests->num_digests > 0) {
|
||||
return ESP_OK;
|
||||
}
|
||||
return ESP_ERR_NOT_FOUND;
|
||||
#else
|
||||
memcpy(public_key_digests->key_digests[0], (uint8_t *)EFUSE_BLK2_RDATA0_REG, ESP_SECURE_BOOT_DIGEST_LEN);
|
||||
public_key_digests->num_digests = 1;
|
||||
return ESP_OK;
|
||||
#endif // SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS
|
||||
#endif // CONFIG_SECURE_BOOT_V2_ENABLED
|
||||
}
|
||||
|
||||
esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length)
|
||||
{
|
||||
uint8_t digest[ESP_SECURE_BOOT_DIGEST_LEN] = {0};
|
||||
uint8_t verified_digest[ESP_SECURE_BOOT_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;
|
||||
}
|
||||
|
||||
// This verify function is called only from app, during ota update.
|
||||
// This function is compiled in case when CONFIG_SECURE_BOOT_V2_ENABLED==y or CONFIG_SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT==y.
|
||||
// if CONFIG_SECURE_BOOT_V2_ENABLED==y and key digests from eFuse are missing, then FAIL (eFuse blocks should be set).
|
||||
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)
|
||||
{
|
||||
bool any_trusted_key = false;
|
||||
|
||||
/* 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, ESP_SECURE_BOOT_DIGEST_LEN);
|
||||
|
||||
esp_image_sig_public_key_digests_t trusted = {0};
|
||||
|
||||
if (get_secure_boot_key_digests(&trusted) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Could not read secure boot digests!");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
|
||||
int ret = 0;
|
||||
mbedtls_rsa_context pk;
|
||||
mbedtls_entropy_context entropy;
|
||||
mbedtls_ctr_drbg_context ctr_drbg;
|
||||
const unsigned rsa_key_size = sizeof(sig_block->block[0].signature);
|
||||
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;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT
|
||||
const unsigned secure_boot_num_blocks = 1;
|
||||
#else
|
||||
const unsigned secure_boot_num_blocks = SECURE_BOOT_NUM_BLOCKS;
|
||||
#endif
|
||||
|
||||
for (unsigned app_blk_idx = 0; app_blk_idx < secure_boot_num_blocks; app_blk_idx++) {
|
||||
uint8_t app_blk_digest[ESP_SECURE_BOOT_DIGEST_LEN] = { 0 };
|
||||
const ets_secure_boot_sig_block_t *app_blk = &sig_block->block[app_blk_idx];
|
||||
const ets_secure_boot_sig_block_t *trusted_block = NULL;
|
||||
|
||||
if (validate_signature_block(app_blk) != ESP_OK) {
|
||||
continue; // Skip invalid signature blocks
|
||||
}
|
||||
|
||||
/* Generate the SHA of the public key components in the signature block */
|
||||
bootloader_sha256_handle_t sig_block_sha = bootloader_sha256_start();
|
||||
bootloader_sha256_data(sig_block_sha, &app_blk->key, sizeof(app_blk->key));
|
||||
bootloader_sha256_finish(sig_block_sha, app_blk_digest);
|
||||
|
||||
/* Check if the key is one we trust */
|
||||
for (unsigned trusted_key_idx = 0; trusted_key_idx < secure_boot_num_blocks; trusted_key_idx++) {
|
||||
if (memcmp(app_blk_digest, trusted.key_digests[trusted_key_idx], ESP_SECURE_BOOT_DIGEST_LEN) == 0) {
|
||||
ESP_LOGI(TAG, "#%d app key digest == #%d trusted key digest", app_blk_idx, trusted_key_idx);
|
||||
trusted_block = app_blk;
|
||||
any_trusted_key = true;
|
||||
break;
|
||||
}
|
||||
ESP_LOGV(TAG, "not trusting app sig %d trust idx %d", app_blk_idx, trusted_key_idx);
|
||||
}
|
||||
|
||||
if (trusted_block == NULL) {
|
||||
continue; // Skip the signature blocks with no trusted digest
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Verifying with RSA-PSS...");
|
||||
|
||||
const mbedtls_mpi N = { .s = 1,
|
||||
.n = sizeof(trusted_block->key.n)/sizeof(mbedtls_mpi_uint),
|
||||
.p = (void *)trusted_block->key.n,
|
||||
};
|
||||
const mbedtls_mpi e = { .s = 1,
|
||||
.n = sizeof(trusted_block->key.e)/sizeof(mbedtls_mpi_uint), // 1
|
||||
.p = (void *)&trusted_block->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] = trusted_block->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, ESP_SECURE_BOOT_DIGEST_LEN,
|
||||
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 != 0 || any_trusted_key == false) ? ESP_ERR_IMAGE_INVALID: ESP_OK;
|
||||
}
|
||||
#endif // CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME || CONFIG_SECURE_SIGNED_ON_UPDATE_NO_SECURE_BOOT
|
||||
@@ -0,0 +1,172 @@
|
||||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#include <string.h>
|
||||
#include "esp_fault.h"
|
||||
#include "bootloader_flash_priv.h"
|
||||
#include "bootloader_sha.h"
|
||||
#include "bootloader_utility.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_image_format.h"
|
||||
#include "esp_secure_boot.h"
|
||||
|
||||
// Secure boot V2 for bootloader.
|
||||
|
||||
#if CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME && CONFIG_SECURE_BOOT_V2_ENABLED
|
||||
|
||||
static const char* TAG = "secure_boot_v2";
|
||||
|
||||
#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[ESP_SECURE_BOOT_DIGEST_LEN] = {0};
|
||||
uint8_t verified_digest[ESP_SECURE_BOOT_DIGEST_LEN] = { 0 }; /* Note: this function doesn't do any anti-FI checks on this buffer */
|
||||
|
||||
/* 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);
|
||||
|
||||
/* 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);
|
||||
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;
|
||||
}
|
||||
|
||||
/* A signature block is valid when it has correct magic byte, crc. */
|
||||
static esp_err_t validate_signature_block(const ets_secure_boot_sig_block_t *block)
|
||||
{
|
||||
if (block->magic_byte != ETS_SECURE_BOOT_V2_SIGNATURE_MAGIC
|
||||
|| block->block_crc != esp_rom_crc32_le(0, (uint8_t *)block, CRC_SIGN_BLOCK_LEN)) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t get_secure_boot_key_digests(esp_image_sig_public_key_digests_t *public_key_digests)
|
||||
{
|
||||
#if SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS > 1
|
||||
// Read key digests from efuse
|
||||
ets_secure_boot_key_digests_t trusted_keys;
|
||||
ets_secure_boot_key_digests_t trusted_key_copies[2];
|
||||
ETS_STATUS ets_ret;
|
||||
|
||||
memset(&trusted_keys, 0, sizeof(ets_secure_boot_key_digests_t));
|
||||
memset(trusted_key_copies, 0, 2 * sizeof(ets_secure_boot_key_digests_t));
|
||||
|
||||
|
||||
ets_ret = ets_secure_boot_read_key_digests(&trusted_keys);
|
||||
|
||||
// Create the copies for FI checks (assuming result is ETS_OK, if it's not then it'll fail the fault check anyhow)
|
||||
ets_secure_boot_read_key_digests(&trusted_key_copies[0]);
|
||||
ets_secure_boot_read_key_digests(&trusted_key_copies[1]);
|
||||
ESP_FAULT_ASSERT(memcmp(&trusted_keys, &trusted_key_copies[0], sizeof(ets_secure_boot_key_digests_t)) == 0);
|
||||
ESP_FAULT_ASSERT(memcmp(&trusted_keys, &trusted_key_copies[1], sizeof(ets_secure_boot_key_digests_t)) == 0);
|
||||
|
||||
if (ets_ret == ETS_OK) {
|
||||
for (unsigned i = 0; i < SECURE_BOOT_NUM_BLOCKS; i++) {
|
||||
if (trusted_keys.key_digests[i] != NULL) {
|
||||
memcpy(public_key_digests->key_digests[i], (uint8_t *)trusted_keys.key_digests[i], ESP_SECURE_BOOT_DIGEST_LEN);
|
||||
public_key_digests->num_digests++;
|
||||
}
|
||||
}
|
||||
if (public_key_digests->num_digests > 0) {
|
||||
return ESP_OK;
|
||||
}
|
||||
}
|
||||
return ESP_ERR_NOT_FOUND;
|
||||
#else
|
||||
bool all_zeroes = true;
|
||||
uint32_t *reg = (uint32_t*)&public_key_digests->key_digests[0];
|
||||
for (int i = 0; i < ESP_SECURE_BOOT_DIGEST_LEN / 4; i++) {
|
||||
*(reg + i) = REG_READ(EFUSE_BLK2_RDATA0_REG + i * 4);
|
||||
all_zeroes = all_zeroes && (*(reg + i) == 0);
|
||||
}
|
||||
if (all_zeroes) {
|
||||
return ESP_ERR_NOT_FOUND;
|
||||
}
|
||||
public_key_digests->num_digests = 1;
|
||||
return ESP_OK;
|
||||
#endif // SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS
|
||||
}
|
||||
|
||||
// if CONFIG_SECURE_BOOT_V2_ENABLED==y and key digests from eFuse are missing, then it is the first boot,
|
||||
// trusted.key_digests are filled from app sig_block.
|
||||
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)
|
||||
{
|
||||
esp_image_sig_public_key_digests_t trusted = {0};
|
||||
bool efuse_keys_are_not_set = false;
|
||||
if (get_secure_boot_key_digests(&trusted) != ESP_OK) {
|
||||
if (esp_secure_boot_enabled()) {
|
||||
ESP_LOGE(TAG, "Could not read eFuse secure boot digests!");
|
||||
return ESP_FAIL;
|
||||
} else {
|
||||
ESP_LOGI(TAG, "Secure boot V2 is not enabled yet and eFuse digest keys are not set");
|
||||
efuse_keys_are_not_set = true;
|
||||
ESP_FAULT_ASSERT(!esp_secure_boot_enabled());
|
||||
}
|
||||
}
|
||||
|
||||
if (!esp_secure_boot_enabled()) {
|
||||
// It is the first boot. eFuse secure boot bit is not set yet. eFuse block(s) can be written or not.
|
||||
// Generating the SHA of the public key components in the signature block
|
||||
for (unsigned i = 0; i < SECURE_BOOT_NUM_BLOCKS; i++) {
|
||||
if (validate_signature_block(&sig_block->block[i]) == ESP_OK) {
|
||||
if (efuse_keys_are_not_set) {
|
||||
// if efuse key digests are not in eFuse yet due to it is the first boot
|
||||
// then use digests from app to skip error in ets_secure_boot_verify_signature().
|
||||
bootloader_sha256_handle_t sig_block_sha = bootloader_sha256_start();
|
||||
bootloader_sha256_data(sig_block_sha, &sig_block->block[i].key, sizeof(sig_block->block[i].key));
|
||||
bootloader_sha256_finish(sig_block_sha, trusted.key_digests[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
ESP_FAULT_ASSERT(!esp_secure_boot_enabled());
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Verifying with RSA-PSS...");
|
||||
#if SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS == 1
|
||||
int sb_result = ets_secure_boot_verify_signature(sig_block, image_digest, trusted.key_digests[0], verified_digest);
|
||||
#else
|
||||
ets_secure_boot_key_digests_t trusted_key_digests;
|
||||
for (unsigned i = 0; i < SECURE_BOOT_NUM_BLOCKS; i++) {
|
||||
trusted_key_digests.key_digests[i] = &trusted.key_digests[i];
|
||||
}
|
||||
int sb_result = ets_secure_boot_verify_signature(sig_block, image_digest, &trusted_key_digests, verified_digest);
|
||||
#endif
|
||||
if (sb_result != SB_SUCCESS) {
|
||||
ESP_LOGE(TAG, "Secure Boot V2 verification failed.");
|
||||
return ESP_ERR_IMAGE_INVALID;
|
||||
} else {
|
||||
ESP_LOGI(TAG, "Signature verified successfully!");
|
||||
return ESP_OK;
|
||||
}
|
||||
}
|
||||
#endif // CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME && CONFIG_SECURE_BOOT_V2_ENABLED
|
||||
@@ -589,13 +589,15 @@ idf_component_register(SRCS "${srcs}"
|
||||
if(CONFIG_BT_ENABLED)
|
||||
target_compile_options(${COMPONENT_LIB} PRIVATE -Wno-implicit-fallthrough -Wno-unused-const-variable)
|
||||
if(CONFIG_IDF_TARGET_ESP32)
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE "-L${CMAKE_CURRENT_LIST_DIR}/controller/lib/esp32")
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE "-L${CMAKE_CURRENT_LIST_DIR}/controller/lib_esp32/esp32")
|
||||
target_link_libraries(${COMPONENT_LIB} PUBLIC btdm_app)
|
||||
elseif(CONFIG_IDF_TARGET_ESP32C3)
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE "-L${CMAKE_CURRENT_LIST_DIR}/controller/lib/esp32c3")
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE
|
||||
"-L${CMAKE_CURRENT_LIST_DIR}/controller/lib_esp32c3_family/esp32c3")
|
||||
target_link_libraries(${COMPONENT_LIB} PUBLIC btdm_app btbb)
|
||||
elseif(CONFIG_IDF_TARGET_ESP32S3)
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE "-L${CMAKE_CURRENT_LIST_DIR}/controller/lib/esp32s3")
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE
|
||||
"-L${CMAKE_CURRENT_LIST_DIR}/controller/lib_esp32c3_family/esp32s3")
|
||||
target_link_libraries(${COMPONENT_LIB} PUBLIC btdm_app btbb)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -9,13 +9,13 @@ COMPONENT_ADD_INCLUDEDIRS := include
|
||||
|
||||
LIBS := btdm_app
|
||||
|
||||
COMPONENT_ADD_LDFLAGS := -lbt -L $(COMPONENT_PATH)/controller/lib/esp32 \
|
||||
COMPONENT_ADD_LDFLAGS := -lbt -L $(COMPONENT_PATH)/controller/lib_esp32/esp32 \
|
||||
$(addprefix -l,$(LIBS))
|
||||
|
||||
# re-link program if BT binary libs change
|
||||
COMPONENT_ADD_LINKER_DEPS := $(patsubst %,$(COMPONENT_PATH)/controller/lib/esp32/lib%.a,$(LIBS))
|
||||
COMPONENT_ADD_LINKER_DEPS := $(patsubst %,$(COMPONENT_PATH)/controller/lib_esp32/esp32/lib%.a,$(LIBS))
|
||||
|
||||
COMPONENT_SUBMODULES += controller/lib
|
||||
COMPONENT_SUBMODULES += controller/lib_esp32
|
||||
|
||||
|
||||
# TODO: annotate fallthroughs in Bluedroid code with comments
|
||||
|
||||
@@ -176,6 +176,14 @@ struct osi_funcs_t {
|
||||
int (* _coex_register_bt_cb)(coex_func_cb_t cb);
|
||||
uint32_t (* _coex_bb_reset_lock)(void);
|
||||
void (* _coex_bb_reset_unlock)(uint32_t restore);
|
||||
int (* _coex_schm_register_btdm_callback)(void *callback);
|
||||
void (* _coex_schm_status_bit_clear)(uint32_t type, uint32_t status);
|
||||
void (* _coex_schm_status_bit_set)(uint32_t type, uint32_t status);
|
||||
uint32_t (* _coex_schm_interval_get)(void);
|
||||
uint8_t (* _coex_schm_curr_period_get)(void);
|
||||
void *(* _coex_schm_curr_phase_get)(void);
|
||||
int (* _coex_wifi_channel_get)(uint8_t *primary, uint8_t *secondary);
|
||||
int (* _coex_register_wifi_channel_change_callback)(void *cb);
|
||||
uint32_t _magic;
|
||||
};
|
||||
|
||||
@@ -224,6 +232,14 @@ extern int coex_bt_release(uint32_t event);
|
||||
extern int coex_register_bt_cb(coex_func_cb_t cb);
|
||||
extern uint32_t coex_bb_reset_lock(void);
|
||||
extern void coex_bb_reset_unlock(uint32_t restore);
|
||||
extern int coex_schm_register_btdm_callback(void *callback);
|
||||
extern void coex_schm_status_bit_clear(uint32_t type, uint32_t status);
|
||||
extern void coex_schm_status_bit_set(uint32_t type, uint32_t status);
|
||||
extern uint32_t coex_schm_interval_get(void);
|
||||
extern uint8_t coex_schm_curr_period_get(void);
|
||||
extern void * coex_schm_curr_phase_get(void);
|
||||
extern int coex_wifi_channel_get(uint8_t *primary, uint8_t *secondary);
|
||||
extern int coex_register_wifi_channel_change_callback(void *cb);
|
||||
extern void coex_ble_adv_priority_high_set(bool high);
|
||||
|
||||
extern char _bss_start_btdm;
|
||||
@@ -294,7 +310,14 @@ static int coex_bt_release_wrapper(uint32_t event);
|
||||
static int coex_register_bt_cb_wrapper(coex_func_cb_t cb);
|
||||
static uint32_t coex_bb_reset_lock_wrapper(void);
|
||||
static void coex_bb_reset_unlock_wrapper(uint32_t restore);
|
||||
|
||||
static int coex_schm_register_btdm_callback_wrapper(void *callback);
|
||||
static void coex_schm_status_bit_clear_wrapper(uint32_t type, uint32_t status);
|
||||
static void coex_schm_status_bit_set_wrapper(uint32_t type, uint32_t status);
|
||||
static uint32_t coex_schm_interval_get_wrapper(void);
|
||||
static uint8_t coex_schm_curr_period_get_wrapper(void);
|
||||
static void * coex_schm_curr_phase_get_wrapper(void);
|
||||
static int coex_wifi_channel_get_wrapper(uint8_t *primary, uint8_t *secondary);
|
||||
static int coex_register_wifi_channel_change_callback_wrapper(void *cb);
|
||||
/* Local variable definition
|
||||
***************************************************************************
|
||||
*/
|
||||
@@ -348,6 +371,14 @@ static const struct osi_funcs_t osi_funcs_ro = {
|
||||
._coex_register_bt_cb = coex_register_bt_cb_wrapper,
|
||||
._coex_bb_reset_lock = coex_bb_reset_lock_wrapper,
|
||||
._coex_bb_reset_unlock = coex_bb_reset_unlock_wrapper,
|
||||
._coex_schm_register_btdm_callback = coex_schm_register_btdm_callback_wrapper,
|
||||
._coex_schm_status_bit_clear = coex_schm_status_bit_clear_wrapper,
|
||||
._coex_schm_status_bit_set = coex_schm_status_bit_set_wrapper,
|
||||
._coex_schm_interval_get = coex_schm_interval_get_wrapper,
|
||||
._coex_schm_curr_period_get = coex_schm_curr_period_get_wrapper,
|
||||
._coex_schm_curr_phase_get = coex_schm_curr_phase_get_wrapper,
|
||||
._coex_wifi_channel_get = coex_wifi_channel_get_wrapper,
|
||||
._coex_register_wifi_channel_change_callback = coex_register_wifi_channel_change_callback_wrapper,
|
||||
._magic = OSI_MAGIC_VALUE,
|
||||
};
|
||||
|
||||
@@ -1001,7 +1032,7 @@ static void coex_bt_wakeup_request_end(void)
|
||||
return;
|
||||
}
|
||||
|
||||
int IRAM_ATTR coex_bt_request_wrapper(uint32_t event, uint32_t latency, uint32_t duration)
|
||||
static int IRAM_ATTR coex_bt_request_wrapper(uint32_t event, uint32_t latency, uint32_t duration)
|
||||
{
|
||||
#if CONFIG_SW_COEXIST_ENABLE
|
||||
return coex_bt_request(event, latency, duration);
|
||||
@@ -1010,7 +1041,7 @@ int IRAM_ATTR coex_bt_request_wrapper(uint32_t event, uint32_t latency, uint32_t
|
||||
#endif
|
||||
}
|
||||
|
||||
int IRAM_ATTR coex_bt_release_wrapper(uint32_t event)
|
||||
static int IRAM_ATTR coex_bt_release_wrapper(uint32_t event)
|
||||
{
|
||||
#if CONFIG_SW_COEXIST_ENABLE
|
||||
return coex_bt_release(event);
|
||||
@@ -1019,7 +1050,7 @@ int IRAM_ATTR coex_bt_release_wrapper(uint32_t event)
|
||||
#endif
|
||||
}
|
||||
|
||||
int coex_register_bt_cb_wrapper(coex_func_cb_t cb)
|
||||
static int coex_register_bt_cb_wrapper(coex_func_cb_t cb)
|
||||
{
|
||||
#if CONFIG_SW_COEXIST_ENABLE
|
||||
return coex_register_bt_cb(cb);
|
||||
@@ -1028,7 +1059,7 @@ int coex_register_bt_cb_wrapper(coex_func_cb_t cb)
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32_t IRAM_ATTR coex_bb_reset_lock_wrapper(void)
|
||||
static uint32_t IRAM_ATTR coex_bb_reset_lock_wrapper(void)
|
||||
{
|
||||
#if CONFIG_SW_COEXIST_ENABLE
|
||||
return coex_bb_reset_lock();
|
||||
@@ -1037,13 +1068,81 @@ uint32_t IRAM_ATTR coex_bb_reset_lock_wrapper(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
void IRAM_ATTR coex_bb_reset_unlock_wrapper(uint32_t restore)
|
||||
static void IRAM_ATTR coex_bb_reset_unlock_wrapper(uint32_t restore)
|
||||
{
|
||||
#if CONFIG_SW_COEXIST_ENABLE
|
||||
coex_bb_reset_unlock(restore);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int coex_schm_register_btdm_callback_wrapper(void *callback)
|
||||
{
|
||||
#if CONFIG_SW_COEXIST_ENABLE
|
||||
return coex_schm_register_btdm_callback(callback);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void coex_schm_status_bit_clear_wrapper(uint32_t type, uint32_t status)
|
||||
{
|
||||
#if CONFIG_SW_COEXIST_ENABLE
|
||||
coex_schm_status_bit_clear(type, status);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void coex_schm_status_bit_set_wrapper(uint32_t type, uint32_t status)
|
||||
{
|
||||
#if CONFIG_SW_COEXIST_ENABLE
|
||||
coex_schm_status_bit_set(type, status);
|
||||
#endif
|
||||
}
|
||||
|
||||
static uint32_t coex_schm_interval_get_wrapper(void)
|
||||
{
|
||||
#if CONFIG_SW_COEXIST_ENABLE
|
||||
return coex_schm_interval_get();
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static uint8_t coex_schm_curr_period_get_wrapper(void)
|
||||
{
|
||||
#if CONFIG_SW_COEXIST_ENABLE
|
||||
return coex_schm_curr_period_get();
|
||||
#else
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void * coex_schm_curr_phase_get_wrapper(void)
|
||||
{
|
||||
#if CONFIG_SW_COEXIST_ENABLE
|
||||
return coex_schm_curr_phase_get();
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int coex_wifi_channel_get_wrapper(uint8_t *primary, uint8_t *secondary)
|
||||
{
|
||||
#if CONFIG_SW_COEXIST_ENABLE
|
||||
return coex_wifi_channel_get(primary, secondary);
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int coex_register_wifi_channel_change_callback_wrapper(void *cb)
|
||||
{
|
||||
#if CONFIG_SW_COEXIST_ENABLE
|
||||
return coex_register_wifi_channel_change_callback(cb);
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool esp_vhci_host_check_send_available(void)
|
||||
{
|
||||
return API_vhci_host_check_send_available();
|
||||
|
||||
@@ -7,7 +7,8 @@ config BT_CTRL_BLE_MAX_ACT
|
||||
default 10
|
||||
range 1 10
|
||||
help
|
||||
BLE maximum instances of bluetooth controller.
|
||||
BLE maximum activities of bluetooth controller,both of connections,
|
||||
scan , sync and adv(periodic adv, multi-adv).
|
||||
|
||||
config BT_CTRL_BLE_MAX_ACT_EFF
|
||||
int
|
||||
@@ -126,10 +127,20 @@ config BT_CTRL_RX_ANTENNA_INDEX_EFF
|
||||
|
||||
choice BT_CTRL_DFT_TX_POWER_LEVEL
|
||||
prompt "BLE default Tx power level"
|
||||
default BT_CTRL_DFT_TX_POWER_LEVEL_P9
|
||||
default BT_CTRL_DFT_TX_POWER_LEVEL_P3
|
||||
help
|
||||
Specify default Tx power level
|
||||
|
||||
config BT_CTRL_DFT_TX_POWER_LEVEL_N27
|
||||
bool "-27dBm"
|
||||
config BT_CTRL_DFT_TX_POWER_LEVEL_N24
|
||||
bool "-24dBm"
|
||||
config BT_CTRL_DFT_TX_POWER_LEVEL_N21
|
||||
bool "-21dBm"
|
||||
config BT_CTRL_DFT_TX_POWER_LEVEL_N18
|
||||
bool "-18dBm"
|
||||
config BT_CTRL_DFT_TX_POWER_LEVEL_N15
|
||||
bool "-15dBm"
|
||||
config BT_CTRL_DFT_TX_POWER_LEVEL_N12
|
||||
bool "-12dBm"
|
||||
config BT_CTRL_DFT_TX_POWER_LEVEL_N9
|
||||
@@ -146,18 +157,32 @@ choice BT_CTRL_DFT_TX_POWER_LEVEL
|
||||
bool "+6dBm"
|
||||
config BT_CTRL_DFT_TX_POWER_LEVEL_P9
|
||||
bool "+9dBm"
|
||||
config BT_CTRL_DFT_TX_POWER_LEVEL_P12
|
||||
bool "+12dBm"
|
||||
config BT_CTRL_DFT_TX_POWER_LEVEL_P15
|
||||
bool "+15dBm"
|
||||
config BT_CTRL_DFT_TX_POWER_LEVEL_P18
|
||||
bool "+18dBm"
|
||||
endchoice
|
||||
|
||||
config BT_CTRL_DFT_TX_POWER_LEVEL_EFF
|
||||
int
|
||||
default 0 if BT_CTRL_DFT_TX_POWER_LEVEL_N12
|
||||
default 1 if BT_CTRL_DFT_TX_POWER_LEVEL_N9
|
||||
default 2 if BT_CTRL_DFT_TX_POWER_LEVEL_N6
|
||||
default 3 if BT_CTRL_DFT_TX_POWER_LEVEL_N3
|
||||
default 4 if BT_CTRL_DFT_TX_POWER_LEVEL_N0
|
||||
default 5 if BT_CTRL_DFT_TX_POWER_LEVEL_P3
|
||||
default 6 if BT_CTRL_DFT_TX_POWER_LEVEL_P6
|
||||
default 7 if BT_CTRL_DFT_TX_POWER_LEVEL_P9
|
||||
default 0 if BT_CTRL_DFT_TX_POWER_LEVEL_N27
|
||||
default 1 if BT_CTRL_DFT_TX_POWER_LEVEL_N24
|
||||
default 2 if BT_CTRL_DFT_TX_POWER_LEVEL_N21
|
||||
default 3 if BT_CTRL_DFT_TX_POWER_LEVEL_N18
|
||||
default 4 if BT_CTRL_DFT_TX_POWER_LEVEL_N15
|
||||
default 5 if BT_CTRL_DFT_TX_POWER_LEVEL_N12
|
||||
default 6 if BT_CTRL_DFT_TX_POWER_LEVEL_N9
|
||||
default 7 if BT_CTRL_DFT_TX_POWER_LEVEL_N6
|
||||
default 8 if BT_CTRL_DFT_TX_POWER_LEVEL_N3
|
||||
default 9 if BT_CTRL_DFT_TX_POWER_LEVEL_N0
|
||||
default 10 if BT_CTRL_DFT_TX_POWER_LEVEL_P3
|
||||
default 11 if BT_CTRL_DFT_TX_POWER_LEVEL_P6
|
||||
default 12 if BT_CTRL_DFT_TX_POWER_LEVEL_P9
|
||||
default 13 if BT_CTRL_DFT_TX_POWER_LEVEL_P12
|
||||
default 14 if BT_CTRL_DFT_TX_POWER_LEVEL_P15
|
||||
default 15 if BT_CTRL_DFT_TX_POWER_LEVEL_P18
|
||||
default 0
|
||||
|
||||
config BT_CTRL_BLE_ADV_REPORT_FLOW_CTRL_SUPP
|
||||
|
||||
@@ -212,6 +212,7 @@ extern void btdm_controller_disable(void);
|
||||
extern uint8_t btdm_controller_get_mode(void);
|
||||
extern const char *btdm_controller_get_compile_version(void);
|
||||
extern void btdm_rf_bb_init_phase2(void); // shall be called after PHY/RF is enabled
|
||||
|
||||
/* Sleep */
|
||||
extern void btdm_controller_enable_sleep(bool enable);
|
||||
extern uint8_t btdm_controller_get_sleep_mode(void);
|
||||
@@ -1334,14 +1335,51 @@ esp_bt_controller_status_t esp_bt_controller_get_status(void)
|
||||
/* extra functions */
|
||||
esp_err_t esp_ble_tx_power_set(esp_ble_power_type_t power_type, esp_power_level_t power_level)
|
||||
{
|
||||
ESP_LOGW(BTDM_LOG_TAG, "%s not implemented, return OK", __func__);
|
||||
return ESP_OK;
|
||||
esp_err_t stat = ESP_FAIL;
|
||||
|
||||
switch (power_type) {
|
||||
case ESP_BLE_PWR_TYPE_ADV:
|
||||
case ESP_BLE_PWR_TYPE_SCAN:
|
||||
case ESP_BLE_PWR_TYPE_DEFAULT:
|
||||
if (ble_txpwr_set(power_type, power_level) == 0) {
|
||||
stat = ESP_OK;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
stat = ESP_ERR_NOT_SUPPORTED;
|
||||
break;
|
||||
}
|
||||
|
||||
return stat;
|
||||
}
|
||||
|
||||
esp_power_level_t esp_ble_tx_power_get(esp_ble_power_type_t power_type)
|
||||
{
|
||||
ESP_LOGW(BTDM_LOG_TAG, "%s not implemented, return 0", __func__);
|
||||
return 0;
|
||||
esp_power_level_t lvl;
|
||||
|
||||
switch (power_type) {
|
||||
case ESP_BLE_PWR_TYPE_ADV:
|
||||
case ESP_BLE_PWR_TYPE_SCAN:
|
||||
lvl = (esp_power_level_t)ble_txpwr_get(power_type);
|
||||
break;
|
||||
case ESP_BLE_PWR_TYPE_CONN_HDL0:
|
||||
case ESP_BLE_PWR_TYPE_CONN_HDL1:
|
||||
case ESP_BLE_PWR_TYPE_CONN_HDL2:
|
||||
case ESP_BLE_PWR_TYPE_CONN_HDL3:
|
||||
case ESP_BLE_PWR_TYPE_CONN_HDL4:
|
||||
case ESP_BLE_PWR_TYPE_CONN_HDL5:
|
||||
case ESP_BLE_PWR_TYPE_CONN_HDL6:
|
||||
case ESP_BLE_PWR_TYPE_CONN_HDL7:
|
||||
case ESP_BLE_PWR_TYPE_CONN_HDL8:
|
||||
case ESP_BLE_PWR_TYPE_DEFAULT:
|
||||
lvl = (esp_power_level_t)ble_txpwr_get(ESP_BLE_PWR_TYPE_DEFAULT);
|
||||
break;
|
||||
default:
|
||||
lvl = ESP_PWR_LVL_INVALID;
|
||||
break;
|
||||
}
|
||||
|
||||
return lvl;
|
||||
}
|
||||
|
||||
esp_err_t esp_bt_sleep_enable (void)
|
||||
|
||||
Submodule components/bt/controller/lib deleted from 5ba6226876
1
components/bt/controller/lib_esp32
Submodule
1
components/bt/controller/lib_esp32
Submodule
Submodule components/bt/controller/lib_esp32 added at ec61ca3caa
1
components/bt/controller/lib_esp32c3_family
Submodule
1
components/bt/controller/lib_esp32c3_family
Submodule
Submodule components/bt/controller/lib_esp32c3_family added at 655bfde644
@@ -751,7 +751,18 @@ static int prov_auth(uint8_t method, uint8_t action, uint8_t size)
|
||||
uint32_t num = 0U;
|
||||
|
||||
bt_mesh_rand(&num, sizeof(num));
|
||||
num %= div[size - 1];
|
||||
|
||||
if (output == BLE_MESH_BLINK ||
|
||||
output == BLE_MESH_BEEP ||
|
||||
output == BLE_MESH_VIBRATE) {
|
||||
/** NOTE: According to the Bluetooth Mesh Profile Specification
|
||||
* Section 5.4.2.4, blink, beep and vibrate should be a random
|
||||
* integer between 0 and 10^size.
|
||||
*/
|
||||
num = (num % (div[size - 1] - 1)) + 1;
|
||||
} else {
|
||||
num %= div[size - 1];
|
||||
}
|
||||
|
||||
sys_put_be32(num, &link.auth[12]);
|
||||
(void)memset(link.auth, 0, 12);
|
||||
|
||||
@@ -1954,7 +1954,17 @@ static int prov_auth(const uint8_t idx, uint8_t method, uint8_t action, uint8_t
|
||||
uint32_t num = 0U;
|
||||
|
||||
bt_mesh_rand(&num, sizeof(num));
|
||||
num %= div[size - 1];
|
||||
|
||||
if (input == BLE_MESH_PUSH ||
|
||||
input == BLE_MESH_TWIST) {
|
||||
/** NOTE: According to the Bluetooth Mesh Profile Specification
|
||||
* Section 5.4.2.4, push and twist should be a random integer
|
||||
* between 0 and 10^size.
|
||||
*/
|
||||
num = (num % (div[size - 1] - 1)) + 1;
|
||||
} else {
|
||||
num %= div[size - 1];
|
||||
}
|
||||
|
||||
sys_put_be32(num, &link[idx].auth[12]);
|
||||
memset(link[idx].auth, 0, 12);
|
||||
@@ -2057,7 +2067,7 @@ int bt_mesh_provisioner_set_oob_input_data(const uint8_t idx, const uint8_t *val
|
||||
memset(link[idx].auth, 0, 16);
|
||||
if (num_flag) {
|
||||
/* Provisioner inputs number */
|
||||
memcpy(link[idx].auth + 12, val, sizeof(uint32_t));
|
||||
sys_memcpy_swap(link[idx].auth + 12, val, sizeof(uint32_t));
|
||||
} else {
|
||||
/* Provisioner inputs string */
|
||||
memcpy(link[idx].auth, val, link[idx].auth_size);
|
||||
@@ -2094,7 +2104,7 @@ int bt_mesh_provisioner_set_oob_output_data(const uint8_t idx, const uint8_t *nu
|
||||
if (num_flag) {
|
||||
/* Provisioner output number */
|
||||
memset(link[idx].auth, 0, 16);
|
||||
memcpy(link[idx].auth + 16 - size, num, size);
|
||||
sys_memcpy_swap(link[idx].auth + 16 - size, num, size);
|
||||
} else {
|
||||
/* Provisioner output string */
|
||||
memset(link[idx].auth, 0, 16);
|
||||
|
||||
@@ -143,6 +143,16 @@ config BT_BLE_BLUFI_ENABLE
|
||||
help
|
||||
This option can be close when the app does not require blufi function.
|
||||
|
||||
config BT_GATT_SR_PROFILES
|
||||
int "Max GATT Server Profiles"
|
||||
depends on BT_GATTS_ENABLE && BT_BLUEDROID_ENABLED
|
||||
range 1 32
|
||||
default 8
|
||||
help
|
||||
Maximum GATT Server Profiles Count
|
||||
|
||||
|
||||
|
||||
choice BT_GATTS_SEND_SERVICE_CHANGE_MODE
|
||||
prompt "GATTS Service Change Mode"
|
||||
default BT_GATTS_SEND_SERVICE_CHANGE_AUTO
|
||||
@@ -183,6 +193,14 @@ config BT_GATTC_CACHE_NVS_FLASH
|
||||
help
|
||||
This select can save gattc cache data to nvs flash
|
||||
|
||||
config BT_GATTC_CONNECT_RETRY_COUNT
|
||||
int "The number of attempts to reconnect if the connection establishment failed"
|
||||
depends on BT_GATTC_ENABLE
|
||||
range 0 7
|
||||
default 3
|
||||
help
|
||||
The number of attempts to reconnect if the connection establishment failed
|
||||
|
||||
config BT_BLE_SMP_ENABLE
|
||||
bool "Include BLE security module(SMP)"
|
||||
depends on BT_BLE_ENABLED
|
||||
@@ -945,7 +963,6 @@ menu "BT DEBUG LOG LEVEL"
|
||||
|
||||
endmenu #BT DEBUG LOG LEVEL
|
||||
|
||||
|
||||
config BT_ACL_CONNECTIONS
|
||||
int "BT/BLE MAX ACL CONNECTIONS(1~7)"
|
||||
depends on BT_BLUEDROID_ENABLED
|
||||
@@ -954,6 +971,13 @@ config BT_ACL_CONNECTIONS
|
||||
help
|
||||
Maximum BT/BLE connection count
|
||||
|
||||
config BT_MULTI_CONNECTION_ENBALE
|
||||
bool "Enable BLE multi-conections"
|
||||
depends on BT_BLUEDROID_ENABLED
|
||||
default y
|
||||
help
|
||||
Enable this option if there are multiple connections
|
||||
|
||||
config BT_ALLOCATION_FROM_SPIRAM_FIRST
|
||||
bool "BT/BLE will first malloc the memory from the PSRAM"
|
||||
depends on BT_BLUEDROID_ENABLED
|
||||
@@ -1004,10 +1028,20 @@ config BT_BLE_ESTAB_LINK_CONN_TOUT
|
||||
|
||||
config BT_BLE_RPA_SUPPORTED
|
||||
bool "Update RPA to Controller"
|
||||
depends on (BT_BLUEDROID_ENABLED && (IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S3))
|
||||
default y
|
||||
depends on BT_BLUEDROID_ENABLED
|
||||
default y if (IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S3)
|
||||
default n if IDF_TARGET_ESP32
|
||||
help
|
||||
This enables controller RPA list function.
|
||||
For ESP32, ESP32 only support network privacy mode. If this option is enabled, ESP32 will only accept
|
||||
advertising packets from peer devices that contain private address, HW will not receive the advertising
|
||||
packets contain identity address after IRK changed. If this option is disabled, address resolution will
|
||||
be performed in the host, so the functions that require controller to resolve address in the white list
|
||||
cannot be used. This option is disabled by default on ESP32, please enable or disable this option according
|
||||
to your own needs.
|
||||
|
||||
For ESP32C3 and esp32s3, devices support network privacy mode and device privacy mode, users can switch the
|
||||
two modes according to their own needs. So this option is enabled by default.
|
||||
|
||||
config BT_BLE_50_FEATURES_SUPPORTED
|
||||
bool "Enable BLE 5.0 features"
|
||||
|
||||
@@ -301,6 +301,7 @@ typedef void (* esp_blufi_event_cb_t)(esp_blufi_cb_event_t event, esp_blufi_cb_p
|
||||
* @param len : length of data from phone
|
||||
* @param output_data : data want to send to phone
|
||||
* @param output_len : length of data want to send to phone
|
||||
* @param need_free : output reporting if memory needs to be freed or not *
|
||||
*/
|
||||
typedef void (*esp_blufi_negotiate_data_handler_t)(uint8_t *data, int len, uint8_t **output_data, int *output_len, bool *need_free);
|
||||
|
||||
@@ -311,7 +312,7 @@ typedef void (*esp_blufi_negotiate_data_handler_t)(uint8_t *data, int len, uint8
|
||||
* @param crypt_len : length of plain text
|
||||
* @return Nonnegative number is encrypted length, if error, return negative number;
|
||||
*/
|
||||
typedef int (* esp_blufi_encrypt_func_t)(uint8_t iv8, uint8_t *crypt_data, int cyprt_len);
|
||||
typedef int (* esp_blufi_encrypt_func_t)(uint8_t iv8, uint8_t *crypt_data, int crypt_len);
|
||||
|
||||
/**
|
||||
* @brief BLUFI decrypt the data after negotiate a share key
|
||||
|
||||
@@ -259,7 +259,7 @@ typedef union {
|
||||
/**
|
||||
* @brief GATT Client callback function type
|
||||
* @param event : Event type
|
||||
* @param gatts_if : GATT client access interface, normally
|
||||
* @param gattc_if : GATT client access interface, normally
|
||||
* different gattc_if correspond to different profile
|
||||
* @param param : Point to callback parameter, currently is union type
|
||||
*/
|
||||
@@ -313,7 +313,7 @@ esp_err_t esp_ble_gattc_app_unregister(esp_gatt_if_t gattc_if);
|
||||
* @param[in] gattc_if: Gatt client access interface.
|
||||
* @param[in] remote_bda: remote device bluetooth device address.
|
||||
* @param[in] remote_addr_type: remote device bluetooth device the address type.
|
||||
* @param[in] is_direct: direct connection or background auto connection
|
||||
* @param[in] is_direct: direct connection or background auto connection(by now, background auto connection is not supported).
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: success
|
||||
|
||||
@@ -188,7 +188,7 @@ typedef void (* esp_hf_incoming_data_cb_t)(const uint8_t *buf, uint32_t len);
|
||||
*
|
||||
* @param[in] len : size(in bytes) in buf
|
||||
*
|
||||
* @param[out] length of data successfully read
|
||||
* @return length of data successfully read
|
||||
*/
|
||||
typedef uint32_t (* esp_hf_outgoing_data_cb_t) (uint8_t *buf, uint32_t len);
|
||||
|
||||
|
||||
@@ -273,7 +273,7 @@ typedef void (* esp_hf_client_incoming_data_cb_t)(const uint8_t *buf, uint32_t l
|
||||
*
|
||||
* @param[in] len : size(in bytes) in buf
|
||||
*
|
||||
* @param[out] length of data successfully read
|
||||
* @return length of data successfully read
|
||||
*
|
||||
*/
|
||||
typedef uint32_t (* esp_hf_client_outgoing_data_cb_t)(uint8_t *buf, uint32_t len);
|
||||
|
||||
@@ -973,10 +973,11 @@ void bta_gattc_start_discover(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
|
||||
p_clcb->p_srcb->srvc_hdl_chg = FALSE;
|
||||
p_clcb->p_srcb->update_count = 0;
|
||||
p_clcb->p_srcb->state = BTA_GATTC_SERV_DISC_ACT;
|
||||
|
||||
#if (BT_MULTI_CONNECTION_ENBALE == FALSE)
|
||||
if (p_clcb->transport == BTA_TRANSPORT_LE) {
|
||||
L2CA_EnableUpdateBleConnParams(p_clcb->p_srcb->server_bda, FALSE);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* set all srcb related clcb into discovery ST */
|
||||
bta_gattc_set_discover_st(p_clcb->p_srcb);
|
||||
@@ -1683,8 +1684,7 @@ static void bta_gattc_conn_cback(tGATT_IF gattc_if, BD_ADDR bda, UINT16 conn_id,
|
||||
tBTA_GATTC_DATA *p_buf;
|
||||
|
||||
if (reason != 0) {
|
||||
APPL_TRACE_WARNING("%s() - cif=%d connected=%d conn_id=%d reason=0x%04x",
|
||||
__FUNCTION__, gattc_if, connected, conn_id, reason);
|
||||
APPL_TRACE_WARNING("gattc_conn_cb: if=%d st=%d id=%d rsn=0x%x", gattc_if, connected, conn_id, reason);
|
||||
}
|
||||
|
||||
bt_bdaddr_t bdaddr;
|
||||
@@ -1702,7 +1702,7 @@ static void bta_gattc_conn_cback(tGATT_IF gattc_if, BD_ADDR bda, UINT16 conn_id,
|
||||
p_buf->int_conn.conn_params.latency = p_lcb->current_used_conn_latency;
|
||||
p_buf->int_conn.conn_params.timeout = p_lcb->current_used_conn_timeout;
|
||||
} else {
|
||||
APPL_TRACE_WARNING("%s not found connection parameters of the device ", __func__);
|
||||
APPL_TRACE_WARNING("gattc_conn_cb: conn params not found");
|
||||
}
|
||||
}
|
||||
p_buf->int_conn.hdr.layer_specific = conn_id;
|
||||
|
||||
@@ -616,9 +616,11 @@ static void bta_gattc_explore_srvc(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb)
|
||||
|
||||
//server discover end, update connection parameters
|
||||
#if BLE_INCLUDED == TRUE
|
||||
#if (BT_MULTI_CONNECTION_ENBALE == FALSE)
|
||||
if (p_clcb->transport == BTA_TRANSPORT_LE) {
|
||||
L2CA_EnableUpdateBleConnParams(p_clcb->p_srcb->server_bda, TRUE);
|
||||
}
|
||||
#endif
|
||||
//discover service complete, trigger callback
|
||||
tBTA_GATTC cb_data;
|
||||
cb_data.dis_cmpl.status = p_clcb->status;
|
||||
|
||||
@@ -53,7 +53,11 @@
|
||||
/* Max HF Clients Supported From App */
|
||||
static UINT16 btc_max_hf_clients = 1;
|
||||
/* HF Param Definition */
|
||||
#if HFP_DYNAMIC_MEMORY == FALSE
|
||||
static hf_local_param_t hf_local_param[BTC_HF_NUM_CB];
|
||||
#else
|
||||
static hf_local_param_t *hf_local_param;
|
||||
#endif
|
||||
|
||||
#if (BTM_WBS_INCLUDED == TRUE)
|
||||
#ifndef BTC_HF_FEATURES
|
||||
@@ -296,7 +300,15 @@ bt_status_t btc_hf_execute_service(BOOLEAN b_enable)
|
||||
************************************************************************************/
|
||||
bt_status_t btc_hf_init(bt_bdaddr_t *bd_addr)
|
||||
{
|
||||
int idx = btc_hf_idx_by_bdaddr(bd_addr);
|
||||
int idx = 0;
|
||||
UNUSED(bd_addr);
|
||||
|
||||
#if HFP_DYNAMIC_MEMORY == TRUE
|
||||
if ((hf_local_param = (hf_local_param_t *)osi_malloc(sizeof(hf_local_param_t) * BTC_HF_NUM_CB)) == NULL) {
|
||||
return BT_STATUS_FAIL;
|
||||
}
|
||||
#endif
|
||||
|
||||
BTC_TRACE_DEBUG("%s - max_hf_clients=%d", __func__, btc_max_hf_clients);
|
||||
/* Invoke the enable service API to the core to set the appropriate service_id
|
||||
* Internally, the HSP_SERVICE_ID shall also be enabled if HFP is enabled (phone)
|
||||
@@ -322,10 +334,18 @@ bt_status_t btc_hf_init(bt_bdaddr_t *bd_addr)
|
||||
|
||||
void btc_hf_deinit(bt_bdaddr_t *bd_addr)
|
||||
{
|
||||
int idx = btc_hf_idx_by_bdaddr(bd_addr);
|
||||
UNUSED(bd_addr);
|
||||
|
||||
BTC_TRACE_EVENT("%s", __FUNCTION__);
|
||||
btc_dm_disable_service(BTA_HFP_SERVICE_ID);
|
||||
hf_local_param[idx].btc_hf_cb.initialized = false;
|
||||
#if HFP_DYNAMIC_MEMORY == TRUE
|
||||
if (hf_local_param) {
|
||||
osi_free(hf_local_param);
|
||||
hf_local_param = NULL;
|
||||
}
|
||||
#else
|
||||
hf_local_param[0].btc_hf_cb.initialized = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
static bt_status_t connect_init(bt_bdaddr_t *bd_addr, uint16_t uuid)
|
||||
@@ -917,6 +937,10 @@ void btc_hf_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src)
|
||||
|
||||
case BTC_HF_COPS_RESPONSE_EVT:
|
||||
{
|
||||
if (src->cops_rep.name == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
dst->cops_rep.name = (char *)osi_malloc(strlen(src->cops_rep.name)+1);
|
||||
if(dst->cops_rep.name) {
|
||||
memcpy(dst->cops_rep.name, src->cops_rep.name, strlen(src->cops_rep.name)+1);
|
||||
@@ -930,6 +954,10 @@ void btc_hf_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src)
|
||||
|
||||
case BTC_HF_CLCC_RESPONSE_EVT:
|
||||
{
|
||||
if (src->clcc_rep.number == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
dst->clcc_rep.number = (char *)osi_malloc(strlen(src->clcc_rep.number)+1);
|
||||
if(dst->clcc_rep.number) {
|
||||
memcpy(dst->clcc_rep.number, src->clcc_rep.number, strlen(src->clcc_rep.number)+1);
|
||||
@@ -943,6 +971,10 @@ void btc_hf_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src)
|
||||
|
||||
case BTC_HF_CNUM_RESPONSE_EVT:
|
||||
{
|
||||
if (src->cnum_rep.number == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
dst->cnum_rep.number = (char *)osi_malloc(strlen(src->cnum_rep.number)+1);
|
||||
if(dst->cnum_rep.number) {
|
||||
memcpy(dst->cnum_rep.number, src->cnum_rep.number, strlen(src->cnum_rep.number)+1);
|
||||
@@ -959,6 +991,10 @@ void btc_hf_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src)
|
||||
case BTC_HF_OUT_CALL_EVT:
|
||||
case BTC_HF_END_CALL_EVT:
|
||||
{
|
||||
if (src->phone.number == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
dst->phone.number = (char *)osi_malloc(strlen(src->phone.number)+1);
|
||||
if(dst->phone.number) {
|
||||
memcpy(dst->phone.number, src->phone.number, strlen(src->phone.number)+1);
|
||||
|
||||
@@ -206,11 +206,6 @@ typedef union
|
||||
/* APP ID definition*/
|
||||
#define BTC_HF_ID_1 0
|
||||
|
||||
#if HFP_DYNAMIC_MEMORY == TRUE
|
||||
extern hf_local_param_t *hf_local_param_ptr;
|
||||
#define hf_local_param (*hf_local_param_ptr)
|
||||
#endif
|
||||
|
||||
/* BTC-AG control block to map bdaddr to BTA handle */
|
||||
typedef struct
|
||||
{
|
||||
|
||||
@@ -134,6 +134,13 @@
|
||||
#define UC_BT_GATTC_CACHE_NVS_FLASH_ENABLED FALSE
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BT_GATTC_CONNECT_RETRY_COUNT
|
||||
#define UC_BT_GATTC_CONNECT_RETRY_COUNT CONFIG_BT_GATTC_CONNECT_RETRY_COUNT
|
||||
#else
|
||||
#define UC_BT_GATTC_CONNECT_RETRY_COUNT 0
|
||||
#endif
|
||||
|
||||
|
||||
//SMP
|
||||
#ifdef CONFIG_BT_SMP_ENABLE
|
||||
#define UC_BT_SMP_ENABLE CONFIG_BT_SMP_ENABLE
|
||||
@@ -203,6 +210,12 @@
|
||||
#define UC_BT_ACL_CONNECTIONS 5
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BT_MULTI_CONNECTION_ENBALE
|
||||
#define UC_BT_MULTI_CONNECTION_ENBALE CONFIG_BT_MULTI_CONNECTION_ENBALE
|
||||
#else
|
||||
#define UC_BT_MULTI_CONNECTION_ENBALE FALSE
|
||||
#endif
|
||||
|
||||
//BT_BLE_ESTAB_LINK_CONN_TOUT
|
||||
#ifdef CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT
|
||||
#define UC_BT_BLE_ESTAB_LINK_CONN_TOUT CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT
|
||||
@@ -224,6 +237,14 @@
|
||||
#define UC_CONFIG_BT_GATTS_PPCP_CHAR_GAP FALSE
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef CONFIG_BT_GATT_MAX_SR_PROFILES
|
||||
#define UC_CONFIG_BT_GATT_MAX_SR_PROFILES CONFIG_BT_GATT_MAX_SR_PROFILES
|
||||
#else
|
||||
#define UC_CONFIG_BT_GATT_MAX_SR_PROFILES 8
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef CONFIG_BT_GATTS_SEND_SERVICE_CHANGE_MODE
|
||||
#define UC_BT_GATTS_SEND_SERVICE_CHANGE_MODE CONFIG_BT_GATTS_SEND_SERVICE_CHANGE_MODE
|
||||
#else
|
||||
|
||||
@@ -202,6 +202,18 @@
|
||||
#define GATTC_CACHE_NVS FALSE
|
||||
#endif /* UC_BT_GATTC_ENABLE && UC_BT_GATTC_CACHE_NVS_FLASH_ENABLED */
|
||||
|
||||
#if (UC_BT_GATTC_ENABLE && UC_BT_GATTC_CONNECT_RETRY_COUNT)
|
||||
#define GATTC_CONNECT_RETRY_COUNT UC_BT_GATTC_CONNECT_RETRY_COUNT
|
||||
#else
|
||||
#define GATTC_CONNECT_RETRY_COUNT 0
|
||||
#endif /* UC_BT_GATTC_ENABLE && UC_BT_GATTC_CONNECT_RETRY_COUNT */
|
||||
|
||||
#if (GATTC_CONNECT_RETRY_COUNT > 0)
|
||||
#define GATTC_CONNECT_RETRY_EN TRUE
|
||||
#else
|
||||
#define GATTC_CONNECT_RETRY_EN FALSE
|
||||
#endif
|
||||
|
||||
#if (UC_BT_SMP_ENABLE)
|
||||
#define SMP_INCLUDED TRUE
|
||||
#if (BLE_INCLUDED == TRUE)
|
||||
@@ -237,6 +249,16 @@
|
||||
#define GATT_MAX_PHY_CHANNEL UC_BT_ACL_CONNECTIONS
|
||||
#endif /* UC_BT_ACL_CONNECTIONS */
|
||||
|
||||
#ifdef UC_BT_MULTI_CONNECTION_ENBALE
|
||||
#define BT_MULTI_CONNECTION_ENBALE UC_BT_MULTI_CONNECTION_ENBALE
|
||||
#endif
|
||||
|
||||
#if(BT_MULTI_CONNECTION_ENBALE && (CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3))
|
||||
#define BLE_CE_LEN_MIN 5
|
||||
#else
|
||||
#define BLE_CE_LEN_MIN 0
|
||||
#endif
|
||||
|
||||
#ifdef UC_BT_BLE_ESTAB_LINK_CONN_TOUT
|
||||
#define BLE_ESTABLISH_LINK_CONNECTION_TIMEOUT UC_BT_BLE_ESTAB_LINK_CONN_TOUT
|
||||
#endif
|
||||
@@ -1224,7 +1246,7 @@
|
||||
#endif
|
||||
|
||||
#ifndef GATT_MAX_SR_PROFILES
|
||||
#define GATT_MAX_SR_PROFILES 8 /* max is 32 */
|
||||
#define GATT_MAX_SR_PROFILES UC_CONFIG_BT_GATT_MAX_SR_PROFILES
|
||||
#endif
|
||||
|
||||
#ifndef GATT_MAX_APPS
|
||||
|
||||
@@ -93,6 +93,10 @@
|
||||
#include "bta_hf_client_int.h"
|
||||
#endif
|
||||
|
||||
#if BTA_AG_INCLUDED == TRUE
|
||||
#include "bta_ag_int.h"
|
||||
#endif
|
||||
|
||||
#if BTA_SDP_INCLUDED == TRUE
|
||||
#include "bta_sdp_int.h"
|
||||
#endif
|
||||
@@ -216,6 +220,12 @@ void BTE_DeinitStack(void)
|
||||
osi_free(bta_hf_client_cb_ptr);
|
||||
bta_hf_client_cb_ptr = NULL;
|
||||
}
|
||||
#endif
|
||||
#if (defined BTA_AG_INCLUDED && BTA_AG_INCLUDED == TRUE)
|
||||
if (bta_ag_cb_ptr){
|
||||
osi_free(bta_ag_cb_ptr);
|
||||
bta_ag_cb_ptr = NULL;
|
||||
}
|
||||
#endif
|
||||
if (bta_dm_conn_srvcs_ptr){
|
||||
osi_free(bta_dm_conn_srvcs_ptr);
|
||||
@@ -374,6 +384,12 @@ bt_status_t BTE_InitStack(void)
|
||||
}
|
||||
memset((void *)bta_hf_client_cb_ptr, 0, sizeof(tBTA_HF_CLIENT_CB));
|
||||
#endif
|
||||
#if (defined BTA_AG_INCLUDED && BTA_AG_INCLUDED == TRUE)
|
||||
if ((bta_ag_cb_ptr = (tBTA_AG_CB *)osi_malloc(sizeof(tBTA_AG_CB))) == NULL) {
|
||||
goto error_exit;
|
||||
}
|
||||
memset((void *)bta_ag_cb_ptr, 0, sizeof(tBTA_AG_CB));
|
||||
#endif
|
||||
#if (defined BTA_JV_INCLUDED && BTA_JV_INCLUDED == TRUE)
|
||||
if ((bta_jv_cb_ptr = (tBTA_JV_CB *)osi_malloc(sizeof(tBTA_JV_CB))) == NULL) {
|
||||
goto error_exit;
|
||||
|
||||
@@ -2076,6 +2076,30 @@ void btm_ble_create_ll_conn_complete (UINT8 status)
|
||||
btm_ble_update_mode_operation(HCI_ROLE_UNKNOWN, NULL, status);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
** Function btm_ble_create_conn_cancel_complete
|
||||
**
|
||||
** Description LE connection cancel complete.
|
||||
**
|
||||
******************************************************************************/
|
||||
void btm_ble_create_conn_cancel_complete (UINT8 *p)
|
||||
{
|
||||
UINT8 status;
|
||||
|
||||
STREAM_TO_UINT8 (status, p);
|
||||
|
||||
switch (status) {
|
||||
case HCI_SUCCESS:
|
||||
if (btm_ble_get_conn_st() == BLE_CONN_CANCEL) {
|
||||
btm_ble_set_conn_st (BLE_CONN_IDLE);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
** Function btm_proc_smp_cback
|
||||
**
|
||||
|
||||
@@ -23,9 +23,26 @@ tBTM_BLE_EXTENDED_CB extend_adv_cb;
|
||||
|
||||
tBTM_BLE_5_HCI_CBACK ble_5_hci_cb;
|
||||
|
||||
#define INVALID_VALUE 0XFF
|
||||
extern BOOLEAN BTM_GetLocalResolvablePrivateAddr(BD_ADDR bda);
|
||||
extern void BTM_UpdateAddrInfor(uint8_t addr_type, BD_ADDR bda);
|
||||
extern void BTM_BleSetStaticAddr(BD_ADDR rand_addr);
|
||||
extern uint32_t BTM_BleUpdateOwnType(uint8_t *own_bda_type, tBTM_START_ADV_CMPL_CBACK *cb);
|
||||
static tBTM_STATUS btm_ble_ext_adv_params_validate(tBTM_BLE_GAP_EXT_ADV_PARAMS *params);
|
||||
static tBTM_STATUS btm_ble_ext_adv_set_data_validate(UINT8 instance, UINT16 len, UINT8 *data);
|
||||
|
||||
typedef struct {
|
||||
uint16_t ter_con_handle;
|
||||
bool invalid;
|
||||
UINT8 instance;
|
||||
int duration;
|
||||
int max_events;
|
||||
uint8_t retry_count;
|
||||
} tBTM_EXT_ADV_RECORD;
|
||||
|
||||
tBTM_EXT_ADV_RECORD adv_record[MAX_BLE_ADV_INSTANCE] = {0};
|
||||
extern void btm_ble_inter_set(bool extble_inter);
|
||||
|
||||
static char *btm_ble_hci_status_to_str(tHCI_STATUS status)
|
||||
{
|
||||
switch(status) {
|
||||
@@ -176,6 +193,16 @@ static char *btm_ble_hci_status_to_str(tHCI_STATUS status)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void btm_ble_extendadvcb_init(void)
|
||||
{
|
||||
memset(&extend_adv_cb, 0, sizeof(tBTM_BLE_EXTENDED_CB));
|
||||
}
|
||||
|
||||
void btm_ble_advrecod_init(void)
|
||||
{
|
||||
memset(&adv_record[0], 0, sizeof(tBTM_EXT_ADV_RECORD)*MAX_BLE_ADV_INSTANCE);
|
||||
}
|
||||
|
||||
void BTM_BleGapRegisterCallback(tBTM_BLE_5_HCI_CBACK cb)
|
||||
{
|
||||
if (cb) {
|
||||
@@ -185,6 +212,15 @@ void BTM_BleGapRegisterCallback(tBTM_BLE_5_HCI_CBACK cb)
|
||||
}
|
||||
}
|
||||
|
||||
void BTM_ExtBleCallbackTrigger(tBTM_BLE_5_GAP_EVENT event, tBTM_BLE_5_GAP_CB_PARAMS *params)
|
||||
{
|
||||
if(params && params->status == BTM_SUCCESS) {
|
||||
btm_ble_inter_set(true);
|
||||
}
|
||||
if (ble_5_hci_cb) {
|
||||
ble_5_hci_cb(event, params);
|
||||
}
|
||||
}
|
||||
|
||||
tBTM_STATUS BTM_BleReadPhy(BD_ADDR bd_addr, UINT8 *tx_phy, UINT8 *rx_phy)
|
||||
{
|
||||
@@ -221,9 +257,9 @@ tBTM_STATUS BTM_BleSetPreferDefaultPhy(UINT8 tx_phy_mask, UINT8 rx_phy_mask)
|
||||
}
|
||||
|
||||
cb_params.set_perf_def_phy.status = err;
|
||||
if (ble_5_hci_cb) {
|
||||
ble_5_hci_cb(BTM_BLE_5_GAP_SET_PREFERED_DEFAULT_PHY_COMPLETE_EVT, &cb_params);
|
||||
}
|
||||
|
||||
BTM_ExtBleCallbackTrigger(BTM_BLE_5_GAP_SET_PREFERED_DEFAULT_PHY_COMPLETE_EVT, &cb_params);
|
||||
|
||||
return status;
|
||||
|
||||
}
|
||||
@@ -247,9 +283,7 @@ tBTM_STATUS BTM_BleSetPreferPhy(BD_ADDR bd_addr, UINT8 all_phys, UINT8 tx_phy_ma
|
||||
|
||||
if (!btsnd_hcic_ble_set_phy(p_lcb->handle, all_phys, tx_phy_mask, rx_phy_mask, phy_options)) {
|
||||
cb_params.status = BTM_ILLEGAL_VALUE;
|
||||
if (ble_5_hci_cb) {
|
||||
ble_5_hci_cb(BTM_BLE_5_GAP_SET_PREFERED_PHY_COMPLETE_EVT, &cb_params);
|
||||
}
|
||||
BTM_ExtBleCallbackTrigger(BTM_BLE_5_GAP_SET_PREFERED_PHY_COMPLETE_EVT, &cb_params);
|
||||
}
|
||||
|
||||
|
||||
@@ -285,6 +319,12 @@ tBTM_STATUS BTM_BleSetExtendedAdvRandaddr(UINT8 instance, BD_ADDR rand_addr)
|
||||
BTM_TRACE_ERROR("%s, fail to send the hci command, the error code = %s(0x%x)",
|
||||
__func__, btm_ble_hci_status_to_str(err), err);
|
||||
status = BTM_ILLEGAL_VALUE;
|
||||
} else {
|
||||
// set random address success, update address infor
|
||||
if(extend_adv_cb.inst[instance].configured && extend_adv_cb.inst[instance].connetable) {
|
||||
BTM_BleSetStaticAddr(rand_addr);
|
||||
BTM_UpdateAddrInfor(BLE_ADDR_RANDOM, rand_addr);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
BTM_TRACE_ERROR("%s invalid random address", __func__);
|
||||
@@ -295,9 +335,7 @@ tBTM_STATUS BTM_BleSetExtendedAdvRandaddr(UINT8 instance, BD_ADDR rand_addr)
|
||||
end:
|
||||
cb_params.status = status;
|
||||
|
||||
if (ble_5_hci_cb) {
|
||||
ble_5_hci_cb(BTM_BLE_5_GAP_EXT_ADV_SET_RAND_ADDR_COMPLETE_EVT, &cb_params);
|
||||
}
|
||||
BTM_ExtBleCallbackTrigger(BTM_BLE_5_GAP_EXT_ADV_SET_RAND_ADDR_COMPLETE_EVT, &cb_params);
|
||||
|
||||
return status;
|
||||
|
||||
@@ -307,6 +345,8 @@ tBTM_STATUS BTM_BleSetExtendedAdvParams(UINT8 instance, tBTM_BLE_GAP_EXT_ADV_PAR
|
||||
tBTM_STATUS status = BTM_SUCCESS;
|
||||
tHCI_STATUS err = HCI_SUCCESS;
|
||||
tBTM_BLE_5_GAP_CB_PARAMS cb_params = {0};
|
||||
bool use_rpa_addr = false;
|
||||
BD_ADDR rand_addr;
|
||||
|
||||
if (instance >= MAX_BLE_ADV_INSTANCE) {
|
||||
status = BTM_ILLEGAL_VALUE;
|
||||
@@ -335,27 +375,41 @@ tBTM_STATUS BTM_BleSetExtendedAdvParams(UINT8 instance, tBTM_BLE_GAP_EXT_ADV_PAR
|
||||
} else {
|
||||
extend_adv_cb.inst[instance].legacy_pdu = false;
|
||||
}
|
||||
// if own_addr_type == BLE_ADDR_PUBLIC_ID or BLE_ADDR_RANDOM_ID,
|
||||
if((params->own_addr_type == BLE_ADDR_PUBLIC_ID || params->own_addr_type == BLE_ADDR_RANDOM_ID) && BTM_GetLocalResolvablePrivateAddr(rand_addr)) {
|
||||
params->own_addr_type = BLE_ADDR_RANDOM;
|
||||
use_rpa_addr = true;
|
||||
} else if(params->own_addr_type == BLE_ADDR_PUBLIC_ID){
|
||||
params->own_addr_type = BLE_ADDR_PUBLIC;
|
||||
} else if (params->own_addr_type == BLE_ADDR_RANDOM_ID) {
|
||||
params->own_addr_type = BLE_ADDR_RANDOM;
|
||||
}
|
||||
|
||||
if ((err = btsnd_hcic_ble_set_ext_adv_params(instance, params->type, params->interval_min, params->interval_max,
|
||||
params->channel_map, params->own_addr_type, params->peer_addr_type,
|
||||
params->peer_addr, params->filter_policy, params->tx_power,
|
||||
params->primary_phy, params->max_skip,
|
||||
params->secondary_phy, params->sid, params->scan_req_notif)) != HCI_SUCCESS) {
|
||||
BTM_TRACE_ERROR("%s, fail to send the hci command, the error code = %s(0x%x)",
|
||||
__func__, btm_ble_hci_status_to_str(err), err);
|
||||
BTM_TRACE_ERROR("LE EA SetParams: cmd err=0x%x", err);
|
||||
status = BTM_ILLEGAL_VALUE;
|
||||
goto end;
|
||||
goto end;
|
||||
}
|
||||
|
||||
extend_adv_cb.inst[instance].configured = true;
|
||||
|
||||
end:
|
||||
|
||||
cb_params.status = status;
|
||||
|
||||
if (ble_5_hci_cb) {
|
||||
ble_5_hci_cb(BTM_BLE_5_GAP_EXT_ADV_SET_PARAMS_COMPLETE_EVT, &cb_params);
|
||||
if(use_rpa_addr) {
|
||||
// update RPA address
|
||||
if((err = btsnd_hcic_ble_set_extend_rand_address(instance, rand_addr)) != HCI_SUCCESS) {
|
||||
BTM_TRACE_ERROR("LE EA SetParams: cmd err=0x%x", err);
|
||||
status = BTM_ILLEGAL_VALUE;
|
||||
} else {
|
||||
// set addr success, update address infor
|
||||
BTM_UpdateAddrInfor(BLE_ADDR_RANDOM, rand_addr);
|
||||
}
|
||||
}
|
||||
cb_params.status = status;
|
||||
BTM_ExtBleCallbackTrigger(BTM_BLE_5_GAP_EXT_ADV_SET_PARAMS_COMPLETE_EVT, &cb_params);
|
||||
|
||||
return status;
|
||||
}
|
||||
@@ -390,14 +444,12 @@ tBTM_STATUS BTM_BleConfigExtendedAdvDataRaw(BOOLEAN is_scan_rsp, UINT8 instance,
|
||||
}
|
||||
if (!is_scan_rsp) {
|
||||
if ((err = btsnd_hcic_ble_set_ext_adv_data(instance, operation, 0, send_data_len, &data[data_offset])) != HCI_SUCCESS) {
|
||||
BTM_TRACE_ERROR("%s, line %d, fail to send the hci command, the error code = %s",
|
||||
__func__, __LINE__, btm_ble_hci_status_to_str(err));
|
||||
BTM_TRACE_ERROR("LE EA SetAdvData: cmd err=0x%x", err);
|
||||
status = BTM_ILLEGAL_VALUE;
|
||||
}
|
||||
} else {
|
||||
if ((err = btsnd_hcic_ble_set_ext_adv_scan_rsp_data(instance, operation, 0, send_data_len, &data[data_offset])) != HCI_SUCCESS) {
|
||||
BTM_TRACE_ERROR("%s, line %d, fail to send the hci command, the error code = %s(0x%x)",
|
||||
__func__, __LINE__, btm_ble_hci_status_to_str(err), err);
|
||||
BTM_TRACE_ERROR("LE EA SetScanRspData: cmd err=0x%x", err);
|
||||
status = BTM_ILLEGAL_VALUE;
|
||||
}
|
||||
}
|
||||
@@ -408,10 +460,7 @@ tBTM_STATUS BTM_BleConfigExtendedAdvDataRaw(BOOLEAN is_scan_rsp, UINT8 instance,
|
||||
|
||||
end:
|
||||
cb_params.status = status;
|
||||
|
||||
if (ble_5_hci_cb) {
|
||||
ble_5_hci_cb(is_scan_rsp ? BTM_BLE_5_GAP_EXT_SCAN_RSP_DATA_SET_COMPLETE_EVT : BTM_BLE_5_GAP_EXT_ADV_DATA_SET_COMPLETE_EVT, &cb_params);
|
||||
}
|
||||
BTM_ExtBleCallbackTrigger(is_scan_rsp ? BTM_BLE_5_GAP_EXT_SCAN_RSP_DATA_SET_COMPLETE_EVT : BTM_BLE_5_GAP_EXT_ADV_DATA_SET_COMPLETE_EVT, &cb_params);
|
||||
|
||||
return status;
|
||||
}
|
||||
@@ -452,8 +501,7 @@ tBTM_STATUS BTM_BleStartExtAdv(BOOLEAN enable, UINT8 num, tBTM_BLE_EXT_ADV *ext_
|
||||
|
||||
if ((err = btsnd_hcic_ble_ext_adv_enable(enable, num, instance,
|
||||
duration, max_events)) != HCI_SUCCESS) {
|
||||
BTM_TRACE_ERROR("%s, fail to send the hci command, the error code = %s(0x%x)",
|
||||
__func__, btm_ble_hci_status_to_str(err), err);
|
||||
BTM_TRACE_ERROR("LE EA En=%d: cmd err=0x%x", enable, err);
|
||||
status = BTM_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
@@ -464,9 +512,8 @@ tBTM_STATUS BTM_BleStartExtAdv(BOOLEAN enable, UINT8 num, tBTM_BLE_EXT_ADV *ext_
|
||||
// enable = false, num == 0 or ext_adv = NULL
|
||||
|
||||
if ((err = btsnd_hcic_ble_ext_adv_enable(enable, num, NULL, NULL, NULL)) != HCI_SUCCESS) {
|
||||
BTM_TRACE_ERROR("%s, fail to send the hci command, the error code = %s(0x%x)",
|
||||
__func__, btm_ble_hci_status_to_str(err), err);
|
||||
status = BTM_ILLEGAL_VALUE;
|
||||
BTM_TRACE_ERROR("LE EA En=%d: cmd err=0x%x", enable, err);
|
||||
status = BTM_ILLEGAL_VALUE;
|
||||
}
|
||||
goto end;
|
||||
}
|
||||
@@ -480,17 +527,72 @@ end:
|
||||
for (int i = 0; i < MAX_BLE_ADV_INSTANCE; i++) {
|
||||
extend_adv_cb.inst[i].configured = false;
|
||||
}
|
||||
// disable all ext adv
|
||||
if(num == 0) {
|
||||
|
||||
for (uint8_t i = 0; i < MAX_BLE_ADV_INSTANCE; i++)
|
||||
{
|
||||
adv_record[i].invalid = false;
|
||||
adv_record[i].instance = INVALID_VALUE;
|
||||
adv_record[i].duration = INVALID_VALUE;
|
||||
adv_record[i].max_events = INVALID_VALUE;
|
||||
adv_record[i].retry_count = 0;
|
||||
}
|
||||
} else {
|
||||
for (uint8_t i = 0; i < num; i++)
|
||||
{
|
||||
uint8_t index = ext_adv[i].instance;
|
||||
adv_record[index].invalid = false;
|
||||
adv_record[index].instance = INVALID_VALUE;
|
||||
adv_record[index].duration = INVALID_VALUE;
|
||||
adv_record[index].max_events = INVALID_VALUE;
|
||||
adv_record[index].retry_count = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
// start extend adv success, save the adv information
|
||||
if(enable && status == BTM_SUCCESS) {
|
||||
for (uint8_t i = 0; i < num; i++)
|
||||
{
|
||||
uint8_t index = ext_adv[i].instance;
|
||||
adv_record[index].invalid = true;
|
||||
adv_record[index].instance = ext_adv[i].instance;
|
||||
adv_record[index].duration = ext_adv[i].duration;
|
||||
adv_record[index].max_events = ext_adv[i].max_events;
|
||||
adv_record[index].retry_count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
cb_params.status = status;
|
||||
|
||||
if (ble_5_hci_cb) {
|
||||
ble_5_hci_cb(enable ? BTM_BLE_5_GAP_EXT_ADV_START_COMPLETE_EVT : BTM_BLE_5_GAP_EXT_ADV_STOP_COMPLETE_EVT, &cb_params);
|
||||
}
|
||||
BTM_ExtBleCallbackTrigger(enable ? BTM_BLE_5_GAP_EXT_ADV_START_COMPLETE_EVT : BTM_BLE_5_GAP_EXT_ADV_STOP_COMPLETE_EVT, &cb_params);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
tBTM_STATUS BTM_BleStartExtAdvRestart(uint8_t con_handle)
|
||||
{
|
||||
tBTM_BLE_EXT_ADV ext_adv;
|
||||
uint8_t index = INVALID_VALUE;
|
||||
for (uint8_t i = 0; i < MAX_BLE_ADV_INSTANCE; i++)
|
||||
{
|
||||
if(adv_record[i].ter_con_handle == con_handle) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if((index >= MAX_BLE_ADV_INSTANCE) || (!adv_record[index].invalid) || (adv_record[index].retry_count > GATTC_CONNECT_RETRY_COUNT)) {
|
||||
return BTM_WRONG_MODE;
|
||||
}
|
||||
|
||||
adv_record[index].retry_count ++;
|
||||
BTM_TRACE_DEBUG("remote device did not reveive aux connect response, retatrt the extend adv to reconnect, adv handle %d con_handle %d\n", index, con_handle);
|
||||
ext_adv.instance = adv_record[index].instance;
|
||||
ext_adv.duration = adv_record[index].duration;
|
||||
ext_adv.max_events = adv_record[index].max_events;
|
||||
return BTM_BleStartExtAdv(true, 1, &ext_adv);
|
||||
}
|
||||
|
||||
tBTM_STATUS BTM_BleExtAdvSetRemove(UINT8 instance)
|
||||
{
|
||||
tBTM_STATUS status = BTM_SUCCESS;
|
||||
@@ -504,18 +606,21 @@ tBTM_STATUS BTM_BleExtAdvSetRemove(UINT8 instance)
|
||||
}
|
||||
|
||||
if ((err = btsnd_hcic_ble_remove_adv_set(instance)) != HCI_SUCCESS) {
|
||||
BTM_TRACE_ERROR("%s, fail to send the hci command, the error code = %s(0x%x)",
|
||||
__func__, btm_ble_hci_status_to_str(err), err);
|
||||
BTM_TRACE_ERROR("LE EAS Rm: cmd err=0x%x", err);
|
||||
status = BTM_ILLEGAL_VALUE;
|
||||
} else {
|
||||
extend_adv_cb.inst[instance].configured = false;
|
||||
extend_adv_cb.inst[instance].legacy_pdu = false;
|
||||
extend_adv_cb.inst[instance].directed = false;
|
||||
extend_adv_cb.inst[instance].scannable = false;
|
||||
extend_adv_cb.inst[instance].connetable = false;
|
||||
}
|
||||
|
||||
end:
|
||||
|
||||
cb_params.status = status;
|
||||
|
||||
if (ble_5_hci_cb) {
|
||||
ble_5_hci_cb(BTM_BLE_5_GAP_EXT_ADV_SET_REMOVE_COMPLETE_EVT, &cb_params);
|
||||
}
|
||||
BTM_ExtBleCallbackTrigger(BTM_BLE_5_GAP_EXT_ADV_SET_REMOVE_COMPLETE_EVT, &cb_params);
|
||||
|
||||
return status;
|
||||
}
|
||||
@@ -527,16 +632,21 @@ tBTM_STATUS BTM_BleExtAdvSetClear(void)
|
||||
tBTM_BLE_5_GAP_CB_PARAMS cb_params = {0};
|
||||
|
||||
if ((err = btsnd_hcic_ble_clear_adv_set()) != HCI_SUCCESS) {
|
||||
BTM_TRACE_ERROR("%s, fail to send the hci command, the error code = %s(0x%x)",
|
||||
__func__, btm_ble_hci_status_to_str(err), err);
|
||||
BTM_TRACE_ERROR("LE EAS Clr: cmd err=0x%x", err);
|
||||
status = BTM_ILLEGAL_VALUE;
|
||||
} else {
|
||||
for (uint8_t i = 0; i < MAX_BLE_ADV_INSTANCE; i++) {
|
||||
extend_adv_cb.inst[i].configured = false;
|
||||
extend_adv_cb.inst[i].legacy_pdu = false;
|
||||
extend_adv_cb.inst[i].directed = false;
|
||||
extend_adv_cb.inst[i].scannable = false;
|
||||
extend_adv_cb.inst[i].connetable = false;
|
||||
}
|
||||
}
|
||||
|
||||
cb_params.status = status;
|
||||
|
||||
if (ble_5_hci_cb) {
|
||||
ble_5_hci_cb(BTM_BLE_5_GAP_EXT_ADV_SET_CLEAR_COMPLETE_EVT, &cb_params);
|
||||
}
|
||||
BTM_ExtBleCallbackTrigger(BTM_BLE_5_GAP_EXT_ADV_SET_CLEAR_COMPLETE_EVT, &cb_params);
|
||||
|
||||
return status;
|
||||
}
|
||||
@@ -559,15 +669,14 @@ tBTM_STATUS BTM_BlePeriodicAdvSetParams(UINT8 instance, tBTM_BLE_Periodic_Adv_Pa
|
||||
extend_adv_cb.inst[instance].connetable ||
|
||||
extend_adv_cb.inst[instance].legacy_pdu) {
|
||||
BTM_TRACE_ERROR("%s, instance = %d, Before set the periodic adv parameters, please configure the the \
|
||||
extend adv to nonscannable and nonconnectable fisrt, and it shouldn't include the legacy bit.", __func__, instance);
|
||||
extend adv to nonscannable and nonconnectable first, and it shouldn't include the legacy bit.", __func__, instance);
|
||||
status = BTM_ILLEGAL_VALUE;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if ((err= btsnd_hcic_ble_set_periodic_adv_params(instance, params->interval_min,
|
||||
params->interval_max, params->properties)) != HCI_SUCCESS) {
|
||||
BTM_TRACE_ERROR("%s, fail to send the hci command, the error code = %s(0x%x)",
|
||||
__func__, btm_ble_hci_status_to_str(err), err);
|
||||
BTM_TRACE_ERROR("LE PA SetParams: cmd err=0x%x", err);
|
||||
status = BTM_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
@@ -575,9 +684,7 @@ end:
|
||||
|
||||
cb_params.status = status;
|
||||
|
||||
if (ble_5_hci_cb) {
|
||||
ble_5_hci_cb(BTM_BLE_5_GAP_PERIODIC_ADV_SET_PARAMS_COMPLETE_EVT, &cb_params);
|
||||
}
|
||||
BTM_ExtBleCallbackTrigger(BTM_BLE_5_GAP_PERIODIC_ADV_SET_PARAMS_COMPLETE_EVT, &cb_params);
|
||||
|
||||
return status;
|
||||
}
|
||||
@@ -619,8 +726,7 @@ tBTM_STATUS BTM_BlePeriodicAdvCfgDataRaw(UINT8 instance, UINT16 len, UINT8 *data
|
||||
}
|
||||
|
||||
if ((err = btsnd_hcic_ble_set_periodic_adv_data(instance, operation, send_data_len, &data[data_offset])) != HCI_SUCCESS) {
|
||||
BTM_TRACE_ERROR("%s, fail to send the hci command, the error code = %s(0x%x)",
|
||||
__func__, btm_ble_hci_status_to_str(err), err);
|
||||
BTM_TRACE_ERROR("LE PA SetData: cmd err=0x%x", err);
|
||||
status = BTM_ILLEGAL_VALUE;
|
||||
}
|
||||
rem_len -= send_data_len;
|
||||
@@ -629,9 +735,7 @@ tBTM_STATUS BTM_BlePeriodicAdvCfgDataRaw(UINT8 instance, UINT16 len, UINT8 *data
|
||||
|
||||
cb_params.status = status;
|
||||
|
||||
if (ble_5_hci_cb) {
|
||||
ble_5_hci_cb(BTM_BLE_5_GAP_PERIODIC_ADV_DATA_SET_COMPLETE_EVT, &cb_params);
|
||||
}
|
||||
BTM_ExtBleCallbackTrigger(BTM_BLE_5_GAP_PERIODIC_ADV_DATA_SET_COMPLETE_EVT, &cb_params);
|
||||
|
||||
return status;
|
||||
}
|
||||
@@ -643,14 +747,13 @@ tBTM_STATUS BTM_BlePeriodicAdvEnable(UINT8 instance, BOOLEAN enable)
|
||||
tBTM_BLE_5_GAP_CB_PARAMS cb_params = {0};
|
||||
|
||||
if (instance >= MAX_BLE_ADV_INSTANCE) {
|
||||
BTM_TRACE_ERROR("%s, invalid insatnce %d", __func__, instance);
|
||||
BTM_TRACE_ERROR("%s, invalid instance %d", __func__, instance);
|
||||
status = BTM_ILLEGAL_VALUE;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if ((err = btsnd_hcic_ble_periodic_adv_enable(enable, instance)) != HCI_SUCCESS) {
|
||||
BTM_TRACE_ERROR("%s, fail to send the hci command, the error code = %s(0x%x)",
|
||||
__func__, btm_ble_hci_status_to_str(err), err);
|
||||
BTM_TRACE_ERROR("LE PA En=%d: cmd err=0x%x", enable, err);
|
||||
status = BTM_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
@@ -658,9 +761,7 @@ end:
|
||||
|
||||
cb_params.status = status;
|
||||
|
||||
if (ble_5_hci_cb) {
|
||||
ble_5_hci_cb(enable ? BTM_BLE_5_GAP_PERIODIC_ADV_START_COMPLETE_EVT : BTM_BLE_5_GAP_PERIODIC_ADV_STOP_COMPLETE_EVT, &cb_params);
|
||||
}
|
||||
BTM_ExtBleCallbackTrigger(enable ? BTM_BLE_5_GAP_PERIODIC_ADV_START_COMPLETE_EVT : BTM_BLE_5_GAP_PERIODIC_ADV_STOP_COMPLETE_EVT, &cb_params);
|
||||
|
||||
return status;
|
||||
|
||||
@@ -688,17 +789,16 @@ tBTM_STATUS BTM_BlePeriodicAdvCreateSync(tBTM_BLE_Periodic_Sync_Params *params)
|
||||
|
||||
if (!btsnd_hcic_ble_periodic_adv_create_sync(params->filter_policy, params->sid, params->addr_type,
|
||||
params->addr, params->sync_timeout, 0)) {
|
||||
BTM_TRACE_ERROR("%s, send cmd failed", __func__);
|
||||
BTM_TRACE_ERROR("LE PA CreateSync cmd failed");
|
||||
status = BTM_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
end:
|
||||
if((status != BTM_SUCCESS) && ble_5_hci_cb) {
|
||||
if(status != BTM_SUCCESS) {
|
||||
cb_params.status = status;
|
||||
ble_5_hci_cb(BTM_BLE_5_GAP_PERIODIC_ADV_CREATE_SYNC_COMPLETE_EVT, &cb_params);
|
||||
BTM_ExtBleCallbackTrigger(BTM_BLE_5_GAP_PERIODIC_ADV_CREATE_SYNC_COMPLETE_EVT, &cb_params);
|
||||
}
|
||||
|
||||
|
||||
return status;
|
||||
}
|
||||
void btm_set_phy_callback(UINT8 status)
|
||||
@@ -706,9 +806,7 @@ void btm_set_phy_callback(UINT8 status)
|
||||
tBTM_BLE_5_GAP_CB_PARAMS cb_params = {0};
|
||||
cb_params.status = status;
|
||||
|
||||
if (ble_5_hci_cb) {
|
||||
ble_5_hci_cb(BTM_BLE_5_GAP_SET_PREFERED_PHY_COMPLETE_EVT, &cb_params);
|
||||
}
|
||||
BTM_ExtBleCallbackTrigger(BTM_BLE_5_GAP_SET_PREFERED_PHY_COMPLETE_EVT, &cb_params);
|
||||
|
||||
}
|
||||
void btm_create_sync_callback(UINT8 status)
|
||||
@@ -716,9 +814,7 @@ void btm_create_sync_callback(UINT8 status)
|
||||
tBTM_BLE_5_GAP_CB_PARAMS cb_params = {0};
|
||||
cb_params.status = status;
|
||||
|
||||
if (ble_5_hci_cb) {
|
||||
ble_5_hci_cb(BTM_BLE_5_GAP_PERIODIC_ADV_CREATE_SYNC_COMPLETE_EVT, &cb_params);
|
||||
}
|
||||
BTM_ExtBleCallbackTrigger(BTM_BLE_5_GAP_PERIODIC_ADV_CREATE_SYNC_COMPLETE_EVT, &cb_params);
|
||||
}
|
||||
|
||||
void btm_read_phy_callback(uint8_t hci_status, uint16_t conn_handle, uint8_t tx_phy, uint8_t rx_phy)
|
||||
@@ -737,9 +833,7 @@ void btm_read_phy_callback(uint8_t hci_status, uint16_t conn_handle, uint8_t tx_
|
||||
cb_params.read_phy.tx_phy = tx_phy;
|
||||
cb_params.read_phy.rx_phy = rx_phy;
|
||||
|
||||
if (ble_5_hci_cb) {
|
||||
ble_5_hci_cb(BTM_BLE_5_GAP_READ_PHY_COMPLETE_EVT, &cb_params);
|
||||
}
|
||||
BTM_ExtBleCallbackTrigger(BTM_BLE_5_GAP_READ_PHY_COMPLETE_EVT, &cb_params);
|
||||
}
|
||||
|
||||
tBTM_STATUS BTM_BlePeriodicAdvSyncCancel(void)
|
||||
@@ -749,16 +843,13 @@ tBTM_STATUS BTM_BlePeriodicAdvSyncCancel(void)
|
||||
tBTM_BLE_5_GAP_CB_PARAMS cb_params = {0};
|
||||
|
||||
if ((err = btsnd_hcic_ble_periodic_adv_create_sync_cancel()) != HCI_SUCCESS) {
|
||||
BTM_TRACE_ERROR("%s, fail to send the hci command, the error code = %s(0x%x)",
|
||||
__func__, btm_ble_hci_status_to_str(err), err);
|
||||
BTM_TRACE_ERROR("LE PA SyncCancel, cmd err=0x%x", err);
|
||||
status = BTM_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
cb_params.status = status;
|
||||
|
||||
if (ble_5_hci_cb) {
|
||||
ble_5_hci_cb(BTM_BLE_5_GAP_PERIODIC_ADV_SYNC_CANCEL_COMPLETE_EVT, &cb_params);
|
||||
}
|
||||
BTM_ExtBleCallbackTrigger(BTM_BLE_5_GAP_PERIODIC_ADV_SYNC_CANCEL_COMPLETE_EVT, &cb_params);
|
||||
|
||||
return status;
|
||||
}
|
||||
@@ -770,16 +861,13 @@ tBTM_STATUS BTM_BlePeriodicAdvSyncTerm(UINT16 sync_handle)
|
||||
tBTM_BLE_5_GAP_CB_PARAMS cb_params = {0};
|
||||
|
||||
if (( err = btsnd_hcic_ble_periodic_adv_term_sync(sync_handle)) != HCI_SUCCESS) {
|
||||
BTM_TRACE_ERROR("%s, fail to send the hci command, the error code = %s(0x%x)",
|
||||
__func__, btm_ble_hci_status_to_str(err), err);
|
||||
BTM_TRACE_ERROR("LE PA SyncTerm: cmd err=0x%x", err);
|
||||
status = BTM_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
cb_params.status = status;
|
||||
|
||||
if (ble_5_hci_cb) {
|
||||
ble_5_hci_cb(BTM_BLE_5_GAP_PERIODIC_ADV_SYNC_TERMINATE_COMPLETE_EVT, &cb_params);
|
||||
}
|
||||
BTM_ExtBleCallbackTrigger(BTM_BLE_5_GAP_PERIODIC_ADV_SYNC_TERMINATE_COMPLETE_EVT, &cb_params);
|
||||
|
||||
return status;
|
||||
}
|
||||
@@ -797,16 +885,13 @@ tBTM_STATUS BTM_BlePeriodicAdvAddDevToList(tBLE_ADDR_TYPE addr_type, BD_ADDR add
|
||||
}
|
||||
|
||||
if ((err = btsnd_hcic_ble_add_dev_to_periodic_adv_list(addr_type, addr, sid)) != HCI_SUCCESS) {
|
||||
BTM_TRACE_ERROR("%s, fail to send the hci command, the error code = %s(0x%x)",
|
||||
__func__, btm_ble_hci_status_to_str(err), err);
|
||||
BTM_TRACE_ERROR("LE PA AddDevToList: cmd err=0x%x", err);
|
||||
status = BTM_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
end:
|
||||
cb_params.status = status;
|
||||
if (ble_5_hci_cb) {
|
||||
ble_5_hci_cb(BTM_BLE_5_GAP_PERIODIC_ADV_ADD_DEV_COMPLETE_EVT, &cb_params);
|
||||
}
|
||||
BTM_ExtBleCallbackTrigger(BTM_BLE_5_GAP_PERIODIC_ADV_ADD_DEV_COMPLETE_EVT, &cb_params);
|
||||
|
||||
return status;
|
||||
}
|
||||
@@ -824,17 +909,14 @@ tBTM_STATUS BTM_BlePeriodicAdvRemoveDevFromList(tBLE_ADDR_TYPE addr_type, BD_ADD
|
||||
}
|
||||
|
||||
if ((err = btsnd_hcic_ble_rm_dev_from_periodic_adv_list(addr_type, addr, sid)) != HCI_SUCCESS) {
|
||||
BTM_TRACE_ERROR("%s, fail to send the hci command, the error code = %s(0x%x)",
|
||||
__func__, btm_ble_hci_status_to_str(err), err);
|
||||
BTM_TRACE_ERROR("LE PA RmDevFromList: cmd err=0x%x", err);
|
||||
status = BTM_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
end:
|
||||
|
||||
cb_params.status = status;
|
||||
if (ble_5_hci_cb) {
|
||||
ble_5_hci_cb(BTM_BLE_5_GAP_PERIODIC_ADV_REMOVE_DEV_COMPLETE_EVT, &cb_params);
|
||||
}
|
||||
BTM_ExtBleCallbackTrigger(BTM_BLE_5_GAP_PERIODIC_ADV_REMOVE_DEV_COMPLETE_EVT, &cb_params);
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -845,15 +927,12 @@ tBTM_STATUS BTM_BlePeriodicAdvClearDev(void)
|
||||
tBTM_BLE_5_GAP_CB_PARAMS cb_params = {0};
|
||||
|
||||
if ((err = btsnd_hcic_ble_clear_periodic_adv_list()) != HCI_SUCCESS) {
|
||||
BTM_TRACE_ERROR("%s, fail to send the hci command, the error code = %s(0x%x)",
|
||||
__func__, btm_ble_hci_status_to_str(err), err);
|
||||
BTM_TRACE_ERROR("LE PA ClrDev: cmd err=0x%x", err);
|
||||
status = BTM_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
cb_params.status = status;
|
||||
if (ble_5_hci_cb) {
|
||||
ble_5_hci_cb(BTM_BLE_5_GAP_PERIODIC_ADV_CLEAR_DEV_COMPLETE_EVT, &cb_params);
|
||||
}
|
||||
BTM_ExtBleCallbackTrigger(BTM_BLE_5_GAP_PERIODIC_ADV_CLEAR_DEV_COMPLETE_EVT, &cb_params);
|
||||
|
||||
return status;
|
||||
}
|
||||
@@ -890,12 +969,17 @@ tBTM_STATUS BTM_BleSetExtendedScanParams(tBTM_BLE_EXT_SCAN_PARAMS *params)
|
||||
phy_count++;
|
||||
}
|
||||
|
||||
if (BTM_BleUpdateOwnType(¶ms->own_addr_type, NULL) != 0 ) {
|
||||
status = BTM_ILLEGAL_VALUE;
|
||||
BTM_TRACE_ERROR("LE UpdateOwnType err");
|
||||
goto end;
|
||||
}
|
||||
|
||||
extend_adv_cb.scan_duplicate = params->scan_duplicate;
|
||||
|
||||
if ((err = btsnd_hcic_ble_set_ext_scan_params(params->own_addr_type, params->filter_policy, phy_mask, phy_count,
|
||||
hci_params)) != HCI_SUCCESS) {
|
||||
BTM_TRACE_ERROR("%s, fail to send the hci command, the error code = %s(0x%x)",
|
||||
__func__, btm_ble_hci_status_to_str(err), err);
|
||||
BTM_TRACE_ERROR("LE ES SetParams: cmd err=0x%x", err);
|
||||
status = BTM_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
@@ -903,9 +987,7 @@ end:
|
||||
|
||||
cb_params.status = status;
|
||||
|
||||
if (ble_5_hci_cb) {
|
||||
ble_5_hci_cb(BTM_BLE_5_GAP_SET_EXT_SCAN_PARAMS_COMPLETE_EVT, &cb_params);
|
||||
}
|
||||
BTM_ExtBleCallbackTrigger(BTM_BLE_5_GAP_SET_EXT_SCAN_PARAMS_COMPLETE_EVT, &cb_params);
|
||||
|
||||
return cb_params.status;
|
||||
}
|
||||
@@ -923,8 +1005,7 @@ tBTM_STATUS BTM_BleExtendedScan(BOOLEAN enable, UINT16 duration, UINT16 period)
|
||||
}
|
||||
|
||||
if ((err = btsnd_hcic_ble_ext_scan_enable(enable, extend_adv_cb.scan_duplicate, duration, period)) != HCI_SUCCESS) {
|
||||
BTM_TRACE_ERROR("%s, fail to send the hci command, the error code = %s(0x%x)",
|
||||
__func__, btm_ble_hci_status_to_str(err), err);
|
||||
BTM_TRACE_ERROR("LE ES En=%d: cmd err=0x%x", enable, err);
|
||||
status = BTM_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
@@ -932,9 +1013,7 @@ end:
|
||||
|
||||
cb_params.status = status;
|
||||
|
||||
if (ble_5_hci_cb) {
|
||||
ble_5_hci_cb(enable ? BTM_BLE_5_GAP_EXT_SCAN_START_COMPLETE_EVT : BTM_BLE_5_GAP_EXT_SCAN_STOP_COMPLETE_EVT, &cb_params);
|
||||
}
|
||||
BTM_ExtBleCallbackTrigger(enable ? BTM_BLE_5_GAP_EXT_SCAN_START_COMPLETE_EVT : BTM_BLE_5_GAP_EXT_SCAN_STOP_COMPLETE_EVT, &cb_params);
|
||||
|
||||
return status;
|
||||
}
|
||||
@@ -1058,20 +1137,15 @@ void btm_ble_update_phy_evt(tBTM_BLE_UPDATE_PHY *params)
|
||||
memcpy(cb_params.phy_update.addr, p_lcb->remote_bd_addr, BD_ADDR_LEN);
|
||||
|
||||
// If the user has register the callback function, should callback it to the application.
|
||||
if (ble_5_hci_cb) {
|
||||
ble_5_hci_cb(BTM_BLE_5_GAP_PHY_UPDATE_COMPLETE_EVT, &cb_params);
|
||||
}
|
||||
|
||||
BTM_ExtBleCallbackTrigger(BTM_BLE_5_GAP_PHY_UPDATE_COMPLETE_EVT, &cb_params);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void btm_ble_scan_timeout_evt(void)
|
||||
{
|
||||
if (ble_5_hci_cb) {
|
||||
ble_5_hci_cb(BTM_BLE_5_GAP_SCAN_TIMEOUT_EVT, NULL);
|
||||
}
|
||||
|
||||
return;
|
||||
BTM_ExtBleCallbackTrigger(BTM_BLE_5_GAP_SCAN_TIMEOUT_EVT, NULL);
|
||||
}
|
||||
|
||||
void btm_ble_adv_set_terminated_evt(tBTM_BLE_ADV_TERMINAT *params)
|
||||
@@ -1083,12 +1157,18 @@ void btm_ble_adv_set_terminated_evt(tBTM_BLE_ADV_TERMINAT *params)
|
||||
return;
|
||||
}
|
||||
|
||||
// adv terminated due to connection, save the adv handle and connection handle
|
||||
if(params->completed_event == 0x00) {
|
||||
adv_record[params->adv_handle].ter_con_handle = params->conn_handle;
|
||||
} else {
|
||||
adv_record[params->adv_handle].ter_con_handle = INVALID_VALUE;
|
||||
adv_record[params->adv_handle].invalid = false;
|
||||
}
|
||||
|
||||
memcpy(&cb_params.adv_term, params, sizeof(tBTM_BLE_ADV_TERMINAT));
|
||||
|
||||
// If the user has register the callback function, should callback it to the application.
|
||||
if (ble_5_hci_cb) {
|
||||
ble_5_hci_cb(BTM_BLE_5_GAP_ADV_TERMINATED_EVT, &cb_params);
|
||||
}
|
||||
BTM_ExtBleCallbackTrigger(BTM_BLE_5_GAP_ADV_TERMINATED_EVT, &cb_params);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -1105,9 +1185,7 @@ void btm_ble_ext_adv_report_evt(tBTM_BLE_EXT_ADV_REPORT *params)
|
||||
memcpy(&cb_params.ext_adv_report, params, sizeof(tBTM_BLE_EXT_ADV_REPORT));
|
||||
|
||||
// If the user has register the callback function, should callback it to the application.
|
||||
if (ble_5_hci_cb) {
|
||||
ble_5_hci_cb(BTM_BLE_5_GAP_EXT_ADV_REPORT_EVT, &cb_params);
|
||||
}
|
||||
BTM_ExtBleCallbackTrigger(BTM_BLE_5_GAP_EXT_ADV_REPORT_EVT, &cb_params);
|
||||
|
||||
return;
|
||||
|
||||
@@ -1125,9 +1203,7 @@ void btm_ble_scan_req_received_evt(tBTM_BLE_SCAN_REQ_RECEIVED *params)
|
||||
memcpy(&cb_params.scan_req, params, sizeof(tBTM_BLE_SCAN_REQ_RECEIVED));
|
||||
|
||||
// If the user has register the callback function, should callback it to the application.
|
||||
if (ble_5_hci_cb) {
|
||||
ble_5_hci_cb(BTM_BLE_5_GAP_SCAN_REQ_RECEIVED_EVT, &cb_params);
|
||||
}
|
||||
BTM_ExtBleCallbackTrigger(BTM_BLE_5_GAP_SCAN_REQ_RECEIVED_EVT, &cb_params);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -1144,9 +1220,7 @@ void btm_ble_channel_select_algorithm_evt(tBTM_BLE_CHANNEL_SEL_ALG *params)
|
||||
memcpy(&cb_params.channel_sel, params, sizeof(tBTM_BLE_CHANNEL_SEL_ALG));
|
||||
|
||||
// If the user has register the callback function, should callback it to the application.
|
||||
if (ble_5_hci_cb) {
|
||||
ble_5_hci_cb(BTM_BLE_5_GAP_CHANNEL_SELETE_ALGORITHM_EVT, &cb_params);
|
||||
}
|
||||
BTM_ExtBleCallbackTrigger(BTM_BLE_5_GAP_CHANNEL_SELETE_ALGORITHM_EVT, &cb_params);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -1163,9 +1237,7 @@ void btm_ble_periodic_adv_report_evt(tBTM_PERIOD_ADV_REPORT *params)
|
||||
memcpy(&cb_params.period_adv_report, params, sizeof(tBTM_PERIOD_ADV_REPORT));
|
||||
|
||||
// If the user has register the callback function, should callback it to the application.
|
||||
if (ble_5_hci_cb) {
|
||||
ble_5_hci_cb(BTM_BLE_5_GAP_PERIODIC_ADV_REPORT_EVT, &cb_params);
|
||||
}
|
||||
BTM_ExtBleCallbackTrigger(BTM_BLE_5_GAP_PERIODIC_ADV_REPORT_EVT, &cb_params);
|
||||
|
||||
return;
|
||||
|
||||
@@ -1183,9 +1255,7 @@ void btm_ble_periodic_adv_sync_lost_evt(tBTM_BLE_PERIOD_ADV_SYNC_LOST *params)
|
||||
memcpy(&cb_params.sync_lost, params, sizeof(tBTM_BLE_PERIOD_ADV_SYNC_LOST));
|
||||
|
||||
// If the user has register the callback function, should callback it to the application.
|
||||
if (ble_5_hci_cb) {
|
||||
ble_5_hci_cb(BTM_BLE_5_GAP_PERIODIC_ADV_SYNC_LOST_EVT, &cb_params);
|
||||
}
|
||||
BTM_ExtBleCallbackTrigger(BTM_BLE_5_GAP_PERIODIC_ADV_SYNC_LOST_EVT, &cb_params);
|
||||
|
||||
return;
|
||||
|
||||
@@ -1203,9 +1273,7 @@ void btm_ble_periodic_adv_sync_establish_evt(tBTM_BLE_PERIOD_ADV_SYNC_ESTAB *par
|
||||
memcpy(&cb_params.sync_estab, params, sizeof(tBTM_BLE_PERIOD_ADV_SYNC_ESTAB));
|
||||
|
||||
// If the user has register the callback function, should callback it to the application.
|
||||
if (ble_5_hci_cb) {
|
||||
ble_5_hci_cb(BTM_BLE_5_GAP_PERIODIC_ADV_SYNC_ESTAB_EVT, &cb_params);
|
||||
}
|
||||
BTM_ExtBleCallbackTrigger(BTM_BLE_5_GAP_PERIODIC_ADV_SYNC_ESTAB_EVT, &cb_params);
|
||||
|
||||
return;
|
||||
|
||||
|
||||
@@ -82,12 +82,25 @@ static UINT8 btm_set_conn_mode_adv_init_addr(tBTM_BLE_INQ_CB *p_cb,
|
||||
tBLE_ADDR_TYPE *p_own_addr_type);
|
||||
static void btm_ble_stop_observe(void);
|
||||
static void btm_ble_stop_discover(void);
|
||||
uint32_t BTM_BleUpdateOwnType(uint8_t *own_bda_type, tBTM_START_ADV_CMPL_CBACK *cb);
|
||||
|
||||
#define BTM_BLE_INQ_RESULT 0x01
|
||||
#define BTM_BLE_OBS_RESULT 0x02
|
||||
#define BTM_BLE_SEL_CONN_RESULT 0x04
|
||||
#define BTM_BLE_DISCO_RESULT 0x08
|
||||
|
||||
static bool is_ble50_inter = false;
|
||||
|
||||
void btm_ble_inter_set(bool extble_inter)
|
||||
{
|
||||
is_ble50_inter = extble_inter;
|
||||
}
|
||||
|
||||
bool btm_ble_inter_get(void)
|
||||
{
|
||||
return is_ble50_inter;
|
||||
}
|
||||
|
||||
/* LE states combo bit to check */
|
||||
const UINT8 btm_le_state_combo_tbl[BTM_BLE_STATE_MAX][BTM_BLE_STATE_MAX][2] = {
|
||||
{/* single state support */
|
||||
@@ -908,6 +921,140 @@ BOOLEAN BTM_BleConfigPrivacy(BOOLEAN privacy_mode, tBTM_SET_LOCAL_PRIVACY_CBACK
|
||||
#endif
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function BTMGetLocalResolvablePrivateAddr
|
||||
**
|
||||
** Description This function is called to get local RPA address
|
||||
**
|
||||
** Parameters bda: address pointer.
|
||||
**
|
||||
**
|
||||
*******************************************************************************/
|
||||
|
||||
BOOLEAN BTM_GetLocalResolvablePrivateAddr(BD_ADDR bda)
|
||||
{
|
||||
tBTM_LE_RANDOM_CB *p_cb = &btm_cb.ble_ctr_cb.addr_mgnt_cb;
|
||||
BTM_TRACE_DEBUG ("get owm resolvable random address");
|
||||
|
||||
if (bda) {
|
||||
/* if privacy disabled, return false */
|
||||
if ((p_cb->exist_addr_bit & BTM_BLE_GAP_ADDR_BIT_RESOLVABLE) == BTM_BLE_GAP_ADDR_BIT_RESOLVABLE) {
|
||||
memcpy(bda, p_cb->resolvale_addr, BD_ADDR_LEN);
|
||||
BTM_TRACE_DEBUG("own resolvable random address: 0x%02x:%02x:%02x:%02x:%02x:%02x",
|
||||
p_cb->resolvale_addr[0], p_cb->resolvale_addr[1],
|
||||
p_cb->resolvale_addr[2], p_cb->resolvale_addr[3],
|
||||
p_cb->resolvale_addr[4], p_cb->resolvale_addr[5]);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function BTM_UpdateAddrInfor
|
||||
**
|
||||
** Description This function is called to update address information
|
||||
**
|
||||
** Parameters addr_type: address type
|
||||
** bda: address pointer.
|
||||
**
|
||||
**
|
||||
*******************************************************************************/
|
||||
void BTM_UpdateAddrInfor(uint8_t addr_type, BD_ADDR bda)
|
||||
{
|
||||
btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type = addr_type;
|
||||
memcpy(btm_cb.ble_ctr_cb.addr_mgnt_cb.private_addr, bda, BD_ADDR_LEN);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function BTM_BleSetStaticAddr
|
||||
**
|
||||
** Description This function is called to save random address
|
||||
**
|
||||
** Parameters rand_addr: address pointer.
|
||||
**
|
||||
**
|
||||
*******************************************************************************/
|
||||
void BTM_BleSetStaticAddr(BD_ADDR rand_addr)
|
||||
{
|
||||
memcpy(btm_cb.ble_ctr_cb.addr_mgnt_cb.static_rand_addr, rand_addr, BD_ADDR_LEN);
|
||||
btm_cb.ble_ctr_cb.addr_mgnt_cb.exist_addr_bit |= BTM_BLE_GAP_ADDR_BIT_RANDOM;
|
||||
}
|
||||
|
||||
uint32_t BTM_BleUpdateOwnType(uint8_t *own_bda_type, tBTM_START_ADV_CMPL_CBACK *cb)
|
||||
{
|
||||
if(*own_bda_type == BLE_ADDR_RANDOM) {
|
||||
if((btm_cb.ble_ctr_cb.addr_mgnt_cb.exist_addr_bit & BTM_BLE_GAP_ADDR_BIT_RANDOM) == BTM_BLE_GAP_ADDR_BIT_RANDOM) {
|
||||
//close privacy
|
||||
#if BLE_PRIVACY_SPT == TRUE
|
||||
if (btm_cb.ble_ctr_cb.privacy_mode != BTM_PRIVACY_NONE) {
|
||||
BTM_BleConfigPrivacy(FALSE, NULL);
|
||||
}
|
||||
#endif
|
||||
btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type = BLE_ADDR_RANDOM;
|
||||
memcpy(btm_cb.ble_ctr_cb.addr_mgnt_cb.private_addr, btm_cb.ble_ctr_cb.addr_mgnt_cb.static_rand_addr, BD_ADDR_LEN);
|
||||
// set address to controller
|
||||
btsnd_hcic_ble_set_random_addr(btm_cb.ble_ctr_cb.addr_mgnt_cb.static_rand_addr);
|
||||
|
||||
} else if((btm_cb.ble_ctr_cb.addr_mgnt_cb.exist_addr_bit & BTM_BLE_GAP_ADDR_BIT_RESOLVABLE) == BTM_BLE_GAP_ADDR_BIT_RESOLVABLE) {
|
||||
btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type = BLE_ADDR_RANDOM;
|
||||
memcpy(btm_cb.ble_ctr_cb.addr_mgnt_cb.private_addr, btm_cb.ble_ctr_cb.addr_mgnt_cb.resolvale_addr, BD_ADDR_LEN);
|
||||
btsnd_hcic_ble_set_random_addr(btm_cb.ble_ctr_cb.addr_mgnt_cb.resolvale_addr);
|
||||
}else {
|
||||
BTM_TRACE_ERROR ("No random address yet, please set random address and try\n");
|
||||
if(cb) {
|
||||
(* cb)(HCI_ERR_ESP_VENDOR_FAIL);
|
||||
}
|
||||
return BTM_ILLEGAL_VALUE;
|
||||
}
|
||||
} else if(*own_bda_type == BLE_ADDR_PUBLIC_ID || *own_bda_type == BLE_ADDR_RANDOM_ID) {
|
||||
if((btm_cb.ble_ctr_cb.addr_mgnt_cb.exist_addr_bit & BTM_BLE_GAP_ADDR_BIT_RESOLVABLE) == BTM_BLE_GAP_ADDR_BIT_RESOLVABLE) {
|
||||
*own_bda_type = BLE_ADDR_RANDOM;
|
||||
btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type = BLE_ADDR_RANDOM;
|
||||
memcpy(btm_cb.ble_ctr_cb.addr_mgnt_cb.private_addr, btm_cb.ble_ctr_cb.addr_mgnt_cb.resolvale_addr, BD_ADDR_LEN);
|
||||
btsnd_hcic_ble_set_random_addr(btm_cb.ble_ctr_cb.addr_mgnt_cb.resolvale_addr);
|
||||
} else {
|
||||
#if BLE_PRIVACY_SPT == TRUE
|
||||
if(btm_cb.ble_ctr_cb.privacy_mode != BTM_PRIVACY_NONE) {
|
||||
BTM_TRACE_ERROR ("Error state\n");
|
||||
if(cb) {
|
||||
(* cb)(HCI_ERR_ESP_VENDOR_FAIL);
|
||||
}
|
||||
return BTM_ILLEGAL_VALUE;
|
||||
}
|
||||
#endif
|
||||
if(*own_bda_type == BLE_ADDR_PUBLIC_ID) {
|
||||
*own_bda_type = BLE_ADDR_PUBLIC;
|
||||
btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type = BLE_ADDR_PUBLIC;
|
||||
} else { //own_bda_type == BLE_ADDR_RANDOM_ID
|
||||
if((btm_cb.ble_ctr_cb.addr_mgnt_cb.exist_addr_bit & BTM_BLE_GAP_ADDR_BIT_RANDOM) == BTM_BLE_GAP_ADDR_BIT_RANDOM) {
|
||||
*own_bda_type = BLE_ADDR_RANDOM;
|
||||
btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type = BLE_ADDR_RANDOM;
|
||||
memcpy(btm_cb.ble_ctr_cb.addr_mgnt_cb.private_addr, btm_cb.ble_ctr_cb.addr_mgnt_cb.static_rand_addr, BD_ADDR_LEN);
|
||||
btsnd_hcic_ble_set_random_addr(btm_cb.ble_ctr_cb.addr_mgnt_cb.static_rand_addr);
|
||||
} else {
|
||||
BTM_TRACE_ERROR ("No RPA and no random address yet, please set RPA or random address and try\n");
|
||||
if(cb) {
|
||||
(* cb)(HCI_ERR_ESP_VENDOR_FAIL);
|
||||
}
|
||||
return BTM_ILLEGAL_VALUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type = BLE_ADDR_PUBLIC;
|
||||
}
|
||||
|
||||
return BTM_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function BTM_BleConfigLocalIcon
|
||||
@@ -1345,69 +1492,9 @@ tBTM_STATUS BTM_BleSetAdvParamsAll(UINT16 adv_int_min, UINT16 adv_int_max, UINT8
|
||||
if (!controller_get_interface()->supports_ble()) {
|
||||
return BTM_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
if(own_bda_type == BLE_ADDR_RANDOM) {
|
||||
if((btm_cb.ble_ctr_cb.addr_mgnt_cb.exist_addr_bit & BTM_BLE_GAP_ADDR_BIT_RANDOM) == BTM_BLE_GAP_ADDR_BIT_RANDOM) {
|
||||
//close privacy
|
||||
#if BLE_PRIVACY_SPT == TRUE
|
||||
if (btm_cb.ble_ctr_cb.privacy_mode != BTM_PRIVACY_NONE) {
|
||||
BTM_BleConfigPrivacy(FALSE, NULL);
|
||||
}
|
||||
#endif
|
||||
btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type = BLE_ADDR_RANDOM;
|
||||
memcpy(btm_cb.ble_ctr_cb.addr_mgnt_cb.private_addr, btm_cb.ble_ctr_cb.addr_mgnt_cb.static_rand_addr, BD_ADDR_LEN);
|
||||
// set address to controller
|
||||
btsnd_hcic_ble_set_random_addr(btm_cb.ble_ctr_cb.addr_mgnt_cb.static_rand_addr);
|
||||
|
||||
} else if((btm_cb.ble_ctr_cb.addr_mgnt_cb.exist_addr_bit & BTM_BLE_GAP_ADDR_BIT_RESOLVABLE) == BTM_BLE_GAP_ADDR_BIT_RESOLVABLE) {
|
||||
btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type = BLE_ADDR_RANDOM;
|
||||
memcpy(btm_cb.ble_ctr_cb.addr_mgnt_cb.private_addr, btm_cb.ble_ctr_cb.addr_mgnt_cb.resolvale_addr, BD_ADDR_LEN);
|
||||
btsnd_hcic_ble_set_random_addr(btm_cb.ble_ctr_cb.addr_mgnt_cb.resolvale_addr);
|
||||
}else {
|
||||
BTM_TRACE_ERROR ("No random address yet, please set random address and try\n");
|
||||
if(adv_cb) {
|
||||
(* adv_cb)(HCI_ERR_ESP_VENDOR_FAIL);
|
||||
}
|
||||
return BTM_ILLEGAL_VALUE;
|
||||
}
|
||||
} else if(own_bda_type == BLE_ADDR_PUBLIC_ID || own_bda_type == BLE_ADDR_RANDOM_ID) {
|
||||
if((btm_cb.ble_ctr_cb.addr_mgnt_cb.exist_addr_bit & BTM_BLE_GAP_ADDR_BIT_RESOLVABLE) == BTM_BLE_GAP_ADDR_BIT_RESOLVABLE) {
|
||||
own_bda_type = BLE_ADDR_RANDOM;
|
||||
btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type = BLE_ADDR_RANDOM;
|
||||
memcpy(btm_cb.ble_ctr_cb.addr_mgnt_cb.private_addr, btm_cb.ble_ctr_cb.addr_mgnt_cb.resolvale_addr, BD_ADDR_LEN);
|
||||
btsnd_hcic_ble_set_random_addr(btm_cb.ble_ctr_cb.addr_mgnt_cb.resolvale_addr);
|
||||
} else {
|
||||
#if BLE_PRIVACY_SPT == TRUE
|
||||
if(btm_cb.ble_ctr_cb.privacy_mode != BTM_PRIVACY_NONE) {
|
||||
BTM_TRACE_ERROR ("Error state\n");
|
||||
if(adv_cb) {
|
||||
(* adv_cb)(HCI_ERR_ESP_VENDOR_FAIL);
|
||||
}
|
||||
return BTM_ILLEGAL_VALUE;
|
||||
}
|
||||
#endif
|
||||
if(own_bda_type == BLE_ADDR_PUBLIC_ID) {
|
||||
own_bda_type = BLE_ADDR_PUBLIC;
|
||||
btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type = BLE_ADDR_PUBLIC;
|
||||
} else { //own_bda_type == BLE_ADDR_RANDOM_ID
|
||||
if((btm_cb.ble_ctr_cb.addr_mgnt_cb.exist_addr_bit & BTM_BLE_GAP_ADDR_BIT_RANDOM) == BTM_BLE_GAP_ADDR_BIT_RANDOM) {
|
||||
own_bda_type = BLE_ADDR_RANDOM;
|
||||
btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type = BLE_ADDR_RANDOM;
|
||||
memcpy(btm_cb.ble_ctr_cb.addr_mgnt_cb.private_addr, btm_cb.ble_ctr_cb.addr_mgnt_cb.static_rand_addr, BD_ADDR_LEN);
|
||||
btsnd_hcic_ble_set_random_addr(btm_cb.ble_ctr_cb.addr_mgnt_cb.static_rand_addr);
|
||||
} else {
|
||||
BTM_TRACE_ERROR ("No RPA and no random address yet, please set RPA or random address and try\n");
|
||||
if(adv_cb) {
|
||||
(* adv_cb)(HCI_ERR_ESP_VENDOR_FAIL);
|
||||
}
|
||||
return BTM_ILLEGAL_VALUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type = BLE_ADDR_PUBLIC;
|
||||
if (BTM_BleUpdateOwnType(&own_bda_type, adv_cb) != 0) {
|
||||
return BTM_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
if (!BTM_BLE_ISVALID_PARAM(adv_int_min, BTM_BLE_ADV_INT_MIN, BTM_BLE_ADV_INT_MAX) ||
|
||||
!BTM_BLE_ISVALID_PARAM(adv_int_max, BTM_BLE_ADV_INT_MIN, BTM_BLE_ADV_INT_MAX)) {
|
||||
BTM_TRACE_ERROR ("adv_int_min or adv_int_max is invalid\n");
|
||||
@@ -1579,61 +1666,9 @@ tBTM_STATUS BTM_BleSetScanFilterParams(tGATT_IF client_if, UINT32 scan_interval,
|
||||
if (!controller_get_interface()->supports_ble()) {
|
||||
return BTM_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
if(addr_type_own == BLE_ADDR_RANDOM) {
|
||||
if((btm_cb.ble_ctr_cb.addr_mgnt_cb.exist_addr_bit & BTM_BLE_GAP_ADDR_BIT_RANDOM) == BTM_BLE_GAP_ADDR_BIT_RANDOM) {
|
||||
//close privacy
|
||||
#if BLE_PRIVACY_SPT == TRUE
|
||||
if (btm_cb.ble_ctr_cb.privacy_mode != BTM_PRIVACY_NONE) {
|
||||
BTM_BleConfigPrivacy(FALSE, NULL);
|
||||
}
|
||||
#endif
|
||||
btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type = BLE_ADDR_RANDOM;
|
||||
memcpy(btm_cb.ble_ctr_cb.addr_mgnt_cb.private_addr, btm_cb.ble_ctr_cb.addr_mgnt_cb.static_rand_addr, BD_ADDR_LEN);
|
||||
// set address to controller
|
||||
btsnd_hcic_ble_set_random_addr(btm_cb.ble_ctr_cb.addr_mgnt_cb.static_rand_addr);
|
||||
|
||||
} else if((btm_cb.ble_ctr_cb.addr_mgnt_cb.exist_addr_bit & BTM_BLE_GAP_ADDR_BIT_RESOLVABLE) == BTM_BLE_GAP_ADDR_BIT_RESOLVABLE) {
|
||||
btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type = BLE_ADDR_RANDOM;
|
||||
memcpy(btm_cb.ble_ctr_cb.addr_mgnt_cb.private_addr, btm_cb.ble_ctr_cb.addr_mgnt_cb.resolvale_addr, BD_ADDR_LEN);
|
||||
btsnd_hcic_ble_set_random_addr(btm_cb.ble_ctr_cb.addr_mgnt_cb.resolvale_addr);
|
||||
}else {
|
||||
BTM_TRACE_ERROR ("No random address yet, please set random address and try\n");
|
||||
return BTM_ILLEGAL_VALUE;
|
||||
}
|
||||
} else if(addr_type_own == BLE_ADDR_PUBLIC_ID || addr_type_own == BLE_ADDR_RANDOM_ID) {
|
||||
if((btm_cb.ble_ctr_cb.addr_mgnt_cb.exist_addr_bit & BTM_BLE_GAP_ADDR_BIT_RESOLVABLE) == BTM_BLE_GAP_ADDR_BIT_RESOLVABLE) {
|
||||
addr_type_own = BLE_ADDR_RANDOM;
|
||||
btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type = BLE_ADDR_RANDOM;
|
||||
memcpy(btm_cb.ble_ctr_cb.addr_mgnt_cb.private_addr, btm_cb.ble_ctr_cb.addr_mgnt_cb.resolvale_addr, BD_ADDR_LEN);
|
||||
btsnd_hcic_ble_set_random_addr(btm_cb.ble_ctr_cb.addr_mgnt_cb.resolvale_addr);
|
||||
} else {
|
||||
#if BLE_PRIVACY_SPT == TRUE
|
||||
if(btm_cb.ble_ctr_cb.privacy_mode != BTM_PRIVACY_NONE) {
|
||||
BTM_TRACE_ERROR ("Error state\n");
|
||||
return BTM_ILLEGAL_VALUE;
|
||||
}
|
||||
#endif
|
||||
if(addr_type_own == BLE_ADDR_PUBLIC_ID) {
|
||||
addr_type_own = BLE_ADDR_PUBLIC;
|
||||
btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type = BLE_ADDR_PUBLIC;
|
||||
} else {
|
||||
//own_bda_type == BLE_ADDR_RANDOM_ID
|
||||
if((btm_cb.ble_ctr_cb.addr_mgnt_cb.exist_addr_bit & BTM_BLE_GAP_ADDR_BIT_RANDOM) == BTM_BLE_GAP_ADDR_BIT_RANDOM) {
|
||||
addr_type_own = BLE_ADDR_RANDOM;
|
||||
btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type = BLE_ADDR_RANDOM;
|
||||
memcpy(btm_cb.ble_ctr_cb.addr_mgnt_cb.private_addr, btm_cb.ble_ctr_cb.addr_mgnt_cb.static_rand_addr, BD_ADDR_LEN);
|
||||
btsnd_hcic_ble_set_random_addr(btm_cb.ble_ctr_cb.addr_mgnt_cb.static_rand_addr);
|
||||
} else {
|
||||
BTM_TRACE_ERROR ("No RPA and no random address yet, please set RPA or random address and try\n");
|
||||
return BTM_ILLEGAL_VALUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type = BLE_ADDR_PUBLIC;
|
||||
if (BTM_BleUpdateOwnType(&addr_type_own, NULL) != 0) {
|
||||
return BTM_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
/* If not supporting extended scan support, use the older range for checking */
|
||||
if (btm_cb.cmn_ble_vsc_cb.extended_scan_support == 0) {
|
||||
max_scan_interval = BTM_BLE_SCAN_INT_MAX;
|
||||
|
||||
@@ -37,6 +37,12 @@ tBTM_CB btm_cb;
|
||||
tBTM_CB *btm_cb_ptr;
|
||||
#endif
|
||||
|
||||
#if (BLE_50_FEATURE_SUPPORT == TRUE)
|
||||
extern void btm_ble_extendadvcb_init(void);
|
||||
extern void btm_ble_advrecod_init(void);
|
||||
#endif
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_init
|
||||
@@ -80,6 +86,11 @@ void btm_init (void)
|
||||
btm_ble_sem_init();
|
||||
#endif
|
||||
btm_sec_dev_init();
|
||||
#if (BLE_50_FEATURE_SUPPORT == TRUE)
|
||||
btm_ble_extendadvcb_init();
|
||||
btm_ble_advrecod_init();
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -413,6 +413,7 @@ tBTM_STATUS btm_ble_start_adv(void);
|
||||
tBTM_STATUS btm_ble_stop_adv(void);
|
||||
tBTM_STATUS btm_ble_start_scan(void);
|
||||
void btm_ble_create_ll_conn_complete (UINT8 status);
|
||||
void btm_ble_create_conn_cancel_complete (UINT8 *p);
|
||||
|
||||
/* LE security function from btm_sec.c */
|
||||
#if SMP_INCLUDED == TRUE
|
||||
|
||||
@@ -707,6 +707,10 @@ static void btu_hcif_disconnection_comp_evt (UINT8 *p)
|
||||
|
||||
handle = HCID_GET_HANDLE (handle);
|
||||
|
||||
if (reason != HCI_ERR_PEER_USER && reason != HCI_ERR_CONN_CAUSE_LOCAL_HOST) {
|
||||
HCI_TRACE_WARNING("DiscCmpl evt: hdl=%d, rsn=0x%x", handle, reason);
|
||||
}
|
||||
|
||||
#if BTM_SCO_INCLUDED == TRUE
|
||||
/* If L2CAP doesn't know about it, send it to SCO */
|
||||
if (!l2c_link_hci_disc_comp (handle, reason)) {
|
||||
@@ -1067,6 +1071,9 @@ static void btu_hcif_hdl_command_complete (UINT16 opcode, UINT8 *p, UINT16 evt_l
|
||||
case HCI_BLE_TEST_END:
|
||||
btm_ble_test_command_complete(p);
|
||||
break;
|
||||
case HCI_BLE_CREATE_CONN_CANCEL:
|
||||
btm_ble_create_conn_cancel_complete(p);
|
||||
break;
|
||||
|
||||
#if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
|
||||
case HCI_BLE_ADD_DEV_RESOLVING_LIST:
|
||||
@@ -1126,7 +1133,7 @@ static void btu_hcif_hdl_command_complete (UINT16 opcode, UINT8 *p, UINT16 evt_l
|
||||
uint8_t status;
|
||||
STREAM_TO_UINT8 (status, p);
|
||||
if(status != HCI_SUCCESS) {
|
||||
HCI_TRACE_ERROR("%s opcode 0x%x status 0x%x", __func__, opcode, status);
|
||||
HCI_TRACE_ERROR("CC evt: op=0x%x, status=0x%x", opcode, status);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -1259,7 +1266,7 @@ static void btu_hcif_hdl_command_status (UINT16 opcode, UINT8 status, UINT8 *p_c
|
||||
{
|
||||
uint8_t btm_status = BTM_SUCCESS;
|
||||
if(status != HCI_SUCCESS) {
|
||||
HCI_TRACE_ERROR("%s, Create sync error, the error code = 0x%x", __func__, status);
|
||||
HCI_TRACE_ERROR("CS evt: LE PA CreateSync status=0x%x", status);
|
||||
btm_status = BTM_ILLEGAL_VALUE;
|
||||
}
|
||||
btm_create_sync_callback(btm_status);
|
||||
@@ -1269,7 +1276,7 @@ static void btu_hcif_hdl_command_status (UINT16 opcode, UINT8 status, UINT8 *p_c
|
||||
{
|
||||
uint8_t btm_status = BTM_SUCCESS;
|
||||
if(status != HCI_SUCCESS) {
|
||||
HCI_TRACE_ERROR("%s, Set phy error, the error code = 0x%x", __func__, status);
|
||||
HCI_TRACE_ERROR("CS evt: LE SetPhy status=0x%x", status);
|
||||
btm_status = BTM_ILLEGAL_VALUE;
|
||||
}
|
||||
btm_set_phy_callback(btm_status);
|
||||
@@ -2064,6 +2071,8 @@ static void btu_ble_ext_adv_report_evt(UINT8 *p, UINT16 evt_len)
|
||||
UINT8 num_reports = {0};
|
||||
//UINT8 legacy_event_type = 0;
|
||||
UINT16 evt_type = 0;
|
||||
uint8_t addr_type;
|
||||
BD_ADDR bda;
|
||||
|
||||
if (!p) {
|
||||
HCI_TRACE_ERROR("%s, Invalid params.", __func__);
|
||||
@@ -2095,8 +2104,16 @@ static void btu_ble_ext_adv_report_evt(UINT8 *p, UINT16 evt_len)
|
||||
}
|
||||
}
|
||||
|
||||
STREAM_TO_UINT8(ext_adv_report.addr_type, p);
|
||||
STREAM_TO_BDADDR(ext_adv_report.addr, p);
|
||||
STREAM_TO_UINT8(addr_type, p);
|
||||
STREAM_TO_BDADDR(bda, p);
|
||||
// If it is an anonymous adv, skip address resolution
|
||||
if(addr_type != 0xFF) {
|
||||
#if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
|
||||
btm_identity_addr_to_random_pseudo(bda, &addr_type, FALSE);
|
||||
#endif
|
||||
}
|
||||
ext_adv_report.addr_type = addr_type;
|
||||
memcpy(ext_adv_report.addr, bda, 6);
|
||||
STREAM_TO_UINT8(ext_adv_report.primary_phy, p);
|
||||
STREAM_TO_UINT8(ext_adv_report.secondry_phy, p);
|
||||
STREAM_TO_UINT8(ext_adv_report.sid, p);
|
||||
|
||||
@@ -1568,8 +1568,8 @@ BOOLEAN btsnd_hcic_ble_create_ext_conn(tHCI_CreatExtConn *p_conn)
|
||||
UINT16_TO_STREAM(pp, params->conn_interval_max);
|
||||
UINT16_TO_STREAM(pp, params->conn_latency);
|
||||
UINT16_TO_STREAM(pp, params->sup_timeout);
|
||||
UINT16_TO_STREAM(pp, params->min_ce_len);
|
||||
UINT16_TO_STREAM(pp, params->max_ce_len);
|
||||
UINT16_TO_STREAM(pp, BLE_CE_LEN_MIN);
|
||||
UINT16_TO_STREAM(pp, BLE_CE_LEN_MIN);
|
||||
}
|
||||
|
||||
if (p_conn->init_phy_mask & 0x02) {
|
||||
@@ -1580,8 +1580,8 @@ BOOLEAN btsnd_hcic_ble_create_ext_conn(tHCI_CreatExtConn *p_conn)
|
||||
UINT16_TO_STREAM(pp, params->conn_interval_max);
|
||||
UINT16_TO_STREAM(pp, params->conn_latency);
|
||||
UINT16_TO_STREAM(pp, params->sup_timeout);
|
||||
UINT16_TO_STREAM(pp, params->min_ce_len);
|
||||
UINT16_TO_STREAM(pp, params->max_ce_len);
|
||||
UINT16_TO_STREAM(pp, BLE_CE_LEN_MIN);
|
||||
UINT16_TO_STREAM(pp, BLE_CE_LEN_MIN);
|
||||
}
|
||||
|
||||
if (p_conn->init_phy_mask & 0x04) {
|
||||
@@ -1592,8 +1592,8 @@ BOOLEAN btsnd_hcic_ble_create_ext_conn(tHCI_CreatExtConn *p_conn)
|
||||
UINT16_TO_STREAM(pp, params->conn_interval_max);
|
||||
UINT16_TO_STREAM(pp, params->conn_latency);
|
||||
UINT16_TO_STREAM(pp, params->sup_timeout);
|
||||
UINT16_TO_STREAM(pp, params->min_ce_len);
|
||||
UINT16_TO_STREAM(pp, params->max_ce_len);
|
||||
UINT16_TO_STREAM(pp, BLE_CE_LEN_MIN);
|
||||
UINT16_TO_STREAM(pp, BLE_CE_LEN_MIN);
|
||||
}
|
||||
|
||||
btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p);
|
||||
|
||||
@@ -168,7 +168,11 @@ typedef UINT8 tBTM_BLE_SFP;
|
||||
|
||||
/* default connection interval max */
|
||||
#ifndef BTM_BLE_CONN_INT_MAX_DEF
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#define BTM_BLE_CONN_INT_MAX_DEF 12 /* recommended max: 15 ms = 12 * 1.25 */
|
||||
#else
|
||||
#define BTM_BLE_CONN_INT_MAX_DEF (((MAX_ACL_CONNECTIONS + 1) * 4) > 12 ? ((MAX_ACL_CONNECTIONS + 1) * 4) : 12) /* recommended max: BTM_BLE_CONN_INT_MAX_DEF * 1.25 ms*/
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* default slave latency */
|
||||
@@ -700,8 +704,6 @@ typedef void (tBTM_BLE_PF_PARAM_CBACK) (tBTM_BLE_PF_ACTION action_type,
|
||||
#define MAX_BLE_ADV_INSTANCE 10
|
||||
typedef struct {
|
||||
UINT8 inst_id;
|
||||
BOOLEAN in_use;
|
||||
UINT8 adv_evt;
|
||||
BOOLEAN configured;
|
||||
BOOLEAN legacy_pdu;
|
||||
|
||||
@@ -714,7 +716,6 @@ typedef struct {
|
||||
typedef struct {
|
||||
tBTM_BLE_EXTENDED_INST inst[MAX_BLE_ADV_INSTANCE]; /* dynamic array to store adv instance */
|
||||
UINT8 scan_duplicate;
|
||||
tBTM_BLE_MULTI_ADV_OPQ op_q;
|
||||
} tBTM_BLE_EXTENDED_CB;
|
||||
|
||||
#define BTM_BLE_GAP_SET_EXT_ADV_PROP_CONNECTABLE (1 << 0)
|
||||
|
||||
@@ -455,6 +455,9 @@ typedef struct t_l2c_linkcb {
|
||||
/* connection parameters update order:
|
||||
waiting_update_conn_xx -> updating_conn_xx -> current_used_conn_xx
|
||||
*/
|
||||
/* create connection retry count*/
|
||||
UINT8 retry_create_con;
|
||||
UINT32 start_time_s;
|
||||
#endif
|
||||
|
||||
#if (L2CAP_ROUND_ROBIN_CHANNEL_SERVICE == TRUE)
|
||||
@@ -597,6 +600,7 @@ extern BOOLEAN l2cu_start_post_bond_timer (UINT16 handle);
|
||||
extern void l2cu_release_lcb (tL2C_LCB *p_lcb);
|
||||
extern tL2C_LCB *l2cu_find_lcb_by_bd_addr (BD_ADDR p_bd_addr, tBT_TRANSPORT transport);
|
||||
extern tL2C_LCB *l2cu_find_lcb_by_handle (UINT16 handle);
|
||||
extern uint8_t l2cu_plcb_active_count(void);
|
||||
extern void l2cu_update_lcb_4_bonding (BD_ADDR p_bd_addr, BOOLEAN is_bonding);
|
||||
|
||||
extern UINT8 l2cu_get_conn_role (tL2C_LCB *p_this_lcb);
|
||||
|
||||
@@ -1833,7 +1833,7 @@ UINT16 L2CA_SendFixedChnlData (UINT16 fixed_cid, BD_ADDR rem_bda, BT_HDR *p_buf)
|
||||
}
|
||||
|
||||
// If already congested, do not accept any more packets
|
||||
if (p_lcb->p_fixed_ccbs[fixed_cid - L2CAP_FIRST_FIXED_CHNL]->cong_sent) {
|
||||
if (p_lcb->p_fixed_ccbs[fixed_cid - L2CAP_FIRST_FIXED_CHNL]->cong_sent && fixed_cid != L2CAP_SMP_CID) {
|
||||
L2CAP_TRACE_DEBUG ("L2CAP - CID: 0x%04x cannot send, already congested\
|
||||
xmit_hold_q.count: %u buff_quota: %u", fixed_cid,
|
||||
fixed_queue_length(p_lcb->p_fixed_ccbs[fixed_cid - L2CAP_FIRST_FIXED_CHNL]->xmit_hold_q),
|
||||
|
||||
@@ -51,6 +51,7 @@ const tHCI_ExtConnParams ext_conn_params = {
|
||||
#endif // #if (BLE_50_FEATURE_SUPPORT == TRUE)
|
||||
|
||||
static BOOLEAN l2cble_start_conn_update (tL2C_LCB *p_lcb);
|
||||
extern int64_t esp_system_get_time(void);
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
@@ -204,6 +205,10 @@ BOOLEAN L2CA_EnableUpdateBleConnParams (BD_ADDR rem_bda, BOOLEAN enable)
|
||||
if (p_lcb->current_used_conn_interval <= BTM_BLE_CONN_INT_MAX_DEF && (p_lcb->conn_update_mask & L2C_BLE_CONN_UPDATE_DISABLE) == 0){
|
||||
return (FALSE);
|
||||
}
|
||||
bool is_disable = (p_lcb->conn_update_mask & L2C_BLE_CONN_UPDATE_DISABLE);
|
||||
if(l2cu_plcb_active_count() >1 && !(enable && is_disable)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (enable) {
|
||||
p_lcb->conn_update_mask &= ~L2C_BLE_CONN_UPDATE_DISABLE;
|
||||
@@ -363,7 +368,7 @@ void l2cble_scanner_conn_comp (UINT16 handle, BD_ADDR bda, tBLE_ADDR_TYPE type,
|
||||
p_dev_rec->conn_params.max_conn_int,
|
||||
p_dev_rec->conn_params.slave_latency,
|
||||
p_dev_rec->conn_params.supervision_tout,
|
||||
0, 0);
|
||||
BLE_CE_LEN_MIN, BLE_CE_LEN_MIN);
|
||||
}
|
||||
|
||||
/* Tell BTM Acl management about the link */
|
||||
@@ -524,7 +529,7 @@ static BOOLEAN l2cble_start_conn_update (tL2C_LCB *p_lcb)
|
||||
#endif
|
||||
) {
|
||||
btsnd_hcic_ble_upd_ll_conn_params(p_lcb->handle, min_conn_int, max_conn_int,
|
||||
slave_latency, supervision_tout, 0, 0);
|
||||
slave_latency, supervision_tout, BLE_CE_LEN_MIN, BLE_CE_LEN_MIN);
|
||||
} else {
|
||||
l2cu_send_peer_ble_par_req (p_lcb, min_conn_int, max_conn_int, slave_latency, supervision_tout);
|
||||
}
|
||||
@@ -552,7 +557,7 @@ static BOOLEAN l2cble_start_conn_update (tL2C_LCB *p_lcb)
|
||||
#endif
|
||||
) {
|
||||
btsnd_hcic_ble_upd_ll_conn_params(p_lcb->handle, p_lcb->waiting_update_conn_min_interval,
|
||||
p_lcb->waiting_update_conn_max_interval, p_lcb->waiting_update_conn_latency, p_lcb->waiting_update_conn_timeout, 0, 0);
|
||||
p_lcb->waiting_update_conn_max_interval, p_lcb->waiting_update_conn_latency, p_lcb->waiting_update_conn_timeout, BLE_CE_LEN_MIN, BLE_CE_LEN_MIN);
|
||||
} else {
|
||||
l2cu_send_peer_ble_par_req (p_lcb, p_lcb->waiting_update_conn_min_interval, p_lcb->waiting_update_conn_max_interval,
|
||||
p_lcb->waiting_update_conn_latency, p_lcb->waiting_update_conn_timeout);
|
||||
@@ -591,7 +596,7 @@ void l2cble_process_conn_update_evt (UINT16 handle, UINT8 status, UINT16 conn_in
|
||||
/* See if we have a link control block for the remote device */
|
||||
p_lcb = l2cu_find_lcb_by_handle(handle);
|
||||
if (!p_lcb) {
|
||||
L2CAP_TRACE_WARNING("l2cble_process_conn_update_evt: Invalid handle: %d", handle);
|
||||
L2CAP_TRACE_WARNING("le con upd: inv hdl=%d", handle);
|
||||
return;
|
||||
}
|
||||
if (status == HCI_SUCCESS){
|
||||
@@ -599,7 +604,7 @@ void l2cble_process_conn_update_evt (UINT16 handle, UINT8 status, UINT16 conn_in
|
||||
p_lcb->current_used_conn_latency = conn_latency;
|
||||
p_lcb->current_used_conn_timeout = conn_timeout;
|
||||
}else{
|
||||
L2CAP_TRACE_WARNING("l2cble_process_conn_update_evt: Error status: %d", status);
|
||||
L2CAP_TRACE_WARNING("le con upd: err_stat=0x%x", status);
|
||||
}
|
||||
|
||||
p_lcb->conn_update_mask &= ~L2C_BLE_UPDATE_PENDING;
|
||||
@@ -617,7 +622,7 @@ void l2cble_process_conn_update_evt (UINT16 handle, UINT8 status, UINT16 conn_in
|
||||
|
||||
btu_stop_timer (&p_lcb->timer_entry);
|
||||
|
||||
L2CAP_TRACE_DEBUG("l2cble_process_conn_update_evt: conn_update_mask=%d", p_lcb->conn_update_mask);
|
||||
L2CAP_TRACE_DEBUG("le con upd: conn_update_mask=%d", p_lcb->conn_update_mask);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
@@ -801,7 +806,6 @@ BOOLEAN l2cble_init_direct_conn (tL2C_LCB *p_lcb)
|
||||
|
||||
#if ( (defined BLE_PRIVACY_SPT) && (BLE_PRIVACY_SPT == TRUE))
|
||||
own_addr_type = btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type;
|
||||
|
||||
#if (!CONTROLLER_RPA_LIST_ENABLE)
|
||||
if(dev_rec_exist) {
|
||||
// if the current address information is valid, get the real address information
|
||||
@@ -825,7 +829,7 @@ BOOLEAN l2cble_init_direct_conn (tL2C_LCB *p_lcb)
|
||||
|
||||
#endif // (!CONTROLLER_RPA_LIST_ENABLE)
|
||||
|
||||
#if CONTROLLER_RPA_LIST_ENABLE
|
||||
#if (CONTROLLER_RPA_LIST_ENABLE)
|
||||
|
||||
if (p_dev_rec->ble.in_controller_list & BTM_RESOLVING_LIST_BIT) {
|
||||
if (btm_cb.ble_ctr_cb.privacy_mode >= BTM_PRIVACY_1_2) {
|
||||
@@ -839,7 +843,6 @@ BOOLEAN l2cble_init_direct_conn (tL2C_LCB *p_lcb)
|
||||
}
|
||||
|
||||
#endif // CONTROLLER_RPA_LIST_ENABLE
|
||||
|
||||
#endif // (defined BLE_PRIVACY_SPT) && (BLE_PRIVACY_SPT == TRUE)
|
||||
|
||||
if (!btm_ble_topology_check(BTM_BLE_STATE_INIT)) {
|
||||
@@ -847,6 +850,18 @@ BOOLEAN l2cble_init_direct_conn (tL2C_LCB *p_lcb)
|
||||
L2CAP_TRACE_ERROR("initate direct connection fail, topology limitation");
|
||||
return FALSE;
|
||||
}
|
||||
uint32_t link_timeout = L2CAP_BLE_LINK_CONNECT_TOUT;
|
||||
if(GATTC_CONNECT_RETRY_COUNT) {
|
||||
if(!p_lcb->retry_create_con) {
|
||||
p_lcb->start_time_s = (esp_system_get_time()/1000);
|
||||
}
|
||||
uint32_t current_time = (esp_system_get_time()/1000);
|
||||
link_timeout = (L2CAP_BLE_LINK_CONNECT_TOUT*1000 - (current_time - p_lcb->start_time_s))/1000;
|
||||
|
||||
if(link_timeout == 0 || link_timeout > L2CAP_BLE_LINK_CONNECT_TOUT) {
|
||||
link_timeout = L2CAP_BLE_LINK_CONNECT_TOUT;
|
||||
}
|
||||
}
|
||||
|
||||
if (!p_lcb->is_aux) {
|
||||
if (!btsnd_hcic_ble_create_ll_conn (scan_int,/* UINT16 scan_int */
|
||||
@@ -863,8 +878,8 @@ BOOLEAN l2cble_init_direct_conn (tL2C_LCB *p_lcb)
|
||||
p_dev_rec->conn_params.slave_latency : BTM_BLE_CONN_SLAVE_LATENCY_DEF), /* UINT16 conn_latency */
|
||||
(UINT16) ((p_dev_rec->conn_params.supervision_tout != BTM_BLE_CONN_PARAM_UNDEF) ?
|
||||
p_dev_rec->conn_params.supervision_tout : BTM_BLE_CONN_TIMEOUT_DEF), /* conn_timeout */
|
||||
0, /* UINT16 min_len */
|
||||
0)) { /* UINT16 max_len */
|
||||
BLE_CE_LEN_MIN, /* UINT16 min_len */
|
||||
BLE_CE_LEN_MIN)) { /* UINT16 max_len */
|
||||
l2cu_release_lcb (p_lcb);
|
||||
L2CAP_TRACE_ERROR("initate direct connection fail, no resources");
|
||||
return (FALSE);
|
||||
@@ -872,13 +887,28 @@ BOOLEAN l2cble_init_direct_conn (tL2C_LCB *p_lcb)
|
||||
p_lcb->link_state = LST_CONNECTING;
|
||||
l2cb.is_ble_connecting = TRUE;
|
||||
memcpy (l2cb.ble_connecting_bda, p_lcb->remote_bd_addr, BD_ADDR_LEN);
|
||||
btu_start_timer (&p_lcb->timer_entry, BTU_TTYPE_L2CAP_LINK, L2CAP_BLE_LINK_CONNECT_TOUT);
|
||||
btu_start_timer (&p_lcb->timer_entry, BTU_TTYPE_L2CAP_LINK, link_timeout);
|
||||
btm_ble_set_conn_st (BLE_DIR_CONN);
|
||||
|
||||
return (TRUE);
|
||||
}
|
||||
} else {
|
||||
#if (BLE_50_FEATURE_SUPPORT == TRUE)
|
||||
|
||||
/*
|
||||
* 0x00 Public Device Address
|
||||
* 0x01 Random Device Address
|
||||
* 0x02 Public Identity Address (corresponds to Resolved Private Address)
|
||||
* 0x03 Random (static) Identity Address (corresponds to Resolved Private Address)
|
||||
* 0xFF No address provided (anonymous advertisement)
|
||||
*/
|
||||
|
||||
if ((peer_addr_type & BLE_ADDR_RANDOM) == BLE_ADDR_RANDOM) {
|
||||
peer_addr_type = BLE_ADDR_RANDOM;
|
||||
} else {
|
||||
peer_addr_type = BLE_ADDR_PUBLIC;
|
||||
}
|
||||
|
||||
tHCI_CreatExtConn aux_conn = {0};
|
||||
aux_conn.filter_policy = FALSE;
|
||||
aux_conn.own_addr_type = own_addr_type;
|
||||
@@ -899,7 +929,7 @@ BOOLEAN l2cble_init_direct_conn (tL2C_LCB *p_lcb)
|
||||
p_lcb->link_state = LST_CONNECTING;
|
||||
l2cb.is_ble_connecting = TRUE;
|
||||
memcpy (l2cb.ble_connecting_bda, p_lcb->remote_bd_addr, BD_ADDR_LEN);
|
||||
btu_start_timer (&p_lcb->timer_entry, BTU_TTYPE_L2CAP_LINK, L2CAP_BLE_LINK_CONNECT_TOUT);
|
||||
btu_start_timer (&p_lcb->timer_entry, BTU_TTYPE_L2CAP_LINK, link_timeout);
|
||||
btm_ble_set_conn_st (BLE_DIR_CONN);
|
||||
if(!btsnd_hcic_ble_create_ext_conn(&aux_conn)) {
|
||||
l2cu_release_lcb (p_lcb);
|
||||
@@ -1104,12 +1134,12 @@ void l2cble_process_rc_param_request_evt(UINT16 handle, UINT16 int_min, UINT16 i
|
||||
/* if update is enabled, always accept connection parameter update */
|
||||
if ((p_lcb->conn_update_mask & L2C_BLE_CONN_UPDATE_DISABLE) == 0) {
|
||||
p_lcb->conn_update_mask |= L2C_BLE_UPDATE_PENDING;
|
||||
btsnd_hcic_ble_rc_param_req_reply(handle, int_min, int_max, latency, timeout, 0, 0);
|
||||
btsnd_hcic_ble_rc_param_req_reply(handle, int_min, int_max, latency, timeout, BLE_CE_LEN_MIN, BLE_CE_LEN_MIN);
|
||||
}else {
|
||||
/* always accept connection parameters request which is sent by itself */
|
||||
if (int_max == BTM_BLE_CONN_INT_MIN) {
|
||||
p_lcb->conn_update_mask |= L2C_BLE_UPDATE_PENDING;
|
||||
btsnd_hcic_ble_rc_param_req_reply(handle, int_min, int_max, latency, timeout, 0, 0);
|
||||
btsnd_hcic_ble_rc_param_req_reply(handle, int_min, int_max, latency, timeout, BLE_CE_LEN_MIN, BLE_CE_LEN_MIN);
|
||||
}else {
|
||||
L2CAP_TRACE_EVENT ("L2CAP - LE - update currently disabled");
|
||||
p_lcb->conn_update_mask |= L2C_BLE_NEW_CONN_PARAM;
|
||||
|
||||
@@ -42,6 +42,11 @@
|
||||
|
||||
static BOOLEAN l2c_link_send_to_lower (tL2C_LCB *p_lcb, BT_HDR *p_buf);
|
||||
|
||||
#if (BLE_50_FEATURE_SUPPORT == TRUE)
|
||||
extern tBTM_STATUS BTM_BleStartExtAdvRestart(uint8_t handle);
|
||||
#endif// #if (BLE_50_FEATURE_SUPPORT == TRUE)
|
||||
extern bool btm_ble_inter_get(void);
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function l2c_link_hci_conn_req
|
||||
@@ -333,7 +338,6 @@ void l2c_link_sec_comp (BD_ADDR p_bda, tBT_TRANSPORT transport, void *p_ref_data
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function l2c_link_hci_disc_comp
|
||||
@@ -456,7 +460,38 @@ BOOLEAN l2c_link_hci_disc_comp (UINT16 handle, UINT8 reason)
|
||||
}
|
||||
|
||||
p_lcb->p_pending_ccb = NULL;
|
||||
#if (BLE_INCLUDED == TRUE && GATTC_CONNECT_RETRY_EN == TRUE)
|
||||
if(reason == HCI_ERR_CONN_FAILED_ESTABLISHMENT && p_lcb->transport == BT_TRANSPORT_LE) {
|
||||
|
||||
if(p_lcb->link_role == HCI_ROLE_MASTER && p_lcb->retry_create_con < GATTC_CONNECT_RETRY_COUNT) {
|
||||
L2CAP_TRACE_DEBUG("master retry connect, retry count %d reason 0x%x\n", p_lcb->retry_create_con, reason);
|
||||
p_lcb->retry_create_con ++;
|
||||
// create connection retry
|
||||
if (l2cu_create_conn(p_lcb, BT_TRANSPORT_LE)) {
|
||||
btm_acl_removed (p_lcb->remote_bd_addr, BT_TRANSPORT_LE);
|
||||
lcb_is_free = FALSE; /* still using this lcb */
|
||||
}
|
||||
}
|
||||
|
||||
#if (BLE_50_FEATURE_SUPPORT == TRUE)
|
||||
if(btm_ble_inter_get() && p_lcb->link_role == HCI_ROLE_SLAVE && p_lcb->retry_create_con < GATTC_CONNECT_RETRY_COUNT) {
|
||||
p_lcb->retry_create_con ++;
|
||||
L2CAP_TRACE_DEBUG("slave restart extend adv, retry count %d reason 0x%x\n", p_lcb->retry_create_con, reason);
|
||||
BTM_BleStartExtAdvRestart(handle);
|
||||
}
|
||||
#endif // #if (BLE_50_FEATURE_SUPPORT == TRUE)
|
||||
|
||||
#if (BLE_42_FEATURE_SUPPORT == TRUE)
|
||||
if(!btm_ble_inter_get() && p_lcb->link_role == HCI_ROLE_SLAVE && p_lcb->retry_create_con < GATTC_CONNECT_RETRY_COUNT) {
|
||||
p_lcb->retry_create_con ++;
|
||||
L2CAP_TRACE_DEBUG("slave resatrt adv, retry count %d reason 0x%x\n", p_lcb->retry_create_con, reason);
|
||||
btm_ble_start_adv();
|
||||
}
|
||||
#endif // #if (BLE_42_FEATURE_SUPPORT == TRUE)
|
||||
}
|
||||
|
||||
|
||||
#endif // #if (BLE_INCLUDED == TRUE)
|
||||
/* Release the LCB */
|
||||
if (lcb_is_free) {
|
||||
l2cu_release_lcb (p_lcb);
|
||||
|
||||
@@ -158,6 +158,10 @@ void l2cu_release_lcb (tL2C_LCB *p_lcb)
|
||||
|
||||
p_lcb->in_use = FALSE;
|
||||
p_lcb->is_bonding = FALSE;
|
||||
#if (BLE_INCLUDED == TRUE)
|
||||
p_lcb->retry_create_con = 0;
|
||||
p_lcb->start_time_s = 0;
|
||||
#endif // #if (BLE_INCLUDED == TRUE)
|
||||
|
||||
/* Stop and release timers */
|
||||
btu_free_timer (&p_lcb->timer_entry);
|
||||
@@ -335,6 +339,26 @@ tL2C_LCB *l2cu_find_free_lcb (void)
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
uint8_t l2cu_plcb_active_count(void)
|
||||
{
|
||||
list_node_t *p_node = NULL;
|
||||
tL2C_LCB *p_lcb = NULL;
|
||||
uint8_t active_count = 0;
|
||||
for (p_node = list_begin(l2cb.p_lcb_pool); p_node; p_node = list_next(p_node)) {
|
||||
p_lcb = list_node(p_node);
|
||||
if (p_lcb && p_lcb->in_use) {
|
||||
active_count ++;
|
||||
}
|
||||
}
|
||||
if (active_count >= MAX_L2CAP_CHANNELS) {
|
||||
L2CAP_TRACE_ERROR("error active count");
|
||||
active_count = 0;
|
||||
}
|
||||
L2CAP_TRACE_DEBUG("plcb active count %d", active_count);
|
||||
return active_count;
|
||||
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function l2cu_get_conn_role
|
||||
@@ -1456,9 +1480,11 @@ void l2cu_change_pri_ccb (tL2C_CCB *p_ccb, tL2CAP_CHNL_PRIORITY priority)
|
||||
** Returns pointer to CCB, or NULL if none
|
||||
**
|
||||
*******************************************************************************/
|
||||
bool l2cu_find_ccb_in_list(void *p_ccb_node, void *p_local_cid);
|
||||
tL2C_CCB *l2cu_allocate_ccb (tL2C_LCB *p_lcb, UINT16 cid)
|
||||
{
|
||||
tL2C_CCB *p_ccb = NULL;
|
||||
uint16_t tmp_cid = L2CAP_BASE_APPL_CID;
|
||||
L2CAP_TRACE_DEBUG ("l2cu_allocate_ccb: cid 0x%04x", cid);
|
||||
|
||||
p_ccb = l2cu_find_free_ccb ();
|
||||
@@ -1481,7 +1507,13 @@ tL2C_CCB *l2cu_allocate_ccb (tL2C_LCB *p_lcb, UINT16 cid)
|
||||
p_ccb->in_use = TRUE;
|
||||
|
||||
/* Get a CID for the connection */
|
||||
p_ccb->local_cid = L2CAP_BASE_APPL_CID + (list_length(l2cb.p_ccb_pool) - 1);
|
||||
for (tmp_cid = L2CAP_BASE_APPL_CID; tmp_cid < MAX_L2CAP_CHANNELS + L2CAP_BASE_APPL_CID; tmp_cid++) {
|
||||
if (list_foreach(l2cb.p_ccb_pool, l2cu_find_ccb_in_list, &tmp_cid) == NULL) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert(tmp_cid != MAX_L2CAP_CHANNELS + L2CAP_BASE_APPL_CID);
|
||||
p_ccb->local_cid = tmp_cid;
|
||||
p_ccb->p_lcb = p_lcb;
|
||||
p_ccb->p_rcb = NULL;
|
||||
p_ccb->should_free_rcb = false;
|
||||
|
||||
@@ -1540,9 +1540,11 @@ void smp_idle_terminate(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
|
||||
*******************************************************************************/
|
||||
void smp_fast_conn_param(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
|
||||
{
|
||||
#if (BT_MULTI_CONNECTION_ENBALE == FALSE)
|
||||
if(p_cb->role == BTM_ROLE_MASTER) {
|
||||
L2CA_EnableUpdateBleConnParams(p_cb->pairing_bda, FALSE);
|
||||
}
|
||||
#endif
|
||||
#if (SMP_SLAVE_CON_PARAMS_UPD_ENABLE == TRUE)
|
||||
else {
|
||||
tBTM_SEC_DEV_REC *p_rec = btm_find_dev (p_cb->pairing_bda);
|
||||
@@ -1554,7 +1556,9 @@ void smp_fast_conn_param(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
|
||||
some peripherals are not able to revert to fast connection parameters
|
||||
during the start of service discovery. Connection paramter updates
|
||||
get enabled again once service discovery completes. */
|
||||
#if (BT_MULTI_CONNECTION_ENBALE == FALSE)
|
||||
L2CA_EnableUpdateBleConnParams(p_cb->pairing_bda, FALSE);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1021,7 +1021,9 @@ void smp_proc_pairing_cmpl(tSMP_CB *p_cb)
|
||||
//clear flag
|
||||
p_rec->ble.skip_update_conn_param = false;
|
||||
} else {
|
||||
#if (BT_MULTI_CONNECTION_ENBALE == FALSE)
|
||||
L2CA_EnableUpdateBleConnParams(p_cb->pairing_bda, TRUE);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -72,11 +72,15 @@ config BT_NIMBLE_LOG_LEVEL
|
||||
|
||||
config BT_NIMBLE_MAX_CONNECTIONS
|
||||
int "Maximum number of concurrent connections"
|
||||
range 1 9
|
||||
default BTDM_CTRL_BLE_MAX_CONN
|
||||
range 1 8 if (IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S3)
|
||||
range 1 9 if IDF_TARGET_ESP32
|
||||
default 3
|
||||
depends on BT_NIMBLE_ENABLED
|
||||
help
|
||||
Defines maximum number of concurrent BLE connections
|
||||
Defines maximum number of concurrent BLE connections. For ESP32, user
|
||||
is expected to configure BTDM_CTRL_BLE_MAX_CONN from controller menu
|
||||
along with this option. Similarly for ESP32-C3 or ESP32-S3, user is expected to
|
||||
configure BT_CTRL_BLE_MAX_ACT from controller menu.
|
||||
|
||||
config BT_NIMBLE_MAX_BONDS
|
||||
int "Maximum number of bonds to save across reboots"
|
||||
@@ -431,6 +435,22 @@ config BT_NIMBLE_HOST_BASED_PRIVACY
|
||||
Use this option to do host based Random Private Address resolution.
|
||||
If this option is disabled then controller based privacy is used.
|
||||
|
||||
config BT_NIMBLE_ENABLE_CONN_REATTEMPT
|
||||
bool "Enable connection reattempts on connection establishment error"
|
||||
default y if (IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S3)
|
||||
default n if IDF_TARGET_ESP32
|
||||
help
|
||||
Enable to make the NimBLE host to reattempt GAP connection on connection
|
||||
establishment failure.
|
||||
|
||||
config BT_NIMBLE_MAX_CONN_REATTEMPT
|
||||
int "Maximum number connection reattempts"
|
||||
range 1 7
|
||||
default 3
|
||||
depends on BT_NIMBLE_ENABLED && BT_NIMBLE_ENABLE_CONN_REATTEMPT
|
||||
help
|
||||
Defines maximum number of connection reattempts.
|
||||
|
||||
config BT_NIMBLE_EXT_ADV
|
||||
bool "Enable extended advertising."
|
||||
default n
|
||||
|
||||
@@ -252,6 +252,7 @@ static struct os_mbuf *ble_hci_trans_acl_buf_alloc(void)
|
||||
static void ble_hci_rx_acl(uint8_t *data, uint16_t len)
|
||||
{
|
||||
struct os_mbuf *m;
|
||||
int rc;
|
||||
int sr;
|
||||
if (len < BLE_HCI_DATA_HDR_SZ || len > MYNEWT_VAL(BLE_ACL_BUF_SIZE)) {
|
||||
return;
|
||||
@@ -260,9 +261,11 @@ static void ble_hci_rx_acl(uint8_t *data, uint16_t len)
|
||||
m = ble_hci_trans_acl_buf_alloc();
|
||||
|
||||
if (!m) {
|
||||
ESP_LOGE(TAG, "%s failed to allocate ACL buffers; increase ACL_BUF_COUNT", __func__);
|
||||
return;
|
||||
}
|
||||
if (os_mbuf_append(m, data, len)) {
|
||||
if ((rc = os_mbuf_append(m, data, len)) != 0) {
|
||||
ESP_LOGE(TAG, "%s failed to os_mbuf_append; rc = %d", __func__, rc);
|
||||
os_mbuf_free_chain(m);
|
||||
return;
|
||||
}
|
||||
|
||||
Submodule components/bt/host/nimble/nimble updated: c6f69c1261...5bb7b40227
@@ -488,6 +488,7 @@ esp_err_t esp_bt_sleep_disable(void);
|
||||
* Note that scan duplicate list will be automatically cleared when the maximum amount of device in the filter is reached
|
||||
* the amount of device in the filter can be configured in menuconfig.
|
||||
*
|
||||
* @note This function name is incorrectly spelled, it will be fixed in release 5.x version.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK : success
|
||||
|
||||
@@ -26,7 +26,7 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
#define ESP_BT_CTRL_CONFIG_MAGIC_VAL 0x5A5AA5A5
|
||||
#define ESP_BT_CTRL_CONFIG_VERSION 0x02101290
|
||||
#define ESP_BT_CTRL_CONFIG_VERSION 0x02103310
|
||||
|
||||
#define ESP_BT_HCI_TL_MAGIC_VALUE 0xfadebead
|
||||
#define ESP_BT_HCI_TL_VERSION 0x00010000
|
||||
@@ -96,6 +96,7 @@ enum {
|
||||
#ifdef CONFIG_BT_ENABLED
|
||||
|
||||
#define BT_CTRL_BLE_MAX_ACT_LIMIT 10 //Maximum BLE activity limitation
|
||||
#define SLAVE_CE_LEN_MIN_DEFAULT 5
|
||||
|
||||
#ifdef CONFIG_BT_CTRL_SCAN_DUPL_TYPE
|
||||
#define SCAN_DUPLICATE_TYPE_VALUE CONFIG_BT_CTRL_SCAN_DUPL_TYPE
|
||||
@@ -133,6 +134,8 @@ enum {
|
||||
|
||||
#define CFG_NASK CFG_MASK_BIT_SCAN_DUPLICATE_OPTION
|
||||
|
||||
#define BLE_HW_TARGET_CODE_ESP32C3_CHIP_ECO0 (0x01010000)
|
||||
|
||||
#define BT_CONTROLLER_INIT_CONFIG_DEFAULT() { \
|
||||
.magic = ESP_BT_CTRL_CONFIG_MAGIC_VAL, \
|
||||
.version = ESP_BT_CTRL_CONFIG_VERSION, \
|
||||
@@ -158,6 +161,8 @@ enum {
|
||||
.normal_adv_size = NORMAL_SCAN_DUPLICATE_CACHE_SIZE, \
|
||||
.mesh_adv_size = MESH_DUPLICATE_SCAN_CACHE_SIZE, \
|
||||
.coex_phy_coded_tx_rx_time_limit = CONFIG_BT_CTRL_COEX_PHY_CODED_TX_RX_TLIM_EFF, \
|
||||
.hw_target_code = BLE_HW_TARGET_CODE_ESP32C3_CHIP_ECO0, \
|
||||
.slave_ce_len_min = SLAVE_CE_LEN_MIN_DEFAULT, \
|
||||
};
|
||||
|
||||
#else
|
||||
@@ -221,6 +226,8 @@ typedef struct {
|
||||
uint16_t normal_adv_size; /*!< Normal adv size for scan duplicate */
|
||||
uint16_t mesh_adv_size; /*!< Mesh adv size for scan duplicate */
|
||||
uint8_t coex_phy_coded_tx_rx_time_limit; /*!< limit on max tx/rx time in case of connection using CODED-PHY with Wi-Fi coexistence */
|
||||
uint32_t hw_target_code; /*!< hardware target */
|
||||
uint8_t slave_ce_len_min;
|
||||
} esp_bt_controller_config_t;
|
||||
|
||||
/**
|
||||
@@ -263,22 +270,23 @@ typedef enum {
|
||||
* @brief Bluetooth TX power level(index), it's just a index corresponding to power(dbm).
|
||||
*/
|
||||
typedef enum {
|
||||
ESP_PWR_LVL_N12 = 0, /*!< Corresponding to -12dbm */
|
||||
ESP_PWR_LVL_N9 = 1, /*!< Corresponding to -9dbm */
|
||||
ESP_PWR_LVL_N6 = 2, /*!< Corresponding to -6dbm */
|
||||
ESP_PWR_LVL_N3 = 3, /*!< Corresponding to -3dbm */
|
||||
ESP_PWR_LVL_N0 = 4, /*!< Corresponding to 0dbm */
|
||||
ESP_PWR_LVL_P3 = 5, /*!< Corresponding to +3dbm */
|
||||
ESP_PWR_LVL_P6 = 6, /*!< Corresponding to +6dbm */
|
||||
ESP_PWR_LVL_P9 = 7, /*!< Corresponding to +9dbm */
|
||||
ESP_PWR_LVL_N14 = ESP_PWR_LVL_N12, /*!< Backward compatibility! Setting to -14dbm will actually result to -12dbm */
|
||||
ESP_PWR_LVL_N11 = ESP_PWR_LVL_N9, /*!< Backward compatibility! Setting to -11dbm will actually result to -9dbm */
|
||||
ESP_PWR_LVL_N8 = ESP_PWR_LVL_N6, /*!< Backward compatibility! Setting to -8dbm will actually result to -6dbm */
|
||||
ESP_PWR_LVL_N5 = ESP_PWR_LVL_N3, /*!< Backward compatibility! Setting to -5dbm will actually result to -3dbm */
|
||||
ESP_PWR_LVL_N2 = ESP_PWR_LVL_N0, /*!< Backward compatibility! Setting to -2dbm will actually result to 0dbm */
|
||||
ESP_PWR_LVL_P1 = ESP_PWR_LVL_P3, /*!< Backward compatibility! Setting to +1dbm will actually result to +3dbm */
|
||||
ESP_PWR_LVL_P4 = ESP_PWR_LVL_P6, /*!< Backward compatibility! Setting to +4dbm will actually result to +6dbm */
|
||||
ESP_PWR_LVL_P7 = ESP_PWR_LVL_P9, /*!< Backward compatibility! Setting to +7dbm will actually result to +9dbm */
|
||||
ESP_PWR_LVL_N27 = 0, /*!< Corresponding to -27dbm */
|
||||
ESP_PWR_LVL_N24 = 1, /*!< Corresponding to -24dbm */
|
||||
ESP_PWR_LVL_N21 = 2, /*!< Corresponding to -21dbm */
|
||||
ESP_PWR_LVL_N18 = 3, /*!< Corresponding to -18dbm */
|
||||
ESP_PWR_LVL_N15 = 4, /*!< Corresponding to -15dbm */
|
||||
ESP_PWR_LVL_N12 = 5, /*!< Corresponding to -12dbm */
|
||||
ESP_PWR_LVL_N9 = 6, /*!< Corresponding to -9dbm */
|
||||
ESP_PWR_LVL_N6 = 7, /*!< Corresponding to -6dbm */
|
||||
ESP_PWR_LVL_N3 = 8, /*!< Corresponding to -3dbm */
|
||||
ESP_PWR_LVL_N0 = 9, /*!< Corresponding to 0dbm */
|
||||
ESP_PWR_LVL_P3 = 10, /*!< Corresponding to +3dbm */
|
||||
ESP_PWR_LVL_P6 = 11, /*!< Corresponding to +6dbm */
|
||||
ESP_PWR_LVL_P9 = 12, /*!< Corresponding to +9dbm */
|
||||
ESP_PWR_LVL_P12 = 13, /*!< Corresponding to +12dbm */
|
||||
ESP_PWR_LVL_P15 = 14, /*!< Corresponding to +15dbm */
|
||||
ESP_PWR_LVL_P18 = 15, /*!< Corresponding to +18dbm */
|
||||
ESP_PWR_LVL_INVALID = 0xFF, /*!< Indicates an invalid value */
|
||||
} esp_power_level_t;
|
||||
|
||||
/**
|
||||
|
||||
@@ -76,7 +76,8 @@ idf_component_register(SRCS "${srcs}"
|
||||
INCLUDE_DIRS ${includes}
|
||||
PRIV_INCLUDE_DIRS "include/driver"
|
||||
PRIV_REQUIRES efuse esp_pm esp_timer esp_ipc
|
||||
REQUIRES esp_ringbuf freertos soc hal esp_hw_support)
|
||||
REQUIRES esp_ringbuf freertos soc hal esp_hw_support
|
||||
LDFRAGMENTS linker.lf)
|
||||
# (REQUIRES cannot hide soc headers, since many arguments in the driver headers are chip-dependent)
|
||||
|
||||
# uses C11 atomic feature
|
||||
|
||||
@@ -87,6 +87,48 @@ menu "Driver configurations"
|
||||
- Alert logging (i.e., setting of the TWAI_ALERT_AND_LOG flag)
|
||||
will have no effect.
|
||||
|
||||
config TWAI_ERRATA_FIX_BUS_OFF_REC
|
||||
bool "Add SW workaround for REC change during bus-off"
|
||||
depends on IDF_TARGET_ESP32
|
||||
default n
|
||||
help
|
||||
When the bus-off condition is reached, the REC should be reset to 0 and frozen (via LOM) by the
|
||||
driver's ISR. However on the ESP32, there is an edge case where the REC will increase before the
|
||||
driver's ISR can respond in time (e.g., due to the rapid occurrence of bus errors), thus causing the
|
||||
REC to be non-zero after bus-off. A non-zero REC can prevent bus-off recovery as the bus-off recovery
|
||||
condition is that both TEC and REC become 0. Enabling this option will add a workaround in the driver
|
||||
to forcibly reset REC to zero on reaching bus-off.
|
||||
|
||||
config TWAI_ERRATA_FIX_TX_INTR_LOST
|
||||
bool "Add SW workaround for TX interrupt lost errata"
|
||||
depends on IDF_TARGET_ESP32
|
||||
default n
|
||||
help
|
||||
On the ESP32, when a transmit interrupt occurs, and interrupt register is read on the same APB clock
|
||||
cycle, the transmit interrupt could be lost. Enabling this option will add a workaround that checks the
|
||||
transmit buffer status bit to recover any lost transmit interrupt.
|
||||
|
||||
config TWAI_ERRATA_FIX_RX_FRAME_INVALID
|
||||
bool "Add SW workaround for invalid RX frame errata"
|
||||
depends on IDF_TARGET_ESP32
|
||||
default n
|
||||
help
|
||||
On the ESP32, when receiving a data or remote frame, if a bus error occurs in the data or CRC field,
|
||||
the data of the next received frame could be invalid. Enabling this option will add a workaround that
|
||||
will reset the peripheral on detection of this errata condition. Note that if a frame is transmitted on
|
||||
the bus whilst the reset is ongoing, the message will not be receive by the peripheral sent on the bus
|
||||
during the reset, the message will be lost.
|
||||
|
||||
config TWAI_ERRATA_FIX_RX_FIFO_CORRUPT
|
||||
bool "Add SW workaround for RX FIFO corruption errata"
|
||||
depends on IDF_TARGET_ESP32
|
||||
default n
|
||||
help
|
||||
On the ESP32, when the RX FIFO overruns and the RX message counter maxes out at 64 messages, the entire
|
||||
RX FIFO is no longer recoverable. Enabling this option will add a workaround that resets the peripheral
|
||||
on detection of this errata condition. Note that if a frame is being sent on the bus during the reset
|
||||
bus during the reset, the message will be lost.
|
||||
|
||||
endmenu # TWAI Configuration
|
||||
|
||||
menu "UART configuration"
|
||||
|
||||
@@ -160,17 +160,12 @@ static void adc_power_on_internal(void)
|
||||
|
||||
void adc_power_acquire(void)
|
||||
{
|
||||
bool powered_on = false;
|
||||
ADC_POWER_ENTER();
|
||||
s_adc_power_on_cnt++;
|
||||
if (s_adc_power_on_cnt == 1) {
|
||||
adc_power_on_internal();
|
||||
powered_on = true;
|
||||
}
|
||||
ADC_POWER_EXIT();
|
||||
if (powered_on) {
|
||||
ESP_LOGV(ADC_TAG, "%s: ADC powered on", __func__);
|
||||
}
|
||||
}
|
||||
|
||||
void adc_power_on(void)
|
||||
@@ -182,12 +177,15 @@ void adc_power_on(void)
|
||||
|
||||
static void adc_power_off_internal(void)
|
||||
{
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
adc_hal_set_power_manage(ADC_POWER_SW_OFF);
|
||||
#else
|
||||
adc_hal_set_power_manage(ADC_POWER_BY_FSM);
|
||||
#endif
|
||||
}
|
||||
|
||||
void adc_power_release(void)
|
||||
{
|
||||
bool powered_off = false;
|
||||
ADC_POWER_ENTER();
|
||||
s_adc_power_on_cnt--;
|
||||
/* Sanity check */
|
||||
@@ -197,12 +195,8 @@ void adc_power_release(void)
|
||||
abort();
|
||||
} else if (s_adc_power_on_cnt == 0) {
|
||||
adc_power_off_internal();
|
||||
powered_off = true;
|
||||
}
|
||||
ADC_POWER_EXIT();
|
||||
if (powered_off) {
|
||||
ESP_LOGV(ADC_TAG, "%s: ADC powered off", __func__);
|
||||
}
|
||||
}
|
||||
|
||||
void adc_power_off(void)
|
||||
@@ -212,6 +206,33 @@ void adc_power_off(void)
|
||||
ADC_POWER_EXIT();
|
||||
}
|
||||
|
||||
esp_err_t adc1_pad_get_io_num(adc1_channel_t channel, gpio_num_t *gpio_num)
|
||||
{
|
||||
ADC_CHANNEL_CHECK(ADC_NUM_1, channel);
|
||||
|
||||
int io = ADC_GET_IO_NUM(ADC_NUM_1, channel);
|
||||
if (io < 0) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
} else {
|
||||
*gpio_num = (gpio_num_t)io;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc2_pad_get_io_num(adc2_channel_t channel, gpio_num_t *gpio_num)
|
||||
{
|
||||
ADC_CHANNEL_CHECK(ADC_NUM_2, channel);
|
||||
|
||||
int io = ADC_GET_IO_NUM(ADC_NUM_2, channel);
|
||||
if (io < 0) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
} else {
|
||||
*gpio_num = (gpio_num_t)io;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
|
||||
esp_err_t adc_set_clk_div(uint8_t clk_div)
|
||||
@@ -323,20 +344,6 @@ esp_err_t adc_rtc_reset(void)
|
||||
/*-------------------------------------------------------------------------------------
|
||||
* ADC1
|
||||
*------------------------------------------------------------------------------------*/
|
||||
esp_err_t adc1_pad_get_io_num(adc1_channel_t channel, gpio_num_t *gpio_num)
|
||||
{
|
||||
ADC_CHANNEL_CHECK(ADC_NUM_1, channel);
|
||||
|
||||
int io = ADC_GET_IO_NUM(ADC_NUM_1, channel);
|
||||
if (io < 0) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
} else {
|
||||
*gpio_num = (gpio_num_t)io;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc1_config_channel_atten(adc1_channel_t channel, adc_atten_t atten)
|
||||
{
|
||||
ADC_CHANNEL_CHECK(ADC_NUM_1, channel);
|
||||
@@ -466,20 +473,6 @@ void adc1_ulp_enable(void)
|
||||
/*---------------------------------------------------------------
|
||||
ADC2
|
||||
---------------------------------------------------------------*/
|
||||
esp_err_t adc2_pad_get_io_num(adc2_channel_t channel, gpio_num_t *gpio_num)
|
||||
{
|
||||
ADC_CHANNEL_CHECK(ADC_NUM_2, channel);
|
||||
|
||||
int io = ADC_GET_IO_NUM(ADC_NUM_2, channel);
|
||||
if (io < 0) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
} else {
|
||||
*gpio_num = (gpio_num_t)io;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/** For ESP32S2 the ADC2 The right to use ADC2 is controlled by the arbiter, and there is no need to set a lock.*/
|
||||
esp_err_t adc2_wifi_acquire(void)
|
||||
{
|
||||
@@ -562,6 +555,7 @@ static inline void adc2_dac_disable( adc2_channel_t channel)
|
||||
*/
|
||||
esp_err_t adc2_get_raw(adc2_channel_t channel, adc_bits_width_t width_bit, int *raw_out)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
int adc_value = 0;
|
||||
|
||||
ADC_CHECK(raw_out != NULL, "ADC out value err", ESP_ERR_INVALID_ARG);
|
||||
@@ -601,7 +595,8 @@ esp_err_t adc2_get_raw(adc2_channel_t channel, adc_bits_width_t width_bit, int *
|
||||
#endif //CONFIG_PM_ENABLE
|
||||
#endif //CONFIG_IDF_TARGET_ESP32
|
||||
|
||||
if (adc_hal_convert(ADC_NUM_2, channel, &adc_value)) {
|
||||
ret = adc_hal_convert(ADC_NUM_2, channel, &adc_value);
|
||||
if (ret != ESP_OK) {
|
||||
adc_value = -1;
|
||||
}
|
||||
|
||||
@@ -618,13 +613,8 @@ esp_err_t adc2_get_raw(adc2_channel_t channel, adc_bits_width_t width_bit, int *
|
||||
adc_power_release();
|
||||
SARADC2_RELEASE();
|
||||
|
||||
if (adc_value < 0) {
|
||||
ESP_LOGD( ADC_TAG, "ADC2 ARB: Return data is invalid." );
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
*raw_out = adc_value;
|
||||
return ESP_OK;
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t adc2_vref_to_gpio(gpio_num_t gpio)
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "soc/io_mux_reg.h"
|
||||
#include "hal/cpu_hal.h"
|
||||
#include "hal/cpu_ll.h"
|
||||
#include "hal/gpio_hal.h"
|
||||
#include "driver/periph_ctrl.h"
|
||||
#include "esp_rom_gpio.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
@@ -267,13 +268,13 @@ esp_err_t dedic_gpio_new_bundle(const dedic_gpio_bundle_config_t *config, dedic_
|
||||
// route dedicated GPIO channel signals to GPIO matrix
|
||||
if (config->flags.in_en) {
|
||||
for (size_t i = 0; i < config->array_size; i++) {
|
||||
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[config->gpio_array[i]], PIN_FUNC_GPIO);
|
||||
gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[config->gpio_array[i]], PIN_FUNC_GPIO);
|
||||
esp_rom_gpio_connect_in_signal(config->gpio_array[i], dedic_gpio_periph_signals.cores[core_id].in_sig_per_channel[in_offset + i], config->flags.in_invert);
|
||||
}
|
||||
}
|
||||
if (config->flags.out_en) {
|
||||
for (size_t i = 0; i < config->array_size; i++) {
|
||||
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[config->gpio_array[i]], PIN_FUNC_GPIO);
|
||||
gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[config->gpio_array[i]], PIN_FUNC_GPIO);
|
||||
esp_rom_gpio_connect_out_signal(config->gpio_array[i], dedic_gpio_periph_signals.cores[core_id].out_sig_per_channel[out_offset + i], config->flags.out_invert, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -135,6 +135,7 @@ esp_err_t adc_digi_init(void)
|
||||
|
||||
esp_err_t adc_digi_deinit(void)
|
||||
{
|
||||
adc_power_release();
|
||||
ADC_ENTER_CRITICAL();
|
||||
adc_hal_digi_deinit();
|
||||
ADC_EXIT_CRITICAL();
|
||||
@@ -143,6 +144,8 @@ esp_err_t adc_digi_deinit(void)
|
||||
|
||||
esp_err_t adc_digi_controller_config(const adc_digi_config_t *config)
|
||||
{
|
||||
/* If enable digital controller, adc xpd should always on. */
|
||||
adc_power_acquire();
|
||||
ADC_ENTER_CRITICAL();
|
||||
adc_hal_digi_controller_config(config);
|
||||
ADC_EXIT_CRITICAL();
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_intr_alloc.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_pm.h"
|
||||
#include "sys/lock.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/semphr.h"
|
||||
@@ -58,38 +59,34 @@ extern portMUX_TYPE rtc_spinlock; //TODO: Will be placed in the appropriate posi
|
||||
#define ADC_ENTER_CRITICAL() portENTER_CRITICAL(&rtc_spinlock)
|
||||
#define ADC_EXIT_CRITICAL() portEXIT_CRITICAL(&rtc_spinlock)
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
Digital Controller Context
|
||||
---------------------------------------------------------------*/
|
||||
/**
|
||||
* 1. adc_digi_mutex: this mutex lock is used for ADC digital controller. On ESP32-C3, the ADC single read APIs (unit1 & unit2)
|
||||
* and ADC DMA continuous read APIs share the ``apb_saradc_struct.h`` regs.
|
||||
*
|
||||
* 2. sar_adc_mutex: this mutex lock is used for SARADC2 module. On ESP32C-C3, the ADC single read APIs (unit2), ADC DMA
|
||||
* continuous read APIs and WIFI share the SARADC2 analog IP.
|
||||
*
|
||||
* Sequence:
|
||||
* Acquire: 1. sar_adc_mutex; 2. adc_digi_mutex;
|
||||
* Release: 1. adc_digi_mutex; 2. sar_adc_mutex;
|
||||
* 1. sar_adc1_lock: this mutex lock is to protect the SARADC1 module.
|
||||
* 2. sar_adc2_lock: this mutex lock is to protect the SARADC2 module. On C3, it is controlled by the digital controller
|
||||
* and PWDET controller.
|
||||
* 3. adc_reg_lock: this spin lock is to protect the shared registers used by ADC1 / ADC2 single read mode.
|
||||
*/
|
||||
static _lock_t adc_digi_mutex;
|
||||
#define ADC_DIGI_LOCK_ACQUIRE() _lock_acquire(&adc_digi_mutex)
|
||||
#define ADC_DIGI_LOCK_RELEASE() _lock_release(&adc_digi_mutex)
|
||||
static _lock_t sar_adc2_mutex;
|
||||
#define SAC_ADC2_LOCK_ACQUIRE() _lock_acquire(&sar_adc2_mutex)
|
||||
#define SAC_ADC2_LOCK_RELEASE() _lock_release(&sar_adc2_mutex)
|
||||
static _lock_t sar_adc1_lock;
|
||||
#define SAR_ADC1_LOCK_ACQUIRE() _lock_acquire(&sar_adc1_lock)
|
||||
#define SAR_ADC1_LOCK_RELEASE() _lock_release(&sar_adc1_lock)
|
||||
static _lock_t sar_adc2_lock;
|
||||
#define SAR_ADC2_LOCK_ACQUIRE() _lock_acquire(&sar_adc2_lock)
|
||||
#define SAR_ADC2_LOCK_RELEASE() _lock_release(&sar_adc2_lock)
|
||||
portMUX_TYPE adc_reg_lock = portMUX_INITIALIZER_UNLOCKED;
|
||||
#define ADC_REG_LOCK_ENTER() portENTER_CRITICAL(&adc_reg_lock)
|
||||
#define ADC_REG_LOCK_EXIT() portEXIT_CRITICAL(&adc_reg_lock)
|
||||
|
||||
#define INTERNAL_BUF_NUM 5
|
||||
#define IN_SUC_EOF_BIT GDMA_LL_EVENT_RX_SUC_EOF
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
Digital Controller Context
|
||||
---------------------------------------------------------------*/
|
||||
typedef struct adc_digi_context_t {
|
||||
intr_handle_t dma_intr_hdl; //MD interrupt handle
|
||||
uint32_t bytes_between_intr; //bytes between in suc eof intr
|
||||
uint8_t *rx_dma_buf; //dma buffer
|
||||
adc_dma_hal_context_t hal_dma; //dma context (hal)
|
||||
adc_dma_hal_config_t hal_dma_config; //dma config (hal)
|
||||
adc_hal_context_t hal; //hal context
|
||||
gdma_channel_handle_t rx_dma_channel; //dma rx channel handle
|
||||
RingbufHandle_t ringbuf_hdl; //RX ringbuffer handler
|
||||
intptr_t rx_eof_desc_addr; //eof descriptor address of RX channel
|
||||
bool ringbuf_overflow_flag; //1: ringbuffer overflow
|
||||
bool driver_start_flag; //1: driver is started; 0: driver is stoped
|
||||
bool use_adc1; //1: ADC unit1 will be used; 0: ADC unit1 won't be used.
|
||||
@@ -97,6 +94,7 @@ typedef struct adc_digi_context_t {
|
||||
adc_atten_t adc1_atten; //Attenuation for ADC1. On this chip each ADC can only support one attenuation.
|
||||
adc_atten_t adc2_atten; //Attenuation for ADC2. On this chip each ADC can only support one attenuation.
|
||||
adc_digi_config_t digi_controller_config; //Digital Controller Configuration
|
||||
esp_pm_lock_handle_t pm_lock; //For power management
|
||||
} adc_digi_context_t;
|
||||
|
||||
static adc_digi_context_t *s_adc_digi_ctx = NULL;
|
||||
@@ -159,20 +157,18 @@ esp_err_t adc_digi_initialize(const adc_digi_init_config_t *init_config)
|
||||
}
|
||||
|
||||
//malloc internal buffer used by DMA
|
||||
s_adc_digi_ctx->bytes_between_intr = init_config->conv_num_each_intr;
|
||||
s_adc_digi_ctx->rx_dma_buf = heap_caps_calloc(1, s_adc_digi_ctx->bytes_between_intr * INTERNAL_BUF_NUM, MALLOC_CAP_INTERNAL);
|
||||
s_adc_digi_ctx->rx_dma_buf = heap_caps_calloc(1, init_config->conv_num_each_intr * INTERNAL_BUF_NUM, MALLOC_CAP_INTERNAL);
|
||||
if (!s_adc_digi_ctx->rx_dma_buf) {
|
||||
ret = ESP_ERR_NO_MEM;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
//malloc dma descriptor
|
||||
s_adc_digi_ctx->hal_dma_config.rx_desc = heap_caps_calloc(1, (sizeof(dma_descriptor_t)) * INTERNAL_BUF_NUM, MALLOC_CAP_DMA);
|
||||
if (!s_adc_digi_ctx->hal_dma_config.rx_desc) {
|
||||
s_adc_digi_ctx->hal.rx_desc = heap_caps_calloc(1, (sizeof(dma_descriptor_t)) * INTERNAL_BUF_NUM, MALLOC_CAP_DMA);
|
||||
if (!s_adc_digi_ctx->hal.rx_desc) {
|
||||
ret = ESP_ERR_NO_MEM;
|
||||
goto cleanup;
|
||||
}
|
||||
s_adc_digi_ctx->hal_dma_config.desc_max_num = INTERNAL_BUF_NUM;
|
||||
|
||||
//malloc pattern table
|
||||
s_adc_digi_ctx->digi_controller_config.adc_pattern = calloc(1, SOC_ADC_PATT_LEN_MAX * sizeof(adc_digi_pattern_table_t));
|
||||
@@ -181,6 +177,13 @@ esp_err_t adc_digi_initialize(const adc_digi_init_config_t *init_config)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
#if CONFIG_PM_ENABLE
|
||||
ret = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "adc_dma", &s_adc_digi_ctx->pm_lock);
|
||||
if (ret != ESP_OK) {
|
||||
goto cleanup;
|
||||
}
|
||||
#endif //CONFIG_PM_ENABLE
|
||||
|
||||
//init gpio pins
|
||||
if (init_config->adc1_chan_mask) {
|
||||
ret = adc_digi_gpio_init(ADC_NUM_1, init_config->adc1_chan_mask);
|
||||
@@ -218,7 +221,13 @@ esp_err_t adc_digi_initialize(const adc_digi_init_config_t *init_config)
|
||||
|
||||
int dma_chan;
|
||||
gdma_get_channel_id(s_adc_digi_ctx->rx_dma_channel, &dma_chan);
|
||||
s_adc_digi_ctx->hal_dma_config.dma_chan = dma_chan;
|
||||
|
||||
adc_hal_config_t config = {
|
||||
.desc_max_num = INTERNAL_BUF_NUM,
|
||||
.dma_chan = dma_chan,
|
||||
.eof_num = init_config->conv_num_each_intr / ADC_HAL_DATA_LEN_PER_CONV
|
||||
};
|
||||
adc_hal_context_config(&s_adc_digi_ctx->hal, &config);
|
||||
|
||||
//enable SARADC module clock
|
||||
periph_module_enable(PERIPH_SARADC_MODULE);
|
||||
@@ -238,7 +247,9 @@ static IRAM_ATTR bool adc_dma_intr(adc_digi_context_t *adc_digi_ctx);
|
||||
|
||||
static IRAM_ATTR bool adc_dma_in_suc_eof_callback(gdma_channel_handle_t dma_chan, gdma_event_data_t *event_data, void *user_data)
|
||||
{
|
||||
assert(event_data);
|
||||
adc_digi_context_t *adc_digi_ctx = (adc_digi_context_t *)user_data;
|
||||
adc_digi_ctx->rx_eof_desc_addr = event_data->rx_eof_desc_addr;
|
||||
return adc_dma_intr(adc_digi_ctx);
|
||||
}
|
||||
|
||||
@@ -246,40 +257,28 @@ static IRAM_ATTR bool adc_dma_intr(adc_digi_context_t *adc_digi_ctx)
|
||||
{
|
||||
portBASE_TYPE taskAwoken = 0;
|
||||
BaseType_t ret;
|
||||
adc_hal_dma_desc_status_t status = false;
|
||||
dma_descriptor_t *current_desc = NULL;
|
||||
|
||||
while (1) {
|
||||
status = adc_hal_get_reading_result(&adc_digi_ctx->hal, adc_digi_ctx->rx_eof_desc_addr, ¤t_desc);
|
||||
if (status != ADC_HAL_DMA_DESC_VALID) {
|
||||
break;
|
||||
}
|
||||
|
||||
while (adc_digi_ctx->hal_dma_config.cur_desc_ptr->dw0.owner == 0) {
|
||||
dma_descriptor_t *current_desc = adc_digi_ctx->hal_dma_config.cur_desc_ptr;
|
||||
ret = xRingbufferSendFromISR(adc_digi_ctx->ringbuf_hdl, current_desc->buffer, current_desc->dw0.length, &taskAwoken);
|
||||
if (ret == pdFALSE) {
|
||||
//ringbuffer overflow
|
||||
adc_digi_ctx->ringbuf_overflow_flag = 1;
|
||||
}
|
||||
|
||||
adc_digi_ctx->hal_dma_config.desc_cnt += 1;
|
||||
//cycle the dma descriptor and buffers
|
||||
adc_digi_ctx->hal_dma_config.cur_desc_ptr = adc_digi_ctx->hal_dma_config.cur_desc_ptr->next;
|
||||
if (!adc_digi_ctx->hal_dma_config.cur_desc_ptr) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!adc_digi_ctx->hal_dma_config.cur_desc_ptr) {
|
||||
|
||||
assert(adc_digi_ctx->hal_dma_config.desc_cnt == adc_digi_ctx->hal_dma_config.desc_max_num);
|
||||
//reset the current descriptor status
|
||||
adc_digi_ctx->hal_dma_config.cur_desc_ptr = adc_digi_ctx->hal_dma_config.rx_desc;
|
||||
adc_digi_ctx->hal_dma_config.desc_cnt = 0;
|
||||
|
||||
if (status == ADC_HAL_DMA_DESC_NULL) {
|
||||
//start next turns of dma operation
|
||||
adc_hal_digi_dma_multi_descriptor(&adc_digi_ctx->hal_dma_config, adc_digi_ctx->rx_dma_buf, adc_digi_ctx->bytes_between_intr, adc_digi_ctx->hal_dma_config.desc_max_num);
|
||||
adc_hal_digi_rxdma_start(&adc_digi_ctx->hal_dma, &adc_digi_ctx->hal_dma_config);
|
||||
adc_hal_digi_rxdma_start(&adc_digi_ctx->hal, adc_digi_ctx->rx_dma_buf);
|
||||
}
|
||||
|
||||
if(taskAwoken == pdTRUE) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return (taskAwoken == pdTRUE);
|
||||
}
|
||||
|
||||
esp_err_t adc_digi_start(void)
|
||||
@@ -288,15 +287,21 @@ esp_err_t adc_digi_start(void)
|
||||
ESP_LOGE(ADC_TAG, "The driver is already started");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
adc_power_acquire();
|
||||
//reset flags
|
||||
s_adc_digi_ctx->ringbuf_overflow_flag = 0;
|
||||
s_adc_digi_ctx->driver_start_flag = 1;
|
||||
|
||||
//When using SARADC2 module, this task needs to be protected from WIFI
|
||||
if (s_adc_digi_ctx->use_adc2) {
|
||||
SAC_ADC2_LOCK_ACQUIRE();
|
||||
if (s_adc_digi_ctx->use_adc1) {
|
||||
SAR_ADC1_LOCK_ACQUIRE();
|
||||
}
|
||||
ADC_DIGI_LOCK_ACQUIRE();
|
||||
if (s_adc_digi_ctx->use_adc2) {
|
||||
SAR_ADC2_LOCK_ACQUIRE();
|
||||
}
|
||||
|
||||
#if CONFIG_PM_ENABLE
|
||||
// Lock APB frequency while ADC driver is in use
|
||||
esp_pm_lock_acquire(s_adc_digi_ctx->pm_lock);
|
||||
#endif
|
||||
|
||||
adc_arbiter_t config = ADC_ARBITER_CONFIG_DEFAULT();
|
||||
if (s_adc_digi_ctx->use_adc1) {
|
||||
@@ -309,26 +314,16 @@ esp_err_t adc_digi_start(void)
|
||||
}
|
||||
|
||||
adc_hal_init();
|
||||
|
||||
adc_hal_arbiter_config(&config);
|
||||
adc_hal_digi_init(&s_adc_digi_ctx->hal_dma, &s_adc_digi_ctx->hal_dma_config);
|
||||
adc_hal_digi_init(&s_adc_digi_ctx->hal);
|
||||
adc_hal_digi_controller_config(&s_adc_digi_ctx->digi_controller_config);
|
||||
|
||||
//create dma descriptors
|
||||
adc_hal_digi_dma_multi_descriptor(&s_adc_digi_ctx->hal_dma_config, s_adc_digi_ctx->rx_dma_buf, s_adc_digi_ctx->bytes_between_intr, s_adc_digi_ctx->hal_dma_config.desc_max_num);
|
||||
adc_hal_digi_set_eof_num(&s_adc_digi_ctx->hal_dma, &s_adc_digi_ctx->hal_dma_config, (s_adc_digi_ctx->bytes_between_intr)/4);
|
||||
//set the current descriptor pointer
|
||||
s_adc_digi_ctx->hal_dma_config.cur_desc_ptr = s_adc_digi_ctx->hal_dma_config.rx_desc;
|
||||
s_adc_digi_ctx->hal_dma_config.desc_cnt = 0;
|
||||
|
||||
//enable in suc eof intr
|
||||
adc_hal_digi_ena_intr(&s_adc_digi_ctx->hal_dma, &s_adc_digi_ctx->hal_dma_config, IN_SUC_EOF_BIT);
|
||||
|
||||
//start ADC
|
||||
adc_hal_digi_start(&s_adc_digi_ctx->hal_dma, &s_adc_digi_ctx->hal_dma_config);
|
||||
|
||||
//reset ADC and DMA
|
||||
adc_hal_fifo_reset(&s_adc_digi_ctx->hal);
|
||||
//start DMA
|
||||
adc_hal_digi_rxdma_start(&s_adc_digi_ctx->hal_dma, &s_adc_digi_ctx->hal_dma_config);
|
||||
adc_hal_digi_rxdma_start(&s_adc_digi_ctx->hal, s_adc_digi_ctx->rx_dma_buf);
|
||||
//start ADC
|
||||
adc_hal_digi_start(&s_adc_digi_ctx->hal);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
@@ -342,20 +337,27 @@ esp_err_t adc_digi_stop(void)
|
||||
s_adc_digi_ctx->driver_start_flag = 0;
|
||||
|
||||
//disable the in suc eof intrrupt
|
||||
adc_hal_digi_dis_intr(&s_adc_digi_ctx->hal_dma, &s_adc_digi_ctx->hal_dma_config, IN_SUC_EOF_BIT);
|
||||
adc_hal_digi_dis_intr(&s_adc_digi_ctx->hal, IN_SUC_EOF_BIT);
|
||||
//clear the in suc eof interrupt
|
||||
adc_hal_digi_clr_intr(&s_adc_digi_ctx->hal_dma, &s_adc_digi_ctx->hal_dma_config, IN_SUC_EOF_BIT);
|
||||
//stop DMA
|
||||
adc_hal_digi_rxdma_stop(&s_adc_digi_ctx->hal_dma, &s_adc_digi_ctx->hal_dma_config);
|
||||
adc_hal_digi_clr_intr(&s_adc_digi_ctx->hal, IN_SUC_EOF_BIT);
|
||||
//stop ADC
|
||||
adc_hal_digi_stop(&s_adc_digi_ctx->hal_dma, &s_adc_digi_ctx->hal_dma_config);
|
||||
adc_hal_digi_stop(&s_adc_digi_ctx->hal);
|
||||
//stop DMA
|
||||
adc_hal_digi_rxdma_stop(&s_adc_digi_ctx->hal);
|
||||
adc_hal_digi_deinit();
|
||||
|
||||
ADC_DIGI_LOCK_RELEASE();
|
||||
//When using SARADC2 module, this task needs to be protected from WIFI
|
||||
if (s_adc_digi_ctx->use_adc2) {
|
||||
SAC_ADC2_LOCK_RELEASE();
|
||||
#if CONFIG_PM_ENABLE
|
||||
if (s_adc_digi_ctx->pm_lock) {
|
||||
esp_pm_lock_release(s_adc_digi_ctx->pm_lock);
|
||||
}
|
||||
#endif //CONFIG_PM_ENABLE
|
||||
|
||||
if (s_adc_digi_ctx->use_adc1) {
|
||||
SAR_ADC1_LOCK_RELEASE();
|
||||
}
|
||||
if (s_adc_digi_ctx->use_adc2) {
|
||||
SAR_ADC2_LOCK_RELEASE();
|
||||
}
|
||||
adc_power_release();
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
@@ -403,17 +405,19 @@ esp_err_t adc_digi_deinitialize(void)
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
if (s_adc_digi_ctx->dma_intr_hdl) {
|
||||
esp_intr_free(s_adc_digi_ctx->dma_intr_hdl);
|
||||
}
|
||||
|
||||
if(s_adc_digi_ctx->ringbuf_hdl) {
|
||||
if (s_adc_digi_ctx->ringbuf_hdl) {
|
||||
vRingbufferDelete(s_adc_digi_ctx->ringbuf_hdl);
|
||||
s_adc_digi_ctx->ringbuf_hdl = NULL;
|
||||
}
|
||||
|
||||
#if CONFIG_PM_ENABLE
|
||||
if (s_adc_digi_ctx->pm_lock) {
|
||||
esp_pm_lock_delete(s_adc_digi_ctx->pm_lock);
|
||||
}
|
||||
#endif //CONFIG_PM_ENABLE
|
||||
|
||||
free(s_adc_digi_ctx->rx_dma_buf);
|
||||
free(s_adc_digi_ctx->hal_dma_config.rx_desc);
|
||||
free(s_adc_digi_ctx->hal.rx_desc);
|
||||
free(s_adc_digi_ctx->digi_controller_config.adc_pattern);
|
||||
gdma_disconnect(s_adc_digi_ctx->rx_dma_channel);
|
||||
gdma_del_channel(s_adc_digi_ctx->rx_dma_channel);
|
||||
@@ -432,6 +436,38 @@ esp_err_t adc_digi_deinitialize(void)
|
||||
static adc_atten_t s_atten1_single[ADC1_CHANNEL_MAX]; //Array saving attenuate of each channel of ADC1, used by single read API
|
||||
static adc_atten_t s_atten2_single[ADC2_CHANNEL_MAX]; //Array saving attenuate of each channel of ADC2, used by single read API
|
||||
|
||||
esp_err_t adc_vref_to_gpio(adc_unit_t adc_unit, gpio_num_t gpio)
|
||||
{
|
||||
esp_err_t ret;
|
||||
uint32_t channel = ADC2_CHANNEL_MAX;
|
||||
if (adc_unit == ADC_UNIT_2) {
|
||||
for (int i = 0; i < ADC2_CHANNEL_MAX; i++) {
|
||||
if (gpio == ADC_GET_IO_NUM(ADC_NUM_2, i)) {
|
||||
channel = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (channel == ADC2_CHANNEL_MAX) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
}
|
||||
|
||||
adc_power_acquire();
|
||||
if (adc_unit & ADC_UNIT_1) {
|
||||
ADC_ENTER_CRITICAL();
|
||||
adc_hal_vref_output(ADC_NUM_1, channel, true);
|
||||
ADC_EXIT_CRITICAL()
|
||||
} else if (adc_unit & ADC_UNIT_2) {
|
||||
ADC_ENTER_CRITICAL();
|
||||
adc_hal_vref_output(ADC_NUM_2, channel, true);
|
||||
ADC_EXIT_CRITICAL()
|
||||
}
|
||||
|
||||
ret = adc_digi_gpio_init(ADC_NUM_2, BIT(channel));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t adc1_config_width(adc_bits_width_t width_bit)
|
||||
{
|
||||
//On ESP32C3, the data width is always 12-bits.
|
||||
@@ -459,41 +495,26 @@ esp_err_t adc1_config_channel_atten(adc1_channel_t channel, adc_atten_t atten)
|
||||
int adc1_get_raw(adc1_channel_t channel)
|
||||
{
|
||||
int raw_out = 0;
|
||||
adc_digi_config_t dig_cfg = {
|
||||
.conv_limit_en = 0,
|
||||
.conv_limit_num = 250,
|
||||
.sample_freq_hz = SOC_ADC_SAMPLE_FREQ_THRES_HIGH,
|
||||
};
|
||||
|
||||
ADC_DIGI_LOCK_ACQUIRE();
|
||||
|
||||
periph_module_enable(PERIPH_SARADC_MODULE);
|
||||
adc_power_acquire();
|
||||
|
||||
SAR_ADC1_LOCK_ACQUIRE();
|
||||
|
||||
adc_atten_t atten = s_atten1_single[channel];
|
||||
uint32_t cal_val = adc_get_calibration_offset(ADC_NUM_1, channel, atten);
|
||||
adc_hal_set_calibration_param(ADC_NUM_1, cal_val);
|
||||
|
||||
adc_hal_digi_controller_config(&dig_cfg);
|
||||
ADC_REG_LOCK_ENTER();
|
||||
adc_hal_set_atten(ADC_NUM_2, channel, atten);
|
||||
adc_hal_convert(ADC_NUM_1, channel, &raw_out);
|
||||
ADC_REG_LOCK_EXIT();
|
||||
|
||||
adc_hal_intr_clear(ADC_EVENT_ADC1_DONE);
|
||||
SAR_ADC1_LOCK_RELEASE();
|
||||
|
||||
adc_hal_adc1_onetime_sample_enable(true);
|
||||
adc_hal_onetime_channel(ADC_NUM_1, channel);
|
||||
adc_hal_set_onetime_atten(atten);
|
||||
|
||||
//Trigger single read.
|
||||
adc_hal_onetime_start(&dig_cfg);
|
||||
while (!adc_hal_intr_get_raw(ADC_EVENT_ADC1_DONE));
|
||||
adc_hal_single_read(ADC_NUM_1, &raw_out);
|
||||
|
||||
adc_hal_intr_clear(ADC_EVENT_ADC1_DONE);
|
||||
adc_hal_adc1_onetime_sample_enable(false);
|
||||
|
||||
adc_hal_digi_deinit();
|
||||
adc_power_release();
|
||||
periph_module_disable(PERIPH_SARADC_MODULE);
|
||||
|
||||
ADC_DIGI_LOCK_RELEASE();
|
||||
|
||||
return raw_out;
|
||||
}
|
||||
|
||||
@@ -519,42 +540,26 @@ esp_err_t adc2_get_raw(adc2_channel_t channel, adc_bits_width_t width_bit, int *
|
||||
}
|
||||
|
||||
esp_err_t ret = ESP_OK;
|
||||
adc_digi_config_t dig_cfg = {
|
||||
.conv_limit_en = 0,
|
||||
.conv_limit_num = 250,
|
||||
.sample_freq_hz = SOC_ADC_SAMPLE_FREQ_THRES_HIGH,
|
||||
};
|
||||
|
||||
SAC_ADC2_LOCK_ACQUIRE();
|
||||
ADC_DIGI_LOCK_ACQUIRE();
|
||||
periph_module_enable(PERIPH_SARADC_MODULE);
|
||||
adc_power_acquire();
|
||||
|
||||
SAR_ADC2_LOCK_ACQUIRE();
|
||||
|
||||
adc_atten_t atten = s_atten2_single[channel];
|
||||
uint32_t cal_val = adc_get_calibration_offset(ADC_NUM_2, channel, atten);
|
||||
adc_hal_set_calibration_param(ADC_NUM_2, cal_val);
|
||||
|
||||
adc_hal_digi_controller_config(&dig_cfg);
|
||||
ADC_REG_LOCK_ENTER();
|
||||
adc_hal_set_atten(ADC_NUM_2, channel, atten);
|
||||
ret = adc_hal_convert(ADC_NUM_2, channel, raw_out);
|
||||
ADC_REG_LOCK_EXIT();
|
||||
|
||||
adc_hal_intr_clear(ADC_EVENT_ADC2_DONE);
|
||||
SAR_ADC2_LOCK_RELEASE();
|
||||
|
||||
adc_hal_adc2_onetime_sample_enable(true);
|
||||
adc_hal_onetime_channel(ADC_NUM_2, channel);
|
||||
adc_hal_set_onetime_atten(atten);
|
||||
|
||||
//Trigger single read.
|
||||
adc_hal_onetime_start(&dig_cfg);
|
||||
while (!adc_hal_intr_get_raw(ADC_EVENT_ADC2_DONE));
|
||||
ret = adc_hal_single_read(ADC_NUM_2, raw_out);
|
||||
|
||||
adc_hal_intr_clear(ADC_EVENT_ADC2_DONE);
|
||||
adc_hal_adc2_onetime_sample_enable(false);
|
||||
|
||||
adc_hal_digi_deinit();
|
||||
adc_power_release();
|
||||
periph_module_disable(PERIPH_SARADC_MODULE);
|
||||
|
||||
ADC_DIGI_LOCK_RELEASE();
|
||||
SAC_ADC2_LOCK_RELEASE();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -581,7 +586,7 @@ esp_err_t adc_digi_controller_config(const adc_digi_config_t *config)
|
||||
s_adc_digi_ctx->use_adc1 = 0;
|
||||
s_adc_digi_ctx->use_adc2 = 0;
|
||||
for (int i = 0; i < config->adc_pattern_len; i++) {
|
||||
const adc_digi_pattern_table_t* pat = &config->adc_pattern[i];
|
||||
const adc_digi_pattern_table_t *pat = &config->adc_pattern[i];
|
||||
if (pat->unit == ADC_NUM_1) {
|
||||
s_adc_digi_ctx->use_adc1 = 1;
|
||||
|
||||
@@ -605,86 +610,6 @@ esp_err_t adc_digi_controller_config(const adc_digi_config_t *config)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc_arbiter_config(adc_unit_t adc_unit, adc_arbiter_t *config)
|
||||
{
|
||||
if (adc_unit & ADC_UNIT_1) {
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
ADC_ENTER_CRITICAL();
|
||||
adc_hal_arbiter_config(config);
|
||||
ADC_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set ADC module controller.
|
||||
* There are five SAR ADC controllers:
|
||||
* Two digital controller: Continuous conversion mode (DMA). High performance with multiple channel scan modes;
|
||||
* Two RTC controller: Single conversion modes (Polling). For low power purpose working during deep sleep;
|
||||
* the other is dedicated for Power detect (PWDET / PKDET), Only support ADC2.
|
||||
*
|
||||
* @note Only ADC2 support arbiter to switch controllers automatically. Access to the ADC is based on the priority of the controller.
|
||||
* @note For ADC1, Controller access is mutually exclusive.
|
||||
*
|
||||
* @param adc_unit ADC unit.
|
||||
* @param ctrl ADC controller, Refer to `adc_controller_t`.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_set_controller(adc_unit_t adc_unit, adc_controller_t ctrl)
|
||||
{
|
||||
adc_arbiter_t config = {0};
|
||||
adc_arbiter_t cfg = ADC_ARBITER_CONFIG_DEFAULT();
|
||||
|
||||
if (adc_unit & ADC_UNIT_1) {
|
||||
adc_hal_set_controller(ADC_NUM_1, ctrl);
|
||||
}
|
||||
if (adc_unit & ADC_UNIT_2) {
|
||||
adc_hal_set_controller(ADC_NUM_2, ctrl);
|
||||
switch (ctrl) {
|
||||
case ADC2_CTRL_FORCE_PWDET:
|
||||
config.pwdet_pri = 2;
|
||||
config.mode = ADC_ARB_MODE_SHIELD;
|
||||
adc_hal_arbiter_config(&config);
|
||||
adc_hal_set_controller(ADC_NUM_2, ADC2_CTRL_PWDET);
|
||||
break;
|
||||
case ADC2_CTRL_FORCE_RTC:
|
||||
config.rtc_pri = 2;
|
||||
config.mode = ADC_ARB_MODE_SHIELD;
|
||||
adc_hal_arbiter_config(&config);
|
||||
adc_hal_set_controller(ADC_NUM_2, ADC_CTRL_RTC);
|
||||
break;
|
||||
case ADC2_CTRL_FORCE_DIG:
|
||||
config.dig_pri = 2;
|
||||
config.mode = ADC_ARB_MODE_SHIELD;
|
||||
adc_hal_arbiter_config(&config);
|
||||
adc_hal_set_controller(ADC_NUM_2, ADC_CTRL_DIG);
|
||||
break;
|
||||
default:
|
||||
adc_hal_arbiter_config(&cfg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset FSM of adc digital controller.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_reset(void)
|
||||
{
|
||||
ADC_ENTER_CRITICAL();
|
||||
adc_hal_digi_reset();
|
||||
adc_hal_digi_clear_pattern_table(ADC_NUM_1);
|
||||
adc_hal_digi_clear_pattern_table(ADC_NUM_2);
|
||||
ADC_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/*************************************/
|
||||
/* Digital controller filter setting */
|
||||
/*************************************/
|
||||
@@ -742,90 +667,6 @@ esp_err_t adc_digi_monitor_enable(adc_digi_monitor_idx_t idx, bool enable)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**************************************/
|
||||
/* Digital controller intr setting */
|
||||
/**************************************/
|
||||
|
||||
esp_err_t adc_digi_intr_enable(adc_unit_t adc_unit, adc_digi_intr_t intr_mask)
|
||||
{
|
||||
ADC_ENTER_CRITICAL();
|
||||
if (adc_unit & ADC_UNIT_1) {
|
||||
adc_hal_digi_intr_enable(ADC_NUM_1, intr_mask);
|
||||
}
|
||||
if (adc_unit & ADC_UNIT_2) {
|
||||
adc_hal_digi_intr_enable(ADC_NUM_2, intr_mask);
|
||||
}
|
||||
ADC_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc_digi_intr_disable(adc_unit_t adc_unit, adc_digi_intr_t intr_mask)
|
||||
{
|
||||
ADC_ENTER_CRITICAL();
|
||||
if (adc_unit & ADC_UNIT_1) {
|
||||
adc_hal_digi_intr_disable(ADC_NUM_1, intr_mask);
|
||||
}
|
||||
if (adc_unit & ADC_UNIT_2) {
|
||||
adc_hal_digi_intr_disable(ADC_NUM_2, intr_mask);
|
||||
}
|
||||
ADC_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t adc_digi_intr_clear(adc_unit_t adc_unit, adc_digi_intr_t intr_mask)
|
||||
{
|
||||
ADC_ENTER_CRITICAL();
|
||||
if (adc_unit & ADC_UNIT_1) {
|
||||
adc_hal_digi_intr_clear(ADC_NUM_1, intr_mask);
|
||||
}
|
||||
if (adc_unit & ADC_UNIT_2) {
|
||||
adc_hal_digi_intr_clear(ADC_NUM_2, intr_mask);
|
||||
}
|
||||
ADC_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
uint32_t adc_digi_intr_get_status(adc_unit_t adc_unit)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
ADC_ENTER_CRITICAL();
|
||||
if (adc_unit & ADC_UNIT_1) {
|
||||
ret = adc_hal_digi_get_intr_status(ADC_NUM_1);
|
||||
}
|
||||
if (adc_unit & ADC_UNIT_2) {
|
||||
ret = adc_hal_digi_get_intr_status(ADC_NUM_2);
|
||||
}
|
||||
ADC_EXIT_CRITICAL();
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool s_isr_registered = 0;
|
||||
static intr_handle_t s_adc_isr_handle = NULL;
|
||||
|
||||
esp_err_t adc_digi_isr_register(void (*fn)(void *), void *arg, int intr_alloc_flags)
|
||||
{
|
||||
ADC_CHECK((fn != NULL), "Parameter error", ESP_ERR_INVALID_ARG);
|
||||
ADC_CHECK(s_isr_registered == 0, "ADC ISR have installed, can not install again", ESP_FAIL);
|
||||
|
||||
esp_err_t ret = esp_intr_alloc(ETS_APB_ADC_INTR_SOURCE, intr_alloc_flags, fn, arg, &s_adc_isr_handle);
|
||||
if (ret == ESP_OK) {
|
||||
s_isr_registered = 1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t adc_digi_isr_deregister(void)
|
||||
{
|
||||
esp_err_t ret = ESP_FAIL;
|
||||
if (s_isr_registered) {
|
||||
ret = esp_intr_free(s_adc_isr_handle);
|
||||
if (ret == ESP_OK) {
|
||||
s_isr_registered = 0;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
RTC controller setting
|
||||
---------------------------------------------------------------*/
|
||||
|
||||
@@ -22,25 +22,6 @@ extern "C" {
|
||||
/*---------------------------------------------------------------
|
||||
Common setting
|
||||
---------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Config ADC module arbiter.
|
||||
* The arbiter is to improve the use efficiency of ADC2. After the control right is robbed by the high priority,
|
||||
* the low priority controller will read the invalid ADC2 data, and the validity of the data can be judged by the flag bit in the data.
|
||||
*
|
||||
* @note Only ADC2 support arbiter.
|
||||
* @note Default priority: Wi-Fi > RTC > Digital;
|
||||
* @note In normal use, there is no need to call this interface to config arbiter.
|
||||
*
|
||||
* @param adc_unit ADC unit.
|
||||
* @param config Refer to `adc_arbiter_t`.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_NOT_SUPPORTED ADC unit not support arbiter.
|
||||
*/
|
||||
esp_err_t adc_arbiter_config(adc_unit_t adc_unit, adc_arbiter_t *config);
|
||||
|
||||
/*************************************/
|
||||
/* Digital controller filter setting */
|
||||
/*************************************/
|
||||
@@ -114,78 +95,6 @@ esp_err_t adc_digi_monitor_set_config(adc_digi_monitor_idx_t idx, adc_digi_monit
|
||||
*/
|
||||
esp_err_t adc_digi_monitor_enable(adc_digi_monitor_idx_t idx, bool enable);
|
||||
|
||||
/**************************************/
|
||||
/* Digital controller intr setting */
|
||||
/**************************************/
|
||||
|
||||
/**
|
||||
* @brief Enable interrupt of adc digital controller by bitmask.
|
||||
*
|
||||
* @param adc_unit ADC unit.
|
||||
* @param intr_mask Interrupt bitmask. See ``adc_digi_intr_t``.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_intr_enable(adc_unit_t adc_unit, adc_digi_intr_t intr_mask);
|
||||
|
||||
/**
|
||||
* @brief Disable interrupt of adc digital controller by bitmask.
|
||||
*
|
||||
* @param adc_unit ADC unit.
|
||||
* @param intr_mask Interrupt bitmask. See ``adc_digi_intr_t``.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_intr_disable(adc_unit_t adc_unit, adc_digi_intr_t intr_mask);
|
||||
|
||||
/**
|
||||
* @brief Clear interrupt of adc digital controller by bitmask.
|
||||
*
|
||||
* @param adc_unit ADC unit.
|
||||
* @param intr_mask Interrupt bitmask. See ``adc_digi_intr_t``.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_intr_clear(adc_unit_t adc_unit, adc_digi_intr_t intr_mask);
|
||||
|
||||
/**
|
||||
* @brief Get interrupt status mask of adc digital controller.
|
||||
*
|
||||
* @param adc_unit ADC unit.
|
||||
* @return
|
||||
* - intr Interrupt bitmask, See ``adc_digi_intr_t``.
|
||||
*/
|
||||
uint32_t adc_digi_intr_get_status(adc_unit_t adc_unit);
|
||||
|
||||
/**
|
||||
* @brief Register ADC interrupt handler, the handler is an ISR.
|
||||
* The handler will be attached to the same CPU core that this function is running on.
|
||||
*
|
||||
* @param fn Interrupt handler function.
|
||||
* @param arg Parameter for handler function
|
||||
* @param intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred)
|
||||
* ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_NOT_FOUND Can not find the interrupt that matches the flags.
|
||||
* - ESP_ERR_INVALID_ARG Function pointer error.
|
||||
*/
|
||||
esp_err_t adc_digi_isr_register(void (*fn)(void *), void *arg, int intr_alloc_flags);
|
||||
|
||||
/**
|
||||
* @brief Deregister ADC interrupt handler, the handler is an ISR.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG hander error.
|
||||
* - ESP_FAIL ISR not be registered.
|
||||
*/
|
||||
esp_err_t adc_digi_isr_deregister(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <esp_types.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <math.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "esp_log.h"
|
||||
@@ -26,6 +27,7 @@
|
||||
#include "driver/temp_sensor.h"
|
||||
#include "regi2c_ctrl.h"
|
||||
#include "esp32c3/rom/ets_sys.h"
|
||||
#include "esp32c3/esp_efuse_rtc_calib.h"
|
||||
|
||||
static const char *TAG = "tsens";
|
||||
|
||||
@@ -58,6 +60,8 @@ static const tsens_dac_offset_t dac_offset[TSENS_DAC_MAX] = {
|
||||
{TSENS_DAC_L4, 2, 10, -40, 20, 3},
|
||||
};
|
||||
|
||||
static float s_deltaT = NAN; // unused number
|
||||
|
||||
esp_err_t temp_sensor_set_config(temp_sensor_config_t tsens)
|
||||
{
|
||||
REG_SET_BIT(SYSTEM_PERIP_CLK_EN1_REG, SYSTEM_TSENS_CLK_EN);
|
||||
@@ -112,6 +116,28 @@ esp_err_t temp_sensor_read_raw(uint32_t *tsens_out)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void read_delta_t_from_efuse(void)
|
||||
{
|
||||
uint32_t version = esp_efuse_rtc_calib_get_ver();
|
||||
if (version == 1) {
|
||||
// fetch calibration value for temp sensor from eFuse
|
||||
s_deltaT = esp_efuse_rtc_calib_get_cal_temp(version);
|
||||
} else {
|
||||
// no value to fetch, use 0.
|
||||
s_deltaT = 0;
|
||||
}
|
||||
ESP_LOGD(TAG, "s_deltaT = %f", s_deltaT);
|
||||
}
|
||||
|
||||
static float parse_temp_sensor_raw_value(uint32_t tsens_raw, const int dac_offset)
|
||||
{
|
||||
if (isnan(s_deltaT)) { //suggests that the value is not initialized
|
||||
read_delta_t_from_efuse();
|
||||
}
|
||||
float result = (TSENS_ADC_FACTOR * (float)tsens_raw - TSENS_DAC_FACTOR * dac_offset - TSENS_SYS_OFFSET) - s_deltaT / 10.0;
|
||||
return result;
|
||||
}
|
||||
|
||||
esp_err_t temp_sensor_read_celsius(float *celsius)
|
||||
{
|
||||
TSENS_CHECK(celsius != NULL, ESP_ERR_INVALID_ARG);
|
||||
@@ -123,7 +149,7 @@ esp_err_t temp_sensor_read_celsius(float *celsius)
|
||||
printf("tsens_out %d\r\n", tsens_out);
|
||||
TSENS_CHECK(ret == ESP_OK, ret);
|
||||
const tsens_dac_offset_t *dac = &dac_offset[tsens.dac_offset];
|
||||
*celsius = (TSENS_ADC_FACTOR * (float)tsens_out - TSENS_DAC_FACTOR * dac->offset - TSENS_SYS_OFFSET);
|
||||
*celsius = parse_temp_sensor_raw_value(tsens_out, dac->offset);
|
||||
if (*celsius < dac->range_min || *celsius > dac->range_max) {
|
||||
ESP_LOGW(TAG, "Exceeding the temperature range!");
|
||||
ret = ESP_ERR_INVALID_STATE;
|
||||
|
||||
@@ -89,6 +89,7 @@ esp_err_t adc_digi_deinit(void)
|
||||
s_adc_digi_arbiter_lock = NULL;
|
||||
}
|
||||
#endif
|
||||
adc_power_release();
|
||||
ADC_ENTER_CRITICAL();
|
||||
adc_hal_digi_deinit();
|
||||
ADC_EXIT_CRITICAL();
|
||||
@@ -124,6 +125,8 @@ esp_err_t adc_digi_controller_config(const adc_digi_config_t *config)
|
||||
}
|
||||
}
|
||||
|
||||
/* If enable digtal controller, adc xpd should always on. */
|
||||
adc_power_acquire();
|
||||
ADC_ENTER_CRITICAL();
|
||||
adc_hal_digi_controller_config(config);
|
||||
ADC_EXIT_CRITICAL();
|
||||
|
||||
@@ -13,12 +13,12 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "driver/touch_sensor_common.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "driver/touch_sensor_common.h"
|
||||
|
||||
/**
|
||||
* @brief Set touch sensor FSM start
|
||||
* @note Start FSM after the touch sensor FSM mode is set.
|
||||
@@ -579,6 +579,22 @@ esp_err_t touch_pad_sleep_channel_reset_benchmark(void);
|
||||
*/
|
||||
esp_err_t touch_pad_sleep_channel_read_proximity_cnt(touch_pad_t pad_num, uint32_t *proximity_cnt);
|
||||
|
||||
/**
|
||||
* @brief Change the operating frequency of touch pad in deep sleep state. Reducing the operating frequency can effectively reduce power consumption.
|
||||
* If this function is not called, the working frequency of touch in the deep sleep state is the same as that in the wake-up state.
|
||||
*
|
||||
* @param sleep_cycle The touch sensor will sleep after each measurement.
|
||||
* sleep_cycle decide the interval between each measurement.
|
||||
* t_sleep = sleep_cycle / (RTC_SLOW_CLK frequency).
|
||||
* The approximate frequency value of RTC_SLOW_CLK can be obtained using rtc_clk_slow_freq_get_hz function.
|
||||
* @param meas_times The times of charge and discharge in each measure process of touch channels.
|
||||
* The timer frequency is 8Mhz. Range: 0 ~ 0xffff.
|
||||
* Recommended typical value: Modify this value to make the measurement time around 1ms.
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t touch_pad_sleep_channel_set_work_time(uint16_t sleep_cycle, uint16_t meas_times);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <math.h>
|
||||
#include "esp_types.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/semphr.h"
|
||||
@@ -61,7 +62,7 @@ static const tsens_dac_offset_t dac_offset[TSENS_DAC_MAX] = {
|
||||
|
||||
static SemaphoreHandle_t rtc_tsens_mux = NULL;
|
||||
|
||||
static float deltaT = 1000; // greater than range
|
||||
static float s_deltaT = NAN; // Unused number
|
||||
|
||||
esp_err_t temp_sensor_set_config(temp_sensor_config_t tsens)
|
||||
{
|
||||
@@ -142,20 +143,20 @@ static void read_delta_t_from_efuse(void)
|
||||
uint32_t version = esp_efuse_rtc_table_read_calib_version();
|
||||
if (version == 1 || version == 2) {
|
||||
// fetch calibration value for temp sensor from eFuse
|
||||
deltaT = esp_efuse_rtc_table_get_parsed_efuse_value(RTCCALIB_IDX_TMPSENSOR, false) / 10.0;
|
||||
s_deltaT = esp_efuse_rtc_table_get_parsed_efuse_value(RTCCALIB_IDX_TMPSENSOR, false) / 10.0;
|
||||
} else {
|
||||
// no value to fetch, use 0.
|
||||
deltaT = 0;
|
||||
s_deltaT = 0;
|
||||
}
|
||||
ESP_LOGD(TAG, "deltaT = %f\n", deltaT);
|
||||
ESP_LOGD(TAG, "s_deltaT = %f\n", s_deltaT);
|
||||
}
|
||||
|
||||
static float parse_temp_sensor_raw_value(uint32_t tsens_raw, const tsens_dac_offset_t *dac)
|
||||
static float parse_temp_sensor_raw_value(uint32_t tsens_raw, const int dac_offset)
|
||||
{
|
||||
if (deltaT > 512) { //suggests that the value is not initialized
|
||||
if (isnan(s_deltaT)) { //suggests that the value is not initialized
|
||||
read_delta_t_from_efuse();
|
||||
}
|
||||
float result = (TSENS_ADC_FACTOR * (float)tsens_raw - TSENS_DAC_FACTOR * dac->offset - TSENS_SYS_OFFSET) - deltaT;
|
||||
float result = (TSENS_ADC_FACTOR * (float)tsens_raw - TSENS_DAC_FACTOR * dac_offset - TSENS_SYS_OFFSET) - s_deltaT;
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -169,7 +170,7 @@ esp_err_t temp_sensor_read_celsius(float *celsius)
|
||||
ret = temp_sensor_read_raw(&tsens_out);
|
||||
TSENS_CHECK(ret == ESP_OK, ret);
|
||||
const tsens_dac_offset_t *dac = &dac_offset[tsens.dac_offset];
|
||||
*celsius = parse_temp_sensor_raw_value(tsens_out, dac);
|
||||
*celsius = parse_temp_sensor_raw_value(tsens_out, dac->offset);
|
||||
if (*celsius < dac->range_min || *celsius > dac->range_max) {
|
||||
ESP_LOGW(TAG, "Exceeding the temperature range!");
|
||||
ret = ESP_ERR_INVALID_STATE;
|
||||
|
||||
@@ -629,3 +629,9 @@ esp_err_t touch_pad_sleep_channel_read_proximity_cnt(touch_pad_t pad_num, uint32
|
||||
touch_hal_sleep_read_proximity_cnt(approach_cnt);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t touch_pad_sleep_channel_set_work_time(uint16_t sleep_cycle, uint16_t meas_times)
|
||||
{
|
||||
touch_hal_sleep_channel_set_work_time(sleep_cycle, meas_times);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@@ -577,6 +577,22 @@ esp_err_t touch_pad_sleep_channel_reset_benchmark(void);
|
||||
*/
|
||||
esp_err_t touch_pad_sleep_channel_read_proximity_cnt(touch_pad_t pad_num, uint32_t *proximity_cnt);
|
||||
|
||||
/**
|
||||
* @brief Change the operating frequency of touch pad in deep sleep state. Reducing the operating frequency can effectively reduce power consumption.
|
||||
* If this function is not called, the working frequency of touch in the deep sleep state is the same as that in the wake-up state.
|
||||
*
|
||||
* @param sleep_cycle The touch sensor will sleep after each measurement.
|
||||
* sleep_cycle decide the interval between each measurement.
|
||||
* t_sleep = sleep_cycle / (RTC_SLOW_CLK frequency).
|
||||
* The approximate frequency value of RTC_SLOW_CLK can be obtained using rtc_clk_slow_freq_get_hz function.
|
||||
* @param meas_times The times of charge and discharge in each measure process of touch channels.
|
||||
* The timer frequency is 8Mhz. Range: 0 ~ 0xffff.
|
||||
* Recommended typical value: Modify this value to make the measurement time around 1ms.
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t touch_pad_sleep_channel_set_work_time(uint16_t sleep_cycle, uint16_t meas_times);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -392,7 +392,7 @@ esp_err_t gpio_config(const gpio_config_t *pGPIOConfig)
|
||||
}
|
||||
|
||||
/* By default, all the pins have to be configured as GPIO pins. */
|
||||
PIN_FUNC_SELECT(io_reg, PIN_FUNC_GPIO);
|
||||
gpio_hal_iomux_func_sel(io_reg, PIN_FUNC_GPIO);
|
||||
}
|
||||
|
||||
io_num++;
|
||||
@@ -562,6 +562,9 @@ esp_err_t gpio_wakeup_enable(gpio_num_t gpio_num, gpio_int_type_t intr_type)
|
||||
#endif
|
||||
portENTER_CRITICAL(&gpio_context.gpio_spinlock);
|
||||
gpio_hal_wakeup_enable(gpio_context.gpio_hal, gpio_num, intr_type);
|
||||
#if SOC_GPIO_SUPPORT_SLP_SWITCH && CONFIG_ESP32C3_LIGHTSLEEP_GPIO_RESET_WORKAROUND
|
||||
gpio_hal_sleep_sel_dis(gpio_context.gpio_hal, gpio_num);
|
||||
#endif
|
||||
portEXIT_CRITICAL(&gpio_context.gpio_spinlock);
|
||||
} else {
|
||||
ESP_LOGE(GPIO_TAG, "GPIO wakeup only supports level mode, but edge mode set. gpio_num:%u", gpio_num);
|
||||
@@ -582,6 +585,9 @@ esp_err_t gpio_wakeup_disable(gpio_num_t gpio_num)
|
||||
#endif
|
||||
portENTER_CRITICAL(&gpio_context.gpio_spinlock);
|
||||
gpio_hal_wakeup_disable(gpio_context.gpio_hal, gpio_num);
|
||||
#if SOC_GPIO_SUPPORT_SLP_SWITCH && CONFIG_ESP32C3_LIGHTSLEEP_GPIO_RESET_WORKAROUND
|
||||
gpio_hal_sleep_sel_en(gpio_context.gpio_hal, gpio_num);
|
||||
#endif
|
||||
portEXIT_CRITICAL(&gpio_context.gpio_spinlock);
|
||||
return ret;
|
||||
}
|
||||
@@ -904,6 +910,9 @@ esp_err_t gpio_deep_sleep_wakeup_enable(gpio_num_t gpio_num, gpio_int_type_t int
|
||||
}
|
||||
portENTER_CRITICAL(&gpio_context.gpio_spinlock);
|
||||
gpio_hal_deepsleep_wakeup_enable(gpio_context.gpio_hal, gpio_num, intr_type);
|
||||
#if SOC_GPIO_SUPPORT_SLP_SWITCH && CONFIG_ESP32C3_LIGHTSLEEP_GPIO_RESET_WORKAROUND
|
||||
gpio_hal_sleep_sel_dis(gpio_context.gpio_hal, gpio_num);
|
||||
#endif
|
||||
portEXIT_CRITICAL(&gpio_context.gpio_spinlock);
|
||||
return ESP_OK;
|
||||
}
|
||||
@@ -916,6 +925,9 @@ esp_err_t gpio_deep_sleep_wakeup_disable(gpio_num_t gpio_num)
|
||||
}
|
||||
portENTER_CRITICAL(&gpio_context.gpio_spinlock);
|
||||
gpio_hal_deepsleep_wakeup_disable(gpio_context.gpio_hal, gpio_num);
|
||||
#if SOC_GPIO_SUPPORT_SLP_SWITCH && CONFIG_ESP32C3_LIGHTSLEEP_GPIO_RESET_WORKAROUND
|
||||
gpio_hal_sleep_sel_en(gpio_context.gpio_hal, gpio_num);
|
||||
#endif
|
||||
portEXIT_CRITICAL(&gpio_context.gpio_spinlock);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "esp_pm.h"
|
||||
#include "soc/soc_memory_layout.h"
|
||||
#include "hal/i2c_hal.h"
|
||||
#include "hal/gpio_hal.h"
|
||||
#include "soc/i2c_periph.h"
|
||||
#include "driver/i2c.h"
|
||||
#include "driver/periph_ctrl.h"
|
||||
@@ -831,7 +832,7 @@ esp_err_t i2c_set_pin(i2c_port_t i2c_num, int sda_io_num, int scl_io_num, bool s
|
||||
scl_in_sig = i2c_periph_signal[i2c_num].scl_in_sig;
|
||||
if (sda_io_num >= 0) {
|
||||
gpio_set_level(sda_io_num, I2C_IO_INIT_LEVEL);
|
||||
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[sda_io_num], PIN_FUNC_GPIO);
|
||||
gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[sda_io_num], PIN_FUNC_GPIO);
|
||||
gpio_set_direction(sda_io_num, GPIO_MODE_INPUT_OUTPUT_OD);
|
||||
|
||||
if (sda_pullup_en == GPIO_PULLUP_ENABLE) {
|
||||
@@ -844,7 +845,7 @@ esp_err_t i2c_set_pin(i2c_port_t i2c_num, int sda_io_num, int scl_io_num, bool s
|
||||
}
|
||||
if (scl_io_num >= 0) {
|
||||
gpio_set_level(scl_io_num, I2C_IO_INIT_LEVEL);
|
||||
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[scl_io_num], PIN_FUNC_GPIO);
|
||||
gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[scl_io_num], PIN_FUNC_GPIO);
|
||||
gpio_set_direction(scl_io_num, GPIO_MODE_INPUT_OUTPUT_OD);
|
||||
esp_rom_gpio_connect_out_signal(scl_io_num, scl_out_sig, 0, 0);
|
||||
esp_rom_gpio_connect_in_signal(scl_io_num, scl_in_sig, 0);
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "soc/lldesc.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/i2s.h"
|
||||
#include "hal/gpio_hal.h"
|
||||
#if SOC_I2S_SUPPORTS_ADC_DAC
|
||||
#include "driver/dac.h"
|
||||
#include "hal/i2s_hal.h"
|
||||
@@ -118,7 +119,7 @@ static inline void gpio_matrix_out_check(int gpio, uint32_t signal_idx, bool out
|
||||
{
|
||||
//if pin = -1, do not need to configure
|
||||
if (gpio != -1) {
|
||||
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[gpio], PIN_FUNC_GPIO);
|
||||
gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[gpio], PIN_FUNC_GPIO);
|
||||
gpio_set_direction(gpio, GPIO_MODE_OUTPUT);
|
||||
esp_rom_gpio_connect_out_signal(gpio, signal_idx, out_inv, oen_inv);
|
||||
}
|
||||
@@ -127,7 +128,7 @@ static inline void gpio_matrix_out_check(int gpio, uint32_t signal_idx, bool out
|
||||
static inline void gpio_matrix_in_check(int gpio, uint32_t signal_idx, bool inv)
|
||||
{
|
||||
if (gpio != -1) {
|
||||
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[gpio], PIN_FUNC_GPIO);
|
||||
gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[gpio], PIN_FUNC_GPIO);
|
||||
//Set direction, for some GPIOs, the input function are not enabled as default.
|
||||
gpio_set_direction(gpio, GPIO_MODE_INPUT);
|
||||
esp_rom_gpio_connect_in_signal(gpio, signal_idx, inv);
|
||||
|
||||
@@ -60,7 +60,7 @@ typedef enum {
|
||||
ADC1_CHANNEL_1, /*!< ADC1 channel 1 is GPIO1 */
|
||||
ADC1_CHANNEL_2, /*!< ADC1 channel 2 is GPIO2 */
|
||||
ADC1_CHANNEL_3, /*!< ADC1 channel 3 is GPIO3 */
|
||||
ADC1_CHANNEL_4, /*!< ADC1 channel 4 is GPIO34 */
|
||||
ADC1_CHANNEL_4, /*!< ADC1 channel 4 is GPIO4 */
|
||||
ADC1_CHANNEL_MAX,
|
||||
} adc1_channel_t;
|
||||
#endif // CONFIG_IDF_TARGET_*
|
||||
@@ -135,7 +135,7 @@ typedef enum {
|
||||
* @brief Digital ADC DMA configuration
|
||||
*/
|
||||
typedef struct adc_digi_init_config_s {
|
||||
uint32_t max_store_buf_size; ///< Max length of the converted data that driver can store before they are processed. When this length is reached, driver will dump out all the old data and start to store them again.
|
||||
uint32_t max_store_buf_size; ///< Max length of the converted data that driver can store before they are processed.
|
||||
uint32_t conv_num_each_intr; ///< Bytes of data that can be converted in 1 interrupt.
|
||||
uint32_t adc1_chan_mask; ///< Channel list of ADC1 to be initialized.
|
||||
uint32_t adc2_chan_mask; ///< Channel list of ADC2 to be initialized.
|
||||
@@ -175,6 +175,7 @@ void adc_power_acquire(void);
|
||||
*/
|
||||
void adc_power_release(void);
|
||||
|
||||
#if !CONFIG_IDF_TARGET_ESP32C3
|
||||
/**
|
||||
* @brief Initialize ADC pad
|
||||
* @param adc_unit ADC unit index
|
||||
@@ -184,11 +185,11 @@ void adc_power_release(void);
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t adc_gpio_init(adc_unit_t adc_unit, adc_channel_t channel);
|
||||
#endif //#if !CONFIG_IDF_TARGET_ESP32C3
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
RTC controller setting
|
||||
ADC Single Read Setting
|
||||
---------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Get the GPIO number of a specific ADC1 channel.
|
||||
*
|
||||
@@ -283,6 +284,7 @@ esp_err_t adc1_config_width(adc_bits_width_t width_bit);
|
||||
*/
|
||||
int adc1_get_raw(adc1_channel_t channel);
|
||||
|
||||
#if !CONFIG_IDF_TARGET_ESP32C3
|
||||
/**
|
||||
* @brief Set ADC data invert
|
||||
* @param adc_unit ADC unit index
|
||||
@@ -323,6 +325,7 @@ esp_err_t adc_set_data_width(adc_unit_t adc_unit, adc_bits_width_t width_bit);
|
||||
* to be called to configure ADC1 channels, before ADC1 is used by the ULP.
|
||||
*/
|
||||
void adc1_ulp_enable(void);
|
||||
#endif //#if !CONFIG_IDF_TARGET_ESP32C3
|
||||
|
||||
/**
|
||||
* @brief Get the GPIO number of a specific ADC2 channel.
|
||||
@@ -449,6 +452,7 @@ esp_err_t adc_vref_to_gpio(adc_unit_t adc_unit, gpio_num_t gpio);
|
||||
* - ESP_ERR_INVALID_ARG: Unsupported GPIO
|
||||
*/
|
||||
esp_err_t adc2_vref_to_gpio(gpio_num_t gpio) __attribute__((deprecated));
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
Digital controller setting
|
||||
---------------------------------------------------------------*/
|
||||
@@ -489,7 +493,7 @@ esp_err_t adc_digi_controller_config(const adc_digi_config_t *config);
|
||||
/**
|
||||
* @brief Initialize the Digital ADC.
|
||||
*
|
||||
* @param init_config Pointer to Digital ADC initilisation config. Refer to ``adc_digi_init_config_t``.
|
||||
* @param init_config Pointer to Digital ADC initilization config. Refer to ``adc_digi_init_config_t``.
|
||||
*
|
||||
* @return
|
||||
* - ESP_ERR_INVALID_ARG If the combination of arguments is invalid.
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
#include "esp_attr.h"
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
#if SOC_DEDICATED_GPIO_SUPPORTED
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@@ -171,3 +173,5 @@ esp_err_t dedic_gpio_bundle_set_interrupt_and_callback(dedic_gpio_bundle_handle_
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //SOC_DEDICATED_GPIO_SUPPORTED
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
// 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
|
||||
@@ -492,28 +492,6 @@ esp_err_t gpio_sleep_set_direction(gpio_num_t gpio_num, gpio_mode_t mode);
|
||||
* - ESP_ERR_INVALID_ARG : Parameter error
|
||||
*/
|
||||
esp_err_t gpio_sleep_set_pull_mode(gpio_num_t gpio_num, gpio_pull_mode_t pull);
|
||||
|
||||
#if CONFIG_GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL
|
||||
/**
|
||||
* @brief Emulate ESP32S2 behaviour to backup FUN_PU, FUN_PD information
|
||||
*
|
||||
* @note Need to be called before sleep.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t gpio_sleep_pupd_config_apply(gpio_num_t gpio_num);
|
||||
|
||||
/**
|
||||
* @brief Emulate ESP32S2 behaviour to restore FUN_PU, FUN_PD information
|
||||
*
|
||||
* @note Need to be called after sleep.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t gpio_sleep_pupd_config_unapply(gpio_num_t gpio_num);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP
|
||||
|
||||
@@ -17,10 +17,12 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include "esp_err.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "soc/soc_caps.h"
|
||||
#include "soc/rtc_io_periph.h"
|
||||
#include "hal/rtc_io_types.h"
|
||||
#include "driver/gpio.h"
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@@ -42,6 +44,7 @@ static inline bool rtc_gpio_is_valid_gpio(gpio_num_t gpio_num)
|
||||
|
||||
#define RTC_GPIO_IS_VALID_GPIO(gpio_num) rtc_gpio_is_valid_gpio(gpio_num) // Deprecated, use rtc_gpio_is_valid_gpio()
|
||||
|
||||
#if SOC_RTCIO_INPUT_OUTPUT_SUPPORTED
|
||||
/**
|
||||
* @brief Get RTC IO index number by gpio number.
|
||||
*
|
||||
@@ -52,15 +55,9 @@ static inline bool rtc_gpio_is_valid_gpio(gpio_num_t gpio_num)
|
||||
*/
|
||||
static inline int rtc_io_number_get(gpio_num_t gpio_num)
|
||||
{
|
||||
#if SOC_RTCIO_INPUT_OUTPUT_SUPPORTED
|
||||
return rtc_io_num_map[gpio_num];
|
||||
#else
|
||||
return gpio_num;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if SOC_RTCIO_INPUT_OUTPUT_SUPPORTED
|
||||
|
||||
/**
|
||||
* @brief Init a GPIO as RTC GPIO
|
||||
*
|
||||
|
||||
@@ -28,6 +28,12 @@ extern "C" {
|
||||
/// Handle representing an SD SPI device
|
||||
typedef int sdspi_dev_handle_t;
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2
|
||||
#define SDSPI_DEFAULT_HOST HSPI_HOST
|
||||
#else
|
||||
#define SDSPI_DEFAULT_HOST SPI2_HOST
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Default sdmmc_host_t structure initializer for SD over SPI driver
|
||||
*
|
||||
@@ -37,7 +43,7 @@ typedef int sdspi_dev_handle_t;
|
||||
*/
|
||||
#define SDSPI_HOST_DEFAULT() {\
|
||||
.flags = SDMMC_HOST_FLAG_SPI | SDMMC_HOST_FLAG_DEINIT_ARG, \
|
||||
.slot = HSPI_HOST, \
|
||||
.slot = SDSPI_DEFAULT_HOST, \
|
||||
.max_freq_khz = SDMMC_FREQ_DEFAULT, \
|
||||
.io_voltage = 3.3f, \
|
||||
.init = &sdspi_host_init, \
|
||||
@@ -71,7 +77,7 @@ typedef struct {
|
||||
* Macro defining default configuration of SD SPI device.
|
||||
*/
|
||||
#define SDSPI_DEVICE_CONFIG_DEFAULT() {\
|
||||
.host_id = HSPI_HOST, \
|
||||
.host_id = SDSPI_DEFAULT_HOST, \
|
||||
.gpio_cs = GPIO_NUM_13, \
|
||||
.gpio_cd = SDSPI_SLOT_NO_CD, \
|
||||
.gpio_wp = SDSPI_SLOT_NO_WP, \
|
||||
@@ -228,7 +234,7 @@ typedef struct {
|
||||
*
|
||||
* @note The SDIO over sdspi needs an extra interrupt line. Call ``gpio_install_isr_service()`` before this function.
|
||||
*
|
||||
* @param slot SPI controller to use (HSPI_HOST or VSPI_HOST)
|
||||
* @param slot SPI controller to use (SPI2_HOST or SPI3_HOST)
|
||||
* @param slot_config pointer to slot configuration structure
|
||||
|
||||
* @deprecated Use `sdspi_host_init_device` instead.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user