Merge cros/upstream to cros/main - 1.21.3-dev

Part of an uprev that contains the following commits:

" 664c95c68 build: unstable release version bump to 1.21.3 (Aleksander Morgado)"
" 6006dd1d6 broadband-modem-qmi: don't fail on power indication registration error (Louis-Alexis Eyraud)"
" 90c1788be build: fix a typo in meson_options doc string (Lubomir Rintel)"
" 3a1cc27f2 bearer-qmi: fix a mnc/mcc typo (Lubomir Rintel)"
" 5ed79518b broadband-modem-mbim,qmi-shared: Fallback from qmi uim service only when not supported (Ulrich Mohr)"
" 766962167 cli: add formating option (json and key/value) for created SMS (Frederic Martinsons)"
" 3b56efed0 build: enable GLib deprecation warnings (Lubomir Rintel)"
" 1af34e174 libmm-glib,common-helpers: undeprecate g_date_time_format_iso8601() (Lubomir Rintel)"
" 6179667d3 libmm-glib,common-helpers: avoid using g_time_zone_new_offset() (Lubomir Rintel)"
" 7750e927f broadband-modem-mbim: Sync state of sim_hot_swap_configured variable (Michal Mazur)"
" 68e92d930 broadband-modem-mbim: Fix bug in cleanup_unsolicited_events_3gpp() (Michal Mazur)"
" f4b8d14b8 bearer-qmi: explicitly ignore PCOs with undefined contents: (Aleksander Morgado)"
" cf59b497b bearer-qmi: app specific info in PCO may be empty (Aleksander Morgado)"
" 34ba11b3f bearer-qmi: fix pco array declaration (Daniele Palmas)"
" d7e599f13 sim-mbim: Reset cached SIM info when SIM is unlocked (Michal Mazur)"
" cc78a6439 broadband-modem-qmi: ignore our own profile changed indications (Aleksander Morgado)"
" e3667ecb5 build: fix dependency on daemon enums required by plugins (Aleksander Morgado)"
" 99570090e build: set LD_LIBRARY_PATH along with GI_TYPELIB_PATH when launching stub (Frederic Martinsons)"
" aa28fc7a9 ci: build single plugins also in main and tags (Aleksander Morgado)"
" ce2a2614e ci: list of plugins from meson configuration itself (Aleksander Morgado)"
" 6c6ece19c ci: update image with gawk and without autotools (Aleksander Morgado)"
" 6eae758a1 ci: fix enabling qmi/mbim/qrtr support in single-plugin tests (Aleksander Morgado)"
" 4a552aa36 ci: fix disabling introspection in single-plugin tests (Aleksander Morgado)"
" efcabb2cd ci: run suspend-resume build tests also in master and tags (Aleksander Morgado)"
" 5f3565f95 ci: use YAML anchor to setup dependencies (Aleksander Morgado)"
" e3dae370d ci: add tests for builtin plugins (Aleksander Morgado)"
" 1c4da332e build: new option to build plugins within the daemon binary (Aleksander Morgado)"
" 1dd70be4c plugins: setup new helper macros to define shared utils (Aleksander Morgado)"
" f0a9f0955 plugins: setup new helper macros to define plugins (Aleksander Morgado)"
" d30ba8414 plugin-manager: don't crash when loading an invalid shared utils library (Aleksander Morgado)"
" 876e8537c plugins: don't include daemon enums sources (Aleksander Morgado)"
" cc90f2ffe build: compile plugins before daemon (Aleksander Morgado)"
" f562a51af build: fix missing module name in shared option utils (Aleksander Morgado)"
" e14b904cb build: move plugins directory to src/plugins (Aleksander Morgado)"
" 072d7ac90 log: avoid redefining MM_MODULE_NAME (Aleksander Morgado)"
" a9651f239 meson: Un-hardcode building a shared library (Fabrice Fontaine)"
" a07d04b0c quectel: add new modem variants to port type rules (Ivan Mikhanchuk)"
" a5058eb79 base-modem: don't assume ports tables always exist (Aleksander Morgado)"
" c7dac2531 port-mbim: chain up device notifications through the port (Aleksander Morgado)"
" 309a8a515 port-mbim: implement the new generic 'removed' signal (Aleksander Morgado)"
" a20f2428e port-qmi: implement the new generic 'removed' signal (Aleksander Morgado)"
" 455c48609 port: define new generic 'removed' signal (Aleksander Morgado)"
" 2a1851536 build: unstable release version bump to 1.21.2 (Aleksander Morgado)"

BUG=b:266901492
FIXED=b:266901492

TEST=None

Cq-Depend: chromium:4237521,chromium:4237202
Change-Id: I1139a3f307722fc79608a9499ebb61ff2f6851e7
diff --git a/DIR_METADATA b/DIR_METADATA
new file mode 100644
index 0000000..5d046e9
--- /dev/null
+++ b/DIR_METADATA
@@ -0,0 +1,43 @@
+# Metadata information for this directory.
+#
+# For more information on DIR_METADATA files, see:
+#   https://source.chromium.org/chromium/infra/infra/+/HEAD:go/src/infra/tools/dirmd/README.md
+#
+# For the schema of this file, see Metadata message:
+#   https://source.chromium.org/chromium/infra/infra/+/HEAD:go/src/infra/tools/dirmd/proto/dir_metadata.proto
+
+team_email: "cros-cellular-core@google.com"
+
+buganizer {
+  # https://b.corp.google.com/issues?q=status:open%20componentid:167157
+  # ChromeOS > Platform > Connectivity > Cellular
+  component_id: 167157
+}
+
+chromeos {
+  cq {
+    # See go/cros-cq-test-config
+    source_test_plans {
+      test_plan_starlark_files {
+        host: "chrome-internal.googlesource.com"
+        project: "chromeos/config-internal"
+        path: "test/plans/v2/ctpv1_compatible/legacy_default_tast_hw.star"
+      }
+      test_plan_starlark_files {
+        host: "chrome-internal.googlesource.com"
+        project: "chromeos/config-internal"
+        path: "test/plans/v2/ctpv1_compatible/legacy_default_autotest_hw.star"
+      }
+      test_plan_starlark_files {
+        host: "chrome-internal.googlesource.com"
+        project: "chromeos/config-internal"
+        path: "test/plans/v2/ctpv1_compatible/legacy_default_vm.star"
+      }
+      test_plan_starlark_files {
+        host: "chrome-internal.googlesource.com"
+        project: "chromeos/config-internal"
+        path: "test/plans/v2/ctpv1_compatible/cellular_cq.star"
+      }
+    }
+  }
+}
diff --git a/OWNERS b/OWNERS
new file mode 100644
index 0000000..9712978
--- /dev/null
+++ b/OWNERS
@@ -0,0 +1,7 @@
+set noparent
+ejcaruso@chromium.org
+pholla@chromium.org
+andrewlassalle@chromium.org
+madhavadas@google.com
+nmarupaka@google.com
+aleksandermj@google.com
diff --git a/PRESUBMIT.cfg b/PRESUBMIT.cfg
new file mode 100644
index 0000000..51d8dd6
--- /dev/null
+++ b/PRESUBMIT.cfg
@@ -0,0 +1,9 @@
+# This sample config file disables all of the ChromiumOS source style checks.
+# Comment out the disable-flags for any checks you want to leave enabled.
+
+[Hook Overrides]
+stray_whitespace_check: false
+long_line_check: false
+cros_license_check: false
+tab_check: false
+
diff --git a/README.chromium b/README.chromium
new file mode 100644
index 0000000..adfc720
--- /dev/null
+++ b/README.chromium
@@ -0,0 +1,19 @@
+DESCRIPTION="Broadband modem support daemon"
+HOMEPAGE="https://modemmanager.org"
+UPSTREAM_REPO="git://anongit.freedesktop.org/ModemManager/ModemManager"
+LOCAL_GIT_REPO="https://chromium.googlesource.com/chromiumos/third_party/modemmanager-next.git"
+UPSTREAM_BUGSDB="https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/issues"
+LOCAL_BUGSDB="http://buganizer.corp.google.com"
+LICENSE="GPLv2"
+LICENSE_FILE="COPYING"
+
+Description:
+
+ModemManager provides a DBus interface to control broadband modem
+devices. The intended user is a network manager program, such as
+NetworkManager, flimflam, or shill.
+
+This repository mirrors the main branch of the upstream repository.
+
+Local changes should be minimal, but support for particular modems may
+make it here before they make it upstream.
diff --git a/meson.build b/meson.build
index 328cac1..8cf8f99 100644
--- a/meson.build
+++ b/meson.build
@@ -326,7 +326,7 @@
   'gosuncn': {'available': true, 'shared': []},
   'haier': {'available': true, 'shared': []},
   'huawei': {'available': true, 'shared': []},
