All of lore.kernel.org
 help / color / mirror / Atom feed
* Read/Write EFcfis/EFcphs-cff
@ 2010-11-29 10:37 Jeevaka Badrappan
  2010-11-29 10:37 ` [PATCH 1/7] call-forwarding: Read/Write cfis/cphs-cff Jeevaka Badrappan
                   ` (6 more replies)
  0 siblings, 7 replies; 16+ messages in thread
From: Jeevaka Badrappan @ 2010-11-29 10:37 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 976 bytes --]


Hi,

This patch reads and writes the VoiceUnconditional call forwarding status
from and to the SIM files EFcfis/EFcphs-cff. New property ForwardingFlagOnSim
is added to inform the status of the VoiceUnconditional status read from SIM.

If EFcfis is present, EFcfis file is read and the status is updated via
properties VoiceUnconditional and ForwardingFlagOnSim. If VoiceUnconditional
call forwaring rule is enabled, VoiceUnconditional property holds the
"forwared to" number whereas ForwardingFlagOnSim holds the status of the call
forwarding rule.

If cfis is not present but EFcphs-cff is present, then EFcphs-cff is read
and the status is updated via the property ForwardingFlagOnSim. 

offline-online state transitions results in caching the call forwaring status
every time. To avoid this, call forwarding atom is moved to the post sim and
its moved also due to the fact that call forwarding status doesn't change in
roaming.

Regards,
Jeevaka


^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH 1/7] call-forwarding: Read/Write cfis/cphs-cff
  2010-11-29 10:37 Read/Write EFcfis/EFcphs-cff Jeevaka Badrappan
@ 2010-11-29 10:37 ` Jeevaka Badrappan
  2010-12-03 19:08   ` Denis Kenzior
  2010-11-29 10:37 ` [PATCH 2/7] ifx: Move call forwarding to post sim Jeevaka Badrappan
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 16+ messages in thread
From: Jeevaka Badrappan @ 2010-11-29 10:37 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 10935 bytes --]

---
 src/call-forwarding.c |  266 +++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 260 insertions(+), 6 deletions(-)

diff --git a/src/call-forwarding.c b/src/call-forwarding.c
index ce03c40..bb345a6 100644
--- a/src/call-forwarding.c
+++ b/src/call-forwarding.c
@@ -34,6 +34,7 @@
 #include "ofono.h"
 
 #include "common.h"
+#include "simutil.h"
 
 #define CALL_FORWARDING_FLAG_CACHED 0x1
 
@@ -58,6 +59,12 @@ struct ofono_call_forwarding {
 	int query_next;
 	int query_end;
 	struct cf_ss_request *ss_req;
+	struct ofono_sim *sim;
+	unsigned char cfis_record_id;
+	unsigned char cfis_indicator;
+	ofono_bool_t cphs_cff_present;
+	ofono_bool_t status_on_sim;
+	ofono_bool_t online;
 	struct ofono_ussd *ussd;
 	unsigned int ussd_watch;
 	const struct ofono_call_forwarding_driver *driver;
@@ -202,6 +209,85 @@ static const char *cf_type_lut[] = {
 	"AllConditional"
 };
 
+static void sim_cfis_update_cb(int ok, void *data)
+{
+	if (!ok)
+		ofono_info("Failed to update EFcfis");
+}
+
+static void sim_cphs_cff_update_cb(int ok, void *data)
+{
+	if (!ok)
+		ofono_info("Failed to update EFcphs-cff");
+}
+
+static void sim_set_cf_indicator(struct ofono_call_forwarding *cf)
+{
+	gboolean cfu_voice = FALSE;
+	struct ofono_call_forwarding_condition *cond = NULL;
+	GSList *l;
+
+	/*
+	 * For now we only support Voice, although Fax & all Data
+	 * basic services are applicable as well.
+	 */
+	for (l = cf->cf_conditions[0]; l; l = l->next) {
+		cond = l->data;
+
+		if ((cond->cls & BEARER_CLASS_VOICE) &&
+				(strlen(cond->phone_number.number) > 0)) {
+			cfu_voice = TRUE;
+			break;
+		}
+	}
+
+	if (cfu_voice == cf->status_on_sim)
+		return;
+
+	cf->status_on_sim = cfu_voice;
+
+	if (cf->cfis_record_id) {
+		unsigned char data[16];
+		int number_len;
+
+		memset(data, 0xff, sizeof(data));
+
+		/* Profile Identifier */
+		data[0] = 0x01;
+
+		if (cfu_voice) {
+			number_len = strlen(cond->phone_number.number);
+
+			/* CFU indicator Status - Voice */
+			data[1] = (cf->cfis_indicator |= 0x01);
+			number_len = (number_len + 1) / 2;
+			data[2] = number_len + 1;
+			data[3] = cond->phone_number.type;
+
+			sim_encode_bcd_number(cond->phone_number.number,
+						data + 4);
+
+		} else
+			data[1] = (cf->cfis_indicator &= 0xFE);
+
+		ofono_sim_write(cf->sim, SIM_EFCFIS_FILEID,
+					sim_cfis_update_cb,
+					OFONO_SIM_FILE_STRUCTURE_FIXED,
+					cf->cfis_record_id, data,
+					sizeof(data), cf);
+		return;
+	}
+
+	if (cf->cphs_cff_present) {
+		unsigned char cff_voice = cfu_voice ? 0x0A : 0x05;
+
+		ofono_sim_write(cf->sim, SIM_EF_CPHS_CFF_FILEID,
+					sim_cphs_cff_update_cb,
+					OFONO_SIM_FILE_STRUCTURE_TRANSPARENT,
+					0, &cff_voice, sizeof(cff_voice), cf);
+	}
+}
+
 static void set_new_cond_list(struct ofono_call_forwarding *cf,
 				int type, GSList *list)
 {
@@ -372,6 +458,7 @@ static DBusMessage *cf_get_properties_reply(DBusMessage *msg,
 	DBusMessageIter iter;
 	DBusMessageIter dict;
 	int i;
+	dbus_bool_t status;
 
 	reply = dbus_message_new_method_return(msg);
 
@@ -384,10 +471,21 @@ static DBusMessage *cf_get_properties_reply(DBusMessage *msg,
 					OFONO_PROPERTIES_ARRAY_SIGNATURE,
 						&dict);
 
-	for (i = 0; i < 4; i++)
-		property_append_cf_conditions(&dict, cf->cf_conditions[i],
+	if (cf->online == TRUE) {
+		for (i = 0; i < 4; i++)
+			property_append_cf_conditions(&dict,
+						cf->cf_conditions[i],
 						BEARER_CLASS_VOICE,
 						cf_type_lut[i]);
+	} else if (cf->status_on_sim == TRUE)
+		property_append_cf_conditions(&dict,
+			cf->cf_conditions[CALL_FORWARDING_TYPE_UNCONDITIONAL],
+			BEARER_CLASS_VOICE,
+			cf_type_lut[CALL_FORWARDING_TYPE_UNCONDITIONAL]);
+
+	status = cf->status_on_sim;
+	ofono_dbus_dict_append(&dict, "ForwardingFlagOnSim", DBUS_TYPE_BOOLEAN,
+					&status);
 
 	dbus_message_iter_close_container(&iter, &dict);
 
@@ -413,7 +511,15 @@ static void get_query_cf_callback(const struct ofono_error *error, int total,
 	}
 
 	if (cf->query_next == CALL_FORWARDING_TYPE_NOT_REACHABLE) {
-		DBusMessage *reply = cf_get_properties_reply(cf->pending, cf);
+		DBusMessage *reply;
+
+		/*
+		* This is to make sure the information received from
+		* network is in sync with the information present in SIM/USIM
+		*/
+		sim_set_cf_indicator(cf);
+
+		reply = cf_get_properties_reply(cf->pending, cf);
 		__ofono_dbus_pending_reply(&cf->pending, reply);
 		return;
 	}
@@ -433,7 +539,8 @@ static DBusMessage *cf_get_properties(DBusConnection *conn, DBusMessage *msg,
 {
 	struct ofono_call_forwarding *cf = data;
 
-	if (cf->flags & CALL_FORWARDING_FLAG_CACHED)
+	if ((cf->flags & CALL_FORWARDING_FLAG_CACHED) ||
+			cf->online == FALSE)
 		return cf_get_properties_reply(msg, cf);
 
 	if (!cf->driver->query)
@@ -536,7 +643,8 @@ static void set_query_cf_callback(const struct ofono_error *error, int total,
 	if (cf->query_next != cf->query_end) {
 		cf->query_next++;
 		set_query_next_cf_cond(cf);
-	}
+	} else
+		sim_set_cf_indicator(cf);
 }
 
 static void set_query_next_cf_cond(struct ofono_call_forwarding *cf)
@@ -597,6 +705,9 @@ static DBusMessage *cf_set_property(DBusConnection *conn, DBusMessage *msg,
 	int cls;
 	int type;
 
+	if (cf->online == FALSE)
+		return __ofono_error_not_available(msg);
+
 	if (__ofono_call_forwarding_is_busy(cf) ||
 			__ofono_ussd_is_busy(cf->ussd))
 		return __ofono_error_busy(msg);
@@ -864,7 +975,8 @@ static void ss_set_query_cf_callback(const struct ofono_error *error, int total,
 	if (cf->query_next != cf->query_end) {
 		cf->query_next++;
 		ss_set_query_next_cf_cond(cf);
-	}
+	} else
+		sim_set_cf_indicator(cf);
 }
 
 static void ss_set_query_next_cf_cond(struct ofono_call_forwarding *cf)
@@ -1112,6 +1224,128 @@ gboolean __ofono_call_forwarding_is_busy(struct ofono_call_forwarding *cf)
 	return cf->pending ? TRUE : FALSE;
 }
 
+static void sim_cfis_read_cb(int ok, int total_length, int record,
+			const unsigned char *data,
+			int record_length, void *userdata)
+{
+	struct ofono_call_forwarding *cf = userdata;
+	DBusConnection *conn = ofono_dbus_get_connection();
+	const char *path = __ofono_atom_get_path(cf->atom);
+
+	if (!ok || record_length < 16 || total_length < record_length) {
+		cf->cfis_indicator = 0;
+		cf->cfis_record_id = 0;
+		return;
+	}
+
+	/*
+	 * Multiple Subscriber Profile number which can have values 1-4.
+	 * Profile id 1 is assumed as the current profile.
+	 */
+	if (data[0] != 1)
+		return;
+
+	cf->cfis_record_id = record;
+
+	/* CFU indicator status */
+	cf->cfis_indicator = data[1];
+
+	/*
+	 * For now we only support Voice, although Fax & all Data
+	 * basic services are applicable as well.
+	 */
+	if (cf->cfis_indicator & 0x01) {
+		int ton_npi;
+		int number_len;
+		const char *number;
+		char attr[64];
+		struct ofono_call_forwarding_condition *cond;
+		GSList *l = NULL;
+		dbus_bool_t status;
+
+		number_len = data[2];
+		ton_npi = data[3];
+
+		if (number_len > 11 || ton_npi == 0xff)
+			return;
+
+		cond = g_try_new0(struct ofono_call_forwarding_condition, 1);
+		if (cond == NULL)
+			return;
+
+		status = cf->status_on_sim = TRUE;
+		cond->status = status;
+		cond->cls = BEARER_CLASS_VOICE;
+		cond->time = 0;
+		cond->phone_number.type = ton_npi;
+
+		sim_extract_bcd_number(data + 4, number_len - 1,
+					cond->phone_number.number);
+		number = phone_number_to_string(&cond->phone_number);
+
+		snprintf(attr, sizeof(attr), "%s%s",
+			bearer_class_to_string(BEARER_CLASS_VOICE),
+			cf_type_lut[CALL_FORWARDING_TYPE_UNCONDITIONAL]);
+
+		cf->cf_conditions[CALL_FORWARDING_TYPE_UNCONDITIONAL] =
+							g_slist_append(l, cond);
+
+		ofono_dbus_signal_property_changed(conn, path,
+				OFONO_CALL_FORWARDING_INTERFACE,
+				attr, DBUS_TYPE_STRING,
+				&number);
+
+		ofono_dbus_signal_property_changed(conn, path,
+				OFONO_CALL_FORWARDING_INTERFACE,
+				"ForwardingFlagOnSim",
+				DBUS_TYPE_BOOLEAN,
+				&status);
+	}
+}
+
+static void sim_cphs_cff_read_cb(int ok, int total_length, int record,
+				const unsigned char *data,
+				int record_length, void *userdata)
+{
+	struct ofono_call_forwarding *cf = userdata;
+	DBusConnection *conn = ofono_dbus_get_connection();
+	const char *path = __ofono_atom_get_path(cf->atom);
+	dbus_bool_t cfu_voice;
+
+	if (!ok || total_length < 1) {
+		cf->cphs_cff_present = FALSE;
+		return;
+	}
+
+	cf->cphs_cff_present = TRUE;
+
+	/*
+	 * For now we only support Voice, although Fax & all Data
+	 * basic services are applicable as well.
+	 */
+	cfu_voice = cf->status_on_sim = ((data[0] & 0xf) == 0xa);
+
+	ofono_dbus_signal_property_changed(conn, path,
+					OFONO_CALL_FORWARDING_INTERFACE,
+					"ForwardingFlagOnSim",
+					DBUS_TYPE_BOOLEAN,
+					&cfu_voice);
+}
+
+static void sim_read_cf_indicator(struct ofono_call_forwarding *cf)
+{
+	if (__ofono_sim_service_available(cf->sim,
+			SIM_UST_SERVICE_CFIS,
+			SIM_SST_SERVICE_CFIS) == TRUE)
+		ofono_sim_read(cf->sim, SIM_EFCFIS_FILEID,
+				OFONO_SIM_FILE_STRUCTURE_FIXED,
+				sim_cfis_read_cb, cf);
+	else
+		ofono_sim_read(cf->sim, SIM_EF_CPHS_CFF_FILEID,
+				OFONO_SIM_FILE_STRUCTURE_TRANSPARENT,
+				sim_cphs_cff_read_cb, cf);
+}
+
 int ofono_call_forwarding_driver_register(const struct ofono_call_forwarding_driver *d)
 {
 	DBG("driver: %p, name: %s", d, d->name);
@@ -1201,6 +1435,13 @@ struct ofono_call_forwarding *ofono_call_forwarding_create(struct ofono_modem *m
 	return cf;
 }
 
+static void modem_online_status_changed(ofono_bool_t online, void *data)
+{
+	struct ofono_call_forwarding *cf = data;
+
+	cf->online = online;
+}
+
 static void ussd_watch(struct ofono_atom *atom,
 			enum ofono_atom_watch_condition cond, void *data)
 {
@@ -1220,6 +1461,7 @@ void ofono_call_forwarding_register(struct ofono_call_forwarding *cf)
 	DBusConnection *conn = ofono_dbus_get_connection();
 	const char *path = __ofono_atom_get_path(cf->atom);
 	struct ofono_modem *modem = __ofono_atom_get_modem(cf->atom);
+	struct ofono_atom *sim_atom;
 	struct ofono_atom *ussd_atom;
 
 	if (!g_dbus_register_interface(conn, path,
@@ -1234,6 +1476,18 @@ void ofono_call_forwarding_register(struct ofono_call_forwarding *cf)
 
 	ofono_modem_add_interface(modem, OFONO_CALL_FORWARDING_INTERFACE);
 
+	sim_atom = __ofono_modem_find_atom(modem, OFONO_ATOM_TYPE_SIM);
+
+	if (sim_atom) {
+		cf->sim = __ofono_atom_get_data(sim_atom);
+
+		if (ofono_sim_get_state(cf->sim) == OFONO_SIM_STATE_READY)
+			sim_read_cf_indicator(cf);
+	}
+
+	__ofono_modem_add_online_watch(modem, modem_online_status_changed,
+					cf, NULL);
+
 	cf->ussd_watch = __ofono_modem_add_atom_watch(modem,
 					OFONO_ATOM_TYPE_USSD,
 					ussd_watch, cf, NULL);
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 2/7] ifx: Move call forwarding to post sim
  2010-11-29 10:37 Read/Write EFcfis/EFcphs-cff Jeevaka Badrappan
  2010-11-29 10:37 ` [PATCH 1/7] call-forwarding: Read/Write cfis/cphs-cff Jeevaka Badrappan
