ofono: Cancel pending SetProperty
[framework/connectivity/connman.git] / plugins / ofono.c
index 47a4b99..f15c36d 100644 (file)
@@ -153,6 +153,24 @@ struct modem_data {
        DBusPendingCall *call_get_contexts;
 };
 
+static const char *api2string(enum ofono_api api)
+{
+       switch (api) {
+       case OFONO_API_SIM:
+               return "sim";
+       case OFONO_API_NETREG:
+               return "netreg";
+       case OFONO_API_CM:
+               return "cm";
+       case OFONO_API_CDMA_NETREG:
+               return "cdma-netreg";
+       case OFONO_API_CDMA_CM:
+               return "cmda-cm";
+       }
+
+       return "unknown";
+}
+
 static char *get_ident(const char *path)
 {
        char *pos;
@@ -320,8 +338,10 @@ static int set_property(struct modem_data *modem,
        DBG("%s path %s %s.%s", modem->path, path, interface, property);
 
        if (modem->call_set_property != NULL) {
-               connman_error("Pending SetProperty");
-               return -EBUSY;
+               DBG("Cancel pending SetProperty");
+
+               dbus_pending_call_cancel(modem->call_set_property);
+               modem->call_set_property = NULL;
        }
 
        message = dbus_message_new_method_call(OFONO_SERVICE, path,
@@ -914,6 +934,7 @@ static void create_device(struct modem_data *modem)
 
        modem->device = device;
 
+       connman_device_set_powered(modem->device, modem->online);
 out:
        g_free(ident);
 }
@@ -979,6 +1000,26 @@ static void add_network(struct modem_data *modem)
                modem->network = NULL;
                return;
        }
+
+       /*
+        * Create the ipconfig layer before trying to connect. Withouth
+        * the ipconfig layer the core is not ready to process errors.
+        */
+       connman_network_set_index(modem->network, -1);
+}
+
+static void remove_network(struct modem_data *modem)
+{
+       DBG("%s", modem->path);
+
+       if (modem->network == NULL)
+               return;
+
+       DBG("network %p", modem->network);
+
+       connman_device_remove_network(modem->device, modem->network);
+       connman_network_unref(modem->network);
+       modem->network = NULL;
 }
 
 static int add_cm_context(struct modem_data *modem, const char *context_path,
@@ -1466,6 +1507,9 @@ static void add_cdma_network(struct modem_data *modem)
        if (modem->context == NULL)
                modem->context = network_context_alloc(modem->path);
 
+       if (modem->name == NULL)
+               modem->name = g_strdup("CDMA Network");
+
        add_network(modem);
 
        if (modem->cdma_cm_powered == TRUE)
@@ -1632,9 +1676,6 @@ static void cdma_cm_update_settings(struct modem_data *modem,
 {
        DBG("%s Settings", modem->path);
 
-       if (modem->context != NULL)
-               return;
-
        extract_ipv4_settings(value, modem->context);
 }
 
@@ -1731,33 +1772,6 @@ static int cdma_cm_get_properties(struct modem_data *modem)
                                cdma_cm_properties_reply, modem);
 }
 
