Open Source Telephony
 help / color / mirror / Atom feed
From: Guillaume Zajac <guillaume.zajac@linux.intel.com>
To: ofono@ofono.org
Subject: [PATCH_v0] ofono: Add support of CDMA modems
Date: Tue, 13 Dec 2011 15:40:37 +0100	[thread overview]
Message-ID: <1323787237-8307-2-git-send-email-guillaume.zajac@linux.intel.com> (raw)
In-Reply-To: <1323787237-8307-1-git-send-email-guillaume.zajac@linux.intel.com>

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

---
 plugins/ofono.c |  356 +++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 345 insertions(+), 11 deletions(-)

diff --git a/plugins/ofono.c b/plugins/ofono.c
index aa9a776..c071558 100644
--- a/plugins/ofono.c
+++ b/plugins/ofono.c
@@ -51,6 +51,9 @@
 #define OFONO_CM_INTERFACE		OFONO_SERVICE ".ConnectionManager"
 #define OFONO_CONTEXT_INTERFACE		OFONO_SERVICE ".ConnectionContext"
 
+#define OFONO_CDMA_CM_INTERFACE		OFONO_SERVICE ".cdma.ConnectionManager"
+#define OFONO_CDMA_NETREG_INTERFACE	OFONO_SERVICE ".cdma.NetworkRegistration"
+
 #define MODEM_ADDED			"ModemAdded"
 #define MODEM_REMOVED			"ModemRemoved"
 #define PROPERTY_CHANGED		"PropertyChanged"
@@ -68,6 +71,8 @@ enum ofono_api {
 	OFONO_API_SIM =		0x1,
 	OFONO_API_NETREG =	0x2,
 	OFONO_API_CM =		0x4,
+	OFONO_API_CDMA_NETREG =	0x8,
+	OFONO_API_CDMA_CM =	0x10,
 };
 
 /*
@@ -121,6 +126,9 @@ struct modem_data {
 	connman_bool_t set_powered;
 	connman_bool_t set_online;
 
+	/* CDMA ConnectionManager Interface */
+	connman_bool_t cdma_cm_powered;
+
 	/* ConnectionManager Interface */
 	connman_bool_t attached;
 	connman_bool_t cm_powered;
@@ -137,6 +145,7 @@ struct modem_data {
 	/* Netreg Interface */
 	char *name;
 	uint8_t strength;
+	uint8_t data_strength; /* 1xEVDO signal strength */
 	connman_bool_t roaming;
 
 	/* pending calls */
@@ -506,6 +515,56 @@ static int context_set_inactive(struct modem_data *modem)
 	return err;
 }
 
+static void cdma_cm_set_powered_reply(struct modem_data *modem,
+					connman_bool_t success)
+{
+	DBG("%s", modem->path);
+
+	if (success == TRUE) {
+		/*
+		 * Don't handle do anything on success here. oFono will send
+		 * the change via PropertyChanged singal.
+		 */
+		return;
+	}
+
+	/*
+	 * Powered = True might fail due a timeout. That means oFono
+	 * still tries to go online. If we retry to set Powered = True,
+	 * we just get a InProgress error message. Should we power
+	 * cycle the modem in such cases?
+	 */
+
+	connman_network_set_error(modem->network,
+				CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
+}
+
+static int cdma_cm_set_powered(struct modem_data *modem)
+{
+	dbus_bool_t powered = TRUE;
+
+	DBG("%s", modem->path);
+
+	return set_property(modem, modem->path, OFONO_CDMA_CM_INTERFACE,
+				"Powered", DBUS_TYPE_BOOLEAN, &powered,
+				cdma_cm_set_powered_reply);
+}
+
+static int cdma_cm_shutdown(struct modem_data *modem)
+{
+	dbus_bool_t powered = FALSE;
+	int err;
+
+	DBG("%s", modem->path);
+
+	err = set_property(modem, modem->path, OFONO_CDMA_CM_INTERFACE,
+				"Powered", DBUS_TYPE_BOOLEAN, &powered, NULL);
+	if (err == -EINPROGRESS)
+		return 0;
+
+	return err;
+}
+
 static void modem_set_online_reply(struct modem_data *modem,
 					connman_bool_t success)
 {
@@ -617,6 +676,12 @@ static uint8_t extract_interfaces(DBusMessageIter *array)
 			interfaces |= OFONO_API_NETREG;
 		else if (g_str_equal(name, OFONO_CM_INTERFACE) == TRUE)
 			interfaces |= OFONO_API_CM;
+		else if (g_str_equal(name,
+				OFONO_CDMA_CM_INTERFACE) == TRUE)
+			interfaces |= OFONO_API_CDMA_CM;
+		else if (g_str_equal(name,
+				OFONO_CDMA_NETREG_INTERFACE) == TRUE)
+			interfaces |= OFONO_API_CDMA_NETREG;
 
 		dbus_message_iter_next(&entry);
 	}
@@ -1258,6 +1323,15 @@ static void netreg_update_strength(struct modem_data *modem,
 	connman_network_update(modem->network);
 }
 
+/* Retrieve 1xEVDO signal strength */
+static void netreg_update_datastrength(struct modem_data *modem,
+					DBusMessageIter *value)
+{
+	dbus_message_iter_get_basic(value, &modem->data_strength);
+
+	DBG("%s Data Strength %d", modem->path, modem->data_strength);
+}
+
 static void netreg_update_roaming(struct modem_data *modem,
 					DBusMessageIter *value)
 {
@@ -1366,6 +1440,101 @@ static int netreg_get_properties(struct modem_data *modem)
 			netreg_properties_reply, modem);
 }
 
