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_find_timeout(GSList *cf_list, int cls)
113 struct ofono_call_forwarding_condition *c;
115 c = cf_cond_find(cf_list, cls);
118 return DEFAULT_NO_REPLY_TIMEOUT;
123 static void cf_cond_list_print(GSList *list)
126 struct ofono_call_forwarding_condition *cond;
128 for (l = list; l; l = l->next) {
131 DBG("CF Condition status: %d, class: %d, number: %s,"
132 " number_type: %d, time: %d",
133 cond->status, cond->cls, cond->phone_number.number,
134 cond->phone_number.type, cond->time);
138 static GSList *cf_cond_list_create(int total,
139 const struct ofono_call_forwarding_condition *list)
144 struct ofono_call_forwarding_condition *cond;
147 * Specification is not really clear how the results are reported,
148 * so assume both multiple list items & compound values of class
151 for (i = 0; i < total; i++) {
152 for (j = 1; j <= BEARER_CLASS_PAD; j = j << 1) {
153 if (!(list[i].cls & j))
156 if (list[i].status == 0)
160 struct ofono_call_forwarding_condition, 1);
164 memcpy(cond, &list[i],
165 sizeof(struct ofono_call_forwarding_condition));
168 l = g_slist_insert_sorted(l, cond, cf_cond_compare);
175 static inline void cf_clear_all(struct ofono_call_forwarding *cf)
179 for (i = 0; i < 4; i++) {
180 g_slist_free_full(cf->cf_conditions[i], g_free);
181 cf->cf_conditions[i] = NULL;
185 static const char *cf_type_lut[] = {
194 static void sim_cfis_update_cb(int ok, void *data)
197 ofono_info("Failed to update EFcfis");
200 static void sim_cphs_cff_update_cb(int ok, void *data)
203 ofono_info("Failed to update EFcphs-cff");
206 static struct ofono_call_forwarding_condition *cf_find_unconditional(
207 struct ofono_call_forwarding *cf)
209 GSList *l = cf->cf_conditions[CALL_FORWARDING_TYPE_UNCONDITIONAL];
210 struct ofono_call_forwarding_condition *cond;
213 * For now we only support Voice, although Fax & all Data
214 * basic services are applicable as well.
216 for (; l; l = l->next) {
219 if (cond->cls > BEARER_CLASS_VOICE)
228 static void sim_set_cf_indicator(struct ofono_call_forwarding *cf)
230 struct ofono_call_forwarding_condition *cfu_voice =
231 cf_find_unconditional(cf);
233 if (cf->cfis_record_id) {
234 unsigned char data[16];
237 memset(data, 0xff, sizeof(data));
239 /* Profile Identifier */
243 number_len = strlen(cfu_voice->phone_number.number);
245 /* CFU indicator Status - Voice */
247 number_len = (number_len + 1) / 2;
248 data[2] = number_len + 1;
249 data[3] = cfu_voice->phone_number.type;
251 sim_encode_bcd_number(cfu_voice->phone_number.number,
259 ofono_sim_write(cf->sim_context, SIM_EFCFIS_FILEID,
261 OFONO_SIM_FILE_STRUCTURE_FIXED,
262 cf->cfis_record_id, data,
267 if (cf->flags & CALL_FORWARDING_FLAG_CPHS_CFF) {
268 unsigned char cff_voice = cfu_voice ? 0x0A : 0x05;
270 ofono_sim_write(cf->sim_context, SIM_EF_CPHS_CFF_FILEID,
271 sim_cphs_cff_update_cb,
272 OFONO_SIM_FILE_STRUCTURE_TRANSPARENT,
273 0, &cff_voice, sizeof(cff_voice), cf);
277 static void set_new_cond_list(struct ofono_call_forwarding *cf,
278 int type, GSList *list)
280 GSList *old = cf->cf_conditions[type];
281 DBusConnection *conn = ofono_dbus_get_connection();
282 const char *path = __ofono_atom_get_path(cf->atom);
285 struct ofono_call_forwarding_condition *lc;
286 struct ofono_call_forwarding_condition *oc;
288 dbus_uint16_t timeout;
291 gboolean update_sim = FALSE;
295 if ((cf->flags & CALL_FORWARDING_FLAG_CPHS_CFF) ||
296 cf->cfis_record_id > 0)
297 old_cfu = is_cfu_enabled(cf);
301 for (l = list; l; l = l->next) {
305 * New condition lists might have attributes we don't care about
306 * triggered by e.g. ss control magic strings just skip them
307 * here. For now we only support Voice, although Fax & all Data
308 * basic services are applicable as well.
310 if (lc->cls > BEARER_CLASS_VOICE)
314 number = phone_number_to_string(&lc->phone_number);
316 snprintf(attr, sizeof(attr), "%s%s",
317 bearer_class_to_string(lc->cls), cf_type_lut[type]);
319 if (type == CALL_FORWARDING_TYPE_NO_REPLY)
320 snprintf(tattr, sizeof(tattr), "%sTimeout", attr);
322 oc = cf_cond_find(old, lc->cls);
323 if (oc) { /* On the old list, must be active */
324 if (oc->phone_number.type != lc->phone_number.type ||
325 strcmp(oc->phone_number.number,
326 lc->phone_number.number)) {
327 ofono_dbus_signal_property_changed(conn, path,
328 OFONO_CALL_FORWARDING_INTERFACE,
329 attr, DBUS_TYPE_STRING,
332 if (type == CALL_FORWARDING_TYPE_UNCONDITIONAL)
336 if (type == CALL_FORWARDING_TYPE_NO_REPLY &&
337 oc->time != lc->time)
338 ofono_dbus_signal_property_changed(conn, path,
339 OFONO_CALL_FORWARDING_INTERFACE,
340 tattr, DBUS_TYPE_UINT16,
343 /* Remove from the old list */
344 old = g_slist_remove(old, oc);
347 number = phone_number_to_string(&lc->phone_number);
349 ofono_dbus_signal_property_changed(conn, path,
350 OFONO_CALL_FORWARDING_INTERFACE,
351 attr, DBUS_TYPE_STRING,
354 if (type == CALL_FORWARDING_TYPE_UNCONDITIONAL)
357 if (type == CALL_FORWARDING_TYPE_NO_REPLY &&
358 lc->time != DEFAULT_NO_REPLY_TIMEOUT)
359 ofono_dbus_signal_property_changed(conn, path,
360 OFONO_CALL_FORWARDING_INTERFACE,
361 tattr, DBUS_TYPE_UINT16,
366 timeout = DEFAULT_NO_REPLY_TIMEOUT;
369 for (o = old; o; o = o->next) {
373 * For now we only support Voice, although Fax & all Data
374 * basic services are applicable as well.
376 if (oc->cls > BEARER_CLASS_VOICE)
379 snprintf(attr, sizeof(attr), "%s%s",
380 bearer_class_to_string(oc->cls), cf_type_lut[type]);
382 if (type == CALL_FORWARDING_TYPE_NO_REPLY)
383 snprintf(tattr, sizeof(tattr), "%sTimeout", attr);
385 ofono_dbus_signal_property_changed(conn, path,
386 OFONO_CALL_FORWARDING_INTERFACE, attr,
387 DBUS_TYPE_STRING, &number);
389 if (type == CALL_FORWARDING_TYPE_UNCONDITIONAL)
392 if (type == CALL_FORWARDING_TYPE_NO_REPLY &&
393 oc->time != DEFAULT_NO_REPLY_TIMEOUT)
394 ofono_dbus_signal_property_changed(conn, path,
395 OFONO_CALL_FORWARDING_INTERFACE,
396 tattr, DBUS_TYPE_UINT16,
400 g_slist_free_full(old, g_free);
401 cf->cf_conditions[type] = list;
403 if (update_sim == TRUE)
404 sim_set_cf_indicator(cf);
406 if ((cf->flags & CALL_FORWARDING_FLAG_CPHS_CFF) ||
407 cf->cfis_record_id > 0)
408 new_cfu = is_cfu_enabled(cf);
412 if (new_cfu != old_cfu) {
413 ofono_bool_t status = new_cfu;
417 * Emit signals to mask/unmask conditional cfs on cfu change
419 for (i = 0; i < 4; i++) {
420 if (i == CALL_FORWARDING_TYPE_UNCONDITIONAL)
423 lc = cf_cond_find(cf->cf_conditions[i],
431 number = phone_number_to_string(
434 ofono_dbus_signal_property_changed(conn, path,
435 OFONO_CALL_FORWARDING_INTERFACE,
437 DBUS_TYPE_STRING, &number);
440 ofono_dbus_signal_property_changed(conn, path,
441 OFONO_CALL_FORWARDING_INTERFACE,
442 "ForwardingFlagOnSim",
443 DBUS_TYPE_BOOLEAN, &status);
447 static inline void property_append_cf_condition(DBusMessageIter *dict, int cls,
450 dbus_uint16_t timeout)
454 int addt = !strcmp(postfix, "NoReply");
456 snprintf(attr, sizeof(attr), "%s%s",
457 bearer_class_to_string(cls), postfix);
460 snprintf(tattr, sizeof(tattr), "%s%sTimeout",
461 bearer_class_to_string(cls), postfix);
463 ofono_dbus_dict_append(dict, attr, DBUS_TYPE_STRING, &value);
466 ofono_dbus_dict_append(dict, tattr, DBUS_TYPE_UINT16, &timeout);
469 static void property_append_cf_conditions(DBusMessageIter *dict,
470 GSList *cf_list, int mask,
475 struct ofono_call_forwarding_condition *cf;
478 for (i = 1, l = cf_list; i <= BEARER_CLASS_PAD; i = i << 1) {
482 while (l && (cf = l->data) && (cf->cls < i))
485 if (l == NULL || cf->cls != i) {
486 property_append_cf_condition(dict, i, postfix, "",
487 DEFAULT_NO_REPLY_TIMEOUT);
491 number = phone_number_to_string(&cf->phone_number);
493 property_append_cf_condition(dict, i, postfix, number,
498 static DBusMessage *cf_get_properties_reply(DBusMessage *msg,
499 struct ofono_call_forwarding *cf)
502 DBusMessageIter iter;
503 DBusMessageIter dict;
506 gboolean cfu_enabled;
509 reply = dbus_message_new_method_return(msg);
513 dbus_message_iter_init_append(reply, &iter);
515 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
516 OFONO_PROPERTIES_ARRAY_SIGNATURE,
519 cfu_enabled = is_cfu_enabled(cf);
521 for (i = 0; i < 4; i++) {
523 * Report conditional cfs as empty when CFU is active
525 if (cfu_enabled && (i != CALL_FORWARDING_TYPE_UNCONDITIONAL))
528 cf_list = cf->cf_conditions[i];
530 property_append_cf_conditions(&dict, cf_list,
535 if ((cf->flags & CALL_FORWARDING_FLAG_CPHS_CFF) ||
536 cf->cfis_record_id > 0)
537 status = cfu_enabled;
541 ofono_dbus_dict_append(&dict, "ForwardingFlagOnSim", DBUS_TYPE_BOOLEAN,
544 dbus_message_iter_close_container(&iter, &dict);
549 static void get_query_cf_callback(const struct ofono_error *error, int total,
550 const struct ofono_call_forwarding_condition *list,
553 struct ofono_call_forwarding *cf = data;
555 if (error->type == OFONO_ERROR_TYPE_NO_ERROR) {
556 GSList *l = cf_cond_list_create(total, list);
558 set_new_cond_list(cf, cf->query_next, l);
560 DBG("%s conditions:", cf_type_lut[cf->query_next]);
562 cf_cond_list_print(l);
564 if (cf->query_next == CALL_FORWARDING_TYPE_NOT_REACHABLE)
565 cf->flags |= CALL_FORWARDING_FLAG_CACHED;
568 if (cf->query_next == CALL_FORWARDING_TYPE_NOT_REACHABLE) {
569 DBusMessage *reply = cf_get_properties_reply(cf->pending, cf);
570 __ofono_dbus_pending_reply(&cf->pending, reply);
575 get_query_next_cf_cond(cf);
578 static inline void get_query_next_cf_cond(struct ofono_call_forwarding *cf)
580 cf->driver->query(cf, cf->query_next, BEARER_CLASS_DEFAULT,
581 get_query_cf_callback, cf);
584 static DBusMessage *cf_get_properties(DBusConnection *conn, DBusMessage *msg,
587 struct ofono_call_forwarding *cf = data;
588 struct ofono_modem *modem = __ofono_atom_get_modem(cf->atom);
590 if ((cf->flags & CALL_FORWARDING_FLAG_CACHED) ||
591 ofono_modem_get_online(modem) == FALSE)
592 return cf_get_properties_reply(msg, cf);
594 if (cf->driver->query == NULL)
595 return __ofono_error_not_implemented(msg);
597 if (__ofono_call_forwarding_is_busy(cf) ||
598 __ofono_ussd_is_busy(cf->ussd))
599 return __ofono_error_busy(msg);
601 cf->pending = dbus_message_ref(msg);
604 get_query_next_cf_cond(cf);
609 static gboolean cf_condition_enabled_property(struct ofono_call_forwarding *cf,
610 const char *property, int *out_type, int *out_cls)
617 for (i = 1; i <= BEARER_CLASS_VOICE; i = i << 1) {
618 prefix = bearer_class_to_string(i);
620 len = strlen(prefix);
622 if (strncmp(property, prefix, len))
626 * We check the 4 call forwarding types, e.g.
627 * unconditional, busy, no reply, not reachable
629 for (j = 0; j < 4; j++)
630 if (!strcmp(property+len, cf_type_lut[j])) {
640 static gboolean cf_condition_timeout_property(const char *property,
647 for (i = 1; i <= BEARER_CLASS_VOICE; i = i << 1) {
648 prefix = bearer_class_to_string(i);
650 len = strlen(prefix);
652 if (strncmp(property, prefix, len))
655 if (!strcmp(property+len, "NoReplyTimeout")) {
664 static void set_query_cf_callback(const struct ofono_error *error, int total,
665 const struct ofono_call_forwarding_condition *list,
668 struct ofono_call_forwarding *cf = data;
672 if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
673 ofono_error("Setting succeeded, but query failed");
674 cf->flags &= ~CALL_FORWARDING_FLAG_CACHED;
675 reply = __ofono_error_failed(cf->pending);
676 __ofono_dbus_pending_reply(&cf->pending, reply);
680 if (cf->query_next == cf->query_end) {
681 reply = dbus_message_new_method_return(cf->pending);
682 __ofono_dbus_pending_reply(&cf->pending, reply);
685 l = cf_cond_list_create(total, list);
686 set_new_cond_list(cf, cf->query_next, l);
688 DBG("%s conditions:", cf_type_lut[cf->query_next]);
689 cf_cond_list_print(l);
691 if (cf->query_next != cf->query_end) {
693 set_query_next_cf_cond(cf);
697 static void set_query_next_cf_cond(struct ofono_call_forwarding *cf)
699 cf->driver->query(cf, cf->query_next, BEARER_CLASS_DEFAULT,
700 set_query_cf_callback, cf);
703 static void set_property_callback(const struct ofono_error *error, void *data)
705 struct ofono_call_forwarding *cf = data;
707 if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
708 DBG("Error occurred during set/erasure");
709 __ofono_dbus_pending_reply(&cf->pending,
710 __ofono_error_failed(cf->pending));
714 /* Successfully set, query the entire set just in case */
715 set_query_next_cf_cond(cf);
718 static DBusMessage *set_property_request(struct ofono_call_forwarding *cf,
721 struct ofono_phone_number *ph,
724 if (ph->number[0] != '\0' && cf->driver->registration == NULL)
725 return __ofono_error_not_implemented(msg);
727 if (ph->number[0] == '\0' && cf->driver->erasure == NULL)
728 return __ofono_error_not_implemented(msg);
730 cf->pending = dbus_message_ref(msg);
731 cf->query_next = type;
732 cf->query_end = type;
734 DBG("Farming off request, will be erasure: %d", ph->number[0] == '\0');
736 if (ph->number[0] != '\0')
737 cf->driver->registration(cf, type, cls, ph, timeout,
738 set_property_callback, cf);
740 cf->driver->erasure(cf, type, cls, set_property_callback, cf);
745 static DBusMessage *cf_set_property(DBusConnection *conn, DBusMessage *msg,
748 struct ofono_call_forwarding *cf = data;
749 struct ofono_modem *modem = __ofono_atom_get_modem(cf->atom);
750 DBusMessageIter iter;
752 const char *property;
756 if (ofono_modem_get_online(modem) == FALSE)
757 return __ofono_error_not_available(msg);
759 if (__ofono_call_forwarding_is_busy(cf) ||
760 __ofono_ussd_is_busy(cf->ussd))
761 return __ofono_error_busy(msg);
763 if (!dbus_message_iter_init(msg, &iter))
764 return __ofono_error_invalid_args(msg);
766 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
767 return __ofono_error_invalid_args(msg);
769 dbus_message_iter_get_basic(&iter, &property);
770 dbus_message_iter_next(&iter);
772 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
773 return __ofono_error_invalid_args(msg);
775 dbus_message_iter_recurse(&iter, &var);
777 if (cf_condition_timeout_property(property, &cls)) {
778 dbus_uint16_t timeout;
779 struct ofono_call_forwarding_condition *c;
781 type = CALL_FORWARDING_TYPE_NO_REPLY;
783 if (dbus_message_iter_get_arg_type(&var) != DBUS_TYPE_UINT16)
784 return __ofono_error_invalid_args(msg);
786 dbus_message_iter_get_basic(&var, &timeout);
788 if (timeout < 1 || timeout > 30)
789 return __ofono_error_invalid_format(msg);
792 c = cf_cond_find(cf->cf_conditions[type], cls);
794 return __ofono_error_failed(msg);
796 return set_property_request(cf, msg, type, cls,
797 &c->phone_number, timeout);
798 } else if (cf_condition_enabled_property(cf, property, &type, &cls)) {
799 struct ofono_phone_number ph;
806 if (dbus_message_iter_get_arg_type(&var) != DBUS_TYPE_STRING)
807 return __ofono_error_invalid_args(msg);
809 dbus_message_iter_get_basic(&var, &number);
811 if (strlen(number) > 0 && !valid_phone_number_format(number))
812 return __ofono_error_invalid_format(msg);
815 * Don't set conditional cfs when cfu is active
817 if (type != CALL_FORWARDING_TYPE_UNCONDITIONAL &&
818 number[0] != '\0' && is_cfu_enabled(cf))
819 return __ofono_error_not_available(msg);
821 if (number[0] != '\0')
822 string_to_phone_number(number, &ph);
824 timeout = cf_find_timeout(cf->cf_conditions[type], cls);
826 return set_property_request(cf, msg, type, cls, &ph,
830 return __ofono_error_invalid_args(msg);
833 static void disable_conditional_callback(const struct ofono_error *error,
836 struct ofono_call_forwarding *cf = data;
838 if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
839 DBG("Error occurred during conditional erasure");
841 __ofono_dbus_pending_reply(&cf->pending,
842 __ofono_error_failed(cf->pending));
846 /* Query the three conditional cf types */
847 cf->query_next = CALL_FORWARDING_TYPE_BUSY;
848 cf->query_end = CALL_FORWARDING_TYPE_NOT_REACHABLE;
849 set_query_next_cf_cond(cf);
852 static void disable_all_callback(const struct ofono_error *error, void *data)
854 struct ofono_call_forwarding *cf = data;
856 if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
857 DBG("Error occurred during erasure of all");
859 __ofono_dbus_pending_reply(&cf->pending,
860 __ofono_error_failed(cf->pending));
864 /* Query all cf types */
865 cf->query_next = CALL_FORWARDING_TYPE_UNCONDITIONAL;
866 cf->query_end = CALL_FORWARDING_TYPE_NOT_REACHABLE;
867 set_query_next_cf_cond(cf);
870 static DBusMessage *cf_disable_all(DBusConnection *conn, DBusMessage *msg,
873 struct ofono_call_forwarding *cf = data;
877 if (cf->driver->erasure == NULL)
878 return __ofono_error_not_implemented(msg);
880 if (__ofono_call_forwarding_is_busy(cf) ||
881 __ofono_ussd_is_busy(cf->ussd))
882 return __ofono_error_busy(msg);
884 if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &strtype,
885 DBUS_TYPE_INVALID) == FALSE)
886 return __ofono_error_invalid_args(msg);
888 if (!strcmp(strtype, "all") || !strcmp(strtype, ""))
889 type = CALL_FORWARDING_TYPE_ALL;
890 else if (!strcmp(strtype, "conditional"))
891 type = CALL_FORWARDING_TYPE_ALL_CONDITIONAL;
893 return __ofono_error_invalid_format(msg);
895 cf->pending = dbus_message_ref(msg);
897 if (type == CALL_FORWARDING_TYPE_ALL)
898 cf->driver->erasure(cf, type, BEARER_CLASS_DEFAULT,
899 disable_all_callback, cf);
901 cf->driver->erasure(cf, type, BEARER_CLASS_DEFAULT,
902 disable_conditional_callback, cf);
907 static GDBusMethodTable cf_methods[] = {
908 { "GetProperties", "", "a{sv}", cf_get_properties,
909 G_DBUS_METHOD_FLAG_ASYNC },
910 { "SetProperty", "sv", "", cf_set_property,
911 G_DBUS_METHOD_FLAG_ASYNC },
912 { "DisableAll", "s", "", cf_disable_all,
913 G_DBUS_METHOD_FLAG_ASYNC },
917 static GDBusSignalTable cf_signals[] = {
918 { "PropertyChanged", "sv" },
922 static DBusMessage *cf_ss_control_reply(struct ofono_call_forwarding *cf,
923 struct cf_ss_request *req)
925 const char *context = "CallForwarding";
926 const char *sig = "(ssa{sv})";
927 const char *ss_type = ss_control_type_to_string(req->ss_type);
928 const char *cf_type = cf_type_lut[req->cf_type];
929 DBusMessageIter iter;
930 DBusMessageIter variant;
931 DBusMessageIter vstruct;
932 DBusMessageIter dict;
935 reply = dbus_message_new_method_return(cf->pending);
937 dbus_message_iter_init_append(reply, &iter);
939 dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &context);
941 dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT, sig,
944 dbus_message_iter_open_container(&variant, DBUS_TYPE_STRUCT, NULL,
947 dbus_message_iter_append_basic(&vstruct, DBUS_TYPE_STRING,
950 dbus_message_iter_append_basic(&vstruct, DBUS_TYPE_STRING,
953 dbus_message_iter_open_container(&vstruct, DBUS_TYPE_ARRAY,
954 OFONO_PROPERTIES_ARRAY_SIGNATURE, &dict);
956 if (req->cf_type == CALL_FORWARDING_TYPE_UNCONDITIONAL ||
957 req->cf_type == CALL_FORWARDING_TYPE_ALL)
958 property_append_cf_conditions(&dict,
959 req->cf_list[CALL_FORWARDING_TYPE_UNCONDITIONAL],
961 cf_type_lut[CALL_FORWARDING_TYPE_UNCONDITIONAL]);
963 if (req->cf_type == CALL_FORWARDING_TYPE_NO_REPLY ||
964 req->cf_type == CALL_FORWARDING_TYPE_ALL ||
965 req->cf_type == CALL_FORWARDING_TYPE_ALL_CONDITIONAL)
966 property_append_cf_conditions(&dict,
967 req->cf_list[CALL_FORWARDING_TYPE_NO_REPLY],
968 req->cls, cf_type_lut[CALL_FORWARDING_TYPE_NO_REPLY]);
970 if (req->cf_type == CALL_FORWARDING_TYPE_NOT_REACHABLE ||
971 req->cf_type == CALL_FORWARDING_TYPE_ALL ||
972 req->cf_type == CALL_FORWARDING_TYPE_ALL_CONDITIONAL)
973 property_append_cf_conditions(&dict,
974 req->cf_list[CALL_FORWARDING_TYPE_NOT_REACHABLE],
976 cf_type_lut[CALL_FORWARDING_TYPE_NOT_REACHABLE]);
978 if (req->cf_type == CALL_FORWARDING_TYPE_BUSY ||
979 req->cf_type == CALL_FORWARDING_TYPE_ALL ||
980 req->cf_type == CALL_FORWARDING_TYPE_ALL_CONDITIONAL)
981 property_append_cf_conditions(&dict,
982 req->cf_list[CALL_FORWARDING_TYPE_BUSY],
983 req->cls, cf_type_lut[CALL_FORWARDING_TYPE_BUSY]);
985 dbus_message_iter_close_container(&vstruct, &dict);
987 dbus_message_iter_close_container(&variant, &vstruct);
989 dbus_message_iter_close_container(&iter, &variant);
994 static void ss_set_query_cf_callback(const struct ofono_error *error, int total,
995 const struct ofono_call_forwarding_condition *list,
998 struct ofono_call_forwarding *cf = data;
1002 if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
1003 ofono_error("Setting succeeded, but query failed");
1004 cf->flags &= ~CALL_FORWARDING_FLAG_CACHED;
1005 reply = __ofono_error_failed(cf->pending);
1006 __ofono_dbus_pending_reply(&cf->pending, reply);
1010 l = cf_cond_list_create(total, list);
1011 DBG("%s conditions:", cf_type_lut[cf->query_next]);
1012 cf_cond_list_print(l);
1014 cf->ss_req->cf_list[cf->query_next] = l;
1016 if (cf->query_next == cf->query_end) {
1017 reply = cf_ss_control_reply(cf, cf->ss_req);
1018 __ofono_dbus_pending_reply(&cf->pending, reply);
1023 set_new_cond_list(cf, cf->query_next, l);
1025 if (cf->query_next != cf->query_end) {
1027 ss_set_query_next_cf_cond(cf);
1031 static void ss_set_query_next_cf_cond(struct ofono_call_forwarding *cf)
1033 cf->driver->query(cf, cf->query_next, BEARER_CLASS_DEFAULT,
1034 ss_set_query_cf_callback, cf);
1037 static void cf_ss_control_callback(const struct ofono_error *error, void *data)
1039 struct ofono_call_forwarding *cf = data;
1041 if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
1042 DBG("Error occurred during cf ss control set/erasure");
1044 __ofono_dbus_pending_reply(&cf->pending,
1045 __ofono_error_failed(cf->pending));
1051 ss_set_query_next_cf_cond(cf);
1054 static gboolean cf_ss_control(int type, const char *sc,
1055 const char *sia, const char *sib,
1056 const char *sic, const char *dn,
1057 DBusMessage *msg, void *data)
1059 struct ofono_call_forwarding *cf = data;
1060 DBusConnection *conn = ofono_dbus_get_connection();
1061 int cls = BEARER_CLASS_SS_DEFAULT;
1062 int timeout = DEFAULT_NO_REPLY_TIMEOUT;
1065 struct ofono_phone_number ph;
1066 void *operation = NULL;
1068 /* Before we do anything, make sure we're actually initialized */
1072 if (__ofono_call_forwarding_is_busy(cf)) {
1073 reply = __ofono_error_busy(msg);
1074 g_dbus_send_message(conn, reply);
1079 DBG("Received call forwarding ss control request");
1081 DBG("type: %d, sc: %s, sia: %s, sib: %s, sic: %s, dn: %s",
1082 type, sc, sia, sib, sic, dn);
1084 if (!strcmp(sc, "21"))
1085 cf_type = CALL_FORWARDING_TYPE_UNCONDITIONAL;
1086 else if (!strcmp(sc, "67"))
1087 cf_type = CALL_FORWARDING_TYPE_BUSY;
1088 else if (!strcmp(sc, "61"))
1089 cf_type = CALL_FORWARDING_TYPE_NO_REPLY;
1090 else if (!strcmp(sc, "62"))
1091 cf_type = CALL_FORWARDING_TYPE_NOT_REACHABLE;
1092 else if (!strcmp(sc, "002"))
1093 cf_type = CALL_FORWARDING_TYPE_ALL;
1094 else if (!strcmp(sc, "004"))
1095 cf_type = CALL_FORWARDING_TYPE_ALL_CONDITIONAL;
1100 (type == SS_CONTROL_TYPE_QUERY ||
1101 type == SS_CONTROL_TYPE_ERASURE ||
1102 type == SS_CONTROL_TYPE_DEACTIVATION))
1106 * Activation / Registration is figured context specific according to
1107 * 22.030 Section 6.5.2 "The UE shall determine from the context
1108 * whether, an entry of a single *, activation or registration
1111 if (type == SS_CONTROL_TYPE_ACTIVATION && strlen(sia) > 0)
1112 type = SS_CONTROL_TYPE_REGISTRATION;
1114 if (type == SS_CONTROL_TYPE_REGISTRATION &&
1115 !valid_phone_number_format(sia))
1118 if (strlen(sib) > 0) {
1122 service_code = strtoul(sib, &end, 10);
1124 if (end == sib || *end != '\0')
1127 cls = mmi_service_code_to_bearer_class(service_code);
1133 if (strlen(sic) > 0) {
1136 if (type != SS_CONTROL_TYPE_REGISTRATION)
1139 if (cf_type != CALL_FORWARDING_TYPE_ALL &&
1140 cf_type != CALL_FORWARDING_TYPE_ALL_CONDITIONAL &&
1141 cf_type != CALL_FORWARDING_TYPE_NO_REPLY)
1144 timeout = strtoul(sic, &end, 10);
1146 if (end == sic || *end != '\0')
1149 if (timeout < 1 || timeout > 30)
1154 case SS_CONTROL_TYPE_REGISTRATION:
1155 operation = cf->driver->registration;
1157 case SS_CONTROL_TYPE_ACTIVATION:
1158 operation = cf->driver->activation;
1160 case SS_CONTROL_TYPE_DEACTIVATION:
1161 operation = cf->driver->deactivation;
1163 case SS_CONTROL_TYPE_ERASURE:
1164 operation = cf->driver->erasure;
1166 case SS_CONTROL_TYPE_QUERY:
1167 operation = cf->driver->query;
1171 if (operation == NULL) {
1172 reply = __ofono_error_not_implemented(msg);
1173 g_dbus_send_message(conn, reply);
1178 cf->ss_req = g_try_new0(struct cf_ss_request, 1);
1180 if (cf->ss_req == NULL) {
1181 reply = __ofono_error_failed(msg);
1182 g_dbus_send_message(conn, reply);
1187 cf->ss_req->ss_type = type;
1188 cf->ss_req->cf_type = cf_type;
1189 cf->ss_req->cls = cls;
1191 cf->pending = dbus_message_ref(msg);
1193 switch (cf->ss_req->cf_type) {
1194 case CALL_FORWARDING_TYPE_ALL:
1195 cf->query_next = CALL_FORWARDING_TYPE_UNCONDITIONAL;
1196 cf->query_end = CALL_FORWARDING_TYPE_NOT_REACHABLE;
1198 case CALL_FORWARDING_TYPE_ALL_CONDITIONAL:
1199 cf->query_next = CALL_FORWARDING_TYPE_BUSY;
1200 cf->query_end = CALL_FORWARDING_TYPE_NOT_REACHABLE;
1203 cf->query_next = cf->ss_req->cf_type;
1204 cf->query_end = cf->ss_req->cf_type;
1209 * Some modems don't understand all classes very well, particularly
1210 * the older models. So if the bearer class is the default, we
1211 * just use the more commonly understood value of 7 since BEARER_SMS
1212 * is not applicable to CallForwarding conditions according to 22.004
1215 if (cls == BEARER_CLASS_SS_DEFAULT)
1216 cls = BEARER_CLASS_DEFAULT;
1218 switch (cf->ss_req->ss_type) {
1219 case SS_CONTROL_TYPE_REGISTRATION:
1220 string_to_phone_number(sia, &ph);
1221 cf->driver->registration(cf, cf_type, cls, &ph, timeout,
1222 cf_ss_control_callback, cf);
1224 case SS_CONTROL_TYPE_ACTIVATION:
1225 cf->driver->activation(cf, cf_type, cls, cf_ss_control_callback,
1228 case SS_CONTROL_TYPE_DEACTIVATION:
1229 cf->driver->deactivation(cf, cf_type, cls,
1230 cf_ss_control_callback, cf);
1232 case SS_CONTROL_TYPE_ERASURE:
1233 cf->driver->erasure(cf, cf_type, cls, cf_ss_control_callback,
1236 case SS_CONTROL_TYPE_QUERY:
1237 ss_set_query_next_cf_cond(cf);
1244 reply = __ofono_error_invalid_format(msg);
1245 g_dbus_send_message(conn, reply);
1249 static void cf_register_ss_controls(struct ofono_call_forwarding *cf)
1251 __ofono_ussd_ssc_register(cf->ussd, "21", cf_ss_control, cf, NULL);
1252 __ofono_ussd_ssc_register(cf->ussd, "67", cf_ss_control, cf, NULL);
1253 __ofono_ussd_ssc_register(cf->ussd, "61", cf_ss_control, cf, NULL);
1254 __ofono_ussd_ssc_register(cf->ussd, "62", cf_ss_control, cf, NULL);
1256 __ofono_ussd_ssc_register(cf->ussd, "002", cf_ss_control, cf, NULL);
1257 __ofono_ussd_ssc_register(cf->ussd, "004", cf_ss_control, cf, NULL);
1260 static void cf_unregister_ss_controls(struct ofono_call_forwarding *cf)
1262 __ofono_ussd_ssc_unregister(cf->ussd, "21");
1263 __ofono_ussd_ssc_unregister(cf->ussd, "67");
1264 __ofono_ussd_ssc_unregister(cf->ussd, "61");
1265 __ofono_ussd_ssc_unregister(cf->ussd, "62");
1267 __ofono_ussd_ssc_unregister(cf->ussd, "002");
1268 __ofono_ussd_ssc_unregister(cf->ussd, "004");
1271 gboolean __ofono_call_forwarding_is_busy(struct ofono_call_forwarding *cf)
1273 return cf->pending ? TRUE : FALSE;
1276 static void sim_cfis_read_cb(int ok, int total_length, int record,
1277 const unsigned char *data,
1278 int record_length, void *userdata)
1280 struct ofono_call_forwarding *cf = userdata;
1281 DBusConnection *conn = ofono_dbus_get_connection();
1282 const char *path = __ofono_atom_get_path(cf->atom);
1284 if (!ok || record_length < 16 || total_length < record_length) {
1285 cf->cfis_record_id = 0;
1290 * Multiple Subscriber Profile number which can have values 1-4.
1291 * Profile id 1 is assumed as the current profile.
1296 cf->cfis_record_id = record;
1298 if (cf->flags & CALL_FORWARDING_FLAG_CACHED)
1302 * For now we only support Voice, although Fax & all Data
1303 * basic services are applicable as well.
1305 if (data[1] & 0x01) {
1310 struct ofono_call_forwarding_condition *cond;
1313 number_len = data[2];
1316 if (number_len > 11 || ton_npi == 0xff)
1319 cond = g_try_new0(struct ofono_call_forwarding_condition, 1);
1324 cond->status = TRUE;
1325 cond->cls = BEARER_CLASS_VOICE;
1327 cond->phone_number.type = ton_npi;
1329 sim_extract_bcd_number(data + 4, number_len - 1,
1330 cond->phone_number.number);
1331 number = phone_number_to_string(&cond->phone_number);
1333 snprintf(attr, sizeof(attr), "%s%s",
1334 bearer_class_to_string(BEARER_CLASS_VOICE),
1335 cf_type_lut[CALL_FORWARDING_TYPE_UNCONDITIONAL]);
1337 cf->cf_conditions[CALL_FORWARDING_TYPE_UNCONDITIONAL] =
1338 g_slist_append(NULL, cond);
1340 ofono_dbus_signal_property_changed(conn, path,
1341 OFONO_CALL_FORWARDING_INTERFACE,
1342 attr, DBUS_TYPE_STRING, &number);
1344 ofono_dbus_signal_property_changed(conn, path,
1345 OFONO_CALL_FORWARDING_INTERFACE,
1346 "ForwardingFlagOnSim",
1347 DBUS_TYPE_BOOLEAN, &status);
1351 static void sim_cphs_cff_read_cb(int ok, int total_length, int record,
1352 const unsigned char *data,
1353 int record_length, void *userdata)
1355 struct ofono_call_forwarding *cf = userdata;
1356 DBusConnection *conn = ofono_dbus_get_connection();
1357 const char *path = __ofono_atom_get_path(cf->atom);
1358 dbus_bool_t cfu_voice;
1360 if (!ok || total_length < 1)
1363 cf->flags |= CALL_FORWARDING_FLAG_CPHS_CFF;
1365 if (cf->flags & CALL_FORWARDING_FLAG_CACHED)
1369 * For now we only support Voice, although Fax & all Data
1370 * basic services are applicable as well.
1372 if ((data[0] & 0xf) != 0xA)
1377 ofono_dbus_signal_property_changed(conn, path,
1378 OFONO_CALL_FORWARDING_INTERFACE,
1379 "ForwardingFlagOnSim",
1380 DBUS_TYPE_BOOLEAN, &cfu_voice);
1383 static void call_forwarding_unregister(struct ofono_atom *atom)
1385 struct ofono_call_forwarding *cf = __ofono_atom_get_data(atom);
1386 const char *path = __ofono_atom_get_path(cf->atom);
1387 DBusConnection *conn = ofono_dbus_get_connection();
1388 struct ofono_modem *modem = __ofono_atom_get_modem(cf->atom);
1390 ofono_modem_remove_interface(modem, OFONO_CALL_FORWARDING_INTERFACE);
1391 g_dbus_unregister_interface(conn, path,
1392 OFONO_CALL_FORWARDING_INTERFACE);
1394 if (cf->sim_context) {
1395 ofono_sim_context_free(cf->sim_context);
1396 cf->sim_context = NULL;
1400 cf_unregister_ss_controls(cf);
1403 __ofono_modem_remove_atom_watch(modem, cf->ussd_watch);
1408 static void sim_cfis_changed(int id, void *userdata)
1410 struct ofono_call_forwarding *cf = userdata;
1412 if (!(cf->flags & CALL_FORWARDING_FLAG_CACHED))
1416 * If the values are cached it's because at least one client
1417 * requested them and we need to notify them about this
1418 * change. However the authoritative source of current
1419 * Call-Forwarding settings is the network operator and the
1420 * query can take a noticeable amount of time. Instead of
1421 * sending PropertyChanged, we reregister the Call Forwarding
1422 * atom. The client will invoke GetProperties only if it
1423 * is still interested.
1425 call_forwarding_unregister(cf->atom);
1426 ofono_call_forwarding_register(cf);
1429 static void sim_read_cf_indicator(struct ofono_call_forwarding *cf)
1431 if (__ofono_sim_service_available(cf->sim,
1432 SIM_UST_SERVICE_CFIS,
1433 SIM_SST_SERVICE_CFIS) == TRUE) {
1434 ofono_sim_read(cf->sim_context, SIM_EFCFIS_FILEID,
1435 OFONO_SIM_FILE_STRUCTURE_FIXED,
1436 sim_cfis_read_cb, cf);
1437 ofono_sim_add_file_watch(cf->sim_context, SIM_EFCFIS_FILEID,
1438 sim_cfis_changed, cf, NULL);
1440 ofono_sim_read(cf->sim_context, SIM_EF_CPHS_CFF_FILEID,
1441 OFONO_SIM_FILE_STRUCTURE_TRANSPARENT,
1442 sim_cphs_cff_read_cb, cf);
1443 ofono_sim_add_file_watch(cf->sim_context,
1444 SIM_EF_CPHS_CFF_FILEID,
1445 sim_cfis_changed, cf, NULL);
1449 int ofono_call_forwarding_driver_register(
1450 const struct ofono_call_forwarding_driver *d)
1452 DBG("driver: %p, name: %s", d, d->name);
1454 if (d->probe == NULL)
1457 g_drivers = g_slist_prepend(g_drivers, (void *) d);
1462 void ofono_call_forwarding_driver_unregister(
1463 const struct ofono_call_forwarding_driver *d)
1465 DBG("driver: %p, name: %s", d, d->name);
1467 g_drivers = g_slist_remove(g_drivers, (void *) d);
1470 static void call_forwarding_remove(struct ofono_atom *atom)
1472 struct ofono_call_forwarding *cf = __ofono_atom_get_data(atom);
1474 DBG("atom: %p", atom);
1479 if (cf->driver && cf->driver->remove)
1480 cf->driver->remove(cf);
1487 struct ofono_call_forwarding *ofono_call_forwarding_create(
1488 struct ofono_modem *modem,
1489 unsigned int vendor,
1490 const char *driver, void *data)
1492 struct ofono_call_forwarding *cf;
1498 cf = g_try_new0(struct ofono_call_forwarding, 1);
1503 cf->atom = __ofono_modem_add_atom(modem,
1504 OFONO_ATOM_TYPE_CALL_FORWARDING,
1505 call_forwarding_remove, cf);
1506 for (l = g_drivers; l; l = l->next) {
1507 const struct ofono_call_forwarding_driver *drv = l->data;
1509 if (g_strcmp0(drv->name, driver))
1512 if (drv->probe(cf, vendor, data) < 0)
1522 static void ussd_watch(struct ofono_atom *atom,
1523 enum ofono_atom_watch_condition cond, void *data)
1525 struct ofono_call_forwarding *cf = data;
1527 if (cond == OFONO_ATOM_WATCH_CONDITION_UNREGISTERED) {
1532 cf->ussd = __ofono_atom_get_data(atom);
1533 cf_register_ss_controls(cf);
1536 void ofono_call_forwarding_register(struct ofono_call_forwarding *cf)
1538 DBusConnection *conn = ofono_dbus_get_connection();
1539 const char *path = __ofono_atom_get_path(cf->atom);
1540 struct ofono_modem *modem = __ofono_atom_get_modem(cf->atom);
1542 if (!g_dbus_register_interface(conn, path,
1543 OFONO_CALL_FORWARDING_INTERFACE,
1544 cf_methods, cf_signals, NULL, cf,
1546 ofono_error("Could not create %s interface",
1547 OFONO_CALL_FORWARDING_INTERFACE);
1552 ofono_modem_add_interface(modem, OFONO_CALL_FORWARDING_INTERFACE);
1554 cf->sim = __ofono_atom_find(OFONO_ATOM_TYPE_SIM, modem);
1556 cf->sim_context = ofono_sim_context_create(cf->sim);
1557 sim_read_cf_indicator(cf);
1560 cf->ussd_watch = __ofono_modem_add_atom_watch(modem,
1561 OFONO_ATOM_TYPE_USSD,
1562 ussd_watch, cf, NULL);
1564 __ofono_atom_register(cf->atom, call_forwarding_unregister);
1567 void ofono_call_forwarding_remove(struct ofono_call_forwarding *cf)
1569 __ofono_atom_free(cf->atom);
1572 void ofono_call_forwarding_set_data(struct ofono_call_forwarding *cf,
1575 cf->driver_data = data;
1578 void *ofono_call_forwarding_get_data(struct ofono_call_forwarding *cf)
1580 return cf->driver_data;