@ 2010-11-29 10:37 ` Jeevaka Badrappan
  2010-11-29 10:37 ` [PATCH 3/7] isigen: " Jeevaka Badrappan
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 16+ messages in thread
From: Jeevaka Badrappan @ 2010-11-29 10:37 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 1080 bytes --]

---
 plugins/ifx.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/plugins/ifx.c b/plugins/ifx.c
index 037273a..cd6e667 100644
--- a/plugins/ifx.c
+++ b/plugins/ifx.c
@@ -703,6 +703,7 @@ static void ifx_post_sim(struct ofono_modem *modem)
 	ofono_stk_create(modem, 0, "ifxmodem", data->dlcs[AUX_DLC]);
 	ofono_phonebook_create(modem, OFONO_VENDOR_IFX,
 					"atmodem", data->dlcs[AUX_DLC]);
+	ofono_call_forwarding_create(modem, 0, "atmodem", data->dlcs[AUX_DLC]);
 }
 
 static void ifx_post_online(struct ofono_modem *modem)
@@ -724,7 +725,6 @@ static void ifx_post_online(struct ofono_modem *modem)
 	ofono_ussd_create(modem, 0, "atmodem", data->dlcs[AUX_DLC]);
 
 	ofono_ssn_create(modem, 0, "atmodem", data->dlcs[AUX_DLC]);
-	ofono_call_forwarding_create(modem, 0, "atmodem", data->dlcs[AUX_DLC]);
 	ofono_call_settings_create(modem, 0, "atmodem", data->dlcs[AUX_DLC]);
 	ofono_call_meter_create(modem, 0, "atmodem", data->dlcs[AUX_DLC]);
 	ofono_call_barring_create(modem, 0, "atmodem", data->dlcs[AUX_DLC]);
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 3/7] isigen: Move call forwarding to post sim
  2010-11-29 10:37 Read/Write EFcfis/EFcphs-cff Jeevaka Badrappan
  2010-11-29 10:37 ` [PATCH 1/7] call-forwarding: Read/Write cfis/cphs-cff Jeevaka Badrappan
  2010-11-29 10:37 ` [PATCH 2/7] ifx: Move call forwarding to post sim Jeevaka Badrappan
@ 2010-11-29 10:37 ` Jeevaka Badrappan
  2010-11-29 10:38 ` [PATCH 4/7] plugins/n900: " Jeevaka Badrappan
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 16+ messages in thread
From: Jeevaka Badrappan @ 2010-11-29 10:37 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 1080 bytes --]

---
 plugins/isigen.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/plugins/isigen.c b/plugins/isigen.c
index 3384e9f..47f2553 100644
--- a/plugins/isigen.c
+++ b/plugins/isigen.c
@@ -402,6 +402,7 @@ static void isigen_post_sim(struct ofono_modem *modem)
 	DBG("(%p) with %s", modem, isi->ifname);
 
 	ofono_phonebook_create(isi->modem, 0, "isimodem", isi->idx);
+	ofono_call_forwarding_create(isi->modem, 0, "isimodem", isi->idx);
 }
 
 static void isigen_post_online(struct ofono_modem *modem)
@@ -418,7 +419,6 @@ static void isigen_post_online(struct ofono_modem *modem)
 	ofono_cbs_create(isi->modem, 0, "isimodem", isi->idx);
 	ofono_ssn_create(isi->modem, 0, "isimodem", isi->idx);
 	ofono_ussd_create(isi->modem, 0, "isimodem", isi->idx);
-	ofono_call_forwarding_create(isi->modem, 0, "isimodem", isi->idx);
 	ofono_call_settings_create(isi->modem, 0, "isimodem", isi->idx);
 	ofono_call_barring_create(isi->modem, 0, "isimodem", isi->idx);
 	ofono_call_meter_create(isi->modem, 0, "isimodem", isi->idx);
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 4/7] plugins/n900: Move call forwarding to post sim
  2010-11-29 10:37 Read/Write EFcfis/EFcphs-cff Jeevaka Badrappan
                   ` (2 preceding siblings ...)
  2010-11-29 10:37 ` [PATCH 3/7] isigen: " Jeevaka Badrappan
@ 2010-11-29 10:38 ` Jeevaka Badrappan
  2010-11-29 10:38 ` [PATCH 5/7] phonesim: " Jeevaka Badrappan
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 16+ messages in thread
From: Jeevaka Badrappan @ 2010-11-29 10:38 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 1032 bytes --]

---
 plugins/n900.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/plugins/n900.c b/plugins/n900.c
index a9e6b59..3f6aa39 100644
--- a/plugins/n900.c
+++ b/plugins/n900.c
@@ -491,6 +491,7 @@ static void n900_post_sim(struct ofono_modem *modem)
 	DBG("");
 
 	ofono_phonebook_create(isi->modem, 0, "isimodem", isi->idx);
+	ofono_call_forwarding_create(isi->modem, 0, "isimodem", isi->idx);
 }
 
 static void n900_post_online(struct ofono_modem *modem)
@@ -506,7 +507,6 @@ static void n900_post_online(struct ofono_modem *modem)
 	ofono_cbs_create(isi->modem, 0, "isimodem", isi->idx);
 	ofono_ssn_create(isi->modem, 0, "isimodem", isi->idx);
 	ofono_ussd_create(isi->modem, 0, "isimodem", isi->idx);
-	ofono_call_forwarding_create(isi->modem, 0, "isimodem", isi->idx);
 	ofono_call_settings_create(isi->modem, 0, "isimodem", isi->idx);
 	ofono_call_barring_create(isi->modem, 0, "isimodem", isi->idx);
 	ofono_call_meter_create(isi->modem, 0, "isimodem", isi->idx);
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 5/7] phonesim: Move call forwarding to post sim
  2010-11-29 10:37 Read/Write EFcfis/EFcphs-cff Jeevaka Badrappan
                   ` (3 preceding siblings ...)
  2010-11-29 10:38 ` [PATCH 4/7] plugins/n900: " Jeevaka Badrappan
