mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Merge branch 'fix/remove_esp_hf_ag_devices_status_indchage_in_example_v5.1' into 'release/v5.1'
fix(bt/bluedroid): Send device status of AG to HF with a different api (backport v5.1) See merge request espressif/esp-idf!26587
This commit is contained in:
commit
894cf042f9
@ -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`.
|
@ -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"
|
||||
|
@ -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;
|
||||
}
|
@ -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__*/
|
@ -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)));
|
||||
|
@ -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__*/
|
||||
|
@ -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`.
|
@ -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"
|
||||
|
@ -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;
|
||||
}
|
@ -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__*/
|
@ -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));
|
||||
|
@ -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__*/
|
||||
|
Loading…
Reference in New Issue
Block a user