1 /* hfp_hf.c - Hands free Profile - Handsfree side handling */
2
3 /*
4 * Copyright (c) 2015-2016 Intel Corporation
5 *
6 * SPDX-License-Identifier: Apache-2.0
7 */
8 #include <zephyr/kernel.h>
9 #include <errno.h>
10 #include <zephyr/sys/atomic.h>
11 #include <zephyr/sys/byteorder.h>
12 #include <zephyr/sys/util.h>
13 #include <zephyr/sys/printk.h>
14
15 #include <zephyr/bluetooth/conn.h>
16
17 #include "common/assert.h"
18
19 #include <zephyr/bluetooth/rfcomm.h>
20 #include <zephyr/bluetooth/hfp_hf.h>
21
22 #include "hci_core.h"
23 #include "conn_internal.h"
24 #include "l2cap_internal.h"
25 #include "rfcomm_internal.h"
26 #include "at.h"
27 #include "hfp_internal.h"
28
29 #define LOG_LEVEL CONFIG_BT_HFP_HF_LOG_LEVEL
30 #include <zephyr/logging/log.h>
31 LOG_MODULE_REGISTER(bt_hfp_hf);
32
33 #define MAX_IND_STR_LEN 17
34
35 struct bt_hfp_hf_cb *bt_hf;
36
37 NET_BUF_POOL_FIXED_DEFINE(hf_pool, CONFIG_BT_MAX_CONN + 1,
38 BT_RFCOMM_BUF_SIZE(BT_HF_CLIENT_MAX_PDU), 8, NULL);
39
40 static struct bt_hfp_hf bt_hfp_hf_pool[CONFIG_BT_MAX_CONN];
41
42 /* The order should follow the enum hfp_hf_ag_indicators */
43 static const struct {
44 char *name;
45 uint32_t min;
46 uint32_t max;
47 } ag_ind[] = {
48 {"service", 0, 1}, /* HF_SERVICE_IND */
49 {"call", 0, 1}, /* HF_CALL_IND */
50 {"callsetup", 0, 3}, /* HF_CALL_SETUP_IND */
51 {"callheld", 0, 2}, /* HF_CALL_HELD_IND */
52 {"signal", 0, 5}, /* HF_SIGNAL_IND */
53 {"roam", 0, 1}, /* HF_ROAM_IND */
54 {"battchg", 0, 5} /* HF_BATTERY_IND */
55 };
56
hf_slc_error(struct at_client * hf_at)57 void hf_slc_error(struct at_client *hf_at)
58 {
59 struct bt_hfp_hf *hf = CONTAINER_OF(hf_at, struct bt_hfp_hf, at);
60 int err;
61
62 LOG_ERR("SLC error: disconnecting");
63 err = bt_rfcomm_dlc_disconnect(&hf->rfcomm_dlc);
64 if (err) {
65 LOG_ERR("Rfcomm: Unable to disconnect :%d", -err);
66 }
67 }
68
hfp_hf_send_cmd(struct bt_hfp_hf * hf,at_resp_cb_t resp,at_finish_cb_t finish,const char * format,...)69 int hfp_hf_send_cmd(struct bt_hfp_hf *hf, at_resp_cb_t resp,
70 at_finish_cb_t finish, const char *format, ...)
71 {
72 struct net_buf *buf;
73 va_list vargs;
74 int ret;
75
76 /* register the callbacks */
77 at_register(&hf->at, resp, finish);
78
79 buf = bt_rfcomm_create_pdu(&hf_pool);
80 if (!buf) {
81 LOG_ERR("No Buffers!");
82 return -ENOMEM;
83 }
84
85 va_start(vargs, format);
86 ret = vsnprintk(buf->data, (net_buf_tailroom(buf) - 1), format, vargs);
87 if (ret < 0) {
88 LOG_ERR("Unable to format variable arguments");
89 return ret;
90 }
91 va_end(vargs);
92
93 net_buf_add(buf, ret);
94 net_buf_add_u8(buf, '\r');
95
96 ret = bt_rfcomm_dlc_send(&hf->rfcomm_dlc, buf);
97 if (ret < 0) {
98 LOG_ERR("Rfcomm send error :(%d)", ret);
99 return ret;
100 }
101
102 return 0;
103 }
104
brsf_handle(struct at_client * hf_at)105 int brsf_handle(struct at_client *hf_at)
106 {
107 struct bt_hfp_hf *hf = CONTAINER_OF(hf_at, struct bt_hfp_hf, at);
108 uint32_t val;
109 int ret;
110
111 ret = at_get_number(hf_at, &val);
112 if (ret < 0) {
113 LOG_ERR("Error getting value");
114 return ret;
115 }
116
117 hf->ag_features = val;
118
119 return 0;
120 }
121
brsf_resp(struct at_client * hf_at,struct net_buf * buf)122 int brsf_resp(struct at_client *hf_at, struct net_buf *buf)
123 {
124 int err;
125
126 LOG_DBG("");
127
128 err = at_parse_cmd_input(hf_at, buf, "BRSF", brsf_handle,
129 AT_CMD_TYPE_NORMAL);
130 if (err < 0) {
131 /* Returning negative value is avoided before SLC connection
132 * established.
133 */
134 LOG_ERR("Error parsing CMD input");
135 hf_slc_error(hf_at);
136 }
137
138 return 0;
139 }
140
cind_handle_values(struct at_client * hf_at,uint32_t index,char * name,uint32_t min,uint32_t max)141 static void cind_handle_values(struct at_client *hf_at, uint32_t index,
142 char *name, uint32_t min, uint32_t max)
143 {
144 struct bt_hfp_hf *hf = CONTAINER_OF(hf_at, struct bt_hfp_hf, at);
145 int i;
146
147 LOG_DBG("index: %u, name: %s, min: %u, max:%u", index, name, min, max);
148
149 for (i = 0; i < ARRAY_SIZE(ag_ind); i++) {
150 if (strcmp(name, ag_ind[i].name) != 0) {
151 continue;
152 }
153 if (min != ag_ind[i].min || max != ag_ind[i].max) {
154 LOG_ERR("%s indicator min/max value not matching", name);
155 }
156
157 hf->ind_table[index] = i;
158 break;
159 }
160 }
161
cind_handle(struct at_client * hf_at)162 int cind_handle(struct at_client *hf_at)
163 {
164 uint32_t index = 0U;
165
166 /* Parsing Example: CIND: ("call",(0,1)) etc.. */
167 while (at_has_next_list(hf_at)) {
168 char name[MAX_IND_STR_LEN];
169 uint32_t min, max;
170
171 if (at_open_list(hf_at) < 0) {
172 LOG_ERR("Could not get open list");
173 goto error;
174 }
175
176 if (at_list_get_string(hf_at, name, sizeof(name)) < 0) {
177 LOG_ERR("Could not get string");
178 goto error;
179 }
180
181 if (at_open_list(hf_at) < 0) {
182 LOG_ERR("Could not get open list");
183 goto error;
184 }
185
186 if (at_list_get_range(hf_at, &min, &max) < 0) {
187 LOG_ERR("Could not get range");
188 goto error;
189 }
190
191 if (at_close_list(hf_at) < 0) {
192 LOG_ERR("Could not get close list");
193 goto error;
194 }
195
196 if (at_close_list(hf_at) < 0) {
197 LOG_ERR("Could not get close list");
198 goto error;
199 }
200
201 cind_handle_values(hf_at, index, name, min, max);
202 index++;
203 }
204
205 return 0;
206 error:
207 LOG_ERR("Error on CIND response");
208 hf_slc_error(hf_at);
209 return -EINVAL;
210 }
211
cind_resp(struct at_client * hf_at,struct net_buf * buf)212 int cind_resp(struct at_client *hf_at, struct net_buf *buf)
213 {
214 int err;
215
216 err = at_parse_cmd_input(hf_at, buf, "CIND", cind_handle,
217 AT_CMD_TYPE_NORMAL);
218 if (err < 0) {
219 LOG_ERR("Error parsing CMD input");
220 hf_slc_error(hf_at);
221 }
222
223 return 0;
224 }
225
ag_indicator_handle_values(struct at_client * hf_at,uint32_t index,uint32_t value)226 void ag_indicator_handle_values(struct at_client *hf_at, uint32_t index,
227 uint32_t value)
228 {
229 struct bt_hfp_hf *hf = CONTAINER_OF(hf_at, struct bt_hfp_hf, at);
230 struct bt_conn *conn = hf->rfcomm_dlc.session->br_chan.chan.conn;
231
232 LOG_DBG("Index :%u, Value :%u", index, value);
233
234 if (index >= ARRAY_SIZE(ag_ind)) {
235 LOG_ERR("Max only %zu indicators are supported", ARRAY_SIZE(ag_ind));
236 return;
237 }
238
239 if (value > ag_ind[hf->ind_table[index]].max ||
240 value < ag_ind[hf->ind_table[index]].min) {
241 LOG_ERR("Indicators out of range - value: %u", value);
242 return;
243 }
244
245 switch (hf->ind_table[index]) {
246 case HF_SERVICE_IND:
247 if (bt_hf->service) {
248 bt_hf->service(conn, value);
249 }
250 break;
251 case HF_CALL_IND:
252 if (bt_hf->call) {
253 bt_hf->call(conn, value);
254 }
255 break;
256 case HF_CALL_SETUP_IND:
257 if (bt_hf->call_setup) {
258 bt_hf->call_setup(conn, value);
259 }
260 break;
261 case HF_CALL_HELD_IND:
262 if (bt_hf->call_held) {
263 bt_hf->call_held(conn, value);
264 }
265 break;
266 case HF_SINGNAL_IND:
267 if (bt_hf->signal) {
268 bt_hf->signal(conn, value);
269 }
270 break;
271 case HF_ROAM_IND:
272 if (bt_hf->roam) {
273 bt_hf->roam(conn, value);
274 }
275 break;
276 case HF_BATTERY_IND:
277 if (bt_hf->battery) {
278 bt_hf->battery(conn, value);
279 }
280 break;
281 default:
282 LOG_ERR("Unknown AG indicator");
283 break;
284 }
285 }
286
cind_status_handle(struct at_client * hf_at)287 int cind_status_handle(struct at_client *hf_at)
288 {
289 uint32_t index = 0U;
290
291 while (at_has_next_list(hf_at)) {
292 uint32_t value;
293 int ret;
294
295 ret = at_get_number(hf_at, &value);
296 if (ret < 0) {
297 LOG_ERR("could not get the value");
298 return ret;
299 }
300
301 ag_indicator_handle_values(hf_at, index, value);
302
303 index++;
304 }
305
306 return 0;
307 }
308
cind_status_resp(struct at_client * hf_at,struct net_buf * buf)309 int cind_status_resp(struct at_client *hf_at, struct net_buf *buf)
310 {
311 int err;
312
313 err = at_parse_cmd_input(hf_at, buf, "CIND", cind_status_handle,
314 AT_CMD_TYPE_NORMAL);
315 if (err < 0) {
316 LOG_ERR("Error parsing CMD input");
317 hf_slc_error(hf_at);
318 }
319
320 return 0;
321 }
322
ciev_handle(struct at_client * hf_at)323 int ciev_handle(struct at_client *hf_at)
324 {
325 uint32_t index, value;
326 int ret;
327
328 ret = at_get_number(hf_at, &index);
329 if (ret < 0) {
330 LOG_ERR("could not get the Index");
331 return ret;
332 }
333 /* The first element of the list shall have 1 */
334 if (!index) {
335 LOG_ERR("Invalid index value '0'");
336 return 0;
337 }
338
339 ret = at_get_number(hf_at, &value);
340 if (ret < 0) {
341 LOG_ERR("could not get the value");
342 return ret;
343 }
344
345 ag_indicator_handle_values(hf_at, (index - 1), value);
346
347 return 0;
348 }
349
ring_handle(struct at_client * hf_at)350 int ring_handle(struct at_client *hf_at)
351 {
352 struct bt_hfp_hf *hf = CONTAINER_OF(hf_at, struct bt_hfp_hf, at);
353 struct bt_conn *conn = hf->rfcomm_dlc.session->br_chan.chan.conn;
354
355 if (bt_hf->ring_indication) {
356 bt_hf->ring_indication(conn);
357 }
358
359 return 0;
360 }
361
362 static const struct unsolicited {
363 const char *cmd;
364 enum at_cmd_type type;
365 int (*func)(struct at_client *hf_at);
366 } handlers[] = {
367 { "CIEV", AT_CMD_TYPE_UNSOLICITED, ciev_handle },
368 { "RING", AT_CMD_TYPE_OTHER, ring_handle }
369 };
370
hfp_hf_unsol_lookup(struct at_client * hf_at)371 static const struct unsolicited *hfp_hf_unsol_lookup(struct at_client *hf_at)
372 {
373 int i;
374
375 for (i = 0; i < ARRAY_SIZE(handlers); i++) {
376 if (!strncmp(hf_at->buf, handlers[i].cmd,
377 strlen(handlers[i].cmd))) {
378 return &handlers[i];
379 }
380 }
381
382 return NULL;
383 }
384
unsolicited_cb(struct at_client * hf_at,struct net_buf * buf)385 int unsolicited_cb(struct at_client *hf_at, struct net_buf *buf)
386 {
387 const struct unsolicited *handler;
388
389 handler = hfp_hf_unsol_lookup(hf_at);
390 if (!handler) {
391 LOG_ERR("Unhandled unsolicited response");
392 return -ENOMSG;
393 }
394
395 if (!at_parse_cmd_input(hf_at, buf, handler->cmd, handler->func,
396 handler->type)) {
397 return 0;
398 }
399
400 return -ENOMSG;
401 }
402
cmd_complete(struct at_client * hf_at,enum at_result result,enum at_cme cme_err)403 int cmd_complete(struct at_client *hf_at, enum at_result result,
404 enum at_cme cme_err)
405 {
406 struct bt_hfp_hf *hf = CONTAINER_OF(hf_at, struct bt_hfp_hf, at);
407 struct bt_conn *conn = hf->rfcomm_dlc.session->br_chan.chan.conn;
408 struct bt_hfp_hf_cmd_complete cmd = { 0 };
409
410 LOG_DBG("");
411
412 switch (result) {
413 case AT_RESULT_OK:
414 cmd.type = HFP_HF_CMD_OK;
415 break;
416 case AT_RESULT_ERROR:
417 cmd.type = HFP_HF_CMD_ERROR;
418 break;
419 case AT_RESULT_CME_ERROR:
420 cmd.type = HFP_HF_CMD_CME_ERROR;
421 cmd.cme = cme_err;
422 break;
423 default:
424 LOG_ERR("Unknown error code");
425 cmd.type = HFP_HF_CMD_UNKNOWN_ERROR;
426 break;
427 }
428
429 if (bt_hf->cmd_complete_cb) {
430 bt_hf->cmd_complete_cb(conn, &cmd);
431 }
432
433 return 0;
434 }
435
cmee_finish(struct at_client * hf_at,enum at_result result,enum at_cme cme_err)436 int cmee_finish(struct at_client *hf_at, enum at_result result,
437 enum at_cme cme_err)
438 {
439 if (result != AT_RESULT_OK) {
440 LOG_ERR("SLC Connection ERROR in response");
441 return -EINVAL;
442 }
443
444 return 0;
445 }
446
slc_completed(struct at_client * hf_at)447 static void slc_completed(struct at_client *hf_at)
448 {
449 struct bt_hfp_hf *hf = CONTAINER_OF(hf_at, struct bt_hfp_hf, at);
450 struct bt_conn *conn = hf->rfcomm_dlc.session->br_chan.chan.conn;
451
452 if (bt_hf->connected) {
453 bt_hf->connected(conn);
454 }
455
456 if (hfp_hf_send_cmd(hf, NULL, cmee_finish, "AT+CMEE=1") < 0) {
457 LOG_ERR("Error Sending AT+CMEE");
458 }
459 }
460
cmer_finish(struct at_client * hf_at,enum at_result result,enum at_cme cme_err)461 int cmer_finish(struct at_client *hf_at, enum at_result result,
462 enum at_cme cme_err)
463 {
464 if (result != AT_RESULT_OK) {
465 LOG_ERR("SLC Connection ERROR in response");
466 hf_slc_error(hf_at);
467 return -EINVAL;
468 }
469
470 slc_completed(hf_at);
471
472 return 0;
473 }
474
cind_status_finish(struct at_client * hf_at,enum at_result result,enum at_cme cme_err)475 int cind_status_finish(struct at_client *hf_at, enum at_result result,
476 enum at_cme cme_err)
477 {
478 struct bt_hfp_hf *hf = CONTAINER_OF(hf_at, struct bt_hfp_hf, at);
479 int err;
480
481 if (result != AT_RESULT_OK) {
482 LOG_ERR("SLC Connection ERROR in response");
483 hf_slc_error(hf_at);
484 return -EINVAL;
485 }
486
487 at_register_unsolicited(hf_at, unsolicited_cb);
488 err = hfp_hf_send_cmd(hf, NULL, cmer_finish, "AT+CMER=3,0,0,1");
489 if (err < 0) {
490 hf_slc_error(hf_at);
491 return err;
492 }
493
494 return 0;
495 }
496
cind_finish(struct at_client * hf_at,enum at_result result,enum at_cme cme_err)497 int cind_finish(struct at_client *hf_at, enum at_result result,
498 enum at_cme cme_err)
499 {
500 struct bt_hfp_hf *hf = CONTAINER_OF(hf_at, struct bt_hfp_hf, at);
501 int err;
502
503 if (result != AT_RESULT_OK) {
504 LOG_ERR("SLC Connection ERROR in response");
505 hf_slc_error(hf_at);
506 return -EINVAL;
507 }
508
509 err = hfp_hf_send_cmd(hf, cind_status_resp, cind_status_finish,
510 "AT+CIND?");
511 if (err < 0) {
512 hf_slc_error(hf_at);
513 return err;
514 }
515
516 return 0;
517 }
518
brsf_finish(struct at_client * hf_at,enum at_result result,enum at_cme cme_err)519 int brsf_finish(struct at_client *hf_at, enum at_result result,
520 enum at_cme cme_err)
521 {
522 struct bt_hfp_hf *hf = CONTAINER_OF(hf_at, struct bt_hfp_hf, at);
523 int err;
524
525 if (result != AT_RESULT_OK) {
526 LOG_ERR("SLC Connection ERROR in response");
527 hf_slc_error(hf_at);
528 return -EINVAL;
529 }
530
531 err = hfp_hf_send_cmd(hf, cind_resp, cind_finish, "AT+CIND=?");
532 if (err < 0) {
533 hf_slc_error(hf_at);
534 return err;
535 }
536
537 return 0;
538 }
539
hf_slc_establish(struct bt_hfp_hf * hf)540 int hf_slc_establish(struct bt_hfp_hf *hf)
541 {
542 int err;
543
544 LOG_DBG("");
545
546 err = hfp_hf_send_cmd(hf, brsf_resp, brsf_finish, "AT+BRSF=%u",
547 hf->hf_features);
548 if (err < 0) {
549 hf_slc_error(&hf->at);
550 return err;
551 }
552
553 return 0;
554 }
555
bt_hfp_hf_lookup_bt_conn(struct bt_conn * conn)556 static struct bt_hfp_hf *bt_hfp_hf_lookup_bt_conn(struct bt_conn *conn)
557 {
558 int i;
559
560 for (i = 0; i < ARRAY_SIZE(bt_hfp_hf_pool); i++) {
561 struct bt_hfp_hf *hf = &bt_hfp_hf_pool[i];
562
563 if (hf->rfcomm_dlc.session->br_chan.chan.conn == conn) {
564 return hf;
565 }
566 }
567
568 return NULL;
569 }
570
bt_hfp_hf_send_cmd(struct bt_conn * conn,enum bt_hfp_hf_at_cmd cmd)571 int bt_hfp_hf_send_cmd(struct bt_conn *conn, enum bt_hfp_hf_at_cmd cmd)
572 {
573 struct bt_hfp_hf *hf;
574 int err;
575
576 LOG_DBG("");
577
578 if (!conn) {
579 LOG_ERR("Invalid connection");
580 return -ENOTCONN;
581 }
582
583 hf = bt_hfp_hf_lookup_bt_conn(conn);
584 if (!hf) {
585 LOG_ERR("No HF connection found");
586 return -ENOTCONN;
587 }
588
589 switch (cmd) {
590 case BT_HFP_HF_ATA:
591 err = hfp_hf_send_cmd(hf, NULL, cmd_complete, "ATA");
592 if (err < 0) {
593 LOG_ERR("Failed ATA");
594 return err;
595 }
596 break;
597 case BT_HFP_HF_AT_CHUP:
598 err = hfp_hf_send_cmd(hf, NULL, cmd_complete, "AT+CHUP");
599 if (err < 0) {
600 LOG_ERR("Failed AT+CHUP");
601 return err;
602 }
603 break;
604 default:
605 LOG_ERR("Invalid AT Command");
606 return -EINVAL;
607 }
608
609 return 0;
610 }
611
hfp_hf_connected(struct bt_rfcomm_dlc * dlc)612 static void hfp_hf_connected(struct bt_rfcomm_dlc *dlc)
613 {
614 struct bt_hfp_hf *hf = CONTAINER_OF(dlc, struct bt_hfp_hf, rfcomm_dlc);
615
616 LOG_DBG("hf connected");
617
618 BT_ASSERT(hf);
619 hf_slc_establish(hf);
620 }
621
hfp_hf_disconnected(struct bt_rfcomm_dlc * dlc)622 static void hfp_hf_disconnected(struct bt_rfcomm_dlc *dlc)
623 {
624 struct bt_conn *conn = dlc->session->br_chan.chan.conn;
625
626 LOG_DBG("hf disconnected!");
627 if (bt_hf->disconnected) {
628 bt_hf->disconnected(conn);
629 }
630 }
631
hfp_hf_recv(struct bt_rfcomm_dlc * dlc,struct net_buf * buf)632 static void hfp_hf_recv(struct bt_rfcomm_dlc *dlc, struct net_buf *buf)
633 {
634 struct bt_hfp_hf *hf = CONTAINER_OF(dlc, struct bt_hfp_hf, rfcomm_dlc);
635
636 if (at_parse_input(&hf->at, buf) < 0) {
637 LOG_ERR("Parsing failed");
638 }
639 }
640
bt_hfp_hf_accept(struct bt_conn * conn,struct bt_rfcomm_dlc ** dlc)641 static int bt_hfp_hf_accept(struct bt_conn *conn, struct bt_rfcomm_dlc **dlc)
642 {
643 int i;
644 static struct bt_rfcomm_dlc_ops ops = {
645 .connected = hfp_hf_connected,
646 .disconnected = hfp_hf_disconnected,
647 .recv = hfp_hf_recv,
648 };
649
650 LOG_DBG("conn %p", conn);
651
652 for (i = 0; i < ARRAY_SIZE(bt_hfp_hf_pool); i++) {
653 struct bt_hfp_hf *hf = &bt_hfp_hf_pool[i];
654 int j;
655
656 if (hf->rfcomm_dlc.session) {
657 continue;
658 }
659
660 hf->at.buf = hf->hf_buffer;
661 hf->at.buf_max_len = HF_MAX_BUF_LEN;
662
663 hf->rfcomm_dlc.ops = &ops;
664 hf->rfcomm_dlc.mtu = BT_HFP_MAX_MTU;
665
666 *dlc = &hf->rfcomm_dlc;
667
668 /* Set the supported features*/
669 hf->hf_features = BT_HFP_HF_SUPPORTED_FEATURES;
670
671 for (j = 0; j < HF_MAX_AG_INDICATORS; j++) {
672 hf->ind_table[j] = -1;
673 }
674
675 return 0;
676 }
677
678 LOG_ERR("Unable to establish HF connection (%p)", conn);
679
680 return -ENOMEM;
681 }
682
hfp_hf_init(void)683 static void hfp_hf_init(void)
684 {
685 static struct bt_rfcomm_server chan = {
686 .channel = BT_RFCOMM_CHAN_HFP_HF,
687 .accept = bt_hfp_hf_accept,
688 };
689
690 bt_rfcomm_server_register(&chan);
691 }
692
bt_hfp_hf_register(struct bt_hfp_hf_cb * cb)693 int bt_hfp_hf_register(struct bt_hfp_hf_cb *cb)
694 {
695 if (!cb) {
696 return -EINVAL;
697 }
698
699 if (bt_hf) {
700 return -EALREADY;
701 }
702
703 bt_hf = cb;
704
705 hfp_hf_init();
706
707 return 0;
708 }
709