+static void add_cdma_network(struct modem_data *modem)
+{
+	/* Be sure that device is created before adding CDMA network */
+	if (modem->device == NULL)
+		return;
+
+	/*
+	 * CDMA modems don't need contexts for data call, however the current
+	 * add_network() logic needs one, so we create one to proceed.
+	 */
+	if (modem->context == NULL)
+		modem->context = network_context_alloc(modem->path);
+
+	add_network(modem);
+
+	if (modem->cdma_cm_powered == TRUE)
+		set_connected(modem);
+}
+
+static gboolean cdma_netreg_changed(DBusConnection *connection,
+					DBusMessage *message,
+					void *user_data)
+{
+	const char *path = dbus_message_get_path(message);
+	struct modem_data *modem;
+	DBusMessageIter iter, value;
+	const char *key;
+
+	DBG("");
+
+	modem = g_hash_table_lookup(modem_hash, path);
+	if (modem == NULL)
+		return TRUE;
+
+	if (modem->ignore == TRUE)
+		return TRUE;
+
+	if (dbus_message_iter_init(message, &iter) == FALSE)
+		return TRUE;
+
+	dbus_message_iter_get_basic(&iter, &key);
+
+	dbus_message_iter_next(&iter);
+	dbus_message_iter_recurse(&iter, &value);
+
+	if (g_str_equal(key, "Name") == TRUE)
+		netreg_update_name(modem, &value);
+	else if (g_str_equal(key, "Strength") == TRUE)
+		netreg_update_strength(modem, &value);
+	else if (g_str_equal(key, "DataStrength") == TRUE)
+		netreg_update_datastrength(modem, &value);
+	else if (g_str_equal(key, "Status") == TRUE)
+		netreg_update_roaming(modem, &value);
+
+	add_cdma_network(modem);
+
+	return TRUE;
+}
+
+static void cdma_netreg_properties_reply(struct modem_data *modem,
+					DBusMessageIter *dict)
+{
+	DBG("%s", modem->path);
+
+	while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
+		DBusMessageIter entry, value;
+		const char *key;
+
+		dbus_message_iter_recurse(dict, &entry);
+		dbus_message_iter_get_basic(&entry, &key);
+
+		dbus_message_iter_next(&entry);
+		dbus_message_iter_recurse(&entry, &value);
+
+		if (g_str_equal(key, "Name") == TRUE)
+			netreg_update_name(modem, &value);
+		else if (g_str_equal(key, "Strength") == TRUE)
+			netreg_update_strength(modem, &value);
+		else if (g_str_equal(key, "DataStrength") == TRUE)
+			netreg_update_datastrength(modem, &value);
+		else if (g_str_equal(key, "Status") == TRUE)
+			netreg_update_roaming(modem, &value);
+
+		dbus_message_iter_next(dict);
+	}
+
+	add_cdma_network(modem);
+}
+
+static int cdma_netreg_get_properties(struct modem_data *modem)
+{
+	return get_properties(modem->path, OFONO_CDMA_NETREG_INTERFACE,
+			cdma_netreg_properties_reply, modem);
+}
+
 static void cm_update_attached(struct modem_data *modem,
 				DBusMessageIter *value)
 {
@@ -1429,6 +1598,51 @@ static gboolean cm_changed(DBusConnection *connection, DBusMessage *message,
 	return TRUE;
 }
 
+static gboolean cdma_cm_changed(DBusConnection *connection,
+				DBusMessage *message, void *user_data)
+{
+	const char *path = dbus_message_get_path(message);
+	struct modem_data *modem;
+	DBusMessageIter iter, value;
+	const char *key;
+
+	modem = g_hash_table_lookup(modem_hash, path);
+	if (modem == NULL)
+		return TRUE;
+
+	if (modem->online == TRUE && modem->network == NULL)
+		cdma_netreg_get_properties(modem);
+
+	if (dbus_message_iter_init(message, &iter) == FALSE)
+		return TRUE;
+
+	dbus_message_iter_get_basic(&iter, &key);
+
+	dbus_message_iter_next(&iter);
+	dbus_message_iter_recurse(&iter, &value);
+
+	if (g_str_equal(key, "Powered") == TRUE) {
+		dbus_message_iter_get_basic(&value, &modem->cdma_cm_powered);
+
+		DBG("%s CDMA cm Powered %d", modem->path,
+						modem->cdma_cm_powered);
+
+		if (modem->network != NULL) {
+			if (modem->cdma_cm_powered == TRUE)
+				set_connected(modem);
+			else
+				set_disconnected(modem);
+		}
+	} if (g_str_equal(key, "Settings") == TRUE) {
+		DBG("%s Settings", modem->path);
+
+		if (modem->context != NULL)
+			extract_ipv4_settings(&value, modem->context);
+	}
+
+	return TRUE;
+}
+
 static void cm_properties_reply(struct modem_data *modem, DBusMessageIter *dict)
 {
 	DBG("%s", modem->path);
@@ -1458,6 +1672,55 @@ static int cm_get_properties(struct modem_data *modem)
 				cm_properties_reply, modem);
 }
 
