Merge branch 'feat/add_api_get_avrc_status_v5.3' into 'release/v5.3'

feat(bt): Add API to get some information of Classic Bluetooth profile(v5.3)

See merge request espressif/esp-idf!38687
This commit is contained in:
Wang Meng Yang
2025-04-27 09:52:58 +08:00
16 changed files with 108 additions and 15 deletions

View File

@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@ -474,4 +474,19 @@ esp_err_t esp_avrc_tg_send_rn_rsp(esp_avrc_rn_event_ids_t event_id, esp_avrc_rn_
} }
esp_err_t esp_avrc_get_profile_status(esp_avrc_profile_status_t *profile_status)
{
if (esp_bluedroid_get_status() != ESP_BLUEDROID_STATUS_ENABLED) {
return ESP_ERR_INVALID_STATE;
}
if (profile_status == NULL) {
return ESP_ERR_INVALID_ARG;
}
memset(profile_status, 0, sizeof(esp_avrc_profile_status_t));
btc_avrc_get_profile_status(profile_status);
return ESP_OK;
}
#endif /* #if BTC_AV_INCLUDED */ #endif /* #if BTC_AV_INCLUDED */

View File

@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@ -155,7 +155,7 @@ typedef enum {
ESP_AVRC_MD_ATTR_TRACK_NUM = 0x8, /*!< track position on the album */ ESP_AVRC_MD_ATTR_TRACK_NUM = 0x8, /*!< track position on the album */
ESP_AVRC_MD_ATTR_NUM_TRACKS = 0x10, /*!< number of tracks on the album */ ESP_AVRC_MD_ATTR_NUM_TRACKS = 0x10, /*!< number of tracks on the album */
ESP_AVRC_MD_ATTR_GENRE = 0x20, /*!< track genre */ ESP_AVRC_MD_ATTR_GENRE = 0x20, /*!< track genre */
ESP_AVRC_MD_ATTR_PLAYING_TIME = 0x40 /*!< total album playing time in miliseconds */ ESP_AVRC_MD_ATTR_PLAYING_TIME = 0x40 /*!< total album playing time in milliseconds */
} esp_avrc_md_attr_mask_t; } esp_avrc_md_attr_mask_t;
/// AVRC event notification ids /// AVRC event notification ids
@ -277,6 +277,14 @@ typedef struct {
uint8_t attr_val; /*!< player application attribute value */ uint8_t attr_val; /*!< player application attribute value */
} esp_avrc_set_app_value_param_t; } esp_avrc_set_app_value_param_t;
/**
* @brief AVRCP profile status parameters
*/
typedef struct {
bool avrc_ct_inited; /*!< AVRCP CT initialization */
bool avrc_tg_inited; /*!< AVRCP TG initialization */
} esp_avrc_profile_status_t;
/// AVRC controller callback parameters /// AVRC controller callback parameters
typedef union { typedef union {
/** /**
@ -656,11 +664,11 @@ bool esp_avrc_psth_bit_mask_operation(esp_avrc_bit_mask_op_t op, esp_avrc_psth_b
/** /**
* *
* @brief Get the requested event notification capabilies on local AVRC target. The capability is returned * @brief Get the requested event notification capabilities on local AVRC target. The capability is returned
* in a bit mask representation in evt_set. This function should be called after esp_avrc_tg_init(). * in a bit mask representation in evt_set. This function should be called after esp_avrc_tg_init().
* *
* For capability type "ESP_AVRC_RN_CAP_ALLOWED_EVT, the retrieved event set is constant and * For capability type "ESP_AVRC_RN_CAP_ALLOWED_EVT, the retrieved event set is constant and
* it covers all of the notifcation events that can possibly be supported with current * it covers all of the notification events that can possibly be supported with current
* implementation. * implementation.
* *
* For capability type ESP_AVRC_RN_CAP_SUPPORTED_EVT, the event set covers the notification * For capability type ESP_AVRC_RN_CAP_SUPPORTED_EVT, the event set covers the notification
@ -729,6 +737,17 @@ bool esp_avrc_rn_evt_bit_mask_operation(esp_avrc_bit_mask_op_t op, esp_avrc_rn_e
esp_err_t esp_avrc_tg_send_rn_rsp(esp_avrc_rn_event_ids_t event_id, esp_avrc_rn_rsp_t rsp, esp_err_t esp_avrc_tg_send_rn_rsp(esp_avrc_rn_event_ids_t event_id, esp_avrc_rn_rsp_t rsp,
esp_avrc_rn_param_t *param); esp_avrc_rn_param_t *param);
/**
* @brief This function is used to get the status of AVRCP
*
* @param[out] profile_status - AVRCP status
*
* @return
* - ESP_OK: success
* - other: failed
*/
esp_err_t esp_avrc_get_profile_status(esp_avrc_profile_status_t *profile_status);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -306,6 +306,8 @@ typedef uint8_t esp_ble_key_mask_t; /* the key mask type */
#define ESP_BLE_ADV_NAME_LEN_MAX 29 #define ESP_BLE_ADV_NAME_LEN_MAX 29
#define ESP_INVALID_CONN_HANDLE 0xfff
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -78,7 +78,8 @@ typedef enum
/// HFP AG profile status parameters /// HFP AG profile status parameters
typedef struct { typedef struct {
bool hfp_ag_inited; /*!< hfp ag initialization */ bool hfp_ag_inited; /*!< hfp ag initialization */
uint8_t conn_num; /*!< Number of connections */ uint8_t slc_conn_num; /*!< Number of Service Level Connections */
uint8_t sync_conn_num; /*!< Number of (e)SCO Connections */
} esp_hf_profile_status_t; } esp_hf_profile_status_t;
/// HFP AG callback parameters /// HFP AG callback parameters

View File

@ -47,7 +47,8 @@ typedef enum {
*/ */
typedef struct { typedef struct {
bool hf_client_inited; /*!< hf client initialization */ bool hf_client_inited; /*!< hf client initialization */
uint8_t conn_num; /*!< Number of connections */ uint8_t slc_conn_num; /*!< Number of Service Level Connections */
uint8_t sync_conn_num; /*!< Number of (e)SCO Connections */
} esp_hf_client_profile_status_t; } esp_hf_client_profile_status_t;
/* features masks of AG */ /* features masks of AG */

View File

@ -151,6 +151,8 @@ typedef enum {
typedef struct { typedef struct {
bool hidd_inited; /*!< HID device initialization */ bool hidd_inited; /*!< HID device initialization */
uint8_t conn_num; /*!< Number of connections */ uint8_t conn_num; /*!< Number of connections */
uint8_t plug_vc_dev_num; /*!< Number of plugged virtual cable devices */
uint8_t reg_app_num; /*!< Number of HID device application registrations */
} esp_hidd_profile_status_t; } esp_hidd_profile_status_t;
/** /**

View File

@ -139,6 +139,7 @@ typedef struct {
typedef struct { typedef struct {
bool hidh_inited; /*!< HID host initialization */ bool hidh_inited; /*!< HID host initialization */
uint8_t conn_num; /*!< Number of connections */ uint8_t conn_num; /*!< Number of connections */
uint8_t plug_vc_dev_num; /*!< Number of plugged virtual cable devices*/
} esp_hidh_profile_status_t; } esp_hidh_profile_status_t;
/** /**

View File

@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@ -1450,4 +1450,22 @@ void btc_avrc_tg_call_handler(btc_msg_t *msg)
btc_avrc_tg_arg_deep_free(msg); btc_avrc_tg_arg_deep_free(msg);
} }
void btc_avrc_get_profile_status(esp_avrc_profile_status_t *param)
{
param->avrc_ct_inited = false;
param->avrc_tg_inited = false;
#if AVRC_DYNAMIC_MEMORY == TRUE
if (btc_rc_cb_ptr)
#endif
{
if (btc_avrc_tg_init_p()) {
param->avrc_tg_inited = true;
}
if (btc_avrc_ct_init_p()) {
param->avrc_ct_inited = true;
}
}
}
#endif /* #if BTC_AV_INCLUDED */ #endif /* #if BTC_AV_INCLUDED */

View File

@ -351,6 +351,9 @@ bt_status_t btc_hf_init(void)
#endif #endif
clear_phone_state(); clear_phone_state();
memset(&hf_local_param[idx].btc_hf_cb, 0, sizeof(btc_hf_cb_t)); memset(&hf_local_param[idx].btc_hf_cb, 0, sizeof(btc_hf_cb_t));
for (int i = 0; i < BTC_HF_NUM_CB; i++) {
hf_local_param[i].btc_hf_cb.sync_conn_hdl = ESP_INVALID_CONN_HANDLE;
}
// set audio path // set audio path
#if (BT_CONTROLLER_INCLUDED == TRUE) #if (BT_CONTROLLER_INCLUDED == TRUE)
#if BTM_SCO_HCI_INCLUDED #if BTM_SCO_HCI_INCLUDED
@ -1411,6 +1414,7 @@ void btc_hf_cb_handler(btc_msg_t *msg)
do { do {
param.audio_stat.state = ESP_HF_AUDIO_STATE_CONNECTED; param.audio_stat.state = ESP_HF_AUDIO_STATE_CONNECTED;
memcpy(param.audio_stat.remote_addr, &hf_local_param[idx].btc_hf_cb.connected_bda,sizeof(esp_bd_addr_t)); memcpy(param.audio_stat.remote_addr, &hf_local_param[idx].btc_hf_cb.connected_bda,sizeof(esp_bd_addr_t));
hf_local_param[idx].btc_hf_cb.sync_conn_hdl = p_data->hdr.sync_conn_handle;
param.audio_stat.sync_conn_handle = p_data->hdr.sync_conn_handle; param.audio_stat.sync_conn_handle = p_data->hdr.sync_conn_handle;
btc_hf_cb_to_app(ESP_HF_AUDIO_STATE_EVT, &param); btc_hf_cb_to_app(ESP_HF_AUDIO_STATE_EVT, &param);
} while(0); } while(0);
@ -1424,6 +1428,7 @@ void btc_hf_cb_handler(btc_msg_t *msg)
do { do {
param.audio_stat.state = ESP_HF_AUDIO_STATE_CONNECTED_MSBC; param.audio_stat.state = ESP_HF_AUDIO_STATE_CONNECTED_MSBC;
memcpy(param.audio_stat.remote_addr, &hf_local_param[idx].btc_hf_cb.connected_bda,sizeof(esp_bd_addr_t)); memcpy(param.audio_stat.remote_addr, &hf_local_param[idx].btc_hf_cb.connected_bda,sizeof(esp_bd_addr_t));
hf_local_param[idx].btc_hf_cb.sync_conn_hdl = p_data->hdr.sync_conn_handle;
param.audio_stat.sync_conn_handle = p_data->hdr.sync_conn_handle; param.audio_stat.sync_conn_handle = p_data->hdr.sync_conn_handle;
btc_hf_cb_to_app(ESP_HF_AUDIO_STATE_EVT, &param); btc_hf_cb_to_app(ESP_HF_AUDIO_STATE_EVT, &param);
} while (0); } while (0);
@ -1435,6 +1440,7 @@ void btc_hf_cb_handler(btc_msg_t *msg)
CHECK_HF_IDX(idx); CHECK_HF_IDX(idx);
do { do {
param.audio_stat.state = ESP_HF_AUDIO_STATE_DISCONNECTED; param.audio_stat.state = ESP_HF_AUDIO_STATE_DISCONNECTED;
hf_local_param[idx].btc_hf_cb.sync_conn_hdl = ESP_INVALID_CONN_HANDLE;
memcpy(param.audio_stat.remote_addr, &hf_local_param[idx].btc_hf_cb.connected_bda, sizeof(esp_bd_addr_t)); memcpy(param.audio_stat.remote_addr, &hf_local_param[idx].btc_hf_cb.connected_bda, sizeof(esp_bd_addr_t));
param.audio_stat.sync_conn_handle = p_data->hdr.sync_conn_handle; param.audio_stat.sync_conn_handle = p_data->hdr.sync_conn_handle;
btc_hf_cb_to_app(ESP_HF_AUDIO_STATE_EVT, &param); btc_hf_cb_to_app(ESP_HF_AUDIO_STATE_EVT, &param);
@ -1669,18 +1675,21 @@ void btc_hf_cb_handler(btc_msg_t *msg)
void btc_hf_get_profile_status(esp_hf_profile_status_t *param) void btc_hf_get_profile_status(esp_hf_profile_status_t *param)
{ {
int idx = 0;
param->hfp_ag_inited = false; // Not initialized by default param->hfp_ag_inited = false; // Not initialized by default
#if HFP_DYNAMIC_MEMORY == TRUE #if HFP_DYNAMIC_MEMORY == TRUE
if (hf_local_param) if (hf_local_param)
#endif #endif
{ {
if (hf_local_param[idx].btc_hf_cb.initialized) { for (int idx = 0; idx < BTC_HF_NUM_CB; idx++) {
param->hfp_ag_inited = true; if (hf_local_param[idx].btc_hf_cb.initialized) {
if (hf_local_param[idx].btc_hf_cb.connection_state == ESP_HF_CONNECTION_STATE_SLC_CONNECTED) { param->hfp_ag_inited = true;
param->conn_num++; if (hf_local_param[idx].btc_hf_cb.connection_state == ESP_HF_CONNECTION_STATE_SLC_CONNECTED) {
param->slc_conn_num++;
if (hf_local_param[idx].btc_hf_cb.sync_conn_hdl != ESP_INVALID_CONN_HANDLE) {
param->sync_conn_num++;
}
}
} }
} }
} }

View File

@ -114,6 +114,7 @@ static inline void btc_hf_client_cb_to_app(esp_hf_client_cb_event_t event, esp_h
static void clear_state(void) static void clear_state(void)
{ {
memset(&hf_client_local_param.btc_hf_client_cb, 0, sizeof(btc_hf_client_cb_t)); memset(&hf_client_local_param.btc_hf_client_cb, 0, sizeof(btc_hf_client_cb_t));
hf_client_local_param.btc_hf_client_cb.sync_conn_hdl = ESP_INVALID_CONN_HANDLE;
} }
static BOOLEAN is_connected(bt_bdaddr_t *bd_addr) static BOOLEAN is_connected(bt_bdaddr_t *bd_addr)
@ -1076,6 +1077,7 @@ void btc_hf_client_cb_handler(btc_msg_t *msg)
param.audio_stat.state = ESP_HF_CLIENT_AUDIO_STATE_CONNECTED; param.audio_stat.state = ESP_HF_CLIENT_AUDIO_STATE_CONNECTED;
memcpy(param.audio_stat.remote_bda, &hf_client_local_param.btc_hf_client_cb.connected_bda, memcpy(param.audio_stat.remote_bda, &hf_client_local_param.btc_hf_client_cb.connected_bda,
sizeof(esp_bd_addr_t)); sizeof(esp_bd_addr_t));
hf_client_local_param.btc_hf_client_cb.sync_conn_hdl = p_data->hdr.sync_conn_handle;
param.audio_stat.sync_conn_handle = p_data->hdr.sync_conn_handle; param.audio_stat.sync_conn_handle = p_data->hdr.sync_conn_handle;
btc_hf_client_cb_to_app(ESP_HF_CLIENT_AUDIO_STATE_EVT, &param); btc_hf_client_cb_to_app(ESP_HF_CLIENT_AUDIO_STATE_EVT, &param);
} while (0); } while (0);
@ -1085,6 +1087,7 @@ void btc_hf_client_cb_handler(btc_msg_t *msg)
param.audio_stat.state = ESP_HF_CLIENT_AUDIO_STATE_CONNECTED_MSBC; param.audio_stat.state = ESP_HF_CLIENT_AUDIO_STATE_CONNECTED_MSBC;
memcpy(param.audio_stat.remote_bda, &hf_client_local_param.btc_hf_client_cb.connected_bda, memcpy(param.audio_stat.remote_bda, &hf_client_local_param.btc_hf_client_cb.connected_bda,
sizeof(esp_bd_addr_t)); sizeof(esp_bd_addr_t));
hf_client_local_param.btc_hf_client_cb.sync_conn_hdl = p_data->hdr.sync_conn_handle;
param.audio_stat.sync_conn_handle = p_data->hdr.sync_conn_handle; param.audio_stat.sync_conn_handle = p_data->hdr.sync_conn_handle;
btc_hf_client_cb_to_app(ESP_HF_CLIENT_AUDIO_STATE_EVT, &param); btc_hf_client_cb_to_app(ESP_HF_CLIENT_AUDIO_STATE_EVT, &param);
} while (0); } while (0);
@ -1094,6 +1097,7 @@ void btc_hf_client_cb_handler(btc_msg_t *msg)
param.audio_stat.state = ESP_HF_CLIENT_AUDIO_STATE_DISCONNECTED; param.audio_stat.state = ESP_HF_CLIENT_AUDIO_STATE_DISCONNECTED;
memcpy(param.audio_stat.remote_bda, &hf_client_local_param.btc_hf_client_cb.connected_bda, memcpy(param.audio_stat.remote_bda, &hf_client_local_param.btc_hf_client_cb.connected_bda,
sizeof(esp_bd_addr_t)); sizeof(esp_bd_addr_t));
hf_client_local_param.btc_hf_client_cb.sync_conn_hdl = ESP_INVALID_CONN_HANDLE;
param.audio_stat.sync_conn_handle = p_data->hdr.sync_conn_handle; param.audio_stat.sync_conn_handle = p_data->hdr.sync_conn_handle;
btc_hf_client_cb_to_app(ESP_HF_CLIENT_AUDIO_STATE_EVT, &param); btc_hf_client_cb_to_app(ESP_HF_CLIENT_AUDIO_STATE_EVT, &param);
} while (0); } while (0);
@ -1211,7 +1215,10 @@ void btc_hf_client_get_profile_status(esp_hf_client_profile_status_t *param)
if (hf_client_local_param.btc_hf_client_cb.initialized) { if (hf_client_local_param.btc_hf_client_cb.initialized) {
param->hf_client_inited = true; param->hf_client_inited = true;
if (hf_client_local_param.btc_hf_client_cb.state == ESP_HF_CLIENT_CONNECTION_STATE_SLC_CONNECTED) { if (hf_client_local_param.btc_hf_client_cb.state == ESP_HF_CLIENT_CONNECTION_STATE_SLC_CONNECTED) {
param->conn_num++; param->slc_conn_num++;
if (hf_client_local_param.btc_hf_client_cb.sync_conn_hdl != ESP_INVALID_CONN_HANDLE) {
param->sync_conn_num++;
}
} }
} }
} }

