upgrade to the version 1.8
[profile/ivi/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 with error: %s",
481                         telephony_error_to_str(error));
482                 __ofono_dbus_pending_reply(&cs->pending,
483                         __ofono_error_from_error(error, cs->pending));
484
485                 return;
486         }
487
488         cs->driver->cw_query(cs, BEARER_CLASS_DEFAULT,
489                                 cw_ss_query_callback, cs);
490 }
491
492 static gboolean cw_ss_control(int type,
493                                 const char *sc, const char *sia,
494                                 const char *sib, const char *sic,
495                                 const char *dn, DBusMessage *msg, void *data)
496 {
497         struct ofono_call_settings *cs = data;
498         DBusConnection *conn = ofono_dbus_get_connection();
499         int cls = BEARER_CLASS_SS_DEFAULT;
500         DBusMessage *reply;
501
502         if (cs == NULL)
503                 return FALSE;
504
505         if (strcmp(sc, "43"))
506                 return FALSE;
507
508         if (__ofono_call_settings_is_busy(cs)) {
509                 reply = __ofono_error_busy(msg);
510                 goto error;
511         }
512
513         if (strlen(sib) || strlen(sib) || strlen(dn))
514                 goto bad_format;
515
516         if ((type == SS_CONTROL_TYPE_QUERY && cs->driver->cw_query == NULL) ||
517                 (type != SS_CONTROL_TYPE_QUERY && cs->driver->cw_set == NULL)) {
518                 reply = __ofono_error_not_implemented(msg);
519                 goto error;
520         }
521
522         if (strlen(sia) > 0) {
523                 long service_code;
524                 char *end;
525
526                 service_code = strtoul(sia, &end, 10);
527
528                 if (end == sia || *end != '\0')
529                         goto bad_format;
530
531                 cls = mmi_service_code_to_bearer_class(service_code);
532                 if (cls == 0)
533                         goto bad_format;
534         }
535
536         cs->ss_req_cls = cls;
537         cs->pending = dbus_message_ref(msg);
538
539         /* For the default case use the more readily accepted value */
540         if (cls == BEARER_CLASS_SS_DEFAULT)
541                 cls = BEARER_CLASS_DEFAULT;
542
543         switch (type) {
544         case SS_CONTROL_TYPE_REGISTRATION:
545         case SS_CONTROL_TYPE_ACTIVATION:
546                 cs->ss_req_type = SS_CONTROL_TYPE_ACTIVATION;
547                 cs->driver->cw_set(cs, 1, cls, cw_ss_set_callback, cs);
548                 break;
549
550         case SS_CONTROL_TYPE_QUERY:
551                 cs->ss_req_type = SS_CONTROL_TYPE_QUERY;
552                 /*
553                  * Always query the entire set, SMS not applicable
554                  * according to 22.004 Appendix A, so CLASS_DEFAULT
555                  * is safe to use here
556                  */
557                 cs->driver->cw_query(cs, BEARER_CLASS_DEFAULT,
558                                         cw_ss_query_callback, cs);
559                 break;
560
561         case SS_CONTROL_TYPE_DEACTIVATION:
562         case SS_CONTROL_TYPE_ERASURE:
563                 cs->ss_req_type = SS_CONTROL_TYPE_DEACTIVATION;
564                 cs->driver->cw_set(cs, 0, cls, cw_ss_set_callback, cs);
565                 break;
566         }
567
568         return TRUE;
569
570 bad_format:
571         reply = __ofono_error_invalid_format(msg);
572 error:
573         g_dbus_send_message(conn, reply);
574         return TRUE;
575 }
576
577 static void generate_ss_query_reply(struct ofono_call_settings *cs,
578                                         const char *context, const char *value)
579 {
580         const char *sig = "(ss)";
581         const char *ss_type = ss_control_type_to_string(cs->ss_req_type);
582         DBusMessageIter iter;
583         DBusMessageIter var;
584         DBusMessageIter vstruct;
585         DBusMessage *reply;
586
587         reply = dbus_message_new_method_return(cs->pending);
588
589         dbus_message_iter_init_append(reply, &iter);
590
591         dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &context);
592
593         dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT, sig, &var);
594
595         dbus_message_iter_open_container(&var, DBUS_TYPE_STRUCT, NULL,
596                                                 &vstruct);
597
598         dbus_message_iter_append_basic(&vstruct, DBUS_TYPE_STRING,
599                                         &ss_type);
600
601         dbus_message_iter_append_basic(&vstruct, DBUS_TYPE_STRING, &value);
602
603         dbus_message_iter_close_container(&var, &vstruct);
604
605         dbus_message_iter_close_container(&iter, &var);
606
607         __ofono_dbus_pending_reply(&cs->pending, reply);
608 }
609
610 static void clip_cnap_colp_colr_ss_query_cb(const struct ofono_error *error,
611                                         int status, void *data)
612 {
613         struct ofono_call_settings *cs = data;
614         const char *context;
615         const char *value;
616
617         if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
618                 DBG("SS control query failed with error: %s",
619                         telephony_error_to_str(error));
620                 __ofono_dbus_pending_reply(&cs->pending,
621                         __ofono_error_from_error(error, cs->pending));
622
623                 return;
624         }
625
626         switch (cs->ss_setting) {
627         case CALL_SETTING_TYPE_CLIP:
628                 set_clip(cs, status);
629                 value = clip_status_to_string(status);
630                 context = "CallingLinePresentation";
631                 break;
632
633         case CALL_SETTING_TYPE_CNAP:
634                 set_cnap(cs, status);
635                 value = cnap_status_to_string(status);
636                 context = "CallingNamePresentation";
637                 break;
638
639
640         case CALL_SETTING_TYPE_COLP:
641                 set_colp(cs, status);
642                 value = colp_status_to_string(status);
643                 context = "ConnectedLinePresentation";
644                 break;
645
646         case CALL_SETTING_TYPE_COLR:
647                 set_colr(cs, status);
648                 value = colr_status_to_string(status);
649                 context = "ConnectedLineRestriction";
650                 break;
651
652         default:
653                 __ofono_dbus_pending_reply(&cs->pending,
654                                 __ofono_error_failed(cs->pending));
655                 ofono_error("Unknown type during COLR/COLP/CLIP/CNAP ss");
656                 return;
657         };
658
659         generate_ss_query_reply(cs, context, value);
660 }
661
662 static gboolean clip_cnap_colp_colr_ss(int type,
663                                 const char *sc, const char *sia,
664                                 const char *sib, const char *sic,
665                                 const char *dn, DBusMessage *msg, void *data)
666 {
667         struct ofono_call_settings *cs = data;
668         DBusConnection *conn = ofono_dbus_get_connection();
669         void (*query_op)(struct ofono_call_settings *cs,
670                                 ofono_call_settings_status_cb_t cb, void *data);
671
672         if (cs == NULL)
673                 return FALSE;
674
675         if (__ofono_call_settings_is_busy(cs)) {
676                 DBusMessage *reply = __ofono_error_busy(msg);
677                 g_dbus_send_message(conn, reply);
678
679                 return TRUE;
680         }
681
682         if (!strcmp(sc, "30")) {
683                 cs->ss_setting = CALL_SETTING_TYPE_CLIP;
684                 query_op = cs->driver->clip_query;
685         } else if (!strcmp(sc, "300")) {
686                 cs->ss_setting = CALL_SETTING_TYPE_CNAP;
687                 query_op = cs->driver->cnap_query;
688         } else if (!strcmp(sc, "76")) {
689                 cs->ss_setting = CALL_SETTING_TYPE_COLP;
690                 query_op = cs->driver->colp_query;
691         } else if (!strcmp(sc, "77")) {
692                 cs->ss_setting = CALL_SETTING_TYPE_COLR;
693                 query_op = cs->driver->colr_query;
694         } else {
695                 return FALSE;
696         }
697
698         if (type != SS_CONTROL_TYPE_QUERY || strlen(sia) || strlen(sib) ||
699                 strlen(sic) || strlen(dn)) {
700                 DBusMessage *reply = __ofono_error_invalid_format(msg);
701                 g_dbus_send_message(conn, reply);
702
703                 return TRUE;
704         }
705
706         if (query_op == NULL) {
707                 DBusMessage *reply = __ofono_error_not_implemented(msg);
708                 g_dbus_send_message(conn, reply);
709
710                 return TRUE;
711         }
712
713         DBG("Received CLIP/CNAP/COLR/COLP query ss control");
714
715         cs->pending = dbus_message_ref(msg);
716
717         query_op(cs, clip_cnap_colp_colr_ss_query_cb, cs);
718
719         return TRUE;
720 }
721
722 static void clir_ss_query_callback(const struct ofono_error *error,
723                                         int override, int network, void *data)
724 {
725         struct ofono_call_settings *cs = data;
726         const char *value;
727
728         if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
729                 DBG("setting clir via SS failed");
730                 __ofono_dbus_pending_reply(&cs->pending,
731                                         __ofono_error_failed(cs->pending));
732
733                 return;
734         }
735
736         switch (network) {
737         case CLIR_STATUS_UNKNOWN:
738                 value = "unknown";
739                 break;
740
741         case CLIR_STATUS_PROVISIONED_PERMANENT:
742                 value = "enabled";
743                 break;
744
745         case CLIR_STATUS_NOT_PROVISIONED:
746                 value = "disabled";
747                 break;
748
749         case CLIR_STATUS_TEMPORARY_RESTRICTED:
750                 if (override == OFONO_CLIR_OPTION_SUPPRESSION)
751                         value = "enabled";
752                 else
753                         value = "disabled";
754                 break;
755
756         case CLIR_STATUS_TEMPORARY_ALLOWED:
757                 if (override == OFONO_CLIR_OPTION_INVOCATION)
758                         value = "enabled";
759                 else
760                         value = "disabled";
761                 break;
762         default:
763                 value = "unknown";
764         };
765
766         generate_ss_query_reply(cs, "CallingLineRestriction", value);
767
768         set_clir_network(cs, network);
769         set_clir_override(cs, override);
770 }
771
772 static void clir_ss_set_callback(const struct ofono_error *error, void *data)
773 {
774         struct ofono_call_settings *cs = data;
775
776         if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
777                 DBG("setting clir via SS failed with error: %s",
778                         telephony_error_to_str(error));
779                 __ofono_dbus_pending_reply(&cs->pending,
780                         __ofono_error_from_error(error, cs->pending));
781
782                 return;
783         }
784
785         cs->driver->clir_query(cs, clir_ss_query_callback, cs);
786 }
787
788 static gboolean clir_ss_control(int type,
789                                 const char *sc, const char *sia,
790                                 const char *sib, const char *sic,
791                                 const char *dn, DBusMessage *msg, void *data)
792 {
793         struct ofono_call_settings *cs = data;
794         DBusConnection *conn = ofono_dbus_get_connection();
795
796         if (cs == NULL)
797                 return FALSE;
798
799         if (strcmp(sc, "31"))
800                 return FALSE;
801
802         if (__ofono_call_settings_is_busy(cs)) {
803                 DBusMessage *reply = __ofono_error_busy(msg);
804                 g_dbus_send_message(conn, reply);
805
806                 return TRUE;
807         }
808
809         /* This is the temporary form of CLIR, handled in voicecalls */
810         if (!strlen(sia) && !strlen(sib) & !strlen(sic) &&
811                         strlen(dn) && type != SS_CONTROL_TYPE_QUERY)
812                 return FALSE;
813
814         if (strlen(sia) || strlen(sib) || strlen(sic) || strlen(dn)) {
815                 DBusMessage *reply = __ofono_error_invalid_format(msg);
816                 g_dbus_send_message(conn, reply);
817
818                 return TRUE;
819         }
820
821         if (type == SS_CONTROL_TYPE_QUERY && cs->driver->clir_query == NULL) {
822                 DBusMessage *reply = __ofono_error_not_implemented(msg);
823                 g_dbus_send_message(conn, reply);
824
825                 return TRUE;
826         }
827
828         if (type != SS_CONTROL_TYPE_QUERY && cs->driver->clir_set == NULL) {
829                 DBusMessage *reply = __ofono_error_not_implemented(msg);
830                 g_dbus_send_message(conn, reply);
831
832                 return TRUE;
833         }
834
835         cs->ss_setting = CALL_SETTING_TYPE_CLIR;
836         cs->pending = dbus_message_ref(msg);
837
838         switch (type) {
839         case SS_CONTROL_TYPE_REGISTRATION:
840         case SS_CONTROL_TYPE_ACTIVATION:
841                 cs->ss_req_type = SS_CONTROL_TYPE_ACTIVATION;
842                 cs->driver->clir_set(cs, OFONO_CLIR_OPTION_SUPPRESSION,
843                                         clir_ss_set_callback, cs);
844                 break;
845
846         case SS_CONTROL_TYPE_QUERY:
847                 cs->ss_req_type = SS_CONTROL_TYPE_QUERY;
848                 cs->driver->clir_query(cs, clir_ss_query_callback, cs);
849                 break;
850
851         case SS_CONTROL_TYPE_DEACTIVATION:
852         case SS_CONTROL_TYPE_ERASURE:
853                 cs->ss_req_type = SS_CONTROL_TYPE_DEACTIVATION;
854                 cs->driver->clir_set(cs, OFONO_CLIR_OPTION_INVOCATION,
855                                         clir_ss_set_callback, cs);
856                 break;
857         };
858
859         return TRUE;
860 }
861
862 static void cs_register_ss_controls(struct ofono_call_settings *cs)
863 {
864         __ofono_ussd_ssc_register(cs->ussd, "30", clip_cnap_colp_colr_ss,
865                                                                 cs, NULL);
866         __ofono_ussd_ssc_register(cs->ussd, "31", clir_ss_control, cs, NULL);
867         __ofono_ussd_ssc_register(cs->ussd, "76", clip_cnap_colp_colr_ss,
868                                                                 cs, NULL);
869         __ofono_ussd_ssc_register(cs->ussd, "300", clip_cnap_colp_colr_ss,
870                                                                 cs, NULL);
871
872         __ofono_ussd_ssc_register(cs->ussd, "43", cw_ss_control, cs, NULL);
873
874         if (cs->driver->colr_query != NULL)
875                 __ofono_ussd_ssc_register(cs->ussd, "77",
876                                         clip_cnap_colp_colr_ss, cs, NULL);
877 }
878
879 static void cs_unregister_ss_controls(struct ofono_call_settings *cs)
880 {
881         __ofono_ussd_ssc_unregister(cs->ussd, "30");
882         __ofono_ussd_ssc_unregister(cs->ussd, "31");
883         __ofono_ussd_ssc_unregister(cs->ussd, "76");
884         __ofono_ussd_ssc_unregister(cs->ussd, "300");
885
886         __ofono_ussd_ssc_unregister(cs->ussd, "43");
887
888         if (cs->driver->colr_query != NULL)
889                 __ofono_ussd_ssc_unregister(cs->ussd, "77");
890 }
891
892 gboolean __ofono_call_settings_is_busy(struct ofono_call_settings *cs)
893 {
894         return cs->pending ? TRUE : FALSE;
895 }
896
897 static DBusMessage *generate_get_properties_reply(struct ofono_call_settings *cs,
898                                                         DBusMessage *msg)
899 {
900         DBusMessage *reply;
901         DBusMessageIter iter;
902         DBusMessageIter dict;
903         const char *str;
904
905         reply = dbus_message_new_method_return(msg);
906         if (reply == NULL)
907                 return NULL;
908
909         dbus_message_iter_init_append(reply, &iter);
910
911         dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
912                                         OFONO_PROPERTIES_ARRAY_SIGNATURE,
913                                         &dict);
914
915         str = clip_status_to_string(cs->clip);
916         ofono_dbus_dict_append(&dict, "CallingLinePresentation",
917                                 DBUS_TYPE_STRING, &str);
918
919         str = cnap_status_to_string(cs->cnap);
920         ofono_dbus_dict_append(&dict, "CallingNamePresentation",
921                                 DBUS_TYPE_STRING, &str);
922
923         str = colp_status_to_string(cs->colp);
924         ofono_dbus_dict_append(&dict, "ConnectedLinePresentation",
925                                 DBUS_TYPE_STRING, &str);
926
927         str = colr_status_to_string(cs->colr);
928         ofono_dbus_dict_append(&dict, "ConnectedLineRestriction",
929                                 DBUS_TYPE_STRING, &str);
930
931         str = cdip_status_to_string(cs->cdip);
932         ofono_dbus_dict_append(&dict, "CalledLinePresentation",
933                                 DBUS_TYPE_STRING, &str);
934
935         str = clir_status_to_string(cs->clir);
936         ofono_dbus_dict_append(&dict, "CallingLineRestriction",
937                                 DBUS_TYPE_STRING, &str);
938
939         str = hide_callerid_to_string(cs->clir_setting);
940         ofono_dbus_dict_append(&dict, "HideCallerId", DBUS_TYPE_STRING, &str);
941
942         property_append_cw_conditions(&dict, cs->cw, BEARER_CLASS_VOICE);
943
944         dbus_message_iter_close_container(&iter, &dict);
945
946         return reply;
947 }
948
949 static void cs_clir_callback(const struct ofono_error *error,
950                                 int override_setting, int network_setting,
951                                 void *data)
952 {
953         struct ofono_call_settings *cs = data;
954
955         if (error->type != OFONO_ERROR_TYPE_NO_ERROR)
956                 goto out;
957
958         set_clir_network(cs, network_setting);
959         set_clir_override(cs, override_setting);
960
961         cs->flags |= CALL_SETTINGS_FLAG_CACHED;
962
963 out:
964         if (cs->pending) {
965                 DBusMessage *reply = generate_get_properties_reply(cs,
966                                                                 cs->pending);
967                 __ofono_dbus_pending_reply(&cs->pending, reply);
968         }
969 }
970
971 static void query_clir(struct ofono_call_settings *cs)
972 {
973         if (cs->driver->clir_query == NULL) {
974                 if (cs->pending) {
975                         DBusMessage *reply =
976                                 generate_get_properties_reply(cs,
977                                                                 cs->pending);
978                         __ofono_dbus_pending_reply(&cs->pending, reply);
979                 }
980
981                 return;
982         }
983
984         cs->driver->clir_query(cs, cs_clir_callback, cs);
985 }
986
987 static void cs_cdip_callback(const struct ofono_error *error,
988                                 int state, void *data)
989 {
990         struct ofono_call_settings *cs = data;
991
992         if (error->type == OFONO_ERROR_TYPE_NO_ERROR)
993                 set_cdip(cs, state);
994
995         query_clir(cs);
996 }
997
998 static void query_cdip(struct ofono_call_settings *cs)
999 {
1000         if (cs->driver->cdip_query == NULL) {
1001                 query_clir(cs);
1002                 return;
1003         }
1004
1005         cs->driver->cdip_query(cs, cs_cdip_callback, cs);
1006 }
1007
1008
1009 static void cs_cnap_callback(const struct ofono_error *error,
1010                                 int state, void *data)
1011 {
1012         struct ofono_call_settings *cs = data;
1013
1014         if (error->type == OFONO_ERROR_TYPE_NO_ERROR)
1015                 set_cnap(cs, state);
1016
1017         query_cdip(cs);
1018 }
1019
1020 static void query_cnap(struct ofono_call_settings *cs)
1021 {
1022         if (cs->driver->cnap_query == NULL) {
1023                 query_cdip(cs);
1024                 return;
1025         }
1026
1027         cs->driver->cnap_query(cs, cs_cnap_callback, cs);
1028 }
1029
1030 static void cs_clip_callback(const struct ofono_error *error,
1031                                 int state, void *data)
1032 {
1033         struct ofono_call_settings *cs = data;
1034
1035         if (error->type == OFONO_ERROR_TYPE_NO_ERROR)
1036                 set_clip(cs, state);
1037
1038         query_cnap(cs);
1039 }
1040
1041 static void query_clip(struct ofono_call_settings *cs)
1042 {
1043         if (cs->driver->clip_query == NULL) {
1044                 query_clir(cs);
1045                 return;
1046         }
1047
1048         cs->driver->clip_query(cs, cs_clip_callback, cs);
1049 }
1050
1051 static void cs_colp_callback(const struct ofono_error *error,
1052                                 int state, void *data)
1053 {
1054         struct ofono_call_settings *cs = data;
1055
1056         if (error->type == OFONO_ERROR_TYPE_NO_ERROR)
1057                 set_colp(cs, state);
1058
1059         query_clip(cs);
1060 }
1061
1062 static void query_colp(struct ofono_call_settings *cs)
1063 {
1064         if (cs->driver->colp_query == NULL) {
1065                 query_clip(cs);
1066                 return;
1067         }
1068
1069         cs->driver->colp_query(cs, cs_colp_callback, cs);
1070 }
1071
1072 static void cs_colr_callback(const struct ofono_error *error,
1073                                 int state, void *data)
1074 {
1075         struct ofono_call_settings *cs = data;
1076
1077         if (error->type == OFONO_ERROR_TYPE_NO_ERROR)
1078                 set_colr(cs, state);
1079
1080         query_colp(cs);
1081 }
1082
1083 static void query_colr(struct ofono_call_settings *cs)
1084 {
1085         if (cs->driver->colr_query == NULL) {
1086                 query_colp(cs);
1087                 return;
1088         }
1089
1090         cs->driver->colr_query(cs, cs_colr_callback, cs);
1091 }
1092
1093 static void cs_cw_callback(const struct ofono_error *error, int status,
1094                                 void *data)
1095 {
1096         struct ofono_call_settings *cs = data;
1097
1098         if (error->type == OFONO_ERROR_TYPE_NO_ERROR)
1099                 set_cw(cs, status, BEARER_CLASS_VOICE);
1100
1101         query_colr(cs);
1102 }
1103
1104 static void query_cw(struct ofono_call_settings *cs)
1105 {
1106         if (cs->driver->cw_query == NULL) {
1107                 query_colr(cs);
1108                 return;
1109         }
1110
1111         cs->driver->cw_query(cs, BEARER_CLASS_DEFAULT, cs_cw_callback, cs);
1112 }
1113
1114 static DBusMessage *cs_get_properties(DBusConnection *conn, DBusMessage *msg,
1115                                         void *data)
1116 {
1117         struct ofono_call_settings *cs = data;
1118
1119         if (__ofono_call_settings_is_busy(cs) || __ofono_ussd_is_busy(cs->ussd))
1120                 return __ofono_error_busy(msg);
1121
1122         if (cs->flags & CALL_SETTINGS_FLAG_CACHED)
1123                 return generate_get_properties_reply(cs, msg);
1124
1125         /* Query the settings and report back */
1126         cs->pending = dbus_message_ref(msg);
1127
1128         query_cw(cs);
1129
1130         return NULL;
1131 }
1132
1133 static void clir_set_query_callback(const struct ofono_error *error,
1134                                         int override_setting,
1135                                         int network_setting, void *data)
1136 {
1137         struct ofono_call_settings *cs = data;
1138         DBusMessage *reply;
1139
1140         if (!__ofono_call_settings_is_busy(cs))
1141                 return;
1142
1143         if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
1144                 ofono_error("set clir successful, but the query was not");
1145
1146                 cs->flags &= ~CALL_SETTINGS_FLAG_CACHED;
1147
1148                 reply = __ofono_error_failed(cs->pending);
1149                 __ofono_dbus_pending_reply(&cs->pending, reply);
1150                 return;
1151         }
1152
1153         reply = dbus_message_new_method_return(cs->pending);
1154         __ofono_dbus_pending_reply(&cs->pending, reply);
1155
1156         set_clir_override(cs, override_setting);
1157         set_clir_network(cs, network_setting);
1158 }
1159
1160 static void clir_set_callback(const struct ofono_error *error, void *data)
1161 {
1162         struct ofono_call_settings *cs = data;
1163
1164         if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
1165                 DBG("setting clir failed");
1166                 __ofono_dbus_pending_reply(&cs->pending,
1167                                         __ofono_error_failed(cs->pending));
1168
1169                 return;
1170         }
1171
1172         /* Assume that if we have clir_set, we have clir_query */
1173         cs->driver->clir_query(cs, clir_set_query_callback, cs);
1174 }
1175
1176 static DBusMessage *set_clir(DBusMessage *msg, struct ofono_call_settings *cs,
1177                                 const char *setting)
1178 {
1179         int clir = -1;
1180
1181         if (cs->driver->clir_set == NULL)
1182                 return __ofono_error_not_implemented(msg);
1183
1184         if (!strcmp(setting, "default"))
1185                 clir = CLIR_STATUS_NOT_PROVISIONED;
1186         else if (!strcmp(setting, "enabled"))
1187                 clir = CLIR_STATUS_PROVISIONED_PERMANENT;
1188         else if (!strcmp(setting, "disabled"))
1189                 clir = CLIR_STATUS_UNKNOWN;
1190
1191         if (clir == -1)
1192                 return __ofono_error_invalid_format(msg);
1193
1194         cs->pending = dbus_message_ref(msg);
1195
1196         cs->driver->clir_set(cs, clir, clir_set_callback, cs);
1197
1198         return NULL;
1199 }
1200
1201 static void cw_set_query_callback(const struct ofono_error *error, int status,
1202                                 void *data)
1203 {
1204         struct ofono_call_settings *cs = data;
1205
1206         if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
1207                 ofono_error("CW set succeeded, but query failed!");
1208
1209                 cs->flags &= ~CALL_SETTINGS_FLAG_CACHED;
1210
1211                 __ofono_dbus_pending_reply(&cs->pending,
1212                                         __ofono_error_failed(cs->pending));
1213                 return;
1214         }
1215
1216         __ofono_dbus_pending_reply(&cs->pending,
1217                                 dbus_message_new_method_return(cs->pending));
1218
1219         set_cw(cs, status, BEARER_CLASS_VOICE);
1220 }
1221
1222 static void cw_set_callback(const struct ofono_error *error, void *data)
1223 {
1224         struct ofono_call_settings *cs = data;
1225
1226         if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
1227                 DBG("Error occurred during CW set");
1228
1229                 __ofono_dbus_pending_reply(&cs->pending,
1230                                         __ofono_error_failed(cs->pending));
1231
1232                 return;
1233         }
1234
1235         cs->driver->cw_query(cs, BEARER_CLASS_DEFAULT,
1236                                 cw_set_query_callback, cs);
1237 }
1238
1239 static DBusMessage *set_cw_req(DBusMessage *msg, struct ofono_call_settings *cs,
1240                                 const char *setting, int cls)
1241 {
1242         int cw;
1243
1244         if (cs->driver->cw_set == NULL)
1245                 return __ofono_error_not_implemented(msg);
1246
1247         if (!strcmp(setting, "enabled"))
1248                 cw = 1;
1249         else if (!strcmp(setting, "disabled"))
1250                 cw = 0;
1251         else
1252                 return __ofono_error_invalid_format(msg);
1253
1254         cs->pending = dbus_message_ref(msg);
1255
1256         cs->driver->cw_set(cs, cw, cls, cw_set_callback, cs);
1257
1258         return NULL;
1259 }
1260
1261 static gboolean is_cw_property(const char *property, int mask, int *out_cls)
1262 {
1263         int i;
1264         int len;
1265         const char *prefix;
1266
1267         for (i = 1; i <= BEARER_CLASS_PAD; i = i << 1) {
1268                 if ((i & mask) == 0)
1269                         continue;
1270
1271                 prefix = bearer_class_to_string(i);
1272
1273                 len = strlen(prefix);
1274
1275                 if (strncmp(property, prefix, len))
1276                         continue;
1277
1278                 if (!strcmp(property+len, "CallWaiting")) {
1279                         *out_cls = i;
1280                         return TRUE;
1281                 }
1282         }
1283
1284         return FALSE;
1285 }
1286
1287 static DBusMessage *cs_set_property(DBusConnection *conn, DBusMessage *msg,
1288                                         void *data)
1289 {
1290         struct ofono_call_settings *cs = data;
1291         DBusMessageIter iter;
1292         DBusMessageIter var;
1293         const char *property;
1294         int cls;
1295
1296         if (__ofono_call_settings_is_busy(cs) || __ofono_ussd_is_busy(cs->ussd))
1297                 return __ofono_error_busy(msg);
1298
1299         if (!dbus_message_iter_init(msg, &iter))
1300                 return __ofono_error_invalid_args(msg);
1301
1302         if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
1303                 return __ofono_error_invalid_args(msg);
1304
1305         dbus_message_iter_get_basic(&iter, &property);
1306         dbus_message_iter_next(&iter);
1307
1308         if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
1309                 return __ofono_error_invalid_args(msg);
1310
1311         dbus_message_iter_recurse(&iter, &var);
1312
1313         if (!strcmp(property, "HideCallerId")) {
1314                 const char *setting;
1315
1316                 if (dbus_message_iter_get_arg_type(&var) != DBUS_TYPE_STRING)
1317                         return __ofono_error_invalid_args(msg);
1318
1319                 dbus_message_iter_get_basic(&var, &setting);
1320
1321                 return set_clir(msg, cs, setting);
1322         } else if (is_cw_property(property, BEARER_CLASS_VOICE, &cls)) {
1323                 const char *setting;
1324
1325                 if (dbus_message_iter_get_arg_type(&var) != DBUS_TYPE_STRING)
1326                         return __ofono_error_invalid_args(msg);
1327
1328                 dbus_message_iter_get_basic(&var, &setting);
1329
1330                 return set_cw_req(msg, cs, setting, cls);
1331         }
1332
1333         return __ofono_error_invalid_args(msg);
1334 }
1335
1336 static const GDBusMethodTable cs_methods[] = {
1337         { GDBUS_ASYNC_METHOD("GetProperties",
1338                                 NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
1339                                 cs_get_properties) },
1340         { GDBUS_ASYNC_METHOD("SetProperty",
1341                         GDBUS_ARGS({ "property", "s" }, { "value", "v" }),
1342                         NULL, cs_set_property) },
1343         { }
1344 };
1345
1346 static const GDBusSignalTable cs_signals[] = {
1347         { GDBUS_SIGNAL("PropertyChanged",
1348                         GDBUS_ARGS({ "property", "s" }, { "value", "v" })) },
1349         { }
1350 };
1351
1352 int ofono_call_settings_driver_register(const struct ofono_call_settings_driver *d)
1353 {
1354         DBG("driver: %p, name: %s", d, d->name);
1355
1356         if (d->probe == NULL)
1357                 return -EINVAL;
1358
1359         g_drivers = g_slist_prepend(g_drivers, (void *) d);
1360
1361         return 0;
1362 }
1363
1364 void ofono_call_settings_driver_unregister(const struct ofono_call_settings_driver *d)
1365 {
1366         DBG("driver: %p, name: %s", d, d->name);
1367
1368         g_drivers = g_slist_remove(g_drivers, (void *) d);
1369 }
1370
1371 static void call_settings_unregister(struct ofono_atom *atom)
1372 {
1373         struct ofono_call_settings *cs = __ofono_atom_get_data(atom);
1374         const char *path = __ofono_atom_get_path(cs->atom);
1375         DBusConnection *conn = ofono_dbus_get_connection();
1376         struct ofono_modem *modem = __ofono_atom_get_modem(cs->atom);
1377
1378         ofono_modem_remove_interface(modem, OFONO_CALL_SETTINGS_INTERFACE);
1379         g_dbus_unregister_interface(conn, path, OFONO_CALL_SETTINGS_INTERFACE);
1380
1381         if (cs->ussd)
1382                 cs_unregister_ss_controls(cs);
1383
1384         if (cs->ussd_watch)
1385                 __ofono_modem_remove_atom_watch(modem, cs->ussd_watch);
1386 }
1387
1388 static void call_settings_remove(struct ofono_atom *atom)
1389 {
1390         struct ofono_call_settings *cs = __ofono_atom_get_data(atom);
1391
1392         DBG("atom: %p", atom);
1393
1394         if (cs == NULL)
1395                 return;
1396
1397         if (cs->driver != NULL && cs->driver->remove != NULL)
1398                 cs->driver->remove(cs);
1399
1400         g_free(cs);
1401 }
1402
1403 struct ofono_call_settings *ofono_call_settings_create(struct ofono_modem *modem,
1404                                                         unsigned int vendor,
1405                                                         const char *driver,
1406                                                         void *data)
1407 {
1408         struct ofono_call_settings *cs;
1409         GSList *l;
1410
1411         if (driver == NULL)
1412                 return NULL;
1413
1414         cs = g_try_new0(struct ofono_call_settings, 1);
1415
1416         if (cs == NULL)
1417                 return NULL;
1418
1419         /* Set all the settings to unknown state */
1420         cs->clip = CLIP_STATUS_UNKNOWN;
1421         cs->cnap = CNAP_STATUS_UNKNOWN;
1422         cs->clir = CLIR_STATUS_UNKNOWN;
1423         cs->colp = COLP_STATUS_UNKNOWN;
1424         cs->colr = COLR_STATUS_UNKNOWN;
1425         cs->atom = __ofono_modem_add_atom(modem, OFONO_ATOM_TYPE_CALL_SETTINGS,
1426                                                 call_settings_remove, cs);
1427
1428         for (l = g_drivers; l; l = l->next) {
1429                 const struct ofono_call_settings_driver *drv = l->data;
1430
1431                 if (g_strcmp0(drv->name, driver))
1432                         continue;
1433
1434                 if (drv->probe(cs, vendor, data) < 0)
1435                         continue;
1436
1437                 cs->driver = drv;
1438                 break;
1439         }
1440
1441         return cs;
1442 }
1443
1444 static void ussd_watch(struct ofono_atom *atom,
1445                         enum ofono_atom_watch_condition cond, void *data)
1446 {
1447         struct ofono_call_settings *cs = data;
1448
1449         if (cond == OFONO_ATOM_WATCH_CONDITION_UNREGISTERED) {
1450                 cs->ussd = NULL;
1451                 return;
1452         }
1453
1454         cs->ussd = __ofono_atom_get_data(atom);
1455         cs_register_ss_controls(cs);
1456 }
1457
1458 void ofono_call_settings_register(struct ofono_call_settings *cs)
1459 {
1460         DBusConnection *conn = ofono_dbus_get_connection();
1461         const char *path = __ofono_atom_get_path(cs->atom);
1462         struct ofono_modem *modem = __ofono_atom_get_modem(cs->atom);
1463
1464         if (!g_dbus_register_interface(conn, path,
1465                                         OFONO_CALL_SETTINGS_INTERFACE,
1466                                         cs_methods, cs_signals, NULL, cs,
1467                                         NULL)) {
1468                 ofono_error("Could not create %s interface",
1469                                 OFONO_CALL_SETTINGS_INTERFACE);
1470
1471                 return;
1472         }
1473
1474         ofono_modem_add_interface(modem, OFONO_CALL_SETTINGS_INTERFACE);
1475
1476         cs->ussd_watch = __ofono_modem_add_atom_watch(modem,
1477                                         OFONO_ATOM_TYPE_USSD,
1478                                         ussd_watch, cs, NULL);
1479
1480         __ofono_atom_register(cs->atom, call_settings_unregister);
1481 }
1482
1483 void ofono_call_settings_remove(struct ofono_call_settings *cs)
1484 {
1485         __ofono_atom_free(cs->atom);
1486 }
1487
1488 void ofono_call_settings_set_data(struct ofono_call_settings *cs, void *data)
1489 {
1490         cs->driver_data = data;
1491 }
1492
1493 void *ofono_call_settings_get_data(struct ofono_call_settings *cs)
1494 {
1495         return cs->driver_data;
1496 }