Merge remote-tracking branch 'cros/upstream' into 'cros/master'

Change-Id: I54cc0c03c5da6956b6f438310bfa0f130e243b87
diff --git a/include/ModemManager-compat.h b/include/ModemManager-compat.h
index 6d65d50..974b69b 100644
--- a/include/ModemManager-compat.h
+++ b/include/ModemManager-compat.h
@@ -20,8 +20,6 @@
 #error "Only <ModemManager.h> can be included directly."
 #endif
 
-#include <glib.h>
-
 #include <ModemManager-enums.h>
 
 #ifndef MM_DISABLE_DEPRECATED
@@ -35,8 +33,15 @@
  * avoid unnecessary API/ABI breaks.
  */
 
+/* deprecated attribute support since gcc 3.1 */
+#if defined __GNUC__ && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
+# define MM_DEPRECATED __attribute__((__deprecated__))
+#else
+# define MM_DEPRECATED
+#endif
+
 /* The following type exists just so that we can get deprecation warnings */
-G_DEPRECATED
+MM_DEPRECATED
 typedef int MMModemBandDeprecated;
 
 /**
diff --git a/plugins/ublox/mm-broadband-modem-ublox.c b/plugins/ublox/mm-broadband-modem-ublox.c
index 0d4dd59..56441d7 100644
--- a/plugins/ublox/mm-broadband-modem-ublox.c
+++ b/plugins/ublox/mm-broadband-modem-ublox.c
@@ -59,6 +59,9 @@
 
     /* Band management */
     FeatureSupport uact;
+
+    /* Regex to ignore */
+    GRegex *pbready_regex;
 };
 
 /*****************************************************************************/
@@ -1000,13 +1003,14 @@
 /* Setup ports (Broadband modem class) */
 
 static void
-setup_ports (MMBroadbandModem *self)
+setup_ports (MMBroadbandModem *_self)
 {
-    MMPortSerialAt *ports[2];
-    guint           i;
+    MMBroadbandModemUblox *self = MM_BROADBAND_MODEM_UBLOX (_self);
+    MMPortSerialAt        *ports[2];
+    guint                  i;
 
     /* Call parent's setup ports first always */
-    MM_BROADBAND_MODEM_CLASS (mm_broadband_modem_ublox_parent_class)->setup_ports (self);
+    MM_BROADBAND_MODEM_CLASS (mm_broadband_modem_ublox_parent_class)->setup_ports (_self);
 
     ports[0] = mm_base_modem_peek_port_primary   (MM_BASE_MODEM (self));
     ports[1] = mm_base_modem_peek_port_secondary (MM_BASE_MODEM (self));
@@ -1019,6 +1023,11 @@
         g_object_set (ports[i],
                       MM_PORT_SERIAL_SEND_DELAY, (guint64) 0,
                       NULL);
+
+        mm_port_serial_at_add_unsolicited_msg_handler (
+            ports[i],
+            self->priv->pbready_regex,
+            NULL, NULL, NULL);
     }
 }
 
@@ -1051,6 +1060,9 @@
     self->priv->mode = MM_UBLOX_NETWORKING_MODE_UNKNOWN;
     self->priv->any_allowed = MM_MODEM_MODE_NONE;
     self->priv->uact = FEATURE_SUPPORT_UNKNOWN;
+
+    self->priv->pbready_regex = g_regex_new ("\\r\\n\\+PBREADY\\r\\n",
+                                             G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
 }
 
 static void
@@ -1085,6 +1097,16 @@
 }
 
 static void
+finalize (GObject *object)
+{
+    MMBroadbandModemUblox *self = MM_BROADBAND_MODEM_UBLOX (object);
+
+    g_regex_unref (self->priv->pbready_regex);
+
+    G_OBJECT_CLASS (mm_broadband_modem_ublox_parent_class)->finalize (object);
+}
+
+static void
 mm_broadband_modem_ublox_class_init (MMBroadbandModemUbloxClass *klass)
 {
     GObjectClass          *object_class = G_OBJECT_CLASS (klass);
@@ -1092,5 +1114,7 @@
 
     g_type_class_add_private (object_class, sizeof (MMBroadbandModemUbloxPrivate));
 
+    object_class->finalize = finalize;
+
     broadband_modem_class->setup_ports = setup_ports;
 }