View File

@ -844,6 +844,7 @@ void btc_hd_cb_handler(btc_msg_t *msg)
// } // }
// btc_storage_set_hidd((bt_bdaddr_t *)&p_data->conn.bda); // btc_storage_set_hidd((bt_bdaddr_t *)&p_data->conn.bda);
btc_hd_cb.status = BTC_HD_CONNECTED; btc_hd_cb.status = BTC_HD_CONNECTED;
btc_hd_cb.in_use = TRUE;
} else if (p_data->conn.conn_status == BTA_HD_CONN_STATE_DISCONNECTED) { } else if (p_data->conn.conn_status == BTA_HD_CONN_STATE_DISCONNECTED) {
btc_hd_cb.status = BTC_HD_DISCONNECTED; btc_hd_cb.status = BTC_HD_DISCONNECTED;
} }
@ -916,6 +917,8 @@ void btc_hd_cb_handler(btc_msg_t *msg)
btc_hd_cb_to_app(ESP_HIDD_CLOSE_EVT, &param); btc_hd_cb_to_app(ESP_HIDD_CLOSE_EVT, &param);
} }
btc_hd_cb.in_use = FALSE;
param.vc_unplug.status = p_data->conn.status; param.vc_unplug.status = p_data->conn.status;
param.vc_unplug.conn_status = p_data->conn.conn_status; param.vc_unplug.conn_status = p_data->conn.conn_status;
btc_hd_cb_to_app(ESP_HIDD_VC_UNPLUG_EVT, &param); btc_hd_cb_to_app(ESP_HIDD_VC_UNPLUG_EVT, &param);
@ -966,6 +969,12 @@ void btc_hd_get_profile_status(esp_hidd_profile_status_t *param)
if (btc_hd_cb.status == BTC_HD_CONNECTED) { if (btc_hd_cb.status == BTC_HD_CONNECTED) {
param->conn_num++; param->conn_num++;
} }
if (btc_hd_cb.in_use) {
param->plug_vc_dev_num++;
}
if (btc_hd_cb.app_registered) {
param->reg_app_num++;
}
} else { } else {
param->hidd_inited = false; param->hidd_inited = false;
} }