@ 2010-11-29 10:38 ` Jeevaka Badrappan
  2010-11-29 10:38 ` [PATCH 6/7] doc: Add new property to call forwarding Jeevaka Badrappan
  2010-11-29 10:38 ` [PATCH 7/7] TODO: Marking the Read/Write EFcfis task as done Jeevaka Badrappan
  6 siblings, 0 replies; 16+ messages in thread
From: Jeevaka Badrappan @ 2010-11-29 10:38 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 879 bytes --]

---
 plugins/phonesim.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/plugins/phonesim.c b/plugins/phonesim.c
index d2faf42..e29d04d 100644
--- a/plugins/phonesim.c
+++ b/plugins/phonesim.c
@@ -470,6 +470,8 @@ static void phonesim_post_sim(struct ofono_modem *modem)
 	if (!data->calypso)
 		ofono_stk_create(modem, OFONO_VENDOR_PHONESIM,
 					"atmodem", data->chat);
+
+	ofono_call_forwarding_create(modem, 0, "atmodem", data->chat);
 }
 
 static void phonesim_post_online(struct ofono_modem *modem)
@@ -482,7 +484,6 @@ static void phonesim_post_online(struct ofono_modem *modem)
 	DBG("%p", modem);
 
 	ofono_ussd_create(modem, 0, "atmodem", data->chat);
-	ofono_call_forwarding_create(modem, 0, "atmodem", data->chat);
 	ofono_call_settings_create(modem, 0, "atmodem", data->chat);
 
 	if (data->calypso)
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 6/7] doc: Add new property to call forwarding
  2010-11-29 10:37 Read/Write EFcfis/EFcphs-cff Jeevaka Badrappan
                   ` (4 preceding siblings ...)
  2010-11-29 10:38 ` [PATCH 5/7] phonesim: " Jeevaka Badrappan
@ 2010-11-29 10:38 ` Jeevaka Badrappan
  2010-11-29 10:38 ` [PATCH 7/7] TODO: Marking the Read/Write EFcfis task as done Jeevaka Badrappan
  6 siblings, 0 replies; 16+ messages in thread
From: Jeevaka Badrappan @ 2010-11-29 10:38 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 574 bytes --]

---
 doc/call-forwarding-api.txt |    5 +++++
 1 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/doc/call-forwarding-api.txt b/doc/call-forwarding-api.txt
index 067531a..e8b4b9f 100644
--- a/doc/call-forwarding-api.txt
+++ b/doc/call-forwarding-api.txt
@@ -57,3 +57,8 @@ Properties	string VoiceUnconditional [readwrite]
 
 			Contains the value of the voice "Not Reachable" call
 			forwarding rule.
+
+		boolean ForwardingFlagOnSim [readonly]
+
+			Boolean representing the voice unconditional call
+			forwarding rule status.
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 7/7] TODO: Marking the Read/Write EFcfis task as done
  2010-11-29 10:37 Read/Write EFcfis/EFcphs-cff Jeevaka Badrappan
                   ` (5 preceding siblings ...)
  2010-11-29 10:38 ` [PATCH 6/7] doc: Add new property to call forwarding Jeevaka Badrappan
@ 2010-11-29 10:38 ` Jeevaka Badrappan
  6 siblings, 0 replies; 16+ messages in thread
From: Jeevaka Badrappan @ 2010-11-29 10:38 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 1560 bytes --]

---
 TODO             |    9 ---------
 doc/features.txt |    5 +++++
 2 files changed, 5 insertions(+), 9 deletions(-)

diff --git a/TODO b/TODO
index c484871..b33063a 100644
--- a/TODO
+++ b/TODO
@@ -92,15 +92,6 @@ SMS
 SIM / SIM File system
 =====================
 
-- Read / Write EFcfis.  Call forwarding settings can be bootstrapped on the
-  SIM for faster notification of the user that call forwarding is active.
-  These settings are stored in EFcfis.  oFono should read these settings and
-  update the call forwarding atom appropriately.
-
-  Priority: Low
-  Complexity: C2
-  Owner: Jeevaka Badrappan <jeevaka.badrappan@elektrobit.com>
-
 - SIM Call History plugin.  New UICCs support four new SIM elementary files
   for storing call history information on the SIM: EFici, EFict, EFoci, EFoct.
   A plugin should be developed for oFono that will write to these files.
diff --git a/doc/features.txt b/doc/features.txt
index 06f5203..0a90a70 100644
--- a/doc/features.txt
+++ b/doc/features.txt
@@ -209,6 +209,11 @@ SIM
   oFono halts the SIM initialization procedure and the modem remains in the
   PRESIM state.  In this state oFono will only allow emergency calls.
 
+- Read / Write EFcfis / EFcphs-cff.  oFono reads EFcfis/EFcphs-cff SIM files
+  to check if VoiceUnconditional call forwarding rule is enabled.  If enabled,
+  ForwardingFlagOnSim will be set and VoiceUnconditional may contain the
+  "forwarded to" number if the number is available.
+
 Radio settings
 ==============
 
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* Re: [PATCH 1/7] call-forwarding: Read/Write cfis/cphs-cff
  2010-11-29 10:37 ` [PATCH 1/7] call-forwarding: Read/Write cfis/cphs-cff Jeevaka Badrappan
@ 2010-12-03 19:08   ` Denis Kenzior
  2010-12-07 13:59     ` Jeevaka.Badrappan
  0 siblings, 1 reply; 16+ messages in thread
From: Denis Kenzior @ 2010-12-03 19:08 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 5249 bytes --]

Hi Jeevaka,

On 11/29/2010 04:37 AM, Jeevaka Badrappan wrote:
> ---
>  src/call-forwarding.c |  266 +++++++++++++++++++++++++++++++++++++++++++++++-
>  1 files changed, 260 insertions(+), 6 deletions(-)
> 
> diff --git a/src/call-forwarding.c b/src/call-forwarding.c
> index ce03c40..bb345a6 100644
> --- a/src/call-forwarding.c
> +++ b/src/call-forwarding.c
> @@ -34,6 +34,7 @@
>  #include "ofono.h"
>  
>  #include "common.h"
> +#include "simutil.h"
>  
>  #define CALL_FORWARDING_FLAG_CACHED 0x1
>  
> @@ -58,6 +59,12 @@ struct ofono_call_forwarding {
>  	int query_next;
>  	int query_end;
>  	struct cf_ss_request *ss_req;
> +	struct ofono_sim *sim;
> +	unsigned char cfis_record_id;
> +	unsigned char cfis_indicator;
> +	ofono_bool_t cphs_cff_present;
> +	ofono_bool_t status_on_sim;
> +	ofono_bool_t online;

Why do you need to track this variable?  Can't you simply call
ofono_modem_get_online()?

>  	struct ofono_ussd *ussd;
>  	unsigned int ussd_watch;
>  	const struct ofono_call_forwarding_driver *driver;

<snip>

> @@ -372,6 +458,7 @@ static DBusMessage *cf_get_properties_reply(DBusMessage *msg,
>  	DBusMessageIter iter;
>  	DBusMessageIter dict;
>  	int i;
> +	dbus_bool_t status;
>  
>  	reply = dbus_message_new_method_return(msg);
>  
> @@ -384,10 +471,21 @@ static DBusMessage *cf_get_properties_reply(DBusMessage *msg,
>  					OFONO_PROPERTIES_ARRAY_SIGNATURE,
>  						&dict);
>  
> -	for (i = 0; i < 4; i++)
> -		property_append_cf_conditions(&dict, cf->cf_conditions[i],
> +	if (cf->online == TRUE) {

So I'm really confused by this one, if we're offline and haven't managed
to query the conditions, just return them.  They will be all empty with
the possible exception of VoiceUnconditional

> +		for (i = 0; i < 4; i++)
> +			property_append_cf_conditions(&dict,
> +						cf->cf_conditions[i],
>  						BEARER_CLASS_VOICE,
>  						cf_type_lut[i]);
> +	} else if (cf->status_on_sim == TRUE)
> +		property_append_cf_conditions(&dict,
> +			cf->cf_conditions[CALL_FORWARDING_TYPE_UNCONDITIONAL],
> +			BEARER_CLASS_VOICE,
> +			cf_type_lut[CALL_FORWARDING_TYPE_UNCONDITIONAL]);
> +
> +	status = cf->status_on_sim;
> +	ofono_dbus_dict_append(&dict, "ForwardingFlagOnSim", DBUS_TYPE_BOOLEAN,
> +					&status);
>  
>  	dbus_message_iter_close_container(&iter, &dict);
>  

<snip>

> @@ -433,7 +539,8 @@ static DBusMessage *cf_get_properties(DBusConnection *conn, DBusMessage *msg,
>  {
>  	struct ofono_call_forwarding *cf = data;
>  
> -	if (cf->flags & CALL_FORWARDING_FLAG_CACHED)
> +	if ((cf->flags & CALL_FORWARDING_FLAG_CACHED) ||
> +			cf->online == FALSE)

Why do you split this on two lines? Are you sure it won't fit on one?

>  		return cf_get_properties_reply(msg, cf);
>  
>  	if (!cf->driver->query)
> @@ -536,7 +643,8 @@ static void set_query_cf_callback(const struct ofono_error *error, int total,
>  	if (cf->query_next != cf->query_end) {
>  		cf->query_next++;
>  		set_query_next_cf_cond(cf);
> -	}
> +	} else
> +		sim_set_cf_indicator(cf);

Should we do this only if we actually queried the set that includes
unconditional?

>  }
>  
>  static void set_query_next_cf_cond(struct ofono_call_forwarding *cf)
> @@ -597,6 +705,9 @@ static DBusMessage *cf_set_property(DBusConnection *conn, DBusMessage *msg,
>  	int cls;
>  	int type;
>  
> +	if (cf->online == FALSE)
> +		return __ofono_error_not_available(msg);
> +
>  	if (__ofono_call_forwarding_is_busy(cf) ||
>  			__ofono_ussd_is_busy(cf->ussd))
>  		return __ofono_error_busy(msg);
> @@ -864,7 +975,8 @@ static void ss_set_query_cf_callback(const struct ofono_error *error, int total,
>  	if (cf->query_next != cf->query_end) {
>  		cf->query_next++;
>  		ss_set_query_next_cf_cond(cf);
> -	}
> +	} else
> +		sim_set_cf_indicator(cf);

Should we do this only if we actually queried the set that includes
unconditional?

>  }
>  
>  static void ss_set_query_next_cf_cond(struct ofono_call_forwarding *cf)

<snip>

> @@ -1220,6 +1461,7 @@ void ofono_call_forwarding_register(struct ofono_call_forwarding *cf)
>  	DBusConnection *conn = ofono_dbus_get_connection();
>  	const char *path = __ofono_atom_get_path(cf->atom);
>  	struct ofono_modem *modem = __ofono_atom_get_modem(cf->atom);
> +	struct ofono_atom *sim_atom;
>  	struct ofono_atom *ussd_atom;
>  
>  	if (!g_dbus_register_interface(conn, path,
> @@ -1234,6 +1476,18 @@ void ofono_call_forwarding_register(struct ofono_call_forwarding *cf)
>  
>  	ofono_modem_add_interface(modem, OFONO_CALL_FORWARDING_INTERFACE);
>  
> +	sim_atom = __ofono_modem_find_atom(modem, OFONO_ATOM_TYPE_SIM);
> +
> +	if (sim_atom) {
> +		cf->sim = __ofono_atom_get_data(sim_atom);
> +
> +		if (ofono_sim_get_state(cf->sim) == OFONO_SIM_STATE_READY)

This check can be skipped, we're always in post_sim state.  The only way
to get there is if we reached OFONO_SIM_STATE_READY

> +			sim_read_cf_indicator(cf);
> +	}
> +
> +	__ofono_modem_add_online_watch(modem, modem_online_status_changed,
> +					cf, NULL);
> +
>  	cf->ussd_watch = __ofono_modem_add_atom_watch(modem,
>  					OFONO_ATOM_TYPE_USSD,
>  					ussd_watch, cf, NULL);

Regards,
-Denis

^ permalink raw reply	[flat|nested] 16+ messages in thread

* RE: [PATCH 1/7] call-forwarding: Read/Write cfis/cphs-cff
  2010-12-03 19:08   ` Denis Kenzior
@ 2010-12-07 13:59     ` Jeevaka.Badrappan
  2010-12-07 18:41       ` Denis Kenzior
  0 siblings, 1 reply; 16+ messages in thread
From: Jeevaka.Badrappan @ 2010-12-07 13:59 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 258 bytes --]

Hi Denis,
 
> > +	ofono_bool_t online;
> 
> Why do you need to track this variable?  Can't you simply 
> call ofono_modem_get_online()?
> 

This way calling of ofono_modem_get_online for each get or set request
can be avoided.

Regards,
Jeevaka

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 1/7] call-forwarding: Read/Write cfis/cphs-cff
  2010-12-07 13:59     ` Jeevaka.Badrappan
@ 2010-12-07 18:41       ` Denis Kenzior
  0 siblings, 0 replies; 16+ messages in thread
From: Denis Kenzior @ 2010-12-07 18:41 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 478 bytes --]

Hi Jeevaka,

On 12/07/2010 07:59 AM, Jeevaka.Badrappan(a)elektrobit.com wrote:
> Hi Denis,
>  
>>> +	ofono_bool_t online;
>>
>> Why do you need to track this variable?  Can't you simply 
>> call ofono_modem_get_online()?
>>
> 
> This way calling of ofono_modem_get_online for each get or set request
> can be avoided.
> 

