mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Merge remote-tracking branch 'origin/master' into feature/github-5838
This commit is contained in:
commit
d98b3948b8
2
.github/workflows/python_lint.yml
vendored
2
.github/workflows/python_lint.yml
vendored
@ -13,7 +13,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: [2.7, 3.5, 3.6, 3.7, 3.8]
|
||||
python-version: [3.6, 3.7, 3.8]
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -88,3 +88,6 @@ build
|
||||
|
||||
# lock files for examples and components
|
||||
dependencies.lock
|
||||
|
||||
# managed_components for examples
|
||||
managed_components
|
||||
|
@ -48,10 +48,11 @@ variables:
|
||||
|
||||
# Docker images
|
||||
BOT_DOCKER_IMAGE_TAG: ":latest"
|
||||
ESP_IDF_DOC_ENV_IMAGE: "$CI_DOCKER_REGISTRY/esp-idf-doc-env:v4.4-1-v3"
|
||||
ESP_IDF_DOC_ENV_IMAGE: "$CI_DOCKER_REGISTRY/esp-idf-doc-env:v4.4-1-v4"
|
||||
ESP_ENV_IMAGE: "$CI_DOCKER_REGISTRY/esp-env:v4.4-1"
|
||||
AFL_FUZZER_TEST_IMAGE: "$CI_DOCKER_REGISTRY/afl-fuzzer-test:v4.4-1-1"
|
||||
CLANG_STATIC_ANALYSIS_IMAGE: "${CI_DOCKER_REGISTRY}/clang-static-analysis:v4.4-1-2"
|
||||
SONARQUBE_SCANNER_IMAGE: "${CI_DOCKER_REGISTRY}/sonarqube-scanner:3"
|
||||
|
||||
# target test config file, used by assign test job
|
||||
CI_TARGET_TEST_CONFIG_FILE: "$CI_PROJECT_DIR/.gitlab/ci/target-test.yml"
|
||||
|
@ -161,6 +161,7 @@
|
||||
/examples/ethernet/ @esp-idf-codeowners/network
|
||||
/examples/get-started/ @esp-idf-codeowners/system
|
||||
/examples/mesh/ @esp-idf-codeowners/wifi
|
||||
/examples/network/ @esp-idf-codeowners/network @esp-idf-codeowners/wifi
|
||||
/examples/openthread/ @esp-idf-codeowners/ieee802154
|
||||
/examples/peripherals/ @esp-idf-codeowners/peripherals
|
||||
/examples/protocols/ @esp-idf-codeowners/network @esp-idf-codeowners/app-utilities
|
||||
|
@ -221,6 +221,14 @@ build_examples_cmake_esp32s2:
|
||||
variables:
|
||||
IDF_TARGET: esp32s2
|
||||
|
||||
build_examples_cmake_esp32s3:
|
||||
extends:
|
||||
- .build_examples_cmake_template
|
||||
- .rules:build:example_test-esp32s3
|
||||
parallel: 8
|
||||
variables:
|
||||
IDF_TARGET: esp32s3
|
||||
|
||||
build_examples_cmake_esp32c3:
|
||||
extends:
|
||||
- .build_examples_cmake_template
|
||||
|
@ -66,7 +66,7 @@ check_docs_lang_sync:
|
||||
parallel:
|
||||
matrix:
|
||||
- DOCLANG: ["en", "zh_CN"]
|
||||
DOCTGT: ["esp32", "esp32s2", "esp32c3"]
|
||||
DOCTGT: ["esp32", "esp32s2", "esp32s3", "esp32c3"]
|
||||
|
||||
check_docs_gh_links:
|
||||
image: $ESP_IDF_DOC_ENV_IMAGE
|
||||
@ -128,13 +128,6 @@ build_docs_html_fast:
|
||||
variables:
|
||||
DOC_BUILDERS: "html"
|
||||
DOCS_FAST_BUILD: "yes"
|
||||
# matrix is redefined to include esp32s3 here
|
||||
# that we can build for S3 MRs during bringup phase without
|
||||
# anything being built and published from master branch
|
||||
parallel:
|
||||
matrix:
|
||||
- DOCLANG: ["en", "zh_CN"]
|
||||
DOCTGT: ["esp32", "esp32s2", "esp32s3", "esp32c3"]
|
||||
|
||||
build_docs_pdf:
|
||||
extends:
|
||||
|
@ -220,11 +220,6 @@ test_efuse_table_on_host_esp32s2:
|
||||
variables:
|
||||
IDF_TARGET: esp32s2
|
||||
|
||||
test_efuse_table_on_host_esp32s2:
|
||||
extends: .test_efuse_table_on_host_template
|
||||
variables:
|
||||
IDF_TARGET: esp32s2
|
||||
|
||||
test_efuse_table_on_host_esp32s3:
|
||||
extends: .test_efuse_table_on_host_template
|
||||
variables:
|
||||
@ -250,10 +245,11 @@ test_espcoredump:
|
||||
expire_in: 1 week
|
||||
variables:
|
||||
IDF_COREDUMP_ELF_REPO: "https://gitlab-ci-token:${BOT_TOKEN}@${CI_SERVER_HOST}:${CI_SERVER_PORT}/idf/idf-coredump-elf.git"
|
||||
IDF_COREDUMP_ELF_TAG: idf-20210910-00
|
||||
# install CMake version specified in tools.json
|
||||
SETUP_TOOLS_LIST: "all"
|
||||
script:
|
||||
- retry_failed git clone ${IDF_COREDUMP_ELF_REPO} -b master
|
||||
- retry_failed git clone ${IDF_COREDUMP_ELF_REPO} -b $IDF_COREDUMP_ELF_TAG
|
||||
- cd ${IDF_PATH}/components/espcoredump/test/
|
||||
- ./test_espcoredump.sh ${CI_PROJECT_DIR}/idf-coredump-elf
|
||||
|
||||
@ -367,3 +363,10 @@ test_cxx_gpio:
|
||||
- cd ${IDF_PATH}/examples/cxx/experimental/experimental_cpp_component/host_test/gpio
|
||||
- idf.py build
|
||||
- build/test_gpio_cxx_host.elf
|
||||
|
||||
test_linux_example:
|
||||
extends: .host_test_template
|
||||
script:
|
||||
- cd ${IDF_PATH}/examples/build_system/cmake/linux_host_app
|
||||
- idf.py build
|
||||
- build/linux_host_app.elf
|
||||
|
@ -113,6 +113,15 @@ check_public_headers:
|
||||
script:
|
||||
- python tools/ci/check_public_headers.py --jobs 4 --prefix xtensa-esp32-elf-
|
||||
|
||||
check_soc_struct_headers:
|
||||
extends:
|
||||
- .pre_check_base_template
|
||||
- .rules:build
|
||||
tags:
|
||||
- build
|
||||
script:
|
||||
- find ${IDF_PATH}/components/soc/*/include/soc/ -name "*_struct.h" -print0 | xargs -0 -n1 ./tools/ci/check_soc_struct_headers.py
|
||||
|
||||
check_esp_err_to_name:
|
||||
extends:
|
||||
- .pre_check_base_template
|
||||
|
@ -30,7 +30,7 @@ check_pylint:
|
||||
- .pre_check_base_template
|
||||
- .rules:patterns:python-files
|
||||
- .before_script_minimal
|
||||
image: $CI_DOCKER_REGISTRY/sonarqube-scanner:2
|
||||
image: $SONARQUBE_SCANNER_IMAGE
|
||||
artifacts:
|
||||
when: always
|
||||
paths:
|
||||
@ -62,11 +62,19 @@ check_pylint:
|
||||
.sonar_scan_template:
|
||||
stage: build
|
||||
image:
|
||||
name: $CI_DOCKER_REGISTRY/sonarqube-scanner:2
|
||||
name: $SONARQUBE_SCANNER_IMAGE
|
||||
before_script:
|
||||
- source tools/ci/utils.sh
|
||||
- export PYTHONPATH="$CI_PROJECT_DIR/tools:$CI_PROJECT_DIR/tools/ci/python_packages:$PYTHONPATH"
|
||||
- fetch_submodules
|
||||
# Exclude the submodules, all paths ends with /**
|
||||
- submodules=$(get_all_submodules)
|
||||
# get all exclude paths specified in tools/ci/sonar_exclude_list.txt | ignore lines start with # | xargs | replace all <space> to <comma>
|
||||
- custom_excludes=$(cat $CI_PROJECT_DIR/tools/ci/sonar_exclude_list.txt | grep -v '^#' | xargs | sed -e 's/ /,/g')
|
||||
# Exclude the report dir as well
|
||||
- export EXCLUSIONS="$custom_excludes,$submodules"
|
||||
- export SONAR_SCANNER_OPTS="-Xmx2048m"
|
||||
|
||||
variables:
|
||||
GIT_DEPTH: 0
|
||||
REPORT_PATTERN: clang_tidy_reports/*.txt
|
||||
@ -95,8 +103,10 @@ code_quality_check:
|
||||
-Dsonar.analysis.mode=preview
|
||||
-Dsonar.branch.name=$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME
|
||||
-Dsonar.cxx.clangtidy.reportPath=$REPORT_PATTERN
|
||||
-Dsonar.exclusions=$EXCLUSIONS
|
||||
-Dsonar.gitlab.ci_merge_request_iid=$CI_MERGE_REQUEST_IID
|
||||
-Dsonar.gitlab.commit_sha=$CI_MERGE_REQUEST_COMMITS
|
||||
-Dsonar.gitlab.merge_request_discussion=true
|
||||
-Dsonar.gitlab.ref_name=$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME
|
||||
-Dsonar.host.url=$SONAR_HOST_URL
|
||||
-Dsonar.login=$SONAR_LOGIN
|
||||
@ -112,6 +122,7 @@ code_quality_report:
|
||||
- sonar-scanner
|
||||
-Dsonar.branch.name=$CI_COMMIT_REF_NAME
|
||||
-Dsonar.cxx.clangtidy.reportPath=$REPORT_PATTERN
|
||||
-Dsonar.exclusions=$EXCLUSIONS
|
||||
-Dsonar.gitlab.commit_sha=$CI_COMMIT_SHA
|
||||
-Dsonar.gitlab.ref_name=$CI_COMMIT_REF_NAME
|
||||
-Dsonar.host.url=$SONAR_HOST_URL
|
||||
|
@ -46,7 +46,7 @@
|
||||
extends:
|
||||
- .example_test_template
|
||||
- .rules:test:example_test-esp32
|
||||
variables:
|
||||
variables:
|
||||
SUBMODULES_TO_FETCH: "all"
|
||||
|
||||
test_weekend_mqtt:
|
||||
@ -60,7 +60,7 @@ test_weekend_mqtt:
|
||||
- export MQTT_PUBLISH_TEST=1
|
||||
- export TEST_PATH=$CI_PROJECT_DIR/tools/test_apps/protocols/mqtt/publish_connect_test
|
||||
- cd $IDF_PATH/tools/ci/python_packages/tiny_test_fw/bin
|
||||
- run_cmd python Runner.py $TEST_PATH -c $TEST_PATH/publish_connect_mqtt_.yml -e $TEST_PATH/env.yml
|
||||
- run_cmd python Runner.py $TEST_PATH -c $TEST_PATH/publish_connect_mqtt_.yml
|
||||
|
||||
.example_test_esp32_template:
|
||||
extends:
|
||||
@ -129,7 +129,7 @@ example_test_002:
|
||||
- ESP32
|
||||
- Example_ShieldBox_Basic
|
||||
|
||||
example_test_enternet:
|
||||
example_test_ethernet:
|
||||
extends: .example_test_esp32_template
|
||||
tags:
|
||||
- ESP32
|
||||
@ -270,20 +270,17 @@ example_test_ESP32_SDSPI:
|
||||
- ESP32
|
||||
- UT_T1_SPIMODE
|
||||
|
||||
# uncomment when ESP32S2 & ESP32C3 runners with external SD connected over SPI are available
|
||||
# ensure the runners have required tags created
|
||||
#
|
||||
#example_test_ESP32S2_SDSPI:
|
||||
# extends: .example_test_esp32s2_template
|
||||
# tags:
|
||||
# - ESP32S2
|
||||
# - UT_T1_SPIMODE
|
||||
#
|
||||
#example_test_ESP32C3_SDSPI:
|
||||
# extends: .example_test_esp32c3_template
|
||||
# tags:
|
||||
# - ESP32C3
|
||||
# - UT_T1_SPIMODE
|
||||
example_test_ESP32S2_SDSPI:
|
||||
extends: .example_test_esp32s2_template
|
||||
tags:
|
||||
- ESP32S2
|
||||
- UT_T1_SPIMODE
|
||||
|
||||
example_test_ESP32C3_SDSPI:
|
||||
extends: .example_test_esp32c3_template
|
||||
tags:
|
||||
- ESP32C3
|
||||
- UT_T1_SPIMODE
|
||||
|
||||
.test_app_template:
|
||||
extends: .target_test_job_template
|
||||
@ -482,7 +479,7 @@ UT_006:
|
||||
|
||||
UT_007:
|
||||
extends: .unit_test_esp32_template
|
||||
parallel: 3
|
||||
parallel: 4
|
||||
tags:
|
||||
- ESP32_IDF
|
||||
- UT_T1_1
|
||||
@ -633,7 +630,7 @@ UT_046:
|
||||
|
||||
UT_047:
|
||||
extends: .unit_test_esp32s2_template
|
||||
parallel: 3
|
||||
parallel: 5
|
||||
tags:
|
||||
- ESP32S2_IDF
|
||||
- UT_T1_1
|
||||
@ -644,6 +641,12 @@ UT_S2_SPI_DUAL:
|
||||
- ESP32S2_IDF
|
||||
- Example_SPI_Multi_device
|
||||
|
||||
UT_S2_SDSPI:
|
||||
extends: .unit_test_esp32s2_template
|
||||
tags:
|
||||
- ESP32S2_IDF
|
||||
- UT_T1_SPIMODE
|
||||
|
||||
UT_C3:
|
||||
extends: .unit_test_esp32c3_template
|
||||
parallel: 32
|
||||
@ -682,9 +685,15 @@ UT_C3_FLASH_SUSPEND:
|
||||
- ESP32C3_IDF
|
||||
- UT_T1_Flash_Suspend
|
||||
|
||||
UT_C3_SDSPI:
|
||||
extends: .unit_test_esp32c3_template
|
||||
tags:
|
||||
- ESP32C3_IDF
|
||||
- UT_T1_SPIMODE
|
||||
|
||||
UT_S3:
|
||||
extends: .unit_test_esp32s3_template
|
||||
parallel: 27
|
||||
parallel: 29
|
||||
tags:
|
||||
- ESP32S3_IDF
|
||||
- UT_T1_1
|
||||
@ -702,6 +711,18 @@ UT_S3_FLASH:
|
||||
- ESP32S3_IDF
|
||||
- UT_T1_ESP_FLASH
|
||||
|
||||
component_ut_test_ip101:
|
||||
extends: .component_ut_esp32_template
|
||||
tags:
|
||||
- ESP32
|
||||
- COMPONENT_UT_IP101
|
||||
|
||||
component_ut_test_lan8720:
|
||||
extends: .component_ut_esp32_template
|
||||
tags:
|
||||
- ESP32
|
||||
- COMPONENT_UT_LAN8720
|
||||
|
||||
.integration_test_template:
|
||||
extends:
|
||||
- .target_test_job_template
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
repos:
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v3.4.0
|
||||
rev: v4.0.1
|
||||
hooks:
|
||||
- id: trailing-whitespace
|
||||
# note: whitespace exclusions use multiline regex, see https://pre-commit.com/#regular-expressions
|
||||
@ -26,12 +26,12 @@ repos:
|
||||
args: ['-f=lf']
|
||||
- id: double-quote-string-fixer
|
||||
- repo: https://gitlab.com/pycqa/flake8
|
||||
rev: 3.8.4
|
||||
rev: 3.9.2
|
||||
hooks:
|
||||
- id: flake8
|
||||
args: ['--config=.flake8', '--tee', '--benchmark']
|
||||
- repo: https://github.com/pycqa/isort
|
||||
rev: 5.6.4
|
||||
rev: 5.9.3
|
||||
hooks:
|
||||
- id: isort
|
||||
name: isort (python)
|
||||
@ -92,11 +92,24 @@ repos:
|
||||
- id: mypy-check
|
||||
name: Check type annotations in python files
|
||||
entry: tools/ci/check_type_comments.py
|
||||
additional_dependencies: ['mypy==0.800', 'mypy-extensions==0.4.3']
|
||||
additional_dependencies:
|
||||
- 'mypy==0.800'
|
||||
- 'mypy-extensions==0.4.3'
|
||||
language: python
|
||||
types: [python]
|
||||
- id: check-copyright
|
||||
name: Check copyright notices
|
||||
entry: tools/ci/check_copyright.py --verbose --replace
|
||||
additional_dependencies:
|
||||
- 'comment_parser == 1.2.3'
|
||||
- 'thefuzz == 0.19.0'
|
||||
- 'thefuzz[speedup] == 0.19.0; sys_platform != "win32"'
|
||||
# don't depend on python-Levenshtein on Windows, as it requires Microsoft C++ Build Tools to install
|
||||
language: python
|
||||
files: \.(py|c|h|cpp|hpp|ld)$
|
||||
require_serial: true
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v3.4.0
|
||||
rev: v4.0.1
|
||||
hooks:
|
||||
- id: file-contents-sorter
|
||||
files: '(tools\/ci\/executable-list\.txt|tools\/ci\/mypy_ignore_list\.txt)'
|
||||
files: 'tools\/ci\/(executable-list\.txt|mypy_ignore_list\.txt|check_copyright_ignore\.txt)'
|
||||
|
@ -20,7 +20,9 @@ if(NOT BOOTLOADER_BUILD)
|
||||
|
||||
if(CONFIG_COMPILER_OPTIMIZATION_SIZE)
|
||||
list(APPEND compile_options "-Os")
|
||||
list(APPEND compile_options "-freorder-blocks")
|
||||
if(CMAKE_C_COMPILER_ID MATCHES "GNU")
|
||||
list(APPEND compile_options "-freorder-blocks")
|
||||
endif()
|
||||
elseif(CONFIG_COMPILER_OPTIMIZATION_DEFAULT)
|
||||
list(APPEND compile_options "-Og")
|
||||
elseif(CONFIG_COMPILER_OPTIMIZATION_NONE)
|
||||
@ -33,7 +35,9 @@ else() # BOOTLOADER_BUILD
|
||||
|
||||
if(CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE)
|
||||
list(APPEND compile_options "-Os")
|
||||
list(APPEND compile_options "-freorder-blocks")
|
||||
if(CMAKE_C_COMPILER_ID MATCHES "GNU")
|
||||
list(APPEND compile_options "-freorder-blocks")
|
||||
endif()
|
||||
elseif(CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_DEBUG)
|
||||
list(APPEND compile_options "-Og")
|
||||
elseif(CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_NONE)
|
||||
@ -74,6 +78,48 @@ if(CONFIG_COMPILER_DISABLE_GCC8_WARNINGS)
|
||||
"-Wno-int-in-bool-context")
|
||||
endif()
|
||||
|
||||
if(CMAKE_C_COMPILER_ID MATCHES "GNU")
|
||||
list(APPEND c_compile_options "-Wno-old-style-declaration")
|
||||
endif()
|
||||
|
||||
# Clang finds some warnings in IDF code which GCC doesn't.
|
||||
# All these warnings should be fixed before Clang is presented
|
||||
# as a toolchain choice for users.
|
||||
if(CMAKE_C_COMPILER_ID MATCHES "Clang")
|
||||
# Clang checks Doxygen comments for being in sync with function prototype.
|
||||
# There are some inconsistencies, especially in ROM headers.
|
||||
list(APPEND compile_options "-Wno-documentation")
|
||||
# GCC allows repeated typedefs when the source and target types are the same.
|
||||
# Clang doesn't allow this. This occurs in many components due to forward
|
||||
# declarations.
|
||||
list(APPEND compile_options "-Wno-typedef-redefinition")
|
||||
# This issue is seemingly related to newlib's char type functions.
|
||||
# Fix is not clear yet.
|
||||
list(APPEND compile_options "-Wno-char-subscripts")
|
||||
# Clang seems to notice format string issues which GCC doesn't.
|
||||
list(APPEND compile_options "-Wno-format-security")
|
||||
# Logic bug in essl component
|
||||
list(APPEND compile_options "-Wno-tautological-overlap-compare")
|
||||
# Some pointer checks in mDNS component check addresses which can't be NULL
|
||||
list(APPEND compile_options "-Wno-tautological-pointer-compare")
|
||||
# Similar to the above, in tcp_transport
|
||||
list(APPEND compile_options "-Wno-pointer-bool-conversion")
|
||||
# mbedTLS md5.c triggers this warning in md5_test_buf (false positive)
|
||||
list(APPEND compile_options "-Wno-string-concatenation")
|
||||
# multiple cases of implict convertions between unrelated enum types
|
||||
list(APPEND compile_options "-Wno-enum-conversion")
|
||||
# When IRAM_ATTR is specified both in function declaration and definition,
|
||||
# it produces different section names, since section names include __COUNTER__.
|
||||
# Occurs in multiple places.
|
||||
list(APPEND compile_options "-Wno-section")
|
||||
# Multiple cases of attributes unknown to clang, for example
|
||||
# __attribute__((optimize("-O3")))
|
||||
list(APPEND compile_options "-Wno-unknown-attributes")
|
||||
# Clang also produces many -Wunused-function warnings which GCC doesn't.
|
||||
# However these aren't treated as errors.
|
||||
endif()
|
||||
# More warnings may exist in unit tests and example projects.
|
||||
|
||||
if(CONFIG_COMPILER_WARN_WRITE_STRINGS)
|
||||
list(APPEND compile_options "-Wwrite-strings")
|
||||
endif()
|
||||
@ -118,7 +164,15 @@ list(APPEND link_options "-fno-lto")
|
||||
# Placing jump tables in flash would cause issues with code that required
|
||||
# to be placed in IRAM
|
||||
list(APPEND compile_options "-fno-jump-tables")
|
||||
list(APPEND compile_options "-fno-tree-switch-conversion")
|
||||
if(CMAKE_C_COMPILER_ID MATCHES "GNU")
|
||||
# This flag is GCC-specific.
|
||||
# Not clear yet if some other flag should be used for Clang.
|
||||
list(APPEND compile_options "-fno-tree-switch-conversion")
|
||||
endif()
|
||||
|
||||
if(CMAKE_C_COMPILER_ID MATCHES "LLVM")
|
||||
list(APPEND compile_options "-fno-use-cxa-atexit")
|
||||
endif()
|
||||
|
||||
idf_build_set_property(COMPILE_OPTIONS "${compile_options}" APPEND)
|
||||
idf_build_set_property(C_COMPILE_OPTIONS "${c_compile_options}" APPEND)
|
||||
|
1
Kconfig
1
Kconfig
@ -11,7 +11,6 @@ mainmenu "Espressif IoT Development Framework Configuration"
|
||||
config IDF_ENV_FPGA
|
||||
# This option is for internal use only
|
||||
bool
|
||||
default "y" if IDF_TARGET="esp32h2" # ESP32H2-TODO: IDF-3378
|
||||
option env="IDF_ENV_FPGA"
|
||||
|
||||
config IDF_TARGET_ARCH_RISCV
|
||||
|
24
README.md
24
README.md
@ -2,7 +2,24 @@
|
||||
|
||||
* [中文版](./README_CN.md)
|
||||
|
||||
ESP-IDF is the development framework for Espressif SoCs (released after 2016<sup>[1](#fn1)</sup>) provided for Windows, Linux and macOS.
|
||||
ESP-IDF is the development framework for Espressif SoCs supported on Windows, Linux and macOS.
|
||||
|
||||
# ESP-IDF Release and SoC Compatibility
|
||||
|
||||
The following table shows ESP-IDF support of Espressif SoCs where ![alt text][preview] and ![alt text][supported] denote preview status and support, respectively. In preview status the build is not yet enabled and some crucial parts could be missing (like documentation, datasheet). Please use an ESP-IDF release where the desired SoC is already supported.
|
||||
|
||||
|Chip | v3.3 | v4.0 | v4.1 | v4.2 | v4.3 | v4.4 | |
|
||||
|:----------- |:---------------------: | :---------------------:| :---------------------:| :---------------------:| :---------------------:| :---------------------:|:---------------------------------------------------------- |
|
||||
|ESP32 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | |
|
||||
|ESP32-S2 | | | | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | |
|
||||
|ESP32-C3 | | | | | ![alt text][supported] | ![alt text][supported] | |
|
||||
|ESP32-S3 | | | | | ![alt text][preview] | ![alt text][supported] | [Announcement](https://www.espressif.com/en/news/ESP32_S3) |
|
||||
|ESP32-H2 | | | | | | ![alt text][preview] | [Announcement](https://www.espressif.com/en/news/ESP32_H2) |
|
||||
|
||||
[supported]: https://img.shields.io/badge/-supported-green "supported"
|
||||
[preview]: https://img.shields.io/badge/-preview-orange "preview"
|
||||
|
||||
Espressif SoCs released before 2016 (ESP8266 and ESP8285) are supported by [RTOS SDK](https://github.com/espressif/ESP8266_RTOS_SDK) instead.
|
||||
|
||||
# Developing With ESP-IDF
|
||||
|
||||
@ -99,8 +116,3 @@ This can be combined with other targets, ie `idf.py -p PORT erase_flash flash` w
|
||||
* [Check the Issues section on github](https://github.com/espressif/esp-idf/issues) if you find a bug or have a feature request. Please check existing Issues before opening a new one.
|
||||
|
||||
* If you're interested in contributing to ESP-IDF, please check the [Contributions Guide](https://docs.espressif.com/projects/esp-idf/en/latest/contribute/index.html).
|
||||
|
||||
|
||||
________
|
||||
|
||||
<a name="fn1">1</a>: ESP8266 and ESP8285 are not supported in ESP-IDF. See [RTOS SDK](https://github.com/espressif/ESP8266_RTOS_SDK) instead.
|
24
README_CN.md
24
README_CN.md
@ -2,7 +2,24 @@
|
||||
|
||||
* [English Version](./README.md)
|
||||
|
||||
ESP-IDF 是乐鑫官方推出的开发框架,适用于 2016 年之后发布的系列芯片<sup>[1](#fn1)</sup>,支持 Windows、Linux 和 macOS 操作系统。
|
||||
ESP-IDF 是乐鑫官方推出的物联网开发框架,支持 Windows、Linux 和 macOS 操作系统。
|
||||
|
||||
# ESP-IDF 与乐鑫芯片
|
||||
|
||||
下表总结了乐鑫芯片在 ESP-IDF 各版本中的支持状态,其中 ![alt text][supported] 代表已支持,![alt text][preview] 代表目前处于预览支持状态。在预览支持阶段,因为新芯片尚未完全添加到构建系统目录,所以一些重要的内容(如文档和技术规格书等)可能会缺失。请确保使用与芯片相匹配的 ESP-IDF 版本。
|
||||
|
||||
| 芯片 | v3.3 | v4.0 | v4.1 | v4.2 | v4.3 | v4.4 | |
|
||||
|:----------- |:---------------------: | :---------------------:| :---------------------:| :---------------------:| :---------------------:| :---------------------:|:---------------------------------------------------------- |
|
||||
|ESP32 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | |
|
||||
|ESP32-S2 | | | | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | |
|
||||
|ESP32-C3 | | | | | ![alt text][supported] | ![alt text][supported] | |
|
||||
|ESP32-S3 | | | | | ![alt text][preview] | ![alt text][supported] | [芯片发布公告](https://www.espressif.com/en/news/ESP32_S3) |
|
||||
|ESP32-H2 | | | | | | ![alt text][preview] | [芯片发布公告](https://www.espressif.com/en/news/ESP32_H2) |
|
||||
|
||||
[supported]: https://img.shields.io/badge/-%E6%94%AF%E6%8C%81-green "supported"
|
||||
[preview]: https://img.shields.io/badge/-%E9%A2%84%E8%A7%88-orange "preview"
|
||||
|
||||
对于 2016 年之前发布的乐鑫芯片(包括 ESP8266 和 ESP8285),请参考 [RTOS SDK](https://github.com/espressif/ESP8266_RTOS_SDK)。
|
||||
|
||||
# 使用 ESP-IDF 进行开发
|
||||
|
||||
@ -99,8 +116,3 @@ ESP-IDF 中的子模块采用相对路径([详见 .gitmodules 文件](.gitmodu
|
||||
* 如果你在使用中发现了错误或者需要新的功能,请先[查看 GitHub Issues](https://github.com/espressif/esp-idf/issues),确保该问题没有重复提交。
|
||||
|
||||
* 如果你有兴趣为 ESP-IDF 作贡献,请先阅读[贡献指南](https://docs.espressif.com/projects/esp-idf/en/latest/contribute/index.html)。
|
||||
|
||||
|
||||
__________
|
||||
|
||||
<a name="fn1">1</a>: ESP-IDF 不支持 ESP8266 和 ESP8285。如有需要,请参考 [RTOS SDK](https://github.com/espressif/ESP8266_RTOS_SDK)。
|
||||
|
160
components/README.md
Normal file
160
components/README.md
Normal file
@ -0,0 +1,160 @@
|
||||
# Core Components
|
||||
|
||||
## Overview
|
||||
|
||||
This document contains details about what the core components are, what they contain, and how they are organized.
|
||||
|
||||
## Organization
|
||||
|
||||
The core components are organized into two groups.
|
||||
|
||||
The first group (referred to as `G0` from now on) contains `hal`, `xtensa` and `riscv` (referred to as `arch` components from now on), `esp_rom`, `esp_common`, and `soc`. This
|
||||
group contain information about and low-level access to underlying hardware; or in the case of `esp_common`, hardware-agnostic code and utilities.
|
||||
These components can depend on each other, but as much as possible have no dependencies outside the group. The reason for this is that, due to the
|
||||
nature of what these components contain, the likelihood is high that a lot of other components will require these. Ideally, then, the dependency
|
||||
relationship only goes one way. This makes it easier for these components, as a group, to be usable in another project. One can conceivably implement
|
||||
a competing SDK to ESP-IDF on top of these components.
|
||||
|
||||
The second group (referred to as `G1` from now on) sits at a higher level than the first group. This group contains the components `esp_hw_support`, `esp_system`, `newlib`, `spi_flash`,
|
||||
`freertos`, `log`, and `heap`. Like the first group, circular dependencies within the group are allowed; and being at a higher level, dependency on the first group
|
||||
is allowed. These components represent software mechanisms essential to building other components.
|
||||
|
||||
## Descriptions
|
||||
|
||||
The following is a short description of the components mentioned above.
|
||||
|
||||
### `G0` Components
|
||||
|
||||
#### `hal`
|
||||
|
||||
Contains the hardware abstraction layer and low-level operation implementations for the various peripherals. The low-level functions assign meaningful names to register-level manipulations; the hardware abstraction provide operations one level above this, grouping these low-level functions
|
||||
into routines that achieve a meaningful action or state of the peripheral.
|
||||
|
||||
Example:
|
||||
|
||||
- `spi_flash_ll_set_address` is a low-level function part of the hardware abstraction `spi_flash_hal_read_block`
|
||||
|
||||
#### `arch`
|
||||
|
||||
Contains low-level architecture operations and definitions, including those for customizations (can be thought of on the same level as the low-level functions of `hal`).
|
||||
This can also contain files provided by the architecture vendor.
|
||||
|
||||
Example:
|
||||
|
||||
- `xt_set_exception_handler`
|
||||
- `riscv_global_interrupts_enable`
|
||||
- `ERI_PERFMON_MAX`
|
||||
|
||||
#### `esp_common`
|
||||
|
||||
Contains hardware-agnostic definitions, constants, macros, utilities, 'pure' and/or algorithmic functions that is useable by all other components (that is, barring there being a more appropriate component to put them in).
|
||||
|
||||
Example:
|
||||
|
||||
- `BIT(nr)` and other bit manipulation utilities in the future
|
||||
- `IDF_DEPRECATED(REASON)`
|
||||
- `ESP_IDF_VERSION_MAJOR`
|
||||
|
||||
#### `soc`
|
||||
|
||||
Contains description of the underlying hardware: register structure, addresses, pins, capabilities, etc.
|
||||
|
||||
Example:
|
||||
|
||||
- `DR_REG_DPORT_BASE`
|
||||
- `SOC_MCPWM_SUPPORTED`
|
||||
- `uart_dev_s`
|
||||
|
||||
#### `esp_rom`
|
||||
|
||||
Contains headers, linker scripts, abstraction layer, patches, and other related files to ROM functions.
|
||||
|
||||
Example:
|
||||
|
||||
- `esp32.rom.eco3.ld`
|
||||
- `rom/aes.h`
|
||||
|
||||
### `G1` Components
|
||||
|
||||
#### `spi_flash`
|
||||
|
||||
SPI flash device access implementation.
|
||||
|
||||
#### `freertos`
|
||||
|
||||
FreeRTOS port to targets supported by ESP-IDF.
|
||||
|
||||
#### `log`
|
||||
|
||||
Logging library.
|
||||
|
||||
#### `heap`
|
||||
|
||||
Heap implementation.
|
||||
|
||||
#### `newlib`
|
||||
|
||||
Some functions n the standard library are implemented here, especially those needing other `G1` components.
|
||||
|
||||
Example:
|
||||
|
||||
- `malloc` is implemented in terms of the component `heap`'s functions
|
||||
- `gettimeofday` is implemented in terms of system time in `esp_system`
|
||||
|
||||
#### `esp_system`
|
||||
|
||||
Contains implementation of system services and controls system behavior. The implementations
|
||||
here may take hardware resources and/or decide on a hardware state needed for support of a system service/feature/mechanism.
|
||||
Currently, this encompasses the following, but not limited to:
|
||||
|
||||
- Startup and initialization
|
||||
- Panic and debug
|
||||
- Reset and reset reason
|
||||
- Task and interrupt watchdogs
|
||||
|
||||
#### `esp_hw_support`
|
||||
|
||||
Contains implementations that provide hardware operations, arbitration, or resource sharing, especially those that
|
||||
is used in the system. Unlike `esp_system`, implementations here do not decide on a hardware state or takes hardware resource, acting
|
||||
merely as facilitator to hardware access. Currently, this encompasses the following, but not limited to:
|
||||
|
||||
- Interrupt allocation
|
||||
- Sleep functions
|
||||
- Memory functions (external SPIRAM, async memory, etc.)
|
||||
- Clock and clock control
|
||||
- Random generation
|
||||
- CPU utilities
|
||||
- MAC settings
|
||||
|
||||
### `esp_hw_support` vs `esp_system`
|
||||
|
||||
This section details list some implementations and the reason for placing it in either `esp_hw_support` or `esp_system`.
|
||||
|
||||
#### `task_wdt.c` (`esp_system`) vs `intr_alloc.c` (`esp_hw_support`)
|
||||
|
||||
The task watchdog fits the definition of taking and configuring hardware resources (wdt, interrupt) for implementation of a system service/mechanism.
|
||||
|
||||
This is in contrast with interrupt allocation that merely facilitates access to the underlying hardware for other implementations -
|
||||
drivers, user code, and even the task watchdog mentioned previously!
|
||||
|
||||
#### `crosscore_int.c` (`esp_system`)
|
||||
|
||||
The current implementation of crosscore interrupts is tightly coupled with a number of interrupt reasons
|
||||
associated with system services/mechanisms: REASON_YIELD (scheduler), REASON_FREQ_SWITCH (power management)
|
||||
REASON_PRINT_BACKTRACE (panic and debug).
|
||||
|
||||
However, if an implementation exists that makes it possible to register an arbitrary interrupt reason - a
|
||||
lower level inter-processor call if you will, then this implementation is a good candidate for `esp_hw_support`.
|
||||
The current implementation in `esp_system` can then just register the interrupt reasons mentioned above.
|
||||
|
||||
#### `esp_mac.h`, `esp_chip_info.h`, `esp_random.h` (`esp_hw_support`)
|
||||
|
||||
The functions in these headers used to be in `esp_system.h`, but have been split-off.
|
||||
However, to maintain backward compatibility, `esp_system.h` includes these headers.
|
||||
|
||||
The remaining functions in `esp_system.h` are those that deal with system behavior, such
|
||||
as `esp_register_shutdown_handler`, or are proxy for other system components's APIs such as
|
||||
`esp_get_free_heap_size`.
|
||||
|
||||
The functions split-off from `esp_system.h` are much more hardware manipulation oriented such as:
|
||||
`esp_read_mac`, `esp_random` and `esp_chip_info`.
|
@ -209,7 +209,7 @@ Notes:
|
||||
#define apiID_VEVENTGROUPDELETE (72u)
|
||||
#define apiID_UXEVENTGROUPGETNUMBER (73u)
|
||||
|
||||
#define traceTASK_NOTIFY_TAKE() SEGGER_SYSVIEW_RecordU32x2(apiFastID_OFFSET + apiID_ULTASKNOTIFYTAKE, xClearCountOnExit, xTicksToWait)
|
||||
#define traceTASK_NOTIFY_TAKE( uxIndexToWait ) SEGGER_SYSVIEW_RecordU32x2(apiFastID_OFFSET + apiID_ULTASKNOTIFYTAKE, xClearCountOnExit, xTicksToWait)
|
||||
#define traceTASK_DELAY() SEGGER_SYSVIEW_RecordU32(apiFastID_OFFSET + apiID_VTASKDELAY, xTicksToDelay)
|
||||
#define traceTASK_DELAY_UNTIL() SEGGER_SYSVIEW_RecordVoid(apiFastID_OFFSET + apiID_VTASKDELAYUNTIL)
|
||||
#define traceTASK_DELETE( pxTCB ) if (pxTCB != NULL) { \
|
||||
@ -217,16 +217,16 @@ Notes:
|
||||
SEGGER_SYSVIEW_ShrinkId((U32)pxTCB)); \
|
||||
SYSVIEW_DeleteTask((U32)pxTCB); \
|
||||
}
|
||||
#define traceTASK_NOTIFY_GIVE_FROM_ISR() SEGGER_SYSVIEW_RecordU32x2(apiFastID_OFFSET + apiID_VTASKNOTIFYGIVEFROMISR, SEGGER_SYSVIEW_ShrinkId((U32)pxTCB), (U32)pxHigherPriorityTaskWoken)
|
||||
#define traceTASK_NOTIFY_GIVE_FROM_ISR( uxIndexToNotify ) SEGGER_SYSVIEW_RecordU32x2(apiFastID_OFFSET + apiID_VTASKNOTIFYGIVEFROMISR, SEGGER_SYSVIEW_ShrinkId((U32)pxTCB), (U32)pxHigherPriorityTaskWoken)
|
||||
#define traceTASK_PRIORITY_INHERIT( pxTCB, uxPriority ) SEGGER_SYSVIEW_RecordU32(apiFastID_OFFSET + apiID_VTASKPRIORITYINHERIT, (U32)pxMutexHolder)
|
||||
#define traceTASK_RESUME( pxTCB ) SEGGER_SYSVIEW_RecordU32(apiFastID_OFFSET + apiID_VTASKRESUME, SEGGER_SYSVIEW_ShrinkId((U32)pxTCB))
|
||||
#define traceINCREASE_TICK_COUNT( xTicksToJump ) SEGGER_SYSVIEW_RecordU32(apiFastID_OFFSET + apiID_VTASKSTEPTICK, xTicksToJump)
|
||||
#define traceTASK_SUSPEND( pxTCB ) SEGGER_SYSVIEW_RecordU32(apiFastID_OFFSET + apiID_VTASKSUSPEND, SEGGER_SYSVIEW_ShrinkId((U32)pxTCB))
|
||||
#define traceTASK_PRIORITY_DISINHERIT( pxTCB, uxBasePriority ) SEGGER_SYSVIEW_RecordU32(apiFastID_OFFSET + apiID_XTASKPRIORITYDISINHERIT, (U32)pxMutexHolder)
|
||||
#define traceTASK_RESUME_FROM_ISR( pxTCB ) SEGGER_SYSVIEW_RecordU32(apiFastID_OFFSET + apiID_XTASKRESUMEFROMISR, SEGGER_SYSVIEW_ShrinkId((U32)pxTCB))
|
||||
#define traceTASK_NOTIFY() SYSVIEW_RecordU32x4(apiFastID_OFFSET + apiID_XTASKGENERICNOTIFY, SEGGER_SYSVIEW_ShrinkId((U32)pxTCB), ulValue, eAction, (U32)pulPreviousNotificationValue)
|
||||
#define traceTASK_NOTIFY_FROM_ISR() SYSVIEW_RecordU32x5(apiFastID_OFFSET + apiID_XTASKGENERICNOTIFYFROMISR, SEGGER_SYSVIEW_ShrinkId((U32)pxTCB), ulValue, eAction, (U32)pulPreviousNotificationValue, (U32)pxHigherPriorityTaskWoken)
|
||||
#define traceTASK_NOTIFY_WAIT() SYSVIEW_RecordU32x4(apiFastID_OFFSET + apiID_XTASKNOTIFYWAIT, ulBitsToClearOnEntry, ulBitsToClearOnExit, (U32)pulNotificationValue, xTicksToWait)
|
||||
#define traceTASK_NOTIFY( uxIndexToNotify ) SYSVIEW_RecordU32x4(apiFastID_OFFSET + apiID_XTASKGENERICNOTIFY, SEGGER_SYSVIEW_ShrinkId((U32)pxTCB), ulValue, eAction, (U32)pulPreviousNotificationValue)
|
||||
#define traceTASK_NOTIFY_FROM_ISR( uxIndexToNotify ) SYSVIEW_RecordU32x5(apiFastID_OFFSET + apiID_XTASKGENERICNOTIFYFROMISR, SEGGER_SYSVIEW_ShrinkId((U32)pxTCB), ulValue, eAction, (U32)pulPreviousNotificationValue, (U32)pxHigherPriorityTaskWoken)
|
||||
#define traceTASK_NOTIFY_WAIT( uxIndexToWait ) SYSVIEW_RecordU32x4(apiFastID_OFFSET + apiID_XTASKNOTIFYWAIT, ulBitsToClearOnEntry, ulBitsToClearOnExit, (U32)pulNotificationValue, xTicksToWait)
|
||||
|
||||
#define traceQUEUE_CREATE( pxNewQueue ) SEGGER_SYSVIEW_RecordU32x3(apiFastID_OFFSET + apiID_XQUEUEGENERICCREATE, uxQueueLength, uxItemSize, ucQueueType)
|
||||
#define traceQUEUE_DELETE( pxQueue ) SEGGER_SYSVIEW_RecordU32(apiFastID_OFFSET + apiID_VQUEUEDELETE, SEGGER_SYSVIEW_ShrinkId((U32)pxQueue))
|
||||
|
@ -46,6 +46,7 @@ if(NOT BOOTLOADER_BUILD)
|
||||
|
||||
add_custom_target(blank_ota_data ALL DEPENDS ${blank_otadata_file})
|
||||
add_dependencies(flash blank_ota_data)
|
||||
add_dependencies(encrypted-flash blank_ota_data)
|
||||
|
||||
set(otatool_py ${python} ${COMPONENT_DIR}/otatool.py)
|
||||
|
||||
|
@ -502,6 +502,7 @@ menu "Security features"
|
||||
bool "Enable hardware Secure Boot in bootloader (READ DOCS FIRST)"
|
||||
default n
|
||||
depends on IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 || ESP32C3_REV_MIN_3 || IDF_TARGET_ESP32S3
|
||||
select ESPTOOLPY_NO_STUB if !IDF_TARGET_ESP32 && !IDF_TARGET_ESP32S2
|
||||
help
|
||||
Build a bootloader which enables Secure Boot on first boot.
|
||||
|
||||
@ -892,6 +893,8 @@ menu "Security features"
|
||||
It is also possible to enable secure download mode at runtime by calling
|
||||
esp_efuse_enable_rom_secure_download_mode()
|
||||
|
||||
Note: Secure Download mode is not available for ESP32 (includes revisions till ECO3).
|
||||
|
||||
config SECURE_INSECURE_ALLOW_DL_MODE
|
||||
bool "UART ROM download mode (Enabled (not recommended))"
|
||||
help
|
||||
|
@ -49,6 +49,7 @@ SECTIONS
|
||||
*libbootloader_support.a:bootloader_sha.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:bootloader_console_loader.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:bootloader_panic.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:bootloader_soc.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:esp_image_format.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:flash_encrypt.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:flash_encryption_secure_features.*(.literal .text .literal.* .text.*)
|
||||
|
@ -36,6 +36,7 @@ SECTIONS
|
||||
*libbootloader_support.a:bootloader_sha.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:bootloader_console_loader.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:bootloader_panic.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:bootloader_soc.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:esp_image_format.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:flash_encrypt.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:flash_encryption_secure_features.*(.literal .text .literal.* .text.*)
|
||||
|
@ -36,6 +36,7 @@ SECTIONS
|
||||
*libbootloader_support.a:bootloader_sha.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:bootloader_console_loader.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:bootloader_panic.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:bootloader_soc.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:esp_image_format.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:flash_encrypt.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:flash_partitions.*(.literal .text .literal.* .text.*)
|
||||
|
@ -36,6 +36,7 @@ SECTIONS
|
||||
*libbootloader_support.a:bootloader_sha.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:bootloader_console_loader.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:bootloader_panic.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:bootloader_soc.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:esp_image_format.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:flash_encrypt.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:flash_encryption_secure_features.*(.literal .text .literal.* .text.*)
|
||||
|
@ -37,6 +37,7 @@ SECTIONS
|
||||
*libbootloader_support.a:bootloader_sha.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:bootloader_console_loader.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:bootloader_panic.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:bootloader_soc.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:esp_image_format.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:flash_encrypt.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:flash_encryption_secure_features.*(.literal .text .literal.* .text.*)
|
||||
|
@ -26,6 +26,7 @@ if(BOOTLOADER_BUILD)
|
||||
"src/bootloader_console_loader.c"
|
||||
"src/bootloader_panic.c"
|
||||
"src/${IDF_TARGET}/bootloader_sha.c"
|
||||
"src/${IDF_TARGET}/bootloader_soc.c"
|
||||
"src/${IDF_TARGET}/bootloader_${IDF_TARGET}.c"
|
||||
)
|
||||
list(APPEND priv_requires hal)
|
||||
|
@ -119,6 +119,15 @@ bool bootloader_common_label_search(const char *list, char *label);
|
||||
*/
|
||||
void bootloader_configure_spi_pins(int drv);
|
||||
|
||||
/**
|
||||
* @brief Get flash CS IO
|
||||
*
|
||||
* Can be determined by eFuse values, or the default value
|
||||
*
|
||||
* @return Flash CS IO
|
||||
*/
|
||||
uint8_t bootloader_flash_get_cs_io(void);
|
||||
|
||||
/**
|
||||
* @brief Calculates a sha-256 for a given partition or returns a appended digest.
|
||||
*
|
||||
|
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* @brief Configure analog super WDT reset
|
||||
*
|
||||
* @param enable Boolean to enable or disable super WDT reset
|
||||
*/
|
||||
void bootloader_ana_super_wdt_reset_config(bool enable);
|
||||
|
||||
/**
|
||||
* @brief Configure analog brownout reset
|
||||
*
|
||||
* @param enable Boolean to enable or disable brownout reset
|
||||
*/
|
||||
void bootloader_ana_bod_reset_config(bool enable);
|
||||
|
||||
/**
|
||||
* @brief Configure analog clock glitch reset
|
||||
*
|
||||
* @param enable Boolean to enable or disable clock glitch reset
|
||||
*/
|
||||
void bootloader_ana_clock_glitch_reset_config(bool enable);
|
@ -23,6 +23,7 @@
|
||||
#include "esp_rom_crc.h"
|
||||
#include "esp_rom_gpio.h"
|
||||
#include "esp_rom_sys.h"
|
||||
#include "esp_rom_efuse.h"
|
||||
#include "esp_flash_partitions.h"
|
||||
#include "bootloader_flash_priv.h"
|
||||
#include "bootloader_common.h"
|
||||
@ -191,8 +192,19 @@ void bootloader_common_vddsdio_configure(void)
|
||||
#endif // CONFIG_BOOTLOADER_VDDSDIO_BOOST
|
||||
}
|
||||
|
||||
|
||||
RESET_REASON bootloader_common_get_reset_reason(int cpu_no)
|
||||
{
|
||||
return (RESET_REASON)esp_rom_get_reset_reason(cpu_no);
|
||||
}
|
||||
|
||||
uint8_t bootloader_flash_get_cs_io(void)
|
||||
{
|
||||
uint8_t cs_io;
|
||||
const uint32_t spiconfig = esp_rom_efuse_get_flash_gpio_info();
|
||||
if (spiconfig == ESP_ROM_EFUSE_FLASH_DEFAULT_SPI) {
|
||||
cs_io = SPI_CS0_GPIO_NUM;
|
||||
} else {
|
||||
cs_io = (spiconfig >> 18) & 0x3f;
|
||||
}
|
||||
return cs_io;
|
||||
}
|
||||
|
@ -7,14 +7,14 @@
|
||||
#include "bootloader_common.h"
|
||||
#include "bootloader_clock.h"
|
||||
#include "soc/efuse_reg.h"
|
||||
#include "soc/apb_ctrl_reg.h"
|
||||
#include "soc/syscon_reg.h"
|
||||
|
||||
uint8_t bootloader_common_get_chip_revision(void)
|
||||
{
|
||||
uint8_t eco_bit0, eco_bit1, eco_bit2;
|
||||
eco_bit0 = (REG_READ(EFUSE_BLK0_RDATA3_REG) & 0xF000) >> 15;
|
||||
eco_bit1 = (REG_READ(EFUSE_BLK0_RDATA5_REG) & 0x100000) >> 20;
|
||||
eco_bit2 = (REG_READ(APB_CTRL_DATE_REG) & 0x80000000) >> 31;
|
||||
eco_bit2 = (REG_READ(SYSCON_DATE_REG) & 0x80000000) >> 31;
|
||||
uint32_t combine_value = (eco_bit2 << 2) | (eco_bit1 << 1) | eco_bit0;
|
||||
uint8_t chip_ver = 0;
|
||||
switch (combine_value) {
|
||||
@ -28,7 +28,7 @@ uint8_t bootloader_common_get_chip_revision(void)
|
||||
chip_ver = 2;
|
||||
break;
|
||||
#if CONFIG_IDF_ENV_FPGA
|
||||
case 4: /* Empty efuses, but APB_CTRL_DATE_REG bit is set */
|
||||
case 4: /* Empty efuses, but SYSCON_DATE_REG bit is set */
|
||||
chip_ver = 3;
|
||||
break;
|
||||
#endif
|
||||
|
@ -33,18 +33,18 @@ void bootloader_flash_update_id()
|
||||
|
||||
void IRAM_ATTR bootloader_flash_cs_timing_config()
|
||||
{
|
||||
// SPI0/1 share the cs_hold / cs_setup, cd_hold_time / cd_setup_time, cs_hold_delay registers for FLASH/PSRAM, so we only need to set SPI0 related registers here
|
||||
//SPI0/1 share the cs_hold / cs_setup, cd_hold_time / cd_setup_time, cs_hold_delay registers for FLASH, so we only need to set SPI0 related registers here
|
||||
#if CONFIG_ESPTOOLPY_OCT_FLASH
|
||||
SET_PERI_REG_MASK(SPI_MEM_USER_REG(0), SPI_MEM_CS_HOLD_M | SPI_MEM_CS_SETUP_M);
|
||||
SET_PERI_REG_BITS(SPI_MEM_CTRL2_REG(0), SPI_MEM_CS_HOLD_TIME_V, FLASH_CS_HOLD_TIME, SPI_MEM_CS_HOLD_TIME_S);
|
||||
SET_PERI_REG_BITS(SPI_MEM_CTRL2_REG(0), SPI_MEM_CS_SETUP_TIME_V, FLASH_CS_SETUP_TIME, SPI_MEM_CS_SETUP_TIME_S);
|
||||
|
||||
SET_PERI_REG_MASK(SPI_MEM_SPI_SMEM_AC_REG(0), SPI_MEM_SPI_SMEM_CS_HOLD_M | SPI_MEM_SPI_SMEM_CS_SETUP_M);
|
||||
SET_PERI_REG_BITS(SPI_MEM_SPI_SMEM_AC_REG(0), SPI_MEM_SPI_SMEM_CS_HOLD_TIME_V, FLASH_CS_HOLD_TIME, SPI_MEM_SPI_SMEM_CS_HOLD_TIME_S);
|
||||
SET_PERI_REG_BITS(SPI_MEM_SPI_SMEM_AC_REG(0), SPI_MEM_SPI_SMEM_CS_SETUP_TIME_V, FLASH_CS_SETUP_TIME, SPI_MEM_SPI_SMEM_CS_SETUP_TIME_S);
|
||||
|
||||
// cs high time
|
||||
//CS high time
|
||||
SET_PERI_REG_BITS(SPI_MEM_CTRL2_REG(0), SPI_MEM_CS_HOLD_DELAY_V, FLASH_CS_HOLD_DELAY, SPI_MEM_CS_HOLD_DELAY_S);
|
||||
SET_PERI_REG_BITS(SPI_MEM_SPI_SMEM_AC_REG(0), SPI_MEM_SPI_SMEM_CS_HOLD_DELAY_V, FLASH_CS_HOLD_DELAY, SPI_MEM_SPI_SMEM_CS_HOLD_DELAY_S);
|
||||
#else
|
||||
SET_PERI_REG_BITS(SPI_MEM_CTRL2_REG(0), SPI_MEM_CS_HOLD_TIME_V, 0, SPI_MEM_CS_HOLD_TIME_S);
|
||||
SET_PERI_REG_BITS(SPI_MEM_CTRL2_REG(0), SPI_MEM_CS_SETUP_TIME_V, 0, SPI_MEM_CS_SETUP_TIME_S);
|
||||
SET_PERI_REG_MASK(SPI_MEM_USER_REG(0), SPI_MEM_CS_HOLD_M | SPI_MEM_CS_SETUP_M);
|
||||
#endif
|
||||
}
|
||||
|
||||
void IRAM_ATTR bootloader_flash_clock_config(const esp_image_header_t *pfhdr)
|
||||
|
@ -76,6 +76,7 @@
|
||||
#include "bootloader_utility.h"
|
||||
#include "bootloader_sha.h"
|
||||
#include "bootloader_console.h"
|
||||
#include "bootloader_soc.h"
|
||||
#include "esp_efuse.h"
|
||||
|
||||
static const char *TAG = "boot";
|
||||
@ -636,6 +637,12 @@ static void load_image(const esp_image_metadata_t *image_data)
|
||||
ESP_LOGI(TAG, "Disabling RNG early entropy source...");
|
||||
bootloader_random_disable();
|
||||
|
||||
/* Disable glitch reset after all the security checks are completed.
|
||||
* Glitch detection can be falsely triggered by EMI interference (high RF TX power, etc)
|
||||
* and to avoid such false alarms, disable it.
|
||||
*/
|
||||
bootloader_ana_clock_glitch_reset_config(false);
|
||||
|
||||
// copy loaded segments to RAM, set up caches for mapped segments, and start application
|
||||
unpack_load_app(image_data);
|
||||
}
|
||||
|
21
components/bootloader_support/src/esp32/bootloader_soc.c
Normal file
21
components/bootloader_support/src/esp32/bootloader_soc.c
Normal file
@ -0,0 +1,21 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include <stdbool.h>
|
||||
|
||||
void bootloader_ana_super_wdt_reset_config(bool enable)
|
||||
{
|
||||
(void)enable;
|
||||
}
|
||||
|
||||
void bootloader_ana_bod_reset_config(bool enable)
|
||||
{
|
||||
(void)enable;
|
||||
}
|
||||
|
||||
void bootloader_ana_clock_glitch_reset_config(bool enable)
|
||||
{
|
||||
(void)enable;
|
||||
}
|
@ -36,6 +36,7 @@
|
||||
#include "regi2c_ctrl.h"
|
||||
#include "bootloader_console.h"
|
||||
#include "bootloader_flash_priv.h"
|
||||
#include "bootloader_soc.h"
|
||||
#include "esp_efuse.h"
|
||||
|
||||
static const char *TAG = "boot.esp32c3";
|
||||
@ -263,7 +264,7 @@ static inline void bootloader_hardware_init(void)
|
||||
}
|
||||
}
|
||||
|
||||
static inline void bootloader_glitch_reset_disable(void)
|
||||
static inline void bootloader_ana_reset_config(void)
|
||||
{
|
||||
/*
|
||||
For origin chip & ECO1: only support swt reset;
|
||||
@ -271,10 +272,27 @@ static inline void bootloader_glitch_reset_disable(void)
|
||||
For ECO3: fix clock glitch reset bug, support all reset, include: swt & brownout & clock glitch reset.
|
||||
*/
|
||||
uint8_t chip_version = bootloader_common_get_chip_revision();
|
||||
if (chip_version < 2) {
|
||||
REG_SET_FIELD(RTC_CNTL_FIB_SEL_REG, RTC_CNTL_FIB_SEL, RTC_CNTL_FIB_SUPER_WDT_RST);
|
||||
} else if (chip_version == 2) {
|
||||
REG_SET_FIELD(RTC_CNTL_FIB_SEL_REG, RTC_CNTL_FIB_SEL, RTC_CNTL_FIB_SUPER_WDT_RST | RTC_CNTL_FIB_BOR_RST);
|
||||
switch (chip_version) {
|
||||
case 0:
|
||||
case 1:
|
||||
//Enable WDT reset. Disable BOR and GLITCH reset
|
||||
bootloader_ana_super_wdt_reset_config(true);
|
||||
bootloader_ana_bod_reset_config(false);
|
||||
bootloader_ana_clock_glitch_reset_config(false);
|
||||
break;
|
||||
case 2:
|
||||
//Enable WDT and BOR reset. Disable GLITCH reset
|
||||
bootloader_ana_super_wdt_reset_config(true);
|
||||
bootloader_ana_bod_reset_config(true);
|
||||
bootloader_ana_clock_glitch_reset_config(false);
|
||||
break;
|
||||
case 3:
|
||||
default:
|
||||
//Enable WDT, BOR, and GLITCH reset
|
||||
bootloader_ana_super_wdt_reset_config(true);
|
||||
bootloader_ana_bod_reset_config(true);
|
||||
bootloader_ana_clock_glitch_reset_config(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -283,7 +301,7 @@ esp_err_t bootloader_init(void)
|
||||
esp_err_t ret = ESP_OK;
|
||||
|
||||
bootloader_hardware_init();
|
||||
bootloader_glitch_reset_disable();
|
||||
bootloader_ana_reset_config();
|
||||
bootloader_super_wdt_auto_feed();
|
||||
// protect memory region
|
||||
bootloader_init_mem();
|
||||
|
41
components/bootloader_support/src/esp32c3/bootloader_soc.c
Normal file
41
components/bootloader_support/src/esp32c3/bootloader_soc.c
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include <stdbool.h>
|
||||
#include "soc/soc.h"
|
||||
#include "soc/rtc_cntl_reg.h"
|
||||
|
||||
void bootloader_ana_super_wdt_reset_config(bool enable)
|
||||
{
|
||||
REG_CLR_BIT(RTC_CNTL_FIB_SEL_REG, RTC_CNTL_FIB_SUPER_WDT_RST);
|
||||
|
||||
if (enable) {
|
||||
REG_SET_BIT(RTC_CNTL_SWD_CONF_REG, RTC_CNTL_SWD_BYPASS_RST);
|
||||
} else {
|
||||
REG_CLR_BIT(RTC_CNTL_SWD_CONF_REG, RTC_CNTL_SWD_BYPASS_RST);
|
||||
}
|
||||
}
|
||||
|
||||
void bootloader_ana_bod_reset_config(bool enable)
|
||||
{
|
||||
REG_CLR_BIT(RTC_CNTL_FIB_SEL_REG, RTC_CNTL_FIB_BOR_RST);
|
||||
|
||||
if (enable) {
|
||||
REG_SET_BIT(RTC_CNTL_BROWN_OUT_REG, RTC_CNTL_BROWN_OUT_ANA_RST_EN);
|
||||
} else {
|
||||
REG_CLR_BIT(RTC_CNTL_BROWN_OUT_REG, RTC_CNTL_BROWN_OUT_ANA_RST_EN);
|
||||
}
|
||||
}
|
||||
|
||||
void bootloader_ana_clock_glitch_reset_config(bool enable)
|
||||
{
|
||||
REG_CLR_BIT(RTC_CNTL_FIB_SEL_REG, RTC_CNTL_FIB_GLITCH_RST);
|
||||
|
||||
if (enable) {
|
||||
REG_SET_BIT(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_GLITCH_RST_EN);
|
||||
} else {
|
||||
REG_CLR_BIT(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_GLITCH_RST_EN);
|
||||
}
|
||||
}
|
@ -36,6 +36,7 @@
|
||||
#include "regi2c_ctrl.h"
|
||||
#include "bootloader_console.h"
|
||||
#include "bootloader_flash_priv.h"
|
||||
#include "bootloader_soc.h"
|
||||
|
||||
static const char *TAG = "boot.esp32h2";
|
||||
|
||||
@ -254,27 +255,15 @@ static void bootloader_super_wdt_auto_feed(void)
|
||||
|
||||
static inline void bootloader_hardware_init(void)
|
||||
{
|
||||
// This check is always included in the bootloader so it can
|
||||
// print the minimum revision error message later in the boot
|
||||
if (bootloader_common_get_chip_revision() < 3) {
|
||||
REGI2C_WRITE_MASK(I2C_ULP, I2C_ULP_IR_FORCE_XPD_IPH, 1);
|
||||
REGI2C_WRITE_MASK(I2C_BIAS, I2C_BIAS_DREG_1P1_PVT, 12);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static inline void bootloader_glitch_reset_disable(void)
|
||||
static inline void bootloader_ana_reset_config(void)
|
||||
{
|
||||
/*
|
||||
For origin chip & ECO1: only support swt reset;
|
||||
For ECO2: fix brownout reset bug, support swt & brownout reset;
|
||||
For ECO3: fix clock glitch reset bug, support all reset, include: swt & brownout & clock glitch reset.
|
||||
*/
|
||||
uint8_t chip_version = bootloader_common_get_chip_revision();
|
||||
if (chip_version < 2) {
|
||||
REG_SET_FIELD(RTC_CNTL_FIB_SEL_REG, RTC_CNTL_FIB_SEL, RTC_CNTL_FIB_SUPER_WDT_RST);
|
||||
} else if (chip_version == 2) {
|
||||
REG_SET_FIELD(RTC_CNTL_FIB_SEL_REG, RTC_CNTL_FIB_SEL, RTC_CNTL_FIB_SUPER_WDT_RST | RTC_CNTL_FIB_BOR_RST);
|
||||
}
|
||||
//Enable WDT, BOR, and GLITCH reset
|
||||
bootloader_ana_super_wdt_reset_config(true);
|
||||
bootloader_ana_bod_reset_config(true);
|
||||
bootloader_ana_clock_glitch_reset_config(true);
|
||||
}
|
||||
|
||||
esp_err_t bootloader_init(void)
|
||||
@ -282,7 +271,7 @@ esp_err_t bootloader_init(void)
|
||||
esp_err_t ret = ESP_OK;
|
||||
|
||||
bootloader_hardware_init();
|
||||
bootloader_glitch_reset_disable();
|
||||
bootloader_ana_reset_config();
|
||||
bootloader_super_wdt_auto_feed();
|
||||
// protect memory region
|
||||
bootloader_init_mem();
|
||||
|
41
components/bootloader_support/src/esp32h2/bootloader_soc.c
Normal file
41
components/bootloader_support/src/esp32h2/bootloader_soc.c
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include <stdbool.h>
|
||||
#include "soc/soc.h"
|
||||
#include "soc/rtc_cntl_reg.h"
|
||||
|
||||
void bootloader_ana_super_wdt_reset_config(bool enable)
|
||||
{
|
||||
REG_CLR_BIT(RTC_CNTL_FIB_SEL_REG, RTC_CNTL_FIB_SUPER_WDT_RST);
|
||||
|
||||
if (enable) {
|
||||
REG_SET_BIT(RTC_CNTL_SWD_CONF_REG, RTC_CNTL_SWD_BYPASS_RST);
|
||||
} else {
|
||||
REG_CLR_BIT(RTC_CNTL_SWD_CONF_REG, RTC_CNTL_SWD_BYPASS_RST);
|
||||
}
|
||||
}
|
||||
|
||||
void bootloader_ana_bod_reset_config(bool enable)
|
||||
{
|
||||
REG_CLR_BIT(RTC_CNTL_FIB_SEL_REG, RTC_CNTL_FIB_BOR_RST);
|
||||
|
||||
if (enable) {
|
||||
REG_SET_BIT(RTC_CNTL_BROWN_OUT_REG, RTC_CNTL_BROWN_OUT_ANA_RST_EN);
|
||||
} else {
|
||||
REG_CLR_BIT(RTC_CNTL_BROWN_OUT_REG, RTC_CNTL_BROWN_OUT_ANA_RST_EN);
|
||||
}
|
||||
}
|
||||
|
||||
void bootloader_ana_clock_glitch_reset_config(bool enable)
|
||||
{
|
||||
REG_CLR_BIT(RTC_CNTL_FIB_SEL_REG, RTC_CNTL_FIB_GLITCH_RST);
|
||||
|
||||
if (enable) {
|
||||
REG_SET_BIT(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_GLITCH_RST_EN);
|
||||
} else {
|
||||
REG_CLR_BIT(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_GLITCH_RST_EN);
|
||||
}
|
||||
}
|
21
components/bootloader_support/src/esp32s2/bootloader_soc.c
Normal file
21
components/bootloader_support/src/esp32s2/bootloader_soc.c
Normal file
@ -0,0 +1,21 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include <stdbool.h>
|
||||
|
||||
void bootloader_ana_super_wdt_reset_config(bool enable)
|
||||
{
|
||||
(void)enable;
|
||||
}
|
||||
|
||||
void bootloader_ana_bod_reset_config(bool enable)
|
||||
{
|
||||
(void)enable;
|
||||
}
|
||||
|
||||
void bootloader_ana_clock_glitch_reset_config(bool enable)
|
||||
{
|
||||
(void)enable;
|
||||
}
|
@ -34,6 +34,7 @@
|
||||
#include "bootloader_mem.h"
|
||||
#include "bootloader_console.h"
|
||||
#include "bootloader_flash_priv.h"
|
||||
#include "bootloader_soc.h"
|
||||
#include "esp_efuse.h"
|
||||
|
||||
|
||||
@ -296,9 +297,18 @@ static void bootloader_super_wdt_auto_feed(void)
|
||||
REG_WRITE(RTC_CNTL_SWD_WPROTECT_REG, 0);
|
||||
}
|
||||
|
||||
static inline void bootloader_ana_reset_config(void)
|
||||
{
|
||||
//Enable WDT, BOR, and GLITCH reset
|
||||
bootloader_ana_super_wdt_reset_config(true);
|
||||
bootloader_ana_bod_reset_config(true);
|
||||
bootloader_ana_clock_glitch_reset_config(true);
|
||||
}
|
||||
|
||||
esp_err_t bootloader_init(void)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
bootloader_ana_reset_config();
|
||||
bootloader_super_wdt_auto_feed();
|
||||
// protect memory region
|
||||
bootloader_init_mem();
|
||||
|
41
components/bootloader_support/src/esp32s3/bootloader_soc.c
Normal file
41
components/bootloader_support/src/esp32s3/bootloader_soc.c
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#include <stdbool.h>
|
||||
#include "soc/soc.h"
|
||||
#include "soc/rtc_cntl_reg.h"
|
||||
|
||||
void bootloader_ana_super_wdt_reset_config(bool enable)
|
||||
{
|
||||
REG_CLR_BIT(RTC_CNTL_FIB_SEL_REG, RTC_CNTL_FIB_SUPER_WDT_RST);
|
||||
|
||||
if (enable) {
|
||||
REG_SET_BIT(RTC_CNTL_SWD_CONF_REG, RTC_CNTL_SWD_BYPASS_RST);
|
||||
} else {
|
||||
REG_CLR_BIT(RTC_CNTL_SWD_CONF_REG, RTC_CNTL_SWD_BYPASS_RST);
|
||||
}
|
||||
}
|
||||
|
||||
void bootloader_ana_bod_reset_config(bool enable)
|
||||
{
|
||||
REG_CLR_BIT(RTC_CNTL_FIB_SEL_REG, RTC_CNTL_FIB_BOR_RST);
|
||||
|
||||
if (enable) {
|
||||
REG_SET_BIT(RTC_CNTL_BROWN_OUT_REG, RTC_CNTL_BROWN_OUT_ANA_RST_EN);
|
||||
} else {
|
||||
REG_CLR_BIT(RTC_CNTL_BROWN_OUT_REG, RTC_CNTL_BROWN_OUT_ANA_RST_EN);
|
||||
}
|
||||
}
|
||||
|
||||
void bootloader_ana_clock_glitch_reset_config(bool enable)
|
||||
{
|
||||
REG_CLR_BIT(RTC_CNTL_FIB_SEL_REG, RTC_CNTL_FIB_GLITCH_RST);
|
||||
|
||||
if (enable) {
|
||||
REG_SET_BIT(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_GLITCH_RST_EN);
|
||||
} else {
|
||||
REG_CLR_BIT(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_GLITCH_RST_EN);
|
||||
}
|
||||
}
|
@ -1,6 +1,8 @@
|
||||
if(CONFIG_BT_ENABLED)
|
||||
if(CONFIG_IDF_TARGET_ESP32)
|
||||
set(srcs "controller/esp32/bt.c")
|
||||
set(srcs "controller/esp32/bt.c"
|
||||
"controller/esp32/hli_api.c"
|
||||
"controller/esp32/hli_vectors.S")
|
||||
elseif(CONFIG_IDF_TARGET_ESP32C3)
|
||||
set(srcs "controller/esp32c3/bt.c")
|
||||
elseif(CONFIG_IDF_TARGET_ESP32S3)
|
||||
@ -55,6 +57,7 @@ if(CONFIG_BT_ENABLED)
|
||||
host/bluedroid/bta/gatt/include
|
||||
host/bluedroid/bta/hf_ag/include
|
||||
host/bluedroid/bta/hf_client/include
|
||||
host/bluedroid/bta/hd/include
|
||||
host/bluedroid/bta/hh/include
|
||||
host/bluedroid/bta/jv/include
|
||||
host/bluedroid/bta/sdp/include
|
||||
@ -66,12 +69,12 @@ if(CONFIG_BT_ENABLED)
|
||||
host/bluedroid/external/sbc/plc/include
|
||||
host/bluedroid/btc/profile/esp/include
|
||||
host/bluedroid/btc/profile/std/a2dp/include
|
||||
host/bluedroid/btc/profile/std/hid/include
|
||||
host/bluedroid/btc/profile/std/include
|
||||
host/bluedroid/btc/include
|
||||
host/bluedroid/stack/btm/include
|
||||
host/bluedroid/stack/gap/include
|
||||
host/bluedroid/stack/gatt/include
|
||||
host/bluedroid/stack/hid/include
|
||||
host/bluedroid/stack/l2cap/include
|
||||
host/bluedroid/stack/sdp/include
|
||||
host/bluedroid/stack/smp/include
|
||||
@ -94,6 +97,8 @@ if(CONFIG_BT_ENABLED)
|
||||
"host/bluedroid/api/esp_gatt_common_api.c"
|
||||
"host/bluedroid/api/esp_gattc_api.c"
|
||||
"host/bluedroid/api/esp_gatts_api.c"
|
||||
"host/bluedroid/api/esp_hidd_api.c"
|
||||
"host/bluedroid/api/esp_hidh_api.c"
|
||||
"host/bluedroid/api/esp_hf_ag_api.c"
|
||||
"host/bluedroid/api/esp_hf_client_api.c"
|
||||
"host/bluedroid/api/esp_spp_api.c"
|
||||
@ -128,6 +133,9 @@ if(CONFIG_BT_ENABLED)
|
||||
"host/bluedroid/bta/gatt/bta_gatts_co.c"
|
||||
"host/bluedroid/bta/gatt/bta_gatts_main.c"
|
||||
"host/bluedroid/bta/gatt/bta_gatts_utils.c"
|
||||
"host/bluedroid/bta/hd/bta_hd_api.c"
|
||||
"host/bluedroid/bta/hd/bta_hd_act.c"
|
||||
"host/bluedroid/bta/hd/bta_hd_main.c"
|
||||
"host/bluedroid/bta/hh/bta_hh_act.c"
|
||||
"host/bluedroid/bta/hh/bta_hh_api.c"
|
||||
"host/bluedroid/bta/hh/bta_hh_cfg.c"
|
||||
@ -184,8 +192,9 @@ if(CONFIG_BT_ENABLED)
|
||||
"host/bluedroid/btc/profile/std/hf_ag/btc_hf_ag.c"
|
||||
"host/bluedroid/btc/profile/std/hf_client/btc_hf_client.c"
|
||||
"host/bluedroid/btc/profile/std/hf_client/bta_hf_client_co.c"
|
||||
"host/bluedroid/btc/profile/std/hid/hidh_api.c"
|
||||
"host/bluedroid/btc/profile/std/hid/hidh_conn.c"
|
||||
"host/bluedroid/btc/profile/std/hid/btc_hd.c"
|
||||
"host/bluedroid/btc/profile/std/hid/btc_hh.c"
|
||||
"host/bluedroid/btc/profile/std/hid/bta_hh_co.c"
|
||||
"host/bluedroid/btc/profile/std/gap/btc_gap_ble.c"
|
||||
"host/bluedroid/btc/profile/std/gap/btc_gap_bt.c"
|
||||
"host/bluedroid/btc/profile/std/gap/bta_gap_bt_co.c"
|
||||
@ -251,6 +260,10 @@ if(CONFIG_BT_ENABLED)
|
||||
"host/bluedroid/stack/avrc/avrc_pars_tg.c"
|
||||
"host/bluedroid/stack/avrc/avrc_sdp.c"
|
||||
"host/bluedroid/stack/avrc/avrc_utils.c"
|
||||
"host/bluedroid/stack/hid/hidd_api.c"
|
||||
"host/bluedroid/stack/hid/hidd_conn.c"
|
||||
"host/bluedroid/stack/hid/hidh_api.c"
|
||||
"host/bluedroid/stack/hid/hidh_conn.c"
|
||||
"host/bluedroid/stack/btm/btm_acl.c"
|
||||
"host/bluedroid/stack/btm/btm_ble.c"
|
||||
"host/bluedroid/stack/btm/btm_ble_addr.c"
|
||||
@ -597,6 +610,8 @@ if(CONFIG_BT_ENABLED)
|
||||
if(CONFIG_IDF_TARGET_ESP32)
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE "-L${CMAKE_CURRENT_LIST_DIR}/controller/lib_esp32/esp32")
|
||||
target_link_libraries(${COMPONENT_LIB} PUBLIC btdm_app)
|
||||
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u ld_include_hli_vectors_bt")
|
||||
elseif(CONFIG_IDF_TARGET_ESP32C3)
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE
|
||||
"-L${CMAKE_CURRENT_LIST_DIR}/controller/lib_esp32c3_family/esp32c3")
|
||||
|
@ -7,42 +7,16 @@ menu "Bluetooth"
|
||||
help
|
||||
Select this option to enable Bluetooth and show the submenu with Bluetooth configuration choices.
|
||||
|
||||
config BT_CTRL_ESP32
|
||||
bool
|
||||
depends on BT_ENABLED && IDF_TARGET_ESP32
|
||||
default y
|
||||
|
||||
config BT_CTRL_ESP32C3
|
||||
bool
|
||||
depends on BT_ENABLED && IDF_TARGET_ESP32C3
|
||||
default y
|
||||
config BT_CTRL_ESP32S3
|
||||
bool
|
||||
depends on BT_ENABLED && IDF_TARGET_ESP32S3
|
||||
default y
|
||||
|
||||
config BT_SOC_SUPPORT_5_0
|
||||
bool
|
||||
depends on BT_ENABLED && (IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S3)
|
||||
default y if BT_ENABLED && (IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S3)
|
||||
default n
|
||||
|
||||
menu "Bluetooth controller(ESP32 Dual Mode Bluetooth)"
|
||||
visible if BT_CTRL_ESP32
|
||||
menu "Bluetooth controller"
|
||||
depends on BT_ENABLED
|
||||
|
||||
source "$IDF_PATH/components/bt/controller/esp32/Kconfig.in"
|
||||
endmenu
|
||||
|
||||
menu "Bluetooth controller(ESP32C3 Bluetooth Low Energy)"
|
||||
visible if BT_CTRL_ESP32C3
|
||||
|
||||
source "$IDF_PATH/components/bt/controller/esp32c3/Kconfig.in"
|
||||
endmenu
|
||||
|
||||
menu "Bluetooth controller(ESP32S3 Bluetooth Low Energy)"
|
||||
visible if BT_CTRL_ESP32S3
|
||||
|
||||
source "$IDF_PATH/components/bt/controller/esp32s3/Kconfig.in"
|
||||
source "$IDF_PATH/components/bt/controller/$IDF_TARGET/Kconfig.in"
|
||||
endmenu
|
||||
|
||||
choice BT_HOST
|
||||
@ -73,12 +47,12 @@ menu "Bluetooth"
|
||||
endchoice
|
||||
|
||||
menu "Bluedroid Options"
|
||||
visible if BT_BLUEDROID_ENABLED
|
||||
depends on BT_BLUEDROID_ENABLED
|
||||
|
||||
source "$IDF_PATH/components/bt/host/bluedroid/Kconfig.in"
|
||||
endmenu
|
||||
menu "NimBLE Options"
|
||||
visible if BT_NIMBLE_ENABLED
|
||||
depends on BT_NIMBLE_ENABLED
|
||||
|
||||
source "$IDF_PATH/components/bt/host/nimble/Kconfig.in"
|
||||
endmenu
|
||||
|
@ -53,6 +53,12 @@
|
||||
#if BTC_HF_CLIENT_INCLUDED
|
||||
#include "btc_hf_client.h"
|
||||
#endif /* #if BTC_HF_CLIENT_INCLUDED */
|
||||
#if BTC_HD_INCLUDED == TRUE
|
||||
#include "btc_hd.h"
|
||||
#endif /* BTC_HD_INCLUDED */
|
||||
#if BTC_HH_INCLUDED == TRUE
|
||||
#include "btc_hh.h"
|
||||
#endif /* BTC_HH_INCLUDED */
|
||||
#endif /* #if CLASSIC_BT_INCLUDED */
|
||||
#endif
|
||||
|
||||
@ -120,6 +126,12 @@ static const btc_func_t profile_tab[BTC_PID_NUM] = {
|
||||
#if BTC_HF_CLIENT_INCLUDED
|
||||
[BTC_PID_HF_CLIENT] = {btc_hf_client_call_handler, btc_hf_client_cb_handler},
|
||||
#endif /* #if BTC_HF_CLIENT_INCLUDED */
|
||||
#if BTC_HD_INCLUDED
|
||||
[BTC_PID_HD] = {btc_hd_call_handler, btc_hd_cb_handler },
|
||||
#endif
|
||||
#if BTC_HH_INCLUDED
|
||||
[BTC_PID_HH] = {btc_hh_call_handler, btc_hh_cb_handler },
|
||||
#endif
|
||||
#endif /* #if CLASSIC_BT_INCLUDED */
|
||||
#endif
|
||||
#if CONFIG_BLE_MESH
|
||||
|
@ -65,6 +65,8 @@ typedef enum {
|
||||
BTC_PID_AVRC_CT,
|
||||
BTC_PID_AVRC_TG,
|
||||
BTC_PID_SPP,
|
||||
BTC_PID_HD,
|
||||
BTC_PID_HH,
|
||||
#if (BTC_HF_INCLUDED == TRUE)
|
||||
BTC_PID_HF,
|
||||
#endif /* BTC_HF_INCLUDED */
|
||||
@ -99,6 +101,10 @@ typedef struct {
|
||||
|
||||
typedef void (* btc_arg_deep_copy_t)(btc_msg_t *msg, void *dst, void *src);
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* transfer an message to another module in the different task.
|
||||
* @param msg message
|
||||
@ -124,4 +130,8 @@ void btc_deinit(void);
|
||||
bool btc_check_queue_is_congest(void);
|
||||
int get_btc_work_queue_size(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __BTC_TASK_H__ */
|
||||
|
@ -10,6 +10,7 @@ COMPONENT_ADD_INCLUDEDIRS := include
|
||||
LIBS := btdm_app
|
||||
|
||||
COMPONENT_ADD_LDFLAGS := -lbt -L $(COMPONENT_PATH)/controller/lib_esp32/esp32 \
|
||||
-u ld_include_hli_vectors_bt \
|
||||
$(addprefix -l,$(LIBS))
|
||||
|
||||
# re-link program if BT binary libs change
|
||||
@ -46,6 +47,7 @@ COMPONENT_PRIV_INCLUDEDIRS += host/bluedroid/bta/include \
|
||||
host/bluedroid/bta/hf_client/include \
|
||||
host/bluedroid/bta/dm/include \
|
||||
host/bluedroid/bta/gatt/include \
|
||||
host/bluedroid/bta/hd/include \
|
||||
host/bluedroid/bta/hh/include \
|
||||
host/bluedroid/bta/jv/include \
|
||||
host/bluedroid/bta/sdp/include \
|
||||
@ -70,6 +72,7 @@ COMPONENT_PRIV_INCLUDEDIRS += host/bluedroid/bta/include \
|
||||
host/bluedroid/stack/gap/include \
|
||||
host/bluedroid/stack/gatt/include \
|
||||
host/bluedroid/stack/hcic/include \
|
||||
host/bluedroid/stack/hid/include \
|
||||
host/bluedroid/stack/l2cap/include \
|
||||
host/bluedroid/stack/sdp/include \
|
||||
host/bluedroid/stack/smp/include \
|
||||
@ -86,6 +89,7 @@ COMPONENT_ADD_INCLUDEDIRS += host/bluedroid/api/include/api \
|
||||
|
||||
COMPONENT_SRCDIRS += host/bluedroid/bta/dm \
|
||||
host/bluedroid/bta/gatt \
|
||||
host/bluedroid/bta/hd \
|
||||
host/bluedroid/bta/hh \
|
||||
host/bluedroid/bta/sdp \
|
||||
host/bluedroid/bta/av \
|
||||
@ -118,6 +122,7 @@ COMPONENT_SRCDIRS += host/bluedroid/bta/dm \
|
||||
host/bluedroid/stack/gap \
|
||||
host/bluedroid/stack/gatt \
|
||||
host/bluedroid/stack/hcic \
|
||||
host/bluedroid/stack/hid \
|
||||
host/bluedroid/stack/include \
|
||||
host/bluedroid/stack/l2cap \
|
||||
host/bluedroid/stack/sdp \
|
||||
|
@ -1,6 +1,5 @@
|
||||
choice BTDM_CTRL_MODE
|
||||
prompt "Bluetooth controller mode (BR/EDR/BLE/DUALMODE)"
|
||||
depends on BT_CTRL_ESP32
|
||||
help
|
||||
Specify the bluetooth controller mode (BR/EDR, BLE or dual mode).
|
||||
|
||||
@ -152,7 +151,7 @@ config BTDM_CTRL_BR_EDR_MAX_SYNC_CONN_EFF
|
||||
|
||||
choice BTDM_CTRL_PINNED_TO_CORE_CHOICE
|
||||
prompt "The cpu core which bluetooth controller run"
|
||||
depends on BT_CTRL_ESP32 && !FREERTOS_UNICORE
|
||||
depends on !FREERTOS_UNICORE
|
||||
help
|
||||
Specify the cpu core to run bluetooth controller.
|
||||
Can not specify no-affinity.
|
||||
@ -172,7 +171,6 @@ config BTDM_CTRL_PINNED_TO_CORE
|
||||
|
||||
choice BTDM_CTRL_HCI_MODE_CHOICE
|
||||
prompt "HCI mode"
|
||||
depends on BT_CTRL_ESP32
|
||||
help
|
||||
Speicify HCI mode as VHCI or UART(H4)
|
||||
|
||||
@ -210,11 +208,8 @@ menu "HCI UART(H4) Options"
|
||||
endmenu
|
||||
|
||||
menu "MODEM SLEEP Options"
|
||||
visible if BT_CTRL_ESP32
|
||||
|
||||
config BTDM_CTRL_MODEM_SLEEP
|
||||
bool "Bluetooth modem sleep"
|
||||
depends on BT_CTRL_ESP32
|
||||
default y
|
||||
help
|
||||
Enable/disable bluetooth controller low power mode.
|
||||
@ -415,3 +410,16 @@ config BTDM_BLE_ADV_REPORT_DISCARD_THRSHOLD
|
||||
of ADV packets lost in the controller reaches this threshold. It is better to set a larger value.
|
||||
If you set `BTDM_BLE_ADV_REPORT_DISCARD_THRSHOLD` to a small value or printf every adv lost event, it
|
||||
may cause adv packets lost more.
|
||||
|
||||
|
||||
config BTDM_RESERVE_DRAM
|
||||
hex
|
||||
default 0xdb5c if BT_ENABLED
|
||||
default 0
|
||||
|
||||
config BTDM_CTRL_HLI
|
||||
bool "High level interrupt"
|
||||
depends on BT_ENABLED
|
||||
default y
|
||||
help
|
||||
Using Level 4 interrupt for Bluetooth.
|
||||
|
@ -40,6 +40,7 @@
|
||||
#include "driver/periph_ctrl.h"
|
||||
#include "soc/rtc.h"
|
||||
#include "soc/soc_memory_layout.h"
|
||||
#include "soc/dport_reg.h"
|
||||
#include "esp32/clk.h"
|
||||
#include "esp_coexist_internal.h"
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
@ -47,6 +48,7 @@
|
||||
#endif
|
||||
|
||||
#include "esp_rom_sys.h"
|
||||
#include "hli_api.h"
|
||||
|
||||
#if CONFIG_BT_ENABLED
|
||||
|
||||
@ -54,6 +56,7 @@
|
||||
************************************************************************
|
||||
*/
|
||||
|
||||
#define UNUSED(x) (void)(x)
|
||||
#define BTDM_LOG_TAG "BTDM_INIT"
|
||||
|
||||
#define BTDM_INIT_PERIOD (5000) /* ms */
|
||||
@ -92,12 +95,12 @@ do{\
|
||||
} while(0)
|
||||
|
||||
#define OSI_FUNCS_TIME_BLOCKING 0xffffffff
|
||||
#define OSI_VERSION 0x00010002
|
||||
#define OSI_VERSION 0x00010003
|
||||
#define OSI_MAGIC_VALUE 0xFADEBEAD
|
||||
|
||||
/* SPIRAM Configuration */
|
||||
#if CONFIG_SPIRAM_USE_MALLOC
|
||||
#define BTDM_MAX_QUEUE_NUM (5)
|
||||
#define BTDM_MAX_QUEUE_NUM (6)
|
||||
#endif
|
||||
|
||||
/* Types definition
|
||||
@ -184,6 +187,10 @@ struct osi_funcs_t {
|
||||
void *(* _coex_schm_curr_phase_get)(void);
|
||||
int (* _coex_wifi_channel_get)(uint8_t *primary, uint8_t *secondary);
|
||||
int (* _coex_register_wifi_channel_change_callback)(void *cb);
|
||||
xt_handler (*_set_isr_l3)(int n, xt_handler f, void *arg);
|
||||
void (*_interrupt_l3_disable)(void);
|
||||
void (*_interrupt_l3_restore)(void);
|
||||
void *(* _customer_queue_create)(uint32_t queue_len, uint32_t item_size);
|
||||
uint32_t _magic;
|
||||
};
|
||||
|
||||
@ -268,8 +275,13 @@ extern uint32_t _btdm_data_end;
|
||||
static bool btdm_queue_generic_register(const btdm_queue_item_t *queue);
|
||||
static bool btdm_queue_generic_deregister(btdm_queue_item_t *queue);
|
||||
#endif /* CONFIG_SPIRAM_USE_MALLOC */
|
||||
static void IRAM_ATTR interrupt_disable(void);
|
||||
static void IRAM_ATTR interrupt_restore(void);
|
||||
|
||||
#if CONFIG_BTDM_CTRL_HLI
|
||||
static xt_handler set_isr_hlevel_wrapper(int n, xt_handler f, void *arg);
|
||||
static void IRAM_ATTR interrupt_hlevel_disable(void);
|
||||
static void IRAM_ATTR interrupt_hlevel_restore(void);
|
||||
#endif /* CONFIG_BTDM_CTRL_HLI */
|
||||
static void IRAM_ATTR task_yield(void);
|
||||
static void IRAM_ATTR task_yield_from_isr(void);
|
||||
static void *semphr_create_wrapper(uint32_t max, uint32_t init);
|
||||
static void semphr_delete_wrapper(void *semphr);
|
||||
@ -281,12 +293,21 @@ static void *mutex_create_wrapper(void);
|
||||
static void mutex_delete_wrapper(void *mutex);
|
||||
static int32_t mutex_lock_wrapper(void *mutex);
|
||||
static int32_t mutex_unlock_wrapper(void *mutex);
|
||||
#if CONFIG_BTDM_CTRL_HLI
|
||||
static void *queue_create_hlevel_wrapper(uint32_t queue_len, uint32_t item_size);
|
||||
static void queue_delete_hlevel_wrapper(void *queue);
|
||||
static int32_t IRAM_ATTR queue_send_hlevel_wrapper(void *queue, void *item, uint32_t block_time_ms);
|
||||
static int32_t IRAM_ATTR queue_send_from_isr_hlevel_wrapper(void *queue, void *item, void *hptw);
|
||||
static int32_t IRAM_ATTR queue_recv_hlevel_wrapper(void *queue, void *item, uint32_t block_time_ms);
|
||||
static int32_t IRAM_ATTR queue_recv_from_isr_hlevel_wrapper(void *queue, void *item, void *hptw);
|
||||
#else
|
||||
static void *queue_create_wrapper(uint32_t queue_len, uint32_t item_size);
|
||||
static void queue_delete_wrapper(void *queue);
|
||||
static int32_t queue_send_wrapper(void *queue, void *item, uint32_t block_time_ms);
|
||||
static int32_t IRAM_ATTR queue_send_wrapper(void *queue, void *item, uint32_t block_time_ms);
|
||||
static int32_t IRAM_ATTR queue_send_from_isr_wrapper(void *queue, void *item, void *hptw);
|
||||
static int32_t queue_recv_wrapper(void *queue, void *item, uint32_t block_time_ms);
|
||||
static int32_t IRAM_ATTR queue_recv_wrapper(void *queue, void *item, uint32_t block_time_ms);
|
||||
static int32_t IRAM_ATTR queue_recv_from_isr_wrapper(void *queue, void *item, void *hptw);
|
||||
#endif /* CONFIG_BTDM_CTRL_HLI */
|
||||
static int32_t task_create_wrapper(void *task_func, const char *name, uint32_t stack_depth, void *param, uint32_t prio, void *task_handle, uint32_t core_id);
|
||||
static void task_delete_wrapper(void *task_handle);
|
||||
static bool IRAM_ATTR is_in_isr_wrapper(void);
|
||||
@ -317,17 +338,30 @@ static uint8_t coex_schm_curr_period_get_wrapper(void);
|
||||
static void * coex_schm_curr_phase_get_wrapper(void);
|
||||
static int coex_wifi_channel_get_wrapper(uint8_t *primary, uint8_t *secondary);
|
||||
static int coex_register_wifi_channel_change_callback_wrapper(void *cb);
|
||||
#if CONFIG_BTDM_CTRL_HLI
|
||||
static void *customer_queue_create_hlevel_wrapper(uint32_t queue_len, uint32_t item_size);
|
||||
#endif /* CONFIG_BTDM_CTRL_HLI */
|
||||
static void IRAM_ATTR interrupt_l3_disable(void);
|
||||
static void IRAM_ATTR interrupt_l3_restore(void);
|
||||
|
||||
/* Local variable definition
|
||||
***************************************************************************
|
||||
*/
|
||||
/* OSI funcs */
|
||||
static const struct osi_funcs_t osi_funcs_ro = {
|
||||
._version = OSI_VERSION,
|
||||
#if CONFIG_BTDM_CTRL_HLI
|
||||
._set_isr = set_isr_hlevel_wrapper,
|
||||
._ints_on = xt_ints_on,
|
||||
._interrupt_disable = interrupt_hlevel_disable,
|
||||
._interrupt_restore = interrupt_hlevel_restore,
|
||||
#else
|
||||
._set_isr = xt_set_interrupt_handler,
|
||||
._ints_on = xt_ints_on,
|
||||
._interrupt_disable = interrupt_disable,
|
||||
._interrupt_restore = interrupt_restore,
|
||||
._task_yield = vPortYield,
|
||||
._interrupt_disable = interrupt_l3_disable,
|
||||
._interrupt_restore = interrupt_l3_restore,
|
||||
#endif /* CONFIG_BTDM_CTRL_HLI */
|
||||
._task_yield = task_yield,
|
||||
._task_yield_from_isr = task_yield_from_isr,
|
||||
._semphr_create = semphr_create_wrapper,
|
||||
._semphr_delete = semphr_delete_wrapper,
|
||||
@ -339,12 +373,21 @@ static const struct osi_funcs_t osi_funcs_ro = {
|
||||
._mutex_delete = mutex_delete_wrapper,
|
||||
._mutex_lock = mutex_lock_wrapper,
|
||||
._mutex_unlock = mutex_unlock_wrapper,
|
||||
#if CONFIG_BTDM_CTRL_HLI
|
||||
._queue_create = queue_create_hlevel_wrapper,
|
||||
._queue_delete = queue_delete_hlevel_wrapper,
|
||||
._queue_send = queue_send_hlevel_wrapper,
|
||||
._queue_send_from_isr = queue_send_from_isr_hlevel_wrapper,
|
||||
._queue_recv = queue_recv_hlevel_wrapper,
|
||||
._queue_recv_from_isr = queue_recv_from_isr_hlevel_wrapper,
|
||||
#else
|
||||
._queue_create = queue_create_wrapper,
|
||||
._queue_delete = queue_delete_wrapper,
|
||||
._queue_send = queue_send_wrapper,
|
||||
._queue_send_from_isr = queue_send_from_isr_wrapper,
|
||||
._queue_recv = queue_recv_wrapper,
|
||||
._queue_recv_from_isr = queue_recv_from_isr_wrapper,
|
||||
#endif /* CONFIG_BTDM_CTRL_HLI */
|
||||
._task_create = task_create_wrapper,
|
||||
._task_delete = task_delete_wrapper,
|
||||
._is_in_isr = is_in_isr_wrapper,
|
||||
@ -378,6 +421,14 @@ static const struct osi_funcs_t osi_funcs_ro = {
|
||||
._coex_schm_curr_phase_get = coex_schm_curr_phase_get_wrapper,
|
||||
._coex_wifi_channel_get = coex_wifi_channel_get_wrapper,
|
||||
._coex_register_wifi_channel_change_callback = coex_register_wifi_channel_change_callback_wrapper,
|
||||
._set_isr_l3 = xt_set_interrupt_handler,
|
||||
._interrupt_l3_disable = interrupt_l3_disable,
|
||||
._interrupt_l3_restore = interrupt_l3_restore,
|
||||
#if CONFIG_BTDM_CTRL_HLI
|
||||
._customer_queue_create = customer_queue_create_hlevel_wrapper,
|
||||
#else
|
||||
._customer_queue_create = NULL,
|
||||
#endif /* CONFIG_BTDM_CTRL_HLI */
|
||||
._magic = OSI_MAGIC_VALUE,
|
||||
};
|
||||
|
||||
@ -494,7 +545,48 @@ static bool btdm_queue_generic_deregister(btdm_queue_item_t *queue)
|
||||
|
||||
#endif /* CONFIG_SPIRAM_USE_MALLOC */
|
||||
|
||||
static void IRAM_ATTR interrupt_disable(void)
|
||||
#if CONFIG_BTDM_CTRL_HLI
|
||||
struct interrupt_hlevel_cb{
|
||||
uint32_t status;
|
||||
uint8_t nested;
|
||||
};
|
||||
|
||||
static DRAM_ATTR struct interrupt_hlevel_cb hli_cb = {
|
||||
.status = 0,
|
||||
.nested = 0,
|
||||
};
|
||||
|
||||
static xt_handler set_isr_hlevel_wrapper(int mask, xt_handler f, void *arg)
|
||||
{
|
||||
esp_err_t err = hli_intr_register((intr_handler_t) f, arg, DPORT_PRO_INTR_STATUS_0_REG, mask);
|
||||
if (err == ESP_OK) {
|
||||
return f;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void IRAM_ATTR interrupt_hlevel_disable(void)
|
||||
{
|
||||
assert(xPortGetCoreID() == CONFIG_BTDM_CTRL_PINNED_TO_CORE);
|
||||
assert(hli_cb.nested != ~0);
|
||||
uint32_t status = hli_intr_disable();
|
||||
if (hli_cb.nested++ == 0) {
|
||||
hli_cb.status = status;
|
||||
}
|
||||
}
|
||||
|
||||
static void IRAM_ATTR interrupt_hlevel_restore(void)
|
||||
{
|
||||
assert(xPortGetCoreID() == CONFIG_BTDM_CTRL_PINNED_TO_CORE);
|
||||
assert(hli_cb.nested > 0);
|
||||
if (--hli_cb.nested == 0) {
|
||||
hli_intr_restore(hli_cb.status);
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_BTDM_CTRL_HLI */
|
||||
|
||||
static void IRAM_ATTR interrupt_l3_disable(void)
|
||||
{
|
||||
if (xPortInIsrContext()) {
|
||||
portENTER_CRITICAL_ISR(&global_int_mux);
|
||||
@ -503,7 +595,7 @@ static void IRAM_ATTR interrupt_disable(void)
|
||||
}
|
||||
}
|
||||
|
||||
static void IRAM_ATTR interrupt_restore(void)
|
||||
static void IRAM_ATTR interrupt_l3_restore(void)
|
||||
{
|
||||
if (xPortInIsrContext()) {
|
||||
portEXIT_CRITICAL_ISR(&global_int_mux);
|
||||
@ -512,6 +604,12 @@ static void IRAM_ATTR interrupt_restore(void)
|
||||
}
|
||||
}
|
||||
|
||||
static void IRAM_ATTR task_yield(void)
|
||||
{
|
||||
vPortYield();
|
||||
}
|
||||
|
||||
|
||||
static void IRAM_ATTR task_yield_from_isr(void)
|
||||
{
|
||||
portYIELD_FROM_ISR();
|
||||
@ -519,18 +617,19 @@ static void IRAM_ATTR task_yield_from_isr(void)
|
||||
|
||||
static void *semphr_create_wrapper(uint32_t max, uint32_t init)
|
||||
{
|
||||
void *handle = NULL;
|
||||
|
||||
#if !CONFIG_SPIRAM_USE_MALLOC
|
||||
return (void *)xSemaphoreCreateCounting(max, init);
|
||||
handle = (void *)xSemaphoreCreateCounting(max, init);
|
||||
#else
|
||||
StaticQueue_t *queue_buffer = NULL;
|
||||
QueueHandle_t handle = NULL;
|
||||
|
||||
queue_buffer = heap_caps_malloc(sizeof(StaticQueue_t), MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
|
||||
if (!queue_buffer) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
handle = xSemaphoreCreateCountingStatic(max, init, queue_buffer);
|
||||
handle = (void *)xSemaphoreCreateCountingStatic(max, init, queue_buffer);
|
||||
if (!handle) {
|
||||
goto error;
|
||||
}
|
||||
@ -544,8 +643,19 @@ static void *semphr_create_wrapper(uint32_t max, uint32_t init)
|
||||
if (!btdm_queue_generic_register(&item)) {
|
||||
goto error;
|
||||
}
|
||||
return handle;
|
||||
#endif
|
||||
|
||||
#if CONFIG_BTDM_CTRL_HLI
|
||||
SemaphoreHandle_t downstream_semaphore = handle;
|
||||
assert(downstream_semaphore);
|
||||
hli_queue_handle_t s_semaphore = hli_semaphore_create(max, downstream_semaphore);
|
||||
assert(downstream_semaphore);
|
||||
return s_semaphore;
|
||||
#else
|
||||
return handle;
|
||||
#endif /* CONFIG_BTDM_CTRL_HLI */
|
||||
|
||||
#if CONFIG_SPIRAM_USE_MALLOC
|
||||
error:
|
||||
if (handle) {
|
||||
vSemaphoreDelete(handle);
|
||||
@ -560,11 +670,22 @@ static void *semphr_create_wrapper(uint32_t max, uint32_t init)
|
||||
|
||||
static void semphr_delete_wrapper(void *semphr)
|
||||
{
|
||||
void *handle = NULL;
|
||||
#if CONFIG_BTDM_CTRL_HLI
|
||||
if (((hli_queue_handle_t)semphr)->downstream != NULL) {
|
||||
handle = ((hli_queue_handle_t)semphr)->downstream;
|
||||
}
|
||||
|
||||
hli_queue_delete(semphr);
|
||||
#else
|
||||
handle = semphr;
|
||||
#endif /* CONFIG_BTDM_CTRL_HLI */
|
||||
|
||||
#if !CONFIG_SPIRAM_USE_MALLOC
|
||||
vSemaphoreDelete(semphr);
|
||||
vSemaphoreDelete(handle);
|
||||
#else
|
||||
btdm_queue_item_t item = {
|
||||
.handle = semphr,
|
||||
.handle = handle,
|
||||
.storage = NULL,
|
||||
.buffer = NULL,
|
||||
};
|
||||
@ -573,33 +694,55 @@ static void semphr_delete_wrapper(void *semphr)
|
||||
vSemaphoreDelete(item.handle);
|
||||
free(item.buffer);
|
||||
}
|
||||
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int32_t IRAM_ATTR semphr_take_from_isr_wrapper(void *semphr, void *hptw)
|
||||
{
|
||||
#if CONFIG_BTDM_CTRL_HLI
|
||||
return (int32_t)xSemaphoreTakeFromISR(((hli_queue_handle_t)semphr)->downstream, hptw);
|
||||
#else
|
||||
return (int32_t)xSemaphoreTakeFromISR(semphr, hptw);
|
||||
#endif /* CONFIG_BTDM_CTRL_HLI */
|
||||
}
|
||||
|
||||
static int32_t IRAM_ATTR semphr_give_from_isr_wrapper(void *semphr, void *hptw)
|
||||
{
|
||||
#if CONFIG_BTDM_CTRL_HLI
|
||||
UNUSED(hptw);
|
||||
assert(xPortGetCoreID() == CONFIG_BTDM_CTRL_PINNED_TO_CORE);
|
||||
return hli_semaphore_give(semphr);
|
||||
#else
|
||||
return (int32_t)xSemaphoreGiveFromISR(semphr, hptw);
|
||||
#endif /* CONFIG_BTDM_CTRL_HLI */
|
||||
}
|
||||
|
||||
static int32_t semphr_take_wrapper(void *semphr, uint32_t block_time_ms)
|
||||
{
|
||||
bool ret;
|
||||
#if CONFIG_BTDM_CTRL_HLI
|
||||
if (block_time_ms == OSI_FUNCS_TIME_BLOCKING) {
|
||||
return (int32_t)xSemaphoreTake(semphr, portMAX_DELAY);
|
||||
ret = xSemaphoreTake(((hli_queue_handle_t)semphr)->downstream, portMAX_DELAY);
|
||||
} else {
|
||||
return (int32_t)xSemaphoreTake(semphr, block_time_ms / portTICK_PERIOD_MS);
|
||||
ret = xSemaphoreTake(((hli_queue_handle_t)semphr)->downstream, block_time_ms / portTICK_PERIOD_MS);
|
||||
}
|
||||
#else
|
||||
if (block_time_ms == OSI_FUNCS_TIME_BLOCKING) {
|
||||
ret = xSemaphoreTake(semphr, portMAX_DELAY);
|
||||
} else {
|
||||
ret = xSemaphoreTake(semphr, block_time_ms / portTICK_PERIOD_MS);
|
||||
}
|
||||
#endif /* CONFIG_BTDM_CTRL_HLI */
|
||||
return (int32_t)ret;
|
||||
}
|
||||
|
||||
static int32_t semphr_give_wrapper(void *semphr)
|
||||
{
|
||||
#if CONFIG_BTDM_CTRL_HLI
|
||||
return (int32_t)xSemaphoreGive(((hli_queue_handle_t)semphr)->downstream);
|
||||
#else
|
||||
return (int32_t)xSemaphoreGive(semphr);
|
||||
#endif /* CONFIG_BTDM_CTRL_HLI */
|
||||
}
|
||||
|
||||
static void *mutex_create_wrapper(void)
|
||||
@ -745,6 +888,79 @@ static void queue_delete_wrapper(void *queue)
|
||||
#endif
|
||||
}
|
||||
|
||||
#if CONFIG_BTDM_CTRL_HLI
|
||||
static void *queue_create_hlevel_wrapper(uint32_t queue_len, uint32_t item_size)
|
||||
{
|
||||
QueueHandle_t downstream_queue = queue_create_wrapper(queue_len, item_size);
|
||||
assert(downstream_queue);
|
||||
hli_queue_handle_t queue = hli_queue_create(queue_len, item_size, downstream_queue);
|
||||
assert(queue);
|
||||
return queue;
|
||||
}
|
||||
|
||||
static void *customer_queue_create_hlevel_wrapper(uint32_t queue_len, uint32_t item_size)
|
||||
{
|
||||
QueueHandle_t downstream_queue = queue_create_wrapper(queue_len, item_size);
|
||||
assert(downstream_queue);
|
||||
hli_queue_handle_t queue = hli_customer_queue_create(queue_len, item_size, downstream_queue);
|
||||
assert(queue);
|
||||
return queue;
|
||||
}
|
||||
|
||||
static void queue_delete_hlevel_wrapper(void *queue)
|
||||
{
|
||||
if (((hli_queue_handle_t)queue)->downstream != NULL) {
|
||||
queue_delete_wrapper(((hli_queue_handle_t)queue)->downstream);
|
||||
}
|
||||
hli_queue_delete(queue);
|
||||
}
|
||||
|
||||
static int32_t queue_send_hlevel_wrapper(void *queue, void *item, uint32_t block_time_ms)
|
||||
{
|
||||
if (block_time_ms == OSI_FUNCS_TIME_BLOCKING) {
|
||||
return (int32_t)xQueueSend(((hli_queue_handle_t)queue)->downstream, item, portMAX_DELAY);
|
||||
} else {
|
||||
return (int32_t)xQueueSend(((hli_queue_handle_t)queue)->downstream, item, block_time_ms / portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Queue send from isr
|
||||
* @param queue The queue which will send to
|
||||
* @param item The message which will be send
|
||||
* @param hptw need do task yield or not
|
||||
* @return send success or not
|
||||
* There is an issue here: When the queue is full, it may reture true but it send fail to the queue, sometimes.
|
||||
* But in Bluetooth controller's isr, We don't care about the return value.
|
||||
* It only required tp send success when the queue is empty all the time.
|
||||
* So, this function meets the requirement.
|
||||
*/
|
||||
static int32_t IRAM_ATTR queue_send_from_isr_hlevel_wrapper(void *queue, void *item, void *hptw)
|
||||
{
|
||||
UNUSED(hptw);
|
||||
assert(xPortGetCoreID() == CONFIG_BTDM_CTRL_PINNED_TO_CORE);
|
||||
return hli_queue_put(queue, item);
|
||||
}
|
||||
|
||||
static int32_t queue_recv_hlevel_wrapper(void *queue, void *item, uint32_t block_time_ms)
|
||||
{
|
||||
bool ret;
|
||||
if (block_time_ms == OSI_FUNCS_TIME_BLOCKING) {
|
||||
ret = xQueueReceive(((hli_queue_handle_t)queue)->downstream, item, portMAX_DELAY);
|
||||
} else {
|
||||
ret = xQueueReceive(((hli_queue_handle_t)queue)->downstream, item, block_time_ms / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
return (int32_t)ret;
|
||||
}
|
||||
|
||||
static int32_t IRAM_ATTR queue_recv_from_isr_hlevel_wrapper(void *queue, void *item, void *hptw)
|
||||
{
|
||||
return (int32_t)xQueueReceiveFromISR(((hli_queue_handle_t)queue)->downstream, item, hptw);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static int32_t queue_send_wrapper(void *queue, void *item, uint32_t block_time_ms)
|
||||
{
|
||||
if (block_time_ms == OSI_FUNCS_TIME_BLOCKING) {
|
||||
@ -760,18 +976,23 @@ static int32_t IRAM_ATTR queue_send_from_isr_wrapper(void *queue, void *item, vo
|
||||
}
|
||||
|
||||
static int32_t queue_recv_wrapper(void *queue, void *item, uint32_t block_time_ms)
|
||||
{
|
||||
{
|
||||
bool ret;
|
||||
if (block_time_ms == OSI_FUNCS_TIME_BLOCKING) {
|
||||
return (int32_t)xQueueReceive(queue, item, portMAX_DELAY);
|
||||
ret = xQueueReceive(queue, item, portMAX_DELAY);
|
||||
} else {
|
||||
return (int32_t)xQueueReceive(queue, item, block_time_ms / portTICK_PERIOD_MS);
|
||||
ret = xQueueReceive(queue, item, block_time_ms / portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
|
||||
return (int32_t)ret;
|
||||
}
|
||||
|
||||
static int32_t IRAM_ATTR queue_recv_from_isr_wrapper(void *queue, void *item, void *hptw)
|
||||
{
|
||||
return (int32_t)xQueueReceiveFromISR(queue, item, hptw);
|
||||
}
|
||||
#endif /* CONFIG_BTDM_CTRL_HLI */
|
||||
|
||||
|
||||
static int32_t task_create_wrapper(void *task_func, const char *name, uint32_t stack_depth, void *param, uint32_t prio, void *task_handle, uint32_t core_id)
|
||||
{
|
||||
@ -1317,11 +1538,35 @@ esp_err_t esp_bt_mem_release(esp_bt_mode_t mode)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
#if CONFIG_BTDM_CTRL_HLI
|
||||
static void hli_queue_setup_cb(void* arg)
|
||||
{
|
||||
hli_queue_setup();
|
||||
}
|
||||
|
||||
static void hli_queue_setup_pinned_to_core(int core_id)
|
||||
{
|
||||
#if CONFIG_FREERTOS_UNICORE
|
||||
hli_queue_setup_cb(NULL);
|
||||
#else /* CONFIG_FREERTOS_UNICORE */
|
||||
if (xPortGetCoreID() == core_id) {
|
||||
hli_queue_setup_cb(NULL);
|
||||
} else {
|
||||
esp_ipc_call(core_id, hli_queue_setup_cb, NULL);
|
||||
}
|
||||
#endif /* !CONFIG_FREERTOS_UNICORE */
|
||||
}
|
||||
#endif /* CONFIG_BTDM_CTRL_HLI */
|
||||
|
||||
esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg)
|
||||
{
|
||||
esp_err_t err;
|
||||
uint32_t btdm_cfg_mask = 0;
|
||||
|
||||
#if CONFIG_BTDM_CTRL_HLI
|
||||
hli_queue_setup_pinned_to_core(CONFIG_BTDM_CTRL_PINNED_TO_CORE);
|
||||
#endif /* CONFIG_BTDM_CTRL_HLI */
|
||||
|
||||
//if all the bt available memory was already released, cannot initialize bluetooth controller
|
||||
if (btdm_dram_available_region[0].mode == ESP_BT_MODE_IDLE) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
@ -1736,4 +1981,15 @@ esp_err_t esp_ble_scan_dupilcate_list_flush(void)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function re-write controller's function,
|
||||
* As coredump can not show paramerters in function which is in a .a file.
|
||||
*
|
||||
* After coredump fixing this issue, just delete this function.
|
||||
*/
|
||||
void IRAM_ATTR r_assert(const char *condition, int param0, int param1, const char *file, int line)
|
||||
{
|
||||
__asm__ __volatile__("ill\n");
|
||||
}
|
||||
|
||||
#endif /* CONFIG_BT_ENABLED */
|
||||
|
306
components/bt/controller/esp32/hli_api.c
Normal file
306
components/bt/controller/esp32/hli_api.c
Normal file
@ -0,0 +1,306 @@
|
||||
// Copyright 2015-2021 Espressif Systems (Shanghai) CO LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
|
||||
#include <string.h>
|
||||
#include "esp_log.h"
|
||||
#include "esp_heap_caps.h"
|
||||
#include "xtensa/core-macros.h"
|
||||
#include "soc/dport_reg.h"
|
||||
#include "hli_api.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/queue.h"
|
||||
|
||||
#if CONFIG_BTDM_CTRL_HLI
|
||||
#define HLI_MAX_HANDLERS 4
|
||||
|
||||
typedef struct {
|
||||
intr_handler_t handler;
|
||||
void* arg;
|
||||
uint32_t intr_reg;
|
||||
uint32_t intr_mask;
|
||||
} hli_handler_info_t;
|
||||
|
||||
typedef struct {
|
||||
#define CUSTOMER_TYPE_REQUEST (0)
|
||||
#define CUSTOMER_TYPE_RELEASE (1)
|
||||
struct {
|
||||
uint32_t cb_type;
|
||||
union {
|
||||
int (* request)(uint32_t, uint32_t, uint32_t);
|
||||
int (* release)(uint32_t);
|
||||
} cb;
|
||||
} customer_cb;
|
||||
uint32_t arg0, arg1, arg2;
|
||||
} customer_swisr_t;
|
||||
|
||||
static void IRAM_ATTR customer_swisr_handle(customer_swisr_t *cus_swisr)
|
||||
{
|
||||
if (cus_swisr->customer_cb.cb_type == CUSTOMER_TYPE_REQUEST) {
|
||||
if (cus_swisr->customer_cb.cb.request != NULL) {
|
||||
cus_swisr->customer_cb.cb.request(cus_swisr->arg0, cus_swisr->arg1, cus_swisr->arg2);
|
||||
}
|
||||
} else if(cus_swisr->customer_cb.cb_type == CUSTOMER_TYPE_RELEASE) {
|
||||
if (cus_swisr->customer_cb.cb.release != NULL) {
|
||||
cus_swisr->customer_cb.cb.release(cus_swisr->arg0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static DRAM_ATTR hli_handler_info_t s_hli_handlers[HLI_MAX_HANDLERS];
|
||||
|
||||
esp_err_t hli_intr_register(intr_handler_t handler, void* arg, uint32_t intr_reg, uint32_t intr_mask)
|
||||
{
|
||||
for (hli_handler_info_t* hip = s_hli_handlers;
|
||||
hip < s_hli_handlers + HLI_MAX_HANDLERS;
|
||||
++hip) {
|
||||
if (hip->handler == NULL) {
|
||||
hip->arg = arg;
|
||||
hip->intr_reg = intr_reg;
|
||||
hip->intr_mask = intr_mask;
|
||||
hip->handler = handler; /* set last, indicates the entry as valid */
|
||||
return ESP_OK;
|
||||
}
|
||||
}
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
void IRAM_ATTR hli_c_handler(void)
|
||||
{
|
||||
bool handled = false;
|
||||
/* Iterate over registered interrupt handlers,
|
||||
* and check if the expected mask is present in the interrupt status register.
|
||||
*/
|
||||
for (hli_handler_info_t* hip = s_hli_handlers;
|
||||
hip < s_hli_handlers + HLI_MAX_HANDLERS;
|
||||
++hip) {
|
||||
if (hip->handler == NULL) {
|
||||
continue;
|
||||
}
|
||||
uint32_t reg = hip->intr_reg;
|
||||
uint32_t val;
|
||||
if (reg == 0) { /* special case for CPU internal interrupts */
|
||||
val = XTHAL_GET_INTERRUPT();
|
||||
} else {
|
||||
/* "reg" might not be in DPORT, but this will work in any case */
|
||||
val = DPORT_REG_READ(reg);
|
||||
}
|
||||
if ((val & hip->intr_mask) != 0) {
|
||||
handled = true;
|
||||
(*hip->handler)(hip->arg);
|
||||
}
|
||||
}
|
||||
if (!handled) {
|
||||
/* no handler found, it is OK in this case. */
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t IRAM_ATTR hli_intr_disable(void)
|
||||
{
|
||||
/* disable level 4 and below */
|
||||
return XTOS_SET_INTLEVEL(XCHAL_DEBUGLEVEL - 2);
|
||||
}
|
||||
|
||||
void IRAM_ATTR hli_intr_restore(uint32_t state)
|
||||
{
|
||||
XTOS_RESTORE_JUST_INTLEVEL(state);
|
||||
}
|
||||
|
||||
#define HLI_META_QUEUE_SIZE 16
|
||||
#define HLI_QUEUE_MAX_ELEM_SIZE 32
|
||||
#define HLI_QUEUE_SW_INT_NUM 29
|
||||
|
||||
#define HLI_QUEUE_FLAG_SEMAPHORE BIT(0)
|
||||
#define HLI_QUEUE_FLAG_CUSTOMER BIT(1)
|
||||
|
||||
static DRAM_ATTR struct hli_queue_t *s_meta_queue_ptr = NULL;
|
||||
static intr_handle_t ret_handle;
|
||||
|
||||
static inline char* IRAM_ATTR wrap_ptr(hli_queue_handle_t queue, char *ptr)
|
||||
{
|
||||
return (ptr == queue->bufend) ? queue->buf : ptr;
|
||||
}
|
||||
|
||||
static inline bool IRAM_ATTR queue_empty(hli_queue_handle_t queue)
|
||||
{
|
||||
return queue->begin == queue->end;
|
||||
}
|
||||
|
||||
static inline bool IRAM_ATTR queue_full(hli_queue_handle_t queue)
|
||||
{
|
||||
return wrap_ptr(queue, queue->end + queue->elem_size) == queue->begin;
|
||||
}
|
||||
|
||||
static void IRAM_ATTR queue_isr_handler(void* arg)
|
||||
{
|
||||
int do_yield = pdFALSE;
|
||||
XTHAL_SET_INTCLEAR(BIT(HLI_QUEUE_SW_INT_NUM));
|
||||
hli_queue_handle_t queue;
|
||||
|
||||
while (hli_queue_get(s_meta_queue_ptr, &queue)) {
|
||||
static DRAM_ATTR char scratch[HLI_QUEUE_MAX_ELEM_SIZE];
|
||||
while (hli_queue_get(queue, scratch)) {
|
||||
int res = pdPASS;
|
||||
if ((queue->flags & HLI_QUEUE_FLAG_CUSTOMER) != 0) {
|
||||
customer_swisr_handle((customer_swisr_t *)scratch);
|
||||
} else if ((queue->flags & HLI_QUEUE_FLAG_SEMAPHORE) != 0) {
|
||||
res = xSemaphoreGiveFromISR((SemaphoreHandle_t) queue->downstream, &do_yield);
|
||||
} else {
|
||||
res = xQueueSendFromISR(queue->downstream, scratch, &do_yield);
|
||||
}
|
||||
if (res == pdFAIL) {
|
||||
/* Failed to send to downstream queue, it is OK in this case. */
|
||||
}
|
||||
}
|
||||
}
|
||||
if (do_yield) {
|
||||
portYIELD_FROM_ISR();
|
||||
}
|
||||
}
|
||||
|
||||
/* Notify the level 3 handler that an element is added to the given hli queue.
|
||||
* Do this by placing the queue handle onto s_meta_queue, and raising a SW interrupt.
|
||||
*
|
||||
* This function must be called with HL interrupts disabled!
|
||||
*/
|
||||
static void IRAM_ATTR queue_signal(hli_queue_handle_t queue)
|
||||
{
|
||||
/* See if the queue is already in s_meta_queue, before adding */
|
||||
bool found = false;
|
||||
const hli_queue_handle_t *end = (hli_queue_handle_t*) s_meta_queue_ptr->end;
|
||||
hli_queue_handle_t *item = (hli_queue_handle_t*) s_meta_queue_ptr->begin;
|
||||
for (;item != end; item = (hli_queue_handle_t*) wrap_ptr(s_meta_queue_ptr, (char*) (item + 1))) {
|
||||
if (*item == queue) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
bool res = hli_queue_put(s_meta_queue_ptr, &queue);
|
||||
if (!res) {
|
||||
esp_rom_printf(DRAM_STR("Fatal error in queue_signal: s_meta_queue full\n"));
|
||||
abort();
|
||||
}
|
||||
XTHAL_SET_INTSET(BIT(HLI_QUEUE_SW_INT_NUM));
|
||||
}
|
||||
}
|
||||
|
||||
static void queue_init(hli_queue_handle_t queue, size_t buf_size, size_t elem_size, QueueHandle_t downstream)
|
||||
{
|
||||
queue->elem_size = elem_size;
|
||||
queue->begin = queue->buf;
|
||||
queue->end = queue->buf;
|
||||
queue->bufend = queue->buf + buf_size;
|
||||
queue->downstream = downstream;
|
||||
queue->flags = 0;
|
||||
}
|
||||
|
||||
void hli_queue_setup(void)
|
||||
{
|
||||
if (s_meta_queue_ptr == NULL) {
|
||||
s_meta_queue_ptr = hli_queue_create(HLI_META_QUEUE_SIZE, sizeof(void*), NULL);
|
||||
ESP_ERROR_CHECK(esp_intr_alloc(ETS_INTERNAL_SW1_INTR_SOURCE, ESP_INTR_FLAG_IRAM, queue_isr_handler, NULL, &ret_handle));
|
||||
xt_ints_on(BIT(HLI_QUEUE_SW_INT_NUM));
|
||||
}
|
||||
}
|
||||
|
||||
void hli_queue_shutdown(void)
|
||||
{
|
||||
if (s_meta_queue_ptr != NULL) {
|
||||
hli_queue_delete(s_meta_queue_ptr);
|
||||
s_meta_queue_ptr = NULL;
|
||||
esp_intr_free(ret_handle);
|
||||
xt_ints_off(BIT(HLI_QUEUE_SW_INT_NUM));
|
||||
}
|
||||
}
|
||||
|
||||
hli_queue_handle_t hli_queue_create(size_t nelem, size_t elem_size, QueueHandle_t downstream)
|
||||
{
|
||||
const size_t buf_elem = nelem + 1;
|
||||
if (elem_size > HLI_QUEUE_MAX_ELEM_SIZE) {
|
||||
return NULL;
|
||||
}
|
||||
size_t buf_size = buf_elem * elem_size;
|
||||
hli_queue_handle_t res = (hli_queue_handle_t) heap_caps_malloc(sizeof(struct hli_queue_t) + buf_size,
|
||||
MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
|
||||
if (res == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
queue_init(res, buf_size, elem_size, downstream);
|
||||
return res;
|
||||
}
|
||||
|
||||
hli_queue_handle_t hli_customer_queue_create(size_t nelem, size_t elem_size, QueueHandle_t downstream)
|
||||
{
|
||||
hli_queue_handle_t res = hli_queue_create(nelem, elem_size, (QueueHandle_t) downstream);
|
||||
if (res == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
res->flags |= HLI_QUEUE_FLAG_CUSTOMER;
|
||||
return res;
|
||||
}
|
||||
|
||||
hli_queue_handle_t hli_semaphore_create(size_t max_count, SemaphoreHandle_t downstream)
|
||||
{
|
||||
const size_t elem_size = 1;
|
||||
hli_queue_handle_t res = hli_queue_create(max_count, elem_size, (QueueHandle_t) downstream);
|
||||
if (res == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
res->flags |= HLI_QUEUE_FLAG_SEMAPHORE;
|
||||
return res;
|
||||
}
|
||||
|
||||
void hli_queue_delete(hli_queue_handle_t queue)
|
||||
{
|
||||
free(queue);
|
||||
}
|
||||
|
||||
bool IRAM_ATTR hli_queue_get(hli_queue_handle_t queue, void* out)
|
||||
{
|
||||
uint32_t int_state = hli_intr_disable();
|
||||
bool res = false;
|
||||
if (!queue_empty(queue)) {
|
||||
memcpy(out, queue->begin, queue->elem_size);
|
||||
queue->begin = wrap_ptr(queue, queue->begin + queue->elem_size);
|
||||
res = true;
|
||||
}
|
||||
hli_intr_restore(int_state);
|
||||
return res;
|
||||
}
|
||||
|
||||
bool IRAM_ATTR hli_queue_put(hli_queue_handle_t queue, const void* data)
|
||||
{
|
||||
uint32_t int_state = hli_intr_disable();
|
||||
bool res = false;
|
||||
bool was_empty = queue_empty(queue);
|
||||
if (!queue_full(queue)) {
|
||||
memcpy(queue->end, data, queue->elem_size);
|
||||
queue->end = wrap_ptr(queue, queue->end + queue->elem_size);
|
||||
if (was_empty && queue != s_meta_queue_ptr) {
|
||||
queue_signal(queue);
|
||||
}
|
||||
res = true;
|
||||
}
|
||||
hli_intr_restore(int_state);
|
||||
return res;
|
||||
}
|
||||
|
||||
bool IRAM_ATTR hli_semaphore_give(hli_queue_handle_t queue)
|
||||
{
|
||||
uint8_t data = 0;
|
||||
return hli_queue_put(queue, &data);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_BTDM_CTRL_HLI */
|
176
components/bt/controller/esp32/hli_api.h
Normal file
176
components/bt/controller/esp32/hli_api.h
Normal file
@ -0,0 +1,176 @@
|
||||
// Copyright 2015-2021 Espressif Systems (Shanghai) CO LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include "esp_err.h"
|
||||
#include "esp_intr_alloc.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "freertos/semphr.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if CONFIG_BTDM_CTRL_HLI
|
||||
|
||||
/*** Queues ***/
|
||||
|
||||
struct hli_queue_t
|
||||
{
|
||||
size_t elem_size;
|
||||
char* begin;
|
||||
char* end;
|
||||
const char* bufend;
|
||||
QueueHandle_t downstream;
|
||||
int flags;
|
||||
char buf[0];
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Register a high level interrupt function
|
||||
*
|
||||
* @param handler interrupt handler function
|
||||
* @param arg argument to pass to the interrupt handler
|
||||
* @param intr_reg address of the peripheral register containing the interrupt status,
|
||||
* or value 0 to get the status from CPU INTERRUPT register
|
||||
* @param intr_mask mask of the interrupt, in the interrupt status register
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
* - ESP_ERR_NO_MEM if too many handlers are registered
|
||||
*/
|
||||
esp_err_t hli_intr_register(intr_handler_t handler, void* arg, uint32_t intr_reg, uint32_t intr_mask);
|
||||
|
||||
/**
|
||||
* @brief Mask all interrupts (including high level ones) on the current CPU
|
||||
*
|
||||
* @return uint32_t interrupt status, pass it to hli_intr_restore
|
||||
*/
|
||||
uint32_t hli_intr_disable(void);
|
||||
|
||||
/**
|
||||
* @brief Re-enable interrupts
|
||||
*
|
||||
* @param state value returned by hli_intr_disable
|
||||
*/
|
||||
void hli_intr_restore(uint32_t state);
|
||||
|
||||
/**
|
||||
* @brief Type of a hli queue
|
||||
*/
|
||||
typedef struct hli_queue_t* hli_queue_handle_t;
|
||||
|
||||
/**
|
||||
* @brief Initialize hli_queue module. Must be called once before using hli queue APIs.
|
||||
*/
|
||||
void hli_queue_setup(void);
|
||||
|
||||
/**
|
||||
* @brief Shutdown hli_queue module.
|
||||
*/
|
||||
void hli_queue_shutdown(void);
|
||||
|
||||
/**
|
||||
* @brief Create a hli queue, wrapping a FreeRTOS queue
|
||||
*
|
||||
* This queue can be used from high level interrupts,
|
||||
* but **ONLY ON THE CPU WHERE hli_queue_setup WAS CALLED**. Values sent to this
|
||||
* queue are automatically forwarded to "downstream" FreeRTOS queue using a level 3
|
||||
* software interrupt.
|
||||
*
|
||||
* @param nelem number of elements in the queue
|
||||
* @param elem_size size of one element; must match element size of a downstream queue
|
||||
* @param downstream FreeRTOS queue to send the values to
|
||||
* @return hli_queue_handle_t handle of the created queue, or NULL on failure
|
||||
*/
|
||||
hli_queue_handle_t hli_queue_create(size_t nelem, size_t elem_size, QueueHandle_t downstream);
|
||||
|
||||
/**
|
||||
* @brief Create a customer hli queue, wrapping a FreeRTOS queue
|
||||
*
|
||||
* This queue can be used from high level interrupts,
|
||||
* but **ONLY ON THE CPU WHERE hli_queue_setup WAS CALLED**. Values sent to this
|
||||
* queue are automatically forwarded to "downstream" FreeRTOS queue using a level 3
|
||||
* software interrupt.
|
||||
*
|
||||
* @param nelem number of elements in the queue
|
||||
* @param elem_size size of one element; must match element size of a downstream queue
|
||||
* @param downstream FreeRTOS queue to send the values to
|
||||
* @return hli_queue_handle_t handle of the created queue, or NULL on failure
|
||||
*/
|
||||
hli_queue_handle_t hli_customer_queue_create(size_t nelem, size_t elem_size, QueueHandle_t downstream);
|
||||
|
||||
/**
|
||||
* @brief Create a hli queue, wrapping a FreeRTOS semaphore
|
||||
*
|
||||
* See notes on hli_queue_create.
|
||||
*
|
||||
* @param max_count maximum semaphore count
|
||||
* @param downstream FreeRTOS semaphore to forward the calls to
|
||||
* @return hli_queue_handle_t handle of the created queue, or NULL on failure
|
||||
*/
|
||||
hli_queue_handle_t hli_semaphore_create(size_t max_count, SemaphoreHandle_t downstream);
|
||||
|
||||
/**
|
||||
* @brief Delete a hli queue
|
||||
*
|
||||
* Make sure noone is using the queue before deleting it.
|
||||
*
|
||||
* @param queue handle returned by hli_queue_create or hli_semaphore_create
|
||||
*/
|
||||
void hli_queue_delete(hli_queue_handle_t queue);
|
||||
|
||||
/**
|
||||
* @brief Get one element from a hli queue
|
||||
*
|
||||
* Usually not used, values get sent to a downstream FreeRTOS queue automatically.
|
||||
* However if downstream queue is NULL, this API can be used to get values from a hli queue.
|
||||
*
|
||||
* @param queue handle of a queue
|
||||
* @param out pointer where to store the element
|
||||
* @return true if the element was successfully read from the queue
|
||||
*/
|
||||
bool hli_queue_get(hli_queue_handle_t queue, void* out);
|
||||
|
||||
/**
|
||||
* @brief Put one element into a hli queue
|
||||
*
|
||||
* This puts copies an element into the queue and raises a software interrupt (level 3).
|
||||
* In the interrupt, the value is copied to a FreeRTOS "downstream" queue.
|
||||
*
|
||||
* Note that if the value does not fit into a downstream queue, no error is returned,
|
||||
* and the value is lost.
|
||||
*
|
||||
* @param queue handle of a queue
|
||||
* @param data pointer to the element to be sent
|
||||
* @return true if data was placed into the hli queue successfully
|
||||
*/
|
||||
bool hli_queue_put(hli_queue_handle_t queue, const void* data);
|
||||
|
||||
/**
|
||||
* @brief "Give" a semaphore wrapped by a hli queue
|
||||
*
|
||||
* @param queue handle returned by hli_semaphore_create
|
||||
* @return true if the event was sent to a hli queue successfully
|
||||
*/
|
||||
bool hli_semaphore_give(hli_queue_handle_t queue);
|
||||
|
||||
#endif /* CONFIG_BTDM_CTRL_HLI */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
275
components/bt/controller/esp32/hli_vectors.S
Normal file
275
components/bt/controller/esp32/hli_vectors.S
Normal file
@ -0,0 +1,275 @@
|
||||
// Copyright 2015-2021 Espressif Systems (Shanghai) CO LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
|
||||
#include <xtensa/coreasm.h>
|
||||
#include <xtensa/corebits.h>
|
||||
#include <xtensa/config/system.h>
|
||||
#include "freertos/xtensa_context.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "soc/soc.h"
|
||||
|
||||
#if CONFIG_BTDM_CTRL_HLI
|
||||
|
||||
/* Interrupt stack size, for C code.
|
||||
* TODO: reduce and make configurable.
|
||||
*/
|
||||
#define L4_INTR_STACK_SIZE 4096
|
||||
|
||||
/* Save area for the CPU state:
|
||||
* - 64 words for the general purpose registers
|
||||
* - 7 words for some of the special registers:
|
||||
* - WINDOWBASE, WINDOWSTART — only WINDOWSTART is truly needed
|
||||
* - SAR, LBEG, LEND, LCOUNT — since the C code might use these
|
||||
* - EPC1 — since the C code might cause window overflow exceptions
|
||||
* This is not laid out as standard exception frame structure
|
||||
* for simplicity of the save/restore code.
|
||||
*/
|
||||
#define REG_FILE_SIZE (64 * 4)
|
||||
#define SPECREG_OFFSET REG_FILE_SIZE
|
||||
#define SPECREG_SIZE (7 * 4)
|
||||
#define REG_SAVE_AREA_SIZE (SPECREG_OFFSET + SPECREG_SIZE)
|
||||
|
||||
.data
|
||||
_l4_intr_stack:
|
||||
.space L4_INTR_STACK_SIZE
|
||||
_l4_save_ctx:
|
||||
.space REG_SAVE_AREA_SIZE
|
||||
|
||||
.section .iram1,"ax"
|
||||
.global xt_highint4
|
||||
.type xt_highint4,@function
|
||||
.align 4
|
||||
|
||||
xt_highint4:
|
||||
|
||||
#if CONFIG_ESP32_ECO3_CACHE_LOCK_FIX
|
||||
/*
|
||||
Here, Timer2 is used to count a little time(50us).
|
||||
The subsequent dram0 write operation is blocked due to live lock, which will
|
||||
cause timer2 to timeout and trigger a level 5 interrupt.
|
||||
*/
|
||||
rsr.ccount a0
|
||||
addmi a0, a0, (CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ*50)
|
||||
wsr a0, CCOMPARE2
|
||||
|
||||
/* Enable Timer 2 interrupt */
|
||||
rsr a0, INTENABLE
|
||||
extui a0, a0, 16, 1
|
||||
bnez a0, 1f
|
||||
movi a0, 0
|
||||
xsr a0, INTENABLE /* disable all interrupts */
|
||||
/* And a0 with (1 << 16) for Timer 2 interrupt mask */
|
||||
addmi a0, a0, (1<<14)
|
||||
addmi a0, a0, (1<<14)
|
||||
addmi a0, a0, (1<<14)
|
||||
addmi a0, a0, (1<<14)
|
||||
wsr a0, INTENABLE /* Enable Timer 2 */
|
||||
1:
|
||||
#endif
|
||||
|
||||
movi a0, _l4_save_ctx
|
||||
/* save 4 lower registers */
|
||||
s32i a1, a0, 4
|
||||
s32i a2, a0, 8
|
||||
s32i a3, a0, 12
|
||||
rsr a2, EXCSAVE_4 /* holds the value of a0 */
|
||||
s32i a2, a0, 0
|
||||
|
||||
/* Save special registers */
|
||||
addi a0, a0, SPECREG_OFFSET
|
||||
rsr a2, WINDOWBASE
|
||||
s32i a2, a0, 0
|
||||
rsr a2, WINDOWSTART
|
||||
s32i a2, a0, 4
|
||||
rsr a2, SAR
|
||||
s32i a2, a0, 8
|
||||
rsr a2, LBEG
|
||||
s32i a2, a0, 12
|
||||
rsr a2, LEND
|
||||
s32i a2, a0, 16
|
||||
rsr a2, LCOUNT
|
||||
s32i a2, a0, 20
|
||||
rsr a2, EPC1
|
||||
s32i a2, a0, 24
|
||||
|
||||
#if CONFIG_ESP32_ECO3_CACHE_LOCK_FIX
|
||||
movi a0, 0
|
||||
xsr a0, INTENABLE /* disable all interrupts */
|
||||
movi a2, ~(1<<16)
|
||||
and a0, a2, a0
|
||||
wsr a0, INTENABLE
|
||||
#endif
|
||||
|
||||
/* disable exception mode, window overflow */
|
||||
movi a0, PS_INTLEVEL(5) | PS_EXCM
|
||||
wsr a0, PS
|
||||
rsync
|
||||
|
||||
/* Save the remaining physical registers.
|
||||
* 4 registers are already saved, which leaves 60 registers to save.
|
||||
* (FIXME: consider the case when the CPU is configured with physical 32 registers)
|
||||
* These 60 registers are saved in 5 iterations, 12 registers at a time.
|
||||
*/
|
||||
movi a1, 5
|
||||
movi a3, _l4_save_ctx + 4 * 4
|
||||
|
||||
/* This is repeated 5 times, each time the window is shifted by 12 registers.
|
||||
* We come here with a1 = downcounter, a3 = save pointer, a2 and a0 unused.
|
||||
*/
|
||||
1:
|
||||
s32i a4, a3, 0
|
||||
s32i a5, a3, 4
|
||||
s32i a6, a3, 8
|
||||
s32i a7, a3, 12
|
||||
s32i a8, a3, 16
|
||||
s32i a9, a3, 20
|
||||
s32i a10, a3, 24
|
||||
s32i a11, a3, 28
|
||||
s32i a12, a3, 32
|
||||
s32i a13, a3, 36
|
||||
s32i a14, a3, 40
|
||||
s32i a15, a3, 44
|
||||
|
||||
/* We are about to rotate the window, so that a12-a15 will become the new a0-a3.
|
||||
* Copy a0-a3 to a12-15 to still have access to these values.
|
||||
* At the same time we can decrement the counter and adjust the save area pointer
|
||||
*/
|
||||
|
||||
/* a0 is constant (_l4_save_ctx), no need to copy */
|
||||
addi a13, a1, -1 /* copy and decrement the downcounter */
|
||||
/* a2 is scratch so no need to copy */
|
||||
addi a15, a3, 48 /* copy and adjust the save area pointer */
|
||||
beqz a13, 2f /* have saved all registers ? */
|
||||
rotw 3 /* rotate the window and go back */
|
||||
j 1b
|
||||
|
||||
/* the loop is complete */
|
||||
2:
|
||||
rotw 4 /* this brings us back to the original window */
|
||||
/* a0 still points to _l4_save_ctx */
|
||||
|
||||
/* Can clear WINDOWSTART now, all registers are saved */
|
||||
rsr a2, WINDOWBASE
|
||||
/* WINDOWSTART = (1 << WINDOWBASE) */
|
||||
movi a3, 1
|
||||
ssl a2
|
||||
sll a3, a3
|
||||
wsr a3, WINDOWSTART
|
||||
|
||||
_highint4_stack_switch:
|
||||
movi a0, 0
|
||||
movi sp, _l4_intr_stack + L4_INTR_STACK_SIZE - 16
|
||||
s32e a0, sp, -12 /* For GDB: set null SP */
|
||||
s32e a0, sp, -16 /* For GDB: set null PC */
|
||||
movi a0, _highint4_stack_switch /* For GDB: cosmetics, for the frame where stack switch happened */
|
||||
|
||||
/* Set up PS for C, disable all interrupts except NMI and debug, and clear EXCM. */
|
||||
movi a6, PS_INTLEVEL(4) | PS_UM | PS_WOE
|
||||
wsr a6, PS
|
||||
rsync
|
||||
|
||||
/* Call C handler */
|
||||
mov a6, sp
|
||||
call4 hli_c_handler
|
||||
|
||||
l32e sp, sp, -12 /* switch back to the original stack */
|
||||
|
||||
/* Done with C handler; re-enable exception mode, disabling window overflow */
|
||||
movi a2, PS_INTLEVEL(5) | PS_EXCM /* TOCHECK */
|
||||
wsr a2, PS
|
||||
rsync
|
||||
|
||||
/* Restore the special registers.
|
||||
* WINDOWSTART will be restored near the end.
|
||||
*/
|
||||
movi a0, _l4_save_ctx + SPECREG_OFFSET
|
||||
l32i a2, a0, 8
|
||||
wsr a2, SAR
|
||||
l32i a2, a0, 12
|
||||
wsr a2, LBEG
|
||||
l32i a2, a0, 16
|
||||
wsr a2, LEND
|
||||
l32i a2, a0, 20
|
||||
wsr a2, LCOUNT
|
||||
l32i a2, a0, 24
|
||||
wsr a2, EPC1
|
||||
|
||||
/* Restoring the physical registers.
|
||||
* This is the reverse to the saving process above.
|
||||
*/
|
||||
|
||||
/* Rotate back to the final window, then start loading 12 registers at a time,
|
||||
* in 5 iterations.
|
||||
* Again, a1 is the downcounter and a3 is the save area pointer.
|
||||
* After each rotation, a1 and a3 are copied from a13 and a15.
|
||||
* To simplify the loop, we put the initial values into a13 and a15.
|
||||
*/
|
||||
rotw -4
|
||||
movi a15, _l4_save_ctx + 64 * 4 /* point to the end of the save area */
|
||||
movi a13, 5
|
||||
|
||||
1:
|
||||
/* Copy a1 and a3 from their previous location,
|
||||
* at the same time decrementing and adjusting the save area pointer.
|
||||
*/
|
||||
addi a1, a13, -1
|
||||
addi a3, a15, -48
|
||||
|
||||
/* Load 12 registers */
|
||||
l32i a4, a3, 0
|
||||
l32i a5, a3, 4
|
||||
l32i a6, a3, 8
|
||||
l32i a7, a3, 12
|
||||
l32i a8, a3, 16
|
||||
l32i a9, a3, 20
|
||||
l32i a10, a3, 24
|
||||
l32i a11, a3, 28 /* ensure PS and EPC written */
|
||||
l32i a12, a3, 32
|
||||
l32i a13, a3, 36
|
||||
l32i a14, a3, 40
|
||||
l32i a15, a3, 44
|
||||
|
||||
/* Done with the loop? */
|
||||
beqz a1, 2f
|
||||
/* If no, rotate the window and repeat */
|
||||
rotw -3
|
||||
j 1b
|
||||
|
||||
2:
|
||||
/* Done with the loop. Only 4 registers (a0-a3 in the original window) remain
|
||||
* to be restored. Also need to restore WINDOWSTART, since all the general
|
||||
* registers are now in place.
|
||||
*/
|
||||
movi a0, _l4_save_ctx
|
||||
|
||||
l32i a2, a0, SPECREG_OFFSET + 4
|
||||
wsr a2, WINDOWSTART
|
||||
|
||||
l32i a1, a0, 4
|
||||
l32i a2, a0, 8
|
||||
l32i a3, a0, 12
|
||||
rsr a0, EXCSAVE_4 /* holds the value of a0 before the interrupt handler */
|
||||
|
||||
/* Return from the interrupt, restoring PS from EPS_4 */
|
||||
rfi 4
|
||||
|
||||
#endif /* CONFIG_BTDM_CTRL_HLI */
|
||||
|
||||
/* The linker has no reason to link in this file; all symbols it exports are already defined
|
||||
(weakly!) in the default int handler. Define a symbol here so we can use it to have the
|
||||
linker inspect this anyway. */
|
||||
|
||||
.global ld_include_hli_vectors_bt
|
||||
ld_include_hli_vectors_bt:
|
0
components/bt/controller/esp32s2/Kconfig.in
Normal file
0
components/bt/controller/esp32s2/Kconfig.in
Normal file
@ -1 +1 @@
|
||||
Subproject commit fb49791b7c1a8a35f06e68124c90022667b4cff1
|
||||
Subproject commit fe0a3d00f11dbf9d219f2a291e3cab7419e5cac1
|
@ -1 +1 @@
|
||||
Subproject commit 9ca8afd50afde57958a67fca65847edc52f7d91c
|
||||
Subproject commit 32f15e826a102d2d64e612620468122ea2234a2e
|
@ -9,10 +9,10 @@ if BLE_MESH
|
||||
config BLE_MESH_USE_DUPLICATE_SCAN
|
||||
bool "Support Duplicate Scan in BLE Mesh"
|
||||
depends on BT_BLUEDROID_ENABLED
|
||||
select BTDM_BLE_SCAN_DUPL if BT_CTRL_ESP32
|
||||
select BTDM_BLE_MESH_SCAN_DUPL_EN if BT_CTRL_ESP32
|
||||
select BT_CTRL_BLE_SCAN_DUPL if BT_CTRL_ESP32C3
|
||||
select BT_CTRL_BLE_MESH_SCAN_DUPL_EN if BT_CTRL_ESP32C3
|
||||
select BTDM_BLE_SCAN_DUPL if IDF_TARGET_ESP32
|
||||
select BTDM_BLE_MESH_SCAN_DUPL_EN if IDF_TARGET_ESP32
|
||||
select BT_CTRL_BLE_SCAN_DUPL if IDF_TARGET_ESP32C3
|
||||
select BT_CTRL_BLE_MESH_SCAN_DUPL_EN if IDF_TARGET_ESP32C3
|
||||
default y
|
||||
help
|
||||
Enable this option to allow using specific duplicate scan filter
|
||||
|
@ -42,7 +42,7 @@ config BT_BLUEDROID_MEM_DEBUG
|
||||
|
||||
config BT_CLASSIC_ENABLED
|
||||
bool "Classic Bluetooth"
|
||||
depends on BT_BLUEDROID_ENABLED && BT_CTRL_ESP32
|
||||
depends on BT_BLUEDROID_ENABLED && IDF_TARGET_ESP32
|
||||
default n
|
||||
help
|
||||
For now this option needs "SMP_ENABLE" to be set to yes
|
||||
@ -99,13 +99,27 @@ config BT_HFP_WBS_ENABLE
|
||||
This enables Wide Band Speech. Should disable it when SCO data path is PCM.
|
||||
Otherwise there will be no data transmited via GPIOs.
|
||||
|
||||
config BT_HID_HOST_ENABLED
|
||||
bool "Classic BT HID Host"
|
||||
config BT_HID_ENABLED
|
||||
bool "Classic BT HID"
|
||||
depends on BT_CLASSIC_ENABLED
|
||||
default n
|
||||
help
|
||||
This enables the BT HID Host
|
||||
|
||||
choice BT_HID_ROLE
|
||||
prompt "Profile Role configuration"
|
||||
depends on BT_HID_ENABLED
|
||||
config BT_HID_HOST_ENABLED
|
||||
bool "Classic BT HID Host"
|
||||
help
|
||||
This enables the BT HID Host
|
||||
|
||||
config BT_HID_DEVICE_ENABLED
|
||||
bool "Classic BT HID Device"
|
||||
help
|
||||
This enables the BT HID Device
|
||||
endchoice
|
||||
|
||||
config BT_SSP_ENABLED
|
||||
bool "Secure Simple Pairing"
|
||||
depends on BT_CLASSIC_ENABLED
|
||||
@ -1056,8 +1070,3 @@ config BT_BLE_42_FEATURES_SUPPORTED
|
||||
default n
|
||||
help
|
||||
This enables BLE 4.2 features.
|
||||
|
||||
config BT_RESERVE_DRAM
|
||||
hex
|
||||
default 0xdb5c if BT_ENABLED
|
||||
default 0
|
||||
|
176
components/bt/host/bluedroid/api/esp_hidd_api.c
Normal file
176
components/bt/host/bluedroid/api/esp_hidd_api.c
Normal file
@ -0,0 +1,176 @@
|
||||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
// Copyright 2019 Blake Felt
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <string.h>
|
||||
#include "esp_err.h"
|
||||
#include "esp_bt_main.h"
|
||||
#include "btc/btc_manage.h"
|
||||
#include "btc_hd.h"
|
||||
#include "esp_hidd_api.h"
|
||||
|
||||
#if (defined BTC_HD_INCLUDED && BTC_HD_INCLUDED == TRUE)
|
||||
|
||||
esp_err_t esp_bt_hid_device_register_callback(esp_hd_cb_t *callback)
|
||||
{
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
|
||||
if (callback == NULL) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
btc_profile_cb_set(BTC_PID_HD, callback);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_bt_hid_device_init(void)
|
||||
{
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
|
||||
btc_msg_t msg;
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_HD;
|
||||
msg.act = BTC_HD_INIT_EVT;
|
||||
|
||||
/* Switch to BTC context */
|
||||
bt_status_t stat = btc_transfer_context(&msg, NULL, 0, NULL);
|
||||
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_err_t esp_bt_hid_device_deinit(void)
|
||||
{
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
|
||||
btc_msg_t msg;
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_HD;
|
||||
msg.act = BTC_HD_DEINIT_EVT;
|
||||
|
||||
bt_status_t stat = btc_transfer_context(&msg, NULL, 0, NULL);
|
||||
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_err_t esp_bt_hid_device_register_app(esp_hidd_app_param_t* app_param, esp_hidd_qos_param_t* in_qos, esp_hidd_qos_param_t* out_qos)
|
||||
{
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
|
||||
btc_msg_t msg;
|
||||
btc_hidd_args_t args;
|
||||
memset(&args, 0, sizeof(btc_hidd_args_t));
|
||||
args.register_app.app_param = app_param;
|
||||
args.register_app.in_qos = in_qos;
|
||||
args.register_app.out_qos = out_qos;
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_HD;
|
||||
msg.act = BTC_HD_REGISTER_APP_EVT;
|
||||
|
||||
bt_status_t stat = btc_transfer_context(&msg, &args, sizeof(btc_hidd_args_t), NULL);
|
||||
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_err_t esp_bt_hid_device_unregister_app(void)
|
||||
{
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
|
||||
btc_msg_t msg;
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_HD;
|
||||
msg.act = BTC_HD_UNREGISTER_APP_EVT;
|
||||
|
||||
bt_status_t stat = btc_transfer_context(&msg, NULL, 0, NULL);
|
||||
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_err_t esp_bt_hid_device_connect(esp_bd_addr_t bd_addr)
|
||||
{
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
|
||||
btc_msg_t msg;
|
||||
btc_hidd_args_t args;
|
||||
memset(&args, 0, sizeof(btc_hidd_args_t));
|
||||
memcpy(args.connect.bd_addr, bd_addr, sizeof(esp_bd_addr_t));
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_HD;
|
||||
msg.act = BTC_HD_CONNECT_EVT;
|
||||
|
||||
bt_status_t stat = btc_transfer_context(&msg, &args, sizeof(btc_hidd_args_t), NULL);
|
||||
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_err_t esp_bt_hid_device_disconnect(void)
|
||||
{
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
|
||||
btc_msg_t msg;
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_HD;
|
||||
msg.act = BTC_HD_DISCONNECT_EVT;
|
||||
|
||||
bt_status_t stat = btc_transfer_context(&msg, NULL, 0, NULL);
|
||||
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_err_t esp_bt_hid_device_send_report(esp_hidd_report_type_t type, uint8_t id, uint16_t len, uint8_t* data)
|
||||
{
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
|
||||
btc_msg_t msg;
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_HD;
|
||||
msg.act = BTC_HD_SEND_REPORT_EVT;
|
||||
|
||||
btc_hidd_args_t args;
|
||||
memset(&args, 0, sizeof(btc_hidd_args_t));
|
||||
args.send_report.type = type;
|
||||
args.send_report.id = id;
|
||||
args.send_report.len = len;
|
||||
args.send_report.data = data;
|
||||
|
||||
bt_status_t stat = btc_transfer_context(&msg, &args, sizeof(btc_hidd_args_t), btc_hd_arg_deep_copy);
|
||||
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_err_t esp_bt_hid_device_report_error(esp_hidd_handshake_error_t error)
|
||||
{
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
|
||||
btc_msg_t msg;
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_HD;
|
||||
msg.act = BTC_HD_REPORT_ERROR_EVT;
|
||||
|
||||
btc_hidd_args_t args;
|
||||
memset(&args, 0, sizeof(btc_hidd_args_t));
|
||||
args.error = error;
|
||||
|
||||
bt_status_t stat = btc_transfer_context(&msg, &args, sizeof(btc_hidd_args_t), NULL);
|
||||
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_err_t esp_bt_hid_device_virtual_cable_unplug(void)
|
||||
{
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
|
||||
btc_msg_t msg;
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_HD;
|
||||
msg.act = BTC_HD_UNPLUG_EVT;
|
||||
|
||||
bt_status_t stat = btc_transfer_context(&msg, NULL, 0, NULL);
|
||||
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
|
||||
}
|
||||
|
||||
#endif /* defined BTC_HD_INCLUDED && BTC_HD_INCLUDED == TRUE */
|
254
components/bt/host/bluedroid/api/esp_hidh_api.c
Normal file
254
components/bt/host/bluedroid/api/esp_hidh_api.c
Normal file
@ -0,0 +1,254 @@
|
||||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
// Copyright 2019 Blake Felt
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "btc/btc_manage.h"
|
||||
#include "btc_hh.h"
|
||||
#include "esp_bt_main.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_hidh_api.h"
|
||||
#include <string.h>
|
||||
|
||||
#if (defined BTC_HH_INCLUDED && BTC_HH_INCLUDED == TRUE)
|
||||
|
||||
esp_err_t esp_bt_hid_host_register_callback(esp_hh_cb_t *callback)
|
||||
{
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
|
||||
if (callback == NULL) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
btc_profile_cb_set(BTC_PID_HH, callback);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_bt_hid_host_init(void)
|
||||
{
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
|
||||
btc_msg_t msg;
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_HH;
|
||||
msg.act = BTC_HH_INIT_EVT;
|
||||
|
||||
bt_status_t stat = btc_transfer_context(&msg, NULL, 0, NULL);
|
||||
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_err_t esp_bt_hid_host_deinit(void)
|
||||
{
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
|
||||
btc_msg_t msg;
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_HH;
|
||||
msg.act = BTC_HH_DEINIT_EVT;
|
||||
|
||||
bt_status_t stat = btc_transfer_context(&msg, NULL, 0, NULL);
|
||||
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_err_t esp_bt_hid_host_connect(esp_bd_addr_t bd_addr)
|
||||
{
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
btc_msg_t msg;
|
||||
btc_hidh_args_t arg;
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_HH;
|
||||
msg.act = BTC_HH_CONNECT_EVT;
|
||||
|
||||
memcpy(arg.connect.bd_addr, bd_addr, sizeof(esp_bd_addr_t));
|
||||
|
||||
bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_hidh_args_t), NULL);
|
||||
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_err_t esp_bt_hid_host_disconnect(esp_bd_addr_t bd_addr)
|
||||
{
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
btc_msg_t msg;
|
||||
btc_hidh_args_t arg;
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_HH;
|
||||
msg.act = BTC_HH_DISCONNECT_EVT;
|
||||
|
||||
memcpy(arg.disconnect.bd_addr, bd_addr, sizeof(esp_bd_addr_t));
|
||||
|
||||
bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_hidh_args_t), NULL);
|
||||
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_err_t esp_bt_hid_host_virtual_cable_unplug(esp_bd_addr_t bd_addr)
|
||||
{
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
btc_msg_t msg;
|
||||
btc_hidh_args_t arg;
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_HH;
|
||||
msg.act = BTC_HH_UNPLUG_EVT;
|
||||
|
||||
memcpy(arg.unplug.bd_addr, bd_addr, sizeof(esp_bd_addr_t));
|
||||
|
||||
bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_hidh_args_t), NULL);
|
||||
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_err_t esp_bt_hid_host_set_info(esp_bd_addr_t bd_addr, esp_hidh_hid_info_t *hid_info)
|
||||
{
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
btc_msg_t msg;
|
||||
btc_hidh_args_t arg;
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_HH;
|
||||
msg.act = BTC_HH_SET_INFO_EVT;
|
||||
|
||||
memcpy(arg.set_info.bd_addr, bd_addr, sizeof(esp_bd_addr_t));
|
||||
arg.set_info.hid_info = hid_info;
|
||||
|
||||
bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_hidh_args_t), btc_hh_arg_deep_copy);
|
||||
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_err_t esp_bt_hid_host_get_protocol(esp_bd_addr_t bd_addr)
|
||||
{
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
btc_msg_t msg;
|
||||
btc_hidh_args_t arg;
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_HH;
|
||||
msg.act = BTC_HH_GET_PROTO_EVT;
|
||||
|
||||
memcpy(arg.get_protocol.bd_addr, bd_addr, sizeof(esp_bd_addr_t));
|
||||
|
||||
bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_hidh_args_t), NULL);
|
||||
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_err_t esp_bt_hid_host_set_protocol(esp_bd_addr_t bd_addr, esp_hidh_protocol_mode_t protocol_mode)
|
||||
{
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
btc_msg_t msg;
|
||||
btc_hidh_args_t arg;
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_HH;
|
||||
msg.act = BTC_HH_SET_PROTO_EVT;
|
||||
|
||||
memcpy(arg.set_protocol.bd_addr, bd_addr, sizeof(esp_bd_addr_t));
|
||||
arg.set_protocol.protocol_mode = protocol_mode;
|
||||
|
||||
bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_hidh_args_t), NULL);
|
||||
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_err_t esp_bt_hid_host_get_idle(esp_bd_addr_t bd_addr)
|
||||
{
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
btc_msg_t msg;
|
||||
btc_hidh_args_t arg;
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_HH;
|
||||
msg.act = BTC_HH_GET_IDLE_EVT;
|
||||
|
||||
memcpy(arg.get_idle.bd_addr, bd_addr, sizeof(esp_bd_addr_t));
|
||||
|
||||
bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_hidh_args_t), NULL);
|
||||
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_err_t esp_bt_hid_host_set_idle(esp_bd_addr_t bd_addr, uint16_t idle_time)
|
||||
{
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
btc_msg_t msg;
|
||||
btc_hidh_args_t arg;
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_HH;
|
||||
msg.act = BTC_HH_SET_IDLE_EVT;
|
||||
|
||||
memcpy(arg.set_idle.bd_addr, bd_addr, sizeof(esp_bd_addr_t));
|
||||
arg.set_idle.idle_time = idle_time;
|
||||
|
||||
bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_hidh_args_t), NULL);
|
||||
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_err_t esp_bt_hid_host_get_report(esp_bd_addr_t bd_addr, esp_hidh_report_type_t report_type, uint8_t report_id,
|
||||
int buffer_size)
|
||||
{
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
btc_msg_t msg;
|
||||
btc_hidh_args_t arg;
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_HH;
|
||||
msg.act = BTC_HH_GET_REPORT_EVT;
|
||||
|
||||
memcpy(arg.get_report.bd_addr, bd_addr, sizeof(esp_bd_addr_t));
|
||||
arg.get_report.report_type = report_type;
|
||||
arg.get_report.report_id = report_id;
|
||||
arg.get_report.buffer_size = buffer_size;
|
||||
|
||||
bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_hidh_args_t), NULL);
|
||||
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_err_t esp_bt_hid_host_set_report(esp_bd_addr_t bd_addr, esp_hidh_report_type_t report_type, uint8_t *report,
|
||||
size_t len)
|
||||
{
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
btc_msg_t msg;
|
||||
btc_hidh_args_t arg;
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_HH;
|
||||
msg.act = BTC_HH_SET_REPORT_EVT;
|
||||
|
||||
memcpy(arg.set_report.bd_addr, bd_addr, sizeof(esp_bd_addr_t));
|
||||
arg.set_report.report_type = report_type;
|
||||
arg.set_report.len = len;
|
||||
arg.set_report.report = report;
|
||||
|
||||
bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_hidh_args_t), btc_hh_arg_deep_copy);
|
||||
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_err_t esp_bt_hid_host_send_data(esp_bd_addr_t bd_addr, uint8_t *data, size_t len)
|
||||
{
|
||||
ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);
|
||||
btc_msg_t msg;
|
||||
btc_hidh_args_t arg;
|
||||
|
||||
msg.sig = BTC_SIG_API_CALL;
|
||||
msg.pid = BTC_PID_HH;
|
||||
msg.act = BTC_HH_SEND_DATA_EVT;
|
||||
|
||||
memcpy(arg.send_data.bd_addr, bd_addr, sizeof(esp_bd_addr_t));
|
||||
arg.send_data.len = len;
|
||||
arg.send_data.data = data;
|
||||
|
||||
bt_status_t stat = btc_transfer_context(&msg, &arg, sizeof(btc_hidh_args_t), btc_hh_arg_deep_copy);
|
||||
return (stat == BT_STATUS_SUCCESS) ? ESP_OK : ESP_FAIL;
|
||||
}
|
||||
|
||||
#endif /* defined BTC_HH_INCLUDED && BTC_HH_INCLUDED == TRUE */
|
@ -467,7 +467,7 @@ typedef struct
|
||||
{
|
||||
uint16_t rx_len; /*!< pkt rx data length value */
|
||||
uint16_t tx_len; /*!< pkt tx data length value */
|
||||
}esp_ble_pkt_data_length_params_t;
|
||||
} esp_ble_pkt_data_length_params_t;
|
||||
|
||||
/**
|
||||
* @brief BLE encryption keys
|
||||
@ -648,7 +648,7 @@ typedef enum {
|
||||
typedef enum{
|
||||
ESP_BLE_WHITELIST_REMOVE = 0X00, /*!< remove mac from whitelist */
|
||||
ESP_BLE_WHITELIST_ADD = 0X01, /*!< add address to whitelist */
|
||||
}esp_ble_wl_opration_t;
|
||||
} esp_ble_wl_opration_t;
|
||||
#if (BLE_42_FEATURE_SUPPORT == TRUE)
|
||||
typedef enum {
|
||||
ESP_BLE_DUPLICATE_EXCEPTIONAL_LIST_ADD = 0, /*!< Add device info into duplicate scan exceptional list */
|
||||
@ -998,7 +998,7 @@ typedef union {
|
||||
uint16_t conn_int; /*!< Current connection interval */
|
||||
uint16_t timeout; /*!< Supervision timeout for the LE Link. Range: 0x000A to 0x0C80.
|
||||
Mandatory Range: 0x000A to 0x0C80 Time = N * 10 msec */
|
||||
}update_conn_params; /*!< Event parameter of ESP_GAP_BLE_UPDATE_CONN_PARAMS_EVT */
|
||||
} update_conn_params; /*!< Event parameter of ESP_GAP_BLE_UPDATE_CONN_PARAMS_EVT */
|
||||
/**
|
||||
* @brief ESP_GAP_BLE_SET_PKT_LENGTH_COMPLETE_EVT
|
||||
*/
|
||||
@ -1018,13 +1018,13 @@ typedef union {
|
||||
struct ble_remove_bond_dev_cmpl_evt_param {
|
||||
esp_bt_status_t status; /*!< Indicate the remove bond device operation success status */
|
||||
esp_bd_addr_t bd_addr; /*!< The device address which has been remove from the bond list */
|
||||
}remove_bond_dev_cmpl; /*!< Event parameter of ESP_GAP_BLE_REMOVE_BOND_DEV_COMPLETE_EVT */
|
||||
} remove_bond_dev_cmpl; /*!< Event parameter of ESP_GAP_BLE_REMOVE_BOND_DEV_COMPLETE_EVT */
|
||||
/**
|
||||
* @brief ESP_GAP_BLE_CLEAR_BOND_DEV_COMPLETE_EVT
|
||||
*/
|
||||
struct ble_clear_bond_dev_cmpl_evt_param {
|
||||
esp_bt_status_t status; /*!< Indicate the clear bond device operation success status */
|
||||
}clear_bond_dev_cmpl; /*!< Event parameter of ESP_GAP_BLE_CLEAR_BOND_DEV_COMPLETE_EVT */
|
||||
} clear_bond_dev_cmpl; /*!< Event parameter of ESP_GAP_BLE_CLEAR_BOND_DEV_COMPLETE_EVT */
|
||||
/**
|
||||
* @brief ESP_GAP_BLE_GET_BOND_DEV_COMPLETE_EVT
|
||||
*/
|
||||
@ -1032,7 +1032,7 @@ typedef union {
|
||||
esp_bt_status_t status; /*!< Indicate the get bond device operation success status */
|
||||
uint8_t dev_num; /*!< Indicate the get number device in the bond list */
|
||||
esp_ble_bond_dev_t *bond_dev; /*!< the pointer to the bond device Structure */
|
||||
}get_bond_dev_cmpl; /*!< Event parameter of ESP_GAP_BLE_GET_BOND_DEV_COMPLETE_EVT */
|
||||
} get_bond_dev_cmpl; /*!< Event parameter of ESP_GAP_BLE_GET_BOND_DEV_COMPLETE_EVT */
|
||||
/**
|
||||
* @brief ESP_GAP_BLE_READ_RSSI_COMPLETE_EVT
|
||||
*/
|
||||
|
@ -380,7 +380,7 @@ esp_err_t esp_ble_gattc_search_service(esp_gatt_if_t gattc_if, uint16_t conn_id,
|
||||
/**
|
||||
* @brief Find all the service with the given service uuid in the gattc cache, if the svc_uuid is NULL, find all the service.
|
||||
* Note: It just get service from local cache, won't get from remote devices. If want to get it from remote device, need
|
||||
* to used the esp_ble_gattc_search_service.
|
||||
* to used the esp_ble_gattc_cache_refresh, then call esp_ble_gattc_get_service again.
|
||||
*
|
||||
* @param[in] gattc_if: Gatt client access interface.
|
||||
* @param[in] conn_id: connection ID which identify the server.
|
||||
|
379
components/bt/host/bluedroid/api/include/api/esp_hidd_api.h
Normal file
379
components/bt/host/bluedroid/api/include/api/esp_hidd_api.h
Normal file
@ -0,0 +1,379 @@
|
||||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
// Copyright 2019 Blake Felt
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef __ESP_HIDD_API_H__
|
||||
#define __ESP_HIDD_API_H__
|
||||
|
||||
#include "esp_bt_defs.h"
|
||||
#include "esp_err.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* sub_class of hid device */
|
||||
#define ESP_HID_CLASS_UNKNOWN (0x00<<2)
|
||||
#define ESP_HID_CLASS_JOS (0x01<<2) /* joy stick */
|
||||
#define ESP_HID_CLASS_GPD (0x02<<2) /* game pad */
|
||||
#define ESP_HID_CLASS_RMC (0x03<<2) /* remote control */
|
||||
#define ESP_HID_CLASS_SED (0x04<<2) /* sensing device */
|
||||
#define ESP_HID_CLASS_DGT (0x05<<2) /* Digitizer tablet */
|
||||
#define ESP_HID_CLASS_CDR (0x06<<2) /* card reader */
|
||||
#define ESP_HID_CLASS_KBD (0x10<<2) /* keyboard */
|
||||
#define ESP_HID_CLASS_MIC (0x20<<2) /* pointing device */
|
||||
#define ESP_HID_CLASS_COM (0x30<<2) /* Combo keyboard/pointing */
|
||||
|
||||
/**
|
||||
* @brief HIDD handshake error
|
||||
*/
|
||||
typedef enum {
|
||||
ESP_HID_PAR_HANDSHAKE_RSP_SUCCESS = 0,
|
||||
ESP_HID_PAR_HANDSHAKE_RSP_NOT_READY = 1,
|
||||
ESP_HID_PAR_HANDSHAKE_RSP_ERR_INVALID_REP_ID = 2,
|
||||
ESP_HID_PAR_HANDSHAKE_RSP_ERR_UNSUPPORTED_REQ = 3,
|
||||
ESP_HID_PAR_HANDSHAKE_RSP_ERR_INVALID_PARAM = 4,
|
||||
ESP_HID_PAR_HANDSHAKE_RSP_ERR_UNKNOWN = 14,
|
||||
ESP_HID_PAR_HANDSHAKE_RSP_ERR_FATAL = 15
|
||||
} esp_hidd_handshake_error_t;
|
||||
|
||||
/**
|
||||
* @brief HIDD report types
|
||||
*/
|
||||
typedef enum {
|
||||
ESP_HIDD_REPORT_TYPE_OTHER = 0,
|
||||
ESP_HIDD_REPORT_TYPE_INPUT,
|
||||
ESP_HIDD_REPORT_TYPE_OUTPUT,
|
||||
ESP_HIDD_REPORT_TYPE_FEATURE,
|
||||
// special value for reports to be sent on INTR(INPUT is assumed)
|
||||
ESP_HIDD_REPORT_TYPE_INTRDATA
|
||||
} esp_hidd_report_type_t;
|
||||
|
||||
/**
|
||||
* @brief HIDD connection state
|
||||
*/
|
||||
typedef enum {
|
||||
ESP_HIDD_CONN_STATE_CONNECTED,
|
||||
ESP_HIDD_CONN_STATE_CONNECTING,
|
||||
ESP_HIDD_CONN_STATE_DISCONNECTED,
|
||||
ESP_HIDD_CONN_STATE_DISCONNECTING,
|
||||
ESP_HIDD_CONN_STATE_UNKNOWN
|
||||
} esp_hidd_connection_state_t;
|
||||
|
||||
/**
|
||||
* @brief HID device protocol modes
|
||||
*/
|
||||
typedef enum {
|
||||
ESP_HIDD_REPORT_MODE = 0x00,
|
||||
ESP_HIDD_BOOT_MODE = 0x01,
|
||||
ESP_HIDD_UNSUPPORTED_MODE = 0xff
|
||||
} esp_hidd_protocol_mode_t;
|
||||
|
||||
|
||||
/**
|
||||
* @brief HIDD characteristics for SDP report
|
||||
*/
|
||||
typedef struct {
|
||||
const char *name;
|
||||
const char *description;
|
||||
const char *provider;
|
||||
uint8_t subclass;
|
||||
uint8_t *desc_list;
|
||||
int desc_list_len;
|
||||
} esp_hidd_app_param_t;
|
||||
|
||||
/**
|
||||
* @brief HIDD Quality of Service parameters
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t service_type;
|
||||
uint32_t token_rate;
|
||||
uint32_t token_bucket_size;
|
||||
uint32_t peak_bandwidth;
|
||||
uint32_t access_latency;
|
||||
uint32_t delay_variation;
|
||||
} esp_hidd_qos_param_t;
|
||||
|
||||
/**
|
||||
* @brief HID device callback function events
|
||||
*/
|
||||
typedef enum {
|
||||
ESP_HIDD_INIT_EVT = 0, /*!< When HID device is inited, the event comes */
|
||||
ESP_HIDD_DEINIT_EVT, /*!< When HID device is deinited, the event comes */
|
||||
ESP_HIDD_REGISTER_APP_EVT, /*!< When HID device application registered, the event comes */
|
||||
ESP_HIDD_UNREGISTER_APP_EVT, /*!< When HID device application unregistered, the event comes */
|
||||
ESP_HIDD_OPEN_EVT, /*!< When HID device connection to host opened, the event comes */
|
||||
ESP_HIDD_CLOSE_EVT, /*!< When HID device connection to host closed, the event comes */
|
||||
ESP_HIDD_SEND_REPORT_EVT, /*!< When HID device send report to lower layer, the event comes */
|
||||
ESP_HIDD_REPORT_ERR_EVT, /*!< When HID device report handshanke error to lower layer, the event comes */
|
||||
ESP_HIDD_GET_REPORT_EVT, /*!< When HID device receives GET_REPORT request from host, the event comes */
|
||||
ESP_HIDD_SET_REPORT_EVT, /*!< When HID device receives SET_REPORT request from host, the event comes */
|
||||
ESP_HIDD_SET_PROTOCOL_EVT, /*!< When HID device receives SET_PROTOCOL request from host, the event comes */
|
||||
ESP_HIDD_INTR_DATA_EVT, /*!< When HID device receives DATA from host on intr, the event comes */
|
||||
ESP_HIDD_VC_UNPLUG_EVT, /*!< When HID device initiates Virtual Cable Unplug, the event comes */
|
||||
ESP_HIDD_API_ERR_EVT /*!< When HID device has API error, the event comes */
|
||||
} esp_hidd_cb_event_t;
|
||||
|
||||
typedef enum {
|
||||
ESP_HIDD_SUCCESS,
|
||||
ESP_HIDD_ERROR, /*!< general ESP HD error */
|
||||
ESP_HIDD_NO_RES, /*!< out of system resources */
|
||||
ESP_HIDD_BUSY, /*!< Temporarily can not handle this request. */
|
||||
ESP_HIDD_NO_DATA, /*!< No data. */
|
||||
ESP_HIDD_NEED_INIT, /*!< HIDD module shall init first */
|
||||
ESP_HIDD_NEED_DEINIT, /*!< HIDD module shall deinit first */
|
||||
ESP_HIDD_NEED_REG, /*!< HIDD module shall register first */
|
||||
ESP_HIDD_NEED_DEREG, /*!< HIDD module shall deregister first */
|
||||
ESP_HIDD_NO_CONNECTION, /*!< connection may have been closed */
|
||||
} esp_hidd_status_t;
|
||||
|
||||
/**
|
||||
* @brief HID device callback parameters union
|
||||
*/
|
||||
typedef union {
|
||||
/**
|
||||
* @brief ESP_HIDD_INIT_EVT
|
||||
*/
|
||||
struct hidd_init_evt_param {
|
||||
esp_hidd_status_t status; /*!< operation status */
|
||||
} init; /*!< HIDD callback param of ESP_HIDD_INIT_EVT */
|
||||
|
||||
/**
|
||||
* @brief ESP_HIDD_DEINIT_EVT
|
||||
*/
|
||||
struct hidd_deinit_evt_param {
|
||||
esp_hidd_status_t status; /*!< operation status */
|
||||
} deinit; /*!< HIDD callback param of ESP_HIDD_DEINIT_EVT */
|
||||
|
||||
/**
|
||||
* @brief ESP_HIDD_REGISTER_APP_EVT
|
||||
*/
|
||||
struct hidd_register_app_evt_param {
|
||||
esp_hidd_status_t status; /*!< operation status */
|
||||
bool in_use; /*!< indicate whether use virtual cable plug host address */
|
||||
esp_bd_addr_t bd_addr; /*!< host address */
|
||||
} register_app; /*!< HIDD callback param of ESP_HIDD_REGISTER_APP_EVT */
|
||||
|
||||
/**
|
||||
* @brief ESP_HIDD_UNREGISTER_APP_EVT
|
||||
*/
|
||||
struct hidd_unregister_app_evt_param {
|
||||
esp_hidd_status_t status; /*!< operation status */
|
||||
} unregister_app; /*!< HIDD callback param of ESP_HIDD_UNREGISTER_APP_EVT */
|
||||
|
||||
/**
|
||||
* @brief ESP_HIDD_OPEN_EVT
|
||||
*/
|
||||
struct hidd_open_evt_param {
|
||||
esp_hidd_status_t status; /*!< operation status */
|
||||
esp_hidd_connection_state_t conn_status; /*!< connection status */
|
||||
esp_bd_addr_t bd_addr; /*!< host address */
|
||||
} open; /*!< HIDD callback param of ESP_HIDD_OPEN_EVT */
|
||||
|
||||
/**
|
||||
* @brief ESP_HIDD_CLOSE_EVT
|
||||
*/
|
||||
struct hidd_close_evt_param {
|
||||
esp_hidd_status_t status; /*!< operation status */
|
||||
esp_hidd_connection_state_t conn_status; /*!< connection status */
|
||||
} close; /*!< HIDD callback param of ESP_HIDD_CLOSE_EVT */
|
||||
|
||||
/**
|
||||
* @brief ESP_HIDD_SEND_REPORT_EVT
|
||||
*/
|
||||
struct hidd_send_report_evt_param {
|
||||
esp_hidd_status_t status; /*!< operation status */
|
||||
uint8_t reason; /*!< lower layer failed reason(ref hiddefs.h) */
|
||||
esp_hidd_report_type_t report_type; /*!< report type */
|
||||
uint8_t report_id; /*!< report id */
|
||||
} send_report; /*!< HIDD callback param of ESP_HIDD_SEND_REPORT_EVT */
|
||||
|
||||
/**
|
||||
* @brief ESP_HIDD_REPORT_ERR_EVT
|
||||
*/
|
||||
struct hidd_report_err_evt_param {
|
||||
esp_hidd_status_t status; /*!< operation status */
|
||||
uint8_t reason; /*!< lower layer failed reason(ref hiddefs.h) */
|
||||
} report_err; /*!< HIDD callback param of ESP_HIDD_REPORT_ERR_EVT */
|
||||
|
||||
/**
|
||||
* @brief ESP_HIDD_GET_REPORT_EVT
|
||||
*/
|
||||
struct hidd_get_report_evt_param {
|
||||
esp_hidd_report_type_t report_type; /*!< report type */
|
||||
uint8_t report_id; /*!< report id */
|
||||
uint16_t buffer_size; /*!< buffer size */
|
||||
} get_report; /*!< HIDD callback param of ESP_HIDD_GET_REPORT_EVT */
|
||||
|
||||
/**
|
||||
* @brief ESP_HIDD_SET_REPORT_EVT
|
||||
*/
|
||||
struct hidd_set_report_evt_param {
|
||||
esp_hidd_report_type_t report_type; /*!< report type */
|
||||
uint8_t report_id; /*!< report id */
|
||||
uint16_t len; /*!< set_report data length */
|
||||
uint8_t *data; /*!< set_report data pointer */
|
||||
} set_report; /*!< HIDD callback param of ESP_HIDD_SET_REPORT_EVT */
|
||||
|
||||
/**
|
||||
* @brief ESP_HIDD_SET_PROTOCOL_EVT
|
||||
*/
|
||||
struct hidd_set_protocol_evt_param {
|
||||
esp_hidd_protocol_mode_t protocol_mode; /*!< protocol mode */
|
||||
} set_protocol; /*!< HIDD callback param of ESP_HIDD_SET_PROTOCOL_EVT */
|
||||
|
||||
/**
|
||||
* @brief ESP_HIDD_INTR_DATA_EVT
|
||||
*/
|
||||
struct hidd_intr_data_evt_param {
|
||||
uint8_t report_id; /*!< interrupt channel report id */
|
||||
uint16_t len; /*!< interrupt channel report data length */
|
||||
uint8_t *data; /*!< interrupt channel report data pointer */
|
||||
} intr_data; /*!< HIDD callback param of ESP_HIDD_INTR_DATA_EVT */
|
||||
|
||||
/**
|
||||
* @brief ESP_HIDD_VC_UNPLUG_EVT
|
||||
*/
|
||||
struct hidd_vc_unplug_param {
|
||||
esp_hidd_status_t status; /*!< operation status */
|
||||
esp_hidd_connection_state_t conn_status; /*!< connection status */
|
||||
} vc_unplug; /*!< HIDD callback param of ESP_HIDD_VC_UNPLUG_EVT */
|
||||
} esp_hidd_cb_param_t;
|
||||
|
||||
/**
|
||||
* @brief HID device callback function type.
|
||||
* @param event: Event type
|
||||
* @param param: Point to callback parameter, currently is union type
|
||||
*/
|
||||
typedef void (esp_hd_cb_t)(esp_hidd_cb_event_t event, esp_hidd_cb_param_t *param);
|
||||
|
||||
/**
|
||||
* @brief This function is called to init callbacks with HID device module.
|
||||
*
|
||||
* @param[in] callback: pointer to the init callback function.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: success
|
||||
* - other: failed
|
||||
*/
|
||||
esp_err_t esp_bt_hid_device_register_callback(esp_hd_cb_t callback);
|
||||
|
||||
/**
|
||||
* @brief This function initializes HIDD. This function should be called after esp_bluedroid_enable and
|
||||
* esp_blueroid_init success, and should be called after esp_bt_hid_device_register_callback.
|
||||
* When the operation is complete the callback function will be called with ESP_HIDD_INIT_EVT.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: success
|
||||
* - other: failed
|
||||
*/
|
||||
esp_err_t esp_bt_hid_device_init(void);
|
||||
|
||||
/**
|
||||
* @brief This function de-initializes HIDD interface. This function should be called after esp_bluedroid_enable() and
|
||||
* esp_blueroid_init() success, and should be called after esp_bt_hid_device_init(). When the operation is complete the callback
|
||||
* function will be called with ESP_HIDD_DEINIT_EVT.
|
||||
*
|
||||
* @return - ESP_OK: success
|
||||
* - other: failed
|
||||
*/
|
||||
esp_err_t esp_bt_hid_device_deinit(void);
|
||||
|
||||
/**
|
||||
* @brief Registers HIDD parameters with SDP and sets l2cap Quality of Service. This function should be called after
|
||||
* esp_bluedroid_enable and esp_blueroid_init success, and must be done after esp_bt_hid_device_init. When the operation is complete the callback
|
||||
* function will be called with ESP_HIDD_REGISTER_APP_EVT.
|
||||
*
|
||||
* @param[in] app_param: HIDD parameters
|
||||
* @param[in] in_qos: incoming QoS parameters
|
||||
* @param[in] out_qos: outgoing QoS parameters
|
||||
*
|
||||
* @return - ESP_OK: success
|
||||
* - other: failed
|
||||
*/
|
||||
esp_err_t esp_bt_hid_device_register_app(esp_hidd_app_param_t *app_param, esp_hidd_qos_param_t *in_qos,
|
||||
esp_hidd_qos_param_t *out_qos);
|
||||
|
||||
/**
|
||||
* @brief Removes HIDD parameters from SDP and resets l2cap Quality of Service. This function should be called after esp_bluedroid_enable and
|
||||
* esp_blueroid_init success, and should be called after esp_bt_hid_device_init. When the operation is complete the callback
|
||||
* function will be called with ESP_HIDD_UNREGISTER_APP_EVT.
|
||||
*
|
||||
* @return - ESP_OK: success
|
||||
* - other: failed
|
||||
*/
|
||||
esp_err_t esp_bt_hid_device_unregister_app(void);
|
||||
|
||||
/**
|
||||
* @brief This function connects HIDD interface to connected bluetooth device, if not done already. When the operation is complete the callback
|
||||
* function will be called with ESP_HIDD_OPEN_EVT.
|
||||
*
|
||||
* @param[in] bd_addr: Remote host bluetooth device address.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: success
|
||||
* - other: failed
|
||||
*/
|
||||
esp_err_t esp_bt_hid_device_connect(esp_bd_addr_t bd_addr);
|
||||
|
||||
/**
|
||||
* @brief This function disconnects HIDD interface. When the operation is complete the callback
|
||||
* function will be called with ESP_HIDD_CLOSE_EVT.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: success
|
||||
* - other: failed
|
||||
*/
|
||||
esp_err_t esp_bt_hid_device_disconnect(void);
|
||||
|
||||
/**
|
||||
* @brief Send HIDD report. When the operation is complete the callback
|
||||
* function will be called with ESP_HIDD_SEND_REPORT_EVT.
|
||||
*
|
||||
* @param[in] type: type of report
|
||||
* @param[in] id: report id as defined by descriptor
|
||||
* @param[in] len: length of report
|
||||
* @param[in] data: report data
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: success
|
||||
* - other: failed
|
||||
*/
|
||||
esp_err_t esp_bt_hid_device_send_report(esp_hidd_report_type_t type, uint8_t id, uint16_t len, uint8_t *data);
|
||||
|
||||
/**
|
||||
* @brief Sends HIDD handshake with error info for invalid set_report. When the operation is complete the callback
|
||||
* function will be called with ESP_HIDD_REPORT_ERR_EVT.
|
||||
*
|
||||
* @param[in] error: type of error
|
||||
*
|
||||
* @return - ESP_OK: success
|
||||
* - other: failed
|
||||
*/
|
||||
esp_err_t esp_bt_hid_device_report_error(esp_hidd_handshake_error_t error);
|
||||
|
||||
/**
|
||||
* @brief Unplug virtual cable of HIDD. When the operation is complete the callback
|
||||
* function will be called with ESP_HIDD_VC_UNPLUG_EVT.
|
||||
*
|
||||
* @return - ESP_OK: success
|
||||
* - other: failed
|
||||
*/
|
||||
esp_err_t esp_bt_hid_device_virtual_cable_unplug(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
465
components/bt/host/bluedroid/api/include/api/esp_hidh_api.h
Normal file
465
components/bt/host/bluedroid/api/include/api/esp_hidh_api.h
Normal file
@ -0,0 +1,465 @@
|
||||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
// Copyright 2019 Blake Felt
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef __ESP_HIDH_API_H__
|
||||
#define __ESP_HIDH_API_H__
|
||||
|
||||
#include "esp_bt_defs.h"
|
||||
#include "esp_err.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define BTHH_MAX_DSC_LEN 884
|
||||
|
||||
/**
|
||||
* @brief HID host connection state
|
||||
*/
|
||||
typedef enum {
|
||||
ESP_HIDH_CONN_STATE_CONNECTED = 0, /*!< connected state */
|
||||
ESP_HIDH_CONN_STATE_CONNECTING, /*!< connecting state */
|
||||
ESP_HIDH_CONN_STATE_DISCONNECTED, /*!< disconnected state */
|
||||
ESP_HIDH_CONN_STATE_DISCONNECTING, /*!< disconnecting state */
|
||||
ESP_HIDH_CONN_STATE_UNKNOWN /*!< unknown state(initial state) */
|
||||
} esp_hidh_connection_state_t;
|
||||
|
||||
typedef enum {
|
||||
ESP_HIDH_OK,
|
||||
ESP_HIDH_HS_HID_NOT_READY, /*!< handshake error : device not ready */
|
||||
ESP_HIDH_HS_INVALID_RPT_ID, /*!< handshake error : invalid report ID */
|
||||
ESP_HIDH_HS_TRANS_NOT_SPT, /*!< handshake error : transaction not spt */
|
||||
ESP_HIDH_HS_INVALID_PARAM, /*!< handshake error : invalid paremter */
|
||||
ESP_HIDH_HS_ERROR, /*!< handshake error : unspecified HS error */
|
||||
ESP_HIDH_ERR, /*!< general ESP HH error */
|
||||
ESP_HIDH_ERR_SDP, /*!< SDP error */
|
||||
ESP_HIDH_ERR_PROTO, /*!< SET_Protocol error,
|
||||
only used in ESP_HIDH_OPEN_EVT callback */
|
||||
|
||||
ESP_HIDH_ERR_DB_FULL, /*!< device database full error, used in
|
||||
ESP_HIDH_OPEN_EVT/ESP_HIDH_ADD_DEV_EVT */
|
||||
ESP_HIDH_ERR_TOD_UNSPT, /*!< type of device not supported */
|
||||
ESP_HIDH_ERR_NO_RES, /*!< out of system resources */
|
||||
ESP_HIDH_ERR_AUTH_FAILED, /*!< authentication fail */
|
||||
ESP_HIDH_ERR_HDL, /*!< connection handle error */
|
||||
ESP_HIDH_ERR_SEC, /*!< encryption error */
|
||||
// self_defined
|
||||
ESP_HIDH_BUSY, /*!< Temporarily can not handle this request. */
|
||||
ESP_HIDH_NO_DATA, /*!< No data. */
|
||||
ESP_HIDH_NEED_INIT, /*!< HIDH module shall init first */
|
||||
ESP_HIDH_NEED_DEINIT, /*!< HIDH module shall deinit first */
|
||||
ESP_HIDH_NO_CONNECTION, /*!< connection may have been closed */
|
||||
} esp_hidh_status_t;
|
||||
|
||||
/**
|
||||
* @brief HID host protocol modes
|
||||
*/
|
||||
typedef enum {
|
||||
ESP_HIDH_BOOT_MODE = 0x00, /*!< boot protocol mode */
|
||||
ESP_HIDH_REPORT_MODE = 0x01, /*!< report protocol mode */
|
||||
ESP_HIDH_UNSUPPORTED_MODE = 0xff /*!< unsupported protocol mode */
|
||||
} esp_hidh_protocol_mode_t;
|
||||
|
||||
/**
|
||||
* @brief HID host report types
|
||||
*/
|
||||
typedef enum {
|
||||
ESP_HIDH_REPORT_TYPE_OTHER = 0, /*!< unsupported report type */
|
||||
ESP_HIDH_REPORT_TYPE_INPUT, /*!< input report type */
|
||||
ESP_HIDH_REPORT_TYPE_OUTPUT, /*!< output report type */
|
||||
ESP_HIDH_REPORT_TYPE_FEATURE, /*!< feature report type */
|
||||
} esp_hidh_report_type_t;
|
||||
|
||||
/**
|
||||
* @brief HID host callback function events
|
||||
*/
|
||||
typedef enum {
|
||||
ESP_HIDH_INIT_EVT = 0, /*!< When HID host is inited, the event comes */
|
||||
ESP_HIDH_DEINIT_EVT, /*!< When HID host is deinited, the event comes */
|
||||
ESP_HIDH_OPEN_EVT, /*!< When HID host connection opened, the event comes */
|
||||
ESP_HIDH_CLOSE_EVT, /*!< When HID host connection closed, the event comes */
|
||||
ESP_HIDH_GET_RPT_EVT, /*!< When Get_Report command is called, the event comes */
|
||||
ESP_HIDH_SET_RPT_EVT, /*!< When Set_Report command is called, the event comes */
|
||||
ESP_HIDH_GET_PROTO_EVT, /*!< When Get_Protocol command is called, the event comes */
|
||||
ESP_HIDH_SET_PROTO_EVT, /*!< When Set_Protocol command is called, the event comes */
|
||||
ESP_HIDH_GET_IDLE_EVT, /*!< When Get_Idle command is called, the event comes */
|
||||
ESP_HIDH_SET_IDLE_EVT, /*!< When Set_Idle command is called, the event comes */
|
||||
ESP_HIDH_GET_DSCP_EVT, /*!< When HIDH is inited, the event comes */
|
||||
ESP_HIDH_ADD_DEV_EVT, /*!< When a device is added, the event comes */
|
||||
ESP_HIDH_RMV_DEV_EVT, /*!< When a device is removed, the event comes */
|
||||
ESP_HIDH_VC_UNPLUG_EVT, /*!< When virtually unplugged, the event comes */
|
||||
ESP_HIDH_DATA_EVT, /*!< When send data on interrupt channel, the event comes */
|
||||
ESP_HIDH_DATA_IND_EVT, /*!< When receive data on interrupt channel, the event comes */
|
||||
ESP_HIDH_SET_INFO_EVT /*!< When set the HID device descriptor, the event comes */
|
||||
} esp_hidh_cb_event_t;
|
||||
|
||||
typedef struct {
|
||||
int attr_mask;
|
||||
uint8_t sub_class;
|
||||
uint8_t app_id;
|
||||
int vendor_id;
|
||||
int product_id;
|
||||
int version;
|
||||
uint8_t ctry_code;
|
||||
int dl_len;
|
||||
uint8_t dsc_list[BTHH_MAX_DSC_LEN];
|
||||
} esp_hidh_hid_info_t;
|
||||
|
||||
/**
|
||||
* @brief HID host callback parameters union
|
||||
*/
|
||||
typedef union {
|
||||
/**
|
||||
* @brief ESP_HIDH_INIT_EVT
|
||||
*/
|
||||
struct hidh_init_evt_param {
|
||||
esp_hidh_status_t status; /*!< status */
|
||||
} init; /*!< HIDH callback param of ESP_HIDH_INIT_EVT */
|
||||
|
||||
/**
|
||||
* @brief ESP_HIDH_DEINIT_EVT
|
||||
*/
|
||||
struct hidh_uninit_evt_param {
|
||||
esp_hidh_status_t status; /*!< status */
|
||||
} deinit; /*!< HIDH callback param of ESP_HIDH_DEINIT_EVT */
|
||||
|
||||
/**
|
||||
* @brief ESP_HIDH_OPEN_EVT
|
||||
*/
|
||||
struct hidh_open_evt_param {
|
||||
esp_hidh_status_t status; /*!< operation status */
|
||||
esp_hidh_connection_state_t conn_status; /*!< connection status */
|
||||
bool is_orig; /*!< indicate if host intiate the connection */
|
||||
uint8_t handle; /*!< device handle */
|
||||
esp_bd_addr_t bd_addr; /*!< device address */
|
||||
} open; /*!< HIDH callback param of ESP_HIDH_OPEN_EVT */
|
||||
|
||||
/**
|
||||
* @brief ESP_HIDH_CLOSE_EVT
|
||||
*/
|
||||
struct hidh_close_evt_param {
|
||||
esp_hidh_status_t status; /*!< operation status */
|
||||
uint8_t reason; /*!< lower layer failed reason(ref hiddefs.h) */
|
||||
esp_hidh_connection_state_t conn_status; /*!< connection status */
|
||||
uint8_t handle; /*!< device handle */
|
||||
} close; /*!< HIDH callback param of ESP_HIDH_CLOSE_EVT */
|
||||
|
||||
/**
|
||||
* @brief ESP_HIDH_VC_UNPLUG_EVT
|
||||
*/
|
||||
struct hidh_unplug_evt_param {
|
||||
esp_hidh_status_t status; /*!< operation status */
|
||||
esp_hidh_connection_state_t conn_status; /*!< connection status */
|
||||
uint8_t handle; /*!< device handle */
|
||||
} unplug; /*!< HIDH callback param of ESP_HIDH_VC_UNPLUG_EVT */
|
||||
|
||||
/**
|
||||
* @brief ESP_HIDH_GET_PROTO_EVT
|
||||
*/
|
||||
struct hidh_get_proto_evt_param {
|
||||
esp_hidh_status_t status; /*!< operation status */
|
||||
uint8_t handle; /*!< device handle */
|
||||
esp_hidh_protocol_mode_t proto_mode; /*!< protocol mode */
|
||||
} get_proto; /*!< HIDH callback param of ESP_HIDH_GET_PROTO_EVT */
|
||||
|
||||
/**
|
||||
* @brief ESP_HIDH_SET_PROTO_EVT
|
||||
*/
|
||||
struct hidh_set_proto_evt_param {
|
||||
esp_hidh_status_t status; /*!< operation status */
|
||||
uint8_t handle; /*!< device handle */
|
||||
} set_proto; /*!< HIDH callback param of ESP_HIDH_SET_PROTO_EVT */
|
||||
|
||||
/**
|
||||
* @brief ESP_HIDH_GET_RPT_EVT
|
||||
*/
|
||||
struct hidh_get_rpt_evt_param {
|
||||
esp_hidh_status_t status; /*!< operation status */
|
||||
uint8_t handle; /*!< device handle */
|
||||
uint16_t len; /*!< data length */
|
||||
uint8_t *data; /*!< data pointer */
|
||||
} get_rpt; /*!< HIDH callback param of ESP_HIDH_GET_RPT_EVT */
|
||||
|
||||
/**
|
||||
* @brief ESP_HIDH_SET_RPT_EVT
|
||||
*/
|
||||
struct hidh_set_rpt_evt_param {
|
||||
esp_hidh_status_t status; /*!< operation status */
|
||||
uint8_t handle; /*!< device handle */
|
||||
} set_rpt; /*!< HIDH callback param of ESP_HIDH_SET_RPT_EVT */
|
||||
|
||||
/**
|
||||
* @brief ESP_HIDH_DATA_EVT
|
||||
*/
|
||||
struct hidh_send_data_evt_param {
|
||||
esp_hidh_status_t status; /*!< operation status */
|
||||
uint8_t handle; /*!< device handle */
|
||||
uint8_t reason; /*!< lower layer failed reason(ref hiddefs.h) */
|
||||
} send_data; /*!< HIDH callback param of ESP_HIDH_DATA_EVT */
|
||||
|
||||
/**
|
||||
* @brief ESP_HIDH_GET_IDLE_EVT
|
||||
*/
|
||||
struct hidh_get_idle_evt_param {
|
||||
esp_hidh_status_t status; /*!< operation status */
|
||||
uint8_t handle; /*!< device handle */
|
||||
uint8_t idle_rate; /*!< idle rate */
|
||||
} get_idle; /*!< HIDH callback param of ESP_HIDH_GET_IDLE_EVT */
|
||||
|
||||
/**
|
||||
* @brief ESP_HIDH_SET_IDLE_EVT
|
||||
*/
|
||||
struct hidh_set_idle_evt_param {
|
||||
esp_hidh_status_t status; /*!< operation status */
|
||||
uint8_t handle; /*!< device handle */
|
||||
} set_idle; /*!< HIDH callback param of ESP_HIDH_SET_IDLE_EVT */
|
||||
|
||||
/**
|
||||
* @brief ESP_HIDH_DATA_IND_EVT
|
||||
*/
|
||||
struct hidh_data_ind_evt_param {
|
||||
esp_hidh_status_t status; /*!< operation status */
|
||||
uint8_t handle; /*!< device handle */
|
||||
esp_hidh_protocol_mode_t proto_mode; /*!< protocol mode */
|
||||
uint16_t len; /*!< data length */
|
||||
uint8_t *data; /*!< data pointer */
|
||||
} data_ind; /*!< HIDH callback param of ESP_HIDH_DATA_IND_EVT */
|
||||
|
||||
/**
|
||||
* @brief ESP_HIDH_ADD_DEV_EVT
|
||||
*/
|
||||
struct hidh_add_dev_evt_param {
|
||||
esp_hidh_status_t status; /*!< operation status */
|
||||
uint8_t handle; /*!< device handle */
|
||||
esp_bd_addr_t bd_addr; /*!< device address */
|
||||
} add_dev; /*!< HIDH callback param of ESP_HIDH_ADD_DEV_EVT */
|
||||
|
||||
/**
|
||||
* @brief ESP_HIDH_RMV_DEV_EVT
|
||||
*/
|
||||
struct hidh_rmv_dev_evt_param {
|
||||
esp_hidh_status_t status; /*!< operation status */
|
||||
uint8_t handle; /*!< device handle */
|
||||
esp_bd_addr_t bd_addr; /*!< device address */
|
||||
} rmv_dev; /*!< HIDH callback param of ESP_HIDH_RMV_DEV_EVT */
|
||||
|
||||
/**
|
||||
* @brief ESP_HIDH_GET_DSCP_EVT
|
||||
*/
|
||||
struct hidh_get_dscp_evt_param {
|
||||
esp_hidh_status_t status; /*!< operation status */
|
||||
uint8_t handle; /*!< device handle */
|
||||
bool added; /*!< Indicate if added */
|
||||
uint16_t vendor_id; /*!< Vendor ID */
|
||||
uint16_t product_id; /*!< Product ID */
|
||||
uint16_t version; /*!< Version */
|
||||
uint16_t ssr_max_latency; /*!< SSR max latency */
|
||||
uint16_t ssr_min_tout; /*!< SSR min timeout */
|
||||
uint8_t ctry_code; /*!< Country Code */
|
||||
uint16_t dl_len; /*!< Device descriptor length */
|
||||
uint8_t *dsc_list; /*!< Device descriptor pointer */
|
||||
} dscp; /*!< HIDH callback param of ESP_HIDH_GET_DSCP_EVT */
|
||||
|
||||
/**
|
||||
* @brief ESP_HIDH_SET_INFO_EVT
|
||||
*/
|
||||
struct hidh_set_info_evt_param {
|
||||
esp_hidh_status_t status; /*!< operation status */
|
||||
uint8_t handle; /*!< device handle */
|
||||
esp_bd_addr_t bd_addr; /*!< device address */
|
||||
} set_info; /*!< HIDH callback param of ESP_HIDH_SET_INFO_EVT */
|
||||
} esp_hidh_cb_param_t;
|
||||
|
||||
/**
|
||||
* @brief HID host callback function type
|
||||
* @param event: Event type
|
||||
* @param param: Point to callback parameter, currently is union type
|
||||
*/
|
||||
typedef void (esp_hh_cb_t)(esp_hidh_cb_event_t event, esp_hidh_cb_param_t *param);
|
||||
|
||||
/**
|
||||
* @brief This function is called to init callbacks with HID host module.
|
||||
*
|
||||
* @param[in] callback: pointer to the init callback function.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: success
|
||||
* - other: failed
|
||||
*/
|
||||
esp_err_t esp_bt_hid_host_register_callback(esp_hh_cb_t callback);
|
||||
|
||||
/**
|
||||
* @brief This function initializes HID host. This function should be called after esp_bluedroid_enable() and
|
||||
* esp_blueroid_init() success, and should be called after esp_bt_hid_host_register_callback().
|
||||
* When the operation is complete the callback function will be called with ESP_HIDH_INIT_EVT.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: success
|
||||
* - other: failed
|
||||
*/
|
||||
esp_err_t esp_bt_hid_host_init(void);
|
||||
|
||||
/**
|
||||
* @brief Closes the interface. This function should be called after esp_bluedroid_enable() and
|
||||
* esp_blueroid_init() success, and should be called after esp_bt_hid_host_init().
|
||||
* When the operation is complete the callback function will be called with ESP_HIDH_DEINIT_EVT.
|
||||
*
|
||||
* @return - ESP_OK: success
|
||||
* - other: failed
|
||||
*/
|
||||
esp_err_t esp_bt_hid_host_deinit(void);
|
||||
|
||||
/**
|
||||
* @brief Connect to hid device. When the operation is complete the callback
|
||||
* function will be called with ESP_HIDH_OPEN_EVT.
|
||||
*
|
||||
* @param[in] bd_addr: Remote device bluetooth device address.
|
||||
*
|
||||
* @return - ESP_OK: success
|
||||
* - other: failed
|
||||
*/
|
||||
esp_err_t esp_bt_hid_host_connect(esp_bd_addr_t bd_addr);
|
||||
|
||||
/**
|
||||
* @brief Disconnect from hid device. When the operation is complete the callback
|
||||
* function will be called with ESP_HIDH_CLOSE_EVT.
|
||||
*
|
||||
* @param[in] bd_addr: Remote device bluetooth device address.
|
||||
*
|
||||
* @return - ESP_OK: success
|
||||
* - other: failed
|
||||
*/
|
||||
esp_err_t esp_bt_hid_host_disconnect(esp_bd_addr_t bd_addr);
|
||||
|
||||
/**
|
||||
* @brief Virtual UnPlug (VUP) the specified HID device. When the operation is complete the callback
|
||||
* function will be called with ESP_HIDH_VC_UNPLUG_EVT.
|
||||
*
|
||||
* @param[in] bd_addr: Remote device bluetooth device address.
|
||||
*
|
||||
* @return - ESP_OK: success
|
||||
* - other: failed
|
||||
*/
|
||||
esp_err_t esp_bt_hid_host_virtual_cable_unplug(esp_bd_addr_t bd_addr);
|
||||
|
||||
/**
|
||||
* @brief Set the HID device descriptor for the specified HID device. When the operation is complete the callback
|
||||
* function will be called with ESP_HIDH_SET_INFO_EVT.
|
||||
*
|
||||
* @param[in] bd_addr: Remote device bluetooth device address.
|
||||
* @param[in] hid_info: HID device descriptor structure.
|
||||
*
|
||||
* @return - ESP_OK: success
|
||||
* - other: failed
|
||||
*/
|
||||
esp_err_t esp_bt_hid_host_set_info(esp_bd_addr_t bd_addr, esp_hidh_hid_info_t *hid_info);
|
||||
|
||||
/**
|
||||
* @brief Get the HID proto mode. When the operation is complete the callback
|
||||
* function will be called with ESP_HIDH_GET_PROTO_EVT.
|
||||
*
|
||||
* @param[in] bd_addr: Remote device bluetooth device address.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: success
|
||||
* - other: failed
|
||||
*/
|
||||
esp_err_t esp_bt_hid_host_get_protocol(esp_bd_addr_t bd_addr);
|
||||
|
||||
/**
|
||||
* @brief Set the HID proto mode. When the operation is complete the callback
|
||||
* function will be called with ESP_HIDH_SET_PROTO_EVT.
|
||||
*
|
||||
* @param[in] bd_addr: Remote device bluetooth device address.
|
||||
* @param[in] protocol_mode: Protocol mode type.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: success
|
||||
* - other: failed
|
||||
*/
|
||||
esp_err_t esp_bt_hid_host_set_protocol(esp_bd_addr_t bd_addr, esp_hidh_protocol_mode_t protocol_mode);
|
||||
|
||||
/**
|
||||
* @brief Get the HID Idle Time. When the operation is complete the callback
|
||||
* function will be called with ESP_HIDH_GET_IDLE_EVT.
|
||||
*
|
||||
* @param[in] bd_addr: Remote device bluetooth device address.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: success
|
||||
* - other: failed
|
||||
*/
|
||||
esp_err_t esp_bt_hid_host_get_idle(esp_bd_addr_t bd_addr);
|
||||
|
||||
/**
|
||||
* @brief Set the HID Idle Time. When the operation is complete the callback
|
||||
* function will be called with ESP_HIDH_SET_IDLE_EVT.
|
||||
*
|
||||
* @param[in] bd_addr: Remote device bluetooth device address.
|
||||
* @param[in] idle_time: Idle time rate
|
||||
*
|
||||
* @return - ESP_OK: success
|
||||
* - other: failed
|
||||
*/
|
||||
esp_err_t esp_bt_hid_host_set_idle(esp_bd_addr_t bd_addr, uint16_t idle_time);
|
||||
|
||||
/**
|
||||
* @brief Send a GET_REPORT to HID device. When the operation is complete the callback
|
||||
* function will be called with ESP_HIDH_GET_RPT_EVT.
|
||||
*
|
||||
* @param[in] bd_addr: Remote device bluetooth device address.
|
||||
* @param[in] report_type: Report type
|
||||
* @param[in] report_id: Report id
|
||||
* @param[in] buffer_size: Buffer size
|
||||
*
|
||||
* @return - ESP_OK: success
|
||||
* - other: failed
|
||||
*/
|
||||
esp_err_t esp_bt_hid_host_get_report(esp_bd_addr_t bd_addr, esp_hidh_report_type_t report_type, uint8_t report_id,
|
||||
int buffer_size);
|
||||
|
||||
/**
|
||||
* @brief Send a SET_REPORT to HID device. When the operation is complete the callback
|
||||
* function will be called with ESP_HIDH_SET_RPT_EVT.
|
||||
*
|
||||
* @param[in] bd_addr: Remote device bluetooth device address.
|
||||
* @param[in] report_type: Report type
|
||||
* @param[in] report: Report data pointer
|
||||
* @param[in] len: Report data length
|
||||
*
|
||||
* @return - ESP_OK: success
|
||||
* - other: failed
|
||||
*/
|
||||
esp_err_t esp_bt_hid_host_set_report(esp_bd_addr_t bd_addr, esp_hidh_report_type_t report_type, uint8_t *report,
|
||||
size_t len);
|
||||
|
||||
/**
|
||||
* @brief Send data to HID device. When the operation is complete the callback
|
||||
* function will be called with ESP_HIDH_DATA_EVT.
|
||||
*
|
||||
* @param[in] bd_addr: Remote device bluetooth device address.
|
||||
* @param[in] data: Data pointer
|
||||
* @param[in] len: Data length
|
||||
*
|
||||
* @return - ESP_OK: success
|
||||
* - other: failed
|
||||
*/
|
||||
esp_err_t esp_bt_hid_host_send_data(esp_bd_addr_t bd_addr, uint8_t *data, size_t len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -126,7 +126,7 @@ static void bta_dm_ctrl_features_rd_cmpl_cback(tBTM_STATUS result);
|
||||
#endif
|
||||
#endif
|
||||
#if (SMP_INCLUDED == TRUE)
|
||||
static void bta_dm_remove_sec_dev_entry(BD_ADDR remote_bd_addr);
|
||||
static BOOLEAN bta_dm_remove_sec_dev_entry(BD_ADDR remote_bd_addr);
|
||||
#endif ///SMP_INCLUDED == TRUE
|
||||
#if (BLE_INCLUDED == TRUE)
|
||||
static void bta_dm_observe_results_cb(tBTM_INQ_RESULTS *p_inq, UINT8 *p_eir);
|
||||
@ -3069,7 +3069,9 @@ static UINT8 bta_dm_authentication_complete_cback(BD_ADDR bd_addr, DEV_CLASS dev
|
||||
bta_dm_cb.p_sec_cback(BTA_DM_AUTH_CMPL_EVT, &sec_event);
|
||||
}
|
||||
|
||||
bta_dm_remove_sec_dev_entry(bd_addr);
|
||||
if (bta_dm_remove_sec_dev_entry(bd_addr)) {
|
||||
return BTM_SEC_DEV_REC_REMOVED;
|
||||
}
|
||||
}
|
||||
|
||||
return BTM_SUCCESS;
|
||||
@ -3740,12 +3742,13 @@ static void bta_dm_delay_role_switch_cback(TIMER_LIST_ENT *p_tle)
|
||||
** remtoe device does not exist, else schedule for dev entry removal upon
|
||||
ACL close
|
||||
**
|
||||
** Returns void
|
||||
** Returns TRUE if device entry is removed from Security device DB, FALSE otherwise
|
||||
**
|
||||
*******************************************************************************/
|
||||
#if (SMP_INCLUDED == TRUE)
|
||||
static void bta_dm_remove_sec_dev_entry(BD_ADDR remote_bd_addr)
|
||||
static BOOLEAN bta_dm_remove_sec_dev_entry(BD_ADDR remote_bd_addr)
|
||||
{
|
||||
BOOLEAN is_device_deleted = FALSE;
|
||||
UINT16 index = 0;
|
||||
if ( BTM_IsAclConnectionUp(remote_bd_addr, BT_TRANSPORT_LE) ||
|
||||
BTM_IsAclConnectionUp(remote_bd_addr, BT_TRANSPORT_BR_EDR)) {
|
||||
@ -3763,7 +3766,7 @@ static void bta_dm_remove_sec_dev_entry(BD_ADDR remote_bd_addr)
|
||||
APPL_TRACE_ERROR(" %s Device does not exist in DB", __FUNCTION__);
|
||||
}
|
||||
} else {
|
||||
BTM_SecDeleteDevice (remote_bd_addr, bta_dm_cb.device_list.peer_device[index].transport);
|
||||
is_device_deleted = BTM_SecDeleteDevice (remote_bd_addr, bta_dm_cb.device_list.peer_device[index].transport);
|
||||
#if (BLE_INCLUDED == TRUE && GATTC_INCLUDED == TRUE)
|
||||
/* need to remove all pending background connection */
|
||||
BTA_GATTC_CancelOpen(0, remote_bd_addr, FALSE);
|
||||
@ -3771,6 +3774,7 @@ static void bta_dm_remove_sec_dev_entry(BD_ADDR remote_bd_addr)
|
||||
BTA_GATTC_Refresh(remote_bd_addr, false);
|
||||
#endif
|
||||
}
|
||||
return is_device_deleted;
|
||||
}
|
||||
#endif ///SMP_INCLUDED == TRUE
|
||||
|
||||
@ -4498,6 +4502,22 @@ void bta_dm_set_encryption (tBTA_DM_MSG *p_data)
|
||||
}
|
||||
#endif ///SMP_INCLUDED == TRUE
|
||||
|
||||
#if (BTA_HD_INCLUDED == TRUE)
|
||||
BOOLEAN bta_dm_check_if_only_hd_connected(BD_ADDR peer_addr)
|
||||
{
|
||||
APPL_TRACE_DEBUG("%s: count(%d)", __func__, bta_dm_conn_srvcs.count);
|
||||
for (uint8_t j = 0; j < bta_dm_conn_srvcs.count; j++) {
|
||||
// Check if profiles other than hid are connected
|
||||
if ((bta_dm_conn_srvcs.conn_srvc[j].id != BTA_ID_HD) &&
|
||||
!bdcmp(bta_dm_conn_srvcs.conn_srvc[j].peer_bdaddr, peer_addr)) {
|
||||
APPL_TRACE_DEBUG("%s: Another profile (id=%d) is connected", __func__, bta_dm_conn_srvcs.conn_srvc[j].id);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
#endif /* BTA_HD_INCLUDED == TRUE */
|
||||
|
||||
#if (BLE_INCLUDED == TRUE)
|
||||
/*******************************************************************************
|
||||
**
|
||||
|
@ -117,11 +117,11 @@ tBTA_DM_CFG *const p_bta_dm_cfg = (tBTA_DM_CFG *) &bta_dm_cfg;
|
||||
tBTA_DM_RM *const p_bta_dm_rm_cfg = (tBTA_DM_RM *) &bta_dm_rm_cfg;
|
||||
|
||||
#if BLE_INCLUDED == TRUE
|
||||
# define BTA_DM_NUM_PM_ENTRY 10 /* number of entries in bta_dm_pm_cfg except the first */
|
||||
# define BTA_DM_NUM_PM_SPEC 10 /* number of entries in bta_dm_pm_spec */
|
||||
#else
|
||||
# define BTA_DM_NUM_PM_ENTRY 8 /* number of entries in bta_dm_pm_cfg except the first */
|
||||
# define BTA_DM_NUM_PM_SPEC 8 /* number of entries in bta_dm_pm_spec */
|
||||
#else
|
||||
# define BTA_DM_NUM_PM_ENTRY 6 /* number of entries in bta_dm_pm_cfg except the first */
|
||||
# define BTA_DM_NUM_PM_SPEC 6 /* number of entries in bta_dm_pm_spec */
|
||||
#endif
|
||||
|
||||
#if (BTA_DM_PM_INCLUDED == TRUE)
|
||||
@ -133,10 +133,12 @@ tBTA_DM_PM_TYPE_QUALIFIER tBTA_DM_PM_CFG bta_dm_pm_cfg[BTA_DM_NUM_PM_ENTRY + 1]
|
||||
{BTA_ID_JV, BTA_APP_ID_1, 2}, /* app BTA_JV_PM_ID_1, reuse ftc spec table */
|
||||
{BTA_ID_JV, BTA_ALL_APP_ID, 3}, /* reuse fts spec table */
|
||||
{BTA_ID_HS, BTA_ALL_APP_ID, 4}, /* HS spec table */
|
||||
{BTA_ID_AVK, BTA_ALL_APP_ID, 5} /* avk spec table */
|
||||
{BTA_ID_AVK, BTA_ALL_APP_ID, 5}, /* avk spec table */
|
||||
{BTA_ID_HD, BTA_ALL_APP_ID, 6}, /* hd spec table */
|
||||
{BTA_ID_HH, BTA_ALL_APP_ID, 7} /* hh spec table */
|
||||
#if BLE_INCLUDED == TRUE
|
||||
, {BTA_ID_GATTC, BTA_ALL_APP_ID, 6} /* gattc spec table */
|
||||
, {BTA_ID_GATTS, BTA_ALL_APP_ID, 7} /* gatts spec table */
|
||||
, {BTA_ID_GATTC, BTA_ALL_APP_ID, 8} /* gattc spec table */
|
||||
, {BTA_ID_GATTS, BTA_ALL_APP_ID, 9} /* gatts spec table */
|
||||
#endif
|
||||
};
|
||||
|
||||
@ -254,10 +256,48 @@ tBTA_DM_PM_TYPE_QUALIFIER tBTA_DM_PM_SPEC bta_dm_pm_spec[BTA_DM_NUM_PM_SPEC] = {
|
||||
{{BTA_DM_PM_ACTIVE, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* busy */
|
||||
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}} /* mode change retry */
|
||||
}
|
||||
},
|
||||
|
||||
/* HD : 6 */
|
||||
{
|
||||
(BTA_DM_PM_SNIFF | BTA_DM_PM_PARK), /* allow park & sniff */
|
||||
#if (BTM_SSR_INCLUDED == TRUE)
|
||||
(BTA_DM_PM_SSR3), /* the SSR entry */
|
||||
#endif
|
||||
{
|
||||
{{BTA_DM_PM_SNIFF_HD_ACTIVE_IDX, 5000 + BTA_DM_PM_SPEC_TO_OFFSET}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn open sniff */
|
||||
{{BTA_DM_PM_NO_PREF, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn close */
|
||||
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app open */
|
||||
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app close */
|
||||
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco open */
|
||||
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco close */
|
||||
{{BTA_DM_PM_SNIFF_HD_IDLE_IDX, 5000 + BTA_DM_PM_SPEC_TO_OFFSET}, {BTA_DM_PM_NO_ACTION, 0}}, /* idle */
|
||||
{{BTA_DM_PM_SNIFF_HD_ACTIVE_IDX, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* busy */
|
||||
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}} /* mode change retry */
|
||||
}
|
||||
},
|
||||
|
||||
/* HH : 7 */
|
||||
{
|
||||
(BTA_DM_PM_SNIFF | BTA_DM_PM_PARK), /* allow park & sniff */
|
||||
#if (BTM_SSR_INCLUDED == TRUE)
|
||||
(BTA_DM_PM_SSR1), /* the SSR entry */
|
||||
#endif
|
||||
{
|
||||
{{BTA_DM_PM_SNIFF_HH_OPEN_IDX, BTA_DM_PM_HH_OPEN_DELAY + BTA_DM_PM_SPEC_TO_OFFSET}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn open sniff */
|
||||
{{BTA_DM_PM_NO_PREF, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* conn close */
|
||||
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app open */
|
||||
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app close */
|
||||
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco open */
|
||||
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* sco close, used for HH suspend */
|
||||
{{BTA_DM_PM_SNIFF_HH_IDLE_IDX, BTA_DM_PM_HH_IDLE_DELAY + BTA_DM_PM_SPEC_TO_OFFSET}, {BTA_DM_PM_NO_ACTION, 0}}, /* idle */
|
||||
{{BTA_DM_PM_SNIFF_HH_ACTIVE_IDX, BTA_DM_PM_HH_ACTIVE_DELAY + BTA_DM_PM_SPEC_TO_OFFSET}, {BTA_DM_PM_NO_ACTION, 0}}, /* busy */
|
||||
{{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}} /* mode change retry */
|
||||
}
|
||||
}
|
||||
|
||||
#if BLE_INCLUDED == TRUE
|
||||
/* GATTC : 6 */
|
||||
/* GATTC : 8 */
|
||||
, {
|
||||
(BTA_DM_PM_SNIFF | BTA_DM_PM_PARK), /* allow park & sniff */
|
||||
#if (BTM_SSR_INCLUDED == TRUE)
|
||||
@ -278,7 +318,7 @@ tBTA_DM_PM_TYPE_QUALIFIER tBTA_DM_PM_SPEC bta_dm_pm_spec[BTA_DM_NUM_PM_SPEC] = {
|
||||
{{BTA_DM_PM_RETRY, 5000 + BTA_DM_PM_SPEC_TO_OFFSET}, {BTA_DM_PM_NO_ACTION, 0}} /* mode change retry */
|
||||
}
|
||||
}
|
||||
/* GATTS : 7 */
|
||||
/* GATTS : 9 */
|
||||
, {
|
||||
(BTA_DM_PM_SNIFF | BTA_DM_PM_PARK), /* allow park & sniff */
|
||||
#if (BTM_SSR_INCLUDED == TRUE)
|
||||
@ -372,7 +412,7 @@ tBTA_DM_SSR_SPEC bta_dm_ssr_spec[] = {
|
||||
seting default max latency and min remote timeout as 0,
|
||||
and always read individual device preference from HH module */
|
||||
{1200, 2, 2}, /* BTA_DM_PM_SSR2 - others (as long as sniff is allowed)*/
|
||||
{360, 160, 2} /* BTA_DM_PM_SSR3 - HD */
|
||||
{360, 160, 1600} /* BTA_DM_PM_SSR3 - HD */
|
||||
};
|
||||
|
||||
tBTA_DM_SSR_SPEC *const p_bta_dm_ssr_spec = (tBTA_DM_SSR_SPEC *) &bta_dm_ssr_spec;
|
||||
|
@ -26,6 +26,7 @@
|
||||
|
||||
#include "common/bt_target.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "bta/bta_sys.h"
|
||||
#if (BLE_INCLUDED == TRUE && (defined BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE))
|
||||
#include "bta/bta_gatt_api.h"
|
||||
#endif
|
||||
@ -1596,6 +1597,11 @@ extern void bta_dm_ble_get_energy_info(tBTA_DM_MSG *p_data);
|
||||
extern void bta_dm_set_encryption(tBTA_DM_MSG *p_data);
|
||||
extern void bta_dm_confirm(tBTA_DM_MSG *p_data);
|
||||
extern void bta_dm_key_req(tBTA_DM_MSG *p_data);
|
||||
|
||||
#if (BTA_HD_INCLUDED == TRUE)
|
||||
extern BOOLEAN bta_dm_check_if_only_hd_connected(BD_ADDR peer_addr);
|
||||
#endif /* BTA_HD_INCLUDED */
|
||||
|
||||
#if (BTM_OOB_INCLUDED == TRUE)
|
||||
extern void bta_dm_loc_oob(tBTA_DM_MSG *p_data);
|
||||
extern void bta_dm_oob_reply(tBTA_DM_MSG *p_data);
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include "gatt_int.h"
|
||||
#include "osi/allocator.h"
|
||||
#include "osi/mutex.h"
|
||||
#include "bta_hh_int.h"
|
||||
|
||||
#if (defined BTA_HH_LE_INCLUDED && BTA_HH_LE_INCLUDED == TRUE)
|
||||
#include "bta_hh_int.h"
|
||||
@ -304,7 +305,10 @@ void bta_gattc_deregister(tBTA_GATTC_CB *p_cb, tBTA_GATTC_RCB *p_clreg)
|
||||
bta_gattc_deregister_cmpl(p_clreg);
|
||||
}
|
||||
} else {
|
||||
APPL_TRACE_ERROR("bta_gattc_deregister Deregister Failedm unknown client cif");
|
||||
APPL_TRACE_ERROR("Deregister Failed unknown client cif");
|
||||
#if defined(BTA_HH_INCLUDED) && (BTA_HH_INCLUDED == TRUE)
|
||||
bta_hh_cleanup_disable(BTA_HH_OK);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
/*******************************************************************************
|
||||
|
774
components/bt/host/bluedroid/bta/hd/bta_hd_act.c
Normal file
774
components/bt/host/bluedroid/bta/hd/bta_hd_act.c
Normal file
@ -0,0 +1,774 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
* Copyright (C) 2005-2012 Broadcom Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************/
|
||||
/******************************************************************************
|
||||
*
|
||||
* This file contains the HID device action functions.
|
||||
*
|
||||
******************************************************************************/
|
||||
#include "common/bt_target.h"
|
||||
|
||||
#if defined(BTA_HD_INCLUDED) && (BTA_HD_INCLUDED == TRUE)
|
||||
|
||||
#include "bta/bta_sys.h"
|
||||
#include "bta_hd_int.h"
|
||||
#include "osi/allocator.h"
|
||||
#include "osi/osi.h"
|
||||
#include "stack/btm_api.h"
|
||||
#include <string.h>
|
||||
|
||||
static void bta_hd_cback(BD_ADDR bd_addr, uint8_t event, uint32_t data, BT_HDR *pdata);
|
||||
|
||||
static bool check_descriptor(uint8_t *data, uint16_t length, bool *has_report_id)
|
||||
{
|
||||
uint8_t *ptr = data;
|
||||
*has_report_id = FALSE;
|
||||
while (ptr < data + length) {
|
||||
uint8_t item = *ptr++;
|
||||
switch (item) {
|
||||
case 0xfe: // long item indicator
|
||||
if (ptr < data + length) {
|
||||
ptr += ((*ptr) + 2);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 0x85: // Report ID
|
||||
*has_report_id = TRUE;
|
||||
default:
|
||||
ptr += (item & 0x03);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (ptr == data + length);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function bta_hd_api_enable
|
||||
*
|
||||
* Description Enables HID device
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
void bta_hd_api_enable(tBTA_HD_DATA *p_data)
|
||||
{
|
||||
tBTA_HD_STATUS status = BTA_HD_ERROR;
|
||||
tHID_STATUS ret;
|
||||
|
||||
APPL_TRACE_API("%s", __func__);
|
||||
|
||||
HID_DevInit();
|
||||
|
||||
memset(&bta_hd_cb, 0, sizeof(tBTA_HD_CB));
|
||||
|
||||
HID_DevSetSecurityLevel(BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT);
|
||||
/* store parameters */
|
||||
bta_hd_cb.p_cback = p_data->api_enable.p_cback;
|
||||
|
||||
ret = HID_DevRegister(bta_hd_cback);
|
||||
if (ret == HID_SUCCESS) {
|
||||
status = BTA_HD_OK;
|
||||
} else {
|
||||
APPL_TRACE_ERROR("%s: Failed to register HID device (%d)", __func__, ret);
|
||||
}
|
||||
|
||||
/* signal BTA call back event */
|
||||
(*bta_hd_cb.p_cback)(BTA_HD_ENABLE_EVT, (tBTA_HD *)&status);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function bta_hd_api_disable
|
||||
*
|
||||
* Description Disables HID device
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
void bta_hd_api_disable(void)
|
||||
{
|
||||
tBTA_HD_STATUS status = BTA_HD_ERROR;
|
||||
tHID_STATUS ret;
|
||||
|
||||
APPL_TRACE_API("%s", __func__);
|
||||
|
||||
/* service is not enabled */
|
||||
if (bta_hd_cb.p_cback == NULL)
|
||||
return;
|
||||
|
||||
/* Remove service record */
|
||||
if (bta_hd_cb.sdp_handle != 0) {
|
||||
SDP_DeleteRecord(bta_hd_cb.sdp_handle);
|
||||
bta_sys_remove_uuid(UUID_SERVCLASS_HUMAN_INTERFACE);
|
||||
}
|
||||
|
||||
/* Deregister with lower layer */
|
||||
ret = HID_DevDeregister();
|
||||
if (ret == HID_SUCCESS) {
|
||||
status = BTA_HD_OK;
|
||||
} else {
|
||||
APPL_TRACE_ERROR("%s: Failed to deregister HID device (%d)", __func__, ret);
|
||||
}
|
||||
|
||||
(*bta_hd_cb.p_cback)(BTA_HD_DISABLE_EVT, (tBTA_HD *)&status);
|
||||
|
||||
memset(&bta_hd_cb, 0, sizeof(tBTA_HD_CB));
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function bta_hd_register_act
|
||||
*
|
||||
* Description Registers SDP record
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
void bta_hd_register_act(tBTA_HD_DATA *p_data)
|
||||
{
|
||||
tBTA_HD ret;
|
||||
tBTA_HD_REGISTER_APP *p_app_data = (tBTA_HD_REGISTER_APP *)p_data;
|
||||
bool use_report_id = FALSE;
|
||||
|
||||
APPL_TRACE_API("%s", __func__);
|
||||
|
||||
ret.reg_status.in_use = FALSE;
|
||||
|
||||
/* Check if len doesn't exceed BTA_HD_APP_DESCRIPTOR_LEN and descriptor
|
||||
* itself is well-formed. Also check if descriptor has Report Id item so we
|
||||
* know if report will have prefix or not. */
|
||||
if (p_app_data->d_len > BTA_HD_APP_DESCRIPTOR_LEN ||
|
||||
!check_descriptor(p_app_data->d_data, p_app_data->d_len, &use_report_id)) {
|
||||
APPL_TRACE_ERROR("%s: Descriptor is too long or malformed", __func__);
|
||||
ret.reg_status.status = BTA_HD_ERROR;
|
||||
(*bta_hd_cb.p_cback)(BTA_HD_REGISTER_APP_EVT, &ret);
|
||||
return;
|
||||
}
|
||||
|
||||
ret.reg_status.status = BTA_HD_OK;
|
||||
|
||||
/* Remove old record if for some reason it's already registered */
|
||||
if (bta_hd_cb.sdp_handle != 0) {
|
||||
SDP_DeleteRecord(bta_hd_cb.sdp_handle);
|
||||
}
|
||||
|
||||
bta_hd_cb.use_report_id = use_report_id;
|
||||
bta_hd_cb.sdp_handle = SDP_CreateRecord();
|
||||
HID_DevAddRecord(bta_hd_cb.sdp_handle, p_app_data->name, p_app_data->description, p_app_data->provider,
|
||||
p_app_data->subclass, p_app_data->d_len, p_app_data->d_data);
|
||||
bta_sys_add_uuid(UUID_SERVCLASS_HUMAN_INTERFACE);
|
||||
|
||||
HID_DevSetIncomingQos(p_app_data->in_qos.service_type, p_app_data->in_qos.token_rate,
|
||||
p_app_data->in_qos.token_bucket_size, p_app_data->in_qos.peak_bandwidth,
|
||||
p_app_data->in_qos.access_latency, p_app_data->in_qos.delay_variation);
|
||||
|
||||
HID_DevSetOutgoingQos(p_app_data->out_qos.service_type, p_app_data->out_qos.token_rate,
|
||||
p_app_data->out_qos.token_bucket_size, p_app_data->out_qos.peak_bandwidth,
|
||||
p_app_data->out_qos.access_latency, p_app_data->out_qos.delay_variation);
|
||||
|
||||
// application is registered so we can accept incoming connections
|
||||
HID_DevSetIncomingPolicy(TRUE);
|
||||
|
||||
if (HID_DevGetDevice(&ret.reg_status.bda) == HID_SUCCESS) {
|
||||
ret.reg_status.in_use = TRUE;
|
||||
}
|
||||
|
||||
(*bta_hd_cb.p_cback)(BTA_HD_REGISTER_APP_EVT, &ret);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function bta_hd_unregister_act
|
||||
*
|
||||
* Description Unregisters SDP record
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
void bta_hd_unregister_act(UNUSED_ATTR tBTA_HD_DATA *p_data)
|
||||
{
|
||||
tBTA_HD_STATUS status = BTA_HD_OK;
|
||||
|
||||
APPL_TRACE_API("%s", __func__);
|
||||
|
||||
// application is no longer registered so we do not want incoming connections
|
||||
HID_DevSetIncomingPolicy(FALSE);
|
||||
|
||||
if (bta_hd_cb.sdp_handle != 0) {
|
||||
SDP_DeleteRecord(bta_hd_cb.sdp_handle);
|
||||
}
|
||||
|
||||
bta_hd_cb.sdp_handle = 0;
|
||||
bta_sys_remove_uuid(UUID_SERVCLASS_HUMAN_INTERFACE);
|
||||
|
||||
(*bta_hd_cb.p_cback)(BTA_HD_UNREGISTER_APP_EVT, (tBTA_HD *)&status);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function bta_hd_unregister2_act
|
||||
*
|
||||
* Description
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
void bta_hd_unregister2_act(tBTA_HD_DATA *p_data)
|
||||
{
|
||||
APPL_TRACE_API("%s", __func__);
|
||||
|
||||
// close first
|
||||
bta_hd_close_act(p_data);
|
||||
|
||||
// then unregister
|
||||
bta_hd_unregister_act(p_data);
|
||||
|
||||
if (bta_hd_cb.disable_w4_close) {
|
||||
bta_hd_api_disable();
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function bta_hd_connect_act
|
||||
*
|
||||
* Description Connect to device (must be virtually plugged)
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
extern void bta_hd_connect_act(tBTA_HD_DATA *p_data)
|
||||
{
|
||||
tHID_STATUS ret;
|
||||
tBTA_HD_DEVICE_CTRL *p_ctrl = (tBTA_HD_DEVICE_CTRL *)p_data;
|
||||
tBTA_HD cback_data;
|
||||
|
||||
APPL_TRACE_API("%s", __func__);
|
||||
do {
|
||||
ret = HID_DevPlugDevice(p_ctrl->addr);
|
||||
if (ret != HID_SUCCESS) {
|
||||
APPL_TRACE_WARNING("%s: HID_DevPlugDevice returned %d", __func__, ret);
|
||||
return;
|
||||
}
|
||||
|
||||
ret = HID_DevConnect();
|
||||
if (ret != HID_SUCCESS) {
|
||||
APPL_TRACE_WARNING("%s: HID_DevConnect returned %d", __func__, ret);
|
||||
return;
|
||||
}
|
||||
} while (0);
|
||||
|
||||
bdcpy(cback_data.conn.bda, p_ctrl->addr);
|
||||
cback_data.conn.status = (ret == HID_SUCCESS ? BTA_HD_OK : BTA_HD_ERROR);
|
||||
cback_data.conn.conn_status = BTA_HD_CONN_STATE_CONNECTING;
|
||||
bta_hd_cb.p_cback(BTA_HD_OPEN_EVT, &cback_data);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function bta_hd_disconnect_act
|
||||
*
|
||||
* Description Disconnect from device
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
extern void bta_hd_disconnect_act(UNUSED_ATTR tBTA_HD_DATA *p_data)
|
||||
{
|
||||
tHID_STATUS ret;
|
||||
tBTA_HD cback_data;
|
||||
|
||||
APPL_TRACE_API("%s", __func__);
|
||||
|
||||
ret = HID_DevDisconnect();
|
||||
|
||||
if (ret != HID_SUCCESS) {
|
||||
APPL_TRACE_WARNING("%s: HID_DevDisconnect returned %d", __func__, ret);
|
||||
return;
|
||||
}
|
||||
|
||||
if (HID_DevGetDevice(&cback_data.conn.bda) == HID_SUCCESS) {
|
||||
cback_data.conn.status = BTA_HD_OK;
|
||||
cback_data.conn.conn_status = BTA_HD_CONN_STATE_DISCONNECTING;
|
||||
bta_hd_cb.p_cback(BTA_HD_CLOSE_EVT, &cback_data);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function bta_hd_add_device_act
|
||||
*
|
||||
* Description
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
extern void bta_hd_add_device_act(tBTA_HD_DATA *p_data)
|
||||
{
|
||||
tBTA_HD_DEVICE_CTRL *p_ctrl = (tBTA_HD_DEVICE_CTRL *)p_data;
|
||||
|
||||
APPL_TRACE_API("%s", __func__);
|
||||
|
||||
HID_DevPlugDevice(p_ctrl->addr);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function bta_hd_remove_device_act
|
||||
*
|
||||
* Description
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
extern void bta_hd_remove_device_act(tBTA_HD_DATA *p_data)
|
||||
{
|
||||
tBTA_HD_DEVICE_CTRL *p_ctrl = (tBTA_HD_DEVICE_CTRL *)p_data;
|
||||
|
||||
APPL_TRACE_API("%s", __func__);
|
||||
|
||||
HID_DevUnplugDevice(p_ctrl->addr);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function bta_hd_send_report_act
|
||||
*
|
||||
* Description Sends report
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
extern void bta_hd_send_report_act(tBTA_HD_DATA *p_data)
|
||||
{
|
||||
tBTA_HD_SEND_REPORT *p_report = (tBTA_HD_SEND_REPORT *)p_data;
|
||||
uint8_t channel;
|
||||
uint8_t report_id;
|
||||
tBTA_HD cback_data;
|
||||
tHID_STATUS ret;
|
||||
|
||||
APPL_TRACE_VERBOSE("%s", __func__);
|
||||
|
||||
channel = p_report->use_intr ? HID_CHANNEL_INTR : HID_CHANNEL_CTRL;
|
||||
report_id = (bta_hd_cb.use_report_id || bta_hd_cb.boot_mode) ? p_report->id : 0x00;
|
||||
|
||||
ret = HID_DevSendReport(channel, p_report->type, report_id, p_report->len, p_report->data);
|
||||
|
||||
/* trigger PM */
|
||||
bta_sys_busy(BTA_ID_HD, 1, bta_hd_cb.bd_addr);
|
||||
bta_sys_idle(BTA_ID_HD, 1, bta_hd_cb.bd_addr);
|
||||
|
||||
cback_data.send_report.status = (ret == HID_SUCCESS ? BTA_HD_OK : BTA_HD_ERROR);
|
||||
cback_data.send_report.reason = ret;
|
||||
cback_data.send_report.report_id = report_id;
|
||||
cback_data.send_report.report_type = p_report->type;
|
||||
bta_hd_cb.p_cback(BTA_HD_SEND_REPORT_EVT, &cback_data);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function bta_hd_report_error_act
|
||||
*
|
||||
* Description
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
extern void bta_hd_report_error_act(tBTA_HD_DATA *p_data)
|
||||
{
|
||||
tBTA_HD_REPORT_ERR *p_report = (tBTA_HD_REPORT_ERR *)p_data;
|
||||
tHID_STATUS ret;
|
||||
tBTA_HD cback_data;
|
||||
|
||||
APPL_TRACE_API("%s: error = %d", __func__, p_report->error);
|
||||
|
||||
ret = HID_DevReportError(p_report->error);
|
||||
|
||||
if (ret != HID_SUCCESS) {
|
||||
APPL_TRACE_WARNING("%s: HID_DevReportError returned %d", __func__, ret);
|
||||
}
|
||||
|
||||
cback_data.report_err.status = (ret == HID_SUCCESS ? BTA_HD_OK : BTA_HD_ERROR);
|
||||
cback_data.report_err.reason = ret;
|
||||
bta_hd_cb.p_cback(BTA_HD_REPORT_ERR_EVT, &cback_data);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function bta_hd_vc_unplug_act
|
||||
*
|
||||
* Description Sends Virtual Cable Unplug
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
extern void bta_hd_vc_unplug_act(UNUSED_ATTR tBTA_HD_DATA *p_data)
|
||||
{
|
||||
tHID_STATUS ret;
|
||||
|
||||
APPL_TRACE_API("%s", __func__);
|
||||
|
||||
bta_hd_cb.vc_unplug = TRUE;
|
||||
ret = HID_DevVirtualCableUnplug();
|
||||
|
||||
if (ret != HID_SUCCESS) {
|
||||
APPL_TRACE_WARNING("%s: HID_DevVirtualCableUnplug returned %d", __func__, ret);
|
||||
}
|
||||
|
||||
/* trigger PM */
|
||||
bta_sys_busy(BTA_ID_HD, 1, bta_hd_cb.bd_addr);
|
||||
bta_sys_idle(BTA_ID_HD, 1, bta_hd_cb.bd_addr);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function bta_hd_open_act
|
||||
*
|
||||
* Description
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
extern void bta_hd_open_act(tBTA_HD_DATA *p_data)
|
||||
{
|
||||
tBTA_HD_CBACK_DATA *p_cback = (tBTA_HD_CBACK_DATA *)p_data;
|
||||
tBTA_HD cback_data;
|
||||
|
||||
APPL_TRACE_API("%s", __func__);
|
||||
|
||||
HID_DevPlugDevice(p_cback->addr);
|
||||
bta_sys_conn_open(BTA_ID_HD, 1, p_cback->addr);
|
||||
|
||||
bdcpy(cback_data.conn.bda, p_cback->addr);
|
||||
bdcpy(bta_hd_cb.bd_addr, p_cback->addr);
|
||||
cback_data.conn.status = BTA_HD_OK;
|
||||
cback_data.conn.conn_status = BTA_HD_CONN_STATE_CONNECTED;
|
||||
bta_hd_cb.p_cback(BTA_HD_OPEN_EVT, &cback_data);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function bta_hd_close_act
|
||||
*
|
||||
* Description
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
extern void bta_hd_close_act(tBTA_HD_DATA *p_data)
|
||||
{
|
||||
tBTA_HD_CBACK_DATA *p_cback = (tBTA_HD_CBACK_DATA *)p_data;
|
||||
tBTA_HD cback_data;
|
||||
tBTA_HD_EVT cback_event = BTA_HD_CLOSE_EVT;
|
||||
|
||||
APPL_TRACE_API("%s", __func__);
|
||||
|
||||
bta_sys_conn_close(BTA_ID_HD, 1, p_cback->addr);
|
||||
|
||||
if (bta_hd_cb.vc_unplug) {
|
||||
bta_hd_cb.vc_unplug = FALSE;
|
||||
HID_DevUnplugDevice(p_cback->addr);
|
||||
cback_event = BTA_HD_VC_UNPLUG_EVT;
|
||||
}
|
||||
|
||||
bdcpy(cback_data.conn.bda, p_cback->addr);
|
||||
memset(bta_hd_cb.bd_addr, 0, sizeof(BD_ADDR));
|
||||
cback_data.conn.status = BTA_HD_OK;
|
||||
cback_data.conn.conn_status = BTA_HD_CONN_STATE_DISCONNECTED;
|
||||
bta_hd_cb.p_cback(cback_event, &cback_data);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function bta_hd_intr_data_act
|
||||
*
|
||||
* Description Handles incoming DATA request on intr
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
extern void bta_hd_intr_data_act(tBTA_HD_DATA *p_data)
|
||||
{
|
||||
tBTA_HD_CBACK_DATA *p_cback = (tBTA_HD_CBACK_DATA *)p_data;
|
||||
BT_HDR *p_msg = p_cback->p_data;
|
||||
uint16_t len = p_msg->len;
|
||||
uint8_t *p_buf = (uint8_t *)(p_msg + 1) + p_msg->offset;
|
||||
tBTA_HD_INTR_DATA ret;
|
||||
|
||||
APPL_TRACE_API("%s", __func__);
|
||||
|
||||
if (bta_hd_cb.use_report_id || bta_hd_cb.boot_mode) {
|
||||
ret.report_id = *p_buf;
|
||||
len--;
|
||||
p_buf++;
|
||||
} else {
|
||||
ret.report_id = 0;
|
||||
}
|
||||
|
||||
ret.len = len;
|
||||
ret.p_data = p_buf;
|
||||
(*bta_hd_cb.p_cback)(BTA_HD_INTR_DATA_EVT, (tBTA_HD *)&ret);
|
||||
if (p_msg) {
|
||||
osi_free(p_msg);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function bta_hd_get_report_act
|
||||
*
|
||||
* Description Handles incoming GET_REPORT request
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
extern void bta_hd_get_report_act(tBTA_HD_DATA *p_data)
|
||||
{
|
||||
tBTA_HD_CBACK_DATA *p_cback = (tBTA_HD_CBACK_DATA *)p_data;
|
||||
bool rep_size_follows = p_cback->data;
|
||||
BT_HDR *p_msg = p_cback->p_data;
|
||||
uint8_t *p_buf = (uint8_t *)(p_msg + 1) + p_msg->offset;
|
||||
tBTA_HD_GET_REPORT ret = {0, 0, 0};
|
||||
uint16_t remaining_len = p_msg->len;
|
||||
|
||||
APPL_TRACE_API("%s", __func__);
|
||||
if (remaining_len < 1) {
|
||||
APPL_TRACE_ERROR("%s invalid data, remaining_len:%d", __func__, remaining_len);
|
||||
return;
|
||||
}
|
||||
|
||||
ret.report_type = *p_buf & HID_PAR_REP_TYPE_MASK;
|
||||
p_buf++;
|
||||
remaining_len--;
|
||||
|
||||
if (bta_hd_cb.use_report_id) {
|
||||
if (remaining_len < 1) {
|
||||
APPL_TRACE_ERROR("%s invalid data, remaining_len:%d", __func__, remaining_len);
|
||||
return;
|
||||
}
|
||||
ret.report_id = *p_buf;
|
||||
p_buf++;
|
||||
remaining_len--;
|
||||
}
|
||||
|
||||
if (rep_size_follows) {
|
||||
if (remaining_len < 2) {
|
||||
APPL_TRACE_ERROR("%s invalid data, remaining_len:%d", __func__, remaining_len);
|
||||
return;
|
||||
}
|
||||
ret.buffer_size = *p_buf | (*(p_buf + 1) << 8);
|
||||
}
|
||||
|
||||
(*bta_hd_cb.p_cback)(BTA_HD_GET_REPORT_EVT, (tBTA_HD *)&ret);
|
||||
if (p_msg) {
|
||||
osi_free(p_msg);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function bta_hd_set_report_act
|
||||
*
|
||||
* Description Handles incoming SET_REPORT request
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
extern void bta_hd_set_report_act(tBTA_HD_DATA *p_data)
|
||||
{
|
||||
tBTA_HD_CBACK_DATA *p_cback = (tBTA_HD_CBACK_DATA *)p_data;
|
||||
BT_HDR *p_msg = p_cback->p_data;
|
||||
uint16_t len = p_msg->len;
|
||||
uint8_t *p_buf = (uint8_t *)(p_msg + 1) + p_msg->offset;
|
||||
tBTA_HD_SET_REPORT ret = {0, 0, 0, NULL};
|
||||
|
||||
APPL_TRACE_API("%s", __func__);
|
||||
|
||||
ret.report_type = *p_buf & HID_PAR_REP_TYPE_MASK;
|
||||
p_buf++;
|
||||
len--;
|
||||
|
||||
if (bta_hd_cb.use_report_id || bta_hd_cb.boot_mode) {
|
||||
ret.report_id = *p_buf;
|
||||
len--;
|
||||
p_buf++;
|
||||
} else {
|
||||
ret.report_id = 0;
|
||||
}
|
||||
|
||||
ret.len = len;
|
||||
ret.p_data = p_buf;
|
||||
(*bta_hd_cb.p_cback)(BTA_HD_SET_REPORT_EVT, (tBTA_HD *)&ret);
|
||||
if (p_msg) {
|
||||
osi_free(p_msg);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function bta_hd_set_protocol_act
|
||||
*
|
||||
* Description
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
extern void bta_hd_set_protocol_act(tBTA_HD_DATA *p_data)
|
||||
{
|
||||
tBTA_HD_CBACK_DATA *p_cback = (tBTA_HD_CBACK_DATA *)p_data;
|
||||
tBTA_HD cback_data;
|
||||
|
||||
APPL_TRACE_API("%s", __func__);
|
||||
|
||||
bta_hd_cb.boot_mode = (p_cback->data == HID_PAR_PROTOCOL_BOOT_MODE);
|
||||
cback_data.set_protocol = p_cback->data;
|
||||
|
||||
(*bta_hd_cb.p_cback)(BTA_HD_SET_PROTOCOL_EVT, &cback_data);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function bta_hd_vc_unplug_done_act
|
||||
*
|
||||
* Description
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
extern void bta_hd_vc_unplug_done_act(tBTA_HD_DATA *p_data)
|
||||
{
|
||||
tBTA_HD_CBACK_DATA *p_cback = (tBTA_HD_CBACK_DATA *)p_data;
|
||||
tBTA_HD cback_data;
|
||||
|
||||
APPL_TRACE_API("%s", __func__);
|
||||
|
||||
bta_sys_conn_close(BTA_ID_HD, 1, p_cback->addr);
|
||||
|
||||
HID_DevUnplugDevice(p_cback->addr);
|
||||
|
||||
bdcpy(cback_data.conn.bda, p_cback->addr);
|
||||
bdcpy(bta_hd_cb.bd_addr, p_cback->addr);
|
||||
cback_data.conn.status = BTA_HD_OK;
|
||||
cback_data.conn.conn_status = BTA_HD_CONN_STATE_DISCONNECTED;
|
||||
(*bta_hd_cb.p_cback)(BTA_HD_VC_UNPLUG_EVT, &cback_data);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function bta_hd_suspend_act
|
||||
*
|
||||
* Description
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
extern void bta_hd_suspend_act(tBTA_HD_DATA *p_data)
|
||||
{
|
||||
tBTA_HD_CBACK_DATA *p_cback = (tBTA_HD_CBACK_DATA *)p_data;
|
||||
|
||||
APPL_TRACE_API("%s", __func__);
|
||||
|
||||
bta_sys_idle(BTA_ID_HD, 1, p_cback->addr);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function bta_hd_exit_suspend_act
|
||||
*
|
||||
* Description
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
extern void bta_hd_exit_suspend_act(tBTA_HD_DATA *p_data)
|
||||
{
|
||||
tBTA_HD_CBACK_DATA *p_cback = (tBTA_HD_CBACK_DATA *)p_data;
|
||||
|
||||
APPL_TRACE_API("%s", __func__);
|
||||
|
||||
bta_sys_busy(BTA_ID_HD, 1, p_cback->addr);
|
||||
bta_sys_idle(BTA_ID_HD, 1, p_cback->addr);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function bta_hd_cback
|
||||
*
|
||||
* Description BTA HD callback function
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
static void bta_hd_cback(BD_ADDR bd_addr, uint8_t event, uint32_t data, BT_HDR *pdata)
|
||||
{
|
||||
tBTA_HD_CBACK_DATA *p_buf = NULL;
|
||||
uint16_t sm_event = BTA_HD_INVALID_EVT;
|
||||
|
||||
APPL_TRACE_API("%s: event=%d", __func__, event);
|
||||
|
||||
switch (event) {
|
||||
case HID_DHOST_EVT_OPEN:
|
||||
sm_event = BTA_HD_INT_OPEN_EVT;
|
||||
break;
|
||||
|
||||
case HID_DHOST_EVT_CLOSE:
|
||||
sm_event = BTA_HD_INT_CLOSE_EVT;
|
||||
break;
|
||||
|
||||
case HID_DHOST_EVT_GET_REPORT:
|
||||
sm_event = BTA_HD_INT_GET_REPORT_EVT;
|
||||
break;
|
||||
|
||||
case HID_DHOST_EVT_SET_REPORT:
|
||||
sm_event = BTA_HD_INT_SET_REPORT_EVT;
|
||||
break;
|
||||
|
||||
case HID_DHOST_EVT_SET_PROTOCOL:
|
||||
sm_event = BTA_HD_INT_SET_PROTOCOL_EVT;
|
||||
break;
|
||||
|
||||
case HID_DHOST_EVT_INTR_DATA:
|
||||
sm_event = BTA_HD_INT_INTR_DATA_EVT;
|
||||
break;
|
||||
|
||||
case HID_DHOST_EVT_VC_UNPLUG:
|
||||
sm_event = BTA_HD_INT_VC_UNPLUG_EVT;
|
||||
break;
|
||||
|
||||
case HID_DHOST_EVT_SUSPEND:
|
||||
sm_event = BTA_HD_INT_SUSPEND_EVT;
|
||||
break;
|
||||
|
||||
case HID_DHOST_EVT_EXIT_SUSPEND:
|
||||
sm_event = BTA_HD_INT_EXIT_SUSPEND_EVT;
|
||||
break;
|
||||
}
|
||||
|
||||
if (sm_event != BTA_HD_INVALID_EVT &&
|
||||
(p_buf = (tBTA_HD_CBACK_DATA *)osi_malloc(sizeof(tBTA_HD_CBACK_DATA) + sizeof(BT_HDR))) != NULL) {
|
||||
p_buf->hdr.event = sm_event;
|
||||
bdcpy(p_buf->addr, bd_addr);
|
||||
p_buf->data = data;
|
||||
p_buf->p_data = pdata;
|
||||
|
||||
bta_sys_sendmsg(p_buf);
|
||||
}
|
||||
}
|
||||
#endif /* BTA_HD_INCLUDED */
|
287
components/bt/host/bluedroid/bta/hd/bta_hd_api.c
Normal file
287
components/bt/host/bluedroid/bta/hd/bta_hd_api.c
Normal file
@ -0,0 +1,287 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
* Copyright (C) 2005-2012 Broadcom Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************/
|
||||
/******************************************************************************
|
||||
*
|
||||
* This file contains the HID DEVICE API in the subsystem of BTA.
|
||||
*
|
||||
******************************************************************************/
|
||||
#include "common/bt_target.h"
|
||||
|
||||
#if defined(BTA_HD_INCLUDED) && (BTA_HD_INCLUDED == TRUE)
|
||||
|
||||
#include "bta/bta_hd_api.h"
|
||||
#include "bta_hd_int.h"
|
||||
#include "osi/allocator.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/*****************************************************************************
|
||||
* Constants
|
||||
****************************************************************************/
|
||||
static const tBTA_SYS_REG bta_hd_reg = {bta_hd_hdl_event, BTA_HdDisable};
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function BTA_HdEnable
|
||||
*
|
||||
* Description Enables HID device
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
void BTA_HdEnable(tBTA_HD_CBACK *p_cback)
|
||||
{
|
||||
tBTA_HD_API_ENABLE *p_buf;
|
||||
APPL_TRACE_API("%s", __func__);
|
||||
bta_sys_register(BTA_ID_HD, &bta_hd_reg);
|
||||
p_buf = (tBTA_HD_API_ENABLE *)osi_malloc((uint16_t)sizeof(tBTA_HD_API_ENABLE));
|
||||
if (p_buf != NULL) {
|
||||
memset(p_buf, 0, sizeof(tBTA_HD_API_ENABLE));
|
||||
p_buf->hdr.event = BTA_HD_API_ENABLE_EVT;
|
||||
p_buf->p_cback = p_cback;
|
||||
bta_sys_sendmsg(p_buf);
|
||||
}
|
||||
}
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function BTA_HdDisable
|
||||
*
|
||||
* Description Disables HID device.
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
void BTA_HdDisable(void)
|
||||
{
|
||||
BT_HDR *p_buf;
|
||||
APPL_TRACE_API("%s", __func__);
|
||||
bta_sys_deregister(BTA_ID_HD);
|
||||
if ((p_buf = (BT_HDR *)osi_malloc(sizeof(BT_HDR))) != NULL) {
|
||||
p_buf->event = BTA_HD_API_DISABLE_EVT;
|
||||
bta_sys_sendmsg(p_buf);
|
||||
}
|
||||
}
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function BTA_HdRegisterApp
|
||||
*
|
||||
* Description This function is called when application should be
|
||||
*registered
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
extern void BTA_HdRegisterApp(tBTA_HD_APP_INFO *p_app_info, tBTA_HD_QOS_INFO *p_in_qos, tBTA_HD_QOS_INFO *p_out_qos)
|
||||
{
|
||||
tBTA_HD_REGISTER_APP *p_buf;
|
||||
APPL_TRACE_API("%s", __func__);
|
||||
if ((p_buf = (tBTA_HD_REGISTER_APP *)osi_malloc(sizeof(tBTA_HD_REGISTER_APP))) != NULL) {
|
||||
p_buf->hdr.event = BTA_HD_API_REGISTER_APP_EVT;
|
||||
if (p_app_info->p_name) {
|
||||
strncpy(p_buf->name, p_app_info->p_name, BTA_HD_APP_NAME_LEN);
|
||||
p_buf->name[BTA_HD_APP_NAME_LEN] = '\0';
|
||||
} else {
|
||||
p_buf->name[0] = '\0';
|
||||
}
|
||||
if (p_app_info->p_description) {
|
||||
strncpy(p_buf->description, p_app_info->p_description, BTA_HD_APP_DESCRIPTION_LEN);
|
||||
p_buf->description[BTA_HD_APP_DESCRIPTION_LEN] = '\0';
|
||||
} else {
|
||||
p_buf->description[0] = '\0';
|
||||
}
|
||||
if (p_app_info->p_provider) {
|
||||
strncpy(p_buf->provider, p_app_info->p_provider, BTA_HD_APP_PROVIDER_LEN);
|
||||
p_buf->provider[BTA_HD_APP_PROVIDER_LEN] = '\0';
|
||||
} else {
|
||||
p_buf->provider[0] = '\0';
|
||||
}
|
||||
p_buf->subclass = p_app_info->subclass;
|
||||
p_buf->d_len = p_app_info->descriptor.dl_len;
|
||||
memcpy(p_buf->d_data, p_app_info->descriptor.dsc_list, p_app_info->descriptor.dl_len);
|
||||
// copy qos data as-is
|
||||
memcpy(&p_buf->in_qos, p_in_qos, sizeof(tBTA_HD_QOS_INFO));
|
||||
memcpy(&p_buf->out_qos, p_out_qos, sizeof(tBTA_HD_QOS_INFO));
|
||||
bta_sys_sendmsg(p_buf);
|
||||
}
|
||||
}
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function BTA_HdUnregisterApp
|
||||
*
|
||||
* Description This function is called when application should be
|
||||
*unregistered
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
extern void BTA_HdUnregisterApp(void)
|
||||
{
|
||||
BT_HDR *p_buf;
|
||||
APPL_TRACE_API("%s", __func__);
|
||||
if ((p_buf = (BT_HDR *)osi_malloc(sizeof(BT_HDR))) != NULL) {
|
||||
p_buf->event = BTA_HD_API_UNREGISTER_APP_EVT;
|
||||
bta_sys_sendmsg(p_buf);
|
||||
}
|
||||
}
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function BTA_HdSendReport
|
||||
*
|
||||
* Description This function is called when report is to be sent
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
extern void BTA_HdSendReport(tBTA_HD_REPORT *p_report)
|
||||
{
|
||||
tBTA_HD_SEND_REPORT *p_buf;
|
||||
APPL_TRACE_VERBOSE("%s", __func__);
|
||||
if (p_report->len > BTA_HD_REPORT_LEN) {
|
||||
APPL_TRACE_WARNING("%s, report len (%d) > MTU len (%d), can't send report."
|
||||
" Increase value of HID_DEV_MTU_SIZE to send larger reports",
|
||||
__func__, p_report->len, BTA_HD_REPORT_LEN);
|
||||
return;
|
||||
}
|
||||
if ((p_buf = (tBTA_HD_SEND_REPORT *)osi_malloc(sizeof(tBTA_HD_SEND_REPORT))) != NULL) {
|
||||
p_buf->hdr.event = BTA_HD_API_SEND_REPORT_EVT;
|
||||
p_buf->use_intr = p_report->use_intr;
|
||||
p_buf->type = p_report->type;
|
||||
p_buf->id = p_report->id;
|
||||
p_buf->len = p_report->len;
|
||||
memcpy(p_buf->data, p_report->p_data, p_report->len);
|
||||
bta_sys_sendmsg(p_buf);
|
||||
}
|
||||
}
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function BTA_HdVirtualCableUnplug
|
||||
*
|
||||
* Description This function is called when VCU shall be sent
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
extern void BTA_HdVirtualCableUnplug(void)
|
||||
{
|
||||
BT_HDR *p_buf;
|
||||
APPL_TRACE_API("%s", __func__);
|
||||
if ((p_buf = (BT_HDR *)osi_malloc(sizeof(BT_HDR))) != NULL) {
|
||||
p_buf->event = BTA_HD_API_VC_UNPLUG_EVT;
|
||||
bta_sys_sendmsg(p_buf);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function BTA_HdConnect
|
||||
*
|
||||
* Description This function is called when connection to host shall be
|
||||
* made
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
extern void BTA_HdConnect(BD_ADDR addr)
|
||||
{
|
||||
tBTA_HD_DEVICE_CTRL *p_buf;
|
||||
APPL_TRACE_API("%s", __func__);
|
||||
|
||||
if ((p_buf = (tBTA_HD_DEVICE_CTRL *)osi_malloc(sizeof(tBTA_HD_DEVICE_CTRL))) != NULL) {
|
||||
p_buf->hdr.event = BTA_HD_API_CONNECT_EVT;
|
||||
memcpy(p_buf->addr, addr, sizeof(BD_ADDR));
|
||||
bta_sys_sendmsg(p_buf);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function BTA_HdDisconnect
|
||||
*
|
||||
* Description This function is called when host shall be disconnected
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
extern void BTA_HdDisconnect(void)
|
||||
{
|
||||
BT_HDR *p_buf;
|
||||
APPL_TRACE_API("%s", __func__);
|
||||
if ((p_buf = (BT_HDR *)osi_malloc(sizeof(BT_HDR))) != NULL) {
|
||||
p_buf->event = BTA_HD_API_DISCONNECT_EVT;
|
||||
bta_sys_sendmsg(p_buf);
|
||||
}
|
||||
}
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function BTA_HdAddDevice
|
||||
*
|
||||
* Description This function is called when a device is virtually cabled
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
extern void BTA_HdAddDevice(BD_ADDR addr)
|
||||
{
|
||||
tBTA_HD_DEVICE_CTRL *p_buf;
|
||||
APPL_TRACE_API("%s", __func__);
|
||||
if ((p_buf = (tBTA_HD_DEVICE_CTRL *)osi_malloc(sizeof(tBTA_HD_DEVICE_CTRL))) != NULL) {
|
||||
p_buf->hdr.event = BTA_HD_API_ADD_DEVICE_EVT;
|
||||
memcpy(p_buf->addr, addr, sizeof(BD_ADDR));
|
||||
bta_sys_sendmsg(p_buf);
|
||||
}
|
||||
}
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function BTA_HdRemoveDevice
|
||||
*
|
||||
* Description This function is called when a device is virtually uncabled
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
extern void BTA_HdRemoveDevice(BD_ADDR addr)
|
||||
{
|
||||
tBTA_HD_DEVICE_CTRL *p_buf;
|
||||
APPL_TRACE_API("%s", __func__);
|
||||
if ((p_buf = (tBTA_HD_DEVICE_CTRL *)osi_malloc(sizeof(tBTA_HD_DEVICE_CTRL))) != NULL) {
|
||||
p_buf->hdr.event = BTA_HD_API_REMOVE_DEVICE_EVT;
|
||||
memcpy(p_buf->addr, addr, sizeof(BD_ADDR));
|
||||
bta_sys_sendmsg(p_buf);
|
||||
}
|
||||
}
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function BTA_HdReportError
|
||||
*
|
||||
* Description This function is called when reporting error for set report
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
extern void BTA_HdReportError(uint8_t error)
|
||||
{
|
||||
tBTA_HD_REPORT_ERR *p_buf;
|
||||
APPL_TRACE_API("%s", __func__);
|
||||
if ((p_buf = (tBTA_HD_REPORT_ERR *)osi_malloc(sizeof(tBTA_HD_REPORT_ERR))) != NULL) {
|
||||
p_buf->hdr.event = BTA_HD_API_REPORT_ERROR_EVT;
|
||||
p_buf->error = error;
|
||||
bta_sys_sendmsg(p_buf);
|
||||
}
|
||||
}
|
||||
#endif /* BTA_HD_INCLUDED */
|
320
components/bt/host/bluedroid/bta/hd/bta_hd_main.c
Normal file
320
components/bt/host/bluedroid/bta/hd/bta_hd_main.c
Normal file
@ -0,0 +1,320 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
* Copyright (C) 2005-2012 Broadcom Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************/
|
||||
/******************************************************************************
|
||||
*
|
||||
* This file contains the HID host main functions and state machine.
|
||||
*
|
||||
******************************************************************************/
|
||||
#include "common/bt_target.h"
|
||||
|
||||
#if defined(BTA_HD_INCLUDED) && (BTA_HD_INCLUDED == TRUE)
|
||||
|
||||
#include "bta/bta_hd_api.h"
|
||||
#include "bta_hd_int.h"
|
||||
#include <string.h>
|
||||
|
||||
/*****************************************************************************
|
||||
* Constants and types
|
||||
****************************************************************************/
|
||||
/* state machine states */
|
||||
enum {
|
||||
BTA_HD_INIT_ST,
|
||||
BTA_HD_IDLE_ST, /* not connected, waiting for connection */
|
||||
BTA_HD_CONN_ST, /* host connected */
|
||||
BTA_HD_TRANSIENT_TO_INIT_ST, /* transient state: going back from CONN to INIT */
|
||||
};
|
||||
typedef uint8_t tBTA_HD_STATE;
|
||||
|
||||
/* state machine actions */
|
||||
enum {
|
||||
BTA_HD_REGISTER_ACT,
|
||||
BTA_HD_UNREGISTER_ACT,
|
||||
BTA_HD_UNREGISTER2_ACT,
|
||||
BTA_HD_CONNECT_ACT,
|
||||
BTA_HD_DISCONNECT_ACT,
|
||||
BTA_HD_ADD_DEVICE_ACT,
|
||||
BTA_HD_REMOVE_DEVICE_ACT,
|
||||
BTA_HD_SEND_REPORT_ACT,
|
||||
BTA_HD_REPORT_ERROR_ACT,
|
||||
BTA_HD_VC_UNPLUG_ACT,
|
||||
BTA_HD_OPEN_ACT,
|
||||
BTA_HD_CLOSE_ACT,
|
||||
BTA_HD_INTR_DATA_ACT,
|
||||
BTA_HD_GET_REPORT_ACT,
|
||||
BTA_HD_SET_REPORT_ACT,
|
||||
BTA_HD_SET_PROTOCOL_ACT,
|
||||
BTA_HD_VC_UNPLUG_DONE_ACT,
|
||||
BTA_HD_SUSPEND_ACT,
|
||||
BTA_HD_EXIT_SUSPEND_ACT,
|
||||
BTA_HD_NUM_ACTIONS
|
||||
};
|
||||
|
||||
#define BTA_HD_IGNORE BTA_HD_NUM_ACTIONS
|
||||
|
||||
typedef void (*tBTA_HD_ACTION)(tBTA_HD_DATA *p_data);
|
||||
/* action functions */
|
||||
const tBTA_HD_ACTION bta_hd_action[] = {
|
||||
bta_hd_register_act, bta_hd_unregister_act, bta_hd_unregister2_act, bta_hd_connect_act,
|
||||
bta_hd_disconnect_act, bta_hd_add_device_act, bta_hd_remove_device_act, bta_hd_send_report_act,
|
||||
bta_hd_report_error_act, bta_hd_vc_unplug_act, bta_hd_open_act, bta_hd_close_act,
|
||||
bta_hd_intr_data_act, bta_hd_get_report_act, bta_hd_set_report_act, bta_hd_set_protocol_act,
|
||||
bta_hd_vc_unplug_done_act, bta_hd_suspend_act, bta_hd_exit_suspend_act,
|
||||
};
|
||||
|
||||
/* state table information */
|
||||
#define BTA_HD_ACTION 0 /* position of action */
|
||||
#define BTA_HD_NEXT_STATE 1 /* position of next state */
|
||||
#define BTA_HD_NUM_COLS 2 /* number of columns */
|
||||
|
||||
const uint8_t bta_hd_st_init[][BTA_HD_NUM_COLS] = {
|
||||
/* Event Action Next state
|
||||
*/
|
||||
/* BTA_HD_API_REGISTER_APP_EVT */ {BTA_HD_REGISTER_ACT, BTA_HD_IDLE_ST},
|
||||
/* BTA_HD_API_UNREGISTER_APP_EVT */ {BTA_HD_IGNORE, BTA_HD_INIT_ST},
|
||||
/* BTA_HD_API_CONNECT_EVT */ {BTA_HD_IGNORE, BTA_HD_INIT_ST},
|
||||
/* BTA_HD_API_DISCONNECT_EVT */ {BTA_HD_IGNORE, BTA_HD_INIT_ST},
|
||||
/* BTA_HD_API_ADD_DEVICE_EVT */ {BTA_HD_ADD_DEVICE_ACT, BTA_HD_INIT_ST},
|
||||
/* BTA_HD_API_REMOVE_DEVICE_EVT */ {BTA_HD_REMOVE_DEVICE_ACT, BTA_HD_INIT_ST},
|
||||
/* BTA_HD_API_SEND_REPORT_EVT */ {BTA_HD_IGNORE, BTA_HD_INIT_ST},
|
||||
/* BTA_HD_API_REPORT_ERROR_EVT */ {BTA_HD_IGNORE, BTA_HD_INIT_ST},
|
||||
/* BTA_HD_API_VC_UNPLUG_EVT */ {BTA_HD_IGNORE, BTA_HD_INIT_ST},
|
||||
/* BTA_HD_INT_OPEN_EVT */ {BTA_HD_IGNORE, BTA_HD_INIT_ST},
|
||||
/* BTA_HD_INT_CLOSE_EVT */ {BTA_HD_IGNORE, BTA_HD_INIT_ST},
|
||||
/* BTA_HD_INT_INTR_DATA_EVT */ {BTA_HD_IGNORE, BTA_HD_INIT_ST},
|
||||
/* BTA_HD_INT_GET_REPORT_EVT */ {BTA_HD_IGNORE, BTA_HD_INIT_ST},
|
||||
/* BTA_HD_INT_SET_REPORT_EVT */ {BTA_HD_IGNORE, BTA_HD_INIT_ST},
|
||||
/* BTA_HD_INT_SET_PROTOCOL_EVT */ {BTA_HD_IGNORE, BTA_HD_INIT_ST},
|
||||
/* BTA_HD_INT_VC_UNPLUG_EVT */ {BTA_HD_IGNORE, BTA_HD_INIT_ST},
|
||||
/* BTA_HD_INT_SUSPEND_EVT */ {BTA_HD_IGNORE, BTA_HD_INIT_ST},
|
||||
/* BTA_HD_INT_EXIT_SUSPEND_EVT */ {BTA_HD_IGNORE, BTA_HD_INIT_ST},
|
||||
};
|
||||
|
||||
const uint8_t bta_hd_st_idle[][BTA_HD_NUM_COLS] = {
|
||||
/* Event Action Next state
|
||||
*/
|
||||
/* BTA_HD_API_REGISTER_APP_EVT */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST},
|
||||
/* BTA_HD_API_UNREGISTER_APP_EVT */ {BTA_HD_UNREGISTER_ACT, BTA_HD_INIT_ST},
|
||||
/* BTA_HD_API_CONNECT_EVT */ {BTA_HD_CONNECT_ACT, BTA_HD_IDLE_ST},
|
||||
/* BTA_HD_API_DISCONNECT_EVT */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST},
|
||||
/* BTA_HD_API_ADD_DEVICE_EVT */ {BTA_HD_ADD_DEVICE_ACT, BTA_HD_IDLE_ST},
|
||||
/* BTA_HD_API_REMOVE_DEVICE_EVT */ {BTA_HD_REMOVE_DEVICE_ACT, BTA_HD_IDLE_ST},
|
||||
/* BTA_HD_API_SEND_REPORT_EVT */ {BTA_HD_SEND_REPORT_ACT, BTA_HD_IDLE_ST},
|
||||
/* BTA_HD_API_REPORT_ERROR_EVT */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST},
|
||||
/* BTA_HD_API_VC_UNPLUG_EVT */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST},
|
||||
/* BTA_HD_INT_OPEN_EVT */ {BTA_HD_OPEN_ACT, BTA_HD_CONN_ST},
|
||||
/* BTA_HD_INT_CLOSE_EVT */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST},
|
||||
/* BTA_HD_INT_INTR_DATA_EVT */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST},
|
||||
/* BTA_HD_INT_GET_REPORT_EVT */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST},
|
||||
/* BTA_HD_INT_SET_REPORT_EVT */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST},
|
||||
/* BTA_HD_INT_SET_PROTOCOL_EVT */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST},
|
||||
/* BTA_HD_INT_VC_UNPLUG_EVT */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST},
|
||||
/* BTA_HD_INT_SUSPEND_EVT */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST},
|
||||
/* BTA_HD_INT_EXIT_SUSPEND_EVT */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST},
|
||||
};
|
||||
|
||||
const uint8_t bta_hd_st_conn[][BTA_HD_NUM_COLS] = {
|
||||
/* Event Action Next state */
|
||||
/* BTA_HD_API_REGISTER_APP_EVT */ {BTA_HD_IGNORE, BTA_HD_CONN_ST},
|
||||
/* BTA_HD_API_UNREGISTER_APP_EVT */ {BTA_HD_DISCONNECT_ACT, BTA_HD_TRANSIENT_TO_INIT_ST},
|
||||
/* BTA_HD_API_CONNECT_EVT */ {BTA_HD_IGNORE, BTA_HD_CONN_ST},
|
||||
/* BTA_HD_API_DISCONNECT_EVT */ {BTA_HD_DISCONNECT_ACT, BTA_HD_CONN_ST},
|
||||
/* BTA_HD_API_ADD_DEVICE_EVT */ {BTA_HD_ADD_DEVICE_ACT, BTA_HD_CONN_ST},
|
||||
/* BTA_HD_API_REMOVE_DEVICE_EVT */ {BTA_HD_REMOVE_DEVICE_ACT, BTA_HD_CONN_ST},
|
||||
/* BTA_HD_API_SEND_REPORT_EVT */ {BTA_HD_SEND_REPORT_ACT, BTA_HD_CONN_ST},
|
||||
/* BTA_HD_API_REPORT_ERROR_EVT */ {BTA_HD_REPORT_ERROR_ACT, BTA_HD_CONN_ST},
|
||||
/* BTA_HD_API_VC_UNPLUG_EVT */ {BTA_HD_VC_UNPLUG_ACT, BTA_HD_CONN_ST},
|
||||
/* BTA_HD_INT_OPEN_EVT */ {BTA_HD_IGNORE, BTA_HD_CONN_ST},
|
||||
/* BTA_HD_INT_CLOSE_EVT */ {BTA_HD_CLOSE_ACT, BTA_HD_IDLE_ST},
|
||||
/* BTA_HD_INT_INTR_DATA_EVT */ {BTA_HD_INTR_DATA_ACT, BTA_HD_CONN_ST},
|
||||
/* BTA_HD_INT_GET_REPORT_EVT */ {BTA_HD_GET_REPORT_ACT, BTA_HD_CONN_ST},
|
||||
/* BTA_HD_INT_SET_REPORT_EVT */ {BTA_HD_SET_REPORT_ACT, BTA_HD_CONN_ST},
|
||||
/* BTA_HD_INT_SET_PROTOCOL_EVT */ {BTA_HD_SET_PROTOCOL_ACT, BTA_HD_CONN_ST},
|
||||
/* BTA_HD_INT_VC_UNPLUG_EVT */ {BTA_HD_VC_UNPLUG_DONE_ACT, BTA_HD_IDLE_ST},
|
||||
/* BTA_HD_INT_SUSPEND_EVT */ {BTA_HD_SUSPEND_ACT, BTA_HD_CONN_ST},
|
||||
/* BTA_HD_INT_EXIT_SUSPEND_EVT */ {BTA_HD_EXIT_SUSPEND_ACT, BTA_HD_CONN_ST},
|
||||
};
|
||||
|
||||
const uint8_t bta_hd_st_transient_to_init[][BTA_HD_NUM_COLS] = {
|
||||
/* Event Action Next state */
|
||||
/* BTA_HD_API_REGISTER_APP_EVT */ {BTA_HD_IGNORE, BTA_HD_TRANSIENT_TO_INIT_ST},
|
||||
/* BTA_HD_API_UNREGISTER_APP_EVT */ {BTA_HD_IGNORE, BTA_HD_TRANSIENT_TO_INIT_ST},
|
||||
/* BTA_HD_API_CONNECT_EVT */ {BTA_HD_IGNORE, BTA_HD_TRANSIENT_TO_INIT_ST},
|
||||
/* BTA_HD_API_DISCONNECT_EVT */ {BTA_HD_IGNORE, BTA_HD_TRANSIENT_TO_INIT_ST},
|
||||
/* BTA_HD_API_ADD_DEVICE_EVT */ {BTA_HD_IGNORE, BTA_HD_TRANSIENT_TO_INIT_ST},
|
||||
/* BTA_HD_API_REMOVE_DEVICE_EVT */ {BTA_HD_IGNORE, BTA_HD_TRANSIENT_TO_INIT_ST},
|
||||
/* BTA_HD_API_SEND_REPORT_EVT */ {BTA_HD_IGNORE, BTA_HD_TRANSIENT_TO_INIT_ST},
|
||||
/* BTA_HD_API_REPORT_ERROR_EVT */ {BTA_HD_IGNORE, BTA_HD_TRANSIENT_TO_INIT_ST},
|
||||
/* BTA_HD_API_VC_UNPLUG_EVT */ {BTA_HD_IGNORE, BTA_HD_TRANSIENT_TO_INIT_ST},
|
||||
/* BTA_HD_INT_OPEN_EVT */ {BTA_HD_IGNORE, BTA_HD_TRANSIENT_TO_INIT_ST},
|
||||
/* BTA_HD_INT_CLOSE_EVT */ {BTA_HD_UNREGISTER2_ACT, BTA_HD_INIT_ST},
|
||||
/* BTA_HD_INT_INTR_DATA_EVT */ {BTA_HD_IGNORE, BTA_HD_TRANSIENT_TO_INIT_ST},
|
||||
/* BTA_HD_INT_GET_REPORT_EVT */ {BTA_HD_IGNORE, BTA_HD_TRANSIENT_TO_INIT_ST},
|
||||
/* BTA_HD_INT_SET_REPORT_EVT */ {BTA_HD_IGNORE, BTA_HD_TRANSIENT_TO_INIT_ST},
|
||||
/* BTA_HD_INT_SET_PROTOCOL_EVT */ {BTA_HD_IGNORE, BTA_HD_TRANSIENT_TO_INIT_ST},
|
||||
/* BTA_HD_INT_VC_UNPLUG_EVT */ {BTA_HD_UNREGISTER2_ACT, BTA_HD_INIT_ST},
|
||||
/* BTA_HD_INT_SUSPEND_EVT */ {BTA_HD_IGNORE, BTA_HD_TRANSIENT_TO_INIT_ST},
|
||||
/* BTA_HD_INT_EXIT_SUSPEND_EVT */ {BTA_HD_IGNORE, BTA_HD_TRANSIENT_TO_INIT_ST},
|
||||
};
|
||||
|
||||
/* type for state table */
|
||||
typedef const uint8_t (*tBTA_HD_ST_TBL)[BTA_HD_NUM_COLS];
|
||||
/* state table */
|
||||
const tBTA_HD_ST_TBL bta_hd_st_tbl[] = {bta_hd_st_init, bta_hd_st_idle, bta_hd_st_conn, bta_hd_st_transient_to_init};
|
||||
|
||||
/*****************************************************************************
|
||||
* Global data
|
||||
****************************************************************************/
|
||||
#if BTA_DYNAMIC_MEMORY == FALSE
|
||||
tBTA_HD_CB bta_hd_cb;
|
||||
#else
|
||||
tBTA_HD_CB *bta_hd_cb_ptr;
|
||||
#endif
|
||||
|
||||
static const char *bta_hd_evt_code(tBTA_HD_INT_EVT evt_code);
|
||||
static const char *bta_hd_state_code(tBTA_HD_STATE state_code);
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function bta_hd_sm_execute
|
||||
*
|
||||
* Description State machine event handling function for HID Device
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
void bta_hd_sm_execute(uint16_t event, tBTA_HD_DATA *p_data)
|
||||
{
|
||||
tBTA_HD_ST_TBL state_table;
|
||||
tBTA_HD_STATE prev_state;
|
||||
uint8_t action;
|
||||
tBTA_HD cback_data;
|
||||
|
||||
APPL_TRACE_EVENT("%s: state=%s (%d) event=%s (%d)", __func__, bta_hd_state_code(bta_hd_cb.state), bta_hd_cb.state,
|
||||
bta_hd_evt_code(event), event);
|
||||
|
||||
prev_state = bta_hd_cb.state;
|
||||
memset(&cback_data, 0, sizeof(tBTA_HD));
|
||||
state_table = bta_hd_st_tbl[bta_hd_cb.state];
|
||||
event &= 0xff;
|
||||
|
||||
if ((action = state_table[event][BTA_HD_ACTION]) < BTA_HD_IGNORE) {
|
||||
(*bta_hd_action[action])(p_data);
|
||||
}
|
||||
|
||||
bta_hd_cb.state = state_table[event][BTA_HD_NEXT_STATE];
|
||||
|
||||
if (bta_hd_cb.state != prev_state) {
|
||||
APPL_TRACE_EVENT("%s: [new] state=%s (%d)", __func__, bta_hd_state_code(bta_hd_cb.state), bta_hd_cb.state);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function bta_hd_hdl_event
|
||||
*
|
||||
* Description HID device main event handling function.
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
bool bta_hd_hdl_event(BT_HDR *p_msg)
|
||||
{
|
||||
APPL_TRACE_API("%s: p_msg->event=%d", __func__, p_msg->event);
|
||||
|
||||
switch (p_msg->event) {
|
||||
case BTA_HD_API_ENABLE_EVT:
|
||||
bta_hd_api_enable((tBTA_HD_DATA *)p_msg);
|
||||
break;
|
||||
case BTA_HD_API_DISABLE_EVT:
|
||||
if (bta_hd_cb.state == BTA_HD_CONN_ST) {
|
||||
APPL_TRACE_WARNING("%s: host connected, disconnect before disabling", __func__);
|
||||
// unregister (and disconnect)
|
||||
bta_hd_cb.disable_w4_close = TRUE;
|
||||
bta_hd_sm_execute(BTA_HD_API_UNREGISTER_APP_EVT, (tBTA_HD_DATA *)p_msg);
|
||||
} else {
|
||||
bta_hd_api_disable();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
bta_hd_sm_execute(p_msg->event, (tBTA_HD_DATA *)p_msg);
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
static const char *bta_hd_evt_code(tBTA_HD_INT_EVT evt_code)
|
||||
{
|
||||
switch (evt_code) {
|
||||
case BTA_HD_API_REGISTER_APP_EVT:
|
||||
return "BTA_HD_API_REGISTER_APP_EVT";
|
||||
case BTA_HD_API_UNREGISTER_APP_EVT:
|
||||
return "BTA_HD_API_UNREGISTER_APP_EVT";
|
||||
case BTA_HD_API_CONNECT_EVT:
|
||||
return "BTA_HD_API_CONNECT_EVT";
|
||||
case BTA_HD_API_DISCONNECT_EVT:
|
||||
return "BTA_HD_API_DISCONNECT_EVT";
|
||||
case BTA_HD_API_ADD_DEVICE_EVT:
|
||||
return "BTA_HD_API_ADD_DEVICE_EVT";
|
||||
case BTA_HD_API_REMOVE_DEVICE_EVT:
|
||||
return "BTA_HD_API_REMOVE_DEVICE_EVT";
|
||||
case BTA_HD_API_SEND_REPORT_EVT:
|
||||
return "BTA_HD_API_SEND_REPORT_EVT";
|
||||
case BTA_HD_API_REPORT_ERROR_EVT:
|
||||
return "BTA_HD_API_REPORT_ERROR_EVT";
|
||||
case BTA_HD_API_VC_UNPLUG_EVT:
|
||||
return "BTA_HD_API_VC_UNPLUG_EVT";
|
||||
case BTA_HD_INT_OPEN_EVT:
|
||||
return "BTA_HD_INT_OPEN_EVT";
|
||||
case BTA_HD_INT_CLOSE_EVT:
|
||||
return "BTA_HD_INT_CLOSE_EVT";
|
||||
case BTA_HD_INT_INTR_DATA_EVT:
|
||||
return "BTA_HD_INT_INTR_DATA_EVT";
|
||||
case BTA_HD_INT_GET_REPORT_EVT:
|
||||
return "BTA_HD_INT_GET_REPORT_EVT";
|
||||
case BTA_HD_INT_SET_REPORT_EVT:
|
||||
return "BTA_HD_INT_SET_REPORT_EVT";
|
||||
case BTA_HD_INT_SET_PROTOCOL_EVT:
|
||||
return "BTA_HD_INT_SET_PROTOCOL_EVT";
|
||||
case BTA_HD_INT_VC_UNPLUG_EVT:
|
||||
return "BTA_HD_INT_VC_UNPLUG_EVT";
|
||||
case BTA_HD_INT_SUSPEND_EVT:
|
||||
return "BTA_HD_INT_SUSPEND_EVT";
|
||||
case BTA_HD_INT_EXIT_SUSPEND_EVT:
|
||||
return "BTA_HD_INT_EXIT_SUSPEND_EVT";
|
||||
default:
|
||||
return "<unknown>";
|
||||
}
|
||||
}
|
||||
|
||||
static const char *bta_hd_state_code(tBTA_HD_STATE state_code)
|
||||
{
|
||||
switch (state_code) {
|
||||
case BTA_HD_INIT_ST:
|
||||
return "BTA_HD_INIT_ST";
|
||||
case BTA_HD_IDLE_ST:
|
||||
return "BTA_HD_IDLE_ST";
|
||||
case BTA_HD_CONN_ST:
|
||||
return "BTA_HD_CONN_ST";
|
||||
case BTA_HD_TRANSIENT_TO_INIT_ST:
|
||||
return "BTA_HD_TRANSIENT_TO_INIT_ST";
|
||||
default:
|
||||
return "<unknown>";
|
||||
}
|
||||
}
|
||||
#endif /* BTA_HD_INCLUDED */
|
168
components/bt/host/bluedroid/bta/hd/include/bta_hd_int.h
Normal file
168
components/bt/host/bluedroid/bta/hd/include/bta_hd_int.h
Normal file
@ -0,0 +1,168 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
* Copyright (C) 2005-2012 Broadcom Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************/
|
||||
/******************************************************************************
|
||||
*
|
||||
* This file contains BTA HID Device internal definitions
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef BTA_HD_INT_H
|
||||
#define BTA_HD_INT_H
|
||||
|
||||
#include "bta/bta_hd_api.h"
|
||||
#include "bta/bta_sys.h"
|
||||
#include "stack/hiddefs.h"
|
||||
|
||||
enum {
|
||||
BTA_HD_API_REGISTER_APP_EVT = BTA_SYS_EVT_START(BTA_ID_HD),
|
||||
BTA_HD_API_UNREGISTER_APP_EVT,
|
||||
BTA_HD_API_CONNECT_EVT,
|
||||
BTA_HD_API_DISCONNECT_EVT,
|
||||
BTA_HD_API_ADD_DEVICE_EVT,
|
||||
BTA_HD_API_REMOVE_DEVICE_EVT,
|
||||
BTA_HD_API_SEND_REPORT_EVT,
|
||||
BTA_HD_API_REPORT_ERROR_EVT,
|
||||
BTA_HD_API_VC_UNPLUG_EVT,
|
||||
BTA_HD_INT_OPEN_EVT,
|
||||
BTA_HD_INT_CLOSE_EVT,
|
||||
BTA_HD_INT_INTR_DATA_EVT,
|
||||
BTA_HD_INT_GET_REPORT_EVT,
|
||||
BTA_HD_INT_SET_REPORT_EVT,
|
||||
BTA_HD_INT_SET_PROTOCOL_EVT,
|
||||
BTA_HD_INT_VC_UNPLUG_EVT,
|
||||
BTA_HD_INT_SUSPEND_EVT,
|
||||
BTA_HD_INT_EXIT_SUSPEND_EVT,
|
||||
/* handled outside state machine */
|
||||
BTA_HD_API_ENABLE_EVT,
|
||||
BTA_HD_API_DISABLE_EVT
|
||||
};
|
||||
typedef uint16_t tBTA_HD_INT_EVT;
|
||||
#define BTA_HD_INVALID_EVT (BTA_HD_API_DISABLE_EVT + 1)
|
||||
typedef struct {
|
||||
BT_HDR hdr;
|
||||
tBTA_HD_CBACK *p_cback;
|
||||
} tBTA_HD_API_ENABLE;
|
||||
#define BTA_HD_APP_NAME_LEN 50
|
||||
#define BTA_HD_APP_DESCRIPTION_LEN 50
|
||||
#define BTA_HD_APP_PROVIDER_LEN 50
|
||||
#define BTA_HD_APP_DESCRIPTOR_LEN 2048
|
||||
#define BTA_HD_STATE_DISABLED 0x00
|
||||
#define BTA_HD_STATE_ENABLED 0x01
|
||||
#define BTA_HD_STATE_IDLE 0x02
|
||||
#define BTA_HD_STATE_CONNECTED 0x03
|
||||
#define BTA_HD_STATE_DISABLING 0x04
|
||||
#define BTA_HD_STATE_REMOVING 0x05
|
||||
typedef struct {
|
||||
BT_HDR hdr;
|
||||
char name[BTA_HD_APP_NAME_LEN + 1];
|
||||
char description[BTA_HD_APP_DESCRIPTION_LEN + 1];
|
||||
char provider[BTA_HD_APP_PROVIDER_LEN + 1];
|
||||
uint8_t subclass;
|
||||
uint16_t d_len;
|
||||
uint8_t d_data[BTA_HD_APP_DESCRIPTOR_LEN];
|
||||
tBTA_HD_QOS_INFO in_qos;
|
||||
tBTA_HD_QOS_INFO out_qos;
|
||||
} tBTA_HD_REGISTER_APP;
|
||||
|
||||
#define BTA_HD_REPORT_LEN HID_DEV_MTU_SIZE
|
||||
|
||||
typedef struct {
|
||||
BT_HDR hdr;
|
||||
bool use_intr;
|
||||
uint8_t type;
|
||||
uint8_t id;
|
||||
uint16_t len;
|
||||
uint8_t data[BTA_HD_REPORT_LEN];
|
||||
} tBTA_HD_SEND_REPORT;
|
||||
|
||||
typedef struct {
|
||||
BT_HDR hdr;
|
||||
BD_ADDR addr;
|
||||
} tBTA_HD_DEVICE_CTRL;
|
||||
|
||||
typedef struct {
|
||||
BT_HDR hdr;
|
||||
uint8_t error;
|
||||
} tBTA_HD_REPORT_ERR;
|
||||
|
||||
/* union of all event data types */
|
||||
typedef union {
|
||||
BT_HDR hdr;
|
||||
tBTA_HD_API_ENABLE api_enable;
|
||||
tBTA_HD_REGISTER_APP register_app;
|
||||
tBTA_HD_SEND_REPORT send_report;
|
||||
tBTA_HD_DEVICE_CTRL device_ctrl;
|
||||
tBTA_HD_REPORT_ERR report_err;
|
||||
} tBTA_HD_DATA;
|
||||
|
||||
typedef struct {
|
||||
BT_HDR hdr;
|
||||
BD_ADDR addr;
|
||||
uint32_t data;
|
||||
BT_HDR *p_data;
|
||||
} tBTA_HD_CBACK_DATA;
|
||||
|
||||
/******************************************************************************
|
||||
* Main Control Block
|
||||
******************************************************************************/
|
||||
typedef struct {
|
||||
tBTA_HD_CBACK *p_cback;
|
||||
uint32_t sdp_handle;
|
||||
uint8_t trace_level;
|
||||
uint8_t state;
|
||||
BD_ADDR bd_addr;
|
||||
bool use_report_id;
|
||||
bool boot_mode;
|
||||
bool vc_unplug;
|
||||
bool disable_w4_close;
|
||||
} tBTA_HD_CB;
|
||||
|
||||
#if BTA_DYNAMIC_MEMORY == FALSE
|
||||
extern tBTA_HD_CB bta_hd_cb;
|
||||
#else
|
||||
extern tBTA_HD_CB *bta_hd_cb_ptr;
|
||||
#define bta_hd_cb (*bta_hd_cb_ptr)
|
||||
#endif
|
||||
|
||||
/*****************************************************************************
|
||||
* Function prototypes
|
||||
****************************************************************************/
|
||||
extern bool bta_hd_hdl_event(BT_HDR *p_msg);
|
||||
extern void bta_hd_api_enable(tBTA_HD_DATA *p_data);
|
||||
extern void bta_hd_api_disable(void);
|
||||
extern void bta_hd_register_act(tBTA_HD_DATA *p_data);
|
||||
extern void bta_hd_unregister_act(tBTA_HD_DATA *p_data);
|
||||
extern void bta_hd_unregister2_act(tBTA_HD_DATA *p_data);
|
||||
extern void bta_hd_connect_act(tBTA_HD_DATA *p_data);
|
||||
extern void bta_hd_disconnect_act(tBTA_HD_DATA *p_data);
|
||||
extern void bta_hd_add_device_act(tBTA_HD_DATA *p_data);
|
||||
extern void bta_hd_remove_device_act(tBTA_HD_DATA *p_data);
|
||||
extern void bta_hd_send_report_act(tBTA_HD_DATA *p_data);
|
||||
extern void bta_hd_report_error_act(tBTA_HD_DATA *p_data);
|
||||
extern void bta_hd_vc_unplug_act(tBTA_HD_DATA *p_data);
|
||||
extern void bta_hd_open_act(tBTA_HD_DATA *p_data);
|
||||
extern void bta_hd_close_act(tBTA_HD_DATA *p_data);
|
||||
extern void bta_hd_intr_data_act(tBTA_HD_DATA *p_data);
|
||||
extern void bta_hd_get_report_act(tBTA_HD_DATA *p_data);
|
||||
extern void bta_hd_set_report_act(tBTA_HD_DATA *p_data);
|
||||
extern void bta_hd_set_protocol_act(tBTA_HD_DATA *p_data);
|
||||
extern void bta_hd_vc_unplug_done_act(tBTA_HD_DATA *p_data);
|
||||
extern void bta_hd_suspend_act(tBTA_HD_DATA *p_data);
|
||||
extern void bta_hd_exit_suspend_act(tBTA_HD_DATA *p_data);
|
||||
|
||||
#endif
|
@ -214,7 +214,7 @@ const UINT8 bta_hf_client_st_closing[][BTA_HF_CLIENT_NUM_COLS] = {
|
||||
/* DISC_OK_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_CLOSING_ST},
|
||||
/* DISC_FAIL_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_CLOSING_ST},
|
||||
/* SCO_OPEN_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_CLOSING_ST},
|
||||
/* SCO_CLOSE_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_CLOSING_ST},
|
||||
/* SCO_CLOSE_EVT */ {BTA_HF_CLIENT_SCO_CONN_CLOSE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_CLOSING_ST},
|
||||
/* SEND_AT_CMD_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_CLOSING_ST},
|
||||
#if (BTM_SCO_HCI_INCLUDED == TRUE )
|
||||
/* CI_SCO_DATA_EVT */ {BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_IGNORE, BTA_HF_CLIENT_CLOSING_ST},
|
||||
|
@ -323,6 +323,7 @@ void bta_hh_start_sdp(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
|
||||
|
||||
p_cb->sec_mask = p_data->api_conn.sec_mask;
|
||||
p_cb->mode = p_data->api_conn.mode;
|
||||
p_cb->new_mode = p_data->api_conn.mode;
|
||||
bta_hh_cb.p_cur = p_cb;
|
||||
|
||||
#if (BTA_HH_LE_INCLUDED == TRUE)
|
||||
@ -451,6 +452,8 @@ void bta_hh_sdp_cmpl(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
|
||||
HID_HostRemoveDev( p_cb->incoming_hid_handle);
|
||||
}
|
||||
conn_dat.status = status;
|
||||
/* check if host initiate the connection*/
|
||||
conn_dat.is_orig = !p_cb->incoming_conn;
|
||||
(* bta_hh_cb.p_cback)(BTA_HH_OPEN_EVT, (tBTA_HH *)&conn_dat);
|
||||
|
||||
/* move state machine W4_CONN ->IDLE */
|
||||
@ -521,6 +524,8 @@ void bta_hh_open_cmpl_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
|
||||
|
||||
memset((void *)&conn, 0, sizeof (tBTA_HH_CONN));
|
||||
conn.handle = dev_handle;
|
||||
/* check if host initiate the connection*/
|
||||
conn.is_orig = !p_cb->incoming_conn;
|
||||
bdcpy(conn.bda, p_cb->addr);
|
||||
|
||||
/* increase connection number */
|
||||
@ -587,6 +592,7 @@ void bta_hh_open_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
|
||||
APPL_TRACE_EVENT ("bta_hh_open_act: Device[%d] connected", dev_handle);
|
||||
#endif
|
||||
|
||||
p_cb->incoming_conn = TRUE;
|
||||
/* SDP has been done */
|
||||
if (p_cb->app_id != 0) {
|
||||
bta_hh_sm_execute(p_cb, BTA_HH_OPEN_CMPL_EVT, p_data);
|
||||
@ -594,7 +600,6 @@ void bta_hh_open_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
|
||||
/* app_id == 0 indicates an incoming conenction request arrives without SDP
|
||||
performed, do it first */
|
||||
{
|
||||
p_cb->incoming_conn = TRUE;
|
||||
/* store the handle here in case sdp fails - need to disconnect */
|
||||
p_cb->incoming_hid_handle = dev_handle;
|
||||
|
||||
@ -676,6 +681,11 @@ void bta_hh_handsk_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
|
||||
case BTA_HH_SET_IDLE_EVT :
|
||||
cback_data.handle = p_cb->hid_handle;
|
||||
cback_data.status = bta_hh_get_trans_status(p_data->hid_cback.data);
|
||||
if (cback_data.status == BTA_HH_OK) {
|
||||
p_cb->mode = p_cb->new_mode;
|
||||
} else {
|
||||
p_cb->new_mode = p_cb->mode;
|
||||
}
|
||||
(* bta_hh_cb.p_cback)(p_cb->w4_evt, (tBTA_HH *)&cback_data);
|
||||
p_cb->w4_evt = 0;
|
||||
break;
|
||||
@ -684,6 +694,8 @@ void bta_hh_handsk_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
|
||||
case BTA_HH_OPEN_EVT:
|
||||
conn.status = p_data->hid_cback.data ? BTA_HH_ERR_PROTO : BTA_HH_OK;
|
||||
conn.handle = p_cb->hid_handle;
|
||||
/* check if host initiate the connection*/
|
||||
conn.is_orig = !p_cb->incoming_conn;
|
||||
bdcpy(conn.bda, p_cb->addr);
|
||||
(* bta_hh_cb.p_cback)(p_cb->w4_evt, (tBTA_HH *)&conn);
|
||||
#if BTA_HH_DEBUG
|
||||
@ -787,6 +799,8 @@ void bta_hh_open_failure(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
|
||||
conn_dat.handle = p_cb->hid_handle;
|
||||
conn_dat.status = (reason == HID_ERR_AUTH_FAILED) ?
|
||||
BTA_HH_ERR_AUTH_FAILED : BTA_HH_ERR;
|
||||
/* check if host initiate the connection*/
|
||||
conn_dat.is_orig = !p_cb->incoming_conn;
|
||||
bdcpy(conn_dat.bda, p_cb->addr);
|
||||
HID_HostCloseDev(p_cb->hid_handle);
|
||||
|
||||
@ -836,6 +850,8 @@ void bta_hh_close_act (tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
|
||||
/* Failure in opening connection */
|
||||
conn_dat.handle = p_cb->hid_handle;
|
||||
conn_dat.status = (reason == HID_ERR_AUTH_FAILED) ? BTA_HH_ERR_AUTH_FAILED : BTA_HH_ERR;
|
||||
/* check if host initiate the connection*/
|
||||
conn_dat.is_orig = !p_cb->incoming_conn;
|
||||
bdcpy(conn_dat.bda, p_cb->addr);
|
||||
HID_HostCloseDev(p_cb->hid_handle);
|
||||
|
||||
@ -1019,7 +1035,9 @@ void bta_hh_maint_dev_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
|
||||
*******************************************************************************/
|
||||
void bta_hh_write_dev_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
|
||||
{
|
||||
tHID_STATUS status;
|
||||
tBTA_HH_CBDATA cbdata = {BTA_HH_OK, 0};
|
||||
tBTA_HH_API_SENDDATA send_data = {BTA_HH_OK, 0, 0};
|
||||
UINT16 event = (p_data->api_sndcmd.t_type - BTA_HH_FST_BTE_TRANS_EVT) +
|
||||
BTA_HH_FST_TRANS_CB_EVT;
|
||||
|
||||
@ -1031,25 +1049,33 @@ void bta_hh_write_dev_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
|
||||
{
|
||||
|
||||
cbdata.handle = p_cb->hid_handle;
|
||||
send_data.handle = p_cb->hid_handle;
|
||||
|
||||
/* match up BTE/BTA report/boot mode def */
|
||||
if (p_data->api_sndcmd.t_type == HID_TRANS_SET_PROTOCOL) {
|
||||
p_cb->new_mode = p_data->api_sndcmd.param;
|
||||
p_data->api_sndcmd.param = ( p_data->api_sndcmd.param == BTA_HH_PROTO_RPT_MODE) ? \
|
||||
HID_PAR_PROTOCOL_REPORT : HID_PAR_PROTOCOL_BOOT_MODE;
|
||||
}
|
||||
|
||||
if (HID_HostWriteDev (p_cb->hid_handle,
|
||||
p_data->api_sndcmd.t_type,
|
||||
p_data->api_sndcmd.param,
|
||||
p_data->api_sndcmd.data,
|
||||
p_data->api_sndcmd.rpt_id,
|
||||
p_data->api_sndcmd.p_data) != HID_SUCCESS) {
|
||||
APPL_TRACE_ERROR("HID_HostWriteDev Error ");
|
||||
status = HID_HostWriteDev(p_cb->hid_handle, p_data->api_sndcmd.t_type, p_data->api_sndcmd.param,
|
||||
p_data->api_sndcmd.data, p_data->api_sndcmd.rpt_id, p_data->api_sndcmd.p_data);
|
||||
if (status != HID_SUCCESS) {
|
||||
APPL_TRACE_ERROR("HID_HostWriteDev status:%d", status);
|
||||
cbdata.status = BTA_HH_ERR;
|
||||
send_data.status = BTA_HH_ERR;
|
||||
|
||||
if (p_data->api_sndcmd.t_type != HID_TRANS_CONTROL &&
|
||||
p_data->api_sndcmd.t_type != HID_TRANS_DATA) {
|
||||
(* bta_hh_cb.p_cback)(event, (tBTA_HH *)&cbdata);
|
||||
if (p_data->api_sndcmd.t_type != HID_TRANS_CONTROL) {
|
||||
switch (p_data->api_sndcmd.t_type) {
|
||||
case HID_TRANS_DATA:
|
||||
event = BTA_HH_DATA_EVT;
|
||||
send_data.reason = status;
|
||||
(*bta_hh_cb.p_cback)(event, (tBTA_HH *)&send_data);
|
||||
break;
|
||||
default:
|
||||
(*bta_hh_cb.p_cback)(event, (tBTA_HH *)&cbdata);
|
||||
break;
|
||||
}
|
||||
} else if (p_data->api_sndcmd.param == BTA_HH_CTRL_VIRTUAL_CABLE_UNPLUG) {
|
||||
(* bta_hh_cb.p_cback)(BTA_HH_VC_UNPLUG_EVT, (tBTA_HH *)&cbdata);
|
||||
}
|
||||
@ -1070,6 +1096,7 @@ void bta_hh_write_dev_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
|
||||
p_cb->w4_evt = event;
|
||||
break;
|
||||
case HID_TRANS_DATA: /* output report */
|
||||
(*bta_hh_cb.p_cback)(BTA_HH_DATA_EVT, (tBTA_HH *)&send_data);
|
||||
/* fall through */
|
||||
case HID_TRANS_CONTROL:
|
||||
/* no handshake event will be generated */
|
||||
@ -1098,7 +1125,6 @@ void bta_hh_write_dev_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
|
||||
bta_sys_busy(BTA_ID_HH, p_cb->app_id, p_cb->addr);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -24,9 +24,9 @@
|
||||
******************************************************************************/
|
||||
|
||||
#include "common/bt_target.h"
|
||||
#include "bta/bta_hh_api.h"
|
||||
|
||||
#if defined(BTA_HH_INCLUDED) && (BTA_HH_INCLUDED == TRUE)
|
||||
#include "bta/bta_hh_api.h"
|
||||
|
||||
|
||||
/* max number of device types supported by BTA */
|
||||
|
@ -32,7 +32,7 @@
|
||||
#include "bta/utl.h"
|
||||
|
||||
#define LOG_TAG "bt_bta_hh"
|
||||
#include "osi/include/log.h"
|
||||
// #include "osi/include/log.h"
|
||||
|
||||
#ifndef BTA_HH_LE_RECONN
|
||||
#define BTA_HH_LE_RECONN TRUE
|
||||
|
@ -292,6 +292,8 @@ void bta_hh_sm_execute(tBTA_HH_DEV_CB *p_cb, UINT16 event, tBTA_HH_DATA *p_data)
|
||||
bdcpy(cback_data.conn.bda, ((tBTA_HH_API_CONN *)p_data)->bd_addr);
|
||||
cback_data.conn.status = BTA_HH_ERR_DB_FULL;
|
||||
cback_data.conn.handle = BTA_HH_INVALID_HANDLE;
|
||||
/* check if host initiate the connection*/
|
||||
cback_data.conn.is_orig = !p_cb->incoming_conn;
|
||||
break;
|
||||
/* DB full, BTA_HhAddDev */
|
||||
case BTA_HH_API_MAINT_DEV_EVT:
|
||||
@ -340,7 +342,7 @@ void bta_hh_sm_execute(tBTA_HH_DEV_CB *p_cb, UINT16 event, tBTA_HH_DATA *p_data)
|
||||
|
||||
default:
|
||||
/* invalid handle, call bad API event */
|
||||
APPL_TRACE_ERROR("wrong device handle: [%d]", p_data->hdr.layer_specific);
|
||||
APPL_TRACE_ERROR("wrong device handle: [%d], event:%d", p_data->hdr.layer_specific, event - BTA_HH_API_OPEN_EVT);
|
||||
/* Free the callback buffer now */
|
||||
if (p_data != NULL && p_data->hid_cback.p_data != NULL) {
|
||||
osi_free(p_data->hid_cback.p_data);
|
||||
@ -443,6 +445,10 @@ BOOLEAN bta_hh_hdl_event(BT_HDR *p_msg)
|
||||
}
|
||||
} else if (p_msg->event == BTA_HH_INT_OPEN_EVT) {
|
||||
index = bta_hh_find_cb(((tBTA_HH_CBACK_DATA *)p_msg)->addr);
|
||||
uint8_t hdl = BTA_HH_IDX_INVALID;
|
||||
if (HID_HostGetDev(((tBTA_HH_CBACK_DATA *)p_msg)->addr, &hdl) == HID_SUCCESS && hdl != BTA_HH_IDX_INVALID) {
|
||||
bta_hh_cb.cb_index[hdl] = bta_hh_cb.kdev[index].index;
|
||||
}
|
||||
} else {
|
||||
index = bta_hh_dev_handle_to_cb_idx((UINT8)p_msg->layer_specific);
|
||||
}
|
||||
|
@ -237,7 +237,7 @@ BOOLEAN bta_hh_tod_spt(tBTA_HH_DEV_CB *p_cb, UINT8 sub_class)
|
||||
}
|
||||
}
|
||||
#if BTA_HH_DEBUG
|
||||
APPL_TRACE_EVENT("bta_hh_tod_spt sub_class:0x%x NOT supported", sub_class);
|
||||
APPL_TRACE_ERROR("bta_hh_tod_spt sub_class:0x%x NOT supported", sub_class);
|
||||
#endif
|
||||
return FALSE;
|
||||
}
|
||||
@ -460,9 +460,11 @@ void bta_hh_cleanup_disable(tBTA_HH_STATUS status)
|
||||
}
|
||||
utl_freebuf((void **)&bta_hh_cb.p_disc_db);
|
||||
|
||||
(* bta_hh_cb.p_cback)(BTA_HH_DISABLE_EVT, (tBTA_HH *)&status);
|
||||
/* all connections are down, no waiting for diconnect */
|
||||
memset(&bta_hh_cb, 0, sizeof(tBTA_HH_CB));
|
||||
if (bta_hh_cb.p_cback) {
|
||||
(*bta_hh_cb.p_cback)(BTA_HH_DISABLE_EVT, (tBTA_HH*)&status);
|
||||
/* all connections are down, no waiting for diconnect */
|
||||
memset(&bta_hh_cb, 0, sizeof(tBTA_HH_CB));
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
|
@ -243,6 +243,7 @@ typedef struct {
|
||||
UINT8 incoming_hid_handle; /* temporary handle for incoming connection? */
|
||||
BOOLEAN opened; /* TRUE if device successfully opened HID connection */
|
||||
tBTA_HH_PROTO_MODE mode; /* protocol mode */
|
||||
tBTA_HH_PROTO_MODE new_mode; /* protocol mode */
|
||||
tBTA_HH_STATE state; /* CB state */
|
||||
|
||||
#if (BTA_HH_LE_INCLUDED == TRUE)
|
||||
@ -364,6 +365,7 @@ extern void bta_hh_disc_cmpl(void);
|
||||
extern tBTA_HH_STATUS bta_hh_read_ssr_param(BD_ADDR bd_addr, UINT16 *p_max_ssr_lat, UINT16 *p_min_ssr_tout);
|
||||
|
||||
/* functions for LE HID */
|
||||
#if (BTA_HH_LE_INCLUDED == TRUE)
|
||||
extern void bta_hh_le_enable(void);
|
||||
extern BOOLEAN bta_hh_le_is_hh_gatt_if(tBTA_GATTC_IF client_if);
|
||||
extern void bta_hh_le_deregister(void);
|
||||
@ -391,6 +393,7 @@ extern void bta_hh_security_cmpl(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf);
|
||||
extern void bta_hh_le_update_scpp(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf);
|
||||
extern void bta_hh_le_notify_enc_cmpl(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data);
|
||||
extern void bta_hh_ci_load_rpt (tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_buf);
|
||||
#endif
|
||||
|
||||
#if BTA_HH_DEBUG
|
||||
extern void bta_hh_trace_dev_db(void);
|
||||
|
@ -78,7 +78,7 @@ typedef UINT8 tBTA_STATUS;
|
||||
#define BTA_SAP_SERVICE_ID 17 /* SIM Access profile */
|
||||
#define BTA_A2DP_SINK_SERVICE_ID 18 /* A2DP Sink */
|
||||
#define BTA_AVRCP_SERVICE_ID 19 /* A/V remote control */
|
||||
#define BTA_HID_SERVICE_ID 20 /* HID */
|
||||
#define BTA_HID_SERVICE_ID 20 /* HID Host*/
|
||||
#define BTA_VDP_SERVICE_ID 21 /* Video distribution */
|
||||
#define BTA_PBAP_SERVICE_ID 22 /* PhoneBook Access Server*/
|
||||
#define BTA_HSP_HS_SERVICE_ID 23 /* HFP HS role */
|
||||
@ -1331,8 +1331,8 @@ typedef UINT8 tBTA_DM_PM_ACTION;
|
||||
#endif
|
||||
|
||||
#ifndef BTA_DM_PM_SNIFF2_MAX
|
||||
#define BTA_DM_PM_SNIFF2_MAX 180
|
||||
#define BTA_DM_PM_SNIFF2_MIN 150
|
||||
#define BTA_DM_PM_SNIFF2_MAX 54 //180
|
||||
#define BTA_DM_PM_SNIFF2_MIN 30 //150
|
||||
#define BTA_DM_PM_SNIFF2_ATTEMPT 4
|
||||
#define BTA_DM_PM_SNIFF2_TIMEOUT 1
|
||||
#endif
|
||||
@ -1345,8 +1345,8 @@ typedef UINT8 tBTA_DM_PM_ACTION;
|
||||
#endif
|
||||
|
||||
#ifndef BTA_DM_PM_SNIFF4_MAX
|
||||
#define BTA_DM_PM_SNIFF4_MAX 54
|
||||
#define BTA_DM_PM_SNIFF4_MIN 30
|
||||
#define BTA_DM_PM_SNIFF4_MAX 18 //54
|
||||
#define BTA_DM_PM_SNIFF4_MIN 10 //30
|
||||
#define BTA_DM_PM_SNIFF4_ATTEMPT 4
|
||||
#define BTA_DM_PM_SNIFF4_TIMEOUT 1
|
||||
#endif
|
||||
|
295
components/bt/host/bluedroid/bta/include/bta/bta_hd_api.h
Normal file
295
components/bt/host/bluedroid/bta/include/bta/bta_hd_api.h
Normal file
@ -0,0 +1,295 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
* Copyright (C) 2002-2012 Broadcom Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef BTA_HD_API_H
|
||||
#define BTA_HD_API_H
|
||||
|
||||
#include "bta_api.h"
|
||||
#include "stack/hidd_api.h"
|
||||
|
||||
#if BTA_HD_INCLUDED == TRUE
|
||||
|
||||
/*****************************************************************************
|
||||
* Constants and Type Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef BTA_HD_DEBUG
|
||||
#define BTA_HD_DEBUG TRUE
|
||||
#endif
|
||||
|
||||
/* BTA HID Device callback events */
|
||||
#define BTA_HD_ENABLE_EVT 0 /* BT-HD enabled */
|
||||
#define BTA_HD_DISABLE_EVT 1 /* BT-HD disabled */
|
||||
#define BTA_HD_REGISTER_APP_EVT 2 /* application registered */
|
||||
#define BTA_HD_UNREGISTER_APP_EVT 3 /* application unregistered */
|
||||
#define BTA_HD_OPEN_EVT 4 /* connection to host opened */
|
||||
#define BTA_HD_CLOSE_EVT 5 /* connection to host closed */
|
||||
#define BTA_HD_GET_REPORT_EVT 6 /* GET_REPORT request from host */
|
||||
#define BTA_HD_SET_REPORT_EVT 7 /* SET_REPORT request from host */
|
||||
#define BTA_HD_SET_PROTOCOL_EVT 8 /* SET_PROTOCOL request from host */
|
||||
#define BTA_HD_INTR_DATA_EVT 9 /* DATA received from host on intr */
|
||||
#define BTA_HD_VC_UNPLUG_EVT 10 /* Virtual Cable Unplug */
|
||||
// #define BTA_HD_CONN_STATE_EVT 11 /* Report connection state change */
|
||||
#define BTA_HD_SEND_REPORT_EVT 12 /* Send report finish */
|
||||
#define BTA_HD_REPORT_ERR_EVT 13 /* Report Handshake finish */
|
||||
#define BTA_HD_API_ERR_EVT 99 /* BT-HD API error */
|
||||
|
||||
typedef uint16_t tBTA_HD_EVT;
|
||||
|
||||
enum { BTA_HD_OK, BTA_HD_ERROR };
|
||||
|
||||
typedef enum {
|
||||
BTA_HD_CONN_STATE_CONNECTED,
|
||||
BTA_HD_CONN_STATE_CONNECTING,
|
||||
BTA_HD_CONN_STATE_DISCONNECTED,
|
||||
BTA_HD_CONN_STATE_DISCONNECTING,
|
||||
BTA_HD_CONN_STATE_UNKNOWN
|
||||
} tBTA_HD_CONN_STAT;
|
||||
|
||||
typedef uint8_t tBTA_HD_STATUS;
|
||||
typedef tHID_DEV_DSCP_INFO tBTA_HD_DEV_DESCR;
|
||||
|
||||
typedef struct {
|
||||
char *p_name;
|
||||
char *p_description;
|
||||
char *p_provider;
|
||||
uint8_t subclass;
|
||||
tBTA_HD_DEV_DESCR descriptor;
|
||||
} tBTA_HD_APP_INFO;
|
||||
|
||||
typedef struct {
|
||||
uint8_t service_type;
|
||||
uint32_t token_rate;
|
||||
uint32_t token_bucket_size;
|
||||
uint32_t peak_bandwidth;
|
||||
uint32_t access_latency;
|
||||
uint32_t delay_variation;
|
||||
} tBTA_HD_QOS_INFO;
|
||||
|
||||
typedef struct {
|
||||
bool use_intr;
|
||||
uint8_t type;
|
||||
uint8_t id;
|
||||
uint16_t len;
|
||||
uint8_t *p_data;
|
||||
} tBTA_HD_REPORT;
|
||||
|
||||
typedef struct {
|
||||
tBTA_HD_STATUS status;
|
||||
bool in_use;
|
||||
BD_ADDR bda;
|
||||
} tBTA_HD_REG_STATUS;
|
||||
|
||||
typedef struct {
|
||||
BD_ADDR bda;
|
||||
tBTA_HD_STATUS status;
|
||||
tBTA_HD_CONN_STAT conn_status;
|
||||
} tBTA_HD_CONN;
|
||||
|
||||
typedef struct {
|
||||
uint8_t report_type;
|
||||
uint8_t report_id;
|
||||
uint16_t buffer_size;
|
||||
} tBTA_HD_GET_REPORT;
|
||||
|
||||
typedef struct {
|
||||
uint8_t report_type;
|
||||
uint8_t report_id;
|
||||
uint16_t len;
|
||||
uint8_t *p_data;
|
||||
} tBTA_HD_SET_REPORT;
|
||||
|
||||
typedef uint8_t tBTA_HD_SET_PROTOCOL;
|
||||
|
||||
typedef struct {
|
||||
uint8_t report_id;
|
||||
uint16_t len;
|
||||
uint8_t *p_data;
|
||||
} tBTA_HD_INTR_DATA;
|
||||
|
||||
typedef struct {
|
||||
tBTA_HD_STATUS status;
|
||||
uint8_t reason;
|
||||
uint8_t report_type;
|
||||
uint8_t report_id;
|
||||
} tBTA_HD_API_SEND_REPORT;
|
||||
|
||||
typedef struct {
|
||||
tBTA_HD_STATUS status;
|
||||
uint8_t reason;
|
||||
} tBTA_HD_API_REPORT_ERR;
|
||||
|
||||
/* union of data associated with HD callback */
|
||||
typedef union {
|
||||
tBTA_HD_STATUS status; /* BTA_HD_ENABLE_EVT
|
||||
BTA_HD_DISABLE_EVT
|
||||
BTA_HD_UNREGISTER_APP_EVT */
|
||||
tBTA_HD_REG_STATUS reg_status; /* BTA_HD_REGISTER_APP_EVT */
|
||||
tBTA_HD_CONN conn; /* BTA_HD_OPEN_EVT
|
||||
BTA_HD_CLOSE_EVT
|
||||
BTA_HD_VC_UNPLUG_EVT
|
||||
BTA_HD_OWN_VC_UNPLUG_EVT */
|
||||
tBTA_HD_GET_REPORT get_report; /* BTA_HD_GET_REPORT */
|
||||
tBTA_HD_SET_REPORT set_report; /* BTA_HD_SET_REPORT */
|
||||
tBTA_HD_SET_PROTOCOL set_protocol; /* BTA_HD_SETPROTOCOL */
|
||||
tBTA_HD_INTR_DATA intr_data; /* BTA_HD_INTR_DATA_EVT */
|
||||
tBTA_HD_API_SEND_REPORT send_report; /* BTA_HD_API_SEND_REPORT_EVT */
|
||||
tBTA_HD_API_REPORT_ERR report_err; /* BTA_HD_API_REPORT_ERR_EVT */
|
||||
} tBTA_HD;
|
||||
|
||||
/* BTA HD callback function */
|
||||
typedef void (tBTA_HD_CBACK)(tBTA_HD_EVT event, tBTA_HD *p_data);
|
||||
|
||||
/*****************************************************************************
|
||||
* External Function Declarations
|
||||
****************************************************************************/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function BTA_HhRegister
|
||||
*
|
||||
* Description This function enable HID host and registers HID-Host with
|
||||
* lower layers.
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
extern void BTA_HdEnable(tBTA_HD_CBACK *p_cback);
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function BTA_HhDeregister
|
||||
*
|
||||
* Description This function is called when the host is about power down.
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
extern void BTA_HdDisable(void);
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function BTA_HdRegisterApp
|
||||
*
|
||||
* Description This function is called when application should be
|
||||
* registered
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
extern void BTA_HdRegisterApp(tBTA_HD_APP_INFO *p_app_info, tBTA_HD_QOS_INFO *p_in_qos, tBTA_HD_QOS_INFO *p_out_qos);
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function BTA_HdUnregisterApp
|
||||
*
|
||||
* Description This function is called when application should be
|
||||
* unregistered
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
extern void BTA_HdUnregisterApp(void);
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function BTA_HdSendReport
|
||||
*
|
||||
* Description This function is called when report is to be sent
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
extern void BTA_HdSendReport(tBTA_HD_REPORT *p_report);
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function BTA_HdVirtualCableUnplug
|
||||
*
|
||||
* Description This function is called when VCU shall be sent
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
extern void BTA_HdVirtualCableUnplug(void);
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function BTA_HdConnect
|
||||
*
|
||||
* Description This function is called when connection to host shall be
|
||||
* made.
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
extern void BTA_HdConnect(BD_ADDR addr);
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function BTA_HdDisconnect
|
||||
*
|
||||
* Description This function is called when host shall be disconnected
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
extern void BTA_HdDisconnect(void);
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function BTA_HdAddDevice
|
||||
*
|
||||
* Description This function is called when a device is virtually cabled
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
extern void BTA_HdAddDevice(BD_ADDR addr);
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function BTA_HdRemoveDevice
|
||||
*
|
||||
* Description This function is called when a device is virtually uncabled
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
extern void BTA_HdRemoveDevice(BD_ADDR addr);
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function BTA_HdReportError
|
||||
*
|
||||
* Description This function is called when reporting error for set report
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
extern void BTA_HdReportError(uint8_t error);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* BTA_HD_INCLUDED */
|
||||
#endif /* BTA_HD_API_H */
|
@ -58,7 +58,8 @@
|
||||
#define BTA_HH_VC_UNPLUG_EVT 13 /* virtually unplugged */
|
||||
#define BTA_HH_DATA_EVT 15
|
||||
#define BTA_HH_API_ERR_EVT 16 /* API error is caught */
|
||||
#define BTA_HH_UPDATE_SCPP_EVT 17 /* update scan paramter complete */
|
||||
#define BTA_HH_UPDATE_SCPP_EVT 17 /* update scan paramter complete */
|
||||
#define BTA_HH_DATA_IND_EVT 18 /* Data on interrupt channel */
|
||||
|
||||
typedef UINT16 tBTA_HH_EVT;
|
||||
|
||||
@ -131,8 +132,8 @@ enum {
|
||||
BTA_HH_ERR_TOD_UNSPT, /* type of device not supported */
|
||||
BTA_HH_ERR_NO_RES, /* out of system resources */
|
||||
BTA_HH_ERR_AUTH_FAILED, /* authentication fail */
|
||||
BTA_HH_ERR_HDL,
|
||||
BTA_HH_ERR_SEC
|
||||
BTA_HH_ERR_HDL, /* connection handle error */
|
||||
BTA_HH_ERR_SEC, /* encryption error */
|
||||
};
|
||||
typedef UINT8 tBTA_HH_STATUS;
|
||||
|
||||
@ -210,6 +211,7 @@ typedef struct {
|
||||
BD_ADDR bda; /* HID device bd address */
|
||||
tBTA_HH_STATUS status; /* operation status */
|
||||
UINT8 handle; /* device handle */
|
||||
BOOLEAN is_orig; /* indicate if host initiate connection */
|
||||
#if (defined BTA_HH_LE_INCLUDED && BTA_HH_LE_INCLUDED == TRUE)
|
||||
BOOLEAN le_hid; /* is LE devices? */
|
||||
BOOLEAN scps_supported; /* scan parameter service supported */
|
||||
@ -257,9 +259,9 @@ typedef struct {
|
||||
typedef struct {
|
||||
tBTA_HH_BOOT_RPT_ID dev_type; /* type of device report */
|
||||
union {
|
||||
tBTA_HH_KEYBD_RPT keybd_rpt; /* keyboard report */
|
||||
tBTA_HH_MICE_RPT mice_rpt; /* mouse report */
|
||||
} data_rpt;
|
||||
tBTA_HH_KEYBD_RPT keybd_rpt; /* keyboard report */
|
||||
tBTA_HH_MICE_RPT mice_rpt; /* mouse report */
|
||||
} data_rpt;
|
||||
} tBTA_HH_BOOT_RPT;
|
||||
|
||||
/* handshake data */
|
||||
@ -267,13 +269,29 @@ typedef struct {
|
||||
tBTA_HH_STATUS status; /* handshake status */
|
||||
UINT8 handle; /* device handle */
|
||||
union {
|
||||
tBTA_HH_PROTO_MODE proto_mode; /* GET_PROTO_EVT :protocol mode */
|
||||
BT_HDR *p_rpt_data; /* GET_RPT_EVT : report data */
|
||||
UINT8 idle_rate; /* GET_IDLE_EVT : idle rate */
|
||||
} rsp_data;
|
||||
tBTA_HH_PROTO_MODE proto_mode; /* GET_PROTO_EVT :protocol mode */
|
||||
BT_HDR *p_rpt_data; /* GET_RPT_EVT : report data */
|
||||
UINT8 idle_rate; /* GET_IDLE_EVT : idle rate */
|
||||
} rsp_data;
|
||||
|
||||
} tBTA_HH_HSDATA;
|
||||
|
||||
|
||||
/* upper layer send data */
|
||||
typedef struct {
|
||||
tBTA_HH_STATUS status; /* handshake status */
|
||||
UINT8 handle; /* device handle */
|
||||
UINT8 reason; /* send data failed reason */
|
||||
} tBTA_HH_API_SENDDATA;
|
||||
|
||||
/* interrupt channel data */
|
||||
typedef struct {
|
||||
tBTA_HH_STATUS status; /* handshake status */
|
||||
UINT8 handle; /* device handle */
|
||||
tBTA_HH_PROTO_MODE proto_mode; /* protocol mode */
|
||||
BT_HDR *p_data; /* DATA_EVT : feature report data */
|
||||
} tBTA_HH_INTDATA;
|
||||
|
||||
/* union of data associated with HD callback */
|
||||
typedef union {
|
||||
tBTA_HH_DEV_INFO dev_info; /* BTA_HH_ADD_DEV_EVT, BTA_HH_RMV_DEV_EVT */
|
||||
@ -290,10 +308,12 @@ typedef union {
|
||||
BTA_HH_GET_RPT_EVT
|
||||
BTA_HH_GET_PROTO_EVT
|
||||
BTA_HH_GET_IDLE_EVT */
|
||||
tBTA_HH_API_SENDDATA send_data; /* BTA_HH_DATA_EVT */
|
||||
tBTA_HH_INTDATA int_data; /* BTA_HH_DATA_IND_EVT */
|
||||
} tBTA_HH;
|
||||
|
||||
/* BTA HH callback function */
|
||||
typedef void (tBTA_HH_CBACK) (tBTA_HH_EVT event, tBTA_HH *p_data);
|
||||
typedef void (tBTA_HH_CBACK)(tBTA_HH_EVT event, tBTA_HH *p_data);
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
|
@ -16,11 +16,13 @@
|
||||
#include "btc/btc_storage.h"
|
||||
#include "btc/btc_util.h"
|
||||
#include "osi/osi.h"
|
||||
#include "osi/allocator.h"
|
||||
#include "common/bt_trace.h"
|
||||
#include "esp_system.h"
|
||||
#include "bta/bta_api.h"
|
||||
#include "device/bdaddr.h"
|
||||
#include "btc/btc_config.h"
|
||||
#include "btc_hh.h"
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
@ -247,3 +249,252 @@ bt_status_t btc_storage_get_bonded_bt_devices_list(bt_bdaddr_t *bond_dev, int *d
|
||||
|
||||
return BT_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
#if (defined BTC_HH_INCLUDED && BTC_HH_INCLUDED == TRUE)
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function btc_storage_add_hid_device_info
|
||||
*
|
||||
* Description BTC storage API - Adds the hid information of bonded hid
|
||||
* devices-to NVRAM
|
||||
*
|
||||
* Returns BT_STATUS_SUCCESS if the store was successful,
|
||||
* BT_STATUS_FAIL otherwise
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
bt_status_t btc_storage_add_hid_device_info(bt_bdaddr_t *remote_bd_addr, uint16_t attr_mask, uint8_t sub_class,
|
||||
uint8_t app_id, uint16_t vendor_id, uint16_t product_id, uint16_t version,
|
||||
uint8_t ctry_code, uint16_t ssr_max_latency, uint16_t ssr_min_tout,
|
||||
uint16_t dl_len, uint8_t *dsc_list)
|
||||
{
|
||||
BTC_TRACE_DEBUG("btc_storage_add_hid_device_info:");
|
||||
bdstr_t bdstr;
|
||||
bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr));
|
||||
btc_config_lock();
|
||||
int ret = btc_config_set_int(bdstr, "HidAttrMask", attr_mask);
|
||||
ret &= btc_config_set_int(bdstr, "HidSubClass", sub_class);
|
||||
ret &= btc_config_set_int(bdstr, "HidAppId", app_id);
|
||||
ret &= btc_config_set_int(bdstr, "HidVendorId", vendor_id);
|
||||
ret &= btc_config_set_int(bdstr, "HidProductId", product_id);
|
||||
ret &= btc_config_set_int(bdstr, "HidVersion", version);
|
||||
ret &= btc_config_set_int(bdstr, "HidCountryCode", ctry_code);
|
||||
ret &= btc_config_set_int(bdstr, "HidSSRMaxLatency", ssr_max_latency);
|
||||
ret &= btc_config_set_int(bdstr, "HidSSRMinTimeout", ssr_min_tout);
|
||||
if (dl_len > 0)
|
||||
btc_config_set_bin(bdstr, "HidDescriptor", dsc_list, dl_len);
|
||||
btc_config_flush();
|
||||
btc_config_unlock();
|
||||
|
||||
BTC_TRACE_DEBUG("Storage add hid device info %d\n", ret);
|
||||
return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function btc_storage_load_bonded_hid_info
|
||||
*
|
||||
* Description BTIF storage API - Loads hid info for all the bonded devices
|
||||
* from NVRAM and adds those devices to the BTA_HH.
|
||||
*
|
||||
* Returns BT_STATUS_SUCCESS if successful, BT_STATUS_FAIL otherwise
|
||||
*
|
||||
******************************************************************************/
|
||||
bt_status_t btc_storage_load_bonded_hid_info(void)
|
||||
{
|
||||
int value;
|
||||
btc_config_lock();
|
||||
for (const btc_config_section_iter_t *iter = btc_config_section_begin(); iter != btc_config_section_end();
|
||||
iter = btc_config_section_next(iter)) {
|
||||
const char *name = btc_config_section_name(iter);
|
||||
if (string_is_bdaddr(name) && btc_config_exist(name, BTC_STORAGE_LINK_KEY_TYPE_STR) &&
|
||||
btc_config_exist(name, BTC_STORAGE_PIN_LENGTH_STR) && btc_config_exist(name, BTC_STORAGE_SC_SUPPORT) &&
|
||||
btc_config_exist(name, BTC_STORAGE_LINK_KEY_STR) && btc_config_exist(name, "HidAttrMask")) {
|
||||
btc_config_get_int(name, "HidAttrMask", &value);
|
||||
uint16_t attr_mask = (uint16_t)value;
|
||||
|
||||
tBTA_HH_DEV_DSCP_INFO dscp_info;
|
||||
memset(&dscp_info, 0, sizeof(dscp_info));
|
||||
|
||||
btc_config_get_int(name, "HidSubClass", &value);
|
||||
uint8_t sub_class = (uint8_t)value;
|
||||
|
||||
btc_config_get_int(name, "HidAppId", &value);
|
||||
uint8_t app_id = (uint8_t)value;
|
||||
|
||||
btc_config_get_int(name, "HidVendorId", &value);
|
||||
dscp_info.vendor_id = (uint16_t)value;
|
||||
|
||||
btc_config_get_int(name, "HidProductId", &value);
|
||||
dscp_info.product_id = (uint16_t)value;
|
||||
|
||||
btc_config_get_int(name, "HidVersion", &value);
|
||||
dscp_info.version = (uint8_t)value;
|
||||
|
||||
btc_config_get_int(name, "HidCountryCode", &value);
|
||||
dscp_info.ctry_code = (uint8_t)value;
|
||||
|
||||
value = 0;
|
||||
btc_config_get_int(name, "HidSSRMaxLatency", &value);
|
||||
dscp_info.ssr_max_latency = (uint16_t)value;
|
||||
|
||||
value = 0;
|
||||
btc_config_get_int(name, "HidSSRMinTimeout", &value);
|
||||
dscp_info.ssr_min_tout = (uint16_t)value;
|
||||
|
||||
size_t len = btc_config_get_bin_length(name, "HidDescriptor");
|
||||
if (len > 0) {
|
||||
dscp_info.descriptor.dl_len = (uint16_t)len;
|
||||
dscp_info.descriptor.dsc_list = (uint8_t *)osi_malloc(len);
|
||||
btc_config_get_bin(name, "HidDescriptor", (uint8_t *)dscp_info.descriptor.dsc_list, &len);
|
||||
}
|
||||
|
||||
// add extracted information to BTA HH
|
||||
bt_bdaddr_t bd_addr;
|
||||
if (string_to_bdaddr(name, &bd_addr) && btc_hh_add_added_dev(*(BD_ADDR *)&bd_addr, attr_mask)) {
|
||||
BTA_HhAddDev(*(BD_ADDR *)&bd_addr, attr_mask, sub_class, app_id, dscp_info);
|
||||
}
|
||||
|
||||
if (dscp_info.descriptor.dsc_list) {
|
||||
osi_free(dscp_info.descriptor.dsc_list);
|
||||
dscp_info.descriptor.dsc_list = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
btc_config_unlock();
|
||||
return BT_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function btc_storage_remove_hid_info
|
||||
*
|
||||
* Description BTC storage API - Deletes the bonded hid device info from
|
||||
* NVRAM
|
||||
*
|
||||
* Returns BT_STATUS_SUCCESS if the deletion was successful,
|
||||
* BT_STATUS_FAIL otherwise
|
||||
*
|
||||
******************************************************************************/
|
||||
bt_status_t btc_storage_remove_hid_info(bt_bdaddr_t *remote_bd_addr)
|
||||
{
|
||||
bdstr_t bdstr;
|
||||
bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr));
|
||||
int ret = 1;
|
||||
btc_config_lock();
|
||||
if (btc_config_exist(bdstr, "HidAttrMask")) {
|
||||
ret &= btc_config_remove(bdstr, "HidAttrMask");
|
||||
}
|
||||
if (btc_config_exist(bdstr, "HidSubClass")) {
|
||||
ret &= btc_config_remove(bdstr, "HidSubClass");
|
||||
}
|
||||
if (btc_config_exist(bdstr, "HidAppId")) {
|
||||
ret &= btc_config_remove(bdstr, "HidAppId");
|
||||
}
|
||||
if (btc_config_exist(bdstr, "HidVendorId")) {
|
||||
ret &= btc_config_remove(bdstr, "HidVendorId");
|
||||
}
|
||||
if (btc_config_exist(bdstr, "HidProductId")) {
|
||||
ret &= btc_config_remove(bdstr, "HidProductId");
|
||||
}
|
||||
if (btc_config_exist(bdstr, "HidVersion")) {
|
||||
ret &= btc_config_remove(bdstr, "HidVersion");
|
||||
}
|
||||
if (btc_config_exist(bdstr, "HidCountryCode")) {
|
||||
ret &= btc_config_remove(bdstr, "HidCountryCode");
|
||||
}
|
||||
if (btc_config_exist(bdstr, "HidSSRMaxLatency")) {
|
||||
ret &= btc_config_remove(bdstr, "HidSSRMaxLatency");
|
||||
}
|
||||
if (btc_config_exist(bdstr, "HidSSRMinTimeout")) {
|
||||
ret &= btc_config_remove(bdstr, "HidSSRMinTimeout");
|
||||
}
|
||||
if (btc_config_exist(bdstr, "HidDescriptor")) {
|
||||
ret &= btc_config_remove(bdstr, "HidDescriptor");
|
||||
}
|
||||
btc_config_flush();
|
||||
btc_config_unlock();
|
||||
BTC_TRACE_DEBUG("%s ret:%d", __func__, ret);
|
||||
return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
|
||||
}
|
||||
#endif //(defined BTC_HH_INCLUDED && BTC_HH_INCLUDED == TRUE)
|
||||
|
||||
#if (defined BTC_HD_INCLUDED && BTC_HD_INCLUDED == TRUE)
|
||||
#include "bta/bta_hd_api.h"
|
||||
/*******************************************************************************
|
||||
* Function btc_storage_load_hidd
|
||||
*
|
||||
* Description Loads hidd bonded device and "plugs" it into hidd
|
||||
*
|
||||
* Returns BT_STATUS_SUCCESS if successful, BT_STATUS_FAIL otherwise
|
||||
*
|
||||
******************************************************************************/
|
||||
bt_status_t btc_storage_load_hidd(void)
|
||||
{
|
||||
bt_bdaddr_t bd_addr;
|
||||
int value;
|
||||
btc_config_lock();
|
||||
for (const btc_config_section_iter_t *iter = btc_config_section_begin(); iter != btc_config_section_end();
|
||||
iter = btc_config_section_next(iter)) {
|
||||
const char *name = btc_config_section_name(iter);
|
||||
if (string_is_bdaddr(name) && btc_config_exist(name, BTC_STORAGE_LINK_KEY_TYPE_STR) &&
|
||||
btc_config_exist(name, BTC_STORAGE_PIN_LENGTH_STR) && btc_config_exist(name, BTC_STORAGE_SC_SUPPORT) &&
|
||||
btc_config_exist(name, BTC_STORAGE_LINK_KEY_STR)) {
|
||||
BTC_TRACE_DEBUG("Remote device:%s", name);
|
||||
if (btc_config_get_int(name, "HidDeviceCabled", &value)) {
|
||||
string_to_bdaddr(name, &bd_addr);
|
||||
BTA_HdAddDevice(bd_addr.address);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
btc_config_unlock();
|
||||
return BT_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function btc_storage_set_hidd
|
||||
*
|
||||
* Description Stores hidd bonded device info in nvram.
|
||||
*
|
||||
* Returns BT_STATUS_SUCCESS
|
||||
*
|
||||
******************************************************************************/
|
||||
bt_status_t btc_storage_set_hidd(bt_bdaddr_t *remote_bd_addr)
|
||||
{
|
||||
bdstr_t bdstr = {0};
|
||||
bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr));
|
||||
btc_config_lock();
|
||||
int ret = btc_config_set_int(bdstr, "HidDeviceCabled", 1);
|
||||
btc_config_flush();
|
||||
btc_config_unlock();
|
||||
BTC_TRACE_DEBUG("%s ret:%d", __func__, ret);
|
||||
return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function btc_storage_remove_hidd
|
||||
*
|
||||
* Description Removes hidd bonded device info from nvram
|
||||
*
|
||||
* Returns BT_STATUS_SUCCESS
|
||||
*
|
||||
******************************************************************************/
|
||||
bt_status_t btc_storage_remove_hidd(bt_bdaddr_t *remote_bd_addr)
|
||||
{
|
||||
bdstr_t bdstr;
|
||||
int ret = 0;
|
||||
bdaddr_to_string(remote_bd_addr, bdstr, sizeof(bdstr));
|
||||
btc_config_lock();
|
||||
if (btc_config_exist(bdstr, "HidVersion")) {
|
||||
ret = btc_config_remove(bdstr, "HidDeviceCabled");
|
||||
}
|
||||
btc_config_flush();
|
||||
btc_config_unlock();
|
||||
|
||||
BTC_TRACE_DEBUG("%s ret:%d", __func__, ret);
|
||||
return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
|
||||
}
|
||||
#endif //(defined BTC_HD_INCLUDED && BTC_HD_INCLUDED == TRUE)
|
||||
|
@ -35,6 +35,10 @@
|
||||
#include "bta/bta_ag_api.h"
|
||||
#endif ///BTA_AG_INCLUDED == TRUE
|
||||
|
||||
#if (BTA_HH_INCLUDED == TRUE)
|
||||
#include "bta/bta_hh_api.h"
|
||||
#endif ///BTA_HH_INCLUDED == TRUE
|
||||
#include "bta/bta_hd_api.h"
|
||||
#include "common/bt_defs.h"
|
||||
#include "stack/btm_api.h"
|
||||
#include "bta/bta_api.h"
|
||||
@ -209,6 +213,56 @@ const char* dump_hf_call_setup_state(esp_hf_call_setup_status_t call_setup_state
|
||||
|
||||
#endif // #if (BTA_AG_INCLUDED == TRUE)
|
||||
|
||||
#if (BTA_HH_INCLUDED == TRUE)
|
||||
const char *dump_hh_event(uint16_t event)
|
||||
{
|
||||
switch (event) {
|
||||
CASE_RETURN_STR(BTA_HH_ENABLE_EVT)
|
||||
CASE_RETURN_STR(BTA_HH_DISABLE_EVT)
|
||||
CASE_RETURN_STR(BTA_HH_OPEN_EVT)
|
||||
CASE_RETURN_STR(BTA_HH_CLOSE_EVT)
|
||||
CASE_RETURN_STR(BTA_HH_GET_RPT_EVT)
|
||||
CASE_RETURN_STR(BTA_HH_SET_RPT_EVT)
|
||||
CASE_RETURN_STR(BTA_HH_GET_PROTO_EVT)
|
||||
CASE_RETURN_STR(BTA_HH_SET_PROTO_EVT)
|
||||
CASE_RETURN_STR(BTA_HH_GET_IDLE_EVT)
|
||||
CASE_RETURN_STR(BTA_HH_SET_IDLE_EVT)
|
||||
CASE_RETURN_STR(BTA_HH_GET_DSCP_EVT)
|
||||
CASE_RETURN_STR(BTA_HH_ADD_DEV_EVT)
|
||||
CASE_RETURN_STR(BTA_HH_RMV_DEV_EVT)
|
||||
CASE_RETURN_STR(BTA_HH_VC_UNPLUG_EVT)
|
||||
CASE_RETURN_STR(BTA_HH_DATA_EVT)
|
||||
CASE_RETURN_STR(BTA_HH_API_ERR_EVT)
|
||||
CASE_RETURN_STR(BTA_HH_UPDATE_SCPP_EVT)
|
||||
CASE_RETURN_STR(BTA_HH_DATA_IND_EVT)
|
||||
default:
|
||||
return "UNKNOWN MSG ID";
|
||||
}
|
||||
}
|
||||
#endif ///BTA_HH_INCLUDED
|
||||
|
||||
#if BTA_HD_INCLUDED == TRUE
|
||||
const char* dump_hd_event(uint16_t event) {
|
||||
switch (event) {
|
||||
CASE_RETURN_STR(BTA_HD_ENABLE_EVT)
|
||||
CASE_RETURN_STR(BTA_HD_DISABLE_EVT)
|
||||
CASE_RETURN_STR(BTA_HD_REGISTER_APP_EVT)
|
||||
CASE_RETURN_STR(BTA_HD_UNREGISTER_APP_EVT)
|
||||
CASE_RETURN_STR(BTA_HD_OPEN_EVT)
|
||||
CASE_RETURN_STR(BTA_HD_CLOSE_EVT)
|
||||
CASE_RETURN_STR(BTA_HD_GET_REPORT_EVT)
|
||||
CASE_RETURN_STR(BTA_HD_SET_REPORT_EVT)
|
||||
CASE_RETURN_STR(BTA_HD_SET_PROTOCOL_EVT)
|
||||
CASE_RETURN_STR(BTA_HD_INTR_DATA_EVT)
|
||||
CASE_RETURN_STR(BTA_HD_VC_UNPLUG_EVT)
|
||||
//CASE_RETURN_STR(BTA_HD_CONN_STATE_EVT)
|
||||
CASE_RETURN_STR(BTA_HD_API_ERR_EVT)
|
||||
default:
|
||||
return "UNKNOWN MSG ID";
|
||||
}
|
||||
}
|
||||
#endif ///BTA_HD_INCLUDED
|
||||
|
||||
UINT32 devclass2uint(DEV_CLASS dev_class)
|
||||
{
|
||||
UINT32 cod = 0;
|
||||
|
@ -27,6 +27,10 @@
|
||||
#define BTC_STORAGE_PIN_LENGTH_STR "PinLength"
|
||||
#define BTC_STORAGE_SC_SUPPORT "SCSupport"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function btc_storage_add_bonded_device
|
||||
@ -91,4 +95,85 @@ int btc_storage_get_num_bt_bond_devices(void);
|
||||
*******************************************************************************/
|
||||
bt_status_t btc_storage_get_bonded_bt_devices_list(bt_bdaddr_t *bond_dev, int *dev_num);
|
||||
|
||||
#if (defined BTC_HH_INCLUDED && BTC_HH_INCLUDED == TRUE)
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function btc_storage_add_hid_device_info
|
||||
*
|
||||
* Description BTC storage API - Adds the hid information of bonded hid
|
||||
* devices-to NVRAM
|
||||
*
|
||||
* Returns BT_STATUS_SUCCESS if the store was successful,
|
||||
* BT_STATUS_FAIL otherwise
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
bt_status_t btc_storage_add_hid_device_info(bt_bdaddr_t *remote_bd_addr, uint16_t attr_mask, uint8_t sub_class,
|
||||
uint8_t app_id, uint16_t vendor_id, uint16_t product_id, uint16_t version,
|
||||
uint8_t ctry_code, uint16_t ssr_max_latency, uint16_t ssr_min_tout,
|
||||
uint16_t dl_len, uint8_t *dsc_list);
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function btc_storage_load_bonded_hid_info
|
||||
*
|
||||
* Description BTIF storage API - Loads hid info for all the bonded devices
|
||||
* from NVRAM and adds those devices to the BTA_HH.
|
||||
*
|
||||
* Returns BT_STATUS_SUCCESS if successful, BT_STATUS_FAIL otherwise
|
||||
*
|
||||
******************************************************************************/
|
||||
bt_status_t btc_storage_load_bonded_hid_info(void);
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function btc_storage_remove_hid_info
|
||||
*
|
||||
* Description BTC storage API - Deletes the bonded hid device info from
|
||||
* NVRAM
|
||||
*
|
||||
* Returns BT_STATUS_SUCCESS if the deletion was successful,
|
||||
* BT_STATUS_FAIL otherwise
|
||||
*
|
||||
******************************************************************************/
|
||||
bt_status_t btc_storage_remove_hid_info(bt_bdaddr_t *remote_bd_addr);
|
||||
#endif // (defined BTC_HH_INCLUDED && BTC_HH_INCLUDED == TRUE)
|
||||
|
||||
#if (defined BTC_HD_INCLUDED && BTC_HD_INCLUDED == TRUE)
|
||||
/*******************************************************************************
|
||||
* Function btc_storage_load_hidd
|
||||
*
|
||||
* Description Loads hidd bonded device and "plugs" it into hidd
|
||||
*
|
||||
* Returns BT_STATUS_SUCCESS if successful, BT_STATUS_FAIL otherwise
|
||||
*
|
||||
******************************************************************************/
|
||||
bt_status_t btc_storage_load_hidd(void);
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function btc_storage_set_hidd
|
||||
*
|
||||
* Description Stores hidd bonded device info in nvram.
|
||||
*
|
||||
* Returns BT_STATUS_SUCCESS
|
||||
*
|
||||
******************************************************************************/
|
||||
bt_status_t btc_storage_set_hidd(bt_bdaddr_t *remote_bd_addr);
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function btc_storage_remove_hidd
|
||||
*
|
||||
* Description Removes hidd bonded device info from nvram
|
||||
*
|
||||
* Returns BT_STATUS_SUCCESS
|
||||
*
|
||||
******************************************************************************/
|
||||
bt_status_t btc_storage_remove_hidd(bt_bdaddr_t *remote_bd_addr);
|
||||
#endif //(defined BTC_HD_INCLUDED && BTC_HD_INCLUDED == TRUE)
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* BTC_STORAGE_H */
|
||||
|
@ -31,7 +31,9 @@
|
||||
********************************************************************************/
|
||||
typedef char bdstr_t[18];
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/*******************************************************************************
|
||||
** Functions
|
||||
********************************************************************************/
|
||||
@ -48,6 +50,14 @@ const char *dump_hf_call_state(esp_hf_call_status_t call_state);
|
||||
const char* dump_hf_call_setup_state(esp_hf_call_setup_status_t call_setup_state);
|
||||
#endif
|
||||
|
||||
#if(BTA_HD_INCLUDED == TRUE)
|
||||
const char* dump_hd_event(uint16_t event);
|
||||
#endif
|
||||
|
||||
#if(BTA_HH_INCLUDED == TRUE)
|
||||
const char* dump_hh_event(uint16_t event);
|
||||
#endif
|
||||
|
||||
UINT32 devclass2uint(DEV_CLASS dev_class);
|
||||
void uint2devclass(UINT32 dev, DEV_CLASS dev_class);
|
||||
void uuid128_be_to_esp_uuid(esp_bt_uuid_t *u, uint8_t* uuid128);
|
||||
@ -58,4 +68,8 @@ esp_bt_status_t btc_hci_to_esp_status(uint8_t hci_status);
|
||||
esp_bt_status_t btc_btm_status_to_esp_status (uint8_t btm_status);
|
||||
esp_bt_status_t btc_bta_status_to_esp_status (uint8_t bta_status);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __BTC_UTIL_H__ */
|
||||
|
152
components/bt/host/bluedroid/btc/profile/std/hid/bta_hh_co.c
Normal file
152
components/bt/host/bluedroid/btc/profile/std/hid/bta_hh_co.c
Normal file
@ -0,0 +1,152 @@
|
||||
#include "btc_hh.h"
|
||||
#include "osi/allocator.h"
|
||||
#include "string.h"
|
||||
#if HID_HOST_INCLUDED == TRUE
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function bta_hh_co_open
|
||||
*
|
||||
* Description When connection is opened, this call-out function is executed
|
||||
* by HH to do platform specific initialization.
|
||||
*
|
||||
* Returns void.
|
||||
******************************************************************************/
|
||||
void bta_hh_co_open(uint8_t dev_handle, uint8_t sub_class, tBTA_HH_ATTR_MASK attr_mask, uint8_t app_id)
|
||||
{
|
||||
uint32_t i;
|
||||
btc_hh_device_t *p_dev = NULL;
|
||||
|
||||
if (dev_handle == BTA_HH_INVALID_HANDLE) {
|
||||
APPL_TRACE_WARNING("%s: Oops, dev_handle (%d) is invalid...", __func__, dev_handle);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < BTC_HH_MAX_HID; i++) {
|
||||
p_dev = &btc_hh_cb.devices[i];
|
||||
if (p_dev->dev_status != ESP_HIDH_CONN_STATE_UNKNOWN && p_dev->dev_handle == dev_handle) {
|
||||
// We found a device with the same handle. Must be a device reconnected.
|
||||
APPL_TRACE_WARNING("%s: Found an existing device with the same handle dev_status=%d, "
|
||||
"dev_handle=0x%2x, attr_mask=0x%04x, sub_class=0x%02x, app_id=%d",
|
||||
__func__, p_dev->dev_status, dev_handle, p_dev->attr_mask, p_dev->sub_class,
|
||||
p_dev->app_id);
|
||||
break;
|
||||
}
|
||||
p_dev = NULL;
|
||||
}
|
||||
|
||||
if (p_dev == NULL) {
|
||||
// Did not find a device reconnection case. Find an empty slot now.
|
||||
for (i = 0; i < BTC_HH_MAX_HID; i++) {
|
||||
if (btc_hh_cb.devices[i].dev_status == ESP_HIDH_CONN_STATE_UNKNOWN) {
|
||||
p_dev = &btc_hh_cb.devices[i];
|
||||
p_dev->dev_handle = dev_handle;
|
||||
p_dev->attr_mask = attr_mask;
|
||||
p_dev->sub_class = sub_class;
|
||||
p_dev->app_id = app_id;
|
||||
p_dev->local_vup = false;
|
||||
|
||||
btc_hh_cb.device_num++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (p_dev == NULL) {
|
||||
APPL_TRACE_ERROR("%s: Error: too many HID devices are connected", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
p_dev->dev_status = ESP_HIDH_CONN_STATE_CONNECTED;
|
||||
APPL_TRACE_DEBUG("%s: Return device status %d", __func__, p_dev->dev_status);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function bta_hh_co_close
|
||||
*
|
||||
* Description When connection is closed, this call-out function is executed
|
||||
* by HH to do platform specific finalization.
|
||||
*
|
||||
* Parameters dev_handle - device handle
|
||||
* app_id - application id
|
||||
*
|
||||
* Returns void.
|
||||
******************************************************************************/
|
||||
void bta_hh_co_close(uint8_t dev_handle, uint8_t app_id)
|
||||
{
|
||||
uint32_t i;
|
||||
btc_hh_device_t *p_dev = NULL;
|
||||
|
||||
APPL_TRACE_WARNING("%s: dev_handle = %d, app_id = %d", __func__, dev_handle, app_id);
|
||||
if (dev_handle == BTA_HH_INVALID_HANDLE) {
|
||||
APPL_TRACE_WARNING("%s: Oops, dev_handle (%d) is invalid...", __func__, dev_handle);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < BTC_HH_MAX_HID; i++) {
|
||||
p_dev = &btc_hh_cb.devices[i];
|
||||
if (p_dev->dev_status != ESP_HIDH_CONN_STATE_UNKNOWN && p_dev->dev_handle == dev_handle) {
|
||||
APPL_TRACE_WARNING("%s: Found an existing device with the same handle "
|
||||
"dev_status = %d, dev_handle =%d",
|
||||
__func__, p_dev->dev_status, p_dev->dev_handle);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function bta_hh_co_data
|
||||
*
|
||||
* Description This function is executed by BTA when HID host receive a
|
||||
* data report on interrupt channel.
|
||||
*
|
||||
* Parameters dev_handle - device handle
|
||||
* *p_rpt - pointer to the report data
|
||||
* len - length of report data
|
||||
* mode - Hid host Protocol Mode
|
||||
* sub_clas - Device Subclass
|
||||
* app_id - application id
|
||||
*
|
||||
* Returns void
|
||||
******************************************************************************/
|
||||
void bta_hh_co_data(UINT8 dev_handle, UINT8 *p_rpt, UINT16 len, tBTA_HH_PROTO_MODE mode, UINT8 sub_class, UINT8 ctry_code,
|
||||
BD_ADDR peer_addr, UINT8 app_id)
|
||||
{
|
||||
btc_msg_t msg;
|
||||
tBTA_HH p_data;
|
||||
BT_HDR *p_buf = NULL;
|
||||
bt_status_t status;
|
||||
tBTA_HH_STATUS ret = BTA_HH_OK;
|
||||
|
||||
msg.sig = BTC_SIG_API_CB;
|
||||
msg.pid = BTC_PID_HH;
|
||||
msg.act = BTA_HH_DATA_IND_EVT;
|
||||
|
||||
APPL_TRACE_DEBUG("%s: dev_handle = %d, subclass = 0x%02X, mode = %d, "
|
||||
"ctry_code = %d, app_id = %d",
|
||||
__func__, dev_handle, sub_class, mode, ctry_code, app_id);
|
||||
|
||||
do {
|
||||
if ((p_buf = osi_malloc(sizeof(BT_HDR) + len)) == NULL) {
|
||||
APPL_TRACE_ERROR("%s malloc failed!", __func__);
|
||||
ret = BTA_HH_ERR_NO_RES;
|
||||
break;
|
||||
}
|
||||
p_buf->offset = 0;
|
||||
p_buf->len = len;
|
||||
p_buf->event = 0;
|
||||
p_buf->layer_specific = dev_handle;
|
||||
memcpy(p_buf->data, p_rpt, len);
|
||||
} while (0);
|
||||
|
||||
p_data.int_data.status = ret;
|
||||
p_data.int_data.handle = dev_handle;
|
||||
p_data.int_data.p_data = p_buf;
|
||||
p_data.int_data.proto_mode = mode;
|
||||
status = btc_transfer_context(&msg, &p_data, sizeof(tBTA_HH), NULL);
|
||||
assert(status == BT_STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
#endif /* HID_HOST_INCLUDED == TRUE */
|
831
components/bt/host/bluedroid/btc/profile/std/hid/btc_hd.c
Normal file
831
components/bt/host/bluedroid/btc/profile/std/hid/btc_hd.c
Normal file
@ -0,0 +1,831 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
* Copyright (C) 2009-2012 Broadcom Corporation
|
||||
* Copyright (C) 2019 Blake Felt
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************/
|
||||
/************************************************************************************
|
||||
*
|
||||
* Filename: btc_hd.c
|
||||
*
|
||||
* Description: HID Device Profile Bluetooth Interface
|
||||
*
|
||||
*
|
||||
***********************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "bta/bta_api.h"
|
||||
#include "bta/bta_hd_api.h"
|
||||
#include "bta/bta_hh_api.h"
|
||||
#include "bta/utl.h"
|
||||
#include "btc/btc_storage.h"
|
||||
#include "btc/btc_util.h"
|
||||
#include "btc/btc_manage.h"
|
||||
#include "btc_hd.h"
|
||||
|
||||
#include "osi/allocator.h"
|
||||
|
||||
#include "esp_hidd_api.h"
|
||||
|
||||
#if HID_DEV_INCLUDED == TRUE
|
||||
#include "bta_dm_int.h"
|
||||
|
||||
/* HD request events */
|
||||
typedef enum { BTC_HD_DUMMY_REQ_EVT = 0 } btc_hd_req_evt_t;
|
||||
|
||||
/*******************************************************************************
|
||||
* Static variables
|
||||
******************************************************************************/
|
||||
btc_hd_cb_t btc_hd_cb;
|
||||
|
||||
// static tBTA_HD_APP_INFO app_info;
|
||||
// static tBTA_HD_QOS_INFO in_qos;
|
||||
// static tBTA_HD_QOS_INFO out_qos;
|
||||
|
||||
/******************************************************************************
|
||||
* Constants & Macros
|
||||
*****************************************************************************/
|
||||
#define BTC_HD_APP_NAME_LEN 50
|
||||
#define BTC_HD_APP_DESCRIPTION_LEN 50
|
||||
#define BTC_HD_APP_PROVIDER_LEN 50
|
||||
#define BTC_HD_APP_DESCRIPTOR_LEN 2048
|
||||
#define COD_HID_KEYBOARD 0x0540
|
||||
#define COD_HID_POINTING 0x0580
|
||||
#define COD_HID_COMBO 0x05C0
|
||||
#define COD_HID_MAJOR 0x0500
|
||||
|
||||
#define is_hidd_init() (btc_hd_cb.status > BTC_HD_DISABLED)
|
||||
#define is_hidd_app_register() (btc_hd_cb.app_registered)
|
||||
|
||||
typedef void (bt_hid_copy_cb_t)(btc_msg_t *msg, void *p_dest, void *p_src);
|
||||
|
||||
static inline void btc_hd_cb_to_app(esp_hidd_cb_event_t event, esp_hidd_cb_param_t *param)
|
||||
{
|
||||
esp_hd_cb_t *btc_hd_cb = (esp_hd_cb_t *)btc_profile_cb_get(BTC_PID_HD);
|
||||
if (btc_hd_cb) {
|
||||
btc_hd_cb(event, param);
|
||||
}
|
||||
}
|
||||
|
||||
static void free_app_info_param(void)
|
||||
{
|
||||
utl_freebuf((void **)&btc_hd_cb.app_info.descriptor.dsc_list);
|
||||
utl_freebuf((void **)&btc_hd_cb.app_info.p_provider);
|
||||
utl_freebuf((void **)&btc_hd_cb.app_info.p_description);
|
||||
utl_freebuf((void **)&btc_hd_cb.app_info.p_name);
|
||||
}
|
||||
|
||||
static void bte_hd_arg_deep_copy(btc_msg_t *msg, void *p_dst, void *p_src)
|
||||
{
|
||||
tBTA_HD *p_dst_data = (tBTA_HD *)p_dst;
|
||||
tBTA_HD *p_src_data = (tBTA_HD *)p_src;
|
||||
switch (msg->act)
|
||||
{
|
||||
case BTA_HD_SET_REPORT_EVT: {
|
||||
uint8_t *src_data = p_src_data->set_report.p_data;
|
||||
if (src_data) {
|
||||
p_dst_data->set_report.p_data = osi_malloc(p_src_data->set_report.len);
|
||||
if (p_dst_data->set_report.p_data == NULL) {
|
||||
BTC_TRACE_ERROR("%s malloc set_report data failed!", __func__);
|
||||
break;
|
||||
}
|
||||
memcpy(p_dst_data->set_report.p_data, src_data, p_src_data->set_report.len);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BTA_HD_INTR_DATA_EVT: {
|
||||
uint8_t *src_data = p_src_data->intr_data.p_data;
|
||||
if (src_data) {
|
||||
p_dst_data->intr_data.p_data = osi_malloc(p_src_data->intr_data.len);
|
||||
if (p_dst_data->intr_data.p_data == NULL) {
|
||||
BTC_TRACE_ERROR("%s malloc intr_data data failed!", __func__);
|
||||
break;
|
||||
}
|
||||
memcpy(p_dst_data->intr_data.p_data, src_data, p_src_data->intr_data.len);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function btc_hd_remove_device
|
||||
*
|
||||
* Description Removes plugged device
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
void btc_hd_remove_device(bt_bdaddr_t bd_addr)
|
||||
{
|
||||
BTA_HdRemoveDevice((uint8_t *)&bd_addr);
|
||||
// btc_storage_remove_hidd(&bd_addr);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function bte_hd_evt
|
||||
*
|
||||
* Description Switches context from BTE to BTC for all BT-HD events
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
static void bte_hd_evt(tBTA_HD_EVT event, tBTA_HD *p_data)
|
||||
{
|
||||
bt_status_t status;
|
||||
int param_len = 0;
|
||||
|
||||
BTC_TRACE_API("%s event=%d", __func__, event);
|
||||
|
||||
switch (event) {
|
||||
case BTA_HD_ENABLE_EVT:
|
||||
case BTA_HD_DISABLE_EVT:
|
||||
case BTA_HD_UNREGISTER_APP_EVT:
|
||||
param_len = sizeof(tBTA_HD_STATUS);
|
||||
break;
|
||||
case BTA_HD_REGISTER_APP_EVT:
|
||||
param_len = sizeof(tBTA_HD_REG_STATUS);
|
||||
break;
|
||||
case BTA_HD_OPEN_EVT:
|
||||
case BTA_HD_CLOSE_EVT:
|
||||
case BTA_HD_VC_UNPLUG_EVT:
|
||||
param_len = sizeof(tBTA_HD_CONN);
|
||||
break;
|
||||
case BTA_HD_GET_REPORT_EVT:
|
||||
param_len += sizeof(tBTA_HD_GET_REPORT);
|
||||
break;
|
||||
case BTA_HD_SET_REPORT_EVT:
|
||||
param_len = sizeof(tBTA_HD_SET_REPORT);
|
||||
break;
|
||||
case BTA_HD_SET_PROTOCOL_EVT:
|
||||
param_len += sizeof(p_data->set_protocol);
|
||||
break;
|
||||
case BTA_HD_INTR_DATA_EVT:
|
||||
param_len = sizeof(tBTA_HD_INTR_DATA);
|
||||
break;
|
||||
case BTA_HD_SEND_REPORT_EVT:
|
||||
param_len = sizeof(tBTA_HD_API_SEND_REPORT);
|
||||
break;
|
||||
case BTA_HD_REPORT_ERR_EVT:
|
||||
param_len = sizeof(tBTA_HD_API_REPORT_ERR);
|
||||
break;
|
||||
}
|
||||
|
||||
btc_msg_t msg;
|
||||
msg.sig = BTC_SIG_API_CB;
|
||||
msg.pid = BTC_PID_HD;
|
||||
msg.act = event;
|
||||
|
||||
status = btc_transfer_context(&msg, p_data, param_len, bte_hd_arg_deep_copy);
|
||||
if (status != BT_STATUS_SUCCESS) {
|
||||
BTC_TRACE_ERROR("context transfer failed");
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function btc_hd_init
|
||||
*
|
||||
* Description Initializes BT-HD interface
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
static void btc_hd_init(void)
|
||||
{
|
||||
BTC_TRACE_API("%s", __func__);
|
||||
esp_hidd_status_t ret = ESP_HIDD_SUCCESS;
|
||||
do {
|
||||
if (is_hidd_init()) {
|
||||
BTC_TRACE_ERROR("%s HD has been initiated, shall uninit first!", __func__);
|
||||
ret = ESP_HIDD_NEED_DEINIT;
|
||||
break;
|
||||
}
|
||||
memset(&btc_hd_cb, 0, sizeof(btc_hd_cb));
|
||||
/* enable HD */
|
||||
BTA_HdEnable(bte_hd_evt);
|
||||
} while (0);
|
||||
|
||||
if (ret != ESP_HIDD_SUCCESS) {
|
||||
esp_hidd_cb_param_t param;
|
||||
param.init.status = ret;
|
||||
btc_hd_cb_to_app(ESP_HIDD_INIT_EVT, ¶m);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function btc_hd_deinit
|
||||
*
|
||||
* Description de-initializes the hd interface
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
static void btc_hd_unregister_app(void);
|
||||
static void btc_hd_deinit(void)
|
||||
{
|
||||
BTC_TRACE_API("%s", __func__);
|
||||
esp_hidd_status_t ret = ESP_HIDD_SUCCESS;
|
||||
do {
|
||||
if (!is_hidd_init()) {
|
||||
BTC_TRACE_ERROR("%s HD has not been initiated, shall init first!", __func__);
|
||||
ret = ESP_HIDD_NEED_INIT;
|
||||
break;
|
||||
}
|
||||
|
||||
btc_hd_cb.service_dereg_active = FALSE;
|
||||
btc_hd_cb.status = BTC_HD_DISABLING;
|
||||
// unresgister app will also relase the connection
|
||||
// and disable after receiving unregister event from lower layer
|
||||
if (is_hidd_app_register()) {
|
||||
btc_hd_unregister_app();
|
||||
} else {
|
||||
BTC_TRACE_WARNING("%s disabling hid device service now", __func__);
|
||||
BTA_HdDisable();
|
||||
}
|
||||
} while (0);
|
||||
|
||||
if (ret != ESP_HIDD_SUCCESS) {
|
||||
esp_hidd_cb_param_t param;
|
||||
param.deinit.status = ret;
|
||||
btc_hd_cb_to_app(ESP_HIDD_DEINIT_EVT, ¶m);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function btc_hd_register_app
|
||||
*
|
||||
* Description Registers HID Device application
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
static void btc_hd_register_app(esp_hidd_app_param_t *p_app_param, esp_hidd_qos_param_t *p_in_qos,
|
||||
esp_hidd_qos_param_t *p_out_qos)
|
||||
{
|
||||
BTC_TRACE_API("%s", __func__);
|
||||
esp_hidd_status_t ret = ESP_HIDD_SUCCESS;
|
||||
do {
|
||||
if (!is_hidd_init()) {
|
||||
BTC_TRACE_ERROR("%s HD has not been initiated, shall init first!", __func__);
|
||||
ret = ESP_HIDD_NEED_INIT;
|
||||
break;
|
||||
}
|
||||
|
||||
if (is_hidd_app_register()) {
|
||||
BTC_TRACE_ERROR("%s: application already registered, shall deregister first!", __func__);
|
||||
ret = ESP_HIDD_NEED_DEREG;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((btc_hd_cb.app_info.p_name = (char *)osi_malloc(BTC_HD_APP_NAME_LEN)) == NULL ||
|
||||
(btc_hd_cb.app_info.p_description = (char *)osi_malloc(BTC_HD_APP_DESCRIPTION_LEN)) == NULL ||
|
||||
(btc_hd_cb.app_info.p_provider = (char *)osi_malloc(BTC_HD_APP_PROVIDER_LEN)) == NULL ||
|
||||
(btc_hd_cb.app_info.descriptor.dsc_list = (uint8_t *)osi_malloc(p_app_param->desc_list_len)) == NULL) {
|
||||
BTC_TRACE_ERROR(
|
||||
"%s malloc app_info failed! p_name:%p, p_description:%p, p_provider:%p, descriptor.dsc_list:%p",
|
||||
__func__, btc_hd_cb.app_info.p_name, btc_hd_cb.app_info.p_description, btc_hd_cb.app_info.p_provider,
|
||||
btc_hd_cb.app_info.descriptor.dsc_list);
|
||||
ret = ESP_HIDD_NO_RES;
|
||||
break;
|
||||
}
|
||||
memcpy(btc_hd_cb.app_info.p_name, p_app_param->name, BTC_HD_APP_NAME_LEN);
|
||||
memcpy(btc_hd_cb.app_info.p_description, p_app_param->description, BTC_HD_APP_DESCRIPTION_LEN);
|
||||
memcpy(btc_hd_cb.app_info.p_provider, p_app_param->provider, BTC_HD_APP_PROVIDER_LEN);
|
||||
memcpy(btc_hd_cb.app_info.descriptor.dsc_list, p_app_param->desc_list, p_app_param->desc_list_len);
|
||||
btc_hd_cb.app_info.subclass = p_app_param->subclass;
|
||||
btc_hd_cb.app_info.descriptor.dl_len = p_app_param->desc_list_len;
|
||||
|
||||
btc_hd_cb.in_qos.service_type = p_in_qos->service_type;
|
||||
btc_hd_cb.in_qos.token_rate = p_in_qos->token_rate;
|
||||
btc_hd_cb.in_qos.token_bucket_size = p_in_qos->token_bucket_size;
|
||||
btc_hd_cb.in_qos.peak_bandwidth = p_in_qos->peak_bandwidth;
|
||||
btc_hd_cb.in_qos.access_latency = p_in_qos->access_latency;
|
||||
btc_hd_cb.in_qos.delay_variation = p_in_qos->delay_variation;
|
||||
btc_hd_cb.out_qos.service_type = p_out_qos->service_type;
|
||||
btc_hd_cb.out_qos.token_rate = p_out_qos->token_rate;
|
||||
btc_hd_cb.out_qos.token_bucket_size = p_out_qos->token_bucket_size;
|
||||
btc_hd_cb.out_qos.peak_bandwidth = p_out_qos->peak_bandwidth;
|
||||
btc_hd_cb.out_qos.access_latency = p_out_qos->access_latency;
|
||||
btc_hd_cb.out_qos.delay_variation = p_out_qos->delay_variation;
|
||||
|
||||
BTA_HdRegisterApp(&btc_hd_cb.app_info, &btc_hd_cb.in_qos, &btc_hd_cb.out_qos);
|
||||
} while(0);
|
||||
|
||||
if (ret != ESP_HIDD_SUCCESS) {
|
||||
esp_hidd_cb_param_t param;
|
||||
param.register_app.status = ret;
|
||||
param.register_app.in_use = false;
|
||||
memset(param.register_app.bd_addr, 0, BD_ADDR_LEN);
|
||||
btc_hd_cb_to_app(ESP_HIDD_REGISTER_APP_EVT, ¶m);
|
||||
}
|
||||
free_app_info_param();
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function btc_hd_unregister_app
|
||||
*
|
||||
* Description Unregisters HID Device application
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
static void btc_hd_unregister_app(void)
|
||||
{
|
||||
BTC_TRACE_API("%s", __func__);
|
||||
esp_hidd_status_t ret = ESP_HIDD_SUCCESS;
|
||||
do {
|
||||
if (!is_hidd_init()) {
|
||||
BTC_TRACE_ERROR("%s HD has not been initiated, shall init first!", __func__);
|
||||
ret = ESP_HIDD_NEED_INIT;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!is_hidd_app_register()) {
|
||||
BTC_TRACE_ERROR("%s: application has not been registered, shall register first!", __func__);
|
||||
ret = ESP_HIDD_NEED_REG;
|
||||
break;
|
||||
}
|
||||
|
||||
if (btc_hd_cb.service_dereg_active) {
|
||||
BTC_TRACE_ERROR("%s: BT-HD deregistering in progress", __func__);
|
||||
ret = ESP_HIDD_BUSY;
|
||||
break;
|
||||
}
|
||||
btc_hd_cb.service_dereg_active = TRUE;
|
||||
BTA_HdUnregisterApp();
|
||||
} while(0);
|
||||
|
||||
if (ret != ESP_HIDD_SUCCESS) {
|
||||
esp_hidd_cb_param_t param;
|
||||
param.unregister_app.status = ret;
|
||||
btc_hd_cb_to_app(ESP_HIDD_UNREGISTER_APP_EVT, ¶m);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function btc_hd_connect
|
||||
*
|
||||
* Description Connects to host
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
static void btc_hd_connect(BD_ADDR bd_addr)
|
||||
{
|
||||
BTC_TRACE_API("%s", __func__);
|
||||
esp_hidd_status_t ret = ESP_HIDD_SUCCESS;
|
||||
do {
|
||||
if (!is_hidd_init()) {
|
||||
BTC_TRACE_ERROR("%s HD has not been initiated, shall init first!", __func__);
|
||||
ret = ESP_HIDD_NEED_INIT;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!is_hidd_app_register()) {
|
||||
BTC_TRACE_ERROR("%s: application has not been registered, shall register first!", __func__);
|
||||
ret = ESP_HIDD_NEED_REG;
|
||||
break;
|
||||
}
|
||||
BTA_HdConnect(bd_addr);
|
||||
} while (0);
|
||||
|
||||
if (ret != ESP_HIDD_SUCCESS) {
|
||||
esp_hidd_cb_param_t param;
|
||||
param.open.status = ret;
|
||||
param.open.conn_status = ESP_HIDD_CONN_STATE_DISCONNECTED;
|
||||
memcpy(param.open.bd_addr, bd_addr, BD_ADDR_LEN);
|
||||
btc_hd_cb_to_app(ESP_HIDD_OPEN_EVT, ¶m);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function btc_hd_disconnect
|
||||
*
|
||||
* Description Disconnects from host
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
static void btc_hd_disconnect(void)
|
||||
{
|
||||
BTC_TRACE_API("%s", __func__);
|
||||
esp_hidd_status_t ret = ESP_HIDD_SUCCESS;
|
||||
do {
|
||||
if (!is_hidd_init()) {
|
||||
BTC_TRACE_ERROR("%s HD has not been initiated, shall init first!", __func__);
|
||||
ret = ESP_HIDD_NEED_INIT;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!is_hidd_app_register()) {
|
||||
BTC_TRACE_ERROR("%s: application has not been registered, shall register first!", __func__);
|
||||
ret = ESP_HIDD_NEED_REG;
|
||||
break;
|
||||
}
|
||||
BTA_HdDisconnect();
|
||||
} while (0);
|
||||
|
||||
if (ret != ESP_HIDD_SUCCESS) {
|
||||
esp_hidd_cb_param_t param;
|
||||
param.close.status = ret;
|
||||
param.close.conn_status = ESP_HIDD_CONN_STATE_DISCONNECTED;
|
||||
btc_hd_cb_to_app(ESP_HIDD_CLOSE_EVT, ¶m);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function btc_hd_send_report
|
||||
*
|
||||
* Description Sends Reports to hid host
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
static void btc_hd_send_report(esp_hidd_report_type_t type, uint8_t id, uint16_t len, uint8_t *p_data)
|
||||
{
|
||||
tBTA_HD_REPORT report;
|
||||
|
||||
BTC_TRACE_API("%s: type=%d id=%d len=%d", __func__, type, id, len);
|
||||
esp_hidd_status_t ret = ESP_HIDD_SUCCESS;
|
||||
do {
|
||||
if (!is_hidd_init()) {
|
||||
BTC_TRACE_ERROR("%s HD has not been initiated, shall init first!", __func__);
|
||||
ret = ESP_HIDD_NEED_INIT;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!is_hidd_app_register()) {
|
||||
BTC_TRACE_ERROR("%s: application has not been registered, shall register first!", __func__);
|
||||
ret = ESP_HIDD_NEED_REG;
|
||||
break;
|
||||
}
|
||||
if (type == ESP_HIDD_REPORT_TYPE_INTRDATA) {
|
||||
report.type = ESP_HIDD_REPORT_TYPE_INPUT;
|
||||
report.use_intr = TRUE;
|
||||
} else {
|
||||
report.type = (type & 0x03);
|
||||
report.use_intr = FALSE;
|
||||
}
|
||||
|
||||
report.id = id;
|
||||
report.len = len;
|
||||
report.p_data = p_data;
|
||||
|
||||
BTA_HdSendReport(&report);
|
||||
} while (0);
|
||||
|
||||
if (ret != ESP_HIDD_SUCCESS) {
|
||||
esp_hidd_cb_param_t param;
|
||||
param.send_report.status = ret;
|
||||
param.send_report.reason = 0;
|
||||
param.send_report.report_type = report.type;
|
||||
param.send_report.report_id = report.id;
|
||||
btc_hd_cb_to_app(ESP_HIDD_SEND_REPORT_EVT, ¶m);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function btc_hd_report_error
|
||||
*
|
||||
* Description Sends HANDSHAKE with error info for invalid SET_REPORT
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
static void btc_hd_report_error(uint8_t error)
|
||||
{
|
||||
BTC_TRACE_API("%s", __func__);
|
||||
esp_hidd_status_t ret = ESP_HIDD_SUCCESS;
|
||||
do {
|
||||
if (!is_hidd_init()) {
|
||||
BTC_TRACE_ERROR("%s HD has not been initiated, shall init first!", __func__);
|
||||
ret = ESP_HIDD_NEED_INIT;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!is_hidd_app_register()) {
|
||||
BTC_TRACE_ERROR("%s: application has not been registered, shall register first!", __func__);
|
||||
ret = ESP_HIDD_NEED_REG;
|
||||
break;
|
||||
}
|
||||
BTA_HdReportError(error);
|
||||
} while (0);
|
||||
|
||||
if (ret != ESP_HIDD_SUCCESS) {
|
||||
esp_hidd_cb_param_t param;
|
||||
param.report_err.status = ret;
|
||||
param.report_err.reason = 0;
|
||||
btc_hd_cb_to_app(ESP_HIDD_REPORT_ERR_EVT, ¶m);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function btc_hd_virtual_cable_unplug
|
||||
*
|
||||
* Description Sends Virtual Cable Unplug to host
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
static void btc_hd_virtual_cable_unplug(void)
|
||||
{
|
||||
BTC_TRACE_API("%s", __func__);
|
||||
esp_hidd_status_t ret = ESP_HIDD_SUCCESS;
|
||||
do {
|
||||
if (!is_hidd_init()) {
|
||||
BTC_TRACE_ERROR("%s HD has not been initiated, shall init first!", __func__);
|
||||
ret = ESP_HIDD_NEED_INIT;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!is_hidd_app_register()) {
|
||||
BTC_TRACE_ERROR("%s: application has not been registered, shall register first!", __func__);
|
||||
ret = ESP_HIDD_NEED_REG;
|
||||
break;
|
||||
}
|
||||
BTA_HdVirtualCableUnplug();
|
||||
} while (0);
|
||||
|
||||
if (ret != ESP_HIDD_SUCCESS) {
|
||||
esp_hidd_cb_param_t param;
|
||||
param.report_err.status = ret;
|
||||
param.report_err.reason = 0;
|
||||
btc_hd_cb_to_app(ESP_HIDD_VC_UNPLUG_EVT, ¶m);
|
||||
}
|
||||
}
|
||||
|
||||
static void btc_hd_call_arg_deep_free(btc_msg_t *msg)
|
||||
{
|
||||
btc_hidd_args_t *arg = (btc_hidd_args_t *)msg->arg;
|
||||
|
||||
switch (msg->act) {
|
||||
case BTC_HD_SEND_REPORT_EVT:
|
||||
utl_freebuf((void **)&arg->send_report.data);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void btc_hd_call_handler(btc_msg_t *msg)
|
||||
{
|
||||
btc_hidd_args_t *arg = (btc_hidd_args_t *)(msg->arg);
|
||||
switch (msg->act) {
|
||||
case BTC_HD_INIT_EVT:
|
||||
btc_hd_init();
|
||||
break;
|
||||
case BTC_HD_DEINIT_EVT:
|
||||
btc_hd_deinit();
|
||||
break;
|
||||
case BTC_HD_REGISTER_APP_EVT:
|
||||
btc_hd_register_app(arg->register_app.app_param, arg->register_app.in_qos, arg->register_app.out_qos);
|
||||
break;
|
||||
case BTC_HD_UNREGISTER_APP_EVT:
|
||||
btc_hd_unregister_app();
|
||||
break;
|
||||
case BTC_HD_CONNECT_EVT:
|
||||
btc_hd_connect(arg->connect.bd_addr);
|
||||
break;
|
||||
case BTC_HD_DISCONNECT_EVT:
|
||||
btc_hd_disconnect();
|
||||
break;
|
||||
case BTC_HD_SEND_REPORT_EVT:
|
||||
btc_hd_send_report(arg->send_report.type, arg->send_report.id, arg->send_report.len, arg->send_report.data);
|
||||
break;
|
||||
case BTC_HD_REPORT_ERROR_EVT:
|
||||
btc_hd_report_error(arg->error);
|
||||
break;
|
||||
case BTC_HD_UNPLUG_EVT:
|
||||
btc_hd_virtual_cable_unplug();
|
||||
break;
|
||||
default:
|
||||
BTC_TRACE_WARNING("unknown hidd action %i", msg->act);
|
||||
break;
|
||||
}
|
||||
btc_hd_call_arg_deep_free(msg);
|
||||
}
|
||||
|
||||
static void btc_hd_cb_arg_deep_free(btc_msg_t *msg)
|
||||
{
|
||||
tBTA_HD *arg = (tBTA_HD *)msg->arg;
|
||||
|
||||
switch (msg->act) {
|
||||
case BTA_HD_SET_REPORT_EVT:
|
||||
utl_freebuf((void **)&arg->set_report.p_data);
|
||||
break;
|
||||
case BTA_HD_INTR_DATA_EVT:
|
||||
utl_freebuf((void **)&arg->intr_data.p_data);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void btc_hd_cb_handler(btc_msg_t *msg)
|
||||
{
|
||||
uint16_t event = msg->act;
|
||||
tBTA_HD *p_data = (tBTA_HD *)msg->arg;
|
||||
esp_hidd_cb_param_t param = {0};
|
||||
BTC_TRACE_API("%s: event=%s", __func__, dump_hd_event(event));
|
||||
|
||||
switch (event) {
|
||||
case BTA_HD_ENABLE_EVT:
|
||||
BTC_TRACE_DEBUG("%s: status=%d", __func__, p_data->status);
|
||||
if (p_data->status == BTA_HD_OK) {
|
||||
btc_storage_load_hidd();
|
||||
btc_hd_cb.status = BTC_HD_ENABLED;
|
||||
} else {
|
||||
btc_hd_cb.status = BTC_HD_DISABLED;
|
||||
BTC_TRACE_WARNING("Failed to enable BT-HD, status=%d", p_data->status);
|
||||
}
|
||||
param.init.status = p_data->status;
|
||||
btc_hd_cb_to_app(ESP_HIDD_INIT_EVT, ¶m);
|
||||
break;
|
||||
case BTA_HD_DISABLE_EVT:
|
||||
BTC_TRACE_DEBUG("%s: status=%d", __func__, p_data->status);
|
||||
if (p_data->status == BTA_HD_OK){
|
||||
btc_hd_cb.status = BTC_HD_DISABLED;
|
||||
if (btc_hd_cb.service_dereg_active) {
|
||||
btc_hd_cb.service_dereg_active = FALSE;
|
||||
}
|
||||
free_app_info_param();
|
||||
memset(&btc_hd_cb, 0, sizeof(btc_hd_cb));
|
||||
} else {
|
||||
BTC_TRACE_WARNING("Failed to disable BT-HD, status=%d", p_data->status);
|
||||
}
|
||||
param.deinit.status = p_data->status;
|
||||
btc_hd_cb_to_app(ESP_HIDD_DEINIT_EVT, ¶m);
|
||||
break;
|
||||
case BTA_HD_REGISTER_APP_EVT:
|
||||
if (p_data->reg_status.status == BTA_HD_OK) {
|
||||
btc_hd_cb.app_registered = TRUE;
|
||||
}
|
||||
param.register_app.status = p_data->reg_status.status;
|
||||
param.register_app.in_use = p_data->reg_status.in_use;
|
||||
if (!p_data->reg_status.in_use) {
|
||||
memset(param.register_app.bd_addr, 0, BD_ADDR_LEN);
|
||||
} else {
|
||||
memcpy(param.register_app.bd_addr, p_data->reg_status.bda, BD_ADDR_LEN);
|
||||
}
|
||||
btc_hd_cb_to_app(ESP_HIDD_REGISTER_APP_EVT, ¶m);
|
||||
break;
|
||||
case BTA_HD_UNREGISTER_APP_EVT:
|
||||
btc_hd_cb.app_registered = FALSE;
|
||||
param.unregister_app.status = p_data->status;
|
||||
btc_hd_cb_to_app(ESP_HIDD_UNREGISTER_APP_EVT, ¶m);
|
||||
if (btc_hd_cb.status == BTC_HD_DISABLING) {
|
||||
BTC_TRACE_WARNING("disabling hid device service now");
|
||||
BTA_HdDisable();
|
||||
}
|
||||
break;
|
||||
case BTA_HD_OPEN_EVT: {
|
||||
bt_bdaddr_t *addr = (bt_bdaddr_t *)&p_data->conn.bda;
|
||||
BTC_TRACE_EVENT("BTA_HD_OPEN_EVT, address (%02x:%02x:%02x:%02x:%02x:%02x)", addr->address[0], addr->address[1],
|
||||
addr->address[2], addr->address[3], addr->address[4], addr->address[5]);
|
||||
if (p_data->conn.status == BTA_HD_OK && p_data->conn.conn_status == BTA_HD_CONN_STATE_CONNECTED) {
|
||||
// /* Check if the connection is from hid host and not hid device */
|
||||
// if (check_cod_hid(addr)) {
|
||||
// /* Incoming connection from hid device, reject it */
|
||||
// BTC_TRACE_WARNING("remote device is not hid host, disconnecting");
|
||||
// btc_hd_cb.forced_disc = TRUE;
|
||||
// BTA_HdDisconnect();
|
||||
// break;
|
||||
// }
|
||||
// btc_storage_set_hidd((bt_bdaddr_t *)&p_data->conn.bda);
|
||||
}
|
||||
param.open.status = p_data->conn.status;
|
||||
param.open.conn_status = p_data->conn.conn_status;
|
||||
memcpy(param.open.bd_addr, p_data->conn.bda, BD_ADDR_LEN);
|
||||
btc_hd_cb_to_app(ESP_HIDD_OPEN_EVT, ¶m);
|
||||
break;
|
||||
}
|
||||
case BTA_HD_CLOSE_EVT:
|
||||
if (btc_hd_cb.forced_disc && p_data->conn.conn_status == BTA_HD_CONN_STATE_DISCONNECTED) {
|
||||
bt_bdaddr_t *addr = (bt_bdaddr_t *)&p_data->conn.bda;
|
||||
BTC_TRACE_WARNING("remote device was forcefully disconnected");
|
||||
btc_hd_remove_device(*addr);
|
||||
btc_hd_cb.forced_disc = FALSE;
|
||||
break;
|
||||
}
|
||||
param.close.status = p_data->conn.status;
|
||||
param.close.conn_status = p_data->conn.conn_status;
|
||||
btc_hd_cb_to_app(ESP_HIDD_CLOSE_EVT, ¶m);
|
||||
break;
|
||||
case BTA_HD_GET_REPORT_EVT:
|
||||
param.get_report.report_type = p_data->get_report.report_type;
|
||||
param.get_report.report_id = p_data->get_report.report_id;
|
||||
param.get_report.buffer_size = p_data->get_report.buffer_size;
|
||||
btc_hd_cb_to_app(ESP_HIDD_GET_REPORT_EVT, ¶m);
|
||||
break;
|
||||
case BTA_HD_SET_REPORT_EVT:
|
||||
param.set_report.report_type = p_data->set_report.report_type;
|
||||
param.set_report.report_id = p_data->set_report.report_id;
|
||||
param.set_report.len = p_data->set_report.len;
|
||||
param.set_report.data = p_data->set_report.p_data;
|
||||
btc_hd_cb_to_app(ESP_HIDD_SET_REPORT_EVT, ¶m);
|
||||
break;
|
||||
case BTA_HD_SET_PROTOCOL_EVT:
|
||||
switch (p_data->set_protocol) {
|
||||
case HID_PAR_PROTOCOL_BOOT_MODE:
|
||||
param.set_protocol.protocol_mode = ESP_HIDD_BOOT_MODE;
|
||||
break;
|
||||
case HID_PAR_PROTOCOL_REPORT:
|
||||
param.set_protocol.protocol_mode = ESP_HIDD_REPORT_MODE;
|
||||
break;
|
||||
default:
|
||||
param.set_protocol.protocol_mode = ESP_HIDD_UNSUPPORTED_MODE;
|
||||
break;
|
||||
}
|
||||
btc_hd_cb_to_app(ESP_HIDD_SET_PROTOCOL_EVT, ¶m);
|
||||
break;
|
||||
case BTA_HD_INTR_DATA_EVT:
|
||||
param.intr_data.report_id = p_data->intr_data.report_id;
|
||||
param.intr_data.len = p_data->intr_data.len;
|
||||
param.intr_data.data = p_data->intr_data.p_data;
|
||||
btc_hd_cb_to_app(ESP_HIDD_INTR_DATA_EVT, ¶m);
|
||||
break;
|
||||
case BTA_HD_VC_UNPLUG_EVT: {
|
||||
bt_bdaddr_t *bd_addr = (bt_bdaddr_t *)&p_data->conn.bda;
|
||||
if (bta_dm_check_if_only_hd_connected(p_data->conn.bda)) {
|
||||
BTC_TRACE_DEBUG("%s: Removing bonding as only HID profile connected", __func__);
|
||||
BTA_DmRemoveDevice((uint8_t *)&p_data->conn.bda, BT_TRANSPORT_BR_EDR);
|
||||
} else {
|
||||
BTC_TRACE_DEBUG("%s: Only removing HID data as some other profiles connected", __func__);
|
||||
btc_hd_remove_device(*bd_addr);
|
||||
}
|
||||
param.close.status = p_data->conn.status;
|
||||
param.close.conn_status = p_data->conn.conn_status;
|
||||
btc_hd_cb_to_app(ESP_HIDD_CLOSE_EVT, ¶m);
|
||||
param.vc_unplug.status = p_data->conn.status;
|
||||
param.vc_unplug.conn_status = p_data->conn.conn_status;
|
||||
btc_hd_cb_to_app(ESP_HIDD_VC_UNPLUG_EVT, ¶m);
|
||||
break;
|
||||
}
|
||||
case BTA_HD_SEND_REPORT_EVT:
|
||||
param.send_report.status = p_data->send_report.status;
|
||||
param.send_report.reason = p_data->send_report.reason;
|
||||
param.send_report.report_type = p_data->send_report.report_type;
|
||||
param.send_report.report_id = p_data->send_report.report_id;
|
||||
btc_hd_cb_to_app(ESP_HIDD_SEND_REPORT_EVT, ¶m);
|
||||
break;
|
||||
case BTA_HD_REPORT_ERR_EVT:
|
||||
param.report_err.status = p_data->report_err.status;
|
||||
param.report_err.reason = p_data->report_err.reason;
|
||||
btc_hd_cb_to_app(ESP_HIDD_REPORT_ERR_EVT, ¶m);
|
||||
break;
|
||||
default:
|
||||
BTC_TRACE_WARNING("%s: unknown event (%d)", __func__, event);
|
||||
break;
|
||||
}
|
||||
btc_hd_cb_arg_deep_free(msg);
|
||||
}
|
||||
|
||||
void btc_hd_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src)
|
||||
{
|
||||
btc_hidd_args_t *dst = (btc_hidd_args_t *)p_dest;
|
||||
btc_hidd_args_t *src = (btc_hidd_args_t *)p_src;
|
||||
|
||||
switch (msg->act) {
|
||||
case BTC_HD_SEND_REPORT_EVT:
|
||||
dst->send_report.data = (uint8_t *)osi_malloc(src->send_report.len);
|
||||
if (dst->send_report.data) {
|
||||
memcpy(dst->send_report.data, src->send_report.data, src->send_report.len);
|
||||
} else {
|
||||
BTC_TRACE_ERROR("%s %d osi_malloc failed\n", __func__, msg->act);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // HID_DEV_INCLUDED==TRUE
|
1569
components/bt/host/bluedroid/btc/profile/std/hid/btc_hh.c
Normal file
1569
components/bt/host/bluedroid/btc/profile/std/hid/btc_hh.c
Normal file
File diff suppressed because it is too large
Load Diff
103
components/bt/host/bluedroid/btc/profile/std/include/btc_hd.h
Normal file
103
components/bt/host/bluedroid/btc/profile/std/include/btc_hd.h
Normal file
@ -0,0 +1,103 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
* Copyright (C) 2009-2012 Broadcom Corporation
|
||||
* Copyright (C) 2019 Blake Felt
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef BTC_HD_H
|
||||
#define BTC_HD_H
|
||||
|
||||
#if BTC_HD_INCLUDED == TRUE
|
||||
|
||||
#include <stdint.h>
|
||||
#include "bta/bta_hd_api.h"
|
||||
#include "btc/btc_task.h"
|
||||
#include "esp_hidd_api.h"
|
||||
|
||||
typedef enum {
|
||||
BTC_HD_INIT_EVT = 0,
|
||||
BTC_HD_DEINIT_EVT,
|
||||
BTC_HD_REGISTER_APP_EVT,
|
||||
BTC_HD_UNREGISTER_APP_EVT,
|
||||
BTC_HD_CONNECT_EVT,
|
||||
BTC_HD_DISCONNECT_EVT,
|
||||
BTC_HD_SEND_REPORT_EVT,
|
||||
BTC_HD_REPORT_ERROR_EVT,
|
||||
BTC_HD_UNPLUG_EVT,
|
||||
} BTC_HD_EVT;
|
||||
|
||||
typedef enum { BTC_HD_DISABLED = 0, BTC_HD_ENABLED, BTC_HD_DISABLING } BTC_HD_STATUS;
|
||||
|
||||
/* BTIF-HD control block */
|
||||
typedef struct {
|
||||
BTC_HD_STATUS status;
|
||||
bool app_registered;
|
||||
bool service_dereg_active;
|
||||
bool forced_disc;
|
||||
tBTA_HD_APP_INFO app_info;
|
||||
tBTA_HD_QOS_INFO in_qos;
|
||||
tBTA_HD_QOS_INFO out_qos;
|
||||
} btc_hd_cb_t;
|
||||
|
||||
/* btc_hidd_args_t */
|
||||
typedef union {
|
||||
// BTC_HD_CONNECT_EVT
|
||||
struct connect_arg {
|
||||
BD_ADDR bd_addr;
|
||||
} connect;
|
||||
|
||||
// BTC_HD_REGISTER_APP_EVT
|
||||
struct register_app_arg {
|
||||
esp_hidd_app_param_t *app_param;
|
||||
esp_hidd_qos_param_t *in_qos;
|
||||
esp_hidd_qos_param_t *out_qos;
|
||||
} register_app;
|
||||
|
||||
// BTC_HD_SEND_REPORT_EVT
|
||||
struct send_report_arg {
|
||||
esp_hidd_report_type_t type;
|
||||
uint8_t id;
|
||||
uint16_t len;
|
||||
uint8_t *data;
|
||||
} send_report;
|
||||
|
||||
// BTC_HD_REPORT_ERROR_EVT
|
||||
uint8_t error;
|
||||
} btc_hidd_args_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/******************************************************************************
|
||||
* Functions
|
||||
******************************************************************************/
|
||||
void btc_hd_call_handler(btc_msg_t *msg);
|
||||
|
||||
void btc_hd_cb_handler(btc_msg_t *msg);
|
||||
|
||||
// extern btc_hd_cb_t btc_hd_cb;
|
||||
// extern void btc_hd_remove_device(bt_bdaddr_t bd_addr);
|
||||
// extern void btc_hd_service_registration();
|
||||
|
||||
void btc_hd_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* BTC_HD_INCLUDED == TRUE */
|
||||
#endif /* BTC_HD_H */
|
187
components/bt/host/bluedroid/btc/profile/std/include/btc_hh.h
Normal file
187
components/bt/host/bluedroid/btc/profile/std/include/btc_hh.h
Normal file
@ -0,0 +1,187 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
* Copyright (C) 2009-2012 Broadcom Corporation
|
||||
* Copyright (C) 2019 Blake Felt
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef BTC_HH_H
|
||||
#define BTC_HH_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "bta/bta_hh_api.h"
|
||||
#include "btc/btc_task.h"
|
||||
#include "osi/alarm.h"
|
||||
#include "esp_hidh_api.h"
|
||||
|
||||
#define BTC_HH_MAX_HID 8
|
||||
#define BTC_HH_MAX_ADDED_DEV 32
|
||||
|
||||
#define BTC_HH_MAX_KEYSTATES 3
|
||||
#define BTC_HH_KEYSTATE_MASK_NUMLOCK 0x01
|
||||
#define BTC_HH_KEYSTATE_MASK_CAPSLOCK 0x02
|
||||
#define BTC_HH_KEYSTATE_MASK_SCROLLLOCK 0x04
|
||||
|
||||
#define BTC_HH_MAX_POLLING_ATTEMPTS 10
|
||||
#define BTC_HH_POLLING_SLEEP_DURATION_US 5000
|
||||
|
||||
/*******************************************************************************
|
||||
* Type definitions and return values
|
||||
******************************************************************************/
|
||||
typedef enum {
|
||||
BTC_HH_INIT_EVT = 0,
|
||||
BTC_HH_CONNECT_EVT,
|
||||
BTC_HH_DISCONNECT_EVT,
|
||||
BTC_HH_UNPLUG_EVT,
|
||||
BTC_HH_SET_INFO_EVT,
|
||||
BTC_HH_GET_PROTO_EVT,
|
||||
BTC_HH_SET_PROTO_EVT,
|
||||
BTC_HH_GET_IDLE_EVT,
|
||||
BTC_HH_SET_IDLE_EVT,
|
||||
BTC_HH_GET_REPORT_EVT,
|
||||
BTC_HH_SET_REPORT_EVT,
|
||||
BTC_HH_SEND_DATA_EVT,
|
||||
BTC_HH_DEINIT_EVT,
|
||||
} BTC_HH_EVT;
|
||||
|
||||
typedef enum {
|
||||
BTC_HH_DISABLED = 0,
|
||||
BTC_HH_ENABLED,
|
||||
BTC_HH_DISABLING,
|
||||
BTC_HH_DEV_UNKNOWN,
|
||||
BTC_HH_DEV_CONNECTING,
|
||||
BTC_HH_DEV_CONNECTED,
|
||||
BTC_HH_DEV_DISCONNECTED
|
||||
} BTC_HH_STATUS;
|
||||
|
||||
typedef struct {
|
||||
esp_hidh_connection_state_t dev_status;
|
||||
uint8_t dev_handle;
|
||||
BD_ADDR bd_addr;
|
||||
uint16_t attr_mask;
|
||||
uint8_t sub_class;
|
||||
uint8_t app_id;
|
||||
bool ready_for_data;
|
||||
osi_alarm_t *vup_timer;
|
||||
bool local_vup; // Indicated locally initiated VUP
|
||||
} btc_hh_device_t;
|
||||
|
||||
/* Control block to maintain properties of devices */
|
||||
typedef struct {
|
||||
uint8_t dev_handle;
|
||||
BD_ADDR bd_addr;
|
||||
uint16_t attr_mask;
|
||||
} btc_hh_added_device_t;
|
||||
|
||||
/**
|
||||
* BTC-HH control block to maintain added devices and currently
|
||||
* connected hid devices
|
||||
*/
|
||||
typedef struct {
|
||||
BTC_HH_STATUS status;
|
||||
btc_hh_device_t devices[BTC_HH_MAX_HID];
|
||||
uint32_t device_num;
|
||||
BTC_HH_EVT add_event;
|
||||
btc_hh_added_device_t added_devices[BTC_HH_MAX_ADDED_DEV];
|
||||
btc_hh_device_t *p_curr_dev;
|
||||
bool service_dereg_active;
|
||||
BD_ADDR pending_conn_address;
|
||||
} btc_hh_cb_t;
|
||||
|
||||
/* btc_spp_args_t */
|
||||
typedef union {
|
||||
// BTC_HH_CONNECT_EVT
|
||||
struct connect_arg {
|
||||
BD_ADDR bd_addr;
|
||||
} connect;
|
||||
|
||||
// BTC_HH_DISCONNECT_EVT
|
||||
struct disconnect_arg {
|
||||
BD_ADDR bd_addr;
|
||||
} disconnect;
|
||||
|
||||
// BTC_HH_UNPLUG_EVT
|
||||
struct unplug_arg {
|
||||
BD_ADDR bd_addr;
|
||||
} unplug;
|
||||
|
||||
// BTC_HH_SET_INFO_EVT
|
||||
struct set_info_arg {
|
||||
BD_ADDR bd_addr;
|
||||
esp_hidh_hid_info_t *hid_info;
|
||||
} set_info;
|
||||
|
||||
// BTC_HH_GET_PROTO_EVT
|
||||
struct get_protocol_arg {
|
||||
BD_ADDR bd_addr;
|
||||
} get_protocol;
|
||||
|
||||
// BTC_HH_SET_PROTO_EVT
|
||||
struct set_protocol_arg {
|
||||
BD_ADDR bd_addr;
|
||||
esp_hidh_protocol_mode_t protocol_mode;
|
||||
} set_protocol;
|
||||
|
||||
// BTC_HH_GET_IDLE_EVT
|
||||
struct get_idle_arg {
|
||||
BD_ADDR bd_addr;
|
||||
} get_idle;
|
||||
|
||||
// BTC_HH_SET_IDLE_EVT
|
||||
struct set_idle_arg {
|
||||
BD_ADDR bd_addr;
|
||||
uint16_t idle_time;
|
||||
} set_idle;
|
||||
|
||||
// BTC_HH_GET_REPORT_EVT
|
||||
struct get_report_arg {
|
||||
BD_ADDR bd_addr;
|
||||
esp_hidh_report_type_t report_type;
|
||||
uint8_t report_id;
|
||||
int buffer_size;
|
||||
} get_report;
|
||||
|
||||
// BTC_HH_SET_REPORT_EVT
|
||||
struct set_report_arg {
|
||||
BD_ADDR bd_addr;
|
||||
esp_hidh_report_type_t report_type;
|
||||
size_t len;
|
||||
uint8_t *report;
|
||||
} set_report;
|
||||
|
||||
// BTC_HH_SEND_DATA_EVT
|
||||
struct send_data_arg {
|
||||
BD_ADDR bd_addr;
|
||||
size_t len;
|
||||
uint8_t *data;
|
||||
} send_data;
|
||||
} btc_hidh_args_t;
|
||||
/*******************************************************************************
|
||||
* Variables
|
||||
******************************************************************************/
|
||||
extern btc_hh_cb_t btc_hh_cb;
|
||||
/*******************************************************************************
|
||||
* Functions
|
||||
******************************************************************************/
|
||||
|
||||
void btc_hh_call_handler(btc_msg_t *msg);
|
||||
|
||||
void btc_hh_cb_handler(btc_msg_t *msg);
|
||||
|
||||
void btc_hh_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src);
|
||||
|
||||
bool btc_hh_add_added_dev(BD_ADDR bd_addr, uint16_t attr_mask);
|
||||
|
||||
#endif /* BTC_HH_H */
|
@ -67,6 +67,13 @@
|
||||
#define UC_BT_HFP_CLIENT_ENABLED FALSE
|
||||
#endif
|
||||
|
||||
//HID
|
||||
#ifdef CONFIG_BT_HID_ENABLED
|
||||
#define UC_BT_HID_ENABLED CONFIG_BT_HID_ENABLED
|
||||
#else
|
||||
#define UC_BT_HID_ENABLED FALSE
|
||||
#endif
|
||||
|
||||
//HID HOST(BT)
|
||||
#ifdef CONFIG_BT_HID_HOST_ENABLED
|
||||
#define UC_BT_HID_HOST_ENABLED CONFIG_BT_HID_HOST_ENABLED
|
||||
@ -74,6 +81,13 @@
|
||||
#define UC_BT_HID_HOST_ENABLED FALSE
|
||||
#endif
|
||||
|
||||
//HID Device(BT)
|
||||
#ifdef CONFIG_BT_HID_DEVICE_ENABLED
|
||||
#define UC_BT_HID_DEVICE_ENABLED CONFIG_BT_HID_DEVICE_ENABLED
|
||||
#else
|
||||
#define UC_BT_HID_DEVICE_ENABLED FALSE
|
||||
#endif
|
||||
|
||||
//SSP
|
||||
#ifdef CONFIG_BT_SSP_ENABLED
|
||||
#define UC_BT_SSP_ENABLED CONFIG_BT_SSP_ENABLED
|
||||
@ -148,7 +162,7 @@
|
||||
#define UC_BT_SMP_SLAVE_CON_PARAMS_UPD_ENABLE FALSE
|
||||
#endif
|
||||
|
||||
#if CONFIG_BT_CTRL_ESP32
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
//BTDM_BLE_ADV_REPORT_FLOW_CTRL_SUPP
|
||||
#ifdef CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_SUPP
|
||||
#define UC_BTDM_BLE_ADV_REPORT_FLOW_CTRL_SUPP CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_SUPP
|
||||
@ -170,9 +184,9 @@
|
||||
#define UC_BTDM_BLE_ADV_REPORT_DISCARD_THRSHOLD 20
|
||||
#endif
|
||||
|
||||
#endif //CONFIG_BT_CTRL_ESP32
|
||||
#endif //CONFIG_IDF_TARGET_ESP32
|
||||
|
||||
#if (CONFIG_BT_CTRL_ESP32C3 || CONFIG_BT_CTRL_ESP32S3)
|
||||
#if (CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3)
|
||||
//BTDM_BLE_ADV_REPORT_FLOW_CTRL_SUPP
|
||||
#ifdef CONFIG_BT_CTRL_BLE_ADV_REPORT_FLOW_CTRL_SUPP
|
||||
#define UC_BTDM_BLE_ADV_REPORT_FLOW_CTRL_SUPP CONFIG_BT_CTRL_BLE_ADV_REPORT_FLOW_CTRL_SUPP
|
||||
@ -194,7 +208,7 @@
|
||||
#define UC_BTDM_BLE_ADV_REPORT_DISCARD_THRSHOLD 20
|
||||
#endif
|
||||
|
||||
#endif //(CONFIG_BT_CTRL_ESP32C3 || CONFIG_BT_CTRL_ESP32S3)
|
||||
#endif //(CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3)
|
||||
|
||||
//BT ACL CONNECTIONS
|
||||
#ifdef CONFIG_BT_ACL_CONNECTIONS
|
||||
@ -365,10 +379,18 @@
|
||||
#define UC_BT_LOG_MCA_TRACE_LEVEL UC_TRACE_LEVEL_WARNING
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BT_LOG_HIDH_TRACE_LEVEL
|
||||
#define UC_BT_LOG_HIDH_TRACE_LEVEL CONFIG_BT_LOG_HIDH_TRACE_LEVEL
|
||||
#ifdef CONFIG_BT_LOG_HID_TRACE_LEVEL
|
||||
#if UC_BT_HID_HOST_ENABLED
|
||||
#define UC_BT_LOG_HIDH_TRACE_LEVEL CONFIG_BT_LOG_HID_TRACE_LEVEL
|
||||
#elif UC_BT_HID_DEVICE_ENABLED
|
||||
#define UC_BT_LOG_HIDD_TRACE_LEVEL CONFIG_BT_LOG_HID_TRACE_LEVEL
|
||||
#endif
|
||||
#else
|
||||
#if UC_BT_HID_HOST_ENABLED
|
||||
#define UC_BT_LOG_HIDH_TRACE_LEVEL UC_TRACE_LEVEL_WARNING
|
||||
#elif UC_BT_HID_DEVICE_ENABLED
|
||||
#define UC_BT_LOG_HIDD_TRACE_LEVEL UC_TRACE_LEVEL_WARNING
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BT_LOG_APPL_TRACE_LEVEL
|
||||
|
@ -130,11 +130,22 @@
|
||||
#define BT_SSP_INCLUDED TRUE
|
||||
#endif /* UC_BT_SSP_ENABLED */
|
||||
|
||||
#if UC_BT_HID_ENABLED
|
||||
#define BT_HID_INCLUDED TRUE
|
||||
#endif /* UC_BT_HID_ENABLED */
|
||||
|
||||
#if UC_BT_HID_HOST_ENABLED
|
||||
#define HID_HOST_INCLUDED TRUE
|
||||
#define BTA_HH_INCLUDED TRUE
|
||||
#define BTC_HH_INCLUDED TRUE
|
||||
#endif /* UC_BT_HID_HOST_ENABLED */
|
||||
|
||||
#if UC_BT_HID_DEVICE_ENABLED
|
||||
#define HID_DEV_INCLUDED TRUE
|
||||
#define BTA_HD_INCLUDED TRUE
|
||||
#define BTC_HD_INCLUDED TRUE
|
||||
#endif /* UC_BT_HID_DEVICE_ENABLED */
|
||||
|
||||
#endif /* UC_BT_CLASSIC_ENABLED */
|
||||
|
||||
/* This is set to enable use of GAP L2CAP connections. */
|
||||
@ -321,6 +332,14 @@
|
||||
#define BTC_SPP_INCLUDED FALSE
|
||||
#endif
|
||||
|
||||
#ifndef BTC_HH_INCLUDED
|
||||
#define BTC_HH_INCLUDED FALSE
|
||||
#endif
|
||||
|
||||
#ifndef BTC_HD_INCLUDED
|
||||
#define BTC_HD_INCLUDED FALSE
|
||||
#endif
|
||||
|
||||
#ifndef SBC_DEC_INCLUDED
|
||||
#define SBC_DEC_INCLUDED FALSE
|
||||
#endif
|
||||
@ -350,6 +369,10 @@
|
||||
#define BTA_PAN_INCLUDED FALSE
|
||||
#endif
|
||||
|
||||
#ifndef BTA_HD_INCLUDED
|
||||
#define BTA_HD_INCLUDED FALSE
|
||||
#endif
|
||||
|
||||
#ifndef BTA_HH_INCLUDED
|
||||
#define BTA_HH_INCLUDED FALSE
|
||||
#endif
|
||||
@ -1378,7 +1401,11 @@
|
||||
|
||||
/* The maximum number of attributes in each record. */
|
||||
#ifndef SDP_MAX_REC_ATTR
|
||||
#if defined(HID_DEV_INCLUDED) && (HID_DEV_INCLUDED==TRUE)
|
||||
#define SDP_MAX_REC_ATTR 25
|
||||
#else
|
||||
#define SDP_MAX_REC_ATTR 8
|
||||
#endif /* defined(HID_DEV_INCLUDED) && (HID_DEV_INCLUDED==TRUE) */
|
||||
#endif
|
||||
|
||||
#ifndef SDP_MAX_PAD_LEN
|
||||
@ -1845,6 +1872,18 @@ Range: 2 octets
|
||||
** HID
|
||||
**
|
||||
******************************************************************************/
|
||||
#ifndef BT_HID_INCLUDED
|
||||
#define BT_HID_INCLUDED FALSE
|
||||
#endif
|
||||
|
||||
/* HID Device Role Included */
|
||||
#ifndef HID_DEV_INCLUDED
|
||||
#define HID_DEV_INCLUDED FALSE
|
||||
#endif
|
||||
|
||||
#ifndef HID_DEV_SUBCLASS
|
||||
#define HID_DEV_SUBCLASS COD_MINOR_POINTING
|
||||
#endif
|
||||
|
||||
#ifndef HID_CONTROL_BUF_SIZE
|
||||
#define HID_CONTROL_BUF_SIZE BT_DEFAULT_BUFFER_SIZE
|
||||
@ -1854,6 +1893,14 @@ Range: 2 octets
|
||||
#define HID_INTERRUPT_BUF_SIZE BT_DEFAULT_BUFFER_SIZE
|
||||
#endif
|
||||
|
||||
#ifndef HID_DEV_MTU_SIZE
|
||||
#define HID_DEV_MTU_SIZE 64
|
||||
#endif
|
||||
|
||||
#ifndef HID_DEV_FLUSH_TO
|
||||
#define HID_DEV_FLUSH_TO 0xffff
|
||||
#endif
|
||||
|
||||
/*************************************************************************
|
||||
** Definitions for Both HID-Host & Device
|
||||
*/
|
||||
|
@ -106,6 +106,7 @@ static inline void trc_dump_buffer(const char *prefix, uint8_t *data, uint16_t l
|
||||
#define BTTRC_ID_STK_CE 51
|
||||
#define BTTRC_ID_STK_SNEP 52
|
||||
#define BTTRC_ID_STK_NDEF 53
|
||||
#define BTTRC_ID_STK_HIDD 54
|
||||
|
||||
/* LayerIDs for BTA */
|
||||
#define BTTRC_ID_BTA_ACC 55 /* Advanced Camera Client */
|
||||
@ -199,6 +200,7 @@ static inline void trc_dump_buffer(const char *prefix, uint8_t *data, uint16_t l
|
||||
#define AVRC_INITIAL_TRACE_LEVEL UC_BT_LOG_AVRC_TRACE_LEVEL
|
||||
#define MCA_INITIAL_TRACE_LEVEL UC_BT_LOG_MCA_TRACE_LEVEL
|
||||
#define HIDH_INITIAL_TRACE_LEVEL UC_BT_LOG_HIDH_TRACE_LEVEL
|
||||
#define HIDD_INITIAL_TRACE_LEVEL UC_BT_LOG_HIDD_TRACE_LEVEL
|
||||
#define APPL_INITIAL_TRACE_LEVEL UC_BT_LOG_APPL_TRACE_LEVEL
|
||||
#define GATT_INITIAL_TRACE_LEVEL UC_BT_LOG_GATT_TRACE_LEVEL
|
||||
#define SMP_INITIAL_TRACE_LEVEL UC_BT_LOG_SMP_TRACE_LEVEL
|
||||
@ -258,6 +260,14 @@ static inline void trc_dump_buffer(const char *prefix, uint8_t *data, uint16_t l
|
||||
#define HIDH_TRACE_EVENT(fmt, args...) {if (hh_cb.trace_level >= BT_TRACE_LEVEL_EVENT && BT_LOG_LEVEL_CHECK(HIDH,EVENT)) BT_PRINT_D("BT_HIDH", fmt, ## args);}
|
||||
#define HIDH_TRACE_DEBUG(fmt, args...) {if (hh_cb.trace_level >= BT_TRACE_LEVEL_DEBUG && BT_LOG_LEVEL_CHECK(HIDH,DEBUG)) BT_PRINT_D("BT_HIDH", fmt, ## args);}
|
||||
|
||||
/* define traces for HID Device */
|
||||
#define HIDD_TRACE_ERROR(fmt, args...) {if (hd_cb.trace_level >= BT_TRACE_LEVEL_ERROR && BT_LOG_LEVEL_CHECK(HIDD, ERROR)) BT_PRINT_E("BT_HIDD", fmt, ## args);}
|
||||
#define HIDD_TRACE_WARNING(fmt, args...) {if (hd_cb.trace_level >= BT_TRACE_LEVEL_WARNING && BT_LOG_LEVEL_CHECK(HIDD, WARNING)) BT_PRINT_W("BT_HIDD", fmt, ## args);}
|
||||
#define HIDD_TRACE_API(fmt, args...) {if (hd_cb.trace_level >= BT_TRACE_LEVEL_API && BT_LOG_LEVEL_CHECK(HIDD,API)) BT_PRINT_I("BT_HIDD", fmt, ## args);}
|
||||
#define HIDD_TRACE_EVENT(fmt, args...) {if (hd_cb.trace_level >= BT_TRACE_LEVEL_EVENT && BT_LOG_LEVEL_CHECK(HIDD,EVENT)) BT_PRINT_D("BT_HIDD", fmt, ## args);}
|
||||
#define HIDD_TRACE_DEBUG(fmt, args...) {if (hd_cb.trace_level >= BT_TRACE_LEVEL_DEBUG && BT_LOG_LEVEL_CHECK(HIDD,DEBUG)) BT_PRINT_D("BT_HIDD", fmt, ## args);}
|
||||
#define HIDD_TRACE_VERBOSE(fmt, args...) {if (hd_cb.trace_level >= BT_TRACE_LEVEL_VERBOSE && BT_LOG_LEVEL_CHECK(HIDD,VERBOSE)) BT_PRINT_D("BT_HIDD", fmt, ## args);}
|
||||
|
||||
/* define traces for BNEP */
|
||||
|
||||
#define BNEP_TRACE_ERROR(fmt, args...) {if (bnep_cb.trace_level >= BT_TRACE_LEVEL_ERROR && BT_LOG_LEVEL_CHECK(BNEP, ERROR)) BT_PRINT_E("BT_BNEP", fmt, ## args);}
|
||||
@ -418,6 +428,14 @@ extern UINT8 btif_trace_level;
|
||||
#define HIDH_TRACE_EVENT(fmt, args...)
|
||||
#define HIDH_TRACE_DEBUG(fmt, args...)
|
||||
|
||||
/* define traces for HID Device */
|
||||
#define HIDD_TRACE_ERROR(fmt, args...)
|
||||
#define HIDD_TRACE_WARNING(fmt, args...)
|
||||
#define HIDD_TRACE_API(fmt, args...)
|
||||
#define HIDD_TRACE_EVENT(fmt, args...)
|
||||
#define HIDD_TRACE_DEBUG(fmt, args...)
|
||||
#define HIDD_TRACE_VERBOSE(fmt, args...)
|
||||
|
||||
/* define traces for BNEP */
|
||||
|
||||
#define BNEP_TRACE_ERROR(fmt, args...)
|
||||
|
@ -52,6 +52,14 @@
|
||||
#include "pan_api.h"
|
||||
#endif
|
||||
|
||||
#if (defined(HID_HOST_INCLUDED) && HID_HOST_INCLUDED == TRUE)
|
||||
#include "stack/hidh_api.h"
|
||||
#endif
|
||||
|
||||
#if (defined(HID_DEV_INCLUDED) && HID_DEV_INCLUDED == TRUE)
|
||||
#include "stack/hidd_api.h"
|
||||
#endif
|
||||
|
||||
#if (defined(AVRC_INCLUDED) && AVRC_INCLUDED == TRUE)
|
||||
#include "stack/avrc_api.h"
|
||||
#endif
|
||||
@ -118,6 +126,10 @@
|
||||
#include "bta_hh_int.h"
|
||||
#endif
|
||||
|
||||
#if BTA_HD_INCLUDED==TRUE
|
||||
#include "bta_hd_int.h"
|
||||
#endif
|
||||
|
||||
#if BTA_JV_INCLUDED==TRUE
|
||||
#include "bta_jv_int.h"
|
||||
#endif
|
||||
@ -175,6 +187,12 @@ void BTE_DeinitStack(void)
|
||||
bta_gattc_cb_ptr = NULL;
|
||||
}
|
||||
#endif
|
||||
#if BTA_HD_INCLUDED==TRUE
|
||||
if (bta_hd_cb_ptr){
|
||||
osi_free(bta_hd_cb_ptr);
|
||||
bta_hd_cb_ptr = NULL;
|
||||
}
|
||||
#endif
|
||||
#if BTA_HH_INCLUDED==TRUE
|
||||
if (bta_hh_cb_ptr){
|
||||
osi_free(bta_hh_cb_ptr);
|
||||
@ -249,6 +267,14 @@ void BTE_DeinitStack(void)
|
||||
}
|
||||
#endif // BTA_INCLUDED == TRUE
|
||||
|
||||
#if (defined(HID_DEV_INCLUDED) && HID_DEV_INCLUDED == TRUE)
|
||||
HID_DevDeinit();
|
||||
#endif
|
||||
|
||||
#if (defined(HID_HOST_INCLUDED) && HID_HOST_INCLUDED == TRUE)
|
||||
HID_HostDeinit();
|
||||
#endif
|
||||
|
||||
#if (defined(GAP_INCLUDED) && GAP_INCLUDED == TRUE)
|
||||
GAP_Deinit();
|
||||
#endif
|
||||
@ -347,7 +373,15 @@ bt_status_t BTE_InitStack(void)
|
||||
#endif
|
||||
|
||||
#if (defined(HID_HOST_INCLUDED) && HID_HOST_INCLUDED == TRUE)
|
||||
HID_HostInit();
|
||||
if (HID_HostInit() != HID_SUCCESS) {
|
||||
goto error_exit;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (defined(HID_DEV_INCLUDED) && HID_DEV_INCLUDED == TRUE)
|
||||
if (HID_DevInit() != HID_SUCCESS) {
|
||||
goto error_exit;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (defined(MCA_INCLUDED) && MCA_INCLUDED == TRUE)
|
||||
@ -434,6 +468,12 @@ bt_status_t BTE_InitStack(void)
|
||||
}
|
||||
memset((void *)bta_hh_cb_ptr, 0, sizeof(tBTA_HH_CB));
|
||||
#endif
|
||||
#if BTA_HD_INCLUDED==TRUE
|
||||
if ((bta_hd_cb_ptr = (tBTA_HD_CB *)osi_malloc(sizeof(tBTA_HD_CB))) == NULL) {
|
||||
goto error_exit;
|
||||
}
|
||||
memset((void *)bta_hd_cb_ptr, 0, sizeof(tBTA_HD_CB));
|
||||
#endif
|
||||
#if BTA_HL_INCLUDED==TRUE
|
||||
memset((void *)bta_hl_cb_ptr, 0, sizeof(tBTA_HL_CB));
|
||||
#endif
|
||||
|
@ -2981,6 +2981,7 @@ void btm_sec_rmt_name_request_complete (UINT8 *p_bd_addr, UINT8 *p_bd_name, UINT
|
||||
int i;
|
||||
DEV_CLASS dev_class;
|
||||
UINT8 old_sec_state;
|
||||
UINT8 res;
|
||||
|
||||
BTM_TRACE_EVENT ("btm_sec_rmt_name_request_complete\n");
|
||||
if (((p_bd_addr == NULL) && !BTM_ACL_IS_CONNECTED(btm_cb.connecting_bda))
|
||||
@ -3161,9 +3162,12 @@ void btm_sec_rmt_name_request_complete (UINT8 *p_bd_addr, UINT8 *p_bd_name, UINT
|
||||
/* This is required when different entities receive link notification and auth complete */
|
||||
if (!(p_dev_rec->security_required & BTM_SEC_OUT_AUTHENTICATE)) {
|
||||
if (btm_cb.api.p_auth_complete_callback) {
|
||||
(*btm_cb.api.p_auth_complete_callback) (p_dev_rec->bd_addr,
|
||||
p_dev_rec->dev_class,
|
||||
p_dev_rec->sec_bd_name, HCI_SUCCESS);
|
||||
res = (*btm_cb.api.p_auth_complete_callback) (p_dev_rec->bd_addr,
|
||||
p_dev_rec->dev_class,
|
||||
p_dev_rec->sec_bd_name, HCI_SUCCESS);
|
||||
if (res == BTM_SEC_DEV_REC_REMOVED) {
|
||||
p_dev_rec = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -3853,6 +3857,7 @@ static void btm_sec_auth_collision (UINT16 handle)
|
||||
#if (SMP_INCLUDED == TRUE)
|
||||
void btm_sec_auth_complete (UINT16 handle, UINT8 status)
|
||||
{
|
||||
UINT8 res;
|
||||
UINT8 old_sm4;
|
||||
tBTM_PAIRING_STATE old_state = btm_cb.pairing_state;
|
||||
tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev_by_handle (handle);
|
||||
@ -3942,9 +3947,12 @@ void btm_sec_auth_complete (UINT16 handle, UINT8 status)
|
||||
if (btm_cb.api.p_auth_complete_callback) {
|
||||
/* report the authentication status */
|
||||
if (old_state != BTM_PAIR_STATE_IDLE) {
|
||||
(*btm_cb.api.p_auth_complete_callback) (p_dev_rec->bd_addr,
|
||||
p_dev_rec->dev_class,
|
||||
p_dev_rec->sec_bd_name, status);
|
||||
res = (*btm_cb.api.p_auth_complete_callback) (p_dev_rec->bd_addr,
|
||||
p_dev_rec->dev_class,
|
||||
p_dev_rec->sec_bd_name, status);
|
||||
if (res == BTM_SEC_DEV_REC_REMOVED) {
|
||||
p_dev_rec = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -4241,6 +4249,7 @@ void btm_sec_connected (UINT8 *bda, UINT16 handle, UINT8 status, UINT8 enc_mode)
|
||||
{
|
||||
tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (bda);
|
||||
UINT8 res;
|
||||
UINT8 sec_dev_rec_status;
|
||||
BOOLEAN is_pairing_device = FALSE;
|
||||
tACL_CONN *p_acl_cb;
|
||||
UINT8 bit_shift = 0;
|
||||
@ -4379,9 +4388,12 @@ void btm_sec_connected (UINT8 *bda, UINT16 handle, UINT8 status, UINT8 enc_mode)
|
||||
|
||||
/* We need to notify host that the key is not known any more */
|
||||
if (btm_cb.api.p_auth_complete_callback) {
|
||||
(*btm_cb.api.p_auth_complete_callback) (p_dev_rec->bd_addr,
|
||||
p_dev_rec->dev_class,
|
||||
p_dev_rec->sec_bd_name, status);
|
||||
sec_dev_rec_status = (*btm_cb.api.p_auth_complete_callback) (p_dev_rec->bd_addr,
|
||||
p_dev_rec->dev_class,
|
||||
p_dev_rec->sec_bd_name, status);
|
||||
if (sec_dev_rec_status == BTM_SEC_DEV_REC_REMOVED) {
|
||||
p_dev_rec = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
@ -4412,9 +4424,12 @@ void btm_sec_connected (UINT8 *bda, UINT16 handle, UINT8 status, UINT8 enc_mode)
|
||||
|
||||
/* We need to notify host that the key is not known any more */
|
||||
if (btm_cb.api.p_auth_complete_callback) {
|
||||
(*btm_cb.api.p_auth_complete_callback) (p_dev_rec->bd_addr,
|
||||
p_dev_rec->dev_class,
|
||||
p_dev_rec->sec_bd_name, status);
|
||||
sec_dev_rec_status = (*btm_cb.api.p_auth_complete_callback) (p_dev_rec->bd_addr,
|
||||
p_dev_rec->dev_class,
|
||||
p_dev_rec->sec_bd_name, status);
|
||||
if (sec_dev_rec_status == BTM_SEC_DEV_REC_REMOVED) {
|
||||
p_dev_rec = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -4447,9 +4462,12 @@ void btm_sec_connected (UINT8 *bda, UINT16 handle, UINT8 status, UINT8 enc_mode)
|
||||
}
|
||||
|
||||
if (btm_cb.api.p_auth_complete_callback) {
|
||||
(*btm_cb.api.p_auth_complete_callback) (p_dev_rec->bd_addr,
|
||||
p_dev_rec->dev_class,
|
||||
p_dev_rec->sec_bd_name, HCI_SUCCESS);
|
||||
sec_dev_rec_status = (*btm_cb.api.p_auth_complete_callback) (p_dev_rec->bd_addr,
|
||||
p_dev_rec->dev_class,
|
||||
p_dev_rec->sec_bd_name, HCI_SUCCESS);
|
||||
if (sec_dev_rec_status == BTM_SEC_DEV_REC_REMOVED) {
|
||||
p_dev_rec = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
btm_sec_change_pairing_state (BTM_PAIR_STATE_IDLE);
|
||||
@ -4668,6 +4686,7 @@ void btm_sec_link_key_notification (UINT8 *p_bda, UINT8 *p_link_key, UINT8 key_t
|
||||
tBTM_SEC_DEV_REC *p_dev_rec = btm_find_or_alloc_dev (p_bda);
|
||||
BOOLEAN we_are_bonding = FALSE;
|
||||
BOOLEAN ltk_derived_lk = FALSE;
|
||||
UINT8 res;
|
||||
|
||||
BTM_TRACE_EVENT ("btm_sec_link_key_notification() BDA:%04x%08x, TYPE: %d\n",
|
||||
(p_bda[0] << 8) + p_bda[1], (p_bda[2] << 24) + (p_bda[3] << 16) + (p_bda[4] << 8) + p_bda[5],
|
||||
@ -4772,8 +4791,11 @@ void btm_sec_link_key_notification (UINT8 *p_bda, UINT8 *p_link_key, UINT8 key_t
|
||||
/* for derived key, always send authentication callback for BR channel */
|
||||
|| ltk_derived_lk) {
|
||||
if (btm_cb.api.p_auth_complete_callback) {
|
||||
(*btm_cb.api.p_auth_complete_callback) (p_dev_rec->bd_addr, p_dev_rec->dev_class,
|
||||
p_dev_rec->sec_bd_name, HCI_SUCCESS);
|
||||
res = (*btm_cb.api.p_auth_complete_callback) (p_dev_rec->bd_addr, p_dev_rec->dev_class,
|
||||
p_dev_rec->sec_bd_name, HCI_SUCCESS);
|
||||
if (res == BTM_SEC_DEV_REC_REMOVED) {
|
||||
p_dev_rec = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -5760,9 +5782,10 @@ static char *btm_pair_state_descr (tBTM_PAIRING_STATE state)
|
||||
*******************************************************************************/
|
||||
void btm_sec_dev_rec_cback_event (tBTM_SEC_DEV_REC *p_dev_rec, UINT8 res, BOOLEAN is_le_transport)
|
||||
{
|
||||
tBTM_SEC_CALLBACK *p_callback = p_dev_rec->p_callback;
|
||||
tBTM_SEC_CALLBACK *p_callback;
|
||||
|
||||
if (p_dev_rec->p_callback) {
|
||||
if (p_dev_rec && p_dev_rec->p_callback) {
|
||||
p_callback = p_dev_rec->p_callback;
|
||||
p_dev_rec->p_callback = NULL;
|
||||
|
||||
#if BLE_INCLUDED == TRUE
|
||||
|
@ -394,9 +394,7 @@ tBTM_STATUS btm_ble_start_inquiry (UINT8 mode, UINT8 duration);
|
||||
void btm_ble_stop_scan(void);
|
||||
void btm_clear_all_pending_le_entry(void);
|
||||
|
||||
BOOLEAN btm_ble_send_extended_scan_params(UINT8 scan_type, UINT32 scan_int,
|
||||
UINT32 scan_win, UINT8 addr_type_own,
|
||||
UINT8 scan_filter_policy);
|
||||
BOOLEAN btm_ble_send_extended_scan_params(UINT8 scan_type, UINT32 scan_int, UINT32 scan_win, UINT8 addr_type_own, UINT8 scan_filter_policy);
|
||||
void btm_ble_stop_inquiry(void);
|
||||
void btm_ble_init (void);
|
||||
void btm_ble_free (void);
|
||||
@ -407,8 +405,7 @@ void btm_ble_conn_complete(UINT8 *p, UINT16 evt_len, BOOLEAN enhanced);
|
||||
void btm_read_ble_local_supported_states_complete(UINT8 *p, UINT16 evt_len);
|
||||
tBTM_BLE_CONN_ST btm_ble_get_conn_st(void);
|
||||
void btm_ble_set_conn_st(tBTM_BLE_CONN_ST new_st);
|
||||
UINT8 *btm_ble_build_adv_data(tBTM_BLE_AD_MASK *p_data_mask, UINT8 **p_dst,
|
||||
tBTM_BLE_ADV_DATA *p_data);
|
||||
UINT8 *btm_ble_build_adv_data(tBTM_BLE_AD_MASK *p_data_mask, UINT8 **p_dst, tBTM_BLE_ADV_DATA *p_data);
|
||||
tBTM_STATUS btm_ble_start_adv(void);
|
||||
tBTM_STATUS btm_ble_stop_adv(void);
|
||||
tBTM_STATUS btm_ble_start_scan(void);
|
||||
|
@ -961,12 +961,10 @@ extern tBTM_CallbackFunc conn_param_update_cb;
|
||||
|
||||
typedef UINT8 tBTM_SEC_ACTION;
|
||||
|
||||
/*
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
*/
|
||||
|
||||
#if BTM_DYNAMIC_MEMORY == FALSE
|
||||
extern tBTM_CB btm_cb;
|
||||
|
@ -54,7 +54,7 @@
|
||||
#endif
|
||||
|
||||
#if (defined(HID_HOST_INCLUDED) && HID_HOST_INCLUDED == TRUE )
|
||||
#include "hidh_int.h"
|
||||
#include "hid_int.h"
|
||||
#endif
|
||||
|
||||
#if (defined(AVDT_INCLUDED) && AVDT_INCLUDED == TRUE)
|
||||
|
586
components/bt/host/bluedroid/stack/hid/hidd_api.c
Normal file
586
components/bt/host/bluedroid/stack/hid/hidd_api.c
Normal file
@ -0,0 +1,586 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
* Copyright (C) 2002-2012 Broadcom Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************/
|
||||
/******************************************************************************
|
||||
*
|
||||
* This file contains the HID Device API entry points
|
||||
*
|
||||
******************************************************************************/
|
||||
//#include <errno.h>
|
||||
//#include <hardware/bluetooth.h>
|
||||
//#include <hardware/bt_hd.h>
|
||||
#include "stack/hidd_api.h"
|
||||
#include "esp_hidd_api.h"
|
||||
#include "hid_int.h"
|
||||
#include "osi/allocator.h"
|
||||
#include "stack/btm_api.h"
|
||||
#include "stack/btu.h"
|
||||
#include "stack/hiddefs.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#if (HID_DEV_INCLUDED == TRUE)
|
||||
|
||||
#if HID_DYNAMIC_MEMORY == FALSE
|
||||
tHID_DEV_CTB hd_cb;
|
||||
#else
|
||||
tHID_DEV_CTB *hidd_cb_ptr = NULL;
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function HID_DevInit
|
||||
*
|
||||
* Description Initializes control block
|
||||
*
|
||||
* Returns tHID_STATUS
|
||||
*
|
||||
******************************************************************************/
|
||||
tHID_STATUS HID_DevInit(void)
|
||||
{
|
||||
#if (HID_DYNAMIC_MEMORY)
|
||||
if (!hidd_cb_ptr) {
|
||||
hidd_cb_ptr = (tHID_DEV_CTB *)osi_malloc(sizeof(tHID_DEV_CTB));
|
||||
if (!hidd_cb_ptr) {
|
||||
return HID_ERR_NO_RESOURCES;
|
||||
}
|
||||
}
|
||||
#endif /* #if (HID_DYNAMIC_MEMORY) */
|
||||
memset(&hd_cb, 0, sizeof(tHID_DEV_CTB));
|
||||
#if defined(HIDD_INITIAL_TRACE_LEVEL)
|
||||
hd_cb.trace_level = HIDD_INITIAL_TRACE_LEVEL;
|
||||
#else
|
||||
hd_cb.trace_level = BT_TRACE_LEVEL_NONE;
|
||||
#endif
|
||||
return HID_SUCCESS;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function HID_DevDeinit
|
||||
*
|
||||
* Description Deinitializes control block
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
void HID_DevDeinit(void)
|
||||
{
|
||||
#if (HID_DYNAMIC_MEMORY)
|
||||
if (hidd_cb_ptr) {
|
||||
osi_free(hidd_cb_ptr);
|
||||
hidd_cb_ptr = NULL;
|
||||
}
|
||||
#endif /* #if (HID_DYNAMIC_MEMORY) */
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function HID_DevSetTraceLevel
|
||||
*
|
||||
* Description This function sets the trace level for HID Dev. If called
|
||||
* with
|
||||
* a value of 0xFF, it simply reads the current trace level.
|
||||
*
|
||||
* Returns the new (current) trace level
|
||||
*
|
||||
******************************************************************************/
|
||||
uint8_t HID_DevSetTraceLevel(uint8_t new_level)
|
||||
{
|
||||
if (new_level != 0xFF) {
|
||||
hd_cb.trace_level = new_level;
|
||||
}
|
||||
|
||||
return (hd_cb.trace_level);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function HID_DevRegister
|
||||
*
|
||||
* Description Registers HID device with lower layers
|
||||
*
|
||||
* Returns tHID_STATUS
|
||||
*
|
||||
******************************************************************************/
|
||||
tHID_STATUS HID_DevRegister(tHID_DEV_HOST_CALLBACK *host_cback)
|
||||
{
|
||||
tHID_STATUS st;
|
||||
HIDD_TRACE_API("%s", __func__);
|
||||
|
||||
if (hd_cb.reg_flag) {
|
||||
return HID_ERR_ALREADY_REGISTERED;
|
||||
}
|
||||
|
||||
if (host_cback == NULL) {
|
||||
return HID_ERR_INVALID_PARAM;
|
||||
}
|
||||
/* Register with L2CAP */
|
||||
if ((st = hidd_conn_reg()) != HID_SUCCESS) {
|
||||
return st;
|
||||
}
|
||||
|
||||
hd_cb.callback = host_cback;
|
||||
hd_cb.reg_flag = TRUE;
|
||||
|
||||
if (hd_cb.pending_data) {
|
||||
osi_free(hd_cb.pending_data);
|
||||
hd_cb.pending_data = NULL;
|
||||
}
|
||||
return (HID_SUCCESS);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function HID_DevDeregister
|
||||
*
|
||||
* Description Deregisters HID device with lower layers
|
||||
*
|
||||
* Returns tHID_STATUS
|
||||
*
|
||||
******************************************************************************/
|
||||
tHID_STATUS HID_DevDeregister(void)
|
||||
{
|
||||
HIDD_TRACE_API("%s", __func__);
|
||||
|
||||
if (!hd_cb.reg_flag)
|
||||
return (HID_ERR_NOT_REGISTERED);
|
||||
hidd_conn_dereg();
|
||||
hd_cb.reg_flag = FALSE;
|
||||
|
||||
return (HID_SUCCESS);
|
||||
}
|
||||
|
||||
tHID_STATUS HID_DevSetSecurityLevel(uint8_t sec_lvl)
|
||||
{
|
||||
HIDD_TRACE_API("%s", __func__);
|
||||
if (!BTM_SetSecurityLevel(FALSE, "", BTM_SEC_SERVICE_HIDD_SEC_CTRL, sec_lvl, HID_PSM_CONTROL, BTM_SEC_PROTO_HID,
|
||||
HIDD_SEC_CHN)) {
|
||||
HIDD_TRACE_ERROR("Security Registration 1 failed");
|
||||
return (HID_ERR_NO_RESOURCES);
|
||||
}
|
||||
if (!BTM_SetSecurityLevel(TRUE, "", BTM_SEC_SERVICE_HIDD_SEC_CTRL, sec_lvl, HID_PSM_CONTROL, BTM_SEC_PROTO_HID,
|
||||
HIDD_SEC_CHN)) {
|
||||
HIDD_TRACE_ERROR("Security Registration 2 failed");
|
||||
return (HID_ERR_NO_RESOURCES);
|
||||
}
|
||||
if (!BTM_SetSecurityLevel(FALSE, "", BTM_SEC_SERVICE_HIDD_NOSEC_CTRL, BTM_SEC_NONE, HID_PSM_CONTROL,
|
||||
BTM_SEC_PROTO_HID, HIDD_NOSEC_CHN)) {
|
||||
HIDD_TRACE_ERROR("Security Registration 3 failed");
|
||||
return (HID_ERR_NO_RESOURCES);
|
||||
}
|
||||
if (!BTM_SetSecurityLevel(TRUE, "", BTM_SEC_SERVICE_HIDD_NOSEC_CTRL, BTM_SEC_NONE, HID_PSM_CONTROL,
|
||||
BTM_SEC_PROTO_HID, HIDD_NOSEC_CHN)) {
|
||||
HIDD_TRACE_ERROR("Security Registration 4 failed");
|
||||
return (HID_ERR_NO_RESOURCES);
|
||||
}
|
||||
if (!BTM_SetSecurityLevel(TRUE, "", BTM_SEC_SERVICE_HIDD_INTR, BTM_SEC_NONE, HID_PSM_INTERRUPT, BTM_SEC_PROTO_HID,
|
||||
0)) {
|
||||
HIDD_TRACE_ERROR("Security Registration 5 failed");
|
||||
return (HID_ERR_NO_RESOURCES);
|
||||
}
|
||||
if (!BTM_SetSecurityLevel(FALSE, "", BTM_SEC_SERVICE_HIDD_INTR, BTM_SEC_NONE, HID_PSM_INTERRUPT, BTM_SEC_PROTO_HID,
|
||||
0)) {
|
||||
HIDD_TRACE_ERROR("Security Registration 6 failed");
|
||||
return (HID_ERR_NO_RESOURCES);
|
||||
}
|
||||
return (HID_SUCCESS);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function HID_DevAddRecord
|
||||
*
|
||||
* Description Creates SDP record for HID device
|
||||
*
|
||||
* Returns tHID_STATUS
|
||||
*
|
||||
******************************************************************************/
|
||||
tHID_STATUS HID_DevAddRecord(uint32_t handle, char *p_name, char *p_description, char *p_provider, uint16_t subclass,
|
||||
uint16_t desc_len, uint8_t *p_desc_data)
|
||||
{
|
||||
bool result = TRUE;
|
||||
|
||||
HIDD_TRACE_API("%s", __func__);
|
||||
|
||||
// Service Class ID List
|
||||
if (result) {
|
||||
uint16_t uuid = UUID_SERVCLASS_HUMAN_INTERFACE;
|
||||
result &= SDP_AddServiceClassIdList(handle, 1, &uuid);
|
||||
}
|
||||
// Protocol Descriptor List
|
||||
if (result) {
|
||||
tSDP_PROTOCOL_ELEM proto_list[2];
|
||||
proto_list[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
|
||||
proto_list[0].num_params = 1;
|
||||
proto_list[0].params[0] = BT_PSM_HIDC;
|
||||
proto_list[1].protocol_uuid = UUID_PROTOCOL_HIDP;
|
||||
proto_list[1].num_params = 0;
|
||||
result &= SDP_AddProtocolList(handle, 2, proto_list);
|
||||
}
|
||||
// Language Base Attribute ID List
|
||||
if (result) {
|
||||
result &=
|
||||
SDP_AddLanguageBaseAttrIDList(handle, LANG_ID_CODE_ENGLISH, LANG_ID_CHAR_ENCODE_UTF8, LANGUAGE_BASE_ID);
|
||||
}
|
||||
// Additional Protocol Descriptor List
|
||||
if (result) {
|
||||
tSDP_PROTO_LIST_ELEM add_proto_list;
|
||||
add_proto_list.num_elems = 2;
|
||||
add_proto_list.list_elem[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
|
||||
add_proto_list.list_elem[0].num_params = 1;
|
||||
add_proto_list.list_elem[0].params[0] = BT_PSM_HIDI;
|
||||
add_proto_list.list_elem[1].protocol_uuid = UUID_PROTOCOL_HIDP;
|
||||
add_proto_list.list_elem[1].num_params = 0;
|
||||
result &= SDP_AddAdditionProtoLists(handle, 1, &add_proto_list);
|
||||
}
|
||||
// Service Name (O)
|
||||
// Service Description (O)
|
||||
// Provider Name (O)
|
||||
if (result) {
|
||||
const char *srv_name = p_name;
|
||||
const char *srv_desc = p_description;
|
||||
const char *provider_name = p_provider;
|
||||
result &= SDP_AddAttribute(handle, ATTR_ID_SERVICE_NAME, TEXT_STR_DESC_TYPE, strlen(srv_name) + 1,
|
||||
(uint8_t *)srv_name);
|
||||
result &= SDP_AddAttribute(handle, ATTR_ID_SERVICE_DESCRIPTION, TEXT_STR_DESC_TYPE, strlen(srv_desc) + 1,
|
||||
(uint8_t *)srv_desc);
|
||||
result &= SDP_AddAttribute(handle, ATTR_ID_PROVIDER_NAME, TEXT_STR_DESC_TYPE, strlen(provider_name) + 1,
|
||||
(uint8_t *)provider_name);
|
||||
}
|
||||
// Bluetooth Profile Descriptor List
|
||||
if (result) {
|
||||
const uint16_t profile_uuid = UUID_SERVCLASS_HUMAN_INTERFACE;
|
||||
const uint16_t version = 0x0100;
|
||||
result &= SDP_AddProfileDescriptorList(handle, profile_uuid, version);
|
||||
}
|
||||
// HID Parser Version
|
||||
if (result) {
|
||||
uint8_t *p;
|
||||
const uint16_t rel_num = 0x0100;
|
||||
const uint16_t parser_version = 0x0111;
|
||||
const uint16_t prof_ver = 0x0100;
|
||||
const uint8_t dev_subclass = subclass;
|
||||
const uint8_t country_code = 0x21;
|
||||
const uint8_t bool_false = 0x00;
|
||||
const uint8_t bool_true = 0x01;
|
||||
uint16_t temp;
|
||||
p = (uint8_t *)&temp;
|
||||
UINT16_TO_BE_STREAM(p, rel_num);
|
||||
result &= SDP_AddAttribute(handle, ATTR_ID_HID_DEVICE_RELNUM, UINT_DESC_TYPE, 2, (uint8_t *)&temp);
|
||||
p = (uint8_t *)&temp;
|
||||
UINT16_TO_BE_STREAM(p, parser_version);
|
||||
result &= SDP_AddAttribute(handle, ATTR_ID_HID_PARSER_VERSION, UINT_DESC_TYPE, 2, (uint8_t *)&temp);
|
||||
result &= SDP_AddAttribute(handle, ATTR_ID_HID_DEVICE_SUBCLASS, UINT_DESC_TYPE, 1, (uint8_t *)&dev_subclass);
|
||||
result &= SDP_AddAttribute(handle, ATTR_ID_HID_COUNTRY_CODE, UINT_DESC_TYPE, 1, (uint8_t *)&country_code);
|
||||
result &= SDP_AddAttribute(handle, ATTR_ID_HID_VIRTUAL_CABLE, BOOLEAN_DESC_TYPE, 1, (uint8_t *)&bool_true);
|
||||
result &= SDP_AddAttribute(handle, ATTR_ID_HID_RECONNECT_INITIATE, BOOLEAN_DESC_TYPE, 1, (uint8_t *)&bool_true);
|
||||
{
|
||||
static uint8_t cdt = 0x22;
|
||||
uint8_t *p_buf;
|
||||
uint8_t seq_len = 4 + desc_len;
|
||||
p_buf = (uint8_t *)osi_malloc(2048);
|
||||
if (p_buf == NULL) {
|
||||
HIDD_TRACE_ERROR("%s: Buffer allocation failure for size = 2048 ", __func__);
|
||||
return HID_ERR_NOT_REGISTERED;
|
||||
}
|
||||
p = p_buf;
|
||||
UINT8_TO_BE_STREAM(p, (DATA_ELE_SEQ_DESC_TYPE << 3) | SIZE_IN_NEXT_BYTE);
|
||||
UINT8_TO_BE_STREAM(p, seq_len);
|
||||
UINT8_TO_BE_STREAM(p, (UINT_DESC_TYPE << 3) | SIZE_ONE_BYTE);
|
||||
UINT8_TO_BE_STREAM(p, cdt);
|
||||
UINT8_TO_BE_STREAM(p, (TEXT_STR_DESC_TYPE << 3) | SIZE_IN_NEXT_BYTE);
|
||||
UINT8_TO_BE_STREAM(p, desc_len);
|
||||
ARRAY_TO_BE_STREAM(p, p_desc_data, (int)desc_len);
|
||||
result &= SDP_AddAttribute(handle, ATTR_ID_HID_DESCRIPTOR_LIST, DATA_ELE_SEQ_DESC_TYPE, p - p_buf, p_buf);
|
||||
osi_free(p_buf);
|
||||
}
|
||||
{
|
||||
uint8_t lang_buf[8];
|
||||
p = lang_buf;
|
||||
uint8_t seq_len = 6;
|
||||
uint16_t lang_english = 0x0409;
|
||||
UINT8_TO_BE_STREAM(p, (DATA_ELE_SEQ_DESC_TYPE << 3) | SIZE_IN_NEXT_BYTE);
|
||||
UINT8_TO_BE_STREAM(p, seq_len);
|
||||
UINT8_TO_BE_STREAM(p, (UINT_DESC_TYPE << 3) | SIZE_TWO_BYTES);
|
||||
UINT16_TO_BE_STREAM(p, lang_english);
|
||||
UINT8_TO_BE_STREAM(p, (UINT_DESC_TYPE << 3) | SIZE_TWO_BYTES);
|
||||
UINT16_TO_BE_STREAM(p, LANGUAGE_BASE_ID);
|
||||
result &=
|
||||
SDP_AddAttribute(handle, ATTR_ID_HID_LANGUAGE_ID_BASE, DATA_ELE_SEQ_DESC_TYPE, p - lang_buf, lang_buf);
|
||||
}
|
||||
result &= SDP_AddAttribute(handle, ATTR_ID_HID_BATTERY_POWER, BOOLEAN_DESC_TYPE, 1, (uint8_t *)&bool_true);
|
||||
result &= SDP_AddAttribute(handle, ATTR_ID_HID_REMOTE_WAKE, BOOLEAN_DESC_TYPE, 1, (uint8_t *)&bool_false);
|
||||
result &=
|
||||
SDP_AddAttribute(handle, ATTR_ID_HID_NORMALLY_CONNECTABLE, BOOLEAN_DESC_TYPE, 1, (uint8_t *)&bool_true);
|
||||
result &= SDP_AddAttribute(handle, ATTR_ID_HID_BOOT_DEVICE, BOOLEAN_DESC_TYPE, 1, (uint8_t *)&bool_true);
|
||||
p = (uint8_t *)&temp;
|
||||
UINT16_TO_BE_STREAM(p, prof_ver);
|
||||
result &= SDP_AddAttribute(handle, ATTR_ID_HID_PROFILE_VERSION, UINT_DESC_TYPE, 2, (uint8_t *)&temp);
|
||||
}
|
||||
if (result) {
|
||||
uint16_t browse_group = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
|
||||
result &= SDP_AddUuidSequence(handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse_group);
|
||||
}
|
||||
if (!result) {
|
||||
HIDD_TRACE_ERROR("%s: failed to complete SDP record", __func__);
|
||||
return HID_ERR_NOT_REGISTERED;
|
||||
}
|
||||
return HID_SUCCESS;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function HID_DevSendReport
|
||||
*
|
||||
* Description Sends report
|
||||
*
|
||||
* Returns tHID_STATUS
|
||||
*
|
||||
******************************************************************************/
|
||||
tHID_STATUS HID_DevSendReport(uint8_t channel, uint8_t type, uint8_t id, uint16_t len, uint8_t *p_data)
|
||||
{
|
||||
HIDD_TRACE_VERBOSE("%s: channel=%d type=%d id=%d len=%d", __func__, channel, type, id, len);
|
||||
|
||||
if (channel == HID_CHANNEL_CTRL) {
|
||||
return hidd_conn_send_data(HID_CHANNEL_CTRL, HID_TRANS_DATA, type, id, len, p_data);
|
||||
}
|
||||
|
||||
if (channel == HID_CHANNEL_INTR && type == HID_PAR_REP_TYPE_INPUT) {
|
||||
// on INTR we can only send INPUT
|
||||
return hidd_conn_send_data(HID_CHANNEL_INTR, HID_TRANS_DATA, HID_PAR_REP_TYPE_INPUT, id, len, p_data);
|
||||
}
|
||||
|
||||
return HID_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function HID_DevVirtualCableUnplug
|
||||
*
|
||||
* Description Sends Virtual Cable Unplug
|
||||
*
|
||||
* Returns tHID_STATUS
|
||||
*
|
||||
******************************************************************************/
|
||||
tHID_STATUS HID_DevVirtualCableUnplug(void)
|
||||
{
|
||||
HIDD_TRACE_API("%s", __func__);
|
||||
|
||||
return hidd_conn_send_data(HID_CHANNEL_CTRL, HID_TRANS_CONTROL, HID_PAR_CONTROL_VIRTUAL_CABLE_UNPLUG, 0, 0, NULL);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function HID_DevPlugDevice
|
||||
*
|
||||
* Description Establishes virtual cable to given host
|
||||
*
|
||||
* Returns tHID_STATUS
|
||||
*
|
||||
******************************************************************************/
|
||||
tHID_STATUS HID_DevPlugDevice(BD_ADDR addr)
|
||||
{
|
||||
hd_cb.device.in_use = TRUE;
|
||||
memcpy(hd_cb.device.addr, addr, sizeof(BD_ADDR));
|
||||
|
||||
return HID_SUCCESS;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function HID_DevUnplugDevice
|
||||
*
|
||||
* Description Unplugs virtual cable from given host
|
||||
*
|
||||
* Returns tHID_STATUS
|
||||
*
|
||||
******************************************************************************/
|
||||
tHID_STATUS HID_DevUnplugDevice(BD_ADDR addr)
|
||||
{
|
||||
if (!memcmp(hd_cb.device.addr, addr, sizeof(BD_ADDR))) {
|
||||
hd_cb.device.in_use = FALSE;
|
||||
hd_cb.device.conn.conn_state = HID_CONN_STATE_UNUSED;
|
||||
hd_cb.device.conn.ctrl_cid = 0;
|
||||
hd_cb.device.conn.intr_cid = 0;
|
||||
}
|
||||
return HID_SUCCESS;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function HID_DevConnect
|
||||
*
|
||||
* Description Connects to device
|
||||
*
|
||||
* Returns tHID_STATUS
|
||||
*
|
||||
******************************************************************************/
|
||||
tHID_STATUS HID_DevConnect(void)
|
||||
{
|
||||
if (!hd_cb.reg_flag) {
|
||||
return HID_ERR_NOT_REGISTERED;
|
||||
}
|
||||
if (!hd_cb.device.in_use) {
|
||||
return HID_ERR_INVALID_PARAM;
|
||||
}
|
||||
if (hd_cb.device.state != HIDD_DEV_NO_CONN) {
|
||||
return HID_ERR_ALREADY_CONN;
|
||||
}
|
||||
return hidd_conn_initiate();
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function HID_DevDisconnect
|
||||
*
|
||||
* Description Disconnects from device
|
||||
*
|
||||
* Returns tHID_STATUS
|
||||
*
|
||||
******************************************************************************/
|
||||
tHID_STATUS HID_DevDisconnect(void)
|
||||
{
|
||||
if (!hd_cb.reg_flag) {
|
||||
return HID_ERR_NOT_REGISTERED;
|
||||
}
|
||||
if (!hd_cb.device.in_use) {
|
||||
return HID_ERR_INVALID_PARAM;
|
||||
}
|
||||
if (hd_cb.device.state == HIDD_DEV_NO_CONN) {
|
||||
return HID_ERR_NO_CONNECTION;
|
||||
}
|
||||
return hidd_conn_disconnect();
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function HID_DevSetIncomingPolicy
|
||||
*
|
||||
* Description Sets policy for incoming connections (allowed/disallowed)
|
||||
*
|
||||
* Returns tHID_STATUS
|
||||
*
|
||||
******************************************************************************/
|
||||
tHID_STATUS HID_DevSetIncomingPolicy(bool allow)
|
||||
{
|
||||
hd_cb.allow_incoming = allow;
|
||||
return HID_SUCCESS;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function HID_DevReportError
|
||||
*
|
||||
* Description Reports error for Set Report via HANDSHAKE
|
||||
*
|
||||
* Returns tHID_STATUS
|
||||
*
|
||||
******************************************************************************/
|
||||
tHID_STATUS HID_DevReportError(uint8_t error)
|
||||
{
|
||||
uint8_t handshake_param;
|
||||
|
||||
HIDD_TRACE_API("%s: error = %d", __func__, error);
|
||||
|
||||
switch (error) {
|
||||
case HID_PAR_HANDSHAKE_RSP_SUCCESS:
|
||||
case HID_PAR_HANDSHAKE_RSP_NOT_READY:
|
||||
case HID_PAR_HANDSHAKE_RSP_ERR_INVALID_REP_ID:
|
||||
case HID_PAR_HANDSHAKE_RSP_ERR_UNSUPPORTED_REQ:
|
||||
case HID_PAR_HANDSHAKE_RSP_ERR_INVALID_PARAM:
|
||||
case HID_PAR_HANDSHAKE_RSP_ERR_UNKNOWN:
|
||||
case HID_PAR_HANDSHAKE_RSP_ERR_FATAL:
|
||||
handshake_param = error;
|
||||
break;
|
||||
default:
|
||||
handshake_param = HID_PAR_HANDSHAKE_RSP_ERR_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
|
||||
return hidd_conn_send_data(0, HID_TRANS_HANDSHAKE, handshake_param, 0, 0, NULL);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function HID_DevGetDevice
|
||||
*
|
||||
* Description Returns the BD Address of virtually cabled device
|
||||
*
|
||||
* Returns tHID_STATUS
|
||||
*
|
||||
******************************************************************************/
|
||||
tHID_STATUS HID_DevGetDevice(BD_ADDR *addr)
|
||||
{
|
||||
HIDD_TRACE_API("%s", __func__);
|
||||
|
||||
if (hd_cb.device.in_use) {
|
||||
memcpy(addr, hd_cb.device.addr, sizeof(BD_ADDR));
|
||||
} else {
|
||||
return HID_ERR_NOT_REGISTERED;
|
||||
}
|
||||
|
||||
return HID_SUCCESS;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function HID_DevSetIncomingQos
|
||||
*
|
||||
* Description Sets Incoming QoS values for Interrupt L2CAP Channel
|
||||
*
|
||||
* Returns tHID_STATUS
|
||||
*
|
||||
******************************************************************************/
|
||||
tHID_STATUS HID_DevSetIncomingQos(uint8_t service_type, uint32_t token_rate, uint32_t token_bucket_size,
|
||||
uint32_t peak_bandwidth, uint32_t latency, uint32_t delay_variation)
|
||||
{
|
||||
HIDD_TRACE_API("%s", __func__);
|
||||
hd_cb.use_in_qos = TRUE;
|
||||
hd_cb.in_qos.service_type = service_type;
|
||||
hd_cb.in_qos.token_rate = token_rate;
|
||||
hd_cb.in_qos.token_bucket_size = token_bucket_size;
|
||||
hd_cb.in_qos.peak_bandwidth = peak_bandwidth;
|
||||
hd_cb.in_qos.latency = latency;
|
||||
hd_cb.in_qos.delay_variation = delay_variation;
|
||||
return HID_SUCCESS;
|
||||
}
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function HID_DevSetOutgoingQos
|
||||
*
|
||||
* Description Sets Outgoing QoS values for Interrupt L2CAP Channel
|
||||
*
|
||||
* Returns tHID_STATUS
|
||||
*
|
||||
******************************************************************************/
|
||||
tHID_STATUS HID_DevSetOutgoingQos(uint8_t service_type, uint32_t token_rate, uint32_t token_bucket_size,
|
||||
uint32_t peak_bandwidth, uint32_t latency, uint32_t delay_variation)
|
||||
{
|
||||
HIDD_TRACE_API("%s", __func__);
|
||||
hd_cb.l2cap_intr_cfg.qos_present = TRUE;
|
||||
hd_cb.l2cap_intr_cfg.qos.service_type = service_type;
|
||||
hd_cb.l2cap_intr_cfg.qos.token_rate = token_rate;
|
||||
hd_cb.l2cap_intr_cfg.qos.token_bucket_size = token_bucket_size;
|
||||
hd_cb.l2cap_intr_cfg.qos.peak_bandwidth = peak_bandwidth;
|
||||
hd_cb.l2cap_intr_cfg.qos.latency = latency;
|
||||
hd_cb.l2cap_intr_cfg.qos.delay_variation = delay_variation;
|
||||
return HID_SUCCESS;
|
||||
}
|
||||
#endif
|
780
components/bt/host/bluedroid/stack/hid/hidd_conn.c
Normal file
780
components/bt/host/bluedroid/stack/hid/hidd_conn.c
Normal file
@ -0,0 +1,780 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
* Copyright (C) 2002-2012 Broadcom Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
******************************************************************************/
|
||||
/******************************************************************************
|
||||
*
|
||||
* this file contains the connection interface functions
|
||||
*
|
||||
******************************************************************************/
|
||||
#include "btm_int.h"
|
||||
#include "hid_conn.h"
|
||||
#include "hid_int.h"
|
||||
#include "osi/allocator.h"
|
||||
#include "osi/osi.h"
|
||||
#include "stack/btm_api.h"
|
||||
#include "stack/btu.h"
|
||||
#include "stack/hidd_api.h"
|
||||
#include "stack/hiddefs.h"
|
||||
#include "stack/l2c_api.h"
|
||||
#include "stack/l2cdefs.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#if (HID_DEV_INCLUDED == TRUE)
|
||||
|
||||
static void hidd_l2cif_connect_ind(BD_ADDR bd_addr, uint16_t cid, uint16_t psm, uint8_t id);
|
||||
static void hidd_l2cif_connect_cfm(uint16_t cid, uint16_t result);
|
||||
static void hidd_l2cif_config_ind(uint16_t cid, tL2CAP_CFG_INFO *p_cfg);
|
||||
static void hidd_l2cif_config_cfm(uint16_t cid, tL2CAP_CFG_INFO *p_cfg);
|
||||
static void hidd_l2cif_disconnect_ind(uint16_t cid, bool ack_needed);
|
||||
static void hidd_l2cif_disconnect_cfm(uint16_t cid, uint16_t result);
|
||||
static void hidd_l2cif_data_ind(uint16_t cid, BT_HDR *p_msg);
|
||||
static void hidd_l2cif_cong_ind(uint16_t cid, bool congested);
|
||||
|
||||
static const tL2CAP_APPL_INFO dev_reg_info = {hidd_l2cif_connect_ind,
|
||||
hidd_l2cif_connect_cfm,
|
||||
NULL,
|
||||
hidd_l2cif_config_ind,
|
||||
hidd_l2cif_config_cfm,
|
||||
hidd_l2cif_disconnect_ind,
|
||||
hidd_l2cif_disconnect_cfm,
|
||||
NULL,
|
||||
hidd_l2cif_data_ind,
|
||||
hidd_l2cif_cong_ind,
|
||||
NULL};
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function hidd_check_config_done
|
||||
*
|
||||
* Description Checks if connection is configured and callback can be fired
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
static void hidd_check_config_done(void)
|
||||
{
|
||||
tHID_CONN *p_hcon;
|
||||
p_hcon = &hd_cb.device.conn;
|
||||
if (((p_hcon->conn_flags & HID_CONN_FLAGS_ALL_CONFIGURED) == HID_CONN_FLAGS_ALL_CONFIGURED) &&
|
||||
(p_hcon->conn_state == HID_CONN_STATE_CONFIG)) {
|
||||
p_hcon->conn_state = HID_CONN_STATE_CONNECTED;
|
||||
hd_cb.device.state = HIDD_DEV_CONNECTED;
|
||||
hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_OPEN, 0, NULL);
|
||||
// send outstanding data on intr
|
||||
if (hd_cb.pending_data) {
|
||||
L2CA_DataWrite(p_hcon->intr_cid, hd_cb.pending_data);
|
||||
hd_cb.pending_data = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function hidh_sec_check_complete_term
|
||||
*
|
||||
* Description HID security check complete callback function.
|
||||
*
|
||||
* Returns Send L2CA_ConnectRsp OK if secutiry check succeed; otherwise
|
||||
* send security block L2C connection response.
|
||||
*
|
||||
******************************************************************************/
|
||||
static void hidd_sec_check_complete(UNUSED_ATTR BD_ADDR bd_addr, UNUSED_ATTR tBT_TRANSPORT transport, void *p_ref_data,
|
||||
uint8_t res)
|
||||
{
|
||||
tHID_DEV_DEV_CTB *p_dev = (tHID_DEV_DEV_CTB *)p_ref_data;
|
||||
if (res == BTM_SUCCESS && p_dev->conn.conn_state == HID_CONN_STATE_SECURITY) {
|
||||
p_dev->conn.disc_reason = HID_SUCCESS;
|
||||
p_dev->conn.conn_state = HID_CONN_STATE_CONNECTING_INTR;
|
||||
L2CA_ConnectRsp(p_dev->addr, p_dev->conn.ctrl_id, p_dev->conn.ctrl_cid, L2CAP_CONN_OK, L2CAP_CONN_OK);
|
||||
L2CA_ConfigReq(p_dev->conn.ctrl_cid, &hd_cb.l2cap_cfg);
|
||||
} else if (res != BTM_SUCCESS) {
|
||||
HIDD_TRACE_WARNING("%s: connection rejected by security", __func__);
|
||||
p_dev->conn.disc_reason = HID_ERR_AUTH_FAILED;
|
||||
p_dev->conn.conn_state = HID_CONN_STATE_UNUSED;
|
||||
L2CA_ConnectRsp(p_dev->addr, p_dev->conn.ctrl_id, p_dev->conn.ctrl_cid, L2CAP_CONN_SECURITY_BLOCK,
|
||||
L2CAP_CONN_OK);
|
||||
return;
|
||||
}
|
||||
}
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function hidd_sec_check_complete_orig
|
||||
*
|
||||
* Description HID security check complete callback function (device
|
||||
*originated)
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
void hidd_sec_check_complete_orig(UNUSED_ATTR BD_ADDR bd_addr, UNUSED_ATTR tBT_TRANSPORT transport, void *p_ref_data,
|
||||
uint8_t res)
|
||||
{
|
||||
tHID_DEV_DEV_CTB *p_dev = (tHID_DEV_DEV_CTB *)p_ref_data;
|
||||
if (p_dev->conn.conn_state != HID_CONN_STATE_SECURITY) {
|
||||
HIDD_TRACE_WARNING("%s: invalid state (%02x)", __func__, p_dev->conn.conn_state);
|
||||
return;
|
||||
}
|
||||
if (res == BTM_SUCCESS) {
|
||||
HIDD_TRACE_EVENT("%s: security ok", __func__);
|
||||
p_dev->conn.disc_reason = HID_SUCCESS;
|
||||
p_dev->conn.conn_state = HID_CONN_STATE_CONFIG;
|
||||
L2CA_ConfigReq(p_dev->conn.ctrl_cid, &hd_cb.l2cap_cfg);
|
||||
} else {
|
||||
HIDD_TRACE_WARNING("%s: security check failed (%02x)", __func__, res);
|
||||
p_dev->conn.disc_reason = HID_ERR_AUTH_FAILED;
|
||||
hidd_conn_disconnect();
|
||||
}
|
||||
}
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function hidd_l2cif_connect_ind
|
||||
*
|
||||
* Description Handles incoming L2CAP connection (we act as server)
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
static void hidd_l2cif_connect_ind(BD_ADDR bd_addr, uint16_t cid, uint16_t psm, uint8_t id)
|
||||
{
|
||||
tHID_CONN *p_hcon;
|
||||
tHID_DEV_DEV_CTB *p_dev;
|
||||
bool accept = TRUE; // accept by default
|
||||
HIDD_TRACE_EVENT("%s: psm=%04x cid=%04x id=%02x", __func__, psm, cid, id);
|
||||
p_dev = &hd_cb.device;
|
||||
if (!hd_cb.allow_incoming) {
|
||||
HIDD_TRACE_WARNING("%s: incoming connections not allowed, rejecting", __func__);
|
||||
L2CA_ConnectRsp(bd_addr, id, cid, L2CAP_CONN_NO_RESOURCES, 0);
|
||||
return;
|
||||
}
|
||||
if (p_dev->in_use && memcmp(bd_addr, p_dev->addr, sizeof(BD_ADDR))) {
|
||||
HIDD_TRACE_WARNING("%s: incoming connections from different device, rejecting", __func__);
|
||||
L2CA_ConnectRsp(bd_addr, id, cid, L2CAP_CONN_NO_RESOURCES, 0);
|
||||
return;
|
||||
} else if (!p_dev->in_use) {
|
||||
p_dev->in_use = TRUE;
|
||||
memcpy(p_dev->addr, bd_addr, sizeof(BD_ADDR));
|
||||
p_dev->state = HIDD_DEV_NO_CONN;
|
||||
}
|
||||
p_hcon = &hd_cb.device.conn;
|
||||
switch (psm) {
|
||||
case HID_PSM_INTERRUPT:
|
||||
if (p_hcon->ctrl_cid == 0) {
|
||||
accept = FALSE;
|
||||
HIDD_TRACE_WARNING("%s: incoming INTR without CTRL, rejecting", __func__);
|
||||
}
|
||||
if (p_hcon->conn_state != HID_CONN_STATE_CONNECTING_INTR) {
|
||||
accept = FALSE;
|
||||
HIDD_TRACE_WARNING("%s: incoming INTR in invalid state (%d), rejecting", __func__, p_hcon->conn_state);
|
||||
}
|
||||
break;
|
||||
case HID_PSM_CONTROL:
|
||||
if (p_hcon->conn_state != HID_CONN_STATE_UNUSED) {
|
||||
accept = FALSE;
|
||||
HIDD_TRACE_WARNING("%s: incoming CTRL in invalid state (%d), rejecting", __func__, p_hcon->conn_state);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
accept = FALSE;
|
||||
HIDD_TRACE_ERROR("%s: received invalid PSM, rejecting", __func__);
|
||||
break;
|
||||
}
|
||||
if (!accept) {
|
||||
L2CA_ConnectRsp(bd_addr, id, cid, L2CAP_CONN_NO_RESOURCES, 0);
|
||||
return;
|
||||
}
|
||||
// for CTRL we need to go through security and we reply in callback from there
|
||||
if (psm == HID_PSM_CONTROL) {
|
||||
p_hcon->conn_flags = 0;
|
||||
p_hcon->ctrl_cid = cid;
|
||||
p_hcon->ctrl_id = id;
|
||||
p_hcon->disc_reason = HID_L2CAP_CONN_FAIL;
|
||||
p_hcon->conn_state = HID_CONN_STATE_SECURITY;
|
||||
if (btm_sec_mx_access_request(p_dev->addr, HID_PSM_CONTROL, FALSE, BTM_SEC_PROTO_HID, HIDD_NOSEC_CHN,
|
||||
&hidd_sec_check_complete, p_dev) == BTM_CMD_STARTED) {
|
||||
L2CA_ConnectRsp(bd_addr, id, cid, L2CAP_CONN_PENDING, L2CAP_CONN_OK);
|
||||
}
|
||||
return;
|
||||
}
|
||||
// for INTR we go directly to config state
|
||||
p_hcon->conn_state = HID_CONN_STATE_CONFIG;
|
||||
p_hcon->intr_cid = cid;
|
||||
L2CA_ConnectRsp(bd_addr, id, cid, L2CAP_CONN_OK, L2CAP_CONN_OK);
|
||||
L2CA_ConfigReq(cid, &hd_cb.l2cap_intr_cfg);
|
||||
}
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function hidd_l2cif_connect_cfm
|
||||
*
|
||||
* Description Handles L2CAP connection response (we act as client)
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
static void hidd_l2cif_connect_cfm(uint16_t cid, uint16_t result)
|
||||
{
|
||||
tHID_DEV_DEV_CTB *p_dev = &hd_cb.device;
|
||||
tHID_CONN *p_hcon = &hd_cb.device.conn;
|
||||
HIDD_TRACE_EVENT("%s: cid=%04x result=%d, conn_state=%d", __func__, cid, result, p_hcon->conn_state);
|
||||
if (p_hcon->ctrl_cid != cid && p_hcon->intr_cid != cid) {
|
||||
HIDD_TRACE_WARNING("%s: unknown cid", __func__);
|
||||
return;
|
||||
}
|
||||
if (!(p_hcon->conn_flags & HID_CONN_FLAGS_IS_ORIG) ||
|
||||
((cid == p_hcon->ctrl_cid) && (p_hcon->conn_state != HID_CONN_STATE_CONNECTING_CTRL && (p_hcon->conn_state != HID_CONN_STATE_DISCONNECTING_INTR))) ||
|
||||
((cid == p_hcon->intr_cid) && (p_hcon->conn_state != HID_CONN_STATE_CONNECTING_INTR) && (p_hcon->conn_state != HID_CONN_STATE_DISCONNECTING_CTRL))) {
|
||||
HIDD_TRACE_WARNING("%s: unexpected, cid:0x%04x, ctrl_cid:0x%04x, intr_cid:0x%04x, conn_state:%d", __func__, cid,
|
||||
p_hcon->ctrl_cid, p_hcon->intr_cid, p_hcon->conn_state);
|
||||
return;
|
||||
}
|
||||
if (result != L2CAP_CONN_OK) {
|
||||
HIDD_TRACE_WARNING("%s: connection failed, now disconnect", __func__);
|
||||
if (cid == p_hcon->ctrl_cid)
|
||||
p_hcon->ctrl_cid = 0;
|
||||
else
|
||||
p_hcon->intr_cid = 0;
|
||||
hidd_conn_disconnect();
|
||||
hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_CLOSE, HID_L2CAP_CONN_FAIL | (uint32_t)result, NULL);
|
||||
return;
|
||||
}
|
||||
/* CTRL connect conf */
|
||||
if (cid == p_hcon->ctrl_cid) {
|
||||
p_hcon->conn_state = HID_CONN_STATE_SECURITY;
|
||||
p_hcon->disc_reason = HID_L2CAP_CONN_FAIL; /* in case disconnected before sec completed */
|
||||
btm_sec_mx_access_request(p_dev->addr, HID_PSM_CONTROL, TRUE, BTM_SEC_PROTO_HID, HIDD_SEC_CHN,
|
||||
&hidd_sec_check_complete_orig, p_dev);
|
||||
} else {
|
||||
p_hcon->conn_state = HID_CONN_STATE_CONFIG;
|
||||
L2CA_ConfigReq(cid, &hd_cb.l2cap_intr_cfg);
|
||||
}
|
||||
return;
|
||||
}
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function hidd_l2cif_config_ind
|
||||
*
|
||||
* Description Handles incoming L2CAP configuration request
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
static void hidd_l2cif_config_ind(uint16_t cid, tL2CAP_CFG_INFO *p_cfg)
|
||||
{
|
||||
tHID_CONN *p_hcon;
|
||||
HIDD_TRACE_EVENT("%s: cid=%04x", __func__, cid);
|
||||
p_hcon = &hd_cb.device.conn;
|
||||
if (p_hcon->ctrl_cid != cid && p_hcon->intr_cid != cid) {
|
||||
HIDD_TRACE_WARNING("%s: unknown cid", __func__);
|
||||
return;
|
||||
}
|
||||
if ((!p_cfg->mtu_present) || (p_cfg->mtu > HID_DEV_MTU_SIZE))
|
||||
p_hcon->rem_mtu_size = HID_DEV_MTU_SIZE;
|
||||
else
|
||||
p_hcon->rem_mtu_size = p_cfg->mtu;
|
||||
// accept without changes
|
||||
p_cfg->flush_to_present = FALSE;
|
||||
p_cfg->mtu_present = FALSE;
|
||||
p_cfg->result = L2CAP_CFG_OK;
|
||||
if (cid == p_hcon->intr_cid && hd_cb.use_in_qos && !p_cfg->qos_present) {
|
||||
p_cfg->qos_present = TRUE;
|
||||
memcpy(&p_cfg->qos, &hd_cb.in_qos, sizeof(FLOW_SPEC));
|
||||
}
|
||||
L2CA_ConfigRsp(cid, p_cfg);
|
||||
// update flags
|
||||
if (cid == p_hcon->ctrl_cid) {
|
||||
p_hcon->conn_flags |= HID_CONN_FLAGS_HIS_CTRL_CFG_DONE;
|
||||
if ((p_hcon->conn_flags & HID_CONN_FLAGS_IS_ORIG) && (p_hcon->conn_flags & HID_CONN_FLAGS_MY_CTRL_CFG_DONE)) {
|
||||
p_hcon->disc_reason = HID_L2CAP_CONN_FAIL;
|
||||
if ((p_hcon->intr_cid = L2CA_ConnectReq(HID_PSM_INTERRUPT, hd_cb.device.addr)) == 0) {
|
||||
p_hcon->conn_state = HID_CONN_STATE_UNUSED;
|
||||
hidd_conn_disconnect();
|
||||
HIDD_TRACE_WARNING("%s: could not start L2CAP connection for INTR", __func__);
|
||||
hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_CLOSE, HID_ERR_L2CAP_FAILED, NULL);
|
||||
return;
|
||||
} else {
|
||||
p_hcon->conn_state = HID_CONN_STATE_CONNECTING_INTR;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
p_hcon->conn_flags |= HID_CONN_FLAGS_HIS_INTR_CFG_DONE;
|
||||
}
|
||||
hidd_check_config_done();
|
||||
}
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function hidd_l2cif_config_cfm
|
||||
*
|
||||
* Description Handles incoming L2CAP configuration response
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
static void hidd_l2cif_config_cfm(uint16_t cid, tL2CAP_CFG_INFO *p_cfg)
|
||||
{
|
||||
tHID_CONN *p_hcon;
|
||||
uint32_t reason;
|
||||
HIDD_TRACE_EVENT("%s: cid=%04x pcfg->result=%d", __func__, cid, p_cfg->result);
|
||||
p_hcon = &hd_cb.device.conn;
|
||||
if (p_hcon->ctrl_cid != cid && p_hcon->intr_cid != cid) {
|
||||
HIDD_TRACE_WARNING("%s: unknown cid", __func__);
|
||||
return;
|
||||
}
|
||||
if (p_hcon->intr_cid == cid && p_cfg->result == L2CAP_CFG_UNACCEPTABLE_PARAMS && p_cfg->qos_present) {
|
||||
tL2CAP_CFG_INFO new_qos;
|
||||
// QoS parameters not accepted for intr, try again with host proposal
|
||||
memcpy(&new_qos, &hd_cb.l2cap_intr_cfg, sizeof(new_qos));
|
||||
memcpy(&new_qos.qos, &p_cfg->qos, sizeof(FLOW_SPEC));
|
||||
new_qos.qos_present = TRUE;
|
||||
HIDD_TRACE_WARNING("%s: config failed, retry", __func__);
|
||||
L2CA_ConfigReq(cid, &new_qos);
|
||||
return;
|
||||
} else if (p_hcon->intr_cid == cid && p_cfg->result == L2CAP_CFG_UNKNOWN_OPTIONS) {
|
||||
// QoS not understood by remote device, try configuring without QoS
|
||||
HIDD_TRACE_WARNING("%s: config failed, retry without QoS", __func__);
|
||||
L2CA_ConfigReq(cid, &hd_cb.l2cap_cfg);
|
||||
return;
|
||||
} else if (p_cfg->result != L2CAP_CFG_OK) {
|
||||
HIDD_TRACE_WARNING("%s: config failed, disconnecting", __func__);
|
||||
hidd_conn_disconnect();
|
||||
reason = HID_L2CAP_CFG_FAIL | (uint32_t)p_cfg->result;
|
||||
hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_CLOSE, reason, NULL);
|
||||
return;
|
||||
}
|
||||
// update flags
|
||||
if (cid == p_hcon->ctrl_cid) {
|
||||
p_hcon->conn_flags |= HID_CONN_FLAGS_MY_CTRL_CFG_DONE;
|
||||
if ((p_hcon->conn_flags & HID_CONN_FLAGS_IS_ORIG) && (p_hcon->conn_flags & HID_CONN_FLAGS_HIS_CTRL_CFG_DONE)) {
|
||||
p_hcon->disc_reason = HID_L2CAP_CONN_FAIL;
|
||||
if ((p_hcon->intr_cid = L2CA_ConnectReq(HID_PSM_INTERRUPT, hd_cb.device.addr)) == 0) {
|
||||
p_hcon->conn_state = HID_CONN_STATE_UNUSED;
|
||||
hidd_conn_disconnect();
|
||||
HIDD_TRACE_WARNING("%s: could not start L2CAP connection for INTR", __func__);
|
||||
hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_CLOSE, HID_ERR_L2CAP_FAILED, NULL);
|
||||
return;
|
||||
} else {
|
||||
p_hcon->conn_state = HID_CONN_STATE_CONNECTING_INTR;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
p_hcon->conn_flags |= HID_CONN_FLAGS_MY_INTR_CFG_DONE;
|
||||
}
|
||||
hidd_check_config_done();
|
||||
}
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function hidd_l2cif_disconnect_ind
|
||||
*
|
||||
* Description Handler incoming L2CAP disconnection request
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
static void hidd_l2cif_disconnect_ind(uint16_t cid, bool ack_needed)
|
||||
{
|
||||
tHID_CONN *p_hcon;
|
||||
HIDD_TRACE_EVENT("%s: cid=%04x ack_needed=%d", __func__, cid, ack_needed);
|
||||
p_hcon = &hd_cb.device.conn;
|
||||
if (p_hcon->conn_state == HID_CONN_STATE_UNUSED || (p_hcon->ctrl_cid != cid && p_hcon->intr_cid != cid)) {
|
||||
HIDD_TRACE_WARNING("%s: unknown cid", __func__);
|
||||
return;
|
||||
}
|
||||
if (ack_needed)
|
||||
L2CA_DisconnectRsp(cid);
|
||||
if (cid == p_hcon->ctrl_cid) {
|
||||
p_hcon->ctrl_cid = 0;
|
||||
p_hcon->conn_state = HID_CONN_STATE_DISCONNECTING_CTRL;
|
||||
} else {
|
||||
p_hcon->intr_cid = 0;
|
||||
p_hcon->conn_state = HID_CONN_STATE_DISCONNECTING_INTR;
|
||||
}
|
||||
if ((p_hcon->ctrl_cid == 0) && (p_hcon->intr_cid == 0)) {
|
||||
HIDD_TRACE_EVENT("%s: INTR and CTRL disconnected", __func__);
|
||||
// clean any outstanding data on intr
|
||||
if (hd_cb.pending_data) {
|
||||
osi_free(hd_cb.pending_data);
|
||||
hd_cb.pending_data = NULL;
|
||||
}
|
||||
hd_cb.device.state = HIDD_DEV_NO_CONN;
|
||||
p_hcon->conn_state = HID_CONN_STATE_UNUSED;
|
||||
hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_CLOSE, p_hcon->disc_reason, NULL);
|
||||
}
|
||||
}
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function hidd_l2cif_disconnect_cfm
|
||||
*
|
||||
* Description Handles L2CAP disconection response
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
static void hidd_l2cif_disconnect_cfm(uint16_t cid, uint16_t result)
|
||||
{
|
||||
tHID_CONN *p_hcon;
|
||||
HIDD_TRACE_EVENT("%s: cid=%04x result=%d", __func__, cid, result);
|
||||
p_hcon = &hd_cb.device.conn;
|
||||
if (p_hcon->conn_state == HID_CONN_STATE_UNUSED || (p_hcon->ctrl_cid != cid && p_hcon->intr_cid != cid)) {
|
||||
HIDD_TRACE_WARNING("%s: unknown cid", __func__);
|
||||
return;
|
||||
}
|
||||
if (cid == p_hcon->ctrl_cid) {
|
||||
p_hcon->ctrl_cid = 0;
|
||||
} else {
|
||||
p_hcon->intr_cid = 0;
|
||||
// now disconnect CTRL
|
||||
L2CA_DisconnectReq(p_hcon->ctrl_cid);
|
||||
}
|
||||
if ((p_hcon->ctrl_cid == 0) && (p_hcon->intr_cid == 0)) {
|
||||
HIDD_TRACE_EVENT("%s: INTR and CTRL disconnected", __func__);
|
||||
hd_cb.device.state = HIDD_DEV_NO_CONN;
|
||||
p_hcon->conn_state = HID_CONN_STATE_UNUSED;
|
||||
if (hd_cb.pending_vc_unplug) {
|
||||
hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_VC_UNPLUG, p_hcon->disc_reason, NULL);
|
||||
hd_cb.pending_vc_unplug = FALSE;
|
||||
} else {
|
||||
hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_CLOSE, p_hcon->disc_reason, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function hidd_l2cif_cong_ind
|
||||
*
|
||||
* Description Handles L2CAP congestion status event
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
static void hidd_l2cif_cong_ind(uint16_t cid, bool congested)
|
||||
{
|
||||
tHID_CONN *p_hcon;
|
||||
HIDD_TRACE_EVENT("%s: cid=%04x congested=%d", __func__, cid, congested);
|
||||
p_hcon = &hd_cb.device.conn;
|
||||
if (p_hcon->conn_state == HID_CONN_STATE_UNUSED || (p_hcon->ctrl_cid != cid && p_hcon->intr_cid != cid)) {
|
||||
HIDD_TRACE_WARNING("%s: unknown cid", __func__);
|
||||
return;
|
||||
}
|
||||
if (congested) {
|
||||
p_hcon->conn_flags |= HID_CONN_FLAGS_CONGESTED;
|
||||
} else {
|
||||
p_hcon->conn_flags &= ~HID_CONN_FLAGS_CONGESTED;
|
||||
}
|
||||
}
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function hidd_l2cif_data_ind
|
||||
*
|
||||
* Description Handler incoming data on L2CAP channel
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
static void hidd_l2cif_data_ind(uint16_t cid, BT_HDR *p_msg)
|
||||
{
|
||||
tHID_CONN *p_hcon;
|
||||
uint8_t *p_data = (uint8_t *)(p_msg + 1) + p_msg->offset;
|
||||
uint8_t msg_type, param;
|
||||
bool err = FALSE;
|
||||
HIDD_TRACE_EVENT("%s: cid=%04x", __func__, cid);
|
||||
p_hcon = &hd_cb.device.conn;
|
||||
if (p_hcon->conn_state == HID_CONN_STATE_UNUSED || (p_hcon->ctrl_cid != cid && p_hcon->intr_cid != cid)) {
|
||||
HIDD_TRACE_WARNING("%s: unknown cid", __func__);
|
||||
osi_free(p_msg);
|
||||
return;
|
||||
}
|
||||
msg_type = HID_GET_TRANS_FROM_HDR(*p_data);
|
||||
param = HID_GET_PARAM_FROM_HDR(*p_data);
|
||||
if (msg_type == HID_TRANS_DATA && cid == p_hcon->intr_cid) {
|
||||
// skip HID header
|
||||
p_msg->offset++;
|
||||
p_msg->len--;
|
||||
hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_INTR_DATA, 0, p_msg);
|
||||
return;
|
||||
}
|
||||
switch (msg_type) {
|
||||
case HID_TRANS_GET_REPORT:
|
||||
// at this stage we don't know if Report Id shall be included in request
|
||||
// so we pass complete packet in callback and let other code analyze this
|
||||
hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_GET_REPORT, !!(param & HID_PAR_GET_REP_BUFSIZE_FOLLOWS), p_msg);
|
||||
break;
|
||||
case HID_TRANS_SET_REPORT:
|
||||
// as above
|
||||
hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_SET_REPORT, 0, p_msg);
|
||||
break;
|
||||
case HID_TRANS_GET_IDLE:
|
||||
hidd_conn_send_data(HID_CHANNEL_CTRL, HID_TRANS_DATA, HID_PAR_REP_TYPE_OTHER, hd_cb.device.idle_time, 0, NULL);
|
||||
osi_free(p_msg);
|
||||
break;
|
||||
case HID_TRANS_SET_IDLE:
|
||||
if (p_msg->len != 2) {
|
||||
HIDD_TRACE_ERROR("%s: invalid len (%d) set idle request received", __func__, p_msg->len);
|
||||
err = TRUE;
|
||||
} else {
|
||||
hd_cb.device.idle_time = p_data[1];
|
||||
HIDD_TRACE_DEBUG("%s: idle_time = %d", __func__, hd_cb.device.idle_time);
|
||||
if (hd_cb.device.idle_time) {
|
||||
HIDD_TRACE_WARNING("%s: idle_time of %d ms not supported by HID Device", __func__,
|
||||
(hd_cb.device.idle_time * 4));
|
||||
err = TRUE;
|
||||
}
|
||||
}
|
||||
if (!err) {
|
||||
hidd_conn_send_data(0, HID_TRANS_HANDSHAKE, HID_PAR_HANDSHAKE_RSP_SUCCESS, 0, 0, NULL);
|
||||
} else {
|
||||
hidd_conn_send_data(0, HID_TRANS_HANDSHAKE, HID_PAR_HANDSHAKE_RSP_ERR_INVALID_PARAM, 0, 0, NULL);
|
||||
}
|
||||
osi_free(p_msg);
|
||||
break;
|
||||
case HID_TRANS_GET_PROTOCOL:
|
||||
hidd_conn_send_data(HID_CHANNEL_CTRL, HID_TRANS_DATA, HID_PAR_REP_TYPE_OTHER, !hd_cb.device.boot_mode, 0, NULL);
|
||||
osi_free(p_msg);
|
||||
break;
|
||||
case HID_TRANS_SET_PROTOCOL:
|
||||
hd_cb.device.boot_mode = !(param & HID_PAR_PROTOCOL_MASK);
|
||||
hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_SET_PROTOCOL, param & HID_PAR_PROTOCOL_MASK, NULL);
|
||||
hidd_conn_send_data(0, HID_TRANS_HANDSHAKE, HID_PAR_HANDSHAKE_RSP_SUCCESS, 0, 0, NULL);
|
||||
osi_free(p_msg);
|
||||
break;
|
||||
case HID_TRANS_CONTROL:
|
||||
switch (param) {
|
||||
case HID_PAR_CONTROL_SUSPEND:
|
||||
hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_SUSPEND, 0, NULL);
|
||||
break;
|
||||
case HID_PAR_CONTROL_EXIT_SUSPEND:
|
||||
hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_EXIT_SUSPEND, 0, NULL);
|
||||
break;
|
||||
case HID_PAR_CONTROL_VIRTUAL_CABLE_UNPLUG:
|
||||
hidd_conn_disconnect();
|
||||
// set flag so we can notify properly when disconnected
|
||||
hd_cb.pending_vc_unplug = TRUE;
|
||||
break;
|
||||
}
|
||||
osi_free(p_msg);
|
||||
break;
|
||||
case HID_TRANS_DATA:
|
||||
default:
|
||||
HIDD_TRACE_WARNING("%s: got unsupported msg (%d)", __func__, msg_type);
|
||||
hidd_conn_send_data(0, HID_TRANS_HANDSHAKE, HID_PAR_HANDSHAKE_RSP_ERR_UNSUPPORTED_REQ, 0, 0, NULL);
|
||||
osi_free(p_msg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function hidd_conn_reg
|
||||
*
|
||||
* Description Registers L2CAP channels
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
tHID_STATUS hidd_conn_reg(void)
|
||||
{
|
||||
HIDD_TRACE_API("%s", __func__);
|
||||
memset(&hd_cb.l2cap_cfg, 0, sizeof(tL2CAP_CFG_INFO));
|
||||
hd_cb.l2cap_cfg.mtu_present = TRUE;
|
||||
hd_cb.l2cap_cfg.mtu = HID_DEV_MTU_SIZE;
|
||||
hd_cb.l2cap_cfg.flush_to_present = TRUE;
|
||||
hd_cb.l2cap_cfg.flush_to = HID_DEV_FLUSH_TO;
|
||||
memset(&hd_cb.l2cap_intr_cfg, 0, sizeof(tL2CAP_CFG_INFO));
|
||||
hd_cb.l2cap_intr_cfg.mtu_present = TRUE;
|
||||
hd_cb.l2cap_intr_cfg.mtu = HID_DEV_MTU_SIZE;
|
||||
hd_cb.l2cap_intr_cfg.flush_to_present = TRUE;
|
||||
hd_cb.l2cap_intr_cfg.flush_to = HID_DEV_FLUSH_TO;
|
||||
if (!L2CA_Register(HID_PSM_CONTROL, (tL2CAP_APPL_INFO *)&dev_reg_info)) {
|
||||
HIDD_TRACE_ERROR("HID Control (device) registration failed");
|
||||
return (HID_ERR_L2CAP_FAILED);
|
||||
}
|
||||
if (!L2CA_Register(HID_PSM_INTERRUPT, (tL2CAP_APPL_INFO *)&dev_reg_info)) {
|
||||
L2CA_Deregister(HID_PSM_CONTROL);
|
||||
HIDD_TRACE_ERROR("HID Interrupt (device) registration failed");
|
||||
return (HID_ERR_L2CAP_FAILED);
|
||||
}
|
||||
return (HID_SUCCESS);
|
||||
}
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function hidd_conn_dereg
|
||||
*
|
||||
* Description Deregisters L2CAP channels
|
||||
*
|
||||
* Returns void
|
||||
*
|
||||
******************************************************************************/
|
||||
void hidd_conn_dereg(void)
|
||||
{
|
||||
HIDD_TRACE_API("%s", __func__);
|
||||
L2CA_Deregister(HID_PSM_CONTROL);
|
||||
L2CA_Deregister(HID_PSM_INTERRUPT);
|
||||
}
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function hidd_conn_initiate
|
||||
*
|
||||
* Description Initiates HID connection to plugged device
|
||||
*
|
||||
* Returns HID_SUCCESS
|
||||
*
|
||||
******************************************************************************/
|
||||
tHID_STATUS hidd_conn_initiate(void)
|
||||
{
|
||||
tHID_DEV_DEV_CTB *p_dev = &hd_cb.device;
|
||||
HIDD_TRACE_API("%s", __func__);
|
||||
if (!p_dev->in_use) {
|
||||
HIDD_TRACE_WARNING("%s: no virtual cable established", __func__);
|
||||
return (HID_ERR_NOT_REGISTERED);
|
||||
}
|
||||
if (p_dev->conn.conn_state != HID_CONN_STATE_UNUSED) {
|
||||
HIDD_TRACE_WARNING("%s: connection already in progress", __func__);
|
||||
return (HID_ERR_CONN_IN_PROCESS);
|
||||
}
|
||||
p_dev->conn.ctrl_cid = 0;
|
||||
p_dev->conn.intr_cid = 0;
|
||||
p_dev->conn.disc_reason = HID_L2CAP_CONN_FAIL;
|
||||
p_dev->conn.conn_flags = HID_CONN_FLAGS_IS_ORIG;
|
||||
BTM_SetOutService(p_dev->addr, BTM_SEC_SERVICE_HIDD_SEC_CTRL, HIDD_SEC_CHN);
|
||||
/* Check if L2CAP started the connection process */
|
||||
if ((p_dev->conn.ctrl_cid = L2CA_ConnectReq(HID_PSM_CONTROL, p_dev->addr)) == 0) {
|
||||
HIDD_TRACE_WARNING("%s: could not start L2CAP connection", __func__);
|
||||
hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_CLOSE, HID_ERR_L2CAP_FAILED, NULL);
|
||||
} else {
|
||||
p_dev->conn.conn_state = HID_CONN_STATE_CONNECTING_CTRL;
|
||||
}
|
||||
return (HID_SUCCESS);
|
||||
}
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function hidd_conn_disconnect
|
||||
*
|
||||
* Description Disconnects existing HID connection
|
||||
*
|
||||
* Returns HID_SUCCESS
|
||||
*
|
||||
******************************************************************************/
|
||||
tHID_STATUS hidd_conn_disconnect(void)
|
||||
{
|
||||
tHID_CONN *p_hcon;
|
||||
HIDD_TRACE_API("%s", __func__);
|
||||
// clean any outstanding data on intr
|
||||
if (hd_cb.pending_data) {
|
||||
osi_free(hd_cb.pending_data);
|
||||
hd_cb.pending_data = NULL;
|
||||
}
|
||||
p_hcon = &hd_cb.device.conn;
|
||||
if ((p_hcon->ctrl_cid != 0) || (p_hcon->intr_cid != 0)) {
|
||||
/* Set l2cap idle timeout to 0 (so ACL link is disconnected
|
||||
* immediately after last channel is closed) */
|
||||
L2CA_SetIdleTimeoutByBdAddr(hd_cb.device.addr, 0, BT_TRANSPORT_BR_EDR);
|
||||
if (p_hcon->intr_cid) {
|
||||
p_hcon->conn_state = HID_CONN_STATE_DISCONNECTING_INTR;
|
||||
L2CA_DisconnectReq(p_hcon->intr_cid);
|
||||
} else if (p_hcon->ctrl_cid) {
|
||||
p_hcon->conn_state = HID_CONN_STATE_DISCONNECTING_CTRL;
|
||||
L2CA_DisconnectReq(p_hcon->ctrl_cid);
|
||||
}
|
||||
} else {
|
||||
HIDD_TRACE_WARNING("%s: already disconnected", __func__);
|
||||
p_hcon->conn_state = HID_CONN_STATE_UNUSED;
|
||||
}
|
||||
return (HID_SUCCESS);
|
||||
}
|
||||
/*******************************************************************************
|
||||
*
|
||||
* Function hidd_conn_send_data
|
||||
*
|
||||
* Description Sends data to host
|
||||
*
|
||||
* Returns tHID_STATUS
|
||||
*
|
||||
******************************************************************************/
|
||||
tHID_STATUS hidd_conn_send_data(uint8_t channel, uint8_t msg_type, uint8_t param, uint8_t data, uint16_t len,
|
||||
uint8_t *p_data)
|
||||
{
|
||||
tHID_CONN *p_hcon;
|
||||
BT_HDR *p_buf;
|
||||
uint8_t *p_out;
|
||||
uint16_t cid;
|
||||
uint16_t buf_size;
|
||||
HIDD_TRACE_VERBOSE("%s: channel(%d), msg_type(%d), len(%d)", __func__, channel, msg_type, len);
|
||||
p_hcon = &hd_cb.device.conn;
|
||||
if (p_hcon->conn_flags & HID_CONN_FLAGS_CONGESTED) {
|
||||
return HID_ERR_CONGESTED;
|
||||
}
|
||||
switch (msg_type) {
|
||||
case HID_TRANS_HANDSHAKE:
|
||||
case HID_TRANS_CONTROL:
|
||||
cid = p_hcon->ctrl_cid;
|
||||
buf_size = HID_CONTROL_BUF_SIZE;
|
||||
break;
|
||||
case HID_TRANS_DATA:
|
||||
if (channel == HID_CHANNEL_CTRL) {
|
||||
cid = p_hcon->ctrl_cid;
|
||||
buf_size = HID_CONTROL_BUF_SIZE;
|
||||
} else {
|
||||
cid = p_hcon->intr_cid;
|
||||
buf_size = HID_INTERRUPT_BUF_SIZE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return (HID_ERR_INVALID_PARAM);
|
||||
}
|
||||
p_buf = (BT_HDR *)osi_malloc(buf_size);
|
||||
if (p_buf == NULL)
|
||||
return (HID_ERR_NO_RESOURCES);
|
||||
p_buf->offset = L2CAP_MIN_OFFSET;
|
||||
p_out = (uint8_t *)(p_buf + 1) + p_buf->offset;
|
||||
*p_out = HID_BUILD_HDR(msg_type, param);
|
||||
p_out++;
|
||||
p_buf->len = 1; // start with header only
|
||||
// add report id prefix only if non-zero (which is reserved)
|
||||
if (msg_type == HID_TRANS_DATA && (data || param == HID_PAR_REP_TYPE_OTHER)) {
|
||||
*p_out = data; // report_id
|
||||
p_out++;
|
||||
p_buf->len++;
|
||||
}
|
||||
if (len > 0 && p_data != NULL) {
|
||||
memcpy(p_out, p_data, len);
|
||||
p_buf->len += len;
|
||||
}
|
||||
// check if connected
|
||||
if (hd_cb.device.state != HIDD_DEV_CONNECTED) {
|
||||
// for DATA on intr we hold transfer and try to reconnect
|
||||
if (msg_type == HID_TRANS_DATA && cid == p_hcon->intr_cid) {
|
||||
// drop previous data, we do not queue it for now
|
||||
if (hd_cb.pending_data) {
|
||||
osi_free(hd_cb.pending_data);
|
||||
}
|
||||
hd_cb.pending_data = p_buf;
|
||||
if (hd_cb.device.conn.conn_state == HID_CONN_STATE_UNUSED) {
|
||||
hidd_conn_initiate();
|
||||
}
|
||||
return HID_SUCCESS;
|
||||
}
|
||||
return HID_ERR_NO_CONNECTION;
|
||||
}
|
||||
#ifdef REPORT_TRANSFER_TIMESTAMP
|
||||
if (report_transfer) {
|
||||
HIDD_TRACE_ERROR("%s: report sent", __func__);
|
||||
}
|
||||
#endif
|
||||
HIDD_TRACE_VERBOSE("%s: report sent", __func__);
|
||||
if (!L2CA_DataWrite(cid, p_buf))
|
||||
return (HID_ERR_CONGESTED);
|
||||
return (HID_SUCCESS);
|
||||
}
|
||||
|
||||
#endif
|
@ -31,7 +31,7 @@
|
||||
#include "stack/bt_types.h"
|
||||
#include "stack/hiddefs.h"
|
||||
#include "stack/hidh_api.h"
|
||||
#include "hidh_int.h"
|
||||
#include "hid_int.h"
|
||||
#include "stack/btm_api.h"
|
||||
#include "stack/btu.h"
|
||||
#include "btm_int.h"
|
||||
@ -39,7 +39,9 @@
|
||||
#if (HID_HOST_INCLUDED == TRUE)
|
||||
|
||||
#if HID_DYNAMIC_MEMORY == FALSE
|
||||
tHID_HOST_CTB hh_cb;
|
||||
tHID_HOST_CTB hh_cb;
|
||||
#else
|
||||
tHID_HOST_CTB *hidh_cb_ptr = NULL;
|
||||
#endif
|
||||
|
||||
static void hidh_search_callback (UINT16 sdp_result);
|
||||
@ -218,18 +220,46 @@ static void hidh_search_callback (UINT16 sdp_result)
|
||||
**
|
||||
** Description This function initializes the control block and trace variable
|
||||
**
|
||||
** Returns void
|
||||
** Returns tHID_STATUS
|
||||
**
|
||||
*******************************************************************************/
|
||||
void HID_HostInit (void)
|
||||
tHID_STATUS HID_HostInit (void)
|
||||
{
|
||||
#if (HID_DYNAMIC_MEMORY)
|
||||
if (!hidh_cb_ptr) {
|
||||
hidh_cb_ptr = (tHID_HOST_CTB *)osi_malloc(sizeof(tHID_HOST_CTB));
|
||||
if (!hidh_cb_ptr) {
|
||||
return HID_ERR_NO_RESOURCES;
|
||||
}
|
||||
}
|
||||
#endif /* #if (HID_DYNAMIC_MEMORY) */
|
||||
memset(&hh_cb, 0, sizeof(tHID_HOST_CTB));
|
||||
|
||||
#if defined(HID_INITIAL_TRACE_LEVEL)
|
||||
hh_cb.trace_level = HID_INITIAL_TRACE_LEVEL;
|
||||
#if defined(HIDH_INITIAL_TRACE_LEVEL)
|
||||
hh_cb.trace_level = HIDH_INITIAL_TRACE_LEVEL;
|
||||
#else
|
||||
hh_cb.trace_level = BT_TRACE_LEVEL_NONE;
|
||||
#endif
|
||||
return HID_SUCCESS;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function HID_HostInit
|
||||
**
|
||||
** Description This function deinitializes the control block
|
||||
**
|
||||
** Returns void
|
||||
**
|
||||
*******************************************************************************/
|
||||
void HID_HostDeinit (void)
|
||||
{
|
||||
#if (HID_DYNAMIC_MEMORY)
|
||||
if (hidh_cb_ptr) {
|
||||
osi_free(hidh_cb_ptr);
|
||||
hidh_cb_ptr = NULL;
|
||||
}
|
||||
#endif /* #if (HID_DYNAMIC_MEMORY) */
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
@ -362,6 +392,36 @@ tHID_STATUS HID_HostAddDev ( BD_ADDR addr, UINT16 attr_mask, UINT8 *handle )
|
||||
return (HID_SUCCESS);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
||||
** Function HID_HostGetDev
|
||||
**
|
||||
** Description This is called so HID-host can find this device.
|
||||
**
|
||||
** Returns tHID_STATUS
|
||||
**
|
||||
*******************************************************************************/
|
||||
tHID_STATUS HID_HostGetDev(BD_ADDR addr, UINT8 *handle)
|
||||
{
|
||||
int i;
|
||||
/* Find an entry for this device in hh_cb.devices array */
|
||||
if (!hh_cb.reg_flag) {
|
||||
return (HID_ERR_NOT_REGISTERED);
|
||||
}
|
||||
|
||||
for (i = 0; i < HID_HOST_MAX_DEVICES; i++) {
|
||||
if ((hh_cb.devices[i].in_use) && (!memcmp(addr, hh_cb.devices[i].addr, BD_ADDR_LEN))) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == HID_HOST_MAX_DEVICES) {
|
||||
*handle = 0xff;
|
||||
} else {
|
||||
*handle = i;
|
||||
}
|
||||
return (HID_SUCCESS);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
**
|
@ -41,7 +41,7 @@
|
||||
#include "stack/hiddefs.h"
|
||||
|
||||
#include "stack/hidh_api.h"
|
||||
#include "hidh_int.h"
|
||||
#include "hid_int.h"
|
||||
#include "osi/osi.h"
|
||||
|
||||
#if (HID_HOST_INCLUDED == TRUE)
|
||||
@ -132,15 +132,16 @@ tHID_STATUS hidh_conn_disconnect (UINT8 dhandle)
|
||||
HIDH_TRACE_EVENT ("HID-Host disconnect");
|
||||
|
||||
if ((p_hcon->ctrl_cid != 0) || (p_hcon->intr_cid != 0)) {
|
||||
p_hcon->conn_state = HID_CONN_STATE_DISCONNECTING;
|
||||
|
||||
/* Set l2cap idle timeout to 0 (so ACL link is disconnected
|
||||
* immediately after last channel is closed) */
|
||||
L2CA_SetIdleTimeoutByBdAddr(hh_cb.devices[dhandle].addr, 0, BT_TRANSPORT_BR_EDR);
|
||||
/* Disconnect both interrupt and control channels */
|
||||
if (p_hcon->intr_cid) {
|
||||
p_hcon->conn_state = HID_CONN_STATE_DISCONNECTING_INTR;
|
||||
L2CA_DisconnectReq (p_hcon->intr_cid);
|
||||
} else if (p_hcon->ctrl_cid) {
|
||||
p_hcon->conn_state = HID_CONN_STATE_DISCONNECTING_CTRL;
|
||||
L2CA_DisconnectReq (p_hcon->ctrl_cid);
|
||||
}
|
||||
} else {
|
||||
@ -360,12 +361,12 @@ static void hidh_l2cif_connect_cfm (UINT16 l2cap_cid, UINT16 result)
|
||||
p_hcon = &hh_cb.devices[dhandle].conn;
|
||||
}
|
||||
|
||||
if ((p_hcon == NULL)
|
||||
|| (!(p_hcon->conn_flags & HID_CONN_FLAGS_IS_ORIG))
|
||||
|| ((l2cap_cid == p_hcon->ctrl_cid) && (p_hcon->conn_state != HID_CONN_STATE_CONNECTING_CTRL))
|
||||
|| ((l2cap_cid == p_hcon->intr_cid) && (p_hcon->conn_state != HID_CONN_STATE_CONNECTING_INTR)
|
||||
&& (p_hcon->conn_state != HID_CONN_STATE_DISCONNECTING))) {
|
||||
HIDH_TRACE_WARNING ("HID-Host Rcvd unexpected conn cnf, CID 0x%x ", l2cap_cid);
|
||||
if ((p_hcon == NULL) || (!(p_hcon->conn_flags & HID_CONN_FLAGS_IS_ORIG)) ||
|
||||
((l2cap_cid == p_hcon->ctrl_cid) && (p_hcon->conn_state != HID_CONN_STATE_CONNECTING_CTRL) &&
|
||||
(p_hcon->conn_state != HID_CONN_STATE_DISCONNECTING_INTR)) ||
|
||||
((l2cap_cid == p_hcon->intr_cid) && (p_hcon->conn_state != HID_CONN_STATE_CONNECTING_INTR) &&
|
||||
(p_hcon->conn_state != HID_CONN_STATE_DISCONNECTING_CTRL))) {
|
||||
HIDH_TRACE_WARNING("HID-Host Rcvd unexpected conn cnf, CID 0x%x ", l2cap_cid);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -592,12 +593,12 @@ static void hidh_l2cif_disconnect_ind (UINT16 l2cap_cid, BOOLEAN ack_needed)
|
||||
|
||||
HIDH_TRACE_EVENT ("HID-Host Rcvd L2CAP disc, CID: 0x%x", l2cap_cid);
|
||||
|
||||
p_hcon->conn_state = HID_CONN_STATE_DISCONNECTING;
|
||||
|
||||
if (l2cap_cid == p_hcon->ctrl_cid) {
|
||||
p_hcon->ctrl_cid = 0;
|
||||
p_hcon->conn_state = HID_CONN_STATE_DISCONNECTING_CTRL;
|
||||
} else {
|
||||
p_hcon->intr_cid = 0;
|
||||
p_hcon->conn_state = HID_CONN_STATE_DISCONNECTING_INTR;
|
||||
}
|
||||
|
||||
if ((p_hcon->ctrl_cid == 0) && (p_hcon->intr_cid == 0)) {
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user