-  'intel': {'available': true, 'shared': ['xmm']},
+  'intel': {'available': true, 'shared': ['fibocom', 'xmm']},
   'iridium': {'available': true, 'shared': []},
   'linktop': {'available': true, 'shared': []},
   'longcheer': {'available': true, 'shared': []},
diff --git a/src/80-mm-candidate.rules b/src/80-mm-candidate.rules
index 905dcee..09e0766 100644
--- a/src/80-mm-candidate.rules
+++ b/src/80-mm-candidate.rules
@@ -25,6 +25,7 @@
 SUBSYSTEMS=="usb", GOTO="mm_candidate_end"
 SUBSYSTEM=="wwan", ENV{DEVTYPE}=="wwan_dev", GOTO="mm_candidate_end"
 SUBSYSTEM=="wwan", ENV{ID_MM_CANDIDATE}="1"
+SUBSYSTEM=="wwan", ENV{ID_MM_FIBOCOM_INITIAL_EPS_OFF_ON}="1"
 SUBSYSTEM=="wwan", ATTR{type}=="AT", ENV{ID_MM_PORT_TYPE_AT_PRIMARY}="1"
 SUBSYSTEM=="wwan", ATTR{type}=="MBIM", ENV{ID_MM_PORT_TYPE_MBIM}="1"
 SUBSYSTEM=="wwan", ATTR{type}=="QMI", ENV{ID_MM_PORT_TYPE_QMI}="1"
diff --git a/src/mm-base-bearer.c b/src/mm-base-bearer.c
index 5217b66..c60115b 100644
--- a/src/mm-base-bearer.c
+++ b/src/mm-base-bearer.c
@@ -52,6 +52,9 @@
 #define BEARER_CONNECTION_MONITOR_INITIAL_TIMEOUT 30
 #define BEARER_CONNECTION_MONITOR_TIMEOUT          5
 
