From 78cbdfa3328c48ca0b4faef65c2b282a5fc00b2b Mon Sep 17 00:00:00 2001 From: weitianhua Date: Fri, 25 Oct 2019 15:53:16 +0800 Subject: [PATCH 1/5] HFP AG Example --- .../bt/host/bluedroid/bta/hf_ag/bta_ag_act.c | 5 +- .../bt/host/bluedroid/bta/hf_ag/bta_ag_main.c | 2 +- .../bt/host/bluedroid/bta/hf_ag/bta_ag_rfc.c | 2 + .../bt/host/bluedroid/bta/hf_ag/bta_ag_sco.c | 26 +- .../bluedroid/bta/hf_ag/include/bta_ag_int.h | 2 - .../bluedroid/bta/include/bta/bta_ag_co.h | 9 +- components/bt/host/bluedroid/hci/hci_hal_h4.c | 3 +- components/bt/sdkconfig.rename | 1 + .../classic_bt/hfp_ag/CMakeLists.txt | 6 + .../bluedroid/classic_bt/hfp_ag/Makefile | 9 + .../bluedroid/classic_bt/hfp_ag/README.md | 282 +++++++++++++++++ .../classic_bt/hfp_ag/main/CMakeLists.txt | 8 + .../classic_bt/hfp_ag/main/app_hf_msg_prs.c | 168 ++++++++++ .../classic_bt/hfp_ag/main/app_hf_msg_prs.h | 48 +++ .../classic_bt/hfp_ag/main/app_hf_msg_set.c | 252 +++++++++++++++ .../classic_bt/hfp_ag/main/app_hf_msg_set.h | 26 ++ .../classic_bt/hfp_ag/main/bt_app_core.c | 112 +++++++ .../classic_bt/hfp_ag/main/bt_app_core.h | 47 +++ .../classic_bt/hfp_ag/main/bt_app_hf.c | 297 ++++++++++++++++++ .../classic_bt/hfp_ag/main/bt_app_hf.h | 27 ++ .../classic_bt/hfp_ag/main/component.mk | 5 + .../classic_bt/hfp_ag/main/console_uart.c | 108 +++++++ .../classic_bt/hfp_ag/main/console_uart.h | 19 ++ .../classic_bt/hfp_ag/main/gpio_pcm_config.c | 92 ++++++ .../classic_bt/hfp_ag/main/gpio_pcm_config.h | 20 ++ .../bluedroid/classic_bt/hfp_ag/main/main.c | 121 +++++++ .../classic_bt/hfp_ag/sdkconfig.defaults | 9 + 27 files changed, 1685 insertions(+), 21 deletions(-) create mode 100644 examples/bluetooth/bluedroid/classic_bt/hfp_ag/CMakeLists.txt create mode 100644 examples/bluetooth/bluedroid/classic_bt/hfp_ag/Makefile create mode 100644 examples/bluetooth/bluedroid/classic_bt/hfp_ag/README.md create mode 100644 examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/CMakeLists.txt create mode 100644 examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/app_hf_msg_prs.c create mode 100644 examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/app_hf_msg_prs.h create mode 100644 examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/app_hf_msg_set.c create mode 100644 examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/app_hf_msg_set.h create mode 100644 examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/bt_app_core.c create mode 100644 examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/bt_app_core.h create mode 100644 examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/bt_app_hf.c create mode 100644 examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/bt_app_hf.h create mode 100644 examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/component.mk create mode 100644 examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/console_uart.c create mode 100644 examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/console_uart.h create mode 100644 examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/gpio_pcm_config.c create mode 100644 examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/gpio_pcm_config.h create mode 100644 examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/main.c create mode 100644 examples/bluetooth/bluedroid/classic_bt/hfp_ag/sdkconfig.defaults diff --git a/components/bt/host/bluedroid/bta/hf_ag/bta_ag_act.c b/components/bt/host/bluedroid/bta/hf_ag/bta_ag_act.c index 39387f594a..db0766470e 100644 --- a/components/bt/host/bluedroid/bta/hf_ag/bta_ag_act.c +++ b/components/bt/host/bluedroid/bta/hf_ag/bta_ag_act.c @@ -398,8 +398,9 @@ void bta_ag_rfc_close(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) bta_sys_conn_close(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr); /* call close call-out */ - // bta_ag_sco_co_close(close.hdr.handle); +#if (BTM_SCO_HCI_INCLUDED == TRUE) bta_ag_sco_co_close(); +#endif /* call close cback */ (*bta_ag_cb.p_cback)(BTA_AG_CLOSE_EVT, (tBTA_AG *) &close); @@ -463,7 +464,9 @@ void bta_ag_rfc_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) bta_ag_at_init(&p_scb->at_cb); /* call app open call-out */ +#if (BTM_SCO_HCI_INCLUDED == TRUE) bta_ag_sco_co_open(bta_ag_scb_to_idx(p_scb), p_scb->air_mode, BTA_HFP_SCO_OUT_PKT_SIZE, bta_ag_svc_id[p_scb->conn_service]); +#endif bta_sys_conn_open(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr); bta_ag_cback_open(p_scb, NULL, BTA_AG_SUCCESS); diff --git a/components/bt/host/bluedroid/bta/hf_ag/bta_ag_main.c b/components/bt/host/bluedroid/bta/hf_ag/bta_ag_main.c index 529047ac8e..4e146d0389 100644 --- a/components/bt/host/bluedroid/bta/hf_ag/bta_ag_main.c +++ b/components/bt/host/bluedroid/bta/hf_ag/bta_ag_main.c @@ -24,6 +24,7 @@ #include #include +#include "bta_ag_int.h" #include "bta/bta_api.h" #include "bta/bta_sys.h" #include "bta/bta_ag_api.h" @@ -32,7 +33,6 @@ #include "common/bt_defs.h" #include "common/bt_trace.h" #include "osi/allocator.h" -#include "bta_ag_int.h" #if (BTA_AG_INCLUDED == TRUE) /***************************************************************************** diff --git a/components/bt/host/bluedroid/bta/hf_ag/bta_ag_rfc.c b/components/bt/host/bluedroid/bta/hf_ag/bta_ag_rfc.c index b6288da9fc..7af0ba3206 100644 --- a/components/bt/host/bluedroid/bta/hf_ag/bta_ag_rfc.c +++ b/components/bt/host/bluedroid/bta/hf_ag/bta_ag_rfc.c @@ -188,7 +188,9 @@ static int bta_ag_data_cback(UINT16 port_handle, void *p_data, UINT16 len, UINT1 UNUSED(port_handle); /* call data call-out directly */ +#if (BTM_SCO_HCI_INCLUDED == TRUE) bta_ag_co_tx_write(handle, (UINT8 *) p_data, len); +#endif return 0; } diff --git a/components/bt/host/bluedroid/bta/hf_ag/bta_ag_sco.c b/components/bt/host/bluedroid/bta/hf_ag/bta_ag_sco.c index 31c852cc7e..351b7bca7c 100644 --- a/components/bt/host/bluedroid/bta/hf_ag/bta_ag_sco.c +++ b/components/bt/host/bluedroid/bta/hf_ag/bta_ag_sco.c @@ -66,9 +66,7 @@ enum BTA_AG_SCO_SHUTDOWN_E, /* shutdown request */ BTA_AG_SCO_CONN_OPEN_E, /* sco open */ BTA_AG_SCO_CONN_CLOSE_E, /* sco closed */ -#if (BTM_SCO_HCI_INCLUDED == TRUE) BTA_AG_SCO_CI_DATA_E /* SCO data ready */ -#endif }; #if (BTM_WBS_INCLUDED == TRUE ) @@ -579,6 +577,7 @@ static void bta_ag_create_sco(tBTA_AG_SCB *p_scb, BOOLEAN is_orig) /* tell sys to stop av if any */ bta_sys_sco_use(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr); +#if (BTM_SCO_HCI_INCLUDED == TRUE) #if (BTM_WBS_INCLUDED == TRUE) /* Allow any platform specific pre-SCO set up to take place */ bta_ag_sco_audio_state(bta_ag_scb_to_idx(p_scb), p_scb->app_id, SCO_STATE_SETUP, esco_codec); @@ -595,6 +594,7 @@ static void bta_ag_create_sco(tBTA_AG_SCB *p_scb, BOOLEAN is_orig) /* Allow any platform specific pre-SCO set up to take place */ bta_ag_sco_audio_state(bta_ag_scb_to_idx(p_scb), p_scb->app_id, SCO_STATE_SETUP); #endif +#endif #if (BTM_SCO_HCI_INCLUDED == TRUE) #if (BTM_WBS_INCLUDED == TRUE) @@ -735,10 +735,7 @@ void bta_ag_codec_negotiate(tBTA_AG_SCB *p_scb) *******************************************************************************/ static void bta_ag_sco_event(tBTA_AG_SCB *p_scb, UINT8 event) { -#if (BTM_SCO_HCI_INCLUDED == TRUE) tBTA_AG_SCO_CB *p_sco = &bta_ag_cb.sco; - BT_HDR *p_buf; -#endif #if (BTM_WBS_INCLUDED == TRUE) tBTA_AG_SCB *p_cn_scb = NULL; /* For codec negotiation */ #endif @@ -748,6 +745,7 @@ static void bta_ag_sco_event(tBTA_AG_SCB *p_scb, UINT8 event) bta_ag_sco_state_str(p_sco->state), event, bta_ag_sco_evt_str(event)); #if (BTM_SCO_HCI_INCLUDED == TRUE) + BT_HDR *p_buf; if (event == BTA_AG_SCO_CI_DATA_E) { UINT16 pkt_offset = 1 + HCI_SCO_PREAMBLE_SIZE; @@ -1512,7 +1510,9 @@ void bta_ag_sco_conn_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) *******************************************************************************/ void bta_ag_sco_conn_close(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) { +#if (BTM_SCO_HCI_INCLUDED == TRUE) UINT16 handle = bta_ag_scb_to_idx(p_scb); +#endif UNUSED(p_data); /* clear current scb */ @@ -1542,6 +1542,7 @@ void bta_ag_sco_conn_close(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) #endif else { +#if (BTM_SCO_HCI_INCLUDED == TRUE) sco_state_t sco_state = bta_ag_cb.sco.p_xfer_scb ? SCO_STATE_OFF_TRANSFER : SCO_STATE_OFF; #if (BTM_WBS_INCLUDED == TRUE) /* Indicate if the closing of audio is because of transfer */ @@ -1549,6 +1550,7 @@ void bta_ag_sco_conn_close(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) #else /* Indicate if the closing of audio is because of transfer */ bta_ag_sco_audio_state(handle, p_scb->app_id, sco_state); +#endif #endif bta_ag_sco_event(p_scb, BTA_AG_SCO_CONN_CLOSE_E); @@ -1626,17 +1628,15 @@ void bta_ag_sco_conn_rsp(tBTA_AG_SCB *p_scb, tBTM_ESCO_CONN_REQ_EVT_DATA *p_data /* tell sys to stop av if any */ bta_sys_sco_use(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr); -#if (BTM_WBS_INCLUDED == FALSE) - /* Allow any platform specific pre-SCO set up to take place */ - bta_ag_sco_audio_state(bta_ag_scb_to_idx(p_scb), p_scb->app_id, SCO_STATE_SETUP); -#else +#if (BTM_SCO_HCI_INCLUDED == TRUE) +#if (BTM_WBS_INCLUDED == TRUE) /* When HS initiated SCO, it cannot be WBS. */ /* Allow any platform specific pre-SCO set up to take place */ - bta_ag_sco_audio_state(bta_ag_scb_to_idx(p_scb), p_scb->app_id, SCO_STATE_SETUP, - BTA_AG_CODEC_CVSD); + bta_ag_sco_audio_state(bta_ag_scb_to_idx(p_scb), p_scb->app_id, SCO_STATE_SETUP, BTA_AG_CODEC_CVSD); +#else + /* Allow any platform specific pre-SCO set up to take place */ + bta_ag_sco_audio_state(bta_ag_scb_to_idx(p_scb), p_scb->app_id, SCO_STATE_SETUP); #endif - -#if (BTM_SCO_HCI_INCLUDED == TRUE) pcm_sample_rate = BTA_HFP_SCO_SAMP_RATE_8K; /* initialize SCO setup, no voice setting for AG, data rate <==> sample rate */ BTM_ConfigScoPath(bta_ag_sco_co_init(pcm_sample_rate, pcm_sample_rate, &codec_info, p_scb->app_id), diff --git a/components/bt/host/bluedroid/bta/hf_ag/include/bta_ag_int.h b/components/bt/host/bluedroid/bta/hf_ag/include/bta_ag_int.h index 440fe1931d..ae63ba4706 100644 --- a/components/bt/host/bluedroid/bta/hf_ag/include/bta_ag_int.h +++ b/components/bt/host/bluedroid/bta/hf_ag/include/bta_ag_int.h @@ -110,9 +110,7 @@ enum BTA_AG_CI_RX_WRITE_EVT, BTA_AG_RING_TOUT_EVT, BTA_AG_SVC_TOUT_EVT, - #if (BTM_SCO_HCI_INCLUDED == TRUE ) BTA_AG_CI_SCO_DATA_EVT, - #endif /* (BTM_SCO_HCI_INCLUDED == TRUE ) */ BTA_AG_CI_SLC_READY_EVT, BTA_AG_MAX_EVT, diff --git a/components/bt/host/bluedroid/bta/include/bta/bta_ag_co.h b/components/bt/host/bluedroid/bta/include/bta/bta_ag_co.h index 818611d8fa..fb1c1bfdef 100644 --- a/components/bt/host/bluedroid/bta/include/bta/bta_ag_co.h +++ b/components/bt/host/bluedroid/bta/include/bta/bta_ag_co.h @@ -21,13 +21,14 @@ * This is the interface file for audio gateway call-out and call-in functions. * ******************************************************************************/ -#ifndef BTA_AG_CIO_H -#define BTA_AG_CIO_H +#ifndef BTA_AG_CO_H +#define BTA_AG_CO_H #include "bta/bta_ag_api.h" #include "hci/hci_audio.h" #if (BTA_AG_INCLUDED == TRUE) +#if (BTM_SCO_HCI_INCLUDED == TRUE) /******************************************************************************* ** ** Function bta_ag_sco_audio_state @@ -155,6 +156,8 @@ extern void bta_ag_ci_rx_write(UINT16 handle, char *p_data, UINT16 len); ******************************************************************************/ extern void bta_ag_ci_slc_ready(UINT16 handle); +#endif /* #if (BTM_SCO_HCI_INCLUDED == TRUE) */ + #endif /* #if (BTA_AG_INCLUDED == TRUE) */ -#endif /* BTA_AG_CIO_H */ \ No newline at end of file +#endif /* BTA_AG_CO_H */ \ No newline at end of file diff --git a/components/bt/host/bluedroid/hci/hci_hal_h4.c b/components/bt/host/bluedroid/hci/hci_hal_h4.c index 85d3598dc1..5508841ea8 100644 --- a/components/bt/host/bluedroid/hci/hci_hal_h4.c +++ b/components/bt/host/bluedroid/hci/hci_hal_h4.c @@ -228,14 +228,15 @@ static void hci_update_adv_report_flow_control(BT_HDR *packet) // update adv free number hci_hal_env.adv_free_num ++; if (esp_vhci_host_check_send_available()){ +#if (BLE_INCLUDED == TRUE) // send hci cmd btsnd_hcic_ble_update_adv_report_flow_control(hci_hal_env.adv_free_num); +#endif hci_hal_env.adv_free_num = 0; } else { //do nothing } } - } #endif diff --git a/components/bt/sdkconfig.rename b/components/bt/sdkconfig.rename index 8c67aa5d30..c0fa93caa7 100644 --- a/components/bt/sdkconfig.rename +++ b/components/bt/sdkconfig.rename @@ -45,6 +45,7 @@ CONFIG_A2DP_ENABLE CONFIG_BT_A2DP_ENABL CONFIG_HFP_ENABLE CONFIG_BT_HFP_ENABLE CONFIG_HFP_ROLE CONFIG_BT_HFP_ROLE CONFIG_HFP_CLIENT_ENABLE CONFIG_BT_HFP_CLIENT_ENABLE +CONFIG_HFP_AG_ENABLE CONFIG_BT_HFP_AG_ENABLE CONFIG_HFP_AUDIO_DATA_PATH CONFIG_BT_HFP_AUDIO_DATA_PATH CONFIG_HFP_AUDIO_DATA_PATH_PCM CONFIG_BT_HFP_AUDIO_DATA_PATH_PCM CONFIG_HFP_AUDIO_DATA_PATH_HCI CONFIG_BT_HFP_AUDIO_DATA_PATH_HCI diff --git a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/CMakeLists.txt b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/CMakeLists.txt new file mode 100644 index 0000000000..ab8aa0ac17 --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/CMakeLists.txt @@ -0,0 +1,6 @@ +# The following lines of boilerplate have to be in your project's +# CMakeLists in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.5) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(hfp_ag) diff --git a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/Makefile b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/Makefile new file mode 100644 index 0000000000..b539a2d52b --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/Makefile @@ -0,0 +1,9 @@ +# +# This is a project Makefile. It is assumed the directory this Makefile resides in is a +# project subdirectory. +# + +PROJECT_NAME := hfp_ag + +include $(IDF_PATH)/make/project.mk + diff --git a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/README.md b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/README.md new file mode 100644 index 0000000000..c0e694e722 --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/README.md @@ -0,0 +1,282 @@ +# Hands-Free Audio Gateway + +This example is to show how to use the APIs of Hands-Free (HF) Audio Gateway (AG) Component and the effects of them with the help of user commands. You can use this example to communicate with a Hands-Free Unit (e.g. a headphone set). This example uses UART as a transportation of user commands and configured GPIO for PCM audio data stream. + +## How to use example + +### Hardware Required + +If possible, example should be able to run on any commonly available ESP32 development board and is supposed to connect to _Hands Free Unit example (hfp_hf)_ in ESP-IDF. + +### Configure the project + +``` +idf.py menuconfig +``` + +- Enable `Classic Bluetooth`, `Hands Free/Handset` and `Aduio Gateway` under `Component config ---> Bluetooth ---> Bluedroid Options`. +- When using PCM as the data path and this example configures PCM audio data to GPIO pins. You can link the GPIO pins to a speaker via i2s port. PCM data path does not support mSBC codec but CVSD codec. +- When using HCI data path, ESP32 support both CVSD and mSBC codec. + +### Build and Flash + +Build the project and flash it to the board, then run monitor tool to view serial output: + +``` +idf.py -p PORT flash monitor +``` + +(Replace PORT with the name of the serial port to use.) + +(To exit the serial monitor, type ``Ctrl-]``.) + +See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects. + +## Example Output + +When you run this example the command table will prints like: + +``` +######################################################################## +HFP AG command usage manual +HFP AG commands begins with "hf" and ends with ";" +Supported commands are as follows, arguments are embraced with < and > + +hf con; -- setup connection with peer device +hf dis; -- release connection with peer device +hf cona; -- setup audio connection with peer device +hf disa; -- release connection with peer device +hf vron; -- start voice recognition +hf vroff; -- stop voice recognition +hf vu ; -- volume update + tgt: 0-speaker, 1-microphone + vol: volume gain ranges from 0 to 15 +hf ind ; -- unsolicited notify device notification to HF Client + call: call status [0,1] + callsetup: call setup status [0,3] + ntk: network status [0,1] + sig: signal strength value from 0~5 +hf ate ; -- send extended at error code + rep: response code from 0 to 7 + err: error code from 0 to 32 +hf iron; -- inband ring tone provided +hf iroff; -- inband ring tone not provided +hf ac; -- Answer Incoming Call from AG +hf rc; -- Reject Incoming Call from AG +hf d ; -- Dial Number by AG, e.g. hf d 11223344 +hf end; -- End up a call by AG +hf h; -- to see the command for HFP AG +######################################################################## +``` + +The commands help table will print out in monitor whenever you type `hf h;` or input a command that is not required by the command parse rule. + +### Service Level Connection and Disconnection + +You can type `hf con;` to establish a service level connection with HF Unit device and log prints like: + +``` +E (100147) CNSL: Command [hf dis;] +disconnect +W (100427) BT_RFCOMM: port_rfc_closed RFCOMM connection in state 3 closed: Closed (res: 19) +W (100427) BT_APPL: BTA_HF_CLIENT_SCO_SHUTDOWN_ST: Ignoring event 3 +E (100427) BT_HF: APP HFP event: CONNECTION_STATE_EVT +E (100437) BT_HF: --connection state disconnected, peer feats 0x0, chld_feats 0x0 +``` + +**Note: Only after HF service is initiated and a service level connection exists between the HF Unit and AG that other commands are available.** + +You can type `hf dis;` to disconnect with the connected HF Unit device, and log prints like: + +``` +E (100147) CNSL: Command [hf dis;] +disconnect +W (100427) BT_RFCOMM: port_rfc_closed RFCOMM connection in state 3 closed: Closed (res: 19) +W (100427) BT_APPL: BTA_HF_CLIENT_SCO_SHUTDOWN_ST: Ignoring event 3 +E (100427) BT_HF: APP HFP event: CONNECTION_STATE_EVT +E (100437) BT_HF: --connection state disconnected, peer feats 0x0, chld_feats 0x0 +``` + +### Audio Connection and Disconnection + +You can type `hf cona;` to establish the audio connection between HF Unit and AG device. Also, you can type `hf disa;` to close the audio data stream. + +#### Situations for Audio Connection + +- Answer an incoming call +- Enable voice recognition +- Dial an outgoing call + +#### Situations for Audio Disconnection + +- Reject an incoming call +- Disable the voice recognition + +#### Audio Data path + +ESP32 supports two type of audio data pth: PCM and HCI. + +- PCM : When using PCM audio data stream is "matrixed" to GPIO pins and you should link these GPIO pins to a speaker via i2s port. +- HCI : When using HCI audio data stream will act in "loopback" mode. For example, you can hear your own voice when you place a call to a phone connected with a ESP32 development borad. + +#### Codec + +ESP32 supports both CVSD and mSBC codec. HF Unit and AG device determine which codec to use when establishing a service level connection. The choice of codec also depends on the user's configuration in `menuconfig`. + +Since CVSD is the default codec in HFP, we just show the situation using mSBC : + +- If you enable `BT_HFP_WBS_ENABLE` in `menuconfig`, mSBC will be available. +- If both HF Unit and AG support mSBC and also `BT_HFP_WBS_ENABLE` is enabled, ESP32 chooses mSBC. +- If you use PCM data path, mSBC is not available. + +### Answer or Reject an Incoming Call + +#### Answer an Incoming Call + +You can type `hf ac;` to answer an incoming call and log prints like: + +``` +E (1066280) CNSL: Command [hf ac;] +Answer Call from AG. +W (1066280) BT_APPL: BTA_AG_SCO_CODEC_ST: Ignoring event 1 +I (1067200) BT_APP_HF: APP HFP event: BCS_EVT +I (1067200) BT_APP_HF: --AG choose codec mode: CVSD Only +E (1067230) BT_BTM: btm_sco_connected, handle 180 +I (1067240) BT_APP_HF: APP HFP event: AUDIO_STATE_EVT +I (1067240) BT_APP_HF: --Audio State connected +``` + +#### Reject an Incoming Call + +You can type `hf rc;` to reject an incoming call and log prints like: + +``` +E (10040) CNSL: Command [hf rc;] +Reject Call from AG. +I (1067240) BT_APP_HF: APP HFP event: AUDIO_STATE_EVT +I (1067240) BT_APP_HF: --Audio State disconnected +``` + +#### End Up a Call + +You can type `hf end;` to end up the current ongoing call and log prints like: + +``` +E (40390) CNSL: Command [hf end;] +End Call from AG. +I (1067240) BT_APP_HF: APP HFP event: AUDIO_STATE_EVT +I (1067240) BT_APP_HF: --Audio State disconnected +``` + +### Dial Number + +You can type `hf d ;` to dial `` from AG and log prints like: + +``` +E (105600) CNSL: Command [hf d 18629485549;] +Dial number 18629485549 +I (105610) BT_APP_HF: APP HFP event: AUDIO_STATE_EVT +I (105610) BT_APP_HF: --Audio State connecting +I (106120) BT_APP_HF: APP HFP event: BCS_EVT +I (106130) BT_APP_HF: --AG choose codec mode: CVSD Only +E (106160) BT_BTM: btm_sco_connected, handle 180 +I (106160) BT_APP_HF: APP HFP event: AUDIO_STATE_EVT +I (106160) BT_APP_HF: --Audio State connected + +``` + +### Volume Control + +You can type `hf vu ;` to sync volume gain of headset or microphone. The parameter set: + +- `` : 0 - headset, 1 - microphone. +- `` : Integer among 0 - 15. + +For example, `hf vu 0 9;` sync the volume of headset and log on AG side prints `volume update`, on HF Unit side log prints like: + +``` +E (17087) BT_HF: APP HFP event: VOLUME_CONTROL_EVT +E (17087) BT_HF: --volume_target: SPEAKER, volume 9 + +``` + +And also, `hf vu 1 9;` sync the volume gain of microphone and log on HF Unit side prints like: + +``` +E (32087) BT_HF: APP HFP event: VOLUME_CONTROL_EVT +E (32087) BT_HF: --volume_target: MICROPHONE, volume 9 + +``` + +#### Voice Recognition + +You can type `hf vron;` to start the voice recognition of AG and type `hf vroff;` to end the voice recognition. Both command will notify the HF Unit the status of voice recognition. For example, type `hf vron;` and log prints like: + +``` +E (203128) CNSL: Command [hf vron;] +Start Voice Recognition. +I (203138) BT_APP_HF: APP HFP event: AUDIO_STATE_EVT +I (203138) BT_APP_HF: --Audio State connecting +I (203148) BT_APP_HF: APP HFP event: AUDIO_STATE_EVT +I (1014138) BT_APP_HF: --Audio State connected + +``` + +#### Notify Device Notification + +When use `hf ind ` AG will send some device status to HF Unit. Log on AG will printout like: `Device Indicator Changed!` and on HF Unit side will prints like: + +``` +E (293641) BT_HF: APP HFP event: CALL_IND_EVT +E (293641) BT_HF: --Call indicator call in progress +E (293641) BT_HF: APP HFP event: CALL_SETUP_IND_EVT +E (293651) BT_HF: --Call setup indicator INCOMING +E (293651) BT_HF: APP HFP event: SIGNAL_STRENGTH_IND_EVT +E (293661) BT_HF: -- signal strength: 5 + +``` + +**Note: AG only sends changed status to HF Unit.** + +#### Send Extended AT Error Code + +You can type `hf ate ` to send extended AT error coed to HF Unit. Parameter set: + +- `` : integer among 0 - 7. +- `` : integer among 0 - 32. + +When you type `hf ate 7 7;` log on AG side prints like `Send CME Error.` and on HF Unit side prints like: + +``` +E (448146) BT_HF: APP HFP event: AT_RESPONSE +E (448146) BT_HF: --AT response event, code 7, cme 7 + +``` + +#### Inband Ring Tone Enable and Disable + +You can type `hf iron;` to enable inband ring tone and type `hf iroff;` to disable inband ring tone. Log on AG side prints like `Device Indicator Changed!` and on HF Unit side prints like: + +``` +E (19546) BT_HF: APP HFP event: INBAND_RING_TONE_EVT +E (19556) BT_HF: --inband ring state Provided + +``` + +## Troubleshooting + +- You should type the command in the terminal according to the format described in the command help table. +- Not all commands in the table are supported by HF Unit. +- If you want to use AG to establish a service level connection with HF Unit, you should add the MAC address of HF Unit in `hfp_hf/main/bt_app.c`, for example: `esp_bd_addr_t peer_addr = {0xb4, 0xe6, 0x2d, 0xeb, 0x09, 0x93};` +- Use `esp_hf_client_register_callback()` and `esp_hf_client_init();` before establishing a service level connection. + +## Example Breakdown + +This example has relatively more source files than other bluetooth examples because _Hands Free Profile_ is somehow complex. But we want to show the functions of _Hands Free Profile_ in a simple way, so we use the _Commands and Effects_ scheme to show the usage of APIs of HFP in ESP-IDF. + +- The example will respond to user command through UART console. Please go to `hfp_hf/main/console_uart.c` for the configuration details. +- For voice interface, ESP32 has provided PCM input/output signals which can be mapped to GPIO pins, please go to `hfp_hf/main/gpio_pcm_config.c` for the configuration details. +- If you want to fix the command table, please refer to `hfp_hf/main/app_hf_msg_set.c`. +- If you want to fix the command parse rules, please refer to `hfp_hf/main/app_hf_msg_prs.c`. +- If you want to fix the responses of AG or want to fix the log, please refer to `hfp_hf/main/bt_app_hf.c`. +- Task configuration part is in `hfp_hf/main/bt_app_core.c`. \ No newline at end of file diff --git a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/CMakeLists.txt b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/CMakeLists.txt new file mode 100644 index 0000000000..eff055634e --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/CMakeLists.txt @@ -0,0 +1,8 @@ +idf_component_register(SRCS "app_hf_msg_prs.c" + "app_hf_msg_set.c" + "bt_app_core.c" + "bt_app_hf.c" + "console_uart.c" + "gpio_pcm_config.c" + "main.c" + INCLUDE_DIRS ".") \ No newline at end of file diff --git a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/app_hf_msg_prs.c b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/app_hf_msg_prs.c new file mode 100644 index 0000000000..2610bf2398 --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/app_hf_msg_prs.c @@ -0,0 +1,168 @@ +/* + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ + +#include +#include +#include +#include +#include +#include +#include "app_hf_msg_prs.h" +#include "app_hf_msg_set.h" + +// according to the design, message header length shall be no less than 2. +#define HF_MSG_HDR_LEN (3) +const static char hf_msg_hdr[HF_MSG_HDR_LEN] = {'h', 'f', ' '}; + +// according to the design, message header length shall be no less than 2. +#define HF_MSG_TAIL_LEN (1) +const static char hf_msg_tail[HF_MSG_TAIL_LEN] = {';'}; + +void hf_msg_parser_reset_state(hf_msg_prs_cb_t *prs) +{ + prs->state = HF_MSG_PRS_IDLE; + prs->cnt = 0; + prs->h_idx = 0; + prs->t_idx = 0; +} + +void hf_msg_parser_register_callback(hf_msg_prs_cb_t *prs, hf_msg_callback cb) +{ + prs->callback = cb; +} + +hf_msg_prs_err_t hf_msg_parse(char c, hf_msg_prs_cb_t *prs) +{ + hf_msg_prs_err_t err = HF_MSG_PRS_ERR_IN_PROGRESS; + switch (prs->state) + { + case HF_MSG_PRS_IDLE: + { + if (c == hf_msg_hdr[0]) { + prs->state = HF_MSG_PRS_HDR; + prs->buf[0] = c; + prs->cnt = 1; + prs->h_idx = 1; + } else { + err = HF_MSG_PRS_ERR_HDR_UNDETECTED; + } + } + break; + + case HF_MSG_PRS_HDR: + { + if (c == hf_msg_hdr[prs->h_idx]) { + prs->buf[prs->cnt++] = c; + if (++(prs->h_idx) == HF_MSG_HDR_LEN) { + prs->state = HF_MSG_PRS_PAYL; + prs->t_idx = 0; + } + } else { + hf_msg_parser_reset_state(prs); + err = HF_MSG_PRS_ERR_HDR_SYNC_FAILED; + } + } + break; + + case HF_MSG_PRS_PAYL: + { + prs->buf[prs->cnt++] = c; + if (c == hf_msg_tail[prs->t_idx]) { + if (++(prs->t_idx) == HF_MSG_TAIL_LEN) { + prs->buf[prs->cnt] = '\0'; + prs->callback(prs->buf, prs->cnt); + hf_msg_parser_reset_state(prs); + err = HF_MSG_PRS_ERR_OK; + break; + } + } else { + prs->t_idx = 0; + } + + if (prs->cnt >= HF_MSG_LEN_MAX) { + hf_msg_parser_reset_state(prs); + err = HF_MSG_PRS_ERR_BUF_OVERFLOW; + } + } + break; + } + return err; +} + + +void hf_msg_split_args(char *start, char *end, char **argv, int *argn) +{ + if (argn == NULL || *argn == 0) { + return; + } + + memset(argv, 0, (*argn) * sizeof(void *)); + + int max_argn = *argn; + *argn = 0; + + char *p = start; + for (int i = 0; i < max_argn; ++i) { + while (isspace((int)*p) && p != end) { + ++p; + } + if (p == end) { + return; + } + + argv[i] = p++; + ++(*argn); + + while (!isspace((int)*p) && p != end) { + ++p; + } + + if (p == end) { + return; + } else { + *p = '\0'; + ++p; + } + } +} + +void hf_msg_args_parser(char *buf, int len) +{ + char *argv[HF_MSG_ARGS_MAX]; + int argn = HF_MSG_ARGS_MAX; + char *start = buf + HF_MSG_HDR_LEN; + // set the command terminitor to '\0' + char *end = buf + len - HF_MSG_TAIL_LEN; + *end = '\0'; + + hf_msg_split_args(start, end, argv, &argn); + + if (argn == 0) { + return; + } + + bool cmd_supported = false; + + hf_msg_hdl_t *cmd_tbl = hf_get_cmd_tbl(); + size_t cmd_tbl_size = hf_get_cmd_tbl_size(); + for (int i = 0; i < cmd_tbl_size; ++i) { + hf_msg_hdl_t *hdl = &cmd_tbl[i]; + if (strcmp(argv[0], hdl->str) == 0) { + if (hdl->handler) { + hdl->handler(argn, argv); + cmd_supported = true; + break; + } + } + } + if (!cmd_supported) { + printf("unsupported command\n"); + hf_msg_show_usage(); + } + return; +} diff --git a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/app_hf_msg_prs.h b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/app_hf_msg_prs.h new file mode 100644 index 0000000000..131a7a5418 --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/app_hf_msg_prs.h @@ -0,0 +1,48 @@ +/* + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ + +#ifndef __APP_HF_MSG_PRS_H__ +#define __APP_HF_MSG_PRS_H__ + +typedef enum { + HF_MSG_PRS_ERR_OK = 0, // a complete message is finished + HF_MSG_PRS_ERR_IN_PROGRESS, // message parsing is in progress + HF_MSG_PRS_ERR_HDR_UNDETECTED, // header not detected + HF_MSG_PRS_ERR_HDR_SYNC_FAILED, // failed to sync header + HF_MSG_PRS_ERR_BUF_OVERFLOW, // exceeds the buffer size: HF_MSG_LEN_MAX +} hf_msg_prs_err_t; + +typedef enum { + HF_MSG_PRS_IDLE = 0, + HF_MSG_PRS_HDR, + HF_MSG_PRS_PAYL, +} hf_msg_prs_state_t; + +typedef void (*hf_msg_callback)(char *buf, int len); + +#define HF_MSG_LEN_MAX (128) + +typedef struct { + hf_msg_prs_state_t state; + char buf[HF_MSG_LEN_MAX + 1]; + int cnt; + int h_idx; + int t_idx; + hf_msg_callback callback; +} hf_msg_prs_cb_t; + +void hf_msg_parser_reset_state(hf_msg_prs_cb_t *prs); + +void hf_msg_parser_register_callback(hf_msg_prs_cb_t *prs, hf_msg_callback cb); + +hf_msg_prs_err_t hf_msg_parse(char c, hf_msg_prs_cb_t *prs); + +void hf_msg_show_usage(void); + +#endif /* __APP_HF_MSG_PRS_H__*/ + diff --git a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/app_hf_msg_set.c b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/app_hf_msg_set.c new file mode 100644 index 0000000000..00aadb3a4d --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/app_hf_msg_set.c @@ -0,0 +1,252 @@ +/* + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ + +#include +#include +#include "esp_hf_ag_api.h" +#include "app_hf_msg_set.h" +#include "bt_app_hf.h" + +void hf_msg_show_usage(void) +{ + printf("########################################################################\n"); + printf("HFP AG command usage manual\n"); + printf("HFP AG commands begins with \"hf\" and ends with \";\"\n"); + printf("Supported commands are as follows, arguments are embraced with < and >\n\n"); + printf("hf con; -- setup connection with peer device\n"); + printf("hf dis; -- release connection with peer device\n"); + printf("hf cona; -- setup audio connection with peer device\n"); + printf("hf disa; -- release connection with peer device\n"); + printf("hf vron; -- start voice recognition\n"); + printf("hf vroff; -- stop voice recognition\n"); + printf("hf vu ; -- volume update\n"); + printf(" tgt: 0-speaker, 1-microphone\n"); + printf(" vol: volume gain ranges from 0 to 15\n"); + printf("hf ind ; -- unsolicited notify device notification to HF Client\n"); + printf(" call: call status [0,1]\n"); + printf(" callsetup: call setup status [0,3]\n"); + printf(" ntk: network status [0,1]\n"); + printf(" sig: signal strength value from 0~5\n"); + printf("hf ate ; -- send extended at error code\n"); + printf(" rep: response code from 0 to 7\n"); + printf(" err: error code from 0 to 32\n"); + printf("hf iron; -- inband ring tone provided\n"); + printf("hf iroff; -- inband ring tone not provided\n"); + printf("hf ac; -- Answer Incoming Call from AG\n"); + printf("hf rc; -- Reject Incoming Call from AG\n"); + printf("hf d ; -- Dial Number by AG, e.g. hf d 11223344\n"); + printf("hf end; -- End up a call by AG\n"); + printf("hf h; -- to see the command for HFP AG\n"); + printf("########################################################################\n"); +} + +#define HF_CMD_HANDLER(cmd) static void hf_##cmd##_handler(int argn, char **argv) + +HF_CMD_HANDLER(help) +{ + hf_msg_show_usage(); +} + +HF_CMD_HANDLER(conn) +{ + printf("Connect.\n"); + esp_bt_hf_connect(hf_peer_addr); +} + +HF_CMD_HANDLER(disc) +{ + printf("Disconnect\n"); + esp_bt_hf_disconnect(hf_peer_addr); +} + +HF_CMD_HANDLER(conn_audio) +{ + printf("Connect Audio\n"); + esp_bt_hf_connect_audio(hf_peer_addr); +} + +HF_CMD_HANDLER(disc_audio) +{ + printf("Disconnect Audio\n"); + esp_bt_hf_disconnect_audio(hf_peer_addr); +} + +//AT+BVRA +HF_CMD_HANDLER(vra_on) +{ + printf("Start Voice Recognition.\n"); + esp_bt_hf_vra(hf_peer_addr,1); +} +//AT+BVRA +HF_CMD_HANDLER(vra_off) +{ + printf("Stop Voicer Recognition.\n"); + esp_bt_hf_vra(hf_peer_addr,0); +} + +//AT+VGS or AT+VGM +HF_CMD_HANDLER(volume_control) +{ + if (argn != 3) { + printf("Insufficient number of arguments"); + return; + } + int target, volume; + if (sscanf(argv[1], "%d", &target) != 1 || + (target != ESP_HF_VOLUME_CONTROL_TARGET_SPK && + target != ESP_HF_VOLUME_CONTROL_TARGET_MIC)) { + printf("Invalid argument for target %s\n", argv[1]); + return; + } + if (sscanf(argv[2], "%d", &volume) != 1 || + (volume < 0 || volume > 15)) { + printf("Invalid argument for volume %s\n", argv[2]); + return; + } + printf("Volume Update\n"); + esp_bt_hf_volume_control(hf_peer_addr, target, volume); +} + +//+CIEV +HF_CMD_HANDLER(ind_change) +{ + if (argn != 5) { + printf("Insufficient number of arguments"); + return; + } + + int call_state, ntk_state, call_setup_state, signal; + + if (sscanf(argv[1], "%d", &call_state) != 1 || + (call_state != ESP_HF_CALL_STATUS_NO_CALLS && + call_state != ESP_HF_CALL_STATUS_CALL_IN_PROGRESS)) { + printf("Invalid argument for call state %s\n", argv[1]); + return; + } + if (sscanf(argv[2], "%d", &call_setup_state) != 1 || + (call_setup_state < ESP_HF_CALL_SETUP_STATUS_IDLE || call_setup_state > ESP_HF_CALL_SETUP_STATUS_OUTGOING_ALERTING)) { + printf("Invalid argument for callsetup state %s\n", argv[2]); + return; + } + if (sscanf(argv[3], "%d", &ntk_state) != 1 || + (ntk_state != ESP_HF_NETWORK_STATE_NOT_AVAILABLE && + ntk_state != ESP_HF_NETWORK_STATE_AVAILABLE)) { + printf("Invalid argument for netwrok state %s\n", argv[3]); + return; + } + if (sscanf(argv[4], "%d", &signal) != 1 || + (signal < 0 || signal > 5)) { + printf("Invalid argument for signal %s\n", argv[4]); + return; + } + printf("Device Indicator Changed!\n"); + esp_bt_hf_indchange_notification(hf_peer_addr, call_state, call_setup_state, ntk_state, signal); +} + +//AT+CMEE +HF_CMD_HANDLER(cme_err) +{ + if (argn != 3) { + printf("Insufficient number of arguments"); + return; + } + + int response_code, error_code; + if (sscanf(argv[1], "%d", &response_code) != 1 || + (response_code < ESP_HF_AT_RESPONSE_CODE_OK && response_code > ESP_HF_AT_RESPONSE_CODE_CME)) { + printf("Invalid argument for response_code %s\n", argv[1]); + return; + } + + if (sscanf(argv[2], "%d", &error_code) != 1 || + (error_code < ESP_HF_CME_AG_FAILURE || error_code > ESP_HF_CME_NETWORK_NOT_ALLOWED)) { + printf("Invalid argument for volume %s\n", argv[2]); + return; + } + + printf("Send CME Error.\n"); + esp_bt_hf_cmee_response(hf_peer_addr,response_code,error_code); +} + +//+BSIR:1 +HF_CMD_HANDLER(ir_on) +{ + printf("Enable Voicer Recognition.\n"); + esp_bt_hf_bsir(hf_peer_addr,1); +} + +//+BSIR:0 +HF_CMD_HANDLER(ir_off) +{ + printf("Disable Voicer Recognition.\n"); + esp_bt_hf_bsir(hf_peer_addr,0); +} + +//Answer Call from AG +HF_CMD_HANDLER(ac) +{ + printf("Answer Call from AG.\n"); + char *number = {"186xxxx5549"}; + esp_bt_hf_answer_call(hf_peer_addr,1,0,1,1,number,0); +} + +//Reject Call from AG +HF_CMD_HANDLER(rc) +{ + printf("Reject Call from AG.\n"); + char *number = {"186xxxx5549"}; + esp_bt_hf_reject_call(hf_peer_addr,0,0,0,0,number,0); +} + +//End Call from AG +HF_CMD_HANDLER(end) +{ + printf("End Call from AG.\n"); + char *number = {"186xxxx5549"}; + esp_bt_hf_end_call(hf_peer_addr,0,0,0,0,number,0); +} + +//Dial Call from AG +HF_CMD_HANDLER(d) +{ + if (argn != 2) { + printf("Insufficient number of arguments"); + } else { + printf("Dial number %s\n", argv[1]); + esp_bt_hf_out_call(hf_peer_addr,1,0,1,2,argv[1],0); + } +} + +static hf_msg_hdl_t hf_cmd_tbl[] = { + {0, "h", hf_help_handler}, + {5, "con", hf_conn_handler}, + {10, "dis", hf_disc_handler}, + {20, "cona", hf_conn_audio_handler}, + {30, "disa", hf_disc_audio_handler}, + {40, "vu", hf_volume_control_handler}, + {50, "ind", hf_ind_change_handler}, + {60, "vron", hf_vra_on_handler}, + {70, "vroff", hf_vra_off_handler}, + {80, "ate", hf_cme_err_handler}, + {90, "iron", hf_ir_on_handler}, + {100, "iroff", hf_ir_off_handler}, + {110, "ac", hf_ac_handler}, + {120, "rc", hf_rc_handler}, + {130, "end", hf_end_handler}, + {140, "d", hf_d_handler}, +}; + +hf_msg_hdl_t *hf_get_cmd_tbl(void) +{ + return hf_cmd_tbl; +} + +size_t hf_get_cmd_tbl_size(void) +{ + return sizeof(hf_cmd_tbl) / sizeof(hf_msg_hdl_t); +} diff --git a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/app_hf_msg_set.h b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/app_hf_msg_set.h new file mode 100644 index 0000000000..de59abf832 --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/app_hf_msg_set.h @@ -0,0 +1,26 @@ +/* + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ + +#ifndef __APP_HF_MSG_SET_H__ +#define __APP_HF_MSG_SET_H__ + +#define HF_MSG_ARGS_MAX (8) + +typedef void (* hf_cmd_handler)(int argn, char **argv); + +typedef struct { + uint16_t opcode; + const char *str; + hf_cmd_handler handler; +} hf_msg_hdl_t; + +extern hf_msg_hdl_t *hf_get_cmd_tbl(void); +extern size_t hf_get_cmd_tbl_size(void); + +void hf_msg_show_usage(void); +#endif /* __APP_HF_MSG_SET_H__*/ diff --git a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/bt_app_core.c b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/bt_app_core.c new file mode 100644 index 0000000000..89749c674f --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/bt_app_core.c @@ -0,0 +1,112 @@ +/* + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ + +#include +#include +#include +#include "freertos/xtensa_api.h" +#include "freertos/FreeRTOSConfig.h" +#include "freertos/FreeRTOS.h" +#include "freertos/queue.h" +#include "freertos/task.h" +#include "esp_log.h" +#include "bt_app_core.h" + +static void bt_app_task_handler(void *arg); +static bool bt_app_send_msg(bt_app_msg_t *msg); +static void bt_app_work_dispatched(bt_app_msg_t *msg); + +static xQueueHandle bt_app_task_queue = NULL; +static xTaskHandle bt_app_task_handle = NULL; + +bool bt_app_work_dispatch(bt_app_cb_t p_cback, uint16_t event, void *p_params, int param_len, bt_app_copy_cb_t p_copy_cback) +{ + ESP_LOGD(BT_APP_CORE_TAG, "%s event 0x%x, param len %d", __func__, event, param_len); + + bt_app_msg_t msg; + memset(&msg, 0, sizeof(bt_app_msg_t)); + + msg.sig = BT_APP_SIG_WORK_DISPATCH; + msg.event = event; + msg.cb = p_cback; + + if (param_len == 0) { + return bt_app_send_msg(&msg); + } else if (p_params && param_len > 0) { + if ((msg.param = malloc(param_len)) != NULL) { + memcpy(msg.param, p_params, param_len); + /* check if caller has provided a copy callback to do the deep copy */ + if (p_copy_cback) { + p_copy_cback(&msg, msg.param, p_params); + } + return bt_app_send_msg(&msg); + } + } + return false; +} + +static bool bt_app_send_msg(bt_app_msg_t *msg) +{ + if (msg == NULL) { + return false; + } + + if (xQueueSend(bt_app_task_queue, msg, 10 / portTICK_RATE_MS) != pdTRUE) { + ESP_LOGE(BT_APP_CORE_TAG, "%s xQueue send failed", __func__); + return false; + } + return true; +} + +static void bt_app_work_dispatched(bt_app_msg_t *msg) +{ + if (msg->cb) { + msg->cb(msg->event, msg->param); + } +} + +static void bt_app_task_handler(void *arg) +{ + bt_app_msg_t msg; + for (;;) { + if (pdTRUE == xQueueReceive(bt_app_task_queue, &msg, (portTickType)portMAX_DELAY)) { + ESP_LOGD(BT_APP_CORE_TAG, "%s, sig 0x%x, 0x%x", __func__, msg.sig, msg.event); + switch (msg.sig) { + case BT_APP_SIG_WORK_DISPATCH: + bt_app_work_dispatched(&msg); + break; + default: + ESP_LOGW(BT_APP_CORE_TAG, "%s, unhandled sig: %d", __func__, msg.sig); + break; + } // switch (msg.sig) + + if (msg.param) { + free(msg.param); + } + } + } +} + +void bt_app_task_start_up(void) +{ + bt_app_task_queue = xQueueCreate(10, sizeof(bt_app_msg_t)); + xTaskCreate(bt_app_task_handler, "BtAppT", 2048, NULL, configMAX_PRIORITIES - 3, &bt_app_task_handle); + return; +} + +void bt_app_task_shut_down(void) +{ + if (bt_app_task_handle) { + vTaskDelete(bt_app_task_handle); + bt_app_task_handle = NULL; + } + if (bt_app_task_queue) { + vQueueDelete(bt_app_task_queue); + bt_app_task_queue = NULL; + } +} diff --git a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/bt_app_core.h b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/bt_app_core.h new file mode 100644 index 0000000000..4415058a71 --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/bt_app_core.h @@ -0,0 +1,47 @@ +/* + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ + +#ifndef __BT_APP_CORE_H__ +#define __BT_APP_CORE_H__ + +#include +#include +#include + +#define BT_APP_CORE_TAG "BT_APP_CORE" + +#define BT_APP_SIG_WORK_DISPATCH (0x01) + +/** + * @brief handler for the dispatched work + */ +typedef void (* bt_app_cb_t) (uint16_t event, void *param); + +/* message to be sent */ +typedef struct { + uint16_t sig; /*!< signal to bt_app_task */ + uint16_t event; /*!< message event id */ + bt_app_cb_t cb; /*!< context switch callback */ + void *param; /*!< parameter area needs to be last */ +} bt_app_msg_t; + +/** + * @brief parameter deep-copy function to be customized + */ +typedef void (* bt_app_copy_cb_t) (bt_app_msg_t *msg, void *p_dest, void *p_src); + +/** + * @brief work dispatcher for the application task + */ +bool bt_app_work_dispatch(bt_app_cb_t p_cback, uint16_t event, void *p_params, int param_len, bt_app_copy_cb_t p_copy_cback); + +void bt_app_task_start_up(void); + +void bt_app_task_shut_down(void); + +#endif /* __BT_APP_CORE_H__ */ 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 new file mode 100644 index 0000000000..bf77eac0ac --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/bt_app_hf.c @@ -0,0 +1,297 @@ +/* + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ + +#include +#include +#include +#include +#include "esp_log.h" +#include "esp_bt_main.h" +#include "esp_bt_device.h" +#include "esp_gap_bt_api.h" +#include "esp_hf_ag_api.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/queue.h" +#include "freertos/semphr.h" +#include "time.h" +#include "sys/time.h" +#include "sdkconfig.h" +#include "bt_app_core.h" +#include "bt_app_hf.h" + +const char *c_hf_evt_str[] = { + "CONNECTION_STATE_EVT", /*!< SERVICE LEVEL CONNECTION STATE CONTROL */ + "AUDIO_STATE_EVT", /*!< AUDIO CONNECTION STATE CONTROL */ + "VR_STATE_CHANGE_EVT", /*!< VOICE RECOGNITION CHANGE */ + "VOLUME_CONTROL_EVT", /*!< AUDIO VOLUME CONTROL */ + "UNKNOW_AT_CMD", /*!< UNKNOW AT COMMAND RECIEVED */ + "CIND_RESPONSE_EVT", /*!< CALL & DEVICE INDICATION */ + "COPS_RESPONSE_EVT", /*!< CURRENT OPERATOR EVENT */ + "CLCC_RESPONSE_EVT", /*!< LIST OF CURRENT CALL EVENT */ + "CNUM_RESPONSE_EVT", /*!< SUBSCRIBER INFORTMATION OF CALL EVENT */ + "DTMF_RESPONSE_EVT", /*!< DTMF TRANSFER EVT */ + "NREC_RESPONSE_EVT", /*!< NREC RESPONSE EVT */ + "ANSWER_INCOMING_EVT", /*!< ANSWER INCOMING EVT */ + "REJECT_INCOMING_EVT", /*!< AREJECT INCOMING EVT */ + "DIAL_EVT", /*!< DIAL INCOMING EVT */ + "BAC_EVT", /*!< CODEC NEGO EVT */ + "BCS_EVT", /*!< CODEC NEGO EVT */ +}; + +//esp_hf_connection_state_t +const char *c_connection_state_str[] = { + "DISCONNECTED", + "CONNECTING", + "CONNECTED", + "SLC_CONNECTED", + "DISCONNECTING", +}; + +// esp_hf_audio_state_t +const char *c_audio_state_str[] = { + "disconnected", + "connecting", + "connected", + "connected_msbc", +}; + +/// esp_hf_vr_state_t +const char *c_vr_state_str[] = { + "Disabled", + "Enabled", +}; + +// esp_hf_nrec_t +const char *c_nrec_status_str[] = { + "NREC DISABLE", + "NREC ABLE", +}; + +// esp_hf_control_target_t +const char *c_volume_control_target_str[] = { + "SPEAKER", + "MICROPHONE", +}; + +// esp_hf_subscriber_service_type_t +char *c_operator_name_str[] = { + "中国移动", + "中国联通", + "中国电信", +}; + +// esp_hf_subscriber_service_type_t +char *c_subscriber_service_type_str[] = { + "UNKNOWN", + "VOICE", + "FAX", +}; + +// esp_hf_nego_codec_status_t +const char *c_codec_mode_str[] = { + "CVSD Only", + "Use CVSD", + "Use MSBC", +}; + +#if CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_HCI +// Produce a sine audio +static const int16_t sine_int16[] = { + 0, 2057, 4107, 6140, 8149, 10126, 12062, 13952, 15786, 17557, + 19260, 20886, 22431, 23886, 25247, 26509, 27666, 28714, 29648, 30466, + 31163, 31738, 32187, 32509, 32702, 32767, 32702, 32509, 32187, 31738, + 31163, 30466, 29648, 28714, 27666, 26509, 25247, 23886, 22431, 20886, + 19260, 17557, 15786, 13952, 12062, 10126, 8149, 6140, 4107, 2057, + 0, -2057, -4107, -6140, -8149, -10126, -12062, -13952, -15786, -17557, +-19260, -20886, -22431, -23886, -25247, -26509, -27666, -28714, -29648, -30466, +-31163, -31738, -32187, -32509, -32702, -32767, -32702, -32509, -32187, -31738, +-31163, -30466, -29648, -28714, -27666, -26509, -25247, -23886, -22431, -20886, +-19260, -17557, -15786, -13952, -12062, -10126, -8149, -6140, -4107, -2057, +}; + +#define TABLE_SIZE_CVSD 100 +static uint32_t bt_app_hf_outgoing_cb(uint8_t *p_buf, uint32_t sz) +{ + int sine_phase = esp_random(); + + for (int i = 0; i < TABLE_SIZE_CVSD; i++) { + p_buf[i * 2] = sine_int16[sine_phase]; + p_buf[i * 2 + 1] = sine_int16[sine_phase]; + ++sine_phase; + if (sine_phase >= TABLE_SIZE_CVSD) { + sine_phase -= TABLE_SIZE_CVSD; + } + } + return sz; +} + +static void bt_app_hf_incoming_cb(const uint8_t *buf, uint32_t sz) +{ + // direct to i2s + esp_hf_outgoing_data_ready(); +} +#endif /* #if CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_HCI */ + +void bt_app_hf_cb(esp_hf_cb_event_t event, esp_hf_cb_param_t *param) +{ + if (event <= ESP_HF_BCS_RESPONSE_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); + } + + switch (event) { + case ESP_HF_CONNECTION_STATE_EVT: + { + ESP_LOGI(BT_HF_TAG, "--connection state %s, peer feats 0x%x, chld_feats 0x%x", + c_connection_state_str[param->conn_stat.state], + param->conn_stat.peer_feat, + param->conn_stat.chld_feat); + memcpy(hf_peer_addr, param->conn_stat.remote_bda, ESP_BD_ADDR_LEN); + if (param->conn_stat.state == ESP_HF_CONNECTION_STATE_CONNECTING) { + esp_bt_hf_connect(hf_peer_addr); + } else if (param->conn_stat.state == ESP_HF_CONNECTION_STATE_DISCONNECTING) { + esp_bt_hf_disconnect(hf_peer_addr); + } + break; + } + + case ESP_HF_AUDIO_STATE_EVT: + { + ESP_LOGI(BT_HF_TAG, "--Audio State %s", c_audio_state_str[param->audio_stat.state]); +#if CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_HCI + if (param->audio_stat.state == ESP_HF_AUDIO_STATE_CONNECTED || + param->audio_stat.state == ESP_HF_AUDIO_STATE_CONNECTED_MSBC) { + esp_bt_hf_register_data_callback(bt_app_hf_incoming_cb, bt_app_hf_outgoing_cb); + } else if (param->audio_stat.state == ESP_HF_AUDIO_STATE_DISCONNECTED) { + ESP_LOGI(BT_HF_TAG, "--ESP AG Audio Connection Disconnected."); + } +#endif /* #if CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_HCI */ + break; + } + + case ESP_HF_BVRA_EVT: + { + ESP_LOGI(BT_HF_TAG, "--Voice Recognition is %s", c_vr_state_str[param->vra_rep.value]); + break; + } + + case ESP_HF_VOLUME_CONTROL_EVT: + { + ESP_LOGI(BT_HF_TAG, "--Volume Target: %s, Volume %d", c_volume_control_target_str[param->volume_control.type], param->volume_control.volume); + break; + } + + case ESP_HF_UNAT_RESPONSE_EVT: + { + ESP_LOGI(BT_HF_TAG, "--UNKOW AT CMD: %s", param->unat_rep.unat); + esp_hf_unat_response(hf_peer_addr, param->unat_rep.unat); + break; + } + + case ESP_HF_CIND_RESPONSE_EVT: + { + ESP_LOGI(BT_HF_TAG, "--CIND Start."); + esp_hf_call_status_t call_status = 0; + esp_hf_call_setup_status_t call_setup_status = 0; + esp_hf_network_state_t ntk_state = 1; + int signal = 4; + esp_hf_roaming_status_t roam = 0; + int batt_lev = 3; + esp_hf_call_held_status_t call_held_status = 0; + esp_bt_hf_cind_response(hf_peer_addr,call_status,call_setup_status,ntk_state,signal,roam,batt_lev,call_held_status); + break; + } + + case ESP_HF_COPS_RESPONSE_EVT: + { + const int svc_type = 1; + esp_bt_hf_cops_response(hf_peer_addr, c_operator_name_str[svc_type]); + break; + } + + case ESP_HF_CLCC_RESPONSE_EVT: + { + int index = 1; + //mandatory + esp_hf_current_call_direction_t dir = 1; + esp_hf_current_call_status_t current_call_status = 0; + esp_hf_current_call_mode_t mode = 0; + esp_hf_current_call_mpty_type_t mpty = 0; + //option + char *number = {"186xxxx5549"}; + esp_hf_call_addr_type_t type = ESP_HF_CALL_ADDR_TYPE_UNKNOWN; + + ESP_LOGI(BT_HF_TAG, "--Calling Line Identification."); + esp_bt_hf_clcc_response(hf_peer_addr, index, dir, current_call_status, mode, mpty, number, type); + break; + } + + case ESP_HF_CNUM_RESPONSE_EVT: + { + char *number = {"186xxxx5549"}; + esp_hf_subscriber_service_type_t type = 1; + ESP_LOGI(BT_HF_TAG, "--Current Number is %s ,Type is %s.", number, c_subscriber_service_type_str[type]); + esp_bt_hf_cnum_response(hf_peer_addr, number,type); + break; + } + + case ESP_HF_VTS_RESPONSE_EVT: + { + ESP_LOGI(BT_HF_TAG, "--DTMF code is: %s.", param->vts_rep.code); + break; + } + + case ESP_HF_NREC_RESPONSE_EVT: + { + ESP_LOGI(BT_HF_TAG, "--NREC status is: %s.", c_nrec_status_str[param->nrec.state]); + break; + } + + case ESP_HF_ATA_RESPONSE_EVT: + { + ESP_LOGI(BT_HF_TAG, "--Asnwer Incoming Call."); + char *number = {"186xxxx5549"}; + esp_bt_hf_answer_call(hf_peer_addr,1,0,1,0,number,0); + break; + } + + case ESP_HF_CHUP_RESPONSE_EVT: + { + ESP_LOGI(BT_HF_TAG, "--Reject Incoming Call."); + char *number = {"186xxxx5549"}; + esp_bt_hf_reject_call(hf_peer_addr,0,0,0,0,number,0); + break; + } + + case ESP_HF_DIAL_EVT: + { + if (param->out_call.num_or_loc) { + //dia_num_or_mem + ESP_LOGI(BT_HF_TAG, "--Dial \"%s\".", param->out_call.num_or_loc); + esp_bt_hf_out_call(hf_peer_addr,1,0,1,0,param->out_call.num_or_loc,0); + } else { + //dia_last + ESP_LOGI(BT_HF_TAG, "--Dial last number."); + } + break; + } + + // case ESP_HF_BAC_RESPONSE_EVT: + case ESP_HF_BCS_RESPONSE_EVT: + { + ESP_LOGI(BT_HF_TAG, "--AG choose codec mode: %s",c_codec_mode_str[param->codec.mode]); + break; + } + + default: + ESP_LOGI(BT_HF_TAG, "Unsupported HF_AG EVT: %d.", event); + break; + } +} \ No newline at end of file diff --git a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/bt_app_hf.h b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/bt_app_hf.h new file mode 100644 index 0000000000..e341d0f687 --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/bt_app_hf.h @@ -0,0 +1,27 @@ +/* + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ + +#ifndef __BT_APP_HF_H__ +#define __BT_APP_HF_H__ + +#include +#include "esp_hf_ag_api.h" +#include "esp_bt_defs.h" + +esp_bd_addr_t hf_peer_addr; // Declaration of peer device bdaddr + +#define BT_HF_TAG "BT_APP_HF" + +/** + * @brief callback function for HF client + */ +void bt_app_hf_cb(esp_hf_cb_event_t event, esp_hf_cb_param_t *param); + + +#endif /* __BT_APP_HF_H__*/ + \ No newline at end of file diff --git a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/component.mk b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/component.mk new file mode 100644 index 0000000000..0b9d7585e7 --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/component.mk @@ -0,0 +1,5 @@ +# +# "main" pseudo-component makefile. +# +# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) + diff --git a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/console_uart.c b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/console_uart.c new file mode 100644 index 0000000000..bb0870c465 --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/console_uart.c @@ -0,0 +1,108 @@ +/* + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ + +#include "driver/uart.h" +#include "freertos/xtensa_api.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/queue.h" +#include "esp_log.h" +#include "console_uart.h" +#include "app_hf_msg_prs.h" + +#define CONSOLE_UART_NUM UART_NUM_0 + +static QueueHandle_t uart_queue; +static hf_msg_prs_cb_t hf_msg_parser; + +static const uart_config_t uart_cfg = { + .baud_rate = 115200, //1.5M + .data_bits = UART_DATA_8_BITS, + .parity = UART_PARITY_DISABLE, + .stop_bits = UART_STOP_BITS_1, + .flow_ctrl = UART_HW_FLOWCTRL_DISABLE, + .rx_flow_ctrl_thresh = 127, +}; + +extern void hf_msg_args_parser(char *buf, int len); + +void hf_msg_handler(char *buf, int len) +{ + ESP_LOGE(TAG_CNSL, "Command [%s]", buf); + hf_msg_args_parser(buf, len); +} + +static void console_uart_task(void *pvParameters) +{ + int len; + uart_event_t event; + hf_msg_prs_cb_t *parser = &hf_msg_parser; + hf_msg_parser_reset_state(parser); + hf_msg_parser_register_callback(parser, hf_msg_handler); + hf_msg_show_usage(); +#define TMP_BUF_LEN 128 + uint8_t tmp_buf[TMP_BUF_LEN] = {0}; + + for (;;) { + //Waiting for UART event. + if (xQueueReceive(uart_queue, (void * )&event, (portTickType)portMAX_DELAY)) { + switch (event.type) { + //Event of UART receving data + case UART_DATA: { + len = uart_read_bytes(CONSOLE_UART_NUM, tmp_buf, TMP_BUF_LEN, 0); + for (int i = 0; i < len; i++) { + hf_msg_parse(tmp_buf[i], parser); + } + break; + } + //Event of HW FIFO overflow detected + case UART_FIFO_OVF: + ESP_LOGI(TAG_CNSL, "hw fifo overflow\n"); + break; + //Event of UART ring buffer full + case UART_BUFFER_FULL: + ESP_LOGI(TAG_CNSL, "ring buffer full\n"); + break; + //Event of UART RX break detected + case UART_BREAK: + ESP_LOGI(TAG_CNSL, "uart rx break\n"); + break; + //Event of UART parity check error + case UART_PARITY_ERR: + ESP_LOGI(TAG_CNSL, "uart parity error\n"); + break; + //Event of UART frame error + case UART_FRAME_ERR: + ESP_LOGI(TAG_CNSL, "uart frame error\n"); + break; + //Others + default: + break; + } + } + } + vTaskDelete(NULL); +} + + +esp_err_t console_uart_init(void) +{ + esp_err_t ret; + + ret = uart_param_config(CONSOLE_UART_NUM, &uart_cfg); + if (ret != ESP_OK) { + ESP_LOGE(TAG_CNSL, "Uart %d initialize err %04x\n", CONSOLE_UART_NUM, ret); + return ret; + } + + uart_set_pin(CONSOLE_UART_NUM, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE); + uart_driver_install(CONSOLE_UART_NUM, 1024, 1024, 8, &uart_queue, 0); + xTaskCreate(console_uart_task, "uTask", 2048, NULL, 8, NULL); + + return ESP_OK; +} diff --git a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/console_uart.h b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/console_uart.h new file mode 100644 index 0000000000..753950de94 --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/console_uart.h @@ -0,0 +1,19 @@ +/* + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ + +#ifndef __CONSOLE_UART_H__ +#define __CONSOLE_UART_H__ + +#define TAG_CNSL "CNSL" + +/** + * @brief configure uart console for command input and process + */ +esp_err_t console_uart_init(void); + +#endif /* __BT_APP_HF_H__*/ diff --git a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/gpio_pcm_config.c b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/gpio_pcm_config.c new file mode 100644 index 0000000000..e56da15742 --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/gpio_pcm_config.c @@ -0,0 +1,92 @@ +/* + This example code is in the Public Domain (or CC0 licensed, at your option.) + + Unless required by applicable law or agreed to in writing, this + software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + CONDITIONS OF ANY KIND, either express or implied. +*/ + +#include "driver/gpio.h" +#include "soc/gpio_reg.h" +#include "soc/gpio_sig_map.h" +#include "gpio_pcm_config.h" + +#define GPIO_OUTPUT_PCM_FSYNC (25) +#define GPIO_OUTPUT_PCM_CLK_OUT (5) +#define GPIO_OUTPUT_PCM_DOUT (26) +#define GPIO_INPUT_PCM_DIN (35) + +#define GPIO_OUTPUT_PCM_PIN_SEL ((1ULL< +#include +#include +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "nvs.h" +#include "nvs_flash.h" +#include "esp_system.h" +#include "esp_log.h" +#include "esp_bt.h" +#include "bt_app_core.h" +#include "esp_bt_main.h" +#include "esp_bt_device.h" +#include "esp_gap_bt_api.h" +#include "esp_hf_ag_api.h" +#include "bt_app_hf.h" +#include "gpio_pcm_config.h" +#include "console_uart.h" + +#define BT_HF_AG_TAG "HF_AG_DEMO_MAIN" + +/* event for handler "hf_ag_hdl_stack_up */ +enum { + BT_APP_EVT_STACK_UP = 0, +}; + +/* handler for bluetooth stack enabled events */ +static void bt_hf_hdl_stack_evt(uint16_t event, void *p_param) +{ + ESP_LOGD(BT_HF_TAG, "%s evt %d", __func__, event); + switch (event) + { + case BT_APP_EVT_STACK_UP: + { + /* set up device name */ + char *dev_name = "ESP_HFP_AG"; + esp_bt_dev_set_device_name(dev_name); + + esp_bt_hf_register_callback(bt_app_hf_cb); + + // init and register for HFP_AG functions + esp_bt_hf_init(hf_peer_addr); + + /* + * Set default parameters for Legacy Pairing + * Use variable pin, input pin code when pairing + */ + esp_bt_pin_type_t pin_type = ESP_BT_PIN_TYPE_VARIABLE; + esp_bt_pin_code_t pin_code; + pin_code[0] = '0'; + pin_code[1] = '0'; + pin_code[2] = '0'; + pin_code[3] = '0'; + esp_bt_gap_set_pin(pin_type, 4, pin_code); + + /* set discoverable and connectable mode, wait to be connected */ + esp_bt_gap_set_scan_mode(ESP_BT_CONNECTABLE, ESP_BT_GENERAL_DISCOVERABLE); + break; + } + default: + ESP_LOGE(BT_HF_TAG, "%s unhandled evt %d", __func__, event); + break; + } +} + +void app_main(void) +{ + /* Initialize NVS — it is used to store PHY calibration data */ + esp_err_t ret = nvs_flash_init(); + if (ret == ESP_ERR_NVS_NO_FREE_PAGES) { + ESP_ERROR_CHECK(nvs_flash_erase()); + ret = nvs_flash_init(); + } + ESP_ERROR_CHECK(ret); + ESP_ERROR_CHECK(esp_bt_controller_mem_release(ESP_BT_MODE_BLE)); + + esp_err_t err; + esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT(); + if ((err = esp_bt_controller_init(&bt_cfg)) != ESP_OK) { + ESP_LOGE(BT_HF_TAG, "%s initialize controller failed: %s\n", __func__, esp_err_to_name(ret)); + return; + } + if ((err = esp_bt_controller_enable(ESP_BT_MODE_CLASSIC_BT)) != ESP_OK) { + ESP_LOGE(BT_HF_TAG, "%s enable controller failed: %s\n", __func__, esp_err_to_name(ret)); + return; + } + if ((err = esp_bluedroid_init()) != ESP_OK) { + ESP_LOGE(BT_HF_TAG, "%s initialize bluedroid failed: %s\n", __func__, esp_err_to_name(ret)); + return; + } + if ((err = esp_bluedroid_enable()) != ESP_OK) { + ESP_LOGE(BT_HF_TAG, "%s enable bluedroid failed: %s\n", __func__, esp_err_to_name(ret)); + return; + } + + /* create application task */ + bt_app_task_start_up(); + + /* Bluetooth device name, connection mode and profile set up */ + bt_app_work_dispatch(bt_hf_hdl_stack_evt, BT_APP_EVT_STACK_UP, NULL, 0, NULL); + + /* initialize console via UART */ + console_uart_init(); + + /* configure the PCM interface and PINs used */ + app_gpio_pcm_io_cfg(); + + /* configure externel chip for acoustic echo cancellation */ +#if ACOUSTIC_ECHO_CANCELLATION_ENABLE + app_gpio_aec_io_cfg(); +#endif /* ACOUSTIC_ECHO_CANCELLATION_ENABLE */ +} \ No newline at end of file diff --git a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/sdkconfig.defaults b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/sdkconfig.defaults new file mode 100644 index 0000000000..0229678ea2 --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/sdkconfig.defaults @@ -0,0 +1,9 @@ +# Override some defaults so BT stack is enabled and +# Classic BT is enabled and BT_DRAM_RELEASE is disabled +CONFIG_BT_ENABLED=y +CONFIG_BT_BLE_ENABLED=n +CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=y +CONFIG_BT_BLUEDROID_ENABLED=y +CONFIG_BT_CLASSIC_ENABLED=y +CONFIG_BT_HFP_ENABLE=y +CONFIG_BT_HFP_AG_ENABLE=y \ No newline at end of file From a47c07d319c8596eb4832739f2189919b853e5fe Mon Sep 17 00:00:00 2001 From: weitianhua Date: Mon, 4 Nov 2019 14:32:50 +0800 Subject: [PATCH 2/5] Update the README.md --- .../bluedroid/classic_bt/hfp_ag/README.md | 28 +++++++++---------- .../classic_bt/hfp_ag/main/app_hf_msg_set.c | 2 +- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/README.md b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/README.md index c0e694e722..91101280a8 100644 --- a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/README.md +++ b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/README.md @@ -1,6 +1,6 @@ # Hands-Free Audio Gateway -This example is to show how to use the APIs of Hands-Free (HF) Audio Gateway (AG) Component and the effects of them with the help of user commands. You can use this example to communicate with a Hands-Free Unit (e.g. a headphone set). This example uses UART as a transportation of user commands and configured GPIO for PCM audio data stream. +This example is to show how to use the APIs of Hands-Free (HF) Audio Gateway (AG) Component and the effects of them with the help of user commands. You can use this example to communicate with a Hands-Free Unit (e.g. a headphone set). This example uses UART as a transportation of user commands and uses GPIO for PCM audio data stream. ## How to use example @@ -15,7 +15,7 @@ idf.py menuconfig ``` - Enable `Classic Bluetooth`, `Hands Free/Handset` and `Aduio Gateway` under `Component config ---> Bluetooth ---> Bluedroid Options`. -- When using PCM as the data path and this example configures PCM audio data to GPIO pins. You can link the GPIO pins to a speaker via i2s port. PCM data path does not support mSBC codec but CVSD codec. +- When using PCM as the data path and this example configures PCM audio data to GPIO pins. You can link the GPIO pins to a speaker via I2S port. PCM data path does not support mSBC codec but CVSD codec. - When using HCI data path, ESP32 support both CVSD and mSBC codec. ### Build and Flash @@ -39,7 +39,7 @@ When you run this example the command table will prints like: ``` ######################################################################## HFP AG command usage manual -HFP AG commands begins with "hf" and ends with ";" +HFP AG commands begins with "hf" and end with ";" Supported commands are as follows, arguments are embraced with < and > hf con; -- setup connection with peer device @@ -84,7 +84,7 @@ E (100427) BT_HF: APP HFP event: CONNECTION_STATE_EVT E (100437) BT_HF: --connection state disconnected, peer feats 0x0, chld_feats 0x0 ``` -**Note: Only after HF service is initiated and a service level connection exists between the HF Unit and AG that other commands are available.** +**Note: Only after HF service is initialized and a service level connection exists between the HF Unit and AG could other commands be available.** You can type `hf dis;` to disconnect with the connected HF Unit device, and log prints like: @@ -101,29 +101,29 @@ E (100437) BT_HF: --connection state disconnected, peer feats 0x0, chld_feats 0x You can type `hf cona;` to establish the audio connection between HF Unit and AG device. Also, you can type `hf disa;` to close the audio data stream. -#### Situations for Audio Connection +#### Use Scenarios for Audio Connection - Answer an incoming call - Enable voice recognition - Dial an outgoing call -#### Situations for Audio Disconnection +#### Use Scenarios for Audio Disconnection - Reject an incoming call - Disable the voice recognition #### Audio Data path -ESP32 supports two type of audio data pth: PCM and HCI. +ESP32 supports two types of audio data path: PCM and HCI. -- PCM : When using PCM audio data stream is "matrixed" to GPIO pins and you should link these GPIO pins to a speaker via i2s port. -- HCI : When using HCI audio data stream will act in "loopback" mode. For example, you can hear your own voice when you place a call to a phone connected with a ESP32 development borad. +- PCM : When using PCM, audio data stream is mapped to GPIO pins and you should link these GPIO pins to a speaker via I2S port. +- HCI : When using HCI, audio data stream acts in "loopback" mode. For example, you can hear your own voice when you place a call to a phone connected with a ESP32 development borad. #### Codec -ESP32 supports both CVSD and mSBC codec. HF Unit and AG device determine which codec to use when establishing a service level connection. The choice of codec also depends on the user's configuration in `menuconfig`. +ESP32 supports both CVSD and mSBC codec. HF Unit and AG device determine which codec to use by exchanging features in the process of a service level connection. The choice of codec also depends on the user's configuration in `menuconfig`. -Since CVSD is the default codec in HFP, we just show the situation using mSBC : +Since CVSD is the default codec in HFP, we just show the scenarios using mSBC : - If you enable `BT_HFP_WBS_ENABLE` in `menuconfig`, mSBC will be available. - If both HF Unit and AG support mSBC and also `BT_HFP_WBS_ENABLE` is enabled, ESP32 chooses mSBC. @@ -192,7 +192,7 @@ You can type `hf vu ;` to sync volume gain of headset or microphone. - `` : 0 - headset, 1 - microphone. - `` : Integer among 0 - 15. -For example, `hf vu 0 9;` sync the volume of headset and log on AG side prints `volume update`, on HF Unit side log prints like: +For example, `hf vu 0 9;` sync the volume of headset and log on AG side prints `volume update`, on HF Unit side log prints like: ``` E (17087) BT_HF: APP HFP event: VOLUME_CONTROL_EVT @@ -200,7 +200,7 @@ E (17087) BT_HF: --volume_target: SPEAKER, volume 9 ``` -And also, `hf vu 1 9;` sync the volume gain of microphone and log on HF Unit side prints like: +And also, `hf vu 1 9;` sync the volume gain of microphone and log on HF Unit side prints like: ``` E (32087) BT_HF: APP HFP event: VOLUME_CONTROL_EVT @@ -224,7 +224,7 @@ I (1014138) BT_APP_HF: --Audio State connected #### Notify Device Notification -When use `hf ind ` AG will send some device status to HF Unit. Log on AG will printout like: `Device Indicator Changed!` and on HF Unit side will prints like: +You can type `hf ind ` to send device status of AG to HF Unit. Log on AG will printout like: `Device Indicator Changed!` and on HF Unit side will prints like: ``` E (293641) BT_HF: APP HFP event: CALL_IND_EVT diff --git a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/app_hf_msg_set.c b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/app_hf_msg_set.c index 00aadb3a4d..a078a6e945 100644 --- a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/app_hf_msg_set.c +++ b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/app_hf_msg_set.c @@ -16,7 +16,7 @@ void hf_msg_show_usage(void) { printf("########################################################################\n"); printf("HFP AG command usage manual\n"); - printf("HFP AG commands begins with \"hf\" and ends with \";\"\n"); + printf("HFP AG commands begins with \"hf\" and end with \";\"\n"); printf("Supported commands are as follows, arguments are embraced with < and >\n\n"); printf("hf con; -- setup connection with peer device\n"); printf("hf dis; -- release connection with peer device\n"); From 0c6e1f7ef8fcffdd1b871a21fe9054707d30f73d Mon Sep 17 00:00:00 2001 From: weitianhua Date: Mon, 4 Nov 2019 16:39:53 +0800 Subject: [PATCH 3/5] Fix the audio crash bugs Fix voice recognition bugs Fix audio memory leak bug. --- .../bluedroid/api/include/api/esp_hf_ag_api.h | 4 +- .../bt/host/bluedroid/bta/hf_ag/bta_ag_api.c | 2 - .../bt/host/bluedroid/bta/hf_ag/bta_ag_cmd.c | 8 ++ .../bt/host/bluedroid/bta/hf_ag/bta_ag_main.c | 2 +- .../btc/profile/std/hf_ag/btc_hf_ag.c | 20 ++- components/bt/host/bluedroid/hci/hci_hal_h4.c | 2 +- .../bluedroid/classic_bt/hfp_ag/README.md | 136 +++++++++--------- .../classic_bt/hfp_ag/main/app_hf_msg_set.c | 7 +- .../classic_bt/hfp_ag/main/bt_app_hf.c | 9 +- .../classic_bt/hfp_ag/main/console_uart.c | 10 +- 10 files changed, 107 insertions(+), 93 deletions(-) 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 65ac4cf3ca..45cc960c0f 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 @@ -49,7 +49,7 @@ typedef enum { ESP_HF_CONNECTION_STATE_EVT = 0, /*!< Connection state changed event */ ESP_HF_AUDIO_STATE_EVT, /*!< Audio connection state change event */ - ESP_HF_BVRA_EVT, /*!< Voice recognition state change event */ + ESP_HF_BVRA_RESPONSE_EVT, /*!< Voice recognition state change event */ ESP_HF_VOLUME_CONTROL_EVT, /*!< Audio volume control command from HF Client, provided by +VGM or +VGS message */ ESP_HF_UNAT_RESPONSE_EVT, /*!< Unknown AT cmd Response*/ @@ -89,7 +89,7 @@ typedef union } audio_stat; /*!< AG callback param of ESP_AG_AUDIO_STATE_EVT */ /** - * @brief ESP_HF_BVRA_EVT + * @brief ESP_HF_BVRA_RESPONSE_EVT */ struct hf_bvra_param { esp_bd_addr_t remote_addr; diff --git a/components/bt/host/bluedroid/bta/hf_ag/bta_ag_api.c b/components/bt/host/bluedroid/bta/hf_ag/bta_ag_api.c index d3fdf8ce47..1d1e62cc1a 100644 --- a/components/bt/host/bluedroid/bta/hf_ag/bta_ag_api.c +++ b/components/bt/host/bluedroid/bta/hf_ag/bta_ag_api.c @@ -262,8 +262,6 @@ void BTA_AgResult(UINT16 handle, tBTA_AG_RES result, tBTA_AG_RES_DATA *p_data) { tBTA_AG_API_RESULT *p_buf; - // printf("BTA_AgReslut: %d\n",result); - if ((p_buf = (tBTA_AG_API_RESULT *) osi_malloc(sizeof(tBTA_AG_API_RESULT))) != NULL) { p_buf->hdr.event = BTA_AG_API_RESULT_EVT; p_buf->hdr.layer_specific = handle; diff --git a/components/bt/host/bluedroid/bta/hf_ag/bta_ag_cmd.c b/components/bt/host/bluedroid/bta/hf_ag/bta_ag_cmd.c index 52bbd3ee60..cdad4ed18c 100644 --- a/components/bt/host/bluedroid/bta/hf_ag/bta_ag_cmd.c +++ b/components/bt/host/bluedroid/bta/hf_ag/bta_ag_cmd.c @@ -991,6 +991,8 @@ void bta_ag_at_hfp_cback(tBTA_AG_SCB *p_scb, UINT16 cmd, UINT8 arg_type, if (!(p_scb->features & BTA_AG_FEAT_VREC)) { event = 0; bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED); + } else { + bta_ag_send_ok(p_scb); } break; @@ -1536,6 +1538,12 @@ void bta_ag_hfp_result(tBTA_AG_SCB *p_scb, tBTA_AG_API_RESULT *p_result) case BTA_AG_BVRA_RES: bta_ag_send_result(p_scb, code, NULL, p_result->data.state); + if (p_result->data.ok_flag!= BTA_AG_OK_ERROR) + { + bta_ag_send_ok(p_scb); + } else { + bta_ag_send_error(p_scb, p_result->data.errcode); + } break; case BTA_AG_BTRH_RES: // Not supported yet diff --git a/components/bt/host/bluedroid/bta/hf_ag/bta_ag_main.c b/components/bt/host/bluedroid/bta/hf_ag/bta_ag_main.c index 4e146d0389..c8e43ed8c5 100644 --- a/components/bt/host/bluedroid/bta/hf_ag/bta_ag_main.c +++ b/components/bt/host/bluedroid/bta/hf_ag/bta_ag_main.c @@ -272,7 +272,7 @@ const tBTA_AG_ST_TBL bta_ag_st_tbl[] = /***************************************************************************** ** Global data *****************************************************************************/ -const char *bta_ag_version = "1.5"; //"1.6" +const char *bta_ag_version = "1.6"; /* AG control block */ #if BTA_DYNAMIC_MEMORY == FALSE tBTA_AG_CB bta_ag_cb; 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 32a55d1220..23872ba858 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 @@ -1301,7 +1301,12 @@ void btc_hf_cb_handler(btc_msg_t *msg) do { memset(¶m, 0, sizeof(esp_hf_cb_param_t)); param.vra_rep.value = p_data->val.num; - btc_hf_cb_to_app(ESP_HF_BVRA_EVT, ¶m); + btc_hf_cb_to_app(ESP_HF_BVRA_RESPONSE_EVT, ¶m); + if (p_data->val.num) { + btc_hf_connect_audio(&hf_local_param[idx].btc_hf_cb.connected_bda); + } else { + btc_hf_disconnect_audio(&hf_local_param[idx].btc_hf_cb.connected_bda); + } } while (0); break; } @@ -1422,6 +1427,14 @@ void btc_hf_cb_handler(btc_msg_t *msg) break; } + case BTA_AG_AT_BCS_EVT: + { + BTC_TRACE_DEBUG("AG Bitmap of peer-codecs %d", p_data->val.num); + memset(¶m, 0, sizeof(esp_hf_cb_param_t)); + param.codec.mode = p_data->val.num; + btc_hf_cb_to_app(ESP_HF_BCS_RESPONSE_EVT, ¶m); + break; + } #if (BTM_WBS_INCLUDED == TRUE ) case BTA_AG_WBS_EVT: { @@ -1453,11 +1466,6 @@ void btc_hf_cb_handler(btc_msg_t *msg) } #endif break; - case BTA_AG_AT_BCS_EVT: - BTC_TRACE_DEBUG("AG final seleded codec is %d 1=CVSD 2=MSBC", p_data->val.num); - /* no ESP_HF_WBS_NONE case, becuase HF 1.6 supported device can send BCS */ - btc_hf_cb_to_app(ESP_HF_BCS_RESPONSE_EVT, ¶m); - break; default: BTC_TRACE_WARNING("%s: Unhandled event: %d", __FUNCTION__, event); break; diff --git a/components/bt/host/bluedroid/hci/hci_hal_h4.c b/components/bt/host/bluedroid/hci/hci_hal_h4.c index 5508841ea8..3eff5fbded 100644 --- a/components/bt/host/bluedroid/hci/hci_hal_h4.c +++ b/components/bt/host/bluedroid/hci/hci_hal_h4.c @@ -339,7 +339,7 @@ static int host_recv_pkt_cb(uint8_t *data, uint16_t len) pkt_size = BT_HDR_SIZE + len; pkt = (BT_HDR *) osi_calloc(pkt_size); - //pkt = (BT_HDR *)hci_hal_env.allocator->alloc(pkt_size); + if (!pkt) { HCI_TRACE_ERROR("%s couldn't aquire memory for inbound data buffer.\n", __func__); return -1; diff --git a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/README.md b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/README.md index 91101280a8..d1319f9be2 100644 --- a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/README.md +++ b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/README.md @@ -1,6 +1,6 @@ # Hands-Free Audio Gateway -This example is to show how to use the APIs of Hands-Free (HF) Audio Gateway (AG) Component and the effects of them with the help of user commands. You can use this example to communicate with a Hands-Free Unit (e.g. a headphone set). This example uses UART as a transportation of user commands and uses GPIO for PCM audio data stream. +This example is to show how to use the APIs of Hands-Free (HF) Audio Gateway (AG) Component and the effects of them by providing a set of commands. You can use this example to communicate with a Hands-Free Unit (e.g. a headphone set). This example uses UART for user commands and uses GPIO for PCM audio data stream. ## How to use example @@ -8,16 +8,19 @@ This example is to show how to use the APIs of Hands-Free (HF) Audio Gateway (AG If possible, example should be able to run on any commonly available ESP32 development board and is supposed to connect to _Hands Free Unit example (hfp_hf)_ in ESP-IDF. +### Audio Data Path + +ESP32 supports two types of audio data path: PCM and HCI. + +- PCM : When using PCM, audio data stream is mapped to GPIO pins and you should link these GPIO pins to a speaker via I2S port. +- HCI : When using HCI, audio data stream will be transport to HF unit app via HCI. + ### Configure the project ``` idf.py menuconfig ``` -- Enable `Classic Bluetooth`, `Hands Free/Handset` and `Aduio Gateway` under `Component config ---> Bluetooth ---> Bluedroid Options`. -- When using PCM as the data path and this example configures PCM audio data to GPIO pins. You can link the GPIO pins to a speaker via I2S port. PCM data path does not support mSBC codec but CVSD codec. -- When using HCI data path, ESP32 support both CVSD and mSBC codec. - ### Build and Flash Build the project and flash it to the board, then run monitor tool to view serial output: @@ -34,7 +37,7 @@ See the Getting Started Guide for full steps to configure and use ESP-IDF to bui ## Example Output -When you run this example the command table will prints like: +When you run this example the commands help table prints like: ``` ######################################################################## @@ -59,12 +62,12 @@ hf ind ; -- unsolicited notify device notifi hf ate ; -- send extended at error code rep: response code from 0 to 7 err: error code from 0 to 32 -hf iron; -- inband ring tone provided -hf iroff; -- inband ring tone not provided +hf iron; -- in-band ring tone provided +hf iroff; -- in-band ring tone not provided hf ac; -- Answer Incoming Call from AG hf rc; -- Reject Incoming Call from AG hf d ; -- Dial Number by AG, e.g. hf d 11223344 -hf end; -- End up a call by AG +hf end; -- End a call by AG hf h; -- to see the command for HFP AG ######################################################################## ``` @@ -76,25 +79,27 @@ The commands help table will print out in monitor whenever you type `hf h;` or i You can type `hf con;` to establish a service level connection with HF Unit device and log prints like: ``` -E (100147) CNSL: Command [hf dis;] -disconnect -W (100427) BT_RFCOMM: port_rfc_closed RFCOMM connection in state 3 closed: Closed (res: 19) -W (100427) BT_APPL: BTA_HF_CLIENT_SCO_SHUTDOWN_ST: Ignoring event 3 -E (100427) BT_HF: APP HFP event: CONNECTION_STATE_EVT -E (100437) BT_HF: --connection state disconnected, peer feats 0x0, chld_feats 0x0 +W (2211) BT_APPL: new conn_srvc id:5, app_id:0 +I (2221) BT_APP_HF: APP HFP event: CONNECTION_STATE_EVT +I (2221) BT_APP_HF: --connection state CONNECTED, peer feats 0x0, chld_feats 0x0 +I (2291) BT_APP_HF: APP HFP event: CIND_RESPONSE_EVT +I (2291) BT_APP_HF: --CIND Start. +I (2331) BT_APP_HF: APP HFP event: CONNECTION_STATE_EVT +I (2331) BT_APP_HF: --connection state SLC_CONNECTED, peer feats 0xff, chld_feats 0x4010 ``` -**Note: Only after HF service is initialized and a service level connection exists between the HF Unit and AG could other commands be available.** +**Note: Only after HFP service is initialized and a service level connection exists between an HF Unit and an AG device, could other commands be available.** You can type `hf dis;` to disconnect with the connected HF Unit device, and log prints like: ``` E (100147) CNSL: Command [hf dis;] disconnect -W (100427) BT_RFCOMM: port_rfc_closed RFCOMM connection in state 3 closed: Closed (res: 19) -W (100427) BT_APPL: BTA_HF_CLIENT_SCO_SHUTDOWN_ST: Ignoring event 3 -E (100427) BT_HF: APP HFP event: CONNECTION_STATE_EVT -E (100437) BT_HF: --connection state disconnected, peer feats 0x0, chld_feats 0x0 +W (77321) BT_RFCOMM: port_rfc_closed RFCOMM connection in state 2 closed: Closed (res: 19) +I (77321) BT_APP_HF: APP HFP event: CONNECTION_STATE_EVT +I (77321) BT_APP_HF: --connection state DISCONNECTED, peer feats 0x0, chld_feats 0x0 +W (77381) BT_RFCOMM: rfc_find_lcid_mcb LCID reused LCID:0x41 current:0x0 +W (77381) BT_RFCOMM: RFCOMM_DisconnectInd LCID:0x41 ``` ### Audio Connection and Disconnection @@ -114,10 +119,8 @@ You can type `hf cona;` to establish the audio connection between HF Unit and AG #### Audio Data path -ESP32 supports two types of audio data path: PCM and HCI. - -- PCM : When using PCM, audio data stream is mapped to GPIO pins and you should link these GPIO pins to a speaker via I2S port. -- HCI : When using HCI, audio data stream acts in "loopback" mode. For example, you can hear your own voice when you place a call to a phone connected with a ESP32 development borad. +- When using PCM as the data path and this example configures PCM audio data to GPIO pins. You can link the GPIO pins to a speaker via I2S port. PCM data path does not support mSBC codec but CVSD codec. +- When using HCI data path, ESP32 support both CVSD and mSBC codec. #### Codec @@ -157,15 +160,17 @@ I (1067240) BT_APP_HF: APP HFP event: AUDIO_STATE_EVT I (1067240) BT_APP_HF: --Audio State disconnected ``` -#### End Up a Call +#### End a Call -You can type `hf end;` to end up the current ongoing call and log prints like: +You can type `hf end;` to end the current ongoing call and log prints like: ``` -E (40390) CNSL: Command [hf end;] +E (157741) CNSL: Command [hf end;] End Call from AG. -I (1067240) BT_APP_HF: APP HFP event: AUDIO_STATE_EVT -I (1067240) BT_APP_HF: --Audio State disconnected +W (157741) BT_APPL: BTA_AG_SCO_CLOSING_ST: Ignoring event 3 +I (159311) BT_APP_HF: APP HFP event: AUDIO_STATE_EVT +I (159311) BT_APP_HF: --Audio State disconnected +I (159311) BT_APP_HF: --ESP AG Audio Connection Disconnected. ``` ### Dial Number @@ -173,58 +178,55 @@ I (1067240) BT_APP_HF: --Audio State disconnected You can type `hf d ;` to dial `` from AG and log prints like: ``` -E (105600) CNSL: Command [hf d 18629485549;] +E (207351) CNSL: Command [hf d 18629485549;] Dial number 18629485549 -I (105610) BT_APP_HF: APP HFP event: AUDIO_STATE_EVT -I (105610) BT_APP_HF: --Audio State connecting -I (106120) BT_APP_HF: APP HFP event: BCS_EVT -I (106130) BT_APP_HF: --AG choose codec mode: CVSD Only -E (106160) BT_BTM: btm_sco_connected, handle 180 -I (106160) BT_APP_HF: APP HFP event: AUDIO_STATE_EVT -I (106160) BT_APP_HF: --Audio State connected - +I (207361) BT_APP_HF: APP HFP event: AUDIO_STATE_EVT +I (207361) BT_APP_HF: --Audio State connecting +W (207361) BT_APPL: BTA_AG_SCO_OPENING_ST: Ignoring event 1 +W (207371) BT_APPL: BTA_AG_SCO_OPENING_ST: Ignoring event 1 +E (208801) BT_BTM: btm_sco_connected, handle 181 +I (208811) BT_APP_HF: APP HFP event: AUDIO_STATE_EVT +I (208811) BT_APP_HF: --Audio State connected ``` ### Volume Control -You can type `hf vu ;` to sync volume gain of headset or microphone. The parameter set: +You can type `hf vu ;` to update volume gain of headset or microphone. The parameter set: - `` : 0 - headset, 1 - microphone. - `` : Integer among 0 - 15. -For example, `hf vu 0 9;` sync the volume of headset and log on AG side prints `volume update`, on HF Unit side log prints like: +For example, `hf vu 0 9;` update the volume of headset and log on AG side prints `Volume Update`, on HF Unit side log prints like: ``` E (17087) BT_HF: APP HFP event: VOLUME_CONTROL_EVT E (17087) BT_HF: --volume_target: SPEAKER, volume 9 - ``` -And also, `hf vu 1 9;` sync the volume gain of microphone and log on HF Unit side prints like: +And also, `hf vu 1 9;` update the volume gain of microphone and log on HF Unit side prints like: ``` E (32087) BT_HF: APP HFP event: VOLUME_CONTROL_EVT E (32087) BT_HF: --volume_target: MICROPHONE, volume 9 - ``` #### Voice Recognition -You can type `hf vron;` to start the voice recognition of AG and type `hf vroff;` to end the voice recognition. Both command will notify the HF Unit the status of voice recognition. For example, type `hf vron;` and log prints like: +You can type `hf vron;` to start the voice recognition of AG and type `hf vroff;` to terminate the voice recognition. Both command will notify the HF Unit the status of voice recognition. For example, type `hf vron;` and log prints like: ``` -E (203128) CNSL: Command [hf vron;] +E (244131) CNSL: Command [hf vron;] Start Voice Recognition. -I (203138) BT_APP_HF: APP HFP event: AUDIO_STATE_EVT -I (203138) BT_APP_HF: --Audio State connecting -I (203148) BT_APP_HF: APP HFP event: AUDIO_STATE_EVT -I (1014138) BT_APP_HF: --Audio State connected - +I (244141) BT_APP_HF: APP HFP event: AUDIO_STATE_EVT +I (244141) BT_APP_HF: --Audio State connecting +E (245301) BT_BTM: btm_sco_connected, handle 181 +I (245311) BT_APP_HF: APP HFP event: AUDIO_STATE_EVT +I (245311) BT_APP_HF: --Audio State connected ``` #### Notify Device Notification -You can type `hf ind ` to send device status of AG to HF Unit. Log on AG will printout like: `Device Indicator Changed!` and on HF Unit side will prints like: +You can type `hf ind ` to send device status of AG to HF Unit. Log on AG prints like: `Device Indicator Changed!` and on HF Unit side prints like: ``` E (293641) BT_HF: APP HFP event: CALL_IND_EVT @@ -233,14 +235,13 @@ E (293641) BT_HF: APP HFP event: CALL_SETUP_IND_EVT E (293651) BT_HF: --Call setup indicator INCOMING E (293651) BT_HF: APP HFP event: SIGNAL_STRENGTH_IND_EVT E (293661) BT_HF: -- signal strength: 5 - ``` **Note: AG only sends changed status to HF Unit.** #### Send Extended AT Error Code -You can type `hf ate ` to send extended AT error coed to HF Unit. Parameter set: +You can type `hf ate ` to send extended AT error code to HF Unit. Parameter set: - `` : integer among 0 - 7. - `` : integer among 0 - 32. @@ -253,30 +254,31 @@ E (448146) BT_HF: --AT response event, code 7, cme 7 ``` -#### Inband Ring Tone Enable and Disable +#### In-Band Ring Tone Setting -You can type `hf iron;` to enable inband ring tone and type `hf iroff;` to disable inband ring tone. Log on AG side prints like `Device Indicator Changed!` and on HF Unit side prints like: +You can type `hf iron;` to enable in-band ring tone and type `hf iroff;` to disable in-band ring tone. Log on AG side prints like `Device Indicator Changed!` and on HF Unit side prints like: ``` -E (19546) BT_HF: APP HFP event: INBAND_RING_TONE_EVT -E (19556) BT_HF: --inband ring state Provided - +E (19546) BT_HF: APP HFP event: IN-BAND_RING_TONE_EVT +E (19556) BT_HF: --in-band ring state Provided ``` ## Troubleshooting -- You should type the command in the terminal according to the format described in the command help table. +If you encounter any problems, please check if the following rules are followed: + +- You should type the command in the terminal according to the format described in the commands help table. - Not all commands in the table are supported by HF Unit. -- If you want to use AG to establish a service level connection with HF Unit, you should add the MAC address of HF Unit in `hfp_hf/main/bt_app.c`, for example: `esp_bd_addr_t peer_addr = {0xb4, 0xe6, 0x2d, 0xeb, 0x09, 0x93};` +- If you want to `hf con;` to establish a service level connection with specific HF Unit, you should add the MAC address of HF Unit in `app_hf_msg_set.c`, for example: `esp_bd_addr_t peer_addr = {0xb4, 0xe6, 0x2d, 0xeb, 0x09, 0x93};` - Use `esp_hf_client_register_callback()` and `esp_hf_client_init();` before establishing a service level connection. ## Example Breakdown -This example has relatively more source files than other bluetooth examples because _Hands Free Profile_ is somehow complex. But we want to show the functions of _Hands Free Profile_ in a simple way, so we use the _Commands and Effects_ scheme to show the usage of APIs of HFP in ESP-IDF. +Due to the complexity of Hands Free Profile, this example has more source files than other bluetooth examples. To show functions of Hands Free Profile in a simple way, we use the Commands and Effects scheme to illustrate APIs of HFP in ESP-IDF. -- The example will respond to user command through UART console. Please go to `hfp_hf/main/console_uart.c` for the configuration details. -- For voice interface, ESP32 has provided PCM input/output signals which can be mapped to GPIO pins, please go to `hfp_hf/main/gpio_pcm_config.c` for the configuration details. -- If you want to fix the command table, please refer to `hfp_hf/main/app_hf_msg_set.c`. -- If you want to fix the command parse rules, please refer to `hfp_hf/main/app_hf_msg_prs.c`. -- If you want to fix the responses of AG or want to fix the log, please refer to `hfp_hf/main/bt_app_hf.c`. -- Task configuration part is in `hfp_hf/main/bt_app_core.c`. \ No newline at end of file +- The example will respond to user command through UART console. Please go to `console_uart.c` for the configuration details. +- For voice interface, ESP32 has provided PCM input/output signals which can be mapped to GPIO pins, please go to `gpio_pcm_config.c` for the configuration details. +- If you want to update the command table, please refer to `app_hf_msg_set.c`. +- If you want to update the command parse rules, please refer to `app_hf_msg_prs.c`. +- If you want to update the responses of AG or want to update the log, please refer to `bt_app_hf.c`. +- Task configuration part is in `bt_app_core.c`. \ No newline at end of file diff --git a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/app_hf_msg_set.c b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/app_hf_msg_set.c index a078a6e945..0e22c87707 100644 --- a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/app_hf_msg_set.c +++ b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/app_hf_msg_set.c @@ -12,6 +12,9 @@ #include "app_hf_msg_set.h" #include "bt_app_hf.h" +// if you want to connect a specific device, add it's bda here +// esp_bd_addr_t hf_peer_addr = {0x70,0x26,0x05,0xca,0xeb,0x21}; + void hf_msg_show_usage(void) { printf("########################################################################\n"); @@ -35,8 +38,8 @@ void hf_msg_show_usage(void) printf("hf ate ; -- send extended at error code\n"); printf(" rep: response code from 0 to 7\n"); printf(" err: error code from 0 to 32\n"); - printf("hf iron; -- inband ring tone provided\n"); - printf("hf iroff; -- inband ring tone not provided\n"); + printf("hf iron; -- in-band ring tone provided\n"); + printf("hf iroff; -- in-band ring tone not provided\n"); printf("hf ac; -- Answer Incoming Call from AG\n"); printf("hf rc; -- Reject Incoming Call from AG\n"); printf("hf d ; -- Dial Number by AG, e.g. hf d 11223344\n"); 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 bf77eac0ac..412ee233b8 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 @@ -154,11 +154,6 @@ void bt_app_hf_cb(esp_hf_cb_event_t event, esp_hf_cb_param_t *param) param->conn_stat.peer_feat, param->conn_stat.chld_feat); memcpy(hf_peer_addr, param->conn_stat.remote_bda, ESP_BD_ADDR_LEN); - if (param->conn_stat.state == ESP_HF_CONNECTION_STATE_CONNECTING) { - esp_bt_hf_connect(hf_peer_addr); - } else if (param->conn_stat.state == ESP_HF_CONNECTION_STATE_DISCONNECTING) { - esp_bt_hf_disconnect(hf_peer_addr); - } break; } @@ -176,7 +171,7 @@ void bt_app_hf_cb(esp_hf_cb_event_t event, esp_hf_cb_param_t *param) break; } - case ESP_HF_BVRA_EVT: + case ESP_HF_BVRA_RESPONSE_EVT: { ESP_LOGI(BT_HF_TAG, "--Voice Recognition is %s", c_vr_state_str[param->vra_rep.value]); break; @@ -283,7 +278,7 @@ void bt_app_hf_cb(esp_hf_cb_event_t event, esp_hf_cb_param_t *param) break; } - // case ESP_HF_BAC_RESPONSE_EVT: + case ESP_HF_BAC_RESPONSE_EVT: case ESP_HF_BCS_RESPONSE_EVT: { ESP_LOGI(BT_HF_TAG, "--AG choose codec mode: %s",c_codec_mode_str[param->codec.mode]); diff --git a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/console_uart.c b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/console_uart.c index bb0870c465..32d8c7c727 100644 --- a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/console_uart.c +++ b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/console_uart.c @@ -62,23 +62,23 @@ static void console_uart_task(void *pvParameters) } //Event of HW FIFO overflow detected case UART_FIFO_OVF: - ESP_LOGI(TAG_CNSL, "hw fifo overflow\n"); + ESP_LOGI(TAG_CNSL, "hw fifo overflow"); break; //Event of UART ring buffer full case UART_BUFFER_FULL: - ESP_LOGI(TAG_CNSL, "ring buffer full\n"); + ESP_LOGI(TAG_CNSL, "ring buffer full"); break; //Event of UART RX break detected case UART_BREAK: - ESP_LOGI(TAG_CNSL, "uart rx break\n"); + ESP_LOGI(TAG_CNSL, "uart rx break"); break; //Event of UART parity check error case UART_PARITY_ERR: - ESP_LOGI(TAG_CNSL, "uart parity error\n"); + ESP_LOGI(TAG_CNSL, "uart parity error"); break; //Event of UART frame error case UART_FRAME_ERR: - ESP_LOGI(TAG_CNSL, "uart frame error\n"); + ESP_LOGI(TAG_CNSL, "uart frame error"); break; //Others default: From 7c18299571df72c29c937602df2c0a8808d22105 Mon Sep 17 00:00:00 2001 From: weitianhua Date: Thu, 7 Nov 2019 14:45:18 +0800 Subject: [PATCH 4/5] Add AG component API_REFERENCE Expose esp_hf_indchange_notification to this example. --- .../bluedroid/api/include/api/esp_hf_ag_api.h | 186 +++++++++++------- .../bt/host/bluedroid/bta/hf_ag/bta_ag_sco.c | 1 - .../btc/profile/std/hf_ag/btc_hf_ag.c | 5 + .../bt/host/bluedroid/stack/btu/btu_task.c | 1 + docs/Doxyfile | 1 + docs/en/api-guides/event-handling.rst | 1 + .../en/api-reference/bluetooth/classic_bt.rst | 1 + docs/en/api-reference/bluetooth/esp_hf_ag.rst | 14 ++ .../api-reference/bluetooth/esp_hf_ag.rst | 1 + .../bluedroid/classic_bt/hfp_ag/README.md | 98 +++++---- .../classic_bt/hfp_ag/main/app_hf_msg_set.c | 2 +- .../classic_bt/hfp_ag/main/bt_app_hf.c | 11 ++ .../classic_bt/hfp_ag/main/console_uart.c | 2 +- 13 files changed, 204 insertions(+), 120 deletions(-) create mode 100644 docs/en/api-reference/bluetooth/esp_hf_ag.rst create mode 100644 docs/zh_CN/api-reference/bluetooth/esp_hf_ag.rst 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 45cc960c0f..3b75669bad 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 @@ -49,10 +49,11 @@ typedef enum { ESP_HF_CONNECTION_STATE_EVT = 0, /*!< Connection state changed event */ ESP_HF_AUDIO_STATE_EVT, /*!< Audio connection state change event */ - ESP_HF_BVRA_RESPONSE_EVT, /*!< Voice recognition state change event */ + ESP_HF_BVRA_RESPONSE_EVT, /*!< Voice recognition state change event */ ESP_HF_VOLUME_CONTROL_EVT, /*!< Audio volume control command from HF Client, provided by +VGM or +VGS message */ ESP_HF_UNAT_RESPONSE_EVT, /*!< Unknown AT cmd Response*/ + ESP_HF_IND_UPDATE_EVT, /*!< Indicator Update Event*/ ESP_HF_CIND_RESPONSE_EVT, /*!< Call And Device Indicator Response*/ ESP_HF_COPS_RESPONSE_EVT, /*!< Current operator information */ ESP_HF_CLCC_RESPONSE_EVT, /*!< List of current calls notification */ @@ -67,7 +68,7 @@ typedef enum ESP_HF_BCS_RESPONSE_EVT, /*!< Codec Negotiation */ } esp_hf_cb_event_t; -// HF callback parameters of corresponding esp event in esp_hf_cb_event_t +/// HFP AG callback parameters typedef union { /** @@ -75,98 +76,85 @@ typedef union */ struct hf_conn_stat_param { esp_bd_addr_t remote_bda; /*!< remote bluetooth device address */ - esp_hf_connection_state_t state; /*!< HF connection state */ - uint32_t peer_feat; /*!< AG supported features */ + esp_hf_connection_state_t state; /*!< Connection state */ + uint32_t peer_feat; /*!< HF supported features */ uint32_t chld_feat; /*!< AG supported features on call hold and multiparty services */ - } conn_stat; /*!< AG callback param of ESP_AG_CONNECTION_STATE_EVT */ + } conn_stat; /*!< AG callback param of ESP_HF_CONNECTION_STATE_EVT */ /** * @brief ESP_HF_AUDIO_STATE_EVT */ struct hf_audio_stat_param { - esp_bd_addr_t remote_addr; /*!< remote bluetooth device address */ + esp_bd_addr_t remote_addr; /*!< remote bluetooth device address */ esp_hf_audio_state_t state; /*!< audio connection state */ - } audio_stat; /*!< AG callback param of ESP_AG_AUDIO_STATE_EVT */ + } audio_stat; /*!< AG callback param of ESP_HF_AUDIO_STATE_EVT */ /** * @brief ESP_HF_BVRA_RESPONSE_EVT */ - struct hf_bvra_param { - esp_bd_addr_t remote_addr; + struct hf_vra_rep_param { + esp_bd_addr_t remote_addr; /*!< remote bluetooth device address */ esp_hf_vr_state_t value; /*!< voice recognition state */ - } vra_rep; /*!< AG callback param of ESP_AG_BVRA_EVT */ + } vra_rep; /*!< AG callback param of ESP_HF_BVRA_RESPONSE_EVT */ /** * @brief ESP_HF_VOLUME_CONTROL_EVT */ struct hf_volume_control_param { - esp_hf_volume_type_t type; /*!< volume control target, speaker or microphone */ - int volume; /*!< gain, ranges from 0 to 15 */ - } volume_control; /*!< AG callback param of ESP_AG_VOLUME_CONTROL_EVT */ + esp_hf_volume_type_t type; /*!< volume control target, speaker or microphone */ + int volume; /*!< gain, ranges from 0 to 15 */ + } volume_control; /*!< AG callback param of ESP_HF_VOLUME_CONTROL_EVT */ /** * @brief ESP_HF_UNAT_RESPOSNE_EVT */ - struct hf_unat_param { - char *unat; - }unat_rep; + struct hf_unat_rep_param { + char *unat; /*!< unknown AT command string */ + }unat_rep; /*!< AG callback param of ESP_HF_UNAT_RESPONSE_EVT */ /** - * @brief ESP_HF_AT_RESPONSE_EVT - */ - struct hf_at_code_param { - esp_hf_at_response_code_t code; /*!< AT response code */ - esp_hf_cme_err_t cme; /*!< Extended Audio Gateway Error Result Code */ - } at; /*!< AG callback param of ESP_HF_EXT_AT_EVT */ - - /** - * @brief ESP_HF_CIND_CALL_EVT + * @brief ESP_HF_CIND_RESPONSE_EVT */ struct hf_cind_param { esp_hf_call_status_t call_status; /*!< call status indicator */ esp_hf_call_setup_status_t call_setup_status; /*!< call setup status indicator */ - esp_hf_network_state_t svc; /*!< bluetooth proprietary call hold status indicator */ + esp_hf_network_state_t svc; /*!< bluetooth proprietary call hold status indicator */ int signal_strength; /*!< bluetooth proprietary call hold status indicator */ esp_hf_roaming_status_t roam; /*!< bluetooth proprietary call hold status indicator */ int battery_level; /*!< battery charge value, ranges from 0 to 5 */ esp_hf_call_held_status_t call_held_status; /*!< bluetooth proprietary call hold status indicator */ - } cind; + } cind; /*!< AG callback param of ESP_HF_CIND_RESPONSE_EVT */ + + /** + * @brief ESP_HF_DIAL_EVT + */ + struct hf_out_call_param { + esp_bd_addr_t remote_addr; /*!< remote bluetooth device address */ + char *num_or_loc; /*!< location in phone memory */ + } out_call; /*!< AG callback param of ESP_HF_DIAL_EVT */ /** * @brief ESP_HF_VTS_RESPOSNE_EVT */ - struct hf_vts_param { - char *code; - }vts_rep; + struct hf_vts_rep_param { + char *code; /*!< MTF code from HF Client */ + }vts_rep; /*!< AG callback param of ESP_HF_VTS_RESPONSE_EVT */ /** * @brief ESP_HF_NREC_RESPOSNE_EVT */ struct hf_nrec_param { - esp_hf_nrec_t state; - } nrec; - - struct hf_outcall_param { - esp_bd_addr_t remote_addr; - char *num_or_loc; - } out_call; - - /** - * @brief ESP_HF_BSIR_EVT - */ - struct hf_bsir_param { - esp_bd_addr_t remote_addr; - esp_hf_in_band_ring_state_t state; /*!< setting state of in-band ring tone */ - } bsir; + esp_hf_nrec_t state; /*!< NREC enabled or disabled */ + } nrec; /*!< AG callback param of ESP_HF_NREC_RESPONSE_EVT */ /** * @brief ESP_HF_BCS_RESPONSE_EVT */ struct hf_codec_param { - esp_hf_wbs_config_t mode; - } codec; + esp_hf_wbs_config_t mode; /*!< codec mode CVSD or mSBC */ + } codec; /*!< AG callback param of ESP_HF_BAC_RESPONSE_EVT */ -} esp_hf_cb_param_t; +} esp_hf_cb_param_t; /*!< HFP AG callback param compound*/ /** * @brief AG incoming data callback function, the callback is useful in case of @@ -206,8 +194,8 @@ typedef void (* esp_hf_cb_t) (esp_hf_cb_event_t event, esp_hf_cb_param_t *param) ** ESP HF API ************************************************************************************/ /** - * @brief Register application callback function to HFP client module. This function should be called - * only after esp_bluedroid_enable() completes successfully, used by HFP client + * @brief Register application callback function to HFP AG module. This function should be called + * only after esp_bluedroid_enable() completes successfully, used by HFP AG * * @param[in] callback: HFP AG event callback function * @@ -224,6 +212,7 @@ esp_err_t esp_bt_hf_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 * + * @param[in] remote_addr: remote bluetooth device address * @return * - ESP_OK: if the initialization request is sent successfully * - ESP_INVALID_STATE: if bluetooth stack is not yet enabled @@ -237,6 +226,7 @@ esp_err_t esp_bt_hf_init(esp_bd_addr_t remote_addr); * @brief De-initialize for HF AG module. This function * should be called only after esp_bluedroid_enable() completes successfully * + * @param[in] remote_addr: remote bluetooth device address * @return * - ESP_OK: success * - ESP_INVALID_STATE: if bluetooth stack is not yet enabled @@ -304,8 +294,8 @@ esp_err_t esp_bt_hf_disconnect_audio(esp_bd_addr_t remote_bda); * @brief Response of Volume Recognition Command(AT+VRA) from HFP client. As a precondition to use this API, * Service Level Connection shall exist with HFP client. * - * @param[in] remote: volume control target, speaker or microphone - * @param[in] volume: gain of the speaker of microphone, ranges 0 to 15 + * @param[in] remote_bda: volume control target, speaker or microphone + * @param[in] value: gain of the speaker of microphone, ranges 0 to 15 * * @return * - ESP_OK: disconnect request is sent to lower layer @@ -318,8 +308,9 @@ esp_err_t esp_bt_hf_vra(esp_bd_addr_t remote_bda, esp_hf_vr_state_t value); /** * * @brief Volume synchronization with HFP client. As a precondition to use this API, - * Service Level Connection shall exist with HFP client + * Service Level Connection shall exist with HFP client. * + * @param[in] remote_bda: remote bluetooth device address * @param[in] type: volume control target, speaker or microphone * @param[in] volume: gain of the speaker of microphone, ranges 0 to 15 * @@ -334,8 +325,10 @@ esp_err_t esp_bt_hf_volume_control(esp_bd_addr_t remote_bda, esp_hf_volume_contr /** * * @brief Handle Unknown AT command from HFP Client. - * As a precondition to use this API, Service Level Connection shall exist between AG and HF Client + * As a precondition to use this API, Service Level Connection shall exist between AG and HF Client. * + * @param[in] remote_addr: remote bluetooth device address + * @param[in] unat: AT command string from HF Client * @return * - ESP_OK: disconnect request is sent to lower layer * - ESP_INVALID_STATE: if bluetooth stack is not yet enabled @@ -347,8 +340,11 @@ esp_err_t esp_hf_unat_response(esp_bd_addr_t remote_addr, char *unat); /** * * @brief Unsolicited send extend AT error code to HFP Client. - * As a precondition to use this API, Service Level Connection shall exist between AG and HF Client + * As a precondition to use this API, Service Level Connection shall exist between AG and HF Client. * + * @param[in] remote_bda: remote bluetooth device address + * @param[in] response_code: AT command response code + * @param[in] error_code: CME error code * @return * - ESP_OK: disconnect request is sent to lower layer * - ESP_INVALID_STATE: if bluetooth stack is not yet enabled @@ -362,6 +358,11 @@ esp_err_t esp_bt_hf_cmee_response(esp_bd_addr_t remote_bda, esp_hf_at_response_c * @brief Usolicited send device status notificationto HFP Client. * As a precondition to use this API, Service Level Connection shall exist between AG and HF Client * + * @param[in] remote_addr: remote bluetooth device address + * @param[in] call_state: call state + * @param[in] call_setup_state: call setup state + * @param[in] ntk_state: network service state + * @param[in] signal: signal strength from 0 to 5 * @return * - ESP_OK: disconnect request is sent to lower layer * - ESP_INVALID_STATE: if bluetooth stack is not yet enabled @@ -377,6 +378,14 @@ esp_err_t esp_bt_hf_indchange_notification(esp_bd_addr_t remote_addr, esp_hf_cal * @brief Response to device individual indicatiors to HFP Client. * As a precondition to use this API, Service Level Connection shall exist between AG and HF Client. * + * @param[in] remote_addr: remote bluetooth device address + * @param[in] call_state: call state + * @param[in] call_setup_state: call setup state + * @param[in] ntk_state: network service state + * @param[in] signal: signal strength from 0 to 5 + * @param[in] roam: roam state + * @param[in] batt_lev: batery level from 0 to 5 + * @param[in] call_held_status: call held status * @return * - ESP_OK: disconnect request is sent to lower layer * - ESP_INVALID_STATE: if bluetooth stack is not yet enabled @@ -391,9 +400,11 @@ esp_err_t esp_bt_hf_cind_response(esp_bd_addr_t remote_addr, /** * - * @brief Query the name of currently selected network operator in AG, - * As a precondition to use this API, Service Level Connection shall exist with HFP Client + * @brief Reponse 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: disconnect request is sent to lower layer * - ESP_INVALID_STATE: if bluetooth stack is not yet enabled @@ -404,9 +415,17 @@ esp_err_t esp_bt_hf_cops_response(esp_bd_addr_t remote_addr, char *name); /** * - * @brief Response to Query list of current calls from HFP Client (use AT+CLCC command), - * As a precondition to use this API, Service Level Connection shall exist between AG and HF Client + * @brief Response to AT+CLCC command from HFP Client. + * As a precondition to use this API, Service Level Connection shall exist between AG and HF Client. * + * @param[in] remote_addr: remote bluetooth device address + * @param[in] index: the index of current call + * @param[in] dir: call direction (incoming/outgoing) + * @param[in] current_call_state: current call state + * @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 * @return * - ESP_OK: disconnect request is sent to lower layer * - ESP_INVALID_STATE: if bluetooth stack is not yet enabled @@ -419,9 +438,12 @@ esp_err_t esp_bt_hf_clcc_response(esp_bd_addr_t remote_addr, int index, esp_hf_c /** * - * @brief Get subscriber information number from HFP client(send AT+CNUM command), - * As a precondition to use this API, Service Level Connection shall exist with AG + * @brief Response for AT+CNUM command from HF Client. + * As a precondition to use this API, Service Level Connection shall exist with AG. * + * @param[in] remote_addr: remote bluetooth device address + * @param[in] number: registration number + * @param[in] type: service type (unknown/voice/fax) * @return * - ESP_OK: disconnect request is sent to lower layer * - ESP_INVALID_STATE: if bluetooth stack is not yet enabled @@ -432,9 +454,11 @@ esp_err_t esp_bt_hf_cnum_response(esp_bd_addr_t remote_addr, char *number, esp_h /** * - * @brief Inform HF Client of Provided or not Inband Ring Tone. - * As a precondition to use this API, Service Level Connection shall exist with AG + * @brief Inform HF Client that AG Provided in-band ring tone or not. + * As a precondition to use this API, Service Level Connection shall exist with AG. * + * @param[in] remote_addr: remote bluetooth device address + * @param[in] state: in-band ring tone state * @return * - ESP_OK: disconnect request is sent to lower layer * - ESP_INVALID_STATE: if bluetooth stack is not yet enabled @@ -445,9 +469,16 @@ esp_err_t esp_bt_hf_bsir(esp_bd_addr_t remote_addr, esp_hf_in_band_ring_state_t /** * - * @brief Answer Incoming Call by AG or response to the AT+A command from Hands-Free Unit. + * @brief Answer Incoming Call from AG. * As a precondition to use this API, Service Level Connection shall exist with AG. * + * @param[in] remote_addr: remote bluetooth device address + * @param[in] num_active: the number of active call + * @param[in] num_held: the number of held call + * @param[in] call_state: call state + * @param[in] call_setup_state: call setup state + * @param[in] number: number of the incoming call + * @param[in] call_addr_type: call address type * @return * - ESP_OK: disconnect request is sent to lower layer * - ESP_INVALID_STATE: if bluetooth stack is not yet enabled @@ -460,9 +491,16 @@ esp_err_t esp_bt_hf_answer_call(esp_bd_addr_t remote_addr, int num_active, int n /** * - * @brief Reject Incoming Call by AG or response to the AT+CHUP command from Hands-Free Unit. + * @brief Reject Incoming Call from AG. * As a precondition to use this API, Service Level Connection shall exist with AG. * + * @param[in] remote_addr: remote bluetooth device address + * @param[in] num_active: the number of active call + * @param[in] num_held: the number of held call + * @param[in] call_state: call state + * @param[in] call_setup_state: call setup state + * @param[in] number: number of the incoming call + * @param[in] call_addr_type: call address type * @return * - ESP_OK: disconnect request is sent to lower layer * - ESP_INVALID_STATE: if bluetooth stack is not yet enabled @@ -475,9 +513,16 @@ esp_err_t esp_bt_hf_reject_call(esp_bd_addr_t remote_addr, int num_active, int n /** * - * @brief Reject Incoming Call by AG or response to the AT+CHUP command from Hands-Free Unit. + * @brief Reject incoming call from AG. * As a precondition to use this API, Service Level Connection shall exist with AG. * + * @param[in] remote_addr: remote bluetooth device address + * @param[in] num_active: the number of active call + * @param[in] num_held: the number of held call + * @param[in] call_state: call state + * @param[in] call_setup_state: call setup state + * @param[in] number: number of the outgoing call + * @param[in] call_addr_type: call address type * @return * - ESP_OK: disconnect request is sent to lower layer * - ESP_INVALID_STATE: if bluetooth stack is not yet enabled @@ -490,9 +535,16 @@ esp_err_t esp_bt_hf_out_call(esp_bd_addr_t remote_addr, int num_active, int num_ /** * - * @brief Reject Incoming Call by AG or response to the AT+CHUP command from Hands-Free Unit. + * @brief End an ongoing call. * As a precondition to use this API, Service Level Connection shall exist with AG. * + * @param[in] remote_addr: remote bluetooth device address + * @param[in] num_active: the number of active call + * @param[in] num_held: the number of held call + * @param[in] call_state: call state + * @param[in] call_setup_state: call setup state + * @param[in] number: number of the call + * @param[in] call_addr_type: call address type * @return * - ESP_OK: disconnect request is sent to lower layer * - ESP_INVALID_STATE: if bluetooth stack is not yet enabled diff --git a/components/bt/host/bluedroid/bta/hf_ag/bta_ag_sco.c b/components/bt/host/bluedroid/bta/hf_ag/bta_ag_sco.c index 351b7bca7c..f101e07b71 100644 --- a/components/bt/host/bluedroid/bta/hf_ag/bta_ag_sco.c +++ b/components/bt/host/bluedroid/bta/hf_ag/bta_ag_sco.c @@ -321,7 +321,6 @@ static void bta_ag_sco_read_cback(UINT16 sco_inx, BT_HDR *p_data, tBTM_SCO_DATA_ /* Callout function must free the data. */ bta_ag_sco_co_in_data(p_data, status); - osi_free(p_data); } #endif /******************************************************************************* 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 23872ba858..0630f66ef6 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 @@ -1332,6 +1332,11 @@ void btc_hf_cb_handler(btc_msg_t *msg) } case BTA_AG_AT_CBC_EVT: + { + btc_hf_cb_to_app(ESP_HF_IND_UPDATE_EVT, NULL); + break; + } + case BTA_AG_AT_CIND_EVT: { btc_hf_cind_evt(&p_data->ind); diff --git a/components/bt/host/bluedroid/stack/btu/btu_task.c b/components/bt/host/bluedroid/stack/btu/btu_task.c index 3e73cbb85c..56fe6c1689 100644 --- a/components/bt/host/bluedroid/stack/btu/btu_task.c +++ b/components/bt/host/bluedroid/stack/btu/btu_task.c @@ -152,6 +152,7 @@ static void btu_hci_msg_process(void *param) case BT_EVT_TO_BTU_HCI_SCO: #if BTM_SCO_INCLUDED == TRUE btm_route_sco_data (p_msg); + osi_free(p_msg); break; #endif diff --git a/docs/Doxyfile b/docs/Doxyfile index 36a38a7a81..72b101fc6b 100644 --- a/docs/Doxyfile +++ b/docs/Doxyfile @@ -57,6 +57,7 @@ INPUT = \ ../../components/bt/host/bluedroid/api/include/api/esp_spp_api.h \ ../../components/bt/host/bluedroid/api/include/api/esp_hf_defs.h \ ../../components/bt/host/bluedroid/api/include/api/esp_hf_client_api.h \ + ../../components/bt/host/bluedroid/api/include/api/esp_hf_ag_api.h \ ## NimBLE related Bluetooth APIs ../../components/bt/host/nimble/esp-hci/include/esp_nimble_hci.h \ ## ESP BLE Mesh APIs diff --git a/docs/en/api-guides/event-handling.rst b/docs/en/api-guides/event-handling.rst index 99a60c7ffe..e0a163b471 100644 --- a/docs/en/api-guides/event-handling.rst +++ b/docs/en/api-guides/event-handling.rst @@ -143,3 +143,4 @@ Various modules of the Bluetooth stack deliver events to applications via dedica * A2DP: :cpp:func:`esp_a2d_register_callback`, :cpp:type:`esp_a2d_cb_event_t`, :cpp:type:`esp_a2d_cb_param_t`. * AVRC: :cpp:func:`esp_avrc_ct_register_callback`, :cpp:type:`esp_avrc_ct_cb_event_t`, :cpp:type:`esp_avrc_ct_cb_param_t`. * HFP Client: :cpp:func:`esp_hf_client_register_callback`, :cpp:type:`esp_hf_client_cb_event_t`, :cpp:type:`esp_hf_client_cb_param_t`. +* HFP AG: :cpp:func:`esp_hf_ag_register_callback`, :cpp:type:`esp_hf_ag_cb_event_t`, :cpp:type:`esp_hf_ag_cb_param_t`. \ No newline at end of file diff --git a/docs/en/api-reference/bluetooth/classic_bt.rst b/docs/en/api-reference/bluetooth/classic_bt.rst index 3a9a30430b..5ddd4f7ffa 100644 --- a/docs/en/api-reference/bluetooth/classic_bt.rst +++ b/docs/en/api-reference/bluetooth/classic_bt.rst @@ -10,3 +10,4 @@ CLASSIC BT BT SPP BT HFP Define BT HFP Client + BT HFP AG diff --git a/docs/en/api-reference/bluetooth/esp_hf_ag.rst b/docs/en/api-reference/bluetooth/esp_hf_ag.rst new file mode 100644 index 0000000000..7cea249b34 --- /dev/null +++ b/docs/en/api-reference/bluetooth/esp_hf_ag.rst @@ -0,0 +1,14 @@ +HFP AG API +============== + +Overview +-------- + +`Instructions`_ + +.. _Instructions: ../template.html + +API Reference +------------- + +.. include:: /_build/inc/esp_hf_ag_api.inc diff --git a/docs/zh_CN/api-reference/bluetooth/esp_hf_ag.rst b/docs/zh_CN/api-reference/bluetooth/esp_hf_ag.rst new file mode 100644 index 0000000000..7b59ca8ae7 --- /dev/null +++ b/docs/zh_CN/api-reference/bluetooth/esp_hf_ag.rst @@ -0,0 +1 @@ +.. include:: ../../../en/api-reference/bluetooth/esp_hf_ag.rst diff --git a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/README.md b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/README.md index d1319f9be2..e2828656a4 100644 --- a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/README.md +++ b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/README.md @@ -1,19 +1,12 @@ # Hands-Free Audio Gateway -This example is to show how to use the APIs of Hands-Free (HF) Audio Gateway (AG) Component and the effects of them by providing a set of commands. You can use this example to communicate with a Hands-Free Unit (e.g. a headphone set). This example uses UART for user commands and uses GPIO for PCM audio data stream. +This example is to show how to use the APIs of Hands-Free (HF) Audio Gateway (AG) Component and the effects of them by providing a set of commands. You can use this example to communicate with a Hands-Free Unit (e.g. a headphone set). This example uses UART for user commands. ## How to use example ### Hardware Required -If possible, example should be able to run on any commonly available ESP32 development board and is supposed to connect to _Hands Free Unit example (hfp_hf)_ in ESP-IDF. - -### Audio Data Path - -ESP32 supports two types of audio data path: PCM and HCI. - -- PCM : When using PCM, audio data stream is mapped to GPIO pins and you should link these GPIO pins to a speaker via I2S port. -- HCI : When using HCI, audio data stream will be transport to HF unit app via HCI. +This example is designed to run on commonly available ESP32 development board, e.g. ESP32-DevKitC. To operate it should be connected to an Hands-Free Unit running on a Headphone/Headset or on another ESP32 development board loaded with Hands Free Unit (hfp_hf) example from ESP-IDF. ### Configure the project @@ -21,9 +14,16 @@ ESP32 supports two types of audio data path: PCM and HCI. idf.py menuconfig ``` +ESP32 supports two types of audio data paths: PCM and HCI but the default sdkconfig of this example does not config the data path in a specific way. You should config the data path you want: + +- PCM : When using PCM, audio data stream is directed to GPIO pins and you should link these GPIO pins to a speaker via I2S port. You should choose PCM in `menuconfig` path: `Component config --> Bluetooth controller --> BR/EDR Sync(SCO/eSCO) default data path --> PCM`and also `Component config --> Bluetooth --> Bluedroid Options -->Hands Free/Handset Profile --> audio(SCO) data path --> PCM`. +- HCI : When using HCI, audio data stream will be transport to HF unit app via HCI. You should choose HCI in `menuconfig` path: `Component config -->Bluetooth controller -->BR/EDR Sync(SCO/eSCO) default data path --> HCI` and also `Component config --> Bluetooth --> Bluedroid Options -->Hands Free/Handset Profile --> audio(SCO) data path --> HCI`. + +**Note: Wide Band Speech is disabled by default, if you want to use it please select it in the menuconfig path: `Component config --> Bluetooth --> Bluedroid Options --> Wide Band Speech`.** + ### Build and Flash -Build the project and flash it to the board, then run monitor tool to view serial output: +Build the project and flash it to the board. Then, run monitor tool to view serial output: ``` idf.py -p PORT flash monitor @@ -33,11 +33,11 @@ idf.py -p PORT flash monitor (To exit the serial monitor, type ``Ctrl-]``.) -See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects. +See the [Getting Started Guide](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/index.html) for full steps to configure and use ESP-IDF to build projects. ## Example Output -When you run this example the commands help table prints like: +When you flash and monitor this example the commands help table prints the following at the very begining: ``` ######################################################################## @@ -54,7 +54,7 @@ hf vroff; -- stop voice recognition hf vu ; -- volume update tgt: 0-speaker, 1-microphone vol: volume gain ranges from 0 to 15 -hf ind ; -- unsolicited notify device notification to HF Client +hf ind ; -- unsolicited indication device status to HF Client call: call status [0,1] callsetup: call setup status [0,3] ntk: network status [0,1] @@ -72,11 +72,15 @@ hf h; -- to see the command for HFP AG ######################################################################## ``` -The commands help table will print out in monitor whenever you type `hf h;` or input a command that is not required by the command parse rule. +**Note:** + +- This command help table will print out in monitor whenever you type `hf h;` or if you input a command that is not required by the command parse rule. +- The command you type will not echo in monitor and your command should always start with `hf` and end with `;` or the example will not responds. +- The command you typed will not echo in monitor. ### Service Level Connection and Disconnection -You can type `hf con;` to establish a service level connection with HF Unit device and log prints like: +You can type `hf con;` to establish a service level connection with HF Unit device and log prints such as: ``` W (2211) BT_APPL: new conn_srvc id:5, app_id:0 @@ -88,9 +92,9 @@ I (2331) BT_APP_HF: APP HFP event: CONNECTION_STATE_EVT I (2331) BT_APP_HF: --connection state SLC_CONNECTED, peer feats 0xff, chld_feats 0x4010 ``` -**Note: Only after HFP service is initialized and a service level connection exists between an HF Unit and an AG device, could other commands be available.** +**Note: Only after Hands-free Profile(HFP) service is initialized and a service level connection exists between an HF Unit and an AG device, could other commands be available.** -You can type `hf dis;` to disconnect with the connected HF Unit device, and log prints like: +You can type `hf dis;` to disconnect with the connected HF Unit device, and log prints such as: ``` E (100147) CNSL: Command [hf dis;] @@ -106,37 +110,32 @@ W (77381) BT_RFCOMM: RFCOMM_DisconnectInd LCID:0x41 You can type `hf cona;` to establish the audio connection between HF Unit and AG device. Also, you can type `hf disa;` to close the audio data stream. -#### Use Scenarios for Audio Connection +#### Scenarios for Audio Connection - Answer an incoming call - Enable voice recognition - Dial an outgoing call -#### Use Scenarios for Audio Disconnection +#### Scenarios for Audio Disconnection - Reject an incoming call - Disable the voice recognition -#### Audio Data path +#### Choise of Codec -- When using PCM as the data path and this example configures PCM audio data to GPIO pins. You can link the GPIO pins to a speaker via I2S port. PCM data path does not support mSBC codec but CVSD codec. -- When using HCI data path, ESP32 support both CVSD and mSBC codec. +ESP32 supports both CVSD and mSBC codec. HF Unit and AG device determine which codec to use by exchanging features during service level connection. The choice of codec also depends on the your configuration in `menuconfig`. -#### Codec - -ESP32 supports both CVSD and mSBC codec. HF Unit and AG device determine which codec to use by exchanging features in the process of a service level connection. The choice of codec also depends on the user's configuration in `menuconfig`. - -Since CVSD is the default codec in HFP, we just show the scenarios using mSBC : +Since CVSD is the default codec in HFP, we just show the scenarios using mSBC: - If you enable `BT_HFP_WBS_ENABLE` in `menuconfig`, mSBC will be available. -- If both HF Unit and AG support mSBC and also `BT_HFP_WBS_ENABLE` is enabled, ESP32 chooses mSBC. +- If both HF Unit and AG support mSBC and `BT_HFP_WBS_ENABLE` is enabled, ESP32 chooses mSBC. - If you use PCM data path, mSBC is not available. ### Answer or Reject an Incoming Call #### Answer an Incoming Call -You can type `hf ac;` to answer an incoming call and log prints like: +You can type `hf ac;` to answer an incoming call and log prints such as: ``` E (1066280) CNSL: Command [hf ac;] @@ -151,7 +150,7 @@ I (1067240) BT_APP_HF: --Audio State connected #### Reject an Incoming Call -You can type `hf rc;` to reject an incoming call and log prints like: +You can type `hf rc;` to reject an incoming call and log prints such as: ``` E (10040) CNSL: Command [hf rc;] @@ -162,7 +161,7 @@ I (1067240) BT_APP_HF: --Audio State disconnected #### End a Call -You can type `hf end;` to end the current ongoing call and log prints like: +You can type `hf end;` to end the current ongoing call and log prints such as: ``` E (157741) CNSL: Command [hf end;] @@ -175,7 +174,7 @@ I (159311) BT_APP_HF: --ESP AG Audio Connection Disconnected. ### Dial Number -You can type `hf d ;` to dial `` from AG and log prints like: +You can type `hf d ;` to dial `` from AG and log prints such as: ``` E (207351) CNSL: Command [hf d 18629485549;] @@ -191,19 +190,19 @@ I (208811) BT_APP_HF: --Audio State connected ### Volume Control -You can type `hf vu ;` to update volume gain of headset or microphone. The parameter set: +You can type `hf vu ;` to update the volume of a headset or microphone. The parameter should be set as follows: - `` : 0 - headset, 1 - microphone. - `` : Integer among 0 - 15. -For example, `hf vu 0 9;` update the volume of headset and log on AG side prints `Volume Update`, on HF Unit side log prints like: +For example, `hf vu 0 9;` updates the volume of headset and the log on the AG side prints `Volume Update`, while on the HF Unit side the log prints: ``` E (17087) BT_HF: APP HFP event: VOLUME_CONTROL_EVT E (17087) BT_HF: --volume_target: SPEAKER, volume 9 ``` -And also, `hf vu 1 9;` update the volume gain of microphone and log on HF Unit side prints like: +And also, `hf vu 1 9;` updates the volume of a microphone and the log on the HF Unit side prints: ``` E (32087) BT_HF: APP HFP event: VOLUME_CONTROL_EVT @@ -212,7 +211,7 @@ E (32087) BT_HF: --volume_target: MICROPHONE, volume 9 #### Voice Recognition -You can type `hf vron;` to start the voice recognition of AG and type `hf vroff;` to terminate the voice recognition. Both command will notify the HF Unit the status of voice recognition. For example, type `hf vron;` and log prints like: +You can type `hf vron;` to start the voice recognition and type `hf vroff;` to terminate this function in the AG device. Both commands will notify the HF Unit the status of voice recognition. For example, type `hf vron;` and the log will prints: ``` E (244131) CNSL: Command [hf vron;] @@ -224,9 +223,9 @@ I (245311) BT_APP_HF: APP HFP event: AUDIO_STATE_EVT I (245311) BT_APP_HF: --Audio State connected ``` -#### Notify Device Notification +#### Device Status Indication -You can type `hf ind ` to send device status of AG to HF Unit. Log on AG prints like: `Device Indicator Changed!` and on HF Unit side prints like: +You can type `hf ind ` to send device status of AG to HF Unit. Log on AG prints such as: `Device Indicator Changed!` and on HF Unit side prints such as: ``` E (293641) BT_HF: APP HFP event: CALL_IND_EVT @@ -237,26 +236,25 @@ E (293651) BT_HF: APP HFP event: SIGNAL_STRENGTH_IND_EVT E (293661) BT_HF: -- signal strength: 5 ``` -**Note: AG only sends changed status to HF Unit.** +**Note: The AG device sends only the changed status to the HF Unit.** #### Send Extended AT Error Code -You can type `hf ate ` to send extended AT error code to HF Unit. Parameter set: +You can type `hf ate ` to send extended AT error code to HF Unit. The parameter should be set as follows: - `` : integer among 0 - 7. - `` : integer among 0 - 32. -When you type `hf ate 7 7;` log on AG side prints like `Send CME Error.` and on HF Unit side prints like: +When you type `hf ate 7 7;` the log on the AG side prints `Send CME Error.` while on the HF Unit side prints: ``` E (448146) BT_HF: APP HFP event: AT_RESPONSE E (448146) BT_HF: --AT response event, code 7, cme 7 - ``` #### In-Band Ring Tone Setting -You can type `hf iron;` to enable in-band ring tone and type `hf iroff;` to disable in-band ring tone. Log on AG side prints like `Device Indicator Changed!` and on HF Unit side prints like: +You can type `hf iron;` to enable the in-band ring tone and type `hf iroff;` to disable it. The log on the AG side prints such as `Device Indicator Changed!` and on HF Unit side it prints such as: ``` E (19546) BT_HF: APP HFP event: IN-BAND_RING_TONE_EVT @@ -268,17 +266,17 @@ E (19556) BT_HF: --in-band ring state Provided If you encounter any problems, please check if the following rules are followed: - You should type the command in the terminal according to the format described in the commands help table. -- Not all commands in the table are supported by HF Unit. -- If you want to `hf con;` to establish a service level connection with specific HF Unit, you should add the MAC address of HF Unit in `app_hf_msg_set.c`, for example: `esp_bd_addr_t peer_addr = {0xb4, 0xe6, 0x2d, 0xeb, 0x09, 0x93};` +- Not all commands in the table are supported by the HF Unit. +- If you want to `hf con;` to establish a service level connection with a specific HF Unit, you should add the MAC address of the HF Unit in `app_hf_msg_set.c` for example: `esp_bd_addr_t peer_addr = {0xb4, 0xe6, 0x2d, 0xeb, 0x09, 0x93};` - Use `esp_hf_client_register_callback()` and `esp_hf_client_init();` before establishing a service level connection. ## Example Breakdown -Due to the complexity of Hands Free Profile, this example has more source files than other bluetooth examples. To show functions of Hands Free Profile in a simple way, we use the Commands and Effects scheme to illustrate APIs of HFP in ESP-IDF. +Due to the complexity of the HFP, this example has more source files than other bluetooth examples. To show the functions of HFP in a simple way, we use the Commands and Effects scheme to illustrate APIs of the HFP in ESP-IDF. -- The example will respond to user command through UART console. Please go to `console_uart.c` for the configuration details. -- For voice interface, ESP32 has provided PCM input/output signals which can be mapped to GPIO pins, please go to `gpio_pcm_config.c` for the configuration details. +- The example will respond to user command through the UART console. Please go to `console_uart.c` for the configuration details. +- For the voice interface, ESP32 has provided PCM input/output signals which can be directed to GPIO pins. So, please go to `gpio_pcm_config.c` for the configuration details. - If you want to update the command table, please refer to `app_hf_msg_set.c`. - If you want to update the command parse rules, please refer to `app_hf_msg_prs.c`. -- If you want to update the responses of AG or want to update the log, please refer to `bt_app_hf.c`. -- Task configuration part is in `bt_app_core.c`. \ No newline at end of file +- If you want to update the responses of the AG or want to update the log, please refer to `bt_app_hf.c`. +- The task configuration part is in `bt_app_core.c`. \ No newline at end of file diff --git a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/app_hf_msg_set.c b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/app_hf_msg_set.c index 0e22c87707..97566f10ef 100644 --- a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/app_hf_msg_set.c +++ b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/app_hf_msg_set.c @@ -30,7 +30,7 @@ void hf_msg_show_usage(void) printf("hf vu ; -- volume update\n"); printf(" tgt: 0-speaker, 1-microphone\n"); printf(" vol: volume gain ranges from 0 to 15\n"); - printf("hf ind ; -- unsolicited notify device notification to HF Client\n"); + printf("hf ind ; -- unsolicited indication device status to HF Client\n"); printf(" call: call status [0,1]\n"); printf(" callsetup: call setup status [0,3]\n"); printf(" ntk: network status [0,1]\n"); 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 412ee233b8..6c9e25d835 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 @@ -190,6 +190,17 @@ void bt_app_hf_cb(esp_hf_cb_event_t event, esp_hf_cb_param_t *param) break; } + case ESP_HF_IND_UPDATE_EVT: + { + ESP_LOGI(BT_HF_TAG, "--UPDATE INDCATOR!"); + esp_hf_call_status_t call_state = 1; + esp_hf_call_setup_status_t call_setup_state = 2; + esp_hf_network_state_t ntk_state = 1; + int signal = 2; + esp_bt_hf_indchange_notification(hf_peer_addr,call_state,call_setup_state,ntk_state,signal); + break; + } + case ESP_HF_CIND_RESPONSE_EVT: { ESP_LOGI(BT_HF_TAG, "--CIND Start."); diff --git a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/console_uart.c b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/console_uart.c index 32d8c7c727..640f15d0af 100644 --- a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/console_uart.c +++ b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/console_uart.c @@ -96,7 +96,7 @@ esp_err_t console_uart_init(void) ret = uart_param_config(CONSOLE_UART_NUM, &uart_cfg); if (ret != ESP_OK) { - ESP_LOGE(TAG_CNSL, "Uart %d initialize err %04x\n", CONSOLE_UART_NUM, ret); + ESP_LOGE(TAG_CNSL, "Uart %d initialize err %04x", CONSOLE_UART_NUM, ret); return ret; } From 897ee41a51315c69a9fa8f39f7b7e198a8a66a64 Mon Sep 17 00:00:00 2001 From: weitianhua Date: Mon, 18 Nov 2019 17:11:35 +0800 Subject: [PATCH 5/5] Change this MR from adding example to bugfix in HFP AG Component --- .../classic_bt/hfp_ag/CMakeLists.txt | 6 - .../bluedroid/classic_bt/hfp_ag/Makefile | 9 - .../bluedroid/classic_bt/hfp_ag/README.md | 282 ---------------- .../classic_bt/hfp_ag/main/CMakeLists.txt | 8 - .../classic_bt/hfp_ag/main/app_hf_msg_prs.c | 168 ---------- .../classic_bt/hfp_ag/main/app_hf_msg_prs.h | 48 --- .../classic_bt/hfp_ag/main/app_hf_msg_set.c | 255 --------------- .../classic_bt/hfp_ag/main/app_hf_msg_set.h | 26 -- .../classic_bt/hfp_ag/main/bt_app_core.c | 112 ------- .../classic_bt/hfp_ag/main/bt_app_core.h | 47 --- .../classic_bt/hfp_ag/main/bt_app_hf.c | 303 ------------------ .../classic_bt/hfp_ag/main/bt_app_hf.h | 27 -- .../classic_bt/hfp_ag/main/component.mk | 5 - .../classic_bt/hfp_ag/main/console_uart.c | 108 ------- .../classic_bt/hfp_ag/main/console_uart.h | 19 -- .../classic_bt/hfp_ag/main/gpio_pcm_config.c | 92 ------ .../classic_bt/hfp_ag/main/gpio_pcm_config.h | 20 -- .../bluedroid/classic_bt/hfp_ag/main/main.c | 121 ------- .../classic_bt/hfp_ag/sdkconfig.defaults | 9 - 19 files changed, 1665 deletions(-) delete mode 100644 examples/bluetooth/bluedroid/classic_bt/hfp_ag/CMakeLists.txt delete mode 100644 examples/bluetooth/bluedroid/classic_bt/hfp_ag/Makefile delete mode 100644 examples/bluetooth/bluedroid/classic_bt/hfp_ag/README.md delete mode 100644 examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/CMakeLists.txt delete mode 100644 examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/app_hf_msg_prs.c delete mode 100644 examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/app_hf_msg_prs.h delete mode 100644 examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/app_hf_msg_set.c delete mode 100644 examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/app_hf_msg_set.h delete mode 100644 examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/bt_app_core.c delete mode 100644 examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/bt_app_core.h delete mode 100644 examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/bt_app_hf.c delete mode 100644 examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/bt_app_hf.h delete mode 100644 examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/component.mk delete mode 100644 examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/console_uart.c delete mode 100644 examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/console_uart.h delete mode 100644 examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/gpio_pcm_config.c delete mode 100644 examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/gpio_pcm_config.h delete mode 100644 examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/main.c delete mode 100644 examples/bluetooth/bluedroid/classic_bt/hfp_ag/sdkconfig.defaults diff --git a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/CMakeLists.txt b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/CMakeLists.txt deleted file mode 100644 index ab8aa0ac17..0000000000 --- a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -# The following lines of boilerplate have to be in your project's -# CMakeLists in this exact order for cmake to work correctly -cmake_minimum_required(VERSION 3.5) - -include($ENV{IDF_PATH}/tools/cmake/project.cmake) -project(hfp_ag) diff --git a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/Makefile b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/Makefile deleted file mode 100644 index b539a2d52b..0000000000 --- a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# -# This is a project Makefile. It is assumed the directory this Makefile resides in is a -# project subdirectory. -# - -PROJECT_NAME := hfp_ag - -include $(IDF_PATH)/make/project.mk - diff --git a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/README.md b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/README.md deleted file mode 100644 index e2828656a4..0000000000 --- a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/README.md +++ /dev/null @@ -1,282 +0,0 @@ -# Hands-Free Audio Gateway - -This example is to show how to use the APIs of Hands-Free (HF) Audio Gateway (AG) Component and the effects of them by providing a set of commands. You can use this example to communicate with a Hands-Free Unit (e.g. a headphone set). This example uses UART for user commands. - -## How to use example - -### Hardware Required - -This example is designed to run on commonly available ESP32 development board, e.g. ESP32-DevKitC. To operate it should be connected to an Hands-Free Unit running on a Headphone/Headset or on another ESP32 development board loaded with Hands Free Unit (hfp_hf) example from ESP-IDF. - -### Configure the project - -``` -idf.py menuconfig -``` - -ESP32 supports two types of audio data paths: PCM and HCI but the default sdkconfig of this example does not config the data path in a specific way. You should config the data path you want: - -- PCM : When using PCM, audio data stream is directed to GPIO pins and you should link these GPIO pins to a speaker via I2S port. You should choose PCM in `menuconfig` path: `Component config --> Bluetooth controller --> BR/EDR Sync(SCO/eSCO) default data path --> PCM`and also `Component config --> Bluetooth --> Bluedroid Options -->Hands Free/Handset Profile --> audio(SCO) data path --> PCM`. -- HCI : When using HCI, audio data stream will be transport to HF unit app via HCI. You should choose HCI in `menuconfig` path: `Component config -->Bluetooth controller -->BR/EDR Sync(SCO/eSCO) default data path --> HCI` and also `Component config --> Bluetooth --> Bluedroid Options -->Hands Free/Handset Profile --> audio(SCO) data path --> HCI`. - -**Note: Wide Band Speech is disabled by default, if you want to use it please select it in the menuconfig path: `Component config --> Bluetooth --> Bluedroid Options --> Wide Band Speech`.** - -### Build and Flash - -Build the project and flash it to the board. Then, run monitor tool to view serial output: - -``` -idf.py -p PORT flash monitor -``` - -(Replace PORT with the name of the serial port to use.) - -(To exit the serial monitor, type ``Ctrl-]``.) - -See the [Getting Started Guide](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/index.html) for full steps to configure and use ESP-IDF to build projects. - -## Example Output - -When you flash and monitor this example the commands help table prints the following at the very begining: - -``` -######################################################################## -HFP AG command usage manual -HFP AG commands begins with "hf" and end with ";" -Supported commands are as follows, arguments are embraced with < and > - -hf con; -- setup connection with peer device -hf dis; -- release connection with peer device -hf cona; -- setup audio connection with peer device -hf disa; -- release connection with peer device -hf vron; -- start voice recognition -hf vroff; -- stop voice recognition -hf vu ; -- volume update - tgt: 0-speaker, 1-microphone - vol: volume gain ranges from 0 to 15 -hf ind ; -- unsolicited indication device status to HF Client - call: call status [0,1] - callsetup: call setup status [0,3] - ntk: network status [0,1] - sig: signal strength value from 0~5 -hf ate ; -- send extended at error code - rep: response code from 0 to 7 - err: error code from 0 to 32 -hf iron; -- in-band ring tone provided -hf iroff; -- in-band ring tone not provided -hf ac; -- Answer Incoming Call from AG -hf rc; -- Reject Incoming Call from AG -hf d ; -- Dial Number by AG, e.g. hf d 11223344 -hf end; -- End a call by AG -hf h; -- to see the command for HFP AG -######################################################################## -``` - -**Note:** - -- This command help table will print out in monitor whenever you type `hf h;` or if you input a command that is not required by the command parse rule. -- The command you type will not echo in monitor and your command should always start with `hf` and end with `;` or the example will not responds. -- The command you typed will not echo in monitor. - -### Service Level Connection and Disconnection - -You can type `hf con;` to establish a service level connection with HF Unit device and log prints such as: - -``` -W (2211) BT_APPL: new conn_srvc id:5, app_id:0 -I (2221) BT_APP_HF: APP HFP event: CONNECTION_STATE_EVT -I (2221) BT_APP_HF: --connection state CONNECTED, peer feats 0x0, chld_feats 0x0 -I (2291) BT_APP_HF: APP HFP event: CIND_RESPONSE_EVT -I (2291) BT_APP_HF: --CIND Start. -I (2331) BT_APP_HF: APP HFP event: CONNECTION_STATE_EVT -I (2331) BT_APP_HF: --connection state SLC_CONNECTED, peer feats 0xff, chld_feats 0x4010 -``` - -**Note: Only after Hands-free Profile(HFP) service is initialized and a service level connection exists between an HF Unit and an AG device, could other commands be available.** - -You can type `hf dis;` to disconnect with the connected HF Unit device, and log prints such as: - -``` -E (100147) CNSL: Command [hf dis;] -disconnect -W (77321) BT_RFCOMM: port_rfc_closed RFCOMM connection in state 2 closed: Closed (res: 19) -I (77321) BT_APP_HF: APP HFP event: CONNECTION_STATE_EVT -I (77321) BT_APP_HF: --connection state DISCONNECTED, peer feats 0x0, chld_feats 0x0 -W (77381) BT_RFCOMM: rfc_find_lcid_mcb LCID reused LCID:0x41 current:0x0 -W (77381) BT_RFCOMM: RFCOMM_DisconnectInd LCID:0x41 -``` - -### Audio Connection and Disconnection - -You can type `hf cona;` to establish the audio connection between HF Unit and AG device. Also, you can type `hf disa;` to close the audio data stream. - -#### Scenarios for Audio Connection - -- Answer an incoming call -- Enable voice recognition -- Dial an outgoing call - -#### Scenarios for Audio Disconnection - -- Reject an incoming call -- Disable the voice recognition - -#### Choise of Codec - -ESP32 supports both CVSD and mSBC codec. HF Unit and AG device determine which codec to use by exchanging features during service level connection. The choice of codec also depends on the your configuration in `menuconfig`. - -Since CVSD is the default codec in HFP, we just show the scenarios using mSBC: - -- If you enable `BT_HFP_WBS_ENABLE` in `menuconfig`, mSBC will be available. -- If both HF Unit and AG support mSBC and `BT_HFP_WBS_ENABLE` is enabled, ESP32 chooses mSBC. -- If you use PCM data path, mSBC is not available. - -### Answer or Reject an Incoming Call - -#### Answer an Incoming Call - -You can type `hf ac;` to answer an incoming call and log prints such as: - -``` -E (1066280) CNSL: Command [hf ac;] -Answer Call from AG. -W (1066280) BT_APPL: BTA_AG_SCO_CODEC_ST: Ignoring event 1 -I (1067200) BT_APP_HF: APP HFP event: BCS_EVT -I (1067200) BT_APP_HF: --AG choose codec mode: CVSD Only -E (1067230) BT_BTM: btm_sco_connected, handle 180 -I (1067240) BT_APP_HF: APP HFP event: AUDIO_STATE_EVT -I (1067240) BT_APP_HF: --Audio State connected -``` - -#### Reject an Incoming Call - -You can type `hf rc;` to reject an incoming call and log prints such as: - -``` -E (10040) CNSL: Command [hf rc;] -Reject Call from AG. -I (1067240) BT_APP_HF: APP HFP event: AUDIO_STATE_EVT -I (1067240) BT_APP_HF: --Audio State disconnected -``` - -#### End a Call - -You can type `hf end;` to end the current ongoing call and log prints such as: - -``` -E (157741) CNSL: Command [hf end;] -End Call from AG. -W (157741) BT_APPL: BTA_AG_SCO_CLOSING_ST: Ignoring event 3 -I (159311) BT_APP_HF: APP HFP event: AUDIO_STATE_EVT -I (159311) BT_APP_HF: --Audio State disconnected -I (159311) BT_APP_HF: --ESP AG Audio Connection Disconnected. -``` - -### Dial Number - -You can type `hf d ;` to dial `` from AG and log prints such as: - -``` -E (207351) CNSL: Command [hf d 18629485549;] -Dial number 18629485549 -I (207361) BT_APP_HF: APP HFP event: AUDIO_STATE_EVT -I (207361) BT_APP_HF: --Audio State connecting -W (207361) BT_APPL: BTA_AG_SCO_OPENING_ST: Ignoring event 1 -W (207371) BT_APPL: BTA_AG_SCO_OPENING_ST: Ignoring event 1 -E (208801) BT_BTM: btm_sco_connected, handle 181 -I (208811) BT_APP_HF: APP HFP event: AUDIO_STATE_EVT -I (208811) BT_APP_HF: --Audio State connected -``` - -### Volume Control - -You can type `hf vu ;` to update the volume of a headset or microphone. The parameter should be set as follows: - -- `` : 0 - headset, 1 - microphone. -- `` : Integer among 0 - 15. - -For example, `hf vu 0 9;` updates the volume of headset and the log on the AG side prints `Volume Update`, while on the HF Unit side the log prints: - -``` -E (17087) BT_HF: APP HFP event: VOLUME_CONTROL_EVT -E (17087) BT_HF: --volume_target: SPEAKER, volume 9 -``` - -And also, `hf vu 1 9;` updates the volume of a microphone and the log on the HF Unit side prints: - -``` -E (32087) BT_HF: APP HFP event: VOLUME_CONTROL_EVT -E (32087) BT_HF: --volume_target: MICROPHONE, volume 9 -``` - -#### Voice Recognition - -You can type `hf vron;` to start the voice recognition and type `hf vroff;` to terminate this function in the AG device. Both commands will notify the HF Unit the status of voice recognition. For example, type `hf vron;` and the log will prints: - -``` -E (244131) CNSL: Command [hf vron;] -Start Voice Recognition. -I (244141) BT_APP_HF: APP HFP event: AUDIO_STATE_EVT -I (244141) BT_APP_HF: --Audio State connecting -E (245301) BT_BTM: btm_sco_connected, handle 181 -I (245311) BT_APP_HF: APP HFP event: AUDIO_STATE_EVT -I (245311) BT_APP_HF: --Audio State connected -``` - -#### Device Status Indication - -You can type `hf ind ` to send device status of AG to HF Unit. Log on AG prints such as: `Device Indicator Changed!` and on HF Unit side prints such as: - -``` -E (293641) BT_HF: APP HFP event: CALL_IND_EVT -E (293641) BT_HF: --Call indicator call in progress -E (293641) BT_HF: APP HFP event: CALL_SETUP_IND_EVT -E (293651) BT_HF: --Call setup indicator INCOMING -E (293651) BT_HF: APP HFP event: SIGNAL_STRENGTH_IND_EVT -E (293661) BT_HF: -- signal strength: 5 -``` - -**Note: The AG device sends only the changed status to the HF Unit.** - -#### Send Extended AT Error Code - -You can type `hf ate ` to send extended AT error code to HF Unit. The parameter should be set as follows: - -- `` : integer among 0 - 7. -- `` : integer among 0 - 32. - -When you type `hf ate 7 7;` the log on the AG side prints `Send CME Error.` while on the HF Unit side prints: - -``` -E (448146) BT_HF: APP HFP event: AT_RESPONSE -E (448146) BT_HF: --AT response event, code 7, cme 7 -``` - -#### In-Band Ring Tone Setting - -You can type `hf iron;` to enable the in-band ring tone and type `hf iroff;` to disable it. The log on the AG side prints such as `Device Indicator Changed!` and on HF Unit side it prints such as: - -``` -E (19546) BT_HF: APP HFP event: IN-BAND_RING_TONE_EVT -E (19556) BT_HF: --in-band ring state Provided -``` - -## Troubleshooting - -If you encounter any problems, please check if the following rules are followed: - -- You should type the command in the terminal according to the format described in the commands help table. -- Not all commands in the table are supported by the HF Unit. -- If you want to `hf con;` to establish a service level connection with a specific HF Unit, you should add the MAC address of the HF Unit in `app_hf_msg_set.c` for example: `esp_bd_addr_t peer_addr = {0xb4, 0xe6, 0x2d, 0xeb, 0x09, 0x93};` -- Use `esp_hf_client_register_callback()` and `esp_hf_client_init();` before establishing a service level connection. - -## Example Breakdown - -Due to the complexity of the HFP, this example has more source files than other bluetooth examples. To show the functions of HFP in a simple way, we use the Commands and Effects scheme to illustrate APIs of the HFP in ESP-IDF. - -- The example will respond to user command through the UART console. Please go to `console_uart.c` for the configuration details. -- For the voice interface, ESP32 has provided PCM input/output signals which can be directed to GPIO pins. So, please go to `gpio_pcm_config.c` for the configuration details. -- If you want to update the command table, please refer to `app_hf_msg_set.c`. -- If you want to update the command parse rules, please refer to `app_hf_msg_prs.c`. -- If you want to update the responses of the AG or want to update the log, please refer to `bt_app_hf.c`. -- The task configuration part is in `bt_app_core.c`. \ No newline at end of file diff --git a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/CMakeLists.txt b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/CMakeLists.txt deleted file mode 100644 index eff055634e..0000000000 --- a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -idf_component_register(SRCS "app_hf_msg_prs.c" - "app_hf_msg_set.c" - "bt_app_core.c" - "bt_app_hf.c" - "console_uart.c" - "gpio_pcm_config.c" - "main.c" - INCLUDE_DIRS ".") \ No newline at end of file diff --git a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/app_hf_msg_prs.c b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/app_hf_msg_prs.c deleted file mode 100644 index 2610bf2398..0000000000 --- a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/app_hf_msg_prs.c +++ /dev/null @@ -1,168 +0,0 @@ -/* - This example code is in the Public Domain (or CC0 licensed, at your option.) - - Unless required by applicable law or agreed to in writing, this - software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, either express or implied. -*/ - -#include -#include -#include -#include -#include -#include -#include "app_hf_msg_prs.h" -#include "app_hf_msg_set.h" - -// according to the design, message header length shall be no less than 2. -#define HF_MSG_HDR_LEN (3) -const static char hf_msg_hdr[HF_MSG_HDR_LEN] = {'h', 'f', ' '}; - -// according to the design, message header length shall be no less than 2. -#define HF_MSG_TAIL_LEN (1) -const static char hf_msg_tail[HF_MSG_TAIL_LEN] = {';'}; - -void hf_msg_parser_reset_state(hf_msg_prs_cb_t *prs) -{ - prs->state = HF_MSG_PRS_IDLE; - prs->cnt = 0; - prs->h_idx = 0; - prs->t_idx = 0; -} - -void hf_msg_parser_register_callback(hf_msg_prs_cb_t *prs, hf_msg_callback cb) -{ - prs->callback = cb; -} - -hf_msg_prs_err_t hf_msg_parse(char c, hf_msg_prs_cb_t *prs) -{ - hf_msg_prs_err_t err = HF_MSG_PRS_ERR_IN_PROGRESS; - switch (prs->state) - { - case HF_MSG_PRS_IDLE: - { - if (c == hf_msg_hdr[0]) { - prs->state = HF_MSG_PRS_HDR; - prs->buf[0] = c; - prs->cnt = 1; - prs->h_idx = 1; - } else { - err = HF_MSG_PRS_ERR_HDR_UNDETECTED; - } - } - break; - - case HF_MSG_PRS_HDR: - { - if (c == hf_msg_hdr[prs->h_idx]) { - prs->buf[prs->cnt++] = c; - if (++(prs->h_idx) == HF_MSG_HDR_LEN) { - prs->state = HF_MSG_PRS_PAYL; - prs->t_idx = 0; - } - } else { - hf_msg_parser_reset_state(prs); - err = HF_MSG_PRS_ERR_HDR_SYNC_FAILED; - } - } - break; - - case HF_MSG_PRS_PAYL: - { - prs->buf[prs->cnt++] = c; - if (c == hf_msg_tail[prs->t_idx]) { - if (++(prs->t_idx) == HF_MSG_TAIL_LEN) { - prs->buf[prs->cnt] = '\0'; - prs->callback(prs->buf, prs->cnt); - hf_msg_parser_reset_state(prs); - err = HF_MSG_PRS_ERR_OK; - break; - } - } else { - prs->t_idx = 0; - } - - if (prs->cnt >= HF_MSG_LEN_MAX) { - hf_msg_parser_reset_state(prs); - err = HF_MSG_PRS_ERR_BUF_OVERFLOW; - } - } - break; - } - return err; -} - - -void hf_msg_split_args(char *start, char *end, char **argv, int *argn) -{ - if (argn == NULL || *argn == 0) { - return; - } - - memset(argv, 0, (*argn) * sizeof(void *)); - - int max_argn = *argn; - *argn = 0; - - char *p = start; - for (int i = 0; i < max_argn; ++i) { - while (isspace((int)*p) && p != end) { - ++p; - } - if (p == end) { - return; - } - - argv[i] = p++; - ++(*argn); - - while (!isspace((int)*p) && p != end) { - ++p; - } - - if (p == end) { - return; - } else { - *p = '\0'; - ++p; - } - } -} - -void hf_msg_args_parser(char *buf, int len) -{ - char *argv[HF_MSG_ARGS_MAX]; - int argn = HF_MSG_ARGS_MAX; - char *start = buf + HF_MSG_HDR_LEN; - // set the command terminitor to '\0' - char *end = buf + len - HF_MSG_TAIL_LEN; - *end = '\0'; - - hf_msg_split_args(start, end, argv, &argn); - - if (argn == 0) { - return; - } - - bool cmd_supported = false; - - hf_msg_hdl_t *cmd_tbl = hf_get_cmd_tbl(); - size_t cmd_tbl_size = hf_get_cmd_tbl_size(); - for (int i = 0; i < cmd_tbl_size; ++i) { - hf_msg_hdl_t *hdl = &cmd_tbl[i]; - if (strcmp(argv[0], hdl->str) == 0) { - if (hdl->handler) { - hdl->handler(argn, argv); - cmd_supported = true; - break; - } - } - } - if (!cmd_supported) { - printf("unsupported command\n"); - hf_msg_show_usage(); - } - return; -} diff --git a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/app_hf_msg_prs.h b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/app_hf_msg_prs.h deleted file mode 100644 index 131a7a5418..0000000000 --- a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/app_hf_msg_prs.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - This example code is in the Public Domain (or CC0 licensed, at your option.) - - Unless required by applicable law or agreed to in writing, this - software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, either express or implied. -*/ - -#ifndef __APP_HF_MSG_PRS_H__ -#define __APP_HF_MSG_PRS_H__ - -typedef enum { - HF_MSG_PRS_ERR_OK = 0, // a complete message is finished - HF_MSG_PRS_ERR_IN_PROGRESS, // message parsing is in progress - HF_MSG_PRS_ERR_HDR_UNDETECTED, // header not detected - HF_MSG_PRS_ERR_HDR_SYNC_FAILED, // failed to sync header - HF_MSG_PRS_ERR_BUF_OVERFLOW, // exceeds the buffer size: HF_MSG_LEN_MAX -} hf_msg_prs_err_t; - -typedef enum { - HF_MSG_PRS_IDLE = 0, - HF_MSG_PRS_HDR, - HF_MSG_PRS_PAYL, -} hf_msg_prs_state_t; - -typedef void (*hf_msg_callback)(char *buf, int len); - -#define HF_MSG_LEN_MAX (128) - -typedef struct { - hf_msg_prs_state_t state; - char buf[HF_MSG_LEN_MAX + 1]; - int cnt; - int h_idx; - int t_idx; - hf_msg_callback callback; -} hf_msg_prs_cb_t; - -void hf_msg_parser_reset_state(hf_msg_prs_cb_t *prs); - -void hf_msg_parser_register_callback(hf_msg_prs_cb_t *prs, hf_msg_callback cb); - -hf_msg_prs_err_t hf_msg_parse(char c, hf_msg_prs_cb_t *prs); - -void hf_msg_show_usage(void); - -#endif /* __APP_HF_MSG_PRS_H__*/ - diff --git a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/app_hf_msg_set.c b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/app_hf_msg_set.c deleted file mode 100644 index 97566f10ef..0000000000 --- a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/app_hf_msg_set.c +++ /dev/null @@ -1,255 +0,0 @@ -/* - This example code is in the Public Domain (or CC0 licensed, at your option.) - - Unless required by applicable law or agreed to in writing, this - software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, either express or implied. -*/ - -#include -#include -#include "esp_hf_ag_api.h" -#include "app_hf_msg_set.h" -#include "bt_app_hf.h" - -// if you want to connect a specific device, add it's bda here -// esp_bd_addr_t hf_peer_addr = {0x70,0x26,0x05,0xca,0xeb,0x21}; - -void hf_msg_show_usage(void) -{ - printf("########################################################################\n"); - printf("HFP AG command usage manual\n"); - printf("HFP AG commands begins with \"hf\" and end with \";\"\n"); - printf("Supported commands are as follows, arguments are embraced with < and >\n\n"); - printf("hf con; -- setup connection with peer device\n"); - printf("hf dis; -- release connection with peer device\n"); - printf("hf cona; -- setup audio connection with peer device\n"); - printf("hf disa; -- release connection with peer device\n"); - printf("hf vron; -- start voice recognition\n"); - printf("hf vroff; -- stop voice recognition\n"); - printf("hf vu ; -- volume update\n"); - printf(" tgt: 0-speaker, 1-microphone\n"); - printf(" vol: volume gain ranges from 0 to 15\n"); - printf("hf ind ; -- unsolicited indication device status to HF Client\n"); - printf(" call: call status [0,1]\n"); - printf(" callsetup: call setup status [0,3]\n"); - printf(" ntk: network status [0,1]\n"); - printf(" sig: signal strength value from 0~5\n"); - printf("hf ate ; -- send extended at error code\n"); - printf(" rep: response code from 0 to 7\n"); - printf(" err: error code from 0 to 32\n"); - printf("hf iron; -- in-band ring tone provided\n"); - printf("hf iroff; -- in-band ring tone not provided\n"); - printf("hf ac; -- Answer Incoming Call from AG\n"); - printf("hf rc; -- Reject Incoming Call from AG\n"); - printf("hf d ; -- Dial Number by AG, e.g. hf d 11223344\n"); - printf("hf end; -- End up a call by AG\n"); - printf("hf h; -- to see the command for HFP AG\n"); - printf("########################################################################\n"); -} - -#define HF_CMD_HANDLER(cmd) static void hf_##cmd##_handler(int argn, char **argv) - -HF_CMD_HANDLER(help) -{ - hf_msg_show_usage(); -} - -HF_CMD_HANDLER(conn) -{ - printf("Connect.\n"); - esp_bt_hf_connect(hf_peer_addr); -} - -HF_CMD_HANDLER(disc) -{ - printf("Disconnect\n"); - esp_bt_hf_disconnect(hf_peer_addr); -} - -HF_CMD_HANDLER(conn_audio) -{ - printf("Connect Audio\n"); - esp_bt_hf_connect_audio(hf_peer_addr); -} - -HF_CMD_HANDLER(disc_audio) -{ - printf("Disconnect Audio\n"); - esp_bt_hf_disconnect_audio(hf_peer_addr); -} - -//AT+BVRA -HF_CMD_HANDLER(vra_on) -{ - printf("Start Voice Recognition.\n"); - esp_bt_hf_vra(hf_peer_addr,1); -} -//AT+BVRA -HF_CMD_HANDLER(vra_off) -{ - printf("Stop Voicer Recognition.\n"); - esp_bt_hf_vra(hf_peer_addr,0); -} - -//AT+VGS or AT+VGM -HF_CMD_HANDLER(volume_control) -{ - if (argn != 3) { - printf("Insufficient number of arguments"); - return; - } - int target, volume; - if (sscanf(argv[1], "%d", &target) != 1 || - (target != ESP_HF_VOLUME_CONTROL_TARGET_SPK && - target != ESP_HF_VOLUME_CONTROL_TARGET_MIC)) { - printf("Invalid argument for target %s\n", argv[1]); - return; - } - if (sscanf(argv[2], "%d", &volume) != 1 || - (volume < 0 || volume > 15)) { - printf("Invalid argument for volume %s\n", argv[2]); - return; - } - printf("Volume Update\n"); - esp_bt_hf_volume_control(hf_peer_addr, target, volume); -} - -//+CIEV -HF_CMD_HANDLER(ind_change) -{ - if (argn != 5) { - printf("Insufficient number of arguments"); - return; - } - - int call_state, ntk_state, call_setup_state, signal; - - if (sscanf(argv[1], "%d", &call_state) != 1 || - (call_state != ESP_HF_CALL_STATUS_NO_CALLS && - call_state != ESP_HF_CALL_STATUS_CALL_IN_PROGRESS)) { - printf("Invalid argument for call state %s\n", argv[1]); - return; - } - if (sscanf(argv[2], "%d", &call_setup_state) != 1 || - (call_setup_state < ESP_HF_CALL_SETUP_STATUS_IDLE || call_setup_state > ESP_HF_CALL_SETUP_STATUS_OUTGOING_ALERTING)) { - printf("Invalid argument for callsetup state %s\n", argv[2]); - return; - } - if (sscanf(argv[3], "%d", &ntk_state) != 1 || - (ntk_state != ESP_HF_NETWORK_STATE_NOT_AVAILABLE && - ntk_state != ESP_HF_NETWORK_STATE_AVAILABLE)) { - printf("Invalid argument for netwrok state %s\n", argv[3]); - return; - } - if (sscanf(argv[4], "%d", &signal) != 1 || - (signal < 0 || signal > 5)) { - printf("Invalid argument for signal %s\n", argv[4]); - return; - } - printf("Device Indicator Changed!\n"); - esp_bt_hf_indchange_notification(hf_peer_addr, call_state, call_setup_state, ntk_state, signal); -} - -//AT+CMEE -HF_CMD_HANDLER(cme_err) -{ - if (argn != 3) { - printf("Insufficient number of arguments"); - return; - } - - int response_code, error_code; - if (sscanf(argv[1], "%d", &response_code) != 1 || - (response_code < ESP_HF_AT_RESPONSE_CODE_OK && response_code > ESP_HF_AT_RESPONSE_CODE_CME)) { - printf("Invalid argument for response_code %s\n", argv[1]); - return; - } - - if (sscanf(argv[2], "%d", &error_code) != 1 || - (error_code < ESP_HF_CME_AG_FAILURE || error_code > ESP_HF_CME_NETWORK_NOT_ALLOWED)) { - printf("Invalid argument for volume %s\n", argv[2]); - return; - } - - printf("Send CME Error.\n"); - esp_bt_hf_cmee_response(hf_peer_addr,response_code,error_code); -} - -//+BSIR:1 -HF_CMD_HANDLER(ir_on) -{ - printf("Enable Voicer Recognition.\n"); - esp_bt_hf_bsir(hf_peer_addr,1); -} - -//+BSIR:0 -HF_CMD_HANDLER(ir_off) -{ - printf("Disable Voicer Recognition.\n"); - esp_bt_hf_bsir(hf_peer_addr,0); -} - -//Answer Call from AG -HF_CMD_HANDLER(ac) -{ - printf("Answer Call from AG.\n"); - char *number = {"186xxxx5549"}; - esp_bt_hf_answer_call(hf_peer_addr,1,0,1,1,number,0); -} - -//Reject Call from AG -HF_CMD_HANDLER(rc) -{ - printf("Reject Call from AG.\n"); - char *number = {"186xxxx5549"}; - esp_bt_hf_reject_call(hf_peer_addr,0,0,0,0,number,0); -} - -//End Call from AG -HF_CMD_HANDLER(end) -{ - printf("End Call from AG.\n"); - char *number = {"186xxxx5549"}; - esp_bt_hf_end_call(hf_peer_addr,0,0,0,0,number,0); -} - -//Dial Call from AG -HF_CMD_HANDLER(d) -{ - if (argn != 2) { - printf("Insufficient number of arguments"); - } else { - printf("Dial number %s\n", argv[1]); - esp_bt_hf_out_call(hf_peer_addr,1,0,1,2,argv[1],0); - } -} - -static hf_msg_hdl_t hf_cmd_tbl[] = { - {0, "h", hf_help_handler}, - {5, "con", hf_conn_handler}, - {10, "dis", hf_disc_handler}, - {20, "cona", hf_conn_audio_handler}, - {30, "disa", hf_disc_audio_handler}, - {40, "vu", hf_volume_control_handler}, - {50, "ind", hf_ind_change_handler}, - {60, "vron", hf_vra_on_handler}, - {70, "vroff", hf_vra_off_handler}, - {80, "ate", hf_cme_err_handler}, - {90, "iron", hf_ir_on_handler}, - {100, "iroff", hf_ir_off_handler}, - {110, "ac", hf_ac_handler}, - {120, "rc", hf_rc_handler}, - {130, "end", hf_end_handler}, - {140, "d", hf_d_handler}, -}; - -hf_msg_hdl_t *hf_get_cmd_tbl(void) -{ - return hf_cmd_tbl; -} - -size_t hf_get_cmd_tbl_size(void) -{ - return sizeof(hf_cmd_tbl) / sizeof(hf_msg_hdl_t); -} diff --git a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/app_hf_msg_set.h b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/app_hf_msg_set.h deleted file mode 100644 index de59abf832..0000000000 --- a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/app_hf_msg_set.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - This example code is in the Public Domain (or CC0 licensed, at your option.) - - Unless required by applicable law or agreed to in writing, this - software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, either express or implied. -*/ - -#ifndef __APP_HF_MSG_SET_H__ -#define __APP_HF_MSG_SET_H__ - -#define HF_MSG_ARGS_MAX (8) - -typedef void (* hf_cmd_handler)(int argn, char **argv); - -typedef struct { - uint16_t opcode; - const char *str; - hf_cmd_handler handler; -} hf_msg_hdl_t; - -extern hf_msg_hdl_t *hf_get_cmd_tbl(void); -extern size_t hf_get_cmd_tbl_size(void); - -void hf_msg_show_usage(void); -#endif /* __APP_HF_MSG_SET_H__*/ diff --git a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/bt_app_core.c b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/bt_app_core.c deleted file mode 100644 index 89749c674f..0000000000 --- a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/bt_app_core.c +++ /dev/null @@ -1,112 +0,0 @@ -/* - This example code is in the Public Domain (or CC0 licensed, at your option.) - - Unless required by applicable law or agreed to in writing, this - software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, either express or implied. -*/ - -#include -#include -#include -#include "freertos/xtensa_api.h" -#include "freertos/FreeRTOSConfig.h" -#include "freertos/FreeRTOS.h" -#include "freertos/queue.h" -#include "freertos/task.h" -#include "esp_log.h" -#include "bt_app_core.h" - -static void bt_app_task_handler(void *arg); -static bool bt_app_send_msg(bt_app_msg_t *msg); -static void bt_app_work_dispatched(bt_app_msg_t *msg); - -static xQueueHandle bt_app_task_queue = NULL; -static xTaskHandle bt_app_task_handle = NULL; - -bool bt_app_work_dispatch(bt_app_cb_t p_cback, uint16_t event, void *p_params, int param_len, bt_app_copy_cb_t p_copy_cback) -{ - ESP_LOGD(BT_APP_CORE_TAG, "%s event 0x%x, param len %d", __func__, event, param_len); - - bt_app_msg_t msg; - memset(&msg, 0, sizeof(bt_app_msg_t)); - - msg.sig = BT_APP_SIG_WORK_DISPATCH; - msg.event = event; - msg.cb = p_cback; - - if (param_len == 0) { - return bt_app_send_msg(&msg); - } else if (p_params && param_len > 0) { - if ((msg.param = malloc(param_len)) != NULL) { - memcpy(msg.param, p_params, param_len); - /* check if caller has provided a copy callback to do the deep copy */ - if (p_copy_cback) { - p_copy_cback(&msg, msg.param, p_params); - } - return bt_app_send_msg(&msg); - } - } - return false; -} - -static bool bt_app_send_msg(bt_app_msg_t *msg) -{ - if (msg == NULL) { - return false; - } - - if (xQueueSend(bt_app_task_queue, msg, 10 / portTICK_RATE_MS) != pdTRUE) { - ESP_LOGE(BT_APP_CORE_TAG, "%s xQueue send failed", __func__); - return false; - } - return true; -} - -static void bt_app_work_dispatched(bt_app_msg_t *msg) -{ - if (msg->cb) { - msg->cb(msg->event, msg->param); - } -} - -static void bt_app_task_handler(void *arg) -{ - bt_app_msg_t msg; - for (;;) { - if (pdTRUE == xQueueReceive(bt_app_task_queue, &msg, (portTickType)portMAX_DELAY)) { - ESP_LOGD(BT_APP_CORE_TAG, "%s, sig 0x%x, 0x%x", __func__, msg.sig, msg.event); - switch (msg.sig) { - case BT_APP_SIG_WORK_DISPATCH: - bt_app_work_dispatched(&msg); - break; - default: - ESP_LOGW(BT_APP_CORE_TAG, "%s, unhandled sig: %d", __func__, msg.sig); - break; - } // switch (msg.sig) - - if (msg.param) { - free(msg.param); - } - } - } -} - -void bt_app_task_start_up(void) -{ - bt_app_task_queue = xQueueCreate(10, sizeof(bt_app_msg_t)); - xTaskCreate(bt_app_task_handler, "BtAppT", 2048, NULL, configMAX_PRIORITIES - 3, &bt_app_task_handle); - return; -} - -void bt_app_task_shut_down(void) -{ - if (bt_app_task_handle) { - vTaskDelete(bt_app_task_handle); - bt_app_task_handle = NULL; - } - if (bt_app_task_queue) { - vQueueDelete(bt_app_task_queue); - bt_app_task_queue = NULL; - } -} diff --git a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/bt_app_core.h b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/bt_app_core.h deleted file mode 100644 index 4415058a71..0000000000 --- a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/bt_app_core.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - This example code is in the Public Domain (or CC0 licensed, at your option.) - - Unless required by applicable law or agreed to in writing, this - software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, either express or implied. -*/ - -#ifndef __BT_APP_CORE_H__ -#define __BT_APP_CORE_H__ - -#include -#include -#include - -#define BT_APP_CORE_TAG "BT_APP_CORE" - -#define BT_APP_SIG_WORK_DISPATCH (0x01) - -/** - * @brief handler for the dispatched work - */ -typedef void (* bt_app_cb_t) (uint16_t event, void *param); - -/* message to be sent */ -typedef struct { - uint16_t sig; /*!< signal to bt_app_task */ - uint16_t event; /*!< message event id */ - bt_app_cb_t cb; /*!< context switch callback */ - void *param; /*!< parameter area needs to be last */ -} bt_app_msg_t; - -/** - * @brief parameter deep-copy function to be customized - */ -typedef void (* bt_app_copy_cb_t) (bt_app_msg_t *msg, void *p_dest, void *p_src); - -/** - * @brief work dispatcher for the application task - */ -bool bt_app_work_dispatch(bt_app_cb_t p_cback, uint16_t event, void *p_params, int param_len, bt_app_copy_cb_t p_copy_cback); - -void bt_app_task_start_up(void); - -void bt_app_task_shut_down(void); - -#endif /* __BT_APP_CORE_H__ */ 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 deleted file mode 100644 index 6c9e25d835..0000000000 --- a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/bt_app_hf.c +++ /dev/null @@ -1,303 +0,0 @@ -/* - This example code is in the Public Domain (or CC0 licensed, at your option.) - - Unless required by applicable law or agreed to in writing, this - software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, either express or implied. -*/ - -#include -#include -#include -#include -#include "esp_log.h" -#include "esp_bt_main.h" -#include "esp_bt_device.h" -#include "esp_gap_bt_api.h" -#include "esp_hf_ag_api.h" -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "freertos/queue.h" -#include "freertos/semphr.h" -#include "time.h" -#include "sys/time.h" -#include "sdkconfig.h" -#include "bt_app_core.h" -#include "bt_app_hf.h" - -const char *c_hf_evt_str[] = { - "CONNECTION_STATE_EVT", /*!< SERVICE LEVEL CONNECTION STATE CONTROL */ - "AUDIO_STATE_EVT", /*!< AUDIO CONNECTION STATE CONTROL */ - "VR_STATE_CHANGE_EVT", /*!< VOICE RECOGNITION CHANGE */ - "VOLUME_CONTROL_EVT", /*!< AUDIO VOLUME CONTROL */ - "UNKNOW_AT_CMD", /*!< UNKNOW AT COMMAND RECIEVED */ - "CIND_RESPONSE_EVT", /*!< CALL & DEVICE INDICATION */ - "COPS_RESPONSE_EVT", /*!< CURRENT OPERATOR EVENT */ - "CLCC_RESPONSE_EVT", /*!< LIST OF CURRENT CALL EVENT */ - "CNUM_RESPONSE_EVT", /*!< SUBSCRIBER INFORTMATION OF CALL EVENT */ - "DTMF_RESPONSE_EVT", /*!< DTMF TRANSFER EVT */ - "NREC_RESPONSE_EVT", /*!< NREC RESPONSE EVT */ - "ANSWER_INCOMING_EVT", /*!< ANSWER INCOMING EVT */ - "REJECT_INCOMING_EVT", /*!< AREJECT INCOMING EVT */ - "DIAL_EVT", /*!< DIAL INCOMING EVT */ - "BAC_EVT", /*!< CODEC NEGO EVT */ - "BCS_EVT", /*!< CODEC NEGO EVT */ -}; - -//esp_hf_connection_state_t -const char *c_connection_state_str[] = { - "DISCONNECTED", - "CONNECTING", - "CONNECTED", - "SLC_CONNECTED", - "DISCONNECTING", -}; - -// esp_hf_audio_state_t -const char *c_audio_state_str[] = { - "disconnected", - "connecting", - "connected", - "connected_msbc", -}; - -/// esp_hf_vr_state_t -const char *c_vr_state_str[] = { - "Disabled", - "Enabled", -}; - -// esp_hf_nrec_t -const char *c_nrec_status_str[] = { - "NREC DISABLE", - "NREC ABLE", -}; - -// esp_hf_control_target_t -const char *c_volume_control_target_str[] = { - "SPEAKER", - "MICROPHONE", -}; - -// esp_hf_subscriber_service_type_t -char *c_operator_name_str[] = { - "中国移动", - "中国联通", - "中国电信", -}; - -// esp_hf_subscriber_service_type_t -char *c_subscriber_service_type_str[] = { - "UNKNOWN", - "VOICE", - "FAX", -}; - -// esp_hf_nego_codec_status_t -const char *c_codec_mode_str[] = { - "CVSD Only", - "Use CVSD", - "Use MSBC", -}; - -#if CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_HCI -// Produce a sine audio -static const int16_t sine_int16[] = { - 0, 2057, 4107, 6140, 8149, 10126, 12062, 13952, 15786, 17557, - 19260, 20886, 22431, 23886, 25247, 26509, 27666, 28714, 29648, 30466, - 31163, 31738, 32187, 32509, 32702, 32767, 32702, 32509, 32187, 31738, - 31163, 30466, 29648, 28714, 27666, 26509, 25247, 23886, 22431, 20886, - 19260, 17557, 15786, 13952, 12062, 10126, 8149, 6140, 4107, 2057, - 0, -2057, -4107, -6140, -8149, -10126, -12062, -13952, -15786, -17557, --19260, -20886, -22431, -23886, -25247, -26509, -27666, -28714, -29648, -30466, --31163, -31738, -32187, -32509, -32702, -32767, -32702, -32509, -32187, -31738, --31163, -30466, -29648, -28714, -27666, -26509, -25247, -23886, -22431, -20886, --19260, -17557, -15786, -13952, -12062, -10126, -8149, -6140, -4107, -2057, -}; - -#define TABLE_SIZE_CVSD 100 -static uint32_t bt_app_hf_outgoing_cb(uint8_t *p_buf, uint32_t sz) -{ - int sine_phase = esp_random(); - - for (int i = 0; i < TABLE_SIZE_CVSD; i++) { - p_buf[i * 2] = sine_int16[sine_phase]; - p_buf[i * 2 + 1] = sine_int16[sine_phase]; - ++sine_phase; - if (sine_phase >= TABLE_SIZE_CVSD) { - sine_phase -= TABLE_SIZE_CVSD; - } - } - return sz; -} - -static void bt_app_hf_incoming_cb(const uint8_t *buf, uint32_t sz) -{ - // direct to i2s - esp_hf_outgoing_data_ready(); -} -#endif /* #if CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_HCI */ - -void bt_app_hf_cb(esp_hf_cb_event_t event, esp_hf_cb_param_t *param) -{ - if (event <= ESP_HF_BCS_RESPONSE_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); - } - - switch (event) { - case ESP_HF_CONNECTION_STATE_EVT: - { - ESP_LOGI(BT_HF_TAG, "--connection state %s, peer feats 0x%x, chld_feats 0x%x", - c_connection_state_str[param->conn_stat.state], - param->conn_stat.peer_feat, - param->conn_stat.chld_feat); - memcpy(hf_peer_addr, param->conn_stat.remote_bda, ESP_BD_ADDR_LEN); - break; - } - - case ESP_HF_AUDIO_STATE_EVT: - { - ESP_LOGI(BT_HF_TAG, "--Audio State %s", c_audio_state_str[param->audio_stat.state]); -#if CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_HCI - if (param->audio_stat.state == ESP_HF_AUDIO_STATE_CONNECTED || - param->audio_stat.state == ESP_HF_AUDIO_STATE_CONNECTED_MSBC) { - esp_bt_hf_register_data_callback(bt_app_hf_incoming_cb, bt_app_hf_outgoing_cb); - } else if (param->audio_stat.state == ESP_HF_AUDIO_STATE_DISCONNECTED) { - ESP_LOGI(BT_HF_TAG, "--ESP AG Audio Connection Disconnected."); - } -#endif /* #if CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_HCI */ - break; - } - - case ESP_HF_BVRA_RESPONSE_EVT: - { - ESP_LOGI(BT_HF_TAG, "--Voice Recognition is %s", c_vr_state_str[param->vra_rep.value]); - break; - } - - case ESP_HF_VOLUME_CONTROL_EVT: - { - ESP_LOGI(BT_HF_TAG, "--Volume Target: %s, Volume %d", c_volume_control_target_str[param->volume_control.type], param->volume_control.volume); - break; - } - - case ESP_HF_UNAT_RESPONSE_EVT: - { - ESP_LOGI(BT_HF_TAG, "--UNKOW AT CMD: %s", param->unat_rep.unat); - esp_hf_unat_response(hf_peer_addr, param->unat_rep.unat); - break; - } - - case ESP_HF_IND_UPDATE_EVT: - { - ESP_LOGI(BT_HF_TAG, "--UPDATE INDCATOR!"); - esp_hf_call_status_t call_state = 1; - esp_hf_call_setup_status_t call_setup_state = 2; - esp_hf_network_state_t ntk_state = 1; - int signal = 2; - esp_bt_hf_indchange_notification(hf_peer_addr,call_state,call_setup_state,ntk_state,signal); - break; - } - - case ESP_HF_CIND_RESPONSE_EVT: - { - ESP_LOGI(BT_HF_TAG, "--CIND Start."); - esp_hf_call_status_t call_status = 0; - esp_hf_call_setup_status_t call_setup_status = 0; - esp_hf_network_state_t ntk_state = 1; - int signal = 4; - esp_hf_roaming_status_t roam = 0; - int batt_lev = 3; - esp_hf_call_held_status_t call_held_status = 0; - esp_bt_hf_cind_response(hf_peer_addr,call_status,call_setup_status,ntk_state,signal,roam,batt_lev,call_held_status); - break; - } - - case ESP_HF_COPS_RESPONSE_EVT: - { - const int svc_type = 1; - esp_bt_hf_cops_response(hf_peer_addr, c_operator_name_str[svc_type]); - break; - } - - case ESP_HF_CLCC_RESPONSE_EVT: - { - int index = 1; - //mandatory - esp_hf_current_call_direction_t dir = 1; - esp_hf_current_call_status_t current_call_status = 0; - esp_hf_current_call_mode_t mode = 0; - esp_hf_current_call_mpty_type_t mpty = 0; - //option - char *number = {"186xxxx5549"}; - esp_hf_call_addr_type_t type = ESP_HF_CALL_ADDR_TYPE_UNKNOWN; - - ESP_LOGI(BT_HF_TAG, "--Calling Line Identification."); - esp_bt_hf_clcc_response(hf_peer_addr, index, dir, current_call_status, mode, mpty, number, type); - break; - } - - case ESP_HF_CNUM_RESPONSE_EVT: - { - char *number = {"186xxxx5549"}; - esp_hf_subscriber_service_type_t type = 1; - ESP_LOGI(BT_HF_TAG, "--Current Number is %s ,Type is %s.", number, c_subscriber_service_type_str[type]); - esp_bt_hf_cnum_response(hf_peer_addr, number,type); - break; - } - - case ESP_HF_VTS_RESPONSE_EVT: - { - ESP_LOGI(BT_HF_TAG, "--DTMF code is: %s.", param->vts_rep.code); - break; - } - - case ESP_HF_NREC_RESPONSE_EVT: - { - ESP_LOGI(BT_HF_TAG, "--NREC status is: %s.", c_nrec_status_str[param->nrec.state]); - break; - } - - case ESP_HF_ATA_RESPONSE_EVT: - { - ESP_LOGI(BT_HF_TAG, "--Asnwer Incoming Call."); - char *number = {"186xxxx5549"}; - esp_bt_hf_answer_call(hf_peer_addr,1,0,1,0,number,0); - break; - } - - case ESP_HF_CHUP_RESPONSE_EVT: - { - ESP_LOGI(BT_HF_TAG, "--Reject Incoming Call."); - char *number = {"186xxxx5549"}; - esp_bt_hf_reject_call(hf_peer_addr,0,0,0,0,number,0); - break; - } - - case ESP_HF_DIAL_EVT: - { - if (param->out_call.num_or_loc) { - //dia_num_or_mem - ESP_LOGI(BT_HF_TAG, "--Dial \"%s\".", param->out_call.num_or_loc); - esp_bt_hf_out_call(hf_peer_addr,1,0,1,0,param->out_call.num_or_loc,0); - } else { - //dia_last - ESP_LOGI(BT_HF_TAG, "--Dial last number."); - } - break; - } - - case ESP_HF_BAC_RESPONSE_EVT: - case ESP_HF_BCS_RESPONSE_EVT: - { - ESP_LOGI(BT_HF_TAG, "--AG choose codec mode: %s",c_codec_mode_str[param->codec.mode]); - break; - } - - default: - ESP_LOGI(BT_HF_TAG, "Unsupported HF_AG EVT: %d.", event); - break; - } -} \ No newline at end of file diff --git a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/bt_app_hf.h b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/bt_app_hf.h deleted file mode 100644 index e341d0f687..0000000000 --- a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/bt_app_hf.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - This example code is in the Public Domain (or CC0 licensed, at your option.) - - Unless required by applicable law or agreed to in writing, this - software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, either express or implied. -*/ - -#ifndef __BT_APP_HF_H__ -#define __BT_APP_HF_H__ - -#include -#include "esp_hf_ag_api.h" -#include "esp_bt_defs.h" - -esp_bd_addr_t hf_peer_addr; // Declaration of peer device bdaddr - -#define BT_HF_TAG "BT_APP_HF" - -/** - * @brief callback function for HF client - */ -void bt_app_hf_cb(esp_hf_cb_event_t event, esp_hf_cb_param_t *param); - - -#endif /* __BT_APP_HF_H__*/ - \ No newline at end of file diff --git a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/component.mk b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/component.mk deleted file mode 100644 index 0b9d7585e7..0000000000 --- a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/component.mk +++ /dev/null @@ -1,5 +0,0 @@ -# -# "main" pseudo-component makefile. -# -# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) - diff --git a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/console_uart.c b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/console_uart.c deleted file mode 100644 index 640f15d0af..0000000000 --- a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/console_uart.c +++ /dev/null @@ -1,108 +0,0 @@ -/* - This example code is in the Public Domain (or CC0 licensed, at your option.) - - Unless required by applicable law or agreed to in writing, this - software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, either express or implied. -*/ - -#include "driver/uart.h" -#include "freertos/xtensa_api.h" -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "freertos/queue.h" -#include "esp_log.h" -#include "console_uart.h" -#include "app_hf_msg_prs.h" - -#define CONSOLE_UART_NUM UART_NUM_0 - -static QueueHandle_t uart_queue; -static hf_msg_prs_cb_t hf_msg_parser; - -static const uart_config_t uart_cfg = { - .baud_rate = 115200, //1.5M - .data_bits = UART_DATA_8_BITS, - .parity = UART_PARITY_DISABLE, - .stop_bits = UART_STOP_BITS_1, - .flow_ctrl = UART_HW_FLOWCTRL_DISABLE, - .rx_flow_ctrl_thresh = 127, -}; - -extern void hf_msg_args_parser(char *buf, int len); - -void hf_msg_handler(char *buf, int len) -{ - ESP_LOGE(TAG_CNSL, "Command [%s]", buf); - hf_msg_args_parser(buf, len); -} - -static void console_uart_task(void *pvParameters) -{ - int len; - uart_event_t event; - hf_msg_prs_cb_t *parser = &hf_msg_parser; - hf_msg_parser_reset_state(parser); - hf_msg_parser_register_callback(parser, hf_msg_handler); - hf_msg_show_usage(); -#define TMP_BUF_LEN 128 - uint8_t tmp_buf[TMP_BUF_LEN] = {0}; - - for (;;) { - //Waiting for UART event. - if (xQueueReceive(uart_queue, (void * )&event, (portTickType)portMAX_DELAY)) { - switch (event.type) { - //Event of UART receving data - case UART_DATA: { - len = uart_read_bytes(CONSOLE_UART_NUM, tmp_buf, TMP_BUF_LEN, 0); - for (int i = 0; i < len; i++) { - hf_msg_parse(tmp_buf[i], parser); - } - break; - } - //Event of HW FIFO overflow detected - case UART_FIFO_OVF: - ESP_LOGI(TAG_CNSL, "hw fifo overflow"); - break; - //Event of UART ring buffer full - case UART_BUFFER_FULL: - ESP_LOGI(TAG_CNSL, "ring buffer full"); - break; - //Event of UART RX break detected - case UART_BREAK: - ESP_LOGI(TAG_CNSL, "uart rx break"); - break; - //Event of UART parity check error - case UART_PARITY_ERR: - ESP_LOGI(TAG_CNSL, "uart parity error"); - break; - //Event of UART frame error - case UART_FRAME_ERR: - ESP_LOGI(TAG_CNSL, "uart frame error"); - break; - //Others - default: - break; - } - } - } - vTaskDelete(NULL); -} - - -esp_err_t console_uart_init(void) -{ - esp_err_t ret; - - ret = uart_param_config(CONSOLE_UART_NUM, &uart_cfg); - if (ret != ESP_OK) { - ESP_LOGE(TAG_CNSL, "Uart %d initialize err %04x", CONSOLE_UART_NUM, ret); - return ret; - } - - uart_set_pin(CONSOLE_UART_NUM, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE); - uart_driver_install(CONSOLE_UART_NUM, 1024, 1024, 8, &uart_queue, 0); - xTaskCreate(console_uart_task, "uTask", 2048, NULL, 8, NULL); - - return ESP_OK; -} diff --git a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/console_uart.h b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/console_uart.h deleted file mode 100644 index 753950de94..0000000000 --- a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/console_uart.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - This example code is in the Public Domain (or CC0 licensed, at your option.) - - Unless required by applicable law or agreed to in writing, this - software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, either express or implied. -*/ - -#ifndef __CONSOLE_UART_H__ -#define __CONSOLE_UART_H__ - -#define TAG_CNSL "CNSL" - -/** - * @brief configure uart console for command input and process - */ -esp_err_t console_uart_init(void); - -#endif /* __BT_APP_HF_H__*/ diff --git a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/gpio_pcm_config.c b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/gpio_pcm_config.c deleted file mode 100644 index e56da15742..0000000000 --- a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/gpio_pcm_config.c +++ /dev/null @@ -1,92 +0,0 @@ -/* - This example code is in the Public Domain (or CC0 licensed, at your option.) - - Unless required by applicable law or agreed to in writing, this - software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, either express or implied. -*/ - -#include "driver/gpio.h" -#include "soc/gpio_reg.h" -#include "soc/gpio_sig_map.h" -#include "gpio_pcm_config.h" - -#define GPIO_OUTPUT_PCM_FSYNC (25) -#define GPIO_OUTPUT_PCM_CLK_OUT (5) -#define GPIO_OUTPUT_PCM_DOUT (26) -#define GPIO_INPUT_PCM_DIN (35) - -#define GPIO_OUTPUT_PCM_PIN_SEL ((1ULL< -#include -#include -#include -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "nvs.h" -#include "nvs_flash.h" -#include "esp_system.h" -#include "esp_log.h" -#include "esp_bt.h" -#include "bt_app_core.h" -#include "esp_bt_main.h" -#include "esp_bt_device.h" -#include "esp_gap_bt_api.h" -#include "esp_hf_ag_api.h" -#include "bt_app_hf.h" -#include "gpio_pcm_config.h" -#include "console_uart.h" - -#define BT_HF_AG_TAG "HF_AG_DEMO_MAIN" - -/* event for handler "hf_ag_hdl_stack_up */ -enum { - BT_APP_EVT_STACK_UP = 0, -}; - -/* handler for bluetooth stack enabled events */ -static void bt_hf_hdl_stack_evt(uint16_t event, void *p_param) -{ - ESP_LOGD(BT_HF_TAG, "%s evt %d", __func__, event); - switch (event) - { - case BT_APP_EVT_STACK_UP: - { - /* set up device name */ - char *dev_name = "ESP_HFP_AG"; - esp_bt_dev_set_device_name(dev_name); - - esp_bt_hf_register_callback(bt_app_hf_cb); - - // init and register for HFP_AG functions - esp_bt_hf_init(hf_peer_addr); - - /* - * Set default parameters for Legacy Pairing - * Use variable pin, input pin code when pairing - */ - esp_bt_pin_type_t pin_type = ESP_BT_PIN_TYPE_VARIABLE; - esp_bt_pin_code_t pin_code; - pin_code[0] = '0'; - pin_code[1] = '0'; - pin_code[2] = '0'; - pin_code[3] = '0'; - esp_bt_gap_set_pin(pin_type, 4, pin_code); - - /* set discoverable and connectable mode, wait to be connected */ - esp_bt_gap_set_scan_mode(ESP_BT_CONNECTABLE, ESP_BT_GENERAL_DISCOVERABLE); - break; - } - default: - ESP_LOGE(BT_HF_TAG, "%s unhandled evt %d", __func__, event); - break; - } -} - -void app_main(void) -{ - /* Initialize NVS — it is used to store PHY calibration data */ - esp_err_t ret = nvs_flash_init(); - if (ret == ESP_ERR_NVS_NO_FREE_PAGES) { - ESP_ERROR_CHECK(nvs_flash_erase()); - ret = nvs_flash_init(); - } - ESP_ERROR_CHECK(ret); - ESP_ERROR_CHECK(esp_bt_controller_mem_release(ESP_BT_MODE_BLE)); - - esp_err_t err; - esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT(); - if ((err = esp_bt_controller_init(&bt_cfg)) != ESP_OK) { - ESP_LOGE(BT_HF_TAG, "%s initialize controller failed: %s\n", __func__, esp_err_to_name(ret)); - return; - } - if ((err = esp_bt_controller_enable(ESP_BT_MODE_CLASSIC_BT)) != ESP_OK) { - ESP_LOGE(BT_HF_TAG, "%s enable controller failed: %s\n", __func__, esp_err_to_name(ret)); - return; - } - if ((err = esp_bluedroid_init()) != ESP_OK) { - ESP_LOGE(BT_HF_TAG, "%s initialize bluedroid failed: %s\n", __func__, esp_err_to_name(ret)); - return; - } - if ((err = esp_bluedroid_enable()) != ESP_OK) { - ESP_LOGE(BT_HF_TAG, "%s enable bluedroid failed: %s\n", __func__, esp_err_to_name(ret)); - return; - } - - /* create application task */ - bt_app_task_start_up(); - - /* Bluetooth device name, connection mode and profile set up */ - bt_app_work_dispatch(bt_hf_hdl_stack_evt, BT_APP_EVT_STACK_UP, NULL, 0, NULL); - - /* initialize console via UART */ - console_uart_init(); - - /* configure the PCM interface and PINs used */ - app_gpio_pcm_io_cfg(); - - /* configure externel chip for acoustic echo cancellation */ -#if ACOUSTIC_ECHO_CANCELLATION_ENABLE - app_gpio_aec_io_cfg(); -#endif /* ACOUSTIC_ECHO_CANCELLATION_ENABLE */ -} \ No newline at end of file diff --git a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/sdkconfig.defaults b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/sdkconfig.defaults deleted file mode 100644 index 0229678ea2..0000000000 --- a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/sdkconfig.defaults +++ /dev/null @@ -1,9 +0,0 @@ -# Override some defaults so BT stack is enabled and -# Classic BT is enabled and BT_DRAM_RELEASE is disabled -CONFIG_BT_ENABLED=y -CONFIG_BT_BLE_ENABLED=n -CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY=y -CONFIG_BT_BLUEDROID_ENABLED=y -CONFIG_BT_CLASSIC_ENABLED=y -CONFIG_BT_HFP_ENABLE=y -CONFIG_BT_HFP_AG_ENABLE=y \ No newline at end of file