diff --git a/src/mm-base-manager.c b/src/mm-base-manager.c
index 1673c25..4b92ab0 100644
--- a/src/mm-base-manager.c
+++ b/src/mm-base-manager.c
@@ -628,7 +628,7 @@
     if (device) {
         g_cancellable_cancel (mm_base_modem_peek_cancellable (modem));
         mm_device_remove_modem (device);
-        g_hash_table_remove (self->priv->devices, device);
+        g_hash_table_remove (self->priv->devices, mm_device_get_uid (device));
     }
 }
 
diff --git a/src/mm-broadband-modem-qmi.c b/src/mm-broadband-modem-qmi.c
index 1154679..d87c39a 100644
--- a/src/mm-broadband-modem-qmi.c
+++ b/src/mm-broadband-modem-qmi.c
@@ -4744,6 +4744,8 @@
     /* Report new registration states */
     mm_iface_modem_3gpp_update_cs_registration_state (MM_IFACE_MODEM_3GPP (self), mm_cs_registration_state);
     mm_iface_modem_3gpp_update_ps_registration_state (MM_IFACE_MODEM_3GPP (self), mm_ps_registration_state);
+    if (mm_access_technologies & MM_MODEM_ACCESS_TECHNOLOGY_LTE)
+        mm_iface_modem_3gpp_update_eps_registration_state (MM_IFACE_MODEM_3GPP (self), mm_ps_registration_state);
 
     /* Get 3GPP location LAC and CI */
     lac = 0;
@@ -5199,6 +5201,7 @@
     guint16 lac;
     guint32 cid;
     gchar *operator_id;
+    gboolean has_lte_info;
 
     ps_registration_state = MM_MODEM_3GPP_REGISTRATION_STATE_UNKNOWN;
     cs_registration_state = MM_MODEM_3GPP_REGISTRATION_STATE_UNKNOWN;
@@ -5210,12 +5213,13 @@
      *   LTE > WCDMA > GSM
      * The first one giving results will be the one reported.
      */