+static void cdma_cm_properties_reply(struct modem_data *modem,
+					DBusMessageIter *dict)
+{
+	DBG("%s", modem->path);
+
+	if (modem->online == TRUE)
+		cdma_netreg_get_properties(modem);
+
+	while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
+		DBusMessageIter entry, value;
+		const char *key;
+
+		dbus_message_iter_recurse(dict, &entry);
+		dbus_message_iter_get_basic(&entry, &key);;
+
+		dbus_message_iter_next(&entry);
+		dbus_message_iter_recurse(&entry, &value);
+
+		if (g_str_equal(key, "Powered") == TRUE) {
+			dbus_message_iter_get_basic(&value,
+						&modem->cdma_cm_powered);
+
+			DBG("%s Powered %d", modem->path,
+						modem->cdma_cm_powered);
+
+			if (modem->network != NULL) {
+				if (modem->cdma_cm_powered == TRUE)
+					set_connected(modem);
+				else
+					set_disconnected(modem);
+			}
+		} if (g_str_equal(key, "Settings") == TRUE) {
+
+			DBG("%s Settings", modem->path);
+
+			if (modem->context != NULL)
+				extract_ipv4_settings(&value, modem->context);
+		}
+
+		dbus_message_iter_next(dict);
+	}
+}
+
+static int cdma_cm_get_properties(struct modem_data *modem)
+{
+	return get_properties(modem->path, OFONO_CDMA_CM_INTERFACE,
+				cdma_cm_properties_reply, modem);
+}
+
 static void update_sim_imsi(struct modem_data *modem,
 				const char *imsi)
 {
@@ -1506,6 +1769,10 @@ static gboolean sim_changed(DBusConnection *connection, DBusMessage *message,
 						OFONO_API_CM) == TRUE) {
 			if (ready_to_create_device(modem) == TRUE)
 				create_device(modem);
+		} else if (has_interface(modem->interfaces,
+						OFONO_API_CDMA_CM) == TRUE) {
+			if (ready_to_create_device(modem) == TRUE)
+				create_device(modem);
 		}
 	}
 
