---
plugins/ofono.c | 246 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 245 insertions(+), 1 deletions(-)
diff --git a/plugins/ofono.c b/plugins/ofono.c
index 1bd9a30..80555ce 100644
--- a/plugins/ofono.c
+++ b/plugins/ofono.c
@@ -50,6 +50,8 @@
#define OFONO_CONTEXT_INTERFACE OFONO_SERVICE
".ConnectionContext"
#define OFONO_SIM_INTERFACE OFONO_SERVICE ".SimManager"
#define OFONO_REGISTRATION_INTERFACE OFONO_SERVICE ".NetworkRegistration"
+#define OFONO_CDMA_SIM_INTERFACE OFONO_SERVICE ".cdma.SimManager"
+#define OFONO_CDMA_CONNECTION_MANAGER_INTERFACE OFONO_SERVICE
".cdma.ConnectionManager"
#define PROPERTY_CHANGED "PropertyChanged"
#define GET_PROPERTIES "GetProperties"
@@ -76,6 +78,8 @@ struct modem_data {
gboolean has_sim;
gboolean has_reg;
gboolean has_gprs;
+ gboolean is_cdma;
+ gboolean cdma_has_sim;
gboolean available;
gboolean pending_online;
dbus_bool_t requested_online;
@@ -551,6 +555,18 @@ static int set_network_active(struct connman_network
*network)
set_active_reply, g_strdup(path), g_free);
}
+static int set_cdma_network_active(struct connman_network *network)
+{
+ dbus_bool_t value = TRUE;
+ const char *path = connman_network_get_string(network, "Path");
+
+ DBG("network %p, path %s", network, path);
+
+ return set_property(path, OFONO_CDMA_CONNECTION_MANAGER_INTERFACE,
+ "Powered", DBUS_TYPE_BOOLEAN, &value,
+ set_active_reply, g_strdup(path), g_free);
+}
+
static int set_network_inactive(struct connman_network *network)
{
int err;
@@ -569,6 +585,24 @@ static int set_network_inactive(struct connman_network
*network)
return err;
}
+static int set_cdma_network_inactive(struct connman_network *network)
+{
+ int err;
+ dbus_bool_t value = FALSE;
+ const char *path = connman_network_get_string(network, "Path");
+
+ DBG("network %p, path %s", network, path);
+
+ err = set_property(path, OFONO_CDMA_CONNECTION_MANAGER_INTERFACE,
+ "Powered", DBUS_TYPE_BOOLEAN, &value,
+ NULL, NULL, NULL);
+
+ if (err == -EINPROGRESS)
+ err = 0;
+
+ return err;
+}
+
static int network_connect(struct connman_network *network)
{
struct connman_device *device;
@@ -584,6 +618,9 @@ static int network_connect(struct connman_network *network)
if (modem == NULL)
return -ENODEV;
+ if (modem->is_cdma)
+ return set_cdma_network_active(network);
+
if (modem->registered == FALSE)
return -ENOLINK;
@@ -598,13 +635,27 @@ static int network_connect(struct connman_network
*network)
static int network_disconnect(struct connman_network *network)
{
+ struct connman_device *device;
+ struct modem_data *modem;
+
DBG("network %p", network);
+ device = connman_network_get_device(network);
+ if (device == NULL)
+ return -ENODEV;
+
+ modem = connman_device_get_data(device);
+ if (modem == NULL)
+ return -ENODEV;
+
if (connman_network_get_index(network) < 0)
return -ENOTCONN;
connman_network_set_associating(network, FALSE);
+ if (modem->is_cdma)
+ return set_cdma_network_inactive(network);
+
return set_network_inactive(network);
}
@@ -936,6 +987,77 @@ static int add_network(struct connman_device *device,
return 0;
}
+static int add_cdma_network(struct connman_device *device, const char *path)
+{
+ struct modem_data *modem = connman_device_get_data(device);
+ struct connman_network *network;
+ struct network_info *info;
+ char *ident;
+ const char *hash_path;
+
+ DBG("modem %p device %p path %s", modem, device, path);
+
+ ident = get_ident(path);
+
+ network = connman_device_get_network(device, ident);
+ if (network != NULL)
+ return -EALREADY;
+
+ info = g_hash_table_lookup(network_hash, path);
+ if (info != NULL) {
+ DBG("path %p already exists with device %p", path,
+ connman_network_get_device(info->network));
+ if (connman_network_get_device(info->network))
+ return -EALREADY;
+ g_hash_table_remove(network_hash, path);
+ }
+
+ network = connman_network_create(ident, CONNMAN_NETWORK_TYPE_CELLULAR);
+ if (network == NULL)
+ return -ENOMEM;
+
+ info = g_try_new0(struct network_info, 1);
+ if (info == NULL) {
+ connman_network_unref(network);
+ return -ENOMEM;
+ }
+
+ connman_ipaddress_clear(&info->ipv4_address);
+ connman_ipaddress_clear(&info->ipv6_address);
+ info->network = network;
+
+ connman_network_set_string(network, "Path", path);
+ hash_path = connman_network_get_string(network, "Path");
+ if (hash_path == NULL) {
+ connman_network_unref(network);
+ g_free(info);
+ return -EIO;
+ }
+
+ create_service(network);
+
+ connman_network_ref(network);
+ g_hash_table_insert(network_hash, (char *) hash_path, info);
+
+ connman_network_set_available(network, TRUE);
+ connman_network_set_index(network, -1);
+
+ connman_network_set_name(network, "CDMA Network");
+
+ if (modem->has_strength)
+ connman_network_set_strength(network, modem->strength);
+
+ if (connman_device_add_network(device, network) != 0)
+ goto error;
+
+ return 0;
+
+error:
+ connman_network_unref(network);
+ g_hash_table_remove(network_hash, hash_path);
+ return -EIO;
+}
+
static void check_networks_reply(DBusPendingCall *call, void *user_data)
{
char *path = user_data;
@@ -1353,6 +1475,9 @@ static void add_device(const char *path, const char *imsi)
if (modem->has_gprs)
check_gprs(modem);
+
+ if (modem->is_cdma)
+ add_cdma_network(device, "/context1");
}
static void sim_properties_reply(DBusPendingCall *call, void *user_data)
@@ -1407,6 +1532,15 @@ static void get_imsi(const char *path)
DBUS_TYPE_INVALID);
}
+static void cdma_get_imsi(const char *path)
+{
+ DBG("path %s", path);
+
+ call_ofono(path, OFONO_CDMA_SIM_INTERFACE, GET_PROPERTIES,
+ sim_properties_reply, g_strdup(path), g_free,
+ DBUS_TYPE_INVALID);
+}
+
static int gprs_change_powered(const char *path, dbus_bool_t powered)
{
DBG("path %s powered %d", path, powered);
@@ -1462,6 +1596,17 @@ static gboolean modem_has_gprs(DBusMessageIter *array)
return modem_has_interface(array, OFONO_GPRS_INTERFACE);
}
+static gboolean modem_is_cdma(DBusMessageIter *array)
+{
+ return modem_has_interface(array,
+ OFONO_CDMA_CONNECTION_MANAGER_INTERFACE);
+}
+
+static gboolean modem_cdma_has_sim(DBusMessageIter *array)
+{
+ return modem_has_interface(array, OFONO_CDMA_SIM_INTERFACE);
+}
+
static void add_modem(const char *path, DBusMessageIter *prop)
{
struct modem_data *modem;
@@ -1471,6 +1616,8 @@ static void add_modem(const char *path, DBusMessageIter
*prop)
gboolean has_sim = FALSE;
gboolean has_reg = FALSE;
gboolean has_gprs = FALSE;
+ gboolean is_cdma = FALSE;
+ gboolean cdma_has_sim = FALSE;
modem = g_hash_table_lookup(modem_hash, path);
@@ -1505,6 +1652,8 @@ static void add_modem(const char *path, DBusMessageIter
*prop)
has_sim = modem_has_sim(&value);
has_reg = modem_has_reg(&value);
has_gprs = modem_has_gprs(&value);
+ is_cdma = modem_is_cdma(&value);
+ cdma_has_sim = modem_cdma_has_sim(&value);
}
dbus_message_iter_next(prop);
@@ -1519,11 +1668,16 @@ static void add_modem(const char *path, DBusMessageIter
*prop)
modem->has_sim = has_sim;
modem->has_reg = has_reg;
modem->has_gprs = has_gprs;
+ modem->is_cdma = is_cdma;
+ modem->cdma_has_sim = is_cdma;
update_modem_online(modem, online);
if (has_sim)
get_imsi(path);
+
+ if (cdma_has_sim)
+ cdma_get_imsi(path);
}
static void manager_modems_reply(DBusPendingCall *call, void *user_data)
@@ -1634,6 +1788,8 @@ static gboolean modem_changed(DBusConnection *connection,
DBusMessage *message,
modem->has_sim = FALSE;
modem->has_reg = FALSE;
modem->has_gprs = FALSE;
+ modem->is_cdma = FALSE;
+ modem->cdma_has_sim = FALSE;
modem_remove_device(modem);
} else if (g_str_equal(key, "Online") == TRUE) {
@@ -1656,10 +1812,31 @@ static gboolean modem_changed(DBusConnection
*connection, DBusMessage *message,
gboolean had_reg = modem->has_reg;
gboolean has_gprs = modem_has_gprs(&value);
gboolean had_gprs = modem->has_gprs;
+ gboolean is_cdma = modem_is_cdma(&value);
+ gboolean cdma_has_sim = modem_cdma_has_sim(&value);
modem->has_sim = has_sim;
modem->has_reg = has_reg;
modem->has_gprs = has_gprs;
+ modem->is_cdma = is_cdma;
+ modem->cdma_has_sim = cdma_has_sim;
+
+ if (is_cdma) {
+ if (modem->device == NULL) {
+ if (cdma_has_sim)
+ cdma_get_imsi(modem->path);
+ else
+ return TRUE;
+ } else if (!cdma_has_sim) {
+ modem_remove_device(modem);
+ return TRUE;
+ }
+
+ if (modem->device != NULL)
+ add_cdma_network(modem->device, "/context1");
+
+ return TRUE;
+ }
if (modem->device == NULL) {
if (has_sim)
@@ -1886,6 +2063,56 @@ static gboolean context_changed(DBusConnection
*connection,
return TRUE;
}
+static gboolean cdma_changed(DBusConnection *connection,
+ DBusMessage *message, void *user_data)
+{
+ const char *path = dbus_message_get_path(message);
+ struct network_info *info;
+ DBusMessageIter iter, value;
+ const char *key;
+
+ DBG("path %s", path);
+
+ info = g_hash_table_lookup(network_hash, path);
+ if (info == NULL)
+ return TRUE;
+
+ if (!pending_network_is_available(info->network)) {
+ g_hash_table_remove(network_hash, path);
+ return TRUE;
+ }
+
+ connman_network_set_associating(info->network, FALSE);
+
+ 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);
+
+ DBG("key %s", key);
+
+ if (g_str_equal(key, "Settings") == TRUE)
+ update_ipv4_settings(&value, info);
+ else if (g_str_equal(key, "Powered") == TRUE) {
+ dbus_bool_t active;
+
+ dbus_message_iter_get_basic(&value, &active);
+
+ if (active == FALSE)
+ set_connected(info, active);
+
+ /* Connect only if requested to do so */
+ if (active == TRUE &&
+ connman_network_get_connecting(info->network) == TRUE)
+ set_connected(info, active);
+ }
+
+ return TRUE;
+}
+
static guint watch;
static guint reg_watch;
static guint sim_watch;
@@ -1896,6 +2123,8 @@ static guint modem_watch;
static guint modem_added_watch;
static guint modem_removed_watch;
static guint context_watch;
+static guint cdma_watch;
+static guint cdma_sim_watch;
static int ofono_init(void)
{
@@ -1962,11 +2191,24 @@ static int ofono_init(void)
context_changed,
NULL, NULL);
+ cdma_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
+ OFONO_CDMA_CONNECTION_MANAGER_INTERFACE,
+ PROPERTY_CHANGED,
+ cdma_changed,
+ NULL, NULL);
+
+ cdma_sim_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
+ OFONO_CDMA_SIM_INTERFACE,
+ PROPERTY_CHANGED,
+ sim_changed,
+ NULL, NULL);
+
if (watch == 0 || gprs_watch == 0 || context_added_watch == 0 ||
context_removed_watch == 0 || modem_watch == 0 ||
reg_watch == 0 || sim_watch == 0 ||
modem_added_watch == 0 || modem_removed_watch == 0 ||
- context_watch == 0) {
+ context_watch == 0 || cdma_watch == 0 ||
+ cdma_sim_watch == 0) {
err = -EIO;
goto remove;
}
@@ -1994,6 +2236,8 @@ remove:
g_dbus_remove_watch(connection, modem_added_watch);
g_dbus_remove_watch(connection, modem_removed_watch);
g_dbus_remove_watch(connection, context_watch);
+ g_dbus_remove_watch(connection, cdma_watch);
+ g_dbus_remove_watch(connection, cdma_sim_watch);
dbus_connection_unref(connection);
--
1.7.1
_______________________________________________
connman mailing list
[email protected]
http://lists.connman.net/listinfo/connman