-    if (!process_lte_info (response_output, indication_output,
-                           &cs_registration_state,
-                           &ps_registration_state,
-                           &lac,
-                           &cid,
-                           &operator_id) &&
+    has_lte_info = process_lte_info (response_output, indication_output,
+                                     &cs_registration_state,
+                                     &ps_registration_state,
+                                     &lac,
+                                     &cid,
+                                     &operator_id);
+    if (!has_lte_info &&
         !process_wcdma_info (response_output, indication_output,
                              &cs_registration_state,
                              &ps_registration_state,
@@ -5240,6 +5244,8 @@
     /* Report new registration states */
     mm_iface_modem_3gpp_update_cs_registration_state (MM_IFACE_MODEM_3GPP (self), cs_registration_state);
     mm_iface_modem_3gpp_update_ps_registration_state (MM_IFACE_MODEM_3GPP (self), ps_registration_state);
+    if (has_lte_info)
+        mm_iface_modem_3gpp_update_eps_registration_state (MM_IFACE_MODEM_3GPP (self), ps_registration_state);
     mm_iface_modem_3gpp_update_location (MM_IFACE_MODEM_3GPP (self), lac, cid);
 }
 
diff --git a/src/mm-broadband-modem.c b/src/mm-broadband-modem.c
index ecefcf2..dfb0425 100644
--- a/src/mm-broadband-modem.c
+++ b/src/mm-broadband-modem.c
@@ -8146,7 +8146,6 @@
 typedef struct {
     MMBroadbandModem *self;
     GSimpleAsyncResult *result;
-    GError *error;
     gboolean has_qcdm_port;
     gboolean has_sprint_commands;
 } SetupRegistrationChecksContext;
@@ -8154,44 +8153,39 @@
 static void
 setup_registration_checks_context_complete_and_free (SetupRegistrationChecksContext *ctx)
 {
-    if (ctx->error)
-        g_simple_async_result_take_error (ctx->result, ctx->error);
-    else {
-        SetupRegistrationChecksResults *results;
+    SetupRegistrationChecksResults *results;
 
-        results = g_new0 (SetupRegistrationChecksResults, 1);
+    results = g_new0 (SetupRegistrationChecksResults, 1);
 
-        /* Skip QCDM steps if no QCDM port */
-        if (!ctx->has_qcdm_port) {
-            mm_dbg ("Will skip all QCDM-based registration checks");
-            results->skip_qcdm_call_manager_step = TRUE;
-            results->skip_qcdm_hdr_step = TRUE;
-        }
-
-        if (MM_IFACE_MODEM_CDMA_GET_INTERFACE (ctx->self)->get_detailed_registration_state ==
-            modem_cdma_get_detailed_registration_state) {
-            /* Skip CDMA1x Serving System check if we have Sprint specific
-             * commands AND if the default detailed registration checker
-             * is the generic one. Implementations knowing that their
-             * CSS response is undesired, should either setup NULL callbacks
-             * for the specific step, or subclass this setup and return
-             * FALSE themselves. */
-            if (ctx->has_sprint_commands) {
-                mm_dbg ("Will skip CDMA1x Serving System check, "
-                        "we do have Sprint commands");
-                results->skip_at_cdma1x_serving_system_step = TRUE;
-            } else {
-                /* If there aren't Sprint specific commands, and the detailed
-                 * registration state getter wasn't subclassed, skip the step */
-                mm_dbg ("Will skip generic detailed registration check, we "
-                        "don't have Sprint commands");
-                results->skip_detailed_registration_state = TRUE;
-            }
-        }
-
-        g_simple_async_result_set_op_res_gpointer (ctx->result, results, g_free);
+    /* Skip QCDM steps if no QCDM port */
+    if (!ctx->has_qcdm_port) {
+        mm_dbg ("Will skip all QCDM-based registration checks");
+        results->skip_qcdm_call_manager_step = TRUE;
+        results->skip_qcdm_hdr_step = TRUE;
     }
 
+    if (MM_IFACE_MODEM_CDMA_GET_INTERFACE (ctx->self)->get_detailed_registration_state ==
+        modem_cdma_get_detailed_registration_state) {
+        /* Skip CDMA1x Serving System check if we have Sprint specific
+         * commands AND if the default detailed registration checker
+         * is the generic one. Implementations knowing that their
+         * CSS response is undesired, should either setup NULL callbacks
+         * for the specific step, or subclass this setup and return
+         * FALSE themselves. */
+        if (ctx->has_sprint_commands) {
+            mm_dbg ("Will skip CDMA1x Serving System check, "
+                    "we do have Sprint commands");
+            results->skip_at_cdma1x_serving_system_step = TRUE;
+        } else {
+            /* If there aren't Sprint specific commands, and the detailed
+             * registration state getter wasn't subclassed, skip the step */
+            mm_dbg ("Will skip generic detailed registration check, we "
+                    "don't have Sprint commands");
+            results->skip_detailed_registration_state = TRUE;
+        }
+    }
+
+    g_simple_async_result_set_op_res_gpointer (ctx->result, results, g_free);
     g_simple_async_result_complete_in_idle (ctx->result);
     g_object_unref (ctx->result);
     g_object_unref (ctx->self);
@@ -8702,7 +8696,7 @@
     mm_base_modem_at_command (MM_BASE_MODEM (self),
                               "+CESQ",
                               3,
-                              TRUE,
+                              FALSE,
                               callback,
                               user_data);
 }
diff --git a/src/mm-iface-modem-3gpp.c b/src/mm-iface-modem-3gpp.c
index 89023a4..4ac32fd 100644
--- a/src/mm-iface-modem-3gpp.c
+++ b/src/mm-iface-modem-3gpp.c
@@ -119,6 +119,17 @@
     return ctx;
 }
 
+static gboolean
+reg_state_is_registered (MMModem3gppRegistrationState state)
+{
+    return state == MM_MODEM_3GPP_REGISTRATION_STATE_HOME ||
+        state == MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING ||
+        state == MM_MODEM_3GPP_REGISTRATION_STATE_HOME_SMS_ONLY ||
+        state == MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING_SMS_ONLY ||
+        state == MM_MODEM_3GPP_REGISTRATION_STATE_HOME_CSFB_NOT_PREFERRED ||
+        state == MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING_CSFB_NOT_PREFERRED;
+}
+
 static MMModem3gppRegistrationState
 get_consolidated_reg_state (RegistrationStateContext *ctx)
 {
@@ -307,12 +318,7 @@
     }
 
     /* If we got registered, end registration checks */
-    if (current_registration_state == MM_MODEM_3GPP_REGISTRATION_STATE_HOME ||
-        current_registration_state == MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING ||
-        current_registration_state == MM_MODEM_3GPP_REGISTRATION_STATE_HOME_SMS_ONLY ||
-        current_registration_state == MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING_SMS_ONLY ||
-        current_registration_state == MM_MODEM_3GPP_REGISTRATION_STATE_HOME_CSFB_NOT_PREFERRED ||
-        current_registration_state == MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING_CSFB_NOT_PREFERRED) {
+    if (reg_state_is_registered (current_registration_state)) {
         /* Request immediate access tech and signal update: we may have changed
          * from home to roaming or viceversa, both registered states, so there
          * wouldn't be an explicit refresh triggered from the modem interface as
@@ -436,9 +442,11 @@
     }
     /* Automatic registration requested? */
     else {
+        MMModem3gppRegistrationState reg_state = mm_gdbus_modem3gpp_get_registration_state (ctx->skeleton);
+
         /* If the modem is already registered and the last time it was asked
          * automatic registration, we're done */
-        if (current_operator_code &&
+        if ((current_operator_code || reg_state_is_registered (reg_state)) &&
             !registration_state_context->manual_registration) {
             mm_dbg ("Already registered in network '%s',"
                     " automatic registration not launched...",
@@ -1195,13 +1203,7 @@
 
     /* Even if registration state didn't change, report access technology,
      * but only if something valid to report */
-    if (state == MM_MODEM_3GPP_REGISTRATION_STATE_HOME ||
-        state == MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING ||
-        state == MM_MODEM_3GPP_REGISTRATION_STATE_HOME_SMS_ONLY ||
-        state == MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING_SMS_ONLY ||
-        state == MM_MODEM_3GPP_REGISTRATION_STATE_HOME_CSFB_NOT_PREFERRED ||
-        state == MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING_CSFB_NOT_PREFERRED ||
-        ctx->reloading_registration_info) {
+    if (reg_state_is_registered (state) || ctx->reloading_registration_info) {
         if (access_tech != MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN)
             mm_iface_modem_update_access_technologies (MM_IFACE_MODEM (self),
                                                        access_tech,
@@ -1234,13 +1236,7 @@
      * location updates, but only if something valid to report. For the case
      * where we're registering (loading current registration info after a state
      * change to registered), we also allow LAC/CID updates. */
-    if (ctx->reloading_registration_info ||
-        state == MM_MODEM_3GPP_REGISTRATION_STATE_HOME ||
-        state == MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING ||
-        state == MM_MODEM_3GPP_REGISTRATION_STATE_HOME_SMS_ONLY ||
-        state == MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING_SMS_ONLY ||
-        state == MM_MODEM_3GPP_REGISTRATION_STATE_HOME_CSFB_NOT_PREFERRED ||
-        state == MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING_CSFB_NOT_PREFERRED) {
+    if (reg_state_is_registered (state) || ctx->reloading_registration_info) {
         if (location_area_code > 0 && cell_id > 0)
             mm_iface_modem_location_3gpp_update_lac_ci (MM_IFACE_MODEM_LOCATION (self),
                                                         location_area_code,
@@ -1292,12 +1288,7 @@
      * sent by the carrier during registration or b) by looking at the
      * registration reject error code.  If b), we want to make sure we
      * preserve the subscription state */
-    if (old_state == MM_MODEM_3GPP_REGISTRATION_STATE_HOME ||
-        old_state == MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING ||
-        old_state == MM_MODEM_3GPP_REGISTRATION_STATE_HOME_SMS_ONLY ||
-        old_state == MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING_SMS_ONLY ||
-        old_state == MM_MODEM_3GPP_REGISTRATION_STATE_HOME_CSFB_NOT_PREFERRED ||
-        old_state == MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING_CSFB_NOT_PREFERRED)
+    if (reg_state_is_registered (old_state))
         clear_subscription_state (self);
 
     /* The property in the interface is bound to the property
@@ -1334,12 +1325,7 @@
     if (new_state == old_state)
         return;
 
-    if (new_state == MM_MODEM_3GPP_REGISTRATION_STATE_HOME ||
-        new_state == MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING ||
-        new_state == MM_MODEM_3GPP_REGISTRATION_STATE_HOME_SMS_ONLY ||
-        new_state == MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING_SMS_ONLY ||
-        new_state == MM_MODEM_3GPP_REGISTRATION_STATE_HOME_CSFB_NOT_PREFERRED ||
-        new_state == MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING_CSFB_NOT_PREFERRED) {
+    if (reg_state_is_registered (new_state)) {
         MMModemState modem_state;
 
         /* If already reloading registration info, skip it */