@@ -1546,6 +1813,12 @@ static void sim_properties_reply(struct modem_data *modem,
 					cm_get_properties(modem);
 					cm_get_contexts(modem);
 				}
+			} else if (has_interface(modem->interfaces,
+					OFONO_API_CDMA_CM) == TRUE) {
+				if (ready_to_create_device(modem) == TRUE)
+					create_device(modem);
+				if (modem->device != NULL)
+					cdma_cm_get_properties(modem);
 			}
 			return;
 		}
@@ -1598,13 +1871,21 @@ static gboolean modem_changed(DBusConnection *connection, DBusMessage *message,
 		if (modem->online == FALSE)
 			return TRUE;
 
-		if (has_interface(modem->interfaces, OFONO_API_CM) == FALSE)
-			return TRUE;
-		if (ready_to_create_device(modem) == TRUE)
-			create_device(modem);
-		if (modem->device != NULL) {
-			cm_get_properties(modem);
-			cm_get_contexts(modem);
+		if (has_interface(modem->interfaces, OFONO_API_CM) == FALSE) {
+			if (ready_to_create_device(modem) == TRUE)
+				create_device(modem);
+			if (modem->device != NULL) {
+				cm_get_properties(modem);
+				cm_get_contexts(modem);
+			}
+		} else if (has_interface(modem->interfaces,
+						OFONO_API_CDMA_CM) == TRUE) {
+			if (ready_to_create_device(modem) == TRUE)
+				create_device(modem);
+			if (modem->device != NULL) {
+				cdma_cm_get_properties(modem);
+				cdma_netreg_get_properties(modem);
+			}
 		}
 	} else if (g_str_equal(key, "Interfaces") == TRUE) {
 		modem->interfaces = extract_interfaces(&value);
@@ -1632,6 +1913,12 @@ static gboolean modem_changed(DBusConnection *connection, DBusMessage *message,
 				cm_get_contexts(modem);
 				return TRUE;
 			}
+		} else if (has_interface(modem->interfaces,
+					OFONO_API_CDMA_CM) == TRUE) {
+				if (ready_to_create_device(modem) == TRUE)
+					create_device(modem);
+				if (modem->device != NULL)
+					cdma_cm_get_properties(modem);
 		} else {
 			if (modem->context != NULL) {
 				remove_cm_context(modem,
@@ -1647,7 +1934,9 @@ static gboolean modem_changed(DBusConnection *connection, DBusMessage *message,
 		if (has_interface(modem->interfaces, OFONO_API_NETREG) == TRUE) {
 			if (modem->attached == TRUE)
 				netreg_get_properties(modem);
-		}
+		} else if (has_interface(modem->interfaces,
+				OFONO_API_CDMA_NETREG) == TRUE)
+			cdma_netreg_get_properties(modem);
 	} else if (g_str_equal(key, "Serial") == TRUE) {
 		char *serial;
 
@@ -1665,6 +1954,12 @@ static gboolean modem_changed(DBusConnection *connection, DBusMessage *message,
 				cm_get_properties(modem);
 				cm_get_contexts(modem);
 			}
+		} else if (has_interface(modem->interfaces, OFONO_API_CDMA_CM)
+				== TRUE) {
+			if (ready_to_create_device(modem) == TRUE)
+				create_device(modem);
+			if (modem->device != NULL)
+				cdma_cm_get_properties(modem);
 		}
 	}
 
@@ -1754,6 +2049,12 @@ static void add_modem(const char *path, DBusMessageIter *prop)
 			cm_get_properties(modem);
 			cm_get_contexts(modem);
 		}
+	} else if (has_interface(modem->interfaces, OFONO_API_CDMA_CM)
+			== TRUE) {
+		if (ready_to_create_device(modem) == TRUE)
+			create_device(modem);
+		if (modem->device != NULL)
+			cdma_cm_get_properties(modem);
 	}
 }
 
