--- 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 _______________________________________________ connman mailing list connman@connman.net http://lists.connman.net/listinfo/connman