3 * oFono - Open Source Telephony
5 * Copyright (C) 2008-2009 Intel Corporation. All rights reserved.
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.
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.
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
39 #define CALL_SETTINGS_FLAG_CACHED 0x1
41 static GSList *g_drivers = NULL;
43 /* 27.007 Section 7.7 */
45 CLIR_STATUS_NOT_PROVISIONED = 0,
46 CLIR_STATUS_PROVISIONED_PERMANENT,
48 CLIR_STATUS_TEMPORARY_RESTRICTED,
49 CLIR_STATUS_TEMPORARY_ALLOWED
52 /* 27.007 Section 7.6 */
54 CLIP_STATUS_NOT_PROVISIONED = 0,
55 CLIP_STATUS_PROVISIONED,
59 /* 27.007 Section 7.8 */
61 COLP_STATUS_NOT_PROVISIONED = 0,
62 COLP_STATUS_PROVISIONED = 1,
63 COLP_STATUS_UNKNOWN = 2
66 /* This is not defined in 27.007, but presumably the same as CLIP/COLP */
68 COLR_STATUS_NOT_PROVISIONED = 0,
69 COLR_STATUS_PROVISIONED = 1,
70 COLR_STATUS_UNKNOWN = 2
73 enum call_setting_type {
74 CALL_SETTING_TYPE_CLIP = 0,
75 CALL_SETTING_TYPE_COLP,
76 CALL_SETTING_TYPE_COLR,
77 CALL_SETTING_TYPE_CLIR,
81 struct ofono_call_settings {
92 enum call_setting_type ss_setting;
93 struct ofono_ussd *ussd;
94 unsigned int ussd_watch;
95 const struct ofono_call_settings_driver *driver;
97 struct ofono_atom *atom;
100 static const char *clip_status_to_string(int status)
103 case CLIP_STATUS_NOT_PROVISIONED:
105 case CLIP_STATUS_PROVISIONED:
112 static const char *colp_status_to_string(int status)
115 case COLP_STATUS_NOT_PROVISIONED:
117 case COLP_STATUS_PROVISIONED:
124 static const char *colr_status_to_string(int status)
127 case COLR_STATUS_NOT_PROVISIONED:
129 case COLR_STATUS_PROVISIONED:
136 static const char *hide_callerid_to_string(int status)
139 case OFONO_CLIR_OPTION_DEFAULT:
141 case OFONO_CLIR_OPTION_INVOCATION:
143 case OFONO_CLIR_OPTION_SUPPRESSION:
150 static const char *clir_status_to_string(int status)
153 case CLIR_STATUS_NOT_PROVISIONED:
155 case CLIR_STATUS_PROVISIONED_PERMANENT:
157 case CLIR_STATUS_TEMPORARY_RESTRICTED:
159 case CLIR_STATUS_TEMPORARY_ALLOWED:
166 static void set_clir_network(struct ofono_call_settings *cs, int clir)
168 DBusConnection *conn;
172 if (cs->clir == clir)
177 conn = ofono_dbus_get_connection();
178 path = __ofono_atom_get_path(cs->atom);
180 str = clir_status_to_string(clir);
182 ofono_dbus_signal_property_changed(conn, path,
183 OFONO_CALL_SETTINGS_INTERFACE,
184 "CallingLineRestriction",
185 DBUS_TYPE_STRING, &str);
188 static void set_clir_override(struct ofono_call_settings *cs, int override)
190 DBusConnection *conn;
194 if (cs->clir_setting == override)
197 cs->clir_setting = override;
199 conn = ofono_dbus_get_connection();
200 path = __ofono_atom_get_path(cs->atom);
202 str = hide_callerid_to_string(override);
204 ofono_dbus_signal_property_changed(conn, path,
205 OFONO_CALL_SETTINGS_INTERFACE,
207 DBUS_TYPE_STRING, &str);
210 static void set_clip(struct ofono_call_settings *cs, int clip)
212 DBusConnection *conn;
216 if (cs->clip == clip)
221 conn = ofono_dbus_get_connection();
222 path = __ofono_atom_get_path(cs->atom);
224 str = clip_status_to_string(clip);
226 ofono_dbus_signal_property_changed(conn, path,
227 OFONO_CALL_SETTINGS_INTERFACE,
228 "CallingLinePresentation",
229 DBUS_TYPE_STRING, &str);
232 static void set_colp(struct ofono_call_settings *cs, int colp)
234 DBusConnection *conn;
238 if (cs->colp == colp)
243 conn = ofono_dbus_get_connection();
244 path = __ofono_atom_get_path(cs->atom);
246 str = colp_status_to_string(colp);
248 ofono_dbus_signal_property_changed(conn, path,
249 OFONO_CALL_SETTINGS_INTERFACE,
250 "CalledLinePresentation",
251 DBUS_TYPE_STRING, &str);
254 static void set_colr(struct ofono_call_settings *cs, int colr)
256 DBusConnection *conn;
260 if (cs->colr == colr)
265 conn = ofono_dbus_get_connection();
266 path = __ofono_atom_get_path(cs->atom);
268 str = colr_status_to_string(colr);
270 ofono_dbus_signal_property_changed(conn, path,
271 OFONO_CALL_SETTINGS_INTERFACE,
272 "CalledLineRestriction",
273 DBUS_TYPE_STRING, &str);
276 static void set_cw(struct ofono_call_settings *cs, int new_cw, int mask)
278 DBusConnection *conn = ofono_dbus_get_connection();
279 const char *path = __ofono_atom_get_path(cs->atom);
284 for (j = 1; j <= BEARER_CLASS_PAD; j = j << 1) {
288 if ((cs->cw & j) == (new_cw & j))
296 sprintf(buf, "%sCallWaiting", bearer_class_to_string(j));
297 ofono_dbus_signal_property_changed(conn, path,
298 OFONO_CALL_SETTINGS_INTERFACE,
299 buf, DBUS_TYPE_STRING,
306 static void property_append_cw_conditions(DBusMessageIter *dict,
307 int conditions, int mask)
313 for (i = 1; i <= BEARER_CLASS_PAD; i = i << 1) {
317 sprintf(prop, "%sCallWaiting", bearer_class_to_string(i));
324 ofono_dbus_dict_append(dict, prop, DBUS_TYPE_STRING, &value);
328 static void generate_cw_ss_query_reply(struct ofono_call_settings *cs)
330 const char *sig = "(sa{sv})";
331 const char *ss_type = ss_control_type_to_string(cs->ss_req_type);
332 const char *context = "CallWaiting";
333 DBusMessageIter iter;
335 DBusMessageIter vstruct;
336 DBusMessageIter dict;
339 reply = dbus_message_new_method_return(cs->pending);
341 dbus_message_iter_init_append(reply, &iter);
343 dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &context);
345 dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT, sig, &var);
347 dbus_message_iter_open_container(&var, DBUS_TYPE_STRUCT, NULL,
350 dbus_message_iter_append_basic(&vstruct, DBUS_TYPE_STRING,
353 dbus_message_iter_open_container(&vstruct, DBUS_TYPE_ARRAY,
354 OFONO_PROPERTIES_ARRAY_SIGNATURE,
357 property_append_cw_conditions(&dict, cs->cw, cs->ss_req_cls);
359 dbus_message_iter_close_container(&vstruct, &dict);
361 dbus_message_iter_close_container(&var, &vstruct);
363 dbus_message_iter_close_container(&iter, &var);
365 __ofono_dbus_pending_reply(&cs->pending, reply);
368 static void cw_ss_query_callback(const struct ofono_error *error, int status,
371 struct ofono_call_settings *cs = data;
373 if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
374 ofono_debug("setting CW via SS failed");
376 cs->flags &= ~CALL_SETTINGS_FLAG_CACHED;
377 __ofono_dbus_pending_reply(&cs->pending,
378 __ofono_error_failed(cs->pending));
383 set_cw(cs, status, BEARER_CLASS_VOICE);
385 generate_cw_ss_query_reply(cs);
388 static void cw_ss_set_callback(const struct ofono_error *error, void *data)
390 struct ofono_call_settings *cs = data;
392 if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
393 ofono_debug("setting CW via SS failed");
394 __ofono_dbus_pending_reply(&cs->pending,
395 __ofono_error_failed(cs->pending));
400 cs->driver->cw_query(cs, BEARER_CLASS_DEFAULT,
401 cw_ss_query_callback, cs);
404 static gboolean cw_ss_control(int type,
405 const char *sc, const char *sia,
406 const char *sib, const char *sic,
407 const char *dn, DBusMessage *msg, void *data)
409 struct ofono_call_settings *cs = data;
410 DBusConnection *conn = ofono_dbus_get_connection();
411 int cls = BEARER_CLASS_SS_DEFAULT;
417 if (strcmp(sc, "43"))
421 reply = __ofono_error_busy(msg);
425 if (strlen(sib) || strlen(sib) || strlen(dn))
428 if ((type == SS_CONTROL_TYPE_QUERY && !cs->driver->cw_query) ||
429 (type != SS_CONTROL_TYPE_QUERY && !cs->driver->cw_set)) {
430 reply = __ofono_error_not_implemented(msg);
434 if (strlen(sia) > 0) {
438 service_code = strtoul(sia, &end, 10);
440 if (end == sia || *end != '\0')
443 cls = mmi_service_code_to_bearer_class(service_code);
448 cs->ss_req_cls = cls;
449 cs->pending = dbus_message_ref(msg);
451 /* For the default case use the more readily accepted value */
452 if (cls == BEARER_CLASS_SS_DEFAULT)
453 cls = BEARER_CLASS_DEFAULT;
456 case SS_CONTROL_TYPE_REGISTRATION:
457 case SS_CONTROL_TYPE_ACTIVATION:
458 cs->ss_req_type = SS_CONTROL_TYPE_ACTIVATION;
459 cs->driver->cw_set(cs, 1, cls, cw_ss_set_callback, cs);
462 case SS_CONTROL_TYPE_QUERY:
463 cs->ss_req_type = SS_CONTROL_TYPE_QUERY;
464 /* Always query the entire set, SMS not applicable
465 * according to 22.004 Appendix A, so CLASS_DEFAULT
466 * is safe to use here
468 cs->driver->cw_query(cs, BEARER_CLASS_DEFAULT,
469 cw_ss_query_callback, cs);
472 case SS_CONTROL_TYPE_DEACTIVATION:
473 case SS_CONTROL_TYPE_ERASURE:
474 cs->ss_req_type = SS_CONTROL_TYPE_DEACTIVATION;
475 cs->driver->cw_set(cs, 0, cls, cw_ss_set_callback, cs);
482 reply = __ofono_error_invalid_format(msg);
484 g_dbus_send_message(conn, reply);
488 static void generate_ss_query_reply(struct ofono_call_settings *cs,
489 const char *context, const char *value)
491 const char *sig = "(ss)";
492 const char *ss_type = ss_control_type_to_string(cs->ss_req_type);
493 DBusMessageIter iter;
495 DBusMessageIter vstruct;
498 reply = dbus_message_new_method_return(cs->pending);
500 dbus_message_iter_init_append(reply, &iter);
502 dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &context);
504 dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT, sig, &var);
506 dbus_message_iter_open_container(&var, DBUS_TYPE_STRUCT, NULL,
509 dbus_message_iter_append_basic(&vstruct, DBUS_TYPE_STRING,
512 dbus_message_iter_append_basic(&vstruct, DBUS_TYPE_STRING, &value);
514 dbus_message_iter_close_container(&var, &vstruct);
516 dbus_message_iter_close_container(&iter, &var);
518 __ofono_dbus_pending_reply(&cs->pending, reply);
521 static void clip_colp_colr_ss_query_cb(const struct ofono_error *error,
522 int status, void *data)
524 struct ofono_call_settings *cs = data;
528 if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
529 ofono_debug("Error occurred during ss control query");
530 __ofono_dbus_pending_reply(&cs->pending,
531 __ofono_error_failed(cs->pending));
536 switch (cs->ss_setting) {
537 case CALL_SETTING_TYPE_CLIP:
538 set_clip(cs, status);
539 value = clip_status_to_string(status);
540 context = "CallingLinePresentation";
543 case CALL_SETTING_TYPE_COLP:
544 set_colp(cs, status);
545 value = colp_status_to_string(status);
546 context = "CalledLinePresentation";
549 case CALL_SETTING_TYPE_COLR:
550 set_colr(cs, status);
551 value = colr_status_to_string(status);
552 context = "CallingLineRestriction";
556 __ofono_dbus_pending_reply(&cs->pending,
557 __ofono_error_failed(cs->pending));
558 ofono_error("Unknown type during COLR/COLP/CLIP ss");
562 generate_ss_query_reply(cs, context, value);
565 static gboolean clip_colp_colr_ss(int type,
566 const char *sc, const char *sia,
567 const char *sib, const char *sic,
568 const char *dn, DBusMessage *msg, void *data)
570 struct ofono_call_settings *cs = data;
571 DBusConnection *conn = ofono_dbus_get_connection();
572 void (*query_op)(struct ofono_call_settings *cs,
573 ofono_call_settings_status_cb_t cb, void *data);
579 DBusMessage *reply = __ofono_error_busy(msg);
580 g_dbus_send_message(conn, reply);
585 if (!strcmp(sc, "30")) {
586 cs->ss_setting = CALL_SETTING_TYPE_CLIP;
587 query_op = cs->driver->clip_query;
588 } else if (!strcmp(sc, "76")) {
589 cs->ss_setting = CALL_SETTING_TYPE_COLP;
590 query_op = cs->driver->colp_query;
591 } else if (!strcmp(sc, "77")) {
592 cs->ss_setting = CALL_SETTING_TYPE_COLR;
593 query_op = cs->driver->colr_query;
597 if (type != SS_CONTROL_TYPE_QUERY || strlen(sia) || strlen(sib) ||
598 strlen(sic) || strlen(dn)) {
599 DBusMessage *reply = __ofono_error_invalid_format(msg);
600 g_dbus_send_message(conn, reply);
606 DBusMessage *reply = __ofono_error_not_implemented(msg);
607 g_dbus_send_message(conn, reply);
612 ofono_debug("Received CLIP/COLR/COLP query ss control");
614 cs->pending = dbus_message_ref(msg);
616 query_op(cs, clip_colp_colr_ss_query_cb, cs);
621 static void clir_ss_query_callback(const struct ofono_error *error,
622 int override, int network, void *data)
624 struct ofono_call_settings *cs = data;
627 if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
628 ofono_debug("setting clir via SS failed");
629 __ofono_dbus_pending_reply(&cs->pending,
630 __ofono_error_failed(cs->pending));
636 case CLIR_STATUS_UNKNOWN:
640 case CLIR_STATUS_PROVISIONED_PERMANENT:
644 case CLIR_STATUS_NOT_PROVISIONED:
648 case CLIR_STATUS_TEMPORARY_RESTRICTED:
649 if (override == OFONO_CLIR_OPTION_SUPPRESSION)
655 case CLIR_STATUS_TEMPORARY_ALLOWED:
656 if (override == OFONO_CLIR_OPTION_INVOCATION)
665 generate_ss_query_reply(cs, "CallingLineRestriction", value);
667 set_clir_network(cs, network);
668 set_clir_override(cs, override);
671 static void clir_ss_set_callback(const struct ofono_error *error, void *data)
673 struct ofono_call_settings *cs = data;
675 if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
676 ofono_debug("setting clir via SS failed");
677 __ofono_dbus_pending_reply(&cs->pending,
678 __ofono_error_failed(cs->pending));
683 cs->driver->clir_query(cs, clir_ss_query_callback, cs);
686 static gboolean clir_ss_control(int type,
687 const char *sc, const char *sia,
688 const char *sib, const char *sic,
689 const char *dn, DBusMessage *msg, void *data)
691 struct ofono_call_settings *cs = data;
692 DBusConnection *conn = ofono_dbus_get_connection();
697 if (strcmp(sc, "31"))
701 DBusMessage *reply = __ofono_error_busy(msg);
702 g_dbus_send_message(conn, reply);
707 /* This is the temporary form of CLIR, handled in voicecalls */
708 if (!strlen(sia) && !strlen(sib) & !strlen(sic) &&
709 strlen(dn) && type != SS_CONTROL_TYPE_QUERY)
712 if (strlen(sia) || strlen(sib) || strlen(sic) || strlen(dn)) {
713 DBusMessage *reply = __ofono_error_invalid_format(msg);
714 g_dbus_send_message(conn, reply);
719 if ((type == SS_CONTROL_TYPE_QUERY && !cs->driver->clir_query) ||
720 (type != SS_CONTROL_TYPE_QUERY && !cs->driver->clir_set)) {
721 DBusMessage *reply = __ofono_error_not_implemented(msg);
722 g_dbus_send_message(conn, reply);
727 cs->ss_setting = CALL_SETTING_TYPE_CLIR;
728 cs->pending = dbus_message_ref(msg);
731 case SS_CONTROL_TYPE_REGISTRATION:
732 case SS_CONTROL_TYPE_ACTIVATION:
733 cs->ss_req_type = SS_CONTROL_TYPE_ACTIVATION;
734 cs->driver->clir_set(cs, OFONO_CLIR_OPTION_INVOCATION,
735 clir_ss_set_callback, cs);
738 case SS_CONTROL_TYPE_QUERY:
739 cs->ss_req_type = SS_CONTROL_TYPE_QUERY;
740 cs->driver->clir_query(cs, clir_ss_query_callback, cs);
743 case SS_CONTROL_TYPE_DEACTIVATION:
744 case SS_CONTROL_TYPE_ERASURE:
745 cs->ss_req_type = SS_CONTROL_TYPE_DEACTIVATION;
746 cs->driver->clir_set(cs, OFONO_CLIR_OPTION_SUPPRESSION,
747 clir_ss_set_callback, cs);
754 static void cs_register_ss_controls(struct ofono_call_settings *cs)
756 __ofono_ussd_ssc_register(cs->ussd, "30", clip_colp_colr_ss, cs, NULL);
757 __ofono_ussd_ssc_register(cs->ussd, "31", clir_ss_control, cs, NULL);
758 __ofono_ussd_ssc_register(cs->ussd, "76", clip_colp_colr_ss, cs, NULL);
760 __ofono_ussd_ssc_register(cs->ussd, "43", cw_ss_control, cs, NULL);
762 if (cs->driver->colr_query)
763 __ofono_ussd_ssc_register(cs->ussd, "77",
764 clip_colp_colr_ss, cs, NULL);
767 static void cs_unregister_ss_controls(struct ofono_call_settings *cs)
769 __ofono_ussd_ssc_unregister(cs->ussd, "30");
770 __ofono_ussd_ssc_unregister(cs->ussd, "31");
771 __ofono_ussd_ssc_unregister(cs->ussd, "76");
773 __ofono_ussd_ssc_unregister(cs->ussd, "43");
775 if (cs->driver->colr_query)
776 __ofono_ussd_ssc_unregister(cs->ussd, "77");
779 static DBusMessage *generate_get_properties_reply(struct ofono_call_settings *cs,
783 DBusMessageIter iter;
784 DBusMessageIter dict;
787 reply = dbus_message_new_method_return(msg);
792 dbus_message_iter_init_append(reply, &iter);
794 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
795 OFONO_PROPERTIES_ARRAY_SIGNATURE,
798 str = clip_status_to_string(cs->clip);
799 ofono_dbus_dict_append(&dict, "CallingLinePresentation",
800 DBUS_TYPE_STRING, &str);
802 str = colp_status_to_string(cs->colp);
803 ofono_dbus_dict_append(&dict, "CalledLinePresentation",
804 DBUS_TYPE_STRING, &str);
806 str = colr_status_to_string(cs->colr);
807 ofono_dbus_dict_append(&dict, "CalledLineRestriction",
808 DBUS_TYPE_STRING, &str);
810 str = clir_status_to_string(cs->clir);
811 ofono_dbus_dict_append(&dict, "CallingLineRestriction",
812 DBUS_TYPE_STRING, &str);
814 str = hide_callerid_to_string(cs->clir_setting);
815 ofono_dbus_dict_append(&dict, "HideCallerId", DBUS_TYPE_STRING, &str);
817 property_append_cw_conditions(&dict, cs->cw, BEARER_CLASS_VOICE);
819 dbus_message_iter_close_container(&iter, &dict);
824 static void cs_clir_callback(const struct ofono_error *error,
825 int override_setting, int network_setting,
828 struct ofono_call_settings *cs = data;
830 if (error->type != OFONO_ERROR_TYPE_NO_ERROR)
833 set_clir_network(cs, network_setting);
834 set_clir_override(cs, override_setting);
836 cs->flags |= CALL_SETTINGS_FLAG_CACHED;
840 DBusMessage *reply = generate_get_properties_reply(cs,
842 __ofono_dbus_pending_reply(&cs->pending, reply);
846 static void query_clir(struct ofono_call_settings *cs)
848 if (!cs->driver->clir_query) {
851 generate_get_properties_reply(cs,
853 __ofono_dbus_pending_reply(&cs->pending, reply);
859 cs->driver->clir_query(cs, cs_clir_callback, cs);
862 static void cs_clip_callback(const struct ofono_error *error,
863 int state, void *data)
865 struct ofono_call_settings *cs = data;
867 if (error->type == OFONO_ERROR_TYPE_NO_ERROR)
873 static void query_clip(struct ofono_call_settings *cs)
875 if (!cs->driver->clip_query) {
880 cs->driver->clip_query(cs, cs_clip_callback, cs);
883 static void cs_colp_callback(const struct ofono_error *error,
884 int state, void *data)
886 struct ofono_call_settings *cs = data;
888 if (error->type == OFONO_ERROR_TYPE_NO_ERROR)
894 static void query_colp(struct ofono_call_settings *cs)
896 if (!cs->driver->colp_query) {
901 cs->driver->colp_query(cs, cs_colp_callback, cs);
904 static void cs_colr_callback(const struct ofono_error *error,
905 int state, void *data)
907 struct ofono_call_settings *cs = data;
909 if (error->type == OFONO_ERROR_TYPE_NO_ERROR)
915 static void query_colr(struct ofono_call_settings *cs)
917 if (!cs->driver->colr_query) {
922 cs->driver->colr_query(cs, cs_colr_callback, cs);
925 static void cs_cw_callback(const struct ofono_error *error, int status,
928 struct ofono_call_settings *cs = data;
930 if (error->type == OFONO_ERROR_TYPE_NO_ERROR)
931 set_cw(cs, status, BEARER_CLASS_VOICE);
936 static void query_cw(struct ofono_call_settings *cs)
938 if (!cs->driver->cw_query) {
943 cs->driver->cw_query(cs, BEARER_CLASS_DEFAULT, cs_cw_callback, cs);
946 static DBusMessage *cs_get_properties(DBusConnection *conn, DBusMessage *msg,
949 struct ofono_call_settings *cs = data;
952 return __ofono_error_busy(msg);
954 if (cs->flags & CALL_SETTINGS_FLAG_CACHED)
955 return generate_get_properties_reply(cs, msg);
957 /* Query the settings and report back */
958 cs->pending = dbus_message_ref(msg);
965 static void clir_set_query_callback(const struct ofono_error *error,
966 int override_setting,
967 int network_setting, void *data)
969 struct ofono_call_settings *cs = data;
975 if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
976 ofono_error("set clir successful, but the query was not");
978 cs->flags &= ~CALL_SETTINGS_FLAG_CACHED;
980 reply = __ofono_error_failed(cs->pending);
981 __ofono_dbus_pending_reply(&cs->pending, reply);
985 reply = dbus_message_new_method_return(cs->pending);
986 __ofono_dbus_pending_reply(&cs->pending, reply);
988 set_clir_override(cs, override_setting);
989 set_clir_network(cs, network_setting);
992 static void clir_set_callback(const struct ofono_error *error, void *data)
994 struct ofono_call_settings *cs = data;
996 if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
997 ofono_debug("setting clir failed");
998 __ofono_dbus_pending_reply(&cs->pending,
999 __ofono_error_failed(cs->pending));
1004 /* Assume that if we have clir_set, we have clir_query */
1005 cs->driver->clir_query(cs, clir_set_query_callback, cs);
1008 static DBusMessage *set_clir(DBusMessage *msg, struct ofono_call_settings *cs,
1009 const char *setting)
1013 if (cs->driver->clir_set == NULL)
1014 return __ofono_error_not_implemented(msg);
1016 if (!strcmp(setting, "default"))
1018 else if (!strcmp(setting, "enabled"))
1020 else if (!strcmp(setting, "disabled"))
1024 return __ofono_error_invalid_format(msg);
1026 cs->pending = dbus_message_ref(msg);
1028 cs->driver->clir_set(cs, clir, clir_set_callback, cs);
1033 static void cw_set_query_callback(const struct ofono_error *error, int status,
1036 struct ofono_call_settings *cs = data;
1038 if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
1039 ofono_error("CW set succeeded, but query failed!");
1041 cs->flags &= ~CALL_SETTINGS_FLAG_CACHED;
1043 __ofono_dbus_pending_reply(&cs->pending,
1044 __ofono_error_failed(cs->pending));
1048 __ofono_dbus_pending_reply(&cs->pending,
1049 dbus_message_new_method_return(cs->pending));
1051 set_cw(cs, status, BEARER_CLASS_VOICE);
1054 static void cw_set_callback(const struct ofono_error *error, void *data)
1056 struct ofono_call_settings *cs = data;
1058 if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
1059 ofono_debug("Error occurred during CW set");
1061 __ofono_dbus_pending_reply(&cs->pending,
1062 __ofono_error_failed(cs->pending));
1067 cs->driver->cw_query(cs, BEARER_CLASS_DEFAULT,
1068 cw_set_query_callback, cs);
1071 static DBusMessage *set_cw_req(DBusMessage *msg, struct ofono_call_settings *cs,
1072 const char *setting, int cls)
1076 if (cs->driver->cw_set == NULL)
1077 return __ofono_error_not_implemented(msg);
1079 if (!strcmp(setting, "enabled"))
1081 else if (!strcmp(setting, "disabled"))
1084 return __ofono_error_invalid_format(msg);
1086 cs->pending = dbus_message_ref(msg);
1088 cs->driver->cw_set(cs, cw, cls, cw_set_callback, cs);
1093 static gboolean is_cw_property(const char *property, int mask, int *out_cls)
1099 for (i = 1; i <= BEARER_CLASS_PAD; i = i << 1) {
1100 if ((i & mask) == 0)
1103 prefix = bearer_class_to_string(i);
1105 len = strlen(prefix);
1107 if (strncmp(property, prefix, len))
1110 if (!strcmp(property+len, "CallWaiting")) {
1119 static DBusMessage *cs_set_property(DBusConnection *conn, DBusMessage *msg,
1122 struct ofono_call_settings *cs = data;
1123 DBusMessageIter iter;
1124 DBusMessageIter var;
1125 const char *property;
1129 return __ofono_error_busy(msg);
1131 if (!dbus_message_iter_init(msg, &iter))
1132 return __ofono_error_invalid_args(msg);
1134 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
1135 return __ofono_error_invalid_args(msg);
1137 dbus_message_iter_get_basic(&iter, &property);
1138 dbus_message_iter_next(&iter);
1140 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
1141 return __ofono_error_invalid_args(msg);
1143 dbus_message_iter_recurse(&iter, &var);
1145 if (!strcmp(property, "HideCallerId")) {
1146 const char *setting;
1148 if (dbus_message_iter_get_arg_type(&var) != DBUS_TYPE_STRING)
1149 return __ofono_error_invalid_args(msg);
1151 dbus_message_iter_get_basic(&var, &setting);
1153 return set_clir(msg, cs, setting);
1154 } else if (is_cw_property(property, BEARER_CLASS_VOICE, &cls)) {
1155 const char *setting;
1157 if (dbus_message_iter_get_arg_type(&var) != DBUS_TYPE_STRING)
1158 return __ofono_error_invalid_args(msg);
1160 dbus_message_iter_get_basic(&var, &setting);
1162 return set_cw_req(msg, cs, setting, cls);
1165 return __ofono_error_invalid_args(msg);
1168 static GDBusMethodTable cs_methods[] = {
1169 { "GetProperties", "", "a{sv}", cs_get_properties,
1170 G_DBUS_METHOD_FLAG_ASYNC },
1171 { "SetProperty", "sv", "", cs_set_property,
1172 G_DBUS_METHOD_FLAG_ASYNC },
1176 static GDBusSignalTable cs_signals[] = {
1177 { "PropertyChanged", "sv" },
1181 int ofono_call_settings_driver_register(const struct ofono_call_settings_driver *d)
1183 DBG("driver: %p, name: %s", d, d->name);
1185 if (d->probe == NULL)
1188 g_drivers = g_slist_prepend(g_drivers, (void *)d);
1193 void ofono_call_settings_driver_unregister(const struct ofono_call_settings_driver *d)
1195 DBG("driver: %p, name: %s", d, d->name);
1197 g_drivers = g_slist_remove(g_drivers, (void *)d);
1200 static void call_settings_unregister(struct ofono_atom *atom)
1202 struct ofono_call_settings *cs = __ofono_atom_get_data(atom);
1203 const char *path = __ofono_atom_get_path(cs->atom);
1204 DBusConnection *conn = ofono_dbus_get_connection();
1205 struct ofono_modem *modem = __ofono_atom_get_modem(cs->atom);
1207 ofono_modem_remove_interface(modem, OFONO_CALL_SETTINGS_INTERFACE);
1208 g_dbus_unregister_interface(conn, path, OFONO_CALL_SETTINGS_INTERFACE);
1211 cs_unregister_ss_controls(cs);
1214 __ofono_modem_remove_atom_watch(modem, cs->ussd_watch);
1217 static void call_settings_remove(struct ofono_atom *atom)
1219 struct ofono_call_settings *cs = __ofono_atom_get_data(atom);
1221 DBG("atom: %p", atom);
1226 if (cs->driver && cs->driver->remove)
1227 cs->driver->remove(cs);
1232 struct ofono_call_settings *ofono_call_settings_create(struct ofono_modem *modem,
1236 struct ofono_call_settings *cs;
1242 cs = g_try_new0(struct ofono_call_settings, 1);
1247 /* Set all the settings to unknown state */
1252 cs->driver_data = data;
1253 cs->atom = __ofono_modem_add_atom(modem, OFONO_ATOM_TYPE_CALL_SETTINGS,
1254 call_settings_remove, cs);
1256 for (l = g_drivers; l; l = l->next) {
1257 const struct ofono_call_settings_driver *drv = l->data;
1259 if (g_strcmp0(drv->name, driver))
1262 if (drv->probe(cs) < 0)
1272 static void ussd_watch(struct ofono_atom *atom,
1273 enum ofono_atom_watch_condition cond, void *data)
1275 struct ofono_call_settings *cs = data;
1277 if (cond == OFONO_ATOM_WATCH_CONDITION_UNREGISTERED) {
1282 cs->ussd = __ofono_atom_get_data(atom);
1283 cs_register_ss_controls(cs);
1286 void ofono_call_settings_register(struct ofono_call_settings *cs)
1288 DBusConnection *conn = ofono_dbus_get_connection();
1289 const char *path = __ofono_atom_get_path(cs->atom);
1290 struct ofono_modem *modem = __ofono_atom_get_modem(cs->atom);
1291 struct ofono_atom *ussd_atom;
1293 if (!g_dbus_register_interface(conn, path,
1294 OFONO_CALL_SETTINGS_INTERFACE,
1295 cs_methods, cs_signals, NULL, cs,
1297 ofono_error("Could not create %s interface",
1298 OFONO_CALL_SETTINGS_INTERFACE);
1303 ofono_modem_add_interface(modem, OFONO_CALL_SETTINGS_INTERFACE);
1305 cs->ussd_watch = __ofono_modem_add_atom_watch(modem,
1306 OFONO_ATOM_TYPE_USSD,
1307 ussd_watch, cs, NULL);
1309 ussd_atom = __ofono_modem_find_atom(modem, OFONO_ATOM_TYPE_USSD);
1311 if (ussd_atom && __ofono_atom_get_registered(ussd_atom))
1312 ussd_watch(ussd_atom, OFONO_ATOM_WATCH_CONDITION_REGISTERED,
1315 __ofono_atom_register(cs->atom, call_settings_unregister);
1318 void ofono_call_settings_remove(struct ofono_call_settings *cs)
1320 __ofono_atom_free(cs->atom);
1323 void ofono_call_settings_set_data(struct ofono_call_settings *cs, void *data)
1325 cs->driver_data = data;
1328 void *ofono_call_settings_get_data(struct ofono_call_settings *cs)
1330 return cs->driver_data;