+/* TODO(b/175305412): Use rmnet_data0 as the only link. */
+#define CHROMEOS_USE_RMNET_DATA0_HACK 1
+
 static void log_object_iface_init (MMLogObjectInterface *iface);
 
 G_DEFINE_TYPE_EXTENDED (MMBaseBearer, mm_base_bearer, MM_GDBUS_TYPE_BEARER_SKELETON, 0,
@@ -892,13 +895,23 @@
                    GTask        *task)
 {
     MMBearerConnectResult *result;
+    const gchar           *data_interface;
 
     result = g_task_get_task_data (task);
 
+    data_interface = mm_port_get_device (mm_bearer_connect_result_peek_data (result));
+
+    /* This hack runs in all modems, but the only ones affected would be the
+     * Qualcomm SoCs. */
+#ifdef CHROMEOS_USE_RMNET_DATA0_HACK
+    if (g_strcmp0 (data_interface, "rmnet_ipa0") == 0)
+        data_interface = "rmnet_data0";
+#endif
+
     /* Update bearer and interface status */
     bearer_update_status_connected (
         self,
-        mm_port_get_device (mm_bearer_connect_result_peek_data (result)),
+        data_interface,
         mm_bearer_connect_result_get_multiplexed (result),
         mm_bearer_connect_result_get_profile_id (result),
         mm_bearer_connect_result_peek_ipv4_config (result),
diff --git a/src/mm-base-sim.c b/src/mm-base-sim.c
index 698c153..765422b 100644
--- a/src/mm-base-sim.c
+++ b/src/mm-base-sim.c
@@ -2413,6 +2413,7 @@
     INITIALIZATION_STEP_SIM_IDENTIFIER,
     INITIALIZATION_STEP_IMSI,
     INITIALIZATION_STEP_OPERATOR_ID,
+    INITIALIZATION_STEP_OPERATOR_ID_RETRY,
     INITIALIZATION_STEP_OPERATOR_NAME,
     INITIALIZATION_STEP_EMERGENCY_NUMBERS,
     INITIALIZATION_STEP_PREFERRED_NETWORKS,
@@ -2797,6 +2798,26 @@
         ctx->step++;
         /* Fall through */
 
+    case INITIALIZATION_STEP_OPERATOR_ID_RETRY:
+        /* This is a retry of the previous step. The query only happens if the
+         *  operator_identifier is still null. */
+        /* Don't load operator ID if the SIM is known to be an eSIM without
+         * profiles; otherwise (if physical SIM, or if eSIM with profile, or if
+         * SIM type unknown) try to load it. */
+        if (IS_ESIM_WITHOUT_PROFILES (self))
+            mm_obj_dbg (self, "not loading operator ID in eSIM without profiles");
+        else if (mm_gdbus_sim_get_operator_identifier (MM_GDBUS_SIM (self)) == NULL &&
+                 MM_BASE_SIM_GET_CLASS (self)->load_operator_identifier &&
+                 MM_BASE_SIM_GET_CLASS (self)->load_operator_identifier_finish) {
+            MM_BASE_SIM_GET_CLASS (self)->load_operator_identifier (
+                self,
+                (GAsyncReadyCallback)init_load_operator_identifier_ready,
+                task);
+            return;
+        }
+        ctx->step++;
+        /* Fall through */
+
     case INITIALIZATION_STEP_OPERATOR_NAME:
         /* Don't load operator name if the SIM is known to be an eSIM without
          * profiles; otherwise (if physical SIM, or if eSIM with profile, or if
diff --git a/src/mm-bearer-mbim.c b/src/mm-bearer-mbim.c
index 28aa963..289691c 100644
--- a/src/mm-bearer-mbim.c
+++ b/src/mm-bearer-mbim.c
@@ -462,6 +462,9 @@
 
         /* Build IPv4 config */
         if (ctx->requested_ip_type == MBIM_CONTEXT_IP_TYPE_IPV4 ||
+#if defined SUPPORT_MBIM_IPV6_WITH_IPV4_ROAMING //TODO(b/183029202): Remove hacks before merging to upstream
+            ctx->requested_ip_type == MBIM_CONTEXT_IP_TYPE_IPV6 ||
+#endif
             ctx->requested_ip_type == MBIM_CONTEXT_IP_TYPE_IPV4V6 ||
             ctx->requested_ip_type == MBIM_CONTEXT_IP_TYPE_IPV4_AND_IPV6) {
             gboolean address_set = FALSE;
@@ -600,11 +603,14 @@
              * otherwise use DHCP to indicate the missing ones should be
              * retrieved from SLAAC or DHCPv6.
              */
+#if defined SUPPORT_MBIM_IPV6_WITH_IPV4_ROAMING //TODO(b/183029202): Remove hacks before merging to upstream
+            mm_bearer_ip_config_set_method (ipv6_config, MM_BEARER_IP_METHOD_STATIC);
+#else
             if (address_set && gateway_set && dns_set)
                 mm_bearer_ip_config_set_method (ipv6_config, MM_BEARER_IP_METHOD_STATIC);
             else
                 mm_bearer_ip_config_set_method (ipv6_config, MM_BEARER_IP_METHOD_DHCP);
-
+#endif
             /* We requested IPv6, but it wasn't reported as activated. If there is no IPv6 address
              * provided by the modem, we assume the IPv6 bearer wasn't truly activated */
             if (!address_set &&
diff --git a/src/mm-bearer-qmi.c b/src/mm-bearer-qmi.c
index caf925d..f1ba704 100644
--- a/src/mm-bearer-qmi.c
+++ b/src/mm-bearer-qmi.c
@@ -42,6 +42,9 @@
 
 #define GLOBAL_PACKET_DATA_HANDLE 0xFFFFFFFF
 
+/* TODO(b/175305412): Use rmnet_data0 as the only link. */
+#define CHROMEOS_USE_RMNET_DATA0_HACK 1
+
 struct _MMBearerQmiPrivate {
     /* Cancellables available during a connection attempt */
     GCancellable *ongoing_connect_user_cancellable;
@@ -766,7 +769,9 @@
     }
 
     if (ctx->link_name) {
+#ifndef CHROMEOS_USE_RMNET_DATA0_HACK
         mm_port_qmi_cleanup_link (ctx->qmi, ctx->link_name, ctx->mux_id, NULL, NULL);
+#endif
         g_free (ctx->link_name);
     }
     g_clear_object (&ctx->link);
@@ -2011,12 +2016,26 @@
         /* if muxing has been enabled in the port, we need to create a new link
          * interface. */
         if (MM_PORT_QMI_DAP_IS_SUPPORTED_QMAP (ctx->dap)) {
+#ifdef CHROMEOS_USE_RMNET_DATA0_HACK
+            g_autoptr (MMBaseModem) modem = NULL;
+
+            g_object_get (ctx->self,
+                          MM_BASE_BEARER_MODEM, &modem,
+                          NULL);
+            g_assert (modem);
+
+            mm_obj_dbg (self, "Forcing rmnet_data0 link");
+            ctx->link_name = g_strdup ("rmnet_data0");
+            ctx->mux_id = 1;
+            ctx->link = mm_base_modem_peek_port (modem, ctx->link_name);
+#else
             mm_port_qmi_setup_link (ctx->qmi,
                                     ctx->data,
                                     ctx->link_prefix_hint,
                                     (GAsyncReadyCallback) setup_link_ready,
                                     task);
             return;
+#endif
         }
         ctx->step++;
         /* fall through */
@@ -2694,11 +2713,13 @@
             g_assert (self->priv->qmi);
             /* Link is disconnected; update the state */
             mm_port_set_connected (self->priv->link, FALSE);
+#ifndef CHROMEOS_USE_RMNET_DATA0_HACK
             mm_port_qmi_cleanup_link (self->priv->qmi,
                                       mm_port_get_device (self->priv->link),
                                       self->priv->mux_id,
                                       NULL,
                                       NULL);
+#endif
             g_clear_object (&self->priv->link);
         }
         self->priv->mux_id = QMI_DEVICE_MUX_ID_UNBOUND;
diff --git a/src/mm-broadband-modem-mbim.c b/src/mm-broadband-modem-mbim.c
index 718975c..dee0984 100644
--- a/src/mm-broadband-modem-mbim.c
+++ b/src/mm-broadband-modem-mbim.c
@@ -388,6 +388,14 @@
     return MM_BROADBAND_MODEM_MBIM_GET_CLASS (self)->peek_port_mbim_for_data (self, data, error);
 }
 
+gboolean
+mm_broadband_modem_mbim_get_is_lte_attach_info_supported (MMBroadbandModemMbim  *self)
+{
+    g_assert (MM_IS_BROADBAND_MODEM_MBIM (self));
+
+    return self->priv->is_lte_attach_info_supported;
+}
+
 /*****************************************************************************/
 /* Current capabilities (Modem interface) */
 
@@ -986,6 +994,9 @@
 
     task = g_task_new (self, NULL, callback, user_data);
 
+    mm_store_vid_pid(mm_base_modem_get_vendor_id (MM_BASE_MODEM (self)),
+                     mm_base_modem_get_product_id (MM_BASE_MODEM (self)));
+
     /* Just use placeholder ATI/ATI1 replies, all the other internal info should be
      * enough for uniqueness */
     device_identifier = mm_broadband_modem_create_device_identifier (MM_BROADBAND_MODEM (self), "", "", &error);
@@ -1665,7 +1676,8 @@
 
     /* Initialized */
     if (ready_state == MBIM_SUBSCRIBER_READY_STATE_DEVICE_LOCKED ||
-        ready_state == MBIM_SUBSCRIBER_READY_STATE_INITIALIZED) {
+        ready_state == MBIM_SUBSCRIBER_READY_STATE_INITIALIZED ||
+        ready_state == MBIM_SUBSCRIBER_READY_STATE_NO_ESIM_PROFILE) {
         MbimMessage *message;
 
         /* Query which lock is to unlock */
@@ -8332,7 +8344,11 @@
      * the backoff index set to the current index of modem
      */
     config_state = g_new (MbimSarConfigState, 1);
+#if defined MBIM_FIBOCOM_SAR_HACK //TODO(b/188002987): Remove hacks before merging to upstream
+    config_state->antenna_index = 0;
+#else
     config_state->antenna_index = 0xFFFFFFFF;
+#endif
     config_state->backoff_index = mm_iface_modem_sar_get_power_level (_self);
 
     g_task_set_task_data (task, GUINT_TO_POINTER (config_state->backoff_index), NULL);
@@ -8397,7 +8413,11 @@
      * the backoff index set to the input power level
      */
     config_state = g_new (MbimSarConfigState, 1);
+#if defined MBIM_FIBOCOM_SAR_HACK //TODO(b/188002987): Remove hacks before merging to upstream
+    config_state->antenna_index = 0;
+#else
     config_state->antenna_index = 0xFFFFFFFF;
+#endif
     config_state->backoff_index = power_level;
 
     task = g_task_new (self, NULL, callback, user_data);
diff --git a/src/mm-broadband-modem-mbim.h b/src/mm-broadband-modem-mbim.h
index e117454..f85d23d 100644
--- a/src/mm-broadband-modem-mbim.h
+++ b/src/mm-broadband-modem-mbim.h
@@ -63,6 +63,8 @@
                                                              MMPort                *data,
                                                              GError               **error);
 
+gboolean mm_broadband_modem_mbim_get_is_lte_attach_info_supported (MMBroadbandModemMbim  *self);
+
 void mm_broadband_modem_mbim_set_unlock_retries (MMBroadbandModemMbim *self,
                                                  MMModemLock           lock_type,
                                                  guint32               remaining_attempts);
diff --git a/src/mm-broadband-modem-qmi.c b/src/mm-broadband-modem-qmi.c
index 9627d60..8b695c8 100644
--- a/src/mm-broadband-modem-qmi.c
+++ b/src/mm-broadband-modem-qmi.c
@@ -85,6 +85,8 @@
                         G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_FIRMWARE, iface_modem_firmware_init)
                         G_IMPLEMENT_INTERFACE (MM_TYPE_SHARED_QMI, shared_qmi_init))
 
+/* TODO(b/175305412): Use rmnet_data0 as the only link. */
+#define CHROMEOS_USE_RMNET_DATA0_HACK 1
 struct _MMBroadbandModemQmiPrivate {
     /* Cached device IDs, retrieved by the modem interface when loading device
      * IDs, and used afterwards in the 3GPP and CDMA interfaces. */
@@ -112,6 +114,13 @@
     /* Index of the WDS profile used as initial EPS bearer */
     guint16 default_attach_pdn;
 
+    /* The WDS profile for the initial EPS bearer is owned by ModemManager
+     * and can be modified */
+    gboolean mm_owned_attach_pdn;
+
+    /* The current PDN list in the modem */
+    GArray *current_pdn_list;
+
     /* Support for the APN type mask in profiles */
     gboolean apn_type_not_supported;
 
@@ -10799,20 +10808,26 @@
     SET_INITIAL_EPS_BEARER_SETTINGS_STEP_FIRST,
     SET_INITIAL_EPS_BEARER_SETTINGS_STEP_LOAD_POWER_STATE,
     SET_INITIAL_EPS_BEARER_SETTINGS_STEP_POWER_DOWN,
+    SET_INITIAL_EPS_BEARER_SETTINGS_STEP_HANDLE_APP_PROFILE,
     SET_INITIAL_EPS_BEARER_SETTINGS_STEP_MODIFY_PROFILE,
+    SET_INITIAL_EPS_BEARER_SETTINGS_STEP_SET_LTE_ATTACH_PDN,
     SET_INITIAL_EPS_BEARER_SETTINGS_STEP_POWER_UP,
     SET_INITIAL_EPS_BEARER_SETTINGS_STEP_LAST_SETTING,
 } SetInitialEpsBearerSettingsStep;
 
 typedef struct {
     SetInitialEpsBearerSettingsStep  step;
+    QmiClientWds                    *client;
     MM3gppProfile                   *profile;
     MMModemPowerState                power_state;
+    gboolean                         setting_mm_owned_pdn;
+    gboolean                         update_lte_attach_pdn;
 } SetInitialEpsBearerSettingsContext;
 
 static void
 set_initial_eps_bearer_settings_context_free (SetInitialEpsBearerSettingsContext *ctx)
 {
+    g_clear_object (&ctx->client);
     g_clear_object (&ctx->profile);
     g_slice_free (SetInitialEpsBearerSettingsContext, ctx);
 }
