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