6bc96580e9166160dadf52424690611c9ce3eedd
[platform/upstream/ofono.git] / src / call-settings.c
1 /*
2  *
3  *  oFono - Open Source Telephony
4  *
5  *  Copyright (C) 2008-2011  Intel Corporation. All rights reserved.
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License version 2 as
9  *  published by the Free Software Foundation.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <string.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <errno.h>
30
31 #include <glib.h>
32 #include <gdbus.h>
33
34 #include "ofono.h"
35
36 #include "common.h"
37
38 #define CALL_SETTINGS_FLAG_CACHED 0x1
39
40 static GSList *g_drivers = NULL;
41
42 /* 27.007 Section 7.7 */
43 enum clir_status {
44         CLIR_STATUS_NOT_PROVISIONED =           0,
45         CLIR_STATUS_PROVISIONED_PERMANENT =     1,
46         CLIR_STATUS_UNKNOWN =                   2,
47         CLIR_STATUS_TEMPORARY_RESTRICTED =      3,
48         CLIR_STATUS_TEMPORARY_ALLOWED =         4
49 };
50
51 /* 27.007 Section 7.6 */
52 enum clip_status {
53         CLIP_STATUS_NOT_PROVISIONED =           0,
54         CLIP_STATUS_PROVISIONED =               1,
55         CLIP_STATUS_UNKNOWN =                   2
56 };
57
58 /* 27.007 Section 7.30 */
59 enum cnap_status {
60         CNAP_STATUS_NOT_PROVISIONED =           0,
61         CNAP_STATUS_PROVISIONED =               1,
62         CNAP_STATUS_UNKNOWN =                   2
63 };
64
65 /* 27.007 Section 7.8 */
66 enum colp_status {
67         COLP_STATUS_NOT_PROVISIONED =           0,
68         COLP_STATUS_PROVISIONED =               1,
69         COLP_STATUS_UNKNOWN =                   2
70 };
71
72 /* 27.007 Section 7.9 */
73 enum cdip_status {
74         CDIP_STATUS_NOT_PROVISIONED =           0,
75         CDIP_STATUS_PROVISIONED =               1,
76         CDIP_STATUS_UNKNOWN =                   2
77 };
78
79 /* This is not defined in 27.007, but presumably the same as CLIP/COLP */
80 enum colr_status {
81         COLR_STATUS_NOT_PROVISIONED =           0,
82         COLR_STATUS_PROVISIONED =               1,
83         COLR_STATUS_UNKNOWN =                   2
84 };
85
86 enum call_setting_type {
87         CALL_SETTING_TYPE_CLIP = 0,
88         CALL_SETTING_TYPE_CNAP,
89         CALL_SETTING_TYPE_CDIP,
90         CALL_SETTING_TYPE_COLP,
91         CALL_SETTING_TYPE_COLR,
92         CALL_SETTING_TYPE_CLIR,
93         CALL_SETTING_TYPE_CW
94 };
95
96 struct ofono_call_settings {
97         int clir;
98         int colr;
99         int clip;
100         int cnap;
101         int cdip;
102         int colp;
103         int clir_setting;
104         int cw;
105         int flags;
106         DBusMessage *pending;
107         int ss_req_type;
108         int ss_req_cls;
109         enum call_setting_type ss_setting;
110         struct ofono_ussd *ussd;
111         unsigned int ussd_watch;
112         const struct ofono_call_settings_driver *driver;
113         void *driver_data;
114         struct ofono_atom *atom;
115 };
116
117 static const char *clip_status_to_string(int status)
118 {
119         switch (status) {
120         case CLIP_STATUS_NOT_PROVISIONED:
121                 return "disabled";
122         case CLIP_STATUS_PROVISIONED:
123                 return "enabled";
124         }
125
126         return "unknown";
127 }
128
129 static const char *cdip_status_to_string(int status)
130 {
131         switch (status) {
132         case CDIP_STATUS_NOT_PROVISIONED:
133                 return "disabled";
134         case CDIP_STATUS_PROVISIONED:
135                 return "enabled";
136         }
137
138         return "unknown";
139 }
140
141 static const char *cnap_status_to_string(int status)
142 {
143         switch (status) {
144         case CNAP_STATUS_NOT_PROVISIONED:
145                 return "disabled";
146         case CNAP_STATUS_PROVISIONED:
147                 return "enabled";
148         }
149
150         return "unknown";
151 }
152
153 static const char *colp_status_to_string(int status)
154 {
155         switch (status) {
156         case COLP_STATUS_NOT_PROVISIONED:
157                 return "disabled";
158         case COLP_STATUS_PROVISIONED:
159                 return "enabled";
160         }
161
162         return "unknown";
163 }
164
165 static const char *colr_status_to_string(int status)
166 {
167         switch (status) {
168         case COLR_STATUS_NOT_PROVISIONED:
169                 return "disabled";
170         case COLR_STATUS_PROVISIONED:
171                 return "enabled";
172         }
173
174         return "unknown";
175 }
176
177 static const char *hide_callerid_to_string(int status)
178 {
179         switch (status) {
180         case OFONO_CLIR_OPTION_DEFAULT:
181                 return "default";
182         case OFONO_CLIR_OPTION_INVOCATION:
183                 return "enabled";
184         case OFONO_CLIR_OPTION_SUPPRESSION:
185                 return "disabled";
186         }
187
188         return "default";
189 }
190
191 static const char *clir_status_to_string(int status)
192 {
193         switch (status) {
194         case CLIR_STATUS_NOT_PROVISIONED:
195                 return "disabled";
196         case CLIR_STATUS_PROVISIONED_PERMANENT:
197                 return "permanent";
198         case CLIR_STATUS_TEMPORARY_RESTRICTED:
199                 return "on";
200         case CLIR_STATUS_TEMPORARY_ALLOWED:
201                 return "off";
202         }
203
204         return "unknown";
205 }
206
207 static void set_clir_network(struct ofono_call_settings *cs, int clir)
208 {
209         DBusConnection *conn;
210         const char *path;
211         const char *str;
212
213         if (cs->clir == clir)
214                 return;
215
216         cs->clir = clir;
217
218         conn = ofono_dbus_get_connection();
219         path = __ofono_atom_get_path(cs->atom);
220
221         str = clir_status_to_string(clir);
222
223         ofono_dbus_signal_property_changed(conn, path,
224                                                 OFONO_CALL_SETTINGS_INTERFACE,
225                                                 "CallingLineRestriction",
226                                                 DBUS_TYPE_STRING, &str);
227 }
228
229 static void set_clir_override(struct ofono_call_settings *cs, int override)
230 {
231         DBusConnection *conn;
232         const char *path;
233         const char *str;
234
235         if (cs->clir_setting == override)
236                 return;
237
238         cs->clir_setting = override;
239
240         conn = ofono_dbus_get_connection();
241         path = __ofono_atom_get_path(cs->atom);
242
243         str = hide_callerid_to_string(override);
244
245         ofono_dbus_signal_property_changed(conn, path,
246                                                 OFONO_CALL_SETTINGS_INTERFACE,
247                                                 "HideCallerId",
248                                                 DBUS_TYPE_STRING, &str);
249 }
250
251 static void set_cdip(struct ofono_call_settings *cs, int cdip)
252 {
253         DBusConnection *conn;
254         const char *path;
255         const char *str;
256
257         if (cs->cdip == cdip)
258                 return;
259
260         cs->cdip = cdip;
261
262         conn = ofono_dbus_get_connection();
263         path = __ofono_atom_get_path(cs->atom);
264
265         str = cdip_status_to_string(cdip);
266
267         ofono_dbus_signal_property_changed(conn, path,
268                                                 OFONO_CALL_SETTINGS_INTERFACE,
269                                                 "CalledLinePresentation",
270                                                 DBUS_TYPE_STRING, &str);
271 }
272
273 static void set_clip(struct ofono_call_settings *cs, int clip)
274 {
275         DBusConnection *conn;
276         const char *path;
277         const char *str;
278
279         if (cs->clip == clip)
280                 return;
281
282         cs->clip = clip;
283
284         conn = ofono_dbus_get_connection();
285         path = __ofono_atom_get_path(cs->atom);
286
287         str = clip_status_to_string(clip);
288
289         ofono_dbus_signal_property_changed(conn, path,
290                                                 OFONO_CALL_SETTINGS_INTERFACE,
291                                                 "CallingLinePresentation",
292                                                 DBUS_TYPE_STRING, &str);
293 }
294
295 static void set_cnap(struct ofono_call_settings *cs, int cnap)
296 {
297         DBusConnection *conn;
298         const char *path;
299         const char *str;
300
301         if (cs->cnap == cnap)
302                 return;
303
304         cs->cnap = cnap;
305
306         conn = ofono_dbus_get_connection();
307         path = __ofono_atom_get_path(cs->atom);
308
309         str = cnap_status_to_string(cnap);
310
311         ofono_dbus_signal_property_changed(conn, path,
312                                                 OFONO_CALL_SETTINGS_INTERFACE,
313                                                 "CallingNamePresentation",
314                                                 DBUS_TYPE_STRING, &str);
315 }
316
317 static void set_colp(struct ofono_call_settings *cs, int colp)
318 {
319         DBusConnection *conn;
320         const char *path;
321         const char *str;
322
323         if (cs->colp == colp)
324                 return;
325
326         cs->colp = colp;
327
328         conn = ofono_dbus_get_connection();
329         path = __ofono_atom_get_path(cs->atom);
330
331         str = colp_status_to_string(colp);
332
333         ofono_dbus_signal_property_changed(conn, path,
334                                                 OFONO_CALL_SETTINGS_INTERFACE,
335                                                 "ConnectedLinePresentation",
336                                                 DBUS_TYPE_STRING, &str);
337 }
338
339 static void set_colr(struct ofono_call_settings *cs, int colr)
340 {
341         DBusConnection *conn;
342         const char *path;
343         const char *str;
344
345         if (cs->colr == colr)
346                 return;
347
348         cs->colr = colr;
349
350         conn = ofono_dbus_get_connection();
351         path = __ofono_atom_get_path(cs->atom);
352
353         str = colr_status_to_string(colr);
354
355         ofono_dbus_signal_property_changed(conn, path,
356                                                 OFONO_CALL_SETTINGS_INTERFACE,
357                                                 "ConnectedLineRestriction",
358                                                 DBUS_TYPE_STRING, &str);
359 }
360
361 static void set_cw(struct ofono_call_settings *cs, int new_cw, int mask)
362 {
363         DBusConnection *conn = ofono_dbus_get_connection();
364         const char *path = __ofono_atom_get_path(cs->atom);
365         char buf[64];
366         int j;
367         const char *value;
368
369         for (j = 1; j <= BEARER_CLASS_PAD; j = j << 1) {
370                 if ((j & mask) == 0)
371                         continue;
372
373                 if ((cs->cw & j) == (new_cw & j))
374                         continue;
375
376                 if (new_cw & j)
377                         value = "enabled";
378                 else
379                         value = "disabled";
380
381                 snprintf(buf, sizeof(buf), "%sCallWaiting",
382                                 bearer_class_to_string(j));
383                 ofono_dbus_signal_property_changed(conn, path,
384                                                 OFONO_CALL_SETTINGS_INTERFACE,
385                                                 buf, DBUS_TYPE_STRING,
386                                                 &value);
387         }
388
389         cs->cw = new_cw;
390 }
391
392 static void property_append_cw_conditions(DBusMessageIter *dict,
393                                                 int conditions, int mask)
394 {
395         int i;
396         char prop[128];
397         const char *value;
398
399         for (i = 1; i <= BEARER_CLASS_PAD; i = i << 1) {
400                 if (!(mask & i))
401                         continue;
402
403                 snprintf(prop, sizeof(prop), "%sCallWaiting",
404                                 bearer_class_to_string(i));
405
406                 if (conditions & i)
407                         value = "enabled";
408                 else
409                         value = "disabled";
410
411                 ofono_dbus_dict_append(dict, prop, DBUS_TYPE_STRING, &value);
412         }
413 }
414
415 static void generate_cw_ss_query_reply(struct ofono_call_settings *cs)
416 {
417         const char *sig = "(sa{sv})";
418         const char *ss_type = ss_control_type_to_string(cs->ss_req_type);
419         const char *context = "CallWaiting";
420         DBusMessageIter iter;
421         DBusMessageIter var;
422         DBusMessageIter vstruct;
423         DBusMessageIter dict;
424         DBusMessage *reply;
425
426         reply = dbus_message_new_method_return(cs->pending);
427
428         dbus_message_iter_init_append(reply, &iter);
429
430         dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &context);
431
432         dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT, sig, &var);
433
434         dbus_message_iter_open_container(&var, DBUS_TYPE_STRUCT, NULL,
435                                                 &vstruct);
436
437         dbus_message_iter_append_basic(&vstruct, DBUS_TYPE_STRING,
438                                         &ss_type);
439
440         dbus_message_iter_open_container(&vstruct, DBUS_TYPE_ARRAY,
441                                         OFONO_PROPERTIES_ARRAY_SIGNATURE,
442                                         &dict);
443
444         property_append_cw_conditions(&dict, cs->cw, cs->ss_req_cls);
445
446         dbus_message_iter_close_container(&vstruct, &dict);
447
448         dbus_message_iter_close_container(&var, &vstruct);
449
450         dbus_message_iter_close_container(&iter, &var);
451
452         __ofono_dbus_pending_reply(&cs->pending, reply);
453 }
454
455 static void cw_ss_query_callback(const struct ofono_error *error, int status,
456                                         void *data)
457 {
458         struct ofono_call_settings *cs = data;
459
460         if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
461                 DBG("setting CW via SS failed");
462
463                 cs->flags &= ~CALL_SETTINGS_FLAG_CACHED;
464                 __ofono_dbus_pending_reply(&cs->pending,
465                                         __ofono_error_failed(cs->pending));
466
467                 return;
468         }
469
470         set_cw(cs, status, BEARER_CLASS_VOICE);
471
472         generate_cw_ss_query_reply(cs);
473 }
474
475 static void cw_ss_set_callback(const struct ofono_error *error, void *data)
476 {
477         struct ofono_call_settings *cs = data;
478
479         if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
480                 DBG("setting CW via SS failed");
481                 __ofono_dbus_pending_reply(&cs->pending,
482                                         __ofono_error_failed(cs->pending));
483
484                 return;
485         }
486
487         cs->driver->cw_query(cs, BEARER_CLASS_DEFAULT,
488                                 cw_ss_query_callback, cs);
489 }
490
491 static gboolean cw_ss_control(int type,
492                                 const char *sc, const char *sia,
493                                 const char *sib, const char *sic,
494                                 const char *dn, DBusMessage *msg, void *data)
495 {
496         struct ofono_call_settings *cs = data;
497         DBusConnection *conn = ofono_dbus_get_connection();
498         int cls = BEARER_CLASS_SS_DEFAULT;
499         DBusMessage *reply;
500
501         if (cs == NULL)
502                 return FALSE;
503
504         if (strcmp(sc, "43"))
505                 return FALSE;
506
507         if (__ofono_call_settings_is_busy(cs)) {
508                 reply = __ofono_error_busy(msg);
509                 goto error;
510         }
511
512         if (strlen(sib) || strlen(sib) || strlen(dn))
513                 goto bad_format;
514
515         if ((type == SS_CONTROL_TYPE_QUERY && cs->driver->cw_query == NULL) ||
516                 (type != SS_CONTROL_TYPE_QUERY && cs->driver->cw_set == NULL)) {
517                 reply = __ofono_error_not_implemented(msg);
518                 goto error;
519         }
520
521         if (strlen(sia) > 0) {
522                 long service_code;
523                 char *end;
524
525                 service_code = strtoul(sia, &end, 10);
526
527                 if (end == sia || *end != '\0')
528                         goto bad_format;
529
530                 cls = mmi_service_code_to_bearer_class(service_code);
531                 if (cls == 0)
532                         goto bad_format;
533         }
534
535         cs->ss_req_cls = cls;
536         cs->pending = dbus_message_ref(msg);
537
538         /* For the default case use the more readily accepted value */
539         if (cls == BEARER_CLASS_SS_DEFAULT)
540                 cls = BEARER_CLASS_DEFAULT;
541
542         switch (type) {
543         case SS_CONTROL_TYPE_REGISTRATION:
544         case SS_CONTROL_TYPE_ACTIVATION:
545                 cs->ss_req_type = SS_CONTROL_TYPE_ACTIVATION;
546                 cs->driver->cw_set(cs, 1, cls, cw_ss_set_callback, cs);
547                 break;
548
549         case SS_CONTROL_TYPE_QUERY:
550                 cs->ss_req_type = SS_CONTROL_TYPE_QUERY;
551                 /*
552                  * Always query the entire set, SMS not applicable
553                  * according to 22.004 Appendix A, so CLASS_DEFAULT
554                  * is safe to use here
555                  */
556                 cs->driver->cw_query(cs, BEARER_CLASS_DEFAULT,
557                                         cw_ss_query_callback, cs);
558                 break;
559
560         case SS_CONTROL_TYPE_DEACTIVATION:
561         case SS_CONTROL_TYPE_ERASURE:
562                 cs->ss_req_type = SS_CONTROL_TYPE_DEACTIVATION;
563                 cs->driver->cw_set(cs, 0, cls, cw_ss_set_callback, cs);
564                 break;
565         }
566
567         return TRUE;
568
569 bad_format:
570         reply = __ofono_error_invalid_format(msg);
571 error:
572         g_dbus_send_message(conn, reply);
573         return TRUE;
574 }
575
576 static void generate_ss_query_reply(struct ofono_call_settings *cs,
577                                         const char *context, const char *value)
578 {
579         const char *sig = "(ss)";
580         const char *ss_type = ss_control_type_to_string(cs->ss_req_type);
581         DBusMessageIter iter;
582         DBusMessageIter var;
583         DBusMessageIter vstruct;
584         DBusMessage *reply;
585
586         reply = dbus_message_new_method_return(cs->pending);
587
588         dbus_message_iter_init_append(reply, &iter);
589
590         dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &context);
591
592         dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT, sig, &var);
593
594         dbus_message_iter_open_container(&var, DBUS_TYPE_STRUCT, NULL,
595                                                 &vstruct);
596
597         dbus_message_iter_append_basic(&vstruct, DBUS_TYPE_STRING,
598                                         &ss_type);
599
600         dbus_message_iter_append_basic(&vstruct, DBUS_TYPE_STRING, &value);
601
602         dbus_message_iter_close_container(&var, &vstruct);
603
604         dbus_message_iter_close_container(&iter, &var);
605
606         __ofono_dbus_pending_reply(&cs->pending, reply);
607 }
608
609 static void clip_cnap_colp_colr_ss_query_cb(const struct ofono_error *error,
610                                         int status, void *data)
611 {
612         struct ofono_call_settings *cs = data;
613         const char *context;
614         const char *value;
615
616         if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
617                 DBG("Error occurred during ss control query");
618                 __ofono_dbus_pending_reply(&cs->pending,
619                                         __ofono_error_failed(cs->pending));
620
621                 return;
622         }
623
624         switch (cs->ss_setting) {
625         case CALL_SETTING_TYPE_CLIP:
626                 set_clip(cs, status);
627                 value = clip_status_to_string(status);
628                 context = "CallingLinePresentation";
629                 break;
630
631         case CALL_SETTING_TYPE_CNAP:
632                 set_cnap(cs, status);
633                 value = cnap_status_to_string(status);
634                 context = "CallingNamePresentation";
635                 break;
636
637
638         case CALL_SETTING_TYPE_COLP:
639                 set_colp(cs, status);
640                 value = colp_status_to_string(status);
641                 context = "ConnectedLinePresentation";
642                 break;
643
644         case CALL_SETTING_TYPE_COLR:
645                 set_colr(cs, status);
646                 value = colr_status_to_string(status);
647                 context = "ConnectedLineRestriction";
648                 break;
649
650         default:
651                 __ofono_dbus_pending_reply(&cs->pending,
652                                 __ofono_error_failed(cs->pending));
653                 ofono_error("Unknown type during COLR/COLP/CLIP/CNAP ss");
654                 return;
655         };
656
657         generate_ss_query_reply(cs, context, value);
658 }
659
660 static gboolean clip_cnap_colp_colr_ss(int type,
661                                 const char *sc, const char *sia,
662                                 const char *sib, const char *sic,
663                                 const char *dn, DBusMessage *msg, void *data)
664 {
665         struct ofono_call_settings *cs = data;
666         DBusConnection *conn = ofono_dbus_get_connection();
667         void (*query_op)(struct ofono_call_settings *cs,
668                                 ofono_call_settings_status_cb_t cb, void *data);
669
670         if (cs == NULL)
671                 return FALSE;
672
673         if (__ofono_call_settings_is_busy(cs)) {
674                 DBusMessage *reply = __ofono_error_busy(msg);
675                 g_dbus_send_message(conn, reply);
676
677                 return TRUE;
678         }
679
680         if (!strcmp(sc, "30")) {
681                 cs->ss_setting = CALL_SETTING_TYPE_CLIP;
682                 query_op = cs->driver->clip_query;
683         } else if (!strcmp(sc, "300")) {
684                 cs->ss_setting = CALL_SETTING_TYPE_CNAP;
685                 query_op = cs->driver->cnap_query;
686         } else if (!strcmp(sc, "76")) {
687                 cs->ss_setting = CALL_SETTING_TYPE_COLP;
688                 query_op = cs->driver->colp_query;
689         } else if (!strcmp(sc, "77")) {
690                 cs->ss_setting = CALL_SETTING_TYPE_COLR;
691                 query_op = cs->driver->colr_query;
692         } else {
693                 return FALSE;
694         }
695
696         if (type != SS_CONTROL_TYPE_QUERY || strlen(sia) || strlen(sib) ||
697                 strlen(sic) || strlen(dn)) {
698                 DBusMessage *reply = __ofono_error_invalid_format(msg);
699                 g_dbus_send_message(conn, reply);
700
701                 return TRUE;
702         }
703
704         if (query_op == NULL) {
705                 DBusMessage *reply = __ofono_error_not_implemented(msg);
706                 g_dbus_send_message(conn, reply);
707
708                 return TRUE;
709         }
710
711         DBG("Received CLIP/CNAP/COLR/COLP query ss control");
712
713         cs->pending = dbus_message_ref(msg);
714
715         query_op(cs, clip_cnap_colp_colr_ss_query_cb, cs);
716
717         return TRUE;
718 }
719
720 static void clir_ss_query_callback(const struct ofono_error *error,
721                                         int override, int network, void *data)
722 {
723         struct ofono_call_settings *cs = data;
724         const char *value;
725
726         if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
727                 DBG("setting clir via SS failed");
728                 __ofono_dbus_pending_reply(&cs->pending,
729                                         __ofono_error_failed(cs->pending));
730
731                 return;
732         }
733
734         switch (network) {
735         case CLIR_STATUS_UNKNOWN:
736                 value = "unknown";
737                 break;
738
739         case CLIR_STATUS_PROVISIONED_PERMANENT:
740                 value = "enabled";
741                 break;
742
743         case CLIR_STATUS_NOT_PROVISIONED:
744                 value = "disabled";
745                 break;
746
747         case CLIR_STATUS_TEMPORARY_RESTRICTED:
748                 if (override == OFONO_CLIR_OPTION_SUPPRESSION)
749                         value = "enabled";
750                 else
751                         value = "disabled";
752                 break;
753
754         case CLIR_STATUS_TEMPORARY_ALLOWED:
755                 if (override == OFONO_CLIR_OPTION_INVOCATION)
756                         value = "enabled";
757                 else
758                         value = "disabled";
759                 break;
760         default:
761                 value = "unknown";
762         };
763
764         generate_ss_query_reply(cs, "CallingLineRestriction", value);
765
766         set_clir_network(cs, network);
767         set_clir_override(cs, override);
768 }
769
770 static void clir_ss_set_callback(const struct ofono_error *error, void *data)
771 {
772         struct ofono_call_settings *cs = data;
773
774         if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
775                 DBG("setting clir via SS failed");
776                 __ofono_dbus_pending_reply(&cs->pending,
777                                         __ofono_error_failed(cs->pending));
778
779                 return;
780         }
781
782         cs->driver->clir_query(cs, clir_ss_query_callback, cs);
783 }
784
785 static gboolean clir_ss_control(int type,
786                                 const char *sc, const char *sia,
787                                 const char *sib, const char *sic,
788                                 const char *dn, DBusMessage *msg, void *data)
789 {
790         struct ofono_call_settings *cs = data;
791         DBusConnection *conn = ofono_dbus_get_connection();
792
793         if (cs == NULL)
794                 return FALSE;
795
796         if (strcmp(sc, "31"))
797                 return FALSE;
798
799         if (__ofono_call_settings_is_busy(cs)) {
800                 DBusMessage *reply = __ofono_error_busy(msg);
801                 g_dbus_send_message(conn, reply);
802
803                 return TRUE;
804         }
805
806         /* This is the temporary form of CLIR, handled in voicecalls */
807         if (!strlen(sia) && !strlen(sib) & !strlen(sic) &&
808                         strlen(dn) && type != SS_CONTROL_TYPE_QUERY)
809                 return FALSE;
810
811         if (strlen(sia) || strlen(sib) || strlen(sic) || strlen(dn)) {
812                 DBusMessage *reply = __ofono_error_invalid_format(msg);
813                 g_dbus_send_message(conn, reply);
814
815                 return TRUE;
816         }
817
818         if (type == SS_CONTROL_TYPE_QUERY && cs->driver->clir_query == NULL) {
819                 DBusMessage *reply = __ofono_error_not_implemented(msg);
820                 g_dbus_send_message(conn, reply);
821
822                 return TRUE;
823         }
824
825         if (type != SS_CONTROL_TYPE_QUERY && cs->driver->clir_set == NULL) {
826                 DBusMessage *reply = __ofono_error_not_implemented(msg);
827                 g_dbus_send_message(conn, reply);
828
829                 return TRUE;
830         }
831
832         cs->ss_setting = CALL_SETTING_TYPE_CLIR;
833         cs->pending = dbus_message_ref(msg);
834
835         switch (type) {
836         case SS_CONTROL_TYPE_REGISTRATION:
837         case SS_CONTROL_TYPE_ACTIVATION:
838                 cs->ss_req_type = SS_CONTROL_TYPE_ACTIVATION;
839                 cs->driver->clir_set(cs, OFONO_CLIR_OPTION_SUPPRESSION,
840                                         clir_ss_set_callback, cs);
841                 break;
842
843         case SS_CONTROL_TYPE_QUERY:
844                 cs->ss_req_type = SS_CONTROL_TYPE_QUERY;
845                 cs->driver->clir_query(cs, clir_ss_query_callback, cs);
846                 break;
847
848         case SS_CONTROL_TYPE_DEACTIVATION:
849         case SS_CONTROL_TYPE_ERASURE:
850                 cs->ss_req_type = SS_CONTROL_TYPE_DEACTIVATION;
851                 cs->driver->clir_set(cs, OFONO_CLIR_OPTION_INVOCATION,
852                                         clir_ss_set_callback, cs);
853                 break;
854         };
855
856         return TRUE;
857 }
858
859 static void cs_register_ss_controls(struct ofono_call_settings *cs)
860 {
861         __ofono_ussd_ssc_register(cs->ussd, "30", clip_cnap_colp_colr_ss,
862                                                                 cs, NULL);
863         __ofono_ussd_ssc_register(cs->ussd, "31", clir_ss_control, cs, NULL);
864         __ofono_ussd_ssc_register(cs->ussd, "76", clip_cnap_colp_colr_ss,
865                                                                 cs, NULL);
866         __ofono_ussd_ssc_register(cs->ussd, "300", clip_cnap_colp_colr_ss,
867                                                                 cs, NULL);
868
869         __ofono_ussd_ssc_register(cs->ussd, "43", cw_ss_control, cs, NULL);
870
871         if (cs->driver->colr_query != NULL)
872                 __ofono_ussd_ssc_register(cs->ussd, "77",
873                                         clip_cnap_colp_colr_ss, cs, NULL);
874 }
875
876 static void cs_unregister_ss_controls(struct ofono_call_settings *cs)
877 {
878         __ofono_ussd_ssc_unregister(cs->ussd, "30");
879         __ofono_ussd_ssc_unregister(cs->ussd, "31");
880         __ofono_ussd_ssc_unregister(cs->ussd, "76");
881         __ofono_ussd_ssc_unregister(cs->ussd, "300");
882
883         __ofono_ussd_ssc_unregister(cs->ussd, "43");
884
885         if (cs->driver->colr_query != NULL)
886                 __ofono_ussd_ssc_unregister(cs->ussd, "77");
887 }
888
889 gboolean __ofono_call_settings_is_busy(struct ofono_call_settings *cs)
890 {
891         return cs->pending ? TRUE : FALSE;
892 }
893
894 static DBusMessage *generate_get_properties_reply(struct ofono_call_settings *cs,
895                                                         DBusMessage *msg)
896 {
897         DBusMessage *reply;
898         DBusMessageIter iter;
899         DBusMessageIter dict;
900         const char *str;
901
902         reply = dbus_message_new_method_return(msg);
903         if (reply == NULL)
904                 return NULL;
905
906         dbus_message_iter_init_append(reply, &iter);
907
908         dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
909                                         OFONO_PROPERTIES_ARRAY_SIGNATURE,
910                                         &dict);
911
912         str = clip_status_to_string(cs->clip);
913         ofono_dbus_dict_append(&dict, "CallingLinePresentation",
914                                 DBUS_TYPE_STRING, &str);
915
916         str = cnap_status_to_string(cs->cnap);
917         ofono_dbus_dict_append(&dict, "CallingNamePresentation",
918                                 DBUS_TYPE_STRING, &str);
919
920         str = colp_status_to_string(cs->colp);
921         ofono_dbus_dict_append(&dict, "ConnectedLinePresentation",
922                                 DBUS_TYPE_STRING, &str);
923
924         str = colr_status_to_string(cs->colr);
925         ofono_dbus_dict_append(&dict, "ConnectedLineRestriction",
926                                 DBUS_TYPE_STRING, &str);
927
928         str = cdip_status_to_string(cs->cdip);
929         ofono_dbus_dict_append(&dict, "CalledLinePresentation",
930                                 DBUS_TYPE_STRING, &str);
931
932         str = clir_status_to_string(cs->clir);
933         ofono_dbus_dict_append(&dict, "CallingLineRestriction",
934                                 DBUS_TYPE_STRING, &str);
935
936         str = hide_callerid_to_string(cs->clir_setting);
937         ofono_dbus_dict_append(&dict, "HideCallerId", DBUS_TYPE_STRING, &str);
938
939         property_append_cw_conditions(&dict, cs->cw, BEARER_CLASS_VOICE);
940
941         dbus_message_iter_close_container(&iter, &dict);
942
943         return reply;
944 }
945
946 static void cs_clir_callback(const struct ofono_error *error,
947                                 int override_setting, int network_setting,
948                                 void *data)
949 {
950         struct ofono_call_settings *cs = data;
951
952         if (error->type != OFONO_ERROR_TYPE_NO_ERROR)
953                 goto out;
954
955         set_clir_network(cs, network_setting);
956         set_clir_override(cs, override_setting);
957
958         cs->flags |= CALL_SETTINGS_FLAG_CACHED;
959
960 out:
961         if (cs->pending) {
962                 DBusMessage *reply = generate_get_properties_reply(cs,
963                                                                 cs->pending);
964                 __ofono_dbus_pending_reply(&cs->pending, reply);
965         }
966 }
967
968 static void query_clir(struct ofono_call_settings *cs)
969 {
970         if (cs->driver->clir_query == NULL) {
971                 if (cs->pending) {
972                         DBusMessage *reply =
973                                 generate_get_properties_reply(cs,
974                                                                 cs->pending);
975                         __ofono_dbus_pending_reply(&cs->pending, reply);
976                 }
977
978                 return;
979         }
980
981         cs->driver->clir_query(cs, cs_clir_callback, cs);
982 }
983
984 static void cs_cdip_callback(const struct ofono_error *error,
985                                 int state, void *data)
986 {
987         struct ofono_call_settings *cs = data;
988
989         if (error->type == OFONO_ERROR_TYPE_NO_ERROR)
990                 set_cdip(cs, state);
991
992         query_clir(cs);
993 }
994
995 static void query_cdip(struct ofono_call_settings *cs)
996 {
997         if (cs->driver->cdip_query == NULL) {
998                 query_clir(cs);
999                 return;
1000         }
1001
1002         cs->driver->cdip_query(cs, cs_cdip_callback, cs);
1003 }
1004
1005
1006 static void cs_cnap_callback(const struct ofono_error *error,
1007                                 int state, void *data)
1008 {
1009         struct ofono_call_settings *cs = data;
1010
1011         if (error->type == OFONO_ERROR_TYPE_NO_ERROR)
1012                 set_cnap(cs, state);
1013
1014         query_cdip(cs);
1015 }
1016
1017 static void query_cnap(struct ofono_call_settings *cs)
1018 {
1019         if (cs->driver->cnap_query == NULL) {
1020                 query_cdip(cs);
1021                 return;
1022         }
1023
1024         cs->driver->cnap_query(cs, cs_cnap_callback, cs);
1025 }
1026
1027 static void cs_clip_callback(const struct ofono_error *error,
1028                                 int state, void *data)
1029 {
1030         struct ofono_call_settings *cs = data;
1031
1032         if (error->type == OFONO_ERROR_TYPE_NO_ERROR)
1033                 set_clip(cs, state);
1034
1035         query_cnap(cs);
1036 }
1037
1038 static void query_clip(struct ofono_call_settings *cs)
1039 {
1040         if (cs->driver->clip_query == NULL) {
1041                 query_clir(cs);
1042                 return;
1043         }
1044
1045         cs->driver->clip_query(cs, cs_clip_callback, cs);
1046 }
1047
1048 static void cs_colp_callback(const struct ofono_error *error,
1049                                 int state, void *data)
1050 {
1051         struct ofono_call_settings *cs = data;
1052
1053         if (error->type == OFONO_ERROR_TYPE_NO_ERROR)
1054                 set_colp(cs, state);
1055
1056         query_clip(cs);
1057 }
1058
1059 static void query_colp(struct ofono_call_settings *cs)
1060 {
1061         if (cs->driver->colp_query == NULL) {
1062                 query_clip(cs);
1063                 return;
1064         }
1065
1066         cs->driver->colp_query(cs, cs_colp_callback, cs);
1067 }
1068
1069 static void cs_colr_callback(const struct ofono_error *error,
1070                                 int state, void *data)
1071 {
1072         struct ofono_call_settings *cs = data;
1073
1074         if (error->type == OFONO_ERROR_TYPE_NO_ERROR)
1075                 set_colr(cs, state);
1076
1077         query_colp(cs);
1078 }
1079
1080 static void query_colr(struct ofono_call_settings *cs)
1081 {
1082         if (cs->driver->colr_query == NULL) {
1083                 query_colp(cs);
1084                 return;
1085         }
1086
1087         cs->driver->colr_query(cs, cs_colr_callback, cs);
1088 }
1089
1090 static void cs_cw_callback(const struct ofono_error *error, int status,
1091                                 void *data)
1092 {
1093         struct ofono_call_settings *cs = data;
1094
1095         if (error->type == OFONO_ERROR_TYPE_NO_ERROR)
1096                 set_cw(cs, status, BEARER_CLASS_VOICE);
1097
1098         query_colr(cs);
1099 }
1100
1101 static void query_cw(struct ofono_call_settings *cs)
1102 {
1103         if (cs->driver->cw_query == NULL) {
1104                 query_colr(cs);
1105                 return;
1106         }
1107
1108         cs->driver->cw_query(cs, BEARER_CLASS_DEFAULT, cs_cw_callback, cs);
1109 }
1110
1111 static DBusMessage *cs_get_properties(DBusConnection *conn, DBusMessage *msg,
1112                                         void *data)
1113 {
1114         struct ofono_call_settings *cs = data;
1115
1116         if (__ofono_call_settings_is_busy(cs) || __ofono_ussd_is_busy(cs->ussd))
1117                 return __ofono_error_busy(msg);
1118
1119         if (cs->flags & CALL_SETTINGS_FLAG_CACHED)
1120                 return generate_get_properties_reply(cs, msg);
1121
1122         /* Query the settings and report back */
1123         cs->pending = dbus_message_ref(msg);
1124
1125         query_cw(cs);
1126
1127         return NULL;
1128 }
1129
1130 static void clir_set_query_callback(const struct ofono_error *error,
1131                                         int override_setting,
1132                                         int network_setting, void *data)
1133 {
1134         struct ofono_call_settings *cs = data;
1135         DBusMessage *reply;
1136
1137         if (!__ofono_call_settings_is_busy(cs))
1138                 return;
1139
1140         if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
1141                 ofono_error("set clir successful, but the query was not");
1142
1143                 cs->flags &= ~CALL_SETTINGS_FLAG_CACHED;
1144
1145                 reply = __ofono_error_failed(cs->pending);
1146                 __ofono_dbus_pending_reply(&cs->pending, reply);
1147                 return;
1148         }
1149
1150         reply = dbus_message_new_method_return(cs->pending);
1151         __ofono_dbus_pending_reply(&cs->pending, reply);
1152
1153         set_clir_override(cs, override_setting);
1154         set_clir_network(cs, network_setting);
1155 }
1156
1157 static void clir_set_callback(const struct ofono_error *error, void *data)
1158 {
1159         struct ofono_call_settings *cs = data;
1160
1161         if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
1162                 DBG("setting clir failed");
1163                 __ofono_dbus_pending_reply(&cs->pending,
1164                                         __ofono_error_failed(cs->pending));
1165
1166                 return;
1167         }
1168
1169         /* Assume that if we have clir_set, we have clir_query */
1170         cs->driver->clir_query(cs, clir_set_query_callback, cs);
1171 }
1172
1173 static DBusMessage *set_clir(DBusMessage *msg, struct ofono_call_settings *cs,
1174                                 const char *setting)
1175 {
1176         int clir = -1;
1177
1178         if (cs->driver->clir_set == NULL)
1179                 return __ofono_error_not_implemented(msg);
1180
1181         if (!strcmp(setting, "default"))
1182                 clir = CLIR_STATUS_NOT_PROVISIONED;
1183         else if (!strcmp(setting, "enabled"))
1184                 clir = CLIR_STATUS_PROVISIONED_PERMANENT;
1185         else if (!strcmp(setting, "disabled"))
1186                 clir = CLIR_STATUS_UNKNOWN;
1187
1188         if (clir == -1)
1189                 return __ofono_error_invalid_format(msg);
1190
1191         cs->pending = dbus_message_ref(msg);
1192
1193         cs->driver->clir_set(cs, clir, clir_set_callback, cs);
1194
1195         return NULL;
1196 }
1197
1198 static void cw_set_query_callback(const struct ofono_error *error, int status,
1199                                 void *data)
1200 {
1201         struct ofono_call_settings *cs = data;
1202
1203         if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
1204                 ofono_error("CW set succeeded, but query failed!");
1205
1206                 cs->flags &= ~CALL_SETTINGS_FLAG_CACHED;
1207
1208                 __ofono_dbus_pending_reply(&cs->pending,
1209                                         __ofono_error_failed(cs->pending));
1210                 return;
1211         }
1212
1213         __ofono_dbus_pending_reply(&cs->pending,
1214                                 dbus_message_new_method_return(cs->pending));
1215
1216         set_cw(cs, status, BEARER_CLASS_VOICE);
1217 }
1218
1219 static void cw_set_callback(const struct ofono_error *error, void *data)
1220 {
1221         struct ofono_call_settings *cs = data;
1222
1223         if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
1224                 DBG("Error occurred during CW set");
1225
1226                 __ofono_dbus_pending_reply(&cs->pending,
1227                                         __ofono_error_failed(cs->pending));
1228
1229                 return;
1230         }
1231
1232         cs->driver->cw_query(cs, BEARER_CLASS_DEFAULT,
1233                                 cw_set_query_callback, cs);
1234 }
1235
1236 static DBusMessage *set_cw_req(DBusMessage *msg, struct ofono_call_settings *cs,
1237                                 const char *setting, int cls)
1238 {
1239         int cw;
1240
1241         if (cs->driver->cw_set == NULL)
1242                 return __ofono_error_not_implemented(msg);
1243
1244         if (!strcmp(setting, "enabled"))
1245                 cw = 1;
1246         else if (!strcmp(setting, "disabled"))
1247                 cw = 0;
1248         else
1249                 return __ofono_error_invalid_format(msg);
1250
1251         cs->pending = dbus_message_ref(msg);
1252
1253         cs->driver->cw_set(cs, cw, cls, cw_set_callback, cs);
1254
1255         return NULL;
1256 }
1257
1258 static gboolean is_cw_property(const char *property, int mask, int *out_cls)
1259 {
1260         int i;
1261         int len;
1262         const char *prefix;
1263
1264         for (i = 1; i <= BEARER_CLASS_PAD; i = i << 1) {
1265                 if ((i & mask) == 0)
1266                         continue;
1267
1268                 prefix = bearer_class_to_string(i);
1269
1270                 len = strlen(prefix);
1271
1272                 if (strncmp(property, prefix, len))
1273                         continue;
1274
1275                 if (!strcmp(property+len, "CallWaiting")) {
1276                         *out_cls = i;
1277                         return TRUE;
1278                 }
1279         }
1280
1281         return FALSE;
1282 }
1283
1284 static DBusMessage *cs_set_property(DBusConnection *conn, DBusMessage *msg,
1285                                         void *data)
1286 {
1287         struct ofono_call_settings *cs = data;
1288         DBusMessageIter iter;
1289         DBusMessageIter var;
1290         const char *property;
1291         int cls;
1292
1293         if (__ofono_call_settings_is_busy(cs) || __ofono_ussd_is_busy(cs->ussd))
1294                 return __ofono_error_busy(msg);
1295
1296         if (!dbus_message_iter_init(msg, &iter))
1297                 return __ofono_error_invalid_args(msg);
1298
1299         if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
1300                 return __ofono_error_invalid_args(msg);
1301
1302         dbus_message_iter_get_basic(&iter, &property);
1303         dbus_message_iter_next(&iter);
1304
1305         if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
1306                 return __ofono_error_invalid_args(msg);
1307
1308         dbus_message_iter_recurse(&iter, &var);
1309
1310         if (!strcmp(property, "HideCallerId")) {
1311                 const char *setting;
1312
1313                 if (dbus_message_iter_get_arg_type(&var) != DBUS_TYPE_STRING)
1314                         return __ofono_error_invalid_args(msg);
1315
1316                 dbus_message_iter_get_basic(&var, &setting);
1317
1318                 return set_clir(msg, cs, setting);
1319         } else if (is_cw_property(property, BEARER_CLASS_VOICE, &cls)) {
1320                 const char *setting;
1321
1322                 if (dbus_message_iter_get_arg_type(&var) != DBUS_TYPE_STRING)
1323                         return __ofono_error_invalid_args(msg);
1324
1325                 dbus_message_iter_get_basic(&var, &setting);
1326
1327                 return set_cw_req(msg, cs, setting, cls);
1328         }
1329
1330         return __ofono_error_invalid_args(msg);
1331 }
1332
1333 static const GDBusMethodTable cs_methods[] = {
1334         { GDBUS_ASYNC_METHOD("GetProperties",
1335                                 NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
1336                                 cs_get_properties) },
1337         { GDBUS_ASYNC_METHOD("SetProperty",
1338                         GDBUS_ARGS({ "property", "s" }, { "value", "v" }),
1339                         NULL, cs_set_property) },
1340         { }
1341 };
1342
1343 static const GDBusSignalTable cs_signals[] = {
1344         { GDBUS_SIGNAL("PropertyChanged",
1345                         GDBUS_ARGS({ "property", "s" }, { "value", "v" })) },
1346         { }
1347 };
1348
1349 int ofono_call_settings_driver_register(const struct ofono_call_settings_driver *d)
1350 {
1351         DBG("driver: %p, name: %s", d, d->name);
1352
1353         if (d->probe == NULL)
1354                 return -EINVAL;
1355
1356         g_drivers = g_slist_prepend(g_drivers, (void *) d);
1357
1358         return 0;
1359 }
1360
1361 void ofono_call_settings_driver_unregister(const struct ofono_call_settings_driver *d)
1362 {
1363         DBG("driver: %p, name: %s", d, d->name);
1364
1365         g_drivers = g_slist_remove(g_drivers, (void *) d);
1366 }
1367
1368 static void call_settings_unregister(struct ofono_atom *atom)
1369 {
1370         struct ofono_call_settings *cs = __ofono_atom_get_data(atom);
1371         const char *path = __ofono_atom_get_path(cs->atom);
1372         DBusConnection *conn = ofono_dbus_get_connection();
1373         struct ofono_modem *modem = __ofono_atom_get_modem(cs->atom);
1374
1375         ofono_modem_remove_interface(modem, OFONO_CALL_SETTINGS_INTERFACE);
1376         g_dbus_unregister_interface(conn, path, OFONO_CALL_SETTINGS_INTERFACE);
1377
1378         if (cs->ussd)
1379                 cs_unregister_ss_controls(cs);
1380
1381         if (cs->ussd_watch)
1382                 __ofono_modem_remove_atom_watch(modem, cs->ussd_watch);
1383 }
1384
1385 static void call_settings_remove(struct ofono_atom *atom)
1386 {
1387         struct ofono_call_settings *cs = __ofono_atom_get_data(atom);
1388
1389         DBG("atom: %p", atom);
1390
1391         if (cs == NULL)
1392                 return;
1393
1394         if (cs->driver != NULL && cs->driver->remove != NULL)
1395                 cs->driver->remove(cs);
1396
1397         g_free(cs);
1398 }
1399
1400 struct ofono_call_settings *ofono_call_settings_create(struct ofono_modem *modem,
1401                                                         unsigned int vendor,
1402                                                         const char *driver,
1403                                                         void *data)
1404 {
1405         struct ofono_call_settings *cs;
1406         GSList *l;
1407
1408         if (driver == NULL)
1409                 return NULL;
1410
1411         cs = g_try_new0(struct ofono_call_settings, 1);
1412
1413         if (cs == NULL)
1414                 return NULL;
1415
1416         /* Set all the settings to unknown state */
1417         cs->clip = CLIP_STATUS_UNKNOWN;
1418         cs->cnap = CNAP_STATUS_UNKNOWN;
1419         cs->clir = CLIR_STATUS_UNKNOWN;
1420         cs->colp = COLP_STATUS_UNKNOWN;
1421         cs->colr = COLR_STATUS_UNKNOWN;
1422         cs->atom = __ofono_modem_add_atom(modem, OFONO_ATOM_TYPE_CALL_SETTINGS,
1423                                                 call_settings_remove, cs);
1424
1425         for (l = g_drivers; l; l = l->next) {
1426                 const struct ofono_call_settings_driver *drv = l->data;
1427
1428                 if (g_strcmp0(drv->name, driver))
1429                         continue;
1430
1431                 if (drv->probe(cs, vendor, data) < 0)
1432                         continue;
1433
1434                 cs->driver = drv;
1435                 break;
1436         }
1437
1438         return cs;
1439 }
1440
1441 static void ussd_watch(struct ofono_atom *atom,
1442                         enum ofono_atom_watch_condition cond, void *data)
1443 {
1444         struct ofono_call_settings *cs = data;
1445
1446         if (cond == OFONO_ATOM_WATCH_CONDITION_UNREGISTERED) {
1447                 cs->ussd = NULL;
1448                 return;
1449         }
1450
1451         cs->ussd = __ofono_atom_get_data(atom);
1452         cs_register_ss_controls(cs);
1453 }
1454
1455 void ofono_call_settings_register(struct ofono_call_settings *cs)
1456 {
1457         DBusConnection *conn = ofono_dbus_get_connection();
1458         const char *path = __ofono_atom_get_path(cs->atom);
1459         struct ofono_modem *modem = __ofono_atom_get_modem(cs->atom);
1460
1461         if (!g_dbus_register_interface(conn, path,
1462                                         OFONO_CALL_SETTINGS_INTERFACE,
1463                                         cs_methods, cs_signals, NULL, cs,
1464                                         NULL)) {
1465                 ofono_error("Could not create %s interface",
1466                                 OFONO_CALL_SETTINGS_INTERFACE);
1467
1468                 return;
1469         }
1470
1471         ofono_modem_add_interface(modem, OFONO_CALL_SETTINGS_INTERFACE);
1472
1473         cs->ussd_watch = __ofono_modem_add_atom_watch(modem,
1474                                         OFONO_ATOM_TYPE_USSD,
1475                                         ussd_watch, cs, NULL);
1476
1477         __ofono_atom_register(cs->atom, call_settings_unregister);
1478 }
1479
1480 void ofono_call_settings_remove(struct ofono_call_settings *cs)
1481 {
1482         __ofono_atom_free(cs->atom);
1483 }
1484
1485 void ofono_call_settings_set_data(struct ofono_call_settings *cs, void *data)
1486 {
1487         cs->driver_data = data;
1488 }
1489
1490 void *ofono_call_settings_get_data(struct ofono_call_settings *cs)
1491 {
1492         return cs->driver_data;
1493 }