@@ -10849,6 +10864,67 @@
 }
 
 static void
+set_initial_eps_bearer_set_lte_attach_pdn_ready (QmiClientWds *client,
+                                                 GAsyncResult *res,
+                                                 GTask        *task)
+{
+    g_autoptr(QmiMessageWdsSetLteAttachPdnListOutput)  output = NULL;
+    GError                                            *error = NULL;
+    MMBroadbandModemQmi                               *self;
+    SetInitialEpsBearerSettingsContext                *ctx;
+
+    self = g_task_get_source_object (task);
+    ctx = g_task_get_task_data (task);
+
+    output = qmi_client_wds_set_lte_attach_pdn_list_finish (client, res, &error);
+    if (!output) {
+        g_prefix_error (&error, "QMI operation failed: ");
+        g_task_return_error (task, error);
+        g_object_unref (task);
+        return;
+    }
+
+    if (!qmi_message_wds_set_lte_attach_pdn_list_output_get_result (output, &error)) {
+        g_prefix_error (&error, "Couldn't set the LTE attach PDN list: ");
+        g_task_return_error (task, error);
+        g_object_unref (task);
+        return;
+    }
+
+    self->priv->mm_owned_attach_pdn = ctx->setting_mm_owned_pdn;
+
+    ctx->step++;
+    set_initial_eps_bearer_settings_step (task);
+}
+
+static void
+set_initial_eps_bearer_set_lte_attach_pdn (GTask *task)
+{
+    g_autoptr(QmiMessageWdsSetLteAttachPdnListInput)  input = NULL;
+    MMBroadbandModemQmi                *self;
+    SetInitialEpsBearerSettingsContext *ctx;
+
+    self = g_task_get_source_object (task);
+    ctx  = g_task_get_task_data (task);
+
+    input = qmi_message_wds_set_lte_attach_pdn_list_input_new ();
+    qmi_message_wds_set_lte_attach_pdn_list_input_set_list (input,
+                                                            self->priv->current_pdn_list,
+                                                            NULL);
+
+    qmi_message_wds_set_lte_attach_pdn_list_input_set_action (input,
+                                                              QMI_WDS_ATTACH_PDN_LIST_ACTION_DETACH_OR_PDN_DISCONNECT,
+                                                              NULL);
+
+    qmi_client_wds_set_lte_attach_pdn_list (ctx->client,
+                                            input,
+                                            10,
+                                            NULL,
+                                            (GAsyncReadyCallback)set_initial_eps_bearer_set_lte_attach_pdn_ready,
+                                            task);
+}
+
+static void
 set_initial_eps_bearer_modify_profile_ready (MMIfaceModem3gppProfileManager *self,
                                              GAsyncResult                   *res,
                                              GTask                          *task)
@@ -10866,6 +10942,13 @@
         return;
     }
 
+    if (mm_3gpp_profile_get_profile_id(ctx->profile) == MM_3GPP_PROFILE_ID_UNKNOWN) {
+        // The profile was just created.
+        ctx->update_lte_attach_pdn = TRUE;
+        /* Update |default_attach_pdn| now so it can be modified in the next step. */
+        MM_BROADBAND_MODEM_QMI(self)->priv->default_attach_pdn = (guint16) mm_3gpp_profile_get_profile_id (stored);
+        g_array_prepend_val (MM_BROADBAND_MODEM_QMI(self)->priv->current_pdn_list, MM_BROADBAND_MODEM_QMI(self)->priv->default_attach_pdn);
+    }
     ctx->step++;
     set_initial_eps_bearer_settings_step (task);
 }
@@ -10888,6 +10971,47 @@
 }
 
 static void
+set_initial_eps_bearer_delete_mm_profile_ready (MMIfaceModem3gppProfileManager *self,
+                                                GAsyncResult                   *res,
+                                                GTask                          *task)
+{
+    GError                             *error = NULL;
+    SetInitialEpsBearerSettingsContext *ctx;
+
+    ctx = g_task_get_task_data (task);
+
+    if (!modem_3gpp_profile_manager_delete_profile_finish (MM_IFACE_MODEM_3GPP_PROFILE_MANAGER(self), res, &error)) {
+        g_prefix_error (&error, "Couldn't delete the profile: ");
+        g_task_return_error (task, error);
+        g_object_unref (task);
+        return;
+    }
+
+    ctx->step = SET_INITIAL_EPS_BEARER_SETTINGS_STEP_SET_LTE_ATTACH_PDN;
+    ctx->update_lte_attach_pdn = TRUE;
+    MM_BROADBAND_MODEM_QMI(self)->priv->current_pdn_list = g_array_remove_index (MM_BROADBAND_MODEM_QMI(self)->priv->current_pdn_list, 0);
+    if (MM_BROADBAND_MODEM_QMI(self)->priv->current_pdn_list->len > 0)
+        MM_BROADBAND_MODEM_QMI(self)->priv->default_attach_pdn = g_array_index (MM_BROADBAND_MODEM_QMI(self)->priv->current_pdn_list, guint16, 0);
+    set_initial_eps_bearer_settings_step (task);
+}
+
+static void
+set_initial_eps_bearer_delete_mm_profile (GTask *task)
+{
+    MMBroadbandModemQmi                *self;
+    SetInitialEpsBearerSettingsContext *ctx;
+
+    self = g_task_get_source_object (task);
+    ctx  = g_task_get_task_data (task);
+
+    modem_3gpp_profile_manager_delete_profile (MM_IFACE_MODEM_3GPP_PROFILE_MANAGER (self),
+                                               ctx->profile,
+                                               "profile-id",
+                                               (GAsyncReadyCallback)set_initial_eps_bearer_delete_mm_profile_ready,
+                                               task);
+}
+
+static void
 set_initial_eps_bearer_power_down_ready (MMIfaceModem *self,
                                          GAsyncResult *res,
                                          GTask        *task)
