3 * oFono - Open Source Telephony
5 * Copyright (C) 2008-2011 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_FORWARDING_FLAG_CACHED 0x1
40 #define CALL_FORWARDING_FLAG_CPHS_CFF 0x2
42 /* According to 27.007 Spec */
43 #define DEFAULT_NO_REPLY_TIMEOUT 20
45 #define is_cfu_enabled(_cf) \
47 cf_find_unconditional(_cf) ? TRUE : FALSE; \
50 enum call_forwarding_type {
51 CALL_FORWARDING_TYPE_UNCONDITIONAL = 0,
52 CALL_FORWARDING_TYPE_BUSY = 1,
53 CALL_FORWARDING_TYPE_NO_REPLY = 2,
54 CALL_FORWARDING_TYPE_NOT_REACHABLE = 3,
55 CALL_FORWARDING_TYPE_ALL = 4,
56 CALL_FORWARDING_TYPE_ALL_CONDITIONAL = 5
59 struct ofono_call_forwarding {
60 GSList *cf_conditions[4];
65 struct cf_ss_request *ss_req;
66 struct ofono_sim *sim;
67 struct ofono_sim_context *sim_context;
68 unsigned char cfis_record_id;
69 struct ofono_ussd *ussd;
70 unsigned int ussd_watch;
71 const struct ofono_call_forwarding_driver *driver;
73 struct ofono_atom *atom;
76 struct cf_ss_request {
83 static GSList *g_drivers = NULL;
85 static void get_query_next_cf_cond(struct ofono_call_forwarding *cf);
86 static void set_query_next_cf_cond(struct ofono_call_forwarding *cf);
87 static void ss_set_query_next_cf_cond(struct ofono_call_forwarding *cf);
89 static gint cf_cond_compare(gconstpointer a, gconstpointer b)
91 const struct ofono_call_forwarding_condition *ca = a;
92 const struct ofono_call_forwarding_condition *cb = b;
94 return ca->cls - cb->cls;
97 static struct ofono_call_forwarding_condition *cf_cond_find(GSList *l, int cls)
99 struct ofono_call_forwarding_condition *c;
101 for (; l; l = l->next) {
111 static int cf_cond_find_timeout(GSList *l, int cls)
113 struct ofono_call_forwarding_condition *cond = cf_cond_find(l, cls);
115 return cond ? cond->time : DEFAULT_NO_REPLY_TIMEOUT;
118 static void cf_cond_list_print(GSList *l)
120 struct ofono_call_forwarding_condition *cond;
122 for (; l ; l = l->next) {
125 DBG("CF Condition status: %d, class: %d, number: %s,"
126 " number_type: %d, time: %d",
127 cond->status, cond->cls, cond->phone_number.number,
128 cond->phone_number.type, cond->time);
132 static GSList *cf_cond_list_create(int total,
133 const struct ofono_call_forwarding_condition *list)
138 struct ofono_call_forwarding_condition *cond;
141 * Specification is not really clear how the results are reported,
142 * so assume both multiple list items & compound values of class
145 for (i = 0; i < total; i++) {
146 for (j = 1; j <= BEARER_CLASS_PAD; j = j << 1) {
147 if (!(list[i].cls & j))
150 if (list[i].status == 0)
154 struct ofono_call_forwarding_condition, 1);
158 memcpy(cond, &list[i],
159 sizeof(struct ofono_call_forwarding_condition));
162 l = g_slist_insert_sorted(l, cond, cf_cond_compare);
169 static inline void cf_clear_all(struct ofono_call_forwarding *cf)
173 for (i = 0; i < 4; i++) {
174 g_slist_free_full(cf->cf_conditions[i], g_free);
175 cf->cf_conditions[i] = NULL;
179 static const char *cf_type_lut[] = {
188 static void sim_cfis_update_cb(int ok, void *data)
191 ofono_info("Failed to update EFcfis");
194 static void sim_cphs_cff_update_cb(int ok, void *data)
197 ofono_info("Failed to update EFcphs-cff");
200 static inline struct ofono_call_forwarding_condition *cf_find_unconditional(
201 struct ofono_call_forwarding *cf)
204 cf->cf_conditions[CALL_FORWARDING_TYPE_UNCONDITIONAL],
208 static void sim_set_cf_indicator(struct ofono_call_forwarding *cf)
210 struct ofono_call_forwarding_condition *cfu_voice =
211 cf_find_unconditional(cf);
213 if (cf->cfis_record_id) {
214 unsigned char data[16];
217 memset(data, 0xff, sizeof(data));
219 /* Profile Identifier */
223 number_len = strlen(cfu_voice->phone_number.number);
225 /* CFU indicator Status - Voice */
227 number_len = (number_len + 1) / 2;
228 data[2] = number_len + 1;
229 data[3] = cfu_voice->phone_number.type;
231 sim_encode_bcd_number(cfu_voice->phone_number.number,
239 ofono_sim_write(cf->sim_context, SIM_EFCFIS_FILEID,
241 OFONO_SIM_FILE_STRUCTURE_FIXED,
242 cf->cfis_record_id, data,
247 if (cf->flags & CALL_FORWARDING_FLAG_CPHS_CFF) {
248 unsigned char cff_voice = cfu_voice ? 0x0A : 0x05;
250 ofono_sim_write(cf->sim_context, SIM_EF_CPHS_CFF_FILEID,
251 sim_cphs_cff_update_cb,
252 OFONO_SIM_FILE_STRUCTURE_TRANSPARENT,
253 0, &cff_voice, sizeof(cff_voice), cf);
257 static void set_new_cond_list(struct ofono_call_forwarding *cf,
258 int type, GSList *list)
260 GSList *old = cf->cf_conditions[type];
261 DBusConnection *conn = ofono_dbus_get_connection();
262 const char *path = __ofono_atom_get_path(cf->atom);
265 struct ofono_call_forwarding_condition *lc;
266 struct ofono_call_forwarding_condition *oc;
268 dbus_uint16_t timeout;
271 gboolean update_sim = FALSE;
275 if ((cf->flags & CALL_FORWARDING_FLAG_CPHS_CFF) ||
276 cf->cfis_record_id > 0)
277 old_cfu = is_cfu_enabled(cf);
281 for (l = list; l; l = l->next) {
285 * New condition lists might have attributes we don't care about
286 * triggered by e.g. ss control magic strings just skip them
287 * here. For now we only support Voice, although Fax & all Data
288 * basic services are applicable as well.
290 if (lc->cls > BEARER_CLASS_VOICE)
294 number = phone_number_to_string(&lc->phone_number);
296 snprintf(attr, sizeof(attr), "%s%s",
297 bearer_class_to_string(lc->cls), cf_type_lut[type]);
299 if (type == CALL_FORWARDING_TYPE_NO_REPLY)
300 snprintf(tattr, sizeof(tattr), "%sTimeout", attr);
302 oc = cf_cond_find(old, lc->cls);
303 if (oc) { /* On the old list, must be active */
304 if (oc->phone_number.type != lc->phone_number.type ||
305 strcmp(oc->phone_number.number,
306 lc->phone_number.number)) {
307 ofono_dbus_signal_property_changed(conn, path,
308 OFONO_CALL_FORWARDING_INTERFACE,
309 attr, DBUS_TYPE_STRING,
312 if (type == CALL_FORWARDING_TYPE_UNCONDITIONAL)
316 if (type == CALL_FORWARDING_TYPE_NO_REPLY &&
317 oc->time != lc->time)
318 ofono_dbus_signal_property_changed(conn, path,
319 OFONO_CALL_FORWARDING_INTERFACE,
320 tattr, DBUS_TYPE_UINT16,
323 /* Remove from the old list */
324 old = g_slist_remove(old, oc);
327 number = phone_number_to_string(&lc->phone_number);
329 ofono_dbus_signal_property_changed(conn, path,
330 OFONO_CALL_FORWARDING_INTERFACE,
331 attr, DBUS_TYPE_STRING,
334 if (type == CALL_FORWARDING_TYPE_UNCONDITIONAL)
337 if (type == CALL_FORWARDING_TYPE_NO_REPLY &&
338 lc->time != DEFAULT_NO_REPLY_TIMEOUT)
339 ofono_dbus_signal_property_changed(conn, path,
340 OFONO_CALL_FORWARDING_INTERFACE,
341 tattr, DBUS_TYPE_UINT16,
346 timeout = DEFAULT_NO_REPLY_TIMEOUT;
349 for (o = old; o; o = o->next) {
353 * For now we only support Voice, although Fax & all Data
354 * basic services are applicable as well.
356 if (oc->cls > BEARER_CLASS_VOICE)
359 snprintf(attr, sizeof(attr), "%s%s",
360 bearer_class_to_string(oc->cls), cf_type_lut[type]);
362 if (type == CALL_FORWARDING_TYPE_NO_REPLY)
363 snprintf(tattr, sizeof(tattr), "%sTimeout", attr);
365 ofono_dbus_signal_property_changed(conn, path,
366 OFONO_CALL_FORWARDING_INTERFACE, attr,
367 DBUS_TYPE_STRING, &number);
369 if (type == CALL_FORWARDING_TYPE_UNCONDITIONAL)
372 if (type == CALL_FORWARDING_TYPE_NO_REPLY &&
373 oc->time != DEFAULT_NO_REPLY_TIMEOUT)
374 ofono_dbus_signal_property_changed(conn, path,
375 OFONO_CALL_FORWARDING_INTERFACE,
376 tattr, DBUS_TYPE_UINT16,
380 g_slist_free_full(old, g_free);
381 cf->cf_conditions[type] = list;
383 if (update_sim == TRUE)
384 sim_set_cf_indicator(cf);
386 if ((cf->flags & CALL_FORWARDING_FLAG_CPHS_CFF) ||
387 cf->cfis_record_id > 0)
388 new_cfu = is_cfu_enabled(cf);
392 if (new_cfu != old_cfu) {
393 ofono_bool_t status = new_cfu;
397 * Emit signals to mask/unmask conditional cfs on cfu change
399 for (i = 0; i < 4; i++) {
400 if (i == CALL_FORWARDING_TYPE_UNCONDITIONAL)
403 lc = cf_cond_find(cf->cf_conditions[i],
411 number = phone_number_to_string(
414 ofono_dbus_signal_property_changed(conn, path,
415 OFONO_CALL_FORWARDING_INTERFACE,
417 DBUS_TYPE_STRING, &number);
420 ofono_dbus_signal_property_changed(conn, path,
421 OFONO_CALL_FORWARDING_INTERFACE,
422 "ForwardingFlagOnSim",
423 DBUS_TYPE_BOOLEAN, &status);
427 static inline void property_append_cf_condition(DBusMessageIter *dict, int cls,
430 dbus_uint16_t timeout)
434 int addt = !strcmp(postfix, "NoReply");
436 snprintf(attr, sizeof(attr), "%s%s",
437 bearer_class_to_string(cls), postfix);
440 snprintf(tattr, sizeof(tattr), "%s%sTimeout",
441 bearer_class_to_string(cls), postfix);
443 ofono_dbus_dict_append(dict, attr, DBUS_TYPE_STRING, &value);
446 ofono_dbus_dict_append(dict, tattr, DBUS_TYPE_UINT16, &timeout);
449 static void property_append_cf_conditions(DBusMessageIter *dict,
450 GSList *cf_list, int mask,
455 struct ofono_call_forwarding_condition *cf;
458 for (i = 1, l = cf_list; i <= BEARER_CLASS_PAD; i = i << 1) {
462 while (l && (cf = l->data) && (cf->cls < i))
465 if (l == NULL || cf->cls != i) {
466 property_append_cf_condition(dict, i, postfix, "",
467 DEFAULT_NO_REPLY_TIMEOUT);
471 number = phone_number_to_string(&cf->phone_number);
473 property_append_cf_condition(dict, i, postfix, number,
478 static DBusMessage *cf_get_properties_reply(DBusMessage *msg,
479 struct ofono_call_forwarding *cf)
482 DBusMessageIter iter;
483 DBusMessageIter dict;
486 gboolean cfu_enabled;
489 reply = dbus_message_new_method_return(msg);
493 dbus_message_iter_init_append(reply, &iter);
495 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
496 OFONO_PROPERTIES_ARRAY_SIGNATURE,
499 cfu_enabled = is_cfu_enabled(cf);
501 for (i = 0; i < 4; i++) {
503 * Report conditional cfs as empty when CFU is active
505 if (cfu_enabled && (i != CALL_FORWARDING_TYPE_UNCONDITIONAL))
508 cf_list = cf->cf_conditions[i];
510 property_append_cf_conditions(&dict, cf_list,
515 if ((cf->flags & CALL_FORWARDING_FLAG_CPHS_CFF) ||
516 cf->cfis_record_id > 0)
517 status = cfu_enabled;
521 ofono_dbus_dict_append(&dict, "ForwardingFlagOnSim", DBUS_TYPE_BOOLEAN,
524 dbus_message_iter_close_container(&iter, &dict);
529 static void get_query_cf_callback(const struct ofono_error *error, int total,
530 const struct ofono_call_forwarding_condition *list,
533 struct ofono_call_forwarding *cf = data;
535 if (error->type == OFONO_ERROR_TYPE_NO_ERROR) {
536 GSList *l = cf_cond_list_create(total, list);
538 set_new_cond_list(cf, cf->query_next, l);
540 DBG("%s conditions:", cf_type_lut[cf->query_next]);
542 cf_cond_list_print(l);
544 if (cf->query_next == CALL_FORWARDING_TYPE_NOT_REACHABLE)
545 cf->flags |= CALL_FORWARDING_FLAG_CACHED;
548 if (cf->query_next == CALL_FORWARDING_TYPE_NOT_REACHABLE) {
549 __ofono_dbus_pending_reply(&cf->pending,
550 cf_get_properties_reply(cf->pending, cf));
555 get_query_next_cf_cond(cf);
558 static inline void get_query_next_cf_cond(struct ofono_call_forwarding *cf)
560 cf->driver->query(cf, cf->query_next, BEARER_CLASS_DEFAULT,
561 get_query_cf_callback, cf);
564 static DBusMessage *cf_get_properties(DBusConnection *conn, DBusMessage *msg,
567 struct ofono_call_forwarding *cf = data;
568 struct ofono_modem *modem = __ofono_atom_get_modem(cf->atom);
570 if ((cf->flags & CALL_FORWARDING_FLAG_CACHED) ||
571 ofono_modem_get_online(modem) == FALSE)
572 return cf_get_properties_reply(msg, cf);
574 if (cf->driver->query == NULL)
575 return __ofono_error_not_implemented(msg);
577 if (__ofono_call_forwarding_is_busy(cf) ||
578 __ofono_ussd_is_busy(cf->ussd))
579 return __ofono_error_busy(msg);
581 cf->pending = dbus_message_ref(msg);
584 get_query_next_cf_cond(cf);
589 static gboolean cf_condition_enabled_property(struct ofono_call_forwarding *cf,
590 const char *property, int *out_type, int *out_cls)
597 for (i = 1; i <= BEARER_CLASS_VOICE; i = i << 1) {
598 prefix = bearer_class_to_string(i);
600 len = strlen(prefix);
602 if (strncmp(property, prefix, len))
606 * We check the 4 call forwarding types, e.g.
607 * unconditional, busy, no reply, not reachable
609 for (j = 0; j < 4; j++)
610 if (!strcmp(property+len, cf_type_lut[j])) {
620 static gboolean cf_condition_timeout_property(const char *property,
627 for (i = 1; i <= BEARER_CLASS_VOICE; i = i << 1) {
628 prefix = bearer_class_to_string(i);
630 len = strlen(prefix);
632 if (strncmp(property, prefix, len))
635 if (!strcmp(property+len, "NoReplyTimeout")) {
644 static void set_query_cf_callback(const struct ofono_error *error, int total,
645 const struct ofono_call_forwarding_condition *list,
648 struct ofono_call_forwarding *cf = data;
650 if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
651 ofono_error("Setting succeeded, but query failed");
652 cf->flags &= ~CALL_FORWARDING_FLAG_CACHED;
653 __ofono_dbus_pending_reply(&cf->pending,
654 __ofono_error_failed(cf->pending));
658 if (cf->query_next == cf->query_end)
659 __ofono_dbus_pending_reply(&cf->pending,
660 dbus_message_new_method_return(cf->pending));
662 set_new_cond_list(cf, cf->query_next, cf_cond_list_create(total, list));
664 DBG("%s conditions:", cf_type_lut[cf->query_next]);
665 cf_cond_list_print(cf->cf_conditions[cf->query_next]);
667 if (cf->query_next == cf->query_end)
671 set_query_next_cf_cond(cf);
674 static void set_query_next_cf_cond(struct ofono_call_forwarding *cf)
676 cf->driver->query(cf, cf->query_next, BEARER_CLASS_DEFAULT,
677 set_query_cf_callback, cf);
680 static void set_property_callback(const struct ofono_error *error, void *data)
682 struct ofono_call_forwarding *cf = data;
684 if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
685 DBG("Error occurred during set/erasure");
686 __ofono_dbus_pending_reply(&cf->pending,
687 __ofono_error_failed(cf->pending));
691 /* Successfully set, query the entire set just in case */
692 set_query_next_cf_cond(cf);
695 static DBusMessage *set_property_request(struct ofono_call_forwarding *cf,
698 struct ofono_phone_number *ph,
701 if (ph->number[0] != '\0' && cf->driver->registration == NULL)
702 return __ofono_error_not_implemented(msg);
704 if (ph->number[0] == '\0' && cf->driver->erasure == NULL)
705 return __ofono_error_not_implemented(msg);
707 cf->pending = dbus_message_ref(msg);
708 cf->query_next = type;
709 cf->query_end = type;
711 DBG("Farming off request, will be erasure: %d", ph->number[0] == '\0');
713 if (ph->number[0] != '\0')
714 cf->driver->registration(cf, type, cls, ph, timeout,
715 set_property_callback, cf);
717 cf->driver->erasure(cf, type, cls, set_property_callback, cf);
722 static DBusMessage *cf_set_property(DBusConnection *conn, DBusMessage *msg,
725 struct ofono_call_forwarding *cf = data;
726 struct ofono_modem *modem = __ofono_atom_get_modem(cf->atom);
727 DBusMessageIter iter;
729 const char *property;
733 if (ofono_modem_get_online(modem) == FALSE)
734 return __ofono_error_not_available(msg);
736 if (__ofono_call_forwarding_is_busy(cf) ||
737 __ofono_ussd_is_busy(cf->ussd))
738 return __ofono_error_busy(msg);
740 if (!dbus_message_iter_init(msg, &iter))
741 return __ofono_error_invalid_args(msg);
743 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
744 return __ofono_error_invalid_args(msg);
746 dbus_message_iter_get_basic(&iter, &property);
747 dbus_message_iter_next(&iter);
749 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
750 return __ofono_error_invalid_args(msg);
752 dbus_message_iter_recurse(&iter, &var);
754 if (cf_condition_timeout_property(property, &cls)) {
755 dbus_uint16_t timeout;
756 struct ofono_call_forwarding_condition *c;
758 type = CALL_FORWARDING_TYPE_NO_REPLY;
760 if (dbus_message_iter_get_arg_type(&var) != DBUS_TYPE_UINT16)
761 return __ofono_error_invalid_args(msg);
763 dbus_message_iter_get_basic(&var, &timeout);
765 if (timeout < 1 || timeout > 30)
766 return __ofono_error_invalid_format(msg);
769 c = cf_cond_find(cf->cf_conditions[type], cls);
771 return __ofono_error_failed(msg);
773 return set_property_request(cf, msg, type, cls,
774 &c->phone_number, timeout);
775 } else if (cf_condition_enabled_property(cf, property, &type, &cls)) {
776 struct ofono_phone_number ph;
783 if (dbus_message_iter_get_arg_type(&var) != DBUS_TYPE_STRING)
784 return __ofono_error_invalid_args(msg);
786 dbus_message_iter_get_basic(&var, &number);
788 if (strlen(number) > 0 && !valid_phone_number_format(number))
789 return __ofono_error_invalid_format(msg);
792 * Don't set conditional cfs when cfu is active
794 if (type != CALL_FORWARDING_TYPE_UNCONDITIONAL &&
795 number[0] != '\0' && is_cfu_enabled(cf))
796 return __ofono_error_not_available(msg);
798 if (number[0] != '\0')
799 string_to_phone_number(number, &ph);
801 timeout = cf_cond_find_timeout(cf->cf_conditions[type], cls);
803 return set_property_request(cf, msg, type, cls, &ph,
807 return __ofono_error_invalid_args(msg);
810 static void disable_conditional_callback(const struct ofono_error *error,
813 struct ofono_call_forwarding *cf = data;
815 if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
816 DBG("Error occurred during conditional erasure");
818 __ofono_dbus_pending_reply(&cf->pending,
819 __ofono_error_failed(cf->pending));
823 /* Query the three conditional cf types */
824 cf->query_next = CALL_FORWARDING_TYPE_BUSY;
825 cf->query_end = CALL_FORWARDING_TYPE_NOT_REACHABLE;
826 set_query_next_cf_cond(cf);
829 static void disable_all_callback(const struct ofono_error *error, void *data)
831 struct ofono_call_forwarding *cf = data;
833 if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
834 DBG("Error occurred during erasure of all");
836 __ofono_dbus_pending_reply(&cf->pending,
837 __ofono_error_failed(cf->pending));
841 /* Query all cf types */
842 cf->query_next = CALL_FORWARDING_TYPE_UNCONDITIONAL;
843 cf->query_end = CALL_FORWARDING_TYPE_NOT_REACHABLE;
844 set_query_next_cf_cond(cf);
847 static DBusMessage *cf_disable_all(DBusConnection *conn, DBusMessage *msg,
850 struct ofono_call_forwarding *cf = data;
854 if (cf->driver->erasure == NULL)
855 return __ofono_error_not_implemented(msg);
857 if (__ofono_call_forwarding_is_busy(cf) ||
858 __ofono_ussd_is_busy(cf->ussd))
859 return __ofono_error_busy(msg);
861 if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &strtype,
862 DBUS_TYPE_INVALID) == FALSE)
863 return __ofono_error_invalid_args(msg);
865 if (!strcmp(strtype, "all") || !strcmp(strtype, ""))
866 type = CALL_FORWARDING_TYPE_ALL;
867 else if (!strcmp(strtype, "conditional"))
868 type = CALL_FORWARDING_TYPE_ALL_CONDITIONAL;
870 return __ofono_error_invalid_format(msg);
872 cf->pending = dbus_message_ref(msg);
874 if (type == CALL_FORWARDING_TYPE_ALL)
875 cf->driver->erasure(cf, type, BEARER_CLASS_DEFAULT,
876 disable_all_callback, cf);
878 cf->driver->erasure(cf, type, BEARER_CLASS_DEFAULT,
879 disable_conditional_callback, cf);
884 static const GDBusMethodTable cf_methods[] = {
885 { GDBUS_ASYNC_METHOD("GetProperties",
886 NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
887 cf_get_properties) },
888 { GDBUS_ASYNC_METHOD("SetProperty",
889 GDBUS_ARGS({ "property", "s" }, { "value", "v" }),
890 NULL, cf_set_property) },
891 { GDBUS_ASYNC_METHOD("DisableAll",
892 GDBUS_ARGS({ "type", "s" }), NULL,
897 static const GDBusSignalTable cf_signals[] = {
898 { GDBUS_SIGNAL("PropertyChanged",
899 GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
903 static DBusMessage *cf_ss_control_reply(struct ofono_call_forwarding *cf,
904 struct cf_ss_request *req)
906 const char *context = "CallForwarding";
907 const char *sig = "(ssa{sv})";
908 const char *ss_type = ss_control_type_to_string(req->ss_type);
909 const char *cf_type = cf_type_lut[req->cf_type];
910 DBusMessageIter iter;
911 DBusMessageIter variant;
912 DBusMessageIter vstruct;
913 DBusMessageIter dict;
916 reply = dbus_message_new_method_return(cf->pending);
918 dbus_message_iter_init_append(reply, &iter);
920 dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &context);
922 dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT, sig,
925 dbus_message_iter_open_container(&variant, DBUS_TYPE_STRUCT, NULL,
928 dbus_message_iter_append_basic(&vstruct, DBUS_TYPE_STRING,
931 dbus_message_iter_append_basic(&vstruct, DBUS_TYPE_STRING,
934 dbus_message_iter_open_container(&vstruct, DBUS_TYPE_ARRAY,
935 OFONO_PROPERTIES_ARRAY_SIGNATURE, &dict);
937 if (req->cf_type == CALL_FORWARDING_TYPE_UNCONDITIONAL ||
938 req->cf_type == CALL_FORWARDING_TYPE_ALL)
939 property_append_cf_conditions(&dict,
940 req->cf_list[CALL_FORWARDING_TYPE_UNCONDITIONAL],
942 cf_type_lut[CALL_FORWARDING_TYPE_UNCONDITIONAL]);
944 if (req->cf_type == CALL_FORWARDING_TYPE_NO_REPLY ||
945 req->cf_type == CALL_FORWARDING_TYPE_ALL ||
946 req->cf_type == CALL_FORWARDING_TYPE_ALL_CONDITIONAL)
947 property_append_cf_conditions(&dict,
948 req->cf_list[CALL_FORWARDING_TYPE_NO_REPLY],
949 req->cls, cf_type_lut[CALL_FORWARDING_TYPE_NO_REPLY]);
951 if (req->cf_type == CALL_FORWARDING_TYPE_NOT_REACHABLE ||
952 req->cf_type == CALL_FORWARDING_TYPE_ALL ||
953 req->cf_type == CALL_FORWARDING_TYPE_ALL_CONDITIONAL)
954 property_append_cf_conditions(&dict,
955 req->cf_list[CALL_FORWARDING_TYPE_NOT_REACHABLE],
957 cf_type_lut[CALL_FORWARDING_TYPE_NOT_REACHABLE]);
959 if (req->cf_type == CALL_FORWARDING_TYPE_BUSY ||
960 req->cf_type == CALL_FORWARDING_TYPE_ALL ||
961 req->cf_type == CALL_FORWARDING_TYPE_ALL_CONDITIONAL)
962 property_append_cf_conditions(&dict,
963 req->cf_list[CALL_FORWARDING_TYPE_BUSY],
964 req->cls, cf_type_lut[CALL_FORWARDING_TYPE_BUSY]);
966 dbus_message_iter_close_container(&vstruct, &dict);
968 dbus_message_iter_close_container(&variant, &vstruct);
970 dbus_message_iter_close_container(&iter, &variant);
975 static void ss_set_query_cf_callback(const struct ofono_error *error, int total,
976 const struct ofono_call_forwarding_condition *list,
979 struct ofono_call_forwarding *cf = data;
983 if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
984 ofono_error("Query failed with error: %s",
985 telephony_error_to_str(error));
986 cf->flags &= ~CALL_FORWARDING_FLAG_CACHED;
987 reply = __ofono_error_from_error(error, cf->pending);
988 __ofono_dbus_pending_reply(&cf->pending, reply);
992 l = cf_cond_list_create(total, list);
993 DBG("%s conditions:", cf_type_lut[cf->query_next]);
994 cf_cond_list_print(l);
996 cf->ss_req->cf_list[cf->query_next] = l;
998 if (cf->query_next == cf->query_end) {
999 reply = cf_ss_control_reply(cf, cf->ss_req);
1000 __ofono_dbus_pending_reply(&cf->pending, reply);
1005 set_new_cond_list(cf, cf->query_next, l);
1007 if (cf->query_next != cf->query_end) {
1009 ss_set_query_next_cf_cond(cf);
1013 static void ss_set_query_next_cf_cond(struct ofono_call_forwarding *cf)
1017 cls = (cf->ss_req->ss_type == SS_CONTROL_TYPE_QUERY) ?
1018 cf->ss_req->cls : BEARER_CLASS_DEFAULT;
1020 if (cls == BEARER_CLASS_SS_DEFAULT)
1021 cls = BEARER_CLASS_DEFAULT;
1023 cf->driver->query(cf, cf->query_next, cls,
1024 ss_set_query_cf_callback, cf);
1027 static void cf_ss_control_callback(const struct ofono_error *error, void *data)
1029 struct ofono_call_forwarding *cf = data;
1031 if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
1033 DBG("CF ss control set/erasure failed with error: %s",
1034 telephony_error_to_str(error));
1035 __ofono_dbus_pending_reply(&cf->pending,
1036 __ofono_error_from_error(error, cf->pending));
1042 ss_set_query_next_cf_cond(cf);
1045 static gboolean cf_ss_control(int type, const char *sc,
1046 const char *sia, const char *sib,
1047 const char *sic, const char *dn,
1048 DBusMessage *msg, void *data)
1050 struct ofono_call_forwarding *cf = data;
1051 DBusConnection *conn = ofono_dbus_get_connection();
1052 int cls = BEARER_CLASS_SS_DEFAULT;
1053 int timeout = DEFAULT_NO_REPLY_TIMEOUT;
1056 struct ofono_phone_number ph;
1057 void *operation = NULL;
1059 /* Before we do anything, make sure we're actually initialized */
1063 if (__ofono_call_forwarding_is_busy(cf)) {
1064 reply = __ofono_error_busy(msg);
1065 g_dbus_send_message(conn, reply);
1070 DBG("Received call forwarding ss control request");
1072 DBG("type: %d, sc: %s, sia: %s, sib: %s, sic: %s, dn: %s",
1073 type, sc, sia, sib, sic, dn);
1075 if (!strcmp(sc, "21"))
1076 cf_type = CALL_FORWARDING_TYPE_UNCONDITIONAL;
1077 else if (!strcmp(sc, "67"))
1078 cf_type = CALL_FORWARDING_TYPE_BUSY;
1079 else if (!strcmp(sc, "61"))
1080 cf_type = CALL_FORWARDING_TYPE_NO_REPLY;
1081 else if (!strcmp(sc, "62"))
1082 cf_type = CALL_FORWARDING_TYPE_NOT_REACHABLE;
1083 else if (!strcmp(sc, "002"))
1084 cf_type = CALL_FORWARDING_TYPE_ALL;
1085 else if (!strcmp(sc, "004"))
1086 cf_type = CALL_FORWARDING_TYPE_ALL_CONDITIONAL;
1091 (type == SS_CONTROL_TYPE_QUERY ||
1092 type == SS_CONTROL_TYPE_ERASURE ||
1093 type == SS_CONTROL_TYPE_DEACTIVATION))
1097 * Activation / Registration is figured context specific according to
1098 * 22.030 Section 6.5.2 "The UE shall determine from the context
1099 * whether, an entry of a single *, activation or registration
1102 if (type == SS_CONTROL_TYPE_ACTIVATION && strlen(sia) > 0)
1103 type = SS_CONTROL_TYPE_REGISTRATION;
1105 if (type == SS_CONTROL_TYPE_REGISTRATION &&
1106 !valid_phone_number_format(sia))
1109 if (strlen(sib) > 0) {
1113 service_code = strtoul(sib, &end, 10);
1115 if (end == sib || *end != '\0')
1118 cls = mmi_service_code_to_bearer_class(service_code);
1124 if (strlen(sic) > 0) {
1127 if (type != SS_CONTROL_TYPE_REGISTRATION)
1130 if (cf_type != CALL_FORWARDING_TYPE_ALL &&
1131 cf_type != CALL_FORWARDING_TYPE_ALL_CONDITIONAL &&
1132 cf_type != CALL_FORWARDING_TYPE_NO_REPLY)
1135 timeout = strtoul(sic, &end, 10);
1137 if (end == sic || *end != '\0')
1140 if (timeout < 1 || timeout > 30)
1145 case SS_CONTROL_TYPE_REGISTRATION:
1146 operation = cf->driver->registration;
1148 case SS_CONTROL_TYPE_ACTIVATION:
1149 operation = cf->driver->activation;
1151 case SS_CONTROL_TYPE_DEACTIVATION:
1152 operation = cf->driver->deactivation;
1154 case SS_CONTROL_TYPE_ERASURE:
1155 operation = cf->driver->erasure;
1157 case SS_CONTROL_TYPE_QUERY:
1158 operation = cf->driver->query;
1162 if (operation == NULL) {
1163 reply = __ofono_error_not_implemented(msg);
1164 g_dbus_send_message(conn, reply);
1169 cf->ss_req = g_try_new0(struct cf_ss_request, 1);
1171 if (cf->ss_req == NULL) {
1172 reply = __ofono_error_failed(msg);
1173 g_dbus_send_message(conn, reply);
1178 cf->ss_req->ss_type = type;
1179 cf->ss_req->cf_type = cf_type;
1180 cf->ss_req->cls = cls;
1182 cf->pending = dbus_message_ref(msg);
1184 switch (cf->ss_req->cf_type) {
1185 case CALL_FORWARDING_TYPE_ALL:
1186 cf->query_next = CALL_FORWARDING_TYPE_UNCONDITIONAL;
1187 cf->query_end = CALL_FORWARDING_TYPE_NOT_REACHABLE;
1189 case CALL_FORWARDING_TYPE_ALL_CONDITIONAL:
1190 cf->query_next = CALL_FORWARDING_TYPE_BUSY;
1191 cf->query_end = CALL_FORWARDING_TYPE_NOT_REACHABLE;
1194 cf->query_next = cf->ss_req->cf_type;
1195 cf->query_end = cf->ss_req->cf_type;
1200 * Some modems don't understand all classes very well, particularly
1201 * the older models. So if the bearer class is the default, we
1202 * just use the more commonly understood value of 7 since BEARER_SMS
1203 * is not applicable to CallForwarding conditions according to 22.004
1206 if (cls == BEARER_CLASS_SS_DEFAULT)
1207 cls = BEARER_CLASS_DEFAULT;
1209 switch (cf->ss_req->ss_type) {
1210 case SS_CONTROL_TYPE_REGISTRATION:
1211 string_to_phone_number(sia, &ph);
1212 cf->driver->registration(cf, cf_type, cls, &ph, timeout,
1213 cf_ss_control_callback, cf);
1215 case SS_CONTROL_TYPE_ACTIVATION:
1216 cf->driver->activation(cf, cf_type, cls, cf_ss_control_callback,
1219 case SS_CONTROL_TYPE_DEACTIVATION:
1220 cf->driver->deactivation(cf, cf_type, cls,
1221 cf_ss_control_callback, cf);
1223 case SS_CONTROL_TYPE_ERASURE:
1224 cf->driver->erasure(cf, cf_type, cls, cf_ss_control_callback,
1227 case SS_CONTROL_TYPE_QUERY:
1228 ss_set_query_next_cf_cond(cf);
1235 reply = __ofono_error_invalid_format(msg);
1236 g_dbus_send_message(conn, reply);
1240 static void cf_register_ss_controls(struct ofono_call_forwarding *cf)
1242 __ofono_ussd_ssc_register(cf->ussd, "21", cf_ss_control, cf, NULL);
1243 __ofono_ussd_ssc_register(cf->ussd, "67", cf_ss_control, cf, NULL);
1244 __ofono_ussd_ssc_register(cf->ussd, "61", cf_ss_control, cf, NULL);
1245 __ofono_ussd_ssc_register(cf->ussd, "62", cf_ss_control, cf, NULL);
1247 __ofono_ussd_ssc_register(cf->ussd, "002", cf_ss_control, cf, NULL);
1248 __ofono_ussd_ssc_register(cf->ussd, "004", cf_ss_control, cf, NULL);
1251 static void cf_unregister_ss_controls(struct ofono_call_forwarding *cf)
1253 __ofono_ussd_ssc_unregister(cf->ussd, "21");
1254 __ofono_ussd_ssc_unregister(cf->ussd, "67");
1255 __ofono_ussd_ssc_unregister(cf->ussd, "61");
1256 __ofono_ussd_ssc_unregister(cf->ussd, "62");
1258 __ofono_ussd_ssc_unregister(cf->ussd, "002");
1259 __ofono_ussd_ssc_unregister(cf->ussd, "004");
1262 gboolean __ofono_call_forwarding_is_busy(struct ofono_call_forwarding *cf)
1264 return cf->pending ? TRUE : FALSE;
1267 static void sim_cfis_read_cb(int ok, int total_length, int record,
1268 const unsigned char *data,
1269 int record_length, void *userdata)
1271 struct ofono_call_forwarding *cf = userdata;
1272 DBusConnection *conn = ofono_dbus_get_connection();
1273 const char *path = __ofono_atom_get_path(cf->atom);
1275 if (!ok || record_length < 16 || total_length < record_length) {
1276 cf->cfis_record_id = 0;
1281 * Multiple Subscriber Profile number which can have values 1-4.
1282 * Profile id 1 is assumed as the current profile.
1287 cf->cfis_record_id = record;
1289 if (cf->flags & CALL_FORWARDING_FLAG_CACHED)
1293 * For now we only support Voice, although Fax & all Data
1294 * basic services are applicable as well.
1296 if (data[1] & 0x01) {
1301 struct ofono_call_forwarding_condition *cond;
1304 number_len = data[2];
1307 if (number_len > 11 || ton_npi == 0xff)
1310 cond = g_try_new0(struct ofono_call_forwarding_condition, 1);
1315 cond->status = TRUE;
1316 cond->cls = BEARER_CLASS_VOICE;
1318 cond->phone_number.type = ton_npi;
1320 sim_extract_bcd_number(data + 4, number_len - 1,
1321 cond->phone_number.number);
1322 number = phone_number_to_string(&cond->phone_number);
1324 snprintf(attr, sizeof(attr), "%s%s",
1325 bearer_class_to_string(BEARER_CLASS_VOICE),
1326 cf_type_lut[CALL_FORWARDING_TYPE_UNCONDITIONAL]);
1328 cf->cf_conditions[CALL_FORWARDING_TYPE_UNCONDITIONAL] =
1329 g_slist_append(NULL, cond);
1331 ofono_dbus_signal_property_changed(conn, path,
1332 OFONO_CALL_FORWARDING_INTERFACE,
1333 attr, DBUS_TYPE_STRING, &number);
1335 ofono_dbus_signal_property_changed(conn, path,
1336 OFONO_CALL_FORWARDING_INTERFACE,
1337 "ForwardingFlagOnSim",
1338 DBUS_TYPE_BOOLEAN, &status);
1342 static void sim_cphs_cff_read_cb(int ok, int total_length, int record,
1343 const unsigned char *data,
1344 int record_length, void *userdata)
1346 struct ofono_call_forwarding *cf = userdata;
1347 DBusConnection *conn = ofono_dbus_get_connection();
1348 const char *path = __ofono_atom_get_path(cf->atom);
1349 dbus_bool_t cfu_voice;
1351 if (!ok || total_length < 1)
1354 cf->flags |= CALL_FORWARDING_FLAG_CPHS_CFF;
1356 if (cf->flags & CALL_FORWARDING_FLAG_CACHED)
1360 * For now we only support Voice, although Fax & all Data
1361 * basic services are applicable as well.
1363 if ((data[0] & 0xf) != 0xA)
1368 ofono_dbus_signal_property_changed(conn, path,
1369 OFONO_CALL_FORWARDING_INTERFACE,
1370 "ForwardingFlagOnSim",
1371 DBUS_TYPE_BOOLEAN, &cfu_voice);
1374 static void call_forwarding_unregister(struct ofono_atom *atom)
1376 struct ofono_call_forwarding *cf = __ofono_atom_get_data(atom);
1377 const char *path = __ofono_atom_get_path(cf->atom);
1378 DBusConnection *conn = ofono_dbus_get_connection();
1379 struct ofono_modem *modem = __ofono_atom_get_modem(cf->atom);
1381 ofono_modem_remove_interface(modem, OFONO_CALL_FORWARDING_INTERFACE);
1382 g_dbus_unregister_interface(conn, path,
1383 OFONO_CALL_FORWARDING_INTERFACE);
1385 if (cf->sim_context) {
1386 ofono_sim_context_free(cf->sim_context);
1387 cf->sim_context = NULL;
1391 cf_unregister_ss_controls(cf);
1394 __ofono_modem_remove_atom_watch(modem, cf->ussd_watch);
1399 static void sim_cfis_changed(int id, void *userdata)
1401 struct ofono_call_forwarding *cf = userdata;
1403 if (!(cf->flags & CALL_FORWARDING_FLAG_CACHED))
1407 * If the values are cached it's because at least one client
1408 * requested them and we need to notify them about this
1409 * change. However the authoritative source of current
1410 * Call-Forwarding settings is the network operator and the
1411 * query can take a noticeable amount of time. Instead of
1412 * sending PropertyChanged, we reregister the Call Forwarding
1413 * atom. The client will invoke GetProperties only if it
1414 * is still interested.
1416 call_forwarding_unregister(cf->atom);
1417 ofono_call_forwarding_register(cf);
1420 static void sim_read_cf_indicator(struct ofono_call_forwarding *cf)
1422 if (__ofono_sim_service_available(cf->sim,
1423 SIM_UST_SERVICE_CFIS,
1424 SIM_SST_SERVICE_CFIS) == TRUE) {
1425 ofono_sim_read(cf->sim_context, SIM_EFCFIS_FILEID,
1426 OFONO_SIM_FILE_STRUCTURE_FIXED,
1427 sim_cfis_read_cb, cf);
1428 ofono_sim_add_file_watch(cf->sim_context, SIM_EFCFIS_FILEID,
1429 sim_cfis_changed, cf, NULL);
1431 ofono_sim_read(cf->sim_context, SIM_EF_CPHS_CFF_FILEID,
1432 OFONO_SIM_FILE_STRUCTURE_TRANSPARENT,
1433 sim_cphs_cff_read_cb, cf);
1434 ofono_sim_add_file_watch(cf->sim_context,
1435 SIM_EF_CPHS_CFF_FILEID,
1436 sim_cfis_changed, cf, NULL);
1440 int ofono_call_forwarding_driver_register(
1441 const struct ofono_call_forwarding_driver *d)
1443 DBG("driver: %p, name: %s", d, d->name);
1445 if (d->probe == NULL)
1448 g_drivers = g_slist_prepend(g_drivers, (void *) d);
1453 void ofono_call_forwarding_driver_unregister(
1454 const struct ofono_call_forwarding_driver *d)
1456 DBG("driver: %p, name: %s", d, d->name);
1458 g_drivers = g_slist_remove(g_drivers, (void *) d);
1461 static void call_forwarding_remove(struct ofono_atom *atom)
1463 struct ofono_call_forwarding *cf = __ofono_atom_get_data(atom);
1465 DBG("atom: %p", atom);
1470 if (cf->driver && cf->driver->remove)
1471 cf->driver->remove(cf);
1478 struct ofono_call_forwarding *ofono_call_forwarding_create(
1479 struct ofono_modem *modem,
1480 unsigned int vendor,
1481 const char *driver, void *data)
1483 struct ofono_call_forwarding *cf;
1489 cf = g_try_new0(struct ofono_call_forwarding, 1);
1494 cf->atom = __ofono_modem_add_atom(modem,
1495 OFONO_ATOM_TYPE_CALL_FORWARDING,
1496 call_forwarding_remove, cf);
1497 for (l = g_drivers; l; l = l->next) {
1498 const struct ofono_call_forwarding_driver *drv = l->data;
1500 if (g_strcmp0(drv->name, driver))
1503 if (drv->probe(cf, vendor, data) < 0)
1513 static void ussd_watch(struct ofono_atom *atom,
1514 enum ofono_atom_watch_condition cond, void *data)
1516 struct ofono_call_forwarding *cf = data;
1518 if (cond == OFONO_ATOM_WATCH_CONDITION_UNREGISTERED) {
1523 cf->ussd = __ofono_atom_get_data(atom);
1524 cf_register_ss_controls(cf);
1527 void ofono_call_forwarding_register(struct ofono_call_forwarding *cf)
1529 DBusConnection *conn = ofono_dbus_get_connection();
1530 const char *path = __ofono_atom_get_path(cf->atom);
1531 struct ofono_modem *modem = __ofono_atom_get_modem(cf->atom);
1533 if (!g_dbus_register_interface(conn, path,
1534 OFONO_CALL_FORWARDING_INTERFACE,
1535 cf_methods, cf_signals, NULL, cf,
1537 ofono_error("Could not create %s interface",
1538 OFONO_CALL_FORWARDING_INTERFACE);
1543 ofono_modem_add_interface(modem, OFONO_CALL_FORWARDING_INTERFACE);
1545 cf->sim = __ofono_atom_find(OFONO_ATOM_TYPE_SIM, modem);
1547 cf->sim_context = ofono_sim_context_create(cf->sim);
1548 sim_read_cf_indicator(cf);
1551 cf->ussd_watch = __ofono_modem_add_atom_watch(modem,
1552 OFONO_ATOM_TYPE_USSD,
1553 ussd_watch, cf, NULL);
1555 __ofono_atom_register(cf->atom, call_forwarding_unregister);
1558 void ofono_call_forwarding_remove(struct ofono_call_forwarding *cf)
1560 __ofono_atom_free(cf->atom);
1563 void ofono_call_forwarding_set_data(struct ofono_call_forwarding *cf,
1566 cf->driver_data = data;
1569 void *ofono_call_forwarding_get_data(struct ofono_call_forwarding *cf)
1571 return cf->driver_data;