Merge branch 'fix/remove_esp_hf_ag_devices_status_indchage_in_example' into 'master'

fix(bt/bluedroid): Send device status of AG to HF with a different api

Closes BT-3437

See merge request espressif/esp-idf!26350
This commit is contained in:
Wang Meng Yang 2023-10-20 09:45:59 +08:00
commit 5557ef4036
12 changed files with 213 additions and 744 deletions

View File

@ -13,7 +13,7 @@ This example is designed to run on commonly available ESP32 development board, e
### Configure the project
Open the project configuration menu:
Open the project configuration menu:
```bash
idf.py menuconfig
@ -234,15 +234,11 @@ I (245311) BT_APP_HF: --Audio State connected
#### Device Status Indication
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:
You can type `ciev <ind_type> <value>` to send device status of AG to HF Unit. Log on AG prints such as: `Device Indicator Changed!` and on HF Unit side prints such as:
```
E (293641) BT_HF: APP HFP event: CALL_IND_EVT
E (293641) BT_HF: --Call indicator call in progress
E (293641) BT_HF: APP HFP event: CALL_SETUP_IND_EVT
E (293651) BT_HF: --Call setup indicator INCOMING
E (293651) BT_HF: APP HFP event: SIGNAL_STRENGTH_IND_EVT
E (293661) BT_HF: -- signal strength: 5
I (106167) BT_HF: APP HFP event: CALL_SETUP_IND_EVT
I (106167) BT_HF: --Call setup indicator INCOMING
```
**Note: The AG device sends only the changed status to the HF Unit.**
@ -274,7 +270,7 @@ E (19556) BT_HF: --in-band ring state Provided
If you encounter any problems, please check if the following rules are followed:
- You should type the command in the terminal according to the format described in the commands help table.
- You should type the command in the terminal according to the format described in the commands help table.
- Not all commands in the table are supported by the HF Unit.
- If you want to `hf con;` to establish a service level connection with a specific HF Unit, you should add the MAC address of the HF Unit in `app_hf_msg_set.c` for example: `esp_bd_addr_t peer_addr = {0xb4, 0xe6, 0x2d, 0xeb, 0x09, 0x93};`
- Use `esp_hf_client_register_callback()` and `esp_hf_client_init();` before establishing a service level connection.
@ -286,6 +282,5 @@ Due to the complexity of the HFP, this example has more source files than other
- The example will respond to user command through the UART console. Please go to `console_uart.c` for the configuration details.
- For the voice interface, ESP32 has provided PCM input/output signals which can be directed to GPIO pins. So, please go to `gpio_pcm_config.c` for the configuration details.
- If you want to update the command table, please refer to `app_hf_msg_set.c`.
- If you want to update the command parse rules, please refer to `app_hf_msg_prs.c`.
- If you want to update the responses of the AG or want to update the log, please refer to `bt_app_hf.c`.
- The task configuration part is in `bt_app_core.c`.

View File

@ -1,5 +1,4 @@
idf_component_register(SRCS "app_hf_msg_prs.c"
"app_hf_msg_set.c"
idf_component_register(SRCS "app_hf_msg_set.c"
"bt_app_core.c"
"bt_app_hf.c"
"gpio_pcm_config.c"

View File

@ -1,166 +0,0 @@
/*
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
#include <ctype.h>
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <stdlib.h>
#include "app_hf_msg_prs.h"
#include "app_hf_msg_set.h"
// according to the design, message header length shall be no less than 2.
#define HF_MSG_HDR_LEN (3)
const static char hf_msg_hdr[HF_MSG_HDR_LEN] = {'h', 'f', ' '};
// according to the design, message header length shall be no less than 2.
#define HF_MSG_TAIL_LEN (1)
const static char hf_msg_tail[HF_MSG_TAIL_LEN] = {';'};
void hf_msg_parser_reset_state(hf_msg_prs_cb_t *prs)
{
prs->state = HF_MSG_PRS_IDLE;
prs->cnt = 0;
prs->h_idx = 0;
prs->t_idx = 0;
}
void hf_msg_parser_register_callback(hf_msg_prs_cb_t *prs, hf_msg_callback cb)
{
prs->callback = cb;
}
hf_msg_prs_err_t hf_msg_parse(char c, hf_msg_prs_cb_t *prs)
{
hf_msg_prs_err_t err = HF_MSG_PRS_ERR_IN_PROGRESS;
switch (prs->state)
{
case HF_MSG_PRS_IDLE:
{
if (c == hf_msg_hdr[0]) {
prs->state = HF_MSG_PRS_HDR;
prs->buf[0] = c;
prs->cnt = 1;
prs->h_idx = 1;
} else {
err = HF_MSG_PRS_ERR_HDR_UNDETECTED;
}
}
break;
case HF_MSG_PRS_HDR:
{
if (c == hf_msg_hdr[prs->h_idx]) {
prs->buf[prs->cnt++] = c;
if (++(prs->h_idx) == HF_MSG_HDR_LEN) {
prs->state = HF_MSG_PRS_PAYL;
prs->t_idx = 0;
}
} else {
hf_msg_parser_reset_state(prs);
err = HF_MSG_PRS_ERR_HDR_SYNC_FAILED;
}
}
break;
case HF_MSG_PRS_PAYL:
{
prs->buf[prs->cnt++] = c;
if (c == hf_msg_tail[prs->t_idx]) {
if (++(prs->t_idx) == HF_MSG_TAIL_LEN) {
prs->buf[prs->cnt] = '\0';
prs->callback(prs->buf, prs->cnt);
hf_msg_parser_reset_state(prs);
err = HF_MSG_PRS_ERR_OK;
break;
}
} else {
prs->t_idx = 0;
}
if (prs->cnt >= HF_MSG_LEN_MAX) {
hf_msg_parser_reset_state(prs);
err = HF_MSG_PRS_ERR_BUF_OVERFLOW;
}
}
break;
}
return err;
}
void hf_msg_split_args(char *start, char *end, char **argv, int *argn)
{
if (argn == NULL || *argn == 0) {
return;
}
memset(argv, 0, (*argn) * sizeof(void *));
int max_argn = *argn;
*argn = 0;
char *p = start;
for (int i = 0; i < max_argn; ++i) {
while (isspace((int)*p) && p != end) {
++p;
}
if (p == end) {
return;
}
argv[i] = p++;
++(*argn);
while (!isspace((int)*p) && p != end) {
++p;
}
if (p == end) {
return;
} else {
*p = '\0';
++p;
}
}
}
void hf_msg_args_parser(char *buf, int len)
{
char *argv[HF_MSG_ARGS_MAX];
int argn = HF_MSG_ARGS_MAX;
char *start = buf + HF_MSG_HDR_LEN;
// set the command terminitor to '\0'
char *end = buf + len - HF_MSG_TAIL_LEN;
*end = '\0';
hf_msg_split_args(start, end, argv, &argn);
if (argn == 0) {
return;
}
bool cmd_supported = false;
hf_msg_hdl_t *cmd_tbl = hf_get_cmd_tbl();
size_t cmd_tbl_size = hf_get_cmd_tbl_size();
for (int i = 0; i < cmd_tbl_size; ++i) {
hf_msg_hdl_t *hdl = &cmd_tbl[i];
if (strcmp(argv[0], hdl->str) == 0) {
if (hdl->handler) {
hdl->handler(argn, argv);
cmd_supported = true;
break;
}
}
}
if (!cmd_supported) {
printf("unsupported command\n");
hf_msg_show_usage();
}
return;
}

View File

@ -1,45 +0,0 @@
/*
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
#ifndef __APP_HF_MSG_PRS_H__
#define __APP_HF_MSG_PRS_H__
typedef enum {
HF_MSG_PRS_ERR_OK = 0, // a complete message is finished
HF_MSG_PRS_ERR_IN_PROGRESS, // message parsing is in progress
HF_MSG_PRS_ERR_HDR_UNDETECTED, // header not detected
HF_MSG_PRS_ERR_HDR_SYNC_FAILED, // failed to sync header
HF_MSG_PRS_ERR_BUF_OVERFLOW, // exceeds the buffer size: HF_MSG_LEN_MAX
} hf_msg_prs_err_t;
typedef enum {
HF_MSG_PRS_IDLE = 0,
HF_MSG_PRS_HDR,
HF_MSG_PRS_PAYL,
} hf_msg_prs_state_t;
typedef void (*hf_msg_callback)(char *buf, int len);
#define HF_MSG_LEN_MAX (128)
typedef struct {
hf_msg_prs_state_t state;
char buf[HF_MSG_LEN_MAX + 1];
int cnt;
int h_idx;
int t_idx;
hf_msg_callback callback;
} hf_msg_prs_cb_t;
void hf_msg_parser_reset_state(hf_msg_prs_cb_t *prs);
void hf_msg_parser_register_callback(hf_msg_prs_cb_t *prs, hf_msg_callback cb);
hf_msg_prs_err_t hf_msg_parse(char c, hf_msg_prs_cb_t *prs);
void hf_msg_show_usage(void);
#endif /* __APP_HF_MSG_PRS_H__*/

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
@ -16,47 +16,9 @@
// if you want to connect a specific device, add it's bda here
esp_bd_addr_t hf_peer_addr = {0xB0, 0xF1, 0xA3, 0x01, 0x2D,0x2E};
void hf_msg_show_usage(void)
{
printf("########################################################################\n");
printf("HFP AG command usage manual\n");
printf("HFP AG commands begins with \"hf\" and end with \";\"\n");
printf("Supported commands are as follows, arguments are embraced with < and >\n\n");
printf("hf con; -- set up connection with peer device\n");
printf("hf dis; -- disconnection with peer device\n");
printf("hf cona; -- set up audio connection with peer device\n");
printf("hf disa; -- release audio connection with peer device\n");
printf("hf vron; -- start voice recognition\n");
printf("hf vroff; -- stop voice recognition\n");
printf("hf vu <tgt> <vol>; -- volume update\n");
printf(" tgt: 0-speaker, 1-microphone\n");
printf(" vol: volume gain ranges from 0 to 15\n");
printf("hf ind <call> <ntk> <callsetup> <sig>; -- unsolicited indication device status to HF Client\n");
printf(" call: call status [0,1]\n");
printf(" callsetup: call setup status [0,3]\n");
printf(" ntk: network status [0,1]\n");
printf(" sig: signal strength value from 0~5\n");
printf("hf ate <rep> <err>; -- send extended at error code\n");
printf(" rep: response code from 0 to 7\n");
printf(" err: error code from 0 to 32\n");
printf("hf iron; -- in-band ring tone provided\n");
printf("hf iroff; -- in-band ring tone not provided\n");
printf("hf ac; -- Answer Incoming Call from AG\n");
printf("hf rc; -- Reject Incoming Call from AG\n");
printf("hf d <num>; -- Dial Number by AG, e.g. hf d 11223344\n");
printf("hf end; -- End up a call by AG\n");
printf("hf h; -- to see the command for HFP AG\n");
printf("########################################################################\n");
}
#define HF_CMD_HANDLER(cmd) static 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");
@ -125,42 +87,65 @@ HF_CMD_HANDLER(volume_control)
}
//+CIEV
HF_CMD_HANDLER(ind_change)
HF_CMD_HANDLER(ciev_report)
{
if (argn != 5) {
if (argn != 3) {
printf("Insufficient number of arguments");
return 1;
}
int call_state, ntk_state, call_setup_state, signal;
int ind_type, value;
if (sscanf(argv[1], "%d", &call_state) != 1 ||
(call_state != ESP_HF_CALL_STATUS_NO_CALLS &&
call_state != ESP_HF_CALL_STATUS_CALL_IN_PROGRESS)) {
printf("Invalid argument for call state %s\n", argv[1]);
sscanf(argv[1], "%d", &ind_type);
sscanf(argv[2], "%d", &value);
if (ind_type > ESP_HF_IND_TYPE_CALLHELD) {
printf("Invalid argument for status type %s\n", argv[1]);
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)) {
if ((ind_type == ESP_HF_IND_TYPE_CALL) &&
(value != ESP_HF_CALL_STATUS_NO_CALLS &&
value != ESP_HF_CALL_STATUS_CALL_IN_PROGRESS)) {
printf("Invalid argument for callsetup state %s\n", argv[2]);
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 network state %s\n", argv[3]);
if ((ind_type == ESP_HF_IND_TYPE_CALLSETUP) &&
(value < ESP_HF_CALL_SETUP_STATUS_IDLE ||
value > ESP_HF_CALL_SETUP_STATUS_OUTGOING_ALERTING)) {
printf("Invalid argument for call state %s\n", argv[2]);
return 1;
}
if (sscanf(argv[4], "%d", &signal) != 1 ||
(signal < 0 || signal > 5)) {
printf("Invalid argument for signal %s\n", argv[4]);
if ((ind_type == ESP_HF_IND_TYPE_SERVICE) &&
(value != ESP_HF_NETWORK_STATE_NOT_AVAILABLE &&
value != ESP_HF_NETWORK_STATE_AVAILABLE)) {
printf("Invalid argument for network state %s\n", argv[2]);
return 1;
}
if ((ind_type == ESP_HF_IND_TYPE_SIGNAL &&
(value < 0 || value > 5))) {
printf("Invalid argument for signal %s\n", argv[2]);
return 1;
}
if ((ind_type == ESP_HF_IND_TYPE_ROAM &&
(value != ESP_HF_ROAMING_STATUS_INACTIVE &&
value != ESP_HF_ROAMING_STATUS_ACTIVE))) {
printf("Invalid argument for roaming state %s\n", argv[2]);
return 1;
}
if ((ind_type == ESP_HF_IND_TYPE_BATTCHG &&
(value < 0 || value > 5))) {
printf("Invalid argument for battery %s\n", argv[2]);
return 1;
}
if ((ind_type == ESP_HF_IND_TYPE_CALLHELD) &&
(value < ESP_HF_CALL_HELD_STATUS_NONE ||
value > ESP_HF_CALL_HELD_STATUS_HELD)) {
printf("Invalid argument for call held state %s\n", argv[2]);
return 1;
}
printf("Device Indicator Changed!\n");
esp_hf_ag_ciev_report(hf_peer_addr, ESP_HF_IND_TYPE_CALL, call_state);
esp_hf_ag_ciev_report(hf_peer_addr, ESP_HF_IND_TYPE_CALLSETUP, call_setup_state);
esp_hf_ag_ciev_report(hf_peer_addr, ESP_HF_IND_TYPE_SERVICE, ntk_state);
esp_hf_ag_ciev_report(hf_peer_addr, ESP_HF_IND_TYPE_SIGNAL, signal);
esp_hf_ag_ciev_report(hf_peer_addr, ind_type, value);
return 0;
}
@ -234,7 +219,7 @@ HF_CMD_HANDLER(end)
}
//Dial Call from AG
HF_CMD_HANDLER(d)
HF_CMD_HANDLER(dn)
{
if (argn != 2) {
printf("Insufficient number of arguments");
@ -246,64 +231,52 @@ HF_CMD_HANDLER(d)
}
static hf_msg_hdl_t hf_cmd_tbl[] = {
{0, "h", hf_help_handler},
{5, "con", hf_conn_handler},
{10, "dis", hf_disc_handler},
{20, "cona", hf_conn_audio_handler},
{30, "disa", hf_disc_audio_handler},
{40, "vu", hf_volume_control_handler},
{50, "ind", hf_ind_change_handler},
{60, "vron", hf_vra_on_handler},
{70, "vroff", hf_vra_off_handler},
{80, "ate", hf_cme_err_handler},
{90, "iron", hf_ir_on_handler},
{100, "iroff", hf_ir_off_handler},
{110, "ac", hf_ac_handler},
{120, "rc", hf_rc_handler},
{130, "end", hf_end_handler},
{140, "d", hf_d_handler},
{"con", hf_conn_handler},
{"dis", hf_disc_handler},
{"cona", hf_conn_audio_handler},
{"disa", hf_disc_audio_handler},
{"vu", hf_volume_control_handler},
{"ciev", hf_ciev_report_handler},
{"vron", hf_vra_on_handler},
{"vroff", hf_vra_off_handler},
{"ate", hf_cme_err_handler},
{"iron", hf_ir_on_handler},
{"iroff", hf_ir_off_handler},
{"ac", hf_ac_handler},
{"rc", hf_rc_handler},
{"end", hf_end_handler},
{"dn", hf_dn_handler},
};
hf_msg_hdl_t *hf_get_cmd_tbl(void)
{
return hf_cmd_tbl;
}
size_t hf_get_cmd_tbl_size(void)
{
return sizeof(hf_cmd_tbl) / sizeof(hf_msg_hdl_t);
}
#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*/
enum hf_cmd_idx {
HF_CMD_IDX_CON = 0, /*set up connection with peer device*/
HF_CMD_IDX_DIS, /*disconnection with peer device*/
HF_CMD_IDX_CONA, /*set up audio connection with peer device*/
HF_CMD_IDX_DISA, /*release audio connection with peer device*/
HF_CMD_IDX_VU, /*volume update*/
HF_CMD_IDX_CIEV, /*unsolicited indication device status to HF Client*/
HF_CMD_IDX_VRON, /*start voice recognition*/
HF_CMD_IDX_VROFF, /*stop voice recognition*/
HF_CMD_IDX_ATE, /*send extended AT error code*/
HF_CMD_IDX_IRON, /*in-band ring tone provided*/
HF_CMD_IDX_IROFF, /*in-band ring tone not provided*/
HF_CMD_IDX_AC, /*Answer Incoming Call from AG*/
HF_CMD_IDX_RC, /*Reject Incoming Call from AG*/
HF_CMD_IDX_END, /*End up a call by AG*/
HF_CMD_IDX_DN /*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",
"release audio connection with peer device",
"volume update",
"unsolicited indication device status to HF Client",
"start voice recognition",
"stop voice recognition",
"send extended at error code",
"send extended AT error code",
"in-band ring tone provided",
"in-band ring tone not provided",
"Answer Incoming Call from AG",
@ -318,10 +291,8 @@ typedef struct {
} vu_args_t;
typedef struct {
struct arg_str *call;
struct arg_str *ntk;
struct arg_str *callsetup;
struct arg_str *sig;
struct arg_str *ind_type;
struct arg_str *value;
struct arg_end *end;
} ind_args_t;
@ -340,77 +311,73 @@ void register_hfp_ag(void)
const esp_console_cmd_t HF_ORDER(con) = {
.command = "con",
.help = hf_cmd_explain[con],
.help = hf_cmd_explain[HF_CMD_IDX_CON],
.hint = NULL,
.func = hf_cmd_tbl[con].handler,
.func = hf_cmd_tbl[HF_CMD_IDX_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],
.help = hf_cmd_explain[HF_CMD_IDX_DIS],
.hint = NULL,
.func = hf_cmd_tbl[dis].handler,
.func = hf_cmd_tbl[HF_CMD_IDX_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],
.help = hf_cmd_explain[HF_CMD_IDX_CONA],
.hint = NULL,
.func = hf_cmd_tbl[cona].handler,
.func = hf_cmd_tbl[HF_CMD_IDX_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],
.help = hf_cmd_explain[HF_CMD_IDX_DISA],
.hint = NULL,
.func = hf_cmd_tbl[disa].handler,
.func = hf_cmd_tbl[HF_CMD_IDX_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],
.help = hf_cmd_explain[HF_CMD_IDX_AC],
.hint = NULL,
.func = hf_cmd_tbl[ac].handler,
.func = hf_cmd_tbl[HF_CMD_IDX_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],
.help = hf_cmd_explain[HF_CMD_IDX_RC],
.hint = NULL,
.func = hf_cmd_tbl[rc].handler,
.func = hf_cmd_tbl[HF_CMD_IDX_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],
const esp_console_cmd_t HF_ORDER(dn) = {
.command = "dn",
.help = hf_cmd_explain[HF_CMD_IDX_DN],
.hint = "<num>",
.func = hf_cmd_tbl[d].handler,
.func = hf_cmd_tbl[HF_CMD_IDX_DN].handler,
};
ESP_ERROR_CHECK(esp_console_cmd_register(&HF_ORDER(d)));
ESP_ERROR_CHECK(esp_console_cmd_register(&HF_ORDER(dn)));
const esp_console_cmd_t HF_ORDER(vron) = {
.command = "vron",
.help = hf_cmd_explain[vron],
.help = hf_cmd_explain[HF_CMD_IDX_VRON],
.hint = NULL,
.func = hf_cmd_tbl[vron].handler,
.func = hf_cmd_tbl[HF_CMD_IDX_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],
.help = hf_cmd_explain[HF_CMD_IDX_VROFF],
.hint = NULL,
.func = hf_cmd_tbl[vroff].handler,
.func = hf_cmd_tbl[HF_CMD_IDX_VROFF].handler,
};
ESP_ERROR_CHECK(esp_console_cmd_register(&HF_ORDER(vroff)));
@ -419,59 +386,58 @@ void register_hfp_ag(void)
vu_args.end = arg_end(1);
const esp_console_cmd_t HF_ORDER(vu) = {
.command = "vu",
.help = hf_cmd_explain[vu],
.help = hf_cmd_explain[HF_CMD_IDX_VU],
.hint = NULL,
.func = hf_cmd_tbl[vu].handler,
.func = hf_cmd_tbl[HF_CMD_IDX_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],
.help = hf_cmd_explain[HF_CMD_IDX_END],
.hint = NULL,
.func = hf_cmd_tbl[end].handler,
.func = hf_cmd_tbl[HF_CMD_IDX_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],
.help = hf_cmd_explain[HF_CMD_IDX_IRON],
.hint = NULL,
.func = hf_cmd_tbl[iron].handler,
.func = hf_cmd_tbl[HF_CMD_IDX_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],
.help = hf_cmd_explain[HF_CMD_IDX_IROFF],
.hint = NULL,
.func = hf_cmd_tbl[iroff].handler,
.func = hf_cmd_tbl[HF_CMD_IDX_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.ind_type = arg_str1(NULL, NULL, "<ind_type>", "\n 1-call\n 2-callsetup\n 3-serval\n \
4-signal\n 5-roam\n 6-battery\n 7-callheld");
ind_args.value = arg_str1(NULL, NULL, "<value>", "value of indicator type");
ind_args.end = arg_end(1);
const esp_console_cmd_t HF_ORDER(ind) = {
.command = "ind",
.help = hf_cmd_explain[ind],
const esp_console_cmd_t HF_ORDER(ciev) = {
.command = "ciev",
.help = hf_cmd_explain[HF_CMD_IDX_CIEV],
.hint = NULL,
.func = hf_cmd_tbl[ind].handler,
.func = hf_cmd_tbl[HF_CMD_IDX_CIEV].handler,
.argtable = &ind_args
};
ESP_ERROR_CHECK(esp_console_cmd_register(&HF_ORDER(ind)));
ESP_ERROR_CHECK(esp_console_cmd_register(&HF_ORDER(ciev)));
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],
.help = hf_cmd_explain[HF_CMD_IDX_ATE],
.hint = NULL,
.func = hf_cmd_tbl[ate].handler,
.func = hf_cmd_tbl[HF_CMD_IDX_ATE].handler,
.argtable = &ate_args
};
ESP_ERROR_CHECK(esp_console_cmd_register(&HF_ORDER(ate)));

View File

@ -12,15 +12,9 @@
typedef int (* hf_cmd_handler)(int argn, char **argv);
typedef struct {
uint16_t opcode;
const char *str;
hf_cmd_handler handler;
} hf_msg_hdl_t;
extern hf_msg_hdl_t *hf_get_cmd_tbl(void);
extern size_t hf_get_cmd_tbl_size(void);
void hf_msg_show_usage(void);
void register_hfp_ag(void);
#endif /* __APP_HF_MSG_SET_H__*/

View File

@ -15,7 +15,7 @@ This example is designed to run on commonly available ESP32 development board, e
### Configure the project
Open the project configuration menu:
Open the project configuration menu:
```bash
idf.py menuconfig
@ -332,6 +332,5 @@ Due to the complexity of HFP, this example has more source files than other blue
- The example will respond to user command through UART console. Please go to `console_uart.c` for the configuration details.
- For voice interface, ESP32 has provided PCM input/output signals which can be mapped to GPIO pins. So, please go to `gpio_pcm_config.c` for the configuration details.
- If you want to update the command table, please refer to `app_hf_msg_set.c`.
- If you want to update the command parse rules, please refer to `app_hf_msg_prs.c`.
- If you want to update the responses of HF Unit or want to update the log, please refer to `bt_app_hf.c`.
- Task configuration part is in `bt_app_core.c`.

