Upgrade bluez5_37 :Merge the code from private
[platform/upstream/bluez.git] / android / hal-handsfree.c
1 /*
2  * Copyright (C) 2014 Intel Corporation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 #include <stdbool.h>
19 #include <stddef.h>
20 #include <string.h>
21 #include <stdlib.h>
22
23 #include <cutils/properties.h>
24
25 #include "hal-log.h"
26 #include "hal.h"
27 #include "hal-msg.h"
28 #include "ipc-common.h"
29 #include "hal-ipc.h"
30 #include "hal-utils.h"
31
32 static const bthf_callbacks_t *cbs = NULL;
33
34 static bool interface_ready(void)
35 {
36         return cbs != NULL;
37 }
38
39 static void handle_conn_state(void *buf, uint16_t len, int fd)
40 {
41         struct hal_ev_handsfree_conn_state *ev = buf;
42
43         if (cbs->connection_state_cb)
44                 cbs->connection_state_cb(ev->state,
45                                                 (bt_bdaddr_t *) (ev->bdaddr));
46 }
47
48 static void handle_audio_state(void *buf, uint16_t len, int fd)
49 {
50         struct hal_ev_handsfree_audio_state *ev = buf;
51
52         if (cbs->audio_state_cb)
53                 cbs->audio_state_cb(ev->state, (bt_bdaddr_t *) (ev->bdaddr));
54 }
55
56 static void handle_vr_state(void *buf, uint16_t len, int fd)
57 {
58         struct hal_ev_handsfree_vr_state *ev = buf;
59
60         if (cbs->vr_cmd_cb)
61 #if ANDROID_VERSION >= PLATFORM_VER(5, 0, 0)
62                 cbs->vr_cmd_cb(ev->state, (bt_bdaddr_t *) (ev->bdaddr));
63 #else
64                 cbs->vr_cmd_cb(ev->state);
65 #endif
66 }
67
68 static void handle_answer(void *buf, uint16_t len, int fd)
69 {
70         if (cbs->answer_call_cmd_cb) {
71 #if ANDROID_VERSION >= PLATFORM_VER(5, 0, 0)
72                 struct hal_ev_handsfree_answer *ev = buf;
73
74                 cbs->answer_call_cmd_cb((bt_bdaddr_t *) (ev->bdaddr));
75 #else
76                 cbs->answer_call_cmd_cb();
77 #endif
78         }
79 }
80
81 static void handle_hangup(void *buf, uint16_t len, int fd)
82 {
83         if (cbs->hangup_call_cmd_cb) {
84 #if ANDROID_VERSION >= PLATFORM_VER(5, 0, 0)
85                 struct hal_ev_handsfree_hangup *ev = buf;
86
87                 cbs->hangup_call_cmd_cb((bt_bdaddr_t *) (ev->bdaddr));
88 #else
89                 cbs->hangup_call_cmd_cb();
90 #endif
91         }
92 }
93
94 static void handle_volume(void *buf, uint16_t len, int fd)
95 {
96         struct hal_ev_handsfree_volume *ev = buf;
97
98         if (cbs->volume_cmd_cb)
99 #if ANDROID_VERSION >= PLATFORM_VER(5, 0, 0)
100                 cbs->volume_cmd_cb(ev->type, ev->volume,
101                                                 (bt_bdaddr_t *) (ev->bdaddr));
102 #else
103                 cbs->volume_cmd_cb(ev->type, ev->volume);
104 #endif
105 }
106
107 static void handle_dial(void *buf, uint16_t len, int fd)
108 {
109         struct hal_ev_handsfree_dial *ev = buf;
110         uint16_t num_len = ev->number_len;
111         char *number = NULL;
112
113         if (len != sizeof(*ev) + num_len ||
114                         (num_len != 0 && ev->number[num_len - 1] != '\0')) {
115                 error("invalid dial event, aborting");
116                 exit(EXIT_FAILURE);
117         }
118
119         if (!cbs->dial_call_cmd_cb)
120                 return;
121
122         if (ev->number_len)
123                 number = (char *) ev->number;
124
125 #if ANDROID_VERSION >= PLATFORM_VER(5, 0, 0)
126         cbs->dial_call_cmd_cb(number, (bt_bdaddr_t *) (ev->bdaddr));
127 #else
128         cbs->dial_call_cmd_cb(number);
129 #endif
130 }
131
132 static void handle_dtmf(void *buf, uint16_t len, int fd)
133 {
134         struct hal_ev_handsfree_dtmf *ev = buf;
135
136         if (cbs->dtmf_cmd_cb)
137 #if ANDROID_VERSION >= PLATFORM_VER(5, 0, 0)
138                 cbs->dtmf_cmd_cb(ev->tone, (bt_bdaddr_t *) (ev->bdaddr));
139 #else
140                 cbs->dtmf_cmd_cb(ev->tone);
141 #endif
142 }
143
144 static void handle_nrec(void *buf, uint16_t len, int fd)
145 {
146         struct hal_ev_handsfree_nrec *ev = buf;
147
148         if (cbs->nrec_cmd_cb)
149 #if ANDROID_VERSION >= PLATFORM_VER(5, 0, 0)
150                 cbs->nrec_cmd_cb(ev->nrec, (bt_bdaddr_t *) (ev->bdaddr));
151 #else
152                 cbs->nrec_cmd_cb(ev->nrec);
153 #endif
154 }
155
156 static void handle_wbs(void *buf, uint16_t len, int fd)
157 {
158 #if ANDROID_VERSION >= PLATFORM_VER(5, 0, 0)
159         struct hal_ev_handsfree_wbs *ev = buf;
160
161         if (cbs->wbs_cb)
162                 cbs->wbs_cb(ev->wbs, (bt_bdaddr_t *) (ev->bdaddr));
163 #endif
164 }
165
166 static void handle_chld(void *buf, uint16_t len, int fd)
167 {
168         struct hal_ev_handsfree_chld *ev = buf;
169
170         if (cbs->chld_cmd_cb)
171 #if ANDROID_VERSION >= PLATFORM_VER(5, 0, 0)
172                 cbs->chld_cmd_cb(ev->chld, (bt_bdaddr_t *) (ev->bdaddr));
173 #else
174                 cbs->chld_cmd_cb(ev->chld);
175 #endif
176 }
177
178 static void handle_cnum(void *buf, uint16_t len, int fd)
179 {
180         if (cbs->cnum_cmd_cb) {
181 #if ANDROID_VERSION >= PLATFORM_VER(5, 0, 0)
182                 struct hal_ev_handsfree_cnum *ev = buf;
183
184                 cbs->cnum_cmd_cb((bt_bdaddr_t *) (ev->bdaddr));
185 #else
186                 cbs->cnum_cmd_cb(NULL);
187 #endif
188         }
189 }
190
191 static void handle_cind(void *buf, uint16_t len, int fd)
192 {
193         if (cbs->cind_cmd_cb) {
194 #if ANDROID_VERSION >= PLATFORM_VER(5, 0, 0)
195                 struct hal_ev_handsfree_cind *ev = buf;
196
197                 cbs->cind_cmd_cb((bt_bdaddr_t *) (ev->bdaddr));
198 #else
199                 cbs->cind_cmd_cb();
200 #endif
201         }
202 }
203
204 static void handle_cops(void *buf, uint16_t len, int fd)
205 {
206         if (cbs->cops_cmd_cb) {
207 #if ANDROID_VERSION >= PLATFORM_VER(5, 0, 0)
208                 struct hal_ev_handsfree_cops *ev = buf;
209
210                 cbs->cops_cmd_cb((bt_bdaddr_t *) (ev->bdaddr));
211 #else
212                 cbs->cops_cmd_cb();
213 #endif
214         }
215 }
216
217 static void handle_clcc(void *buf, uint16_t len, int fd)
218 {
219         if (cbs->clcc_cmd_cb) {
220 #if ANDROID_VERSION >= PLATFORM_VER(5, 0, 0)
221                 struct hal_ev_handsfree_clcc *ev = buf;
222
223                 cbs->clcc_cmd_cb((bt_bdaddr_t *) (ev->bdaddr));
224 #else
225                 cbs->clcc_cmd_cb();
226 #endif
227         }
228 }
229
230 static void handle_unknown_at(void *buf, uint16_t len, int fd)
231 {
232         struct hal_ev_handsfree_unknown_at *ev = buf;
233
234         if (len != sizeof(*ev) + ev->len ||
235                         (ev->len != 0 && ev->buf[ev->len - 1] != '\0')) {
236                 error("invalid unknown command event, aborting");
237                 exit(EXIT_FAILURE);
238         }
239
240         if (cbs->unknown_at_cmd_cb)
241 #if ANDROID_VERSION >= PLATFORM_VER(5, 0, 0)
242                 cbs->unknown_at_cmd_cb((char *) ev->buf,
243                                                 (bt_bdaddr_t *) (ev->bdaddr));
244 #else
245                 cbs->unknown_at_cmd_cb((char *) ev->buf);
246 #endif
247 }
248
249 static void handle_hsp_key_press(void *buf, uint16_t len, int fd)
250 {
251         if (cbs->key_pressed_cmd_cb) {
252 #if ANDROID_VERSION >= PLATFORM_VER(5, 0, 0)
253                 struct hal_ev_handsfree_hsp_key_press *ev = buf;
254
255                 cbs->key_pressed_cmd_cb((bt_bdaddr_t *) (ev->bdaddr));
256 #else
257                 cbs->key_pressed_cmd_cb();
258 #endif
259         }
260 }
261
262 /*
263  * handlers will be called from notification thread context,
264  * index in table equals to 'opcode - HAL_MINIMUM_EVENT'
265  */
266 static const struct hal_ipc_handler ev_handlers[] = {
267         /* HAL_EV_HANDSFREE_CONN_STATE */
268         { handle_conn_state, false,
269                                 sizeof(struct hal_ev_handsfree_conn_state) },
270         /* HAL_EV_HANDSFREE_AUDIO_STATE */
271         { handle_audio_state, false,
272                                 sizeof(struct hal_ev_handsfree_audio_state) },
273         /* HAL_EV_HANDSFREE_VR */
274         { handle_vr_state, false, sizeof(struct hal_ev_handsfree_vr_state) },
275         /* HAL_EV_HANDSFREE_ANSWER */
276         { handle_answer, false, sizeof(struct hal_ev_handsfree_answer) },
277         /* HAL_EV_HANDSFREE_HANGUP */
278         { handle_hangup, false, sizeof(struct hal_ev_handsfree_hangup) },
279         /* HAL_EV_HANDSFREE_VOLUME */
280         { handle_volume, false, sizeof(struct hal_ev_handsfree_volume) },
281         /* HAL_EV_HANDSFREE_DIAL */
282         { handle_dial, true, sizeof(struct hal_ev_handsfree_dial) },
283         /* HAL_EV_HANDSFREE_DTMF */
284         { handle_dtmf, false, sizeof(struct hal_ev_handsfree_dtmf) },
285         /* HAL_EV_HANDSFREE_NREC */
286         { handle_nrec, false, sizeof(struct hal_ev_handsfree_nrec) },
287         /* HAL_EV_HANDSFREE_CHLD */
288         { handle_chld, false, sizeof(struct hal_ev_handsfree_chld) },
289         /* HAL_EV_HANDSFREE_CNUM */
290         { handle_cnum, false, sizeof(struct hal_ev_handsfree_cnum) },
291         /* HAL_EV_HANDSFREE_CIND */
292         { handle_cind, false, sizeof(struct hal_ev_handsfree_cind) },
293         /* HAL_EV_HANDSFREE_COPS */
294         { handle_cops, false, sizeof(struct hal_ev_handsfree_cops) },
295         /* HAL_EV_HANDSFREE_CLCC */
296         { handle_clcc, false, sizeof(struct hal_ev_handsfree_clcc) },
297         /* HAL_EV_HANDSFREE_UNKNOWN_AT */
298         { handle_unknown_at, true, sizeof(struct hal_ev_handsfree_unknown_at) },
299         /* HAL_EV_HANDSFREE_HSP_KEY_PRESS */
300         { handle_hsp_key_press, false,
301                                 sizeof(struct hal_ev_handsfree_hsp_key_press) },
302         /* HAL_EV_HANDSFREE_WBS */
303         { handle_wbs, false, sizeof(struct hal_ev_handsfree_wbs) },
304 };
305
306 static uint8_t get_mode(void)
307 {
308         char value[PROPERTY_VALUE_MAX];
309
310         if (get_config("handsfree", value, NULL) > 0) {
311                 if (!strcasecmp(value, "hfp"))
312                         return HAL_MODE_HANDSFREE_HFP;
313
314                 if (!strcasecmp(value, "hfp_wbs"))
315                         return HAL_MODE_HANDSFREE_HFP_WBS;
316         }
317
318         return HAL_MODE_HANDSFREE_HSP_ONLY;
319 }
320
321 static bt_status_t init_real(bthf_callbacks_t *callbacks, int max_hf_clients)
322 {
323         struct hal_cmd_register_module cmd;
324         int ret;
325
326         DBG("");
327
328         if (interface_ready())
329                 return BT_STATUS_DONE;
330
331         cbs = callbacks;
332
333         hal_ipc_register(HAL_SERVICE_ID_HANDSFREE, ev_handlers,
334                                 sizeof(ev_handlers)/sizeof(ev_handlers[0]));
335
336         cmd.service_id = HAL_SERVICE_ID_HANDSFREE;
337         cmd.mode = get_mode();
338         cmd.max_clients = max_hf_clients;
339
340         ret = hal_ipc_cmd(HAL_SERVICE_ID_CORE, HAL_OP_REGISTER_MODULE,
341                                         sizeof(cmd), &cmd, NULL, NULL, NULL);
342
343         if (ret != BT_STATUS_SUCCESS) {
344                 cbs = NULL;
345                 hal_ipc_unregister(HAL_SERVICE_ID_HANDSFREE);
346         }
347
348         return ret;
349 }
350
351 #if ANDROID_VERSION >= PLATFORM_VER(5, 0, 0)
352 static bt_status_t init(bthf_callbacks_t *callbacks, int max_hf_clients)
353 {
354         return init_real(callbacks, max_hf_clients);
355 }
356 #else
357 static bt_status_t init(bthf_callbacks_t *callbacks)
358 {
359         return init_real(callbacks, 1);
360 }
361 #endif
362
363 static bt_status_t handsfree_connect(bt_bdaddr_t *bd_addr)
364 {
365         struct hal_cmd_handsfree_connect cmd;
366
367         DBG("");
368
369         if (!interface_ready())
370                 return BT_STATUS_NOT_READY;
371
372         if (!bd_addr)
373                 return BT_STATUS_PARM_INVALID;
374
375         memcpy(cmd.bdaddr, bd_addr, sizeof(cmd.bdaddr));
376
377         return hal_ipc_cmd(HAL_SERVICE_ID_HANDSFREE, HAL_OP_HANDSFREE_CONNECT,
378                                         sizeof(cmd), &cmd, NULL, NULL, NULL);
379 }
380
381 static bt_status_t disconnect(bt_bdaddr_t *bd_addr)
382 {
383         struct hal_cmd_handsfree_disconnect cmd;
384
385         DBG("");
386
387         if (!interface_ready())
388                 return BT_STATUS_NOT_READY;
389
390         if (!bd_addr)
391                 return BT_STATUS_PARM_INVALID;
392
393         memcpy(cmd.bdaddr, bd_addr, sizeof(cmd.bdaddr));
394
395         return hal_ipc_cmd(HAL_SERVICE_ID_HANDSFREE,
396                                 HAL_OP_HANDSFREE_DISCONNECT, sizeof(cmd), &cmd,
397                                 NULL, NULL, NULL);
398 }
399
400 static bt_status_t connect_audio(bt_bdaddr_t *bd_addr)
401 {
402         struct hal_cmd_handsfree_connect_audio cmd;
403
404         DBG("");
405
406         if (!interface_ready())
407                 return BT_STATUS_NOT_READY;
408
409         if (!bd_addr)
410                 return BT_STATUS_PARM_INVALID;
411
412         memcpy(cmd.bdaddr, bd_addr, sizeof(cmd.bdaddr));
413
414         return hal_ipc_cmd(HAL_SERVICE_ID_HANDSFREE,
415                                 HAL_OP_HANDSFREE_CONNECT_AUDIO, sizeof(cmd),
416                                 &cmd, NULL, NULL, NULL);
417 }
418
419 static bt_status_t disconnect_audio(bt_bdaddr_t *bd_addr)
420 {
421         struct hal_cmd_handsfree_disconnect_audio cmd;
422
423         DBG("");
424
425         if (!interface_ready())
426                 return BT_STATUS_NOT_READY;
427
428         if (!bd_addr)
429                 return BT_STATUS_PARM_INVALID;
430
431         memcpy(cmd.bdaddr, bd_addr, sizeof(cmd.bdaddr));
432
433         return hal_ipc_cmd(HAL_SERVICE_ID_HANDSFREE,
434                                 HAL_OP_HANDSFREE_DISCONNECT_AUDIO, sizeof(cmd),
435                                 &cmd, NULL, NULL, NULL);
436 }
437
438 static bt_status_t start_voice_recognition_real(bt_bdaddr_t *bd_addr)
439 {
440         struct hal_cmd_handsfree_start_vr cmd;
441
442         DBG("");
443
444         if (!interface_ready())
445                 return BT_STATUS_NOT_READY;
446
447         memset(&cmd, 0, sizeof(cmd));
448
449         if (bd_addr)
450                 memcpy(cmd.bdaddr, bd_addr, sizeof(cmd.bdaddr));
451
452         return hal_ipc_cmd(HAL_SERVICE_ID_HANDSFREE, HAL_OP_HANDSFREE_START_VR,
453                                         sizeof(cmd), &cmd, NULL, NULL, NULL);
454 }
455
456 #if ANDROID_VERSION >= PLATFORM_VER(5, 0, 0)
457 static bt_status_t start_voice_recognition(bt_bdaddr_t *bd_addr)
458 {
459         return start_voice_recognition_real(bd_addr);
460 }
461 #else
462 static bt_status_t start_voice_recognition(void)
463 {
464         return start_voice_recognition_real(NULL);
465 }
466 #endif
467
468 static bt_status_t stop_voice_recognition_real(bt_bdaddr_t *bd_addr)
469 {
470         struct hal_cmd_handsfree_stop_vr cmd;
471
472         DBG("");
473
474         if (!interface_ready())
475                 return BT_STATUS_NOT_READY;
476
477         memset(&cmd, 0, sizeof(cmd));
478
479         if (bd_addr)
480                 memcpy(cmd.bdaddr, bd_addr, sizeof(cmd.bdaddr));
481
482         return hal_ipc_cmd(HAL_SERVICE_ID_HANDSFREE, HAL_OP_HANDSFREE_STOP_VR,
483                                         sizeof(cmd), &cmd, NULL, NULL, NULL);
484 }
485
486 #if ANDROID_VERSION >= PLATFORM_VER(5, 0, 0)
487 static bt_status_t stop_voice_recognition(bt_bdaddr_t *bd_addr)
488 {
489         return stop_voice_recognition_real(bd_addr);
490 }
491 #else
492 static bt_status_t stop_voice_recognition(void)
493 {
494         return stop_voice_recognition_real(NULL);
495 }
496 #endif
497
498 static bt_status_t volume_control_real(bthf_volume_type_t type, int volume,
499                                                         bt_bdaddr_t *bd_addr)
500 {
501         struct hal_cmd_handsfree_volume_control cmd;
502
503         DBG("");
504
505         if (!interface_ready())
506                 return BT_STATUS_NOT_READY;
507
508         memset(&cmd, 0, sizeof(cmd));
509
510         cmd.type = type;
511         cmd.volume = volume;
512
513         if (bd_addr)
514                 memcpy(cmd.bdaddr, bd_addr, sizeof(cmd.bdaddr));
515
516         return hal_ipc_cmd(HAL_SERVICE_ID_HANDSFREE,
517                                 HAL_OP_HANDSFREE_VOLUME_CONTROL, sizeof(cmd),
518                                 &cmd, NULL, NULL, NULL);
519 }
520
521 #if ANDROID_VERSION >= PLATFORM_VER(5, 0, 0)
522 static bt_status_t volume_control(bthf_volume_type_t type, int volume,
523                                                         bt_bdaddr_t *bd_addr)
524 {
525         return volume_control_real(type, volume, bd_addr);
526 }
527 #else
528 static bt_status_t volume_control(bthf_volume_type_t type, int volume)
529 {
530         return volume_control_real(type, volume, NULL);
531 }
532 #endif
533
534 static bt_status_t device_status_notification(bthf_network_state_t state,
535                                                 bthf_service_type_t type,
536                                                 int signal, int battery)
537 {
538         struct hal_cmd_handsfree_device_status_notif cmd;
539
540         DBG("");
541
542         if (!interface_ready())
543                 return BT_STATUS_NOT_READY;
544
545         cmd.state = state;
546         cmd.type = type;
547         cmd.signal = signal;
548         cmd.battery = battery;
549
550         return hal_ipc_cmd(HAL_SERVICE_ID_HANDSFREE,
551                                         HAL_OP_HANDSFREE_DEVICE_STATUS_NOTIF,
552                                         sizeof(cmd), &cmd, NULL, NULL, NULL);
553 }
554
555 static bt_status_t cops_response_real(const char *cops, bt_bdaddr_t *bd_addr)
556 {
557         char buf[IPC_MTU];
558         struct hal_cmd_handsfree_cops_response *cmd = (void *) buf;
559         size_t len;
560
561         DBG("");
562
563         if (!interface_ready())
564                 return BT_STATUS_NOT_READY;
565
566         if (!cops)
567                 return BT_STATUS_PARM_INVALID;
568
569         memset(cmd, 0, sizeof(*cmd));
570
571         if (bd_addr)
572                 memcpy(cmd->bdaddr, bd_addr, sizeof(cmd->bdaddr));
573
574         /* Size of cmd.buf */
575         cmd->len = strlen(cops) + 1;
576         memcpy(cmd->buf, cops, cmd->len);
577
578         len = sizeof(*cmd) + cmd->len;
579
580         return hal_ipc_cmd(HAL_SERVICE_ID_HANDSFREE,
581                                                 HAL_OP_HANDSFREE_COPS_RESPONSE,
582                                                 len, cmd, NULL, NULL, NULL);
583 }
584
585 #if ANDROID_VERSION >= PLATFORM_VER(5, 0, 0)
586 static bt_status_t cops_response(const char *cops, bt_bdaddr_t *bd_addr)
587 {
588         return cops_response_real(cops, bd_addr);
589 }
590 #else
591 static bt_status_t cops_response(const char *cops)
592 {
593         return cops_response_real(cops, NULL);
594 }
595 #endif
596
597 static bt_status_t cind_response_real(int svc, int num_active, int num_held,
598                                         bthf_call_state_t state, int signal,
599                                         int roam, int batt_chg,
600                                         bt_bdaddr_t *bd_addr)
601 {
602         struct hal_cmd_handsfree_cind_response cmd;
603
604         DBG("");
605
606         if (!interface_ready())
607                 return BT_STATUS_NOT_READY;
608
609         memset(&cmd, 0, sizeof(cmd));
610
611         if (bd_addr)
612                 memcpy(cmd.bdaddr, bd_addr, sizeof(cmd.bdaddr));
613
614         cmd.svc = svc;
615         cmd.num_active = num_active;
616         cmd.num_held = num_held;
617         cmd.state = state;
618         cmd.signal = signal;
619         cmd.roam = roam;
620         cmd.batt_chg = batt_chg;
621
622         return hal_ipc_cmd(HAL_SERVICE_ID_HANDSFREE,
623                                         HAL_OP_HANDSFREE_CIND_RESPONSE,
624                                         sizeof(cmd), &cmd, NULL, NULL, NULL);
625 }
626
627 #if ANDROID_VERSION >= PLATFORM_VER(5, 0, 0)
628 static bt_status_t cind_response(int svc, int num_active, int num_held,
629                                         bthf_call_state_t state, int signal,
630                                         int roam, int batt_chg,
631                                         bt_bdaddr_t *bd_addr)
632 {
633         return cind_response_real(svc, num_active, num_held, state, signal,
634                                                 roam, batt_chg, bd_addr);
635 }
636 #else
637 static bt_status_t cind_response(int svc, int num_active, int num_held,
638                                         bthf_call_state_t state, int signal,
639                                         int roam, int batt_chg)
640 {
641         return cind_response_real(svc, num_active, num_held, state, signal,
642                                                 roam, batt_chg, NULL);
643 }
644 #endif
645
646 static bt_status_t formatted_at_response_real(const char *rsp,
647                                                         bt_bdaddr_t *bd_addr)
648 {
649         char buf[IPC_MTU];
650         struct hal_cmd_handsfree_formatted_at_response *cmd = (void *) buf;
651         size_t len;
652
653         DBG("");
654
655         if (!interface_ready())
656                 return BT_STATUS_NOT_READY;
657
658         if (!rsp)
659                 return BT_STATUS_PARM_INVALID;
660
661         memset(cmd, 0, sizeof(*cmd));
662
663         if (bd_addr)
664                 memcpy(cmd->bdaddr, bd_addr, sizeof(cmd->bdaddr));
665
666         cmd->len = strlen(rsp) + 1;
667         memcpy(cmd->buf, rsp, cmd->len);
668
669         len = sizeof(*cmd) + cmd->len;
670
671         return hal_ipc_cmd(HAL_SERVICE_ID_HANDSFREE,
672                                         HAL_OP_HANDSFREE_FORMATTED_AT_RESPONSE,
673                                         len, cmd, NULL, NULL, NULL);
674 }
675
676 #if ANDROID_VERSION >= PLATFORM_VER(5, 0, 0)
677 static bt_status_t formatted_at_response(const char *rsp, bt_bdaddr_t *bd_addr)
678 {
679         return formatted_at_response_real(rsp, bd_addr);
680 }
681 #else
682 static bt_status_t formatted_at_response(const char *rsp)
683 {
684         return formatted_at_response_real(rsp, NULL);
685 }
686 #endif
687
688 static bt_status_t at_response_real(bthf_at_response_t response, int error,
689                                                         bt_bdaddr_t *bd_addr)
690 {
691         struct hal_cmd_handsfree_at_response cmd;
692
693         DBG("");
694
695         if (!interface_ready())
696                 return BT_STATUS_NOT_READY;
697
698         if (bd_addr)
699                 memcpy(cmd.bdaddr, bd_addr, sizeof(cmd.bdaddr));
700
701         memset(&cmd, 0, sizeof(cmd));
702
703         cmd.response = response;
704         cmd.error = error;
705
706         return hal_ipc_cmd(HAL_SERVICE_ID_HANDSFREE,
707                                         HAL_OP_HANDSFREE_AT_RESPONSE,
708                                         sizeof(cmd), &cmd, NULL, NULL, NULL);
709 }
710
711 #if ANDROID_VERSION >= PLATFORM_VER(5, 0, 0)
712 static bt_status_t at_response(bthf_at_response_t response, int error,
713                                                         bt_bdaddr_t *bd_addr)
714 {
715         return at_response_real(response, error, bd_addr);
716 }
717 #else
718 static bt_status_t at_response(bthf_at_response_t response, int error)
719 {
720         return at_response_real(response, error, NULL);
721 }
722 #endif
723
724 static bt_status_t clcc_response_real(int index, bthf_call_direction_t dir,
725                                         bthf_call_state_t state,
726                                         bthf_call_mode_t mode,
727                                         bthf_call_mpty_type_t mpty,
728                                         const char *number,
729                                         bthf_call_addrtype_t type,
730                                         bt_bdaddr_t *bd_addr)
731 {
732         char buf[IPC_MTU];
733         struct hal_cmd_handsfree_clcc_response *cmd = (void *) buf;
734         size_t len;
735
736         DBG("");
737
738         if (!interface_ready())
739                 return BT_STATUS_NOT_READY;
740
741         memset(cmd, 0, sizeof(*cmd));
742
743         if (bd_addr)
744                 memcpy(cmd->bdaddr, bd_addr, sizeof(cmd->bdaddr));
745
746         cmd->index = index;
747         cmd->dir = dir;
748         cmd->state = state;
749         cmd->mode = mode;
750         cmd->mpty = mpty;
751         cmd->type = type;
752
753         if (number) {
754                 cmd->number_len = strlen(number) + 1;
755                 memcpy(cmd->number, number, cmd->number_len);
756         } else {
757                 cmd->number_len = 0;
758         }
759
760         len = sizeof(*cmd) + cmd->number_len;
761
762         return hal_ipc_cmd(HAL_SERVICE_ID_HANDSFREE,
763                                                 HAL_OP_HANDSFREE_CLCC_RESPONSE,
764                                                 len, cmd, NULL, NULL, NULL);
765 }
766
767 #if ANDROID_VERSION >= PLATFORM_VER(5, 0, 0)
768 static bt_status_t clcc_response(int index, bthf_call_direction_t dir,
769                                         bthf_call_state_t state,
770                                         bthf_call_mode_t mode,
771                                         bthf_call_mpty_type_t mpty,
772                                         const char *number,
773                                         bthf_call_addrtype_t type,
774                                         bt_bdaddr_t *bd_addr)
775 {
776         return clcc_response_real(index, dir, state, mode, mpty, number, type,
777                                                                 bd_addr);
778 }
779 #else
780 static bt_status_t clcc_response(int index, bthf_call_direction_t dir,
781                                         bthf_call_state_t state,
782                                         bthf_call_mode_t mode,
783                                         bthf_call_mpty_type_t mpty,
784                                         const char *number,
785                                         bthf_call_addrtype_t type)
786 {
787         return clcc_response_real(index, dir, state, mode, mpty, number, type,
788                                                                         NULL);
789 }
790 #endif
791
792 static bt_status_t phone_state_change(int num_active, int num_held,
793                                         bthf_call_state_t state,
794                                         const char *number,
795                                         bthf_call_addrtype_t type)
796 {
797         char buf[IPC_MTU];
798         struct hal_cmd_handsfree_phone_state_change *cmd = (void *) buf;
799         size_t len;
800
801         DBG("");
802
803         if (!interface_ready())
804                 return BT_STATUS_NOT_READY;
805
806         cmd->num_active = num_active;
807         cmd->num_held = num_held;
808         cmd->state = state;
809         cmd->type = type;
810
811         if (number) {
812                 cmd->number_len = strlen(number) + 1;
813                 memcpy(cmd->number, number, cmd->number_len);
814         } else {
815                 cmd->number_len = 0;
816         }
817
818         len = sizeof(*cmd) + cmd->number_len;
819
820         return hal_ipc_cmd(HAL_SERVICE_ID_HANDSFREE,
821                                         HAL_OP_HANDSFREE_PHONE_STATE_CHANGE,
822                                         len, cmd, NULL, NULL, NULL);
823 }
824
825 static void cleanup(void)
826 {
827         struct hal_cmd_unregister_module cmd;
828
829         DBG("");
830
831         if (!interface_ready())
832                 return;
833
834         cmd.service_id = HAL_SERVICE_ID_HANDSFREE;
835
836         hal_ipc_cmd(HAL_SERVICE_ID_CORE, HAL_OP_UNREGISTER_MODULE,
837                                         sizeof(cmd), &cmd, NULL, NULL, NULL);
838
839         hal_ipc_unregister(HAL_SERVICE_ID_HANDSFREE);
840
841         cbs = NULL;
842 }
843
844 #if ANDROID_VERSION >= PLATFORM_VER(5, 0, 0)
845 static bt_status_t configure_wbs(bt_bdaddr_t *bd_addr, bthf_wbs_config_t config)
846 {
847         struct hal_cmd_handsfree_configure_wbs cmd;
848
849         DBG("%u", config);
850
851         if (!interface_ready())
852                 return BT_STATUS_NOT_READY;
853
854         if (!bd_addr)
855                 return BT_STATUS_PARM_INVALID;
856
857         memcpy(cmd.bdaddr, bd_addr, sizeof(cmd.bdaddr));
858         cmd.config = config;
859
860         return hal_ipc_cmd(HAL_SERVICE_ID_HANDSFREE,
861                                         HAL_OP_HANDSFREE_CONFIGURE_WBS,
862                                         sizeof(cmd), &cmd, NULL, NULL, NULL);
863 }
864 #endif
865
866 static bthf_interface_t iface = {
867         .size = sizeof(iface),
868         .init = init,
869         .connect = handsfree_connect,
870         .disconnect = disconnect,
871         .connect_audio = connect_audio,
872         .disconnect_audio = disconnect_audio,
873         .start_voice_recognition = start_voice_recognition,
874         .stop_voice_recognition = stop_voice_recognition,
875         .volume_control = volume_control,
876         .device_status_notification = device_status_notification,
877         .cops_response = cops_response,
878         .cind_response = cind_response,
879         .formatted_at_response = formatted_at_response,
880         .at_response = at_response,
881         .clcc_response = clcc_response,
882         .phone_state_change = phone_state_change,
883         .cleanup = cleanup,
884 #if ANDROID_VERSION >= PLATFORM_VER(5, 0, 0)
885         .configure_wbs = configure_wbs,
886 #endif
887 };
888
889 bthf_interface_t *bt_get_handsfree_interface(void)
890 {
891         return &iface;
892 }