mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Merge branch 'feature/hfp_console' into 'master'
Feature/modify hfp console style by using esp console Closes BT-1052 See merge request espressif/esp-idf!10973
This commit is contained in:
commit
ffa29f8098
@ -464,9 +464,6 @@ 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);
|
||||
|
||||
|
@ -1482,12 +1482,19 @@ void bta_ag_sco_conn_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
|
||||
bta_ag_sco_audio_state(bta_ag_scb_to_idx(p_scb), p_scb->app_id, SCO_STATE_ON);
|
||||
#endif
|
||||
/* open SCO codec if SCO is routed through transport */
|
||||
bta_ag_sco_co_open(bta_ag_scb_to_idx(p_scb), p_scb->air_mode, BTA_HFP_SCO_OUT_PKT_SIZE, BTA_AG_CI_SCO_DATA_EVT);
|
||||
bta_ag_sco_co_open(bta_ag_scb_to_idx(p_scb), p_scb->air_mode, p_scb->out_pkt_len, BTA_AG_CI_SCO_DATA_EVT);
|
||||
#endif
|
||||
|
||||
#if (BTM_WBS_INCLUDED == TRUE)
|
||||
/* call app callback */
|
||||
if (p_scb->sco_codec == BTA_AG_CODEC_MSBC) {
|
||||
bta_ag_cback_sco(p_scb, BTA_AG_AUDIO_MSBC_OPEN_EVT);
|
||||
} else {
|
||||
bta_ag_cback_sco(p_scb, BTA_AG_AUDIO_OPEN_EVT);
|
||||
}
|
||||
#else
|
||||
bta_ag_cback_sco(p_scb, BTA_AG_AUDIO_OPEN_EVT);
|
||||
|
||||
#endif
|
||||
p_scb->retry_with_sco_only = FALSE;
|
||||
#if (BTM_WBS_INCLUDED == TRUE)
|
||||
/* reset to mSBC T2 settings as the preferred */
|
||||
|
@ -145,6 +145,7 @@ typedef UINT8 tBTA_AG_RES;
|
||||
#if (BTM_WBS_INCLUDED == TRUE )
|
||||
#define BTA_AG_WBS_EVT 31 /* SCO codec nego */
|
||||
#endif
|
||||
#define BTA_AG_AUDIO_MSBC_OPEN_EVT 32 /* Audio connection with mSBC codec open */
|
||||
|
||||
/* Values below are for HFP only */
|
||||
#define BTA_AG_AT_A_EVT 10 /* Answer a incoming call */
|
||||
|
@ -1312,6 +1312,16 @@ void btc_hf_cb_handler(btc_msg_t *msg)
|
||||
break;
|
||||
}
|
||||
|
||||
case BTA_AG_AUDIO_MSBC_OPEN_EVT:
|
||||
{
|
||||
do {
|
||||
memset(¶m, 0, sizeof(esp_hf_cb_param_t));
|
||||
param.audio_stat.state = ESP_HF_AUDIO_STATE_CONNECTED_MSBC;
|
||||
memcpy(param.audio_stat.remote_addr, &hf_local_param[idx].btc_hf_cb.connected_bda,sizeof(esp_bd_addr_t));
|
||||
btc_hf_cb_to_app(ESP_HF_AUDIO_STATE_EVT, ¶m);
|
||||
} while (0);
|
||||
break;
|
||||
}
|
||||
case BTA_AG_AUDIO_CLOSE_EVT:
|
||||
{
|
||||
do {
|
||||
|
@ -43,47 +43,24 @@ See the [Getting Started Guide](https://docs.espressif.com/projects/esp-idf/en/l
|
||||
When you flash and monitor this example, the commands help table prints the following log 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 >
|
||||
Type 'help' to get the list of commands.
|
||||
Use UP/DOWN arrows to navigate through command history.
|
||||
Press TAB when typing command name to auto-complete.
|
||||
|
||||
==================================================
|
||||
| Steps to test hfp_ag |
|
||||
| |
|
||||
| 1. Print 'help' to gain overview of commands |
|
||||
| 2. Setup a service level connection |
|
||||
| 3. Run hfp_ag to test |
|
||||
| |
|
||||
=================================================
|
||||
|
||||
hf con; -- set up connection with peer device
|
||||
hf dis; -- 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 <tgt> <vol>; -- volume update
|
||||
tgt: 0-speaker, 1-microphone
|
||||
vol: volume gain ranges from 0 to 15
|
||||
hf ind <call> <ntk> <callsetup> <sig>; -- 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 <rep> <err>; -- 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 <num>; -- 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 respond.
|
||||
- The command you type in 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:
|
||||
You can type `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
|
||||
@ -97,10 +74,9 @@ I (2331) BT_APP_HF: --connection state SLC_CONNECTED, peer feats 0xff, chld_feat
|
||||
|
||||
**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:
|
||||
You can type `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
|
||||
@ -111,7 +87,7 @@ 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.
|
||||
You can type `cona` to establish the audio connection between HF Unit and AG device. Also, you can type `disa` to close the audio data stream.
|
||||
|
||||
#### Scenarios for Audio Connection
|
||||
|
||||
@ -138,10 +114,9 @@ Since CVSD is the default codec in HFP, we just show the scenarios using mSBC:
|
||||
|
||||
#### Answer an Incoming Call
|
||||
|
||||
You can type `hf ac;` to answer an incoming call and log prints such as:
|
||||
You can type `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
|
||||
@ -153,10 +128,9 @@ 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:
|
||||
You can type `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
|
||||
@ -164,10 +138,9 @@ 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:
|
||||
You can type `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
|
||||
@ -177,10 +150,9 @@ I (159311) BT_APP_HF: --ESP AG Audio Connection Disconnected.
|
||||
|
||||
### Dial Number
|
||||
|
||||
You can type `hf d <num>;` to dial `<num>` from AG and log prints such as:
|
||||
You can type `d <num>` to dial `<num>` from AG and log prints such as:
|
||||
|
||||
```
|
||||
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
|
||||
@ -193,19 +165,19 @@ I (208811) BT_APP_HF: --Audio State connected
|
||||
|
||||
### Volume Control
|
||||
|
||||
You can type `hf vu <tgt> <vol>;` to update the volume of a headset or microphone. The parameter should be set as follows:
|
||||
You can type `vu <tgt> <vol>` to update the volume of a headset or microphone. The parameter should be set as follows:
|
||||
|
||||
- `<tgt>` : 0 - headset, 1 - microphone.
|
||||
- `<vol>` : 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:
|
||||
For example, `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:
|
||||
And also, `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
|
||||
@ -214,10 +186,9 @@ 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 print:
|
||||
You can type `vron` to start the voice recognition and type `vroff` to terminate this function in the AG device. Both commands will notify the HF Unit the status of voice recognition. For example, type `vron` and the log will print:
|
||||
|
||||
```
|
||||
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
|
||||
@ -228,7 +199,7 @@ I (245311) BT_APP_HF: --Audio State connected
|
||||
|
||||
#### Device Status Indication
|
||||
|
||||
You can type `hf ind <call> <ntk> <callsetup> <sig>` 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:
|
||||
You can type `ind <call> <ntk> <callsetup> <sig>` 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
|
||||
@ -243,12 +214,12 @@ E (293661) BT_HF: -- signal strength: 5
|
||||
|
||||
#### Send Extended AT Error Code
|
||||
|
||||
You can type `hf ate <rep> <err>` to send extended AT error code to HF Unit. The parameter should be set as follows:
|
||||
You can type `ate <rep> <err>` to send extended AT error code to HF Unit. The parameter should be set as follows:
|
||||
|
||||
- `<rep>` : integer among 0 - 7.
|
||||
- `<err>` : 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:
|
||||
When you type `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
|
||||
@ -257,7 +228,7 @@ 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:
|
||||
You can type `iron` to enable the in-band ring tone and type `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
|
||||
|
@ -2,7 +2,6 @@ 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 ".")
|
||||
|
@ -11,10 +11,12 @@
|
||||
#include "esp_hf_ag_api.h"
|
||||
#include "app_hf_msg_set.h"
|
||||
#include "bt_app_hf.h"
|
||||
#include "esp_console.h"
|
||||
#include "argtable3/argtable3.h"
|
||||
#include "esp_log.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};
|
||||
|
||||
esp_bd_addr_t hf_peer_addr = {0xB0, 0xF1, 0xA3, 0x01, 0x2D,0x2E};
|
||||
void hf_msg_show_usage(void)
|
||||
{
|
||||
printf("########################################################################\n");
|
||||
@ -48,35 +50,40 @@ void hf_msg_show_usage(void)
|
||||
printf("########################################################################\n");
|
||||
}
|
||||
|
||||
#define HF_CMD_HANDLER(cmd) static void hf_##cmd##_handler(int argn, char **argv)
|
||||
#define HF_CMD_HANDLER(cmd) static int hf_##cmd##_handler(int argn, char **argv)
|
||||
|
||||
HF_CMD_HANDLER(help)
|
||||
{
|
||||
hf_msg_show_usage();
|
||||
return 0;
|
||||
}
|
||||
|
||||
HF_CMD_HANDLER(conn)
|
||||
{
|
||||
printf("Connect.\n");
|
||||
esp_bt_hf_connect(hf_peer_addr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
HF_CMD_HANDLER(disc)
|
||||
{
|
||||
printf("Disconnect\n");
|
||||
esp_bt_hf_disconnect(hf_peer_addr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
HF_CMD_HANDLER(conn_audio)
|
||||
{
|
||||
printf("Connect Audio\n");
|
||||
esp_bt_hf_connect_audio(hf_peer_addr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
HF_CMD_HANDLER(disc_audio)
|
||||
{
|
||||
printf("Disconnect Audio\n");
|
||||
esp_bt_hf_disconnect_audio(hf_peer_addr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//AT+BVRA
|
||||
@ -84,12 +91,14 @@ HF_CMD_HANDLER(vra_on)
|
||||
{
|
||||
printf("Start Voice Recognition.\n");
|
||||
esp_bt_hf_vra(hf_peer_addr,1);
|
||||
return 0;
|
||||
}
|
||||
//AT+BVRA
|
||||
HF_CMD_HANDLER(vra_off)
|
||||
{
|
||||
printf("Stop Voicer Recognition.\n");
|
||||
esp_bt_hf_vra(hf_peer_addr,0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//AT+VGS or AT+VGM
|
||||
@ -97,22 +106,23 @@ HF_CMD_HANDLER(volume_control)
|
||||
{
|
||||
if (argn != 3) {
|
||||
printf("Insufficient number of arguments");
|
||||
return;
|
||||
return 1;
|
||||
}
|
||||
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;
|
||||
return 1;
|
||||
}
|
||||
if (sscanf(argv[2], "%d", &volume) != 1 ||
|
||||
(volume < 0 || volume > 15)) {
|
||||
printf("Invalid argument for volume %s\n", argv[2]);
|
||||
return;
|
||||
return 1;
|
||||
}
|
||||
printf("Volume Update\n");
|
||||
esp_bt_hf_volume_control(hf_peer_addr, target, volume);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//+CIEV
|
||||
@ -120,7 +130,7 @@ HF_CMD_HANDLER(ind_change)
|
||||
{
|
||||
if (argn != 5) {
|
||||
printf("Insufficient number of arguments");
|
||||
return;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int call_state, ntk_state, call_setup_state, signal;
|
||||
@ -129,26 +139,27 @@ HF_CMD_HANDLER(ind_change)
|
||||
(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;
|
||||
return 1;
|
||||
}
|
||||
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;
|
||||
return 1;
|
||||
}
|
||||
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;
|
||||
return 1;
|
||||
}
|
||||
if (sscanf(argv[4], "%d", &signal) != 1 ||
|
||||
(signal < 0 || signal > 5)) {
|
||||
printf("Invalid argument for signal %s\n", argv[4]);
|
||||
return;
|
||||
return 1;
|
||||
}
|
||||
printf("Device Indicator Changed!\n");
|
||||
esp_bt_hf_indchange_notification(hf_peer_addr, call_state, call_setup_state, ntk_state, signal);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//AT+CMEE
|
||||
@ -156,24 +167,25 @@ HF_CMD_HANDLER(cme_err)
|
||||
{
|
||||
if (argn != 3) {
|
||||
printf("Insufficient number of arguments");
|
||||
return;
|
||||
return 1;
|
||||
}
|
||||
|
||||
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;
|
||||
return 1;
|
||||
}
|
||||
|
||||
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;
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("Send CME Error.\n");
|
||||
esp_bt_hf_cmee_response(hf_peer_addr,response_code,error_code);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//+BSIR:1
|
||||
@ -181,6 +193,7 @@ HF_CMD_HANDLER(ir_on)
|
||||
{
|
||||
printf("Enable Voicer Recognition.\n");
|
||||
esp_bt_hf_bsir(hf_peer_addr,1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//+BSIR:0
|
||||
@ -188,6 +201,7 @@ HF_CMD_HANDLER(ir_off)
|
||||
{
|
||||
printf("Disable Voicer Recognition.\n");
|
||||
esp_bt_hf_bsir(hf_peer_addr,0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//Answer Call from AG
|
||||
@ -196,6 +210,7 @@ HF_CMD_HANDLER(ac)
|
||||
printf("Answer Call from AG.\n");
|
||||
char *number = {"123456"};
|
||||
esp_bt_hf_answer_call(hf_peer_addr,1,0,1,1,number,0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//Reject Call from AG
|
||||
@ -204,6 +219,7 @@ HF_CMD_HANDLER(rc)
|
||||
printf("Reject Call from AG.\n");
|
||||
char *number = {"123456"};
|
||||
esp_bt_hf_reject_call(hf_peer_addr,0,0,0,0,number,0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//End Call from AG
|
||||
@ -212,6 +228,7 @@ HF_CMD_HANDLER(end)
|
||||
printf("End Call from AG.\n");
|
||||
char *number = {"123456"};
|
||||
esp_bt_hf_end_call(hf_peer_addr,0,0,0,0,number,0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//Dial Call from AG
|
||||
@ -223,6 +240,7 @@ HF_CMD_HANDLER(d)
|
||||
printf("Dial number %s\n", argv[1]);
|
||||
esp_bt_hf_out_call(hf_peer_addr,1,0,1,2,argv[1],0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static hf_msg_hdl_t hf_cmd_tbl[] = {
|
||||
@ -253,3 +271,206 @@ size_t hf_get_cmd_tbl_size(void)
|
||||
{
|
||||
return sizeof(hf_cmd_tbl) / sizeof(hf_msg_hdl_t);
|
||||
}
|
||||
|
||||
#define HF_ORDER(name) name##_cmd
|
||||
enum hf_cmd_name {
|
||||
h = 0, /*show command manual*/
|
||||
con, /*set up connection with peer device*/
|
||||
dis, /*disconnection with peer device*/
|
||||
cona, /*set up audio connection with peer device*/
|
||||
disa, /*release connection with peer device*/
|
||||
vu, /*volume update*/
|
||||
ind, /*unsolicited indication device status to HF Client*/
|
||||
vron, /*start voice recognition*/
|
||||
vroff, /*stop voice recognition*/
|
||||
ate, /*send extended at error code*/
|
||||
iron, /*in-band ring tone provided*/
|
||||
iroff, /*in-band ring tone not provided*/
|
||||
ac, /*Answer Incoming Call from AG*/
|
||||
rc, /*Reject Incoming Call from AG*/
|
||||
end, /*End up a call by AG*/
|
||||
d /*Dial Number by AG, e.g. d 11223344*/
|
||||
};
|
||||
static char *hf_cmd_explain[] = {
|
||||
"show command manual",
|
||||
"set up connection with peer device",
|
||||
"disconnection with peer device",
|
||||
"set up audio connection with peer device",
|
||||
"release connection with peer device",
|
||||
"volume update",
|
||||
"unsolicited indication device status to HF Client",
|
||||
"start voice recognition",
|
||||
"stop voice recognition",
|
||||
"send extended at error code",
|
||||
"in-band ring tone provided",
|
||||
"in-band ring tone not provided",
|
||||
"Answer Incoming Call from AG",
|
||||
"Reject Incoming Call from AG",
|
||||
"End up a call by AG",
|
||||
"Dial Number by AG, e.g. d 11223344",
|
||||
};
|
||||
typedef struct {
|
||||
struct arg_str *tgt;
|
||||
struct arg_str *vol;
|
||||
struct arg_end *end;
|
||||
} vu_args_t;
|
||||
|
||||
typedef struct {
|
||||
struct arg_str *call;
|
||||
struct arg_str *ntk;
|
||||
struct arg_str *callsetup;
|
||||
struct arg_str *sig;
|
||||
struct arg_end *end;
|
||||
} ind_args_t;
|
||||
|
||||
typedef struct {
|
||||
struct arg_str *rep;
|
||||
struct arg_str *err;
|
||||
struct arg_end *end;
|
||||
} ate_args_t;
|
||||
|
||||
static vu_args_t vu_args;
|
||||
static ind_args_t ind_args;
|
||||
static ate_args_t ate_args;
|
||||
|
||||
void register_hfp_ag(void)
|
||||
{
|
||||
|
||||
const esp_console_cmd_t HF_ORDER(con) = {
|
||||
.command = "con",
|
||||
.help = hf_cmd_explain[con],
|
||||
.hint = NULL,
|
||||
.func = hf_cmd_tbl[con].handler,
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&HF_ORDER(con)));
|
||||
|
||||
const esp_console_cmd_t HF_ORDER(dis) = {
|
||||
.command = "dis",
|
||||
.help = hf_cmd_explain[dis],
|
||||
.hint = NULL,
|
||||
.func = hf_cmd_tbl[dis].handler,
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&HF_ORDER(dis)));
|
||||
|
||||
const esp_console_cmd_t HF_ORDER(cona) = {
|
||||
.command = "cona",
|
||||
.help = hf_cmd_explain[cona],
|
||||
.hint = NULL,
|
||||
.func = hf_cmd_tbl[cona].handler,
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&HF_ORDER(cona)));
|
||||
|
||||
const esp_console_cmd_t HF_ORDER(disa) = {
|
||||
.command = "disa",
|
||||
.help = hf_cmd_explain[disa],
|
||||
.hint = NULL,
|
||||
.func = hf_cmd_tbl[disa].handler,
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&HF_ORDER(disa)));
|
||||
|
||||
|
||||
|
||||
const esp_console_cmd_t HF_ORDER(ac) = {
|
||||
.command = "ac",
|
||||
.help = hf_cmd_explain[ac],
|
||||
.hint = NULL,
|
||||
.func = hf_cmd_tbl[ac].handler,
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&HF_ORDER(ac)));
|
||||
|
||||
const esp_console_cmd_t HF_ORDER(rc) = {
|
||||
.command = "rc",
|
||||
.help = hf_cmd_explain[rc],
|
||||
.hint = NULL,
|
||||
.func = hf_cmd_tbl[rc].handler,
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&HF_ORDER(rc)));
|
||||
|
||||
const esp_console_cmd_t HF_ORDER(d) = {
|
||||
.command = "d",
|
||||
.help = hf_cmd_explain[d],
|
||||
.hint = "<num>",
|
||||
.func = hf_cmd_tbl[d].handler,
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&HF_ORDER(d)));
|
||||
|
||||
|
||||
|
||||
const esp_console_cmd_t HF_ORDER(vron) = {
|
||||
.command = "vron",
|
||||
.help = hf_cmd_explain[vron],
|
||||
.hint = NULL,
|
||||
.func = hf_cmd_tbl[vron].handler,
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&HF_ORDER(vron)));
|
||||
|
||||
const esp_console_cmd_t HF_ORDER(vroff) = {
|
||||
.command = "vroff",
|
||||
.help = hf_cmd_explain[vroff],
|
||||
.hint = NULL,
|
||||
.func = hf_cmd_tbl[vroff].handler,
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&HF_ORDER(vroff)));
|
||||
|
||||
vu_args.tgt = arg_str1(NULL, NULL, "<tgt>", "\n 0-speaker\n 1-microphone");
|
||||
vu_args.vol = arg_str1(NULL, NULL, "<vol>", "volume gain ranges from 0 to 15");
|
||||
vu_args.end = arg_end(1);
|
||||
const esp_console_cmd_t HF_ORDER(vu) = {
|
||||
.command = "vu",
|
||||
.help = hf_cmd_explain[vu],
|
||||
.hint = NULL,
|
||||
.func = hf_cmd_tbl[vu].handler,
|
||||
.argtable = &vu_args
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&HF_ORDER(vu)));
|
||||
|
||||
const esp_console_cmd_t HF_ORDER(end) = {
|
||||
.command = "end",
|
||||
.help = hf_cmd_explain[end],
|
||||
.hint = NULL,
|
||||
.func = hf_cmd_tbl[end].handler,
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&HF_ORDER(end)));
|
||||
|
||||
const esp_console_cmd_t HF_ORDER(iron) = {
|
||||
.command = "iron",
|
||||
.help = hf_cmd_explain[iron],
|
||||
.hint = NULL,
|
||||
.func = hf_cmd_tbl[iron].handler,
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&HF_ORDER(iron)));
|
||||
|
||||
const esp_console_cmd_t HF_ORDER(iroff) = {
|
||||
.command = "iroff",
|
||||
.help = hf_cmd_explain[iroff],
|
||||
.hint = NULL,
|
||||
.func = hf_cmd_tbl[iroff].handler,
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&HF_ORDER(iroff)));
|
||||
|
||||
ind_args.call = arg_str1(NULL, NULL, "<call>", "call status [0,1]");
|
||||
ind_args.callsetup = arg_str1(NULL, NULL, "<callsetup>", "call setup status [0,3]");
|
||||
ind_args.ntk = arg_str1(NULL, NULL, "<ntk>", "network status [0,1]");
|
||||
ind_args.sig = arg_str1(NULL, NULL, "<sig>", "signal strength value from 0~5");
|
||||
ind_args.end = arg_end(1);
|
||||
const esp_console_cmd_t HF_ORDER(ind) = {
|
||||
.command = "ind",
|
||||
.help = hf_cmd_explain[ind],
|
||||
.hint = NULL,
|
||||
.func = hf_cmd_tbl[ind].handler,
|
||||
.argtable = &ind_args
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&HF_ORDER(ind)));
|
||||
|
||||
ate_args.err = arg_str1(NULL, NULL, "<err>", "error code from 0 to 32");
|
||||
ate_args.rep = arg_str1(NULL, NULL, "<rep>", "response code from 0 to 7");
|
||||
ate_args.end = arg_end(1);
|
||||
const esp_console_cmd_t HF_ORDER(ate) = {
|
||||
.command = "ate",
|
||||
.help = hf_cmd_explain[ate],
|
||||
.hint = NULL,
|
||||
.func = hf_cmd_tbl[ate].handler,
|
||||
.argtable = &ate_args
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&HF_ORDER(ate)));
|
||||
}
|
||||
|
@ -11,7 +11,7 @@
|
||||
|
||||
#define HF_MSG_ARGS_MAX (8)
|
||||
|
||||
typedef void (* hf_cmd_handler)(int argn, char **argv);
|
||||
typedef int (* hf_cmd_handler)(int argn, char **argv);
|
||||
|
||||
typedef struct {
|
||||
uint16_t opcode;
|
||||
@ -23,4 +23,6 @@ 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);
|
||||
|
||||
void register_hfp_ag(void);
|
||||
#endif /* __APP_HF_MSG_SET_H__*/
|
||||
|
@ -15,15 +15,18 @@
|
||||
#include "esp_bt_device.h"
|
||||
#include "esp_gap_bt_api.h"
|
||||
#include "esp_hf_ag_api.h"
|
||||
#include "esp_timer.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "freertos/ringbuf.h"
|
||||
#include "time.h"
|
||||
#include "sys/time.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "bt_app_core.h"
|
||||
#include "bt_app_hf.h"
|
||||
#include "osi/allocator.h"
|
||||
|
||||
const char *c_hf_evt_str[] = {
|
||||
"CONNECTION_STATE_EVT", /*!< SERVICE LEVEL CONNECTION STATE CONTROL */
|
||||
@ -101,9 +104,10 @@ const char *c_codec_mode_str[] = {
|
||||
"Use MSBC",
|
||||
};
|
||||
|
||||
#if CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_HCI
|
||||
#if CONFIG_BT_HFP_AUDIO_DATA_PATH_HCI
|
||||
#define TABLE_SIZE 100
|
||||
// Produce a sine audio
|
||||
static const int16_t sine_int16[] = {
|
||||
static const int16_t sine_int16[TABLE_SIZE] = {
|
||||
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,
|
||||
@ -116,8 +120,64 @@ static const int16_t sine_int16[] = {
|
||||
-19260, -17557, -15786, -13952, -12062, -10126, -8149, -6140, -4107, -2057,
|
||||
};
|
||||
|
||||
#define TABLE_SIZE_CVSD 100
|
||||
#define ESP_HFP_RINGBUF_SIZE 3600
|
||||
|
||||
// 7500 microseconds(=12 slots) is aligned to 1 msbc frame duration, and is multiple of common Tesco for eSCO link with EV3 or 2-EV3 packet type
|
||||
#define PCM_BLOCK_DURATION_US (7500)
|
||||
|
||||
#define WBS_PCM_SAMPLING_RATE_KHZ (16)
|
||||
#define PCM_SAMPLING_RATE_KHZ (8)
|
||||
|
||||
#define BYTES_PER_SAMPLE (2)
|
||||
|
||||
// input can refer to Enhanced Setup Synchronous Connection Command in core spec4.2 Vol2, Part E
|
||||
#define WBS_PCM_INPUT_DATA_SIZE (WBS_PCM_SAMPLING_RATE_KHZ * PCM_BLOCK_DURATION_US / 1000 * BYTES_PER_SAMPLE) //240
|
||||
#define PCM_INPUT_DATA_SIZE (PCM_SAMPLING_RATE_KHZ * PCM_BLOCK_DURATION_US / 1000 * BYTES_PER_SAMPLE) //120
|
||||
|
||||
#define PCM_GENERATOR_TICK_US (4000)
|
||||
|
||||
static long s_data_num = 0;
|
||||
static RingbufHandle_t s_m_rb = NULL;
|
||||
static uint64_t s_time_new, s_time_old;
|
||||
static esp_timer_handle_t s_periodic_timer;
|
||||
static uint64_t s_last_enter_time, s_now_enter_time;
|
||||
static uint64_t s_us_duration;
|
||||
static xSemaphoreHandle s_send_data_Semaphore = NULL;
|
||||
static xTaskHandle s_bt_app_send_data_task_handler = NULL;
|
||||
static esp_hf_audio_state_t s_audio_code;
|
||||
|
||||
static void print_speed(void);
|
||||
|
||||
static uint32_t bt_app_hf_outgoing_cb(uint8_t *p_buf, uint32_t sz)
|
||||
{
|
||||
size_t item_size = 0;
|
||||
uint8_t *data;
|
||||
if (!s_m_rb) {
|
||||
return 0;
|
||||
}
|
||||
vRingbufferGetInfo(s_m_rb, NULL, NULL, NULL, NULL, &item_size);
|
||||
if (item_size >= sz) {
|
||||
data = xRingbufferReceiveUpTo(s_m_rb, &item_size, 0, sz);
|
||||
memcpy(p_buf, data, item_size);
|
||||
vRingbufferReturnItem(s_m_rb, data);
|
||||
return sz;
|
||||
} else {
|
||||
// data not enough, do not read\n
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void bt_app_hf_incoming_cb(const uint8_t *buf, uint32_t sz)
|
||||
{
|
||||
s_time_new = esp_timer_get_time();
|
||||
s_data_num += sz;
|
||||
if ((s_time_new - s_time_old) >= 3000000) {
|
||||
print_speed();
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t bt_app_hf_create_audio_data(uint8_t *p_buf, uint32_t sz)
|
||||
{
|
||||
static int sine_phase = 0;
|
||||
|
||||
@ -125,19 +185,108 @@ static uint32_t bt_app_hf_outgoing_cb(uint8_t *p_buf, uint32_t sz)
|
||||
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;
|
||||
if (sine_phase >= TABLE_SIZE) {
|
||||
sine_phase -= TABLE_SIZE;
|
||||
}
|
||||
}
|
||||
return sz;
|
||||
}
|
||||
|
||||
static void bt_app_hf_incoming_cb(const uint8_t *buf, uint32_t sz)
|
||||
static void print_speed(void)
|
||||
{
|
||||
// direct to i2s
|
||||
esp_hf_outgoing_data_ready();
|
||||
float tick_s = (s_time_new - s_time_old) / 1000000.0;
|
||||
float speed = s_data_num * 8 / tick_s / 1000.0;
|
||||
ESP_LOGI(BT_HF_TAG, "speed(%fs ~ %fs): %f kbit/s" , s_time_old / 1000000.0, s_time_new / 1000000.0, speed);
|
||||
s_data_num = 0;
|
||||
s_time_old = s_time_new;
|
||||
}
|
||||
#endif /* #if CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_HCI */
|
||||
|
||||
static void bt_app_send_data_timer_cb(void *arg)
|
||||
{
|
||||
if (!xSemaphoreGive(s_send_data_Semaphore)) {
|
||||
ESP_LOGE(BT_HF_TAG, "%s xSemaphoreGive failed", __func__);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void bt_app_send_data_task(void *arg)
|
||||
{
|
||||
uint64_t frame_data_num;
|
||||
uint32_t item_size = 0;
|
||||
uint8_t *buf = NULL;
|
||||
for (;;) {
|
||||
if (xSemaphoreTake(s_send_data_Semaphore, (portTickType)portMAX_DELAY)) {
|
||||
s_now_enter_time = esp_timer_get_time();
|
||||
s_us_duration = s_now_enter_time - s_last_enter_time;
|
||||
if(s_audio_code == ESP_HF_AUDIO_STATE_CONNECTED_MSBC) {
|
||||
// time of a frame is 7.5ms, sample is 120, data is 2 (byte/sample), so a frame is 240 byte (HF_SBC_ENC_RAW_DATA_SIZE)
|
||||
frame_data_num = s_us_duration / (PCM_BLOCK_DURATION_US / WBS_PCM_INPUT_DATA_SIZE);
|
||||
s_last_enter_time += frame_data_num * (PCM_BLOCK_DURATION_US / WBS_PCM_INPUT_DATA_SIZE);
|
||||
} else {
|
||||
frame_data_num = s_us_duration / (PCM_BLOCK_DURATION_US / PCM_INPUT_DATA_SIZE);
|
||||
s_last_enter_time += frame_data_num * (PCM_BLOCK_DURATION_US / PCM_INPUT_DATA_SIZE);
|
||||
}
|
||||
buf = osi_malloc(frame_data_num);
|
||||
if (!buf) {
|
||||
ESP_LOGE(BT_HF_TAG, "%s, no mem", __FUNCTION__);
|
||||
continue;
|
||||
}
|
||||
bt_app_hf_create_audio_data(buf, frame_data_num);
|
||||
BaseType_t done = xRingbufferSend(s_m_rb, buf, frame_data_num, 0);
|
||||
if (!done) {
|
||||
ESP_LOGE(BT_HF_TAG, "rb send fail\n");
|
||||
}
|
||||
osi_free(buf);
|
||||
vRingbufferGetInfo(s_m_rb, NULL, NULL, NULL, NULL, &item_size);
|
||||
|
||||
if(s_audio_code == ESP_HF_AUDIO_STATE_CONNECTED_MSBC) {
|
||||
if(item_size >= WBS_PCM_INPUT_DATA_SIZE) {
|
||||
esp_hf_outgoing_data_ready();
|
||||
}
|
||||
} else {
|
||||
if(item_size >= PCM_INPUT_DATA_SIZE) {
|
||||
esp_hf_outgoing_data_ready();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
void bt_app_send_data(void)
|
||||
{
|
||||
s_send_data_Semaphore = xSemaphoreCreateBinary();
|
||||
xTaskCreate(bt_app_send_data_task, "BtAppSendDataTask", 2048, NULL, configMAX_PRIORITIES - 3, &s_bt_app_send_data_task_handler);
|
||||
s_m_rb = xRingbufferCreate(ESP_HFP_RINGBUF_SIZE, RINGBUF_TYPE_BYTEBUF);
|
||||
const esp_timer_create_args_t c_periodic_timer_args = {
|
||||
.callback = &bt_app_send_data_timer_cb,
|
||||
.name = "periodic"
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_timer_create(&c_periodic_timer_args, &s_periodic_timer));
|
||||
ESP_ERROR_CHECK(esp_timer_start_periodic(s_periodic_timer, PCM_GENERATOR_TICK_US));
|
||||
s_last_enter_time = esp_timer_get_time();
|
||||
return;
|
||||
}
|
||||
|
||||
void bt_app_send_data_shut_down(void)
|
||||
{
|
||||
if (s_bt_app_send_data_task_handler) {
|
||||
vTaskDelete(s_bt_app_send_data_task_handler);
|
||||
s_bt_app_send_data_task_handler = NULL;
|
||||
}
|
||||
if (s_send_data_Semaphore) {
|
||||
vSemaphoreDelete(s_send_data_Semaphore);
|
||||
s_send_data_Semaphore = NULL;
|
||||
}
|
||||
if(s_periodic_timer) {
|
||||
ESP_ERROR_CHECK(esp_timer_stop(s_periodic_timer));
|
||||
ESP_ERROR_CHECK(esp_timer_delete(s_periodic_timer));
|
||||
}
|
||||
if (s_m_rb) {
|
||||
vRingbufferDelete(s_m_rb);
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif /* #if CONFIG_BT_HFP_AUDIO_DATA_PATH_HCI */
|
||||
|
||||
void bt_app_hf_cb(esp_hf_cb_event_t event, esp_hf_cb_param_t *param)
|
||||
{
|
||||
@ -161,15 +310,24 @@ void bt_app_hf_cb(esp_hf_cb_event_t event, esp_hf_cb_param_t *param)
|
||||
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 CONFIG_BT_HFP_AUDIO_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) {
|
||||
s_audio_code = ESP_HF_AUDIO_STATE_CONNECTED;
|
||||
} else {
|
||||
s_audio_code = ESP_HF_AUDIO_STATE_CONNECTED_MSBC;
|
||||
}
|
||||
s_time_old = esp_timer_get_time();
|
||||
esp_bt_hf_register_data_callback(bt_app_hf_incoming_cb, bt_app_hf_outgoing_cb);
|
||||
/* Begin send esco data task */
|
||||
bt_app_send_data();
|
||||
} else if (param->audio_stat.state == ESP_HF_AUDIO_STATE_DISCONNECTED) {
|
||||
ESP_LOGI(BT_HF_TAG, "--ESP AG Audio Connection Disconnected.");
|
||||
bt_app_send_data_shut_down();
|
||||
}
|
||||
#endif /* #if CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_HCI */
|
||||
#endif /* #if CONFIG_BT_HFP_AUDIO_DATA_PATH_HCI */
|
||||
break;
|
||||
}
|
||||
|
||||
@ -290,7 +448,7 @@ void bt_app_hf_cb(esp_hf_cb_event_t event, esp_hf_cb_param_t *param)
|
||||
}
|
||||
break;
|
||||
}
|
||||
#if (BTM_WBS_INCLUDED == TRUE)
|
||||
#if (CONFIG_BT_HFP_WBS_ENABLE)
|
||||
case ESP_HF_WBS_RESPONSE_EVT:
|
||||
{
|
||||
ESP_LOGI(BT_HF_TAG, "--Current codec: %s",c_codec_mode_str[param->wbs_rep.codec]);
|
||||
@ -306,5 +464,6 @@ void bt_app_hf_cb(esp_hf_cb_event_t event, esp_hf_cb_param_t *param)
|
||||
default:
|
||||
ESP_LOGI(BT_HF_TAG, "Unsupported HF_AG EVT: %d.", event);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -21,6 +21,4 @@ esp_bd_addr_t hf_peer_addr; // Declaration of peer device bdaddr
|
||||
* @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__*/
|
||||
|
@ -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,
|
||||
.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;
|
||||
}
|
@ -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__*/
|
@ -24,7 +24,8 @@
|
||||
#include "esp_hf_ag_api.h"
|
||||
#include "bt_app_hf.h"
|
||||
#include "gpio_pcm_config.h"
|
||||
#include "console_uart.h"
|
||||
#include "esp_console.h"
|
||||
#include "app_hf_msg_set.h"
|
||||
|
||||
#define BT_HF_AG_TAG "HF_AG_DEMO_MAIN"
|
||||
|
||||
@ -108,14 +109,35 @@ void app_main(void)
|
||||
/* 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();
|
||||
|
||||
#if CONFIG_BT_HFP_AUDIO_DATA_PATH_PCM
|
||||
/* configure the PCM interface and PINs used */
|
||||
app_gpio_pcm_io_cfg();
|
||||
#endif
|
||||
|
||||
/* configure externel chip for acoustic echo cancellation */
|
||||
#if ACOUSTIC_ECHO_CANCELLATION_ENABLE
|
||||
app_gpio_aec_io_cfg();
|
||||
#endif /* ACOUSTIC_ECHO_CANCELLATION_ENABLE */
|
||||
|
||||
esp_console_repl_t *repl = NULL;
|
||||
esp_console_repl_config_t repl_config = ESP_CONSOLE_REPL_CONFIG_DEFAULT();
|
||||
esp_console_dev_uart_config_t uart_config = ESP_CONSOLE_DEV_UART_CONFIG_DEFAULT();
|
||||
repl_config.prompt = "hfp_ag>";
|
||||
|
||||
// init console REPL environment
|
||||
ESP_ERROR_CHECK(esp_console_new_repl_uart(&uart_config, &repl_config, &repl));
|
||||
|
||||
/* Register commands */
|
||||
register_hfp_ag();
|
||||
printf("\n ==================================================\n");
|
||||
printf(" | Steps to test hfp_ag |\n");
|
||||
printf(" | |\n");
|
||||
printf(" | 1. Print 'help' to gain overview of commands |\n");
|
||||
printf(" | 2. Setup a service level connection |\n");
|
||||
printf(" | 3. Run hfp_ag to test |\n");
|
||||
printf(" | |\n");
|
||||
printf(" =================================================\n\n");
|
||||
|
||||
// start console REPL
|
||||
ESP_ERROR_CHECK(esp_console_start_repl(repl));
|
||||
}
|
||||
|
@ -40,54 +40,29 @@ See the [Getting Started Guide](https://docs.espressif.com/projects/esp-idf/en/l
|
||||
|
||||
## Example Output
|
||||
|
||||
When you run this example, the commands help table prints the following at the very begining:
|
||||
When you run this example, the explain prints the following at the very begining:
|
||||
|
||||
```
|
||||
########################################################################
|
||||
HF client command usage manual
|
||||
HF client commands begin 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 qop; -- query current operator name
|
||||
hf qc; -- query current call status
|
||||
hf ac; -- answer incoming call
|
||||
hf rc; -- reject incoming call
|
||||
hf d <num>; -- dial <num>, e.g. hf d 11223344
|
||||
hf rd; -- redial
|
||||
hf dm <index>; -- dial memory
|
||||
hf vron; -- start voice recognition
|
||||
hf vroff; -- stop voice recognition
|
||||
hf vu <tgt> <vol>; -- volume update
|
||||
tgt: 0-speaker, 1-microphone
|
||||
vol: volume gain ranges from 0 to 15
|
||||
hf rs; -- retrieve subscriber information
|
||||
hf rv; -- retrieve last voice tag number
|
||||
hf rh <btrh>; -- response and hold
|
||||
btrh:
|
||||
0 - put call on hold,
|
||||
1 - accept the held call,
|
||||
2 -reject the held call
|
||||
hf k <dtmf>; -- send dtmf code.
|
||||
dtmf: single character in set 0-9, *, #, A-D
|
||||
hf h; -- show command manual
|
||||
########################################################################
|
||||
Type 'help' to get the list of commands.
|
||||
Use UP/DOWN arrows to navigate through command history.
|
||||
Press TAB when typing command name to auto-complete.
|
||||
|
||||
==================================================
|
||||
| Steps to test hfp_hf |
|
||||
| |
|
||||
| 1. Print 'help' to gain overview of commands |
|
||||
| 2. Setup a service level connection |
|
||||
| 3. Run hfp_hf to test |
|
||||
| |
|
||||
=================================================
|
||||
|
||||
```
|
||||
|
||||
**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 AG device and log prints such as:
|
||||
You can type `con` to establish a service level connection with AG device and log prints such as:
|
||||
|
||||
```
|
||||
E (78502) CNSL: Command [hf con;]
|
||||
connect
|
||||
W (79632) BT_APPL: new conn_srvc id:27, app_id:1
|
||||
I (79642) BT_HF: APP HFP event: CONNECTION_STATE_EVT
|
||||
@ -114,10 +89,9 @@ I (79872) BT_HF: --inband ring state Provided
|
||||
|
||||
**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 AG device, and log prints such as:
|
||||
You can type `dis` to disconnect with the connected AG device, and log prints such as:
|
||||
|
||||
```
|
||||
E (93382) CNSL: Command [hf dis;]
|
||||
disconnect
|
||||
W (93702) BT_RFCOMM: port_rfc_closed RFCOMM connection in state 3 closed: Closed (res: 19)
|
||||
W (93712) BT_APPL: BTA_HF_CLIENT_SCO_SHUTDOWN_ST: Ignoring event 3
|
||||
@ -127,10 +101,9 @@ I (93712) 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. Log prints such as:
|
||||
You can type `cona` to establish the audio connection between HF Unit and AG device. Log prints such as:
|
||||
|
||||
```
|
||||
E (117232) CNSL: Command [hf cona;]
|
||||
connect audio
|
||||
I (117232) BT_HF: APP HFP event: AUDIO_STATE_EVT
|
||||
I (117232) BT_HF: --audio state connecting
|
||||
@ -139,10 +112,9 @@ I (117262) BT_HF: APP HFP event: AUDIO_STATE_EVT
|
||||
I (117262) BT_HF: --audio state connected
|
||||
```
|
||||
|
||||
Also, you can type `hf disa;` to close the audio data stream. Log prints such as:
|
||||
Also, you can type `disa` to close the audio data stream. Log prints such as:
|
||||
|
||||
```
|
||||
E (133002) CNSL: Command [hf disa;]
|
||||
disconnect audio
|
||||
I (133262) BT_HF: APP HFP event: AUDIO_STATE_EVT
|
||||
I (133262) BT_HF: --audio state disconnected
|
||||
@ -172,10 +144,9 @@ Since CVSD is the default codec in HFP, we just show the scenarios using mSBC:
|
||||
|
||||
#### Answer an incoming call
|
||||
|
||||
You can type `hf ac;` to answer an incoming call and log prints such as:
|
||||
You can type `ac` to answer an incoming call and log prints such as:
|
||||
|
||||
```
|
||||
E (196982) CNSL: Command [hf ac;]
|
||||
Answer call
|
||||
I (197102) BT_HF: APP HFP event: AT_RESPONSE
|
||||
I (197102) BT_HF: --AT response event, code 0, cme 0
|
||||
@ -188,10 +159,9 @@ I (197242) BT_HF: --audio state connected
|
||||
|
||||
#### Reject an incoming call
|
||||
|
||||
You can type `hf rc;` to reject an incoming call and log prints such as:
|
||||
You can type `rc` to reject an incoming call and log prints such as:
|
||||
|
||||
```
|
||||
E (210112) CNSL: Command [hf rc;]
|
||||
Reject call
|
||||
I (210822) BT_HF: APP HFP event: AT_RESPONSE
|
||||
I (210822) BT_HF: --AT response event, code 0, cme 0
|
||||
@ -205,14 +175,13 @@ I (210902) BT_HF: --Call indicator NO call in progress
|
||||
|
||||
This example supports three dialing commands:
|
||||
|
||||
- `hf d <num>;` Dial the specific number.
|
||||
- `hf rd;` Redial the last number.
|
||||
- `hf dm <index>` Dial the specific indexed number in the AG memory.
|
||||
- `d <num>` Dial the specific number.
|
||||
- `rd` Redial the last number.
|
||||
- `dm <index>` Dial the specific indexed number in the AG memory.
|
||||
|
||||
For example, type `hf d 186xxxx5549;` to make an outgoing call to `186xxxx5549` and log prints such as:
|
||||
For example, type `d 186xxxx5549` to make an outgoing call to `186xxxx5549` and log prints such as:
|
||||
|
||||
```
|
||||
E (228882) CNSL: Command [hf d 186xxxx5549;]
|
||||
Dial number 186xxxx5549
|
||||
E (229702) BT_BTM: btm_sco_connected, handle 181
|
||||
I (229712) BT_HF: APP HFP event: CALL_SETUP_IND_EVT
|
||||
@ -227,25 +196,25 @@ I (229732) BT_HF: --Call setup indicator NONE
|
||||
|
||||
#### Respond and Hold
|
||||
|
||||
You can type `hf rh <btrh>;` to respond or hold the current call. The parameter should be set as follows:
|
||||
You can type `rh <btrh>` to respond or hold the current call. The parameter should be set as follows:
|
||||
|
||||
- `<btrh>` : 0 - hold current call, 1 - answer held call, 2 - end held call.
|
||||
|
||||
#### Volume Control
|
||||
|
||||
You can type `hf vu <tgt> <vol>;` to update volume gain of speaker or microphone. The parameter should be set as follows:
|
||||
You can type `vu <tgt> <vol>` to update volume gain of speaker or microphone. The parameter should be set as follows:
|
||||
|
||||
- `<tgt>` : 0 - speaker, 1 - microphone.
|
||||
- `<vol>` : Integer among 0 - 15.
|
||||
|
||||
For example, type `hf vu 0 9;` to update the volume of speaker and log on AG prints:
|
||||
For example, type `vu 0 9` to update the volume of speaker and log on AG prints:
|
||||
|
||||
```
|
||||
I (43684) BT_APP_HF: APP HFP event: VOLUME_CONTROL_EVT
|
||||
I (43684) BT_APP_HF: --Volume Target: SPEAKER, Volume 9
|
||||
```
|
||||
|
||||
And also, `hf vu 1 9;` update the volume gain of microphone and log on AG prints:
|
||||
And also, `vu 1 9` update the volume gain of microphone and log on AG prints:
|
||||
|
||||
```
|
||||
I (177254) BT_APP_HF: APP HFP event: VOLUME_CONTROL_EVT
|
||||
@ -254,10 +223,9 @@ I (177254) BT_APP_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 this function. For example, type `hf vron;` and log prints such as:
|
||||
You can type `vron` to start the voice recognition of AG and type `vroff` to terminate this function. For example, type `vron` and log prints such as:
|
||||
|
||||
```
|
||||
E (292432) CNSL: Command [hf vron;]
|
||||
Start voice recognition
|
||||
I (293172) BT_HF: APP HFP event: AT_RESPONSE
|
||||
I (293172) BT_HF: --AT response event, code 0, cme 0
|
||||
@ -268,10 +236,9 @@ I (293702) BT_HF: --audio state connecte
|
||||
|
||||
#### Query Current Operator Name
|
||||
|
||||
You can type `hf qop;` to query the current operator name and log prints like:
|
||||
You can type `qop` to query the current operator name and log prints like:
|
||||
|
||||
```
|
||||
E (338322) CNSL: Command [hf qop;]
|
||||
Query operator
|
||||
I (339202) BT_HF: APP HFP event: CURRENT_OPERATOR_EVT
|
||||
I (339202) BT_HF: --operator name: 中国联通
|
||||
@ -281,10 +248,9 @@ I (339202) BT_HF: --AT response event, code 0, cme 0
|
||||
|
||||
#### Retrieve Subscriber Information
|
||||
|
||||
You can type `hf rs;` to retrieve subscriber information and log prints such as:
|
||||
You can type `rs` to retrieve subscriber information and log prints such as:
|
||||
|
||||
```
|
||||
E (352902) CNSL: Command [hf rs;]
|
||||
Retrieve subscriber information
|
||||
I (353702) BT_HF: APP HFP event: SUBSCRIBER_INFO_EVT
|
||||
I (353702) BT_HF: --subscriber type unknown, number 186xxxx5549
|
||||
@ -294,10 +260,9 @@ I (353702) BT_HF: --AT response event, code 0, cme 0
|
||||
|
||||
#### Query Current Call Status
|
||||
|
||||
You can type `hf qc;` to query current call status and log prints like:
|
||||
You can type `qc` to query current call status and log prints like:
|
||||
|
||||
```
|
||||
E (354522) CNSL: Command [hf qc;]
|
||||
Query current call status
|
||||
I (354582) BT_HF: APP HFP event: CLCC_EVT
|
||||
I (354582) BT_HF: --Current call: idx 1, dir incoming, state active, mpty single, number 186xxxx5549
|
||||
@ -307,7 +272,7 @@ I (354592) BT_HF: --AT response event, code 0, cme 0
|
||||
|
||||
#### Transport DTMF Code
|
||||
|
||||
You can type `hf k <dtmf>;` to transport a DTMF code to AG. Log on HF unit side prints like:`send dtmf code: 9` and log on AG side prints such as:
|
||||
You can type `k <dtmf>` to transport a DTMF code to AG. Log on HF unit side prints like:`send dtmf code: 9` and log on AG side prints such as:
|
||||
|
||||
```
|
||||
I (196284) BT_APP_HF: APP HFP event: DTMF_RESPONSE_EVT
|
||||
@ -320,7 +285,7 @@ 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 AG device like _Hands Free Audio Gateway (hfp_ag)_ example from ESP-IDF.
|
||||
- If you want to use `hf con;` to establish a service level connection with specific AG device, you should add the MAC address of the AG device in `bt_app.c`, for example: `esp_bd_addr_t peer_addr = {0xb4, 0xe6, 0x2d, 0xeb, 0x09, 0x93};`
|
||||
- If you want to use `con` to establish a service level connection with specific AG device, you should add the MAC address of the AG device in `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
|
||||
|
@ -2,7 +2,6 @@ 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 ".")
|
||||
|
@ -10,6 +10,9 @@
|
||||
#include <string.h>
|
||||
#include "esp_hf_client_api.h"
|
||||
#include "app_hf_msg_set.h"
|
||||
#include "esp_console.h"
|
||||
#include "argtable3/argtable3.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
extern esp_bd_addr_t peer_addr;
|
||||
|
||||
@ -48,53 +51,61 @@ void hf_msg_show_usage(void)
|
||||
printf("########################################################################\n");
|
||||
}
|
||||
|
||||
#define HF_CMD_HANDLER(cmd) static void hf_##cmd##_handler(int argn, char **argv)
|
||||
#define HF_CMD_HANDLER(cmd) static int hf_##cmd##_handler(int argn, char **argv)
|
||||
|
||||
|
||||
HF_CMD_HANDLER(help)
|
||||
{
|
||||
hf_msg_show_usage();
|
||||
return 0;
|
||||
}
|
||||
|
||||
HF_CMD_HANDLER(conn)
|
||||
{
|
||||
printf("connect\n");
|
||||
esp_hf_client_connect(peer_addr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
HF_CMD_HANDLER(disc)
|
||||
{
|
||||
printf("disconnect\n");
|
||||
esp_hf_client_disconnect(peer_addr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
HF_CMD_HANDLER(conn_audio)
|
||||
{
|
||||
printf("connect audio\n");
|
||||
esp_hf_client_connect_audio(peer_addr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
HF_CMD_HANDLER(disc_audio)
|
||||
{
|
||||
printf("disconnect audio\n");
|
||||
esp_hf_client_disconnect_audio(peer_addr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
HF_CMD_HANDLER(query_op)
|
||||
{
|
||||
printf("Query operator\n");
|
||||
esp_hf_client_query_current_operator_name();
|
||||
return 0;
|
||||
}
|
||||
|
||||
HF_CMD_HANDLER(answer)
|
||||
{
|
||||
printf("Answer call\n");
|
||||
esp_hf_client_answer_call();
|
||||
return 0;
|
||||
}
|
||||
HF_CMD_HANDLER(reject)
|
||||
{
|
||||
printf("Reject call\n");
|
||||
esp_hf_client_reject_call();
|
||||
return 0;
|
||||
}
|
||||
|
||||
HF_CMD_HANDLER(dial)
|
||||
@ -105,28 +116,31 @@ HF_CMD_HANDLER(dial)
|
||||
printf("Dial number %s\n", argv[1]);
|
||||
esp_hf_client_dial(argv[1]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
HF_CMD_HANDLER(redial)
|
||||
{
|
||||
printf("Dial number\n");
|
||||
esp_hf_client_dial(NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
HF_CMD_HANDLER(dial_mem)
|
||||
{
|
||||
if (argn != 2) {
|
||||
printf("Insufficient number of arguments");
|
||||
return;
|
||||
return 1;
|
||||
}
|
||||
int index;
|
||||
if (sscanf(argv[1], "%d", &index) != 1) {
|
||||
printf("Invalid argument %s\n", argv[1]);
|
||||
return;
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("Dial memory %d\n", index);
|
||||
esp_hf_client_dial_memory(index);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@ -134,74 +148,81 @@ HF_CMD_HANDLER(start_vr)
|
||||
{
|
||||
printf("Start voice recognition\n");
|
||||
esp_hf_client_start_voice_recognition();
|
||||
return 0;
|
||||
}
|
||||
|
||||
HF_CMD_HANDLER(stop_vr)
|
||||
{
|
||||
printf("Stop voice recognition\n");
|
||||
esp_hf_client_stop_voice_recognition();
|
||||
return 0;
|
||||
}
|
||||
|
||||
HF_CMD_HANDLER(volume_update)
|
||||
{
|
||||
if (argn != 3) {
|
||||
printf("Insufficient number of arguments");
|
||||
return;
|
||||
return 1;
|
||||
}
|
||||
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;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (sscanf(argv[2], "%d", &volume) != 1 ||
|
||||
(volume < 0 || volume > 15)) {
|
||||
printf("Invalid argument for volume %s\n", argv[2]);
|
||||
return;
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("volume update\n");
|
||||
esp_hf_client_volume_update(target, volume);
|
||||
return 0;
|
||||
}
|
||||
|
||||
HF_CMD_HANDLER(query_call)
|
||||
{
|
||||
printf("Query current call status\n");
|
||||
esp_hf_client_query_current_calls();
|
||||
return 0;
|
||||
}
|
||||
|
||||
HF_CMD_HANDLER(retrieve_subscriber)
|
||||
{
|
||||
printf("Retrieve subscriber information\n");
|
||||
esp_hf_client_retrieve_subscriber_info();
|
||||
return 0;
|
||||
}
|
||||
|
||||
HF_CMD_HANDLER(request_last_voice_tag)
|
||||
{
|
||||
printf("Request last voice tag\n");
|
||||
esp_hf_client_request_last_voice_tag_number();
|
||||
return 0;
|
||||
}
|
||||
|
||||
HF_CMD_HANDLER(btrh)
|
||||
{
|
||||
if (argn != 2) {
|
||||
printf("Insufficient number of arguments");
|
||||
return;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int btrh;
|
||||
if (sscanf(argv[1], "%d", &btrh) != 1) {
|
||||
printf("Invalid argument %s\n", argv[1]);
|
||||
return;
|
||||
return 1;
|
||||
}
|
||||
if (btrh < ESP_HF_BTRH_CMD_HOLD || btrh > ESP_HF_BTRH_CMD_REJECT) {
|
||||
printf("Invalid argument %s\n", argv[1]);
|
||||
return;
|
||||
return 1;
|
||||
}
|
||||
printf("respond and hold command: %d\n", btrh);
|
||||
esp_hf_client_send_btrh_cmd(btrh);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool is_dtmf_code(char c)
|
||||
@ -222,16 +243,17 @@ HF_CMD_HANDLER(dtmf)
|
||||
{
|
||||
if (argn != 2) {
|
||||
printf("Insufficient number of arguments");
|
||||
return;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (strlen(argv[1]) != 1 || !is_dtmf_code(argv[1][0])) {
|
||||
printf("Invalid argument %s\n", argv[1]);
|
||||
return;
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("send dtmf code: %s\n", argv[1]);
|
||||
esp_hf_client_send_dtmf(argv[1][0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static hf_msg_hdl_t hf_cmd_tbl[] = {
|
||||
@ -265,3 +287,215 @@ size_t hf_get_cmd_tbl_size(void)
|
||||
{
|
||||
return sizeof(hf_cmd_tbl) / sizeof(hf_msg_hdl_t);
|
||||
}
|
||||
|
||||
#define HF_ORDER(name) name##_cmd
|
||||
enum hf_cmd_name {
|
||||
h = 0, /*show command manual*/
|
||||
con, /*set up connection with peer device*/
|
||||
dis, /*release connection with peer device*/
|
||||
cona, /*setup audio connection with peer device*/
|
||||
disa, /*setup audio connection with peer device*/
|
||||
qop, /*query current operator name*/
|
||||
qc, /*query current call status*/
|
||||
ac, /*answer incoming call*/
|
||||
rc, /*reject incoming call*/
|
||||
d, /*dial <num>, e.g. d 11223344*/
|
||||
rd, /*redial*/
|
||||
dm, /*dial memory*/
|
||||
vron, /*start voice recognition*/
|
||||
vroff, /*stop voice recognition*/
|
||||
vu, /*volume update*/
|
||||
rs, /*retrieve subscriber information*/
|
||||
rv, /*retrieve last voice tag number*/
|
||||
rh, /*response and hold*/
|
||||
k /*send dtmf code*/
|
||||
};
|
||||
static char *hf_cmd_explain[] = {
|
||||
"show command manual",
|
||||
"set up connection with peer device",
|
||||
"release connection with peer device",
|
||||
"setup audio connection with peer device",
|
||||
"release connection with peer device",
|
||||
"query current operator name",
|
||||
"query current call status",
|
||||
"answer incoming call",
|
||||
"reject incoming call",
|
||||
"dial <num>, e.g. d 11223344",
|
||||
"redial",
|
||||
"dial memory",
|
||||
"start voice recognition",
|
||||
"stop voice recognition",
|
||||
"volume update",
|
||||
"retrieve subscriber information",
|
||||
"retrieve last voice tag number",
|
||||
"response and hold",
|
||||
"send dtmf code.\n <dtmf> single character in set 0-9, *, #, A-D",
|
||||
};
|
||||
typedef struct {
|
||||
struct arg_str *tgt;
|
||||
struct arg_str *vol;
|
||||
struct arg_end *end;
|
||||
} vu_args_t;
|
||||
|
||||
typedef struct {
|
||||
struct arg_str *btrh;
|
||||
struct arg_end *end;
|
||||
} rh_args_t;
|
||||
|
||||
static vu_args_t vu_args;
|
||||
static rh_args_t rh_args;
|
||||
|
||||
void register_hfp_hf(void)
|
||||
{
|
||||
|
||||
const esp_console_cmd_t con_cmd = {
|
||||
.command = "con",
|
||||
.help = hf_cmd_explain[con],
|
||||
.hint = NULL,
|
||||
.func = hf_cmd_tbl[con].handler,
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&con_cmd));
|
||||
|
||||
const esp_console_cmd_t dis_cmd = {
|
||||
.command = "dis",
|
||||
.help = hf_cmd_explain[dis],
|
||||
.hint = NULL,
|
||||
.func = hf_cmd_tbl[dis].handler,
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&dis_cmd));
|
||||
|
||||
const esp_console_cmd_t cona_cmd = {
|
||||
.command = "cona",
|
||||
.help = hf_cmd_explain[cona],
|
||||
.hint = NULL,
|
||||
.func = hf_cmd_tbl[cona].handler,
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&cona_cmd));
|
||||
|
||||
const esp_console_cmd_t disa_cmd = {
|
||||
.command = "disa",
|
||||
.help = hf_cmd_explain[disa],
|
||||
.hint = NULL,
|
||||
.func = hf_cmd_tbl[disa].handler,
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&disa_cmd));
|
||||
|
||||
const esp_console_cmd_t qop_cmd = {
|
||||
.command = "qop",
|
||||
.help = hf_cmd_explain[qop],
|
||||
.hint = NULL,
|
||||
.func = hf_cmd_tbl[qop].handler,
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&qop_cmd));
|
||||
|
||||
const esp_console_cmd_t qc_cmd = {
|
||||
.command = "qc",
|
||||
.help = hf_cmd_explain[qc],
|
||||
.hint = NULL,
|
||||
.func = hf_cmd_tbl[qc].handler,
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&qc_cmd));
|
||||
|
||||
const esp_console_cmd_t ac_cmd = {
|
||||
.command = "ac",
|
||||
.help = hf_cmd_explain[ac],
|
||||
.hint = NULL,
|
||||
.func = hf_cmd_tbl[ac].handler,
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&ac_cmd));
|
||||
|
||||
const esp_console_cmd_t rc_cmd = {
|
||||
.command = "rc",
|
||||
.help = hf_cmd_explain[rc],
|
||||
.hint = NULL,
|
||||
.func = hf_cmd_tbl[rc].handler,
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&rc_cmd));
|
||||
|
||||
const esp_console_cmd_t d_cmd = {
|
||||
.command = "d",
|
||||
.help = hf_cmd_explain[d],
|
||||
.hint = "<num>",
|
||||
.func = hf_cmd_tbl[d].handler,
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&d_cmd));
|
||||
|
||||
const esp_console_cmd_t rd_cmd = {
|
||||
.command = "rd",
|
||||
.help = hf_cmd_explain[rd],
|
||||
.hint = NULL,
|
||||
.func = hf_cmd_tbl[rd].handler,
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&rd_cmd));
|
||||
|
||||
const esp_console_cmd_t dm_cmd = {
|
||||
.command = "dm",
|
||||
.help = hf_cmd_explain[dm],
|
||||
.hint = "<index>",
|
||||
.func = hf_cmd_tbl[dm].handler,
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&dm_cmd));
|
||||
|
||||
const esp_console_cmd_t vron_cmd = {
|
||||
.command = "vron",
|
||||
.help = hf_cmd_explain[vron],
|
||||
.hint = NULL,
|
||||
.func = hf_cmd_tbl[vron].handler,
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&vron_cmd));
|
||||
|
||||
const esp_console_cmd_t vroff_cmd = {
|
||||
.command = "vroff",
|
||||
.help = hf_cmd_explain[vroff],
|
||||
.hint = NULL,
|
||||
.func = hf_cmd_tbl[vroff].handler,
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&vroff_cmd));
|
||||
|
||||
vu_args.tgt = arg_str1(NULL, NULL, "<tgt>", "\n 0-speaker\n 1-microphone");
|
||||
vu_args.vol = arg_str1(NULL, NULL, "<vol>", "volume gain ranges from 0 to 15");
|
||||
vu_args.end = arg_end(1);
|
||||
const esp_console_cmd_t vu_cmd = {
|
||||
.command = "vu",
|
||||
.help = hf_cmd_explain[vu],
|
||||
.hint = NULL,
|
||||
.func = hf_cmd_tbl[vu].handler,
|
||||
.argtable = &vu_args
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&vu_cmd));
|
||||
|
||||
const esp_console_cmd_t rs_cmd = {
|
||||
.command = "rs",
|
||||
.help = hf_cmd_explain[rs],
|
||||
.hint = NULL,
|
||||
.func = hf_cmd_tbl[rs].handler,
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&rs_cmd));
|
||||
|
||||
const esp_console_cmd_t rv_cmd = {
|
||||
.command = "rv",
|
||||
.help = hf_cmd_explain[rv],
|
||||
.hint = NULL,
|
||||
.func = hf_cmd_tbl[rv].handler,
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&rv_cmd));
|
||||
|
||||
rh_args.btrh = arg_str1(NULL, NULL, "<btrh>", "\n 0 - put call on hold,\n 1 - accept the held call,\n 2 -reject the held call");
|
||||
rh_args.end = arg_end(1);
|
||||
const esp_console_cmd_t rh_cmd = {
|
||||
.command = "rh",
|
||||
.help = hf_cmd_explain[rh],
|
||||
.hint = NULL,
|
||||
.func = hf_cmd_tbl[rh].handler,
|
||||
.argtable = &rh_args
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&rh_cmd));
|
||||
|
||||
const esp_console_cmd_t k_cmd = {
|
||||
.command = "k",
|
||||
.help = hf_cmd_explain[k],
|
||||
.hint = "<dtmf>",
|
||||
.func = hf_cmd_tbl[k].handler,
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&k_cmd));
|
||||
}
|
||||
|
@ -11,7 +11,7 @@
|
||||
|
||||
#define HF_MSG_ARGS_MAX (5)
|
||||
|
||||
typedef void (* hf_cmd_handler)(int argn, char **argv);
|
||||
typedef int (* hf_cmd_handler)(int argn, char **argv);
|
||||
|
||||
typedef struct {
|
||||
uint16_t opcode;
|
||||
@ -23,4 +23,6 @@ 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);
|
||||
|
||||
void register_hfp_hf(void);
|
||||
#endif /* __APP_HF_MSG_SET_H__*/
|
||||
|
@ -168,11 +168,11 @@ const char *c_inband_ring_state_str[] = {
|
||||
"Provided",
|
||||
};
|
||||
|
||||
// esp_bd_addr_t peer_addr;
|
||||
extern esp_bd_addr_t peer_addr;
|
||||
// If you want to connect a specific device, add it's address here
|
||||
esp_bd_addr_t peer_addr = {0xb4, 0xe6, 0x2d, 0xeb, 0x09, 0x93};
|
||||
// esp_bd_addr_t peer_addr = {0xac, 0x67, 0xb2, 0x53, 0x77, 0xbe};
|
||||
|
||||
#if CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_HCI
|
||||
#if CONFIG_BT_HFP_AUDIO_DATA_PATH_HCI
|
||||
|
||||
#define ESP_HFP_RINGBUF_SIZE 3600
|
||||
static RingbufHandle_t m_rb = NULL;
|
||||
@ -224,7 +224,7 @@ static void bt_app_hf_client_incoming_cb(const uint8_t *buf, uint32_t sz)
|
||||
|
||||
esp_hf_client_outgoing_data_ready();
|
||||
}
|
||||
#endif /* #if CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_HCI */
|
||||
#endif /* #if CONFIG_BT_HFP_AUDIO_DATA_PATH_HCI */
|
||||
|
||||
/* callback for HF_CLIENT */
|
||||
void bt_app_hf_client_cb(esp_hf_client_cb_event_t event, esp_hf_client_cb_param_t *param)
|
||||
@ -250,7 +250,7 @@ void bt_app_hf_client_cb(esp_hf_client_cb_event_t event, esp_hf_client_cb_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 CONFIG_BT_HFP_AUDIO_DATA_PATH_HCI
|
||||
if (param->audio_stat.state == ESP_HF_CLIENT_AUDIO_STATE_CONNECTED ||
|
||||
param->audio_stat.state == ESP_HF_CLIENT_AUDIO_STATE_CONNECTED_MSBC) {
|
||||
esp_hf_client_register_data_callback(bt_app_hf_client_incoming_cb,
|
||||
@ -259,7 +259,7 @@ void bt_app_hf_client_cb(esp_hf_client_cb_event_t event, esp_hf_client_cb_param_
|
||||
} else if (param->audio_stat.state == ESP_HF_CLIENT_AUDIO_STATE_DISCONNECTED) {
|
||||
bt_app_hf_client_audio_close();
|
||||
}
|
||||
#endif /* #if CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_HCI */
|
||||
#endif /* #if CONFIG_BT_HFP_AUDIO_DATA_PATH_HCI */
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1,119 +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[128] = {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;
|
||||
}
|
@ -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__*/
|
@ -24,7 +24,123 @@
|
||||
#include "esp_hf_client_api.h"
|
||||
#include "bt_app_hf.h"
|
||||
#include "gpio_pcm_config.h"
|
||||
#include "console_uart.h"
|
||||
#include "esp_console.h"
|
||||
#include "app_hf_msg_set.h"
|
||||
|
||||
esp_bd_addr_t peer_addr = {0};
|
||||
static char peer_bdname[ESP_BT_GAP_MAX_BDNAME_LEN + 1];
|
||||
static uint8_t peer_bdname_len;
|
||||
|
||||
static const char remote_device_name[] = "ESP_HFP_AG";
|
||||
|
||||
static bool get_name_from_eir(uint8_t *eir, char *bdname, uint8_t *bdname_len)
|
||||
{
|
||||
uint8_t *rmt_bdname = NULL;
|
||||
uint8_t rmt_bdname_len = 0;
|
||||
|
||||
if (!eir) {
|
||||
return false;
|
||||
}
|
||||
|
||||
rmt_bdname = esp_bt_gap_resolve_eir_data(eir, ESP_BT_EIR_TYPE_CMPL_LOCAL_NAME, &rmt_bdname_len);
|
||||
if (!rmt_bdname) {
|
||||
rmt_bdname = esp_bt_gap_resolve_eir_data(eir, ESP_BT_EIR_TYPE_SHORT_LOCAL_NAME, &rmt_bdname_len);
|
||||
}
|
||||
|
||||
if (rmt_bdname) {
|
||||
if (rmt_bdname_len > ESP_BT_GAP_MAX_BDNAME_LEN) {
|
||||
rmt_bdname_len = ESP_BT_GAP_MAX_BDNAME_LEN;
|
||||
}
|
||||
|
||||
if (bdname) {
|
||||
memcpy(bdname, rmt_bdname, rmt_bdname_len);
|
||||
bdname[rmt_bdname_len] = '\0';
|
||||
}
|
||||
if (bdname_len) {
|
||||
*bdname_len = rmt_bdname_len;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void esp_bt_gap_cb(esp_bt_gap_cb_event_t event, esp_bt_gap_cb_param_t *param)
|
||||
{
|
||||
switch (event) {
|
||||
case ESP_BT_GAP_DISC_RES_EVT: {
|
||||
for (int i = 0; i < param->disc_res.num_prop; i++){
|
||||
if (param->disc_res.prop[i].type == ESP_BT_GAP_DEV_PROP_EIR
|
||||
&& get_name_from_eir(param->disc_res.prop[i].val, peer_bdname, &peer_bdname_len)){
|
||||
if (strcmp(peer_bdname, remote_device_name) == 0) {
|
||||
memcpy(peer_addr, param->disc_res.bda, ESP_BD_ADDR_LEN);
|
||||
ESP_LOGI(BT_HF_TAG, "Found a target device address: \n");
|
||||
esp_log_buffer_hex(BT_HF_TAG, peer_addr, ESP_BD_ADDR_LEN);
|
||||
ESP_LOGI(BT_HF_TAG, "Found a target device name: %s", peer_bdname);
|
||||
printf("Connect.\n");
|
||||
esp_hf_client_connect(peer_addr);
|
||||
esp_bt_gap_cancel_discovery();
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ESP_BT_GAP_DISC_STATE_CHANGED_EVT:
|
||||
ESP_LOGI(BT_HF_TAG, "ESP_BT_GAP_DISC_STATE_CHANGED_EVT");
|
||||
case ESP_BT_GAP_RMT_SRVCS_EVT:
|
||||
case ESP_BT_GAP_RMT_SRVC_REC_EVT:
|
||||
break;
|
||||
case ESP_BT_GAP_AUTH_CMPL_EVT: {
|
||||
if (param->auth_cmpl.stat == ESP_BT_STATUS_SUCCESS) {
|
||||
ESP_LOGI(BT_HF_TAG, "authentication success: %s", param->auth_cmpl.device_name);
|
||||
esp_log_buffer_hex(BT_HF_TAG, param->auth_cmpl.bda, ESP_BD_ADDR_LEN);
|
||||
} else {
|
||||
ESP_LOGE(BT_HF_TAG, "authentication failed, status:%d", param->auth_cmpl.stat);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ESP_BT_GAP_PIN_REQ_EVT: {
|
||||
ESP_LOGI(BT_HF_TAG, "ESP_BT_GAP_PIN_REQ_EVT min_16_digit:%d", param->pin_req.min_16_digit);
|
||||
if (param->pin_req.min_16_digit) {
|
||||
ESP_LOGI(BT_HF_TAG, "Input pin code: 0000 0000 0000 0000");
|
||||
esp_bt_pin_code_t pin_code = {0};
|
||||
esp_bt_gap_pin_reply(param->pin_req.bda, true, 16, pin_code);
|
||||
} else {
|
||||
ESP_LOGI(BT_HF_TAG, "Input pin code: 1234");
|
||||
esp_bt_pin_code_t pin_code;
|
||||
pin_code[0] = '1';
|
||||
pin_code[1] = '2';
|
||||
pin_code[2] = '3';
|
||||
pin_code[3] = '4';
|
||||
esp_bt_gap_pin_reply(param->pin_req.bda, true, 4, pin_code);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
#if (CONFIG_BT_SSP_ENABLED == true)
|
||||
case ESP_BT_GAP_CFM_REQ_EVT:
|
||||
ESP_LOGI(BT_HF_TAG, "ESP_BT_GAP_CFM_REQ_EVT Please compare the numeric value: %d", param->cfm_req.num_val);
|
||||
esp_bt_gap_ssp_confirm_reply(param->cfm_req.bda, true);
|
||||
break;
|
||||
case ESP_BT_GAP_KEY_NOTIF_EVT:
|
||||
ESP_LOGI(BT_HF_TAG, "ESP_BT_GAP_KEY_NOTIF_EVT passkey:%d", param->key_notif.passkey);
|
||||
break;
|
||||
case ESP_BT_GAP_KEY_REQ_EVT:
|
||||
ESP_LOGI(BT_HF_TAG, "ESP_BT_GAP_KEY_REQ_EVT Please enter passkey!");
|
||||
break;
|
||||
#endif
|
||||
|
||||
case ESP_BT_GAP_MODE_CHG_EVT:
|
||||
ESP_LOGI(BT_HF_TAG, "ESP_BT_GAP_MODE_CHG_EVT mode:%d", param->mode_chg.mode);
|
||||
break;
|
||||
|
||||
default: {
|
||||
ESP_LOGI(BT_HF_TAG, "event: %d", event);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* event for handler "bt_av_hdl_stack_up */
|
||||
enum {
|
||||
@ -74,16 +190,36 @@ void app_main(void)
|
||||
/* Bluetooth device name, connection mode and profile set up */
|
||||
bt_app_work_dispatch(bt_hf_client_hdl_stack_evt, BT_APP_EVT_STACK_UP, NULL, 0, NULL);
|
||||
|
||||
/* initialize console via UART */
|
||||
console_uart_init();
|
||||
|
||||
#if CONFIG_BT_HFP_AUDIO_DATA_PATH_PCM
|
||||
/* configure the PCM interface and PINs used */
|
||||
app_gpio_pcm_io_cfg();
|
||||
#endif
|
||||
|
||||
/* configure externel chip for acoustic echo cancellation */
|
||||
#if ACOUSTIC_ECHO_CANCELLATION_ENABLE
|
||||
app_gpio_aec_io_cfg();
|
||||
#endif /* ACOUSTIC_ECHO_CANCELLATION_ENABLE */
|
||||
esp_console_repl_t *repl = NULL;
|
||||
esp_console_repl_config_t repl_config = ESP_CONSOLE_REPL_CONFIG_DEFAULT();
|
||||
esp_console_dev_uart_config_t uart_config = ESP_CONSOLE_DEV_UART_CONFIG_DEFAULT();
|
||||
repl_config.prompt = "hfp_hf>";
|
||||
|
||||
// init console REPL environment
|
||||
ESP_ERROR_CHECK(esp_console_new_repl_uart(&uart_config, &repl_config, &repl));
|
||||
|
||||
/* Register commands */
|
||||
register_hfp_hf();
|
||||
printf("\n ==================================================\n");
|
||||
printf(" | Steps to test hfp_hf |\n");
|
||||
printf(" | |\n");
|
||||
printf(" | 1. Print 'help' to gain overview of commands |\n");
|
||||
printf(" | 2. Setup a service level connection |\n");
|
||||
printf(" | 3. Run hfp_hf to test |\n");
|
||||
printf(" | |\n");
|
||||
printf(" =================================================\n\n");
|
||||
|
||||
// start console REPL
|
||||
ESP_ERROR_CHECK(esp_console_start_repl(repl));
|
||||
}
|
||||
|
||||
|
||||
@ -96,6 +232,8 @@ static void bt_hf_client_hdl_stack_evt(uint16_t event, void *p_param)
|
||||
char *dev_name = "ESP_HFP_HF";
|
||||
esp_bt_dev_set_device_name(dev_name);
|
||||
|
||||
/* register GAP callback function */
|
||||
esp_bt_gap_register_callback(esp_bt_gap_cb);
|
||||
esp_hf_client_register_callback(bt_app_hf_client_cb);
|
||||
esp_hf_client_init();
|
||||
|
||||
@ -109,6 +247,10 @@ static void bt_hf_client_hdl_stack_evt(uint16_t event, void *p_param)
|
||||
|
||||
/* set discoverable and connectable mode, wait to be connected */
|
||||
esp_bt_gap_set_scan_mode(ESP_BT_CONNECTABLE, ESP_BT_GENERAL_DISCOVERABLE);
|
||||
|
||||
/* start device discovery */
|
||||
ESP_LOGI(BT_HF_TAG, "Starting device discovery...");
|
||||
esp_bt_gap_start_discovery(ESP_BT_INQ_MODE_GENERAL_INQUIRY, 10, 0);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
Loading…
Reference in New Issue
Block a user