1 /*
2 This example code is in the Public Domain (or CC0 licensed, at your option.)
3
4 Unless required by applicable law or agreed to in writing, this
5 software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
6 CONDITIONS OF ANY KIND, either express or implied.
7 */
8
9 #include <stdio.h>
10 #include <string.h>
11 #include "esp_hf_ag_api.h"
12 #include "app_hf_msg_set.h"
13 #include "bt_app_hf.h"
14 #include "esp_console.h"
15 #include "argtable3/argtable3.h"
16 #include "esp_log.h"
17
18 // if you want to connect a specific device, add it's bda here
19 esp_bd_addr_t hf_peer_addr = {0xB0, 0xF1, 0xA3, 0x01, 0x2D,0x2E};
hf_msg_show_usage(void)20 void hf_msg_show_usage(void)
21 {
22 printf("########################################################################\n");
23 printf("HFP AG command usage manual\n");
24 printf("HFP AG commands begins with \"hf\" and end with \";\"\n");
25 printf("Supported commands are as follows, arguments are embraced with < and >\n\n");
26 printf("hf con; -- set up connection with peer device\n");
27 printf("hf dis; -- disconnection with peer device\n");
28 printf("hf cona; -- set up audio connection with peer device\n");
29 printf("hf disa; -- release audio connection with peer device\n");
30 printf("hf vron; -- start voice recognition\n");
31 printf("hf vroff; -- stop voice recognition\n");
32 printf("hf vu <tgt> <vol>; -- volume update\n");
33 printf(" tgt: 0-speaker, 1-microphone\n");
34 printf(" vol: volume gain ranges from 0 to 15\n");
35 printf("hf ind <call> <ntk> <callsetup> <sig>; -- unsolicited indication device status to HF Client\n");
36 printf(" call: call status [0,1]\n");
37 printf(" callsetup: call setup status [0,3]\n");
38 printf(" ntk: network status [0,1]\n");
39 printf(" sig: signal strength value from 0~5\n");
40 printf("hf ate <rep> <err>; -- send extended at error code\n");
41 printf(" rep: response code from 0 to 7\n");
42 printf(" err: error code from 0 to 32\n");
43 printf("hf iron; -- in-band ring tone provided\n");
44 printf("hf iroff; -- in-band ring tone not provided\n");
45 printf("hf ac; -- Answer Incoming Call from AG\n");
46 printf("hf rc; -- Reject Incoming Call from AG\n");
47 printf("hf d <num>; -- Dial Number by AG, e.g. hf d 11223344\n");
48 printf("hf end; -- End up a call by AG\n");
49 printf("hf h; -- to see the command for HFP AG\n");
50 printf("########################################################################\n");
51 }
52
53 #define HF_CMD_HANDLER(cmd) static int hf_##cmd##_handler(int argn, char **argv)
54
HF_CMD_HANDLER(help)55 HF_CMD_HANDLER(help)
56 {
57 hf_msg_show_usage();
58 return 0;
59 }
60
HF_CMD_HANDLER(conn)61 HF_CMD_HANDLER(conn)
62 {
63 printf("Connect.\n");
64 esp_bt_hf_connect(hf_peer_addr);
65 return 0;
66 }
67
HF_CMD_HANDLER(disc)68 HF_CMD_HANDLER(disc)
69 {
70 printf("Disconnect\n");
71 esp_bt_hf_disconnect(hf_peer_addr);
72 return 0;
73 }
74
HF_CMD_HANDLER(conn_audio)75 HF_CMD_HANDLER(conn_audio)
76 {
77 printf("Connect Audio\n");
78 esp_bt_hf_connect_audio(hf_peer_addr);
79 return 0;
80 }
81
HF_CMD_HANDLER(disc_audio)82 HF_CMD_HANDLER(disc_audio)
83 {
84 printf("Disconnect Audio\n");
85 esp_bt_hf_disconnect_audio(hf_peer_addr);
86 return 0;
87 }
88
89 //AT+BVRA
HF_CMD_HANDLER(vra_on)90 HF_CMD_HANDLER(vra_on)
91 {
92 printf("Start Voice Recognition.\n");
93 esp_bt_hf_vra(hf_peer_addr,1);
94 return 0;
95 }
96 //AT+BVRA
HF_CMD_HANDLER(vra_off)97 HF_CMD_HANDLER(vra_off)
98 {
99 printf("Stop Voicer Recognition.\n");
100 esp_bt_hf_vra(hf_peer_addr,0);
101 return 0;
102 }
103
104 //AT+VGS or AT+VGM
HF_CMD_HANDLER(volume_control)105 HF_CMD_HANDLER(volume_control)
106 {
107 if (argn != 3) {
108 printf("Insufficient number of arguments");
109 return 1;
110 }
111 int target, volume;
112 if (sscanf(argv[1], "%d", &target) != 1 ||
113 (target != ESP_HF_VOLUME_CONTROL_TARGET_SPK &&
114 target != ESP_HF_VOLUME_CONTROL_TARGET_MIC)) {
115 printf("Invalid argument for target %s\n", argv[1]);
116 return 1;
117 }
118 if (sscanf(argv[2], "%d", &volume) != 1 ||
119 (volume < 0 || volume > 15)) {
120 printf("Invalid argument for volume %s\n", argv[2]);
121 return 1;
122 }
123 printf("Volume Update\n");
124 esp_bt_hf_volume_control(hf_peer_addr, target, volume);
125 return 0;
126 }
127
128 //+CIEV
HF_CMD_HANDLER(ind_change)129 HF_CMD_HANDLER(ind_change)
130 {
131 if (argn != 5) {
132 printf("Insufficient number of arguments");
133 return 1;
134 }
135
136 int call_state, ntk_state, call_setup_state, signal;
137
138 if (sscanf(argv[1], "%d", &call_state) != 1 ||
139 (call_state != ESP_HF_CALL_STATUS_NO_CALLS &&
140 call_state != ESP_HF_CALL_STATUS_CALL_IN_PROGRESS)) {
141 printf("Invalid argument for call state %s\n", argv[1]);
142 return 1;
143 }
144 if (sscanf(argv[2], "%d", &call_setup_state) != 1 ||
145 (call_setup_state < ESP_HF_CALL_SETUP_STATUS_IDLE || call_setup_state > ESP_HF_CALL_SETUP_STATUS_OUTGOING_ALERTING)) {
146 printf("Invalid argument for callsetup state %s\n", argv[2]);
147 return 1;
148 }
149 if (sscanf(argv[3], "%d", &ntk_state) != 1 ||
150 (ntk_state != ESP_HF_NETWORK_STATE_NOT_AVAILABLE &&
151 ntk_state != ESP_HF_NETWORK_STATE_AVAILABLE)) {
152 printf("Invalid argument for netwrok state %s\n", argv[3]);
153 return 1;
154 }
155 if (sscanf(argv[4], "%d", &signal) != 1 ||
156 (signal < 0 || signal > 5)) {
157 printf("Invalid argument for signal %s\n", argv[4]);
158 return 1;
159 }
160 printf("Device Indicator Changed!\n");
161 esp_bt_hf_indchange_notification(hf_peer_addr, call_state, call_setup_state, ntk_state, signal);
162 return 0;
163 }
164
165 //AT+CMEE
HF_CMD_HANDLER(cme_err)166 HF_CMD_HANDLER(cme_err)
167 {
168 if (argn != 3) {
169 printf("Insufficient number of arguments");
170 return 1;
171 }
172
173 int response_code, error_code;
174 if (sscanf(argv[1], "%d", &response_code) != 1 ||
175 (response_code < ESP_HF_AT_RESPONSE_CODE_OK && response_code > ESP_HF_AT_RESPONSE_CODE_CME)) {
176 printf("Invalid argument for response_code %s\n", argv[1]);
177 return 1;
178 }
179
180 if (sscanf(argv[2], "%d", &error_code) != 1 ||
181 (error_code < ESP_HF_CME_AG_FAILURE || error_code > ESP_HF_CME_NETWORK_NOT_ALLOWED)) {
182 printf("Invalid argument for volume %s\n", argv[2]);
183 return 1;
184 }
185
186 printf("Send CME Error.\n");
187 esp_bt_hf_cmee_response(hf_peer_addr,response_code,error_code);
188 return 0;
189 }
190
191 //+BSIR:1
HF_CMD_HANDLER(ir_on)192 HF_CMD_HANDLER(ir_on)
193 {
194 printf("Enable Voicer Recognition.\n");
195 esp_bt_hf_bsir(hf_peer_addr,1);
196 return 0;
197 }
198
199 //+BSIR:0
HF_CMD_HANDLER(ir_off)200 HF_CMD_HANDLER(ir_off)
201 {
202 printf("Disable Voicer Recognition.\n");
203 esp_bt_hf_bsir(hf_peer_addr,0);
204 return 0;
205 }
206
207 //Answer Call from AG
HF_CMD_HANDLER(ac)208 HF_CMD_HANDLER(ac)
209 {
210 printf("Answer Call from AG.\n");
211 char *number = {"123456"};
212 esp_bt_hf_answer_call(hf_peer_addr,1,0,1,1,number,0);
213 return 0;
214 }
215
216 //Reject Call from AG
HF_CMD_HANDLER(rc)217 HF_CMD_HANDLER(rc)
218 {
219 printf("Reject Call from AG.\n");
220 char *number = {"123456"};
221 esp_bt_hf_reject_call(hf_peer_addr,0,0,0,0,number,0);
222 return 0;
223 }
224
225 //End Call from AG
HF_CMD_HANDLER(end)226 HF_CMD_HANDLER(end)
227 {
228 printf("End Call from AG.\n");
229 char *number = {"123456"};
230 esp_bt_hf_end_call(hf_peer_addr,0,0,0,0,number,0);
231 return 0;
232 }
233
234 //Dial Call from AG
HF_CMD_HANDLER(d)235 HF_CMD_HANDLER(d)
236 {
237 if (argn != 2) {
238 printf("Insufficient number of arguments");
239 } else {
240 printf("Dial number %s\n", argv[1]);
241 esp_bt_hf_out_call(hf_peer_addr,1,0,1,2,argv[1],0);
242 }
243 return 0;
244 }
245
246 static hf_msg_hdl_t hf_cmd_tbl[] = {
247 {0, "h", hf_help_handler},
248 {5, "con", hf_conn_handler},
249 {10, "dis", hf_disc_handler},
250 {20, "cona", hf_conn_audio_handler},
251 {30, "disa", hf_disc_audio_handler},
252 {40, "vu", hf_volume_control_handler},
253 {50, "ind", hf_ind_change_handler},
254 {60, "vron", hf_vra_on_handler},
255 {70, "vroff", hf_vra_off_handler},
256 {80, "ate", hf_cme_err_handler},
257 {90, "iron", hf_ir_on_handler},
258 {100, "iroff", hf_ir_off_handler},
259 {110, "ac", hf_ac_handler},
260 {120, "rc", hf_rc_handler},
261 {130, "end", hf_end_handler},
262 {140, "d", hf_d_handler},
263 };
264
hf_get_cmd_tbl(void)265 hf_msg_hdl_t *hf_get_cmd_tbl(void)
266 {
267 return hf_cmd_tbl;
268 }
269
hf_get_cmd_tbl_size(void)270 size_t hf_get_cmd_tbl_size(void)
271 {
272 return sizeof(hf_cmd_tbl) / sizeof(hf_msg_hdl_t);
273 }
274
275 #define HF_ORDER(name) name##_cmd
276 enum hf_cmd_name {
277 h = 0, /*show command manual*/
278 con, /*set up connection with peer device*/
279 dis, /*disconnection with peer device*/
280 cona, /*set up audio connection with peer device*/
281 disa, /*release connection with peer device*/
282 vu, /*volume update*/
283 ind, /*unsolicited indication device status to HF Client*/
284 vron, /*start voice recognition*/
285 vroff, /*stop voice recognition*/
286 ate, /*send extended at error code*/
287 iron, /*in-band ring tone provided*/
288 iroff, /*in-band ring tone not provided*/
289 ac, /*Answer Incoming Call from AG*/
290 rc, /*Reject Incoming Call from AG*/
291 end, /*End up a call by AG*/
292 d /*Dial Number by AG, e.g. d 11223344*/
293 };
294 static char *hf_cmd_explain[] = {
295 "show command manual",
296 "set up connection with peer device",
297 "disconnection with peer device",
298 "set up audio connection with peer device",
299 "release connection with peer device",
300 "volume update",
301 "unsolicited indication device status to HF Client",
302 "start voice recognition",
303 "stop voice recognition",
304 "send extended at error code",
305 "in-band ring tone provided",
306 "in-band ring tone not provided",
307 "Answer Incoming Call from AG",
308 "Reject Incoming Call from AG",
309 "End up a call by AG",
310 "Dial Number by AG, e.g. d 11223344",
311 };
312 typedef struct {
313 struct arg_str *tgt;
314 struct arg_str *vol;
315 struct arg_end *end;
316 } vu_args_t;
317
318 typedef struct {
319 struct arg_str *call;
320 struct arg_str *ntk;
321 struct arg_str *callsetup;
322 struct arg_str *sig;
323 struct arg_end *end;
324 } ind_args_t;
325
326 typedef struct {
327 struct arg_str *rep;
328 struct arg_str *err;
329 struct arg_end *end;
330 } ate_args_t;
331
332 static vu_args_t vu_args;
333 static ind_args_t ind_args;
334 static ate_args_t ate_args;
335
register_hfp_ag(void)336 void register_hfp_ag(void)
337 {
338
339 const esp_console_cmd_t HF_ORDER(con) = {
340 .command = "con",
341 .help = hf_cmd_explain[con],
342 .hint = NULL,
343 .func = hf_cmd_tbl[con].handler,
344 };
345 ESP_ERROR_CHECK(esp_console_cmd_register(&HF_ORDER(con)));
346
347 const esp_console_cmd_t HF_ORDER(dis) = {
348 .command = "dis",
349 .help = hf_cmd_explain[dis],
350 .hint = NULL,
351 .func = hf_cmd_tbl[dis].handler,
352 };
353 ESP_ERROR_CHECK(esp_console_cmd_register(&HF_ORDER(dis)));
354
355 const esp_console_cmd_t HF_ORDER(cona) = {
356 .command = "cona",
357 .help = hf_cmd_explain[cona],
358 .hint = NULL,
359 .func = hf_cmd_tbl[cona].handler,
360 };
361 ESP_ERROR_CHECK(esp_console_cmd_register(&HF_ORDER(cona)));
362
363 const esp_console_cmd_t HF_ORDER(disa) = {
364 .command = "disa",
365 .help = hf_cmd_explain[disa],
366 .hint = NULL,
367 .func = hf_cmd_tbl[disa].handler,
368 };
369 ESP_ERROR_CHECK(esp_console_cmd_register(&HF_ORDER(disa)));
370
371
372
373 const esp_console_cmd_t HF_ORDER(ac) = {
374 .command = "ac",
375 .help = hf_cmd_explain[ac],
376 .hint = NULL,
377 .func = hf_cmd_tbl[ac].handler,
378 };
379 ESP_ERROR_CHECK(esp_console_cmd_register(&HF_ORDER(ac)));
380
381 const esp_console_cmd_t HF_ORDER(rc) = {
382 .command = "rc",
383 .help = hf_cmd_explain[rc],
384 .hint = NULL,
385 .func = hf_cmd_tbl[rc].handler,
386 };
387 ESP_ERROR_CHECK(esp_console_cmd_register(&HF_ORDER(rc)));
388
389 const esp_console_cmd_t HF_ORDER(d) = {
390 .command = "d",
391 .help = hf_cmd_explain[d],
392 .hint = "<num>",
393 .func = hf_cmd_tbl[d].handler,
394 };
395 ESP_ERROR_CHECK(esp_console_cmd_register(&HF_ORDER(d)));
396
397
398
399 const esp_console_cmd_t HF_ORDER(vron) = {
400 .command = "vron",
401 .help = hf_cmd_explain[vron],
402 .hint = NULL,
403 .func = hf_cmd_tbl[vron].handler,
404 };
405 ESP_ERROR_CHECK(esp_console_cmd_register(&HF_ORDER(vron)));
406
407 const esp_console_cmd_t HF_ORDER(vroff) = {
408 .command = "vroff",
409 .help = hf_cmd_explain[vroff],
410 .hint = NULL,
411 .func = hf_cmd_tbl[vroff].handler,
412 };
413 ESP_ERROR_CHECK(esp_console_cmd_register(&HF_ORDER(vroff)));
414
415 vu_args.tgt = arg_str1(NULL, NULL, "<tgt>", "\n 0-speaker\n 1-microphone");
416 vu_args.vol = arg_str1(NULL, NULL, "<vol>", "volume gain ranges from 0 to 15");
417 vu_args.end = arg_end(1);
418 const esp_console_cmd_t HF_ORDER(vu) = {
419 .command = "vu",
420 .help = hf_cmd_explain[vu],
421 .hint = NULL,
422 .func = hf_cmd_tbl[vu].handler,
423 .argtable = &vu_args
424 };
425 ESP_ERROR_CHECK(esp_console_cmd_register(&HF_ORDER(vu)));
426
427 const esp_console_cmd_t HF_ORDER(end) = {
428 .command = "end",
429 .help = hf_cmd_explain[end],
430 .hint = NULL,
431 .func = hf_cmd_tbl[end].handler,
432 };
433 ESP_ERROR_CHECK(esp_console_cmd_register(&HF_ORDER(end)));
434
435 const esp_console_cmd_t HF_ORDER(iron) = {
436 .command = "iron",
437 .help = hf_cmd_explain[iron],
438 .hint = NULL,
439 .func = hf_cmd_tbl[iron].handler,
440 };
441 ESP_ERROR_CHECK(esp_console_cmd_register(&HF_ORDER(iron)));
442
443 const esp_console_cmd_t HF_ORDER(iroff) = {
444 .command = "iroff",
445 .help = hf_cmd_explain[iroff],
446 .hint = NULL,
447 .func = hf_cmd_tbl[iroff].handler,
448 };
449 ESP_ERROR_CHECK(esp_console_cmd_register(&HF_ORDER(iroff)));
450
451 ind_args.call = arg_str1(NULL, NULL, "<call>", "call status [0,1]");
452 ind_args.callsetup = arg_str1(NULL, NULL, "<callsetup>", "call setup status [0,3]");
453 ind_args.ntk = arg_str1(NULL, NULL, "<ntk>", "network status [0,1]");
454 ind_args.sig = arg_str1(NULL, NULL, "<sig>", "signal strength value from 0~5");
455 ind_args.end = arg_end(1);
456 const esp_console_cmd_t HF_ORDER(ind) = {
457 .command = "ind",
458 .help = hf_cmd_explain[ind],
459 .hint = NULL,
460 .func = hf_cmd_tbl[ind].handler,
461 .argtable = &ind_args
462 };
463 ESP_ERROR_CHECK(esp_console_cmd_register(&HF_ORDER(ind)));
464
465 ate_args.err = arg_str1(NULL, NULL, "<err>", "error code from 0 to 32");
466 ate_args.rep = arg_str1(NULL, NULL, "<rep>", "response code from 0 to 7");
467 ate_args.end = arg_end(1);
468 const esp_console_cmd_t HF_ORDER(ate) = {
469 .command = "ate",
470 .help = hf_cmd_explain[ate],
471 .hint = NULL,
472 .func = hf_cmd_tbl[ate].handler,
473 .argtable = &ate_args
474 };
475 ESP_ERROR_CHECK(esp_console_cmd_register(&HF_ORDER(ate)));
476 }
477