Sure, but it is doubtful you really need to 'optimize' those cases.  The
code is way cleaner without it in my opinion.

Regards,
-Denis

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 1/7] call-forwarding: Read/Write cfis/cphs-cff
  2010-12-17  7:04   ` Jeevaka Badrappan
@ 2010-12-17 23:16     ` Denis Kenzior
  0 siblings, 0 replies; 16+ messages in thread
From: Denis Kenzior @ 2010-12-17 23:16 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 911 bytes --]

Hi Jeevaka,

On 12/17/2010 01:04 AM, Jeevaka Badrappan wrote:
> ---
>  src/call-forwarding.c |  243 ++++++++++++++++++++++++++++++++++++++++++++++++-
>  1 files changed, 241 insertions(+), 2 deletions(-)
> 

So I applied this patch but refactored it very heavily afterward.  Can
you do review the changes and make sure you're OK with them?  Can you
also submit the needed records for phonesim, so we can get those tested
as well?

I still have one concern with cfis_record_id selection logic.  There are
a couple of possibilities we might not be handling correctly:

- if no EFcfis records contain proper MSP ids
- if EFcfis record has a valid MSP id, but is relevant to teleservices
besides voice.  We still potentially select this record, even though a
voice specific record might or might not exist.

Overall I think we need to test this feature quite a bit more...