-static connman_bool_t connection_manager_init(struct modem_data *modem)
-{
-       if (has_interface(modem->interfaces, OFONO_API_CM) == TRUE) {
-               if (ready_to_create_device(modem) == TRUE)
-                       create_device(modem);
-
-               if (modem->device != NULL) {
-                       cm_get_properties(modem);
-                       cm_get_contexts(modem);
-               }
-
-               return TRUE;
-       }
-
-       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 TRUE;
-       }
-
-       return FALSE;
-}
-
 static void sim_update_imsi(struct modem_data *modem,
                                DBusMessageIter* value)
 {
@@ -1797,17 +1811,16 @@ static gboolean sim_changed(DBusConnection *connection, DBusMessage *message,
        if (g_str_equal(key, "SubscriberIdentity") == TRUE) {
                sim_update_imsi(modem, &value);
 
-               if (modem->online == FALSE) {
-                       modem_set_online(modem, TRUE);
-               } else if (has_interface(modem->interfaces,
-                                               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);
-               }
+               if (ready_to_create_device(modem) == FALSE)
+                       return TRUE;
+
+               /*
+                * This is a GSM modem. Create the device and
+                * register it at the core. Enabling (setting
+                * it online is done through the
+                * modem_enable() callback.
+                */
+               create_device(modem);
        }
 
        return TRUE;
@@ -1830,8 +1843,31 @@ static void sim_properties_reply(struct modem_data *modem,
 
                if (g_str_equal(key, "SubscriberIdentity") == TRUE) {
                        sim_update_imsi(modem, &value);
-                       connection_manager_init(modem);
 
+                       if (ready_to_create_device(modem) == FALSE)
+                               return;
+
+                       /*
+                        * This is a GSM modem. Create the device and
+                        * register it at the core. Enabling (setting
+                        * it online is done through the
+                        * modem_enable() callback.
+                        */
+                       create_device(modem);
+
+                       if (modem->online == FALSE)
+                               return;
+
+                       /*
+                        * The modem is already online and we have the CM interface.
+                        * There will be no interface update and therefore our
+                        * state machine will not go to next step. We have to
+                        * trigger it from here.
+                        */
+                       if (has_interface(modem->interfaces, OFONO_API_CM) == TRUE) {
+                               cm_get_properties(modem);
+                               cm_get_contexts(modem);
+                       }
                        return;
                }
 
@@ -1845,6 +1881,88 @@ static int sim_get_properties(struct modem_data *modem)
                                sim_properties_reply, modem);
 }
 
+static connman_bool_t api_added(uint8_t old_iface, uint8_t new_iface,
+                               enum ofono_api api)
+{
+       if (has_interface(old_iface, api) == FALSE &&
+                       has_interface(new_iface, api) == TRUE) {
+               DBG("%s added", api2string(api));
+               return TRUE;
+       }
+
+       return FALSE;
+}
+
+static connman_bool_t api_removed(uint8_t old_iface, uint8_t new_iface,
+                               enum ofono_api api)
+{
+       if (has_interface(old_iface, api) == TRUE &&
+                       has_interface(new_iface, api) == FALSE) {
+               DBG("%s removed", api2string(api));
+               return TRUE;
+       }
+
+       return FALSE;
+}
+
+static void modem_update_interfaces(struct modem_data *modem,
+                               uint8_t old_ifaces,
+                               uint8_t new_ifaces)
+{
+       DBG("%s", modem->path);
+
+       if (api_added(old_ifaces, new_ifaces, OFONO_API_SIM) == TRUE) {
+               if (modem->imsi == NULL &&
+                               modem->set_powered == FALSE) {
+                       /*
+                        * Only use do GetProperties() when
+                        * device has not been powered up.
+                        */
+                       sim_get_properties(modem);
+               }
+       }
+
+       if (api_added(old_ifaces, new_ifaces, OFONO_API_CM) == TRUE) {
+               if (modem->device != NULL) {
+                       cm_get_properties(modem);
+                       cm_get_contexts(modem);
+               }
+       }
+
+       if (api_added(old_ifaces, new_ifaces, OFONO_API_CDMA_CM) == TRUE) {
+               if (ready_to_create_device(modem) == TRUE)
+                       create_device(modem);
+
+               if (modem->device != NULL)
+                       cdma_cm_get_properties(modem);
+       }
+
+       if (api_added(old_ifaces, new_ifaces, OFONO_API_NETREG) == TRUE) {
+               if (modem->attached == TRUE)
+                       netreg_get_properties(modem);
+       }
+
+       if (api_added(old_ifaces, new_ifaces, OFONO_API_CDMA_NETREG) == TRUE) {
+               cdma_netreg_get_properties(modem);
+       }
+
+       if (api_removed(old_ifaces, new_ifaces, OFONO_API_CM) == TRUE) {
+               remove_cm_context(modem, modem->context->path);
+       }
+
+       if (api_removed(old_ifaces, new_ifaces, OFONO_API_CDMA_CM) == TRUE) {
+               remove_cm_context(modem, modem->context->path);
+       }
+
+       if (api_removed(old_ifaces, new_ifaces, OFONO_API_NETREG) == TRUE) {
+               remove_network(modem);
+       }
+
+       if (api_removed(old_ifaces, new_ifaces, OFONO_API_CDMA_NETREG == TRUE)) {
+               remove_network(modem);
+       }
+}
+
 static gboolean modem_changed(DBusConnection *connection, DBusMessage *message,
                                void *user_data)
 {
@@ -1880,10 +1998,10 @@ static gboolean modem_changed(DBusConnection *connection, DBusMessage *message,
 
                DBG("%s Online %d", modem->path, modem->online);
 
-               if (modem->online == FALSE)
+               if (modem->device == NULL)
                        return TRUE;
 
-               connection_manager_init(modem);
+               connman_device_set_powered(modem->device, modem->online);
        } else if (g_str_equal(key, "Interfaces") == TRUE) {
                uint8_t interfaces;
 
@@ -1892,41 +2010,11 @@ static gboolean modem_changed(DBusConnection *connection, DBusMessage *message,
                if (interfaces == modem->interfaces)
                        return TRUE;
 
-               modem->interfaces = interfaces;
-
-               DBG("%s Interfaces 0x%02x", modem->path,
-                       modem->interfaces);
-
-               if (has_interface(modem->interfaces, OFONO_API_SIM) == TRUE) {
-                       if (modem->imsi == NULL &&
-                                       modem->set_powered == FALSE) {
-                               /*
-                                * Only use do GetProperties() when
-                                * device has not been powered up.
-                                */
-                               sim_get_properties(modem);
-                               return TRUE;
-                       }
-               }
-
-               if (connection_manager_init(modem) == FALSE) {
-                       if (modem->context != NULL) {
-                               remove_cm_context(modem,
-                                               modem->context->path);
-                       }
+               DBG("%s Interfaces 0x%02x", modem->path, interfaces);
 
-                       if (modem->device != NULL)
-                               destroy_device(modem);
+               modem_update_interfaces(modem, modem->interfaces, interfaces);
 
-                       return TRUE;
-               }
-
-               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);
+               modem->interfaces = interfaces;
        } else if (g_str_equal(key, "Serial") == TRUE) {
                char *serial;
 
@@ -1937,7 +2025,11 @@ static gboolean modem_changed(DBusConnection *connection, DBusMessage *message,
 
                DBG("%s Serial %s", modem->path, modem->serial);
 
-               connection_manager_init(modem);
+               if (has_interface(modem->interfaces,
+                                        OFONO_API_CDMA_CM) == TRUE) {
+                       if (ready_to_create_device(modem) == TRUE)
+                               create_device(modem);
+               }
        }
 
        return TRUE;
@@ -2015,12 +2107,12 @@ static void add_modem(const char *path, DBusMessageIter *prop)
        if (modem->ignore == TRUE)
                return;
 
-       if (modem->powered == FALSE)
+       if (modem->powered == FALSE) {
                modem_set_powered(modem, TRUE);
-       else if (has_interface(modem->interfaces, OFONO_API_SIM) == TRUE)
-               sim_get_properties(modem);
-       else
-               connection_manager_init(modem);
+               return;
+       }
+
+       modem_update_interfaces(modem, 0, modem->interfaces);
 }
 
 static void modem_power_down(gpointer key, gpointer value, gpointer user_data)
@@ -2319,6 +2411,22 @@ static struct connman_device_driver modem_driver = {
        .disable        = modem_disable,
 };
 
+static int tech_probe(struct connman_technology *technology)
+{
+       return 0;
+}
+
+static void tech_remove(struct connman_technology *technology)
+{
+}
+
+static struct connman_technology_driver tech_driver = {
+       .name           = "cellular",
+       .type           = CONNMAN_SERVICE_TYPE_CELLULAR,
+       .probe          = tech_probe,
+       .remove         = tech_remove,
+};
+
 static guint watch;
 static guint modem_added_watch;
 static guint modem_removed_watch;
@@ -2433,6 +2541,13 @@ static int ofono_init(void)
                goto remove;
        }
 
+       err = connman_technology_driver_register(&tech_driver);
+       if (err < 0) {
+               connman_device_driver_unregister(&modem_driver);
+               connman_network_driver_unregister(&network_driver);
+               goto remove;
+       }
+
        return 0;
 
 remove:
@@ -2476,6 +2591,7 @@ static void ofono_exit(void)
                context_hash = NULL;
        }
 
+       connman_technology_driver_unregister(&tech_driver);
        connman_device_driver_unregister(&modem_driver);
        connman_network_driver_unregister(&network_driver);