View File

@ -1582,6 +1582,11 @@ void btc_hh_get_profile_status(esp_hidh_profile_status_t *param)
if (btc_hh_cb.status == BTC_HH_DEV_CONNECTED) { if (btc_hh_cb.status == BTC_HH_DEV_CONNECTED) {
param->conn_num++; param->conn_num++;
} }
for (int i = 0; i < BTC_HH_MAX_ADDED_DEV; i++) {
if (memcmp(btc_hh_cb.added_devices[i].bd_addr, bd_addr_null, BD_ADDR_LEN) != 0) {
param->plug_vc_dev_num++;
}
}
} else { } else {
param->hidh_inited = false; param->hidh_inited = false;
} }

View File

@ -179,6 +179,7 @@ uint16_t btc_avrc_tg_get_rn_supported_evt(void);
bool btc_avrc_tg_check_rn_supported_evt(uint16_t evt_set); bool btc_avrc_tg_check_rn_supported_evt(uint16_t evt_set);
bool btc_avrc_tg_rn_evt_supported(uint8_t event_id); bool btc_avrc_tg_rn_evt_supported(uint8_t event_id);
bool btc_avrc_ct_rn_evt_supported(uint8_t event_id); bool btc_avrc_ct_rn_evt_supported(uint8_t event_id);
void btc_avrc_get_profile_status(esp_avrc_profile_status_t *param);
#endif ///BTC_AV_INCLUDED == TRUE #endif ///BTC_AV_INCLUDED == TRUE

