diff --git a/components/bt/host/bluedroid/api/include/api/esp_hf_ag_api.h b/components/bt/host/bluedroid/api/include/api/esp_hf_ag_api.h index 84086118f3..c079614b29 100644 --- a/components/bt/host/bluedroid/api/include/api/esp_hf_ag_api.h +++ b/components/bt/host/bluedroid/api/include/api/esp_hf_ag_api.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -63,6 +63,7 @@ typedef enum ESP_HF_WBS_RESPONSE_EVT, /*!< Codec Status */ ESP_HF_BCS_RESPONSE_EVT, /*!< Final Codec Choice */ ESP_HF_PKT_STAT_NUMS_GET_EVT, /*!< Request number of packet different status */ + ESP_HF_PROF_STATE_EVT, /*!< Indicate HF init or deinit complete */ } esp_hf_cb_event_t; /// Dial type of ESP_HF_DIAL_EVT @@ -223,6 +224,13 @@ typedef union uint32_t tx_discarded; /*!< the total number of packets send lost */ } pkt_nums; /*!< AG callback param of ESP_HF_PKT_STAT_NUMS_GET_EVT */ + /** + * @brief ESP_HF_PROF_STATE_EVT + */ + struct ag_prof_stat_param { + esp_hf_prof_state_t state; /*!< hf profile state param */ + } prof_stat; /*!< status to indicate hf prof init or deinit */ + } esp_hf_cb_param_t; /*!< HFP AG callback param compound*/ /** @@ -284,6 +292,7 @@ esp_err_t esp_hf_ag_register_callback(esp_hf_cb_t callback); * * @brief Initialize the bluetooth HF AG module. * This function should be called after esp_bluedroid_enable() completes successfully. + * ESP_HF_PROF_STATE_EVT with ESP_HF_INIT_SUCCESS will reported to the APP layer. * * @return * - ESP_OK: if the initialization request is sent successfully @@ -297,6 +306,7 @@ esp_err_t esp_hf_ag_init(void); * * @brief De-initialize for HF AG module. * This function should be called only after esp_bluedroid_enable() completes successfully. + * ESP_HF_PROF_STATE_EVT with ESP_HF_DEINIT_SUCCESS will reported to the APP layer. * * @return * - ESP_OK: success @@ -504,13 +514,13 @@ esp_err_t esp_hf_ag_cind_response(esp_bd_addr_t remote_addr, /** * - * @brief Reponse for AT+COPS command from HF Client. + * @brief Response for AT+COPS command from HF Client. * As a precondition to use this API, Service Level Connection shall exist with HFP client. * * @param[in] remote_addr: remote bluetooth device address * @param[in] name: current operator name * @return - * - ESP_OK: reponse for AT+COPS command is sent to lower layer + * - ESP_OK: response for AT+COPS command is sent to lower layer * - ESP_ERR_INVALID_STATE: if bluetooth stack is not yet enabled * - ESP_FAIL: others * @@ -529,7 +539,7 @@ esp_err_t esp_hf_ag_cops_response(esp_bd_addr_t remote_addr, char *name); * @param[in] mode: current call mode (voice/data/fax) * @param[in] mpty: single or multi type * @param[in] number: current call number - * @param[in] type: international type or unknow + * @param[in] type: international type or unknown * @return * - ESP_OK: response to AT+CLCC command is sent to lower layer * - ESP_ERR_INVALID_STATE: if bluetooth stack is not yet enabled diff --git a/components/bt/host/bluedroid/api/include/api/esp_hf_client_api.h b/components/bt/host/bluedroid/api/include/api/esp_hf_client_api.h index 9353fc032b..cbc7277e65 100644 --- a/components/bt/host/bluedroid/api/include/api/esp_hf_client_api.h +++ b/components/bt/host/bluedroid/api/include/api/esp_hf_client_api.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -97,6 +97,7 @@ typedef enum { ESP_HF_CLIENT_BINP_EVT, /*!< requested number of last voice tag from AG */ ESP_HF_CLIENT_RING_IND_EVT, /*!< ring indication event */ ESP_HF_CLIENT_PKT_STAT_NUMS_GET_EVT, /*!< requested number of packet different status */ + ESP_HF_CLIENT_PROF_STATE_EVT, /*!< Indicate HF CLIENT init or deinit complete */ } esp_hf_client_cb_event_t; /// HFP client callback parameters @@ -266,6 +267,13 @@ typedef union { uint32_t tx_discarded; /*!< the total number of packets send lost */ } pkt_nums; /*!< HF callback param of ESP_HF_CLIENT_PKT_STAT_NUMS_GET_EVT */ + /** + * @brief ESP_HF_CLIENT_PROF_STATE_EVT + */ + struct hf_client_prof_stat_param { + esp_hf_prof_state_t state; /*!< hf client profile state param */ + } prof_stat; /*!< status to indicate hf client prof init or deinit */ + } esp_hf_client_cb_param_t; /*!< HFP client callback parameters */ /** @@ -323,6 +331,7 @@ esp_err_t esp_hf_client_register_callback(esp_hf_client_cb_t callback); * * @brief Initialize the bluetooth HFP client module. * This function should be called after esp_bluedroid_enable() completes successfully. + * ESP_HF_CLIENT_PROF_STATE_EVT with ESP_HF_INIT_SUCCESS will reported to the APP layer. * * @return * - ESP_OK: if the initialization request is sent successfully @@ -336,6 +345,7 @@ esp_err_t esp_hf_client_init(void); * * @brief De-initialize for HFP client module. * This function should be called only after esp_bluedroid_enable() completes successfully. + * ESP_HF_CLIENT_PROF_STATE_EVT with ESP_HF_DEINIT_SUCCESS will reported to the APP layer. * * @return * - ESP_OK: success @@ -422,7 +432,7 @@ esp_err_t esp_hf_client_start_voice_recognition(void); * As a precondition to use this API, Service Level Connection shall exist with AG. * * @return - * - ESP_OK: stoping voice recognition is sent to lower layer + * - ESP_OK: stopping voice recognition is sent to lower layer * - ESP_ERR_INVALID_STATE: if bluetooth stack is not yet enabled * - ESP_FAIL: others * diff --git a/components/bt/host/bluedroid/api/include/api/esp_hf_defs.h b/components/bt/host/bluedroid/api/include/api/esp_hf_defs.h index b7671ff1e7..ec41b8641a 100644 --- a/components/bt/host/bluedroid/api/include/api/esp_hf_defs.h +++ b/components/bt/host/bluedroid/api/include/api/esp_hf_defs.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -13,6 +13,16 @@ extern "C" { #endif +/// profile states +typedef enum { + ESP_HF_INIT_SUCCESS = 0, /*!< Indicate init successful */ + ESP_HF_INIT_ALREADY, /*!< Indicate init repeated */ + ESP_HF_INIT_FAIL, /*!< Indicate init fail */ + ESP_HF_DEINIT_SUCCESS, /*!< Indicate deinit successful */ + ESP_HF_DEINIT_ALREADY, /*!< Indicate deinit repeated */ + ESP_HF_DEINIT_FAIL, /*!< Indicate deinit fail */ +} esp_hf_prof_state_t; + /// in-band ring tone state typedef enum { ESP_HF_IN_BAND_RINGTONE_NOT_PROVIDED = 0, @@ -128,7 +138,7 @@ typedef enum { /// +CLCC address type typedef enum { - ESP_HF_CALL_ADDR_TYPE_UNKNOWN = 0x81, /*!< unkown address type */ + ESP_HF_CALL_ADDR_TYPE_UNKNOWN = 0x81, /*!< unknown address type */ ESP_HF_CALL_ADDR_TYPE_INTERNATIONAL = 0x91, /*!< international address */ } esp_hf_call_addr_type_t; @@ -160,7 +170,7 @@ typedef enum ESP_HF_NREC_START } esp_hf_nrec_t; -///+CCWA resposne status +///+CCWA response status typedef enum { ESP_HF_CALL_WAITING_INACTIVE, ESP_HF_CALL_WAITING_ACTIVE, diff --git a/components/bt/host/bluedroid/btc/profile/std/hf_ag/btc_hf_ag.c b/components/bt/host/bluedroid/btc/profile/std/hf_ag/btc_hf_ag.c index 99f7a19f2d..caa900e85a 100644 --- a/components/bt/host/bluedroid/btc/profile/std/hf_ag/btc_hf_ag.c +++ b/components/bt/host/bluedroid/btc/profile/std/hf_ag/btc_hf_ag.c @@ -316,6 +316,14 @@ bt_status_t btc_hf_init(void) { int idx = 0; + if (hf_local_param[idx].btc_hf_cb.initialized) { + esp_hf_cb_param_t param = { + .prof_stat.state = ESP_HF_INIT_ALREADY, + }; + btc_hf_cb_to_app(ESP_HF_PROF_STATE_EVT, ¶m); + return BT_STATUS_SUCCESS; + } + BTC_TRACE_DEBUG("%s - max_hf_clients=%d", __func__, btc_max_hf_clients); #if HFP_DYNAMIC_MEMORY == TRUE @@ -338,8 +346,6 @@ bt_status_t btc_hf_init(void) #endif clear_phone_state(); memset(&hf_local_param[idx].btc_hf_cb, 0, sizeof(btc_hf_cb_t)); - // custom initialization here - hf_local_param[idx].btc_hf_cb.initialized = true; // set audio path #if (BT_CONTROLLER_INCLUDED == TRUE) #if BTM_SCO_HCI_INCLUDED @@ -349,14 +355,24 @@ bt_status_t btc_hf_init(void) #endif esp_bredr_sco_datapath_set(data_path); #endif + return BT_STATUS_SUCCESS; } void btc_hf_deinit(void) { BTC_TRACE_EVENT("%s", __FUNCTION__); + + int idx = 0; + if (!hf_local_param[idx].btc_hf_cb.initialized) { + esp_hf_cb_param_t param = { + .prof_stat.state = ESP_HF_DEINIT_ALREADY, + }; + btc_hf_cb_to_app(ESP_HF_PROF_STATE_EVT, ¶m); + return; + } + btc_dm_disable_service(BTA_HFP_SERVICE_ID); - hf_local_param[0].btc_hf_cb.initialized = false; } static void btc_hf_cb_release(void) @@ -1268,7 +1284,13 @@ void btc_hf_cb_handler(btc_msg_t *msg) break; case BTA_AG_DISABLE_EVT: { + idx = 0; btc_hf_cb_release(); + if (hf_local_param[idx].btc_hf_cb.initialized) { + param.prof_stat.state = ESP_HF_DEINIT_SUCCESS; + btc_hf_cb_to_app(ESP_HF_PROF_STATE_EVT, ¶m); + } + hf_local_param[idx].btc_hf_cb.initialized = false; break; } case BTA_AG_REGISTER_EVT: @@ -1278,6 +1300,11 @@ void btc_hf_cb_handler(btc_msg_t *msg) hf_local_param[idx].btc_hf_cb.handle = p_data->reg.hdr.handle; BTC_TRACE_DEBUG("%s: BTA_AG_REGISTER_EVT," "hf_local_param[%d].btc_hf_cb.handle = %d", __FUNCTION__, idx, hf_local_param[idx].btc_hf_cb.handle); + if (!hf_local_param[idx].btc_hf_cb.initialized) { + param.prof_stat.state = ESP_HF_INIT_SUCCESS; + btc_hf_cb_to_app(ESP_HF_PROF_STATE_EVT, ¶m); + } + hf_local_param[idx].btc_hf_cb.initialized = true; break; } diff --git a/components/bt/host/bluedroid/btc/profile/std/hf_client/btc_hf_client.c b/components/bt/host/bluedroid/btc/profile/std/hf_client/btc_hf_client.c index 67973bc267..ea12a6928a 100644 --- a/components/bt/host/bluedroid/btc/profile/std/hf_client/btc_hf_client.c +++ b/components/bt/host/bluedroid/btc/profile/std/hf_client/btc_hf_client.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -169,12 +169,18 @@ bt_status_t btc_hf_client_init(void) { BTC_TRACE_EVENT("%s", __FUNCTION__); + if (hf_client_local_param.btc_hf_client_cb.initialized) { + esp_hf_client_cb_param_t param = { + .prof_stat.state = ESP_HF_INIT_ALREADY, + }; + btc_hf_client_cb_to_app(ESP_HF_CLIENT_PROF_STATE_EVT, ¶m); + return BT_STATUS_SUCCESS; + } + btc_dm_enable_service(BTA_HFP_HS_SERVICE_ID); clear_state(); - hf_client_local_param.btc_hf_client_cb.initialized = true; - #if (BT_CONTROLLER_INCLUDED == TRUE) #if BTM_SCO_HCI_INCLUDED uint8_t data_path = ESP_SCO_DATA_PATH_HCI; @@ -232,9 +238,15 @@ void btc_hf_client_deinit( void ) { BTC_TRACE_EVENT("%s", __FUNCTION__); - btc_dm_disable_service(BTA_HFP_HS_SERVICE_ID); + if (!hf_client_local_param.btc_hf_client_cb.initialized) { + esp_hf_client_cb_param_t param = { + .prof_stat.state = ESP_HF_DEINIT_ALREADY, + }; + btc_hf_client_cb_to_app(ESP_HF_CLIENT_PROF_STATE_EVT, ¶m); + return; + } - hf_client_local_param.btc_hf_client_cb.initialized = false; + btc_dm_disable_service(BTA_HFP_HS_SERVICE_ID); } /******************************************************************************* @@ -852,10 +864,21 @@ void btc_hf_client_cb_handler(btc_msg_t *msg) switch (event) { case BTA_HF_CLIENT_ENABLE_EVT: + break; case BTA_HF_CLIENT_DISABLE_EVT: + if (hf_client_local_param.btc_hf_client_cb.initialized) { + param.prof_stat.state = ESP_HF_DEINIT_SUCCESS, + btc_hf_client_cb_to_app(ESP_HF_CLIENT_PROF_STATE_EVT, ¶m); + } + hf_client_local_param.btc_hf_client_cb.initialized = false; break; case BTA_HF_CLIENT_REGISTER_EVT: hf_client_local_param.btc_hf_client_cb.handle = p_data->reg.handle; + if (!hf_client_local_param.btc_hf_client_cb.initialized) { + param.prof_stat.state = ESP_HF_INIT_SUCCESS, + btc_hf_client_cb_to_app(ESP_HF_CLIENT_PROF_STATE_EVT, ¶m); + } + hf_client_local_param.btc_hf_client_cb.initialized = true; break; case BTA_HF_CLIENT_OPEN_EVT: if (p_data->open.status == BTA_HF_CLIENT_SUCCESS) diff --git a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/bt_app_hf.c b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/bt_app_hf.c index 5c38abda40..5267bce644 100644 --- a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/bt_app_hf.c +++ b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/bt_app_hf.c @@ -46,6 +46,7 @@ const char *c_hf_evt_str[] = { "WBS_EVT", /*!< CURRENT CODEC EVT */ "BCS_EVT", /*!< CODEC NEGO EVT */ "PKT_STAT_EVT", /*!< REQUEST PACKET STATUS EVT */ + "PROF_STATE_EVT", /*!< Indicate HF init or deinit complete */ }; //esp_hf_connection_state_t @@ -293,7 +294,7 @@ void bt_app_send_data_shut_down(void) void bt_app_hf_cb(esp_hf_cb_event_t event, esp_hf_cb_param_t *param) { - if (event <= ESP_HF_PKT_STAT_NUMS_GET_EVT) { + if (event <= ESP_HF_PROF_STATE_EVT) { ESP_LOGI(BT_HF_TAG, "APP HFP event: %s", c_hf_evt_str[event]); } else { ESP_LOGE(BT_HF_TAG, "APP HFP invalid event %d", event); @@ -499,6 +500,17 @@ void bt_app_hf_cb(esp_hf_cb_event_t event, esp_hf_cb_param_t *param) ESP_LOGI(BT_HF_TAG, "ESP_HF_PKT_STAT_NUMS_GET_EVT: %d.", event); break; } + case ESP_HF_PROF_STATE_EVT: + { + if (ESP_HF_INIT_SUCCESS == param->prof_stat.state) { + ESP_LOGI(BT_HF_TAG, "AG PROF STATE: Init Complete"); + } else if (ESP_HF_DEINIT_SUCCESS == param->prof_stat.state) { + ESP_LOGI(BT_HF_TAG, "AG PROF STATE: Deinit Complete"); + } else { + ESP_LOGE(BT_HF_TAG, "AG PROF STATE error: %d", param->prof_stat.state); + } + break; + } default: ESP_LOGI(BT_HF_TAG, "Unsupported HF_AG EVT: %d.", event); diff --git a/examples/bluetooth/bluedroid/classic_bt/hfp_hf/main/bt_app_hf.c b/examples/bluetooth/bluedroid/classic_bt/hfp_hf/main/bt_app_hf.c index cca5956276..26f2af87d8 100644 --- a/examples/bluetooth/bluedroid/classic_bt/hfp_hf/main/bt_app_hf.c +++ b/examples/bluetooth/bluedroid/classic_bt/hfp_hf/main/bt_app_hf.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -49,6 +49,7 @@ const char *c_hf_evt_str[] = { "LAST_VOICE_TAG_NUMBER_EVT", /*!< requested number from AG event */ "RING_IND_EVT", /*!< ring indication event */ "PKT_STAT_EVT", /*!< requested number of packet status event */ + "PROF_STATE_EVT", /*!< Indicate HF CLIENT init or deinit complete */ }; // esp_hf_client_connection_state_t @@ -229,7 +230,7 @@ static void bt_app_hf_client_incoming_cb(const uint8_t *buf, uint32_t sz) /* callback for HF_CLIENT */ void bt_app_hf_client_cb(esp_hf_client_cb_event_t event, esp_hf_client_cb_param_t *param) { - if (event <= ESP_HF_CLIENT_PKT_STAT_NUMS_GET_EVT) { + if (event <= ESP_HF_CLIENT_PROF_STATE_EVT) { ESP_LOGI(BT_HF_TAG, "APP HFP event: %s", c_hf_evt_str[event]); } else { ESP_LOGE(BT_HF_TAG, "APP HFP invalid event %d", event); @@ -399,6 +400,17 @@ void bt_app_hf_client_cb(esp_hf_client_cb_event_t event, esp_hf_client_cb_param_ ESP_LOGE(BT_HF_TAG, "ESP_HF_CLIENT_PKT_STAT_NUMS_GET_EVT: %d", event); break; } + case ESP_HF_CLIENT_PROF_STATE_EVT: + { + if (ESP_HF_INIT_SUCCESS == param->prof_stat.state) { + ESP_LOGI(BT_HF_TAG, "HF PROF STATE: Init Complete"); + } else if (ESP_HF_DEINIT_SUCCESS == param->prof_stat.state) { + ESP_LOGI(BT_HF_TAG, "HF PROF STATE: Deinit Complete"); + } else { + ESP_LOGE(BT_HF_TAG, "HF PROF STATE error: %d", param->prof_stat.state); + } + break; + } default: ESP_LOGE(BT_HF_TAG, "HF_CLIENT EVT: %d", event); break;