f921f835df6486e8dd12e4a7ad562b3b34e2d7d0
[platform/upstream/ofono.git] / src / handsfree.c
1 /*
2  *
3  *  oFono - Open Source Telephony
4  *
5  *  Copyright (C) 2008-2011  Intel Corporation. All rights reserved.
6  *  Copyright (C) 2011  BMW Car IT GmbH. All rights reserved.
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License version 2 as
10  *  published by the Free Software Foundation.
11  *
12  *  This program is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  *
17  *  You should have received a copy of the GNU General Public License
18  *  along with this program; if not, write to the Free Software
19  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20  *
21  */
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #define _GNU_SOURCE
28 #include <string.h>
29 #include <stdlib.h>
30 #include <stdio.h>
31 #include <errno.h>
32 #include <unistd.h>
33
34 #include <glib.h>
35
36 #include <ofono/log.h>
37 #include <ofono/modem.h>
38 #include <ofono/handsfree.h>
39
40 #include <gdbus.h>
41 #include "ofono.h"
42 #include "common.h"
43 #include "hfp.h"
44
45 static GSList *g_drivers = NULL;
46
47 #define HANDSFREE_FLAG_CACHED 0x1
48
49 struct ofono_handsfree {
50         ofono_bool_t nrec;
51         ofono_bool_t inband_ringing;
52         ofono_bool_t voice_recognition;
53         ofono_bool_t voice_recognition_pending;
54         unsigned int ag_features;
55         unsigned int ag_chld_features;
56         unsigned char battchg;
57         GSList *subscriber_numbers;
58
59         const struct ofono_handsfree_driver *driver;
60         void *driver_data;
61         struct ofono_atom *atom;
62         DBusMessage *pending;
63         int flags;
64 };
65
66 static const char **ag_features_list(unsigned int features,
67                                         unsigned int chld_features)
68 {
69         static const char *list[10];
70         unsigned int i = 0;
71
72         if (features & HFP_AG_FEATURE_3WAY)
73                 list[i++] = "three-way-calling";
74
75         if (features & HFP_AG_FEATURE_ECNR)
76                 list[i++] = "echo-canceling-and-noise-reduction";
77
78         if (features & HFP_AG_FEATURE_VOICE_RECOG)
79                 list[i++] = "voice-recognition";
80
81         if (features & HFP_AG_FEATURE_ATTACH_VOICE_TAG)
82                 list[i++] = "attach-voice-tag";
83
84         if (chld_features & HFP_AG_CHLD_0)
85                 list[i++] = "release-all-held";
86
87         if (chld_features & HFP_AG_CHLD_1x)
88                 list[i++] = "release-specified-active-call";
89
90         if (chld_features & HFP_AG_CHLD_2x)
91                 list[i++] = "private-chat";
92
93         if (chld_features & HFP_AG_CHLD_3)
94                 list[i++] = "create-multiparty";
95
96         if (chld_features & HFP_AG_CHLD_4)
97                 list[i++] = "transfer";
98
99         list[i] = NULL;
100
101         return list;
102 }
103
104 void ofono_handsfree_set_inband_ringing(struct ofono_handsfree *hf,
105                                                 ofono_bool_t enabled)
106 {
107         DBusConnection *conn = ofono_dbus_get_connection();
108         const char *path = __ofono_atom_get_path(hf->atom);
109         dbus_bool_t dbus_enabled = enabled;
110
111         if (hf->inband_ringing == enabled)
112                 return;
113
114         hf->inband_ringing = enabled;
115
116         if (__ofono_atom_get_registered(hf->atom) == FALSE)
117                 return;
118
119         ofono_dbus_signal_property_changed(conn, path,
120                                         OFONO_HANDSFREE_INTERFACE,
121                                         "InbandRinging", DBUS_TYPE_BOOLEAN,
122                                         &dbus_enabled);
123 }
124
125 void ofono_handsfree_voice_recognition_notify(struct ofono_handsfree *hf,
126                                                 ofono_bool_t enabled)
127 {
128         DBusConnection *conn = ofono_dbus_get_connection();
129         const char *path = __ofono_atom_get_path(hf->atom);
130         dbus_bool_t dbus_enabled = enabled;
131
132         if (hf->voice_recognition == enabled)
133                 return;
134
135         hf->voice_recognition = enabled;
136
137         ofono_dbus_signal_property_changed(conn, path,
138                                         OFONO_HANDSFREE_INTERFACE,
139                                         "VoiceRecognition", DBUS_TYPE_BOOLEAN,
140                                         &dbus_enabled);
141 }
142
143 void ofono_handsfree_set_ag_features(struct ofono_handsfree *hf,
144                                         unsigned int ag_features)
145 {
146         if (hf == NULL)
147                 return;
148
149         hf->ag_features = ag_features;
150 }
151
152 void ofono_handsfree_set_ag_chld_features(struct ofono_handsfree *hf,
153                                         unsigned int ag_chld_features)
154 {
155         if (hf == NULL)
156                 return;
157
158         hf->ag_chld_features = ag_chld_features;
159 }
160
161 void ofono_handsfree_battchg_notify(struct ofono_handsfree *hf,
162                                         unsigned char level)
163 {
164         DBusConnection *conn = ofono_dbus_get_connection();
165         const char *path = __ofono_atom_get_path(hf->atom);
166
167         if (hf == NULL)
168                 return;
169
170         if (hf->battchg == level)
171                 return;
172
173         hf->battchg = level;
174
175         if (__ofono_atom_get_registered(hf->atom) == FALSE)
176                 return;
177
178         ofono_dbus_signal_property_changed(conn, path,
179                                         OFONO_HANDSFREE_INTERFACE,
180                                         "BatteryChargeLevel", DBUS_TYPE_BYTE,
181                                         &level);
182 }
183
184 static gboolean ofono_handsfree_is_busy(struct ofono_handsfree *hf)
185 {
186         return hf->pending ? TRUE : FALSE;
187 }
188
189 static void ofono_append_subscriber_numbers(GSList *subscriber_numbers,
190                                                 DBusMessageIter *iter)
191 {
192         DBusMessageIter entry;
193         DBusMessageIter variant, array;
194         int i;
195         GSList *l;
196         const char *subscriber_number_string;
197         char arraysig[3];
198         char *subscriber_number_text = "SubscriberNumbers";
199
200         arraysig[0] = DBUS_TYPE_ARRAY;
201         arraysig[1] = DBUS_TYPE_STRING;
202         arraysig[2] = '\0';
203
204         dbus_message_iter_open_container(iter, DBUS_TYPE_DICT_ENTRY,
205                                         NULL, &entry);
206         dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING,
207                                         &subscriber_number_text);
208         dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
209                                         arraysig, &variant);
210         dbus_message_iter_open_container(&variant, DBUS_TYPE_ARRAY,
211                                         DBUS_TYPE_STRING_AS_STRING, &array);
212
213         for (i = 0, l = subscriber_numbers; l; l = l->next, i++) {
214                 subscriber_number_string = phone_number_to_string(l->data);
215                 dbus_message_iter_append_basic(&array, DBUS_TYPE_STRING,
216                                                 &subscriber_number_string);
217         }
218
219         dbus_message_iter_close_container(&variant, &array);
220
221         dbus_message_iter_close_container(&entry, &variant);
222         dbus_message_iter_close_container(iter, &entry);
223 }
224
225 static DBusMessage *generate_get_properties_reply(struct ofono_handsfree *hf,
226                                                 DBusMessage *msg)
227 {
228         DBusMessage *reply;
229         DBusMessageIter iter;
230         DBusMessageIter dict;
231         dbus_bool_t inband_ringing;
232         dbus_bool_t voice_recognition;
233         const char **features;
234
235         reply = dbus_message_new_method_return(msg);
236         if (reply == NULL)
237                 return NULL;
238
239         dbus_message_iter_init_append(reply, &iter);
240
241         dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
242                                         OFONO_PROPERTIES_ARRAY_SIGNATURE,
243                                         &dict);
244
245         inband_ringing = hf->inband_ringing;
246         ofono_dbus_dict_append(&dict, "InbandRinging", DBUS_TYPE_BOOLEAN,
247                                 &inband_ringing);
248
249         if (hf->ag_features & HFP_AG_FEATURE_ECNR)
250                 ofono_dbus_dict_append(&dict, "EchoCancelingNoiseReduction",
251                                                 DBUS_TYPE_BOOLEAN, &hf->nrec);
252
253         voice_recognition = hf->voice_recognition;
254         ofono_dbus_dict_append(&dict, "VoiceRecognition", DBUS_TYPE_BOOLEAN,
255                                 &voice_recognition);
256
257         features = ag_features_list(hf->ag_features, hf->ag_chld_features);
258         ofono_dbus_dict_append_array(&dict, "Features", DBUS_TYPE_STRING,
259                                         &features);
260
261         ofono_dbus_dict_append(&dict, "BatteryChargeLevel", DBUS_TYPE_BYTE,
262                                 &hf->battchg);
263
264         if (hf->subscriber_numbers)
265                 ofono_append_subscriber_numbers(hf->subscriber_numbers, &dict);
266
267         dbus_message_iter_close_container(&iter, &dict);
268
269         return reply;
270 }
271
272 static void hf_cnum_callback(const struct ofono_error *error, int total,
273                                 const struct ofono_phone_number *numbers,
274                                 void *data)
275 {
276         struct ofono_handsfree *hf = data;
277         int num;
278         struct ofono_phone_number *subscriber_number_string;
279
280         if (error->type != OFONO_ERROR_TYPE_NO_ERROR)
281                 goto out;
282
283         for (num = 0; num < total; num++) {
284                 subscriber_number_string = g_new0(struct ofono_phone_number, 1);
285
286                 subscriber_number_string->type = numbers[num].type;
287                 strncpy(subscriber_number_string->number, numbers[num].number,
288                                         OFONO_MAX_PHONE_NUMBER_LENGTH+1);
289
290                 hf->subscriber_numbers = g_slist_prepend(hf->subscriber_numbers,
291                                         subscriber_number_string);
292         }
293
294         hf->subscriber_numbers = g_slist_reverse(hf->subscriber_numbers);
295
296 out:
297         hf->flags |= HANDSFREE_FLAG_CACHED;
298
299         if (hf->pending) {
300                 DBusMessage *reply =
301                         generate_get_properties_reply(hf, hf->pending);
302                 __ofono_dbus_pending_reply(&hf->pending, reply);
303         }
304 }
305
306 static void query_cnum(struct ofono_handsfree *hf)
307 {
308         if (hf->driver->cnum_query == NULL) {
309                 if (hf->pending) {
310                         DBusMessage *reply =
311                                 generate_get_properties_reply(hf, hf->pending);
312                         __ofono_dbus_pending_reply(&hf->pending, reply);
313                 }
314
315                 return;
316         }
317
318         hf->driver->cnum_query(hf, hf_cnum_callback, hf);
319 }
320
321 static DBusMessage *handsfree_get_properties(DBusConnection *conn,
322                                                 DBusMessage *msg, void *data)
323 {
324         struct ofono_handsfree *hf = data;
325
326         if (ofono_handsfree_is_busy(hf))
327                 return __ofono_error_busy(msg);
328
329         if (hf->flags & HANDSFREE_FLAG_CACHED)
330                 return generate_get_properties_reply(hf, msg);
331
332         /* Query the settings and report back */
333         hf->pending = dbus_message_ref(msg);
334
335         query_cnum(hf);
336
337         return NULL;
338 }
339
340 static void voicerec_set_cb(const struct ofono_error *error, void *data)
341 {
342         struct ofono_handsfree *hf = data;
343         DBusConnection *conn = ofono_dbus_get_connection();
344         const char *path = __ofono_atom_get_path(hf->atom);
345
346         if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
347                 __ofono_dbus_pending_reply(&hf->pending,
348                                         __ofono_error_failed(hf->pending));
349                 return;
350         }
351
352         hf->voice_recognition = hf->voice_recognition_pending;
353
354         __ofono_dbus_pending_reply(&hf->pending,
355                                 dbus_message_new_method_return(hf->pending));
356
357         ofono_dbus_signal_property_changed(conn, path,
358                                         OFONO_HANDSFREE_INTERFACE,
359                                         "VoiceRecognition",
360                                         DBUS_TYPE_BOOLEAN,
361                                         &hf->voice_recognition);
362 }
363
364 static void nrec_set_cb(const struct ofono_error *error, void *data)
365 {
366         struct ofono_handsfree *hf = data;
367         DBusConnection *conn = ofono_dbus_get_connection();
368         const char *path = __ofono_atom_get_path(hf->atom);
369
370         if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
371                 __ofono_dbus_pending_reply(&hf->pending,
372                                         __ofono_error_failed(hf->pending));
373                 return;
374         }
375
376         hf->nrec = FALSE;
377
378         __ofono_dbus_pending_reply(&hf->pending,
379                                 dbus_message_new_method_return(hf->pending));
380
381         ofono_dbus_signal_property_changed(conn, path,
382                                         OFONO_HANDSFREE_INTERFACE,
383                                         "EchoCancelingNoiseReduction",
384                                         DBUS_TYPE_BOOLEAN,
385                                         &hf->nrec);
386 }
387
388 static DBusMessage *handsfree_set_property(DBusConnection *conn,
389                                                 DBusMessage *msg, void *data)
390 {
391         struct ofono_handsfree *hf = data;
392         DBusMessageIter iter, var;
393         ofono_bool_t enabled;
394         const char *name;
395
396         if (hf->pending)
397                 return __ofono_error_busy(msg);
398
399         if (dbus_message_iter_init(msg, &iter) == FALSE)
400                 return __ofono_error_invalid_args(msg);
401
402         if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
403                 return __ofono_error_invalid_args(msg);
404
405         dbus_message_iter_get_basic(&iter, &name);
406         dbus_message_iter_next(&iter);
407
408         if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
409                 return __ofono_error_invalid_args(msg);
410
411         dbus_message_iter_recurse(&iter, &var);
412
413         if (dbus_message_iter_get_arg_type(&var) != DBUS_TYPE_BOOLEAN)
414                 return __ofono_error_invalid_args(msg);
415
416         dbus_message_iter_get_basic(&var, &enabled);
417
418         if (g_str_equal(name, "VoiceRecognition") == TRUE) {
419
420                 if (!hf->driver->voice_recognition)
421                         return __ofono_error_not_implemented(msg);
422
423                 if (hf->voice_recognition == enabled)
424                         return dbus_message_new_method_return(msg);
425
426                 hf->voice_recognition_pending = enabled;
427                 hf->pending = dbus_message_ref(msg);
428                 hf->driver->voice_recognition(hf, enabled, voicerec_set_cb, hf);
429         } else if (g_str_equal(name, "EchoCancelingNoiseReduction") == TRUE) {
430
431                 if (!(hf->ag_features & HFP_AG_FEATURE_ECNR))
432                         return __ofono_error_not_supported(msg);
433
434                 if (!hf->driver->disable_nrec || enabled == TRUE)
435                         return __ofono_error_not_implemented(msg);
436
437                 if (hf->nrec == FALSE)
438                         return dbus_message_new_method_return(msg);
439
440                 hf->pending = dbus_message_ref(msg);
441                 hf->driver->disable_nrec(hf, nrec_set_cb, hf);
442         } else
443                 return __ofono_error_invalid_args(msg);
444
445         return NULL;
446 }
447
448 static void request_phone_number_cb(const struct ofono_error *error,
449                                         const struct ofono_phone_number *number,
450                                         void *data)
451 {
452         struct ofono_handsfree *hf = data;
453         DBusMessage *reply;
454         const char *phone_number;
455
456         if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
457                 DBG("Phone number request callback returned error: %s",
458                         telephony_error_to_str(error));
459
460                 reply = __ofono_error_failed(hf->pending);
461                 __ofono_dbus_pending_reply(&hf->pending, reply);
462                 return;
463         }
464
465         phone_number = phone_number_to_string(number);
466         reply = dbus_message_new_method_return(hf->pending);
467         dbus_message_append_args(reply, DBUS_TYPE_STRING, &phone_number,
468                                         DBUS_TYPE_INVALID);
469         __ofono_dbus_pending_reply(&hf->pending, reply);
470 }
471
472 static DBusMessage *handsfree_request_phone_number(DBusConnection *conn,
473                                                 DBusMessage *msg, void *data)
474 {
475         struct ofono_handsfree *hf = data;
476
477         if (hf->pending)
478                 return __ofono_error_busy(msg);
479
480         if (!hf->driver->request_phone_number)
481                 return __ofono_error_not_supported(msg);
482
483         hf->pending = dbus_message_ref(msg);
484         hf->driver->request_phone_number(hf, request_phone_number_cb, hf);
485
486         return NULL;
487 }
488
489 static const GDBusMethodTable handsfree_methods[] = {
490         { GDBUS_METHOD("GetProperties",
491                         NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
492                         handsfree_get_properties) },
493         { GDBUS_ASYNC_METHOD("SetProperty",
494                         GDBUS_ARGS({ "property", "s" }, { "value", "v" }),
495                         NULL, handsfree_set_property) },
496         { GDBUS_ASYNC_METHOD("RequestPhoneNumber",
497                         NULL, GDBUS_ARGS({ "number", "s" }),
498                         handsfree_request_phone_number) },
499         { }
500 };
501
502 static const GDBusSignalTable handsfree_signals[] = {
503         { GDBUS_SIGNAL("PropertyChanged",
504                         GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
505         { }
506 };
507
508 static void handsfree_remove(struct ofono_atom *atom)
509 {
510         struct ofono_handsfree *hf = __ofono_atom_get_data(atom);
511
512         DBG("atom: %p", atom);
513
514         if (hf == NULL)
515                 return;
516
517         if (hf->driver != NULL && hf->driver->remove != NULL)
518                 hf->driver->remove(hf);
519
520         g_free(hf);
521 }
522
523 struct ofono_handsfree *ofono_handsfree_create(struct ofono_modem *modem,
524                                         unsigned int vendor,
525                                         const char *driver,
526                                         void *data)
527 {
528         struct ofono_handsfree *hf;
529         GSList *l;
530
531         if (driver == NULL)
532                 return NULL;
533
534         hf = g_try_new0(struct ofono_handsfree, 1);
535         if (hf == NULL)
536                 return NULL;
537
538         hf->atom = __ofono_modem_add_atom(modem,
539                                         OFONO_ATOM_TYPE_HANDSFREE,
540                                         handsfree_remove, hf);
541         hf->nrec = TRUE;
542
543         for (l = g_drivers; l; l = l->next) {
544                 const struct ofono_handsfree_driver *drv = l->data;
545
546                 if (g_strcmp0(drv->name, driver))
547                         continue;
548
549                 if (drv->probe(hf, vendor, data) < 0)
550                         continue;
551
552                 hf->driver = drv;
553                 break;
554         }
555
556         return hf;
557 }
558
559 static void handsfree_unregister(struct ofono_atom *atom)
560 {
561         DBusConnection *conn = ofono_dbus_get_connection();
562         struct ofono_modem *modem = __ofono_atom_get_modem(atom);
563         const char *path = __ofono_atom_get_path(atom);
564         struct ofono_handsfree *hf = __ofono_atom_get_data(atom);
565
566         if (hf->pending) {
567                 DBusMessage *reply = __ofono_error_failed(hf->pending);
568                 __ofono_dbus_pending_reply(&hf->pending, reply);
569         }
570
571         g_slist_foreach(hf->subscriber_numbers, (GFunc) g_free, NULL);
572         g_slist_free(hf->subscriber_numbers);
573         hf->subscriber_numbers = NULL;
574
575         ofono_modem_remove_interface(modem, OFONO_HANDSFREE_INTERFACE);
576         g_dbus_unregister_interface(conn, path,
577                                         OFONO_HANDSFREE_INTERFACE);
578 }
579
580 void ofono_handsfree_register(struct ofono_handsfree *hf)
581 {
582         DBusConnection *conn = ofono_dbus_get_connection();
583         struct ofono_modem *modem = __ofono_atom_get_modem(hf->atom);
584         const char *path = __ofono_atom_get_path(hf->atom);
585
586         if (!g_dbus_register_interface(conn, path,
587                                         OFONO_HANDSFREE_INTERFACE,
588                                         handsfree_methods, handsfree_signals,
589                                         NULL, hf, NULL)) {
590                 ofono_error("Could not create %s interface",
591                                         OFONO_HANDSFREE_INTERFACE);
592
593                 return;
594         }
595
596         ofono_modem_add_interface(modem, OFONO_HANDSFREE_INTERFACE);
597
598         __ofono_atom_register(hf->atom, handsfree_unregister);
599 }
600
601 int ofono_handsfree_driver_register(const struct ofono_handsfree_driver *d)
602 {
603         DBG("driver: %p, name: %s", d, d->name);
604
605         if (d->probe == NULL)
606                 return -EINVAL;
607
608         g_drivers = g_slist_prepend(g_drivers, (void *) d);
609
610         return 0;
611 }
612
613 void ofono_handsfree_driver_unregister(
614                                 const struct ofono_handsfree_driver *d)
615 {
616         DBG("driver: %p, name: %s", d, d->name);
617
618         g_drivers = g_slist_remove(g_drivers, (void *) d);
619 }
620
621 void ofono_handsfree_remove(struct ofono_handsfree *hf)
622 {
623         __ofono_atom_free(hf->atom);
624 }
625
626 void ofono_handsfree_set_data(struct ofono_handsfree *hf, void *data)
627 {
628         hf->driver_data = data;
629 }
630
631 void *ofono_handsfree_get_data(struct ofono_handsfree *hf)
632 {
633         return hf->driver_data;
634 }