modify console by using console REPL environment

This commit is contained in:
liaowenhao 2020-08-20 15:31:45 +08:00 committed by bot
parent fee77509a9
commit 7e10572e8b
15 changed files with 596 additions and 429 deletions

View File

@ -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

View File

@ -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 ".")

View File

@ -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 = {0xac, 0x67, 0xb2, 0x53, 0x79, 0xda};
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)));
}

View File

@ -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__*/

View File

@ -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;
}

View File

@ -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__*/

View File

@ -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,9 +109,6 @@ 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();
/* configure the PCM interface and PINs used */
app_gpio_pcm_io_cfg();
@ -118,4 +116,26 @@ void app_main(void)
#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));
}

View File

@ -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

View File

@ -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 ".")

View File

@ -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));
}

View File

@ -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__*/

View File

@ -170,7 +170,7 @@ const char *c_inband_ring_state_str[] = {
// 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

View File

@ -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;
}

View File

@ -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__*/

View File

@ -24,7 +24,8 @@
#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"
/* event for handler "bt_av_hdl_stack_up */
enum {
@ -74,9 +75,6 @@ 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();
/* configure the PCM interface and PINs used */
app_gpio_pcm_io_cfg();
@ -84,6 +82,27 @@ void app_main(void)
#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));
}