forked from espressif/esp-idf
Compare commits
158 Commits
v5.0-beta1
...
v5.1-dev
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
012fafb827 | ||
|
|
87fbc2f487 | ||
|
|
6e98440ab1 | ||
|
|
75cdc683ff | ||
|
|
6c8375e2d2 | ||
|
|
bc08de5f46 | ||
|
|
c462711c74 | ||
|
|
d8190673fe | ||
|
|
03ce915668 | ||
|
|
d10d57a597 | ||
|
|
e596c84d49 | ||
|
|
401c10ecfb | ||
|
|
879352b7f3 | ||
|
|
cb1033abf8 | ||
|
|
842efaf753 | ||
|
|
f352469cd3 | ||
|
|
76a084caa3 | ||
|
|
38264f0812 | ||
|
|
b2eb0e16d4 | ||
|
|
762da7e5ba | ||
|
|
104bd44377 | ||
|
|
307d26659e | ||
|
|
7bfb89e3b3 | ||
|
|
373524cec2 | ||
|
|
df1c54d6fc | ||
|
|
e8915e14e7 | ||
|
|
e57257a6db | ||
|
|
3689035b7c | ||
|
|
1bb1b70e0f | ||
|
|
24f9e348c9 | ||
|
|
b6d69840e8 | ||
|
|
4c446222e1 | ||
|
|
a32a89b002 | ||
|
|
3e4c0a40c2 | ||
|
|
e380704731 | ||
|
|
5fd42affdb | ||
|
|
804bdc1721 | ||
|
|
50229cfe06 | ||
|
|
de365f0e7a | ||
|
|
8de9fd8cd7 | ||
|
|
45524408df | ||
|
|
035924a8f1 | ||
|
|
f332790af5 | ||
|
|
480f80868a | ||
|
|
cf4cfc69ed | ||
|
|
a5a171926b | ||
|
|
031adc01c4 | ||
|
|
ca175857d1 | ||
|
|
8987164385 | ||
|
|
7faf1bee73 | ||
|
|
3f6a1625bb | ||
|
|
a0689f0434 | ||
|
|
8e88444f29 | ||
|
|
0da97b43d3 | ||
|
|
59ecac263e | ||
|
|
2462003fde | ||
|
|
f402778320 | ||
|
|
8c756dad23 | ||
|
|
85fc8321c8 | ||
|
|
5fb109f2e8 | ||
|
|
f315986401 | ||
|
|
c47c0097e2 | ||
|
|
9bda2381ea | ||
|
|
5f074e1336 | ||
|
|
0a1fa3e204 | ||
|
|
9a5f854760 | ||
|
|
a075aa564f | ||
|
|
57336e0a0e | ||
|
|
3c8671f592 | ||
|
|
578bfa3600 | ||
|
|
c0b86fefc6 | ||
|
|
eea8a285e3 | ||
|
|
7c1ee339bc | ||
|
|
81c87cf4ca | ||
|
|
77e98e468d | ||
|
|
036705fe8f | ||
|
|
2f7bae7a6e | ||
|
|
e25cda2c40 | ||
|
|
ab8be80c3c | ||
|
|
d7ab8fd4ba | ||
|
|
03a8235098 | ||
|
|
1fa411d515 | ||
|
|
67d0a10548 | ||
|
|
ff71e54f70 | ||
|
|
5d23a757d6 | ||
|
|
7d5eb1fc01 | ||
|
|
2d173c0777 | ||
|
|
06b31d487b | ||
|
|
30639b1093 | ||
|
|
df3e506703 | ||
|
|
956f08826f | ||
|
|
681fe85dd6 | ||
|
|
b9b047399d | ||
|
|
20e253e663 | ||
|
|
7720e348c2 | ||
|
|
9b518380b2 | ||
|
|
0f555b2a1d | ||
|
|
dba813bac4 | ||
|
|
b684730da2 | ||
|
|
17e312f87b | ||
|
|
d0a2849b02 | ||
|
|
01baaf33ed | ||
|
|
9c6e636c0a | ||
|
|
742663dd9b | ||
|
|
8132f8b5e1 | ||
|
|
b885499c74 | ||
|
|
905856a054 | ||
|
|
4d0385d9f0 | ||
|
|
592afea93e | ||
|
|
3fcfc80c17 | ||
|
|
aeb9cd267f | ||
|
|
0d4a533b74 | ||
|
|
59ef1e1928 | ||
|
|
526f8f048b | ||
|
|
0e3bd7592f | ||
|
|
4a617e459a | ||
|
|
8357fc728f | ||
|
|
c0030f6d62 | ||
|
|
7c78de7be8 | ||
|
|
6658b7eb0a | ||
|
|
e51df179ad | ||
|
|
da91fb7a81 | ||
|
|
13770a2660 | ||
|
|
af329784b1 | ||
|
|
1265a2db9d | ||
|
|
7c17a04733 | ||
|
|
198fd08fb3 | ||
|
|
e9c18ad02f | ||
|
|
028d071e84 | ||
|
|
a542e9424c | ||
|
|
f44196c46b | ||
|
|
4ab8f00b47 | ||
|
|
5e8ba9cea8 | ||
|
|
70eabb5492 | ||
|
|
7cb9304b65 | ||
|
|
ca0d8be5b8 | ||
|
|
486dbf441b | ||
|
|
32efa1e92d | ||
|
|
22f65d961f | ||
|
|
bb5a95f1aa | ||
|
|
65aea5d177 | ||
|
|
2ad49a9be5 | ||
|
|
31183270fb | ||
|
|
21a4eda4d4 | ||
|
|
d6461d91e2 | ||
|
|
bf10146a15 | ||
|
|
3254f8deae | ||
|
|
98d346a81e | ||
|
|
b0881a1e6c | ||
|
|
3a9f711f77 | ||
|
|
22d771bf51 | ||
|
|
421a408b42 | ||
|
|
7eedd710c2 | ||
|
|
4f80c0f27e | ||
|
|
5e6a16380a | ||
|
|
4f1046a292 | ||
|
|
c2a5f48498 | ||
|
|
5d27d66ddd |
@@ -89,7 +89,7 @@ variables:
|
||||
CI_PYTHON_CONSTRAINT_BRANCH: ""
|
||||
|
||||
# Update the filename for a specific ESP-IDF release. It is used only with CI_PYTHON_CONSTRAINT_BRANCH.
|
||||
CI_PYTHON_CONSTRAINT_FILE: "espidf.constraints.v5.0.txt"
|
||||
CI_PYTHON_CONSTRAINT_FILE: "espidf.constraints.v5.1.txt"
|
||||
|
||||
# Set this variable to repository name of a Python tool you wish to install and test in the context of ESP-IDF CI.
|
||||
# Keep the variable empty when not used.
|
||||
@@ -211,7 +211,7 @@ before_script:
|
||||
# This adds tools (compilers) and the version-specific Python environment to PATH
|
||||
- *setup_tools_unless_target_test
|
||||
# Install packages required by CI scripts into IDF Python environment
|
||||
- pip install -r $IDF_PATH/tools/ci/python_packages/ttfw_idf/requirements.txt
|
||||
- pip install -r $IDF_PATH/tools/requirements/requirements.ci.txt
|
||||
- source tools/ci/configure_ci_environment.sh
|
||||
# Part of tools/ci/setup_python.sh; we don't use pyenv on macOS, so can't run the rest of the script.
|
||||
- export PYTHONPATH="$IDF_PATH/tools:$IDF_PATH/tools/ci/python_packages:$PYTHONPATH"
|
||||
@@ -228,9 +228,8 @@ before_script:
|
||||
- *setup_tools_unless_target_test
|
||||
- fetch_submodules
|
||||
- *download_test_python_contraint_file
|
||||
- $IDF_PATH/tools/idf_tools.py install-python-env --features pytest
|
||||
# TODO: remove this, IDFCI-1207
|
||||
- pip install esptool -c ~/.espressif/${CI_PYTHON_CONSTRAINT_FILE}
|
||||
# only need ci and pytest related packages, ttfw requirements would be mocked if not installed
|
||||
- $IDF_PATH/tools/idf_tools.py install-python-env --features pytest,ci
|
||||
- eval "$($IDF_PATH/tools/idf_tools.py export)" # use idf venv instead
|
||||
|
||||
.before_script_build_jobs:
|
||||
@@ -244,13 +243,9 @@ before_script:
|
||||
- *setup_tools_unless_target_test
|
||||
- fetch_submodules
|
||||
- *download_test_python_contraint_file
|
||||
- $IDF_PATH/tools/idf_tools.py install-python-env --features pytest
|
||||
# TODO: remove this, IDFCI-1207
|
||||
- pip install esptool -c ~/.espressif/${CI_PYTHON_CONSTRAINT_FILE}
|
||||
# only need ci and pytest related packages, ttfw requirements would be mocked if not installed
|
||||
- $IDF_PATH/tools/idf_tools.py install-python-env --features pytest,ci
|
||||
- eval "$($IDF_PATH/tools/idf_tools.py export)" # use idf venv instead
|
||||
# not only need pytest related packages, but also needs ttfw requirements
|
||||
- internal_pip_install $IDF_BUILD_APPS_PROJ idf_build_apps
|
||||
- pip install -r tools/ci/python_packages/ttfw_idf/requirements.txt -c ~/.espressif/${CI_PYTHON_CONSTRAINT_FILE}
|
||||
- export EXTRA_CFLAGS=${PEDANTIC_CFLAGS}
|
||||
- export EXTRA_CXXFLAGS=${PEDANTIC_CXXFLAGS}
|
||||
|
||||
|
||||
@@ -300,11 +300,11 @@ build_ssc_esp32s3:
|
||||
-t $IDF_TARGET
|
||||
--config "configs/*="
|
||||
--copy-sdkconfig
|
||||
--preserve-all
|
||||
--collect-size-info $SIZE_INFO_LOCATION
|
||||
--collect-app-info list_job_${CI_NODE_INDEX:-1}.json
|
||||
--parallel-count ${CI_NODE_TOTAL:-1}
|
||||
--parallel-index ${CI_NODE_INDEX:-1}
|
||||
--preserve-all
|
||||
- run_cmd python tools/unit-test-app/tools/UnitTestParser.py tools/unit-test-app ${CI_NODE_INDEX:-1}
|
||||
|
||||
build_esp_idf_tests_cmake_esp32:
|
||||
|
||||
@@ -62,7 +62,7 @@ check_docs_lang_sync:
|
||||
dependencies: []
|
||||
script:
|
||||
- cd docs
|
||||
- pip install -U -r requirements.txt
|
||||
- pip install -U -r $IDF_PATH/tools/requirements/requirements.docs.txt
|
||||
- build-docs -t $DOCTGT -bs $DOC_BUILDERS -l $DOCLANG build
|
||||
parallel:
|
||||
matrix:
|
||||
@@ -76,7 +76,7 @@ check_docs_gh_links:
|
||||
- .doc-rules:build:docs
|
||||
script:
|
||||
- cd docs
|
||||
- pip install -U -r requirements.txt
|
||||
- pip install -U -r $IDF_PATH/tools/requirements/requirements.docs.txt
|
||||
- build-docs gh-linkcheck
|
||||
|
||||
# stage: build_doc
|
||||
@@ -161,7 +161,7 @@ build_docs_pdf:
|
||||
script:
|
||||
- add_doc_server_ssh_keys $DOCS_DEPLOY_PRIVATEKEY $DOCS_DEPLOY_SERVER $DOCS_DEPLOY_SERVER_USER
|
||||
- export GIT_VER=$(git describe --always ${PIPELINE_COMMIT_SHA} --)
|
||||
- pip install -U -r docs/requirements.txt
|
||||
- pip install -U -r $IDF_PATH/tools/requirements/requirements.docs.txt
|
||||
- deploy-docs
|
||||
|
||||
# stage: test_deploy
|
||||
@@ -227,5 +227,5 @@ check_doc_links:
|
||||
allow_failure: true
|
||||
script:
|
||||
- cd docs
|
||||
- pip install -U -r requirements.txt
|
||||
- pip install -U -r $IDF_PATH/tools/requirements/requirements.docs.txt
|
||||
- build-docs -t $DOCTGT -l $DOCLANG linkcheck
|
||||
|
||||
@@ -1,8 +1,21 @@
|
||||
.pytest_template:
|
||||
.target_test_template:
|
||||
image: $TARGET_TEST_ENV_IMAGE
|
||||
stage: target_test
|
||||
timeout: 1 hour
|
||||
extends: .before_script_pytest
|
||||
variables:
|
||||
GIT_DEPTH: 1
|
||||
SUBMODULES_TO_FETCH: "none"
|
||||
cache:
|
||||
# Usually do not need submodule-cache in target_test
|
||||
- key: pip-cache
|
||||
paths:
|
||||
- .cache/pip
|
||||
policy: pull
|
||||
|
||||
.pytest_template:
|
||||
extends:
|
||||
- .target_test_template
|
||||
- .before_script_pytest
|
||||
artifacts:
|
||||
when: always
|
||||
paths:
|
||||
@@ -11,9 +24,6 @@
|
||||
reports:
|
||||
junit: XUNIT_RESULT.xml
|
||||
expire_in: 1 week
|
||||
variables:
|
||||
GIT_DEPTH: 1
|
||||
SUBMODULES_TO_FETCH: "none"
|
||||
script:
|
||||
- retry_failed git clone $KNOWN_FAILURE_CASES_REPO known_failure_cases
|
||||
# get runner env config file
|
||||
@@ -70,6 +80,14 @@ example_test_pytest_esp32c2_generic:
|
||||
- build_pytest_examples_esp32c2
|
||||
tags: [ esp32c2, generic, xtal_40mhz ]
|
||||
|
||||
example_test_pytest_esp32c2_26mhz:
|
||||
extends:
|
||||
- .pytest_examples_dir_template
|
||||
- .rules:test:example_test-esp32c2
|
||||
needs:
|
||||
- build_pytest_examples_esp32c2
|
||||
tags: [ esp32c2, xtal_26mhz ]
|
||||
|
||||
example_test_pytest_esp32c3_generic:
|
||||
extends:
|
||||
- .pytest_examples_dir_template
|
||||
@@ -340,6 +358,14 @@ test_app_test_pytest_esp32c2_generic:
|
||||
- build_pytest_test_apps_esp32c2
|
||||
tags: [ esp32c2, generic, xtal_40mhz ]
|
||||
|
||||
test_app_test_pytest_esp32c2_26mhz:
|
||||
extends:
|
||||
- .pytest_test_apps_dir_template
|
||||
- .rules:test:custom_test-esp32c2
|
||||
needs:
|
||||
- build_pytest_test_apps_esp32c2
|
||||
tags: [ esp32c2, xtal_26mhz ]
|
||||
|
||||
test_app_test_pytest_esp32c3_generic:
|
||||
extends:
|
||||
- .pytest_test_apps_dir_template
|
||||
@@ -356,6 +382,30 @@ test_app_test_pytest_esp32s2_usb_host:
|
||||
- build_pytest_test_apps_esp32s2
|
||||
tags: [ esp32s2, usb_host ]
|
||||
|
||||
test_app_test_pytest_esp32s3_mspi_f8r8:
|
||||
extends:
|
||||
- .pytest_test_apps_dir_template
|
||||
- .rules:test:custom_test-esp32s3
|
||||
needs:
|
||||
- build_pytest_test_apps_esp32s3
|
||||
tags: [ esp32s3, MSPI_F8R8 ]
|
||||
|
||||
test_app_test_pytest_esp32s3_mspi_f4r8:
|
||||
extends:
|
||||
- .pytest_test_apps_dir_template
|
||||
- .rules:test:custom_test-esp32s3
|
||||
needs:
|
||||
- build_pytest_test_apps_esp32s3
|
||||
tags: [ esp32s3, MSPI_F4R8 ]
|
||||
|
||||
test_app_test_pytest_esp32s3_mspi_f4r4:
|
||||
extends:
|
||||
- .pytest_test_apps_dir_template
|
||||
- .rules:test:custom_test-esp32s3
|
||||
needs:
|
||||
- build_pytest_test_apps_esp32s3
|
||||
tags: [ esp32s3, MSPI_F4R4 ]
|
||||
|
||||
# for parallel jobs, CI_JOB_NAME will be "job_name index/total" (for example, "IT_001 1/2")
|
||||
# we need to convert to pattern "job_name_index.yml"
|
||||
.define_config_file_name: &define_config_file_name |
|
||||
@@ -364,9 +414,8 @@ test_app_test_pytest_esp32s2_usb_host:
|
||||
CONFIG_FILE="${CONFIG_FILE_PATH}/${JOB_FULL_NAME}.yml"
|
||||
|
||||
.target_test_job_template:
|
||||
stage: target_test
|
||||
timeout: 1 hour
|
||||
image: $TARGET_TEST_ENV_IMAGE
|
||||
extends:
|
||||
- .target_test_template
|
||||
artifacts:
|
||||
when: always
|
||||
paths:
|
||||
@@ -378,11 +427,9 @@ test_app_test_pytest_esp32s2_usb_host:
|
||||
junit: $LOG_PATH/*/XUNIT_RESULT.xml
|
||||
expire_in: 1 week
|
||||
variables:
|
||||
GIT_DEPTH: 1
|
||||
TEST_FW_PATH: "$CI_PROJECT_DIR/tools/tiny-test-fw"
|
||||
LOG_PATH: "$CI_PROJECT_DIR/TEST_LOGS"
|
||||
ENV_FILE: "$CI_PROJECT_DIR/ci-test-runner-configs/$CI_RUNNER_DESCRIPTION/EnvConfig.yml"
|
||||
SUBMODULES_TO_FETCH: "none"
|
||||
script:
|
||||
- *define_config_file_name
|
||||
# first test if config file exists, if not exist, exit 0
|
||||
@@ -405,13 +452,6 @@ test_app_test_pytest_esp32s2_usb_host:
|
||||
TEST_CASE_PATH: "$CI_PROJECT_DIR/examples"
|
||||
CONFIG_FILE_PATH: "${CI_PROJECT_DIR}/examples/test_configs"
|
||||
|
||||
.example_debug_template:
|
||||
extends:
|
||||
- .example_test_template
|
||||
- .rules:test:example_test-esp32
|
||||
variables:
|
||||
SUBMODULES_TO_FETCH: "all"
|
||||
|
||||
test_weekend_mqtt:
|
||||
extends:
|
||||
- .test_app_esp32_template
|
||||
@@ -543,12 +583,10 @@ example_test_010:
|
||||
- Example_ExtFlash
|
||||
|
||||
example_test_011:
|
||||
extends: .example_debug_template
|
||||
extends: .example_test_esp32_template
|
||||
tags:
|
||||
- ESP32
|
||||
- Example_T2_RS485
|
||||
variables:
|
||||
SETUP_TOOLS: "1"
|
||||
|
||||
example_test_013:
|
||||
extends: .example_test_esp32_template
|
||||
@@ -654,6 +692,12 @@ test_app_test_esp32c2_generic:
|
||||
- Example_GENERIC
|
||||
- xtal_40mhz
|
||||
|
||||
test_app_test_esp32c2_26mhz:
|
||||
extends: .test_app_esp32c2_template
|
||||
tags:
|
||||
- ESP32C2
|
||||
- xtal_26mhz
|
||||
|
||||
test_app_test_005:
|
||||
extends: .test_app_esp32c3_template
|
||||
tags:
|
||||
@@ -672,24 +716,6 @@ test_app_test_esp32_generic:
|
||||
- ESP32
|
||||
- Example_GENERIC
|
||||
|
||||
test_app_test_flash_psram_f4r4:
|
||||
extends: .test_app_esp32s3_template
|
||||
tags:
|
||||
- ESP32S3
|
||||
- MSPI_F4R4
|
||||
|
||||
test_app_test_flash_psram_f4r8:
|
||||
extends: .test_app_esp32s3_template
|
||||
tags:
|
||||
- ESP32S3
|
||||
- MSPI_F4R8
|
||||
|
||||
test_app_test_flash_psram_f8r8:
|
||||
extends: .test_app_esp32s3_template
|
||||
tags:
|
||||
- ESP32S3
|
||||
- MSPI_F8R8
|
||||
|
||||
.unit_test_template:
|
||||
extends: .target_test_job_template
|
||||
needs: # the assign already needs all the build jobs
|
||||
@@ -923,6 +949,13 @@ UT_C2:
|
||||
- UT_T1_1
|
||||
- xtal_40mhz
|
||||
|
||||
UT_C2_26M:
|
||||
extends: .unit_test_esp32c2_template
|
||||
tags:
|
||||
- ESP32C2_IDF
|
||||
- UT_T1_1
|
||||
- xtal_26mhz
|
||||
|
||||
UT_C3:
|
||||
extends: .unit_test_esp32c3_template
|
||||
parallel: 31
|
||||
|
||||
@@ -24,9 +24,7 @@ upload-pip-cache:
|
||||
- is_based_on_commits $REQUIRED_ANCESTOR_COMMITS
|
||||
- source tools/ci/setup_python.sh
|
||||
- rm -rf .cache/pip # clear old packages
|
||||
- $IDF_PATH/tools/idf_tools.py install-python-env --features pytest
|
||||
# TODO: remove this, IDFCI-1207
|
||||
- pip install esptool -c ~/.espressif/${CI_PYTHON_CONSTRAINT_FILE}
|
||||
- $IDF_PATH/tools/idf_tools.py install-python-env --features pytest,ci
|
||||
parallel:
|
||||
matrix:
|
||||
- GEO: [ 'shiny', 'brew' ]
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
idf_component_register(SRC_DIRS "."
|
||||
PRIV_INCLUDE_DIRS "."
|
||||
PRIV_REQUIRES cmock driver)
|
||||
target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format")
|
||||
|
||||
@@ -2,3 +2,4 @@ idf_component_register(SRC_DIRS "."
|
||||
PRIV_INCLUDE_DIRS "."
|
||||
PRIV_REQUIRES cmock test_utils app_update bootloader_support nvs_flash driver
|
||||
)
|
||||
target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format")
|
||||
|
||||
@@ -5,15 +5,41 @@
|
||||
*/
|
||||
/** Simplified memory map for the bootloader.
|
||||
* Make sure the bootloader can load into main memory without overwriting itself.
|
||||
* We put 2nd bootloader in the high address space (before ROM stack/data/bss).
|
||||
* See memory usage for ROM bootloader at the end of this file.
|
||||
*
|
||||
* ESP32-C2 ROM static data usage is as follows:
|
||||
* - 0x3fccb264 - 0x3fcdcb70: Shared buffers, used in UART/USB/SPI download mode only
|
||||
* - 0x3fcdcb70 - 0x3fcdeb70: PRO CPU stack, can be reclaimed as heap after RTOS startup
|
||||
* - 0x3fcdeb70 - 0x3fce0000: ROM .bss and .data (not easily reclaimable)
|
||||
*
|
||||
* The 2nd stage bootloader can take space up to the end of ROM shared
|
||||
* buffers area (0x3fcdcb70).
|
||||
*/
|
||||
|
||||
/* The offset between Dbus and Ibus. Used to convert between 0x403xxxxx and 0x3fcxxxxx addresses. */
|
||||
iram_dram_offset = 0x6e0000;
|
||||
|
||||
/* We consider 0x3fcdcb70 to be the last usable address for 2nd stage bootloader stack overhead, dram_seg,
|
||||
* and work out iram_seg and iram_loader_seg addresses from there, backwards.
|
||||
*/
|
||||
|
||||
/* These lengths can be adjusted, if necessary: */
|
||||
bootloader_usable_dram_end = 0x3fcdcb70;
|
||||
bootloader_stack_overhead = 0x2000; /* For safety margin between bootloader data section and startup stacks */
|
||||
bootloader_dram_seg_len = 0x5000;
|
||||
bootloader_iram_loader_seg_len = 0x7000;
|
||||
bootloader_iram_seg_len = 0x2000;
|
||||
|
||||
/* Start of the lower region is determined by region size and the end of the higher region */
|
||||
bootloader_dram_seg_end = bootloader_usable_dram_end - bootloader_stack_overhead;
|
||||
bootloader_dram_seg_start = bootloader_dram_seg_end - bootloader_dram_seg_len;
|
||||
bootloader_iram_loader_seg_start = bootloader_dram_seg_start - bootloader_iram_loader_seg_len + iram_dram_offset;
|
||||
bootloader_iram_seg_start = bootloader_iram_loader_seg_start - bootloader_iram_seg_len;
|
||||
|
||||
MEMORY
|
||||
{
|
||||
iram_seg (RWX) : org = 0x403AE000, len = 0x2000
|
||||
iram_loader_seg (RWX) : org = 0x403B0000, len = 0x6000
|
||||
dram_seg (RW) : org = 0x3FCD6000, len = 0x4000
|
||||
iram_seg (RWX) : org = bootloader_iram_seg_start, len = bootloader_iram_seg_len
|
||||
iram_loader_seg (RWX) : org = bootloader_iram_loader_seg_start, len = bootloader_iram_loader_seg_len
|
||||
dram_seg (RW) : org = bootloader_dram_seg_start, len = bootloader_dram_seg_len
|
||||
}
|
||||
|
||||
/* Default entry point: */
|
||||
@@ -183,17 +209,34 @@ SECTIONS
|
||||
/**
|
||||
* Appendix: Memory Usage of ROM bootloader
|
||||
*
|
||||
* +--------+--------------+------+ 0x3FCC_B0B0
|
||||
* | ^ |
|
||||
* | | |
|
||||
* | | data/bss |
|
||||
* | | |
|
||||
* | v |
|
||||
* +------------------------------+ 0x3FCD_C9C0
|
||||
* | ^ |
|
||||
* | | |
|
||||
* | | stack |
|
||||
* | | |
|
||||
* | v |
|
||||
* +------------------------------+ 0x3FCD_E9C0
|
||||
* 0x3fccb264 ------------------> _dram0_0_start
|
||||
* | |
|
||||
* | |
|
||||
* | | 1. Large buffers that are only used in certain boot modes, see shared_buffers.h
|
||||
* | |
|
||||
* | |
|
||||
* 0x3fcdcb70 ------------------> __stack_sentry
|
||||
* | |
|
||||
* | | 2. Startup pro cpu stack (freed when IDF app is running)
|
||||
* | |
|
||||
* 0x3fcdeb70 ------------------> __stack (pro cpu)
|
||||
* | |
|
||||
* | |
|
||||
* | | 3. Shared memory only used in startup code or nonos/early boot*
|
||||
* | | (can be freed when IDF runs)
|
||||
* | |
|
||||
* | |
|
||||
* 0x3fcdf4bc ------------------> _dram0_rtos_reserved_start
|
||||
* | |
|
||||
* | |
|
||||
* | | 4. Shared memory used in startup code and when IDF runs
|
||||
* | |
|
||||
* | |
|
||||
* 0x3fcdfa70 ------------------> _dram0_rtos_reserved_end
|
||||
* | |
|
||||
* 0x3fcdfa74 ------------------> _data_start_interface
|
||||
* | |
|
||||
* | | 5. End of DRAM is the 'interface' data with constant addresses (ECO compatible)
|
||||
* | |
|
||||
* 0x3fce0000 ------------------> _data_end_interface
|
||||
*/
|
||||
|
||||
@@ -5,15 +5,41 @@
|
||||
*/
|
||||
/** Simplified memory map for the bootloader.
|
||||
* Make sure the bootloader can load into main memory without overwriting itself.
|
||||
* We put 2nd bootloader in the high address space (before ROM stack/data/bss).
|
||||
* See memory usage for ROM bootloader at the end of this file.
|
||||
*
|
||||
* ESP32-C3 ROM static data usage is as follows:
|
||||
* - 0x3fccae00 - 0x3fcdc710: Shared buffers, used in UART/USB/SPI download mode only
|
||||
* - 0x3fcdc710 - 0x3fcde710: PRO CPU stack, can be reclaimed as heap after RTOS startup
|
||||
* - 0x3fcde710 - 0x3fce0000: ROM .bss and .data (not easily reclaimable)
|
||||
*
|
||||
* The 2nd stage bootloader can take space up to the end of ROM shared
|
||||
* buffers area (0x3fcdc710).
|
||||
*/
|
||||
|
||||
/* The offset between Dbus and Ibus. Used to convert between 0x403xxxxx and 0x3fcxxxxx addresses. */
|
||||
iram_dram_offset = 0x700000;
|
||||
|
||||
/* We consider 0x3fcdc710 to be the last usable address for 2nd stage bootloader stack overhead, dram_seg,
|
||||
* and work out iram_seg and iram_loader_seg addresses from there, backwards.
|
||||
*/
|
||||
|
||||
/* These lengths can be adjusted, if necessary: */
|
||||
bootloader_usable_dram_end = 0x3fcdc710;
|
||||
bootloader_stack_overhead = 0x2000; /* For safety margin between bootloader data section and startup stacks */
|
||||
bootloader_dram_seg_len = 0x5000;
|
||||
bootloader_iram_loader_seg_len = 0x7000;
|
||||
bootloader_iram_seg_len = 0x2000;
|
||||
|
||||
/* Start of the lower region is determined by region size and the end of the higher region */
|
||||
bootloader_dram_seg_end = bootloader_usable_dram_end - bootloader_stack_overhead;
|
||||
bootloader_dram_seg_start = bootloader_dram_seg_end - bootloader_dram_seg_len;
|
||||
bootloader_iram_loader_seg_start = bootloader_dram_seg_start - bootloader_iram_loader_seg_len + iram_dram_offset;
|
||||
bootloader_iram_seg_start = bootloader_iram_loader_seg_start - bootloader_iram_seg_len;
|
||||
|
||||
MEMORY
|
||||
{
|
||||
iram_seg (RWX) : org = 0x403CE000, len = 0x1600
|
||||
iram_loader_seg (RWX) : org = 0x403CF600, len = 0x6A00
|
||||
dram_seg (RW) : org = 0x3FCD6000, len = 0x4000
|
||||
iram_seg (RWX) : org = bootloader_iram_seg_start, len = bootloader_iram_seg_len
|
||||
iram_loader_seg (RWX) : org = bootloader_iram_loader_seg_start, len = bootloader_iram_loader_seg_len
|
||||
dram_seg (RW) : org = bootloader_dram_seg_start, len = bootloader_dram_seg_len
|
||||
}
|
||||
|
||||
/* Default entry point: */
|
||||
@@ -184,17 +210,34 @@ SECTIONS
|
||||
/**
|
||||
* Appendix: Memory Usage of ROM bootloader
|
||||
*
|
||||
* +--------+--------------+------+ 0x3FCC_AE00
|
||||
* | ^ |
|
||||
* | | |
|
||||
* | | data/bss |
|
||||
* | | |
|
||||
* | v |
|
||||
* +------------------------------+ 0x3FCD_C710
|
||||
* | ^ |
|
||||
* | | |
|
||||
* | | stack |
|
||||
* | | |
|
||||
* | v |
|
||||
* +------------------------------+ 0x3FCD_E710
|
||||
* 0x3fccae00 ------------------> _dram0_0_start
|
||||
* | |
|
||||
* | |
|
||||
* | | 1. Large buffers that are only used in certain boot modes, see shared_buffers.h
|
||||
* | |
|
||||
* | |
|
||||
* 0x3fcdc710 ------------------> __stack_sentry
|
||||
* | |
|
||||
* | | 2. Startup pro cpu stack (freed when IDF app is running)
|
||||
* | |
|
||||
* 0x3fcde710 ------------------> __stack (pro cpu)
|
||||
* | |
|
||||
* | |
|
||||
* | | 3. Shared memory only used in startup code or nonos/early boot*
|
||||
* | | (can be freed when IDF runs)
|
||||
* | |
|
||||
* | |
|
||||
* 0x3fcdf060 ------------------> _dram0_rtos_reserved_start
|
||||
* | |
|
||||
* | |
|
||||
* | | 4. Shared memory used in startup code and when IDF runs
|
||||
* | |
|
||||
* | |
|
||||
* 0x3fcdf664 ------------------> _dram0_rtos_reserved_end
|
||||
* | |
|
||||
* 0x3fcdf830 ------------------> _data_start_interface
|
||||
* | |
|
||||
* | | 5. End of DRAM is the 'interface' data with constant addresses (ECO compatible)
|
||||
* | |
|
||||
* 0x3fce0000 ------------------> _data_end_interface
|
||||
*/
|
||||
|
||||
@@ -5,15 +5,41 @@
|
||||
*/
|
||||
/** Simplified memory map for the bootloader.
|
||||
* Make sure the bootloader can load into main memory without overwriting itself.
|
||||
* We put 2nd bootloader in the high address space (before ROM stack/data/bss).
|
||||
* See memory usage for ROM bootloader at the end of this file.
|
||||
*
|
||||
* ESP32-H2 ROM static data usage is as follows:
|
||||
* - 0x3fccb900 - 0x3fcdd210: Shared buffers, used in UART/USB/SPI download mode only
|
||||
* - 0x3fcdd210 - 0x3fcdf210: PRO CPU stack, can be reclaimed as heap after RTOS startup
|
||||
* - 0x3fcdf210 - 0x3fce0000: ROM .bss and .data (not easily reclaimable)
|
||||
*
|
||||
* The 2nd stage bootloader can take space up to the end of ROM shared
|
||||
* buffers area (0x3fce9704). For alignment purpose we shall use value (0x3fce9700).
|
||||
*/
|
||||
|
||||
/* The offset between Dbus and Ibus. Used to convert between 0x403xxxxx and 0x3fcxxxxx addresses. */
|
||||
iram_dram_offset = 0x700000;
|
||||
|
||||
/* We consider 0x3fce9700 to be the last usable address for 2nd stage bootloader stack overhead, dram_seg,
|
||||
* and work out iram_seg and iram_loader_seg addresses from there, backwards.
|
||||
*/
|
||||
|
||||
/* These lengths can be adjusted, if necessary: */
|
||||
bootloader_usable_dram_end = 0x3fcdd120;
|
||||
bootloader_stack_overhead = 0x2000; /* For safety margin between bootloader data section and startup stacks */
|
||||
bootloader_dram_seg_len = 0x5000;
|
||||
bootloader_iram_loader_seg_len = 0x7000;
|
||||
bootloader_iram_seg_len = 0x2000;
|
||||
|
||||
/* Start of the lower region is determined by region size and the end of the higher region */
|
||||
bootloader_dram_seg_end = bootloader_usable_dram_end - bootloader_stack_overhead;
|
||||
bootloader_dram_seg_start = bootloader_dram_seg_end - bootloader_dram_seg_len;
|
||||
bootloader_iram_loader_seg_start = bootloader_dram_seg_start - bootloader_iram_loader_seg_len + iram_dram_offset;
|
||||
bootloader_iram_seg_start = bootloader_iram_loader_seg_start - bootloader_iram_seg_len;
|
||||
|
||||
MEMORY
|
||||
{
|
||||
iram_seg (RWX) : org = 0x403CE000, len = 0x2000
|
||||
iram_loader_seg (RWX) : org = 0x403D0000, len = 0x6000
|
||||
dram_seg (RW) : org = 0x3FCD6000, len = 0x4000
|
||||
iram_seg (RWX) : org = bootloader_iram_seg_start, len = bootloader_iram_seg_len
|
||||
iram_loader_seg (RWX) : org = bootloader_iram_loader_seg_start, len = bootloader_iram_loader_seg_len
|
||||
dram_seg (RW) : org = bootloader_dram_seg_start, len = bootloader_dram_seg_len
|
||||
}
|
||||
|
||||
/* Default entry point: */
|
||||
@@ -181,17 +207,34 @@ SECTIONS
|
||||
/**
|
||||
* Appendix: Memory Usage of ROM bootloader
|
||||
*
|
||||
* +--------+--------------+------+ 0x3FCC_B900
|
||||
* | ^ |
|
||||
* | | |
|
||||
* | | data/bss |
|
||||
* | | |
|
||||
* | v |
|
||||
* +------------------------------+ 0x3FCD_D210
|
||||
* | ^ |
|
||||
* | | |
|
||||
* | | stack |
|
||||
* | | |
|
||||
* | v |
|
||||
* +------------------------------+ 0x3FCD_F210
|
||||
* 0x3fccb81c ------------------> _dram0_0_start
|
||||
* | |
|
||||
* | |
|
||||
* | | 1. Large buffers that are only used in certain boot modes, see shared_buffers.h
|
||||
* | |
|
||||
* | |
|
||||
* 0x3fcdd120 ------------------> __stack_sentry
|
||||
* | |
|
||||
* | | 2. Startup pro cpu stack (freed when IDF app is running)
|
||||
* | |
|
||||
* 0x3fcdf120 ------------------> __stack (pro cpu)
|
||||
* | |
|
||||
* | |
|
||||
* | | 3. Shared memory only used in startup code or nonos/early boot*
|
||||
* | | (can be freed when IDF runs)
|
||||
* | |
|
||||
* | |
|
||||
* 0x3fcdfa6c ------------------> _dram0_rtos_reserved_start
|
||||
* | |
|
||||
* | |
|
||||
* | | 4. Shared memory used in startup code and when IDF runs
|
||||
* | |
|
||||
* | |
|
||||
* 0x3fcdfe40 ------------------> _dram0_rtos_reserved_end
|
||||
* | |
|
||||
* 0x3fcdfe4c ------------------> _data_start_interface
|
||||
* | |
|
||||
* | | 5. End of DRAM is the 'interface' data with constant addresses (ECO compatible)
|
||||
* | |
|
||||
* 0x3fce0000 ------------------> _data_end_interface
|
||||
*/
|
||||
|
||||
@@ -233,3 +233,42 @@ SECTIONS
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Appendix: Memory Usage of ROM bootloader
|
||||
*
|
||||
* 0x3fcd7e00 ------------------> _dram0_0_start
|
||||
* | |
|
||||
* | |
|
||||
* | | 1. Large buffers that are only used in certain boot modes, see shared_buffers.h
|
||||
* | |
|
||||
* | |
|
||||
* 0x3fce9710 ------------------> __stack_sentry
|
||||
* | |
|
||||
* | | 2. Startup pro cpu stack (freed when IDF app is running)
|
||||
* | |
|
||||
* 0x3fceb710 ------------------> __stack (pro cpu)
|
||||
* | |
|
||||
* | | Startup app cpu stack
|
||||
* | |
|
||||
* 0x3fced710 ------------------> __stack_app (app cpu)
|
||||
* | |
|
||||
* | |
|
||||
* | | 3. Shared memory only used in startup code or nonos/early boot*
|
||||
* | | (can be freed when IDF runs)
|
||||
* | |
|
||||
* | |
|
||||
* 0x3fceee34 ------------------> _dram0_rtos_reserved_start
|
||||
* | |
|
||||
* | |
|
||||
* | | 4. Shared memory used in startup code and when IDF runs
|
||||
* | |
|
||||
* | |
|
||||
* 0x3fcef770 ------------------> _dram0_rtos_reserved_end
|
||||
* | |
|
||||
* 0x3fcef81c ------------------> _data_start_interface
|
||||
* | |
|
||||
* | | 5. End of DRAM is the 'interface' data with constant addresses (ECO compatible)
|
||||
* | |
|
||||
* 0x3fcf0000 ------------------> _data_end_interface
|
||||
*/
|
||||
|
||||
@@ -148,3 +148,5 @@ endif()
|
||||
if(BOOTLOADER_BUILD)
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u abort")
|
||||
endif()
|
||||
|
||||
target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format")
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
idf_component_register(SRC_DIRS "."
|
||||
PRIV_INCLUDE_DIRS "."
|
||||
PRIV_REQUIRES cmock bootloader_support app_update)
|
||||
target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format")
|
||||
|
||||
@@ -53,6 +53,8 @@ if(CONFIG_BT_ENABLED)
|
||||
"common/osi/buffer.c"
|
||||
"common/osi/config.c"
|
||||
"common/osi/fixed_queue.c"
|
||||
"common/osi/pkt_queue.c"
|
||||
"common/osi/fixed_pkt_queue.c"
|
||||
"common/osi/future.c"
|
||||
"common/osi/hash_functions.c"
|
||||
"common/osi/hash_map.c"
|
||||
@@ -715,6 +717,8 @@ if(CONFIG_BT_ENABLED)
|
||||
"host/bluedroid/btc/profile/std/gatt/btc_gatt_util.c"
|
||||
"host/bluedroid/btc/profile/std/gatt/btc_gatts.c"
|
||||
PROPERTIES COMPILE_FLAGS -Wno-address-of-packed-member)
|
||||
|
||||
target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format")
|
||||
endif()
|
||||
|
||||
if(CONFIG_BT_NIMBLE_MESH)
|
||||
|
||||
@@ -60,6 +60,10 @@
|
||||
#endif /* #if CLASSIC_BT_INCLUDED */
|
||||
#endif
|
||||
|
||||
#if (BLE_INCLUDED == TRUE)
|
||||
#include "btc_gap_ble.h"
|
||||
#endif
|
||||
|
||||
#if CONFIG_BLE_MESH
|
||||
#include "btc_ble_mesh_ble.h"
|
||||
#include "btc_ble_mesh_prov.h"
|
||||
@@ -75,6 +79,9 @@
|
||||
#define BTC_TASK_STACK_SIZE (BT_BTC_TASK_STACK_SIZE + BT_TASK_EXTRA_STACK_SIZE) //by menuconfig
|
||||
#define BTC_TASK_NAME "BTC_TASK"
|
||||
#define BTC_TASK_PRIO (BT_TASK_MAX_PRIORITIES - 6)
|
||||
#define BTC_TASK_WORKQUEUE_NUM (2)
|
||||
#define BTC_TASK_WORKQUEUE0_LEN (0)
|
||||
#define BTC_TASK_WORKQUEUE1_LEN (5)
|
||||
|
||||
osi_thread_t *btc_thread;
|
||||
|
||||
@@ -414,7 +421,9 @@ error_exit:;
|
||||
|
||||
bt_status_t btc_init(void)
|
||||
{
|
||||
btc_thread = osi_thread_create(BTC_TASK_NAME, BTC_TASK_STACK_SIZE, BTC_TASK_PRIO, BTC_TASK_PINNED_TO_CORE, 2);
|
||||
const size_t workqueue_len[] = {BTC_TASK_WORKQUEUE0_LEN, BTC_TASK_WORKQUEUE1_LEN};
|
||||
btc_thread = osi_thread_create(BTC_TASK_NAME, BTC_TASK_STACK_SIZE, BTC_TASK_PRIO, BTC_TASK_PINNED_TO_CORE,
|
||||
BTC_TASK_WORKQUEUE_NUM, workqueue_len);
|
||||
if (btc_thread == NULL) {
|
||||
return BT_STATUS_NOMEM;
|
||||
}
|
||||
@@ -427,6 +436,7 @@ bt_status_t btc_init(void)
|
||||
|
||||
#if (BLE_INCLUDED == TRUE)
|
||||
btc_gap_callback_init();
|
||||
btc_gap_ble_init();
|
||||
#endif ///BLE_INCLUDED == TRUE
|
||||
|
||||
#if SCAN_QUEUE_CONGEST_CHECK
|
||||
@@ -444,7 +454,9 @@ void btc_deinit(void)
|
||||
|
||||
osi_thread_free(btc_thread);
|
||||
btc_thread = NULL;
|
||||
|
||||
#if (BLE_INCLUDED == TRUE)
|
||||
btc_gap_ble_deinit();
|
||||
#endif ///BLE_INCLUDED == TRUE
|
||||
#if SCAN_QUEUE_CONGEST_CHECK
|
||||
btc_adv_list_deinit();
|
||||
#endif
|
||||
@@ -463,3 +475,8 @@ int get_btc_work_queue_size(void)
|
||||
{
|
||||
return osi_thread_queue_wait_size(btc_thread, 0);
|
||||
}
|
||||
|
||||
osi_thread_t *btc_get_current_thread(void)
|
||||
{
|
||||
return btc_thread;
|
||||
}
|
||||
|
||||
@@ -124,6 +124,13 @@ void btc_deinit(void);
|
||||
bool btc_check_queue_is_congest(void);
|
||||
int get_btc_work_queue_size(void);
|
||||
|
||||
/**
|
||||
* get the BTC thread handle
|
||||
* @return NULL: fail
|
||||
* others: pointer of osi_thread structure of BTC
|
||||
*/
|
||||
osi_thread_t *btc_get_current_thread(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -85,4 +85,11 @@
|
||||
#define UC_BT_BLUFI_ENABLE FALSE
|
||||
#endif
|
||||
|
||||
//MEMORY DEBUG
|
||||
#ifdef CONFIG_BT_BLUEDROID_MEM_DEBUG
|
||||
#define UC_BT_BLUEDROID_MEM_DEBUG TRUE
|
||||
#else
|
||||
#define UC_BT_BLUEDROID_MEM_DEBUG FALSE
|
||||
#endif
|
||||
|
||||
#endif /* __BT_USER_CONFIG_H__ */
|
||||
|
||||
161
components/bt/common/osi/fixed_pkt_queue.c
Normal file
161
components/bt/common/osi/fixed_pkt_queue.c
Normal file
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "osi/allocator.h"
|
||||
#include "osi/pkt_queue.h"
|
||||
#include "osi/fixed_pkt_queue.h"
|
||||
#include "osi/osi.h"
|
||||
#include "osi/semaphore.h"
|
||||
|
||||
typedef struct fixed_pkt_queue_t {
|
||||
struct pkt_queue *pkt_list;
|
||||
osi_sem_t enqueue_sem;
|
||||
osi_sem_t dequeue_sem;
|
||||
size_t capacity;
|
||||
fixed_pkt_queue_cb dequeue_ready;
|
||||
} fixed_pkt_queue_t;
|
||||
|
||||
fixed_pkt_queue_t *fixed_pkt_queue_new(size_t capacity)
|
||||
{
|
||||
fixed_pkt_queue_t *ret = osi_calloc(sizeof(fixed_pkt_queue_t));
|
||||
if (!ret) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
ret->capacity = capacity;
|
||||
ret->pkt_list = pkt_queue_create();
|
||||
if (!ret->pkt_list) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
osi_sem_new(&ret->enqueue_sem, capacity, capacity);
|
||||
if (!ret->enqueue_sem) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
osi_sem_new(&ret->dequeue_sem, capacity, 0);
|
||||
if (!ret->dequeue_sem) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
error:
|
||||
fixed_pkt_queue_free(ret, NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void fixed_pkt_queue_free(fixed_pkt_queue_t *queue, fixed_pkt_queue_free_cb free_cb)
|
||||
{
|
||||
if (queue == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
fixed_pkt_queue_unregister_dequeue(queue);
|
||||
|
||||
pkt_queue_destroy(queue->pkt_list, (pkt_queue_free_cb)free_cb);
|
||||
queue->pkt_list = NULL;
|
||||
|
||||
if (queue->enqueue_sem) {
|
||||
osi_sem_free(&queue->enqueue_sem);
|
||||
}
|
||||
if (queue->dequeue_sem) {
|
||||
osi_sem_free(&queue->dequeue_sem);
|
||||
}
|
||||
osi_free(queue);
|
||||
}
|
||||
|
||||
bool fixed_pkt_queue_is_empty(fixed_pkt_queue_t *queue)
|
||||
{
|
||||
if (queue == NULL) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return pkt_queue_is_empty(queue->pkt_list);
|
||||
}
|
||||
|
||||
size_t fixed_pkt_queue_length(fixed_pkt_queue_t *queue)
|
||||
{
|
||||
if (queue == NULL) {
|
||||
return 0;
|
||||
}
|
||||
return pkt_queue_length(queue->pkt_list);
|
||||
}
|
||||
|
||||
size_t fixed_pkt_queue_capacity(fixed_pkt_queue_t *queue)
|
||||
{
|
||||
assert(queue != NULL);
|
||||
|
||||
return queue->capacity;
|
||||
}
|
||||
|
||||
bool fixed_pkt_queue_enqueue(fixed_pkt_queue_t *queue, pkt_linked_item_t *linked_pkt, uint32_t timeout)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
assert(queue != NULL);
|
||||
assert(linked_pkt != NULL);
|
||||
|
||||
if (osi_sem_take(&queue->enqueue_sem, timeout) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = pkt_queue_enqueue(queue->pkt_list, linked_pkt);
|
||||
|
||||
assert(ret == true);
|
||||
osi_sem_give(&queue->dequeue_sem);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
pkt_linked_item_t *fixed_pkt_queue_dequeue(fixed_pkt_queue_t *queue, uint32_t timeout)
|
||||
{
|
||||
pkt_linked_item_t *ret = NULL;
|
||||
|
||||
assert(queue != NULL);
|
||||
|
||||
if (osi_sem_take(&queue->dequeue_sem, timeout) != 0) {
|
||||
return NULL;
|
||||
}
|
||||
ret = pkt_queue_dequeue(queue->pkt_list);
|
||||
|
||||
osi_sem_give(&queue->enqueue_sem);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
pkt_linked_item_t *fixed_pkt_queue_try_peek_first(fixed_pkt_queue_t *queue)
|
||||
{
|
||||
if (queue == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return pkt_queue_try_peek_first(queue->pkt_list);
|
||||
}
|
||||
|
||||
void fixed_pkt_queue_register_dequeue(fixed_pkt_queue_t *queue, fixed_pkt_queue_cb ready_cb)
|
||||
{
|
||||
assert(queue != NULL);
|
||||
assert(ready_cb != NULL);
|
||||
|
||||
queue->dequeue_ready = ready_cb;
|
||||
}
|
||||
|
||||
void fixed_pkt_queue_unregister_dequeue(fixed_pkt_queue_t *queue)
|
||||
{
|
||||
assert(queue != NULL);
|
||||
|
||||
queue->dequeue_ready = NULL;
|
||||
}
|
||||
|
||||
void fixed_pkt_queue_process(fixed_pkt_queue_t *queue)
|
||||
{
|
||||
assert(queue != NULL);
|
||||
|
||||
if (queue->dequeue_ready) {
|
||||
queue->dequeue_ready(queue);
|
||||
}
|
||||
}
|
||||
79
components/bt/common/osi/include/osi/fixed_pkt_queue.h
Normal file
79
components/bt/common/osi/include/osi/fixed_pkt_queue.h
Normal file
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef _FIXED_PKT_QUEUE_H_
|
||||
#define _FIXED_PKT_QUEUE_H_
|
||||
|
||||
|
||||
#include "osi/pkt_queue.h"
|
||||
#include "osi/semaphore.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef FIXED_PKT_QUEUE_SIZE_MAX
|
||||
#define FIXED_PKT_QUEUE_SIZE_MAX 254
|
||||
#endif
|
||||
|
||||
#define FIXED_PKT_QUEUE_MAX_TIMEOUT OSI_SEM_MAX_TIMEOUT
|
||||
|
||||
struct fixed_pkt_queue_t;
|
||||
|
||||
typedef struct fixed_pkt_queue_t fixed_pkt_queue_t;
|
||||
|
||||
typedef void (*fixed_pkt_queue_free_cb)(pkt_linked_item_t *data);
|
||||
typedef void (*fixed_pkt_queue_cb)(fixed_pkt_queue_t *queue);
|
||||
|
||||
// Creates a new fixed queue with the given |capacity|. If more elements than
|
||||
// |capacity| are added to the queue, the caller is blocked until space is
|
||||
// made available in the queue. Returns NULL on failure. The caller must free
|
||||
// the returned queue with |fixed_pkt_queue_free|.
|
||||
fixed_pkt_queue_t *fixed_pkt_queue_new(size_t capacity);
|
||||
|
||||
// Freeing a queue that is currently in use (i.e. has waiters
|
||||
// blocked on it) results in undefined behaviour.
|
||||
void fixed_pkt_queue_free(fixed_pkt_queue_t *queue, fixed_pkt_queue_free_cb free_cb);
|
||||
|
||||
// Returns a value indicating whether the given |queue| is empty. If |queue|
|
||||
// is NULL, the return value is true.
|
||||
bool fixed_pkt_queue_is_empty(fixed_pkt_queue_t *queue);
|
||||
|
||||
// Returns the length of the |queue|. If |queue| is NULL, the return value
|
||||
// is 0.
|
||||
size_t fixed_pkt_queue_length(fixed_pkt_queue_t *queue);
|
||||
|
||||
// Returns the maximum number of elements this queue may hold. |queue| may
|
||||
// not be NULL.
|
||||
size_t fixed_pkt_queue_capacity(fixed_pkt_queue_t *queue);
|
||||
|
||||
// Enqueues the given |data| into the |queue|. The caller will be blocked or immediately return or wait for timeout according to the parameter timeout.
|
||||
// If enqueue failed, it will return false, otherwise return true
|
||||
bool fixed_pkt_queue_enqueue(fixed_pkt_queue_t *queue, pkt_linked_item_t *linked_pkt, uint32_t timeout);
|
||||
|
||||
// Dequeues the next element from |queue|. If the queue is currently empty,
|
||||
// this function will block the caller until an item is enqueued or immediately return or wait for timeout according to the parameter timeout.
|
||||
// If dequeue failed, it will return NULL, otherwise return a point.
|
||||
pkt_linked_item_t *fixed_pkt_queue_dequeue(fixed_pkt_queue_t *queue, uint32_t timeout);
|
||||
|
||||
// Returns the first element from |queue|, if present, without dequeuing it.
|
||||
// This function will never block the caller. Returns NULL if there are no
|
||||
// elements in the queue or |queue| is NULL.
|
||||
pkt_linked_item_t *fixed_pkt_queue_try_peek_first(fixed_pkt_queue_t *queue);
|
||||
|
||||
// Registers |queue| with |reactor| for dequeue operations. When there is an element
|
||||
// in the queue, ready_cb will be called. The |context| parameter is passed, untouched,
|
||||
// to the callback routine. Neither |queue|, nor |reactor|, nor |read_cb| may be NULL.
|
||||
// |context| may be NULL.
|
||||
void fixed_pkt_queue_register_dequeue(fixed_pkt_queue_t *queue, fixed_pkt_queue_cb ready_cb);
|
||||
|
||||
// Unregisters the dequeue ready callback for |queue| from whichever reactor
|
||||
// it is registered with, if any. This function is idempotent.
|
||||
void fixed_pkt_queue_unregister_dequeue(fixed_pkt_queue_t *queue);
|
||||
|
||||
void fixed_pkt_queue_process(fixed_pkt_queue_t *queue);
|
||||
|
||||
#endif
|
||||
88
components/bt/common/osi/include/osi/pkt_queue.h
Normal file
88
components/bt/common/osi/include/osi/pkt_queue.h
Normal file
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef _PKT_LIST_H_
|
||||
#define _PKT_LIST_H_
|
||||
|
||||
#include "sys/queue.h"
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct pkt_queue;
|
||||
|
||||
typedef struct pkt_linked_item {
|
||||
STAILQ_ENTRY(pkt_linked_item) next;
|
||||
uint8_t data[];
|
||||
} pkt_linked_item_t;
|
||||
|
||||
#define BT_PKT_LINKED_HDR_SIZE (sizeof (pkt_linked_item_t))
|
||||
|
||||
typedef void (*pkt_queue_free_cb)(pkt_linked_item_t *item);
|
||||
|
||||
/*
|
||||
* brief: create a pkt_queue instance. pkt_queue is a wrapper class of a FIFO implemented by single linked list.
|
||||
* The enqueue and dequeue operations of the FIFO are protected against race conditions of multiple tasks
|
||||
* return: NULL if not enough memory, otherwise a valid pointer
|
||||
*/
|
||||
struct pkt_queue *pkt_queue_create(void);
|
||||
|
||||
/*
|
||||
* brief: enqueue one item to the FIFO
|
||||
* param queue: pkt_queue instance created using pkt_queue_create
|
||||
* param item: the item to be enqueued to the FIFO
|
||||
* return: true if enqueued successfully, false when the arguments passed in are invalid
|
||||
*/
|
||||
bool pkt_queue_enqueue(struct pkt_queue *queue, pkt_linked_item_t *item);
|
||||
|
||||
/*
|
||||
* brief: dequeue one item for the FIFO
|
||||
* param queue: pkt_queue instance created using pkt_queue_create
|
||||
* return: pointer of type pkt_linked_item_t dequeued, NULL if the queue is empty or upon exception
|
||||
*/
|
||||
pkt_linked_item_t *pkt_queue_dequeue(struct pkt_queue *queue);
|
||||
|
||||
/*
|
||||
* brief: get the pointer of the first item from the FIFO but not get it dequeued
|
||||
* param queue: pkt_queue instance created using pkt_queue_create
|
||||
* return: pointer of the first item in the FIFO, NULL if the FIFO is empty
|
||||
*/
|
||||
pkt_linked_item_t *pkt_queue_try_peek_first(struct pkt_queue *queue);
|
||||
|
||||
/*
|
||||
* brief: retrieve the number of items existing in the FIFO
|
||||
* param queue: pkt_queue instance created using pkt_queue_create
|
||||
* return: total number of items in the FIFO
|
||||
*/
|
||||
size_t pkt_queue_length(const struct pkt_queue *queue);
|
||||
|
||||
/*
|
||||
* brief: retrieve the status whether the FIFO is empty
|
||||
* param queue: pkt_queue instance created using pkt_queue_create
|
||||
* return: false if the FIFO is not empty, otherwise true
|
||||
*/
|
||||
bool pkt_queue_is_empty(const struct pkt_queue *queue);
|
||||
|
||||
/*
|
||||
* brief: delete the item in the FIFO one by one
|
||||
* param free_cb: destructor function for each item in the FIFO, if set to NULL, will use osi_free_func by default
|
||||
*/
|
||||
void pkt_queue_flush(struct pkt_queue *queue, pkt_queue_free_cb free_cb);
|
||||
|
||||
/*
|
||||
* brief: delete the items in the FIFO and then destroy the pkt_queue instance.
|
||||
* param free_cb: destructor function for each item in the FIFO, if set to NULL, will use osi_free_func by default
|
||||
*/
|
||||
void pkt_queue_destroy(struct pkt_queue *queue, pkt_queue_free_cb free_cb);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -20,6 +20,7 @@
|
||||
#define OSI_THREAD_MAX_TIMEOUT OSI_SEM_MAX_TIMEOUT
|
||||
|
||||
struct osi_thread;
|
||||
struct osi_event;
|
||||
|
||||
typedef struct osi_thread osi_thread_t;
|
||||
|
||||
@@ -40,7 +41,7 @@ typedef enum {
|
||||
* param work_queue_num: speicify queue number, the queue[0] has highest priority, and the priority is decrease by index
|
||||
* return : if create successfully, return thread handler; otherwise return NULL.
|
||||
*/
|
||||
osi_thread_t *osi_thread_create(const char *name, size_t stack_size, int priority, osi_thread_core_t core, uint8_t work_queue_num);
|
||||
osi_thread_t *osi_thread_create(const char *name, size_t stack_size, int priority, osi_thread_core_t core, uint8_t work_queue_num, const size_t work_queue_len[]);
|
||||
|
||||
/*
|
||||
* brief: Destroy a thread or task
|
||||
@@ -80,4 +81,42 @@ const char *osi_thread_name(osi_thread_t *thread);
|
||||
*/
|
||||
int osi_thread_queue_wait_size(osi_thread_t *thread, int wq_idx);
|
||||
|
||||
/*
|
||||
* brief: Create an osi_event struct and register the handler function and its argument
|
||||
* An osi_event is a kind of work that can be posted to the workqueue of osi_thread to process,
|
||||
* but the work can have at most one instance the thread workqueue before it is processed. This
|
||||
* allows the "single post, multiple data processing" jobs.
|
||||
* param func: the handler to process the job
|
||||
* param context: the argument to be passed to the handler function when the job is being processed
|
||||
* return: NULL if no memory, otherwise a valid struct pointer
|
||||
*/
|
||||
struct osi_event *osi_event_create(osi_thread_func_t func, void *context);
|
||||
|
||||
/*
|
||||
* brief: Bind an osi_event to a specific work queue for an osi_thread.
|
||||
* After binding is completed, a function call of API osi_thread_post_event will send a work
|
||||
* to the workqueue of the thread, with specified queue index.
|
||||
* param func: event: the pointer to osi_event that is created using osi_event_create
|
||||
* param thread: the pointer to osi_thread that is created using osi_thread_create
|
||||
* param queue_idx: the index of the workqueue of the specified osi_thread, with range starting from 0 to work_queue_num - 1
|
||||
* return: true if osi_event binds to the thread's workqueue successfully, otherwise false
|
||||
*/
|
||||
bool osi_event_bind(struct osi_event* event, osi_thread_t *thread, int queue_idx);
|
||||
|
||||
/*
|
||||
* brief: Destroy the osi_event struct created by osi_event_create and free the allocated memory
|
||||
* param event: the pointer to osi_event
|
||||
*/
|
||||
void osi_event_delete(struct osi_event* event);
|
||||
|
||||
/*
|
||||
* brief: try sending a work to the binded thread's workqueue, so that it can be handled by the worker thread
|
||||
* param event: pointer to osi_event, created by osi_event_create
|
||||
* param timeout: post timeout, OSI_THREAD_MAX_TIMEOUT means blocking forever, 0 means never blocking, others means block millisecond
|
||||
* return: true if the message is enqueued to the thread workqueue, otherwise failed
|
||||
* note: if the return value of function is false, it is the case that the workqueue of the thread is full, and users
|
||||
* are expected to post the event sometime later to get the work handled.
|
||||
*/
|
||||
bool osi_thread_post_event(struct osi_event *event, uint32_t timeout);
|
||||
|
||||
#endif /* __THREAD_H__ */
|
||||
|
||||
144
components/bt/common/osi/pkt_queue.c
Normal file
144
components/bt/common/osi/pkt_queue.c
Normal file
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "osi/pkt_queue.h"
|
||||
#include "osi/allocator.h"
|
||||
#include "osi/mutex.h"
|
||||
|
||||
|
||||
STAILQ_HEAD(pkt_queue_header, pkt_linked_item);
|
||||
|
||||
struct pkt_queue {
|
||||
osi_mutex_t lock;
|
||||
size_t length;
|
||||
struct pkt_queue_header header;
|
||||
} pkt_queue_t;
|
||||
|
||||
struct pkt_queue *pkt_queue_create(void)
|
||||
{
|
||||
struct pkt_queue *queue = calloc(1, sizeof(struct pkt_queue));
|
||||
if (queue == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
if (osi_mutex_new(&queue->lock) != 0) {
|
||||
osi_free(queue);
|
||||
}
|
||||
struct pkt_queue_header *p = &queue->header;
|
||||
STAILQ_INIT(p);
|
||||
|
||||
return queue;
|
||||
}
|
||||
|
||||
static void pkt_queue_cleanup(struct pkt_queue *queue, pkt_queue_free_cb free_cb)
|
||||
{
|
||||
if (queue == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct pkt_queue_header *header = &queue->header;
|
||||
pkt_linked_item_t *item = STAILQ_FIRST(header);
|
||||
pkt_linked_item_t *tmp;
|
||||
|
||||
pkt_queue_free_cb free_func = (free_cb != NULL) ? free_cb : (pkt_queue_free_cb)osi_free_func;
|
||||
|
||||
while (item != NULL) {
|
||||
tmp = STAILQ_NEXT(item, next);
|
||||
free_func(item);
|
||||
item = tmp;
|
||||
queue->length--;
|
||||
}
|
||||
STAILQ_INIT(header);
|
||||
queue->length = 0;
|
||||
}
|
||||
|
||||
void pkt_queue_flush(struct pkt_queue *queue, pkt_queue_free_cb free_cb)
|
||||
{
|
||||
if (queue == NULL) {
|
||||
return;
|
||||
}
|
||||
osi_mutex_lock(&queue->lock, OSI_MUTEX_MAX_TIMEOUT);
|
||||
pkt_queue_cleanup(queue, free_cb);
|
||||
osi_mutex_unlock(&queue->lock);
|
||||
}
|
||||
|
||||
void pkt_queue_destroy(struct pkt_queue *queue, pkt_queue_free_cb free_cb)
|
||||
{
|
||||
if (queue == NULL) {
|
||||
return;
|
||||
}
|
||||
osi_mutex_lock(&queue->lock, OSI_MUTEX_MAX_TIMEOUT);
|
||||
pkt_queue_cleanup(queue, free_cb);
|
||||
osi_mutex_unlock(&queue->lock);
|
||||
|
||||
osi_mutex_free(&queue->lock);
|
||||
osi_free(queue);
|
||||
}
|
||||
|
||||
pkt_linked_item_t *pkt_queue_dequeue(struct pkt_queue *queue)
|
||||
{
|
||||
if (queue == NULL || queue->length == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct pkt_linked_item *item;
|
||||
struct pkt_queue_header *header;
|
||||
osi_mutex_lock(&queue->lock, OSI_MUTEX_MAX_TIMEOUT);
|
||||
header = &queue->header;
|
||||
item = STAILQ_FIRST(header);
|
||||
if (item != NULL) {
|
||||
STAILQ_REMOVE_HEAD(header, next);
|
||||
if (queue->length > 0) {
|
||||
queue->length--;
|
||||
}
|
||||
}
|
||||
osi_mutex_unlock(&queue->lock);
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
bool pkt_queue_enqueue(struct pkt_queue *queue, pkt_linked_item_t *item)
|
||||
{
|
||||
if (queue == NULL || item == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
struct pkt_queue_header *header;
|
||||
osi_mutex_lock(&queue->lock, OSI_MUTEX_MAX_TIMEOUT);
|
||||
header = &queue->header;
|
||||
STAILQ_INSERT_TAIL(header, item, next);
|
||||
queue->length++;
|
||||
osi_mutex_unlock(&queue->lock);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t pkt_queue_length(const struct pkt_queue *queue)
|
||||
{
|
||||
if (queue == NULL) {
|
||||
return 0;
|
||||
}
|
||||
return queue->length;
|
||||
}
|
||||
|
||||
bool pkt_queue_is_empty(const struct pkt_queue *queue)
|
||||
{
|
||||
return pkt_queue_length(queue) == 0;
|
||||
}
|
||||
|
||||
pkt_linked_item_t *pkt_queue_try_peek_first(struct pkt_queue *queue)
|
||||
{
|
||||
if (queue == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct pkt_queue_header *header = &queue->header;
|
||||
pkt_linked_item_t *item;
|
||||
osi_mutex_lock(&queue->lock, OSI_MUTEX_MAX_TIMEOUT);
|
||||
item = STAILQ_FIRST(header);
|
||||
osi_mutex_unlock(&queue->lock);
|
||||
|
||||
return item;
|
||||
}
|
||||
@@ -19,16 +19,28 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "osi/allocator.h"
|
||||
#include "osi/fixed_queue.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "osi/semaphore.h"
|
||||
#include "osi/thread.h"
|
||||
#include "osi/mutex.h"
|
||||
|
||||
struct work_item {
|
||||
osi_thread_func_t func;
|
||||
void *context;
|
||||
};
|
||||
|
||||
struct work_queue {
|
||||
QueueHandle_t queue;
|
||||
size_t capacity;
|
||||
};
|
||||
|
||||
struct osi_thread {
|
||||
TaskHandle_t thread_handle; /*!< Store the thread object */
|
||||
int thread_id; /*!< May for some OS, such as Linux */
|
||||
bool stop;
|
||||
uint8_t work_queue_num; /*!< Work queue number */
|
||||
fixed_queue_t **work_queues; /*!< Point to queue array, and the priority inverse array index */
|
||||
struct work_queue **work_queues; /*!< Point to queue array, and the priority inverse array index */
|
||||
osi_sem_t work_sem;
|
||||
osi_sem_t stop_sem;
|
||||
};
|
||||
@@ -39,13 +51,98 @@ struct osi_thread_start_arg {
|
||||
int error;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
osi_thread_func_t func;
|
||||
void *context;
|
||||
} work_item_t;
|
||||
struct osi_event {
|
||||
struct work_item item;
|
||||
osi_mutex_t lock;
|
||||
uint16_t is_queued;
|
||||
uint16_t queue_idx;
|
||||
osi_thread_t *thread;
|
||||
};
|
||||
|
||||
static const size_t DEFAULT_WORK_QUEUE_CAPACITY = 100;
|
||||
|
||||
static struct work_queue *osi_work_queue_create(size_t capacity)
|
||||
{
|
||||
if (capacity == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct work_queue *wq = (struct work_queue *)osi_malloc(sizeof(struct work_queue));
|
||||
if (wq != NULL) {
|
||||
wq->queue = xQueueCreate(capacity, sizeof(struct work_item));
|
||||
if (wq->queue != 0) {
|
||||
wq->capacity = capacity;
|
||||
return wq;
|
||||
} else {
|
||||
osi_free(wq);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void osi_work_queue_delete(struct work_queue *wq)
|
||||
{
|
||||
if (wq != NULL) {
|
||||
if (wq->queue != 0) {
|
||||
vQueueDelete(wq->queue);
|
||||
}
|
||||
wq->queue = 0;
|
||||
wq->capacity = 0;
|
||||
osi_free(wq);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static bool osi_thead_work_queue_get(struct work_queue *wq, struct work_item *item)
|
||||
{
|
||||
assert (wq != NULL);
|
||||
assert (wq->queue != 0);
|
||||
assert (item != NULL);
|
||||
|
||||
if (pdTRUE == xQueueReceive(wq->queue, item, 0)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool osi_thead_work_queue_put(struct work_queue *wq, const struct work_item *item, uint32_t timeout)
|
||||
{
|
||||
assert (wq != NULL);
|
||||
assert (wq->queue != 0);
|
||||
assert (item != NULL);
|
||||
|
||||
bool ret = true;
|
||||
if (timeout == OSI_SEM_MAX_TIMEOUT) {
|
||||
if (xQueueSend(wq->queue, item, portMAX_DELAY) != pdTRUE) {
|
||||
ret = false;
|
||||
}
|
||||
} else {
|
||||
if (xQueueSend(wq->queue, item, timeout / portTICK_PERIOD_MS) != pdTRUE) {
|
||||
ret = false;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static size_t osi_thead_work_queue_len(struct work_queue *wq)
|
||||
{
|
||||
assert (wq != NULL);
|
||||
assert (wq->queue != 0);
|
||||
assert (wq->capacity != 0);
|
||||
|
||||
size_t available_spaces = (size_t)uxQueueSpacesAvailable(wq->queue);
|
||||
|
||||
if (available_spaces <= wq->capacity) {
|
||||
return wq->capacity - available_spaces;
|
||||
} else {
|
||||
assert (0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void osi_thread_run(void *arg)
|
||||
{
|
||||
struct osi_thread_start_arg *start = (struct osi_thread_start_arg *)arg;
|
||||
@@ -62,11 +159,10 @@ static void osi_thread_run(void *arg)
|
||||
break;
|
||||
}
|
||||
|
||||
struct work_item item;
|
||||
while (!thread->stop && idx < thread->work_queue_num) {
|
||||
work_item_t *item = fixed_queue_dequeue(thread->work_queues[idx], 0);
|
||||
if (item) {
|
||||
item->func(item->context);
|
||||
osi_free(item);
|
||||
if (osi_thead_work_queue_get(thread->work_queues[idx], &item) == true) {
|
||||
item.func(item.context);
|
||||
idx = 0;
|
||||
continue;
|
||||
} else {
|
||||
@@ -107,14 +203,14 @@ static void osi_thread_stop(osi_thread_t *thread)
|
||||
}
|
||||
|
||||
//in linux, the stack_size, priority and core may not be set here, the code will be ignore the arguments
|
||||
osi_thread_t *osi_thread_create(const char *name, size_t stack_size, int priority, osi_thread_core_t core, uint8_t work_queue_num)
|
||||
osi_thread_t *osi_thread_create(const char *name, size_t stack_size, int priority, osi_thread_core_t core, uint8_t work_queue_num, const size_t work_queue_len[])
|
||||
{
|
||||
int ret;
|
||||
struct osi_thread_start_arg start_arg = {0};
|
||||
|
||||
if (stack_size <= 0 ||
|
||||
core < OSI_THREAD_CORE_0 || core > OSI_THREAD_CORE_AFFINITY ||
|
||||
work_queue_num <= 0) {
|
||||
work_queue_num <= 0 || work_queue_len == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -125,13 +221,14 @@ osi_thread_t *osi_thread_create(const char *name, size_t stack_size, int priorit
|
||||
|
||||
thread->stop = false;
|
||||
thread->work_queue_num = work_queue_num;
|
||||
thread->work_queues = (fixed_queue_t **)osi_malloc(sizeof(fixed_queue_t *) * work_queue_num);
|
||||
thread->work_queues = (struct work_queue **)osi_malloc(sizeof(struct work_queue *) * work_queue_num);
|
||||
if (thread->work_queues == NULL) {
|
||||
goto _err;
|
||||
}
|
||||
|
||||
for (int i = 0; i < thread->work_queue_num; i++) {
|
||||
thread->work_queues[i] = fixed_queue_new(DEFAULT_WORK_QUEUE_CAPACITY);
|
||||
size_t queue_len = work_queue_len[i] ? work_queue_len[i] : DEFAULT_WORK_QUEUE_CAPACITY;
|
||||
thread->work_queues[i] = osi_work_queue_create(queue_len);
|
||||
if (thread->work_queues[i] == NULL) {
|
||||
goto _err;
|
||||
}
|
||||
@@ -175,12 +272,14 @@ _err:
|
||||
|
||||
for (int i = 0; i < thread->work_queue_num; i++) {
|
||||
if (thread->work_queues[i]) {
|
||||
fixed_queue_free(thread->work_queues[i], osi_free_func);
|
||||
osi_work_queue_delete(thread->work_queues[i]);
|
||||
}
|
||||
thread->work_queues[i] = NULL;
|
||||
}
|
||||
|
||||
if (thread->work_queues) {
|
||||
osi_free(thread->work_queues);
|
||||
thread->work_queues = NULL;
|
||||
}
|
||||
|
||||
if (thread->work_sem) {
|
||||
@@ -206,12 +305,14 @@ void osi_thread_free(osi_thread_t *thread)
|
||||
|
||||
for (int i = 0; i < thread->work_queue_num; i++) {
|
||||
if (thread->work_queues[i]) {
|
||||
fixed_queue_free(thread->work_queues[i], osi_free_func);
|
||||
osi_work_queue_delete(thread->work_queues[i]);
|
||||
thread->work_queues[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (thread->work_queues) {
|
||||
osi_free(thread->work_queues);
|
||||
thread->work_queues = NULL;
|
||||
}
|
||||
|
||||
if (thread->work_sem) {
|
||||
@@ -235,15 +336,12 @@ bool osi_thread_post(osi_thread_t *thread, osi_thread_func_t func, void *context
|
||||
return false;
|
||||
}
|
||||
|
||||
work_item_t *item = (work_item_t *)osi_malloc(sizeof(work_item_t));
|
||||
if (item == NULL) {
|
||||
return false;
|
||||
}
|
||||
item->func = func;
|
||||
item->context = context;
|
||||
struct work_item item;
|
||||
|
||||
if (fixed_queue_enqueue(thread->work_queues[queue_idx], item, timeout) == false) {
|
||||
osi_free(item);
|
||||
item.func = func;
|
||||
item.context = context;
|
||||
|
||||
if (osi_thead_work_queue_put(thread->work_queues[queue_idx], &item, timeout) == false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -273,5 +371,83 @@ int osi_thread_queue_wait_size(osi_thread_t *thread, int wq_idx)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return fixed_queue_length(thread->work_queues[wq_idx]);
|
||||
return (int)(osi_thead_work_queue_len(thread->work_queues[wq_idx]));
|
||||
}
|
||||
|
||||
|
||||
struct osi_event *osi_event_create(osi_thread_func_t func, void *context)
|
||||
{
|
||||
struct osi_event *event = osi_calloc(sizeof(struct osi_event));
|
||||
if (event != NULL) {
|
||||
if (osi_mutex_new(&event->lock) == 0) {
|
||||
event->item.func = func;
|
||||
event->item.context = context;
|
||||
return event;
|
||||
}
|
||||
osi_free(event);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void osi_event_delete(struct osi_event* event)
|
||||
{
|
||||
if (event != NULL) {
|
||||
osi_mutex_free(&event->lock);
|
||||
memset(event, 0, sizeof(struct osi_event));
|
||||
osi_free(event);
|
||||
}
|
||||
}
|
||||
|
||||
bool osi_event_bind(struct osi_event* event, osi_thread_t *thread, int queue_idx)
|
||||
{
|
||||
if (event == NULL || event->thread != NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (thread == NULL || queue_idx >= thread->work_queue_num) {
|
||||
return false;
|
||||
}
|
||||
|
||||
event->thread = thread;
|
||||
event->queue_idx = queue_idx;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void osi_thread_generic_event_handler(void *context)
|
||||
{
|
||||
struct osi_event *event = (struct osi_event *)context;
|
||||
if (event != NULL && event->item.func != NULL) {
|
||||
osi_mutex_lock(&event->lock, OSI_MUTEX_MAX_TIMEOUT);
|
||||
event->is_queued = 0;
|
||||
osi_mutex_unlock(&event->lock);
|
||||
event->item.func(event->item.context);
|
||||
}
|
||||
}
|
||||
|
||||
bool osi_thread_post_event(struct osi_event *event, uint32_t timeout)
|
||||
{
|
||||
assert(event != NULL && event->thread != NULL);
|
||||
assert(event->queue_idx >= 0 && event->queue_idx < event->thread->work_queue_num);
|
||||
bool ret = false;
|
||||
if (event->is_queued == 0) {
|
||||
uint16_t acquire_cnt = 0;
|
||||
osi_mutex_lock(&event->lock, OSI_MUTEX_MAX_TIMEOUT);
|
||||
event->is_queued += 1;
|
||||
acquire_cnt = event->is_queued;
|
||||
osi_mutex_unlock(&event->lock);
|
||||
|
||||
if (acquire_cnt == 1) {
|
||||
ret = osi_thread_post(event->thread, osi_thread_generic_event_handler, event, event->queue_idx, timeout);
|
||||
if (!ret) {
|
||||
// clear "is_queued" when post failure, to allow for following event posts
|
||||
osi_mutex_lock(&event->lock, OSI_MUTEX_MAX_TIMEOUT);
|
||||
event->is_queued = 0;
|
||||
osi_mutex_unlock(&event->lock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -571,12 +571,18 @@ void ble_rtc_clk_init(void)
|
||||
// LP_TIMER_SEL_XTAL -> 1
|
||||
// LP_TIMER_SEL_8M -> 0
|
||||
// LP_TIMER_SEL_RTC_SLOW -> 0
|
||||
// LP_TIMER_CLK_DIV_NUM -> 1250
|
||||
SET_PERI_REG_BITS(MODEM_CLKRST_MODEM_LP_TIMER_CONF_REG, 1, 0, MODEM_CLKRST_LP_TIMER_SEL_XTAL32K_S);
|
||||
SET_PERI_REG_BITS(MODEM_CLKRST_MODEM_LP_TIMER_CONF_REG, 1, 1, MODEM_CLKRST_LP_TIMER_SEL_XTAL_S);
|
||||
SET_PERI_REG_BITS(MODEM_CLKRST_MODEM_LP_TIMER_CONF_REG, 1, 0, MODEM_CLKRST_LP_TIMER_SEL_8M_S);
|
||||
SET_PERI_REG_BITS(MODEM_CLKRST_MODEM_LP_TIMER_CONF_REG, 1, 0, MODEM_CLKRST_LP_TIMER_SEL_RTC_SLOW_S);
|
||||
|
||||
#ifdef CONFIG_ESP32C2_XTAL_FREQ_26
|
||||
// LP_TIMER_CLK_DIV_NUM -> 130
|
||||
SET_PERI_REG_BITS(MODEM_CLKRST_MODEM_LP_TIMER_CONF_REG, MODEM_CLKRST_LP_TIMER_CLK_DIV_NUM, 129, MODEM_CLKRST_LP_TIMER_CLK_DIV_NUM_S);
|
||||
#else
|
||||
// LP_TIMER_CLK_DIV_NUM -> 250
|
||||
SET_PERI_REG_BITS(MODEM_CLKRST_MODEM_LP_TIMER_CONF_REG, MODEM_CLKRST_LP_TIMER_CLK_DIV_NUM, 249, MODEM_CLKRST_LP_TIMER_CLK_DIV_NUM_S);
|
||||
#endif // CONFIG_ESP32C2_XTAL_FREQ_26
|
||||
|
||||
// MODEM_CLKRST_ETM_CLK_ACTIVE -> 1
|
||||
// MODEM_CLKRST_ETM_CLK_SEL -> 0
|
||||
|
||||
Submodule components/bt/controller/lib_esp32 updated: 9bc3e81aa1...c98341759b
Submodule components/bt/controller/lib_esp32c2/esp32c2-bt-lib updated: d652897062...bdab852aa2
@@ -117,9 +117,8 @@ void BTA_AvRegister(tBTA_AV_CHNL chnl, const char *p_service_name, UINT8 app_id,
|
||||
p_buf->hdr.event = BTA_AV_API_REGISTER_EVT;
|
||||
if (p_service_name) {
|
||||
BCM_STRNCPY_S(p_buf->p_service_name, p_service_name, BTA_SERVICE_NAME_LEN);
|
||||
p_buf->p_service_name[BTA_SERVICE_NAME_LEN - 1] = 0;
|
||||
} else {
|
||||
p_buf->p_service_name[0] = 0;
|
||||
p_buf->p_service_name[0] = '\0';
|
||||
}
|
||||
p_buf->app_id = app_id;
|
||||
p_buf->p_app_data_cback = p_data_cback;
|
||||
@@ -307,9 +306,10 @@ void BTA_AvReconfig(tBTA_AV_HNDL hndl, BOOLEAN suspend, UINT8 sep_info_idx,
|
||||
p_buf->num_protect = num_protect;
|
||||
p_buf->suspend = suspend;
|
||||
p_buf->sep_info_idx = sep_info_idx;
|
||||
p_buf->p_protect_info = (UINT8 *)(p_buf + 1);
|
||||
memcpy(p_buf->codec_info, p_codec_info, AVDT_CODEC_SIZE);
|
||||
memcpy(p_buf->p_protect_info, p_protect_info, num_protect);
|
||||
if (p_protect_info && num_protect) {
|
||||
memcpy(p_buf->p_protect_info, p_protect_info, num_protect);
|
||||
}
|
||||
bta_sys_sendmsg(p_buf);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,21 +74,17 @@ void bta_av_ci_setconfig(tBTA_AV_HNDL hndl, UINT8 err_code, UINT8 category,
|
||||
{
|
||||
tBTA_AV_CI_SETCONFIG *p_buf;
|
||||
|
||||
if ((p_buf = (tBTA_AV_CI_SETCONFIG *) osi_malloc(sizeof(tBTA_AV_CI_SETCONFIG))) != NULL) {
|
||||
if ((p_buf = (tBTA_AV_CI_SETCONFIG *) osi_malloc(sizeof(tBTA_AV_CI_SETCONFIG) + num_seid)) != NULL) {
|
||||
p_buf->hdr.layer_specific = hndl;
|
||||
p_buf->hdr.event = (err_code == AVDT_SUCCESS) ?
|
||||
BTA_AV_CI_SETCONFIG_OK_EVT : BTA_AV_CI_SETCONFIG_FAIL_EVT;
|
||||
p_buf->err_code = err_code;
|
||||
p_buf->category = category;
|
||||
p_buf->recfg_needed = recfg_needed;
|
||||
p_buf->num_seid = num_seid;
|
||||
p_buf->avdt_handle = avdt_handle;
|
||||
p_buf->num_seid = num_seid;
|
||||
if (p_seid && num_seid) {
|
||||
p_buf->p_seid = (UINT8 *)(p_buf + 1);
|
||||
memcpy(p_buf->p_seid, p_seid, num_seid);
|
||||
} else {
|
||||
p_buf->p_seid = NULL;
|
||||
p_buf->num_seid = 0;
|
||||
}
|
||||
|
||||
bta_sys_sendmsg(p_buf);
|
||||
|
||||
@@ -474,6 +474,7 @@ static void bta_av_api_sink_enable(tBTA_AV_DATA *p_data)
|
||||
APPL_TRACE_DEBUG("bta_av_api_sink_enable %d \n", activate_sink)
|
||||
char p_service_name[BTA_SERVICE_NAME_LEN + 1];
|
||||
BCM_STRNCPY_S(p_service_name, BTIF_AVK_SERVICE_NAME, BTA_SERVICE_NAME_LEN);
|
||||
p_service_name[BTA_SERVICE_NAME_LEN] = '\0';
|
||||
|
||||
if (activate_sink) {
|
||||
AVDT_SINK_Activate();
|
||||
@@ -537,6 +538,7 @@ static void bta_av_api_register(tBTA_AV_DATA *p_data)
|
||||
UINT8 index = 0;
|
||||
char p_avk_service_name[BTA_SERVICE_NAME_LEN + 1];
|
||||
BCM_STRNCPY_S(p_avk_service_name, BTIF_AVK_SERVICE_NAME, BTA_SERVICE_NAME_LEN);
|
||||
p_avk_service_name[BTA_SERVICE_NAME_LEN] = '\0';
|
||||
|
||||
memset(&cs, 0, sizeof(tAVDT_CS));
|
||||
|
||||
|
||||
@@ -264,10 +264,10 @@ typedef struct {
|
||||
typedef struct {
|
||||
BT_HDR hdr;
|
||||
UINT8 codec_info[AVDT_CODEC_SIZE]; /* codec configuration */
|
||||
UINT8 *p_protect_info;
|
||||
UINT8 num_protect;
|
||||
BOOLEAN suspend;
|
||||
UINT8 sep_info_idx;
|
||||
UINT8 num_protect;
|
||||
UINT8 p_protect_info[0];
|
||||
} tBTA_AV_API_RCFG;
|
||||
|
||||
/* data type for BTA_AV_CI_SETCONFIG_OK_EVT and BTA_AV_CI_SETCONFIG_FAIL_EVT */
|
||||
@@ -276,10 +276,10 @@ typedef struct {
|
||||
tBTA_AV_HNDL hndl;
|
||||
UINT8 err_code;
|
||||
UINT8 category;
|
||||
UINT8 num_seid;
|
||||
UINT8 *p_seid;
|
||||
BOOLEAN recfg_needed;
|
||||
UINT8 avdt_handle; /* local sep type for which this stream will be set up */
|
||||
UINT8 num_seid;
|
||||
UINT8 p_seid[0];
|
||||
} tBTA_AV_CI_SETCONFIG;
|
||||
|
||||
/* data type for all stream events from AVDTP */
|
||||
|
||||
@@ -705,7 +705,7 @@ static BOOLEAN bta_dm_read_remote_device_name (BD_ADDR bd_addr, tBT_TRANSPORT tr
|
||||
APPL_TRACE_DEBUG("bta_dm_read_remote_device_name");
|
||||
|
||||
bdcpy(bta_dm_search_cb.peer_bdaddr, bd_addr);
|
||||
bta_dm_search_cb.peer_name[0] = 0;
|
||||
bta_dm_search_cb.peer_name[0] = '\0';
|
||||
|
||||
btm_status = BTM_ReadRemoteDeviceName (bta_dm_search_cb.peer_bdaddr,
|
||||
(tBTM_CMPL_CB *) bta_dm_remname_cback,
|
||||
@@ -743,7 +743,7 @@ void bta_dm_read_rmt_name(tBTA_DM_MSG *p_data)
|
||||
{
|
||||
APPL_TRACE_DEBUG("%s",__func__);
|
||||
bdcpy(bta_dm_search_cb.peer_bdaddr, p_data->get_rmt_name.rmt_addr);
|
||||
bta_dm_search_cb.peer_name[0] = 0;
|
||||
bta_dm_search_cb.peer_name[0] = '\0';
|
||||
|
||||
tBTM_STATUS btm_status = BTM_ReadRemoteDeviceName(bta_dm_search_cb.peer_bdaddr,
|
||||
(tBTM_CMPL_CB *) p_data->get_rmt_name.rmt_name_cb,
|
||||
@@ -1621,7 +1621,7 @@ void bta_dm_discover (tBTA_DM_MSG *p_data)
|
||||
bta_dm_search_cb.services_to_search = bta_dm_search_cb.services;
|
||||
bta_dm_search_cb.service_index = 0;
|
||||
bta_dm_search_cb.services_found = 0;
|
||||
bta_dm_search_cb.peer_name[0] = 0;
|
||||
bta_dm_search_cb.peer_name[0] = '\0';
|
||||
bta_dm_search_cb.sdp_search = p_data->discover.sdp_search;
|
||||
bta_dm_search_cb.p_btm_inq_info = BTM_InqDbRead (p_data->discover.bd_addr);
|
||||
bta_dm_search_cb.transport = p_data->discover.transport;
|
||||
@@ -1896,8 +1896,8 @@ void bta_dm_sdp_result (tBTA_DM_MSG *p_data)
|
||||
if (SDP_FindServiceUUIDInRec(p_sdp_rec, &service_uuid)) {
|
||||
/* send result back to app now, one by one */
|
||||
bdcpy (result.disc_ble_res.bd_addr, bta_dm_search_cb.peer_bdaddr);
|
||||
BCM_STRNCPY_S((char *)result.disc_ble_res.bd_name, bta_dm_get_remname(), (BD_NAME_LEN));
|
||||
result.disc_ble_res.bd_name[BD_NAME_LEN] = 0;
|
||||
BCM_STRNCPY_S((char *)result.disc_ble_res.bd_name, bta_dm_get_remname(), BD_NAME_LEN);
|
||||
result.disc_ble_res.bd_name[BD_NAME_LEN] = '\0';
|
||||
result.disc_ble_res.service.len = service_uuid.len;
|
||||
result.disc_ble_res.service.uu.uuid16 = service_uuid.uu.uuid16;
|
||||
|
||||
@@ -2037,10 +2037,8 @@ void bta_dm_sdp_result (tBTA_DM_MSG *p_data)
|
||||
|
||||
}
|
||||
bdcpy (p_msg->disc_result.result.disc_res.bd_addr, bta_dm_search_cb.peer_bdaddr);
|
||||
BCM_STRNCPY_S((char *)p_msg->disc_result.result.disc_res.bd_name, bta_dm_get_remname(), (BD_NAME_LEN - 1));
|
||||
|
||||
/* make sure the string is null terminated */
|
||||
p_msg->disc_result.result.disc_res.bd_name[BD_NAME_LEN - 1] = 0;
|
||||
BCM_STRNCPY_S((char *)p_msg->disc_result.result.disc_res.bd_name, bta_dm_get_remname(), BD_NAME_LEN);
|
||||
p_msg->disc_result.result.disc_res.bd_name[BD_NAME_LEN] = '\0';
|
||||
|
||||
bta_sys_sendmsg(p_msg);
|
||||
}
|
||||
@@ -2063,10 +2061,8 @@ void bta_dm_sdp_result (tBTA_DM_MSG *p_data)
|
||||
p_msg->disc_result.result.disc_res.result = BTA_FAILURE;
|
||||
p_msg->disc_result.result.disc_res.services = bta_dm_search_cb.services_found;
|
||||
bdcpy (p_msg->disc_result.result.disc_res.bd_addr, bta_dm_search_cb.peer_bdaddr);
|
||||
BCM_STRNCPY_S((char *)p_msg->disc_result.result.disc_res.bd_name,bta_dm_get_remname(), (BD_NAME_LEN - 1));
|
||||
|
||||
/* make sure the string is null terminated */
|
||||
p_msg->disc_result.result.disc_res.bd_name[BD_NAME_LEN - 1] = 0;
|
||||
BCM_STRNCPY_S((char *)p_msg->disc_result.result.disc_res.bd_name, bta_dm_get_remname(), BD_NAME_LEN);
|
||||
p_msg->disc_result.result.disc_res.bd_name[BD_NAME_LEN] = '\0';
|
||||
|
||||
bta_sys_sendmsg(p_msg);
|
||||
}
|
||||
@@ -2447,10 +2443,8 @@ static void bta_dm_find_services ( BD_ADDR bd_addr)
|
||||
p_msg->hdr.event = BTA_DM_DISCOVERY_RESULT_EVT;
|
||||
p_msg->disc_result.result.disc_res.services = bta_dm_search_cb.services_found;
|
||||
bdcpy (p_msg->disc_result.result.disc_res.bd_addr, bta_dm_search_cb.peer_bdaddr);
|
||||
BCM_STRNCPY_S((char *)p_msg->disc_result.result.disc_res.bd_name,bta_dm_get_remname(), (BD_NAME_LEN - 1));
|
||||
|
||||
/* make sure the string is terminated */
|
||||
p_msg->disc_result.result.disc_res.bd_name[BD_NAME_LEN - 1] = 0;
|
||||
BCM_STRNCPY_S((char *)p_msg->disc_result.result.disc_res.bd_name,bta_dm_get_remname(), BD_NAME_LEN);
|
||||
p_msg->disc_result.result.disc_res.bd_name[BD_NAME_LEN] = '\0';
|
||||
|
||||
bta_sys_sendmsg(p_msg);
|
||||
}
|
||||
@@ -2632,10 +2626,8 @@ static void bta_dm_discover_device(BD_ADDR remote_bd_addr)
|
||||
p_msg->disc_result.result.disc_res.result = BTA_SUCCESS;
|
||||
p_msg->disc_result.result.disc_res.services = bta_dm_search_cb.services_found;
|
||||
bdcpy (p_msg->disc_result.result.disc_res.bd_addr, bta_dm_search_cb.peer_bdaddr);
|
||||
BCM_STRNCPY_S((char *)p_msg->disc_result.result.disc_res.bd_name,(char *)bta_dm_search_cb.peer_name, (BD_NAME_LEN - 1));
|
||||
|
||||
/* make sure the string is terminated */
|
||||
p_msg->disc_result.result.disc_res.bd_name[BD_NAME_LEN - 1] = 0;
|
||||
BCM_STRNCPY_S((char *)p_msg->disc_result.result.disc_res.bd_name, bta_dm_get_remname(), BD_NAME_LEN);
|
||||
p_msg->disc_result.result.disc_res.bd_name[BD_NAME_LEN] = '\0';
|
||||
|
||||
bta_sys_sendmsg(p_msg);
|
||||
}
|
||||
@@ -2772,11 +2764,11 @@ static void bta_dm_service_search_remname_cback (BD_ADDR bd_addr, DEV_CLASS dc,
|
||||
/* if this is what we are looking for */
|
||||
if (!bdcmp( bta_dm_search_cb.peer_bdaddr, bd_addr)) {
|
||||
rem_name.length = strlen((char *)bd_name);
|
||||
if (rem_name.length > (BD_NAME_LEN - 1)) {
|
||||
rem_name.length = (BD_NAME_LEN - 1);
|
||||
rem_name.remote_bd_name[(BD_NAME_LEN - 1)] = 0;
|
||||
if (rem_name.length > BD_NAME_LEN) {
|
||||
rem_name.length = BD_NAME_LEN;
|
||||
}
|
||||
BCM_STRNCPY_S((char *)rem_name.remote_bd_name, (char *)bd_name, (BD_NAME_LEN - 1));
|
||||
BCM_STRNCPY_S((char *)rem_name.remote_bd_name, (char *)bd_name, BD_NAME_LEN);
|
||||
rem_name.remote_bd_name[BD_NAME_LEN] = '\0';
|
||||
rem_name.status = BTM_SUCCESS;
|
||||
|
||||
bta_dm_remname_cback(&rem_name);
|
||||
@@ -2793,7 +2785,7 @@ static void bta_dm_service_search_remname_cback (BD_ADDR bd_addr, DEV_CLASS dc,
|
||||
APPL_TRACE_WARNING("bta_dm_service_search_remname_cback: BTM_ReadRemoteDeviceName returns 0x%02X", btm_status);
|
||||
|
||||
rem_name.length = 0;
|
||||
rem_name.remote_bd_name[0] = 0;
|
||||
rem_name.remote_bd_name[0] = '\0';
|
||||
rem_name.status = btm_status;
|
||||
bta_dm_remname_cback(&rem_name);
|
||||
}
|
||||
@@ -2818,8 +2810,8 @@ static void bta_dm_remname_cback (tBTM_REMOTE_DEV_NAME *p_remote_name)
|
||||
p_remote_name->remote_bd_name);
|
||||
/* remote name discovery is done but it could be failed */
|
||||
bta_dm_search_cb.name_discover_done = TRUE;
|
||||
BCM_STRNCPY_S((char *)bta_dm_search_cb.peer_name, (char *)p_remote_name->remote_bd_name, (BD_NAME_LEN));
|
||||
bta_dm_search_cb.peer_name[BD_NAME_LEN] = 0;
|
||||
BCM_STRNCPY_S((char *)bta_dm_search_cb.peer_name, (char *)p_remote_name->remote_bd_name, BD_NAME_LEN);
|
||||
bta_dm_search_cb.peer_name[BD_NAME_LEN] = '\0';
|
||||
|
||||
BTM_SecDeleteRmtNameNotifyCallback(&bta_dm_service_search_remname_cback);
|
||||
|
||||
@@ -2831,10 +2823,8 @@ static void bta_dm_remname_cback (tBTM_REMOTE_DEV_NAME *p_remote_name)
|
||||
|
||||
if ((p_msg = (tBTA_DM_REM_NAME *) osi_malloc(sizeof(tBTA_DM_REM_NAME))) != NULL) {
|
||||
bdcpy (p_msg->result.disc_res.bd_addr, bta_dm_search_cb.peer_bdaddr);
|
||||
BCM_STRNCPY_S((char *)p_msg->result.disc_res.bd_name, (char *)p_remote_name->remote_bd_name, (BD_NAME_LEN));
|
||||
|
||||
/* make sure the string is null terminated */
|
||||
p_msg->result.disc_res.bd_name[BD_NAME_LEN] = 0;
|
||||
BCM_STRNCPY_S((char *)p_msg->result.disc_res.bd_name, (char *)p_remote_name->remote_bd_name, BD_NAME_LEN);
|
||||
p_msg->result.disc_res.bd_name[BD_NAME_LEN] = '\0';
|
||||
|
||||
p_msg->hdr.event = BTA_DM_REMT_NAME_EVT;
|
||||
bta_sys_sendmsg(p_msg);
|
||||
@@ -2862,10 +2852,8 @@ static UINT8 bta_dm_authorize_cback (BD_ADDR bd_addr, DEV_CLASS dev_class, BD_NA
|
||||
bdcpy(sec_event.authorize.bd_addr, bd_addr);
|
||||
memcpy(sec_event.authorize.dev_class, dev_class, DEV_CLASS_LEN);
|
||||
|
||||
BCM_STRNCPY_S((char *)sec_event.authorize.bd_name, (char *)bd_name, (BD_NAME_LEN - 1));
|
||||
|
||||
/* make sure the string is null terminated */
|
||||
sec_event.authorize.bd_name[BD_NAME_LEN - 1] = 0;
|
||||
BCM_STRNCPY_S((char *)sec_event.authorize.bd_name, (char *)bd_name, BD_NAME_LEN);
|
||||
sec_event.authorize.bd_name[BD_NAME_LEN] = '\0';
|
||||
|
||||
#if ( defined(BTA_JV_INCLUDED) && BTA_JV_INCLUDED == TRUE )
|
||||
sec_event.authorize.service = service_id;
|
||||
@@ -2911,7 +2899,6 @@ static UINT8 bta_dm_authorize_cback (BD_ADDR bd_addr, DEV_CLASS dev_class, BD_NA
|
||||
{
|
||||
tBTM_REMOTE_DEV_NAME *p_result = (tBTM_REMOTE_DEV_NAME *)p_data;
|
||||
tBTA_DM_SEC sec_event;
|
||||
UINT32 bytes_to_copy;
|
||||
tBTA_DM_SEC_EVT event = bta_dm_cb.pin_evt;
|
||||
|
||||
if (BTA_DM_SP_CFM_REQ_EVT == event) {
|
||||
@@ -2920,12 +2907,10 @@ static UINT8 bta_dm_authorize_cback (BD_ADDR bd_addr, DEV_CLASS dev_class, BD_NA
|
||||
BTA_COPY_DEVICE_CLASS(sec_event.cfm_req.dev_class, bta_dm_cb.pin_dev_class);
|
||||
|
||||
if (p_result && p_result->status == BTM_SUCCESS) {
|
||||
bytes_to_copy = (p_result->length < (BD_NAME_LEN - 1))
|
||||
? p_result->length : (BD_NAME_LEN - 1);
|
||||
memcpy(sec_event.cfm_req.bd_name, p_result->remote_bd_name, bytes_to_copy);
|
||||
sec_event.pin_req.bd_name[BD_NAME_LEN - 1] = 0;
|
||||
BCM_STRNCPY_S((char *)sec_event.cfm_req.bd_name, (char *)p_result->remote_bd_name, BD_NAME_LEN);
|
||||
sec_event.pin_req.bd_name[BD_NAME_LEN] = '\0';
|
||||
} else { /* No name found */
|
||||
sec_event.cfm_req.bd_name[0] = 0;
|
||||
sec_event.cfm_req.bd_name[0] = '\0';
|
||||
}
|
||||
|
||||
sec_event.key_notif.passkey = bta_dm_cb.num_val; /* get PIN code numeric number */
|
||||
@@ -2938,12 +2923,10 @@ static UINT8 bta_dm_authorize_cback (BD_ADDR bd_addr, DEV_CLASS dev_class, BD_NA
|
||||
BTA_COPY_DEVICE_CLASS(sec_event.pin_req.dev_class, bta_dm_cb.pin_dev_class);
|
||||
|
||||
if (p_result && p_result->status == BTM_SUCCESS) {
|
||||
bytes_to_copy = (p_result->length < (BD_NAME_LEN - 1))
|
||||
? p_result->length : (BD_NAME_LEN - 1);
|
||||
memcpy(sec_event.pin_req.bd_name, p_result->remote_bd_name, bytes_to_copy);
|
||||
sec_event.pin_req.bd_name[BD_NAME_LEN - 1] = 0;
|
||||
BCM_STRNCPY_S((char *)sec_event.pin_req.bd_name, (char *)p_result->remote_bd_name, BD_NAME_LEN);
|
||||
sec_event.pin_req.bd_name[BD_NAME_LEN] = '\0';
|
||||
} else { /* No name found */
|
||||
sec_event.pin_req.bd_name[0] = 0;
|
||||
sec_event.pin_req.bd_name[0] = '\0';
|
||||
}
|
||||
|
||||
event = bta_dm_cb.pin_evt;
|
||||
@@ -2976,8 +2959,8 @@ static UINT8 bta_dm_pin_cback (BD_ADDR bd_addr, DEV_CLASS dev_class, BD_NAME bd_
|
||||
|
||||
bdcpy(sec_event.pin_req.bd_addr, bd_addr);
|
||||
BTA_COPY_DEVICE_CLASS(sec_event.pin_req.dev_class, dev_class);
|
||||
BCM_STRNCPY_S((char *)sec_event.pin_req.bd_name, (char *)bd_name, (BD_NAME_LEN - 1));
|
||||
sec_event.pin_req.bd_name[BD_NAME_LEN - 1] = 0;
|
||||
BCM_STRNCPY_S((char *)sec_event.pin_req.bd_name, (char *)bd_name, BD_NAME_LEN);
|
||||
sec_event.pin_req.bd_name[BD_NAME_LEN] = '\0';
|
||||
sec_event.pin_req.min_16_digit = min_16_digit;
|
||||
|
||||
bta_dm_cb.p_sec_cback(BTA_DM_PIN_REQ_EVT, &sec_event);
|
||||
@@ -3151,8 +3134,8 @@ static UINT8 bta_dm_sp_cback (tBTM_SP_EVT event, tBTM_SP_EVT_DATA *p_data)
|
||||
copy these values into key_notif from cfm_req */
|
||||
bdcpy(sec_event.key_notif.bd_addr, p_data->cfm_req.bd_addr);
|
||||
BTA_COPY_DEVICE_CLASS(sec_event.key_notif.dev_class, p_data->cfm_req.dev_class);
|
||||
BCM_STRNCPY_S((char *)sec_event.key_notif.bd_name, (char *)p_data->cfm_req.bd_name, (BD_NAME_LEN - 1));
|
||||
sec_event.key_notif.bd_name[BD_NAME_LEN - 1] = 0;
|
||||
BCM_STRNCPY_S((char *)sec_event.key_notif.bd_name, (char *)p_data->cfm_req.bd_name, BD_NAME_LEN);
|
||||
sec_event.key_notif.bd_name[BD_NAME_LEN] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3172,8 +3155,8 @@ static UINT8 bta_dm_sp_cback (tBTM_SP_EVT event, tBTM_SP_EVT_DATA *p_data)
|
||||
} else {
|
||||
bdcpy(sec_event.key_notif.bd_addr, p_data->key_notif.bd_addr);
|
||||
BTA_COPY_DEVICE_CLASS(sec_event.key_notif.dev_class, p_data->key_notif.dev_class);
|
||||
BCM_STRNCPY_S((char *)sec_event.key_notif.bd_name, (char *)p_data->key_notif.bd_name, (BD_NAME_LEN - 1));
|
||||
sec_event.key_notif.bd_name[BD_NAME_LEN - 1] = 0;
|
||||
BCM_STRNCPY_S((char *)sec_event.key_notif.bd_name, (char *)p_data->key_notif.bd_name, BD_NAME_LEN);
|
||||
sec_event.key_notif.bd_name[BD_NAME_LEN] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3193,8 +3176,8 @@ static UINT8 bta_dm_sp_cback (tBTM_SP_EVT event, tBTM_SP_EVT_DATA *p_data)
|
||||
} else {
|
||||
bdcpy(sec_event.key_notif.bd_addr, p_data->key_notif.bd_addr);
|
||||
BTA_COPY_DEVICE_CLASS(sec_event.key_notif.dev_class, p_data->key_notif.dev_class);
|
||||
BCM_STRNCPY_S((char *)sec_event.key_notif.bd_name,(char *)p_data->key_notif.bd_name, (BD_NAME_LEN - 1));
|
||||
sec_event.key_notif.bd_name[BD_NAME_LEN - 1] = 0;
|
||||
BCM_STRNCPY_S((char *)sec_event.key_notif.bd_name,(char *)p_data->key_notif.bd_name, BD_NAME_LEN);
|
||||
sec_event.key_notif.bd_name[BD_NAME_LEN] = '\0';
|
||||
}
|
||||
}
|
||||
bta_dm_cb.p_sec_cback(pin_evt, &sec_event);
|
||||
@@ -3222,8 +3205,8 @@ static UINT8 bta_dm_sp_cback (tBTM_SP_EVT event, tBTM_SP_EVT_DATA *p_data)
|
||||
|
||||
bdcpy(sec_event.rmt_oob.bd_addr, p_data->rmt_oob.bd_addr);
|
||||
BTA_COPY_DEVICE_CLASS(sec_event.rmt_oob.dev_class, p_data->rmt_oob.dev_class);
|
||||
BCM_STRNCPY_S((char *)sec_event.rmt_oob.bd_name, (char *)p_data->rmt_oob.bd_name, (BD_NAME_LEN - 1));
|
||||
sec_event.rmt_oob.bd_name[BD_NAME_LEN - 1] = 0;
|
||||
BCM_STRNCPY_S((char *)sec_event.rmt_oob.bd_name, (char *)p_data->rmt_oob.bd_name, BD_NAME_LEN);
|
||||
sec_event.rmt_oob.bd_name[BD_NAME_LEN] = '\0';
|
||||
|
||||
bta_dm_cb.p_sec_cback(BTA_DM_SP_RMT_OOB_EVT, &sec_event);
|
||||
|
||||
@@ -4656,11 +4639,11 @@ static UINT8 bta_dm_ble_smp_cback (tBTM_LE_EVT event, BD_ADDR bda, tBTM_LE_EVT_D
|
||||
bdcpy(sec_event.ble_req.bd_addr, bda);
|
||||
p_name = BTM_SecReadDevName(bda);
|
||||
if (p_name != NULL) {
|
||||
BCM_STRNCPY_S((char *)sec_event.ble_req.bd_name,p_name, (BD_NAME_LEN));
|
||||
BCM_STRNCPY_S((char *)sec_event.ble_req.bd_name, p_name, BD_NAME_LEN);
|
||||
sec_event.ble_req.bd_name[BD_NAME_LEN] = '\0';
|
||||
} else {
|
||||
sec_event.ble_req.bd_name[0] = 0;
|
||||
sec_event.ble_req.bd_name[0] = '\0';
|
||||
}
|
||||
sec_event.ble_req.bd_name[BD_NAME_LEN] = 0;
|
||||
bta_dm_cb.p_sec_cback(BTA_DM_BLE_SEC_REQ_EVT, &sec_event);
|
||||
break;
|
||||
|
||||
@@ -4668,11 +4651,11 @@ static UINT8 bta_dm_ble_smp_cback (tBTM_LE_EVT event, BD_ADDR bda, tBTM_LE_EVT_D
|
||||
bdcpy(sec_event.key_notif.bd_addr, bda);
|
||||
p_name = BTM_SecReadDevName(bda);
|
||||
if (p_name != NULL) {
|
||||
BCM_STRNCPY_S((char *)sec_event.key_notif.bd_name, p_name, (BD_NAME_LEN));
|
||||
BCM_STRNCPY_S((char *)sec_event.key_notif.bd_name, p_name, BD_NAME_LEN);
|
||||
sec_event.key_notif.bd_name[BD_NAME_LEN] = '\0';
|
||||
} else {
|
||||
sec_event.key_notif.bd_name[0] = 0;
|
||||
sec_event.key_notif.bd_name[0] = '\0';
|
||||
}
|
||||
sec_event.ble_req.bd_name[BD_NAME_LEN] = 0;
|
||||
sec_event.key_notif.passkey = p_data->key_notif;
|
||||
bta_dm_cb.p_sec_cback(BTA_DM_BLE_PASSKEY_NOTIF_EVT, &sec_event);
|
||||
break;
|
||||
@@ -4689,8 +4672,8 @@ static UINT8 bta_dm_ble_smp_cback (tBTM_LE_EVT event, BD_ADDR bda, tBTM_LE_EVT_D
|
||||
|
||||
case BTM_LE_NC_REQ_EVT:
|
||||
bdcpy(sec_event.key_notif.bd_addr, bda);
|
||||
BCM_STRNCPY_S((char *)sec_event.key_notif.bd_name,bta_dm_get_remname(), (BD_NAME_LEN));
|
||||
sec_event.ble_req.bd_name[BD_NAME_LEN] = 0;
|
||||
BCM_STRNCPY_S((char *)sec_event.key_notif.bd_name,bta_dm_get_remname(), BD_NAME_LEN);
|
||||
sec_event.key_notif.bd_name[BD_NAME_LEN] = '\0';
|
||||
sec_event.key_notif.passkey = p_data->key_notif;
|
||||
bta_dm_cb.p_sec_cback(BTA_DM_BLE_NC_REQ_EVT, &sec_event);
|
||||
break;
|
||||
@@ -4709,9 +4692,10 @@ static UINT8 bta_dm_ble_smp_cback (tBTM_LE_EVT event, BD_ADDR bda, tBTM_LE_EVT_D
|
||||
#endif
|
||||
p_name = BTM_SecReadDevName(bda);
|
||||
if (p_name != NULL) {
|
||||
BCM_STRNCPY_S((char *)sec_event.auth_cmpl.bd_name, p_name, (BD_NAME_LEN));
|
||||
BCM_STRNCPY_S((char *)sec_event.auth_cmpl.bd_name, p_name, BD_NAME_LEN);
|
||||
sec_event.auth_cmpl.bd_name[BD_NAME_LEN] = '\0';
|
||||
} else {
|
||||
sec_event.auth_cmpl.bd_name[0] = 0;
|
||||
sec_event.auth_cmpl.bd_name[0] = '\0';
|
||||
}
|
||||
if (p_data->complt.reason != 0) {
|
||||
sec_event.auth_cmpl.fail_reason = BTA_DM_AUTH_CONVERT_SMP_CODE(((UINT8)p_data->complt.reason));
|
||||
@@ -6197,8 +6181,8 @@ static void bta_dm_gatt_disc_result(tBTA_GATT_ID service_id)
|
||||
|
||||
/* send result back to app now, one by one */
|
||||
bdcpy (result.disc_ble_res.bd_addr, bta_dm_search_cb.peer_bdaddr);
|
||||
BCM_STRNCPY_S((char *)result.disc_ble_res.bd_name, bta_dm_get_remname(), (BD_NAME_LEN - 1));
|
||||
result.disc_ble_res.bd_name[BD_NAME_LEN] = 0;
|
||||
BCM_STRNCPY_S((char *)result.disc_ble_res.bd_name, bta_dm_get_remname(), BD_NAME_LEN);
|
||||
result.disc_ble_res.bd_name[BD_NAME_LEN] = '\0';
|
||||
memcpy(&result.disc_ble_res.service, &service_id.uuid, sizeof(tBT_UUID));
|
||||
|
||||
bta_dm_search_cb.p_search_cback(BTA_DM_DISC_BLE_RES_EVT, &result);
|
||||
@@ -6240,10 +6224,8 @@ static void bta_dm_gatt_disc_complete(UINT16 conn_id, tBTA_GATT_STATUS status)
|
||||
p_msg->disc_result.result.disc_res.num_uuids = 0;
|
||||
p_msg->disc_result.result.disc_res.p_uuid_list = NULL;
|
||||
bdcpy (p_msg->disc_result.result.disc_res.bd_addr, bta_dm_search_cb.peer_bdaddr);
|
||||
BCM_STRNCPY_S((char *)p_msg->disc_result.result.disc_res.bd_name,bta_dm_get_remname(), (BD_NAME_LEN - 1));
|
||||
|
||||
/* make sure the string is terminated */
|
||||
p_msg->disc_result.result.disc_res.bd_name[BD_NAME_LEN - 1] = 0;
|
||||
BCM_STRNCPY_S((char *)p_msg->disc_result.result.disc_res.bd_name, bta_dm_get_remname(), BD_NAME_LEN);
|
||||
p_msg->disc_result.result.disc_res.bd_name[BD_NAME_LEN] = '\0';
|
||||
|
||||
p_msg->disc_result.result.disc_res.device_type |= BT_DEVICE_TYPE_BLE;
|
||||
if ( bta_dm_search_cb.ble_raw_used > 0 ) {
|
||||
|
||||
@@ -174,8 +174,8 @@ void BTA_DmSetDeviceName(const char *p_name)
|
||||
if ((p_msg = (tBTA_DM_API_SET_NAME *) osi_malloc(sizeof(tBTA_DM_API_SET_NAME))) != NULL) {
|
||||
p_msg->hdr.event = BTA_DM_API_SET_NAME_EVT;
|
||||
/* truncate the name if needed */
|
||||
BCM_STRNCPY_S((char *)p_msg->name, p_name, BD_NAME_LEN - 1);
|
||||
p_msg->name[BD_NAME_LEN - 1] = 0;
|
||||
BCM_STRNCPY_S((char *)p_msg->name, p_name, BD_NAME_LEN);
|
||||
p_msg->name[BD_NAME_LEN] = '\0';
|
||||
|
||||
bta_sys_sendmsg(p_msg);
|
||||
}
|
||||
|
||||
@@ -123,9 +123,9 @@ void BTA_AgRegister(tBTA_SERVICE_MASK services, tBTA_SEC sec_mask,tBTA_AG_FEAT f
|
||||
for (i = 0; i < BTA_AG_NUM_IDX; i++) {
|
||||
if(p_service_names[i]) {
|
||||
BCM_STRNCPY_S(p_buf->p_name[i], p_service_names[i], BTA_SERVICE_NAME_LEN);
|
||||
p_buf->p_name[i][BTA_SERVICE_NAME_LEN] = 0;
|
||||
p_buf->p_name[i][BTA_SERVICE_NAME_LEN] = '\0';
|
||||
} else {
|
||||
p_buf->p_name[i][0] = 0;
|
||||
p_buf->p_name[i][0] = '\0';
|
||||
}
|
||||
}
|
||||
bta_sys_sendmsg(p_buf);
|
||||
|
||||
@@ -798,7 +798,7 @@ void bta_ag_at_hsp_cback(tBTA_AG_SCB *p_scb, UINT16 cmd, UINT8 arg_type,
|
||||
val.hdr.app_id = p_scb->app_id;
|
||||
val.num = (UINT16) int_arg;
|
||||
BCM_STRNCPY_S(val.str, p_arg, BTA_AG_AT_MAX_LEN);
|
||||
val.str[BTA_AG_AT_MAX_LEN] = 0;
|
||||
val.str[BTA_AG_AT_MAX_LEN] = '\0';
|
||||
/* call callback with event */
|
||||
(*bta_ag_cb.p_cback)(bta_ag_hsp_cb_evt[cmd], (tBTA_AG *) &val);
|
||||
}
|
||||
@@ -836,7 +836,7 @@ void bta_ag_at_hfp_cback(tBTA_AG_SCB *p_scb, UINT16 cmd, UINT8 arg_type,
|
||||
val.num = int_arg;
|
||||
bdcpy(val.bd_addr, p_scb->peer_addr);
|
||||
BCM_STRNCPY_S(val.str, p_arg, BTA_AG_AT_MAX_LEN);
|
||||
val.str[BTA_AG_AT_MAX_LEN] = 0;
|
||||
val.str[BTA_AG_AT_MAX_LEN] = '\0';
|
||||
event = bta_ag_hfp_cb_evt[cmd];
|
||||
|
||||
switch (cmd)
|
||||
@@ -1212,7 +1212,7 @@ void bta_ag_at_err_cback(tBTA_AG_SCB *p_scb, BOOLEAN unknown, char *p_arg)
|
||||
val.hdr.app_id = p_scb->app_id;
|
||||
val.num = 0;
|
||||
BCM_STRNCPY_S(val.str, p_arg, BTA_AG_AT_MAX_LEN);
|
||||
val.str[BTA_AG_AT_MAX_LEN] = 0;
|
||||
val.str[BTA_AG_AT_MAX_LEN] = '\0';
|
||||
(*bta_ag_cb.p_cback)(BTA_AG_AT_UNAT_EVT, (tBTA_AG *) &val);
|
||||
} else {
|
||||
bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED);
|
||||
@@ -1357,7 +1357,7 @@ void bta_ag_hfp_result(tBTA_AG_SCB *p_scb, tBTA_AG_API_RESULT *p_result)
|
||||
}
|
||||
}
|
||||
APPL_TRACE_DEBUG("CLIP type :%d", p_result->data.num);
|
||||
p_scb->clip[0] = 0;
|
||||
p_scb->clip[0] = '\0';
|
||||
if (p_result->data.str[0] != 0) {
|
||||
snprintf(p_scb->clip, sizeof(p_scb->clip), "%s,%d", p_result->data.str, p_result->data.num);
|
||||
}
|
||||
|
||||
@@ -142,7 +142,7 @@ void BTA_HfClientRegister(tBTA_SEC sec_mask, tBTA_HF_CLIENT_FEAT features,
|
||||
p_buf->sec_mask = sec_mask;
|
||||
if (p_service_name) {
|
||||
BCM_STRNCPY_S(p_buf->name, p_service_name, BTA_SERVICE_NAME_LEN);
|
||||
p_buf->name[BTA_SERVICE_NAME_LEN] = 0;
|
||||
p_buf->name[BTA_SERVICE_NAME_LEN] = '\0';
|
||||
} else {
|
||||
p_buf->name[0] = '\0';
|
||||
}
|
||||
|
||||
@@ -74,9 +74,6 @@ static void btc_deinit_bluetooth(void)
|
||||
#if BTA_DYNAMIC_MEMORY
|
||||
xSemaphoreTake(deinit_semaphore, BTA_DISABLE_DELAY / portTICK_PERIOD_MS);
|
||||
#endif /* #if BTA_DYNAMIC_MEMORY */
|
||||
#if (BLE_INCLUDED == TRUE)
|
||||
btc_gap_ble_deinit();
|
||||
#endif ///BLE_INCLUDED == TRUE
|
||||
bta_dm_sm_deinit();
|
||||
#if (GATTC_INCLUDED)
|
||||
bta_gattc_deinit();
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
#include "common/bt_defs.h"
|
||||
#include "osi/allocator.h"
|
||||
#include "osi/mutex.h"
|
||||
#include "osi/semaphore.h"
|
||||
#include "osi/thread.h"
|
||||
#include "osi/fixed_queue.h"
|
||||
#include "stack/a2d_api.h"
|
||||
@@ -38,8 +37,6 @@
|
||||
|
||||
#if (BTC_AV_SINK_INCLUDED == TRUE)
|
||||
|
||||
extern osi_thread_t *btc_thread;
|
||||
|
||||
/*****************************************************************************
|
||||
** Constants
|
||||
*****************************************************************************/
|
||||
@@ -82,6 +79,8 @@ enum {
|
||||
#define MAX_OUTPUT_A2DP_SNK_FRAME_QUEUE_SZ (25)
|
||||
#define JITTER_BUFFER_WATER_LEVEL (5)
|
||||
|
||||
#define BTC_A2DP_SNK_DATA_QUEUE_IDX (1)
|
||||
|
||||
typedef struct {
|
||||
uint32_t sig;
|
||||
void *param;
|
||||
@@ -97,7 +96,7 @@ typedef struct {
|
||||
typedef struct {
|
||||
BOOLEAN rx_flush; /* discards any incoming data when true */
|
||||
UINT8 channel_count;
|
||||
osi_sem_t post_sem;
|
||||
struct osi_event *data_ready_event;
|
||||
fixed_queue_t *RxSbcQ;
|
||||
UINT32 sample_rate;
|
||||
} tBTC_A2DP_SINK_CB;
|
||||
@@ -214,7 +213,7 @@ bool btc_a2dp_sink_startup(void)
|
||||
|
||||
APPL_TRACE_EVENT("## A2DP SINK START MEDIA THREAD ##");
|
||||
|
||||
a2dp_sink_local_param.btc_aa_snk_task_hdl = btc_thread;
|
||||
a2dp_sink_local_param.btc_aa_snk_task_hdl = btc_get_current_thread();
|
||||
|
||||
if (btc_a2dp_sink_ctrl(BTC_MEDIA_TASK_SINK_INIT, NULL) == false) {
|
||||
goto error_exit;
|
||||
@@ -294,11 +293,6 @@ void btc_a2dp_sink_on_suspended(tBTA_AV_SUSPEND *p_av)
|
||||
return;
|
||||
}
|
||||
|
||||
static void btc_a2dp_sink_data_post(void)
|
||||
{
|
||||
osi_thread_post(a2dp_sink_local_param.btc_aa_snk_task_hdl, btc_a2dp_sink_data_ready, NULL, 1, OSI_THREAD_MAX_TIMEOUT);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btc_a2dp_sink_clear_track
|
||||
@@ -356,7 +350,6 @@ static void btc_a2dp_sink_data_ready(UNUSED_ATTR void *context)
|
||||
tBT_SBC_HDR *p_msg;
|
||||
int nb_of_msgs_to_process = 0;
|
||||
|
||||
osi_sem_give(&a2dp_sink_local_param.btc_aa_snk_cb.post_sem);
|
||||
if (fixed_queue_is_empty(a2dp_sink_local_param.btc_aa_snk_cb.RxSbcQ)) {
|
||||
APPL_TRACE_DEBUG(" QUE EMPTY ");
|
||||
} else {
|
||||
@@ -380,6 +373,10 @@ static void btc_a2dp_sink_data_ready(UNUSED_ATTR void *context)
|
||||
nb_of_msgs_to_process--;
|
||||
}
|
||||
APPL_TRACE_DEBUG(" Process Frames - ");
|
||||
|
||||
if (!fixed_queue_is_empty(a2dp_sink_local_param.btc_aa_snk_cb.RxSbcQ)) {
|
||||
osi_thread_post_event(a2dp_sink_local_param.btc_aa_snk_cb.data_ready_event, OSI_THREAD_MAX_TIMEOUT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -691,9 +688,7 @@ UINT8 btc_a2dp_sink_enque_buf(BT_HDR *p_pkt)
|
||||
APPL_TRACE_VERBOSE("btc_a2dp_sink_enque_buf %d + \n", p_msg->num_frames_to_be_processed);
|
||||
fixed_queue_enqueue(a2dp_sink_local_param.btc_aa_snk_cb.RxSbcQ, p_msg, FIXED_QUEUE_MAX_TIMEOUT);
|
||||
if (fixed_queue_length(a2dp_sink_local_param.btc_aa_snk_cb.RxSbcQ) >= JITTER_BUFFER_WATER_LEVEL) {
|
||||
if (osi_sem_take(&a2dp_sink_local_param.btc_aa_snk_cb.post_sem, 0) == 0) {
|
||||
btc_a2dp_sink_data_post();
|
||||
}
|
||||
osi_thread_post_event(a2dp_sink_local_param.btc_aa_snk_cb.data_ready_event, OSI_THREAD_MAX_TIMEOUT);
|
||||
}
|
||||
} else {
|
||||
/* let caller deal with a failed allocation */
|
||||
@@ -729,9 +724,12 @@ static void btc_a2dp_sink_thread_init(UNUSED_ATTR void *context)
|
||||
memset(&a2dp_sink_local_param.btc_aa_snk_cb, 0, sizeof(a2dp_sink_local_param.btc_aa_snk_cb));
|
||||
|
||||
btc_a2dp_sink_state = BTC_A2DP_SINK_STATE_ON;
|
||||
if (!a2dp_sink_local_param.btc_aa_snk_cb.post_sem) {
|
||||
osi_sem_new(&a2dp_sink_local_param.btc_aa_snk_cb.post_sem, 1, 1);
|
||||
}
|
||||
|
||||
struct osi_event *data_event = osi_event_create(btc_a2dp_sink_data_ready, NULL);
|
||||
assert (data_event != NULL);
|
||||
osi_event_bind(data_event, a2dp_sink_local_param.btc_aa_snk_task_hdl, BTC_A2DP_SNK_DATA_QUEUE_IDX);
|
||||
a2dp_sink_local_param.btc_aa_snk_cb.data_ready_event = data_event;
|
||||
|
||||
a2dp_sink_local_param.btc_aa_snk_cb.RxSbcQ = fixed_queue_new(QUEUE_SIZE_MAX);
|
||||
|
||||
btc_a2dp_control_init();
|
||||
@@ -749,10 +747,8 @@ static void btc_a2dp_sink_thread_cleanup(UNUSED_ATTR void *context)
|
||||
|
||||
a2dp_sink_local_param.btc_aa_snk_cb.RxSbcQ = NULL;
|
||||
|
||||
if (a2dp_sink_local_param.btc_aa_snk_cb.post_sem) {
|
||||
osi_sem_free(&a2dp_sink_local_param.btc_aa_snk_cb.post_sem);
|
||||
a2dp_sink_local_param.btc_aa_snk_cb.post_sem = NULL;
|
||||
}
|
||||
osi_event_delete(a2dp_sink_local_param.btc_aa_snk_cb.data_ready_event);
|
||||
a2dp_sink_local_param.btc_aa_snk_cb.data_ready_event = NULL;
|
||||
}
|
||||
|
||||
#endif /* BTC_AV_SINK_INCLUDED */
|
||||
|
||||
@@ -42,8 +42,6 @@
|
||||
|
||||
#if BTC_AV_SRC_INCLUDED
|
||||
|
||||
extern osi_thread_t *btc_thread;
|
||||
|
||||
/*****************************************************************************
|
||||
** Constants
|
||||
*****************************************************************************/
|
||||
@@ -118,6 +116,8 @@ enum {
|
||||
#define MAX_OUTPUT_A2DP_FRAME_QUEUE_SZ (5)
|
||||
#define MAX_OUTPUT_A2DP_SRC_FRAME_QUEUE_SZ (27) // 18 for 20ms tick
|
||||
|
||||
#define BTC_A2DP_SRC_DATA_QUEUE_IDX (1)
|
||||
|
||||
typedef struct {
|
||||
uint32_t sig;
|
||||
void *param;
|
||||
@@ -154,6 +154,7 @@ typedef struct {
|
||||
tBTC_AV_MEDIA_FEEDINGS media_feeding;
|
||||
SBC_ENC_PARAMS encoder;
|
||||
osi_alarm_t *media_alarm;
|
||||
struct osi_event *poll_data;
|
||||
} tBTC_A2DP_SOURCE_CB;
|
||||
|
||||
typedef struct {
|
||||
@@ -283,7 +284,7 @@ bool btc_a2dp_source_startup(void)
|
||||
|
||||
APPL_TRACE_EVENT("## A2DP SOURCE START MEDIA THREAD ##");
|
||||
|
||||
a2dp_source_local_param.btc_aa_src_task_hdl = btc_thread;
|
||||
a2dp_source_local_param.btc_aa_src_task_hdl = btc_get_current_thread();
|
||||
|
||||
if (btc_a2dp_source_ctrl(BTC_MEDIA_TASK_INIT, NULL) == false) {
|
||||
goto error_exit;
|
||||
@@ -1532,7 +1533,7 @@ static void btc_a2dp_source_aa_stop_tx(void)
|
||||
static void btc_a2dp_source_alarm_cb(UNUSED_ATTR void *context)
|
||||
{
|
||||
if (a2dp_source_local_param.btc_aa_src_task_hdl) {
|
||||
osi_thread_post(a2dp_source_local_param.btc_aa_src_task_hdl, btc_a2dp_source_handle_timer, NULL, 1, OSI_THREAD_MAX_TIMEOUT);
|
||||
osi_thread_post_event(a2dp_source_local_param.btc_aa_src_cb.poll_data, OSI_THREAD_MAX_TIMEOUT);
|
||||
} else {
|
||||
APPL_TRACE_DEBUG("[%s] A2DP ALREADY FREED", __func__);
|
||||
btc_a2dp_source_aa_stop_tx();
|
||||
@@ -1587,6 +1588,11 @@ static void btc_a2dp_source_thread_init(UNUSED_ATTR void *context)
|
||||
|
||||
btc_a2dp_source_state = BTC_A2DP_SOURCE_STATE_ON;
|
||||
|
||||
struct osi_event *poll_data = osi_event_create(btc_a2dp_source_handle_timer, NULL);
|
||||
assert(poll_data != NULL);
|
||||
osi_event_bind(poll_data, a2dp_source_local_param.btc_aa_src_task_hdl, BTC_A2DP_SRC_DATA_QUEUE_IDX);
|
||||
a2dp_source_local_param.btc_aa_src_cb.poll_data = poll_data;
|
||||
|
||||
a2dp_source_local_param.btc_aa_src_cb.TxAaQ = fixed_queue_new(QUEUE_SIZE_MAX);
|
||||
|
||||
btc_a2dp_control_init();
|
||||
@@ -1602,6 +1608,9 @@ static void btc_a2dp_source_thread_cleanup(UNUSED_ATTR void *context)
|
||||
fixed_queue_free(a2dp_source_local_param.btc_aa_src_cb.TxAaQ, osi_free_func);
|
||||
|
||||
a2dp_source_local_param.btc_aa_src_cb.TxAaQ = NULL;
|
||||
|
||||
osi_event_delete(a2dp_source_local_param.btc_aa_src_cb.poll_data);
|
||||
a2dp_source_local_param.btc_aa_src_cb.poll_data = NULL;
|
||||
}
|
||||
|
||||
#endif /* BTC_AV_INCLUDED */
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
#include "btc/btc_dm.h"
|
||||
#include "btc/btc_util.h"
|
||||
#include "osi/mutex.h"
|
||||
#include "osi/thread.h"
|
||||
#include "osi/pkt_queue.h"
|
||||
#include "esp_bt.h"
|
||||
|
||||
#if (BLE_INCLUDED == TRUE)
|
||||
@@ -48,6 +50,19 @@ static uint16_t btc_adv_list_count = 0;
|
||||
#define BTC_ADV_LIST_MAX_COUNT 200
|
||||
#endif
|
||||
|
||||
#define BTC_GAP_BLE_ADV_RPT_QUEUE_IDX (1)
|
||||
#define BTC_GAP_BLE_ADV_RPT_BATCH_SIZE (10)
|
||||
#define BTC_GAP_BLE_ADV_RPT_QUEUE_LEN_MAX (200)
|
||||
|
||||
#if (BLE_42_FEATURE_SUPPORT == TRUE)
|
||||
typedef struct {
|
||||
struct pkt_queue *adv_rpt_queue;
|
||||
struct osi_event *adv_rpt_ready;
|
||||
} btc_gap_ble_env_t;
|
||||
|
||||
static btc_gap_ble_env_t btc_gap_ble_env;
|
||||
#endif
|
||||
|
||||
static inline void btc_gap_ble_cb_to_app(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param)
|
||||
{
|
||||
esp_gap_ble_cb_t btc_gap_ble_cb = (esp_gap_ble_cb_t)btc_profile_cb_get(BTC_PID_GAP_BLE);
|
||||
@@ -548,8 +563,82 @@ static void btc_ble_set_scan_params(esp_ble_scan_params_t *scan_params, tBLE_SCA
|
||||
}
|
||||
}
|
||||
|
||||
static void btc_gap_ble_adv_pkt_handler(void *arg)
|
||||
{
|
||||
btc_gap_ble_env_t *p_env = &btc_gap_ble_env;
|
||||
size_t pkts_to_process = pkt_queue_length(p_env->adv_rpt_queue);
|
||||
if (pkts_to_process > BTC_GAP_BLE_ADV_RPT_BATCH_SIZE) {
|
||||
pkts_to_process = BTC_GAP_BLE_ADV_RPT_BATCH_SIZE;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < pkts_to_process; i++) {
|
||||
pkt_linked_item_t *linked_pkt = pkt_queue_dequeue(p_env->adv_rpt_queue);
|
||||
if (linked_pkt != NULL) {
|
||||
esp_ble_gap_cb_param_t *param = (esp_ble_gap_cb_param_t *)(linked_pkt->data);
|
||||
btc_gap_ble_cb_to_app(ESP_GAP_BLE_SCAN_RESULT_EVT, param);
|
||||
osi_free(linked_pkt);
|
||||
}
|
||||
}
|
||||
|
||||
if (pkt_queue_length(p_env->adv_rpt_queue) != 0) {
|
||||
osi_thread_post_event(p_env->adv_rpt_ready, OSI_THREAD_MAX_TIMEOUT);
|
||||
}
|
||||
}
|
||||
|
||||
static void btc_process_adv_rpt_pkt(tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARCH *p_data)
|
||||
{
|
||||
#if SCAN_QUEUE_CONGEST_CHECK
|
||||
if(btc_check_queue_is_congest()) {
|
||||
BTC_TRACE_DEBUG("BtcQueue is congested");
|
||||
if(btc_get_adv_list_length() > BTC_ADV_LIST_MAX_LENGTH || btc_adv_list_count > BTC_ADV_LIST_MAX_COUNT) {
|
||||
btc_adv_list_refresh();
|
||||
btc_adv_list_count = 0;
|
||||
}
|
||||
if(btc_check_adv_list(p_data->inq_res.bd_addr, p_data->inq_res.ble_addr_type)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
btc_adv_list_count ++;
|
||||
#endif
|
||||
|
||||
// drop ADV packets if data queue length goes above threshold
|
||||
btc_gap_ble_env_t *p_env = &btc_gap_ble_env;
|
||||
if (pkt_queue_length(p_env->adv_rpt_queue) >= BTC_GAP_BLE_ADV_RPT_QUEUE_LEN_MAX) {
|
||||
return;
|
||||
}
|
||||
|
||||
pkt_linked_item_t *linked_pkt = osi_calloc(BT_PKT_LINKED_HDR_SIZE + sizeof(esp_ble_gap_cb_param_t));
|
||||
if (linked_pkt == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct ble_scan_result_evt_param *scan_rst = (struct ble_scan_result_evt_param *)linked_pkt->data;
|
||||
|
||||
do {
|
||||
scan_rst->search_evt = event;
|
||||
bdcpy(scan_rst->bda, p_data->inq_res.bd_addr);
|
||||
scan_rst->dev_type = p_data->inq_res.device_type;
|
||||
scan_rst->rssi = p_data->inq_res.rssi;
|
||||
scan_rst->ble_addr_type = p_data->inq_res.ble_addr_type;
|
||||
scan_rst->ble_evt_type = p_data->inq_res.ble_evt_type;
|
||||
scan_rst->flag = p_data->inq_res.flag;
|
||||
scan_rst->num_resps = 1;
|
||||
scan_rst->adv_data_len = p_data->inq_res.adv_data_len;
|
||||
scan_rst->scan_rsp_len = p_data->inq_res.scan_rsp_len;
|
||||
memcpy(scan_rst->ble_adv, p_data->inq_res.p_eir, sizeof(scan_rst->ble_adv));
|
||||
} while (0);
|
||||
|
||||
pkt_queue_enqueue(p_env->adv_rpt_queue, linked_pkt);
|
||||
osi_thread_post_event(p_env->adv_rpt_ready, OSI_THREAD_MAX_TIMEOUT);
|
||||
}
|
||||
|
||||
static void btc_search_callback(tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARCH *p_data)
|
||||
{
|
||||
if (event == BTA_DM_INQ_RES_EVT) {
|
||||
btc_process_adv_rpt_pkt(event, p_data);
|
||||
return;
|
||||
}
|
||||
|
||||
esp_ble_gap_cb_param_t param;
|
||||
btc_msg_t msg = {0};
|
||||
|
||||
@@ -559,32 +648,8 @@ static void btc_search_callback(tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARCH *p_data
|
||||
|
||||
param.scan_rst.search_evt = event;
|
||||
switch (event) {
|
||||
case BTA_DM_INQ_RES_EVT: {
|
||||
#if SCAN_QUEUE_CONGEST_CHECK
|
||||
if(btc_check_queue_is_congest()) {
|
||||
BTC_TRACE_DEBUG("BtcQueue is congested");
|
||||
if(btc_get_adv_list_length() > BTC_ADV_LIST_MAX_LENGTH || btc_adv_list_count > BTC_ADV_LIST_MAX_COUNT) {
|
||||
btc_adv_list_refresh();
|
||||
btc_adv_list_count = 0;
|
||||
}
|
||||
if(btc_check_adv_list(p_data->inq_res.bd_addr, p_data->inq_res.ble_addr_type)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
btc_adv_list_count ++;
|
||||
#endif
|
||||
bdcpy(param.scan_rst.bda, p_data->inq_res.bd_addr);
|
||||
param.scan_rst.dev_type = p_data->inq_res.device_type;
|
||||
param.scan_rst.rssi = p_data->inq_res.rssi;
|
||||
param.scan_rst.ble_addr_type = p_data->inq_res.ble_addr_type;
|
||||
param.scan_rst.ble_evt_type = p_data->inq_res.ble_evt_type;
|
||||
param.scan_rst.flag = p_data->inq_res.flag;
|
||||
param.scan_rst.num_resps = 1;
|
||||
param.scan_rst.adv_data_len = p_data->inq_res.adv_data_len;
|
||||
param.scan_rst.scan_rsp_len = p_data->inq_res.scan_rsp_len;
|
||||
memcpy(param.scan_rst.ble_adv, p_data->inq_res.p_eir, sizeof(param.scan_rst.ble_adv));
|
||||
case BTA_DM_INQ_RES_EVT:
|
||||
break;
|
||||
}
|
||||
case BTA_DM_INQ_CMPL_EVT: {
|
||||
param.scan_rst.num_resps = p_data->inq_cmpl.num_resps;
|
||||
BTC_TRACE_DEBUG("%s BLE observe complete. Num Resp %d\n", __FUNCTION__, p_data->inq_cmpl.num_resps);
|
||||
@@ -1841,9 +1906,31 @@ void btc_gap_callback_init(void)
|
||||
#endif // #if (BLE_50_FEATURE_SUPPORT == TRUE)
|
||||
}
|
||||
|
||||
bool btc_gap_ble_init(void)
|
||||
{
|
||||
#if (BLE_42_FEATURE_SUPPORT == TRUE)
|
||||
btc_gap_ble_env_t *p_env = &btc_gap_ble_env;
|
||||
p_env->adv_rpt_queue = pkt_queue_create();
|
||||
assert(p_env->adv_rpt_queue != NULL);
|
||||
|
||||
p_env->adv_rpt_ready = osi_event_create(btc_gap_ble_adv_pkt_handler, NULL);
|
||||
assert(p_env->adv_rpt_ready != NULL);
|
||||
osi_event_bind(p_env->adv_rpt_ready, btc_get_current_thread(), BTC_GAP_BLE_ADV_RPT_QUEUE_IDX);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
void btc_gap_ble_deinit(void)
|
||||
{
|
||||
#if (BLE_42_FEATURE_SUPPORT == TRUE)
|
||||
#if (BLE_42_FEATURE_SUPPORT == TRUE)
|
||||
btc_gap_ble_env_t *p_env = &btc_gap_ble_env;
|
||||
|
||||
osi_event_delete(p_env->adv_rpt_ready);
|
||||
p_env->adv_rpt_ready = NULL;
|
||||
|
||||
pkt_queue_destroy(p_env->adv_rpt_queue, NULL);
|
||||
p_env->adv_rpt_queue = NULL;
|
||||
|
||||
btc_cleanup_adv_data(&gl_bta_adv_data);
|
||||
btc_cleanup_adv_data(&gl_bta_scan_rsp_data);
|
||||
#endif // #if (BLE_42_FEATURE_SUPPORT == TRUE)
|
||||
|
||||
@@ -345,6 +345,7 @@ void btc_gap_ble_arg_deep_free(btc_msg_t *msg);
|
||||
void btc_gap_ble_cb_deep_free(btc_msg_t *msg);
|
||||
void btc_gap_ble_cb_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src);
|
||||
void btc_gap_callback_init(void);
|
||||
bool btc_gap_ble_init(void);
|
||||
void btc_gap_ble_deinit(void);
|
||||
void btc_adv_list_init(void);
|
||||
void btc_adv_list_deinit(void);
|
||||
|
||||
@@ -19,24 +19,38 @@
|
||||
#include "common/bt_defs.h"
|
||||
#include "common/bt_trace.h"
|
||||
#include "stack/bt_types.h"
|
||||
#include "osi/fixed_queue.h"
|
||||
#include "hci/hci_hal.h"
|
||||
#include "hci/hci_internals.h"
|
||||
#include "hci/hci_layer.h"
|
||||
#include "osi/thread.h"
|
||||
#include "osi/pkt_queue.h"
|
||||
#if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE)
|
||||
#include "osi/mutex.h"
|
||||
#include "osi/alarm.h"
|
||||
#endif
|
||||
#include "esp_bt.h"
|
||||
#include "stack/hcimsgs.h"
|
||||
|
||||
#if SOC_ESP_NIMBLE_CONTROLLER
|
||||
#include "nimble/ble_hci_trans.h"
|
||||
#endif
|
||||
|
||||
#if (C2H_FLOW_CONTROL_INCLUDED == TRUE)
|
||||
#include "l2c_int.h"
|
||||
#endif ///C2H_FLOW_CONTROL_INCLUDED == TRUE
|
||||
#include "stack/hcimsgs.h"
|
||||
#if SOC_ESP_NIMBLE_CONTROLLER
|
||||
#include "nimble/ble_hci_trans.h"
|
||||
#endif
|
||||
#define HCI_HAL_SERIAL_BUFFER_SIZE 1026
|
||||
|
||||
#define HCI_BLE_EVENT 0x3e
|
||||
#define PACKET_TYPE_TO_INBOUND_INDEX(type) ((type) - 2)
|
||||
#define PACKET_TYPE_TO_INDEX(type) ((type) - 1)
|
||||
#define HCI_UPSTREAM_DATA_QUEUE_IDX (1)
|
||||
#if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE)
|
||||
#define HCI_BLE_ADV_MIN_CREDITS_TO_RELEASE (10)
|
||||
#define HCI_ADV_FLOW_MONITOR_PERIOD_MS (500)
|
||||
#else
|
||||
#define HCI_HAL_BLE_ADV_RPT_QUEUE_LEN_MAX (200)
|
||||
#endif
|
||||
|
||||
extern bool BTU_check_queue_is_congest(void);
|
||||
|
||||
|
||||
@@ -55,64 +69,102 @@ static const uint16_t outbound_event_types[] = {
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
size_t buffer_size;
|
||||
fixed_queue_t *rx_q;
|
||||
uint16_t adv_free_num;
|
||||
struct pkt_queue *adv_rpt_q;
|
||||
#if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE)
|
||||
osi_mutex_t adv_flow_lock;
|
||||
osi_alarm_t *adv_flow_monitor;
|
||||
int adv_credits;
|
||||
int adv_credits_to_release;
|
||||
pkt_linked_item_t *adv_fc_cmd_buf;
|
||||
bool cmd_buf_in_use;
|
||||
#endif
|
||||
hci_hal_callbacks_t *callbacks;
|
||||
osi_thread_t *hci_h4_thread;
|
||||
struct osi_event *upstream_data_ready;
|
||||
} hci_hal_env_t;
|
||||
|
||||
|
||||
static hci_hal_env_t hci_hal_env;
|
||||
static const hci_hal_t interface;
|
||||
static const hci_hal_callbacks_t *callbacks;
|
||||
static const esp_vhci_host_callback_t vhci_host_cb;
|
||||
static osi_thread_t *hci_h4_thread;
|
||||
|
||||
static void host_send_pkt_available_cb(void);
|
||||
static int host_recv_pkt_cb(uint8_t *data, uint16_t len);
|
||||
static void hci_hal_h4_hdl_rx_packet(BT_HDR *packet);
|
||||
static void hci_hal_h4_hdl_rx_adv_rpt(pkt_linked_item_t *linked_pkt);
|
||||
static void hci_upstream_data_handler(void *arg);
|
||||
static bool hci_upstream_data_post(uint32_t timeout);
|
||||
|
||||
static void hci_hal_h4_rx_handler(void *arg);
|
||||
static void event_uart_has_bytes(fixed_queue_t *queue);
|
||||
#if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE)
|
||||
static void hci_adv_flow_monitor(void *context);
|
||||
static void hci_adv_flow_cmd_free_cb(pkt_linked_item_t *linked_pkt);
|
||||
#endif
|
||||
|
||||
|
||||
static void hci_hal_env_init(
|
||||
size_t buffer_size,
|
||||
size_t max_buffer_count)
|
||||
static bool hci_hal_env_init(const hci_hal_callbacks_t *upper_callbacks, osi_thread_t *task_thread)
|
||||
{
|
||||
assert(buffer_size > 0);
|
||||
assert(max_buffer_count > 0);
|
||||
assert(upper_callbacks != NULL);
|
||||
assert(task_thread != NULL);
|
||||
|
||||
hci_hal_env.buffer_size = buffer_size;
|
||||
hci_hal_env.adv_free_num = 0;
|
||||
hci_hal_env.hci_h4_thread = task_thread;
|
||||
hci_hal_env.callbacks = (hci_hal_callbacks_t *)upper_callbacks;
|
||||
|
||||
hci_hal_env.rx_q = fixed_queue_new(max_buffer_count);
|
||||
if (hci_hal_env.rx_q) {
|
||||
fixed_queue_register_dequeue(hci_hal_env.rx_q, event_uart_has_bytes);
|
||||
} else {
|
||||
HCI_TRACE_ERROR("%s unable to create rx queue.\n", __func__);
|
||||
}
|
||||
#if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE)
|
||||
hci_hal_env.adv_fc_cmd_buf = osi_calloc(HCI_CMD_LINKED_BUF_SIZE(HCIC_PARAM_SIZE_BLE_UPDATE_ADV_FLOW_CONTROL));
|
||||
assert(hci_hal_env.adv_fc_cmd_buf != NULL);
|
||||
osi_mutex_new(&hci_hal_env.adv_flow_lock);
|
||||
osi_mutex_lock(&hci_hal_env.adv_flow_lock, OSI_MUTEX_MAX_TIMEOUT);
|
||||
hci_hal_env.adv_credits = BLE_ADV_REPORT_FLOW_CONTROL_NUM;
|
||||
hci_hal_env.adv_credits_to_release = 0;
|
||||
hci_hal_env.cmd_buf_in_use = false;
|
||||
osi_mutex_unlock(&hci_hal_env.adv_flow_lock);
|
||||
hci_hal_env.adv_flow_monitor = osi_alarm_new("adv_fc_mon", hci_adv_flow_monitor, NULL, HCI_ADV_FLOW_MONITOR_PERIOD_MS);
|
||||
assert (hci_hal_env.adv_flow_monitor != NULL);
|
||||
#endif
|
||||
|
||||
return;
|
||||
hci_hal_env.rx_q = fixed_queue_new(QUEUE_SIZE_MAX);
|
||||
assert(hci_hal_env.rx_q != NULL);
|
||||
|
||||
hci_hal_env.adv_rpt_q = pkt_queue_create();
|
||||
assert(hci_hal_env.adv_rpt_q != NULL);
|
||||
|
||||
struct osi_event *event = osi_event_create(hci_upstream_data_handler, NULL);
|
||||
assert(event != NULL);
|
||||
hci_hal_env.upstream_data_ready = event;
|
||||
osi_event_bind(hci_hal_env.upstream_data_ready, hci_hal_env.hci_h4_thread, HCI_UPSTREAM_DATA_QUEUE_IDX);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void hci_hal_env_deinit(void)
|
||||
{
|
||||
fixed_queue_free(hci_hal_env.rx_q, osi_free_func);
|
||||
hci_hal_env.rx_q = NULL;
|
||||
|
||||
pkt_queue_destroy(hci_hal_env.adv_rpt_q, NULL);
|
||||
hci_hal_env.adv_rpt_q = NULL;
|
||||
|
||||
osi_event_delete(hci_hal_env.upstream_data_ready);
|
||||
hci_hal_env.upstream_data_ready = NULL;
|
||||
|
||||
#if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE)
|
||||
hci_hal_env.cmd_buf_in_use = true;
|
||||
osi_alarm_cancel(hci_hal_env.adv_flow_monitor);
|
||||
osi_alarm_free(hci_hal_env.adv_flow_monitor);
|
||||
hci_hal_env.adv_flow_monitor = NULL;
|
||||
osi_mutex_free(&hci_hal_env.adv_flow_lock);
|
||||
osi_free(hci_hal_env.adv_fc_cmd_buf);
|
||||
hci_hal_env.adv_fc_cmd_buf = NULL;
|
||||
#endif
|
||||
|
||||
hci_hal_env.hci_h4_thread = NULL;
|
||||
|
||||
memset(&hci_hal_env, 0, sizeof(hci_hal_env_t));
|
||||
}
|
||||
|
||||
static bool hal_open(const hci_hal_callbacks_t *upper_callbacks, void *task_thread)
|
||||
{
|
||||
assert(upper_callbacks != NULL);
|
||||
assert(task_thread != NULL);
|
||||
|
||||
callbacks = upper_callbacks;
|
||||
#if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE)
|
||||
hci_hal_env_init(HCI_HAL_SERIAL_BUFFER_SIZE, BLE_ADV_REPORT_FLOW_CONTROL_NUM + L2CAP_HOST_FC_ACL_BUFS + QUEUE_SIZE_MAX); // adv flow control num + ACL flow control num + hci cmd numeber
|
||||
#else
|
||||
hci_hal_env_init(HCI_HAL_SERIAL_BUFFER_SIZE, QUEUE_SIZE_MAX);
|
||||
#endif
|
||||
|
||||
hci_h4_thread = (osi_thread_t *)task_thread;
|
||||
hci_hal_env_init(upper_callbacks, (osi_thread_t *)task_thread);
|
||||
|
||||
//register vhci host cb
|
||||
if (esp_vhci_host_register_callback(&vhci_host_cb) != ESP_OK) {
|
||||
@@ -125,8 +177,6 @@ static bool hal_open(const hci_hal_callbacks_t *upper_callbacks, void *task_thre
|
||||
static void hal_close(void)
|
||||
{
|
||||
hci_hal_env_deinit();
|
||||
|
||||
hci_h4_thread = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -166,14 +216,40 @@ static uint16_t transmit_data(serial_data_type_t type,
|
||||
}
|
||||
|
||||
// Internal functions
|
||||
static void hci_hal_h4_rx_handler(void *arg)
|
||||
static void hci_upstream_data_handler(void *arg)
|
||||
{
|
||||
fixed_queue_process(hci_hal_env.rx_q);
|
||||
fixed_queue_t *rx_q = hci_hal_env.rx_q;
|
||||
struct pkt_queue *adv_rpt_q = hci_hal_env.adv_rpt_q;
|
||||
size_t pkts_to_process;
|
||||
|
||||
do {
|
||||
pkts_to_process = fixed_queue_length(rx_q);
|
||||
for (size_t i = 0; i < pkts_to_process; i++) {
|
||||
BT_HDR *packet = fixed_queue_dequeue(rx_q, 0);
|
||||
if (packet != NULL) {
|
||||
hci_hal_h4_hdl_rx_packet(packet);
|
||||
}
|
||||
}
|
||||
} while (0);
|
||||
|
||||
do {
|
||||
pkts_to_process = pkt_queue_length(adv_rpt_q);
|
||||
for (size_t i = 0; i < pkts_to_process; i++) {
|
||||
pkt_linked_item_t *linked_pkt = pkt_queue_dequeue(adv_rpt_q);
|
||||
if (linked_pkt != NULL) {
|
||||
hci_hal_h4_hdl_rx_adv_rpt(linked_pkt);
|
||||
}
|
||||
}
|
||||
} while (0);
|
||||
|
||||
if (!fixed_queue_is_empty(rx_q) || pkt_queue_length(adv_rpt_q) > 0) {
|
||||
hci_upstream_data_post(OSI_THREAD_MAX_TIMEOUT);
|
||||
}
|
||||
}
|
||||
|
||||
bool hci_hal_h4_task_post(uint32_t timeout)
|
||||
static bool hci_upstream_data_post(uint32_t timeout)
|
||||
{
|
||||
return osi_thread_post(hci_h4_thread, hci_hal_h4_rx_handler, NULL, 1, timeout);
|
||||
return osi_thread_post_event(hci_hal_env.upstream_data_ready, timeout);
|
||||
}
|
||||
|
||||
#if (C2H_FLOW_CONTROL_INCLUDED == TRUE)
|
||||
@@ -192,13 +268,13 @@ static void hci_packet_complete(BT_HDR *packet){
|
||||
}
|
||||
#endif ///C2H_FLOW_CONTROL_INCLUDED == TRUE
|
||||
|
||||
bool host_recv_adv_packet(BT_HDR *packet)
|
||||
bool host_recv_adv_packet(uint8_t *packet)
|
||||
{
|
||||
assert(packet);
|
||||
if(packet->data[0] == DATA_TYPE_EVENT && packet->data[1] == HCI_BLE_EVENT) {
|
||||
if(packet->data[3] == HCI_BLE_ADV_PKT_RPT_EVT
|
||||
if(packet[0] == DATA_TYPE_EVENT && packet[1] == HCI_BLE_EVENT) {
|
||||
if(packet[3] == HCI_BLE_ADV_PKT_RPT_EVT || packet[3] == HCI_BLE_DIRECT_ADV_EVT
|
||||
#if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE)
|
||||
|| packet->data[3] == HCI_BLE_ADV_DISCARD_REPORT_EVT
|
||||
|| packet[3] == HCI_BLE_ADV_DISCARD_REPORT_EVT
|
||||
#endif
|
||||
) {
|
||||
return true;
|
||||
@@ -208,21 +284,128 @@ bool host_recv_adv_packet(BT_HDR *packet)
|
||||
}
|
||||
|
||||
#if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE)
|
||||
static void hci_update_adv_report_flow_control(BT_HDR *packet)
|
||||
static void hci_adv_flow_monitor(void *context)
|
||||
{
|
||||
// this is adv packet
|
||||
if(host_recv_adv_packet(packet)) {
|
||||
// update adv free number
|
||||
hci_hal_env.adv_free_num ++;
|
||||
if (esp_vhci_host_check_send_available()){
|
||||
// send hci cmd
|
||||
btsnd_hcic_ble_update_adv_report_flow_control(hci_hal_env.adv_free_num);
|
||||
hci_hal_env.adv_free_num = 0;
|
||||
hci_adv_credits_force_release(0);
|
||||
}
|
||||
|
||||
static void hci_adv_credits_consumed(uint16_t num)
|
||||
{
|
||||
osi_mutex_lock(&hci_hal_env.adv_flow_lock, OSI_MUTEX_MAX_TIMEOUT);
|
||||
assert(hci_hal_env.adv_credits >= num);
|
||||
hci_hal_env.adv_credits -= num;
|
||||
osi_mutex_unlock(&hci_hal_env.adv_flow_lock);
|
||||
}
|
||||
|
||||
int hci_adv_credits_prep_to_release(uint16_t num)
|
||||
{
|
||||
if (num == 0) {
|
||||
return hci_hal_env.adv_credits_to_release;
|
||||
}
|
||||
|
||||
osi_mutex_lock(&hci_hal_env.adv_flow_lock, OSI_MUTEX_MAX_TIMEOUT);
|
||||
int credits_to_release = hci_hal_env.adv_credits_to_release + num;
|
||||
assert(hci_hal_env.adv_credits_to_release <= BLE_ADV_REPORT_FLOW_CONTROL_NUM);
|
||||
hci_hal_env.adv_credits_to_release = credits_to_release;
|
||||
osi_mutex_unlock(&hci_hal_env.adv_flow_lock);
|
||||
|
||||
if (credits_to_release == num && num != 0) {
|
||||
osi_alarm_cancel(hci_hal_env.adv_flow_monitor);
|
||||
osi_alarm_set(hci_hal_env.adv_flow_monitor, HCI_ADV_FLOW_MONITOR_PERIOD_MS);
|
||||
}
|
||||
return credits_to_release;
|
||||
}
|
||||
|
||||
static int hci_adv_credits_release(void)
|
||||
{
|
||||
osi_mutex_lock(&hci_hal_env.adv_flow_lock, OSI_MUTEX_MAX_TIMEOUT);
|
||||
int credits_released = hci_hal_env.adv_credits_to_release;
|
||||
hci_hal_env.adv_credits += credits_released;
|
||||
hci_hal_env.adv_credits_to_release -= credits_released;
|
||||
assert(hci_hal_env.adv_credits <= BLE_ADV_REPORT_FLOW_CONTROL_NUM);
|
||||
assert(hci_hal_env.adv_credits_to_release >= 0);
|
||||
osi_mutex_unlock(&hci_hal_env.adv_flow_lock);
|
||||
|
||||
if (hci_hal_env.adv_credits_to_release == 0) {
|
||||
osi_alarm_cancel(hci_hal_env.adv_flow_monitor);
|
||||
}
|
||||
return credits_released;
|
||||
}
|
||||
|
||||
static int hci_adv_credits_release_rollback(uint16_t num)
|
||||
{
|
||||
osi_mutex_lock(&hci_hal_env.adv_flow_lock, OSI_MUTEX_MAX_TIMEOUT);
|
||||
hci_hal_env.adv_credits -= num;
|
||||
hci_hal_env.adv_credits_to_release += num;
|
||||
assert(hci_hal_env.adv_credits >=0);
|
||||
assert(hci_hal_env.adv_credits_to_release <= BLE_ADV_REPORT_FLOW_CONTROL_NUM);
|
||||
osi_mutex_unlock(&hci_hal_env.adv_flow_lock);
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
static void hci_adv_flow_cmd_free_cb(pkt_linked_item_t *linked_pkt)
|
||||
{
|
||||
osi_mutex_lock(&hci_hal_env.adv_flow_lock, OSI_MUTEX_MAX_TIMEOUT);
|
||||
hci_hal_env.cmd_buf_in_use = false;
|
||||
osi_mutex_unlock(&hci_hal_env.adv_flow_lock);
|
||||
hci_adv_credits_try_release(0);
|
||||
}
|
||||
|
||||
bool hci_adv_flow_try_send_command(uint16_t credits_released)
|
||||
{
|
||||
bool sent = false;
|
||||
bool use_static_buffer = false;
|
||||
|
||||
/* first try using static buffer, then dynamic buffer */
|
||||
if (!hci_hal_env.cmd_buf_in_use) {
|
||||
osi_mutex_lock(&hci_hal_env.adv_flow_lock, OSI_MUTEX_MAX_TIMEOUT);
|
||||
if (!hci_hal_env.cmd_buf_in_use) {
|
||||
hci_hal_env.cmd_buf_in_use = true;
|
||||
use_static_buffer = true;
|
||||
}
|
||||
osi_mutex_unlock(&hci_hal_env.adv_flow_lock);
|
||||
}
|
||||
|
||||
if (use_static_buffer) {
|
||||
hci_cmd_metadata_t *metadata = (hci_cmd_metadata_t *)(hci_hal_env.adv_fc_cmd_buf->data);
|
||||
BT_HDR *static_buffer = &metadata->command;
|
||||
metadata->command_free_cb = hci_adv_flow_cmd_free_cb;
|
||||
sent = btsnd_hcic_ble_update_adv_report_flow_control(credits_released, static_buffer);
|
||||
} else {
|
||||
sent = btsnd_hcic_ble_update_adv_report_flow_control(credits_released, NULL);
|
||||
}
|
||||
|
||||
return sent;
|
||||
}
|
||||
|
||||
int hci_adv_credits_try_release(uint16_t num)
|
||||
{
|
||||
int credits_released = 0;
|
||||
if (hci_adv_credits_prep_to_release(num) >= HCI_BLE_ADV_MIN_CREDITS_TO_RELEASE) {
|
||||
credits_released = hci_adv_credits_release();
|
||||
if (credits_released > 0) {
|
||||
if (!hci_adv_flow_try_send_command(credits_released)) {
|
||||
hci_adv_credits_release_rollback(credits_released);
|
||||
}
|
||||
} else {
|
||||
//do nothing
|
||||
assert (credits_released == 0);
|
||||
}
|
||||
}
|
||||
return credits_released;
|
||||
}
|
||||
|
||||
int hci_adv_credits_force_release(uint16_t num)
|
||||
{
|
||||
hci_adv_credits_prep_to_release(num);
|
||||
int credits_released = hci_adv_credits_release();
|
||||
if (credits_released > 0) {
|
||||
if (!hci_adv_flow_try_send_command(credits_released)) {
|
||||
hci_adv_credits_release_rollback(credits_released);
|
||||
}
|
||||
}
|
||||
|
||||
return credits_released;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -283,61 +466,125 @@ static void hci_hal_h4_hdl_rx_packet(BT_HDR *packet)
|
||||
return;
|
||||
}
|
||||
|
||||
#if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE)
|
||||
hci_update_adv_report_flow_control(packet);
|
||||
#endif
|
||||
|
||||
#if SCAN_QUEUE_CONGEST_CHECK
|
||||
if(BTU_check_queue_is_congest() && host_recv_adv_packet(packet)) {
|
||||
HCI_TRACE_DEBUG("BtuQueue is congested");
|
||||
osi_free(packet);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
packet->event = outbound_event_types[PACKET_TYPE_TO_INDEX(type)];
|
||||
callbacks->packet_ready(packet);
|
||||
hci_hal_env.callbacks->packet_ready(packet);
|
||||
}
|
||||
|
||||
static void event_uart_has_bytes(fixed_queue_t *queue)
|
||||
static void hci_hal_h4_hdl_rx_adv_rpt(pkt_linked_item_t *linked_pkt)
|
||||
{
|
||||
BT_HDR *packet;
|
||||
while (!fixed_queue_is_empty(queue)) {
|
||||
packet = fixed_queue_dequeue(queue, FIXED_QUEUE_MAX_TIMEOUT);
|
||||
hci_hal_h4_hdl_rx_packet(packet);
|
||||
uint8_t type;
|
||||
uint8_t hdr_size;
|
||||
uint16_t length;
|
||||
uint8_t *stream = NULL;
|
||||
|
||||
if (!linked_pkt) {
|
||||
return;
|
||||
}
|
||||
|
||||
BT_HDR* packet = (BT_HDR *)linked_pkt->data;
|
||||
stream = packet->data + packet->offset;
|
||||
|
||||
assert(host_recv_adv_packet(stream) == true);
|
||||
|
||||
STREAM_TO_UINT8(type, stream);
|
||||
packet->offset++;
|
||||
packet->len--;
|
||||
hdr_size = preamble_sizes[type - 1];
|
||||
|
||||
if (packet->len < hdr_size) {
|
||||
HCI_TRACE_ERROR("Wrong packet length type=%d pkt_len=%d hdr_len=%d",
|
||||
type, packet->len, hdr_size);
|
||||
goto _discard_packet;
|
||||
}
|
||||
|
||||
stream += hdr_size - 1;
|
||||
STREAM_TO_UINT8(length, stream);
|
||||
if ((length + hdr_size) != packet->len) {
|
||||
HCI_TRACE_ERROR("Wrong packet length type=%d hdr_len=%d pd_len=%d "
|
||||
"pkt_len=%d", type, hdr_size, length, packet->len);
|
||||
goto _discard_packet;
|
||||
}
|
||||
|
||||
#if SCAN_QUEUE_CONGEST_CHECK
|
||||
if(BTU_check_queue_is_congest()) {
|
||||
HCI_TRACE_DEBUG("BtuQueue is congested");
|
||||
goto _discard_packet;
|
||||
}
|
||||
#endif
|
||||
|
||||
packet->event = outbound_event_types[PACKET_TYPE_TO_INDEX(type)];
|
||||
hci_hal_env.callbacks->adv_rpt_ready(linked_pkt);
|
||||
|
||||
return;
|
||||
|
||||
_discard_packet:
|
||||
osi_free(linked_pkt);
|
||||
#if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE)
|
||||
hci_adv_credits_prep_to_release(1);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void host_send_pkt_available_cb(void)
|
||||
{
|
||||
//Controller rx cache buffer is ready for receiving new host packet
|
||||
//Just Call Host main thread task to process pending packets.
|
||||
hci_host_task_post(OSI_THREAD_MAX_TIMEOUT);
|
||||
hci_downstream_data_post(OSI_THREAD_MAX_TIMEOUT);
|
||||
}
|
||||
|
||||
static int host_recv_pkt_cb(uint8_t *data, uint16_t len)
|
||||
{
|
||||
//Target has packet to host, malloc new buffer for packet
|
||||
BT_HDR *pkt;
|
||||
BT_HDR *pkt = NULL;
|
||||
pkt_linked_item_t *linked_pkt = NULL;
|
||||
size_t pkt_size;
|
||||
|
||||
if (hci_hal_env.rx_q == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
pkt_size = BT_HDR_SIZE + len;
|
||||
pkt = (BT_HDR *) osi_calloc(pkt_size);
|
||||
bool is_adv_rpt = host_recv_adv_packet(data);
|
||||
|
||||
if (!pkt) {
|
||||
HCI_TRACE_ERROR("%s couldn't aquire memory for inbound data buffer.\n", __func__);
|
||||
return -1;
|
||||
if (!is_adv_rpt) {
|
||||
pkt_size = BT_HDR_SIZE + len;
|
||||
pkt = (BT_HDR *) osi_calloc(pkt_size);
|
||||
if (!pkt) {
|
||||
HCI_TRACE_ERROR("%s couldn't aquire memory for inbound data buffer.\n", __func__);
|
||||
assert(0);
|
||||
}
|
||||
|
||||
pkt->offset = 0;
|
||||
pkt->len = len;
|
||||
pkt->layer_specific = 0;
|
||||
memcpy(pkt->data, data, len);
|
||||
fixed_queue_enqueue(hci_hal_env.rx_q, pkt, FIXED_QUEUE_MAX_TIMEOUT);
|
||||
} else {
|
||||
#if !BLE_ADV_REPORT_FLOW_CONTROL
|
||||
// drop the packets if pkt_queue length goes beyond upper limit
|
||||
if (pkt_queue_length(hci_hal_env.adv_rpt_q) > HCI_HAL_BLE_ADV_RPT_QUEUE_LEN_MAX) {
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
pkt_size = BT_PKT_LINKED_HDR_SIZE + BT_HDR_SIZE + len;
|
||||
linked_pkt = (pkt_linked_item_t *) osi_calloc(pkt_size);
|
||||
if (!linked_pkt) {
|
||||
#if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE)
|
||||
hci_adv_credits_consumed(1);
|
||||
hci_adv_credits_prep_to_release(1);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
pkt = (BT_HDR *)linked_pkt->data;
|
||||
pkt->offset = 0;
|
||||
pkt->len = len;
|
||||
pkt->layer_specific = 0;
|
||||
memcpy(pkt->data, data, len);
|
||||
pkt_queue_enqueue(hci_hal_env.adv_rpt_q, linked_pkt);
|
||||
#if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE)
|
||||
hci_adv_credits_consumed(1);
|
||||
#endif
|
||||
}
|
||||
pkt->offset = 0;
|
||||
pkt->len = len;
|
||||
pkt->layer_specific = 0;
|
||||
memcpy(pkt->data, data, len);
|
||||
fixed_queue_enqueue(hci_hal_env.rx_q, pkt, FIXED_QUEUE_MAX_TIMEOUT);
|
||||
hci_hal_h4_task_post(0);
|
||||
|
||||
hci_upstream_data_post(OSI_THREAD_MAX_TIMEOUT);
|
||||
|
||||
BTTRC_DUMP_BUFFER("Recv Pkt", pkt->data, len);
|
||||
|
||||
|
||||
@@ -35,20 +35,17 @@
|
||||
#include "osi/thread.h"
|
||||
#include "osi/mutex.h"
|
||||
#include "osi/fixed_queue.h"
|
||||
#include "osi/fixed_pkt_queue.h"
|
||||
|
||||
#define HCI_HOST_TASK_PINNED_TO_CORE (TASK_PINNED_TO_CORE)
|
||||
#define HCI_HOST_TASK_STACK_SIZE (2048 + BT_TASK_EXTRA_STACK_SIZE)
|
||||
#define HCI_HOST_TASK_PRIO (BT_TASK_MAX_PRIORITIES - 3)
|
||||
#define HCI_HOST_TASK_NAME "hciT"
|
||||
#define HCI_HOST_TASK_WORKQUEUE_NUM (2)
|
||||
#define HCI_HOST_TASK_WORKQUEUE0_LEN (1) // for downstream datapath
|
||||
#define HCI_HOST_TASK_WORKQUEUE1_LEN (1) // for upstream datapath
|
||||
|
||||
typedef struct {
|
||||
uint16_t opcode;
|
||||
future_t *complete_future;
|
||||
command_complete_cb complete_callback;
|
||||
command_status_cb status_callback;
|
||||
void *context;
|
||||
BT_HDR *command;
|
||||
} waiting_command_t;
|
||||
#define HCI_DOWNSTREAM_DATA_QUEUE_IDX (0)
|
||||
|
||||
typedef struct {
|
||||
bool timer_is_set;
|
||||
@@ -59,9 +56,9 @@ typedef struct {
|
||||
|
||||
typedef struct {
|
||||
int command_credits;
|
||||
fixed_queue_t *command_queue;
|
||||
fixed_pkt_queue_t *command_queue;
|
||||
fixed_queue_t *packet_queue;
|
||||
|
||||
struct osi_event *downstream_data_ready;
|
||||
command_waiting_response_t cmd_waiting_q;
|
||||
|
||||
/*
|
||||
@@ -89,16 +86,17 @@ static const packet_fragmenter_callbacks_t packet_fragmenter_callbacks;
|
||||
|
||||
static int hci_layer_init_env(void);
|
||||
static void hci_layer_deinit_env(void);
|
||||
static void hci_host_thread_handler(void *arg);
|
||||
static void event_command_ready(fixed_queue_t *queue);
|
||||
static void hci_downstream_data_handler(void *arg);
|
||||
static void event_command_ready(fixed_pkt_queue_t *queue);
|
||||
static void event_packet_ready(fixed_queue_t *queue);
|
||||
static void restart_command_waiting_response_timer(command_waiting_response_t *cmd_wait_q);
|
||||
static void command_timed_out(void *context);
|
||||
static void hal_says_packet_ready(BT_HDR *packet);
|
||||
static bool filter_incoming_event(BT_HDR *packet);
|
||||
static serial_data_type_t event_to_data_type(uint16_t event);
|
||||
static waiting_command_t *get_waiting_command(command_opcode_t opcode);
|
||||
static pkt_linked_item_t *get_waiting_command(command_opcode_t opcode);
|
||||
static void dispatch_reassembled(BT_HDR *packet);
|
||||
static void dispatch_adv_report(pkt_linked_item_t *linked_pkt);
|
||||
|
||||
// Module lifecycle functions
|
||||
int hci_start_up(void)
|
||||
@@ -107,11 +105,15 @@ int hci_start_up(void)
|
||||
goto error;
|
||||
}
|
||||
|
||||
hci_host_thread = osi_thread_create(HCI_HOST_TASK_NAME, HCI_HOST_TASK_STACK_SIZE, HCI_HOST_TASK_PRIO, HCI_HOST_TASK_PINNED_TO_CORE, 2);
|
||||
const size_t workqueue_len[] = {HCI_HOST_TASK_WORKQUEUE0_LEN, HCI_HOST_TASK_WORKQUEUE1_LEN};
|
||||
hci_host_thread = osi_thread_create(HCI_HOST_TASK_NAME, HCI_HOST_TASK_STACK_SIZE, HCI_HOST_TASK_PRIO, HCI_HOST_TASK_PINNED_TO_CORE,
|
||||
HCI_HOST_TASK_WORKQUEUE_NUM, workqueue_len);
|
||||
if (hci_host_thread == NULL) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
osi_event_bind(hci_host_env.downstream_data_ready, hci_host_thread, HCI_DOWNSTREAM_DATA_QUEUE_IDX);
|
||||
|
||||
packet_fragmenter->init(&packet_fragmenter_callbacks);
|
||||
hal->open(&hal_callbacks, hci_host_thread);
|
||||
|
||||
@@ -136,10 +138,9 @@ void hci_shut_down(void)
|
||||
hci_host_thread = NULL;
|
||||
}
|
||||
|
||||
|
||||
bool hci_host_task_post(uint32_t timeout)
|
||||
bool hci_downstream_data_post(uint32_t timeout)
|
||||
{
|
||||
return osi_thread_post(hci_host_thread, hci_host_thread_handler, NULL, 0, timeout);
|
||||
return osi_thread_post_event(hci_host_env.downstream_data_ready, timeout);
|
||||
}
|
||||
|
||||
static int hci_layer_init_env(void)
|
||||
@@ -150,14 +151,18 @@ static int hci_layer_init_env(void)
|
||||
// as per the Bluetooth spec, Volume 2, Part E, 4.4 (Command Flow Control)
|
||||
// This value can change when you get a command complete or command status event.
|
||||
hci_host_env.command_credits = 1;
|
||||
hci_host_env.command_queue = fixed_queue_new(QUEUE_SIZE_MAX);
|
||||
hci_host_env.command_queue = fixed_pkt_queue_new(QUEUE_SIZE_MAX);
|
||||
if (hci_host_env.command_queue) {
|
||||
fixed_queue_register_dequeue(hci_host_env.command_queue, event_command_ready);
|
||||
fixed_pkt_queue_register_dequeue(hci_host_env.command_queue, event_command_ready);
|
||||
} else {
|
||||
HCI_TRACE_ERROR("%s unable to create pending command queue.", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct osi_event *event = osi_event_create(hci_downstream_data_handler, NULL);
|
||||
assert(event != NULL);
|
||||
hci_host_env.downstream_data_ready = event;
|
||||
|
||||
hci_host_env.packet_queue = fixed_queue_new(QUEUE_SIZE_MAX);
|
||||
if (hci_host_env.packet_queue) {
|
||||
fixed_queue_register_dequeue(hci_host_env.packet_queue, event_packet_ready);
|
||||
@@ -191,8 +196,11 @@ static void hci_layer_deinit_env(void)
|
||||
{
|
||||
command_waiting_response_t *cmd_wait_q;
|
||||
|
||||
osi_event_delete(hci_host_env.downstream_data_ready);
|
||||
hci_host_env.downstream_data_ready = NULL;
|
||||
|
||||
if (hci_host_env.command_queue) {
|
||||
fixed_queue_free(hci_host_env.command_queue, osi_free_func);
|
||||
fixed_pkt_queue_free(hci_host_env.command_queue, (fixed_pkt_queue_free_cb)osi_free_func);
|
||||
}
|
||||
if (hci_host_env.packet_queue) {
|
||||
fixed_queue_free(hci_host_env.packet_queue, osi_free_func);
|
||||
@@ -208,7 +216,7 @@ static void hci_layer_deinit_env(void)
|
||||
#endif // #if (BLE_50_FEATURE_SUPPORT == TRUE)
|
||||
}
|
||||
|
||||
static void hci_host_thread_handler(void *arg)
|
||||
static void hci_downstream_data_handler(void *arg)
|
||||
{
|
||||
/*
|
||||
* Previous task handles RX queue and two TX Queues, Since there is
|
||||
@@ -218,18 +226,19 @@ static void hci_host_thread_handler(void *arg)
|
||||
* All packets will be directly copied to single queue in driver layer with
|
||||
* H4 type header added (1 byte).
|
||||
*/
|
||||
if (esp_vhci_host_check_send_available()) {
|
||||
while (esp_vhci_host_check_send_available()) {
|
||||
/*Now Target only allowed one packet per TX*/
|
||||
BT_HDR *pkt = packet_fragmenter->fragment_current_packet();
|
||||
if (pkt != NULL) {
|
||||
packet_fragmenter->fragment_and_dispatch(pkt);
|
||||
} else {
|
||||
if (!fixed_queue_is_empty(hci_host_env.command_queue) &&
|
||||
} else if (!fixed_pkt_queue_is_empty(hci_host_env.command_queue) &&
|
||||
hci_host_env.command_credits > 0) {
|
||||
fixed_queue_process(hci_host_env.command_queue);
|
||||
} else if (!fixed_queue_is_empty(hci_host_env.packet_queue)) {
|
||||
fixed_queue_process(hci_host_env.packet_queue);
|
||||
}
|
||||
fixed_pkt_queue_process(hci_host_env.command_queue);
|
||||
} else if (!fixed_queue_is_empty(hci_host_env.packet_queue)) {
|
||||
fixed_queue_process(hci_host_env.packet_queue);
|
||||
} else {
|
||||
// No downstream packet to send, stop processing
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -240,81 +249,73 @@ static void transmit_command(
|
||||
command_status_cb status_callback,
|
||||
void *context)
|
||||
{
|
||||
uint8_t *stream;
|
||||
waiting_command_t *wait_entry = osi_calloc(sizeof(waiting_command_t));
|
||||
if (!wait_entry) {
|
||||
HCI_TRACE_ERROR("%s couldn't allocate space for wait entry.", __func__);
|
||||
return;
|
||||
}
|
||||
hci_cmd_metadata_t *metadata = HCI_GET_CMD_METAMSG(command);
|
||||
pkt_linked_item_t *linked_pkt = HCI_GET_CMD_LINKED_STRUCT(metadata);
|
||||
|
||||
stream = command->data + command->offset;
|
||||
STREAM_TO_UINT16(wait_entry->opcode, stream);
|
||||
wait_entry->complete_callback = complete_callback;
|
||||
wait_entry->status_callback = status_callback;
|
||||
wait_entry->command = command;
|
||||
wait_entry->context = context;
|
||||
assert(command->layer_specific == HCI_CMD_BUF_TYPE_METADATA);
|
||||
metadata->flags_vnd |= HCI_CMD_MSG_F_VND_QUEUED;
|
||||
|
||||
// Store the command message type in the event field
|
||||
// in case the upper layer didn't already
|
||||
command->event = MSG_STACK_TO_HC_HCI_CMD;
|
||||
HCI_TRACE_DEBUG("HCI Enqueue Comamnd opcode=0x%x\n", wait_entry->opcode);
|
||||
|
||||
HCI_TRACE_DEBUG("HCI Enqueue Comamnd opcode=0x%x\n", metadata->opcode);
|
||||
BTTRC_DUMP_BUFFER(NULL, command->data + command->offset, command->len);
|
||||
|
||||
fixed_queue_enqueue(hci_host_env.command_queue, wait_entry, FIXED_QUEUE_MAX_TIMEOUT);
|
||||
hci_host_task_post(OSI_THREAD_MAX_TIMEOUT);
|
||||
fixed_pkt_queue_enqueue(hci_host_env.command_queue, linked_pkt, FIXED_PKT_QUEUE_MAX_TIMEOUT);
|
||||
hci_downstream_data_post(OSI_THREAD_MAX_TIMEOUT);
|
||||
|
||||
}
|
||||
|
||||
static future_t *transmit_command_futured(BT_HDR *command)
|
||||
{
|
||||
waiting_command_t *wait_entry = osi_calloc(sizeof(waiting_command_t));
|
||||
assert(wait_entry != NULL);
|
||||
hci_cmd_metadata_t *metadata = HCI_GET_CMD_METAMSG(command);
|
||||
pkt_linked_item_t *linked_pkt = HCI_GET_CMD_LINKED_STRUCT(metadata);
|
||||
|
||||
assert(command->layer_specific == HCI_CMD_BUF_TYPE_METADATA);
|
||||
metadata->flags_vnd |= (HCI_CMD_MSG_F_VND_QUEUED | HCI_CMD_MSG_F_VND_FUTURE);
|
||||
|
||||
future_t *future = future_new();
|
||||
|
||||
uint8_t *stream = command->data + command->offset;
|
||||
STREAM_TO_UINT16(wait_entry->opcode, stream);
|
||||
wait_entry->complete_future = future;
|
||||
wait_entry->command = command;
|
||||
metadata->complete_future = future;
|
||||
|
||||
// Store the command message type in the event field
|
||||
// in case the upper layer didn't already
|
||||
command->event = MSG_STACK_TO_HC_HCI_CMD;
|
||||
|
||||
fixed_queue_enqueue(hci_host_env.command_queue, wait_entry, FIXED_QUEUE_MAX_TIMEOUT);
|
||||
hci_host_task_post(OSI_THREAD_MAX_TIMEOUT);
|
||||
fixed_pkt_queue_enqueue(hci_host_env.command_queue, linked_pkt, FIXED_PKT_QUEUE_MAX_TIMEOUT);
|
||||
hci_downstream_data_post(OSI_THREAD_MAX_TIMEOUT);
|
||||
return future;
|
||||
}
|
||||
|
||||
static void transmit_downward(uint16_t type, void *data)
|
||||
{
|
||||
if (type == MSG_STACK_TO_HC_HCI_CMD) {
|
||||
transmit_command((BT_HDR *)data, NULL, NULL, NULL);
|
||||
HCI_TRACE_WARNING("%s legacy transmit of command. Use transmit_command instead.\n", __func__);
|
||||
HCI_TRACE_ERROR("%s legacy transmit of command. Use transmit_command instead.\n", __func__);
|
||||
assert(0);
|
||||
} else {
|
||||
fixed_queue_enqueue(hci_host_env.packet_queue, data, FIXED_QUEUE_MAX_TIMEOUT);
|
||||
}
|
||||
|
||||
hci_host_task_post(OSI_THREAD_MAX_TIMEOUT);
|
||||
hci_downstream_data_post(OSI_THREAD_MAX_TIMEOUT);
|
||||
}
|
||||
|
||||
|
||||
// Command/packet transmitting functions
|
||||
static void event_command_ready(fixed_queue_t *queue)
|
||||
static void event_command_ready(fixed_pkt_queue_t *queue)
|
||||
{
|
||||
waiting_command_t *wait_entry = NULL;
|
||||
pkt_linked_item_t *wait_entry = NULL;
|
||||
command_waiting_response_t *cmd_wait_q = &hci_host_env.cmd_waiting_q;
|
||||
|
||||
wait_entry = fixed_queue_dequeue(queue, FIXED_QUEUE_MAX_TIMEOUT);
|
||||
wait_entry = fixed_pkt_queue_dequeue(queue, FIXED_QUEUE_MAX_TIMEOUT);
|
||||
hci_cmd_metadata_t *metadata = (hci_cmd_metadata_t *)(wait_entry->data);
|
||||
metadata->flags_vnd |= HCI_CMD_MSG_F_VND_SENT;
|
||||
metadata->flags_vnd &= ~HCI_CMD_MSG_F_VND_QUEUED;
|
||||
|
||||
if(wait_entry->opcode == HCI_HOST_NUM_PACKETS_DONE
|
||||
#if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE)
|
||||
|| wait_entry->opcode == HCI_VENDOR_BLE_ADV_REPORT_FLOW_CONTROL
|
||||
#endif
|
||||
){
|
||||
packet_fragmenter->fragment_and_dispatch(wait_entry->command);
|
||||
osi_free(wait_entry->command);
|
||||
osi_free(wait_entry);
|
||||
if (metadata->flags_src & HCI_CMD_MSG_F_SRC_NOACK) {
|
||||
packet_fragmenter->fragment_and_dispatch(&metadata->command);
|
||||
hci_cmd_free_cb free_func = metadata->command_free_cb ? metadata->command_free_cb : (hci_cmd_free_cb) osi_free_func;
|
||||
free_func(wait_entry);
|
||||
return;
|
||||
}
|
||||
hci_host_env.command_credits--;
|
||||
@@ -324,7 +325,7 @@ static void event_command_ready(fixed_queue_t *queue)
|
||||
osi_mutex_unlock(&cmd_wait_q->commands_pending_response_lock);
|
||||
|
||||
// Send it off
|
||||
packet_fragmenter->fragment_and_dispatch(wait_entry->command);
|
||||
packet_fragmenter->fragment_and_dispatch(&metadata->command);
|
||||
|
||||
restart_command_waiting_response_timer(cmd_wait_q);
|
||||
}
|
||||
@@ -389,7 +390,7 @@ static void restart_command_waiting_response_timer(command_waiting_response_t *c
|
||||
static void command_timed_out(void *context)
|
||||
{
|
||||
command_waiting_response_t *cmd_wait_q = (command_waiting_response_t *)context;
|
||||
waiting_command_t *wait_entry;
|
||||
pkt_linked_item_t *wait_entry;
|
||||
|
||||
osi_mutex_lock(&cmd_wait_q->commands_pending_response_lock, OSI_MUTEX_MAX_TIMEOUT);
|
||||
wait_entry = (list_is_empty(cmd_wait_q->commands_pending_response) ?
|
||||
@@ -402,7 +403,8 @@ static void command_timed_out(void *context)
|
||||
// We shouldn't try to recover the stack from this command timeout.
|
||||
// If it's caused by a software bug, fix it. If it's a hardware bug, fix it.
|
||||
{
|
||||
HCI_TRACE_ERROR("%s hci layer timeout waiting for response to a command. opcode: 0x%x", __func__, wait_entry->opcode);
|
||||
hci_cmd_metadata_t *metadata = (hci_cmd_metadata_t *)(wait_entry->data);
|
||||
HCI_TRACE_ERROR("%s hci layer timeout waiting for response to a command. opcode: 0x%x", __func__, metadata->opcode);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -416,12 +418,18 @@ static void hal_says_packet_ready(BT_HDR *packet)
|
||||
}
|
||||
}
|
||||
|
||||
static void hal_says_adv_rpt_ready(pkt_linked_item_t *linked_pkt)
|
||||
{
|
||||
dispatch_adv_report(linked_pkt);
|
||||
}
|
||||
|
||||
// Returns true if the event was intercepted and should not proceed to
|
||||
// higher layers. Also inspects an incoming event for interesting
|
||||
// information, like how many commands are now able to be sent.
|
||||
static bool filter_incoming_event(BT_HDR *packet)
|
||||
{
|
||||
waiting_command_t *wait_entry = NULL;
|
||||
pkt_linked_item_t *wait_entry = NULL;
|
||||
hci_cmd_metadata_t *metadata = NULL;
|
||||
uint8_t *stream = packet->data + packet->offset;
|
||||
uint8_t event_code;
|
||||
command_opcode_t opcode;
|
||||
@@ -435,10 +443,11 @@ static bool filter_incoming_event(BT_HDR *packet)
|
||||
STREAM_TO_UINT8(hci_host_env.command_credits, stream);
|
||||
STREAM_TO_UINT16(opcode, stream);
|
||||
wait_entry = get_waiting_command(opcode);
|
||||
metadata = (hci_cmd_metadata_t *)(wait_entry->data);
|
||||
if (!wait_entry) {
|
||||
HCI_TRACE_WARNING("%s command complete event with no matching command. opcode: 0x%x.", __func__, opcode);
|
||||
} else if (wait_entry->complete_callback) {
|
||||
wait_entry->complete_callback(packet, wait_entry->context);
|
||||
} else if (metadata->command_complete_cb) {
|
||||
metadata->command_complete_cb(packet, metadata->context);
|
||||
#if (BLE_50_FEATURE_SUPPORT == TRUE)
|
||||
BlE_SYNC *sync_info = btsnd_hcic_ble_get_sync_info();
|
||||
if(!sync_info) {
|
||||
@@ -450,8 +459,8 @@ static bool filter_incoming_event(BT_HDR *packet)
|
||||
}
|
||||
}
|
||||
#endif // #if (BLE_50_FEATURE_SUPPORT == TRUE)
|
||||
} else if (wait_entry->complete_future) {
|
||||
future_ready(wait_entry->complete_future, packet);
|
||||
} else if (metadata->flags_vnd & HCI_CMD_MSG_F_VND_FUTURE) {
|
||||
future_ready((future_t *)(metadata->complete_future), packet);
|
||||
}
|
||||
|
||||
goto intercepted;
|
||||
@@ -464,10 +473,11 @@ static bool filter_incoming_event(BT_HDR *packet)
|
||||
// If a command generates a command status event, it won't be getting a command complete event
|
||||
|
||||
wait_entry = get_waiting_command(opcode);
|
||||
metadata = (hci_cmd_metadata_t *)(wait_entry->data);
|
||||
if (!wait_entry) {
|
||||
HCI_TRACE_WARNING("%s command status event with no matching command. opcode: 0x%x", __func__, opcode);
|
||||
} else if (wait_entry->status_callback) {
|
||||
wait_entry->status_callback(status, wait_entry->command, wait_entry->context);
|
||||
} else if (metadata->command_status_cb) {
|
||||
metadata->command_status_cb(status, &metadata->command, metadata->context);
|
||||
}
|
||||
|
||||
goto intercepted;
|
||||
@@ -479,23 +489,22 @@ intercepted:
|
||||
|
||||
/*Tell HCI Host Task to continue TX Pending commands*/
|
||||
if (hci_host_env.command_credits &&
|
||||
!fixed_queue_is_empty(hci_host_env.command_queue)) {
|
||||
hci_host_task_post(OSI_THREAD_MAX_TIMEOUT);
|
||||
!fixed_pkt_queue_is_empty(hci_host_env.command_queue)) {
|
||||
hci_downstream_data_post(OSI_THREAD_MAX_TIMEOUT);
|
||||
}
|
||||
|
||||
if (wait_entry) {
|
||||
// If it has a callback, it's responsible for freeing the packet
|
||||
if (event_code == HCI_COMMAND_STATUS_EVT ||
|
||||
(!wait_entry->complete_callback && !wait_entry->complete_future)) {
|
||||
(!metadata->command_complete_cb && !metadata->complete_future)) {
|
||||
osi_free(packet);
|
||||
}
|
||||
|
||||
// If it has a callback, it's responsible for freeing the command
|
||||
if (event_code == HCI_COMMAND_COMPLETE_EVT || !wait_entry->status_callback) {
|
||||
osi_free(wait_entry->command);
|
||||
if (event_code == HCI_COMMAND_COMPLETE_EVT || !metadata->command_status_cb) {
|
||||
hci_cmd_free_cb free_func = metadata->command_free_cb ? metadata->command_free_cb : (hci_cmd_free_cb) osi_free_func;
|
||||
free_func(wait_entry);
|
||||
}
|
||||
|
||||
osi_free(wait_entry);
|
||||
} else {
|
||||
osi_free(packet);
|
||||
}
|
||||
@@ -513,6 +522,17 @@ static void dispatch_reassembled(BT_HDR *packet)
|
||||
}
|
||||
}
|
||||
|
||||
static void dispatch_adv_report(pkt_linked_item_t *linked_pkt)
|
||||
{
|
||||
// Events should already have been dispatched before this point
|
||||
//Tell Up-layer received packet.
|
||||
if (btu_task_post(SIG_BTU_HCI_ADV_RPT_MSG, linked_pkt, OSI_THREAD_MAX_TIMEOUT) == false) {
|
||||
osi_free(linked_pkt);
|
||||
#if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE)
|
||||
hci_adv_credits_try_release(1);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
// Misc internal functions
|
||||
|
||||
// TODO(zachoverflow): we seem to do this a couple places, like the HCI inject module. #centralize
|
||||
@@ -531,7 +551,7 @@ static serial_data_type_t event_to_data_type(uint16_t event)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static waiting_command_t *get_waiting_command(command_opcode_t opcode)
|
||||
static pkt_linked_item_t *get_waiting_command(command_opcode_t opcode)
|
||||
{
|
||||
command_waiting_response_t *cmd_wait_q = &hci_host_env.cmd_waiting_q;
|
||||
osi_mutex_lock(&cmd_wait_q->commands_pending_response_lock, OSI_MUTEX_MAX_TIMEOUT);
|
||||
@@ -539,15 +559,15 @@ static waiting_command_t *get_waiting_command(command_opcode_t opcode)
|
||||
for (const list_node_t *node = list_begin(cmd_wait_q->commands_pending_response);
|
||||
node != list_end(cmd_wait_q->commands_pending_response);
|
||||
node = list_next(node)) {
|
||||
waiting_command_t *wait_entry = list_node(node);
|
||||
if (!wait_entry || wait_entry->opcode != opcode) {
|
||||
continue;
|
||||
pkt_linked_item_t *wait_entry = list_node(node);
|
||||
if (wait_entry) {
|
||||
hci_cmd_metadata_t *metadata = (hci_cmd_metadata_t *)(wait_entry->data);
|
||||
if (metadata->opcode == opcode) {
|
||||
list_remove(cmd_wait_q->commands_pending_response, wait_entry);
|
||||
osi_mutex_unlock(&cmd_wait_q->commands_pending_response_lock);
|
||||
return wait_entry;
|
||||
}
|
||||
}
|
||||
|
||||
list_remove(cmd_wait_q->commands_pending_response, wait_entry);
|
||||
|
||||
osi_mutex_unlock(&cmd_wait_q->commands_pending_response_lock);
|
||||
return wait_entry;
|
||||
}
|
||||
|
||||
osi_mutex_unlock(&cmd_wait_q->commands_pending_response_lock);
|
||||
@@ -565,7 +585,8 @@ static void init_layer_interface(void)
|
||||
}
|
||||
|
||||
static const hci_hal_callbacks_t hal_callbacks = {
|
||||
hal_says_packet_ready
|
||||
hal_says_packet_ready,
|
||||
hal_says_adv_rpt_ready,
|
||||
};
|
||||
|
||||
static const packet_fragmenter_callbacks_t packet_fragmenter_callbacks = {
|
||||
|
||||
@@ -27,7 +27,6 @@
|
||||
#include "hci/hci_packet_factory.h"
|
||||
|
||||
|
||||
static BT_HDR *make_packet(size_t data_size);
|
||||
static BT_HDR *make_command_no_params(uint16_t opcode);
|
||||
static BT_HDR *make_command(uint16_t opcode, size_t parameter_size, uint8_t **stream_out);
|
||||
|
||||
@@ -234,7 +233,9 @@ static BT_HDR *make_command_no_params(uint16_t opcode)
|
||||
|
||||
static BT_HDR *make_command(uint16_t opcode, size_t parameter_size, uint8_t **stream_out)
|
||||
{
|
||||
BT_HDR *packet = make_packet(HCI_COMMAND_PREAMBLE_SIZE + parameter_size);
|
||||
BT_HDR *packet = HCI_GET_CMD_BUF(parameter_size);
|
||||
hci_cmd_metadata_t *metadata = HCI_GET_CMD_METAMSG(packet);
|
||||
metadata->opcode = opcode;
|
||||
|
||||
uint8_t *stream = packet->data;
|
||||
UINT16_TO_STREAM(stream, opcode);
|
||||
@@ -247,17 +248,6 @@ static BT_HDR *make_command(uint16_t opcode, size_t parameter_size, uint8_t **st
|
||||
return packet;
|
||||
}
|
||||
|
||||
static BT_HDR *make_packet(size_t data_size)
|
||||
{
|
||||
BT_HDR *ret = (BT_HDR *)osi_calloc(sizeof(BT_HDR) + data_size);
|
||||
assert(ret);
|
||||
ret->event = 0;
|
||||
ret->offset = 0;
|
||||
ret->layer_specific = 0;
|
||||
ret->len = data_size;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const hci_packet_factory_t interface = {
|
||||
make_reset,
|
||||
make_read_buffer_size,
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "osi/pkt_queue.h"
|
||||
#include "stack/bt_types.h"
|
||||
#if SOC_ESP_NIMBLE_CONTROLLER
|
||||
#include "os/os_mbuf.h"
|
||||
@@ -34,12 +34,14 @@ typedef enum {
|
||||
} serial_data_type_t;
|
||||
|
||||
typedef void (*packet_ready_cb)(BT_HDR *packet);
|
||||
typedef void (*adv_rpt_ready_cb)(pkt_linked_item_t *linked_pkt);
|
||||
|
||||
typedef struct {
|
||||
// Called when the HAL detects inbound data.
|
||||
// Data |type| may be ACL, SCO, or EVENT.
|
||||
// Executes in the context of the thread supplied to |init|.
|
||||
packet_ready_cb packet_ready;
|
||||
adv_rpt_ready_cb adv_rpt_ready;
|
||||
|
||||
/*
|
||||
// Called when the HAL detects inbound astronauts named Dave.
|
||||
|
||||
@@ -19,11 +19,13 @@
|
||||
#ifndef _HCI_LAYER_H_
|
||||
#define _HCI_LAYER_H_
|
||||
|
||||
#include "common/bt_target.h"
|
||||
#include "stack/bt_types.h"
|
||||
#include "osi/allocator.h"
|
||||
#include "osi/osi.h"
|
||||
#include "osi/future.h"
|
||||
#include "osi/thread.h"
|
||||
#include "osi/pkt_queue.h"
|
||||
|
||||
///// LEGACY DEFINITIONS /////
|
||||
|
||||
@@ -46,6 +48,9 @@
|
||||
/* Local Bluetooth Controller ID for BR/EDR */
|
||||
#define LOCAL_BR_EDR_CONTROLLER_ID 0
|
||||
|
||||
#define HCI_CMD_MSG_F_VND_FUTURE (0x01)
|
||||
#define HCI_CMD_MSG_F_VND_QUEUED (0x02)
|
||||
#define HCI_CMD_MSG_F_VND_SENT (0x04)
|
||||
///// END LEGACY DEFINITIONS /////
|
||||
|
||||
typedef struct hci_hal_t hci_hal_t;
|
||||
@@ -97,6 +102,12 @@ const hci_t *hci_layer_get_interface(void);
|
||||
int hci_start_up(void);
|
||||
void hci_shut_down(void);
|
||||
|
||||
bool hci_host_task_post(uint32_t timeout);
|
||||
bool hci_downstream_data_post(uint32_t timeout);
|
||||
|
||||
#if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE)
|
||||
int hci_adv_credits_prep_to_release(uint16_t num);
|
||||
int hci_adv_credits_try_release(uint16_t num);
|
||||
int hci_adv_credits_force_release(uint16_t num);
|
||||
#endif
|
||||
|
||||
#endif /* _HCI_LAYER_H_ */
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
#include "device/controller.h"
|
||||
#include "stack/hcimsgs.h"
|
||||
#include "stack/gap_api.h"
|
||||
|
||||
#include "hci/hci_layer.h"
|
||||
#if BLE_INCLUDED == TRUE
|
||||
#include "l2c_int.h"
|
||||
|
||||
@@ -57,6 +57,8 @@
|
||||
#define MIN_ADV_LENGTH 2
|
||||
#define BTM_VSC_CHIP_CAPABILITY_RSP_LEN_L_RELEASE 9
|
||||
|
||||
#define BTM_BLE_GAP_ADV_RPT_BATCH_SIZE (10)
|
||||
|
||||
#if BTM_DYNAMIC_MEMORY == FALSE
|
||||
static tBTM_BLE_VSC_CB cmn_ble_gap_vsc_cb;
|
||||
#else
|
||||
@@ -82,6 +84,7 @@ 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);
|
||||
static void btm_adv_pkt_handler(void *arg);
|
||||
uint32_t BTM_BleUpdateOwnType(uint8_t *own_bda_type, tBTM_START_ADV_CMPL_CBACK *cb);
|
||||
|
||||
#define BTM_BLE_INQ_RESULT 0x01
|
||||
@@ -3455,6 +3458,49 @@ void btm_send_sel_conn_callback(BD_ADDR remote_bda, UINT8 evt_type, UINT8 *p_dat
|
||||
}
|
||||
}
|
||||
|
||||
static void btm_adv_pkt_handler(void *arg)
|
||||
{
|
||||
UINT8 hci_evt_code, hci_evt_len;
|
||||
UINT8 ble_sub_code;
|
||||
|
||||
tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
|
||||
size_t pkts_to_process = pkt_queue_length(p_cb->adv_rpt_queue);
|
||||
if (pkts_to_process > BTM_BLE_GAP_ADV_RPT_BATCH_SIZE) {
|
||||
pkts_to_process = BTM_BLE_GAP_ADV_RPT_BATCH_SIZE;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < pkts_to_process; i++) {
|
||||
pkt_linked_item_t *linked_pkt = pkt_queue_dequeue(p_cb->adv_rpt_queue);
|
||||
assert(linked_pkt != NULL);
|
||||
BT_HDR *packet = (BT_HDR *)linked_pkt->data;
|
||||
uint8_t *p = packet->data + packet->offset;
|
||||
STREAM_TO_UINT8 (hci_evt_code, p);
|
||||
STREAM_TO_UINT8 (hci_evt_len, p);
|
||||
STREAM_TO_UINT8 (ble_sub_code, p);
|
||||
if (ble_sub_code == HCI_BLE_ADV_PKT_RPT_EVT) {
|
||||
btm_ble_process_adv_pkt(p);
|
||||
} else if (ble_sub_code == HCI_BLE_ADV_DISCARD_REPORT_EVT) {
|
||||
btm_ble_process_adv_discard_evt(p);
|
||||
} else if (ble_sub_code == HCI_BLE_DIRECT_ADV_EVT) {
|
||||
btm_ble_process_direct_adv_pkt(p);
|
||||
} else {
|
||||
assert (0);
|
||||
}
|
||||
|
||||
osi_free(linked_pkt);
|
||||
#if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE)
|
||||
hci_adv_credits_try_release(1);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (pkt_queue_length(p_cb->adv_rpt_queue) != 0) {
|
||||
btu_task_post(SIG_BTU_HCI_ADV_RPT_MSG, NULL, OSI_THREAD_MAX_TIMEOUT);
|
||||
}
|
||||
|
||||
UNUSED(hci_evt_code);
|
||||
UNUSED(hci_evt_len);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_ble_process_adv_pkt
|
||||
@@ -3750,6 +3796,12 @@ void btm_ble_process_adv_discard_evt(UINT8 *p)
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void btm_ble_process_direct_adv_pkt(UINT8 *p)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btm_ble_start_scan
|
||||
@@ -4414,6 +4466,13 @@ void btm_ble_init (void)
|
||||
|
||||
p_cb->inq_var.evt_type = BTM_BLE_NON_CONNECT_EVT;
|
||||
|
||||
p_cb->adv_rpt_queue = pkt_queue_create();
|
||||
assert(p_cb->adv_rpt_queue != NULL);
|
||||
|
||||
p_cb->adv_rpt_ready = osi_event_create(btm_adv_pkt_handler, NULL);
|
||||
assert(p_cb->adv_rpt_ready != NULL);
|
||||
osi_event_bind(p_cb->adv_rpt_ready, btu_get_current_thread(), 0);
|
||||
|
||||
#if BLE_VND_INCLUDED == FALSE
|
||||
btm_ble_adv_filter_init();
|
||||
#endif
|
||||
@@ -4436,6 +4495,12 @@ void btm_ble_free (void)
|
||||
|
||||
fixed_queue_free(p_cb->conn_pending_q, osi_free_func);
|
||||
|
||||
pkt_queue_destroy(p_cb->adv_rpt_queue, NULL);
|
||||
p_cb->adv_rpt_queue = NULL;
|
||||
|
||||
osi_event_delete(p_cb->adv_rpt_ready);
|
||||
p_cb->adv_rpt_ready = NULL;
|
||||
|
||||
#if BTM_DYNAMIC_MEMORY == TRUE
|
||||
osi_free(cmn_ble_gap_vsc_cb_ptr);
|
||||
cmn_ble_gap_vsc_cb_ptr = NULL;
|
||||
@@ -4530,4 +4595,22 @@ BOOLEAN BTM_Ble_Authorization(BD_ADDR bd_addr, BOOLEAN authorize)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bool btm_ble_adv_pkt_ready(void)
|
||||
{
|
||||
tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
|
||||
osi_thread_post_event(p_cb->adv_rpt_ready, OSI_THREAD_MAX_TIMEOUT);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool btm_ble_adv_pkt_post(pkt_linked_item_t *pkt)
|
||||
{
|
||||
if (pkt == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
|
||||
pkt_queue_enqueue(p_cb->adv_rpt_queue, pkt);
|
||||
return true;
|
||||
}
|
||||
#endif /* BLE_INCLUDED */
|
||||
|
||||
@@ -662,14 +662,13 @@ tBTM_DEV_STATUS_CB *BTM_RegisterForDeviceStatusNotif (tBTM_DEV_STATUS_CB *p_cb)
|
||||
tBTM_STATUS BTM_VendorSpecificCommand(UINT16 opcode, UINT8 param_len,
|
||||
UINT8 *p_param_buf, tBTM_VSC_CMPL_CB *p_cb)
|
||||
{
|
||||
void *p_buf;
|
||||
BT_HDR *p_buf;
|
||||
|
||||
BTM_TRACE_EVENT ("BTM: BTM_VendorSpecificCommand: Opcode: 0x%04X, ParamLen: %i.",
|
||||
opcode, param_len);
|
||||
|
||||
/* Allocate a buffer to hold HCI command plus the callback function */
|
||||
if ((p_buf = osi_malloc((UINT16)(sizeof(BT_HDR) + sizeof (tBTM_CMPL_CB *) +
|
||||
param_len + HCIC_PREAMBLE_SIZE))) != NULL) {
|
||||
if ((p_buf = HCI_GET_CMD_BUF(param_len)) != NULL) {
|
||||
/* Send the HCI command (opcode will be OR'd with HCI_GRP_VENDOR_SPECIFIC) */
|
||||
btsnd_hcic_vendor_spec_cmd (p_buf, opcode, param_len, p_param_buf, (void *)p_cb);
|
||||
|
||||
|
||||
@@ -2304,7 +2304,7 @@ void btm_process_remote_name (BD_ADDR bda, BD_NAME bdn, UINT16 evt_len, UINT8 hc
|
||||
else {
|
||||
rem_name.status = BTM_BAD_VALUE_RET;
|
||||
rem_name.length = 0;
|
||||
rem_name.remote_bd_name[0] = 0;
|
||||
rem_name.remote_bd_name[0] = '\0';
|
||||
}
|
||||
memcpy(rem_name.bd_addr, p_inq->remname_bda, BD_ADDR_LEN);
|
||||
/* Reset the remote BAD to zero and call callback if possible */
|
||||
@@ -2395,6 +2395,7 @@ tBTM_STATUS BTM_WriteEIR( BT_HDR *p_buff, BOOLEAN fec_required)
|
||||
if (controller_get_interface()->supports_extended_inquiry_response()) {
|
||||
BTM_TRACE_API("Write Extended Inquiry Response to controller\n");
|
||||
btsnd_hcic_write_ext_inquiry_response (p_buff, fec_required);
|
||||
osi_free(p_buff);
|
||||
return BTM_SUCCESS;
|
||||
} else {
|
||||
osi_free(p_buff);
|
||||
|
||||
@@ -592,6 +592,7 @@ static BOOLEAN btm_sec_set_security_level (CONNECTION_TYPE conn_type, const char
|
||||
p_srec->orig_mx_chan_id = mx_chan_id;
|
||||
#if BTM_SEC_SERVICE_NAME_LEN > 0
|
||||
BCM_STRNCPY_S ((char *)p_srec->orig_service_name, p_name, BTM_SEC_SERVICE_NAME_LEN);
|
||||
p_srec->orig_service_name[BTM_SEC_SERVICE_NAME_LEN] = '\0';
|
||||
#endif
|
||||
/* clear out the old setting, just in case it exists */
|
||||
#if (L2CAP_UCD_INCLUDED == TRUE)
|
||||
@@ -637,6 +638,7 @@ static BOOLEAN btm_sec_set_security_level (CONNECTION_TYPE conn_type, const char
|
||||
p_srec->term_mx_chan_id = mx_chan_id;
|
||||
#if BTM_SEC_SERVICE_NAME_LEN > 0
|
||||
BCM_STRNCPY_S ((char *)p_srec->term_service_name, p_name, BTM_SEC_SERVICE_NAME_LEN);
|
||||
p_srec->term_service_name[BTM_SEC_SERVICE_NAME_LEN] = '\0';
|
||||
#endif
|
||||
/* clear out the old setting, just in case it exists */
|
||||
#if (L2CAP_UCD_INCLUDED == TRUE)
|
||||
@@ -3031,11 +3033,12 @@ void btm_sec_rmt_name_request_complete (UINT8 *p_bd_addr, UINT8 *p_bd_name, UINT
|
||||
old_sec_state = p_dev_rec->sec_state;
|
||||
if (status == HCI_SUCCESS) {
|
||||
BCM_STRNCPY_S ((char *)p_dev_rec->sec_bd_name, (char *)p_bd_name, BTM_MAX_REM_BD_NAME_LEN);
|
||||
p_dev_rec->sec_bd_name[BTM_MAX_REM_BD_NAME_LEN] = '\0';
|
||||
p_dev_rec->sec_flags |= BTM_SEC_NAME_KNOWN;
|
||||
BTM_TRACE_EVENT ("setting BTM_SEC_NAME_KNOWN sec_flags:0x%x\n", p_dev_rec->sec_flags);
|
||||
} else {
|
||||
/* Notify all clients waiting for name to be resolved even if it failed so clients can continue */
|
||||
p_dev_rec->sec_bd_name[0] = 0;
|
||||
p_dev_rec->sec_bd_name[0] = '\0';
|
||||
}
|
||||
|
||||
if (p_dev_rec->sec_state == BTM_SEC_STATE_GETTING_NAME) {
|
||||
@@ -3755,7 +3758,7 @@ void btm_rem_oob_req (UINT8 *p)
|
||||
memcpy (evt_data.bd_addr, p_dev_rec->bd_addr, BD_ADDR_LEN);
|
||||
memcpy (evt_data.dev_class, p_dev_rec->dev_class, DEV_CLASS_LEN);
|
||||
BCM_STRNCPY_S((char *)evt_data.bd_name, (char *)p_dev_rec->sec_bd_name, BTM_MAX_REM_BD_NAME_LEN);
|
||||
evt_data.bd_name[BTM_MAX_REM_BD_NAME_LEN] = 0;
|
||||
evt_data.bd_name[BTM_MAX_REM_BD_NAME_LEN] = '\0';
|
||||
|
||||
btm_sec_change_pairing_state(BTM_PAIR_STATE_WAIT_LOCAL_OOB_RSP);
|
||||
if ((*btm_cb.api.p_sp_callback) (BTM_SP_RMT_OOB_EVT, (tBTM_SP_EVT_DATA *)&evt_data) == BTM_NOT_AUTHORIZED) {
|
||||
@@ -4903,7 +4906,7 @@ static void btm_sec_pairing_timeout (TIMER_LIST_ENT *p_tle)
|
||||
/* We need to notify the UI that no longer need the PIN */
|
||||
if (btm_cb.api.p_auth_complete_callback) {
|
||||
if (p_dev_rec == NULL) {
|
||||
name[0] = 0;
|
||||
name[0] = '\0';
|
||||
(*btm_cb.api.p_auth_complete_callback) (p_cb->pairing_bda,
|
||||
NULL,
|
||||
name, HCI_ERR_CONNECTION_TOUT);
|
||||
@@ -4963,7 +4966,7 @@ static void btm_sec_pairing_timeout (TIMER_LIST_ENT *p_tle)
|
||||
btm_sec_change_pairing_state (BTM_PAIR_STATE_IDLE);
|
||||
if (btm_cb.api.p_auth_complete_callback) {
|
||||
if (p_dev_rec == NULL) {
|
||||
name[0] = 0;
|
||||
name[0] = '\0';
|
||||
(*btm_cb.api.p_auth_complete_callback) (p_cb->pairing_bda,
|
||||
NULL,
|
||||
name, HCI_ERR_CONNECTION_TOUT);
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
|
||||
#include "common/bt_target.h"
|
||||
#include "osi/fixed_queue.h"
|
||||
#include "osi/pkt_queue.h"
|
||||
#include "osi/thread.h"
|
||||
#include "stack/hcidefs.h"
|
||||
#include "stack/btm_ble_api.h"
|
||||
#include "btm_int.h"
|
||||
@@ -341,6 +343,9 @@ typedef struct {
|
||||
tBTM_CMPL_CB *p_scan_cmpl_cb;
|
||||
TIMER_LIST_ENT scan_timer_ent;
|
||||
|
||||
struct pkt_queue *adv_rpt_queue;
|
||||
struct osi_event *adv_rpt_ready;
|
||||
|
||||
/* background connection procedure cb value */
|
||||
tBTM_BLE_CONN_TYPE bg_conn_type;
|
||||
UINT32 scan_int;
|
||||
@@ -384,6 +389,9 @@ extern "C" {
|
||||
void btm_ble_timeout(TIMER_LIST_ENT *p_tle);
|
||||
void btm_ble_process_adv_pkt (UINT8 *p);
|
||||
void btm_ble_process_adv_discard_evt(UINT8 *p);
|
||||
void btm_ble_process_direct_adv_pkt (UINT8 *p);
|
||||
bool btm_ble_adv_pkt_ready(void);
|
||||
bool btm_ble_adv_pkt_post(pkt_linked_item_t *pkt);
|
||||
void btm_ble_proc_scan_rsp_rpt (UINT8 *p);
|
||||
tBTM_STATUS btm_ble_read_remote_name(BD_ADDR remote_bda, tBTM_INQ_INFO *p_cur, tBTM_CMPL_CB *p_cb);
|
||||
BOOLEAN btm_ble_cancel_remote_name(BD_ADDR remote_bda);
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
#include "common/bt_trace.h"
|
||||
|
||||
#include "osi/thread.h"
|
||||
#include "osi/pkt_queue.h"
|
||||
//#include "osi/mutex.h"
|
||||
// TODO(zachoverflow): remove this horrible hack
|
||||
#include "stack/btu.h"
|
||||
@@ -124,8 +125,6 @@ static void btu_hcif_ssr_evt_dump (UINT8 *p, UINT16 evt_len);
|
||||
|
||||
#if BLE_INCLUDED == TRUE
|
||||
static void btu_ble_ll_conn_complete_evt (UINT8 *p, UINT16 evt_len);
|
||||
static void btu_ble_process_adv_pkt (UINT8 *p);
|
||||
static void btu_ble_process_adv_dis(UINT8 *p);
|
||||
static void btu_ble_read_remote_feat_evt (UINT8 *p);
|
||||
static void btu_ble_ll_conn_param_upd_evt (UINT8 *p, UINT16 evt_len);
|
||||
static void btu_ble_ll_get_conn_param_format_err_from_contoller (UINT8 status, UINT16 handle);
|
||||
@@ -360,10 +359,10 @@ void btu_hcif_process_event (UNUSED_ATTR UINT8 controller_id, BT_HDR *p_msg)
|
||||
|
||||
switch (ble_sub_code) {
|
||||
case HCI_BLE_ADV_PKT_RPT_EVT: /* result of inquiry */
|
||||
btu_ble_process_adv_pkt(p);
|
||||
break;
|
||||
case HCI_BLE_ADV_DISCARD_REPORT_EVT:
|
||||
btu_ble_process_adv_dis(p);
|
||||
case HCI_BLE_DIRECT_ADV_EVT:
|
||||
// These three events are directed to another specialized processing path
|
||||
HCI_TRACE_ERROR("Unexpected HCI BLE event = 0x%02x", ble_sub_code);
|
||||
break;
|
||||
case HCI_BLE_CONN_COMPLETE_EVT:
|
||||
btu_ble_ll_conn_complete_evt(p, hci_evt_len);
|
||||
@@ -453,15 +452,21 @@ void btu_hcif_send_cmd (UNUSED_ATTR UINT8 controller_id, BT_HDR *p_buf)
|
||||
|
||||
STREAM_TO_UINT16(opcode, stream);
|
||||
|
||||
// Eww...horrible hackery here
|
||||
/* If command was a VSC, then extract command_complete callback */
|
||||
if ((opcode & HCI_GRP_VENDOR_SPECIFIC) == HCI_GRP_VENDOR_SPECIFIC
|
||||
assert (p_buf->layer_specific == HCI_CMD_BUF_TYPE_METADATA);
|
||||
hci_cmd_metadata_t *metadata = HCI_GET_CMD_METAMSG(p_buf);
|
||||
metadata->command_complete_cb = btu_hcif_command_complete_evt;
|
||||
metadata->command_status_cb = btu_hcif_command_status_evt;
|
||||
metadata->opcode = opcode;
|
||||
|
||||
vsc_callback = metadata->context;
|
||||
/* If command is not a VSC, then the context field should be empty */
|
||||
if ((opcode & HCI_GRP_VENDOR_SPECIFIC) != HCI_GRP_VENDOR_SPECIFIC
|
||||
#if BLE_INCLUDED == TRUE
|
||||
|| (opcode == HCI_BLE_RAND)
|
||||
|| (opcode == HCI_BLE_ENCRYPT)
|
||||
&& (opcode != HCI_BLE_RAND)
|
||||
&& (opcode != HCI_BLE_ENCRYPT)
|
||||
#endif
|
||||
) {
|
||||
vsc_callback = *((void **)(p_buf + 1));
|
||||
) {
|
||||
assert (vsc_callback == NULL);
|
||||
}
|
||||
|
||||
hci_layer_get_interface()->transmit_command(
|
||||
@@ -474,6 +479,7 @@ void btu_hcif_send_cmd (UNUSED_ATTR UINT8 controller_id, BT_HDR *p_buf)
|
||||
btu_check_bt_sleep ();
|
||||
#endif
|
||||
}
|
||||
|
||||
#if (BLE_50_FEATURE_SUPPORT == TRUE)
|
||||
UINT8 btu_hcif_send_cmd_sync (UINT8 controller_id, BT_HDR *p_buf)
|
||||
{
|
||||
@@ -494,15 +500,22 @@ UINT8 btu_hcif_send_cmd_sync (UINT8 controller_id, BT_HDR *p_buf)
|
||||
|
||||
sync_info->opcode = opcode;
|
||||
|
||||
// Eww...horrible hackery here
|
||||
/* If command was a VSC, then extract command_complete callback */
|
||||
if ((opcode & HCI_GRP_VENDOR_SPECIFIC) == HCI_GRP_VENDOR_SPECIFIC
|
||||
assert (p_buf->layer_specific == HCI_CMD_BUF_TYPE_METADATA);
|
||||
hci_cmd_metadata_t *metadata = HCI_GET_CMD_METAMSG(p_buf);
|
||||
metadata->command_complete_cb = btu_hcif_command_complete_evt;
|
||||
metadata->command_status_cb = btu_hcif_command_status_evt;
|
||||
metadata->command_free_cb = NULL;
|
||||
metadata->opcode = opcode;
|
||||
|
||||
vsc_callback = metadata->context;
|
||||
/* If command is not a VSC, then the context field should be empty */
|
||||
if ((opcode & HCI_GRP_VENDOR_SPECIFIC) != HCI_GRP_VENDOR_SPECIFIC
|
||||
#if BLE_INCLUDED == TRUE
|
||||
|| (opcode == HCI_BLE_RAND)
|
||||
|| (opcode == HCI_BLE_ENCRYPT)
|
||||
&& (opcode != HCI_BLE_RAND)
|
||||
&& (opcode != HCI_BLE_ENCRYPT)
|
||||
#endif
|
||||
) {
|
||||
vsc_callback = *((void **)(p_buf + 1));
|
||||
) {
|
||||
assert (vsc_callback == NULL);
|
||||
}
|
||||
|
||||
hci_layer_get_interface()->transmit_command(
|
||||
@@ -1436,7 +1449,11 @@ static void btu_hcif_command_status_evt_on_task(BT_HDR *event)
|
||||
stream,
|
||||
hack->context);
|
||||
|
||||
osi_free(hack->command);
|
||||
// check the HCI command integrity: opcode
|
||||
hci_cmd_metadata_t *metadata = HCI_GET_CMD_METAMSG(hack->command);
|
||||
assert(metadata->opcode == opcode);
|
||||
|
||||
HCI_FREE_CMD_BUF(hack->command);
|
||||
osi_free(event);
|
||||
}
|
||||
|
||||
@@ -2015,18 +2032,6 @@ static void btu_hcif_encryption_key_refresh_cmpl_evt (UINT8 *p)
|
||||
}
|
||||
#endif ///SMP_INCLUDED == TRUE
|
||||
|
||||
static void btu_ble_process_adv_pkt (UINT8 *p)
|
||||
{
|
||||
HCI_TRACE_DEBUG("btu_ble_process_adv_pkt\n");
|
||||
|
||||
btm_ble_process_adv_pkt(p);
|
||||
}
|
||||
|
||||
static void btu_ble_process_adv_dis(UINT8 *p)
|
||||
{
|
||||
btm_ble_process_adv_discard_evt(p);
|
||||
}
|
||||
|
||||
static void btu_ble_ll_conn_complete_evt ( UINT8 *p, UINT16 evt_len)
|
||||
{
|
||||
btm_ble_conn_complete(p, evt_len, FALSE);
|
||||
|
||||
@@ -48,6 +48,8 @@
|
||||
#define BTU_TASK_STACK_SIZE (BT_BTU_TASK_STACK_SIZE + BT_TASK_EXTRA_STACK_SIZE)
|
||||
#define BTU_TASK_PRIO (BT_TASK_MAX_PRIORITIES - 5)
|
||||
#define BTU_TASK_NAME "BTU_TASK"
|
||||
#define BTU_TASK_WORKQUEUE_NUM (2)
|
||||
#define BTU_TASK_WORKQUEUE0_LEN (0)
|
||||
|
||||
hash_map_t *btu_general_alarm_hash_map;
|
||||
osi_mutex_t btu_general_alarm_lock;
|
||||
@@ -181,7 +183,9 @@ void BTU_StartUp(void)
|
||||
|
||||
osi_mutex_new(&btu_l2cap_alarm_lock);
|
||||
|
||||
btu_thread = osi_thread_create(BTU_TASK_NAME, BTU_TASK_STACK_SIZE, BTU_TASK_PRIO, BTU_TASK_PINNED_TO_CORE, 1);
|
||||
const size_t workqueue_len[] = {BTU_TASK_WORKQUEUE0_LEN};
|
||||
btu_thread = osi_thread_create(BTU_TASK_NAME, BTU_TASK_STACK_SIZE, BTU_TASK_PRIO, BTU_TASK_PINNED_TO_CORE,
|
||||
BTU_TASK_WORKQUEUE_NUM, workqueue_len);
|
||||
if (btu_thread == NULL) {
|
||||
goto error_exit;
|
||||
}
|
||||
@@ -265,3 +269,8 @@ int get_btu_work_queue_size(void)
|
||||
{
|
||||
return osi_thread_queue_wait_size(btu_thread, 0);
|
||||
}
|
||||
|
||||
osi_thread_t *btu_get_current_thread(void)
|
||||
{
|
||||
return btu_thread;
|
||||
}
|
||||
|
||||
@@ -227,6 +227,18 @@ bool btu_task_post(uint32_t sig, void *param, uint32_t timeout)
|
||||
case SIG_BTU_HCI_MSG:
|
||||
status = osi_thread_post(btu_thread, btu_hci_msg_process, param, 0, timeout);
|
||||
break;
|
||||
case SIG_BTU_HCI_ADV_RPT_MSG:
|
||||
#if BLE_INCLUDED == TRUE
|
||||
if (param != NULL) {
|
||||
btm_ble_adv_pkt_post(param);
|
||||
}
|
||||
btm_ble_adv_pkt_ready();
|
||||
status = true;
|
||||
#else
|
||||
osi_free(param);
|
||||
status = false;
|
||||
#endif
|
||||
break;
|
||||
#if (defined(BTA_INCLUDED) && BTA_INCLUDED == TRUE)
|
||||
case SIG_BTU_BTA_MSG:
|
||||
status = osi_thread_post(btu_thread, bta_sys_event, param, 0, timeout);
|
||||
|
||||
@@ -33,7 +33,6 @@
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
#define HCI_GET_CMD_BUF(paramlen) ((BT_HDR *)osi_malloc(HCIC_PREAMBLE_SIZE + sizeof(BT_HDR) + paramlen))
|
||||
#if (BLE_50_FEATURE_SUPPORT == TRUE)
|
||||
static BlE_SYNC ble_sync_info;
|
||||
|
||||
@@ -557,19 +556,17 @@ BOOLEAN btsnd_hcic_ble_encrypt (UINT8 *key, UINT8 key_len,
|
||||
BT_HDR *p;
|
||||
UINT8 *pp;
|
||||
|
||||
if ((p = HCI_GET_CMD_BUF(sizeof (void *) +
|
||||
HCIC_PARAM_SIZE_BLE_ENCRYPT)) == NULL) {
|
||||
if ((p = HCI_GET_CMD_BUF(HCIC_PARAM_SIZE_BLE_ENCRYPT)) == NULL) {
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
pp = (UINT8 *)(p + 1);
|
||||
|
||||
p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_BLE_ENCRYPT;
|
||||
p->offset = sizeof(void *);
|
||||
|
||||
*((void **)pp) = p_cmd_cplt_cback; /* Store command complete callback in buffer */
|
||||
pp += sizeof(void *); /* Skip over callback pointer */
|
||||
p->offset = 0;
|
||||
|
||||
hci_cmd_metadata_t *metadata = HCI_GET_CMD_METAMSG(p);
|
||||
metadata->context = p_cmd_cplt_cback;
|
||||
|
||||
UINT16_TO_STREAM (pp, HCI_BLE_ENCRYPT);
|
||||
UINT8_TO_STREAM (pp, HCIC_PARAM_SIZE_BLE_ENCRYPT);
|
||||
@@ -596,18 +593,17 @@ BOOLEAN btsnd_hcic_ble_rand (void *p_cmd_cplt_cback)
|
||||
BT_HDR *p;
|
||||
UINT8 *pp;
|
||||
|
||||
if ((p = HCI_GET_CMD_BUF(sizeof (void *) +
|
||||
HCIC_PARAM_SIZE_BLE_RAND)) == NULL) {
|
||||
if ((p = HCI_GET_CMD_BUF(HCIC_PARAM_SIZE_BLE_RAND)) == NULL) {
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
pp = (UINT8 *)(p + 1);
|
||||
|
||||
p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_BLE_RAND;
|
||||
p->offset = sizeof(void *);
|
||||
p->offset = 0;
|
||||
|
||||
*((void **)pp) = p_cmd_cplt_cback; /* Store command complete callback in buffer */
|
||||
pp += sizeof(void *); /* Skip over callback pointer */
|
||||
hci_cmd_metadata_t *metadata = HCI_GET_CMD_METAMSG(p);
|
||||
metadata->context = p_cmd_cplt_cback;
|
||||
|
||||
UINT16_TO_STREAM (pp, HCI_BLE_RAND);
|
||||
UINT8_TO_STREAM (pp, HCIC_PARAM_SIZE_BLE_RAND);
|
||||
@@ -1032,15 +1028,26 @@ BOOLEAN btsnd_hcic_ble_set_data_length(UINT16 conn_handle, UINT16 tx_octets, UIN
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOLEAN btsnd_hcic_ble_update_adv_report_flow_control (UINT16 num)
|
||||
BOOLEAN btsnd_hcic_ble_update_adv_report_flow_control (UINT16 num, BT_HDR *static_buf)
|
||||
{
|
||||
BT_HDR *p;
|
||||
UINT8 *pp;
|
||||
|
||||
if ((p = HCI_GET_CMD_BUF (HCIC_PARAM_SIZE_BLE_UPDATE_ADV_FLOW_CONTROL)) == NULL) {
|
||||
return (FALSE);
|
||||
if (static_buf != NULL) {
|
||||
p = static_buf;
|
||||
} else {
|
||||
if ((p = HCI_GET_CMD_BUF (HCIC_PARAM_SIZE_BLE_UPDATE_ADV_FLOW_CONTROL)) == NULL) {
|
||||
return (FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
hci_cmd_metadata_t *metadata = HCI_GET_CMD_METAMSG(p);
|
||||
metadata->flags_src = HCI_CMD_MSG_F_SRC_NOACK;
|
||||
if (static_buf == p) {
|
||||
assert(metadata->command_free_cb != NULL);
|
||||
}
|
||||
p->layer_specific = HCI_CMD_BUF_TYPE_METADATA;
|
||||
|
||||
pp = (UINT8 *)(p + 1);
|
||||
|
||||
p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_BLE_UPDATE_ADV_FLOW_CONTROL;
|
||||
|
||||
@@ -35,8 +35,6 @@
|
||||
|
||||
#include "btm_int.h" /* Included for UIPC_* macro definitions */
|
||||
|
||||
#define HCI_GET_CMD_BUF(paramlen) ((BT_HDR *)osi_malloc(HCIC_PREAMBLE_SIZE + sizeof(BT_HDR) + paramlen))
|
||||
|
||||
BOOLEAN btsnd_hcic_inquiry(const LAP inq_lap, UINT8 duration, UINT8 response_cnt)
|
||||
{
|
||||
BT_HDR *p;
|
||||
@@ -1331,6 +1329,9 @@ BOOLEAN btsnd_hcic_host_num_xmitted_pkts (UINT8 num_handles, UINT16 *handle,
|
||||
p->len = HCIC_PREAMBLE_SIZE + 1 + (num_handles * 4);
|
||||
p->offset = 0;
|
||||
|
||||
hci_cmd_metadata_t *metadata = HCI_GET_CMD_METAMSG(p);
|
||||
metadata->flags_src |= HCI_CMD_MSG_F_SRC_NOACK;
|
||||
|
||||
UINT16_TO_STREAM (pp, HCI_HOST_NUM_PACKETS_DONE);
|
||||
UINT8_TO_STREAM (pp, p->len - HCIC_PREAMBLE_SIZE);
|
||||
|
||||
@@ -1431,9 +1432,13 @@ BOOLEAN btsnd_hcic_sniff_sub_rate(UINT16 handle, UINT16 max_lat,
|
||||
#endif /* BTM_SSR_INCLUDED */
|
||||
|
||||
/**** Extended Inquiry Response Commands ****/
|
||||
void btsnd_hcic_write_ext_inquiry_response (void *buffer, UINT8 fec_req)
|
||||
void btsnd_hcic_write_ext_inquiry_response (BT_HDR *buffer, UINT8 fec_req)
|
||||
{
|
||||
BT_HDR *p = (BT_HDR *)buffer;
|
||||
BT_HDR *p;
|
||||
if ((p = HCI_GET_CMD_BUF(HCIC_PARAM_SIZE_EXT_INQ_RESP)) == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
UINT8 *pp = (UINT8 *)(p + 1);
|
||||
|
||||
p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_EXT_INQ_RESP;
|
||||
@@ -1441,9 +1446,10 @@ void btsnd_hcic_write_ext_inquiry_response (void *buffer, UINT8 fec_req)
|
||||
|
||||
UINT16_TO_STREAM (pp, HCI_WRITE_EXT_INQ_RESPONSE);
|
||||
UINT8_TO_STREAM (pp, HCIC_PARAM_SIZE_EXT_INQ_RESP);
|
||||
|
||||
UINT8_TO_STREAM (pp, fec_req);
|
||||
|
||||
memcpy(pp, buffer->data + 4, p->len - 4);
|
||||
|
||||
btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID, p);
|
||||
}
|
||||
|
||||
@@ -1862,17 +1868,17 @@ BOOLEAN btsnd_hcic_write_pagescan_type (UINT8 type)
|
||||
#error "HCI_CMD_POOL_BUF_SIZE must be larger than 268"
|
||||
#endif
|
||||
|
||||
void btsnd_hcic_vendor_spec_cmd (void *buffer, UINT16 opcode, UINT8 len,
|
||||
void btsnd_hcic_vendor_spec_cmd (BT_HDR *buffer, UINT16 opcode, UINT8 len,
|
||||
UINT8 *p_data, void *p_cmd_cplt_cback)
|
||||
{
|
||||
BT_HDR *p = (BT_HDR *)buffer;
|
||||
BT_HDR *p = buffer;
|
||||
UINT8 *pp = (UINT8 *)(p + 1);
|
||||
|
||||
p->len = HCIC_PREAMBLE_SIZE + len;
|
||||
p->offset = sizeof(void *);
|
||||
p->offset = 0;
|
||||
|
||||
*((void **)pp) = p_cmd_cplt_cback; /* Store command complete callback in buffer */
|
||||
pp += sizeof(void *); /* Skip over callback pointer */
|
||||
hci_cmd_metadata_t * metadata = HCI_GET_CMD_METAMSG(p);
|
||||
metadata->context = p_cmd_cplt_cback;
|
||||
|
||||
UINT16_TO_STREAM (pp, HCI_GRP_VENDOR_SPECIFIC | opcode);
|
||||
UINT8_TO_STREAM (pp, len);
|
||||
|
||||
@@ -175,6 +175,7 @@ typedef enum {
|
||||
SIG_BTU_GENERAL_ALARM,
|
||||
SIG_BTU_ONESHOT_ALARM,
|
||||
SIG_BTU_L2CAP_ALARM,
|
||||
SIG_BTU_HCI_ADV_RPT_MSG,
|
||||
SIG_BTU_NUM,
|
||||
} SIG_BTU_t;
|
||||
|
||||
@@ -297,6 +298,7 @@ bool btu_task_post(uint32_t sig, void *param, uint32_t timeout);
|
||||
|
||||
int get_btu_work_queue_size(void);
|
||||
|
||||
osi_thread_t *btu_get_current_thread(void);
|
||||
/*
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -19,9 +19,66 @@
|
||||
#ifndef HCIMSGS_H
|
||||
#define HCIMSGS_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include "common/bt_target.h"
|
||||
#include "stack/hcidefs.h"
|
||||
#include "stack/bt_types.h"
|
||||
#include "osi/pkt_queue.h"
|
||||
#include "osi/allocator.h"
|
||||
|
||||
#define HCI_CMD_BUF_TYPE_METADATA (0xa56e)
|
||||
|
||||
#define HCI_CMD_MSG_F_SRC_NOACK (0x01)
|
||||
|
||||
typedef void (*hci_cmd_cmpl_cb)(BT_HDR *response, void *context);
|
||||
typedef void (*hci_cmd_stat_cb)(uint8_t status, BT_HDR *command, void *context);
|
||||
typedef void (*hci_cmd_free_cb)(pkt_linked_item_t *linked_pkt);
|
||||
|
||||
typedef struct {
|
||||
uint8_t flags_src;
|
||||
uint8_t flags_vnd; // used for downstream layer
|
||||
uint16_t opcode;
|
||||
hci_cmd_cmpl_cb command_complete_cb;
|
||||
hci_cmd_stat_cb command_status_cb;
|
||||
void *context;
|
||||
void *complete_future;
|
||||
hci_cmd_free_cb command_free_cb;
|
||||
BT_HDR command;
|
||||
} hci_cmd_metadata_t;
|
||||
|
||||
#define HCI_CMD_METADATA_HDR_SIZE (sizeof(hci_cmd_metadata_t))
|
||||
|
||||
#define HCI_CMD_LINKED_BUF_SIZE(paramlen) (BT_PKT_LINKED_HDR_SIZE + HCI_CMD_METADATA_HDR_SIZE + HCIC_PREAMBLE_SIZE + (paramlen))
|
||||
|
||||
#define HCI_GET_CMD_METAMSG(cmd_ptr) (hci_cmd_metadata_t *)((void *)(cmd_ptr) - offsetof(hci_cmd_metadata_t, command))
|
||||
#define HCI_GET_CMD_LINKED_STRUCT(metadata_ptr) (pkt_linked_item_t *)((void *)(metadata_ptr) - offsetof(pkt_linked_item_t, data))
|
||||
|
||||
static inline BT_HDR *hci_get_cmd_buf(size_t param_len)
|
||||
{
|
||||
pkt_linked_item_t *linked_pkt = osi_calloc(HCI_CMD_LINKED_BUF_SIZE(param_len));
|
||||
if (linked_pkt == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
hci_cmd_metadata_t *metadata = (hci_cmd_metadata_t *)linked_pkt->data;
|
||||
BT_HDR *command = &metadata->command;
|
||||
|
||||
command->layer_specific = HCI_CMD_BUF_TYPE_METADATA;
|
||||
command->len = HCIC_PREAMBLE_SIZE + param_len;
|
||||
command->offset = 0;
|
||||
|
||||
return command;
|
||||
}
|
||||
|
||||
static inline void hci_free_cmd_buf(BT_HDR *buf)
|
||||
{
|
||||
assert(buf->layer_specific == HCI_CMD_BUF_TYPE_METADATA);
|
||||
hci_cmd_metadata_t *metadata = HCI_GET_CMD_METAMSG(buf);
|
||||
pkt_linked_item_t *linked_pkt = HCI_GET_CMD_LINKED_STRUCT(metadata);
|
||||
osi_free(linked_pkt);
|
||||
}
|
||||
|
||||
#define HCI_GET_CMD_BUF(param_len) hci_get_cmd_buf(param_len)
|
||||
#define HCI_FREE_CMD_BUF(buf) hci_free_cmd_buf(buf)
|
||||
|
||||
void bte_main_hci_send(BT_HDR *p_msg, UINT16 event);
|
||||
void bte_main_lpm_allow_bt_device_sleep(void);
|
||||
@@ -378,7 +435,7 @@ BOOLEAN btsnd_hcic_sniff_sub_rate(UINT16 handle, UINT16 max_lat,
|
||||
#endif /* BTM_SSR_INCLUDED */
|
||||
|
||||
/* Extended Inquiry Response */
|
||||
void btsnd_hcic_write_ext_inquiry_response(void *buffer, UINT8 fec_req);
|
||||
void btsnd_hcic_write_ext_inquiry_response(BT_HDR *buffer, UINT8 fec_req);
|
||||
|
||||
#define HCIC_PARAM_SIZE_EXT_INQ_RESP 241
|
||||
|
||||
@@ -641,7 +698,7 @@ BOOLEAN btsnd_hcic_write_inquiry_mode(UINT8 type); /* Write Inquiry
|
||||
|
||||
#define HCID_GET_SCO_LEN(p) (*((UINT8 *)((p) + 1) + p->offset + 2))
|
||||
|
||||
void btsnd_hcic_vendor_spec_cmd (void *buffer, UINT16 opcode,
|
||||
void btsnd_hcic_vendor_spec_cmd (BT_HDR *buffer, UINT16 opcode,
|
||||
UINT8 len, UINT8 *p_data,
|
||||
void *p_cmd_cplt_cback);
|
||||
|
||||
@@ -882,7 +939,7 @@ BOOLEAN btsnd_hcic_read_authenticated_payload_tout(UINT16 handle);
|
||||
BOOLEAN btsnd_hcic_write_authenticated_payload_tout(UINT16 handle,
|
||||
UINT16 timeout);
|
||||
|
||||
BOOLEAN btsnd_hcic_ble_update_adv_report_flow_control (UINT16 num);
|
||||
BOOLEAN btsnd_hcic_ble_update_adv_report_flow_control (UINT16 num, BT_HDR *static_buf);
|
||||
#if (BLE_50_FEATURE_SUPPORT == TRUE)
|
||||
BOOLEAN btsnd_hcic_ble_read_phy(UINT16 conn_handle);
|
||||
|
||||
|
||||
@@ -118,7 +118,7 @@ esp_err_t esp_ble_tx_power_set(esp_ble_power_type_t power_type, esp_power_level_
|
||||
esp_power_level_t esp_ble_tx_power_get(esp_ble_power_type_t power_type);
|
||||
|
||||
|
||||
#define CONFIG_VERSION 0x20220105
|
||||
#define CONFIG_VERSION 0x20220729
|
||||
#define CONFIG_MAGIC 0x5A5AA5A5
|
||||
|
||||
/**
|
||||
@@ -173,6 +173,7 @@ typedef struct {
|
||||
uint8_t coex_phy_coded_tx_rx_time_limit;
|
||||
uint8_t dis_scan_backoff;
|
||||
uint8_t esp_scan_filter_en;
|
||||
uint8_t main_xtal_freq;
|
||||
uint32_t config_magic;
|
||||
} esp_bt_controller_config_t;
|
||||
|
||||
@@ -223,6 +224,7 @@ typedef struct {
|
||||
.coex_phy_coded_tx_rx_time_limit = DEFAULT_BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EFF, \
|
||||
.dis_scan_backoff = NIMBLE_DISABLE_SCAN_BACKOFF, \
|
||||
.esp_scan_filter_en = 0, \
|
||||
.main_xtal_freq = CONFIG_ESP32C2_XTAL_FREQ, \
|
||||
.config_magic = CONFIG_MAGIC, \
|
||||
};
|
||||
|
||||
|
||||
@@ -192,7 +192,11 @@ extern "C" {
|
||||
|
||||
#define BLE_LL_CONN_DEF_AUTH_PYLD_TMO_N (3000)
|
||||
|
||||
#define RTC_FREQ_N (32000) /* in Hz */
|
||||
#ifdef CONFIG_ESP32C2_XTAL_FREQ_26
|
||||
#define RTC_FREQ_N (40000) /* in Hz */
|
||||
#else
|
||||
#define RTC_FREQ_N (32000) /* in Hz */
|
||||
#endif // CONFIG_ESP32C2_XTAL_FREQ_26
|
||||
|
||||
#define BLE_LL_TX_PWR_DBM_N (0)
|
||||
|
||||
|
||||
@@ -2,4 +2,5 @@ if(CONFIG_BT_ENABLED OR CMAKE_BUILD_EARLY_EXPANSION)
|
||||
idf_component_register(SRC_DIRS "."
|
||||
PRIV_INCLUDE_DIRS "."
|
||||
PRIV_REQUIRES cmock nvs_flash bt esp_ringbuf)
|
||||
target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format")
|
||||
endif()
|
||||
|
||||
@@ -22,3 +22,6 @@ idf_component_register(SRCS "commands.c"
|
||||
INCLUDE_DIRS "."
|
||||
REQUIRES vfs
|
||||
PRIV_REQUIRES driver)
|
||||
|
||||
|
||||
target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format")
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
idf_component_register(SRC_DIRS .
|
||||
PRIV_INCLUDE_DIRS .
|
||||
PRIV_REQUIRES cmock test_utils console)
|
||||
target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format")
|
||||
|
||||
@@ -121,7 +121,9 @@ else()
|
||||
idf_component_register(SRCS "${srcs}"
|
||||
INCLUDE_DIRS ${includes}
|
||||
PRIV_INCLUDE_DIRS "include/driver"
|
||||
PRIV_REQUIRES efuse esp_timer esp_adc
|
||||
PRIV_REQUIRES efuse esp_timer
|
||||
REQUIRES esp_pm esp_ringbuf freertos soc hal esp_hw_support
|
||||
LDFRAGMENTS linker.lf)
|
||||
endif()
|
||||
|
||||
target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format")
|
||||
|
||||
@@ -19,11 +19,11 @@
|
||||
#include "freertos/timers.h"
|
||||
#include "freertos/ringbuf.h"
|
||||
#include "esp_private/periph_ctrl.h"
|
||||
#include "esp_private/adc_private.h"
|
||||
#include "esp_private/adc_lock.h"
|
||||
#include "esp_private/adc_share_hw_ctrl.h"
|
||||
#include "hal/adc_types.h"
|
||||
#include "hal/adc_hal.h"
|
||||
#include "hal/dma_types.h"
|
||||
#include "hal/adc_hal_common.h"
|
||||
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/adc_types_legacy.h"
|
||||
@@ -588,3 +588,23 @@ static void check_adc_continuous_driver_conflict(void)
|
||||
}
|
||||
ESP_EARLY_LOGW(ADC_TAG, "legacy driver is deprecated, please migrate to `esp_adc/adc_continuous.h`");
|
||||
}
|
||||
|
||||
#if SOC_ADC_CALIBRATION_V1_SUPPORTED
|
||||
/*---------------------------------------------------------------
|
||||
ADC Hardware Calibration
|
||||
---------------------------------------------------------------*/
|
||||
static __attribute__((constructor)) void adc_hw_calibration(void)
|
||||
{
|
||||
//Calculate all ICode
|
||||
for (int i = 0; i < SOC_ADC_PERIPH_NUM; i++) {
|
||||
adc_hal_calibration_init(i);
|
||||
for (int j = 0; j < SOC_ADC_ATTEN_NUM; j++) {
|
||||
/**
|
||||
* This may get wrong when attenuations are NOT consecutive on some chips,
|
||||
* update this when bringing up the calibration on that chip
|
||||
*/
|
||||
adc_calc_hw_calibration_code(i, j);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif //#if SOC_ADC_CALIBRATION_V1_SUPPORTED
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
#include "esp_pm.h"
|
||||
#endif
|
||||
#include "esp_private/adc_private.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
|
||||
#include "driver/adc_i2s_legacy.h"
|
||||
|
||||
@@ -18,13 +18,13 @@
|
||||
#include "driver/rtc_io.h"
|
||||
#include "sys/lock.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_private/adc_private.h"
|
||||
#include "esp_private/adc_share_hw_ctrl.h"
|
||||
#include "adc1_private.h"
|
||||
#include "hal/adc_types.h"
|
||||
#include "hal/adc_hal.h"
|
||||
#include "hal/adc_hal_common.h"
|
||||
#include "hal/adc_hal_conf.h"
|
||||
#include "esp_private/periph_ctrl.h"
|
||||
#include "esp_private/adc_lock.h"
|
||||
#include "driver/adc_types_legacy.h"
|
||||
|
||||
#if SOC_DAC_SUPPORTED
|
||||
@@ -904,8 +904,6 @@ static esp_err_t adc_hal_convert(adc_unit_t adc_n, int channel, int *out_raw)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
#if !CONFIG_IDF_TARGET_ESP32
|
||||
//wrapper should be removed after I2S deprecation
|
||||
/**
|
||||
* @brief This function will be called during start up, to check that adc_oneshot driver is not running along with the legacy adc oneshot driver
|
||||
*/
|
||||
@@ -921,4 +919,23 @@ static void check_adc_oneshot_driver_conflict(void)
|
||||
}
|
||||
ESP_EARLY_LOGW(ADC_TAG, "legacy driver is deprecated, please migrate to `esp_adc/adc_oneshot.h`");
|
||||
}
|
||||
#endif
|
||||
|
||||
#if SOC_ADC_CALIBRATION_V1_SUPPORTED
|
||||
/*---------------------------------------------------------------
|
||||
ADC Hardware Calibration
|
||||
---------------------------------------------------------------*/
|
||||
static __attribute__((constructor)) void adc_hw_calibration(void)
|
||||
{
|
||||
//Calculate all ICode
|
||||
for (int i = 0; i < SOC_ADC_PERIPH_NUM; i++) {
|
||||
adc_hal_calibration_init(i);
|
||||
for (int j = 0; j < SOC_ADC_ATTEN_NUM; j++) {
|
||||
/**
|
||||
* This may get wrong when attenuations are NOT consecutive on some chips,
|
||||
* update this when bringing up the calibration on that chip
|
||||
*/
|
||||
adc_calc_hw_calibration_code(i, j);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif //#if SOC_ADC_CALIBRATION_V1_SUPPORTED
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
#include "hal/i2s_hal.h"
|
||||
#if SOC_I2S_SUPPORTS_DAC
|
||||
#include "driver/dac.h"
|
||||
#include "esp_private/adc_private.h"
|
||||
#include "esp_private/adc_share_hw_ctrl.h"
|
||||
#include "adc1_private.h"
|
||||
#include "driver/adc_i2s_legacy.h"
|
||||
#include "driver/adc_types_legacy.h"
|
||||
@@ -804,6 +804,8 @@ static esp_err_t i2s_calculate_clock(i2s_port_t i2s_num, i2s_hal_clock_info_t *c
|
||||
|
||||
/* Calculate clock for common mode */
|
||||
ESP_RETURN_ON_ERROR(i2s_calculate_common_clock(i2s_num, clk_info), TAG, "Common clock calculate failed");
|
||||
ESP_LOGD(TAG, "[sclk] %d [mclk] %d [mclk_div] %d [bclk] %d [bclk_div] %d",
|
||||
clk_info->sclk, clk_info->mclk, clk_info->mclk_div, clk_info->bclk, clk_info->bclk_div);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -177,9 +177,8 @@ esp_err_t mcpwm_new_soft_fault(const mcpwm_soft_fault_config_t *config, mcpwm_fa
|
||||
return ESP_OK;
|
||||
|
||||
err:
|
||||
if (soft_fault) {
|
||||
free(soft_fault);
|
||||
}
|
||||
// soft_fault must be NULL in the error handling path, and it's a determined behaviour to free a NULL pointer in esp-idf
|
||||
free(soft_fault);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -252,9 +252,8 @@ esp_err_t mcpwm_new_soft_sync_src(const mcpwm_soft_sync_config_t *config, mcpwm_
|
||||
return ESP_OK;
|
||||
|
||||
err:
|
||||
if (soft_sync) {
|
||||
free(soft_sync);
|
||||
}
|
||||
// soft_sync must be NULL in the error handling path, and it's a determined behaviour to free a NULL pointer in esp-idf
|
||||
free(soft_sync);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -46,6 +46,7 @@ static esp_err_t rmt_bytes_encoder_reset(rmt_encoder_t *encoder)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
__attribute__((always_inline))
|
||||
static inline uint8_t _bitwise_reverse(uint8_t n)
|
||||
{
|
||||
n = ((n & 0xf0) >> 4) | ((n & 0x0f) << 4);
|
||||
|
||||
@@ -268,8 +268,8 @@ esp_err_t rmt_new_tx_channel(const rmt_tx_channel_config_t *config, rmt_channel_
|
||||
rmt_ll_tx_set_limit(hal->regs, channel_id, tx_channel->ping_pong_symbols);
|
||||
// disable carrier modulation by default, can reenable by `rmt_apply_carrier()`
|
||||
rmt_ll_tx_enable_carrier_modulation(hal->regs, channel_id, false);
|
||||
// idle level is determind by eof encoder, not set to a fixed value
|
||||
rmt_ll_tx_fix_idle_level(hal->regs, channel_id, 0, false);
|
||||
// idle level is determined by register value
|
||||
rmt_ll_tx_fix_idle_level(hal->regs, channel_id, 0, true);
|
||||
// always enable tx wrap, both DMA mode and ping-pong mode rely this feature
|
||||
rmt_ll_tx_enable_wrap(hal->regs, channel_id, true);
|
||||
|
||||
@@ -662,6 +662,7 @@ static void IRAM_ATTR rmt_tx_do_transaction(rmt_tx_channel_t *tx_chan, rmt_tx_tr
|
||||
#endif
|
||||
// turn on the TX machine
|
||||
portENTER_CRITICAL_ISR(&channel->spinlock);
|
||||
rmt_ll_tx_fix_idle_level(hal->regs, channel_id, t->flags.eot_level, true);
|
||||
rmt_ll_tx_start(hal->regs, channel_id);
|
||||
portEXIT_CRITICAL_ISR(&channel->spinlock);
|
||||
}
|
||||
@@ -720,9 +721,6 @@ static esp_err_t rmt_tx_disable(rmt_channel_handle_t channel)
|
||||
int channel_id = channel->channel_id;
|
||||
|
||||
portENTER_CRITICAL(&channel->spinlock);
|
||||
// when this function called, the transaction might be middle-way, the output level when we stop the transmitter is nondeterministic,
|
||||
// so we fix the idle level temporarily
|
||||
rmt_ll_tx_fix_idle_level(hal->regs, channel->channel_id, tx_chan->cur_trans ? tx_chan->cur_trans->flags.eot_level : 0, true);
|
||||
rmt_ll_tx_enable_loop(hal->regs, channel->channel_id, false);
|
||||
#if SOC_RMT_SUPPORT_TX_ASYNC_STOP
|
||||
rmt_ll_tx_stop(hal->regs, channel->channel_id);
|
||||
@@ -740,11 +738,6 @@ static esp_err_t rmt_tx_disable(rmt_channel_handle_t channel)
|
||||
rmt_ll_clear_interrupt_status(hal->regs, RMT_LL_EVENT_TX_MASK(channel_id));
|
||||
portEXIT_CRITICAL(&group->spinlock);
|
||||
|
||||
portENTER_CRITICAL(&channel->spinlock);
|
||||
// restore the idle level selection, to be determind by eof symbol
|
||||
rmt_ll_tx_fix_idle_level(hal->regs, channel_id, 0, false);
|
||||
portEXIT_CRITICAL(&channel->spinlock);
|
||||
|
||||
#if SOC_RMT_SUPPORT_DMA
|
||||
if (channel->dma_chan) {
|
||||
gdma_stop(channel->dma_chan);
|
||||
|
||||
@@ -2,3 +2,4 @@ idf_component_register(SRC_DIRS . param_test touch_sensor_test dac_dma_test
|
||||
PRIV_INCLUDE_DIRS include param_test/include touch_sensor_test/include
|
||||
PRIV_REQUIRES cmock test_utils driver nvs_flash esp_serial_slave_link
|
||||
esp_timer esp_adc esp_event esp_wifi)
|
||||
target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format")
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
*/
|
||||
/* This file is from test_uart.c, but mainly about RS485 */
|
||||
|
||||
|
||||
#include <string.h>
|
||||
#include <sys/param.h>
|
||||
#include "unity.h"
|
||||
@@ -14,22 +13,17 @@
|
||||
#include "esp_log.h"
|
||||
#include "esp_random.h" // for uint32_t esp_random()
|
||||
|
||||
#define UART_TAG "Uart"
|
||||
#define UART_NUM1 (UART_NUM_1)
|
||||
#define BUF_SIZE (100)
|
||||
#define UART1_RX_PIN (22)
|
||||
#define UART1_TX_PIN (23)
|
||||
#define UART_BAUD_11520 (11520)
|
||||
#define UART_BAUD_115200 (115200)
|
||||
#define TOLERANCE (0.02) //baud rate error tolerance 2%.
|
||||
|
||||
#define UART_TOLERANCE_CHECK(val, uper_limit, lower_limit) ( (val) <= (uper_limit) && (val) >= (lower_limit) )
|
||||
#define UART_NUM1 (UART_NUM_1)
|
||||
#define UART_BAUD_RATE (115200 * 10)
|
||||
#define BUF_SIZE (512)
|
||||
#define UART1_RX_PIN (22)
|
||||
#define UART1_TX_PIN (23)
|
||||
|
||||
// RTS for RS485 Half-Duplex Mode manages DE/~RE
|
||||
#define UART1_RTS_PIN (18)
|
||||
#define UART1_RTS_PIN (18)
|
||||
|
||||
// Number of packets to be send during test
|
||||
#define PACKETS_NUMBER (10)
|
||||
#define PACKETS_NUMBER (40)
|
||||
|
||||
// Wait timeout for uart driver
|
||||
#define PACKET_READ_TICS (1000 / portTICK_PERIOD_MS)
|
||||
@@ -158,7 +152,7 @@ static uint16_t buffer_fill_random(uint8_t *buffer, size_t length)
|
||||
static void rs485_init(void)
|
||||
{
|
||||
uart_config_t uart_config = {
|
||||
.baud_rate = UART_BAUD_115200,
|
||||
.baud_rate = UART_BAUD_RATE,
|
||||
.data_bits = UART_DATA_8_BITS,
|
||||
.parity = UART_PARITY_DISABLE,
|
||||
.stop_bits = UART_STOP_BITS_1,
|
||||
@@ -210,7 +204,7 @@ static void rs485_slave(void)
|
||||
unity_wait_for_signal("Master_started");
|
||||
for(int pack_count = 0; pack_count < PACKETS_NUMBER; pack_count++) {
|
||||
//Read slave_data from UART
|
||||
int len = uart_read_bytes(UART_NUM1, slave_data, BUF_SIZE, (PACKET_READ_TICS * 2));
|
||||
int len = uart_read_bytes(UART_NUM1, slave_data, BUF_SIZE, PACKET_READ_TICS);
|
||||
//Write slave_data back to UART
|
||||
if (len > 2) {
|
||||
esp_err_t status = print_packet_data("Received ", slave_data, len);
|
||||
@@ -259,7 +253,7 @@ static void rs485_master(void)
|
||||
uart_write_bytes(UART_NUM1, (char*)master_buffer, BUF_SIZE);
|
||||
uart_wait_tx_idle_polling(UART_NUM1);
|
||||
// Read translated packet from slave
|
||||
int len = uart_read_bytes(UART_NUM1, slave_buffer, BUF_SIZE, (PACKET_READ_TICS * 2));
|
||||
int len = uart_read_bytes(UART_NUM1, slave_buffer, BUF_SIZE, PACKET_READ_TICS);
|
||||
// Check if the received packet is too short
|
||||
if (len > 2) {
|
||||
// Print received packet and check checksum
|
||||
@@ -280,6 +274,7 @@ static void rs485_master(void)
|
||||
uart_wait_tx_done(UART_NUM1, PACKET_READ_TICS);
|
||||
// Free the buffer and delete driver at the end
|
||||
free(master_buffer);
|
||||
free(slave_buffer);
|
||||
uart_driver_delete(UART_NUM1);
|
||||
TEST_ASSERT(err_count <= 1);
|
||||
printf("Test completed. Received packets = %d, errors = %d\r\n", (uint16_t)good_count, (uint16_t)err_count);
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
CONFIG_COMPILER_DUMP_RTL_FILES=y
|
||||
CONFIG_GPIO_CTRL_FUNC_IN_IRAM=y
|
||||
CONFIG_COMPILER_OPTIMIZATION_NONE=y
|
||||
# silent the error check, as the error string are stored in rodata, causing RTL check failure
|
||||
CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT=y
|
||||
# GPIO test uses IPC call, the default stack size of IPC task can satisfy the -O0 optimization
|
||||
CONFIG_ESP_IPC_TASK_STACK_SIZE=2048
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
CONFIG_COMPILER_DUMP_RTL_FILES=y
|
||||
CONFIG_GPTIMER_CTRL_FUNC_IN_IRAM=y
|
||||
CONFIG_GPTIMER_ISR_IRAM_SAFE=y
|
||||
CONFIG_COMPILER_OPTIMIZATION_NONE=y
|
||||
# silent the error check, as the error string are stored in rodata, causing RTL check failure
|
||||
CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT=y
|
||||
|
||||
@@ -4,3 +4,4 @@ set(srcs "test_app_main.c"
|
||||
|
||||
idf_component_register(SRCS ${srcs}
|
||||
WHOLE_ARCHIVE)
|
||||
target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format")
|
||||
|
||||
@@ -364,18 +364,26 @@ TEST_CASE("I2S_thread_concurrent_safety_test", "[i2s]")
|
||||
TEST_ESP_OK(i2s_del_channel(rx_handle));
|
||||
}
|
||||
|
||||
static uint32_t get_start_index(uint16_t *buf, uint32_t len, uint32_t start_val)
|
||||
static bool whether_contains_exapected_data(uint16_t *src, uint32_t src_len, uint32_t src_step, uint32_t start_val, uint32_t val_step)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
for (i = 0; i < len; i++) {
|
||||
if (buf[i] == start_val) {
|
||||
printf("%d %d %d %d %d %d %d %d\n",
|
||||
buf[i], buf[i+1], buf[i+2], buf[i+3],
|
||||
buf[i+4], buf[i+5], buf[i+6], buf[i+7]);
|
||||
break;
|
||||
uint32_t val = start_val;
|
||||
uint32_t index_step = 1;
|
||||
for (int i = 0; val < 100 && i < src_len; i += index_step) {
|
||||
if (src[i] == val) {
|
||||
if (val == start_val && i < src_len - 8) {
|
||||
printf("start index: %d ---> \n%d %d %d %d %d %d %d %d\n", i,
|
||||
src[i], src[i+1], src[i+2], src[i+3],
|
||||
src[i+4], src[i+5], src[i+6], src[i+7]);
|
||||
}
|
||||
index_step = src_step;
|
||||
val += val_step;
|
||||
} else {
|
||||
index_step = 1;
|
||||
val = start_val;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
|
||||
return val >= 100;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -394,6 +402,8 @@ TEST_CASE("I2S_mono_stereo_loopback_test", "[i2s]")
|
||||
i2s_chan_handle_t tx_handle;
|
||||
i2s_chan_handle_t rx_handle;
|
||||
|
||||
bool is_failed = false;
|
||||
|
||||
i2s_chan_config_t chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM_0, I2S_ROLE_MASTER);
|
||||
chan_cfg.dma_desc_num = 8;
|
||||
chan_cfg.dma_frame_num = 128;
|
||||
@@ -429,7 +439,6 @@ TEST_CASE("I2S_mono_stereo_loopback_test", "[i2s]")
|
||||
uint16_t *r_buf = calloc(1, READ_BUF_LEN);
|
||||
size_t w_bytes = 0;
|
||||
size_t r_bytes = 0;
|
||||
uint32_t index = 0;
|
||||
uint32_t retry = 0;
|
||||
for (int n = 0; n < WRITE_BUF_LEN / 2; n++) {
|
||||
w_buf[n] = n%100;
|
||||
@@ -439,7 +448,7 @@ TEST_CASE("I2S_mono_stereo_loopback_test", "[i2s]")
|
||||
* tx format: 0x00[L] 0x01[R] 0x02[L] 0x03[R] ...
|
||||
* rx receive: 0x01[R] 0x03[R] ... */
|
||||
TEST_ESP_OK(i2s_channel_write(tx_handle, w_buf, WRITE_BUF_LEN, &w_bytes, portMAX_DELAY));
|
||||
for (retry = 0, index = READ_BUF_LEN / 2; (retry < RETEY_TIMES) && (index >= READ_BUF_LEN / 2 - 50); retry++) {
|
||||
for (retry = 0; retry < RETEY_TIMES; retry++) {
|
||||
TEST_ESP_OK(i2s_channel_read(rx_handle, r_buf, READ_BUF_LEN, &r_bytes, portMAX_DELAY));
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
/* The data of tx/rx channels are flipped on ESP32 */
|
||||
@@ -449,12 +458,15 @@ TEST_CASE("I2S_mono_stereo_loopback_test", "[i2s]")
|
||||
r_buf[n+1] = temp;
|
||||
}
|
||||
#endif
|
||||
index = get_start_index(r_buf, READ_BUF_LEN / 2, 1);
|
||||
/* Expected: 1 3 5 7 9 ... 97 99 */
|
||||
if (whether_contains_exapected_data(r_buf, READ_BUF_LEN / 2, 1, 1, 2)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
printf("Data start index: %d\n", index);
|
||||
TEST_ASSERT(index < READ_BUF_LEN / 2 - 50);
|
||||
for (int16_t j = 1; j < 100; j += 2) {
|
||||
TEST_ASSERT_EQUAL_INT16(r_buf[index++], j);
|
||||
if (retry >= RETEY_TIMES) {
|
||||
printf("rx right mono test failed\n");
|
||||
is_failed = true;
|
||||
goto err;
|
||||
}
|
||||
printf("rx right mono test passed\n");
|
||||
|
||||
@@ -468,7 +480,7 @@ TEST_CASE("I2S_mono_stereo_loopback_test", "[i2s]")
|
||||
TEST_ESP_OK(i2s_channel_enable(tx_handle));
|
||||
TEST_ESP_OK(i2s_channel_enable(rx_handle));
|
||||
TEST_ESP_OK(i2s_channel_write(tx_handle, w_buf, WRITE_BUF_LEN, &w_bytes, portMAX_DELAY));
|
||||
for (retry = 0, index = READ_BUF_LEN / 2; (retry < RETEY_TIMES) && (index >= READ_BUF_LEN / 2 - 50); retry++) {
|
||||
for (retry = 0; retry < RETEY_TIMES; retry++) {
|
||||
TEST_ESP_OK(i2s_channel_read(rx_handle, r_buf, READ_BUF_LEN, &r_bytes, portMAX_DELAY));
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
/* The data of tx/rx channels are flipped on ESP32 */
|
||||
@@ -478,12 +490,15 @@ TEST_CASE("I2S_mono_stereo_loopback_test", "[i2s]")
|
||||
r_buf[n+1] = temp;
|
||||
}
|
||||
#endif
|
||||
index = get_start_index(r_buf, READ_BUF_LEN / 2, 2);
|
||||
/* Expected: 2 4 6 8 10 ... 96 98 */
|
||||
if (whether_contains_exapected_data(r_buf, READ_BUF_LEN / 2, 1, 2, 2)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
printf("Data start index: %d\n", index);
|
||||
TEST_ASSERT(index < READ_BUF_LEN / 2 - 50);
|
||||
for (int16_t j = 2; j < 100; j += 2) {
|
||||
TEST_ASSERT_EQUAL_INT16(r_buf[index++], j);
|
||||
if (retry >= RETEY_TIMES) {
|
||||
printf("rx left mono test failed\n");
|
||||
is_failed = true;
|
||||
goto err;
|
||||
}
|
||||
printf("rx left mono test passed\n");
|
||||
|
||||
@@ -498,15 +513,17 @@ TEST_CASE("I2S_mono_stereo_loopback_test", "[i2s]")
|
||||
TEST_ESP_OK(i2s_channel_enable(tx_handle));
|
||||
TEST_ESP_OK(i2s_channel_enable(rx_handle));
|
||||
TEST_ESP_OK(i2s_channel_write(tx_handle, w_buf, WRITE_BUF_LEN, &w_bytes, portMAX_DELAY));
|
||||
for (retry = 0, index = READ_BUF_LEN / 2; (retry < RETEY_TIMES) && (index >= READ_BUF_LEN / 2 - 100); retry++) {
|
||||
for (retry = 0; retry < RETEY_TIMES; retry++) {
|
||||
TEST_ESP_OK(i2s_channel_read(rx_handle, r_buf, READ_BUF_LEN, &r_bytes, portMAX_DELAY));
|
||||
index = get_start_index(r_buf, READ_BUF_LEN / 2, 1);
|
||||
/* Expected: 1 2 3 4 ... 98 99 */
|
||||
if (whether_contains_exapected_data(r_buf, READ_BUF_LEN / 2, 1, 1, 1)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
printf("Data start index: %d\n", index);
|
||||
TEST_ASSERT(index < READ_BUF_LEN / 2 - 100);
|
||||
for (int16_t j = 1; j < 100; j ++) {
|
||||
TEST_ASSERT_EQUAL_INT16(r_buf[index++], j); // receive all number
|
||||
if (retry >= RETEY_TIMES) {
|
||||
printf("tx/rx stereo test failed\n");
|
||||
is_failed = true;
|
||||
goto err;
|
||||
}
|
||||
printf("tx/rx stereo test passed\n");
|
||||
|
||||
@@ -522,25 +539,35 @@ TEST_CASE("I2S_mono_stereo_loopback_test", "[i2s]")
|
||||
TEST_ESP_OK(i2s_channel_enable(tx_handle));
|
||||
TEST_ESP_OK(i2s_channel_enable(rx_handle));
|
||||
TEST_ESP_OK(i2s_channel_write(tx_handle, w_buf, WRITE_BUF_LEN, &w_bytes, portMAX_DELAY));
|
||||
for (retry = 0, index = READ_BUF_LEN / 2; (retry < RETEY_TIMES) && (index >= READ_BUF_LEN / 2 - 100); retry++) {
|
||||
for (retry = 0; retry < RETEY_TIMES; retry++) {
|
||||
TEST_ESP_OK(i2s_channel_read(rx_handle, r_buf, READ_BUF_LEN, &r_bytes, portMAX_DELAY));
|
||||
index = get_start_index(r_buf, READ_BUF_LEN / 2, 1);
|
||||
/* Expected: 1 x 2 x 3 x ... 98 x 99 */
|
||||
if (whether_contains_exapected_data(r_buf, READ_BUF_LEN / 2, 2, 1, 1)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
printf("Data start index: %d\n", index);
|
||||
TEST_ASSERT(index < READ_BUF_LEN / 2 - 200);
|
||||
for (int16_t j = 1; j < 100; j ++) {
|
||||
TEST_ASSERT_EQUAL_INT16(r_buf[index], j);
|
||||
index += 2;
|
||||
if (retry >= RETEY_TIMES) {
|
||||
printf("tx mono rx stereo test failed\n");
|
||||
is_failed = true;
|
||||
goto err;
|
||||
}
|
||||
printf("tx mono rx stereo test passed\n");
|
||||
#endif
|
||||
|
||||
err:
|
||||
if (is_failed) {
|
||||
for (int i = 0; i < READ_BUF_LEN / 2; i++) {
|
||||
printf("%x ", r_buf[i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
free(w_buf);
|
||||
free(r_buf);
|
||||
TEST_ESP_OK(i2s_channel_disable(tx_handle));
|
||||
TEST_ESP_OK(i2s_channel_disable(rx_handle));
|
||||
TEST_ESP_OK(i2s_del_channel(tx_handle));
|
||||
TEST_ESP_OK(i2s_del_channel(rx_handle));
|
||||
TEST_ASSERT_FALSE(is_failed);
|
||||
}
|
||||
|
||||
TEST_CASE("I2S_memory_leak_test", "[i2s]")
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
CONFIG_COMPILER_DUMP_RTL_FILES=y
|
||||
CONFIG_I2S_ISR_IRAM_SAFE=y
|
||||
|
||||
CONFIG_COMPILER_OPTIMIZATION_NONE=y
|
||||
# silent the error check, as the error string are stored in rodata, causing RTL check failure
|
||||
CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT=y
|
||||
|
||||
@@ -3,7 +3,6 @@ CONFIG_FREERTOS_USE_TICKLESS_IDLE=y
|
||||
CONFIG_COMPILER_OPTIMIZATION_SIZE=y
|
||||
CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y
|
||||
CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT=y
|
||||
CONFIG_I2S_ISR_IRAM_SAFE=y
|
||||
CONFIG_COMPILER_DUMP_RTL_FILES=y
|
||||
# silent the error check, as the error string are stored in rodata, causing RTL check failure
|
||||
CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT=y
|
||||
|
||||
@@ -3,3 +3,4 @@ set(srcs "test_app_main.c"
|
||||
|
||||
idf_component_register(SRCS ${srcs}
|
||||
WHOLE_ARCHIVE)
|
||||
target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format")
|
||||
|
||||
@@ -29,6 +29,9 @@
|
||||
#include "driver/pulse_cnt.h"
|
||||
#include "soc/pcnt_periph.h"
|
||||
#endif
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
#include "esp_pm.h"
|
||||
#endif
|
||||
|
||||
#include "../../test_inc/test_i2s.h"
|
||||
|
||||
@@ -211,6 +214,28 @@ TEST_CASE("I2S_basic_driver_installation_uninstallation_and_settings_test", "[i2
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_STATE, i2s_driver_uninstall(I2S_NUM_0));
|
||||
}
|
||||
|
||||
static bool whether_contains_exapected_data(uint16_t *src, uint32_t src_len, uint32_t src_step, uint32_t start_val, uint32_t val_step)
|
||||
{
|
||||
uint32_t val = start_val;
|
||||
uint32_t index_step = 1;
|
||||
for (int i = 0; val < 100 && i < src_len; i += index_step) {
|
||||
if (src[i] == val) {
|
||||
if (val == start_val && i < src_len - 8) {
|
||||
printf("start index: %d ---> \n%d %d %d %d %d %d %d %d\n", i,
|
||||
src[i], src[i+1], src[i+2], src[i+3],
|
||||
src[i+4], src[i+5], src[i+6], src[i+7]);
|
||||
}
|
||||
index_step = src_step;
|
||||
val += val_step;
|
||||
} else {
|
||||
index_step = 1;
|
||||
val = start_val;
|
||||
}
|
||||
}
|
||||
|
||||
return val >= 100;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Test mono and stereo mode of I2S by loopback
|
||||
* @note Only rx channel distinguish left mono and right mono, tx channel does not
|
||||
@@ -222,6 +247,7 @@ TEST_CASE("I2S_mono_stereo_loopback_test", "[i2s_legacy]")
|
||||
{
|
||||
#define WRITE_BUF_LEN 2000
|
||||
#define READ_BUF_LEN 4000
|
||||
#define RETEY_TIMES 3
|
||||
// master driver installed and send data
|
||||
i2s_config_t master_i2s_config = {
|
||||
.mode = I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_RX,
|
||||
@@ -269,6 +295,8 @@ TEST_CASE("I2S_mono_stereo_loopback_test", "[i2s_legacy]")
|
||||
uint16_t *r_buf = calloc(1, READ_BUF_LEN);
|
||||
size_t w_bytes = 0;
|
||||
size_t r_bytes = 0;
|
||||
uint32_t retry = 0;
|
||||
bool is_failed = false;
|
||||
for (int n = 0; n < WRITE_BUF_LEN / 2; n++) {
|
||||
w_buf[n] = n%100;
|
||||
}
|
||||
@@ -276,28 +304,25 @@ TEST_CASE("I2S_mono_stereo_loopback_test", "[i2s_legacy]")
|
||||
* tx format: 0x00[L] 0x01[R] 0x02[L] 0x03[R] ...
|
||||
* rx receive: 0x01[R] 0x03[R] ... */
|
||||
TEST_ESP_OK(i2s_write(I2S_NUM_0, w_buf, WRITE_BUF_LEN, &w_bytes, portMAX_DELAY));
|
||||
TEST_ESP_OK(i2s_read(I2S_NUM_0, r_buf, READ_BUF_LEN, &r_bytes, portMAX_DELAY));
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
/* The data of tx/rx channels are flipped on ESP32 */
|
||||
for (int n = 0; n < READ_BUF_LEN / 2; n += 2) {
|
||||
int16_t temp = r_buf[n];
|
||||
r_buf[n] = r_buf[n+1];
|
||||
r_buf[n+1] = temp;
|
||||
}
|
||||
#endif
|
||||
int i = 0;
|
||||
for (i = 0; (i < READ_BUF_LEN / 2); i++) {
|
||||
if (r_buf[i] == 1) {
|
||||
printf("%d %d %d %d\n%d %d %d %d\n",
|
||||
r_buf[i], r_buf[i+1], r_buf[i+2], r_buf[i+3],
|
||||
r_buf[i+4], r_buf[i+5], r_buf[i+6], r_buf[i+7]);
|
||||
for (retry = 0; retry < RETEY_TIMES; retry++) {
|
||||
TEST_ESP_OK(i2s_read(I2S_NUM_0, r_buf, READ_BUF_LEN, &r_bytes, portMAX_DELAY));
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
/* The data of tx/rx channels are flipped on ESP32 */
|
||||
for (int n = 0; n < READ_BUF_LEN / 2; n += 2) {
|
||||
int16_t temp = r_buf[n];
|
||||
r_buf[n] = r_buf[n+1];
|
||||
r_buf[n+1] = temp;
|
||||
}
|
||||
#endif
|
||||
/* Expected: 1 3 5 7 9 ... 97 99 */
|
||||
if (whether_contains_exapected_data(r_buf, READ_BUF_LEN / 2, 1, 1, 2)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
printf("Data start index: %d\n", i);
|
||||
TEST_ASSERT(i < READ_BUF_LEN / 2 - 50);
|
||||
for (int16_t j = 1; j < 100; j += 2) {
|
||||
TEST_ASSERT_EQUAL_INT16(r_buf[i++], j);
|
||||
if (retry >= RETEY_TIMES) {
|
||||
printf("rx right mono test failed\n");
|
||||
is_failed = true;
|
||||
goto err;
|
||||
}
|
||||
printf("rx right mono test passed\n");
|
||||
|
||||
@@ -306,21 +331,17 @@ TEST_CASE("I2S_mono_stereo_loopback_test", "[i2s_legacy]")
|
||||
* rx receive: 0x00[L] 0x01[R] 0x02[L] 0x03[R] ... */
|
||||
TEST_ESP_OK(i2s_set_clk(I2S_NUM_0, SAMPLE_RATE, SAMPLE_BITS, I2S_CHANNEL_STEREO));
|
||||
TEST_ESP_OK(i2s_write(I2S_NUM_0, w_buf, WRITE_BUF_LEN, &w_bytes, portMAX_DELAY));
|
||||
TEST_ESP_OK(i2s_read(I2S_NUM_0, r_buf, READ_BUF_LEN, &r_bytes, portMAX_DELAY));
|
||||
|
||||
for (i = 0; (i < READ_BUF_LEN / 2); i++) {
|
||||
if (r_buf[i] == 1) {
|
||||
printf("%d %d %d %d\n%d %d %d %d\n",
|
||||
r_buf[i], r_buf[i+1], r_buf[i+2], r_buf[i+3],
|
||||
r_buf[i+4], r_buf[i+5], r_buf[i+6], r_buf[i+7]);
|
||||
for (retry = 0; retry < RETEY_TIMES; retry++) {
|
||||
TEST_ESP_OK(i2s_read(I2S_NUM_0, r_buf, READ_BUF_LEN, &r_bytes, portMAX_DELAY));
|
||||
/* Expected: 1 2 3 4 ... 98 99 */
|
||||
if (whether_contains_exapected_data(r_buf, READ_BUF_LEN / 2, 1, 1, 1)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
printf("Data start index: %d\n", i);
|
||||
TEST_ASSERT(i < READ_BUF_LEN / 2 - 100);
|
||||
TEST_ASSERT(i % 2);
|
||||
for (int16_t j = 1; j < 100; j ++) {
|
||||
TEST_ASSERT_EQUAL_INT16(r_buf[i++], j); // receive all number
|
||||
if (retry >= RETEY_TIMES) {
|
||||
printf("tx/rx stereo test failed\n");
|
||||
is_failed = true;
|
||||
goto err;
|
||||
}
|
||||
printf("tx/rx stereo test passed\n");
|
||||
|
||||
@@ -329,20 +350,17 @@ TEST_CASE("I2S_mono_stereo_loopback_test", "[i2s_legacy]")
|
||||
* rx receive: 0x01[R] 0x02[R] ... */
|
||||
TEST_ESP_OK(i2s_set_clk(I2S_NUM_0, SAMPLE_RATE, I2S_BITS_PER_SAMPLE_32BIT, I2S_CHANNEL_MONO));
|
||||
TEST_ESP_OK(i2s_write(I2S_NUM_0, w_buf, WRITE_BUF_LEN, &w_bytes, portMAX_DELAY));
|
||||
TEST_ESP_OK(i2s_read(I2S_NUM_0, r_buf, READ_BUF_LEN, &r_bytes, portMAX_DELAY));
|
||||
|
||||
for (i = 0; i < READ_BUF_LEN / 2; i++) {
|
||||
if (r_buf[i] == 1) {
|
||||
printf("%d %d %d %d\n%d %d %d %d\n",
|
||||
r_buf[i], r_buf[i+1], r_buf[i+2], r_buf[i+3],
|
||||
r_buf[i+4], r_buf[i+5], r_buf[i+6], r_buf[i+7]);
|
||||
for (retry = 0; retry < RETEY_TIMES; retry++) {
|
||||
TEST_ESP_OK(i2s_read(I2S_NUM_0, r_buf, READ_BUF_LEN, &r_bytes, portMAX_DELAY));
|
||||
/* Expected: 1 2 3 4 ... 98 99 */
|
||||
if (whether_contains_exapected_data(r_buf, READ_BUF_LEN / 2, 1, 1, 1)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
printf("Data start index: %d\n", i);
|
||||
TEST_ASSERT(i < READ_BUF_LEN / 2 - 100);
|
||||
for (int16_t j = 1; j < 100; j ++) {
|
||||
TEST_ASSERT_EQUAL_INT16(r_buf[i++], j);
|
||||
if (retry >= RETEY_TIMES) {
|
||||
printf("tx/rx mono test failed\n");
|
||||
is_failed = true;
|
||||
goto err;
|
||||
}
|
||||
printf("tx/rx mono test passed\n");
|
||||
|
||||
@@ -364,33 +382,39 @@ TEST_CASE("I2S_mono_stereo_loopback_test", "[i2s_legacy]")
|
||||
* tx format: 0x00[L] 0x01[R] 0x02[L] 0x03[R] ...
|
||||
* rx receive: 0x00[R] 0x02[R] ... */
|
||||
TEST_ESP_OK(i2s_write(I2S_NUM_0, w_buf, WRITE_BUF_LEN, &w_bytes, portMAX_DELAY));
|
||||
TEST_ESP_OK(i2s_read(I2S_NUM_0, r_buf, READ_BUF_LEN, &r_bytes, portMAX_DELAY));
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
/* The data of tx/rx channels are flipped on ESP32 */
|
||||
for (int n = 0; n < READ_BUF_LEN / 2; n += 2) {
|
||||
int16_t temp = r_buf[n];
|
||||
r_buf[n] = r_buf[n+1];
|
||||
r_buf[n+1] = temp;
|
||||
}
|
||||
#endif
|
||||
for (i = 0; (i < READ_BUF_LEN / 2); i++) {
|
||||
if (r_buf[i] == 2) {
|
||||
printf("%d %d %d %d\n%d %d %d %d\n",
|
||||
r_buf[i], r_buf[i+1], r_buf[i+2], r_buf[i+3],
|
||||
r_buf[i+4], r_buf[i+5], r_buf[i+6], r_buf[i+7]);
|
||||
for (retry = 0; retry < RETEY_TIMES; retry++) {
|
||||
TEST_ESP_OK(i2s_read(I2S_NUM_0, r_buf, READ_BUF_LEN, &r_bytes, portMAX_DELAY));
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
/* The data of tx/rx channels are flipped on ESP32 */
|
||||
for (int n = 0; n < READ_BUF_LEN / 2; n += 2) {
|
||||
int16_t temp = r_buf[n];
|
||||
r_buf[n] = r_buf[n+1];
|
||||
r_buf[n+1] = temp;
|
||||
}
|
||||
#endif
|
||||
/* Expected: 2 4 6 8 10 ... 96 98 */
|
||||
if (whether_contains_exapected_data(r_buf, READ_BUF_LEN / 2, 1, 2, 2)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
printf("Data start index: %d\n", i);
|
||||
TEST_ASSERT(i < READ_BUF_LEN / 2 - 50);
|
||||
for (int16_t j = 2; j < 100; j += 2) {
|
||||
TEST_ASSERT_EQUAL_INT16(r_buf[i++], j);
|
||||
if (retry >= RETEY_TIMES) {
|
||||
printf("rx left mono test failed\n");
|
||||
is_failed = true;
|
||||
goto err;
|
||||
}
|
||||
printf("rx left mono test passed\n");
|
||||
|
||||
err:
|
||||
if (is_failed) {
|
||||
for (int i = 0; i < READ_BUF_LEN / 2; i++) {
|
||||
printf("%x ", r_buf[i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
free(w_buf);
|
||||
free(r_buf);
|
||||
TEST_ESP_OK(i2s_driver_uninstall(I2S_NUM_0));
|
||||
TEST_ASSERT_FALSE(is_failed);
|
||||
}
|
||||
|
||||
#if SOC_I2S_SUPPORTS_TDM
|
||||
@@ -854,6 +878,14 @@ static void i2s_test_common_sample_rate(i2s_port_t id)
|
||||
32000, 44100, 48000, 64000, 88200, 96000,
|
||||
128000, 144000, 196000};
|
||||
int real_pulse = 0;
|
||||
|
||||
// Acquire the PM lock incase Dynamic Frequency Scaling(DFS) lower the frequency
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
esp_pm_lock_handle_t pm_lock;
|
||||
esp_pm_lock_type_t pm_type = ESP_PM_APB_FREQ_MAX;
|
||||
TEST_ESP_OK(esp_pm_lock_create(pm_type, 0, "legacy_i2s_test", &pm_lock));
|
||||
esp_pm_lock_acquire(pm_lock);
|
||||
#endif
|
||||
for (int i = 0; i < 15; i++) {
|
||||
int expt_pulse = (int16_t)((float)test_freq[i] * (TEST_I2S_PERIOD_MS / 1000.0));
|
||||
TEST_ESP_OK(i2s_set_clk(id, test_freq[i], SAMPLE_BITS, I2S_CHANNEL_STEREO));
|
||||
@@ -868,6 +900,10 @@ static void i2s_test_common_sample_rate(i2s_port_t id)
|
||||
// Check if the error between real pulse number and expected pulse number is within 1%
|
||||
TEST_ASSERT_INT_WITHIN(expt_pulse * 0.01, expt_pulse, real_pulse);
|
||||
}
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
esp_pm_lock_release(pm_lock);
|
||||
esp_pm_lock_delete(pm_lock);
|
||||
#endif
|
||||
TEST_ESP_OK(pcnt_del_channel(pcnt_chan));
|
||||
TEST_ESP_OK(pcnt_unit_stop(pcnt_unit));
|
||||
TEST_ESP_OK(pcnt_unit_disable(pcnt_unit));
|
||||
|
||||
@@ -3,4 +3,3 @@ CONFIG_FREERTOS_USE_TICKLESS_IDLE=y
|
||||
CONFIG_COMPILER_OPTIMIZATION_SIZE=y
|
||||
CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y
|
||||
CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT=y
|
||||
CONFIG_I2S_ISR_IRAM_SAFE=y
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
|
||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||
#define ADC_TEST_LOW_VAL 0
|
||||
#define ADC_TEST_LOW_THRESH 30
|
||||
#define ADC_TEST_LOW_THRESH 50
|
||||
|
||||
#define ADC_TEST_HIGH_VAL 4095
|
||||
#define ADC_TEST_HIGH_THRESH 10
|
||||
|
||||
@@ -3,3 +3,4 @@ set(srcs "test_app_main.c"
|
||||
|
||||
idf_component_register(SRCS ${srcs}
|
||||
WHOLE_ARCHIVE)
|
||||
target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format")
|
||||
|
||||
@@ -8,7 +8,12 @@ set(srcs "test_app_main.c"
|
||||
"test_mcpwm_timer.c"
|
||||
"test_mcpwm_utils.c")
|
||||
|
||||
if(CONFIG_MCPWM_ISR_IRAM_SAFE)
|
||||
list(APPEND srcs "test_mcpwm_iram.c")
|
||||
endif()
|
||||
|
||||
# In order for the cases defined by `TEST_CASE` to be linked into the final elf,
|
||||
# the component can be registered as WHOLE_ARCHIVE
|
||||
idf_component_register(SRCS ${srcs}
|
||||
WHOLE_ARCHIVE)
|
||||
target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format")
|
||||
|
||||
90
components/driver/test_apps/mcpwm/main/test_mcpwm_iram.c
Normal file
90
components/driver/test_apps/mcpwm/main/test_mcpwm_iram.c
Normal file
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/event_groups.h"
|
||||
#include "unity.h"
|
||||
#include "soc/soc_caps.h"
|
||||
#include "esp_private/esp_clk.h"
|
||||
#include "esp_private/spi_flash_os.h"
|
||||
#include "driver/mcpwm_cap.h"
|
||||
#include "driver/mcpwm_sync.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "test_mcpwm_utils.h"
|
||||
|
||||
static bool IRAM_ATTR test_capture_callback_iram_safe(mcpwm_cap_channel_handle_t cap_channel, const mcpwm_capture_event_data_t *edata, void *user_data)
|
||||
{
|
||||
uint32_t *cap_value = (uint32_t *)user_data;
|
||||
if (edata->cap_edge == MCPWM_CAP_EDGE_NEG) {
|
||||
cap_value[1] = edata->cap_value;
|
||||
} else {
|
||||
cap_value[0] = edata->cap_value;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void IRAM_ATTR test_mcpwm_capture_gpio_simulate(int gpio_sig)
|
||||
{
|
||||
// disable flash cache
|
||||
spi_flash_guard_get()->start();
|
||||
gpio_set_level(gpio_sig, 1);
|
||||
esp_rom_delay_us(1000);
|
||||
gpio_set_level(gpio_sig, 0);
|
||||
// enable flash cache
|
||||
spi_flash_guard_get()->end();
|
||||
}
|
||||
|
||||
TEST_CASE("mcpwm_capture_iram_safe", "[mcpwm]")
|
||||
{
|
||||
printf("install mcpwm capture timer\r\n");
|
||||
mcpwm_cap_timer_handle_t cap_timer = NULL;
|
||||
mcpwm_capture_timer_config_t cap_timer_config = {
|
||||
.clk_src = MCPWM_CAPTURE_CLK_SRC_APB,
|
||||
.group_id = 0,
|
||||
};
|
||||
TEST_ESP_OK(mcpwm_new_capture_timer(&cap_timer_config, &cap_timer));
|
||||
|
||||
const int cap_gpio = 0;
|
||||
// put the GPIO into a preset state
|
||||
gpio_set_level(cap_gpio, 0);
|
||||
|
||||
printf("install mcpwm capture channel\r\n");
|
||||
mcpwm_cap_channel_handle_t pps_channel;
|
||||
mcpwm_capture_channel_config_t cap_chan_config = {
|
||||
.gpio_num = cap_gpio,
|
||||
.prescale = 1,
|
||||
.flags.pos_edge = true,
|
||||
.flags.neg_edge = true,
|
||||
.flags.io_loop_back = true, // so we can use GPIO functions to simulate the external capture signal
|
||||
.flags.pull_up = true,
|
||||
};
|
||||
TEST_ESP_OK(mcpwm_new_capture_channel(cap_timer, &cap_chan_config, &pps_channel));
|
||||
|
||||
printf("install callback for capture channel\r\n");
|
||||
mcpwm_capture_event_callbacks_t cbs = {
|
||||
.on_cap = test_capture_callback_iram_safe,
|
||||
};
|
||||
uint32_t cap_value[2] = {0};
|
||||
TEST_ESP_OK(mcpwm_capture_channel_register_event_callbacks(pps_channel, &cbs, cap_value));
|
||||
|
||||
printf("enable and start capture timer\r\n");
|
||||
TEST_ESP_OK(mcpwm_capture_timer_enable(cap_timer));
|
||||
TEST_ESP_OK(mcpwm_capture_timer_start(cap_timer));
|
||||
|
||||
printf("disable cache, simulate GPIO capture signal\r\n");
|
||||
test_mcpwm_capture_gpio_simulate(cap_gpio);
|
||||
|
||||
printf("capture value: Pos=%u, Neg=%u\r\n", cap_value[0], cap_value[1]);
|
||||
// Capture timer is clocked from APB by default
|
||||
uint32_t clk_src_res = esp_clk_apb_freq();
|
||||
TEST_ASSERT_UINT_WITHIN(2000, clk_src_res / 1000, cap_value[1] - cap_value[0]);
|
||||
|
||||
printf("uninstall capture channel and timer\r\n");
|
||||
TEST_ESP_OK(mcpwm_del_capture_channel(pps_channel));
|
||||
TEST_ESP_OK(mcpwm_capture_timer_disable(cap_timer));
|
||||
TEST_ESP_OK(mcpwm_del_capture_timer(cap_timer));
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
CONFIG_COMPILER_DUMP_RTL_FILES=y
|
||||
CONFIG_MCPWM_ISR_IRAM_SAFE=y
|
||||
|
||||
CONFIG_GPIO_CTRL_FUNC_IN_IRAM=y
|
||||
CONFIG_COMPILER_OPTIMIZATION_NONE=y
|
||||
# silent the error check, as the error string are stored in rodata, causing RTL check failure
|
||||
CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT=y
|
||||
|
||||
@@ -2,6 +2,6 @@ CONFIG_COMPILER_DUMP_RTL_FILES=y
|
||||
CONFIG_PCNT_CTRL_FUNC_IN_IRAM=y
|
||||
CONFIG_PCNT_ISR_IRAM_SAFE=y
|
||||
CONFIG_GPIO_CTRL_FUNC_IN_IRAM=y
|
||||
|
||||
CONFIG_COMPILER_OPTIMIZATION_NONE=y
|
||||
# silent the error check, as the error string are stored in rodata, causing RTL check failure
|
||||
CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT=y
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
CONFIG_COMPILER_DUMP_RTL_FILES=y
|
||||
CONFIG_RMT_ISR_IRAM_SAFE=y
|
||||
|
||||
CONFIG_COMPILER_OPTIMIZATION_NONE=y
|
||||
# silent the error check, as the error string are stored in rodata, causing RTL check failure
|
||||
CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT=y
|
||||
CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT=y
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
CONFIG_COMPILER_DUMP_RTL_FILES=y
|
||||
CONFIG_SDM_CTRL_FUNC_IN_IRAM=y
|
||||
|
||||
CONFIG_COMPILER_OPTIMIZATION_NONE=y
|
||||
# silent the error check, as the error string are stored in rodata, causing RTL check failure
|
||||
CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT=y
|
||||
|
||||
@@ -77,3 +77,5 @@ set(EFUSE_TEST_TABLE_CSV_PATH "${COMPONENT_DIR}/test/esp_efuse_test_table.csv")
|
||||
add_custom_target(efuse_test_table COMMAND "${python}"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/efuse_table_gen.py"
|
||||
${EFUSE_TEST_TABLE_CSV_PATH} ${GEN_EFUSE_TABLE_ARG})
|
||||
|
||||
target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format")
|
||||
|
||||
@@ -248,6 +248,7 @@ class FuseTable(list):
|
||||
'extern "C" {',
|
||||
'#endif',
|
||||
'',
|
||||
'#include "esp_efuse.h"',
|
||||
'',
|
||||
'// md5_digest_table ' + self.md5_digest_table,
|
||||
'// This file was generated from the file ' + file_name + '.csv. DO NOT CHANGE THIS FILE MANUALLY.',
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "esp_efuse.h"
|
||||
|
||||
// md5_digest_table 6256f9b7c6783e0b651bf52b5b162aa8
|
||||
// This file was generated from the file esp_efuse_table.csv. DO NOT CHANGE THIS FILE MANUALLY.
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "esp_efuse.h"
|
||||
|
||||
// md5_digest_table ef050bc1e4bf0d8384aa3e4c0256d7d3
|
||||
// This file was generated from the file esp_efuse_table.csv. DO NOT CHANGE THIS FILE MANUALLY.
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "esp_efuse.h"
|
||||
|
||||
// md5_digest_table d006c80095638b5dbdc8649bf7e04dce
|
||||
// This file was generated from the file esp_efuse_table.csv. DO NOT CHANGE THIS FILE MANUALLY.
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "esp_efuse.h"
|
||||
|
||||
// md5_digest_table 4ff665f7ab2f32b83f2b5b232bcdeac8
|
||||
// This file was generated from the file esp_efuse_table.csv. DO NOT CHANGE THIS FILE MANUALLY.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user