diff --git a/plugins/mm-modem-gobi-gsm.c b/plugins/mm-modem-gobi-gsm.c
index 3b9e9ec..252a64a 100644
--- a/plugins/mm-modem-gobi-gsm.c
+++ b/plugins/mm-modem-gobi-gsm.c
@@ -24,6 +24,7 @@
 #include "mm-callback-info.h"
 #include "mm-modem-gsm-card.h"
 #include "mm-at-serial-port.h"
+#include "mm-modem-helpers.h"
 
 static void modem_init (MMModem *modem_class);
 static void modem_gsm_card_init (MMModemGsmCard *gsm_card_class);
@@ -36,7 +37,9 @@ G_DEFINE_TYPE_EXTENDED (MMModemGobiGsm, mm_modem_gobi_gsm, MM_TYPE_GENERIC_GSM,
 MMModem *
 mm_modem_gobi_gsm_new (const char *device,
                        const char *driver,
-                       const char *plugin)
+                       const char *plugin,
+                       guint32 vendor,
+                       guint32 product)
 {
     g_return_val_if_fail (device != NULL, NULL);
     g_return_val_if_fail (driver != NULL, NULL);
@@ -52,6 +55,50 @@ mm_modem_gobi_gsm_new (const char *device,
 /*****************************************************************************/
 
 static void
+get_act_request_done (MMAtSerialPort *port,
+                      GString *response,
+                      GError *error,
+                      gpointer user_data)
+{
+    MMCallbackInfo *info = user_data;
+    MMModemGsmAccessTech act = MM_MODEM_GSM_ACCESS_TECH_UNKNOWN;
+    const char *p;
+
+    if (error)
+        info->error = g_error_copy (error);
+    else {
+        p = mm_strip_tag (response->str, "*CNTI:");
+        p = strchr (p, ',');
+        if (p)
+            act = mm_gsm_string_to_access_tech (p + 1);
+    }
+
+    mm_callback_info_set_result (info, GUINT_TO_POINTER (act), NULL);
+    mm_callback_info_schedule (info);
+}
+
+static void
+get_access_technology (MMGenericGsm *modem,
+                       MMModemUIntFn callback,
+                       gpointer user_data)
+{
+    MMAtSerialPort *port;
+    MMCallbackInfo *info;
+
+    info = mm_callback_info_uint_new (MM_MODEM (modem), callback, user_data);
+
+    port = mm_generic_gsm_get_best_at_port (modem, &info->error);
+    if (!port) {
+        mm_callback_info_schedule (info);
+        return;
+    }
+
+    mm_at_serial_port_queue_command (port, "*CNTI=0", 3, get_act_request_done, info);
+}
+
+/*****************************************************************************/
+
+static void
 get_string_done (MMAtSerialPort *port,
                  GString *response,
                  GError *error,
@@ -109,5 +156,8 @@ mm_modem_gobi_gsm_init (MMModemGobiGsm *self)
 static void
 mm_modem_gobi_gsm_class_init (MMModemGobiGsmClass *klass)
 {
+    MMGenericGsmClass *gsm_class = MM_GENERIC_GSM_CLASS (klass);
+
+    gsm_class->get_access_technology = get_access_technology;
 }
 
diff --git a/plugins/mm-modem-gobi-gsm.h b/plugins/mm-modem-gobi-gsm.h
index 4bd262f..b1af164 100644
--- a/plugins/mm-modem-gobi-gsm.h
+++ b/plugins/mm-modem-gobi-gsm.h
@@ -38,6 +38,8 @@ GType mm_modem_gobi_gsm_get_type (void);
 
 MMModem *mm_modem_gobi_gsm_new (const char *device,
                                 const char *driver,
-                                const char *plugin_name);
+                                const char *plugin_name,
+                                guint32 vendor,
+                                guint32 product);
 
 #endif /* MM_MODEM_GOBI_GSM_H */
diff --git a/plugins/mm-plugin-gobi.c b/plugins/mm-plugin-gobi.c
index fbe3878..b91d515 100644
--- a/plugins/mm-plugin-gobi.c
+++ b/plugins/mm-plugin-gobi.c
@@ -68,7 +68,6 @@ supports_port (MMPluginBase *base,
                MMPluginBaseSupportsTask *task)
 {
     GUdevDevice *port;
-    guint32 cached = 0, level;
     const char *driver;
 
     /* Can't do anything with non-serial ports */
@@ -80,15 +79,6 @@ supports_port (MMPluginBase *base,
     if (!driver || strcmp (driver, "qcserial"))
         return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
 
-    if (mm_plugin_base_get_cached_port_capabilities (base, port, &cached)) {
-        level = get_level_for_capabilities (cached);
-        if (level) {
-            mm_plugin_base_supports_task_complete (task, level);
-            return MM_PLUGIN_SUPPORTS_PORT_IN_PROGRESS;
-        }
-        return MM_PLUGIN_SUPPORTS_PORT_UNSUPPORTED;
-    }
-
     /* Otherwise kick off a probe */
     if (mm_plugin_base_probe_port (base, task, NULL))
         return MM_PLUGIN_SUPPORTS_PORT_IN_PROGRESS;
@@ -106,6 +96,7 @@ grab_port (MMPluginBase *base,
     MMModem *modem = NULL;
     const char *name, *subsys, *sysfs_path;
     guint32 caps;
+    guint16 vendor = 0, product = 0;
 
     port = mm_plugin_base_supports_task_get_port (task);
     g_assert (port);
@@ -113,13 +104,20 @@ grab_port (MMPluginBase *base,
     subsys = g_udev_device_get_subsystem (port);
     name = g_udev_device_get_name (port);
 
+    if (!mm_plugin_base_get_device_ids (base, subsys, name, &vendor, &product)) {
+        g_set_error (error, 0, 0, "Could not get modem product ID.");
+        return NULL;
+    }
+
     caps = mm_plugin_base_supports_task_get_probed_capabilities (task);
     sysfs_path = mm_plugin_base_supports_task_get_physdev_path (task);
     if (!existing) {
         if (caps & MM_PLUGIN_BASE_PORT_CAP_GSM) {
             modem = mm_modem_gobi_gsm_new (sysfs_path,
                                            mm_plugin_base_supports_task_get_driver (task),
-                                           mm_plugin_get_name (MM_PLUGIN (base)));
+                                           mm_plugin_get_name (MM_PLUGIN (base)),
+                                           vendor,
+                                           product);
         } else if (caps & CAP_CDMA) {
             modem = mm_generic_cdma_new (sysfs_path,
                                          mm_plugin_base_supports_task_get_driver (task),
diff --git a/src/mm-generic-gsm.c b/src/mm-generic-gsm.c
index ce58b2c..8ff86d3 100644
--- a/src/mm-generic-gsm.c
+++ b/src/mm-generic-gsm.c
@@ -1625,7 +1625,7 @@ reg_status_updated (MMGenericGsm *self, int new_value, GError **error)
 
     switch (new_value) {
     case 0:
-        status = MM_MODEM_GSM_NETWORK_REG_STATUS_IDLE;
+        status = MM_MODEM_GSM_NETWORK_REG_STATUS_HOME;
         break;
     case 1:
         status = MM_MODEM_GSM_NETWORK_REG_STATUS_HOME;
@@ -1875,6 +1875,8 @@ get_registration_status (MMAtSerialPort *port, MMCallbackInfo *info)
     mm_at_serial_port_queue_command (port, "+CREG?", 10, get_reg_status_done, info);
 }
 
+#define ALTERNATE_COPS_TRIED_TAG "alternate-cops-tried"
+
 static void
 register_done (MMAtSerialPort *port,
                GString *response,
@@ -1895,6 +1897,16 @@ register_done (MMAtSerialPort *port,
     if (priv->pending_reg_info) {
         g_warn_if_fail (info == priv->pending_reg_info);
 
+        if (error) {
+            gboolean alternate_cops_tried = !!mm_callback_info_get_data (info, ALTERNATE_COPS_TRIED_TAG);
+
+            if (alternate_cops_tried == FALSE && !priv->manual_reg) {
+                mm_callback_info_set_data (info, ALTERNATE_COPS_TRIED_TAG, GUINT_TO_POINTER (TRUE), NULL);
+                mm_at_serial_port_queue_command (port, "+CREG=0", 120, register_done, info);
+                return;
+            }
+        }
+
         /* Don't use cached registration state here since it could be up to
          * 30 seconds old.  Get fresh registration state.
          */
diff --git a/src/mm-modem.h b/src/mm-modem.h
index 8bb23a0..fa176f9 100644
--- a/src/mm-modem.h
+++ b/src/mm-modem.h
@@ -62,6 +62,8 @@ typedef enum {
 #define MM_MODEM_VALID         "valid"      /* not exported */
 #define MM_MODEM_PLUGIN        "plugin"     /* not exported */
 #define MM_MODEM_STATE         "state"      /* not exported */
+#define MM_MODEM_HW_VID        "hw-vid"     /* not exported */
+#define MM_MODEM_HW_PID        "hw-pid"     /* not exported */
 
 #define MM_MODEM_TYPE_UNKNOWN  0
 #define MM_MODEM_TYPE_GSM      1