Regards,
-Denis

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH 1/7] call-forwarding: Read/Write cfis/cphs-cff
  2010-12-10 18:56 ` [PATCH 1/7] call-forwarding: Read/Write cfis/cphs-cff Jeevaka Badrappan
@ 2010-12-17  7:04   ` Jeevaka Badrappan
  2010-12-17 23:16     ` Denis Kenzior
  0 siblings, 1 reply; 16+ messages in thread
From: Jeevaka Badrappan @ 2010-12-17  7:04 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 10978 bytes --]

---
 src/call-forwarding.c |  243 ++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 241 insertions(+), 2 deletions(-)

diff --git a/src/call-forwarding.c b/src/call-forwarding.c
index bb8aa37..ed67b21 100644
--- a/src/call-forwarding.c
+++ b/src/call-forwarding.c
@@ -34,6 +34,7 @@
 #include "ofono.h"
 
 #include "common.h"
+#include "simutil.h"
 
 #define CALL_FORWARDING_FLAG_CACHED 0x1
 
@@ -58,6 +59,11 @@ struct ofono_call_forwarding {
 	int query_next;
 	int query_end;
 	struct cf_ss_request *ss_req;
+	struct ofono_sim *sim;
+	unsigned char cfis_record_id;
+	unsigned char cfis_indicator;
+	ofono_bool_t cphs_cff_present;
+	ofono_bool_t status_on_sim;
 	struct ofono_ussd *ussd;
 	unsigned int ussd_watch;
 	const struct ofono_call_forwarding_driver *driver;
@@ -202,6 +208,83 @@ static const char *cf_type_lut[] = {
 	"AllConditional"
 };
 
+static void sim_cfis_update_cb(int ok, void *data)
+{
+	if (!ok)
+		ofono_info("Failed to update EFcfis");
+}
+
+static void sim_cphs_cff_update_cb(int ok, void *data)
+{
+	if (!ok)
+		ofono_info("Failed to update EFcphs-cff");
+}
+
+static void sim_set_cf_indicator(struct ofono_call_forwarding *cf)
+{
+	gboolean cfu_voice = FALSE;
+	struct ofono_call_forwarding_condition *cond = NULL;
+	GSList *l;
+	const char *number = NULL;
+
+	/*
+	 * For now we only support Voice, although Fax & all Data
+	 * basic services are applicable as well.
+	 */
+	for (l = cf->cf_conditions[0]; l; l = l->next) {
+		cond = l->data;
+
+		if ((cond->cls & BEARER_CLASS_VOICE) &&
+				(strlen(cond->phone_number.number) > 0)) {
+			number = phone_number_to_string(&cond->phone_number);
+			cfu_voice = TRUE;
+			break;
+		}
+	}
+
+	cf->status_on_sim = cfu_voice;
+
+	if (cf->cfis_record_id) {
+		unsigned char data[16];
+		int number_len;
+
+		memset(data, 0xff, sizeof(data));
+
+		/* Profile Identifier */
+		data[0] = 0x01;
+
+		if (cfu_voice) {
+			number_len = strlen(cond->phone_number.number);
+
+			/* CFU indicator Status - Voice */
+			data[1] = (cf->cfis_indicator |= 0x01);
+			number_len = (number_len + 1) / 2;
+			data[2] = number_len + 1;
+			data[3] = cond->phone_number.type;
+
+			sim_encode_bcd_number(cond->phone_number.number,
+						data + 4);
+		} else
+			data[1] = (cf->cfis_indicator &= 0xFE);
+
+		ofono_sim_write(cf->sim, SIM_EFCFIS_FILEID,
+					sim_cfis_update_cb,
+					OFONO_SIM_FILE_STRUCTURE_FIXED,
+					cf->cfis_record_id, data,
+					sizeof(data), cf);
+		return;
+	}
+
+	if (cf->cphs_cff_present) {
+		unsigned char cff_voice = cfu_voice ? 0x0A : 0x05;
+
+		ofono_sim_write(cf->sim, SIM_EF_CPHS_CFF_FILEID,
+					sim_cphs_cff_update_cb,
+					OFONO_SIM_FILE_STRUCTURE_TRANSPARENT,
+					0, &cff_voice, sizeof(cff_voice), cf);
+	}
+}
+
 static void set_new_cond_list(struct ofono_call_forwarding *cf,
 				int type, GSList *list)
 {
@@ -216,6 +299,7 @@ static void set_new_cond_list(struct ofono_call_forwarding *cf,
 	dbus_uint16_t timeout;
 	char attr[64];
 	char tattr[64];
+	gboolean update_sim = FALSE;
 
 	for (l = list; l; l = l->next) {
 		lc = l->data;
@@ -246,12 +330,16 @@ static void set_new_cond_list(struct ofono_call_forwarding *cf,
 
 			if (oc->phone_number.type != lc->phone_number.type ||
 				strcmp(oc->phone_number.number,
-					lc->phone_number.number))
+					lc->phone_number.number)) {
 				ofono_dbus_signal_property_changed(conn, path,
 						OFONO_CALL_FORWARDING_INTERFACE,
 						attr, DBUS_TYPE_STRING,
 						&number);
 
+				if (type == CALL_FORWARDING_TYPE_UNCONDITIONAL)
+					update_sim = TRUE;
+			}
+
 			if (type == CALL_FORWARDING_TYPE_NO_REPLY &&
 				oc->time != lc->time)
 				ofono_dbus_signal_property_changed(conn, path,
@@ -270,6 +358,9 @@ static void set_new_cond_list(struct ofono_call_forwarding *cf,
 						attr, DBUS_TYPE_STRING,
 						&number);
 
+			if (type == CALL_FORWARDING_TYPE_UNCONDITIONAL)
+				update_sim = TRUE;
+
 			if (type == CALL_FORWARDING_TYPE_NO_REPLY &&
 				lc->time != DEFAULT_NO_REPLY_TIMEOUT)
 				ofono_dbus_signal_property_changed(conn, path,
@@ -302,6 +393,9 @@ static void set_new_cond_list(struct ofono_call_forwarding *cf,
 					OFONO_CALL_FORWARDING_INTERFACE, attr,
 					DBUS_TYPE_STRING, &number);
 
+		if (type == CALL_FORWARDING_TYPE_UNCONDITIONAL)
+			update_sim = TRUE;
+
 		if (type == CALL_FORWARDING_TYPE_NO_REPLY &&
 			oc->time != DEFAULT_NO_REPLY_TIMEOUT)
 			ofono_dbus_signal_property_changed(conn, path,
@@ -312,6 +406,9 @@ static void set_new_cond_list(struct ofono_call_forwarding *cf,
 
 	cf_list_clear(old);
 	cf->cf_conditions[type] = list;
+
+	if (update_sim == TRUE)
+		sim_set_cf_indicator(cf);
 }
 
 static inline void property_append_cf_condition(DBusMessageIter *dict, int cls,
@@ -372,6 +469,7 @@ static DBusMessage *cf_get_properties_reply(DBusMessage *msg,
 	DBusMessageIter iter;
 	DBusMessageIter dict;
 	int i;
+	dbus_bool_t status;
 
 	reply = dbus_message_new_method_return(msg);
 	if (reply == NULL)
@@ -388,6 +486,10 @@ static DBusMessage *cf_get_properties_reply(DBusMessage *msg,
 						BEARER_CLASS_VOICE,
 						cf_type_lut[i]);
 
+	status = cf->status_on_sim;
+	ofono_dbus_dict_append(&dict, "ForwardingFlagOnSim", DBUS_TYPE_BOOLEAN,
+					&status);
+
 	dbus_message_iter_close_container(&iter, &dict);
 
 	return reply;
@@ -431,8 +533,10 @@ static DBusMessage *cf_get_properties(DBusConnection *conn, DBusMessage *msg,
 					void *data)
 {
 	struct ofono_call_forwarding *cf = data;
+	struct ofono_modem *modem = __ofono_atom_get_modem(cf->atom);
 
-	if (cf->flags & CALL_FORWARDING_FLAG_CACHED)
+	if ((cf->flags & CALL_FORWARDING_FLAG_CACHED) ||
+			ofono_modem_get_online(modem) == FALSE)
 		return cf_get_properties_reply(msg, cf);
 
 	if (cf->driver->query == NULL)
@@ -590,12 +694,16 @@ static DBusMessage *cf_set_property(DBusConnection *conn, DBusMessage *msg,
 					void *data)
 {
 	struct ofono_call_forwarding *cf = data;
+	struct ofono_modem *modem = __ofono_atom_get_modem(cf->atom);
 	DBusMessageIter iter;
 	DBusMessageIter var;
 	const char *property;
 	int cls;
 	int type;
 
+	if (ofono_modem_get_online(modem) == FALSE)
+		return __ofono_error_not_available(msg);
+
 	if (__ofono_call_forwarding_is_busy(cf) ||
 			__ofono_ussd_is_busy(cf->ussd))
 		return __ofono_error_busy(msg);
@@ -1111,6 +1219,128 @@ gboolean __ofono_call_forwarding_is_busy(struct ofono_call_forwarding *cf)
 	return cf->pending ? TRUE : FALSE;
 }
 
+static void sim_cfis_read_cb(int ok, int total_length, int record,
+			const unsigned char *data,
+			int record_length, void *userdata)
+{
+	struct ofono_call_forwarding *cf = userdata;
+	DBusConnection *conn = ofono_dbus_get_connection();
+	const char *path = __ofono_atom_get_path(cf->atom);
+
+	if (!ok || record_length < 16 || total_length < record_length) {
+		cf->cfis_indicator = 0;
+		cf->cfis_record_id = 0;
+		return;
+	}
+
+	/*
+	 * Multiple Subscriber Profile number which can have values 1-4.
+	 * Profile id 1 is assumed as the current profile.
+	 */
+	if (data[0] != 1)
+		return;
+
+	cf->cfis_record_id = record;
+
+	/* CFU indicator status */
+	cf->cfis_indicator = data[1];
+
+	/*
+	 * For now we only support Voice, although Fax & all Data
+	 * basic services are applicable as well.
+	 */
+	if (cf->cfis_indicator & 0x01) {
+		int ton_npi;
+		int number_len;
+		const char *number;
+		char attr[64];
+		struct ofono_call_forwarding_condition *cond;
+		GSList *l = NULL;
+		dbus_bool_t status;
+
+		number_len = data[2];
+		ton_npi = data[3];
+
+		if (number_len > 11 || ton_npi == 0xff)
+			return;
+
+		cond = g_try_new0(struct ofono_call_forwarding_condition, 1);
+		if (cond == NULL)
+			return;
+
+		status = cf->status_on_sim = TRUE;
+		cond->status = status;
+		cond->cls = BEARER_CLASS_VOICE;
+		cond->time = 0;
+		cond->phone_number.type = ton_npi;
+
+		sim_extract_bcd_number(data + 4, number_len - 1,
+					cond->phone_number.number);
+		number = phone_number_to_string(&cond->phone_number);
+
+		snprintf(attr, sizeof(attr), "%s%s",
+			bearer_class_to_string(BEARER_CLASS_VOICE),
+			cf_type_lut[CALL_FORWARDING_TYPE_UNCONDITIONAL]);
+
+		cf->cf_conditions[CALL_FORWARDING_TYPE_UNCONDITIONAL] =
+							g_slist_append(l, cond);
+
+		ofono_dbus_signal_property_changed(conn, path,
+				OFONO_CALL_FORWARDING_INTERFACE,
+				attr, DBUS_TYPE_STRING,
+				&number);
+
+		ofono_dbus_signal_property_changed(conn, path,
+				OFONO_CALL_FORWARDING_INTERFACE,
+				"ForwardingFlagOnSim",
+				DBUS_TYPE_BOOLEAN,
+				&status);
+	}
+}
+
+static void sim_cphs_cff_read_cb(int ok, int total_length, int record,
+				const unsigned char *data,
+				int record_length, void *userdata)
+{
+	struct ofono_call_forwarding *cf = userdata;
+	DBusConnection *conn = ofono_dbus_get_connection();
+	const char *path = __ofono_atom_get_path(cf->atom);
+	dbus_bool_t cfu_voice;
+
+	if (!ok || total_length < 1) {
+		cf->cphs_cff_present = FALSE;
+		return;
+	}
+
+	cf->cphs_cff_present = TRUE;
+
+	/*
+	 * For now we only support Voice, although Fax & all Data
+	 * basic services are applicable as well.
+	 */
+	cfu_voice = cf->status_on_sim = ((data[0] & 0xf) == 0xa);
+
+	ofono_dbus_signal_property_changed(conn, path,
+					OFONO_CALL_FORWARDING_INTERFACE,
+					"ForwardingFlagOnSim",
+					DBUS_TYPE_BOOLEAN,
+					&cfu_voice);
+}
+
+static void sim_read_cf_indicator(struct ofono_call_forwarding *cf)
+{
+	if (__ofono_sim_service_available(cf->sim,
+			SIM_UST_SERVICE_CFIS,
+			SIM_SST_SERVICE_CFIS) == TRUE)
+		ofono_sim_read(cf->sim, SIM_EFCFIS_FILEID,
+				OFONO_SIM_FILE_STRUCTURE_FIXED,
+				sim_cfis_read_cb, cf);
+	else
+		ofono_sim_read(cf->sim, SIM_EF_CPHS_CFF_FILEID,
+				OFONO_SIM_FILE_STRUCTURE_TRANSPARENT,
+				sim_cphs_cff_read_cb, cf);
+}
+
 int ofono_call_forwarding_driver_register(const struct ofono_call_forwarding_driver *d)
 {
 	DBG("driver: %p, name: %s", d, d->name);
@@ -1219,6 +1449,7 @@ void ofono_call_forwarding_register(struct ofono_call_forwarding *cf)
 	DBusConnection *conn = ofono_dbus_get_connection();
 	const char *path = __ofono_atom_get_path(cf->atom);
 	struct ofono_modem *modem = __ofono_atom_get_modem(cf->atom);
+	struct ofono_atom *sim_atom;
 	struct ofono_atom *ussd_atom;
 
 	if (!g_dbus_register_interface(conn, path,
@@ -1233,6 +1464,14 @@ void ofono_call_forwarding_register(struct ofono_call_forwarding *cf)
 
 	ofono_modem_add_interface(modem, OFONO_CALL_FORWARDING_INTERFACE);
 
+	sim_atom = __ofono_modem_find_atom(modem, OFONO_ATOM_TYPE_SIM);
+
+	if (sim_atom) {
+		cf->sim = __ofono_atom_get_data(sim_atom);
+
+		sim_read_cf_indicator(cf);
+	}
+
 	cf->ussd_watch = __ofono_modem_add_atom_watch(modem,
 					OFONO_ATOM_TYPE_USSD,
 					ussd_watch, cf, NULL);
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 1/7] call-forwarding: Read/Write cfis/cphs-cff
  2010-12-10 18:56 Read/Write EFcfis/EFcphs-cff files-v4 Jeevaka Badrappan
@ 2010-12-10 18:56 ` Jeevaka Badrappan
  2010-12-17  7:04   ` Jeevaka Badrappan
  0 siblings, 1 reply; 16+ messages in thread
From: Jeevaka Badrappan @ 2010-12-10 18:56 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 9918 bytes --]

---
 src/call-forwarding.c |  246 ++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 245 insertions(+), 1 deletions(-)

diff --git a/src/call-forwarding.c b/src/call-forwarding.c
index bb8aa37..69427a8 100644
--- a/src/call-forwarding.c
+++ b/src/call-forwarding.c
@@ -34,6 +34,7 @@
 #include "ofono.h"
 
 #include "common.h"
+#include "simutil.h"
 
 #define CALL_FORWARDING_FLAG_CACHED 0x1
 
@@ -58,6 +59,12 @@ struct ofono_call_forwarding {
 	int query_next;
 	int query_end;
 	struct cf_ss_request *ss_req;
+	struct ofono_sim *sim;
+	unsigned char cfis_record_id;
+	unsigned char cfis_indicator;
+	char *cfu_number;
+	ofono_bool_t cphs_cff_present;
+	ofono_bool_t status_on_sim;
 	struct ofono_ussd *ussd;
 	unsigned int ussd_watch;
 	const struct ofono_call_forwarding_driver *driver;
@@ -202,6 +209,94 @@ static const char *cf_type_lut[] = {
 	"AllConditional"
 };
 
+static void sim_cfis_update_cb(int ok, void *data)
+{
+	if (!ok)
+		ofono_info("Failed to update EFcfis");
+}
+
+static void sim_cphs_cff_update_cb(int ok, void *data)
+{
+	if (!ok)
+		ofono_info("Failed to update EFcphs-cff");
+}
+
+static void sim_set_cf_indicator(struct ofono_call_forwarding *cf)
+{
+	gboolean cfu_voice = FALSE;
+	struct ofono_call_forwarding_condition *cond = NULL;
+	GSList *l;
+	const char *number = NULL;
+
+	/*
+	 * For now we only support Voice, although Fax & all Data
+	 * basic services are applicable as well.
+	 */
+	for (l = cf->cf_conditions[0]; l; l = l->next) {
+		cond = l->data;
+
+		if ((cond->cls & BEARER_CLASS_VOICE) &&
+				(strlen(cond->phone_number.number) > 0)) {
+			number = phone_number_to_string(&cond->phone_number);
+			cfu_voice = TRUE;
+			break;
+		}
+	}
+
+	if (cfu_voice == cf->status_on_sim &&
+			!g_strcmp0(number, cf->cfu_number))
+		return;
+
+	cf->status_on_sim = cfu_voice;
+
+	if (cf->cfis_record_id) {
+		unsigned char data[16];
+		int number_len;
+
+		memset(data, 0xff, sizeof(data));
+
+		/* Profile Identifier */
+		data[0] = 0x01;
+
+		if (cfu_voice) {
+			number_len = strlen(cond->phone_number.number);
+
+			/* CFU indicator Status - Voice */
+			data[1] = (cf->cfis_indicator |= 0x01);
+			number_len = (number_len + 1) / 2;
+			data[2] = number_len + 1;
+			data[3] = cond->phone_number.type;
+
+			g_free(cf->cfu_number);
+			cf->cfu_number = g_strdup(number);
+
+			sim_encode_bcd_number(cond->phone_number.number,
+						data + 4);
+		} else {
+			data[1] = (cf->cfis_indicator &= 0xFE);
+
+			g_free(cf->cfu_number);
+			cf->cfu_number = NULL;
+		}
+
+		ofono_sim_write(cf->sim, SIM_EFCFIS_FILEID,
+					sim_cfis_update_cb,
+					OFONO_SIM_FILE_STRUCTURE_FIXED,
+					cf->cfis_record_id, data,
+					sizeof(data), cf);
+		return;
+	}
+
+	if (cf->cphs_cff_present) {
+		unsigned char cff_voice = cfu_voice ? 0x0A : 0x05;
+
+		ofono_sim_write(cf->sim, SIM_EF_CPHS_CFF_FILEID,
+					sim_cphs_cff_update_cb,
+					OFONO_SIM_FILE_STRUCTURE_TRANSPARENT,
+					0, &cff_voice, sizeof(cff_voice), cf);
+	}
+}
+
 static void set_new_cond_list(struct ofono_call_forwarding *cf,
 				int type, GSList *list)
 {
@@ -312,6 +407,9 @@ static void set_new_cond_list(struct ofono_call_forwarding *cf,
 
 	cf_list_clear(old);
 	cf->cf_conditions[type] = list;
+
+	if (cf->query_next == CALL_FORWARDING_TYPE_UNCONDITIONAL)
+		sim_set_cf_indicator(cf);
 }
 
 static inline void property_append_cf_condition(DBusMessageIter *dict, int cls,
@@ -372,6 +470,7 @@ static DBusMessage *cf_get_properties_reply(DBusMessage *msg,
 	DBusMessageIter iter;
 	DBusMessageIter dict;
 	int i;
+	dbus_bool_t status;
 
 	reply = dbus_message_new_method_return(msg);
 	if (reply == NULL)
@@ -388,6 +487,10 @@ static DBusMessage *cf_get_properties_reply(DBusMessage *msg,
 						BEARER_CLASS_VOICE,
 						cf_type_lut[i]);
 
+	status = cf->status_on_sim;
+	ofono_dbus_dict_append(&dict, "ForwardingFlagOnSim", DBUS_TYPE_BOOLEAN,
+					&status);
+
 	dbus_message_iter_close_container(&iter, &dict);
 
 	return reply;
@@ -431,8 +534,10 @@ static DBusMessage *cf_get_properties(DBusConnection *conn, DBusMessage *msg,
 					void *data)
 {
 	struct ofono_call_forwarding *cf = data;
+	struct ofono_modem *modem = __ofono_atom_get_modem(cf->atom);
 
-	if (cf->flags & CALL_FORWARDING_FLAG_CACHED)
+	if ((cf->flags & CALL_FORWARDING_FLAG_CACHED) ||
+			ofono_modem_get_online(modem) == FALSE)
 		return cf_get_properties_reply(msg, cf);
 
 	if (cf->driver->query == NULL)
@@ -590,12 +695,16 @@ static DBusMessage *cf_set_property(DBusConnection *conn, DBusMessage *msg,
 					void *data)
 {
 	struct ofono_call_forwarding *cf = data;
+	struct ofono_modem *modem = __ofono_atom_get_modem(cf->atom);
 	DBusMessageIter iter;
 	DBusMessageIter var;
 	const char *property;
 	int cls;
 	int type;
 
+	if (ofono_modem_get_online(modem) == FALSE)
+		return __ofono_error_not_available(msg);
+
 	if (__ofono_call_forwarding_is_busy(cf) ||
 			__ofono_ussd_is_busy(cf->ussd))
 		return __ofono_error_busy(msg);
@@ -1111,6 +1220,130 @@ gboolean __ofono_call_forwarding_is_busy(struct ofono_call_forwarding *cf)
 	return cf->pending ? TRUE : FALSE;
 }
 
+static void sim_cfis_read_cb(int ok, int total_length, int record,
+			const unsigned char *data,
+			int record_length, void *userdata)
+{
+	struct ofono_call_forwarding *cf = userdata;
+	DBusConnection *conn = ofono_dbus_get_connection();
+	const char *path = __ofono_atom_get_path(cf->atom);
+
+	if (!ok || record_length < 16 || total_length < record_length) {
+		cf->cfis_indicator = 0;
+		cf->cfis_record_id = 0;
+		return;
+	}
+
+	/*
+	 * Multiple Subscriber Profile number which can have values 1-4.
+	 * Profile id 1 is assumed as the current profile.
+	 */
+	if (data[0] != 1)
+		return;
+
+	cf->cfis_record_id = record;
+
+	/* CFU indicator status */
+	cf->cfis_indicator = data[1];
+
+	/*
+	 * For now we only support Voice, although Fax & all Data
+	 * basic services are applicable as well.
+	 */
+	if (cf->cfis_indicator & 0x01) {
+		int ton_npi;
+		int number_len;
+		const char *number;
+		char attr[64];
+		struct ofono_call_forwarding_condition *cond;
+		GSList *l = NULL;
+		dbus_bool_t status;
+
+		number_len = data[2];
+		ton_npi = data[3];
+
+		if (number_len > 11 || ton_npi == 0xff)
+			return;
+
+		cond = g_try_new0(struct ofono_call_forwarding_condition, 1);
+		if (cond == NULL)
+			return;
+
+		status = cf->status_on_sim = TRUE;
+		cond->status = status;
+		cond->cls = BEARER_CLASS_VOICE;
+		cond->time = 0;
+		cond->phone_number.type = ton_npi;
+
+		sim_extract_bcd_number(data + 4, number_len - 1,
+					cond->phone_number.number);
+		number = phone_number_to_string(&cond->phone_number);
+
+		cf->cfu_number = g_strdup(number);
+
+		snprintf(attr, sizeof(attr), "%s%s",
+			bearer_class_to_string(BEARER_CLASS_VOICE),
+			cf_type_lut[CALL_FORWARDING_TYPE_UNCONDITIONAL]);
+
+		cf->cf_conditions[CALL_FORWARDING_TYPE_UNCONDITIONAL] =
+							g_slist_append(l, cond);
+
+		ofono_dbus_signal_property_changed(conn, path,
+				OFONO_CALL_FORWARDING_INTERFACE,
+				attr, DBUS_TYPE_STRING,
+				&number);
+
+		ofono_dbus_signal_property_changed(conn, path,
+				OFONO_CALL_FORWARDING_INTERFACE,
+				"ForwardingFlagOnSim",
+				DBUS_TYPE_BOOLEAN,
+				&status);
+	}
+}
+
+static void sim_cphs_cff_read_cb(int ok, int total_length, int record,
+				const unsigned char *data,
+				int record_length, void *userdata)
+{
+	struct ofono_call_forwarding *cf = userdata;
+	DBusConnection *conn = ofono_dbus_get_connection();
+	const char *path = __ofono_atom_get_path(cf->atom);
+	dbus_bool_t cfu_voice;
+
+	if (!ok || total_length < 1) {
+		cf->cphs_cff_present = FALSE;
+		return;
+	}
+
+	cf->cphs_cff_present = TRUE;
+
+	/*
+	 * For now we only support Voice, although Fax & all Data
+	 * basic services are applicable as well.
+	 */
+	cfu_voice = cf->status_on_sim = ((data[0] & 0xf) == 0xa);
+
+	ofono_dbus_signal_property_changed(conn, path,
+					OFONO_CALL_FORWARDING_INTERFACE,
+					"ForwardingFlagOnSim",
+					DBUS_TYPE_BOOLEAN,
+					&cfu_voice);
+}
+
+static void sim_read_cf_indicator(struct ofono_call_forwarding *cf)
+{
+	if (__ofono_sim_service_available(cf->sim,
+			SIM_UST_SERVICE_CFIS,
+			SIM_SST_SERVICE_CFIS) == TRUE)
+		ofono_sim_read(cf->sim, SIM_EFCFIS_FILEID,
+				OFONO_SIM_FILE_STRUCTURE_FIXED,
+				sim_cfis_read_cb, cf);
+	else
+		ofono_sim_read(cf->sim, SIM_EF_CPHS_CFF_FILEID,
+				OFONO_SIM_FILE_STRUCTURE_TRANSPARENT,
+				sim_cphs_cff_read_cb, cf);
+}
+
 int ofono_call_forwarding_driver_register(const struct ofono_call_forwarding_driver *d)
 {
 	DBG("driver: %p, name: %s", d, d->name);
@@ -1160,6 +1393,8 @@ static void call_forwarding_remove(struct ofono_atom *atom)
 	if (cf->driver && cf->driver->remove)
 		cf->driver->remove(cf);
 
+	g_free(cf->cfu_number);
+
 	cf_clear_all(cf);
 
 	g_free(cf);
@@ -1219,6 +1454,7 @@ void ofono_call_forwarding_register(struct ofono_call_forwarding *cf)
 	DBusConnection *conn = ofono_dbus_get_connection();
 	const char *path = __ofono_atom_get_path(cf->atom);
 	struct ofono_modem *modem = __ofono_atom_get_modem(cf->atom);
+	struct ofono_atom *sim_atom;
 	struct ofono_atom *ussd_atom;
 
 	if (!g_dbus_register_interface(conn, path,
@@ -1233,6 +1469,14 @@ void ofono_call_forwarding_register(struct ofono_call_forwarding *cf)
 
 	ofono_modem_add_interface(modem, OFONO_CALL_FORWARDING_INTERFACE);
 
+	sim_atom = __ofono_modem_find_atom(modem, OFONO_ATOM_TYPE_SIM);
+
+	if (sim_atom) {
+		cf->sim = __ofono_atom_get_data(sim_atom);
+
+		sim_read_cf_indicator(cf);
+	}
+
 	cf->ussd_watch = __ofono_modem_add_atom_watch(modem,
 					OFONO_ATOM_TYPE_USSD,
 					ussd_watch, cf, NULL);
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 1/7] call-forwarding: Read/Write cfis/cphs-cff
  2010-12-09 17:43 Read/Write EFcfis/EFcphs-cff files-v3 Jeevaka Badrappan
@ 2010-12-09 17:43 ` Jeevaka Badrappan
  0 siblings, 0 replies; 16+ messages in thread