View File

@ -55,6 +55,7 @@ typedef struct {
bool app_registered; bool app_registered;
bool service_dereg_active; bool service_dereg_active;
bool forced_disc; bool forced_disc;
bool in_use;
tBTA_HD_APP_INFO app_info; tBTA_HD_APP_INFO app_info;
tBTA_HD_QOS_INFO in_qos; tBTA_HD_QOS_INFO in_qos;
tBTA_HD_QOS_INFO out_qos; tBTA_HD_QOS_INFO out_qos;

View File

@ -211,6 +211,7 @@ typedef struct
{ {
bool initialized; bool initialized;
UINT16 handle; UINT16 handle;
UINT16 sync_conn_hdl;
bt_bdaddr_t connected_bda; bt_bdaddr_t connected_bda;
tBTA_AG_PEER_FEAT peer_feat; tBTA_AG_PEER_FEAT peer_feat;
tBTA_AG_CHLD_FEAT chld_feat; tBTA_AG_CHLD_FEAT chld_feat;

View File

@ -134,6 +134,7 @@ typedef struct
{ {
bool initialized; bool initialized;
UINT16 handle; UINT16 handle;
UINT16 sync_conn_hdl;
bt_bdaddr_t connected_bda; bt_bdaddr_t connected_bda;
esp_hf_client_connection_state_t state; esp_hf_client_connection_state_t state;
esp_hf_vr_state_t vr_state; esp_hf_vr_state_t vr_state;