@@ -10935,6 +11059,7 @@
 {
     SetInitialEpsBearerSettingsContext *ctx;
     MMBroadbandModemQmi                *self;
+    const gchar*                        apn_name;
 
     self = g_task_get_source_object (task);
     ctx  = g_task_get_task_data (task);
@@ -10962,11 +11087,55 @@
             ctx->step++;
             /* fall through */
 
+        case SET_INITIAL_EPS_BEARER_SETTINGS_STEP_HANDLE_APP_PROFILE:
+            apn_name = mm_3gpp_profile_get_apn(ctx->profile);
+            ctx->update_lte_attach_pdn = FALSE;
+            mm_obj_info (self, "Set Initial eps settings: apn_name: %s", apn_name);
+            if (apn_name && g_strcmp0 (apn_name, "") != 0) {
+                ctx->setting_mm_owned_pdn = TRUE;
+                mm_3gpp_profile_set_profile_name(ctx->profile, MM_BROADBAND_MODEM_QMI_PROFILE_NAME);
+                if (self->priv->mm_owned_attach_pdn) {
+                    mm_obj_info (self, "Overriding MM owned profile %d with APN: %s.",
+                        self->priv->default_attach_pdn, apn_name);
+                    ctx->step++;
+                    /* fall through */
+                } else {
+                    mm_obj_info (self, "creating a profile for initial EPS bearer settings...");
+                    mm_3gpp_profile_set_profile_id(ctx->profile, MM_3GPP_PROFILE_ID_UNKNOWN);
+                    ctx->update_lte_attach_pdn = FALSE;
+                    ctx->step++;
+                    /* fall through */
+                }
+            } else {
+                /* Note: Never store an empty APN on the mm_owned_profile_index, since the logic in iface-modem-3gpp
+                   will skip the reattach if the new settings are also empty, and we might get stuck with empty APN
+                   settings which have the wrong |ip_type|. */
+                mm_obj_info (self, "Empty APN name provided. Falling back to modem profile for Attach APN.");
+                ctx->setting_mm_owned_pdn = FALSE;
+                if (self->priv->mm_owned_attach_pdn) {
+                    mm_obj_info (self, "Deleting MM owned profile for initial EPS bearer settings...");
+                    set_initial_eps_bearer_delete_mm_profile (task);
+                } else {
+                    ctx->step = SET_INITIAL_EPS_BEARER_SETTINGS_STEP_POWER_UP;
+                    set_initial_eps_bearer_settings_step (task);
+                }
+                return;
+            }
+
         case SET_INITIAL_EPS_BEARER_SETTINGS_STEP_MODIFY_PROFILE:
             mm_obj_dbg (self, "modifying initial EPS bearer settings profile...");
             set_initial_eps_bearer_modify_profile (task);
             return;
 
+        case SET_INITIAL_EPS_BEARER_SETTINGS_STEP_SET_LTE_ATTACH_PDN:
+            if (ctx->update_lte_attach_pdn) {
+                mm_obj_info (self, "updating lte attach pdn after changing initial EPS bearer settings...");
+                set_initial_eps_bearer_set_lte_attach_pdn (task);
+                return;
+            }
+            ctx->step++;
+            /* fall through */
+
         case SET_INITIAL_EPS_BEARER_SETTINGS_STEP_POWER_UP:
             if (ctx->power_state == MM_MODEM_POWER_STATE_ON) {
                 mm_obj_dbg (self, "powering up after changing initial EPS bearer settings...");
@@ -10997,6 +11166,13 @@
     SetInitialEpsBearerSettingsContext *ctx;
     GTask                              *task;
     MM3gppProfile                      *profile;
+    QmiClient                          *client;
+
+
+    if (!mm_shared_qmi_ensure_client (MM_SHARED_QMI (self),
+                                      QMI_SERVICE_WDS, &client,
+                                      callback, user_data))
+        return;
 
     task = g_task_new (self, NULL, callback, user_data);
 
@@ -11012,6 +11188,7 @@
 
     ctx = g_slice_new0 (SetInitialEpsBearerSettingsContext);
     ctx->profile = g_object_ref (profile);
+    ctx->client = QMI_CLIENT_WDS (g_object_ref (client));
     ctx->step = SET_INITIAL_EPS_BEARER_SETTINGS_STEP_FIRST;
     g_task_set_task_data (task, ctx, (GDestroyNotify) set_initial_eps_bearer_settings_context_free);
 
@@ -11037,6 +11214,9 @@
     GError                   *error = NULL;
     g_autoptr(MM3gppProfile)  profile = NULL;
     MMBearerProperties       *properties;
+    MMBroadbandModemQmi      *self;
+
+    self = g_task_get_source_object (task);
 
     profile = mm_iface_modem_3gpp_profile_manager_get_profile_finish (_self, res, &error);
     if (!profile) {
@@ -11045,6 +11225,10 @@
         return;
     }
 
+    self->priv->mm_owned_attach_pdn = FALSE;
+    if (g_strcmp0(mm_3gpp_profile_get_profile_name (profile), MM_BROADBAND_MODEM_QMI_PROFILE_NAME) == 0)
+            self->priv->mm_owned_attach_pdn = TRUE;
+
     properties = mm_bearer_properties_new_from_profile (profile, &error);
     if (!properties)
         g_task_return_error (task, error);
@@ -11103,8 +11287,12 @@
         return;
     }
 
+    /* Resize array to match |current_list| */
+    g_array_set_size (self->priv->current_pdn_list, current_list->len);
+
     mm_obj_dbg (self, "Found %u LTE attach PDNs defined", current_list->len);
     for (i = 0; i < current_list->len; i++) {
+        g_array_index (self->priv->current_pdn_list, guint16, i) = g_array_index (current_list, guint16, i);
         if (i == 0) {
             self->priv->default_attach_pdn = g_array_index (current_list, guint16, i);
             mm_obj_dbg (self, "Default LTE attach PDN profile: %u", self->priv->default_attach_pdn);
@@ -13100,7 +13288,16 @@
         return;
     }
 
+#ifndef CHROMEOS_USE_RMNET_DATA0_HACK
     initialization_reset_ports (task);
+#else
+    mm_port_qmi_open (ctx->qmi,
+                      TRUE,
+                      NULL,
+                      (GAsyncReadyCallback)qmi_port_open_ready,
+                      task);
+#endif
+
 }
 
 /*****************************************************************************/
@@ -13132,6 +13329,7 @@
     self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
                                               MM_TYPE_BROADBAND_MODEM_QMI,
                                               MMBroadbandModemQmiPrivate);
+    self->priv->current_pdn_list = g_array_new (FALSE, FALSE, sizeof (guint16));
     self->priv->system_info_registration_state_cs = MM_MODEM_3GPP_REGISTRATION_STATE_UNKNOWN;
     self->priv->system_info_registration_state_ps = MM_MODEM_3GPP_REGISTRATION_STATE_UNKNOWN;
     self->priv->system_info_registration_state_eps = MM_MODEM_3GPP_REGISTRATION_STATE_UNKNOWN;
@@ -13152,6 +13350,9 @@
     if (self->priv->supported_bands)
         g_array_unref (self->priv->supported_bands);
 
+    if (self->priv->current_pdn_list)
+        g_array_free (self->priv->current_pdn_list, TRUE);
+
     G_OBJECT_CLASS (mm_broadband_modem_qmi_parent_class)->finalize (object);
 }
 
diff --git a/src/mm-broadband-modem-qmi.h b/src/mm-broadband-modem-qmi.h
index e324d79..4a9b516 100644
--- a/src/mm-broadband-modem-qmi.h
+++ b/src/mm-broadband-modem-qmi.h
@@ -25,6 +25,9 @@
 #define MM_IS_BROADBAND_MODEM_QMI_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  MM_TYPE_BROADBAND_MODEM_QMI))
 #define MM_BROADBAND_MODEM_QMI_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  MM_TYPE_BROADBAND_MODEM_QMI, MMBroadbandModemQmiClass))
 
+/* Chromium OS specific profile */
+#define MM_BROADBAND_MODEM_QMI_PROFILE_NAME    "CrOS_attach_PDN"
+
 typedef struct _MMBroadbandModemQmi MMBroadbandModemQmi;
 typedef struct _MMBroadbandModemQmiClass MMBroadbandModemQmiClass;
 typedef struct _MMBroadbandModemQmiPrivate MMBroadbandModemQmiPrivate;
diff --git a/src/mm-iface-modem-3gpp.c b/src/mm-iface-modem-3gpp.c
index 6766ddf..332da7f 100644
--- a/src/mm-iface-modem-3gpp.c
+++ b/src/mm-iface-modem-3gpp.c
@@ -1179,7 +1179,11 @@
         return;
     }
 
