Merge remote-tracking branch 'cros/upstream' into 'cros/master'
diff --git a/include/ModemManager-errors.h b/include/ModemManager-errors.h
index b349fd8..f2dc0b6 100644
--- a/include/ModemManager-errors.h
+++ b/include/ModemManager-errors.h
@@ -226,6 +226,7 @@
  * @MM_SERIAL_ERROR_FLASH_FAILED: Could not flash the device.
  * @MM_SERIAL_ERROR_NOT_OPEN: The serial port is not open.
  * @MM_SERIAL_ERROR_PARSE_FAILED: The serial port specific parsing failed.
+ * @MM_SERIAL_ERROR_FRAME_NOT_FOUND: The serial port reported that the frame marker wasn't found (e.g. for QCDM).
  *
  * Serial errors that may be reported by ModemManager.
  */
@@ -238,6 +239,7 @@
     MM_SERIAL_ERROR_FLASH_FAILED          = 5, /*< nick=FlashFailed        >*/
     MM_SERIAL_ERROR_NOT_OPEN              = 6, /*< nick=NotOpen            >*/
     MM_SERIAL_ERROR_PARSE_FAILED          = 7, /*< nick=ParseFailed        >*/
+    MM_SERIAL_ERROR_FRAME_NOT_FOUND       = 8, /*< nick=FrameNotFound      >*/
 } MMSerialError;
 
 /**
diff --git a/plugins/tests/test-fixture.c b/plugins/tests/test-fixture.c
index 81644ab..1ddddd0 100644
--- a/plugins/tests/test-fixture.c
+++ b/plugins/tests/test-fixture.c
@@ -37,7 +37,7 @@
     if (fixture->connection == NULL)
         g_error ("Error getting connection to test bus: %s", error->message);
 
-    /* Ping to autostart MM; wait up to 3s */
+    /* Ping to autostart MM; wait up to 30s */
     result = g_dbus_connection_call_sync (fixture->connection,
                                           "org.freedesktop.ModemManager1",
                                           "/org/freedesktop/ModemManager1",
diff --git a/src/77-mm-usb-device-blacklist.rules b/src/77-mm-usb-device-blacklist.rules
index 5076ea0..e518ed9 100644
--- a/src/77-mm-usb-device-blacklist.rules
+++ b/src/77-mm-usb-device-blacklist.rules
@@ -128,4 +128,7 @@
 # Infineon Flashloader used by Intel XMM modem bootloader
 ATTRS{idVendor}=="8087", ATTRS{idProduct}=="0716", ENV{ID_MM_DEVICE_IGNORE}="1"
 
+# GW Instek AFG-2225 arbitrary function generator
+ATTRS{idVendor}=="2184", ATTRS{idProduct}=="001c", ENV{ID_MM_DEVICE_IGNORE}="1"
+
 LABEL="mm_usb_device_blacklist_end"
diff --git a/src/mm-bearer-mbim.c b/src/mm-bearer-mbim.c
index 358b261..c554c52 100644
--- a/src/mm-bearer-mbim.c
+++ b/src/mm-bearer-mbim.c
@@ -950,6 +950,15 @@
     return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error);
 }
 
+static void
+reset_bearer_connection (MMBearerMbim *self)
+{
+    if (self->priv->data) {
+        mm_port_set_connected (self->priv->data, FALSE);
+        g_clear_object (&self->priv->data);
+    }
+}
+
 static void disconnect_context_step (DisconnectContext *ctx);
 
 static void
@@ -1064,8 +1073,7 @@
 
     case DISCONNECT_STEP_LAST:
         /* Port is disconnected; update the state */
-        mm_port_set_connected (ctx->self->priv->data, FALSE);
-        g_clear_object (&ctx->self->priv->data);
+        reset_bearer_connection (ctx->self);
 
         g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE);
         disconnect_context_complete_and_free (ctx);
@@ -1126,6 +1134,20 @@
 
 /*****************************************************************************/
 
