diff --git a/components/bt/CMakeLists.txt b/components/bt/CMakeLists.txt index aa8a4b0cb1..4f8d9f1440 100644 --- a/components/bt/CMakeLists.txt +++ b/components/bt/CMakeLists.txt @@ -443,6 +443,7 @@ if(CONFIG_BT_ENABLED) "host/bluedroid/stack/btm/btm_dev.c" "host/bluedroid/stack/btm/btm_devctl.c" "host/bluedroid/stack/btm/btm_inq.c" + "host/bluedroid/stack/btm/btm_bredr_pwr_ctrl.c" "host/bluedroid/stack/btm/btm_main.c" "host/bluedroid/stack/btm/btm_pm.c" "host/bluedroid/stack/btm/btm_sco.c" diff --git a/components/bt/controller/esp32/bt.c b/components/bt/controller/esp32/bt.c index f2e4306a10..beb5c228b2 100644 --- a/components/bt/controller/esp32/bt.c +++ b/components/bt/controller/esp32/bt.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -261,6 +261,9 @@ extern void btdm_aa_check_enhance_enable(void); #ifdef CONFIG_BT_BLUEDROID_ENABLED extern void bt_stack_enableSecCtrlVsCmd(bool en); #endif // CONFIG_BT_BLUEDROID_ENABLED +#if UC_BR_EDR_POWER_CTRL_VSC_ENABLED +extern void bt_stack_enablePwrCtrlVsCmd(bool en); +#endif // UC_BR_EDR_POWER_CTRL_VSC_ENABLED #if defined(CONFIG_BT_NIMBLE_ENABLED) || defined(CONFIG_BT_BLUEDROID_ENABLED) extern void bt_stack_enableCoexVsCmd(bool en); extern void scan_stack_enableAdvFlowCtrlVsCmd(bool en); @@ -1678,7 +1681,7 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) } //overwrite some parameters - cfg->bt_max_sync_conn = UT_BR_EDR_CTRL_MAX_SYNC_CONN_EFF; + cfg->bt_max_sync_conn = UC_BR_EDR_CTRL_MAX_SYNC_CONN_EFF; cfg->magic = ESP_BT_CONTROLLER_CONFIG_MAGIC_VAL; if (((cfg->mode & ESP_BT_MODE_BLE) && (cfg->ble_max_conn <= 0 || cfg->ble_max_conn > BTDM_CONTROLLER_BLE_MAX_CONN_LIMIT)) @@ -1748,6 +1751,9 @@ esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg) #ifdef CONFIG_BT_BLUEDROID_ENABLED bt_stack_enableSecCtrlVsCmd(true); #endif // CONFIG_BT_BLUEDROID_ENABLED +#if UC_BR_EDR_POWER_CTRL_VSC_ENABLED + bt_stack_enablePwrCtrlVsCmd(true); +#endif // UC_BR_EDR_POWER_CTRL_VSC_ENABLED #if defined(CONFIG_BT_NIMBLE_ENABLED) || defined(CONFIG_BT_BLUEDROID_ENABLED) bt_stack_enableCoexVsCmd(true); scan_stack_enableAdvFlowCtrlVsCmd(true); @@ -1796,6 +1802,9 @@ esp_err_t esp_bt_controller_deinit(void) #ifdef CONFIG_BT_BLUEDROID_ENABLED bt_stack_enableSecCtrlVsCmd(false); #endif // CONFIG_BT_BLUEDROID_ENABLED +#if UC_BR_EDR_POWER_CTRL_VSC_ENABLED + bt_stack_enablePwrCtrlVsCmd(false); +#endif // UC_BR_EDR_POWER_CTRL_VSC_ENABLED #if defined(CONFIG_BT_NIMBLE_ENABLED) || defined(CONFIG_BT_BLUEDROID_ENABLED) bt_stack_enableCoexVsCmd(false); scan_stack_enableAdvFlowCtrlVsCmd(false); @@ -2012,6 +2021,11 @@ esp_power_level_t esp_ble_tx_power_get(esp_ble_power_type_t power_type) esp_err_t esp_bredr_tx_power_set(esp_power_level_t min_power_level, esp_power_level_t max_power_level) { +#if UC_BR_EDR_POWER_CTRL_VSC_ENABLED + UNUSED(min_power_level); + UNUSED(max_power_level); + return ESP_ERR_NOT_SUPPORTED; +#else esp_err_t err; int ret; @@ -2026,15 +2040,22 @@ esp_err_t esp_bredr_tx_power_set(esp_power_level_t min_power_level, esp_power_le } return err; +#endif // #if UC_BR_EDR_POWER_CTRL_VSC_ENABLED } esp_err_t esp_bredr_tx_power_get(esp_power_level_t *min_power_level, esp_power_level_t *max_power_level) { +#if UC_BR_EDR_POWER_CTRL_VSC_ENABLED + UNUSED(min_power_level); + UNUSED(max_power_level); + return ESP_ERR_NOT_SUPPORTED; +#else if (bredr_txpwr_get((int *)min_power_level, (int *)max_power_level) != 0) { return ESP_ERR_INVALID_ARG; } return ESP_OK; +#endif // #if UC_BR_EDR_POWER_CTRL_VSC_ENABLED } esp_err_t esp_bt_sleep_enable (void) diff --git a/components/bt/controller/esp32/esp_bredr_cfg.h b/components/bt/controller/esp32/esp_bredr_cfg.h index c245bf4dbe..17e32db82d 100644 --- a/components/bt/controller/esp32/esp_bredr_cfg.h +++ b/components/bt/controller/esp32/esp_bredr_cfg.h @@ -16,18 +16,25 @@ extern "C" { defined(CONFIG_BTDM_CTRL_BR_EDR_MAX_SYNC_CONN) && (CONFIG_BTDM_CTRL_BR_EDR_MAX_SYNC_CONN == 0) #pragma message ("BT: forcing BR/EDR max sync conn eff to 1 (Bluedroid HFP requires SCO/eSCO)") -#define UT_BR_EDR_CTRL_MAX_SYNC_CONN_EFF (1) +#define UC_BR_EDR_CTRL_MAX_SYNC_CONN_EFF (1) #elif defined(CONFIG_BTDM_CTRL_BR_EDR_MAX_SYNC_CONN) -#define UT_BR_EDR_CTRL_MAX_SYNC_CONN_EFF (CONFIG_BTDM_CTRL_BR_EDR_MAX_SYNC_CONN) +#define UC_BR_EDR_CTRL_MAX_SYNC_CONN_EFF (CONFIG_BTDM_CTRL_BR_EDR_MAX_SYNC_CONN) #else -#define UT_BR_EDR_CTRL_MAX_SYNC_CONN_EFF (0) +#define UC_BR_EDR_CTRL_MAX_SYNC_CONN_EFF (0) #endif +/* Enable BR/EDR power control vsc */ +#if defined(CONFIG_BT_CLASSIC_ENABLE_POWER_CTRL_VSC) +#define UC_BR_EDR_POWER_CTRL_VSC_ENABLED CONFIG_BT_CLASSIC_ENABLE_POWER_CTRL_VSC +#else +#define UC_BR_EDR_POWER_CTRL_VSC_ENABLED (0) +#endif + #ifdef __cplusplus } #endif diff --git a/components/bt/controller/lib_esp32 b/components/bt/controller/lib_esp32 index a348e3fbc7..4c40f02e72 160000 --- a/components/bt/controller/lib_esp32 +++ b/components/bt/controller/lib_esp32 @@ -1 +1 @@ -Subproject commit a348e3fbc75411acd88357af9e1d6a76621c449e +Subproject commit 4c40f02e7255d0a4c859f70dababf2400eafcbfe diff --git a/components/bt/host/bluedroid/Kconfig.in b/components/bt/host/bluedroid/Kconfig.in index 83b88a28e7..34d8778e0f 100644 --- a/components/bt/host/bluedroid/Kconfig.in +++ b/components/bt/host/bluedroid/Kconfig.in @@ -48,6 +48,13 @@ config BT_CLASSIC_ENABLED help For now this option needs "SMP_ENABLE" to be set to yes +config BT_CLASSIC_ENABLE_POWER_CTRL_VSC + bool "Enable Espressif Vendor-specific HCI commands for power control of Classic Bluetooth" + depends on BT_CLASSIC_ENABLED + default n + help + Enable Espressif Vendor-specific HCI commands for power control of Classic Bluetooth + choice BT_ENC_KEY_SIZE_CTRL_ENABLED prompt "configure encryption key size" depends on BT_CLASSIC_ENABLED diff --git a/components/bt/host/bluedroid/api/esp_gap_bt_api.c b/components/bt/host/bluedroid/api/esp_gap_bt_api.c index cc874374e8..200630e11a 100644 --- a/components/bt/host/bluedroid/api/esp_gap_bt_api.c +++ b/components/bt/host/bluedroid/api/esp_gap_bt_api.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -244,6 +244,103 @@ esp_err_t esp_bt_gap_read_rssi_delta(esp_bd_addr_t remote_addr) return (btc_transfer_context(&msg, &arg, sizeof(btc_gap_bt_args_t), NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); } +#if (ESP_BT_CLASSIC_ENABLE_POWER_CTRL_VSC == TRUE) +esp_err_t esp_bt_gap_read_acl_real_rssi(esp_bd_addr_t remote_addr) +{ + btc_msg_t msg; + btc_gap_bt_args_t arg; + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_GAP_BT; + msg.act = BTC_GAP_BT_ACT_READ_ACL_REAL_RSSI; + memcpy(arg.read_acl_real_rssi.bda.address, remote_addr, sizeof(esp_bd_addr_t)); + + return (btc_transfer_context(&msg, &arg, sizeof(btc_gap_bt_args_t), NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} + +esp_err_t esp_bt_gap_read_new_conn_tx_pwr_rng(void) +{ + btc_msg_t msg; + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_GAP_BT; + msg.act = BTC_GAP_BT_ACT_READ_NEW_CONN_TX_PWR_LVL; + + return (btc_transfer_context(&msg, NULL, 0, NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} + +esp_err_t esp_bt_gap_write_new_conn_tx_pwr_rng(int8_t pwr_lvl_min, int8_t pwr_lvl_max) +{ + btc_msg_t msg; + btc_gap_bt_args_t arg; + + if (pwr_lvl_min < ESP_TX_PWR_LVL_MIN || pwr_lvl_min > ESP_TX_PWR_LVL_MAX || + pwr_lvl_max < ESP_TX_PWR_LVL_MIN || pwr_lvl_max > ESP_TX_PWR_LVL_MAX || + pwr_lvl_min > pwr_lvl_max) { + return ESP_ERR_INVALID_ARG; + } + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_GAP_BT; + msg.act = BTC_GAP_BT_ACT_WRITE_NEW_CONN_TX_PWR_LVL; + arg.write_new_conn_tx_pwr_lvl.pwr_lvl_min = pwr_lvl_min; + arg.write_new_conn_tx_pwr_lvl.pwr_lvl_max = pwr_lvl_max; + + return (btc_transfer_context(&msg, &arg, sizeof(btc_gap_bt_args_t), NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} +#endif // #if (ESP_BT_CLASSIC_ENABLE_POWER_CTRL_VSC == TRUE) + +esp_err_t esp_bt_gap_read_tx_pwr_lvl(esp_bt_gap_tx_pwr_lvl_type_t type) +{ + btc_msg_t msg; + btc_gap_bt_args_t arg; + +#if (ESP_BT_CLASSIC_ENABLE_POWER_CTRL_VSC == TRUE) + if (type >= ESP_BT_GAP_TX_PWR_LVL_TYPE_MAX) { + return ESP_ERR_INVALID_ARG; + } +#else + if (type != ESP_BT_GAP_TX_PWR_LVL_ISCAN) { + return ESP_ERR_NOT_SUPPORTED; + } +#endif // #if (ESP_BT_CLASSIC_ENABLE_POWER_CTRL_VSC == TRUE) + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_GAP_BT; + msg.act = BTC_GAP_BT_ACT_READ_TX_PWR_LVL; + arg.read_tx_pwr_lvl.type = type; + + return (btc_transfer_context(&msg, &arg, sizeof(btc_gap_bt_args_t), NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} + +esp_err_t esp_bt_gap_write_tx_pwr_lvl(esp_bt_gap_tx_pwr_lvl_type_t type, int8_t tx_power) +{ + btc_msg_t msg; + btc_gap_bt_args_t arg; + +#if (ESP_BT_CLASSIC_ENABLE_POWER_CTRL_VSC == TRUE) + if (type >= ESP_BT_GAP_TX_PWR_LVL_TYPE_MAX || + tx_power < ESP_TX_PWR_LVL_MIN || tx_power > ESP_TX_PWR_LVL_MAX) { + return ESP_ERR_INVALID_ARG; + } +#else + if (type != ESP_BT_GAP_TX_PWR_LVL_INQ) { + return ESP_ERR_NOT_SUPPORTED; + } + if (tx_power < ESP_TX_PWR_LVL_MIN || tx_power > ESP_TX_PWR_LVL_MAX) { + return ESP_ERR_INVALID_ARG; + } +#endif // #if (ESP_BT_CLASSIC_ENABLE_POWER_CTRL_VSC == TRUE) + + msg.sig = BTC_SIG_API_CALL; + msg.pid = BTC_PID_GAP_BT; + msg.act = BTC_GAP_BT_ACT_WRITE_TX_PWR_LVL; + arg.write_tx_pwr_lvl.type = type; + arg.write_tx_pwr_lvl.tx_power = tx_power; + + return (btc_transfer_context(&msg, &arg, sizeof(btc_gap_bt_args_t), NULL, NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); +} + esp_err_t esp_bt_gap_remove_bond_device(esp_bd_addr_t bd_addr) { btc_msg_t msg; diff --git a/components/bt/host/bluedroid/api/include/api/esp_gap_bt_api.h b/components/bt/host/bluedroid/api/include/api/esp_gap_bt_api.h index 886be4e89f..1197748462 100644 --- a/components/bt/host/bluedroid/api/include/api/esp_gap_bt_api.h +++ b/components/bt/host/bluedroid/api/include/api/esp_gap_bt_api.h @@ -295,6 +295,11 @@ typedef enum { ESP_BT_GAP_ENC_CHG_EVT, /*!< Encryption change event */ ESP_BT_GAP_SET_MIN_ENC_KEY_SIZE_EVT, /*!< Set minimum encryption key size */ ESP_BT_GAP_GET_DEV_NAME_CMPL_EVT, /*!< Get device name complete event */ + ESP_BT_GAP_READ_ACL_REAL_RSSI_EVT, /*!< Read ACL real RSSI event (vendor-specific) */ + ESP_BT_GAP_READ_NEW_CONN_TX_PWR_RNG_EVT, /*!< Read new connection transmit power range event (for ACL) */ + ESP_BT_GAP_WRITE_NEW_CONN_TX_PWR_RNG_EVT, /*!< Write new connection transmit power range event (for ACL) */ + ESP_BT_GAP_READ_TX_PWR_LVL_EVT, /*!< Read inq/iscan/page/pscan transmit power level event */ + ESP_BT_GAP_WRITE_TX_PWR_LVL_EVT, /*!< Write inq/iscan/page/pscan transmit power level event */ ESP_BT_GAP_EVT_MAX, } esp_bt_gap_cb_event_t; @@ -304,6 +309,19 @@ typedef enum { ESP_BT_INQ_MODE_LIMITED_INQUIRY, /*!< Limited inquiry mode */ } esp_bt_inq_mode_t; +#define ESP_TX_PWR_LVL_MIN (-70) /*!< TX power level min */ +#define ESP_TX_PWR_LVL_MAX (+20) /*!< TX power level max */ +/** + * @brief BR/EDR TX power level type for inq/iscan/page/pscan control + */ +typedef enum { + ESP_BT_GAP_TX_PWR_LVL_INQ = 0, /*!< Inquiry TX power level (read/write) */ + ESP_BT_GAP_TX_PWR_LVL_ISCAN, /*!< Inquiry scan TX power level (read/write) */ + ESP_BT_GAP_TX_PWR_LVL_PAGE, /*!< Page TX power level (read/write) */ + ESP_BT_GAP_TX_PWR_LVL_PSCAN, /*!< Page scan TX power level (read/write) */ + ESP_BT_GAP_TX_PWR_LVL_TYPE_MAX, /*!< TX power level type max */ +} esp_bt_gap_tx_pwr_lvl_type_t; + /* Minimum and Maximum inquiry length */ #define ESP_BT_GAP_MIN_INQ_LEN (0x01) /*!< Minimum inquiry duration, unit is 1.28s */ #define ESP_BT_GAP_MAX_INQ_LEN (0x30) /*!< Maximum inquiry duration, unit is 1.28s */ @@ -366,6 +384,48 @@ typedef union { int8_t rssi_delta; /*!< rssi delta value range -128 ~127, The value zero indicates that the RSSI is inside the Golden Receive Power Range */ } read_rssi_delta; /*!< read rssi parameter struct */ + /** + * @brief ESP_BT_GAP_READ_ACL_REAL_RSSI_EVT + */ + struct read_acl_real_rssi_param { + esp_bd_addr_t bda; /*!< remote bluetooth device address*/ + esp_bt_status_t stat; /*!< read rssi status */ + int8_t rssi; /*!< ACL real RSSI value range -128 ~127 */ + } read_acl_real_rssi; /*!< read acl real rssi parameter struct */ + + /** + * @brief ESP_BT_GAP_READ_NEW_CONN_TX_PWR_RNG_EVT + */ + struct read_new_conn_tx_pwr_lvl_param { + esp_bt_status_t stat; /*!< read new connection transmit power level status */ + int8_t pwr_lvl_min; /*!< new connection transmit power level value range -70 ~ 20 dbm*/ + int8_t pwr_lvl_max; /*!< new connection transmit power level value range -70 ~ 20 dbm*/ + } read_new_conn_tx_pwr_lvl; /*!< read new connection transmit power level parameter struct */ + + /** + * @brief ESP_BT_GAP_WRITE_NEW_CONN_TX_PWR_RNG_EVT + */ + struct write_new_conn_tx_pwr_lvl_param { + esp_bt_status_t stat; /*!< write new connection transmit power level status */ + } write_new_conn_tx_pwr_lvl; /*!< write new connection transmit power level parameter struct */ + + /** + * @brief ESP_BT_GAP_READ_TX_PWR_LVL_EVT + */ + struct read_tx_pwr_lvl_param { + esp_bt_status_t stat; /*!< read inq/iscan/page/pscan transmit power level status */ + esp_bt_gap_tx_pwr_lvl_type_t type; /*!< read tx power level type */ + int8_t tx_power; /*!< inq/iscan/page/pscan transmit power level value range -70 ~ 20 dBm */ + } read_tx_pwr_lvl; /*!< read inq/iscan/page/pscan transmit power level parameter struct */ + + /** + * @brief ESP_BT_GAP_WRITE_TX_PWR_LVL_EVT + */ + struct write_tx_pwr_lvl_param { + esp_bt_status_t stat; /*!< write inq/iscan/page/pscan transmit power level status */ + esp_bt_gap_tx_pwr_lvl_type_t type; /*!< write tx power level type */ + } write_tx_pwr_lvl; /*!< write inq/iscan/page/pscan transmit power level parameter struct */ + /** * @brief ESP_BT_GAP_CONFIG_EIR_DATA_EVT */ @@ -762,6 +822,103 @@ esp_err_t esp_bt_gap_get_cod(esp_bt_cod_t *cod); */ esp_err_t esp_bt_gap_read_rssi_delta(esp_bd_addr_t remote_addr); +/** + * @brief This function is called to read ACL real RSSI by address after connected. + * The RSSI value returned by ESP_BT_GAP_READ_ACL_REAL_RSSI_EVT. + * + * @note + * 1. This function relies on Espressif vendor-specific HCI and is only used for internal testing. + * 2. This function requires the `BT_CLASSIC_ENABLE_POWER_CTRL_VSC` configuration to be enabled when used. + * And it will disable `esp_bredr_tx_power_set()` and `esp_bredr_tx_power_get()`. + * + * @param[in] remote_addr - remote device address, corresponding to a certain connection handle + * + * @return + * - ESP_OK : Succeed + * - ESP_FAIL: others + */ +esp_err_t esp_bt_gap_read_acl_real_rssi(esp_bd_addr_t remote_addr); + +/** + * @brief This function is called to read new connection transmit power level (for ACL). + * The new connection transmit power level value returned by ESP_BT_GAP_READ_NEW_CONN_TX_PWR_RNG_EVT. + * + * @note + * 1. This function relies on Espressif vendor-specific HCI and is only used for internal testing. + * 2. This function requires the `BT_CLASSIC_ENABLE_POWER_CTRL_VSC` configuration to be enabled when used. + * And it will disable `esp_bredr_tx_power_set()` and `esp_bredr_tx_power_get()`. + * + * + * @return + * - ESP_OK : Succeed + * - ESP_FAIL: others + */ +esp_err_t esp_bt_gap_read_new_conn_tx_pwr_rng(void); + +/** + * @brief This function is called to write new connection transmit power level (for ACL). + * The write status returned by ESP_BT_GAP_WRITE_NEW_CONN_TX_PWR_RNG_EVT. + * + * @note + * 1. This function relies on Espressif vendor-specific HCI and is only used for internal testing. + * 2. This function requires the `BT_CLASSIC_ENABLE_POWER_CTRL_VSC` configuration to be enabled when used. + * And it will disable `esp_bredr_tx_power_set()` and `esp_bredr_tx_power_get()`. + * + * @param[in] pwr_lvl_min - new connection transmit power level value range -70 ~ 20 dBm + * @param[in] pwr_lvl_max - new connection transmit power level value range -70 ~ 20 dBm + * + * @return + * - ESP_OK : Succeed + * - ESP_ERR_INVALID_ARG: Invalid arg + * - ESP_FAIL: others + */ +esp_err_t esp_bt_gap_write_new_conn_tx_pwr_rng(int8_t pwr_lvl_min, int8_t pwr_lvl_max); + +/** + * @brief This function is called to read inquiry response transmit power level by standard HCI, + * and inquiry/page/page scan transmit power level by vendor specific HCI. + * The value is returned by ESP_BT_GAP_READ_TX_PWR_LVL_EVT. + * + * @note + * 1. This function relies on Espressif vendor-specific HCI and is only used for internal testing + * when type is inquiry/page/page scan. + * 2. This function requires the `BT_CLASSIC_ENABLE_POWER_CTRL_VSC` configuration to be enabled when read + * inquiry/page/page scan transmit power level, and it will disable `esp_bredr_tx_power_set()` + * and `esp_bredr_tx_power_get()`. + * + * @param[in] type - read type, supports INQ/ISCAN/PAGE/PSCAN + * + * @return + * - ESP_OK : Succeed + * - ESP_ERR_INVALID_ARG: Invalid arg + * - ESP_ERR_NOT_SUPPORTED: Not supported + * - ESP_FAIL: others + */ +esp_err_t esp_bt_gap_read_tx_pwr_lvl(esp_bt_gap_tx_pwr_lvl_type_t type); + +/** + * @brief This function is called to write inquiry transmit power level by standard HCI, + * and inquiry response/page/page scan transmit power level by vendor specific HCI. + * The write status returned by ESP_BT_GAP_WRITE_TX_PWR_LVL_EVT. + * + * @note + * 1. This function relies on Espressif vendor-specific HCI and is only used for internal testing + * when type is inquiry response/page/page scan. + * 2. This function requires the `BT_CLASSIC_ENABLE_POWER_CTRL_VSC` configuration to be enabled when write + * inquiry response/page/page scan transmit power level, and it will disable `esp_bredr_tx_power_set()` + * and `esp_bredr_tx_power_get()`. + * + * @param[in] type - write type, supports INQ/ISCAN/PAGE/PSCAN + * @param[in] tx_power - transmit power level value range -70 ~ 20 dBm + * + * @return + * - ESP_OK : Succeed + * - ESP_ERR_INVALID_ARG: Invalid arg + * - ESP_ERR_NOT_SUPPORTED: Not supported + * - ESP_FAIL: others + */ +esp_err_t esp_bt_gap_write_tx_pwr_lvl(esp_bt_gap_tx_pwr_lvl_type_t type, int8_t tx_power); + /** * @brief Removes a device from the security database list of * peer device. diff --git a/components/bt/host/bluedroid/bta/dm/bta_dm_act.c b/components/bt/host/bluedroid/bta/dm/bta_dm_act.c index 4126f21eec..151f6eed6a 100644 --- a/components/bt/host/bluedroid/bta/dm/bta_dm_act.c +++ b/components/bt/host/bluedroid/bta/dm/bta_dm_act.c @@ -1017,7 +1017,59 @@ void bta_dm_read_rssi(tBTA_DM_MSG *p_data) } } +#if (ESP_BT_CLASSIC_ENABLE_POWER_CTRL_VSC == TRUE) +void bta_dm_read_acl_real_rssi(tBTA_DM_MSG *p_data) +{ + if (p_data->acl_real_rssi.read_acl_real_rssi_cb != NULL) { + BTM_ReadAclRealRSSI(p_data->acl_real_rssi.remote_addr, p_data->acl_real_rssi.read_acl_real_rssi_cb); + } else { + APPL_TRACE_ERROR("%s(), the callback function can't be NULL.", __func__); + } +} + +void bta_dm_read_new_conn_tx_pwr_lvl(tBTA_DM_MSG *p_data) +{ + if (p_data->read_new_conn_tx_pwr_lvl.read_new_conn_tx_pwr_lvl_cb != NULL) { + BTM_ReadNewConnTxPwrLvl(p_data->read_new_conn_tx_pwr_lvl.read_new_conn_tx_pwr_lvl_cb); + } else { + APPL_TRACE_ERROR("%s(), the callback function can't be NULL.", __func__); + } +} + +void bta_dm_write_new_conn_tx_pwr_lvl(tBTA_DM_MSG *p_data) +{ + if (p_data->write_new_conn_tx_pwr_lvl.write_new_conn_tx_pwr_lvl_cb != NULL) { + BTM_WriteNewConnTxPwrLvl(p_data->write_new_conn_tx_pwr_lvl.pwr_lvl_min, + p_data->write_new_conn_tx_pwr_lvl.pwr_lvl_max, + p_data->write_new_conn_tx_pwr_lvl.write_new_conn_tx_pwr_lvl_cb); + } else { + APPL_TRACE_ERROR("%s(), the callback function can't be NULL.", __func__); + } +} +#endif // #if (ESP_BT_CLASSIC_ENABLE_POWER_CTRL_VSC == TRUE) + #if (CLASSIC_BT_INCLUDED == TRUE) +void bta_dm_read_bredr_tx_pwr_lvl(tBTA_DM_MSG *p_data) +{ + if (p_data->read_bredr_tx_pwr_lvl.read_bredr_tx_pwr_lvl_cb != NULL) { + BTM_ReadBredrTxPwrLvl(p_data->read_bredr_tx_pwr_lvl.type, + p_data->read_bredr_tx_pwr_lvl.read_bredr_tx_pwr_lvl_cb); + } else { + APPL_TRACE_ERROR("%s(), the callback function can't be NULL.", __func__); + } +} + +void bta_dm_write_bredr_tx_pwr_lvl(tBTA_DM_MSG *p_data) +{ + if (p_data->write_bredr_tx_pwr_lvl.write_bredr_tx_pwr_lvl_cb != NULL) { + BTM_WriteBredrTxPwrLvl(p_data->write_bredr_tx_pwr_lvl.type, + p_data->write_bredr_tx_pwr_lvl.tx_power, + p_data->write_bredr_tx_pwr_lvl.write_bredr_tx_pwr_lvl_cb); + } else { + APPL_TRACE_ERROR("%s(), the callback function can't be NULL.", __func__); + } +} + /******************************************************************************* ** ** Function bta_dm_set_visibility diff --git a/components/bt/host/bluedroid/bta/dm/bta_dm_api.c b/components/bt/host/bluedroid/bta/dm/bta_dm_api.c index aaf0d8864f..4d2e40031d 100644 --- a/components/bt/host/bluedroid/bta/dm/bta_dm_api.c +++ b/components/bt/host/bluedroid/bta/dm/bta_dm_api.c @@ -523,7 +523,65 @@ void BTA_DmReadRSSI(BD_ADDR remote_addr, tBTA_TRANSPORT transport, tBTA_CMPL_CB } } +#if (ESP_BT_CLASSIC_ENABLE_POWER_CTRL_VSC == TRUE) +void BTA_DmReadAclRealRssi(BD_ADDR remote_addr, tBTA_CMPL_CB *cmpl_cb) +{ + tBTA_DM_API_READ_ACL_REAL_RSSI *p_msg; + if ((p_msg = (tBTA_DM_API_READ_ACL_REAL_RSSI *)osi_malloc(sizeof(tBTA_DM_API_READ_ACL_REAL_RSSI))) != NULL) { + p_msg->hdr.event = BTA_DM_API_READ_ACL_REAL_RSSI_EVT; + memcpy(p_msg->remote_addr, remote_addr, sizeof(BD_ADDR)); + p_msg->read_acl_real_rssi_cb = cmpl_cb; + bta_sys_sendmsg(p_msg); + } +} + +void BTA_DmReadNewConnTxPwrLvl(tBTA_CMPL_CB *cmpl_cb) +{ + tBTA_DM_API_READ_NEW_CONN_TX_PWR_LVL *p_msg; + if ((p_msg = (tBTA_DM_API_READ_NEW_CONN_TX_PWR_LVL *)osi_malloc(sizeof(tBTA_DM_API_READ_NEW_CONN_TX_PWR_LVL))) != NULL) { + p_msg->hdr.event = BTA_DM_API_READ_NEW_CONN_TX_PWR_LVL_EVT; + p_msg->read_new_conn_tx_pwr_lvl_cb = cmpl_cb; + bta_sys_sendmsg(p_msg); + } +} + +void BTA_DmWriteNewConnTxPwrLvl(INT8 pwr_lvl_min, INT8 pwr_lvl_max, tBTA_CMPL_CB *cmpl_cb) +{ + tBTA_DM_API_WRITE_NEW_CONN_TX_PWR_LVL *p_msg; + if ((p_msg = (tBTA_DM_API_WRITE_NEW_CONN_TX_PWR_LVL *)osi_malloc(sizeof(tBTA_DM_API_WRITE_NEW_CONN_TX_PWR_LVL))) != NULL) { + p_msg->hdr.event = BTA_DM_API_WRITE_NEW_CONN_TX_PWR_LVL_EVT; + p_msg->pwr_lvl_min = pwr_lvl_min; + p_msg->pwr_lvl_max = pwr_lvl_max; + p_msg->write_new_conn_tx_pwr_lvl_cb = cmpl_cb; + bta_sys_sendmsg(p_msg); + } +} +#endif // #if (ESP_BT_CLASSIC_ENABLE_POWER_CTRL_VSC == TRUE) + #if (CLASSIC_BT_INCLUDED == TRUE) +void BTA_DmReadBredrTxPwrLvl(tBTM_TX_PWR_LVL_TYPE type, tBTA_CMPL_CB *cmpl_cb) +{ + tBTA_DM_API_READ_BREDR_TX_PWR_LVL *p_msg; + if ((p_msg = (tBTA_DM_API_READ_BREDR_TX_PWR_LVL *)osi_malloc(sizeof(tBTA_DM_API_READ_BREDR_TX_PWR_LVL))) != NULL) { + p_msg->hdr.event = BTA_DM_API_READ_BREDR_TX_PWR_LVL_EVT; + p_msg->type = type; + p_msg->read_bredr_tx_pwr_lvl_cb = cmpl_cb; + bta_sys_sendmsg(p_msg); + } +} + +void BTA_DmWriteBredrTxPwrLvl(tBTM_TX_PWR_LVL_TYPE type, INT8 tx_power, tBTA_CMPL_CB *cmpl_cb) +{ + tBTA_DM_API_WRITE_BREDR_TX_PWR_LVL *p_msg; + if ((p_msg = (tBTA_DM_API_WRITE_BREDR_TX_PWR_LVL *)osi_malloc(sizeof(tBTA_DM_API_WRITE_BREDR_TX_PWR_LVL))) != NULL) { + p_msg->hdr.event = BTA_DM_API_WRITE_BREDR_TX_PWR_LVL_EVT; + p_msg->type = type; + p_msg->tx_power = tx_power; + p_msg->write_bredr_tx_pwr_lvl_cb = cmpl_cb; + bta_sys_sendmsg(p_msg); + } +} + /******************************************************************************* ** ** Function BTA_DmSetVisibility diff --git a/components/bt/host/bluedroid/bta/dm/bta_dm_main.c b/components/bt/host/bluedroid/bta/dm/bta_dm_main.c index 6d86d41be3..4829a2b404 100644 --- a/components/bt/host/bluedroid/bta/dm/bta_dm_main.c +++ b/components/bt/host/bluedroid/bta/dm/bta_dm_main.c @@ -177,6 +177,15 @@ const tBTA_DM_ACTION bta_dm_action[BTA_DM_MAX_EVT] = { bta_dm_update_white_list, /* BTA_DM_API_UPDATE_WHITE_LIST_EVT */ bta_dm_clear_white_list, /* BTA_DM_API_CLEAR_WHITE_LIST_EVT */ bta_dm_read_rssi, /* BTA_DM_API_READ_RSSI_EVT */ +#if (ESP_BT_CLASSIC_ENABLE_POWER_CTRL_VSC == TRUE) + bta_dm_read_acl_real_rssi, /* BTA_DM_API_READ_ACL_REAL_RSSI_EVT */ + bta_dm_read_new_conn_tx_pwr_lvl, /* BTA_DM_API_READ_NEW_CONN_TX_PWR_LVL_EVT */ + bta_dm_write_new_conn_tx_pwr_lvl, /* BTA_DM_API_WRITE_NEW_CONN_TX_PWR_LVL_EVT */ +#endif // #if (ESP_BT_CLASSIC_ENABLE_POWER_CTRL_VSC == TRUE) +#if (CLASSIC_BT_INCLUDED == TRUE) + bta_dm_read_bredr_tx_pwr_lvl, /* BTA_DM_API_READ_BREDR_TX_PWR_LVL_EVT */ + bta_dm_write_bredr_tx_pwr_lvl, /* BTA_DM_API_WRITE_BREDR_TX_PWR_LVL_EVT */ +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) #if BLE_INCLUDED == TRUE #if ((BLE_42_SCAN_EN == TRUE) || (BLE_50_EXTEND_SCAN_EN == TRUE)) bta_dm_ble_update_duplicate_exceptional_list,/* BTA_DM_API_UPDATE_DUPLICATE_EXCEPTIONAL_LIST_EVT */ diff --git a/components/bt/host/bluedroid/bta/dm/include/bta_dm_int.h b/components/bt/host/bluedroid/bta/dm/include/bta_dm_int.h index f4498b54da..4b634823f1 100644 --- a/components/bt/host/bluedroid/bta/dm/include/bta_dm_int.h +++ b/components/bt/host/bluedroid/bta/dm/include/bta_dm_int.h @@ -170,6 +170,15 @@ enum { BTA_DM_API_UPDATE_WHITE_LIST_EVT, BTA_DM_API_CLEAR_WHITE_LIST_EVT, BTA_DM_API_READ_RSSI_EVT, +#if (ESP_BT_CLASSIC_ENABLE_POWER_CTRL_VSC == TRUE) + BTA_DM_API_READ_ACL_REAL_RSSI_EVT, + BTA_DM_API_READ_NEW_CONN_TX_PWR_LVL_EVT, + BTA_DM_API_WRITE_NEW_CONN_TX_PWR_LVL_EVT, +#endif // #if (ESP_BT_CLASSIC_ENABLE_POWER_CTRL_VSC == TRUE) +#if (CLASSIC_BT_INCLUDED == TRUE) + BTA_DM_API_READ_BREDR_TX_PWR_LVL_EVT, + BTA_DM_API_WRITE_BREDR_TX_PWR_LVL_EVT, +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) #if BLE_INCLUDED == TRUE #if ((BLE_42_SCAN_EN == TRUE) || (BLE_50_EXTEND_SCAN_EN == TRUE)) BTA_DM_API_UPDATE_DUPLICATE_EXCEPTIONAL_LIST_EVT, @@ -456,6 +465,41 @@ typedef struct { tBTA_CMPL_CB *read_rssi_cb; }tBTA_DM_API_READ_RSSI; +#if (ESP_BT_CLASSIC_ENABLE_POWER_CTRL_VSC == TRUE) +typedef struct { + BT_HDR hdr; + BD_ADDR remote_addr; + tBTA_CMPL_CB *read_acl_real_rssi_cb; +} tBTA_DM_API_READ_ACL_REAL_RSSI; + +typedef struct { + BT_HDR hdr; + tBTA_CMPL_CB *read_new_conn_tx_pwr_lvl_cb; +} tBTA_DM_API_READ_NEW_CONN_TX_PWR_LVL; + +typedef struct { + BT_HDR hdr; + INT8 pwr_lvl_min; + INT8 pwr_lvl_max; + tBTA_CMPL_CB *write_new_conn_tx_pwr_lvl_cb; +} tBTA_DM_API_WRITE_NEW_CONN_TX_PWR_LVL; +#endif // #if (ESP_BT_CLASSIC_ENABLE_POWER_CTRL_VSC == TRUE) + +#if (CLASSIC_BT_INCLUDED == TRUE) +typedef struct { + BT_HDR hdr; + tBTM_TX_PWR_LVL_TYPE type; + tBTA_CMPL_CB *read_bredr_tx_pwr_lvl_cb; +} tBTA_DM_API_READ_BREDR_TX_PWR_LVL; + +typedef struct { + BT_HDR hdr; + tBTM_TX_PWR_LVL_TYPE type; + INT8 tx_power; + tBTA_CMPL_CB *write_bredr_tx_pwr_lvl_cb; +} tBTA_DM_API_WRITE_BREDR_TX_PWR_LVL; +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) + typedef struct { BT_HDR hdr; BD_ADDR remote_addr; @@ -1629,6 +1673,15 @@ typedef union { tBTA_DM_API_UPDATE_WHITE_LIST white_list; #endif ///BLE_INCLUDED == TRUE tBTA_DM_API_READ_RSSI rssi; +#if (ESP_BT_CLASSIC_ENABLE_POWER_CTRL_VSC == TRUE) + tBTA_DM_API_READ_ACL_REAL_RSSI acl_real_rssi; + tBTA_DM_API_READ_NEW_CONN_TX_PWR_LVL read_new_conn_tx_pwr_lvl; + tBTA_DM_API_WRITE_NEW_CONN_TX_PWR_LVL write_new_conn_tx_pwr_lvl; +#endif // #if (ESP_BT_CLASSIC_ENABLE_POWER_CTRL_VSC == TRUE) +#if (CLASSIC_BT_INCLUDED == TRUE) + tBTA_DM_API_READ_BREDR_TX_PWR_LVL read_bredr_tx_pwr_lvl; + tBTA_DM_API_WRITE_BREDR_TX_PWR_LVL write_bredr_tx_pwr_lvl; +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) tBTA_DM_API_READ_CH_MAP ch_map; @@ -2212,6 +2265,15 @@ extern void bta_dm_update_white_list(tBTA_DM_MSG *p_data); extern void bta_dm_clear_white_list(tBTA_DM_MSG *p_data); extern void bta_dm_ble_read_adv_tx_power(tBTA_DM_MSG *p_data); extern void bta_dm_read_rssi(tBTA_DM_MSG *p_data); +#if (ESP_BT_CLASSIC_ENABLE_POWER_CTRL_VSC == TRUE) +extern void bta_dm_read_acl_real_rssi(tBTA_DM_MSG *p_data); +extern void bta_dm_read_new_conn_tx_pwr_lvl(tBTA_DM_MSG *p_data); +extern void bta_dm_write_new_conn_tx_pwr_lvl(tBTA_DM_MSG *p_data); +#endif // #if (ESP_BT_CLASSIC_ENABLE_POWER_CTRL_VSC == TRUE) +#if (CLASSIC_BT_INCLUDED == TRUE) +extern void bta_dm_read_bredr_tx_pwr_lvl(tBTA_DM_MSG *p_data); +extern void bta_dm_write_bredr_tx_pwr_lvl(tBTA_DM_MSG *p_data); +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) extern void bta_dm_read_ble_channel_map(tBTA_DM_MSG *p_data); #if (CLASSIC_BT_INCLUDED == TRUE) extern void bta_dm_set_visibility (tBTA_DM_MSG *p_data); diff --git a/components/bt/host/bluedroid/bta/include/bta/bta_api.h b/components/bt/host/bluedroid/bta/include/bta/bta_api.h index 116bdc9557..10e0f58687 100644 --- a/components/bt/host/bluedroid/bta/include/bta/bta_api.h +++ b/components/bt/host/bluedroid/bta/include/bta/bta_api.h @@ -2019,6 +2019,15 @@ extern void BTA_DmBleReadAdvTxPower(tBTA_CMPL_CB *cmpl_cb); #endif ///BLE_INCLUDED == TRUE extern void BTA_DmReadRSSI(BD_ADDR remote_addr, tBTA_TRANSPORT transport, tBTA_CMPL_CB *cmpl_cb); +#if (ESP_BT_CLASSIC_ENABLE_POWER_CTRL_VSC == TRUE) +extern void BTA_DmReadAclRealRssi(BD_ADDR remote_addr, tBTA_CMPL_CB *cmpl_cb); +extern void BTA_DmReadNewConnTxPwrLvl(tBTA_CMPL_CB *cmpl_cb); +extern void BTA_DmWriteNewConnTxPwrLvl(INT8 pwr_lvl_min, INT8 pwr_lvl_max, tBTA_CMPL_CB *cmpl_cb); +#endif // #if (ESP_BT_CLASSIC_ENABLE_POWER_CTRL_VSC == TRUE) +#if (CLASSIC_BT_INCLUDED == TRUE) +extern void BTA_DmReadBredrTxPwrLvl(tBTM_TX_PWR_LVL_TYPE type, tBTA_CMPL_CB *cmpl_cb); +extern void BTA_DmWriteBredrTxPwrLvl(tBTM_TX_PWR_LVL_TYPE type, INT8 tx_power, tBTA_CMPL_CB *cmpl_cb); +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) extern void BTA_DmBleReadChannelMap(BD_ADDR remote_device, tBTA_CMPL_CB *p_callback); /******************************************************************************* diff --git a/components/bt/host/bluedroid/btc/profile/std/gap/btc_gap_bt.c b/components/bt/host/bluedroid/btc/profile/std/gap/btc_gap_bt.c index 099bea519f..9d22b7e418 100644 --- a/components/bt/host/bluedroid/btc/profile/std/gap/btc_gap_bt.c +++ b/components/bt/host/bluedroid/btc/profile/std/gap/btc_gap_bt.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -652,6 +652,143 @@ static void btc_gap_bt_read_rssi_delta(btc_gap_bt_args_t *arg) BTA_DmReadRSSI(arg->read_rssi_delta.bda.address, BTA_TRANSPORT_BR_EDR, btc_gap_bt_read_rssi_delta_cmpl_callback); } +#if (ESP_BT_CLASSIC_ENABLE_POWER_CTRL_VSC == TRUE) +static void btc_gap_bt_read_acl_real_rssi_cmpl_callback(void *p_data) +{ + tBTM_ACL_REAL_RSSI_RESULTS *result = (tBTM_ACL_REAL_RSSI_RESULTS *)p_data; + esp_bt_gap_cb_param_t param; + bt_status_t ret; + btc_msg_t msg; + msg.sig = BTC_SIG_API_CB; + msg.pid = BTC_PID_GAP_BT; + msg.act = BTC_GAP_BT_READ_ACL_REAL_RSSI_EVT; + memcpy(param.read_acl_real_rssi.bda, result->rem_bda, sizeof(BD_ADDR)); + param.read_acl_real_rssi.stat = btc_btm_status_to_esp_status(result->status); + param.read_acl_real_rssi.rssi = result->rssi; + + ret = btc_transfer_context(&msg, ¶m, + sizeof(esp_bt_gap_cb_param_t), NULL, NULL); + + if (ret != BT_STATUS_SUCCESS) { + BTC_TRACE_ERROR("%s btc_transfer_context failed\n", __func__); + } +} + +static void btc_gap_bt_read_acl_real_rssi(btc_gap_bt_args_t *arg) +{ + BTA_DmReadAclRealRssi(arg->read_acl_real_rssi.bda.address, btc_gap_bt_read_acl_real_rssi_cmpl_callback); +} + +static void btc_gap_bt_read_new_conn_tx_pwr_lvl_cmpl_callback(void *p_data) +{ + tBTM_READ_NEW_CONN_TX_PWR_LVL_RESULTS *result = (tBTM_READ_NEW_CONN_TX_PWR_LVL_RESULTS *)p_data; + esp_bt_gap_cb_param_t param; + bt_status_t ret; + btc_msg_t msg; + + msg.sig = BTC_SIG_API_CB; + msg.pid = BTC_PID_GAP_BT; + msg.act = BTC_GAP_BT_READ_NEW_CONN_TX_PWR_LVL_EVT; + param.read_new_conn_tx_pwr_lvl.stat = btc_btm_status_to_esp_status(result->status); + param.read_new_conn_tx_pwr_lvl.pwr_lvl_min = result->pwr_lvl_min; + param.read_new_conn_tx_pwr_lvl.pwr_lvl_max = result->pwr_lvl_max; + + ret = btc_transfer_context(&msg, ¶m, + sizeof(esp_bt_gap_cb_param_t), NULL, NULL); + + if (ret != BT_STATUS_SUCCESS) { + BTC_TRACE_ERROR("%s btc_transfer_context failed\n", __func__); + } +} + +static void btc_gap_bt_write_new_conn_tx_pwr_lvl_cmpl_callback(void *p_data) +{ + tBTM_WRITE_NEW_CONN_TX_PWR_LVL_RESULTS *result = (tBTM_WRITE_NEW_CONN_TX_PWR_LVL_RESULTS *)p_data; + esp_bt_gap_cb_param_t param; + bt_status_t ret; + btc_msg_t msg; + + msg.sig = BTC_SIG_API_CB; + msg.pid = BTC_PID_GAP_BT; + msg.act = BTC_GAP_BT_WRITE_NEW_CONN_TX_PWR_LVL_EVT; + param.write_new_conn_tx_pwr_lvl.stat = btc_btm_status_to_esp_status(result->status); + + ret = btc_transfer_context(&msg, ¶m, + sizeof(esp_bt_gap_cb_param_t), NULL, NULL); + + if (ret != BT_STATUS_SUCCESS) { + BTC_TRACE_ERROR("%s btc_transfer_context failed\n", __func__); + } +} + +static void btc_gap_bt_read_new_conn_tx_pwr_lvl(void) +{ + BTA_DmReadNewConnTxPwrLvl(btc_gap_bt_read_new_conn_tx_pwr_lvl_cmpl_callback); +} + +static void btc_gap_bt_write_new_conn_tx_pwr_lvl(btc_gap_bt_args_t *arg) +{ + BTA_DmWriteNewConnTxPwrLvl(arg->write_new_conn_tx_pwr_lvl.pwr_lvl_min, + arg->write_new_conn_tx_pwr_lvl.pwr_lvl_max, + btc_gap_bt_write_new_conn_tx_pwr_lvl_cmpl_callback); +} +#endif // #if (ESP_BT_CLASSIC_ENABLE_POWER_CTRL_VSC == TRUE) + +static void btc_gap_bt_read_tx_pwr_lvl_cmpl_callback(void *p_data) +{ + tBTM_READ_TX_PWR_LVL_RESULTS *result = (tBTM_READ_TX_PWR_LVL_RESULTS *)p_data; + esp_bt_gap_cb_param_t param; + bt_status_t ret; + btc_msg_t msg; + + msg.sig = BTC_SIG_API_CB; + msg.pid = BTC_PID_GAP_BT; + msg.act = BTC_GAP_BT_READ_TX_PWR_LVL_EVT; + param.read_tx_pwr_lvl.stat = btc_btm_status_to_esp_status(result->status); + param.read_tx_pwr_lvl.type = result->type; + param.read_tx_pwr_lvl.tx_power = result->tx_power; + + ret = btc_transfer_context(&msg, ¶m, + sizeof(esp_bt_gap_cb_param_t), NULL, NULL); + + if (ret != BT_STATUS_SUCCESS) { + BTC_TRACE_ERROR("%s btc_transfer_context failed\n", __func__); + } +} + +static void btc_gap_bt_write_tx_pwr_lvl_cmpl_callback(void *p_data) +{ + tBTM_WRITE_TX_PWR_LVL_RESULTS *result = (tBTM_WRITE_TX_PWR_LVL_RESULTS *)p_data; + esp_bt_gap_cb_param_t param; + bt_status_t ret; + btc_msg_t msg; + + msg.sig = BTC_SIG_API_CB; + msg.pid = BTC_PID_GAP_BT; + msg.act = BTC_GAP_BT_WRITE_TX_PWR_LVL_EVT; + param.write_tx_pwr_lvl.stat = btc_btm_status_to_esp_status(result->status); + param.write_tx_pwr_lvl.type = result->type; + + ret = btc_transfer_context(&msg, ¶m, + sizeof(esp_bt_gap_cb_param_t), NULL, NULL); + + if (ret != BT_STATUS_SUCCESS) { + BTC_TRACE_ERROR("%s btc_transfer_context failed\n", __func__); + } +} + +static void btc_gap_bt_read_tx_pwr_lvl(btc_gap_bt_args_t *arg) +{ + BTA_DmReadBredrTxPwrLvl((tBTM_TX_PWR_LVL_TYPE)arg->read_tx_pwr_lvl.type, btc_gap_bt_read_tx_pwr_lvl_cmpl_callback); +} + +static void btc_gap_bt_write_tx_pwr_lvl(btc_gap_bt_args_t *arg) +{ + BTA_DmWriteBredrTxPwrLvl((tBTM_TX_PWR_LVL_TYPE)arg->write_tx_pwr_lvl.type, + arg->write_tx_pwr_lvl.tx_power, + btc_gap_bt_write_tx_pwr_lvl_cmpl_callback); +} + static esp_err_t btc_gap_bt_remove_bond_device(btc_gap_bt_args_t *arg) { BD_ADDR bd_addr; @@ -933,6 +1070,13 @@ void btc_gap_bt_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src) case BTC_GAP_BT_ACT_GET_REMOTE_SERVICE_RECORD: case BTC_GAP_BT_ACT_SET_COD: case BTC_GAP_BT_ACT_READ_RSSI_DELTA: +#if (ESP_BT_CLASSIC_ENABLE_POWER_CTRL_VSC == TRUE) + case BTC_GAP_BT_ACT_READ_ACL_REAL_RSSI: + case BTC_GAP_BT_ACT_READ_NEW_CONN_TX_PWR_LVL: + case BTC_GAP_BT_ACT_WRITE_NEW_CONN_TX_PWR_LVL: +#endif // #if (ESP_BT_CLASSIC_ENABLE_POWER_CTRL_VSC == TRUE) + case BTC_GAP_BT_ACT_READ_TX_PWR_LVL: + case BTC_GAP_BT_ACT_WRITE_TX_PWR_LVL: case BTC_GAP_BT_ACT_REMOVE_BOND_DEVICE: case BTC_GAP_BT_ACT_PIN_REPLY: case BTC_GAP_BT_ACT_SET_PIN_TYPE: @@ -1016,6 +1160,13 @@ void btc_gap_bt_arg_deep_free(btc_msg_t *msg) case BTC_GAP_BT_ACT_GET_REMOTE_SERVICE_RECORD: case BTC_GAP_BT_ACT_SET_COD: case BTC_GAP_BT_ACT_READ_RSSI_DELTA: +#if (ESP_BT_CLASSIC_ENABLE_POWER_CTRL_VSC == TRUE) + case BTC_GAP_BT_ACT_READ_ACL_REAL_RSSI: + case BTC_GAP_BT_ACT_READ_NEW_CONN_TX_PWR_LVL: + case BTC_GAP_BT_ACT_WRITE_NEW_CONN_TX_PWR_LVL: +#endif // #if (ESP_BT_CLASSIC_ENABLE_POWER_CTRL_VSC == TRUE) + case BTC_GAP_BT_ACT_READ_TX_PWR_LVL: + case BTC_GAP_BT_ACT_WRITE_TX_PWR_LVL: case BTC_GAP_BT_ACT_REMOVE_BOND_DEVICE: case BTC_GAP_BT_ACT_PIN_REPLY: case BTC_GAP_BT_ACT_SET_PIN_TYPE: @@ -1095,6 +1246,28 @@ void btc_gap_bt_call_handler(btc_msg_t *msg) btc_gap_bt_read_rssi_delta(arg); break; } +#if (ESP_BT_CLASSIC_ENABLE_POWER_CTRL_VSC == TRUE) + case BTC_GAP_BT_ACT_READ_ACL_REAL_RSSI: { + btc_gap_bt_read_acl_real_rssi(arg); + break; + } + case BTC_GAP_BT_ACT_READ_NEW_CONN_TX_PWR_LVL: { + btc_gap_bt_read_new_conn_tx_pwr_lvl(); + break; + } + case BTC_GAP_BT_ACT_WRITE_NEW_CONN_TX_PWR_LVL: { + btc_gap_bt_write_new_conn_tx_pwr_lvl(arg); + break; + } +#endif // #if (ESP_BT_CLASSIC_ENABLE_POWER_CTRL_VSC == TRUE) + case BTC_GAP_BT_ACT_READ_TX_PWR_LVL: { + btc_gap_bt_read_tx_pwr_lvl(arg); + break; + } + case BTC_GAP_BT_ACT_WRITE_TX_PWR_LVL: { + btc_gap_bt_write_tx_pwr_lvl(arg); + break; + } case BTC_GAP_BT_ACT_REMOVE_BOND_DEVICE:{ btc_gap_bt_remove_bond_device(arg); break; @@ -1197,6 +1370,11 @@ void btc_gap_bt_cb_deep_free(btc_msg_t *msg) osi_free(((tBTA_DM_SEARCH_PARAM *) (msg->arg)) ->p_data); break; case BTC_GAP_BT_READ_RSSI_DELTA_EVT: + case BTC_GAP_BT_READ_ACL_REAL_RSSI_EVT: + case BTC_GAP_BT_READ_NEW_CONN_TX_PWR_LVL_EVT: + case BTC_GAP_BT_WRITE_NEW_CONN_TX_PWR_LVL_EVT: + case BTC_GAP_BT_READ_TX_PWR_LVL_EVT: + case BTC_GAP_BT_WRITE_TX_PWR_LVL_EVT: case BTC_GAP_BT_CONFIG_EIR_DATA_EVT: case BTC_GAP_BT_AUTH_CMPL_EVT: case BTC_GAP_BT_ENC_CHG_EVT: @@ -1244,6 +1422,26 @@ void btc_gap_bt_cb_handler(btc_msg_t *msg) btc_gap_bt_cb_to_app(ESP_BT_GAP_READ_RSSI_DELTA_EVT, (esp_bt_gap_cb_param_t *)msg->arg); break; } + case BTC_GAP_BT_READ_ACL_REAL_RSSI_EVT:{ + btc_gap_bt_cb_to_app(ESP_BT_GAP_READ_ACL_REAL_RSSI_EVT, (esp_bt_gap_cb_param_t *)msg->arg); + break; + } + case BTC_GAP_BT_READ_NEW_CONN_TX_PWR_LVL_EVT:{ + btc_gap_bt_cb_to_app(ESP_BT_GAP_READ_NEW_CONN_TX_PWR_RNG_EVT, (esp_bt_gap_cb_param_t *)msg->arg); + break; + } + case BTC_GAP_BT_WRITE_NEW_CONN_TX_PWR_LVL_EVT:{ + btc_gap_bt_cb_to_app(ESP_BT_GAP_WRITE_NEW_CONN_TX_PWR_RNG_EVT, (esp_bt_gap_cb_param_t *)msg->arg); + break; + } + case BTC_GAP_BT_READ_TX_PWR_LVL_EVT:{ + btc_gap_bt_cb_to_app(ESP_BT_GAP_READ_TX_PWR_LVL_EVT, (esp_bt_gap_cb_param_t *)msg->arg); + break; + } + case BTC_GAP_BT_WRITE_TX_PWR_LVL_EVT:{ + btc_gap_bt_cb_to_app(ESP_BT_GAP_WRITE_TX_PWR_LVL_EVT, (esp_bt_gap_cb_param_t *)msg->arg); + break; + } case BTC_GAP_BT_CONFIG_EIR_DATA_EVT: { btc_gap_bt_cb_to_app(ESP_BT_GAP_CONFIG_EIR_DATA_EVT, (esp_bt_gap_cb_param_t *)msg->arg); break; diff --git a/components/bt/host/bluedroid/btc/profile/std/include/btc_gap_bt.h b/components/bt/host/bluedroid/btc/profile/std/include/btc_gap_bt.h index 846e28f07a..b8476d1e12 100644 --- a/components/bt/host/bluedroid/btc/profile/std/include/btc_gap_bt.h +++ b/components/bt/host/bluedroid/btc/profile/std/include/btc_gap_bt.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -27,6 +27,11 @@ typedef enum { BTC_GAP_BT_KEY_NOTIF_EVT, BTC_GAP_BT_KEY_REQ_EVT, BTC_GAP_BT_READ_RSSI_DELTA_EVT, + BTC_GAP_BT_READ_ACL_REAL_RSSI_EVT, + BTC_GAP_BT_READ_NEW_CONN_TX_PWR_LVL_EVT, + BTC_GAP_BT_WRITE_NEW_CONN_TX_PWR_LVL_EVT, + BTC_GAP_BT_READ_TX_PWR_LVL_EVT, + BTC_GAP_BT_WRITE_TX_PWR_LVL_EVT, BTC_GAP_BT_CONFIG_EIR_DATA_EVT, BTC_GAP_BT_SET_AFH_CHANNELS_EVT, BTC_GAP_BT_READ_REMOTE_NAME_EVT, @@ -50,6 +55,13 @@ typedef enum { BTC_GAP_BT_ACT_GET_REMOTE_SERVICE_RECORD, BTC_GAP_BT_ACT_SET_COD, BTC_GAP_BT_ACT_READ_RSSI_DELTA, +#if (ESP_BT_CLASSIC_ENABLE_POWER_CTRL_VSC == TRUE) + BTC_GAP_BT_ACT_READ_ACL_REAL_RSSI, + BTC_GAP_BT_ACT_READ_NEW_CONN_TX_PWR_LVL, + BTC_GAP_BT_ACT_WRITE_NEW_CONN_TX_PWR_LVL, +#endif // (ESP_BT_CLASSIC_ENABLE_POWER_CTRL_VSC == TRUE) + BTC_GAP_BT_ACT_READ_TX_PWR_LVL, + BTC_GAP_BT_ACT_WRITE_TX_PWR_LVL, BTC_GAP_BT_ACT_REMOVE_BOND_DEVICE, BTC_GAP_BT_ACT_SET_PIN_TYPE, BTC_GAP_BT_ACT_PIN_REPLY, @@ -105,6 +117,30 @@ typedef union { bt_bdaddr_t bda; } read_rssi_delta; +#if (ESP_BT_CLASSIC_ENABLE_POWER_CTRL_VSC == TRUE) + //BTC_GAP_BT_ACT_READ_ACL_REAL_RSSI, + struct bt_read_acl_real_rssi_args { + bt_bdaddr_t bda; + } read_acl_real_rssi; + + // BTC_GAP_BT_ACT_WRITE_NEW_CONN_TX_PWR_LVL + struct bt_write_new_conn_tx_pwr_lvl_args { + int8_t pwr_lvl_min; + int8_t pwr_lvl_max; + } write_new_conn_tx_pwr_lvl; +#endif // #if (ESP_BT_CLASSIC_ENABLE_POWER_CTRL_VSC == TRUE) + + // BTC_GAP_BT_ACT_READ_TX_PWR_LVL + struct bt_read_tx_pwr_lvl_args { + esp_bt_gap_tx_pwr_lvl_type_t type; + } read_tx_pwr_lvl; + + // BTC_GAP_BT_ACT_WRITE_TX_PWR_LVL + struct bt_write_tx_pwr_lvl_args { + esp_bt_gap_tx_pwr_lvl_type_t type; + int8_t tx_power; + } write_tx_pwr_lvl; + // BTC_GAP_BT_ACT_REMOVE_BOND_DEVICE struct rm_bond_device_args { bt_bdaddr_t bda; diff --git a/components/bt/host/bluedroid/common/include/common/bluedroid_user_config.h b/components/bt/host/bluedroid/common/include/common/bluedroid_user_config.h index a64805544a..640229d6a4 100644 --- a/components/bt/host/bluedroid/common/include/common/bluedroid_user_config.h +++ b/components/bt/host/bluedroid/common/include/common/bluedroid_user_config.h @@ -125,6 +125,13 @@ #define UC_BT_ENC_KEY_SIZE_CTRL_MODE 0 #endif +//Enable Classic Bluetooth power control vsc +#ifdef CONFIG_BT_CLASSIC_ENABLE_POWER_CTRL_VSC +#define UC_BT_CLASSIC_ENABLE_POWER_CTRL_VSC CONFIG_BT_CLASSIC_ENABLE_POWER_CTRL_VSC +#else +#define UC_BT_CLASSIC_ENABLE_POWER_CTRL_VSC FALSE +#endif + //BLE #ifdef CONFIG_BT_BLE_ENABLED #define UC_BT_BLE_ENABLED CONFIG_BT_BLE_ENABLED diff --git a/components/bt/host/bluedroid/common/include/common/bt_target.h b/components/bt/host/bluedroid/common/include/common/bt_target.h index 8bf3e829f0..b0b98df646 100644 --- a/components/bt/host/bluedroid/common/include/common/bt_target.h +++ b/components/bt/host/bluedroid/common/include/common/bt_target.h @@ -78,6 +78,8 @@ #define ENC_KEY_SIZE_CTRL_MODE_VSC 2 #define ENC_KEY_SIZE_CTRL_MODE UC_BT_ENC_KEY_SIZE_CTRL_MODE +#define ESP_BT_CLASSIC_ENABLE_POWER_CTRL_VSC UC_BT_CLASSIC_ENABLE_POWER_CTRL_VSC + #if (UC_BT_A2DP_ENABLED == TRUE) #define BTA_AR_INCLUDED TRUE #define BTA_AV_INCLUDED TRUE diff --git a/components/bt/host/bluedroid/stack/btm/btm_acl.c b/components/bt/host/bluedroid/stack/btm/btm_acl.c index a5aed0a91b..9949c5585e 100644 --- a/components/bt/host/bluedroid/stack/btm/btm_acl.c +++ b/components/bt/host/bluedroid/stack/btm/btm_acl.c @@ -56,6 +56,97 @@ static void btm_process_remote_ext_features (tACL_CONN *p_acl_cb, UINT8 num_read #define BTM_DEV_REPLY_TIMEOUT 3 /* 3 second timeout waiting for responses */ +#if (ESP_BT_CLASSIC_ENABLE_POWER_CTRL_VSC == TRUE) +static void btm_read_acl_real_rssi_vsc_cmpl_cb(tBTM_VSC_CMPL *p1) +{ + tBTM_CMPL_CB *p_cb = btm_cb.devcb.p_acl_real_rssi_cmpl_cb; + tBTM_ACL_REAL_RSSI_RESULTS results; + UINT16 handle = 0; + tACL_CONN *p_acl_cb = NULL; + + btu_stop_timer(&btm_cb.devcb.acl_real_rssi_timer); + btm_cb.devcb.p_acl_real_rssi_cmpl_cb = NULL; + + memset(&results, 0, sizeof(results)); + results.status = BTM_ERR_PROCESSING; + results.hci_status = HCI_ERR_UNSPECIFIED; + + if (p1 == NULL || p1->p_param_buf == NULL || p1->param_len < 1) { + goto out; + } + + UINT8 *p = p1->p_param_buf; + STREAM_TO_UINT8(results.hci_status, p); + if (results.hci_status != HCI_SUCCESS) { + results.status = BTM_ERR_PROCESSING; + goto out; + } + + // Expected payload (after status): [handle:2][rssi:1] + if (p1->param_len < 1 + 3) { + results.status = BTM_ERR_PROCESSING; + goto out; + } + + STREAM_TO_UINT16(handle, p); + STREAM_TO_UINT8(results.rssi, p); + results.status = BTM_SUCCESS; + + p_acl_cb = btm_handle_to_acl(handle); + if (p_acl_cb) { + memcpy(results.rem_bda, p_acl_cb->remote_addr, BD_ADDR_LEN); + } + +out: + if (p_cb) { + (*p_cb)(&results); + } +} + +tBTM_STATUS BTM_ReadAclRealRSSI(BD_ADDR remote_bda, tBTM_CMPL_CB *p_cb) +{ + tACL_CONN *p; + tBTM_ACL_REAL_RSSI_RESULTS result; + + memset(&result, 0, sizeof(result)); + + /* If someone already waiting on the result, do not allow another */ + if (btm_cb.devcb.p_acl_real_rssi_cmpl_cb) { + result.status = BTM_BUSY; + (*p_cb)(&result); + return (BTM_BUSY); + } + + p = btm_bda_to_acl(remote_bda, BT_TRANSPORT_BR_EDR); + if (p != (tACL_CONN *)NULL) { + btu_start_timer(&btm_cb.devcb.acl_real_rssi_timer, BTU_TTYPE_BTM_ACL, BTM_DEV_REPLY_TIMEOUT); + btm_cb.devcb.p_acl_real_rssi_cmpl_cb = p_cb; + + UINT8 param[2]; + UINT8 *pp = param; + UINT16_TO_STREAM(pp, p->hci_handle); + + tBTM_STATUS st = BTM_VendorSpecificCommand(HCI_VENDOR_BT_RD_ACL_REAL_RSSI, + sizeof(param), + param, + btm_read_acl_real_rssi_vsc_cmpl_cb); + if (st != BTM_CMD_STARTED) { + btm_cb.devcb.p_acl_real_rssi_cmpl_cb = NULL; + btu_stop_timer(&btm_cb.devcb.acl_real_rssi_timer); + result.status = BTM_NO_RESOURCES; + (*p_cb)(&result); + return (BTM_NO_RESOURCES); + } + return (BTM_CMD_STARTED); + } + + /* If here, no BD Addr found */ + result.status = BTM_UNKNOWN_ADDR; + (*p_cb)(&result); + return (BTM_UNKNOWN_ADDR); +} +#endif // #if (ESP_BT_CLASSIC_ENABLE_POWER_CTRL_VSC == TRUE) + /******************************************************************************* ** ** Function btm_acl_init diff --git a/components/bt/host/bluedroid/stack/btm/btm_bredr_pwr_ctrl.c b/components/bt/host/bluedroid/stack/btm/btm_bredr_pwr_ctrl.c new file mode 100644 index 0000000000..77ebbb1e6a --- /dev/null +++ b/components/bt/host/bluedroid/stack/btm/btm_bredr_pwr_ctrl.c @@ -0,0 +1,454 @@ +/* + * SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/****************************************************************************** + * + * This file contains functions for BR/EDR power control. + * + ******************************************************************************/ + +#include + +#include "stack/bt_types.h" +#include "common/bt_target.h" +#include "stack/btu.h" +#include "stack/btm_api.h" +#include "btm_int.h" +#include "stack/hcidefs.h" + +#if (CLASSIC_BT_INCLUDED == TRUE) + +#define BTM_BREDR_PWR_CTRL_REPLY_TIMEOUT 3 /* 3 second timeout waiting for responses */ + +#if (ESP_BT_CLASSIC_ENABLE_POWER_CTRL_VSC == TRUE) +static void btm_read_new_conn_tx_pwr_lvl_vsc_cmpl_cb(tBTM_VSC_CMPL *p1) +{ + tBTM_CMPL_CB *p_cb = btm_cb.devcb.p_read_new_conn_tx_pwr_lvl_cmpl_cb; + tBTM_READ_NEW_CONN_TX_PWR_LVL_RESULTS result; + + btu_stop_timer(&btm_cb.devcb.read_new_conn_tx_pwr_lvl_timer); + btm_cb.devcb.p_read_new_conn_tx_pwr_lvl_cmpl_cb = NULL; + + memset(&result, 0, sizeof(result)); + result.status = BTM_ERR_PROCESSING; + result.hci_status = HCI_ERR_UNSPECIFIED; + + if (p1 == NULL || p1->p_param_buf == NULL || p1->param_len < 1) { + goto out; + } + + UINT8 *p = p1->p_param_buf; + STREAM_TO_UINT8(result.hci_status, p); + if (result.hci_status != HCI_SUCCESS) { + goto out; + } + + if (p1->param_len < 1 + 2) { + goto out; + } + + STREAM_TO_UINT8(result.pwr_lvl_min, p); + STREAM_TO_UINT8(result.pwr_lvl_max, p); + result.status = BTM_SUCCESS; + +out: + if (p_cb) { + (*p_cb)(&result); + } +} + +tBTM_STATUS BTM_ReadNewConnTxPwrLvl(tBTM_CMPL_CB *p_cb) +{ + tBTM_STATUS status; + tBTM_READ_NEW_CONN_TX_PWR_LVL_RESULTS result; + + if (btm_cb.devcb.p_read_new_conn_tx_pwr_lvl_cmpl_cb) { + result.status = BTM_BUSY; + (*p_cb)(&result); + return BTM_BUSY; + } + + btu_start_timer(&btm_cb.devcb.read_new_conn_tx_pwr_lvl_timer, + BTU_TTYPE_BTM_BREDR_PWR_CTRL, + BTM_BREDR_PWR_CTRL_REPLY_TIMEOUT); + btm_cb.devcb.p_read_new_conn_tx_pwr_lvl_cmpl_cb = p_cb; + + status = BTM_VendorSpecificCommand(HCI_VENDOR_BT_RD_NEW_CONN_TX_PWR_LVL, + 0, NULL, btm_read_new_conn_tx_pwr_lvl_vsc_cmpl_cb); + if (status != BTM_CMD_STARTED) { + btm_cb.devcb.p_read_new_conn_tx_pwr_lvl_cmpl_cb = NULL; + btu_stop_timer(&btm_cb.devcb.read_new_conn_tx_pwr_lvl_timer); + result.status = status; + (*p_cb)(&result); + return BTM_NO_RESOURCES; + } + + return BTM_CMD_STARTED; +} + +static void btm_write_new_conn_tx_pwr_lvl_vsc_cmpl_cb(tBTM_VSC_CMPL *p1) +{ + tBTM_CMPL_CB *p_cb = btm_cb.devcb.p_write_new_conn_tx_pwr_lvl_cmpl_cb; + tBTM_WRITE_NEW_CONN_TX_PWR_LVL_RESULTS result; + + btu_stop_timer(&btm_cb.devcb.write_new_conn_tx_pwr_lvl_timer); + btm_cb.devcb.p_write_new_conn_tx_pwr_lvl_cmpl_cb = NULL; + + memset(&result, 0, sizeof(result)); + result.status = BTM_ERR_PROCESSING; + result.hci_status = HCI_ERR_UNSPECIFIED; + + if (p1 == NULL || p1->p_param_buf == NULL || p1->param_len < 1) { + goto out; + } + + UINT8 *p = p1->p_param_buf; + STREAM_TO_UINT8(result.hci_status, p); + if (result.hci_status != HCI_SUCCESS) { + goto out; + } + + result.status = BTM_SUCCESS; + +out: + if (p_cb) { + (*p_cb)(&result); + } +} + +tBTM_STATUS BTM_WriteNewConnTxPwrLvl(INT8 pwr_lvl_min, INT8 pwr_lvl_max, tBTM_CMPL_CB *p_cb) +{ + tBTM_STATUS status; + tBTM_WRITE_NEW_CONN_TX_PWR_LVL_RESULTS result; + UINT8 param[2]; + UINT8 *p = param; + + if (btm_cb.devcb.p_write_new_conn_tx_pwr_lvl_cmpl_cb) { + result.status = BTM_BUSY; + (*p_cb)(&result); + return BTM_BUSY; + } + + btu_start_timer(&btm_cb.devcb.write_new_conn_tx_pwr_lvl_timer, + BTU_TTYPE_BTM_BREDR_PWR_CTRL, + BTM_BREDR_PWR_CTRL_REPLY_TIMEOUT); + btm_cb.devcb.p_write_new_conn_tx_pwr_lvl_cmpl_cb = p_cb; + + INT8_TO_STREAM(p, pwr_lvl_min); + INT8_TO_STREAM(p, pwr_lvl_max); + status = BTM_VendorSpecificCommand(HCI_VENDOR_BT_WR_NEW_CONN_TX_PWR_LVL, + sizeof(param), param, btm_write_new_conn_tx_pwr_lvl_vsc_cmpl_cb); + if (status != BTM_CMD_STARTED) { + btm_cb.devcb.p_write_new_conn_tx_pwr_lvl_cmpl_cb = NULL; + btu_stop_timer(&btm_cb.devcb.write_new_conn_tx_pwr_lvl_timer); + result.status = status; + (*p_cb)(&result); + return BTM_NO_RESOURCES; + } + + return BTM_CMD_STARTED; +} + +static void btm_read_tx_pwr_lvl_vsc_cmpl_cb(tBTM_TX_PWR_LVL_TYPE type, tBTM_VSC_CMPL *p1, + TIMER_LIST_ENT *timer, tBTM_CMPL_CB **pp_cb) +{ + tBTM_CMPL_CB *p_cb = *pp_cb; + tBTM_READ_TX_PWR_LVL_RESULTS result; + + btu_stop_timer(timer); + *pp_cb = NULL; + + memset(&result, 0, sizeof(result)); + result.type = type; + result.status = BTM_ERR_PROCESSING; + result.hci_status = HCI_ERR_UNSPECIFIED; + + if (p1 == NULL || p1->p_param_buf == NULL || p1->param_len < 1) { + goto out; + } + + UINT8 *p = p1->p_param_buf; + STREAM_TO_UINT8(result.hci_status, p); + if (result.hci_status != HCI_SUCCESS) { + goto out; + } + + if (p1->param_len < 1 + 1) { + goto out; + } + + STREAM_TO_UINT8(result.tx_power, p); + result.status = BTM_SUCCESS; + +out: + if (p_cb) { + (*p_cb)(&result); + } +} + +static void btm_read_inq_tx_pwr_lvl_vsc_cmpl_cb(tBTM_VSC_CMPL *p1) +{ + btm_read_tx_pwr_lvl_vsc_cmpl_cb(BTM_TX_PWR_LVL_INQ, p1, + &btm_cb.devcb.read_inq_tx_pwr_lvl_timer, + &btm_cb.devcb.p_read_inq_tx_pwr_lvl_cmpl_cb); +} + +static void btm_read_page_tx_pwr_lvl_vsc_cmpl_cb(tBTM_VSC_CMPL *p1) +{ + btm_read_tx_pwr_lvl_vsc_cmpl_cb(BTM_TX_PWR_LVL_PAGE, p1, + &btm_cb.devcb.read_page_tx_pwr_lvl_timer, + &btm_cb.devcb.p_read_page_tx_pwr_lvl_cmpl_cb); +} + +static void btm_read_pscan_tx_pwr_lvl_vsc_cmpl_cb(tBTM_VSC_CMPL *p1) +{ + btm_read_tx_pwr_lvl_vsc_cmpl_cb(BTM_TX_PWR_LVL_PSCAN, p1, + &btm_cb.devcb.read_pscan_tx_pwr_lvl_timer, + &btm_cb.devcb.p_read_pscan_tx_pwr_lvl_cmpl_cb); +} +#endif // #if (ESP_BT_CLASSIC_ENABLE_POWER_CTRL_VSC == TRUE) + +tBTM_STATUS BTM_ReadBredrTxPwrLvl(tBTM_TX_PWR_LVL_TYPE type, tBTM_CMPL_CB *p_cb) +{ +#if (ESP_BT_CLASSIC_ENABLE_POWER_CTRL_VSC == TRUE) + UINT16 opcode; + TIMER_LIST_ENT *timer; + tBTM_CMPL_CB **pp_cb; + tBTM_VSC_CMPL_CB *p_vsc_cb; + + tBTM_STATUS status; + tBTM_READ_TX_PWR_LVL_RESULTS result; +#endif // #if (ESP_BT_CLASSIC_ENABLE_POWER_CTRL_VSC == TRUE) + + switch (type) { + case BTM_TX_PWR_LVL_ISCAN: + // standard HCI + return BTM_ReadInquiryRspTxPower(p_cb); +#if (ESP_BT_CLASSIC_ENABLE_POWER_CTRL_VSC == TRUE) + case BTM_TX_PWR_LVL_INQ: + opcode = HCI_VENDOR_BT_RD_INQ_TX_PWR_LVL; + timer = &btm_cb.devcb.read_inq_tx_pwr_lvl_timer; + pp_cb = &btm_cb.devcb.p_read_inq_tx_pwr_lvl_cmpl_cb; + p_vsc_cb = btm_read_inq_tx_pwr_lvl_vsc_cmpl_cb; + break; + case BTM_TX_PWR_LVL_PAGE: + opcode = HCI_VENDOR_BT_RD_PAGE_TX_PWR_LVL; + timer = &btm_cb.devcb.read_page_tx_pwr_lvl_timer; + pp_cb = &btm_cb.devcb.p_read_page_tx_pwr_lvl_cmpl_cb; + p_vsc_cb = btm_read_page_tx_pwr_lvl_vsc_cmpl_cb; + break; + case BTM_TX_PWR_LVL_PSCAN: + opcode = HCI_VENDOR_BT_RD_PSCAN_TX_PWR_LVL; + timer = &btm_cb.devcb.read_pscan_tx_pwr_lvl_timer; + pp_cb = &btm_cb.devcb.p_read_pscan_tx_pwr_lvl_cmpl_cb; + p_vsc_cb = btm_read_pscan_tx_pwr_lvl_vsc_cmpl_cb; + break; +#endif // #if (ESP_BT_CLASSIC_ENABLE_POWER_CTRL_VSC == TRUE) + default: + BTM_TRACE_ERROR("BTM_ReadBredrTxPwrLvl invalid type: %d", type); + return BTM_ILLEGAL_VALUE; + } + +#if (ESP_BT_CLASSIC_ENABLE_POWER_CTRL_VSC == TRUE) + if (*pp_cb) { + memset(&result, 0, sizeof(result)); + result.type = type; + result.status = BTM_BUSY; + if (p_cb) { + (*p_cb)(&result); + } + return BTM_BUSY; + } + + btu_start_timer(timer, BTU_TTYPE_BTM_BREDR_PWR_CTRL, BTM_BREDR_PWR_CTRL_REPLY_TIMEOUT); + *pp_cb = p_cb; + + status = BTM_VendorSpecificCommand(opcode, 0, NULL, p_vsc_cb); + if (status != BTM_CMD_STARTED) { + *pp_cb = NULL; + btu_stop_timer(timer); + memset(&result, 0, sizeof(result)); + result.type = type; + result.status = status; + if (p_cb) { + (*p_cb)(&result); + } + return BTM_NO_RESOURCES; + } + + return BTM_CMD_STARTED; +#endif // #if (ESP_BT_CLASSIC_ENABLE_POWER_CTRL_VSC == TRUE) +} + +#if (ESP_BT_CLASSIC_ENABLE_POWER_CTRL_VSC == TRUE) +static void btm_write_tx_pwr_lvl_vsc_cmpl_cb(tBTM_TX_PWR_LVL_TYPE type, tBTM_VSC_CMPL *p1, + TIMER_LIST_ENT *timer, tBTM_CMPL_CB **pp_cb) +{ + tBTM_CMPL_CB *p_cb = *pp_cb; + tBTM_WRITE_TX_PWR_LVL_RESULTS result; + + btu_stop_timer(timer); + *pp_cb = NULL; + + memset(&result, 0, sizeof(result)); + result.type = type; + result.status = BTM_ERR_PROCESSING; + result.hci_status = HCI_ERR_UNSPECIFIED; + + if (p1 == NULL || p1->p_param_buf == NULL || p1->param_len < 1) { + goto out; + } + + UINT8 *p = p1->p_param_buf; + STREAM_TO_UINT8(result.hci_status, p); + if (result.hci_status != HCI_SUCCESS) { + goto out; + } + + result.status = BTM_SUCCESS; + +out: + if (p_cb) { + (*p_cb)(&result); + } +} + +static void btm_write_iscan_tx_pwr_lvl_vsc_cmpl_cb(tBTM_VSC_CMPL *p1) +{ + btm_write_tx_pwr_lvl_vsc_cmpl_cb(BTM_TX_PWR_LVL_ISCAN, p1, + &btm_cb.devcb.write_iscan_tx_pwr_lvl_timer, + &btm_cb.devcb.p_write_iscan_tx_pwr_lvl_cmpl_cb); +} + +static void btm_write_page_tx_pwr_lvl_vsc_cmpl_cb(tBTM_VSC_CMPL *p1) +{ + btm_write_tx_pwr_lvl_vsc_cmpl_cb(BTM_TX_PWR_LVL_PAGE, p1, + &btm_cb.devcb.write_page_tx_pwr_lvl_timer, + &btm_cb.devcb.p_write_page_tx_pwr_lvl_cmpl_cb); +} + +static void btm_write_pscan_tx_pwr_lvl_vsc_cmpl_cb(tBTM_VSC_CMPL *p1) +{ + btm_write_tx_pwr_lvl_vsc_cmpl_cb(BTM_TX_PWR_LVL_PSCAN, p1, + &btm_cb.devcb.write_pscan_tx_pwr_lvl_timer, + &btm_cb.devcb.p_write_pscan_tx_pwr_lvl_cmpl_cb); +} +#endif // #if (ESP_BT_CLASSIC_ENABLE_POWER_CTRL_VSC == TRUE) + +tBTM_STATUS BTM_WriteBredrTxPwrLvl(tBTM_TX_PWR_LVL_TYPE type, INT8 tx_power, tBTM_CMPL_CB *p_cb) +{ +#if (ESP_BT_CLASSIC_ENABLE_POWER_CTRL_VSC == TRUE) + UINT16 opcode; + TIMER_LIST_ENT *timer; + tBTM_CMPL_CB **pp_cb; + tBTM_VSC_CMPL_CB *p_vsc_cb; + + tBTM_STATUS status; + tBTM_WRITE_TX_PWR_LVL_RESULTS result; + UINT8 param[1]; + UINT8 *p = param; +#endif // #if (ESP_BT_CLASSIC_ENABLE_POWER_CTRL_VSC == TRUE) + + switch (type) { + case BTM_TX_PWR_LVL_INQ: + // standard HCI + return BTM_WriteInquiryTxPower(tx_power, p_cb); +#if (ESP_BT_CLASSIC_ENABLE_POWER_CTRL_VSC == TRUE) + case BTM_TX_PWR_LVL_ISCAN: + opcode = HCI_VENDOR_BT_WR_ISCAN_TX_PWR_LVL; + timer = &btm_cb.devcb.write_iscan_tx_pwr_lvl_timer; + pp_cb = &btm_cb.devcb.p_write_iscan_tx_pwr_lvl_cmpl_cb; + p_vsc_cb = btm_write_iscan_tx_pwr_lvl_vsc_cmpl_cb; + break; + case BTM_TX_PWR_LVL_PAGE: + opcode = HCI_VENDOR_BT_WR_PAGE_TX_PWR_LVL; + timer = &btm_cb.devcb.write_page_tx_pwr_lvl_timer; + pp_cb = &btm_cb.devcb.p_write_page_tx_pwr_lvl_cmpl_cb; + p_vsc_cb = btm_write_page_tx_pwr_lvl_vsc_cmpl_cb; + break; + case BTM_TX_PWR_LVL_PSCAN: + opcode = HCI_VENDOR_BT_WR_PSCAN_TX_PWR_LVL; + timer = &btm_cb.devcb.write_pscan_tx_pwr_lvl_timer; + pp_cb = &btm_cb.devcb.p_write_pscan_tx_pwr_lvl_cmpl_cb; + p_vsc_cb = btm_write_pscan_tx_pwr_lvl_vsc_cmpl_cb; + break; +#endif // #if (ESP_BT_CLASSIC_ENABLE_POWER_CTRL_VSC == TRUE) + default: + BTM_TRACE_ERROR("BTM_WriteBredrTxPwrLvl invalid type: %d", type); + return BTM_ILLEGAL_VALUE; + } + +#if (ESP_BT_CLASSIC_ENABLE_POWER_CTRL_VSC == TRUE) + if (*pp_cb) { + memset(&result, 0, sizeof(result)); + result.type = type; + result.status = BTM_BUSY; + if (p_cb) { + (*p_cb)(&result); + } + return BTM_BUSY; + } + + btu_start_timer(timer, BTU_TTYPE_BTM_BREDR_PWR_CTRL, BTM_BREDR_PWR_CTRL_REPLY_TIMEOUT); + *pp_cb = p_cb; + + INT8_TO_STREAM(p, tx_power); + status = BTM_VendorSpecificCommand(opcode, sizeof(param), param, p_vsc_cb); + if (status != BTM_CMD_STARTED) { + *pp_cb = NULL; + btu_stop_timer(timer); + memset(&result, 0, sizeof(result)); + result.type = type; + result.status = status; + if (p_cb) { + (*p_cb)(&result); + } + return BTM_NO_RESOURCES; + } + + return BTM_CMD_STARTED; +#endif // #if (ESP_BT_CLASSIC_ENABLE_POWER_CTRL_VSC == TRUE) +} + +/******************************************************************************* +** +** Function btm_bredr_pwr_ctrl_timeout +** +** Description This function processes a BR/EDR power control vsc timeout. +** +** Returns void +** +*******************************************************************************/ +void btm_bredr_pwr_ctrl_timeout(TIMER_LIST_ENT *p_tle) +{ + if (p_tle == &btm_cb.devcb.write_inq_txpwer_timer) { + btm_write_inq_tx_power_complete(NULL); + } else if (p_tle == &btm_cb.devcb.read_iscan_txpwer_timer) { + btm_read_iscan_tx_power_complete(NULL); + +#if (ESP_BT_CLASSIC_ENABLE_POWER_CTRL_VSC == TRUE) + } else if (p_tle == &btm_cb.devcb.read_new_conn_tx_pwr_lvl_timer) { + btm_read_new_conn_tx_pwr_lvl_vsc_cmpl_cb(NULL); + } else if (p_tle == &btm_cb.devcb.write_new_conn_tx_pwr_lvl_timer) { + btm_write_new_conn_tx_pwr_lvl_vsc_cmpl_cb(NULL); + } else if (p_tle == &btm_cb.devcb.read_inq_tx_pwr_lvl_timer) { + btm_read_inq_tx_pwr_lvl_vsc_cmpl_cb(NULL); + } else if (p_tle == &btm_cb.devcb.read_page_tx_pwr_lvl_timer) { + btm_read_page_tx_pwr_lvl_vsc_cmpl_cb(NULL); + } else if (p_tle == &btm_cb.devcb.read_pscan_tx_pwr_lvl_timer) { + btm_read_pscan_tx_pwr_lvl_vsc_cmpl_cb(NULL); + } else if (p_tle == &btm_cb.devcb.write_iscan_tx_pwr_lvl_timer) { + btm_write_iscan_tx_pwr_lvl_vsc_cmpl_cb(NULL); + } else if (p_tle == &btm_cb.devcb.write_page_tx_pwr_lvl_timer) { + btm_write_page_tx_pwr_lvl_vsc_cmpl_cb(NULL); + } else if (p_tle == &btm_cb.devcb.write_pscan_tx_pwr_lvl_timer) { + btm_write_pscan_tx_pwr_lvl_vsc_cmpl_cb(NULL); + +#endif // #if (ESP_BT_CLASSIC_ENABLE_POWER_CTRL_VSC == TRUE) + } +} + +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) diff --git a/components/bt/host/bluedroid/stack/btm/btm_inq.c b/components/bt/host/bluedroid/stack/btm/btm_inq.c index db93304a4e..4a2e7201c7 100644 --- a/components/bt/host/bluedroid/stack/btm/btm_inq.c +++ b/components/bt/host/bluedroid/stack/btm/btm_inq.c @@ -1100,23 +1100,79 @@ tBTM_STATUS BTM_ClearInqDb (BD_ADDR p_bda) *******************************************************************************/ tBTM_STATUS BTM_ReadInquiryRspTxPower (tBTM_CMPL_CB *p_cb) { - if (btm_cb.devcb.p_txpwer_cmpl_cb) { + tBTM_READ_TX_PWR_LVL_RESULTS result; + + if (btm_cb.devcb.p_read_iscan_txpwer_cmpl_cb) { + memset(&result, 0, sizeof(result)); + result.type = BTM_TX_PWR_LVL_ISCAN; + result.status = BTM_BUSY; + if (p_cb) { + (*p_cb)(&result); + } return (BTM_BUSY); } - btu_start_timer (&btm_cb.devcb.txpwer_timer, BTU_TTYPE_BTM_ACL, BTM_INQ_REPLY_TIMEOUT ); - - - btm_cb.devcb.p_txpwer_cmpl_cb = p_cb; + btu_start_timer (&btm_cb.devcb.read_iscan_txpwer_timer, BTU_TTYPE_BTM_BREDR_PWR_CTRL, BTM_INQ_REPLY_TIMEOUT ); + btm_cb.devcb.p_read_iscan_txpwer_cmpl_cb = p_cb; if (!btsnd_hcic_read_inq_tx_power ()) { - btm_cb.devcb.p_txpwer_cmpl_cb = NULL; - btu_stop_timer (&btm_cb.devcb.txpwer_timer); + btm_cb.devcb.p_read_iscan_txpwer_cmpl_cb = NULL; + btu_stop_timer (&btm_cb.devcb.read_iscan_txpwer_timer); + memset(&result, 0, sizeof(result)); + result.type = BTM_TX_PWR_LVL_ISCAN; + result.status = BTM_NO_RESOURCES; + if (p_cb) { + (*p_cb)(&result); + } return (BTM_NO_RESOURCES); } else { return (BTM_CMD_STARTED); } } + +/******************************************************************************* +** +** Function BTM_WriteInquiryTxPower +** +** Description This command writes the inquiry transmit power level used +** to transmit inquiry response packets. +** +** Returns BTM_CMD_STARTED if command issued to controller. +** BTM_NO_RESOURCES if couldn't allocate memory to issue command +** BTM_BUSY if command is already in progress +** +*******************************************************************************/ +tBTM_STATUS BTM_WriteInquiryTxPower(INT8 tx_power, tBTM_CMPL_CB *p_cb) +{ + tBTM_WRITE_TX_PWR_LVL_RESULTS result; + + if (btm_cb.devcb.p_write_inq_txpwer_cmpl_cb) { + memset(&result, 0, sizeof(result)); + result.type = BTM_TX_PWR_LVL_INQ; + result.status = BTM_BUSY; + if (p_cb) { + (*p_cb)(&result); + } + return BTM_BUSY; + } + + btu_start_timer(&btm_cb.devcb.write_inq_txpwer_timer, BTU_TTYPE_BTM_BREDR_PWR_CTRL, BTM_INQ_REPLY_TIMEOUT); + btm_cb.devcb.p_write_inq_txpwer_cmpl_cb = p_cb; + + if (!btsnd_hcic_write_inq_tx_power(tx_power)) { + btm_cb.devcb.p_write_inq_txpwer_cmpl_cb = NULL; + btu_stop_timer(&btm_cb.devcb.write_inq_txpwer_timer); + memset(&result, 0, sizeof(result)); + result.type = BTM_TX_PWR_LVL_INQ; + result.status = BTM_NO_RESOURCES; + if (p_cb) { + (*p_cb)(&result); + } + return BTM_NO_RESOURCES; + } + + return BTM_CMD_STARTED; +} #endif // (CLASSIC_BT_INCLUDED == TRUE) /********************************************************************************* @@ -2187,40 +2243,77 @@ void btm_inq_rmt_name_failed (void) #if (CLASSIC_BT_INCLUDED == TRUE) /******************************************************************************* ** -** Function btm_read_linq_tx_power_complete +** Function btm_read_iscan_tx_power_complete ** -** Description read inquiry tx power level complete callback function. +** Description read inquiry scan tx power level complete callback function. ** ** Returns void ** *******************************************************************************/ -void btm_read_linq_tx_power_complete(UINT8 *p) +void btm_read_iscan_tx_power_complete(UINT8 *p) { - tBTM_CMPL_CB *p_cb = btm_cb.devcb.p_txpwer_cmpl_cb; - tBTM_INQ_TXPWR_RESULTS results; + tBTM_CMPL_CB *p_cb = btm_cb.devcb.p_read_iscan_txpwer_cmpl_cb; + tBTM_READ_TX_PWR_LVL_RESULTS results; - btu_stop_timer (&btm_cb.devcb.txpwer_timer); + memset(&results, 0, sizeof(results)); + results.type = BTM_TX_PWR_LVL_ISCAN; + + btu_stop_timer (&btm_cb.devcb.read_iscan_txpwer_timer); /* If there was a callback registered for read inq tx power, call it */ - btm_cb.devcb.p_txpwer_cmpl_cb = NULL; + btm_cb.devcb.p_read_iscan_txpwer_cmpl_cb = NULL; if (p_cb) { - STREAM_TO_UINT8 (results.hci_status, p); + if (p) { + STREAM_TO_UINT8 (results.hci_status, p); - if (results.hci_status == HCI_SUCCESS) { - results.status = BTM_SUCCESS; + if (results.hci_status == HCI_SUCCESS) { + results.status = BTM_SUCCESS; - STREAM_TO_UINT8 (results.tx_power, p); - BTM_TRACE_EVENT ("BTM INQ TX POWER Complete: tx_power %d, hci status 0x%02x\n", - results.tx_power, results.hci_status); + STREAM_TO_UINT8 (results.tx_power, p); + BTM_TRACE_EVENT ("BTM INQ TX POWER Complete: tx_power %d, hci status 0x%02x\n", + results.tx_power, results.hci_status); + } else { + results.status = BTM_ERR_PROCESSING; + } } else { results.status = BTM_ERR_PROCESSING; } - (*p_cb)(&results); } +} +/******************************************************************************* +** +** Function btm_write_inq_tx_power_complete +** +** Description write inquiry tx power level complete callback function. +** +** Returns void +** +*******************************************************************************/ +void btm_write_inq_tx_power_complete(UINT8 *p) +{ + tBTM_CMPL_CB *p_cb = btm_cb.devcb.p_write_inq_txpwer_cmpl_cb; + tBTM_WRITE_TX_PWR_LVL_RESULTS results; + + memset(&results, 0, sizeof(results)); + results.type = BTM_TX_PWR_LVL_INQ; + + btu_stop_timer(&btm_cb.devcb.write_inq_txpwer_timer); + btm_cb.devcb.p_write_inq_txpwer_cmpl_cb = NULL; + + if (p_cb) { + if (p) { + STREAM_TO_UINT8(results.hci_status, p); + results.status = (results.hci_status == HCI_SUCCESS) ? BTM_SUCCESS : BTM_ERR_PROCESSING; + } else { + results.status = BTM_ERR_PROCESSING; + } + (*p_cb)(&results); + } } #endif // #if (CLASSIC_BT_INCLUDED == TRUE) + /******************************************************************************* ** ** Function BTM_WriteEIR diff --git a/components/bt/host/bluedroid/stack/btm/include/btm_int.h b/components/bt/host/bluedroid/stack/btm/include/btm_int.h index 25a45d2e88..2f1ae39414 100644 --- a/components/bt/host/bluedroid/stack/btm/include/btm_int.h +++ b/components/bt/host/bluedroid/stack/btm/include/btm_int.h @@ -199,6 +199,47 @@ tBTM_CMPL_CB *p_rln_cmpl_cb; /* Callback function to be called when TIMER_LIST_ENT rssi_timer; tBTM_CMPL_CB *p_rssi_cmpl_cb; /* Callback function to be called when */ /* read rssi function completes */ + +#if (ESP_BT_CLASSIC_ENABLE_POWER_CTRL_VSC == TRUE) +TIMER_LIST_ENT acl_real_rssi_timer; +tBTM_CMPL_CB *p_acl_real_rssi_cmpl_cb; /* Callback function to be called when */ +/* read acl real rssi function completes */ + +TIMER_LIST_ENT read_new_conn_tx_pwr_lvl_timer; +tBTM_CMPL_CB *p_read_new_conn_tx_pwr_lvl_cmpl_cb; /* Callback function to be called when */ +/* read new connection transmit power level function completes */ + +TIMER_LIST_ENT write_new_conn_tx_pwr_lvl_timer; +tBTM_CMPL_CB *p_write_new_conn_tx_pwr_lvl_cmpl_cb; /* Callback function to be called when */ +/* write new connection transmit power level function completes */ +#endif // #if (ESP_BT_CLASSIC_ENABLE_POWER_CTRL_VSC == TRUE) + +#if (CLASSIC_BT_INCLUDED == TRUE) +TIMER_LIST_ENT read_page_tx_pwr_lvl_timer; +tBTM_CMPL_CB *p_read_page_tx_pwr_lvl_cmpl_cb; /* Callback function to be called when */ +/* read page transmit power level function completes */ + +TIMER_LIST_ENT write_page_tx_pwr_lvl_timer; +tBTM_CMPL_CB *p_write_page_tx_pwr_lvl_cmpl_cb; /* Callback function to be called when */ +/* write page transmit power level function completes */ + +TIMER_LIST_ENT read_pscan_tx_pwr_lvl_timer; +tBTM_CMPL_CB *p_read_pscan_tx_pwr_lvl_cmpl_cb; /* Callback function to be called when */ +/* read page scan transmit power level function completes */ + +TIMER_LIST_ENT write_pscan_tx_pwr_lvl_timer; +tBTM_CMPL_CB *p_write_pscan_tx_pwr_lvl_cmpl_cb; /* Callback function to be called when */ +/* write page scan transmit power level function completes */ + +TIMER_LIST_ENT read_inq_tx_pwr_lvl_timer; +tBTM_CMPL_CB *p_read_inq_tx_pwr_lvl_cmpl_cb; /* Callback function to be called when */ +/* read inquiry transmit power level function completes */ + +TIMER_LIST_ENT write_iscan_tx_pwr_lvl_timer; +tBTM_CMPL_CB *p_write_iscan_tx_pwr_lvl_cmpl_cb; /* Callback function to be called when */ +/* write inquiry scan transmit power level function completes */ +#endif // (CLASSIC_BT_INCLUDED == TRUE) + #if BLE_INCLUDED == TRUE tBTM_CMPL_CB *p_ble_ch_map_cmpl_cb; /* Callback function to be called when */ #endif // #if BLE_INCLUDED == TRUE @@ -210,11 +251,15 @@ tBTM_CMPL_CB *p_lnk_qual_cmpl_cb;/* Callback function to be called when #if (CLASSIC_BT_INCLUDED == TRUE) /* read link quality function completes */ -TIMER_LIST_ENT txpwer_timer; -tBTM_CMPL_CB *p_txpwer_cmpl_cb; /* Callback function to be called when */ +TIMER_LIST_ENT read_iscan_txpwer_timer; +tBTM_CMPL_CB *p_read_iscan_txpwer_cmpl_cb; /* Callback function to be called when */ +/* read inq scan tx power function completes */ + +TIMER_LIST_ENT write_inq_txpwer_timer; +tBTM_CMPL_CB *p_write_inq_txpwer_cmpl_cb; /* Callback function to be called when */ +/* write inq tx power function completes */ #endif // #if (CLASSIC_BT_INCLUDED == TRUE) -/* read inq tx power function completes */ #if (CLASSIC_BT_INCLUDED == TRUE) TIMER_LIST_ENT qossu_timer; tBTM_CMPL_CB *p_qossu_cmpl_cb; /* Callback function to be called when */ @@ -1082,6 +1127,18 @@ BOOLEAN btm_inq_find_bdaddr (BD_ADDR p_bda); BOOLEAN btm_lookup_eir(BD_ADDR_PTR p_rem_addr); +#if (CLASSIC_BT_INCLUDED == TRUE) +void btm_read_iscan_tx_power_complete (UINT8 *p); +void btm_write_inq_tx_power_complete (UINT8 *p); +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) + +/* Internal functions provided by btm_bredr_pwr_ctrl.c +******************************************* +*/ +#if (CLASSIC_BT_INCLUDED == TRUE) +void btm_bredr_pwr_ctrl_timeout(TIMER_LIST_ENT *p_tle); +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) + /* Internal functions provided by btm_acl.c ******************************************** */ @@ -1253,7 +1310,6 @@ tBTM_STATUS btm_sec_mx_access_request (BD_ADDR bd_addr, UINT16 psm, BOOLEAN is_ tBTM_SEC_CALLBACK *p_callback, void *p_ref_data); void btm_sec_conn_req (UINT8 *bda, UINT8 *dc); void btm_create_conn_cancel_complete (UINT8 *p, UINT16 evt_len); -void btm_read_linq_tx_power_complete (UINT8 *p); void btm_sec_init (UINT8 sec_mode); void btm_sec_dev_reset (void); diff --git a/components/bt/host/bluedroid/stack/btu/btu_hcif.c b/components/bt/host/bluedroid/stack/btu/btu_hcif.c index 75b62e5b59..47d547ac62 100644 --- a/components/bt/host/bluedroid/stack/btu/btu_hcif.c +++ b/components/bt/host/bluedroid/stack/btu/btu_hcif.c @@ -1245,7 +1245,10 @@ static void btu_hcif_hdl_command_complete (UINT16 opcode, UINT8 *p, UINT16 evt_l #if (CLASSIC_BT_INCLUDED == TRUE) case HCI_READ_INQ_TX_POWER_LEVEL: - btm_read_linq_tx_power_complete (p); + btm_read_iscan_tx_power_complete (p); + break; + case HCI_WRITE_INQ_TX_POWER_LEVEL: + btm_write_inq_tx_power_complete(p); break; case HCI_SET_AFH_CHANNELS: btm_set_afh_channels_complete(p); diff --git a/components/bt/host/bluedroid/stack/btu/btu_task.c b/components/bt/host/bluedroid/stack/btu/btu_task.c index f6ce7e4426..32588a3d6e 100644 --- a/components/bt/host/bluedroid/stack/btu/btu_task.c +++ b/components/bt/host/bluedroid/stack/btu/btu_task.c @@ -412,6 +412,11 @@ static void btu_general_alarm_process(void *param) case BTU_TTYPE_BTM_SET_PAGE_TO: btm_page_to_setup_timeout(p_tle); break; +#if (CLASSIC_BT_INCLUDED == TRUE) + case BTU_TTYPE_BTM_BREDR_PWR_CTRL: + btm_bredr_pwr_ctrl_timeout(p_tle); + break; +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) default: for (int i = 0; i < BTU_MAX_REG_TIMER; i++) { if (btu_cb.timer_reg[i].timer_cb == NULL) { diff --git a/components/bt/host/bluedroid/stack/hcic/hcicmds.c b/components/bt/host/bluedroid/stack/hcic/hcicmds.c index 3a176a5897..3839fe316e 100644 --- a/components/bt/host/bluedroid/stack/hcic/hcicmds.c +++ b/components/bt/host/bluedroid/stack/hcic/hcicmds.c @@ -1672,6 +1672,28 @@ BOOLEAN btsnd_hcic_read_inq_tx_power (void) return (TRUE); } +BOOLEAN btsnd_hcic_write_inq_tx_power (INT8 tx_power) +{ + BT_HDR *p; + UINT8 *pp; + + if ((p = HCI_GET_CMD_BUF(HCIC_PARAM_SIZE_W_INQ_TX_POWER)) == NULL) { + return (FALSE); + } + + pp = (UINT8 *)(p + 1); + + p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_W_INQ_TX_POWER; + p->offset = 0; + + UINT16_TO_STREAM (pp, HCI_WRITE_INQ_TX_POWER_LEVEL); + UINT8_TO_STREAM (pp, HCIC_PARAM_SIZE_W_INQ_TX_POWER); + INT8_TO_STREAM (pp, tx_power); + + btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID, p); + return (TRUE); +} + BOOLEAN btsnd_hcic_send_keypress_notif (BD_ADDR bd_addr, UINT8 notif) { BT_HDR *p; diff --git a/components/bt/host/bluedroid/stack/include/stack/btm_api.h b/components/bt/host/bluedroid/stack/include/stack/btm_api.h index 3f932d087d..69ed5e27bb 100644 --- a/components/bt/host/bluedroid/stack/include/stack/btm_api.h +++ b/components/bt/host/bluedroid/stack/include/stack/btm_api.h @@ -795,6 +795,66 @@ typedef struct { BD_ADDR rem_bda; } tBTM_RSSI_RESULTS; +#if (ESP_BT_CLASSIC_ENABLE_POWER_CTRL_VSC == TRUE) +/* Structure returned with read ACL real RSSI event (in tBTM_CMPL_CB callback function) +** in response to BTM_ReadAclRealRSSI call. +*/ +typedef struct { + tBTM_STATUS status; + UINT8 hci_status; + INT8 rssi; + BD_ADDR rem_bda; +} tBTM_ACL_REAL_RSSI_RESULTS; + +/* Structure returned with read new connection transmit power level event (in tBTM_CMPL_CB callback function) +** in response to BTM_ReadNewConnTxPwrLvl call. +*/ +typedef struct { + tBTM_STATUS status; + UINT8 hci_status; + INT8 pwr_lvl_min; + INT8 pwr_lvl_max; +} tBTM_READ_NEW_CONN_TX_PWR_LVL_RESULTS; + +/* Structure returned with write new connection transmit power level event (in tBTM_CMPL_CB callback function) +** in response to BTM_WriteNewConnTxPwrLvl call. +*/ +typedef struct { + tBTM_STATUS status; + UINT8 hci_status; +} tBTM_WRITE_NEW_CONN_TX_PWR_LVL_RESULTS; +#endif // #if (ESP_BT_CLASSIC_ENABLE_POWER_CTRL_VSC == TRUE) + +#if (CLASSIC_BT_INCLUDED == TRUE) +/* BR/EDR tx power level type for inq/iscan/page/pscan control */ +typedef enum { + BTM_TX_PWR_LVL_INQ = 0, + BTM_TX_PWR_LVL_ISCAN, + BTM_TX_PWR_LVL_PAGE, + BTM_TX_PWR_LVL_PSCAN, + BTM_TX_PWR_LVL_MAX, +} tBTM_TX_PWR_LVL_TYPE; + +/* Structure returned with read inq/iscan/page/pscan tx power level event (in tBTM_CMPL_CB callback function) +** in response to BTM_ReadBredrTxPwrLvl/BTM_ReadInquiryRspTxPower call. +*/ +typedef struct { + tBTM_STATUS status; + UINT8 hci_status; + INT8 tx_power; + tBTM_TX_PWR_LVL_TYPE type; +} tBTM_READ_TX_PWR_LVL_RESULTS; + +/* Structure returned with write inq/iscan/page/pscan tx power level event (in tBTM_CMPL_CB callback function) +** in response to BTM_WriteBredrTxPwrLvl/BTM_WriteInquiryTxPower call. +*/ +typedef struct { + tBTM_STATUS status; + UINT8 hci_status; + tBTM_TX_PWR_LVL_TYPE type; +} tBTM_WRITE_TX_PWR_LVL_RESULTS; +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) + /* Structure returned with read channel map event (in tBTM_CMPL_CB callback function) ** in response to BTM_ReadChannelMap call. */ @@ -876,16 +936,6 @@ typedef struct { UINT8 hci_status; } tBTM_BLE_SET_CHANNELS_RESULTS; -/* Structure returned with read inq tx power quality event (in tBTM_CMPL_CB callback function) -** in response to BTM_ReadInquiryRspTxPower call. -*/ -typedef struct { - tBTM_STATUS status; - UINT8 hci_status; - INT8 tx_power; -} tBTM_INQ_TXPWR_RESULTS; - - enum { BTM_ACL_CONN_CMPL_EVT, BTM_ACL_DISCONN_CMPL_EVT @@ -2798,6 +2848,7 @@ tBTM_INQ_INFO *BTM_InqDbNext (tBTM_INQ_INFO *p_cur); //extern tBTM_STATUS BTM_ClearInqDb (BD_ADDR p_bda); +#if (CLASSIC_BT_INCLUDED == TRUE) /******************************************************************************* ** ** Function BTM_ReadInquiryRspTxPower @@ -2812,6 +2863,21 @@ tBTM_STATUS BTM_ClearInqDb (BD_ADDR p_bda); //extern tBTM_STATUS BTM_ReadInquiryRspTxPower (tBTM_CMPL_CB *p_cb); +/******************************************************************************* +** +** Function BTM_WriteInquiryTxPower +** +** Description This command writes the inquiry transmit power level used +** to transmit inquiry response packets. +** +** Returns BTM_CMD_STARTED if command issued to controller. +** BTM_NO_RESOURCES if couldn't allocate memory to issue command +** BTM_BUSY if command is already in progress +** +*******************************************************************************/ +tBTM_STATUS BTM_WriteInquiryTxPower(INT8 tx_power, tBTM_CMPL_CB *p_cb); +#endif // #if (CLASSIC_BT_INCLUDED == TRUE) + #if SDP_INCLUDED == TRUE /******************************************************************************* ** @@ -3018,6 +3084,88 @@ tBTM_STATUS BTM_SwitchRole (BD_ADDR remote_bd_addr, //extern tBTM_STATUS BTM_ReadRSSI (BD_ADDR remote_bda, tBT_TRANSPORT transport, tBTM_CMPL_CB *p_cb); +#if (ESP_BT_CLASSIC_ENABLE_POWER_CTRL_VSC == TRUE) +/******************************************************************************* +** +** Function BTM_ReadAclRealRSSI +** +** Description This function is called to read ACL real RSSI. +** The RSSI of results are returned in the callback. +** (tBTM_ACL_REAL_RSSI_RESULTS) +** +** Returns BTM_CMD_STARTED if command issued to controller. +** BTM_NO_RESOURCES if couldn't allocate memory to issue command +** BTM_UNKNOWN_ADDR if no active link with bd addr specified +** BTM_BUSY if command is already in progress +** +*******************************************************************************/ +tBTM_STATUS BTM_ReadAclRealRSSI(BD_ADDR remote_bda, tBTM_CMPL_CB *p_cb); + +/******************************************************************************* +** +** Function BTM_ReadNewConnTxPwrLvl +** +** Description This function is called to read new connection transmit power level. +** The new connection transmit power level value returned in the callback. +** (tBTM_READ_NEW_CONN_TX_PWR_LVL_RESULTS) +** +** Returns BTM_CMD_STARTED if command issued to controller. +** BTM_NO_RESOURCES if couldn't allocate memory to issue command +** BTM_BUSY if command is already in progress +** +*******************************************************************************/ +tBTM_STATUS BTM_ReadNewConnTxPwrLvl(tBTM_CMPL_CB *p_cb); + +/******************************************************************************* +** +** Function BTM_WriteNewConnTxPwrLvl +** +** Description This function is called to write new connection transmit power level. +** The new connection transmit power level value returned in the callback. +** (tBTM_WRITE_NEW_CONN_TX_PWR_LVL_RESULTS) +** +** Returns BTM_CMD_STARTED if command issued to controller. +** BTM_NO_RESOURCES if couldn't allocate memory to issue command +** BTM_BUSY if command is already in progress +** +*******************************************************************************/ +tBTM_STATUS BTM_WriteNewConnTxPwrLvl(INT8 pwr_lvl_min, INT8 pwr_lvl_max, tBTM_CMPL_CB *p_cb); +#endif // #if (ESP_BT_CLASSIC_ENABLE_POWER_CTRL_VSC == TRUE) + +#if (CLASSIC_BT_INCLUDED == TRUE) +/******************************************************************************* +** +** Function BTM_ReadBredrTxPwrLvl +** +** Description This function is called to read inq/iscan/page/pscan transmit power level. +** The corresponding transmit power level value returned in the callback. +** (tBTM_READ_TX_PWR_LVL_RESULTS) +** +** Returns BTM_CMD_STARTED if command issued to controller. +** BTM_NO_RESOURCES if couldn't allocate memory to issue command +** BTM_BUSY if command is already in progress +** BTM_ILLEGAL_VALUE if type is invalid +** +*******************************************************************************/ +tBTM_STATUS BTM_ReadBredrTxPwrLvl(tBTM_TX_PWR_LVL_TYPE type, tBTM_CMPL_CB *p_cb); + +/******************************************************************************* +** +** Function BTM_WriteBredrTxPwrLvl +** +** Description This function is called to write inq/iscan/page/pscan transmit power level. +** The corresponding write status returned in the callback. +** (tBTM_WRITE_TX_PWR_LVL_RESULTS) +** +** Returns BTM_CMD_STARTED if command issued to controller. +** BTM_NO_RESOURCES if couldn't allocate memory to issue command +** BTM_BUSY if command is already in progress +** BTM_ILLEGAL_VALUE if type is invalid +** +*******************************************************************************/ +tBTM_STATUS BTM_WriteBredrTxPwrLvl(tBTM_TX_PWR_LVL_TYPE type, INT8 tx_power, tBTM_CMPL_CB *p_cb); +#endif // (CLASSIC_BT_INCLUDED == TRUE) + /******************************************************************************* ** ** Function BTM_ReadChannelMap diff --git a/components/bt/host/bluedroid/stack/include/stack/btu.h b/components/bt/host/bluedroid/stack/include/stack/btu.h index 8df767b4fd..075adcdd1b 100644 --- a/components/bt/host/bluedroid/stack/include/stack/btu.h +++ b/components/bt/host/bluedroid/stack/include/stack/btu.h @@ -169,6 +169,9 @@ typedef void (*tBTU_EVENT_CALLBACK)(BT_HDR *p_hdr); /* BTU internal timer for set page timeout*/ #define BTU_TTYPE_BTM_SET_PAGE_TO 111 +/* BTU internal timer for BR/EDR power control*/ +#define BTU_TTYPE_BTM_BREDR_PWR_CTRL 112 + /* BTU Task Signal */ typedef enum { SIG_BTU_START_UP = 0, diff --git a/components/bt/host/bluedroid/stack/include/stack/hcidefs.h b/components/bt/host/bluedroid/stack/include/stack/hcidefs.h index ca6f901377..ee50f60559 100644 --- a/components/bt/host/bluedroid/stack/include/stack/hcidefs.h +++ b/components/bt/host/bluedroid/stack/include/stack/hcidefs.h @@ -512,6 +512,15 @@ #define HCI_SUBCODE_BT_SET_AFH_REPORTING_MODE 0x09 #define HCI_SUBCODE_BT_MASK_RMT_AFH_CH_CLASS 0x0A #define HCI_SUBCODE_BT_WR_AUTO_RATE_INIT_ENABLE 0x0B +#define HCI_SUBCODE_BT_RD_ACL_REAL_RSSI 0x11 +#define HCI_SUBCODE_BT_RD_NEW_CONN_TX_PWR_LVL 0x12 +#define HCI_SUBCODE_BT_WR_NEW_CONN_TX_PWR_LVL 0x13 +#define HCI_SUBCODE_BT_RD_PAGE_TX_PWR_LVL 0x14 +#define HCI_SUBCODE_BT_WR_PAGE_TX_PWR_LVL 0x15 +#define HCI_SUBCODE_BT_RD_PSCAN_TX_PWR_LVL 0x16 +#define HCI_SUBCODE_BT_WR_PSCAN_TX_PWR_LVL 0x17 +#define HCI_SUBCODE_BT_RD_INQ_TX_PWR_LVL 0x18 +#define HCI_SUBCODE_BT_WR_ISCAN_TX_PWR_LVL 0x19 #define HCI_SUBCODE_BT_MAX 0x7F #define HCI_ESP_VENDOR_OPCODE_BUILD(ogf, group, subcode) ((ogf << 10) | (group <<7) | (subcode << 0)) @@ -561,6 +570,15 @@ #define HCI_VENDOR_BT_SET_AFH_REPORTING_MODE HCI_ESP_VENDOR_OPCODE_BUILD(HCI_VENDOR_OGF, HCI_ESP_GROUP_BT, HCI_SUBCODE_BT_SET_AFH_REPORTING_MODE) #define HCI_VENDOR_BT_MASK_RMT_AFH_CH_CLASS HCI_ESP_VENDOR_OPCODE_BUILD(HCI_VENDOR_OGF, HCI_ESP_GROUP_BT, HCI_SUBCODE_BT_MASK_RMT_AFH_CH_CLASS) #define HCI_VENDOR_BT_WR_AUTO_RATE_INIT_ENABLE HCI_ESP_VENDOR_OPCODE_BUILD(HCI_VENDOR_OGF, HCI_ESP_GROUP_BT, HCI_SUBCODE_BT_WR_AUTO_RATE_INIT_ENABLE) +#define HCI_VENDOR_BT_RD_ACL_REAL_RSSI HCI_ESP_VENDOR_OPCODE_BUILD(HCI_VENDOR_OGF, HCI_ESP_GROUP_BT, HCI_SUBCODE_BT_RD_ACL_REAL_RSSI) +#define HCI_VENDOR_BT_RD_NEW_CONN_TX_PWR_LVL HCI_ESP_VENDOR_OPCODE_BUILD(HCI_VENDOR_OGF, HCI_ESP_GROUP_BT, HCI_SUBCODE_BT_RD_NEW_CONN_TX_PWR_LVL) +#define HCI_VENDOR_BT_WR_NEW_CONN_TX_PWR_LVL HCI_ESP_VENDOR_OPCODE_BUILD(HCI_VENDOR_OGF, HCI_ESP_GROUP_BT, HCI_SUBCODE_BT_WR_NEW_CONN_TX_PWR_LVL) +#define HCI_VENDOR_BT_RD_PAGE_TX_PWR_LVL HCI_ESP_VENDOR_OPCODE_BUILD(HCI_VENDOR_OGF, HCI_ESP_GROUP_BT, HCI_SUBCODE_BT_RD_PAGE_TX_PWR_LVL) +#define HCI_VENDOR_BT_WR_PAGE_TX_PWR_LVL HCI_ESP_VENDOR_OPCODE_BUILD(HCI_VENDOR_OGF, HCI_ESP_GROUP_BT, HCI_SUBCODE_BT_WR_PAGE_TX_PWR_LVL) +#define HCI_VENDOR_BT_RD_PSCAN_TX_PWR_LVL HCI_ESP_VENDOR_OPCODE_BUILD(HCI_VENDOR_OGF, HCI_ESP_GROUP_BT, HCI_SUBCODE_BT_RD_PSCAN_TX_PWR_LVL) +#define HCI_VENDOR_BT_WR_PSCAN_TX_PWR_LVL HCI_ESP_VENDOR_OPCODE_BUILD(HCI_VENDOR_OGF, HCI_ESP_GROUP_BT, HCI_SUBCODE_BT_WR_PSCAN_TX_PWR_LVL) +#define HCI_VENDOR_BT_RD_INQ_TX_PWR_LVL HCI_ESP_VENDOR_OPCODE_BUILD(HCI_VENDOR_OGF, HCI_ESP_GROUP_BT, HCI_SUBCODE_BT_RD_INQ_TX_PWR_LVL) +#define HCI_VENDOR_BT_WR_ISCAN_TX_PWR_LVL HCI_ESP_VENDOR_OPCODE_BUILD(HCI_VENDOR_OGF, HCI_ESP_GROUP_BT, HCI_SUBCODE_BT_WR_ISCAN_TX_PWR_LVL) /* subcode for multi adv feature */ #define BTM_BLE_MULTI_ADV_SET_PARAM 0x01 diff --git a/components/bt/host/bluedroid/stack/include/stack/hcimsgs.h b/components/bt/host/bluedroid/stack/include/stack/hcimsgs.h index 2e003353da..86e6d29fdd 100644 --- a/components/bt/host/bluedroid/stack/include/stack/hcimsgs.h +++ b/components/bt/host/bluedroid/stack/include/stack/hcimsgs.h @@ -509,6 +509,11 @@ BOOLEAN btsnd_hcic_read_inq_tx_power (void); #define HCIC_PARAM_SIZE_R_TX_POWER 0 +/* Write Inquiry Tx Power Level */ +BOOLEAN btsnd_hcic_write_inq_tx_power (INT8 tx_power); + +#define HCIC_PARAM_SIZE_W_INQ_TX_POWER 1 + /* Read Default Erroneous Data Reporting */ BOOLEAN btsnd_hcic_read_default_erroneous_data_rpt (void); diff --git a/components/bt/include/esp32/include/esp_bt.h b/components/bt/include/esp32/include/esp_bt.h index 375900e668..41821366d6 100644 --- a/components/bt/include/esp32/include/esp_bt.h +++ b/components/bt/include/esp32/include/esp_bt.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -47,7 +47,7 @@ extern "C" { #define SOC_MEM_BT_EM_PER_SYNC_SIZE 0x870 -#define SOC_MEM_BT_EM_BREDR_REAL_END (SOC_MEM_BT_EM_BREDR_NO_SYNC_END + UT_BR_EDR_CTRL_MAX_SYNC_CONN_EFF * SOC_MEM_BT_EM_PER_SYNC_SIZE) +#define SOC_MEM_BT_EM_BREDR_REAL_END (SOC_MEM_BT_EM_BREDR_NO_SYNC_END + UC_BR_EDR_CTRL_MAX_SYNC_CONN_EFF * SOC_MEM_BT_EM_PER_SYNC_SIZE) #endif //CONFIG_BT_ENABLED @@ -242,7 +242,7 @@ the adv packet will be discarded until the memory is restored. */ .bt_sco_datapath = CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF, \ .auto_latency = BTDM_CTRL_AUTO_LATENCY_EFF, \ .bt_legacy_auth_vs_evt = BTDM_CTRL_LEGACY_AUTH_VENDOR_EVT_EFF, \ - .bt_max_sync_conn = UT_BR_EDR_CTRL_MAX_SYNC_CONN_EFF, \ + .bt_max_sync_conn = UC_BR_EDR_CTRL_MAX_SYNC_CONN_EFF, \ .ble_sca = CONFIG_BTDM_BLE_SLEEP_CLOCK_ACCURACY_INDEX_EFF, \ .pcm_role = CONFIG_BTDM_CTRL_PCM_ROLE_EFF, \ .pcm_polar = CONFIG_BTDM_CTRL_PCM_POLAR_EFF, \ @@ -634,6 +634,7 @@ esp_err_t esp_ble_scan_dupilcate_list_flush(void); * such as performing discovery, profile initialization, and so on. * 2. For BR/EDR to use the new TX power for inquiry, call this function before starting an inquiry. * If BR/EDR is already inquiring, restart the inquiry after calling this function. + * 3. If `BT_CLASSIC_ENABLE_POWER_CTRL_VSC` is enabled, this function will be not supported. * * @param[in] min_power_level The minimum power level. The default value is `ESP_PWR_LVL_N0`. * @param[in] max_power_level The maximum power level. The default value is `ESP_PWR_LVL_P3`. @@ -650,6 +651,9 @@ esp_err_t esp_bredr_tx_power_set(esp_power_level_t min_power_level, esp_power_le * * The corresponding power levels will be stored into the arguments. * + * @note + * 1. If `BT_CLASSIC_ENABLE_POWER_CTRL_VSC` is enabled, this function will be not supported. + * * @param[out] min_power_level Pointer to store the minimum power level * @param[out] max_power_level The maximum power level * diff --git a/components/bt/include/esp32/include/esp_bt_vs.h b/components/bt/include/esp32/include/esp_bt_vs.h index e8472ab57c..1ec7bab26e 100644 --- a/components/bt/include/esp32/include/esp_bt_vs.h +++ b/components/bt/include/esp32/include/esp_bt_vs.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -224,6 +224,51 @@ struct bt_hci_vs_legacy_rem_auth_evt { */ #define ESP_BT_VS_WR_AUTO_RATE_INIT_OCF (0x018b) +/** + * @note The init function is `bt_stack_enablePwrCtrlVsCmd(true)` + */ +#define ESP_BT_VS_RD_ACL_REAL_RSSI_OCF (0x0191) + +/** + * @note The init function is `bt_stack_enablePwrCtrlVsCmd(true)` + */ +#define ESP_BT_VS_RD_NEW_CONN_TX_PWR_LVL_OCF (0x0192) + +/** + * @note The init function is `bt_stack_enablePwrCtrlVsCmd(true)` + */ +#define ESP_BT_VS_WR_NEW_CONN_TX_PWR_LVL_OCF (0x0193) + +/** + * @note The init function is `bt_stack_enablePwrCtrlVsCmd(true)` + */ +#define ESP_BT_VS_RD_PAGE_TX_PWR_LVL_OCF (0x0194) + +/** + * @note The init function is `bt_stack_enablePwrCtrlVsCmd(true)` + */ +#define ESP_BT_VS_WR_PAGE_TX_PWR_LVL_OCF (0x0195) + +/** + * @note The init function is `bt_stack_enablePwrCtrlVsCmd(true)` + */ +#define ESP_BT_VS_RD_PSCAN_TX_PWR_LVL_OCF (0x0196) + +/** + * @note The init function is `bt_stack_enablePwrCtrlVsCmd(true)` + */ +#define ESP_BT_VS_WR_PSCAN_TX_PWR_LVL_OCF (0x0197) + +/** + * @note The init function is `bt_stack_enablePwrCtrlVsCmd(true)` + */ +#define ESP_BT_VS_RD_INQ_TX_PWR_LVL_OCF (0x0198) + +/** + * @note The init function is `bt_stack_enablePwrCtrlVsCmd(true)` + */ +#define ESP_BT_VS_WR_ISCAN_TX_PWR_LVL_OCF (0x0199) + // // @brief HCI VS Events for Espressif's Internal-Use Debugging // diff --git a/components/esp_rom/esp32/ld/esp32.rom.ld b/components/esp_rom/esp32/ld/esp32.rom.ld index 6cca533158..85bcb7ad4b 100644 --- a/components/esp_rom/esp32/ld/esp32.rom.ld +++ b/components/esp_rom/esp32/ld/esp32.rom.ld @@ -674,6 +674,7 @@ PROVIDE ( ld_inq_end = 0x4003ab48 ); PROVIDE ( ld_inq_sched = 0x4003aba4 ); PROVIDE ( ld_inq_frm_cbk = 0x4003ae4c ); PROVIDE ( ld_pscan_frm_cbk = 0x4003ebe4 ); +PROVIDE ( ld_pscan_evt_start_cbk = 0x4003e924 ); PROVIDE ( r_ld_acl_active_hop_types_get = 0x40036e10 ); PROVIDE ( r_ld_acl_afh_confirm = 0x40036d40 ); PROVIDE ( r_ld_acl_afh_prepare = 0x40036c84 ); @@ -776,12 +777,14 @@ PROVIDE ( r_ld_iscan_restart = 0x4003ba44 ); PROVIDE ( r_ld_iscan_start = 0x4003bb28 ); PROVIDE ( r_ld_iscan_stop = 0x4003bf1c ); PROVIDE ( r_ld_iscan_tx_pwr_get = 0x4003c138 ); +PROVIDE ( ld_iscan_evt_start_cbk = 0x4003b58c ); PROVIDE ( r_ld_page_init = 0x4003d808 ); PROVIDE ( r_ld_page_reset = 0x4003d814 ); PROVIDE ( r_ld_page_start = 0x4003d848 ); PROVIDE ( r_ld_page_stop = 0x4003da54 ); PROVIDE ( ld_page_frm_cbk = 0x4003d280 ); PROVIDE ( ld_page_em_init = 0x4003cb34 ); +PROVIDE ( ld_page_evt_start_cbk = 0x4003cf40); PROVIDE ( r_ld_pca_coarse_clock_adjust = 0x4003e324 ); PROVIDE ( r_ld_pca_init = 0x4003deb4 ); PROVIDE ( r_ld_pca_initiate_clock_dragging = 0x4003e4ac ); diff --git a/docs/en/api-reference/bluetooth/bt_vhci.rst b/docs/en/api-reference/bluetooth/bt_vhci.rst index 7a5dcac19b..d54bd0788d 100644 --- a/docs/en/api-reference/bluetooth/bt_vhci.rst +++ b/docs/en/api-reference/bluetooth/bt_vhci.rst @@ -115,6 +115,15 @@ The following HCI VS debugging commands are implemented in Bluetooth Low Energy .. doxygendefine:: ESP_BT_VS_SET_AFH_REPORTING_MODE_OCF .. doxygendefine:: ESP_BT_VS_MASK_RMT_CHANNEL_CLASSIFICATION_OCF .. doxygendefine:: ESP_BT_VS_WR_AUTO_RATE_INIT_OCF + .. doxygendefine:: ESP_BT_VS_RD_ACL_REAL_RSSI_OCF + .. doxygendefine:: ESP_BT_VS_RD_NEW_CONN_TX_PWR_LVL_OCF + .. doxygendefine:: ESP_BT_VS_WR_NEW_CONN_TX_PWR_LVL_OCF + .. doxygendefine:: ESP_BT_VS_RD_PAGE_TX_PWR_LVL_OCF + .. doxygendefine:: ESP_BT_VS_WR_PAGE_TX_PWR_LVL_OCF + .. doxygendefine:: ESP_BT_VS_RD_PSCAN_TX_PWR_LVL_OCF + .. doxygendefine:: ESP_BT_VS_WR_PSCAN_TX_PWR_LVL_OCF + .. doxygendefine:: ESP_BT_VS_RD_INQ_TX_PWR_LVL_OCF + .. doxygendefine:: ESP_BT_VS_WR_ISCAN_TX_PWR_LVL_OCF .. only:: esp32c3 or esp32s3 diff --git a/docs/zh_CN/api-reference/bluetooth/bt_vhci.rst b/docs/zh_CN/api-reference/bluetooth/bt_vhci.rst index f9f7ee6f0c..a4c7f3f750 100644 --- a/docs/zh_CN/api-reference/bluetooth/bt_vhci.rst +++ b/docs/zh_CN/api-reference/bluetooth/bt_vhci.rst @@ -115,6 +115,15 @@ .. doxygendefine:: ESP_BT_VS_SET_AFH_REPORTING_MODE_OCF .. doxygendefine:: ESP_BT_VS_MASK_RMT_CHANNEL_CLASSIFICATION_OCF .. doxygendefine:: ESP_BT_VS_WR_AUTO_RATE_INIT_OCF + .. doxygendefine:: ESP_BT_VS_RD_ACL_REAL_RSSI_OCF + .. doxygendefine:: ESP_BT_VS_RD_NEW_CONN_TX_PWR_LVL_OCF + .. doxygendefine:: ESP_BT_VS_WR_NEW_CONN_TX_PWR_LVL_OCF + .. doxygendefine:: ESP_BT_VS_RD_PAGE_TX_PWR_LVL_OCF + .. doxygendefine:: ESP_BT_VS_WR_PAGE_TX_PWR_LVL_OCF + .. doxygendefine:: ESP_BT_VS_RD_PSCAN_TX_PWR_LVL_OCF + .. doxygendefine:: ESP_BT_VS_WR_PSCAN_TX_PWR_LVL_OCF + .. doxygendefine:: ESP_BT_VS_RD_INQ_TX_PWR_LVL_OCF + .. doxygendefine:: ESP_BT_VS_WR_ISCAN_TX_PWR_LVL_OCF .. only:: esp32c3 or esp32s3