@@ -1969,7 +2270,14 @@ static int network_connect(struct connman_network *network)
 
 	DBG("%s network %p", modem->path, network);
 
-	return context_set_active(modem);
+	if (has_interface(modem->interfaces, OFONO_API_CM) == TRUE)
+		return context_set_active(modem);
+	else if (has_interface(modem->interfaces, OFONO_API_CDMA_CM) == TRUE)
+		return cdma_cm_set_powered(modem);
+	else
+		connman_error("No connection manager interface available...");
+
+	return -ENOSYS;
 }
 
 static int network_disconnect(struct connman_network *network)
@@ -1978,7 +2286,14 @@ static int network_disconnect(struct connman_network *network)
 
 	DBG("%s network %p", modem->path, network);
 
-	return context_set_inactive(modem);
+	if (has_interface(modem->interfaces, OFONO_API_CM) == TRUE)
+		return context_set_inactive(modem);
+	else if (has_interface(modem->interfaces, OFONO_API_CDMA_CM) == TRUE)
+		return cdma_cm_shutdown(modem);
+	else
+		connman_error("No connection manager interface available...");
+
+	return -ENOSYS;
 }
 
 static struct connman_network_driver network_driver = {
@@ -2043,6 +2358,8 @@ static guint context_added_watch;
 static guint context_removed_watch;
 static guint netreg_watch;
 static guint context_watch;
+static guint cdma_cm_watch;
+static guint cdma_netreg_watch;
 
 static int ofono_init(void)
 {
@@ -2112,12 +2429,25 @@ static int ofono_init(void)
 						netreg_changed,
 						NULL, NULL);
 
+	cdma_cm_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
+						OFONO_CDMA_CM_INTERFACE,
+						PROPERTY_CHANGED,
+						cdma_cm_changed,
+						NULL, NULL);
+
+	cdma_netreg_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
+						OFONO_CDMA_NETREG_INTERFACE,
+						PROPERTY_CHANGED,
+						cdma_netreg_changed,
+						NULL, NULL);
+
 
 	if (watch == 0 || modem_added_watch == 0 || modem_removed_watch == 0 ||
 			modem_watch == 0 || cm_watch == 0 || sim_watch == 0 ||
 			context_added_watch == 0 ||
 			context_removed_watch == 0 ||
-			context_watch == 0 || netreg_watch == 0) {
+			context_watch == 0 || netreg_watch == 0 ||
+			cdma_cm_watch == 0 || cdma_netreg_watch == 0) {
 		err = -EIO;
 		goto remove;
 	}
@@ -2135,6 +2465,8 @@ static int ofono_init(void)
 	return 0;
 
 remove:
+	g_dbus_remove_watch(connection, cdma_netreg_watch);
+	g_dbus_remove_watch(connection, cdma_cm_watch);
 	g_dbus_remove_watch(connection, netreg_watch);
 	g_dbus_remove_watch(connection, context_watch);
 	g_dbus_remove_watch(connection, context_removed_watch);
@@ -2176,6 +2508,8 @@ static void ofono_exit(void)
 	connman_device_driver_unregister(&modem_driver);
 	connman_network_driver_unregister(&network_driver);
 
+	g_dbus_remove_watch(connection, cdma_netreg_watch);
+	g_dbus_remove_watch(connection, cdma_cm_watch);
 	g_dbus_remove_watch(connection, netreg_watch);
 	g_dbus_remove_watch(connection, context_watch);
 	g_dbus_remove_watch(connection, context_removed_watch);
-- 
1.7.1


  reply	other threads:[~2011-12-13 14:40 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-12-13 14:40 [PATCH_v0] CDMA modem implementation support Guillaume Zajac
2011-12-13 14:40 ` Guillaume Zajac [this message]
2011-12-13 14:46 ` Denis Kenzior
2011-12-13 14:51   ` Guillaume Zajac

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1323787237-8307-2-git-send-email-guillaume.zajac@linux.intel.com \
    --to=guillaume.zajac@linux.intel.com \
    --cc=ofono@ofono.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox