From 45fb14422439c4db0b0bec52963791c869a3fdec Mon Sep 17 00:00:00 2001 From: weitianhua Date: Mon, 2 Dec 2019 15:29:55 +0800 Subject: [PATCH 1/5] Add hfp_ag example with updated doc --- .../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 insertions(+) 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/examples/bluetooth/bluedroid/classic_bt/hfp_ag/CMakeLists.txt b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/CMakeLists.txt new file mode 100644 index 000000000..ab8aa0ac1 --- /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 000000000..b539a2d52 --- /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 000000000..e2828656a --- /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 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 new file mode 100644 index 000000000..eff055634 --- /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 000000000..2610bf239 --- /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 000000000..131a7a541 --- /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 000000000..97566f10e --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/app_hf_msg_set.c @@ -0,0 +1,255 @@ +/* + 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 new file mode 100644 index 000000000..de59abf83 --- /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 000000000..89749c674 --- /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 000000000..4415058a7 --- /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 000000000..6c9e25d83 --- /dev/null +++ b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/main/bt_app_hf.c @@ -0,0 +1,303 @@ +/* + 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 new file mode 100644 index 000000000..e341d0f68 --- /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 000000000..0b9d7585e --- /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 000000000..640f15d0a --- /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"); + 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 new file mode 100644 index 000000000..753950de9 --- /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 000000000..e56da1574 --- /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 000000000..0229678ea --- /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 ad4b11a4f1247f0eb9f4869ec88a4138d49ebffb Mon Sep 17 00:00:00 2001 From: weitianhua Date: Mon, 2 Dec 2019 18:17:44 +0800 Subject: [PATCH 2/5] Fix crash when WBS enabled. --- .../bluedroid/api/include/api/esp_hf_ag_api.h | 15 +++-- .../btc/profile/std/hf_ag/btc_hf_ag.c | 58 ++++++++----------- .../bluedroid/classic_bt/hfp_ag/README.md | 6 +- .../classic_bt/hfp_ag/main/app_hf_msg_set.c | 6 +- .../classic_bt/hfp_ag/main/bt_app_hf.c | 17 ++++-- .../classic_bt/hfp_ag/main/console_uart.c | 2 +- 6 files changed, 53 insertions(+), 51 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 3b75669ba..bdfa3db00 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 @@ -64,8 +64,8 @@ typedef enum ESP_HF_ATA_RESPONSE_EVT, /*!< Answer an Incoming Call */ ESP_HF_CHUP_RESPONSE_EVT, /*!< Reject an Incoming Call */ ESP_HF_DIAL_EVT, /*!< Origin an outgoing call with specific number or the dial the last number */ - ESP_HF_BAC_RESPONSE_EVT, /*!< Codec Negotiation */ - ESP_HF_BCS_RESPONSE_EVT, /*!< Codec Negotiation */ + ESP_HF_WBS_RESPONSE_EVT, /*!< Codec Status */ + ESP_HF_BCS_RESPONSE_EVT, /*!< Final Codec Choice */ } esp_hf_cb_event_t; /// HFP AG callback parameters @@ -147,12 +147,19 @@ typedef union esp_hf_nrec_t state; /*!< NREC enabled or disabled */ } nrec; /*!< AG callback param of ESP_HF_NREC_RESPONSE_EVT */ + /** + * @brief ESP_HF_WBS_RESPONSE_EVT + */ + struct hf_wbs_rep_param { + esp_hf_wbs_config_t codec; /*!< codec mode CVSD or mSBC */ + } wbs_rep; /*!< AG callback param of ESP_HF_WBS_RESPONSE_EVT */ + /** * @brief ESP_HF_BCS_RESPONSE_EVT */ - struct hf_codec_param { + struct hf_bcs_rep_param { esp_hf_wbs_config_t mode; /*!< codec mode CVSD or mSBC */ - } codec; /*!< AG callback param of ESP_HF_BAC_RESPONSE_EVT */ + } bcs_rep; /*!< AG callback param of ESP_HF_BCS_RESPONSE_EVT */ } esp_hf_cb_param_t; /*!< HFP AG callback param compound*/ 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 0630f66ef..bd8d2e405 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 @@ -80,7 +80,7 @@ static hf_local_param_t hf_local_param[BTC_HF_NUM_CB]; /* wide band synchronous */ #ifndef BTC_HF_WBS_PREFERRED -#define BTC_HF_WBS_PREFERRED FALSE +#define BTC_HF_WBS_PREFERRED TRUE #endif BOOLEAN btc_conf_hf_force_wbs = BTC_HF_WBS_PREFERRED; @@ -1426,51 +1426,41 @@ void btc_hf_cb_handler(btc_msg_t *msg) case BTA_AG_AT_BAC_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_BAC_RESPONSE_EVT, ¶m); - 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: - { - BTC_TRACE_DEBUG("BTA_AG_WBS_EVT Set codec status %d codec %d 1=CVSD 2=MSBC", p_data->val.hdr.status, p_data->val.num); - memset(¶m, 0, sizeof(esp_hf_cb_param_t)); - param.codec.mode = p_data->val.num; - if(p_data->val.num == BTA_AG_CODEC_CVSD) { - btc_hf_cb_to_app(ESP_HF_BCS_RESPONSE_EVT, ¶m); - } else if(p_data->val.num == BTA_AG_CODEC_MSBC) { - btc_hf_cb_to_app(ESP_HF_BCS_RESPONSE_EVT, ¶m); - } else { - btc_hf_cb_to_app(ESP_HF_BCS_RESPONSE_EVT, ¶m); - } - break; - } -#endif - #if (BTM_WBS_INCLUDED == TRUE) /* If the peer supports mSBC and the BTC prefferred codec is also mSBC, then ** we should set the BTA AG Codec to mSBC. This would trigger a +BCS to mSBC at the time ** of SCO connection establishment */ if ((btc_conf_hf_force_wbs == TRUE) && (p_data->val.num & BTA_AG_CODEC_MSBC)) { - BTC_TRACE_EVENT("%s btc_hf override-Preferred Codec to MSBC", __FUNCTION__); + BTC_TRACE_DEBUG("%s btc_hf override-Preferred Codec to MSBC", __FUNCTION__); BTA_AgSetCodec(hf_local_param[idx].btc_hf_cb.handle,BTA_AG_CODEC_MSBC); } else { - BTC_TRACE_EVENT("%s btif_hf override-Preferred Codec to CVSD", __FUNCTION__); + BTC_TRACE_DEBUG("%s btc_hf override-Preferred Codec to CVSD", __FUNCTION__); BTA_AgSetCodec(hf_local_param[idx].btc_hf_cb.handle,BTA_AG_CODEC_CVSD); } #endif break; + } + +#if (BTM_WBS_INCLUDED == TRUE) + case BTA_AG_WBS_EVT: + { + BTC_TRACE_DEBUG("Set codec status %d codec %d 1=CVSD 2=MSBC", p_data->val.hdr.status, p_data->val.value); + memset(¶m, 0, sizeof(esp_hf_cb_param_t)); + param.wbs_rep.codec = p_data->val.value; + btc_hf_cb_to_app(ESP_HF_WBS_RESPONSE_EVT, ¶m); + break; + } +#endif + case BTA_AG_AT_BCS_EVT: + { + BTC_TRACE_DEBUG("AG final seleded codec is %d 1=CVSD 2=MSBC", p_data->val.num); + memset(¶m, 0, sizeof(esp_hf_cb_param_t)); + param.bcs_rep.mode = p_data->val.num; + /* No ESP_HF_WBS_NONE case, becuase HFP 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/examples/bluetooth/bluedroid/classic_bt/hfp_ag/README.md b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/README.md index e2828656a..ae4fdb6f4 100644 --- a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/README.md +++ b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/README.md @@ -6,7 +6,7 @@ This example is to show how to use the APIs of Hands-Free (HF) Audio Gateway (AG ### 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. +This example is designed to run on commonly available ESP32 development board, e.g. ESP32-DevKitC. To operate this example, 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 @@ -177,8 +177,8 @@ I (159311) BT_APP_HF: --ESP AG Audio Connection Disconnected. You can type `hf d ;` to dial `` from AG and log prints such as: ``` -E (207351) CNSL: Command [hf d 18629485549;] -Dial number 18629485549 +E (207351) CNSL: Command [hf d 123456;] +Dial number 123456 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 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 97566f10e..b45c4960b 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 @@ -194,7 +194,7 @@ HF_CMD_HANDLER(ir_off) HF_CMD_HANDLER(ac) { printf("Answer Call from AG.\n"); - char *number = {"186xxxx5549"}; + char *number = {"123456"}; esp_bt_hf_answer_call(hf_peer_addr,1,0,1,1,number,0); } @@ -202,7 +202,7 @@ HF_CMD_HANDLER(ac) HF_CMD_HANDLER(rc) { printf("Reject Call from AG.\n"); - char *number = {"186xxxx5549"}; + char *number = {"123456"}; esp_bt_hf_reject_call(hf_peer_addr,0,0,0,0,number,0); } @@ -210,7 +210,7 @@ HF_CMD_HANDLER(rc) HF_CMD_HANDLER(end) { printf("End Call from AG.\n"); - char *number = {"186xxxx5549"}; + char *number = {"123456"}; esp_bt_hf_end_call(hf_peer_addr,0,0,0,0,number,0); } 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 6c9e25d83..4635d9063 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 @@ -40,7 +40,7 @@ const char *c_hf_evt_str[] = { "ANSWER_INCOMING_EVT", /*!< ANSWER INCOMING EVT */ "REJECT_INCOMING_EVT", /*!< AREJECT INCOMING EVT */ "DIAL_EVT", /*!< DIAL INCOMING EVT */ - "BAC_EVT", /*!< CODEC NEGO EVT */ + "WBS_EVT", /*!< CURRENT CODEC EVT */ "BCS_EVT", /*!< CODEC NEGO EVT */ }; @@ -231,7 +231,7 @@ void bt_app_hf_cb(esp_hf_cb_event_t event, esp_hf_cb_param_t *param) esp_hf_current_call_mode_t mode = 0; esp_hf_current_call_mpty_type_t mpty = 0; //option - char *number = {"186xxxx5549"}; + char *number = {"123456"}; esp_hf_call_addr_type_t type = ESP_HF_CALL_ADDR_TYPE_UNKNOWN; ESP_LOGI(BT_HF_TAG, "--Calling Line Identification."); @@ -241,7 +241,7 @@ void bt_app_hf_cb(esp_hf_cb_event_t event, esp_hf_cb_param_t *param) case ESP_HF_CNUM_RESPONSE_EVT: { - char *number = {"186xxxx5549"}; + char *number = {"123456"}; 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); @@ -288,11 +288,16 @@ void bt_app_hf_cb(esp_hf_cb_event_t event, esp_hf_cb_param_t *param) } break; } - - case ESP_HF_BAC_RESPONSE_EVT: +#if (BTM_WBS_INCLUDED == TRUE) + case ESP_HF_WBS_RESPONSE_EVT: + { + ESP_LOGI(BT_HF_TAG, "--Current codec: %s",c_codec_mode_str[param->wbs_rep.codec]); + break; + } +#endif case ESP_HF_BCS_RESPONSE_EVT: { - ESP_LOGI(BT_HF_TAG, "--AG choose codec mode: %s",c_codec_mode_str[param->codec.mode]); + ESP_LOGI(BT_HF_TAG, "--Consequence of codec negotiation: %s",c_codec_mode_str[param->bcs_rep.mode]); break; } 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 640f15d0a..9cdcfa563 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 @@ -21,7 +21,7 @@ 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 + .baud_rate = 115200, .data_bits = UART_DATA_8_BITS, .parity = UART_PARITY_DISABLE, .stop_bits = UART_STOP_BITS_1, From 392eb79704585c5481b304752800710a1ec88497 Mon Sep 17 00:00:00 2001 From: weitianhua Date: Wed, 4 Dec 2019 15:37:31 +0800 Subject: [PATCH 3/5] Format the BTM_WBS_INCLUDED macro --- .../bt/host/bluedroid/bta/hf_ag/bta_ag_act.c | 17 +++++++++-------- .../bt/host/bluedroid/bta/hf_ag/bta_ag_cmd.c | 4 ++-- .../bt/host/bluedroid/bta/hf_ag/bta_ag_main.c | 2 +- .../bt/host/bluedroid/bta/hf_ag/bta_ag_sco.c | 8 ++++---- .../bluedroid/bta/hf_ag/include/bta_ag_int.h | 8 +++----- .../host/bluedroid/bta/include/bta/bta_ag_co.h | 2 +- .../bt/host/bluedroid/btc/core/btc_util.c | 2 +- .../bluedroid/btc/profile/std/hf_ag/bta_ag_co.c | 2 +- .../bluedroid/btc/profile/std/hf_ag/btc_hf_ag.c | 4 ++-- .../bt/host/bluedroid/stack/btm/btm_sco.c | 8 +++----- .../bluedroid/stack/include/stack/sdpdefs.h | 2 +- .../classic_bt/hfp_ag/main/bt_app_hf.c | 11 +++++++---- 12 files changed, 35 insertions(+), 35 deletions(-) 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 db0766470..5313cfd61 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 @@ -339,7 +339,7 @@ void bta_ag_rfc_fail(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) p_scb->conn_handle = 0; p_scb->conn_service = 0; p_scb->peer_features = 0; -#if (BTM_WBS_INCLUDED == TRUE ) +#if (BTM_WBS_INCLUDED == TRUE) p_scb->peer_codecs = BTA_AG_CODEC_NONE; p_scb->sco_codec = BTA_AG_CODEC_NONE; #endif @@ -373,7 +373,7 @@ void bta_ag_rfc_close(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) /* reinitialize stuff */ p_scb->conn_service = 0; p_scb->peer_features = 0; -#if (BTM_WBS_INCLUDED == TRUE ) +#if (BTM_WBS_INCLUDED == TRUE) p_scb->peer_codecs = BTA_AG_CODEC_NONE; p_scb->sco_codec = BTA_AG_CODEC_NONE; /* Clear these flags upon SLC teardown */ @@ -722,7 +722,7 @@ void bta_ag_svc_conn_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) evt.hdr.app_id = p_scb->app_id; evt.peer_feat = p_scb->peer_features; bdcpy(evt.bd_addr, p_scb->peer_addr); -#if (BTM_WBS_INCLUDED == TRUE ) +#if (BTM_WBS_INCLUDED == TRUE) evt.peer_codec = p_scb->peer_codecs; #endif if ((p_scb->call_ind != BTA_AG_CALL_INACTIVE) || @@ -787,7 +787,7 @@ void bta_ag_rcvd_slc_ready(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) *******************************************************************************/ void bta_ag_setcodec(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) { -#if (BTM_WBS_INCLUDED == TRUE ) +#if (BTM_WBS_INCLUDED == TRUE) tBTA_AG_PEER_CODEC codec_type = p_data->api_setcodec.codec; tBTA_AG_VAL val; @@ -797,22 +797,23 @@ void bta_ag_setcodec(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data) (codec_type != BTA_AG_CODEC_MSBC)) { val.num = codec_type; val.hdr.status = BTA_AG_FAIL_RESOURCES; - APPL_TRACE_ERROR("bta_ag_setcodec error: unsupported codec type %d", codec_type); + APPL_TRACE_ERROR("%s error: unsupported codec type %d", __func__, codec_type); (*bta_ag_cb.p_cback)(BTA_AG_WBS_EVT, (tBTA_AG *) &val); return; } - if((p_scb->peer_codecs & codec_type) || (codec_type == BTA_AG_CODEC_NONE) || + if ((p_scb->peer_codecs & codec_type) || + (codec_type == BTA_AG_CODEC_NONE) || (codec_type == BTA_AG_CODEC_CVSD)) { p_scb->sco_codec = codec_type; p_scb->codec_updated = TRUE; val.num = codec_type; val.hdr.status = BTA_AG_SUCCESS; - APPL_TRACE_DEBUG("bta_ag_setcodec: Updated codec type %d", codec_type); + APPL_TRACE_DEBUG("%s: Updated codec type %d", __func__, codec_type); } else { val.num = codec_type; val.hdr.status = BTA_AG_FAIL_RESOURCES; - APPL_TRACE_ERROR("bta_ag_setcodec error: unsupported codec type %d", codec_type); + APPL_TRACE_ERROR("%s error: unsupported codec type %d",__func__, codec_type); } (*bta_ag_cb.p_cback)(BTA_AG_WBS_EVT, (tBTA_AG *) &val); #endif 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 cdad4ed18..fe7100f19 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 @@ -628,7 +628,7 @@ static UINT8 bta_ag_parse_chld(tBTA_AG_SCB *p_scb, char *p_s) return(retval); } -#if (BTM_WBS_INCLUDED == TRUE ) +#if (BTM_WBS_INCLUDED == TRUE) /******************************************************************************* ** ** Function bta_ag_parse_bac @@ -1101,7 +1101,7 @@ void bta_ag_at_hfp_cback(tBTA_AG_SCB *p_scb, UINT16 cmd, UINT8 arg_type, } break; -#if (BTM_WBS_INCLUDED == TRUE ) +#if (BTM_WBS_INCLUDED == TRUE) case BTA_AG_HF_CMD_BAC: { bta_ag_send_ok(p_scb); 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 c8e43ed8c..26ddd7099 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 @@ -422,7 +422,7 @@ static tBTA_AG_SCB *bta_ag_scb_alloc(void) /* initialize variables */ p_scb->in_use = TRUE; p_scb->sco_idx = BTM_INVALID_SCO_INDEX; -#if (BTM_WBS_INCLUDED == TRUE ) +#if (BTM_WBS_INCLUDED == TRUE) p_scb->codec_updated = FALSE; #endif /* set up timers */ 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 351b7bca7..d5ec213f0 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 @@ -58,7 +58,7 @@ enum BTA_AG_SCO_LISTEN_E, /* listen request */ BTA_AG_SCO_OPEN_E, /* open request */ BTA_AG_SCO_XFER_E, /* transfer request */ -#if (BTM_WBS_INCLUDED == TRUE ) +#if (BTM_WBS_INCLUDED == TRUE) BTA_AG_SCO_CN_DONE_E, /* codec negotiation done */ BTA_AG_SCO_REOPEN_E, /* Retry with other codec when failed */ #endif @@ -69,7 +69,7 @@ enum BTA_AG_SCO_CI_DATA_E /* SCO data ready */ }; -#if (BTM_WBS_INCLUDED == TRUE ) +#if (BTM_WBS_INCLUDED == TRUE) #define BTA_AG_NUM_CODECS 3 #define BTA_AG_ESCO_SETTING_IDX_CVSD 0 /* eSCO setting for CVSD */ #define BTA_AG_ESCO_SETTING_IDX_T1 1 /* eSCO setting for mSBC T1 */ @@ -721,7 +721,7 @@ void bta_ag_codec_negotiate(tBTA_AG_SCB *p_scb) bta_ag_sco_codec_nego(p_scb, TRUE); } } -#endif /* (BTM_WBS_INCLUDED == TRUE ) */ +#endif /******************************************************************************* ** @@ -1298,7 +1298,7 @@ static void bta_ag_sco_event(tBTA_AG_SCB *p_scb, UINT8 event) bta_ag_sco_evt_str(event)); } -#if (BTM_WBS_INCLUDED == TRUE ) +#if (BTM_WBS_INCLUDED == TRUE) if (p_cn_scb) { bta_ag_codec_negotiate(p_cn_scb); 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 ae63ba470..8f1e9037b 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 @@ -136,7 +136,7 @@ enum { BTA_AG_SCO_SHUTDOWN_ST, /* no sco listening, all sco connections closed */ BTA_AG_SCO_LISTEN_ST, /* sco listening */ -#if (BTM_WBS_INCLUDED == TRUE ) +#if (BTM_WBS_INCLUDED == TRUE) BTA_AG_SCO_CODEC_ST, /* sco codec negotiation */ #endif BTA_AG_SCO_OPENING_ST, /* sco connection opening */ @@ -225,7 +225,7 @@ typedef union tBTA_AG_API_REGISTER api_register; tBTA_AG_API_OPEN api_open; tBTA_AG_API_RESULT api_result; -#if (BTM_WBS_INCLUDED == TRUE ) +#if (BTM_WBS_INCLUDED == TRUE) tBTA_AG_API_SETCODEC api_setcodec; #endif tBTA_AG_DISC_RESULT disc_result; @@ -421,6 +421,7 @@ extern void bta_ag_sco_close(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data); #if (BTM_WBS_INCLUDED == TRUE) extern void bta_ag_sco_codec_nego(tBTA_AG_SCB *p_scb, BOOLEAN result); extern void bta_ag_codec_negotiate (tBTA_AG_SCB *p_scb); +extern void bta_ag_send_bcs(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data); #endif extern void bta_ag_sco_shutdown(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data); extern void bta_ag_sco_conn_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data); @@ -430,9 +431,6 @@ extern void bta_ag_post_sco_close(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data); extern void bta_ag_svc_conn_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data); extern void bta_ag_result(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data); extern void bta_ag_setcodec(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data); -#if (BTM_WBS_INCLUDED == TRUE) -extern void bta_ag_send_bcs(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data); -#endif extern void bta_ag_send_ring(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data); extern void bta_ag_ci_sco_data(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data); extern void bta_ag_set_esco_param(BOOLEAN set_reset, tBTM_ESCO_PARAMS *param); 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 fb1c1bfde..f4a5703d2 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 @@ -46,7 +46,7 @@ ** Returns void ** *******************************************************************************/ -#if (BTM_WBS_INCLUDED == TRUE ) +#if (BTM_WBS_INCLUDED == TRUE) void bta_ag_sco_audio_state(UINT16 handle, UINT8 app_id, UINT8 state, tBTA_AG_PEER_CODEC codec); #else void bta_ag_sco_audio_state(UINT16 handle, UINT8 app_id, UINT8 state); diff --git a/components/bt/host/bluedroid/btc/core/btc_util.c b/components/bt/host/bluedroid/btc/core/btc_util.c index 589b3ac4b..f79b65e8e 100644 --- a/components/bt/host/bluedroid/btc/core/btc_util.c +++ b/components/bt/host/bluedroid/btc/core/btc_util.c @@ -156,7 +156,7 @@ const char* dump_hf_event(UINT16 event) CASE_RETURN_STR(BTA_AG_MIC_EVT) CASE_RETURN_STR(BTA_AG_AT_CKPD_EVT) CASE_RETURN_STR(BTA_AG_DISABLE_EVT) -#if (BTM_WBS_INCLUDED == TRUE ) +#if (BTM_WBS_INCLUDED == TRUE) CASE_RETURN_STR(BTA_AG_WBS_EVT) #endif CASE_RETURN_STR(BTA_AG_AT_A_EVT) diff --git a/components/bt/host/bluedroid/btc/profile/std/hf_ag/bta_ag_co.c b/components/bt/host/bluedroid/btc/profile/std/hf_ag/bta_ag_co.c index 22bec07f1..7c80f9910 100644 --- a/components/bt/host/bluedroid/btc/profile/std/hf_ag/bta_ag_co.c +++ b/components/bt/host/bluedroid/btc/profile/std/hf_ag/bta_ag_co.c @@ -353,7 +353,7 @@ static void bta_ag_decode_msbc_frame(UINT8 **data, UINT8 *length, BOOLEAN is_bad ** Returns void ** *******************************************************************************/ -#if (BTM_WBS_INCLUDED == TRUE ) +#if (BTM_WBS_INCLUDED == TRUE) void bta_ag_sco_audio_state(UINT16 handle, UINT8 app_id, UINT8 state, tBTA_AG_PEER_CODEC codec) #else void bta_ag_sco_audio_state(UINT16 handle, UINT8 app_id, UINT8 state) 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 bd8d2e405..d7a2821c1 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 @@ -1441,7 +1441,6 @@ void btc_hf_cb_handler(btc_msg_t *msg) #endif break; } - #if (BTM_WBS_INCLUDED == TRUE) case BTA_AG_WBS_EVT: { @@ -1451,7 +1450,7 @@ void btc_hf_cb_handler(btc_msg_t *msg) btc_hf_cb_to_app(ESP_HF_WBS_RESPONSE_EVT, ¶m); break; } -#endif + case BTA_AG_AT_BCS_EVT: { BTC_TRACE_DEBUG("AG final seleded codec is %d 1=CVSD 2=MSBC", p_data->val.num); @@ -1461,6 +1460,7 @@ void btc_hf_cb_handler(btc_msg_t *msg) btc_hf_cb_to_app(ESP_HF_BCS_RESPONSE_EVT, ¶m); break; } +#endif default: BTC_TRACE_WARNING("%s: Unhandled event: %d", __FUNCTION__, event); break; diff --git a/components/bt/host/bluedroid/stack/btm/btm_sco.c b/components/bt/host/bluedroid/stack/btm/btm_sco.c index a291a63ec..0b05b18ba 100644 --- a/components/bt/host/bluedroid/stack/btm/btm_sco.c +++ b/components/bt/host/bluedroid/stack/btm/btm_sco.c @@ -525,18 +525,16 @@ static tBTM_STATUS btm_send_connect_request(UINT16 acl_handle, /* Return error if no packet types left */ if (temp_pkt_types == 0) { - BTM_TRACE_ERROR("%s: SCO Conn (BR/EDR SC): No packet types available", - __FUNCTION__); + BTM_TRACE_ERROR("%s: SCO Conn (BR/EDR SC): No packet types available",__FUNCTION__); return (BTM_WRONG_MODE); } } else { - BTM_TRACE_DEBUG("%s: SCO Conn(BR/EDR SC):local or peer does not support BR/EDR SC", - __FUNCTION__); + BTM_TRACE_DEBUG("%s: SCO Conn(BR/EDR SC):local or peer does not support BR/EDR SC",__FUNCTION__); } } - BTM_TRACE_API(" txbw 0x%x, rxbw 0x%x, lat 0x%x, voice 0x%x, retrans 0x%02x, pkt 0x%04x", + BTM_TRACE_API("txbw 0x%x, rxbw 0x%x, lat 0x%x, voice 0x%x, retrans 0x%02x, pkt 0x%04x", p_setup->tx_bw, p_setup->rx_bw, p_setup->max_latency, p_setup->voice_contfmt, p_setup->retrans_effort, temp_pkt_types); diff --git a/components/bt/host/bluedroid/stack/include/stack/sdpdefs.h b/components/bt/host/bluedroid/stack/include/stack/sdpdefs.h index 44d87e74b..1befddf35 100644 --- a/components/bt/host/bluedroid/stack/include/stack/sdpdefs.h +++ b/components/bt/host/bluedroid/stack/include/stack/sdpdefs.h @@ -276,7 +276,7 @@ #define UUID_SERVCLASS_TEST_SERVER 0x9000 /* Test Group UUID */ -#if (BTM_WBS_INCLUDED == TRUE ) +#if (BTM_WBS_INCLUDED == TRUE) #define UUID_CODEC_CVSD 0x0001 /* CVSD */ #define UUID_CODEC_MSBC 0x0002 /* mSBC */ #endif 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 4635d9063..546e2c05e 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 @@ -161,8 +161,11 @@ void bt_app_hf_cb(esp_hf_cb_event_t event, esp_hf_cb_param_t *param) { 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) { + if (param->audio_stat.state == ESP_HF_AUDIO_STATE_CONNECTED +#if (BTM_WBS_INCLUDED == TRUE) + || param->audio_stat.state == ESP_HF_AUDIO_STATE_CONNECTED_MSBC +#endif + ) { 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."); @@ -263,7 +266,7 @@ void bt_app_hf_cb(esp_hf_cb_event_t event, esp_hf_cb_param_t *param) case ESP_HF_ATA_RESPONSE_EVT: { ESP_LOGI(BT_HF_TAG, "--Asnwer Incoming Call."); - char *number = {"186xxxx5549"}; + char *number = {"123456"}; esp_bt_hf_answer_call(hf_peer_addr,1,0,1,0,number,0); break; } @@ -271,7 +274,7 @@ void bt_app_hf_cb(esp_hf_cb_event_t event, esp_hf_cb_param_t *param) case ESP_HF_CHUP_RESPONSE_EVT: { ESP_LOGI(BT_HF_TAG, "--Reject Incoming Call."); - char *number = {"186xxxx5549"}; + char *number = {"123456"}; esp_bt_hf_reject_call(hf_peer_addr,0,0,0,0,number,0); break; } From c2e97b104236234465f79dd7e914fcb2df2b64c5 Mon Sep 17 00:00:00 2001 From: weitianhua Date: Wed, 4 Dec 2019 16:41:04 +0800 Subject: [PATCH 4/5] Enable mSBC for demo --- .../bt/host/bluedroid/bta/hf_ag/bta_ag_sco.c | 2 +- .../bluedroid/classic_bt/hfp_ag/README.md | 24 +++++++++---------- .../classic_bt/hfp_ag/main/app_hf_msg_set.c | 8 +++---- .../classic_bt/hfp_ag/main/bt_app_hf.c | 1 + 4 files changed, 18 insertions(+), 17 deletions(-) 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 d5ec213f0..a02c1dd09 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 @@ -316,7 +316,7 @@ static void bta_ag_sco_read_cback(UINT16 sco_inx, BT_HDR *p_data, tBTM_SCO_DATA_ { if (status != BTM_SCO_DATA_CORRECT) { - APPL_TRACE_DEBUG("bta_ag_sco_read_cback: status(%d)", status); + ets_printf("bta_ag_sco_read_cback: status(%d)", status); } /* Callout function must free the data. */ diff --git a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/README.md b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/README.md index ae4fdb6f4..9abc13b30 100644 --- a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/README.md +++ b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/README.md @@ -6,7 +6,7 @@ This example is to show how to use the APIs of Hands-Free (HF) Audio Gateway (AG ### Hardware Required -This example is designed to run on commonly available ESP32 development board, e.g. ESP32-DevKitC. To operate this example, 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. +This example is designed to run on commonly available ESP32 development board, e.g. ESP32-DevKitC. To operate this example, it should be connected to a 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 @@ -14,10 +14,10 @@ This example is designed to run on commonly available ESP32 development board, e 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: +ESP32 supports two types of audio data paths: PCM and HCI. Because the default sdkconfig of this example does not configured 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`. +- HCI : When using HCI, audio data stream will be transported 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`.** @@ -37,7 +37,7 @@ See the [Getting Started Guide](https://docs.espressif.com/projects/esp-idf/en/l ## Example Output -When you flash and monitor this example the commands help table prints the following at the very begining: +When you flash and monitor this example, the commands help table prints the following log at the very begining: ``` ######################################################################## @@ -45,10 +45,10 @@ 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 con; -- set up 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 cona; -- set up audio connection with peer device +hf disa; -- release audio connection with peer device hf vron; -- start voice recognition hf vroff; -- stop voice recognition hf vu ; -- volume update @@ -75,8 +75,8 @@ 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. +- 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 respond. +- The command you type in will not echo in monitor. ### Service Level Connection and Disconnection @@ -121,7 +121,7 @@ You can type `hf cona;` to establish the audio connection between HF Unit and AG - Reject an incoming call - Disable the voice recognition -#### Choise of Codec +#### Choice 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`. @@ -211,7 +211,7 @@ 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: +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 print: ``` E (244131) CNSL: Command [hf vron;] @@ -274,7 +274,7 @@ If you encounter any problems, please check if the following rules are followed: 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. +- 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`. 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 b45c4960b..ee674640a 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 @@ -21,10 +21,10 @@ void hf_msg_show_usage(void) 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 con; -- set up connection with peer device\n"); + printf("hf dis; -- disconnection with peer device\n"); + printf("hf cona; -- set up audio connection with peer device\n"); + printf("hf disa; -- release audio 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"); 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 546e2c05e..022807bca 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 @@ -31,6 +31,7 @@ const char *c_hf_evt_str[] = { "VR_STATE_CHANGE_EVT", /*!< VOICE RECOGNITION CHANGE */ "VOLUME_CONTROL_EVT", /*!< AUDIO VOLUME CONTROL */ "UNKNOW_AT_CMD", /*!< UNKNOW AT COMMAND RECIEVED */ + "IND_UPDATE", /*!< INDICATION UPDATE */ "CIND_RESPONSE_EVT", /*!< CALL & DEVICE INDICATION */ "COPS_RESPONSE_EVT", /*!< CURRENT OPERATOR EVENT */ "CLCC_RESPONSE_EVT", /*!< LIST OF CURRENT CALL EVENT */ From 4cba4ddadcf3e2bf58e45380ff7eb08162cd4ac4 Mon Sep 17 00:00:00 2001 From: weitianhua Date: Thu, 12 Dec 2019 17:09:59 +0800 Subject: [PATCH 5/5] Make only for ESP32 --- examples/bluetooth/bluedroid/classic_bt/hfp_ag/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/CMakeLists.txt b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/CMakeLists.txt index ab8aa0ac1..f724b1556 100644 --- a/examples/bluetooth/bluedroid/classic_bt/hfp_ag/CMakeLists.txt +++ b/examples/bluetooth/bluedroid/classic_bt/hfp_ag/CMakeLists.txt @@ -2,5 +2,6 @@ # CMakeLists in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.5) +set(SUPPORTED_TARGETS esp32) include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(hfp_ag)