View File

@ -1,5 +1,4 @@
idf_component_register(SRCS "app_hf_msg_prs.c"
"app_hf_msg_set.c"
idf_component_register(SRCS "app_hf_msg_set.c"
"bt_app_core.c"
"bt_app_hf.c"
"gpio_pcm_config.c"

View File

@ -1,165 +0,0 @@
/*
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
#include <ctype.h>
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <stdlib.h>
#include "app_hf_msg_prs.h"
#include "app_hf_msg_set.h"
// according to the design, message header length shall be no less than 2.
#define HF_MSG_HDR_LEN (3)
const static char hf_msg_hdr[HF_MSG_HDR_LEN] = {'h', 'f', ' '};
// according to the design, message header length shall be no less than 2.
#define HF_MSG_TAIL_LEN (1)
const static char hf_msg_tail[HF_MSG_TAIL_LEN] = {';'};
void hf_msg_parser_reset_state(hf_msg_prs_cb_t *prs)
{
prs->state = HF_MSG_PRS_IDLE;
prs->cnt = 0;
prs->h_idx = 0;
prs->t_idx = 0;
}
void hf_msg_parser_register_callback(hf_msg_prs_cb_t *prs, hf_msg_callback cb)
{
prs->callback = cb;
}
hf_msg_prs_err_t hf_msg_parse(char c, hf_msg_prs_cb_t *prs)
{
hf_msg_prs_err_t err = HF_MSG_PRS_ERR_IN_PROGRESS;
switch (prs->state) {
case HF_MSG_PRS_IDLE:
{
if (c == hf_msg_hdr[0]) {
prs->state = HF_MSG_PRS_HDR;
prs->buf[0] = c;
prs->cnt = 1;
prs->h_idx = 1;
} else {
err = HF_MSG_PRS_ERR_HDR_UNDETECTED;
}
break;
}
case HF_MSG_PRS_HDR:
{
if (c == hf_msg_hdr[prs->h_idx]) {
prs->buf[prs->cnt++] = c;
if (++(prs->h_idx) == HF_MSG_HDR_LEN) {
prs->state = HF_MSG_PRS_PAYL;
prs->t_idx = 0;
}
} else {
hf_msg_parser_reset_state(prs);
err = HF_MSG_PRS_ERR_HDR_SYNC_FAILED;
}
break;
}
case HF_MSG_PRS_PAYL:
{
prs->buf[prs->cnt++] = c;
if (c == hf_msg_tail[prs->t_idx]) {
if (++(prs->t_idx) == HF_MSG_TAIL_LEN) {
prs->buf[prs->cnt] = '\0';
prs->callback(prs->buf, prs->cnt);
hf_msg_parser_reset_state(prs);
err = HF_MSG_PRS_ERR_OK;
break;
}
} else {
prs->t_idx = 0;
}
if (prs->cnt >= HF_MSG_LEN_MAX) {
hf_msg_parser_reset_state(prs);
err = HF_MSG_PRS_ERR_BUF_OVERFLOW;
}
break;
}
}
return err;
}
void hf_msg_split_args(char *start, char *end, char **argv, int *argn)
{
if (argn == NULL || *argn == 0) {
return;
}
memset(argv, 0, (*argn) * sizeof(void *));
int max_argn = *argn;
*argn = 0;
char *p = start;
for (int i = 0; i < max_argn; ++i) {
while (isspace((int)*p) && p != end) {
++p;
}
if (p == end) {
return;
}
argv[i] = p++;
++(*argn);
while (!isspace((int)*p) && p != end) {
++p;
}
if (p == end) {
return;
} else {
*p = '\0';
++p;
}
}
}
void hf_msg_args_parser(char *buf, int len)
{
char *argv[HF_MSG_ARGS_MAX];
int argn = HF_MSG_ARGS_MAX;
char *start = buf + HF_MSG_HDR_LEN;
// set the command terminator to '\0'
char *end = buf + len - HF_MSG_TAIL_LEN;
*end = '\0';
hf_msg_split_args(start, end, argv, &argn);
if (argn == 0) {
return;
}
bool cmd_supported = false;
hf_msg_hdl_t *cmd_tbl = hf_get_cmd_tbl();
size_t cmd_tbl_size = hf_get_cmd_tbl_size();
for (int i = 0; i < cmd_tbl_size; ++i) {
hf_msg_hdl_t *hdl = &cmd_tbl[i];
if (strcmp(argv[0], hdl->str) == 0) {
if (hdl->handler) {
hdl->handler(argn, argv);
cmd_supported = true;
break;
}
}
}
if (!cmd_supported) {
printf("unsupported command\n");
hf_msg_show_usage();
}
return;
}

View File

@ -1,45 +0,0 @@
/*
* SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
#ifndef __APP_HF_MSG_PRS_H__
#define __APP_HF_MSG_PRS_H__
typedef enum {
HF_MSG_PRS_ERR_OK = 0, // a complete message is finished
HF_MSG_PRS_ERR_IN_PROGRESS, // message parsing is in progress
HF_MSG_PRS_ERR_HDR_UNDETECTED, // header not detected
HF_MSG_PRS_ERR_HDR_SYNC_FAILED, // failed to sync header
HF_MSG_PRS_ERR_BUF_OVERFLOW, // exceeds the buffer size: HF_MSG_LEN_MAX
} hf_msg_prs_err_t;
typedef enum {
HF_MSG_PRS_IDLE = 0,
HF_MSG_PRS_HDR,
HF_MSG_PRS_PAYL,
} hf_msg_prs_state_t;
typedef void (*hf_msg_callback)(char *buf, int len);
#define HF_MSG_LEN_MAX (128)
typedef struct {
hf_msg_prs_state_t state;
char buf[HF_MSG_LEN_MAX + 1];
int cnt;
int h_idx;
int t_idx;
hf_msg_callback callback;
} hf_msg_prs_cb_t;
void hf_msg_parser_reset_state(hf_msg_prs_cb_t *prs);
void hf_msg_parser_register_callback(hf_msg_prs_cb_t *prs, hf_msg_callback cb);
hf_msg_prs_err_t hf_msg_parse(char c, hf_msg_prs_cb_t *prs);
void hf_msg_show_usage(void);
#endif /* __APP_HF_MSG_PRS_H__*/

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
@ -35,52 +35,8 @@ static vu_args_t vu_args;
static rh_args_t rh_args;
static bat_args_t bat_args;
void hf_msg_show_usage(void)
{
printf("########################################################################\n");
printf("HF client command usage manual\n");
printf("HF client commands begin with \"hf\" and end with \";\"\n");
printf("Supported commands are as follows, arguments are embraced with < and >\n");
printf("hf con; -- setup connection with peer device\n");
printf("hf dis; -- release connection with peer device\n");
printf("hf cona; -- setup audio connection with peer device\n");
printf("hf disa; -- release connection with peer device\n");
printf("hf qop; -- query current operator name\n");
printf("hf qc; -- query current call status\n");
printf("hf ac; -- answer incoming call\n");
printf("hf rc; -- reject incoming call\n");
printf("hf d <num>; -- dial <num>, e.g. hf d 11223344\n");
printf("hf rd; -- redial\n");
printf("hf dm <index>; -- dial memory\n");
printf("hf vron; -- start voice recognition\n");
printf("hf vroff; -- stop voice recognition\n");
printf("hf vu <tgt> <vol>; -- volume update\n");
printf(" tgt: 0-speaker, 1-microphone\n");
printf(" vol: volume gain ranges from 0 to 15\n");
printf("hf rs; -- retrieve subscriber information\n");
printf("hf rv; -- retrieve last voice tag number\n");
printf("hf rh <btrh>; -- response and hold\n");
printf(" btrh:\n");
printf(" 0 - put call on hold,\n");
printf(" 1 - accept the held call,\n");
printf(" 2 -reject the held call\n");
printf("hf k <dtmf>; -- send dtmf code.\n");
printf(" dtmf: single character in set 0-9, *, #, A-D\n");
printf("hf xp; -- Enable Vendor specific feature for battery status\n");
printf("hf bat; -- Send battery status\n");
printf("hf h; -- show command manual\n");
printf("########################################################################\n");
}
#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");
@ -307,69 +263,57 @@ HF_CMD_HANDLER(iphoneaccev)
static hf_msg_hdl_t hf_cmd_tbl[] = {
{0, "h", hf_help_handler},
{5, "con", hf_conn_handler},
{10, "dis", hf_disc_handler},
{20, "cona", hf_conn_audio_handler},
{30, "disa", hf_disc_audio_handler},
{40, "qop", hf_query_op_handler},
{120, "qc", hf_query_call_handler},
{50, "ac", hf_answer_handler},
{60, "rc", hf_reject_handler},
{70, "d", hf_dial_handler},
{80, "rd", hf_redial_handler},
{85, "dm", hf_dial_mem_handler},
{90, "vron", hf_start_vr_handler},
{100, "vroff", hf_stop_vr_handler},
{110, "vu", hf_volume_update_handler},
{130, "rs", hf_retrieve_subscriber_handler},
{140, "rv", hf_request_last_voice_tag_handler},
{150, "rh", hf_btrh_handler},
{160, "k", hf_dtmf_handler},
{170, "xp", hf_xapl_handler},
{180, "bat", hf_iphoneaccev_handler},
{"con", hf_conn_handler},
{"dis", hf_disc_handler},
{"cona", hf_conn_audio_handler},
{"disa", hf_disc_audio_handler},
{"qop", hf_query_op_handler},
{"qc", hf_query_call_handler},
{"ac", hf_answer_handler},
{"rc", hf_reject_handler},
{"d", hf_dial_handler},
{"rd", hf_redial_handler},
{"dm", hf_dial_mem_handler},
{"vron", hf_start_vr_handler},
{"vroff", hf_stop_vr_handler},
{"vu", hf_volume_update_handler},
{"rs", hf_retrieve_subscriber_handler},
{"rv", hf_request_last_voice_tag_handler},
{"rh", hf_btrh_handler},
{"k", hf_dtmf_handler},
{"xp", hf_xapl_handler},
{"bat", hf_iphoneaccev_handler},
};
hf_msg_hdl_t *hf_get_cmd_tbl(void)
{
return hf_cmd_tbl;
}
size_t hf_get_cmd_tbl_size(void)
{
return sizeof(hf_cmd_tbl) / sizeof(hf_msg_hdl_t);
}
#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*/
xp, /*send XAPL feature enable command to indicate battery level*/
bat, /*send battery level and docker status*/
enum hf_cmd_idx {
HF_CMD_IDX_CON = 0, /*set up connection with peer device*/
HF_CMD_IDX_DIS, /*disconnection with peer device*/
HF_CMD_IDX_CONA, /*set up audio connection with peer device*/
HF_CMD_IDX_DISA, /*release audio connection with peer device*/
HF_CMD_IDX_QOP, /*query current operator name*/
HF_CMD_IDX_QC, /*query current call status*/
HF_CMD_IDX_AC, /*answer incoming call*/
HF_CMD_IDX_RC, /*reject incoming call*/
HF_CMD_IDX_D, /*dial <num>, e.g. d 11223344*/
HF_CMD_IDX_RD, /*redial*/
HF_CMD_IDX_DM, /*dial memory*/
HF_CMD_IDX_VRON, /*start voice recognition*/
HF_CMD_IDX_VROFF, /*stop voice recognition*/
HF_CMD_IDX_VU, /*volume update*/
HF_CMD_IDX_RS, /*retrieve subscriber information*/
HF_CMD_IDX_RV, /*retrieve last voice tag number*/
HF_CMD_IDX_RH, /*response and hold*/
HF_CMD_IDX_K, /*send dtmf code*/
HF_CMD_IDX_XP, /*send XAPL feature enable command to indicate battery level*/
HF_CMD_IDX_BAT, /*send battery level and docker status*/
};
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",
"release audio connection with peer device",
"query current operator name",
"query current call status",
"answer incoming call",
@ -385,7 +329,7 @@ static char *hf_cmd_explain[] = {
"response and hold",
"send dtmf code.\n <dtmf> single character in set 0-9, *, #, A-D",
"send XAPL feature enable command to indicate battery level",
"send battery level and docker status.",
"send battery level and docker status",
};
void register_hfp_hf(void)
@ -393,105 +337,105 @@ void register_hfp_hf(void)
const esp_console_cmd_t con_cmd = {
.command = "con",
.help = hf_cmd_explain[con],
.help = hf_cmd_explain[HF_CMD_IDX_CON],
.hint = NULL,
.func = hf_cmd_tbl[con].handler,
.func = hf_cmd_tbl[HF_CMD_IDX_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],
.help = hf_cmd_explain[HF_CMD_IDX_DIS],
.hint = NULL,
.func = hf_cmd_tbl[dis].handler,
.func = hf_cmd_tbl[HF_CMD_IDX_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],
.help = hf_cmd_explain[HF_CMD_IDX_CONA],
.hint = NULL,
.func = hf_cmd_tbl[cona].handler,
.func = hf_cmd_tbl[HF_CMD_IDX_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],
.help = hf_cmd_explain[HF_CMD_IDX_DISA],
.hint = NULL,
.func = hf_cmd_tbl[disa].handler,
.func = hf_cmd_tbl[HF_CMD_IDX_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],
.help = hf_cmd_explain[HF_CMD_IDX_QOP],
.hint = NULL,
.func = hf_cmd_tbl[qop].handler,
.func = hf_cmd_tbl[HF_CMD_IDX_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],
.help = hf_cmd_explain[HF_CMD_IDX_QC],
.hint = NULL,
.func = hf_cmd_tbl[qc].handler,
.func = hf_cmd_tbl[HF_CMD_IDX_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],
.help = hf_cmd_explain[HF_CMD_IDX_AC],
.hint = NULL,
.func = hf_cmd_tbl[ac].handler,
.func = hf_cmd_tbl[HF_CMD_IDX_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],
.help = hf_cmd_explain[HF_CMD_IDX_RC],
.hint = NULL,
.func = hf_cmd_tbl[rc].handler,
.func = hf_cmd_tbl[HF_CMD_IDX_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],
.help = hf_cmd_explain[HF_CMD_IDX_D],
.hint = "<num>",
.func = hf_cmd_tbl[d].handler,
.func = hf_cmd_tbl[HF_CMD_IDX_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],
.help = hf_cmd_explain[HF_CMD_IDX_RD],
.hint = NULL,
.func = hf_cmd_tbl[rd].handler,
.func = hf_cmd_tbl[HF_CMD_IDX_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],
.help = hf_cmd_explain[HF_CMD_IDX_DM],
.hint = "<index>",
.func = hf_cmd_tbl[dm].handler,
.func = hf_cmd_tbl[HF_CMD_IDX_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],
.help = hf_cmd_explain[HF_CMD_IDX_VRON],
.hint = NULL,
.func = hf_cmd_tbl[vron].handler,
.func = hf_cmd_tbl[HF_CMD_IDX_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],
.help = hf_cmd_explain[HF_CMD_IDX_VROFF],
.hint = NULL,
.func = hf_cmd_tbl[vroff].handler,
.func = hf_cmd_tbl[HF_CMD_IDX_VROFF].handler,
};
ESP_ERROR_CHECK(esp_console_cmd_register(&vroff_cmd));
@ -500,26 +444,26 @@ void register_hfp_hf(void)
vu_args.end = arg_end(1);
const esp_console_cmd_t vu_cmd = {
.command = "vu",
.help = hf_cmd_explain[vu],
.help = hf_cmd_explain[HF_CMD_IDX_VU],
.hint = NULL,
.func = hf_cmd_tbl[vu].handler,
.func = hf_cmd_tbl[HF_CMD_IDX_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],
.help = hf_cmd_explain[HF_CMD_IDX_RS],
.hint = NULL,
.func = hf_cmd_tbl[rs].handler,
.func = hf_cmd_tbl[HF_CMD_IDX_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],
.help = hf_cmd_explain[HF_CMD_IDX_RV],
.hint = NULL,
.func = hf_cmd_tbl[rv].handler,
.func = hf_cmd_tbl[HF_CMD_IDX_RV].handler,
};
ESP_ERROR_CHECK(esp_console_cmd_register(&rv_cmd));
@ -527,26 +471,26 @@ void register_hfp_hf(void)
rh_args.end = arg_end(1);
const esp_console_cmd_t rh_cmd = {
.command = "rh",
.help = hf_cmd_explain[rh],
.help = hf_cmd_explain[HF_CMD_IDX_RH],
.hint = NULL,
.func = hf_cmd_tbl[rh].handler,
.func = hf_cmd_tbl[HF_CMD_IDX_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],
.help = hf_cmd_explain[HF_CMD_IDX_K],
.hint = "<dtmf>",
.func = hf_cmd_tbl[k].handler,
.func = hf_cmd_tbl[HF_CMD_IDX_K].handler,
};
ESP_ERROR_CHECK(esp_console_cmd_register(&k_cmd));
const esp_console_cmd_t xp_cmd = {
.command = "xp",
.help = hf_cmd_explain[xp],
.help = hf_cmd_explain[HF_CMD_IDX_XP],
.hint = NULL,
.func = hf_cmd_tbl[xp].handler,
.func = hf_cmd_tbl[HF_CMD_IDX_XP].handler,
};
ESP_ERROR_CHECK(esp_console_cmd_register(&xp_cmd));
@ -555,9 +499,9 @@ void register_hfp_hf(void)
bat_args.end = arg_end(1);
const esp_console_cmd_t bat_cmd = {
.command = "bat",
.help = hf_cmd_explain[bat],
.help = hf_cmd_explain[HF_CMD_IDX_BAT],
.hint = "<bat_level> <docked>",
.func = hf_cmd_tbl[bat].handler,
.func = hf_cmd_tbl[HF_CMD_IDX_BAT].handler,
.argtable = &bat_args,
};
ESP_ERROR_CHECK(esp_console_cmd_register(&bat_cmd));

View File

@ -12,15 +12,9 @@
typedef int (* hf_cmd_handler)(int argn, char **argv);
typedef struct {
uint16_t opcode;
const char *str;
hf_cmd_handler handler;
} hf_msg_hdl_t;
extern hf_msg_hdl_t *hf_get_cmd_tbl(void);
extern size_t hf_get_cmd_tbl_size(void);
void hf_msg_show_usage(void);
void register_hfp_hf(void);
#endif /* __APP_HF_MSG_SET_H__*/