-    if (!mm_bearer_properties_cmp (new_config, ctx->config, MM_BEARER_PROPERTIES_CMP_FLAGS_EPS)) {
+    /* When we request to set an empty/NULL APN, we instead select the default initial attach APN used by the modem,
+       which will probably not be an empty APN. If that's the case, we won't check for equality between the requested
+       APN and the APN which is now set. */
+    if (mm_bearer_properties_get_apn (ctx->config) && g_strcmp0 (mm_bearer_properties_get_apn (ctx->config), "") != 0 &&
+        !mm_bearer_properties_cmp (new_config, ctx->config, MM_BEARER_PROPERTIES_CMP_FLAGS_EPS)) {
         mm_obj_warn (self, "requested and reloaded initial EPS bearer settings don't match");
         mm_obj_info (self, "reloaded initial EPS bearer settings:");
         mm_log_bearer_properties (self, MM_LOG_LEVEL_INFO, "  ", new_config);
diff --git a/src/mm-modem-helpers-mbim.c b/src/mm-modem-helpers-mbim.c
index 47776be..da6a47d 100644
--- a/src/mm-modem-helpers-mbim.c
+++ b/src/mm-modem-helpers-mbim.c
@@ -22,6 +22,12 @@
 
 #include <string.h>
 
+#define FM350_VID 0x14C3
+#define FM350_PID 0x4D75
+
+static guint device_pid;
+static guint device_vid;
+
 /*****************************************************************************/
 
 MMModemCapability
@@ -440,12 +446,25 @@
     /* MBIM_NW_ERROR_SYNCH_FAILURE */
 };
 
+void
+mm_store_vid_pid(guint vid,guint pid)
+{
+    device_vid = vid;
+    device_pid = pid;
+}
+
 GError *
 mm_mobile_equipment_error_from_mbim_nw_error (MbimNwError nw_error,
                                               gpointer    log_object)
 {
     const gchar            *msg;
 
+    if ( device_vid == FM350_VID && device_pid == FM350_PID) {
+        if (nw_error > 100) {
+            nw_error -= 100;  /* Work around to convert AT error to 3GPP Error*/
+        }
+    }
+
     if (nw_error < G_N_ELEMENTS (mbim_nw_errors)) {
         MMMobileEquipmentError  error_code;
 
diff --git a/src/mm-modem-helpers-mbim.h b/src/mm-modem-helpers-mbim.h
index ee0a374..d5ccfa3 100644
--- a/src/mm-modem-helpers-mbim.h
+++ b/src/mm-modem-helpers-mbim.h
@@ -54,6 +54,8 @@
 MbimPinType mbim_pin_type_from_mm_modem_3gpp_facility (MMModem3gppFacility facility);
 MMModem3gppFacility mm_modem_3gpp_facility_from_mbim_pin_type (MbimPinType pin_type);
 
+void mm_store_vid_pid(guint vid,guint pid);
+
 GError *mm_mobile_equipment_error_from_mbim_nw_error (MbimNwError nw_error,
                                                       gpointer    log_object);
 
diff --git a/src/plugins/fibocom/77-mm-fibocom-port-types.rules b/src/plugins/fibocom/77-mm-fibocom-port-types.rules
index 1fb2662..61387d4 100644
--- a/src/plugins/fibocom/77-mm-fibocom-port-types.rules
+++ b/src/plugins/fibocom/77-mm-fibocom-port-types.rules
@@ -2,6 +2,12 @@
 ACTION!="add|change|move|bind", GOTO="mm_fibocom_port_types_end"
 SUBSYSTEMS=="usb", ATTRS{idVendor}=="2cb7", GOTO="mm_fibocom_port_types"
 SUBSYSTEMS=="usb", ATTRS{idVendor}=="1782", GOTO="mm_fibocom_port_types"
+SUBSYSTEMS=="pci", SUBSYSTEM=="wwan", ATTRS{vendor}=="0x14c3", GOTO="mm_fibocom_pci_port_types"
+GOTO="mm_fibocom_port_types_end"
+
+LABEL="mm_fibocom_pci_port_types"
+# ChromeOS specific configuration
+SUBSYSTEM=="wwan", ATTR{type}=="AT", ENV{ID_MM_PORT_IGNORE}="1"
 GOTO="mm_fibocom_port_types_end"
 
 LABEL="mm_fibocom_port_types"
@@ -11,12 +17,20 @@
 # Fibocom L850-GL attach APN with toggle modem power
 ATTRS{idVendor}=="2cb7", ATTRS{idProduct}=="0007", ENV{ID_MM_FIBOCOM_INITIAL_EPS_OFF_ON}="1"
 
+# Fibocom FM101-GL attach APN with toggle modem power
+ATTRS{idVendor}=="2cb7", ATTRS{idProduct}=="01a2", ENV{ID_MM_FIBOCOM_INITIAL_EPS_OFF_ON}="1"
+
 # Fibocom L850-GL
 #  ttyACM0 (if #2): AT port
 #  ttyACM1 (if #4): debug port (ignore)
 #  ttyACM2 (if #6): AT port
 ATTRS{idVendor}=="2cb7", ATTRS{idProduct}=="0007", ENV{.MM_USBIFNUM}=="04", ENV{ID_MM_PORT_IGNORE}="1"
 
+# Fibocom L850-GL: ChromeOS specific configuration
+#  ttyACM0 (if #2): managed by modemfwd (ignored in MM)
+#  ttyACM2 (if #6): managed by ModemManager
+ATTRS{idVendor}=="2cb7", ATTRS{idProduct}=="0007", ENV{.MM_USBIFNUM}=="02", ENV{ID_MM_PORT_IGNORE}="1"
+
 # Fibocom NL668-AM
 #  ttyACM0 (if #2): AT port
 #  ttyACM1 (if #3): AT port
@@ -25,6 +39,10 @@
 ATTRS{idVendor}=="2cb7", ATTRS{idProduct}=="01a0", ENV{.MM_USBIFNUM}=="03", SUBSYSTEM=="tty", ENV{ID_MM_PORT_TYPE_AT_SECONDARY}="1"
 ATTRS{idVendor}=="2cb7", ATTRS{idProduct}=="01a0", ENV{.MM_USBIFNUM}=="04", ENV{ID_MM_PORT_IGNORE}="1"
 
+# Fibocom NL668-AM: ChromeOS specific configuration
+#  ttyACM0 (if #2): managed by modemfwd (ignored in MM)
+ATTRS{idVendor}=="2cb7", ATTRS{idProduct}=="01a0", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_IGNORE}="1"
+
 # Fibocom FM150
 #  ttyUSB0 (if #0): QCDM port
 #  ttyUSB1 (if #1): AT port
@@ -45,6 +63,11 @@
 ATTRS{idVendor}=="2cb7", ATTRS{idProduct}=="01a2", ENV{.MM_USBIFNUM}=="04", ENV{ID_MM_PORT_IGNORE}="1"
 ATTRS{idVendor}=="2cb7", ATTRS{idProduct}=="01a2", ENV{.MM_USBIFNUM}=="05", ENV{ID_MM_PORT_IGNORE}="1"
 
+# Fibocom FM101-GL (MBIM): ChromeOS specific configuration
+#  ttyUSB0 (if #2): ignored in MM
+#  ttyUSB1 (if #3): ignored in MM
+ATTRS{idVendor}=="2cb7", ATTRS{idProduct}=="01a2", ENV{.MM_USBIFNUM}=="02", SUBSYSTEM=="tty", ENV{ID_MM_PORT_IGNORE}="1"
+
 # Fibocom FM101-GL (ADB)
 #  ttyUSB0 (if #2): debug port (ignore)
 #  ttyUSB1 (if #3): AT port
diff --git a/src/plugins/fibocom/mm-shared-fibocom.c b/src/plugins/fibocom/mm-shared-fibocom.c
index 10b82c5..c963664 100644
--- a/src/plugins/fibocom/mm-shared-fibocom.c
+++ b/src/plugins/fibocom/mm-shared-fibocom.c
@@ -27,6 +27,8 @@
 #include "mm-broadband-modem-mbim.h"
 #include "mm-iface-modem.h"
 #include "mm-iface-modem-3gpp.h"
+#include "mm-modem-helpers-mbim.h"
+#include "mm-port-mbim.h"
 #include "mm-shared-fibocom.h"
 
 /*****************************************************************************/
@@ -109,6 +111,209 @@
     g_object_unref (task);
 }
 
+
+
+static gboolean
+peek_device (gpointer              self,
+             MbimDevice          **o_device,
+             GAsyncReadyCallback   callback,
+             gpointer              user_data)
+{
+    MMPortMbim *port;
+
+    port = mm_broadband_modem_mbim_peek_port_mbim (MM_BROADBAND_MODEM_MBIM (self));
+    if (!port) {
+        g_task_report_new_error (self, callback, user_data, peek_device,
+                                 MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Couldn't peek MBIM port");
+        return FALSE;
+    }
+
+    *o_device = mm_port_mbim_peek_device (port);
+    return TRUE;
+}
+
+
+static void
+parent_att_hack_set_lte_attach_configuration_set_ready (MbimDevice   *device,
+                                                        GAsyncResult *res,
+                                                        GTask        *task)
+{
+    MbimMessage          *response;
+    GError               *error = NULL;
+
+    response = mbim_device_command_finish (device, res, &error);
+    if (!response || !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error))
+        g_task_return_error (task, error);
+    else
+        g_task_return_boolean (task, TRUE);
+    g_object_unref (task);
+
+    if (response)
+        mbim_message_unref (response);
+}
+
+/* This function is almost identical to before_set_lte_attach_configuration_query_ready in mm-broadband-modem-mbim.c
+ * The only difference is the code related to ptr_home/ptr_partner/ptr_non_partner and the flow that is executed after this function. */
+static void
+parent_att_hack_before_set_lte_attach_configuration_query_ready (MbimDevice   *device,
+                                                                 GAsyncResult *res,
+                                                                 GTask        *task)
+{
+    MMBroadbandModemMbim                       *self;
+    MbimMessage                                *request;
+    MbimMessage                                *response;
+    GError                                     *error = NULL;
+    MMBearerProperties                         *config;
+    guint32                                     n_configurations = 0;
+    MbimLteAttachConfiguration                **configurations = NULL;
+    gint                                        i;
+    MbimLteAttachConfiguration *ptr_home = NULL, *ptr_partner = NULL, *ptr_non_partner = NULL;
+
+    self   = g_task_get_source_object (task);
+    config = g_task_get_task_data (task);
+
+    response = mbim_device_command_finish (device, res, &error);
+    if (!response ||
+        !mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error) ||
+        !mbim_message_ms_basic_connect_extensions_lte_attach_configuration_response_parse (
+            response,
+            &n_configurations,
+            &configurations,
+            &error)) {
+        g_task_return_error (task, error);
+        g_object_unref (task);
+        goto out;
+    }
+
+    /* We should always receive 3 configurations but the MBIM API doesn't force
+     * that so we'll just assume we don't get always the same fixed number */
+    for (i = 0; i < n_configurations; i++) {
+        MMBearerIpFamily ip_family;
+        MMBearerAllowedAuth auth;
+
+        /* We only support configuring the HOME settings */
+        if (configurations[i]->roaming != MBIM_LTE_ATTACH_CONTEXT_ROAMING_CONTROL_HOME)
+            continue;
+
+        ip_family = mm_bearer_properties_get_ip_type (config);
+        if (ip_family == MM_BEARER_IP_FAMILY_NONE || ip_family == MM_BEARER_IP_FAMILY_ANY)
+            configurations[i]->ip_type = MBIM_CONTEXT_IP_TYPE_DEFAULT;
+        else {
+            configurations[i]->ip_type = mm_bearer_ip_family_to_mbim_context_ip_type (ip_family, &error);
+            if (error) {
+                configurations[i]->ip_type = MBIM_CONTEXT_IP_TYPE_DEFAULT;
+                mm_obj_warn (self, "unexpected IP type settings requested: %s", error->message);
+                g_clear_error (&error);
+            }
+        }
+
+        g_clear_pointer (&(configurations[i]->access_string), g_free);
+        configurations[i]->access_string = g_strdup (mm_bearer_properties_get_apn (config));
+
+        g_clear_pointer (&(configurations[i]->user_name), g_free);
+        configurations[i]->user_name = g_strdup (mm_bearer_properties_get_user (config));
+
+        g_clear_pointer (&(configurations[i]->password), g_free);
+        configurations[i]->password = g_strdup (mm_bearer_properties_get_password (config));
+
+        auth = mm_bearer_properties_get_allowed_auth (config);
+        if ((auth != MM_BEARER_ALLOWED_AUTH_UNKNOWN) || configurations[i]->user_name || configurations[i]->password) {
+            configurations[i]->auth_protocol = mm_bearer_allowed_auth_to_mbim_auth_protocol (auth, self, &error);
+            if (error) {
+                configurations[i]->auth_protocol = MBIM_AUTH_PROTOCOL_NONE;
+                mm_obj_warn (self, "unexpected auth settings requested: %s", error->message);
+                g_clear_error (&error);
+            }
+        } else {
+            configurations[i]->auth_protocol = MBIM_AUTH_PROTOCOL_NONE;
+        }
+
+        configurations[i]->source = MBIM_CONTEXT_SOURCE_USER;
+        configurations[i]->compression = MBIM_COMPRESSION_NONE;
+        break;
+    }
+
+    /* Code customization start b/224986971 */
+    for (i = 0; i < n_configurations; i++) {
+        if (configurations[i]->roaming == MBIM_LTE_ATTACH_CONTEXT_ROAMING_CONTROL_HOME)
+            ptr_home = configurations[i];
+        else if (configurations[i]->roaming == MBIM_LTE_ATTACH_CONTEXT_ROAMING_CONTROL_NON_PARTNER)
+            ptr_non_partner = configurations[i];
+        else
+            ptr_partner = configurations[i];
+    }
+    /* Sort the profiles in the order home, non_partner and partner, so we can easily remove the last one(partner). */
+    if (n_configurations == 3 && ptr_home && ptr_partner && ptr_non_partner) {
+        mm_obj_info (self, "removing partner profile");
+        configurations[0] = ptr_home;
+        configurations[1] = ptr_non_partner;
+        configurations[2] = ptr_partner;
+        n_configurations = 2;
+    }
+    /* Code customization end b/224986971 */
+
+    request = mbim_message_ms_basic_connect_extensions_lte_attach_configuration_set_new (
+                  MBIM_LTE_ATTACH_CONTEXT_OPERATION_DEFAULT,
+                  n_configurations,
+                  (const MbimLteAttachConfiguration *const *)configurations,
+                  &error);
+    if (!request) {
+        g_task_return_error (task, error);
+        g_object_unref (task);
+        goto out;
+    }
+    mbim_device_command (device,
+                         request,
+                         10,
+                         NULL,
+                         (GAsyncReadyCallback)parent_att_hack_set_lte_attach_configuration_set_ready,
+                         task);
+    mbim_message_unref (request);
+
+ out:
+    if (configurations)
+        mbim_lte_attach_configuration_array_free (configurations);
+
+    if (response)
+        mbim_message_unref (response);
+}
+
+/* This function is functionally identical to set_initial_eps_bearer_settings in mm-broadband-modem-mbim.c */
+static void
+parent_att_hack_set_initial_eps_bearer_settings (MMIfaceModem3gpp    *_self,
+                                                 MMBearerProperties  *config,
+                                                 GAsyncReadyCallback  callback,
+                                                 gpointer             user_data)
+{
+    MMSharedFibocom *self = MM_SHARED_FIBOCOM (_self);
+    GTask                *task;
+    MbimDevice           *device;
+    MbimMessage          *message;
+
+    if (!peek_device (MM_BROADBAND_MODEM_MBIM (self), &device, callback, user_data))
+        return;
+
+    task = g_task_new (self, NULL, callback, user_data);
+
+    if (!mm_broadband_modem_mbim_get_is_lte_attach_info_supported(MM_BROADBAND_MODEM_MBIM (self))) {
+        g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED,
+                                 "LTE attach configuration is unsupported");
+        g_object_unref (task);
+        return;
+    }
+
+    g_task_set_task_data (task, g_object_ref (config), g_object_unref);
+
+    message = mbim_message_ms_basic_connect_extensions_lte_attach_configuration_query_new (NULL);
+    mbim_device_command (device,
+                         message,
+                         10,
+                         NULL,
+                         (GAsyncReadyCallback)parent_att_hack_before_set_lte_attach_configuration_query_ready,
+                         task);
+    mbim_message_unref (message);
+}
+
 static void
 parent_set_initial_eps_bearer_settings_ready (MMIfaceModem3gpp *self,
                                               GAsyncResult     *res,
@@ -146,6 +351,9 @@
     MMSharedFibocom                    *self;
     SetInitialEpsBearerSettingsContext *ctx;
     Private                            *priv;
+    g_autoptr(MMBaseSim)                modem_sim = NULL;
+    gchar                              *apn;
+    gchar                              *operator_identifier = NULL;
 
     self = g_task_get_source_object (task);
     ctx  = g_task_get_task_data (task);
@@ -155,6 +363,24 @@
     g_assert (priv->iface_modem_3gpp_parent->set_initial_eps_bearer_settings);
     g_assert (priv->iface_modem_3gpp_parent->set_initial_eps_bearer_settings_finish);
 
+    g_object_get (self,
+                  MM_IFACE_MODEM_SIM, &modem_sim,
+                  NULL);
+    if (modem_sim)
+        operator_identifier = mm_gdbus_sim_get_operator_identifier(modem_sim);
+    apn = mm_bearer_properties_get_apn (ctx->config);
+    mm_obj_info (self, "operator_identifier: '%s' apn='%s'", operator_identifier, apn);
+    if (mm_base_modem_get_vendor_id (MM_BASE_MODEM (self)) == 0x2cb7 &&
+        mm_base_modem_get_product_id (MM_BASE_MODEM (self)) == 0x0007 &&
+        operator_identifier && g_strcmp0(operator_identifier, "310280") == 0) {
+        mm_obj_info (self, "executing custom attach logic for AT&T 310280");
+        parent_att_hack_set_initial_eps_bearer_settings (MM_IFACE_MODEM_3GPP (self),
+                                                         ctx->config,
+                                                         (GAsyncReadyCallback)parent_set_initial_eps_bearer_settings_ready,
+                                                         task);
+        return;
+    }
+
     priv->iface_modem_3gpp_parent->set_initial_eps_bearer_settings (MM_IFACE_MODEM_3GPP (self),
                                                                     ctx->config,
                                                                     (GAsyncReadyCallback)parent_set_initial_eps_bearer_settings_ready,
diff --git a/src/plugins/intel/mm-broadband-modem-mbim-intel.c b/src/plugins/intel/mm-broadband-modem-mbim-intel.c
index f6cf33d..b4e1d93 100644
--- a/src/plugins/intel/mm-broadband-modem-mbim-intel.c
+++ b/src/plugins/intel/mm-broadband-modem-mbim-intel.c
@@ -29,15 +29,21 @@
 #include "mm-broadband-modem-mbim-intel.h"
 #include "mm-iface-modem-location.h"
 #include "mm-shared-xmm.h"
+#include "mm-shared-fibocom.h"
 
 static void iface_modem_location_init (MMIfaceModemLocation *iface);
+static void iface_modem_3gpp_init     (MMIfaceModem3gpp *iface);
 static void shared_xmm_init           (MMSharedXmm          *iface);
+static void shared_fibocom_init       (MMSharedFibocom *iface);
 
 static MMIfaceModemLocation *iface_modem_location_parent;
+static MMIfaceModem3gpp *iface_modem_3gpp_parent;
 
 G_DEFINE_TYPE_EXTENDED (MMBroadbandModemMbimIntel, mm_broadband_modem_mbim_intel, MM_TYPE_BROADBAND_MODEM_MBIM, 0,
                         G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_LOCATION, iface_modem_location_init)
-                        G_IMPLEMENT_INTERFACE (MM_TYPE_SHARED_XMM,  shared_xmm_init))
+                        G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_3GPP, iface_modem_3gpp_init)
+                        G_IMPLEMENT_INTERFACE (MM_TYPE_SHARED_XMM,  shared_xmm_init)
+                        G_IMPLEMENT_INTERFACE (MM_TYPE_SHARED_FIBOCOM, shared_fibocom_init))
 
 /*****************************************************************************/
 