From: Jeevaka Badrappan @ 2010-12-09 17:43 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 10715 bytes --]

---
 src/call-forwarding.c |  256 ++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 255 insertions(+), 1 deletions(-)

diff --git a/src/call-forwarding.c b/src/call-forwarding.c
index bb8aa37..085e638 100644
--- a/src/call-forwarding.c
+++ b/src/call-forwarding.c
@@ -34,6 +34,7 @@
 #include "ofono.h"
 
 #include "common.h"
+#include "simutil.h"
 
 #define CALL_FORWARDING_FLAG_CACHED 0x1
 
@@ -58,6 +59,12 @@ struct ofono_call_forwarding {
 	int query_next;
 	int query_end;
 	struct cf_ss_request *ss_req;
+	struct ofono_sim *sim;
+	unsigned char cfis_record_id;
+	unsigned char cfis_indicator;
+	char *cfu_number;
+	ofono_bool_t cphs_cff_present;
+	ofono_bool_t status_on_sim;
 	struct ofono_ussd *ussd;
 	unsigned int ussd_watch;
 	const struct ofono_call_forwarding_driver *driver;
@@ -202,6 +209,94 @@ static const char *cf_type_lut[] = {
 	"AllConditional"
 };
 
+static void sim_cfis_update_cb(int ok, void *data)
+{
+	if (!ok)
+		ofono_info("Failed to update EFcfis");
+}
+
+static void sim_cphs_cff_update_cb(int ok, void *data)
+{
+	if (!ok)
+		ofono_info("Failed to update EFcphs-cff");
+}
+
+static void sim_set_cf_indicator(struct ofono_call_forwarding *cf)
+{
+	gboolean cfu_voice = FALSE;
+	struct ofono_call_forwarding_condition *cond = NULL;
+	GSList *l;
+	const char *number = NULL;
+
+	/*
+	 * For now we only support Voice, although Fax & all Data
+	 * basic services are applicable as well.
+	 */
+	for (l = cf->cf_conditions[0]; l; l = l->next) {
+		cond = l->data;
+
+		if ((cond->cls & BEARER_CLASS_VOICE) &&
+				(strlen(cond->phone_number.number) > 0)) {
+			number = phone_number_to_string(&cond->phone_number);
+			cfu_voice = TRUE;
+			break;
+		}
+	}
+
+	if (cfu_voice == cf->status_on_sim &&
+			!g_strcmp0(number, cf->cfu_number))
+		return;
+
+	cf->status_on_sim = cfu_voice;
+
+	if (cf->cfis_record_id) {
+		unsigned char data[16];
+		int number_len;
+
+		memset(data, 0xff, sizeof(data));
+
+		/* Profile Identifier */
+		data[0] = 0x01;
+
+		if (cfu_voice) {
+			number_len = strlen(cond->phone_number.number);
+
+			/* CFU indicator Status - Voice */
+			data[1] = (cf->cfis_indicator |= 0x01);
+			number_len = (number_len + 1) / 2;
+			data[2] = number_len + 1;
+			data[3] = cond->phone_number.type;
+
+			g_free(cf->cfu_number);
+			cf->cfu_number = g_strdup(number);
+
+			sim_encode_bcd_number(cond->phone_number.number,
+						data + 4);
+		} else {
+			data[1] = (cf->cfis_indicator &= 0xFE);
+
+			g_free(cf->cfu_number);
+			cf->cfu_number = NULL;
+		}
+
+		ofono_sim_write(cf->sim, SIM_EFCFIS_FILEID,
+					sim_cfis_update_cb,
+					OFONO_SIM_FILE_STRUCTURE_FIXED,
+					cf->cfis_record_id, data,
+					sizeof(data), cf);
+		return;
+	}
+
+	if (cf->cphs_cff_present) {
+		unsigned char cff_voice = cfu_voice ? 0x0A : 0x05;
+
+		ofono_sim_write(cf->sim, SIM_EF_CPHS_CFF_FILEID,
+					sim_cphs_cff_update_cb,
+					OFONO_SIM_FILE_STRUCTURE_TRANSPARENT,
+					0, &cff_voice, sizeof(cff_voice), cf);
+	}
+}
+
 static void set_new_cond_list(struct ofono_call_forwarding *cf,
 				int type, GSList *list)
 {
@@ -372,6 +467,7 @@ static DBusMessage *cf_get_properties_reply(DBusMessage *msg,
 	DBusMessageIter iter;
 	DBusMessageIter dict;
 	int i;
+	dbus_bool_t status;
 
 	reply = dbus_message_new_method_return(msg);
 	if (reply == NULL)
@@ -388,6 +484,10 @@ static DBusMessage *cf_get_properties_reply(DBusMessage *msg,
 						BEARER_CLASS_VOICE,
 						cf_type_lut[i]);
 
+	status = cf->status_on_sim;
+	ofono_dbus_dict_append(&dict, "ForwardingFlagOnSim", DBUS_TYPE_BOOLEAN,
+					&status);
+
 	dbus_message_iter_close_container(&iter, &dict);
 
 	return reply;
@@ -417,6 +517,13 @@ static void get_query_cf_callback(const struct ofono_error *error, int total,
 		return;
 	}
 
+	/*
+	 * This is to make sure the information received from network is
+	 * in sync with the information present in SIM/USIM.
+	 */
+	if (cf->query_next == CALL_FORWARDING_TYPE_UNCONDITIONAL)
+		sim_set_cf_indicator(cf);
+
 	cf->query_next++;
 	get_query_next_cf_cond(cf);
 }
@@ -431,8 +538,10 @@ static DBusMessage *cf_get_properties(DBusConnection *conn, DBusMessage *msg,
 					void *data)
 {
 	struct ofono_call_forwarding *cf = data;
+	struct ofono_modem *modem = __ofono_atom_get_modem(cf->atom);
 
-	if (cf->flags & CALL_FORWARDING_FLAG_CACHED)
+	if ((cf->flags & CALL_FORWARDING_FLAG_CACHED) ||
+			ofono_modem_get_online(modem) == FALSE)
 		return cf_get_properties_reply(msg, cf);
 
 	if (cf->driver->query == NULL)
@@ -532,6 +641,9 @@ static void set_query_cf_callback(const struct ofono_error *error, int total,
 	DBG("%s conditions:", cf_type_lut[cf->query_next]);
 	cf_cond_list_print(l);
 
+	if (cf->query_next == CALL_FORWARDING_TYPE_UNCONDITIONAL)
+		sim_set_cf_indicator(cf);
+
 	if (cf->query_next != cf->query_end) {
 		cf->query_next++;
 		set_query_next_cf_cond(cf);
@@ -590,12 +702,16 @@ static DBusMessage *cf_set_property(DBusConnection *conn, DBusMessage *msg,
 					void *data)
 {
 	struct ofono_call_forwarding *cf = data;
+	struct ofono_modem *modem = __ofono_atom_get_modem(cf->atom);
 	DBusMessageIter iter;
 	DBusMessageIter var;
 	const char *property;
 	int cls;
 	int type;
 
+	if (ofono_modem_get_online(modem) == FALSE)
+		return __ofono_error_not_available(msg);
+
 	if (__ofono_call_forwarding_is_busy(cf) ||
 			__ofono_ussd_is_busy(cf->ussd))
 		return __ofono_error_busy(msg);
@@ -860,6 +976,9 @@ static void ss_set_query_cf_callback(const struct ofono_error *error, int total,
 
 	set_new_cond_list(cf, cf->query_next, l);
 
+	if (cf->query_next == CALL_FORWARDING_TYPE_UNCONDITIONAL)
+		sim_set_cf_indicator(cf);
+
 	if (cf->query_next != cf->query_end) {
 		cf->query_next++;
 		ss_set_query_next_cf_cond(cf);
@@ -1111,6 +1230,130 @@ gboolean __ofono_call_forwarding_is_busy(struct ofono_call_forwarding *cf)
 	return cf->pending ? TRUE : FALSE;
 }
 
+static void sim_cfis_read_cb(int ok, int total_length, int record,
+			const unsigned char *data,
+			int record_length, void *userdata)
+{
+	struct ofono_call_forwarding *cf = userdata;
+	DBusConnection *conn = ofono_dbus_get_connection();
+	const char *path = __ofono_atom_get_path(cf->atom);
+
+	if (!ok || record_length < 16 || total_length < record_length) {
+		cf->cfis_indicator = 0;
+		cf->cfis_record_id = 0;
+		return;
+	}
+
+	/*
+	 * Multiple Subscriber Profile number which can have values 1-4.
+	 * Profile id 1 is assumed as the current profile.
+	 */
+	if (data[0] != 1)
+		return;
+
+	cf->cfis_record_id = record;
+
+	/* CFU indicator status */
+	cf->cfis_indicator = data[1];
+
+	/*
+	 * For now we only support Voice, although Fax & all Data
+	 * basic services are applicable as well.
+	 */
+	if (cf->cfis_indicator & 0x01) {
+		int ton_npi;
+		int number_len;
+		const char *number;
+		char attr[64];
+		struct ofono_call_forwarding_condition *cond;
+		GSList *l = NULL;
+		dbus_bool_t status;
+
+		number_len = data[2];
+		ton_npi = data[3];
+
+		if (number_len > 11 || ton_npi == 0xff)
+			return;
+
+		cond = g_try_new0(struct ofono_call_forwarding_condition, 1);
+		if (cond == NULL)
+			return;
+
+		status = cf->status_on_sim = TRUE;
+		cond->status = status;
+		cond->cls = BEARER_CLASS_VOICE;
+		cond->time = 0;
+		cond->phone_number.type = ton_npi;
+
+		sim_extract_bcd_number(data + 4, number_len - 1,
+					cond->phone_number.number);
+		number = phone_number_to_string(&cond->phone_number);
+
+		cf->cfu_number = g_strdup(number);
+
+		snprintf(attr, sizeof(attr), "%s%s",
+			bearer_class_to_string(BEARER_CLASS_VOICE),
+			cf_type_lut[CALL_FORWARDING_TYPE_UNCONDITIONAL]);
+
+		cf->cf_conditions[CALL_FORWARDING_TYPE_UNCONDITIONAL] =
+							g_slist_append(l, cond);
+
+		ofono_dbus_signal_property_changed(conn, path,
+				OFONO_CALL_FORWARDING_INTERFACE,
+				attr, DBUS_TYPE_STRING,
+				&number);
+
+		ofono_dbus_signal_property_changed(conn, path,
+				OFONO_CALL_FORWARDING_INTERFACE,
+				"ForwardingFlagOnSim",
+				DBUS_TYPE_BOOLEAN,
+				&status);
+	}
+}
+
+static void sim_cphs_cff_read_cb(int ok, int total_length, int record,
+				const unsigned char *data,
+				int record_length, void *userdata)
+{
+	struct ofono_call_forwarding *cf = userdata;
+	DBusConnection *conn = ofono_dbus_get_connection();
+	const char *path = __ofono_atom_get_path(cf->atom);
+	dbus_bool_t cfu_voice;
+
+	if (!ok || total_length < 1) {
+		cf->cphs_cff_present = FALSE;
+		return;
+	}
+
+	cf->cphs_cff_present = TRUE;
+
+	/*
+	 * For now we only support Voice, although Fax & all Data
+	 * basic services are applicable as well.
+	 */
+	cfu_voice = cf->status_on_sim = ((data[0] & 0xf) == 0xa);
+
+	ofono_dbus_signal_property_changed(conn, path,
+					OFONO_CALL_FORWARDING_INTERFACE,
+					"ForwardingFlagOnSim",
+					DBUS_TYPE_BOOLEAN,
+					&cfu_voice);
+}
+
+static void sim_read_cf_indicator(struct ofono_call_forwarding *cf)
+{
+	if (__ofono_sim_service_available(cf->sim,
+			SIM_UST_SERVICE_CFIS,
+			SIM_SST_SERVICE_CFIS) == TRUE)
+		ofono_sim_read(cf->sim, SIM_EFCFIS_FILEID,
+				OFONO_SIM_FILE_STRUCTURE_FIXED,
+				sim_cfis_read_cb, cf);
+	else
+		ofono_sim_read(cf->sim, SIM_EF_CPHS_CFF_FILEID,
+				OFONO_SIM_FILE_STRUCTURE_TRANSPARENT,
+				sim_cphs_cff_read_cb, cf);
+}
+
 int ofono_call_forwarding_driver_register(const struct ofono_call_forwarding_driver *d)
 {
 	DBG("driver: %p, name: %s", d, d->name);
@@ -1160,6 +1403,8 @@ static void call_forwarding_remove(struct ofono_atom *atom)
 	if (cf->driver && cf->driver->remove)
 		cf->driver->remove(cf);
 
+	g_free(cf->cfu_number);
+
 	cf_clear_all(cf);
 
 	g_free(cf);
@@ -1219,6 +1464,7 @@ void ofono_call_forwarding_register(struct ofono_call_forwarding *cf)
 	DBusConnection *conn = ofono_dbus_get_connection();
 	const char *path = __ofono_atom_get_path(cf->atom);
 	struct ofono_modem *modem = __ofono_atom_get_modem(cf->atom);
+	struct ofono_atom *sim_atom;
 	struct ofono_atom *ussd_atom;
 
 	if (!g_dbus_register_interface(conn, path,
@@ -1233,6 +1479,14 @@ void ofono_call_forwarding_register(struct ofono_call_forwarding *cf)
 
 	ofono_modem_add_interface(modem, OFONO_CALL_FORWARDING_INTERFACE);
 
+	sim_atom = __ofono_modem_find_atom(modem, OFONO_ATOM_TYPE_SIM);
+
+	if (sim_atom) {
+		cf->sim = __ofono_atom_get_data(sim_atom);
+
+		sim_read_cf_indicator(cf);
+	}
+
 	cf->ussd_watch = __ofono_modem_add_atom_watch(modem,
 					OFONO_ATOM_TYPE_USSD,
 					ussd_watch, cf, NULL);
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 1/7] call-forwarding: Read/Write cfis/cphs-cff
  2010-12-07 20:37 Read/Write EFcfis/EFcphs-cff files Jeevaka Badrappan
@ 2010-12-07 20:37 ` Jeevaka Badrappan
  0 siblings, 0 replies; 16+ messages in thread
From: Jeevaka Badrappan @ 2010-12-07 20:37 UTC (permalink / raw)
  To: ofono

[-- Attachment #1: Type: text/plain, Size: 10159 bytes --]

---
 src/call-forwarding.c |  242 ++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 241 insertions(+), 1 deletions(-)

diff --git a/src/call-forwarding.c b/src/call-forwarding.c
index bb8aa37..aafb1ce 100644
--- a/src/call-forwarding.c
+++ b/src/call-forwarding.c
@@ -34,6 +34,7 @@
 #include "ofono.h"
 
 #include "common.h"
+#include "simutil.h"
 
 #define CALL_FORWARDING_FLAG_CACHED 0x1
 
@@ -58,6 +59,11 @@ struct ofono_call_forwarding {
 	int query_next;
 	int query_end;
 	struct cf_ss_request *ss_req;
+	struct ofono_sim *sim;
+	unsigned char cfis_record_id;
+	unsigned char cfis_indicator;
+	ofono_bool_t cphs_cff_present;
+	ofono_bool_t status_on_sim;
 	struct ofono_ussd *ussd;
 	unsigned int ussd_watch;
 	const struct ofono_call_forwarding_driver *driver;
@@ -202,6 +208,85 @@ static const char *cf_type_lut[] = {
 	"AllConditional"
 };
 
+static void sim_cfis_update_cb(int ok, void *data)
+{
+	if (!ok)
+		ofono_info("Failed to update EFcfis");
+}
+
+static void sim_cphs_cff_update_cb(int ok, void *data)
+{
+	if (!ok)
+		ofono_info("Failed to update EFcphs-cff");
+}
+
+static void sim_set_cf_indicator(struct ofono_call_forwarding *cf)
+{
+	gboolean cfu_voice = FALSE;
+	struct ofono_call_forwarding_condition *cond = NULL;
+	GSList *l;
+
+	/*
+	 * For now we only support Voice, although Fax & all Data
+	 * basic services are applicable as well.
+	 */
+	for (l = cf->cf_conditions[0]; l; l = l->next) {
+		cond = l->data;
+
+		if ((cond->cls & BEARER_CLASS_VOICE) &&
+				(strlen(cond->phone_number.number) > 0)) {
+			cfu_voice = TRUE;
+			break;
+		}
+	}
+
+	if (cfu_voice == cf->status_on_sim)
+		return;
+
+	cf->status_on_sim = cfu_voice;
+
+	if (cf->cfis_record_id) {
+		unsigned char data[16];
+		int number_len;
+
+		memset(data, 0xff, sizeof(data));
+
+		/* Profile Identifier */
+		data[0] = 0x01;
+
+		if (cfu_voice) {
+			number_len = strlen(cond->phone_number.number);
+
+			/* CFU indicator Status - Voice */
+			data[1] = (cf->cfis_indicator |= 0x01);
+			number_len = (number_len + 1) / 2;
+			data[2] = number_len + 1;
+			data[3] = cond->phone_number.type;
+
+			sim_encode_bcd_number(cond->phone_number.number,
+						data + 4);
+
+		} else
+			data[1] = (cf->cfis_indicator &= 0xFE);
+
+		ofono_sim_write(cf->sim, SIM_EFCFIS_FILEID,
+					sim_cfis_update_cb,
+					OFONO_SIM_FILE_STRUCTURE_FIXED,
+					cf->cfis_record_id, data,
+					sizeof(data), cf);
+		return;
+	}
+
+	if (cf->cphs_cff_present) {
+		unsigned char cff_voice = cfu_voice ? 0x0A : 0x05;
+
+		ofono_sim_write(cf->sim, SIM_EF_CPHS_CFF_FILEID,
+					sim_cphs_cff_update_cb,
+					OFONO_SIM_FILE_STRUCTURE_TRANSPARENT,
+					0, &cff_voice, sizeof(cff_voice), cf);
+	}
+}
+
 static void set_new_cond_list(struct ofono_call_forwarding *cf,
 				int type, GSList *list)
 {
@@ -372,6 +457,7 @@ static DBusMessage *cf_get_properties_reply(DBusMessage *msg,
 	DBusMessageIter iter;
 	DBusMessageIter dict;
 	int i;
+	dbus_bool_t status;
 
 	reply = dbus_message_new_method_return(msg);
 	if (reply == NULL)
@@ -388,6 +474,10 @@ static DBusMessage *cf_get_properties_reply(DBusMessage *msg,
 						BEARER_CLASS_VOICE,
 						cf_type_lut[i]);
 
+	status = cf->status_on_sim;
+	ofono_dbus_dict_append(&dict, "ForwardingFlagOnSim", DBUS_TYPE_BOOLEAN,
+					&status);
+
 	dbus_message_iter_close_container(&iter, &dict);
 
 	return reply;
@@ -417,6 +507,13 @@ static void get_query_cf_callback(const struct ofono_error *error, int total,
 		return;
 	}
 
+	/*
+	 * This is to make sure the information received from network is
+	 * in sync with the information present in SIM/USIM.
+	 */
+	if (cf->query_next == CALL_FORWARDING_TYPE_UNCONDITIONAL)
+		sim_set_cf_indicator(cf);
+
 	cf->query_next++;
 	get_query_next_cf_cond(cf);
 }
@@ -431,8 +528,10 @@ static DBusMessage *cf_get_properties(DBusConnection *conn, DBusMessage *msg,
 					void *data)
 {
 	struct ofono_call_forwarding *cf = data;
+	struct ofono_modem *modem = __ofono_atom_get_modem(cf->atom);
 
-	if (cf->flags & CALL_FORWARDING_FLAG_CACHED)
+	if ((cf->flags & CALL_FORWARDING_FLAG_CACHED) ||
+			ofono_modem_get_online(modem) == FALSE)
 		return cf_get_properties_reply(msg, cf);
 
 	if (cf->driver->query == NULL)
@@ -532,6 +631,9 @@ static void set_query_cf_callback(const struct ofono_error *error, int total,
 	DBG("%s conditions:", cf_type_lut[cf->query_next]);
 	cf_cond_list_print(l);
 
+	if (cf->query_next == CALL_FORWARDING_TYPE_UNCONDITIONAL)
+		sim_set_cf_indicator(cf);
+
 	if (cf->query_next != cf->query_end) {
 		cf->query_next++;
 		set_query_next_cf_cond(cf);
@@ -590,12 +692,16 @@ static DBusMessage *cf_set_property(DBusConnection *conn, DBusMessage *msg,
 					void *data)
 {
 	struct ofono_call_forwarding *cf = data;
+	struct ofono_modem *modem = __ofono_atom_get_modem(cf->atom);
 	DBusMessageIter iter;
 	DBusMessageIter var;
 	const char *property;
 	int cls;
 	int type;
 
+	if (ofono_modem_get_online(modem) == FALSE)
+		return __ofono_error_not_available(msg);
+
 	if (__ofono_call_forwarding_is_busy(cf) ||
 			__ofono_ussd_is_busy(cf->ussd))
 		return __ofono_error_busy(msg);
@@ -860,6 +966,9 @@ static void ss_set_query_cf_callback(const struct ofono_error *error, int total,
 
 	set_new_cond_list(cf, cf->query_next, l);
 
+	if (cf->query_next == CALL_FORWARDING_TYPE_UNCONDITIONAL)
+		sim_set_cf_indicator(cf);
+
 	if (cf->query_next != cf->query_end) {
 		cf->query_next++;
 		ss_set_query_next_cf_cond(cf);
@@ -1111,6 +1220,128 @@ gboolean __ofono_call_forwarding_is_busy(struct ofono_call_forwarding *cf)
 	return cf->pending ? TRUE : FALSE;
 }
 
+static void sim_cfis_read_cb(int ok, int total_length, int record,
+			const unsigned char *data,
+			int record_length, void *userdata)
+{
+	struct ofono_call_forwarding *cf = userdata;
+	DBusConnection *conn = ofono_dbus_get_connection();
+	const char *path = __ofono_atom_get_path(cf->atom);
+
+	if (!ok || record_length < 16 || total_length < record_length) {
+		cf->cfis_indicator = 0;
+		cf->cfis_record_id = 0;
+		return;
+	}
+
+	/*
+	 * Multiple Subscriber Profile number which can have values 1-4.
+	 * Profile id 1 is assumed as the current profile.
+	 */
+	if (data[0] != 1)
+		return;
+
+	cf->cfis_record_id = record;
+
+	/* CFU indicator status */
+	cf->cfis_indicator = data[1];
+
+	/*
+	 * For now we only support Voice, although Fax & all Data
+	 * basic services are applicable as well.
+	 */
+	if (cf->cfis_indicator & 0x01) {
+		int ton_npi;
+		int number_len;
+		const char *number;
+		char attr[64];
+		struct ofono_call_forwarding_condition *cond;
+		GSList *l = NULL;
+		dbus_bool_t status;
+
+		number_len = data[2];
+		ton_npi = data[3];
+
+		if (number_len > 11 || ton_npi == 0xff)
+			return;
+
+		cond = g_try_new0(struct ofono_call_forwarding_condition, 1);
+		if (cond == NULL)
+			return;
+
+		status = cf->status_on_sim = TRUE;
+		cond->status = status;
+		cond->cls = BEARER_CLASS_VOICE;
+		cond->time = 0;
+		cond->phone_number.type = ton_npi;
+
+		sim_extract_bcd_number(data + 4, number_len - 1,
+					cond->phone_number.number);
+		number = phone_number_to_string(&cond->phone_number);
+
+		snprintf(attr, sizeof(attr), "%s%s",
+			bearer_class_to_string(BEARER_CLASS_VOICE),
+			cf_type_lut[CALL_FORWARDING_TYPE_UNCONDITIONAL]);
+
+		cf->cf_conditions[CALL_FORWARDING_TYPE_UNCONDITIONAL] =
+							g_slist_append(l, cond);
+
+		ofono_dbus_signal_property_changed(conn, path,
+				OFONO_CALL_FORWARDING_INTERFACE,
+				attr, DBUS_TYPE_STRING,
+				&number);
+
+		ofono_dbus_signal_property_changed(conn, path,
+				OFONO_CALL_FORWARDING_INTERFACE,
+				"ForwardingFlagOnSim",
+				DBUS_TYPE_BOOLEAN,
+				&status);
+	}
+}
+
+static void sim_cphs_cff_read_cb(int ok, int total_length, int record,
+				const unsigned char *data,
+				int record_length, void *userdata)
+{
+	struct ofono_call_forwarding *cf = userdata;
+	DBusConnection *conn = ofono_dbus_get_connection();
+	const char *path = __ofono_atom_get_path(cf->atom);
+	dbus_bool_t cfu_voice;
+
+	if (!ok || total_length < 1) {
+		cf->cphs_cff_present = FALSE;
+		return;
+	}
+
+	cf->cphs_cff_present = TRUE;
+
+	/*
+	 * For now we only support Voice, although Fax & all Data
+	 * basic services are applicable as well.
+	 */
+	cfu_voice = cf->status_on_sim = ((data[0] & 0xf) == 0xa);
+
+	ofono_dbus_signal_property_changed(conn, path,
+					OFONO_CALL_FORWARDING_INTERFACE,
+					"ForwardingFlagOnSim",
+					DBUS_TYPE_BOOLEAN,
+					&cfu_voice);
+}
+
+static void sim_read_cf_indicator(struct ofono_call_forwarding *cf)
+{
+	if (__ofono_sim_service_available(cf->sim,
+			SIM_UST_SERVICE_CFIS,
+			SIM_SST_SERVICE_CFIS) == TRUE)
+		ofono_sim_read(cf->sim, SIM_EFCFIS_FILEID,
+				OFONO_SIM_FILE_STRUCTURE_FIXED,
+				sim_cfis_read_cb, cf);
+	else
+		ofono_sim_read(cf->sim, SIM_EF_CPHS_CFF_FILEID,
+				OFONO_SIM_FILE_STRUCTURE_TRANSPARENT,
+				sim_cphs_cff_read_cb, cf);
+}
+
 int ofono_call_forwarding_driver_register(const struct ofono_call_forwarding_driver *d)
 {
 	DBG("driver: %p, name: %s", d, d->name);
@@ -1219,6 +1450,7 @@ void ofono_call_forwarding_register(struct ofono_call_forwarding *cf)
 	DBusConnection *conn = ofono_dbus_get_connection();
 	const char *path = __ofono_atom_get_path(cf->atom);
 	struct ofono_modem *modem = __ofono_atom_get_modem(cf->atom);
+	struct ofono_atom *sim_atom;
 	struct ofono_atom *ussd_atom;
 
 	if (!g_dbus_register_interface(conn, path,
@@ -1233,6 +1465,14 @@ void ofono_call_forwarding_register(struct ofono_call_forwarding *cf)
 
 	ofono_modem_add_interface(modem, OFONO_CALL_FORWARDING_INTERFACE);
 
+	sim_atom = __ofono_modem_find_atom(modem, OFONO_ATOM_TYPE_SIM);
+
+	if (sim_atom) {
+		cf->sim = __ofono_atom_get_data(sim_atom);
+
+		sim_read_cf_indicator(cf);
+	}
+
 	cf->ussd_watch = __ofono_modem_add_atom_watch(modem,
 					OFONO_ATOM_TYPE_USSD,
 					ussd_watch, cf, NULL);
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2010-12-17 23:16 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-11-29 10:37 Read/Write EFcfis/EFcphs-cff Jeevaka Badrappan
2010-11-29 10:37 ` [PATCH 1/7] call-forwarding: Read/Write cfis/cphs-cff Jeevaka Badrappan
2010-12-03 19:08   ` Denis Kenzior
2010-12-07 13:59     ` Jeevaka.Badrappan
2010-12-07 18:41       ` Denis Kenzior
2010-11-29 10:37 ` [PATCH 2/7] ifx: Move call forwarding to post sim Jeevaka Badrappan
2010-11-29 10:37 ` [PATCH 3/7] isigen: " Jeevaka Badrappan
2010-11-29 10:38 ` [PATCH 4/7] plugins/n900: " Jeevaka Badrappan
2010-11-29 10:38 ` [PATCH 5/7] phonesim: " Jeevaka Badrappan
2010-11-29 10:38 ` [PATCH 6/7] doc: Add new property to call forwarding Jeevaka Badrappan
2010-11-29 10:38 ` [PATCH 7/7] TODO: Marking the Read/Write EFcfis task as done Jeevaka Badrappan
2010-12-07 20:37 Read/Write EFcfis/EFcphs-cff files Jeevaka Badrappan
2010-12-07 20:37 ` [PATCH 1/7] call-forwarding: Read/Write cfis/cphs-cff Jeevaka Badrappan
2010-12-09 17:43 Read/Write EFcfis/EFcphs-cff files-v3 Jeevaka Badrappan
2010-12-09 17:43 ` [PATCH 1/7] call-forwarding: Read/Write cfis/cphs-cff Jeevaka Badrappan
2010-12-10 18:56 Read/Write EFcfis/EFcphs-cff files-v4 Jeevaka Badrappan
2010-12-10 18:56 ` [PATCH 1/7] call-forwarding: Read/Write cfis/cphs-cff Jeevaka Badrappan
2010-12-17  7:04   ` Jeevaka Badrappan
2010-12-17 23:16     ` Denis Kenzior

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.