+static void
+report_connection_status (MMBaseBearer *self,
+                          MMBearerConnectionStatus status)
+{
+    if (status == MM_BEARER_CONNECTION_STATUS_DISCONNECTED)
+        /* Cleanup all connection related data */
+        reset_bearer_connection (MM_BEARER_MBIM (self));
+
+    /* Chain up parent's report_connection_status() */
+    MM_BASE_BEARER_CLASS (mm_bearer_mbim_parent_class)->report_connection_status (self, status);
+}
+
+/*****************************************************************************/
+
 MMBaseBearer *
 mm_bearer_mbim_new (MMBroadbandModemMbim *modem,
                     MMBearerProperties *config,
@@ -1221,6 +1243,7 @@
     base_bearer_class->connect_finish = connect_finish;
     base_bearer_class->disconnect = disconnect;
     base_bearer_class->disconnect_finish = disconnect_finish;
+    base_bearer_class->report_connection_status = report_connection_status;
 
     properties[PROP_SESSION_ID] =
         g_param_spec_uint (MM_BEARER_MBIM_SESSION_ID,
diff --git a/src/mm-broadband-modem-qmi.c b/src/mm-broadband-modem-qmi.c
index f4b6c55..4021b56 100644
--- a/src/mm-broadband-modem-qmi.c
+++ b/src/mm-broadband-modem-qmi.c
@@ -7776,7 +7776,8 @@
         qmi_message_pds_get_agps_config_output_get_location_server_url (
             output,
             &url,
-            NULL)) {
+            NULL) &&
+        url->len > 0) {
         str = g_convert (url->data, url->len, "UTF-8", "UTF-16BE", NULL, NULL, NULL);
     }
 
diff --git a/src/mm-modem-helpers.c b/src/mm-modem-helpers.c
index e4967d7..64b4928 100644
--- a/src/mm-modem-helpers.c
+++ b/src/mm-modem-helpers.c
@@ -1899,6 +1899,8 @@
 {
     if (g_str_equal (pdp_type, "IP"))
         return MM_BEARER_IP_FAMILY_IPV4;
+    if (g_str_equal (pdp_type, "IPV4"))
+        return MM_BEARER_IP_FAMILY_IPV4;
     if (g_str_equal (pdp_type, "IPV6"))
         return MM_BEARER_IP_FAMILY_IPV6;
     if (g_str_equal (pdp_type, "IPV4V6"))
diff --git a/src/mm-port-probe.c b/src/mm-port-probe.c
index 5209667..94e7d3b 100644
--- a/src/mm-port-probe.c
+++ b/src/mm-port-probe.c
@@ -602,6 +602,9 @@
             is_qcdm = TRUE;
             qcdm_result_unref (result);
         }
+    } else if (g_error_matches (error, MM_SERIAL_ERROR, MM_SERIAL_ERROR_PARSE_FAILED)) {
+        /* Failed to unescape QCDM packet: don't retry */
+        mm_dbg ("QCDM parsing error: %s", error->message);
     } else {
         if (!g_error_matches (error, MM_SERIAL_ERROR, MM_SERIAL_ERROR_RESPONSE_TIMEOUT))
             mm_dbg ("QCDM probe error: (%d) %s", error->code, error->message);
diff --git a/src/mm-port-serial-qcdm.c b/src/mm-port-serial-qcdm.c
index 42d12d7..b63927f 100644
--- a/src/mm-port-serial-qcdm.c
+++ b/src/mm-port-serial-qcdm.c
@@ -100,9 +100,9 @@
     /* Get the offset into the buffer of where the QCDM frame starts */
     start = 0;
     if (!find_qcdm_start (response_buffer, &start)) {
-        error = g_error_new_literal (MM_CORE_ERROR,
-                                     MM_CORE_ERROR_FAILED,
-                                     "Failed to parse QCDM packet");
+        error = g_error_new_literal (MM_SERIAL_ERROR,
+                                     MM_SERIAL_ERROR_FRAME_NOT_FOUND,
+                                     "QCDM frame start not found");
         /* Discard the unparsable data */
         used = response_buffer->len;
         goto out;
@@ -117,8 +117,8 @@
                                      &used,
                                      &more);
     if (!success) {
-        error = g_error_new_literal (MM_CORE_ERROR,
-                                     MM_CORE_ERROR_FAILED,
+        error = g_error_new_literal (MM_SERIAL_ERROR,
+                                     MM_SERIAL_ERROR_PARSE_FAILED,
                                      "Failed to unescape QCDM packet");
         g_free (unescaped_buffer);
         unescaped_buffer = NULL;
diff --git a/src/tests/test-qcdm-serial-port.c b/src/tests/test-qcdm-serial-port.c
index cd9365b..1f88fad 100644
--- a/src/tests/test-qcdm-serial-port.c
+++ b/src/tests/test-qcdm-serial-port.c
@@ -280,7 +280,8 @@
 
     response = mm_port_serial_qcdm_command_finish (port, res, &error);
 
-    g_assert_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED);
+    /* Expect any kind of error */
+    g_assert (error != NULL);
     g_error_free (error);
     g_assert (response == NULL);