@@ -116,6 +122,15 @@
     iface->set_supl_server_finish            = mm_shared_xmm_location_set_supl_server_finish;
 }
 
+static void
+iface_modem_3gpp_init (MMIfaceModem3gpp *iface)
+{
+    iface_modem_3gpp_parent = g_type_interface_peek_parent (iface);
+
+    iface->set_initial_eps_bearer_settings        = mm_shared_fibocom_set_initial_eps_bearer_settings;
+    iface->set_initial_eps_bearer_settings_finish = mm_shared_fibocom_set_initial_eps_bearer_settings_finish;
+}
+
 static MMBroadbandModemClass *
 peek_parent_broadband_modem_class (MMSharedXmm *self)
 {
@@ -128,6 +143,18 @@
     return iface_modem_location_parent;
 }
 
+static MMIfaceModem3gpp *
+peek_parent_3gpp_interface (MMSharedFibocom *self)
+{
+    return iface_modem_3gpp_parent;
+}
+
+static void
+shared_fibocom_init (MMSharedFibocom *iface)
+{
+    iface->peek_parent_3gpp_interface = peek_parent_3gpp_interface;
+}
+
 static void
 shared_xmm_init (MMSharedXmm *iface)
 {
diff --git a/src/plugins/intel/mm-plugin-intel.c b/src/plugins/intel/mm-plugin-intel.c
index 62e2350..ce11d33 100644
--- a/src/plugins/intel/mm-plugin-intel.c
+++ b/src/plugins/intel/mm-plugin-intel.c
@@ -67,7 +67,7 @@
 mm_plugin_create_intel (void)
 {
     static const gchar   *subsystems[] = { "net", "wwan", NULL };
-    static const guint16  vendor_ids[]  = { 0x8086, 0 };
+    static const guint16  vendor_ids[]  = { 0x8086, 0x14C3, 0 };
 
     return MM_PLUGIN (
                g_object_new (MM_TYPE_PLUGIN_INTEL,
diff --git a/src/plugins/meson.build b/src/plugins/meson.build
index 0309312..fbcefda 100644
--- a/src/plugins/meson.build
+++ b/src/plugins/meson.build
@@ -501,7 +501,7 @@
 
   plugins += {'plugin-intel': {
     'plugin': true,
-    'module': {'sources': sources, 'include_directories': plugins_incs + [xmm_inc], 'c_args': common_c_args},
+    'module': {'sources': sources, 'include_directories': plugins_incs + [xmm_inc] + [fibocom_inc], 'c_args': common_c_args},
   }}
 endif
 
diff --git a/src/plugins/qcom-soc/77-mm-qcom-soc.rules b/src/plugins/qcom-soc/77-mm-qcom-soc.rules
index 9719f96..8320a85 100644
--- a/src/plugins/qcom-soc/77-mm-qcom-soc.rules
+++ b/src/plugins/qcom-soc/77-mm-qcom-soc.rules
@@ -37,4 +37,7 @@
 # flag all rpmsg ports under this plugin as candidate
 KERNEL=="rpmsg*", SUBSYSTEM=="rpmsg", ENV{ID_MM_CANDIDATE}="1"
 
+# TODO(b/175305412): flag rmnet_data0 port under this plugin as candidate.
+KERNEL=="rmnet_data0", SUBSYSTEM=="net", ENV{ID_MM_CANDIDATE}="1"
+
 LABEL="mm_qcom_soc_end"
diff --git a/src/plugins/tests/test-fixture.c b/src/plugins/tests/test-fixture.c
index 29eb8d5..ac2d3e6 100644
--- a/src/plugins/tests/test-fixture.c
+++ b/src/plugins/tests/test-fixture.c
@@ -142,7 +142,7 @@
             break;
 
         /* Blocking wait */
-        g_assert_cmpuint (wait_time, <=, 20);
+        g_assert_cmpuint (wait_time, <=, 120);
         wait_time++;
         sleep (1);
     }
diff --git a/src/tests/test-qcdm-serial-port.c b/src/tests/test-qcdm-serial-port.c
index fff345d..bf8ff4b 100644
--- a/src/tests/test-qcdm-serial-port.c
+++ b/src/tests/test-qcdm-serial-port.c
@@ -444,10 +444,13 @@
 {
     g_test_init (&argc, &argv, NULL);
 
-    TESTCASE_PTY ("/MM/QCDM/Verinfo", test_verinfo);
-    TESTCASE_PTY ("/MM/QCDM/Sierra-Cns-Rejected", test_sierra_cns_rejected);
-    TESTCASE_PTY ("/MM/QCDM/Random-Data-Rejected", test_random_data_rejected);
-    TESTCASE_PTY ("/MM/QCDM/Leading-Frame-Markers", test_leading_frame_markers);
+    // Disabled in ChromiumOS because of flakiness.
+    // TODO(b/172214192); Re-enabled them once
+    // https://gitlab.freedesktop.org/mobile-broadband/ModemManager/-/issues/184 is resolved
+    // TESTCASE_PTY ("/MM/QCDM/Verinfo", test_verinfo);
+    // TESTCASE_PTY ("/MM/QCDM/Sierra-Cns-Rejected", test_sierra_cns_rejected);
+    // TESTCASE_PTY ("/MM/QCDM/Random-Data-Rejected", test_random_data_rejected);
+    // TESTCASE_PTY ("/MM/QCDM/Leading-Frame-Markers", test_leading_frame_markers);
 
     return g_test_run ();
 }
diff --git a/unblocked_terms.txt b/unblocked_terms.txt
new file mode 100644
index 0000000..cc0e0cd
--- /dev/null
+++ b/unblocked_terms.txt
@@ -0,0 +1,12 @@
+# Don't delete this file if you want to keep keyword_check enabled even if it's
+# empty.
+# See repohooks/README.md for more details.
+black.?list
+dummy
+gr[ae]y.?list
+\bhe\b
+\bshe\b
+master
+\bnative
+slave
+white.?list