forked from espressif/esp-idf
Compare commits
489 Commits
Author | SHA1 | Date | |
---|---|---|---|
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 | |||
3b9af23290 | |||
ff12b50e45 | |||
f6336516d1 | |||
4d80dd1238 | |||
8a2155f95e | |||
367190deaf | |||
dbb632fe34 | |||
1329747dc1 | |||
f9e1942252 | |||
82ffb33085 | |||
9fd12182de | |||
d42958439d | |||
37946ab300 | |||
2b7a3f6d85 | |||
60642e580c | |||
4235e80008 | |||
a8e0989648 | |||
28f50addda | |||
9393a402eb | |||
268787c5fb | |||
d92ac450a2 | |||
233f3f80e5 | |||
d01efe4b8c | |||
e48935d187 | |||
12bbd1f051 | |||
0305d13467 | |||
e6ace495b4 | |||
b449909b35 | |||
0253d825e9 | |||
32b0836485 | |||
7dca6b7428 | |||
b180c2a146 | |||
113bf479a4 | |||
774f010196 | |||
22a8fe5b6f | |||
d36c72fba0 | |||
1c8fd4041e | |||
d4263c2558 | |||
ea49545269 | |||
9ca05c17ae | |||
fd93c475b6 | |||
27c72a4105 | |||
5c8b1d6ab8 | |||
c5f8fbea02 | |||
cf7891cb93 | |||
1e77586120 | |||
1ea548ecb3 | |||
962ea61d53 | |||
d61ee580d5 | |||
947e445e02 | |||
1821fd766b | |||
d508182429 | |||
58c9a2eaba | |||
07b62da0d4 | |||
fb82bdb9da | |||
f3be9976b9 | |||
b639514793 | |||
f12b571f82 | |||
c0f06115d4 | |||
20b25a9667 | |||
1d9d444c07 | |||
060a829091 | |||
78314df2a5 | |||
8ceb462993 | |||
6accffecea | |||
de79e482c9 | |||
6638b81f8e | |||
d92b647199 | |||
965daf977a | |||
aa652adc12 | |||
5795075460 | |||
198d350fe5 | |||
24f3341a2d | |||
5a429f644f | |||
9aae8e0ce3 | |||
e5e47ebae6 | |||
436c3c289e | |||
2aa6aa8b88 | |||
3e9cd49d32 | |||
2c1845995b | |||
0c77299c34 | |||
9ac3e7c5d1 | |||
c42ce05941 | |||
ea2eb9d833 | |||
dec52a93d4 | |||
41bee7831f | |||
bd1b4dbda1 | |||
1de12526eb | |||
f0f2799946 | |||
5aabdd8abf | |||
8a2f91b48a | |||
ed6fb33726 | |||
66d10f0eec | |||
97f248d22c | |||
ffc4ff5a8c | |||
326d76ebdf | |||
c6ed522d60 | |||
8e187e7157 | |||
19f18aaa11 | |||
626a861115 | |||
a0fdf4b06c | |||
3d9523724d | |||
813b6c4ef6 | |||
1b849d59de | |||
87576aba28 | |||
57fb076590 | |||
360e7c4d51 | |||
9083ef97e5 | |||
a7a1e4dfba | |||
8ad92a92b9 | |||
321ee21c4c | |||
33820657c5 | |||
33892aadb9 | |||
ad669801ae |
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 */
|
||||
|
@ -274,6 +274,10 @@ menu "Bootloader config"
|
||||
|
||||
config BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP
|
||||
bool "Skip image validation when exiting deep sleep"
|
||||
# note: dependencies for this config item are different to other "skip image validation"
|
||||
# options, allowing to turn on "allow insecure options" and have secure boot with
|
||||
# "skip validation when existing deep sleep". Keeping this to avoid a breaking change,
|
||||
# but - as noted in help - it invalidates the integrity of Secure Boot checks
|
||||
depends on (SECURE_BOOT && SECURE_BOOT_INSECURE) || !SECURE_BOOT
|
||||
default n
|
||||
help
|
||||
@ -286,6 +290,48 @@ menu "Bootloader config"
|
||||
partition as this would skip the validation upon first load of the new
|
||||
OTA partition.
|
||||
|
||||
It is possible to enable this option with Secure Boot if "allow insecure
|
||||
options" is enabled, however it's strongly recommended to NOT enable it as
|
||||
it may allow a Secure Boot bypass.
|
||||
|
||||
config BOOTLOADER_SKIP_VALIDATE_ON_POWER_ON
|
||||
bool "Skip image validation from power on reset (READ HELP FIRST)"
|
||||
# only available if both Secure Boot and Check Signature on Boot are disabled
|
||||
depends on !SECURE_SIGNED_ON_BOOT
|
||||
default n
|
||||
help
|
||||
Some applications need to boot very quickly from power on. By default, the entire app binary
|
||||
is read from flash and verified which takes up a significant portion of the boot time.
|
||||
|
||||
Enabling this option will skip validation of the app when the SoC boots from power on.
|
||||
Note that in this case it's not possible for the bootloader to detect if an app image is
|
||||
corrupted in the flash, therefore it's not possible to safely fall back to a different app
|
||||
partition. Flash corruption of this kind is unlikely but can happen if there is a serious
|
||||
firmware bug or physical damage.
|
||||
|
||||
Following other reset types, the bootloader will still validate the app image. This increases
|
||||
the chances that flash corruption resulting in a crash can be detected following soft reset, and
|
||||
the bootloader will fall back to a valid app image. To increase the chances of successfully recovering
|
||||
from a flash corruption event, keep the option BOOTLOADER_WDT_ENABLE enabled and consider also enabling
|
||||
BOOTLOADER_WDT_DISABLE_IN_USER_CODE - then manually disable the RTC Watchdog once the app is running.
|
||||
In addition, enable both the Task and Interrupt watchdog timers with reset options set.
|
||||
|
||||
config BOOTLOADER_SKIP_VALIDATE_ALWAYS
|
||||
bool "Skip image validation always (READ HELP FIRST)"
|
||||
# only available if both Secure Boot and Check Signature on Boot are disabled
|
||||
depends on !SECURE_SIGNED_ON_BOOT
|
||||
default n
|
||||
select BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP
|
||||
select BOOTLOADER_SKIP_VALIDATE_ON_POWER_ON
|
||||
help
|
||||
Selecting this option prevents the bootloader from ever validating the app image before
|
||||
booting it. Any flash corruption of the selected app partition will make the entire SoC
|
||||
unbootable.
|
||||
|
||||
Although flash corruption is a very rare case, it is not recommended to select this option.
|
||||
Consider selecting "Skip image validation from power on reset" instead. However, if boot time
|
||||
is the only important factor then it can be enabled.
|
||||
|
||||
config BOOTLOADER_RESERVE_RTC_SIZE
|
||||
hex
|
||||
default 0x10 if BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP || BOOTLOADER_CUSTOM_RESERVE_RTC
|
||||
@ -378,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"
|
||||
@ -390,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.
|
||||
@ -399,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.
|
||||
@ -425,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.
|
||||
|
||||
@ -442,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.
|
||||
|
||||
@ -456,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.
|
||||
@ -626,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"
|
||||
@ -692,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
|
||||
@ -752,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;
|
||||
}
|
@ -327,11 +327,24 @@ err:
|
||||
|
||||
esp_err_t bootloader_load_image(const esp_partition_pos_t *part, esp_image_metadata_t *data)
|
||||
{
|
||||
#ifdef BOOTLOADER_BUILD
|
||||
return image_load(ESP_IMAGE_LOAD, part, data);
|
||||
#else
|
||||
#if !defined(BOOTLOADER_BUILD)
|
||||
return ESP_FAIL;
|
||||
#endif
|
||||
#else
|
||||
esp_image_load_mode_t mode = ESP_IMAGE_LOAD;
|
||||
|
||||
#if !defined(CONFIG_SECURE_BOOT)
|
||||
/* Skip validation under particular configurations */
|
||||
#if CONFIG_BOOTLOADER_SKIP_VALIDATE_ALWAYS
|
||||
mode = ESP_IMAGE_LOAD_NO_VALIDATE;
|
||||
#elif CONFIG_BOOTLOADER_SKIP_VALIDATE_ON_POWER_ON
|
||||
if (rtc_get_reset_reason(0) == POWERON_RESET) {
|
||||
mode = ESP_IMAGE_LOAD_NO_VALIDATE;
|
||||
}
|
||||
#endif // CONFIG_BOOTLOADER_SKIP_...
|
||||
#endif // CONFIG_SECURE_BOOT
|
||||
|
||||
return image_load(mode, part, data);
|
||||
#endif // BOOTLOADER_BUILD
|
||||
}
|
||||
|
||||
esp_err_t bootloader_load_image_no_verify(const esp_partition_pos_t *part, esp_image_metadata_t *data)
|
||||
@ -348,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;
|
||||
@ -808,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();
|
||||
@ -1442,16 +1541,12 @@ esp_err_t esp_bt_controller_deinit(void)
|
||||
static void bt_shutdown(void)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
ESP_LOGD(BTDM_LOG_TAG, "stop/deinit bt");
|
||||
ESP_LOGD(BTDM_LOG_TAG, "stop Bluetooth");
|
||||
|
||||
ret = esp_bt_controller_disable();
|
||||
if (ESP_OK != ret) {
|
||||
ESP_LOGW(BTDM_LOG_TAG, "controller disable ret=%d", ret);
|
||||
}
|
||||
ret = esp_bt_controller_deinit();
|
||||
if (ESP_OK != ret) {
|
||||
ESP_LOGW(BTDM_LOG_TAG, "controller deinit ret=%d", ret);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
@ -740,13 +741,16 @@ static void IRAM_ATTR btdm_sleep_exit_phase0(void *param)
|
||||
}
|
||||
#endif
|
||||
|
||||
btdm_wakeup_request();
|
||||
int event = (int) param;
|
||||
if (event == BTDM_ASYNC_WAKEUP_SRC_VHCI || event == BTDM_ASYNC_WAKEUP_SRC_DISA) {
|
||||
btdm_wakeup_request();
|
||||
}
|
||||
|
||||
if (s_lp_cntl.wakeup_timer_required && s_lp_stat.wakeup_timer_started) {
|
||||
esp_timer_stop(s_btdm_slp_tmr);
|
||||
s_lp_stat.wakeup_timer_started = 0;
|
||||
}
|
||||
int event = (int) param;
|
||||
|
||||
if (event == BTDM_ASYNC_WAKEUP_SRC_VHCI || event == BTDM_ASYNC_WAKEUP_SRC_DISA) {
|
||||
semphr_give_wrapper(s_wakeup_req_sem);
|
||||
}
|
||||
@ -1331,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 d1115cabc2
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"
|
||||
|
@ -133,7 +133,8 @@ esp_err_t esp_spp_start_srv(esp_spp_sec_t sec_mask,
|
||||
btc_spp_args_t arg;
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
|
||||
if (strlen(name) > ESP_SPP_SERVER_NAME_MAX) {
|
||||
if (name == NULL || strlen(name) > ESP_SPP_SERVER_NAME_MAX) {
|
||||
LOG_ERROR("Invalid server name!\n");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
@ -157,13 +158,34 @@ esp_err_t esp_spp_start_srv(esp_spp_sec_t sec_mask,
|
||||
esp_err_t esp_spp_stop_srv(void)
|
||||
{
|
||||
btc_msg_t msg;
|
||||
btc_spp_args_t arg;
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_SPP;
|
||||
msg.act = BTC_SPP_ACT_STOP_SRV;
|
||||
arg.stop_srv.scn = BTC_SPP_INVALID_SCN;
|
||||
|
||||
return (btc_transfer_context(&msg, NULL, sizeof(btc_spp_args_t), NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
|
||||
return (btc_transfer_context(&msg, &arg, sizeof(btc_spp_args_t), NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
|
||||
}
|
||||
|
||||
esp_err_t esp_spp_stop_srv_scn(uint8_t scn)
|
||||
{
|
||||
btc_msg_t msg;
|
||||
btc_spp_args_t arg;
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
|
||||
if ((scn == 0) || (scn >= PORT_MAX_RFC_PORTS)) {
|
||||
LOG_ERROR("Invalid SCN!\n");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_SPP;
|
||||
msg.act = BTC_SPP_ACT_STOP_SRV;
|
||||
arg.stop_srv.scn = scn;
|
||||
|
||||
return (btc_transfer_context(&msg, &arg, sizeof(btc_spp_args_t), NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|
@ -26,11 +26,12 @@ typedef enum {
|
||||
ESP_SPP_SUCCESS = 0, /*!< Successful operation. */
|
||||
ESP_SPP_FAILURE, /*!< Generic failure. */
|
||||
ESP_SPP_BUSY, /*!< Temporarily can not handle this request. */
|
||||
ESP_SPP_NO_DATA, /*!< no data. */
|
||||
ESP_SPP_NO_DATA, /*!< No data */
|
||||
ESP_SPP_NO_RESOURCE, /*!< No more resource */
|
||||
ESP_SPP_NEED_INIT, /*!< SPP module shall init first */
|
||||
ESP_SPP_NEED_DEINIT, /*!< SPP module shall deinit first */
|
||||
ESP_SPP_NO_CONNECTION, /*!< connection may have been closed */
|
||||
ESP_SPP_NO_CONNECTION, /*!< Connection may have been closed */
|
||||
ESP_SPP_NO_SERVER, /*!< No SPP server */
|
||||
} esp_spp_status_t;
|
||||
|
||||
/* Security Setting Mask
|
||||
@ -101,9 +102,10 @@ typedef union {
|
||||
* @brief SPP_DISCOVERY_COMP_EVT
|
||||
*/
|
||||
struct spp_discovery_comp_evt_param {
|
||||
esp_spp_status_t status; /*!< status */
|
||||
uint8_t scn_num; /*!< The num of scn_num */
|
||||
uint8_t scn[ESP_SPP_MAX_SCN]; /*!< channel # */
|
||||
esp_spp_status_t status; /*!< status */
|
||||
uint8_t scn_num; /*!< The num of scn_num */
|
||||
uint8_t scn[ESP_SPP_MAX_SCN]; /*!< channel # */
|
||||
const char *service_name[ESP_SPP_MAX_SCN]; /*!< service_name */
|
||||
} disc_comp; /*!< SPP callback param of SPP_DISCOVERY_COMP_EVT */
|
||||
|
||||
/**
|
||||
@ -143,6 +145,7 @@ typedef union {
|
||||
esp_spp_status_t status; /*!< status */
|
||||
uint32_t handle; /*!< The connection handle */
|
||||
uint8_t sec_id; /*!< security ID used by this server */
|
||||
uint8_t scn; /*!< Server channel number */
|
||||
bool use_co; /*!< TRUE to use co_rfc_data */
|
||||
} start; /*!< SPP callback param of ESP_SPP_START_EVT */
|
||||
|
||||
@ -151,6 +154,7 @@ typedef union {
|
||||
*/
|
||||
struct spp_srv_stop_evt_param {
|
||||
esp_spp_status_t status; /*!< status */
|
||||
uint8_t scn; /*!< Server channel number */
|
||||
} srv_stop; /*!< SPP callback param of ESP_SPP_SRV_STOP_EVT */
|
||||
|
||||
/**
|
||||
@ -304,7 +308,7 @@ esp_err_t esp_spp_disconnect(uint32_t handle);
|
||||
esp_err_t esp_spp_start_srv(esp_spp_sec_t sec_mask, esp_spp_role_t role, uint8_t local_scn, const char *name);
|
||||
|
||||
/**
|
||||
* @brief This function stops a SPP server.
|
||||
* @brief This function stops all SPP servers.
|
||||
* The operation will close all active SPP connection first, then the callback function will be called
|
||||
* with ESP_SPP_CLOSE_EVT, and the number of ESP_SPP_CLOSE_EVT is equal to the number of connection.
|
||||
* When the operation is completed, the callback is called with ESP_SPP_SRV_STOP_EVT.
|
||||
@ -314,8 +318,24 @@ esp_err_t esp_spp_start_srv(esp_spp_sec_t sec_mask, esp_spp_role_t role, uint8_t
|
||||
* - ESP_OK: success
|
||||
* - other: failed
|
||||
*/
|
||||
|
||||
esp_err_t esp_spp_stop_srv(void);
|
||||
|
||||
/**
|
||||
* @brief This function stops a specific SPP server.
|
||||
* The operation will close all active SPP connection first on the specific SPP server, then the callback function will be called
|
||||
* with ESP_SPP_CLOSE_EVT, and the number of ESP_SPP_CLOSE_EVT is equal to the number of connection.
|
||||
* When the operation is completed, the callback is called with ESP_SPP_SRV_STOP_EVT.
|
||||
* This funciton must be called after esp_spp_init() successful and before esp_spp_deinit().
|
||||
*
|
||||
* @param[in] scn: Server channel number.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: success
|
||||
* - other: failed
|
||||
*/
|
||||
esp_err_t esp_spp_stop_srv_scn(uint8_t scn);
|
||||
|
||||
/**
|
||||
* @brief This function is used to write data, only for ESP_SPP_MODE_CB.
|
||||
* When this function need to be called repeatedly, it is strongly recommended to call this function again after
|
||||
|
@ -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;
|
||||
|
@ -172,9 +172,10 @@ typedef struct {
|
||||
|
||||
/* data associated with BTA_JV_DISCOVERY_COMP_EVT_ */
|
||||
typedef struct {
|
||||
tBTA_JV_STATUS status; /* Whether the operation succeeded or failed. */
|
||||
UINT8 scn_num; /* num of channel */
|
||||
UINT8 scn[BTA_JV_MAX_SCN]; /* channel # */
|
||||
tBTA_JV_STATUS status; /* Whether the operation succeeded or failed. */
|
||||
UINT8 scn_num; /* num of channel */
|
||||
UINT8 scn[BTA_JV_MAX_SCN]; /* channel # */
|
||||
const char *service_name[BTA_JV_MAX_SCN]; /* service_name */
|
||||
} tBTA_JV_DISCOVERY_COMP;
|
||||
|
||||
/* data associated with BTA_JV_CREATE_RECORD_EVT */
|
||||
@ -305,6 +306,7 @@ typedef struct {
|
||||
tBTA_JV_STATUS status; /* Whether the operation succeeded or failed. */
|
||||
UINT32 handle; /* The connection handle */
|
||||
UINT8 sec_id; /* security ID used by this server */
|
||||
UINT8 scn; /* Server channe number */
|
||||
BOOLEAN use_co; /* TRUE to use co_rfc_data */
|
||||
} tBTA_JV_RFCOMM_START;
|
||||
|
||||
@ -376,8 +378,9 @@ typedef struct {
|
||||
|
||||
/* data associated with BTA_JV_FREE_SCN_EVT */
|
||||
typedef struct {
|
||||
tBTA_JV_STATUS status; /* Status of the operation */
|
||||
tBTA_JV_SERVER_STATUS server_status;
|
||||
tBTA_JV_STATUS status; /* Status of the operation */
|
||||
tBTA_JV_SERVER_STATUS server_status; /* Server status */
|
||||
UINT8 scn; /* Server channe number */
|
||||
} tBTA_JV_FREE_SCN;
|
||||
|
||||
|
||||
|
@ -856,6 +856,7 @@ void bta_jv_free_scn(tBTA_JV_MSG *p_data)
|
||||
tBTA_JV_FREE_SCN evt_data = {
|
||||
.status = BTA_JV_SUCCESS,
|
||||
.server_status = BTA_JV_SERVER_STATUS_MAX,
|
||||
.scn = scn
|
||||
};
|
||||
|
||||
tBTA_JV_FREE_SCN_USER_DATA *user_data = NULL;
|
||||
@ -949,6 +950,7 @@ static void bta_jv_start_discovery_cback(UINT16 result, void *user_data)
|
||||
status = BTA_JV_FAILURE;
|
||||
if (result == SDP_SUCCESS || result == SDP_DB_FULL) {
|
||||
tSDP_DISC_REC *p_sdp_rec = NULL;
|
||||
tSDP_DISC_ATTR *p_attr = NULL;
|
||||
tSDP_PROTOCOL_ELEM pe;
|
||||
logu("bta_jv_cb.uuid", bta_jv_cb.uuid.uu.uuid128);
|
||||
tBT_UUID su = shorten_sdp_uuid(&bta_jv_cb.uuid);
|
||||
@ -957,7 +959,13 @@ static void bta_jv_start_discovery_cback(UINT16 result, void *user_data)
|
||||
p_sdp_rec = SDP_FindServiceUUIDInDb(p_bta_jv_cfg->p_sdp_db, &su, p_sdp_rec);
|
||||
APPL_TRACE_DEBUG("p_sdp_rec:%p", p_sdp_rec);
|
||||
if (p_sdp_rec && SDP_FindProtocolListElemInRec(p_sdp_rec, UUID_PROTOCOL_RFCOMM, &pe)){
|
||||
dcomp.scn[dcomp.scn_num++] = (UINT8) pe.params[0];
|
||||
dcomp.scn[dcomp.scn_num] = (UINT8) pe.params[0];
|
||||
if ((p_attr = SDP_FindAttributeInRec(p_sdp_rec, ATTR_ID_SERVICE_NAME)) != NULL) {
|
||||
dcomp.service_name[dcomp.scn_num] = (char *)p_attr->attr_value.v.array;
|
||||
} else {
|
||||
dcomp.service_name[dcomp.scn_num] = NULL;
|
||||
}
|
||||
dcomp.scn_num++;
|
||||
status = BTA_JV_SUCCESS;
|
||||
}
|
||||
} while (p_sdp_rec);
|
||||
@ -2154,6 +2162,7 @@ void bta_jv_rfcomm_start_server(tBTA_JV_MSG *p_data)
|
||||
evt_data.status = BTA_JV_SUCCESS;
|
||||
evt_data.handle = p_pcb->handle;
|
||||
evt_data.sec_id = sec_id;
|
||||
evt_data.scn = rs->local_scn;
|
||||
evt_data.use_co = TRUE;
|
||||
|
||||
PORT_ClearKeepHandleFlag(handle);
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -28,6 +28,8 @@
|
||||
|
||||
#define ESP_SPP_RINGBUF_SIZE 1000
|
||||
|
||||
#define BTC_SPP_INVALID_SCN 0x00
|
||||
|
||||
typedef enum {
|
||||
BTC_SPP_ACT_INIT = 0,
|
||||
BTC_SPP_ACT_UNINIT,
|
||||
@ -74,6 +76,10 @@ typedef union {
|
||||
UINT8 max_session;
|
||||
char name[ESP_SPP_SERVER_NAME_MAX + 1];
|
||||
} start_srv;
|
||||
//BTC_SPP_ACT_STOP_SRV
|
||||
struct stop_srv_arg {
|
||||
UINT8 scn;
|
||||
} stop_srv;
|
||||
//BTC_SPP_ACT_WRITE
|
||||
struct write_arg {
|
||||
UINT32 handle;
|
||||
|
@ -265,6 +265,10 @@ static void btc_create_server_fail_cb(void)
|
||||
{
|
||||
esp_spp_cb_param_t param;
|
||||
param.start.status = ESP_SPP_FAILURE;
|
||||
param.start.handle = 0;
|
||||
param.start.sec_id = 0;
|
||||
param.start.scn = BTC_SPP_INVALID_SCN;
|
||||
param.start.use_co = FALSE;
|
||||
btc_spp_cb_to_app(ESP_SPP_START_EVT, ¶m);
|
||||
}
|
||||
|
||||
@ -531,6 +535,7 @@ static void btc_spp_uninit(void)
|
||||
esp_spp_cb_param_t param;
|
||||
BTC_TRACE_ERROR("%s unable to malloc user data!", __func__);
|
||||
param.srv_stop.status = ESP_SPP_NO_RESOURCE;
|
||||
param.srv_stop.scn = spp_local_param.spp_slots[i]->scn;
|
||||
btc_spp_cb_to_app(ESP_SPP_SRV_STOP_EVT, ¶m);
|
||||
}
|
||||
BTA_JvFreeChannel(spp_local_param.spp_slots[i]->scn, BTA_JV_CONN_TYPE_RFCOMM,
|
||||
@ -672,61 +677,117 @@ static void btc_spp_start_srv(btc_spp_args_t *arg)
|
||||
if (ret != ESP_SPP_SUCCESS) {
|
||||
esp_spp_cb_param_t param;
|
||||
param.start.status = ret;
|
||||
param.start.handle = 0;
|
||||
param.start.sec_id = 0;
|
||||
param.start.scn = BTC_SPP_INVALID_SCN;
|
||||
param.start.use_co = FALSE;
|
||||
btc_spp_cb_to_app(ESP_SPP_START_EVT, ¶m);
|
||||
}
|
||||
}
|
||||
|
||||
static void btc_spp_stop_srv(void)
|
||||
static void btc_spp_stop_srv(btc_spp_args_t *arg)
|
||||
{
|
||||
esp_spp_status_t ret = ESP_SPP_SUCCESS;
|
||||
bool is_remove_all = false;
|
||||
uint8_t i, j, srv_cnt = 0;
|
||||
uint8_t *srv_scn_arr = osi_malloc(MAX_RFC_PORTS);
|
||||
if (arg->stop_srv.scn == BTC_SPP_INVALID_SCN) {
|
||||
is_remove_all = true;
|
||||
}
|
||||
|
||||
do {
|
||||
if (!is_spp_init()) {
|
||||
BTC_TRACE_ERROR("%s SPP have not been init\n", __func__);
|
||||
ret = ESP_SPP_NEED_INIT;
|
||||
break;
|
||||
}
|
||||
if (srv_scn_arr == NULL) {
|
||||
BTC_TRACE_ERROR("%s malloc srv_scn_arr failed\n", __func__);
|
||||
ret = ESP_SPP_NO_RESOURCE;
|
||||
break;
|
||||
}
|
||||
|
||||
osi_mutex_lock(&spp_local_param.spp_slot_mutex, OSI_MUTEX_MAX_TIMEOUT);
|
||||
// first, remove all connection
|
||||
for (size_t i = 1; i <= MAX_RFC_PORTS; i++) {
|
||||
if (spp_local_param.spp_slots[i] != NULL && spp_local_param.spp_slots[i]->connected) {
|
||||
BTA_JvRfcommClose(spp_local_param.spp_slots[i]->rfc_handle, (tBTA_JV_RFCOMM_CBACK *)btc_spp_rfcomm_inter_cb,
|
||||
(void *)spp_local_param.spp_slots[i]->id);
|
||||
// [1] find all server
|
||||
for (i = 1; i <= MAX_RFC_PORTS; i++) {
|
||||
if (spp_local_param.spp_slots[i] != NULL && !spp_local_param.spp_slots[i]->connected &&
|
||||
spp_local_param.spp_slots[i]->sdp_handle > 0) {
|
||||
if (is_remove_all) {
|
||||
srv_scn_arr[srv_cnt++] = spp_local_param.spp_slots[i]->scn;
|
||||
} else if (spp_local_param.spp_slots[i]->scn == arg->stop_srv.scn) {
|
||||
srv_scn_arr[srv_cnt++] = spp_local_param.spp_slots[i]->scn;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// second, remove all server
|
||||
for (size_t i = 1; i <= MAX_RFC_PORTS; i++) {
|
||||
if (spp_local_param.spp_slots[i] != NULL && !spp_local_param.spp_slots[i]->connected) {
|
||||
if (spp_local_param.spp_slots[i]->sdp_handle > 0) {
|
||||
BTA_JvDeleteRecord(spp_local_param.spp_slots[i]->sdp_handle);
|
||||
}
|
||||
if (srv_cnt == 0) {
|
||||
if (is_remove_all) {
|
||||
BTC_TRACE_ERROR("%s can not find any server!\n", __func__);
|
||||
} else {
|
||||
BTC_TRACE_ERROR("%s can not find server:%d!\n", __func__, arg->stop_srv.scn);
|
||||
}
|
||||
ret = ESP_SPP_NO_SERVER;
|
||||
break;
|
||||
}
|
||||
|
||||
if (spp_local_param.spp_slots[i]->rfc_handle > 0) {
|
||||
BTA_JvRfcommStopServer(spp_local_param.spp_slots[i]->rfc_handle,
|
||||
(void *)spp_local_param.spp_slots[i]->id);
|
||||
// [2] remove all local related connection
|
||||
for (j = 0; j < srv_cnt; j++) {
|
||||
for (i = 1; i <= MAX_RFC_PORTS; i++) {
|
||||
if (spp_local_param.spp_slots[i] != NULL && spp_local_param.spp_slots[i]->connected &&
|
||||
spp_local_param.spp_slots[i]->sdp_handle > 0 &&
|
||||
spp_local_param.spp_slots[i]->scn == srv_scn_arr[j]) {
|
||||
BTA_JvRfcommClose(spp_local_param.spp_slots[i]->rfc_handle,
|
||||
(tBTA_JV_RFCOMM_CBACK *)btc_spp_rfcomm_inter_cb,
|
||||
(void *)spp_local_param.spp_slots[i]->id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tBTA_JV_FREE_SCN_USER_DATA *user_data = osi_malloc(sizeof(tBTA_JV_FREE_SCN_USER_DATA));
|
||||
if (user_data) {
|
||||
user_data->server_status = BTA_JV_SERVER_RUNNING;
|
||||
user_data->slot_id = spp_local_param.spp_slots[i]->id;
|
||||
} else {
|
||||
esp_spp_cb_param_t param;
|
||||
BTC_TRACE_ERROR("%s unable to malloc user data!", __func__);
|
||||
param.srv_stop.status = ESP_SPP_NO_RESOURCE;
|
||||
btc_spp_cb_to_app(ESP_SPP_SRV_STOP_EVT, ¶m);
|
||||
// [3] remove all server
|
||||
for (j = 0; j < srv_cnt; j++) {
|
||||
for (i = 1; i <= MAX_RFC_PORTS; i++) {
|
||||
if (spp_local_param.spp_slots[i] != NULL && !spp_local_param.spp_slots[i]->connected &&
|
||||
spp_local_param.spp_slots[i]->sdp_handle > 0 &&
|
||||
spp_local_param.spp_slots[i]->scn == srv_scn_arr[j]) {
|
||||
if (spp_local_param.spp_slots[i]->sdp_handle > 0) {
|
||||
BTA_JvDeleteRecord(spp_local_param.spp_slots[i]->sdp_handle);
|
||||
}
|
||||
|
||||
if (spp_local_param.spp_slots[i]->rfc_handle > 0) {
|
||||
BTA_JvRfcommStopServer(spp_local_param.spp_slots[i]->rfc_handle,
|
||||
(void *)spp_local_param.spp_slots[i]->id);
|
||||
}
|
||||
|
||||
tBTA_JV_FREE_SCN_USER_DATA *user_data = osi_malloc(sizeof(tBTA_JV_FREE_SCN_USER_DATA));
|
||||
if (user_data) {
|
||||
user_data->server_status = BTA_JV_SERVER_RUNNING;
|
||||
user_data->slot_id = spp_local_param.spp_slots[i]->id;
|
||||
} else {
|
||||
esp_spp_cb_param_t param;
|
||||
BTC_TRACE_ERROR("%s unable to malloc user data!", __func__);
|
||||
param.srv_stop.status = ESP_SPP_NO_RESOURCE;
|
||||
param.srv_stop.scn = spp_local_param.spp_slots[i]->scn;
|
||||
btc_spp_cb_to_app(ESP_SPP_SRV_STOP_EVT, ¶m);
|
||||
}
|
||||
BTA_JvFreeChannel(spp_local_param.spp_slots[i]->scn, BTA_JV_CONN_TYPE_RFCOMM,
|
||||
(tBTA_JV_RFCOMM_CBACK *)btc_spp_rfcomm_inter_cb, (void *)user_data);
|
||||
}
|
||||
BTA_JvFreeChannel(spp_local_param.spp_slots[i]->scn, BTA_JV_CONN_TYPE_RFCOMM,
|
||||
(tBTA_JV_RFCOMM_CBACK *)btc_spp_rfcomm_inter_cb, (void *)user_data);
|
||||
}
|
||||
}
|
||||
osi_mutex_unlock(&spp_local_param.spp_slot_mutex);
|
||||
} while(0);
|
||||
} while (0);
|
||||
|
||||
if (ret != ESP_SPP_SUCCESS) {
|
||||
esp_spp_cb_param_t param;
|
||||
param.srv_stop.status = ret;
|
||||
param.srv_stop.scn = BTC_SPP_INVALID_SCN;
|
||||
btc_spp_cb_to_app(ESP_SPP_SRV_STOP_EVT, ¶m);
|
||||
}
|
||||
|
||||
if (srv_scn_arr) {
|
||||
osi_free(srv_scn_arr);
|
||||
srv_scn_arr = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void btc_spp_write(btc_spp_args_t *arg)
|
||||
@ -849,7 +910,7 @@ void btc_spp_call_handler(btc_msg_t *msg)
|
||||
btc_spp_start_srv(arg);
|
||||
break;
|
||||
case BTC_SPP_ACT_STOP_SRV:
|
||||
btc_spp_stop_srv();
|
||||
btc_spp_stop_srv(arg);
|
||||
break;
|
||||
case BTC_SPP_ACT_WRITE:
|
||||
btc_spp_write(arg);
|
||||
@ -876,6 +937,8 @@ void btc_spp_cb_handler(btc_msg_t *msg)
|
||||
param.disc_comp.status = p_data->disc_comp.status;
|
||||
param.disc_comp.scn_num = p_data->disc_comp.scn_num;
|
||||
memcpy(param.disc_comp.scn, p_data->disc_comp.scn, p_data->disc_comp.scn_num);
|
||||
memcpy(param.disc_comp.service_name, p_data->disc_comp.service_name,
|
||||
p_data->disc_comp.scn_num * sizeof(const char *));
|
||||
btc_spp_cb_to_app(ESP_SPP_DISCOVERY_COMP_EVT, ¶m);
|
||||
break;
|
||||
case BTA_JV_RFCOMM_CL_INIT_EVT:
|
||||
@ -909,6 +972,7 @@ void btc_spp_cb_handler(btc_msg_t *msg)
|
||||
param.start.status = p_data->rfc_start.status;
|
||||
param.start.handle = p_data->rfc_start.handle;
|
||||
param.start.sec_id = p_data->rfc_start.sec_id;
|
||||
param.start.scn = p_data->rfc_start.scn;
|
||||
param.start.use_co = p_data->rfc_start.use_co;
|
||||
btc_spp_cb_to_app(ESP_SPP_START_EVT, ¶m);
|
||||
break;
|
||||
@ -1130,6 +1194,7 @@ void btc_spp_cb_handler(btc_msg_t *msg)
|
||||
case BTA_JV_FREE_SCN_EVT:
|
||||
if (p_data->free_scn.server_status == BTA_JV_SERVER_RUNNING) {
|
||||
param.srv_stop.status = p_data->free_scn.status;
|
||||
param.srv_stop.scn = p_data->free_scn.scn;
|
||||
btc_spp_cb_to_app(ESP_SPP_SRV_STOP_EVT, ¶m);
|
||||
}
|
||||
break;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -414,12 +414,13 @@ void btm_ble_resolve_random_addr(BD_ADDR random_bda, tBTM_BLE_RESOLVE_CBACK *p_c
|
||||
/* start to resolve random address */
|
||||
/* check for next security record */
|
||||
for (p_node = list_begin(btm_cb.p_sec_dev_rec_list); p_node; p_node = list_next(p_node)) {
|
||||
p_dev_rec = list_node(p_node);
|
||||
p_dev_rec = list_node(p_node);
|
||||
p_mgnt_cb->p_dev_rec = p_dev_rec;
|
||||
if (btm_ble_match_random_bda(p_dev_rec)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
p_mgnt_cb->p_dev_rec = NULL;
|
||||
}
|
||||
btm_ble_resolve_address_cmpl();
|
||||
} else {
|
||||
(*p_cback)(NULL, p);
|
||||
|
@ -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
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -4589,26 +4589,6 @@ void btm_sec_disconnected (UINT16 handle, UINT8 reason)
|
||||
#endif ///BT_USE_TRACES == TRUE && SMP_INCLUDED == TRUE
|
||||
BTM_TRACE_EVENT("%s before update sec_flags=0x%x\n", __func__, p_dev_rec->sec_flags);
|
||||
|
||||
/* If we are in the process of bonding we need to tell client that auth failed */
|
||||
if ( (btm_cb.pairing_state != BTM_PAIR_STATE_IDLE)
|
||||
&& (memcmp (btm_cb.pairing_bda, p_dev_rec->bd_addr, BD_ADDR_LEN) == 0)) {
|
||||
btm_sec_change_pairing_state (BTM_PAIR_STATE_IDLE);
|
||||
p_dev_rec->sec_flags &= ~BTM_SEC_LINK_KEY_KNOWN;
|
||||
if (btm_cb.api.p_auth_complete_callback) {
|
||||
/* If the disconnection reason is REPEATED_ATTEMPTS,
|
||||
send this error message to complete callback function
|
||||
to display the error message of Repeated attempts.
|
||||
All others, send HCI_ERR_AUTH_FAILURE. */
|
||||
if (reason == HCI_ERR_REPEATED_ATTEMPTS) {
|
||||
result = HCI_ERR_REPEATED_ATTEMPTS;
|
||||
} else if (old_pairing_flags & BTM_PAIR_FLAGS_WE_STARTED_DD) {
|
||||
result = HCI_ERR_HOST_REJECT_SECURITY;
|
||||
}
|
||||
(*btm_cb.api.p_auth_complete_callback) (p_dev_rec->bd_addr, p_dev_rec->dev_class,
|
||||
p_dev_rec->sec_bd_name, result);
|
||||
}
|
||||
}
|
||||
|
||||
#if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE
|
||||
btm_ble_update_mode_operation(HCI_ROLE_UNKNOWN, p_dev_rec->bd_addr, HCI_SUCCESS);
|
||||
/* see sec_flags processing in btm_acl_removed */
|
||||
@ -4645,6 +4625,26 @@ void btm_sec_disconnected (UINT16 handle, UINT8 reason)
|
||||
}
|
||||
|
||||
BTM_TRACE_EVENT("%s after update sec_flags=0x%x\n", __func__, p_dev_rec->sec_flags);
|
||||
|
||||
/* If we are in the process of bonding we need to tell client that auth failed */
|
||||
if ( (btm_cb.pairing_state != BTM_PAIR_STATE_IDLE)
|
||||
&& (memcmp (btm_cb.pairing_bda, p_dev_rec->bd_addr, BD_ADDR_LEN) == 0)) {
|
||||
btm_sec_change_pairing_state (BTM_PAIR_STATE_IDLE);
|
||||
p_dev_rec->sec_flags &= ~BTM_SEC_LINK_KEY_KNOWN;
|
||||
if (btm_cb.api.p_auth_complete_callback) {
|
||||
/* If the disconnection reason is REPEATED_ATTEMPTS,
|
||||
send this error message to complete callback function
|
||||
to display the error message of Repeated attempts.
|
||||
All others, send HCI_ERR_AUTH_FAILURE. */
|
||||
if (reason == HCI_ERR_REPEATED_ATTEMPTS) {
|
||||
result = HCI_ERR_REPEATED_ATTEMPTS;
|
||||
} else if (old_pairing_flags & BTM_PAIR_FLAGS_WE_STARTED_DD) {
|
||||
result = HCI_ERR_HOST_REJECT_SECURITY;
|
||||
}
|
||||
(*btm_cb.api.p_auth_complete_callback) (p_dev_rec->bd_addr, p_dev_rec->dev_class,
|
||||
p_dev_rec->sec_bd_name, result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
|
@ -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"
|
||||
@ -32,6 +33,7 @@
|
||||
#include "hal/adc_hal.h"
|
||||
#include "hal/dma_types.h"
|
||||
#include "esp32c3/esp_efuse_rtc_calib.h"
|
||||
#include "esp_private/gdma.h"
|
||||
|
||||
#define ADC_CHECK_RET(fun_ret) ({ \
|
||||
if (fun_ret != ESP_OK) { \
|
||||
@ -57,37 +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.
|
||||
@ -95,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;
|
||||
@ -104,7 +104,7 @@ static uint32_t adc_get_calibration_offset(adc_ll_num_t adc_n, adc_channel_t cha
|
||||
/*---------------------------------------------------------------
|
||||
ADC Continuous Read Mode (via DMA)
|
||||
---------------------------------------------------------------*/
|
||||
static void adc_dma_intr(void* arg);
|
||||
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);
|
||||
|
||||
static int8_t adc_digi_get_io_num(uint8_t adc_unit, uint8_t adc_channel)
|
||||
{
|
||||
@ -149,11 +149,6 @@ esp_err_t adc_digi_initialize(const adc_digi_init_config_t *init_config)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ret = esp_intr_alloc(SOC_GDMA_ADC_INTR_SOURCE, 0, adc_dma_intr, (void *)s_adc_digi_ctx, &s_adc_digi_ctx->dma_intr_hdl);
|
||||
if (ret != ESP_OK) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
//ringbuffer
|
||||
s_adc_digi_ctx->ringbuf_hdl = xRingbufferCreate(init_config->max_store_buf_size, RINGBUF_TYPE_BYTEBUF);
|
||||
if (!s_adc_digi_ctx->ringbuf_hdl) {
|
||||
@ -161,22 +156,19 @@ esp_err_t adc_digi_initialize(const adc_digi_init_config_t *init_config)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
//malloc internal buffer
|
||||
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);
|
||||
//malloc internal buffer used by DMA
|
||||
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;
|
||||
s_adc_digi_ctx->hal_dma_config.dma_chan = init_config->dma_chan;
|
||||
|
||||
//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));
|
||||
@ -185,6 +177,14 @@ 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);
|
||||
if (ret != ESP_OK) {
|
||||
@ -198,8 +198,39 @@ esp_err_t adc_digi_initialize(const adc_digi_init_config_t *init_config)
|
||||
}
|
||||
}
|
||||
|
||||
//alloc rx gdma channel
|
||||
gdma_channel_alloc_config_t rx_alloc_config = {
|
||||
.direction = GDMA_CHANNEL_DIRECTION_RX,
|
||||
};
|
||||
ret = gdma_new_channel(&rx_alloc_config, &s_adc_digi_ctx->rx_dma_channel);
|
||||
if (ret != ESP_OK) {
|
||||
goto cleanup;
|
||||
}
|
||||
gdma_connect(s_adc_digi_ctx->rx_dma_channel, GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_ADC, 0));
|
||||
|
||||
gdma_strategy_config_t strategy_config = {
|
||||
.auto_update_desc = true,
|
||||
.owner_check = true
|
||||
};
|
||||
gdma_apply_strategy(s_adc_digi_ctx->rx_dma_channel, &strategy_config);
|
||||
|
||||
gdma_rx_event_callbacks_t cbs = {
|
||||
.on_recv_eof = adc_dma_in_suc_eof_callback
|
||||
};
|
||||
gdma_register_rx_event_callbacks(s_adc_digi_ctx->rx_dma_channel, &cbs, s_adc_digi_ctx);
|
||||
|
||||
int dma_chan;
|
||||
gdma_get_channel_id(s_adc_digi_ctx->rx_dma_channel, &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);
|
||||
periph_module_enable(PERIPH_GDMA_MODULE);
|
||||
|
||||
adc_hal_calibration_init(ADC_NUM_1);
|
||||
adc_hal_calibration_init(ADC_NUM_2);
|
||||
@ -212,46 +243,42 @@ cleanup:
|
||||
|
||||
}
|
||||
|
||||
static IRAM_ATTR void adc_dma_intr(void *arg)
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
//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);
|
||||
|
||||
while (s_adc_digi_ctx->hal_dma_config.cur_desc_ptr->dw0.owner == 0) {
|
||||
|
||||
dma_descriptor_t *current_desc = s_adc_digi_ctx->hal_dma_config.cur_desc_ptr;
|
||||
ret = xRingbufferSendFromISR(s_adc_digi_ctx->ringbuf_hdl, current_desc->buffer, current_desc->dw0.length, &taskAwoken);
|
||||
if (ret == pdFALSE) {
|
||||
//ringbuffer overflow
|
||||
s_adc_digi_ctx->ringbuf_overflow_flag = 1;
|
||||
}
|
||||
|
||||
s_adc_digi_ctx->hal_dma_config.desc_cnt += 1;
|
||||
//cycle the dma descriptor and buffers
|
||||
s_adc_digi_ctx->hal_dma_config.cur_desc_ptr = s_adc_digi_ctx->hal_dma_config.cur_desc_ptr->next;
|
||||
if (!s_adc_digi_ctx->hal_dma_config.cur_desc_ptr) {
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
if (!s_adc_digi_ctx->hal_dma_config.cur_desc_ptr) {
|
||||
|
||||
assert(s_adc_digi_ctx->hal_dma_config.desc_cnt == s_adc_digi_ctx->hal_dma_config.desc_max_num);
|
||||
//reset the current descriptor status
|
||||
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;
|
||||
|
||||
if (status == ADC_HAL_DMA_DESC_NULL) {
|
||||
//start next turns of dma operation
|
||||
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_rxdma_start(&s_adc_digi_ctx->hal_dma, &s_adc_digi_ctx->hal_dma_config);
|
||||
adc_hal_digi_rxdma_start(&adc_digi_ctx->hal, adc_digi_ctx->rx_dma_buf);
|
||||
}
|
||||
|
||||
if(taskAwoken == pdTRUE) {
|
||||
portYIELD_FROM_ISR();
|
||||
}
|
||||
return (taskAwoken == pdTRUE);
|
||||
}
|
||||
|
||||
esp_err_t adc_digi_start(void)
|
||||
@ -260,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) {
|
||||
@ -281,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;
|
||||
}
|
||||
@ -314,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;
|
||||
}
|
||||
@ -375,23 +405,27 @@ 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);
|
||||
|
||||
free(s_adc_digi_ctx);
|
||||
s_adc_digi_ctx = NULL;
|
||||
|
||||
periph_module_disable(PERIPH_SARADC_MODULE);
|
||||
periph_module_disable(PERIPH_GDMA_MODULE);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
@ -402,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.
|
||||
@ -429,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;
|
||||
}
|
||||
|
||||
@ -489,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;
|
||||
}
|
||||
|
||||
@ -551,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;
|
||||
|
||||
@ -575,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 */
|
||||
/*************************************/
|
||||
@ -712,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
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user