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

Change-Id: I753a8aaa7c1fb054ac6f249c86b5476f65e98914
diff --git a/.gitignore b/.gitignore
index 9846a32..d80e0ff 100644
--- a/.gitignore
+++ b/.gitignore
@@ -69,8 +69,6 @@
 /libqcdm/tests/ipv6pref
 /libqcdm/tests/reset
 
-/libwmc/tests/test-wmc
-
 /data/org.freedesktop.ModemManager1.conf
 /data/org.freedesktop.ModemManager1.service
 /data/org.freedesktop.ModemManager1.policy
@@ -159,10 +157,9 @@
 /m4/fcntl-o.m4
 /m4/threadlib.m4
 
-/uml290/uml290mode
-
 /plugins/test-suite.log
 /plugins/test-udev-rules
+/plugins/test-keyfiles
 /plugins/test-modem-helpers-*
 /plugins/test-service-*
 
diff --git a/Makefile.am b/Makefile.am
index 1002182..b70b062 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -6,14 +6,12 @@
 	data \
 	include \
 	libqcdm \
-	libwmc \
 	libmm-glib \
 	src \
 	plugins \
 	cli \
 	vapi \
 	introspection \
-	uml290 \
 	test \
 	examples \
 	docs \
diff --git a/cli/mmcli-modem.c b/cli/mmcli-modem.c
index 9c96429..e6c4a62 100644
--- a/cli/mmcli-modem.c
+++ b/cli/mmcli-modem.c
@@ -351,6 +351,8 @@
     mmcli_output_string           (MMC_F_HARDWARE_MANUFACTURER,           mm_modem_get_manufacturer (ctx->modem));
     mmcli_output_string           (MMC_F_HARDWARE_MODEL,                  mm_modem_get_model (ctx->modem));
     mmcli_output_string           (MMC_F_HARDWARE_REVISION,               mm_modem_get_revision (ctx->modem));
+    mmcli_output_string           (MMC_F_HARDWARE_CARRIER_CONF,           mm_modem_get_carrier_configuration (ctx->modem));
+    mmcli_output_string           (MMC_F_HARDWARE_CARRIER_CONF_REV,       mm_modem_get_carrier_configuration_revision (ctx->modem));
     mmcli_output_string           (MMC_F_HARDWARE_HW_REVISION,            mm_modem_get_hardware_revision (ctx->modem));
     mmcli_output_string_multiline (MMC_F_HARDWARE_SUPPORTED_CAPABILITIES, supported_capabilities_string);
     mmcli_output_string_multiline (MMC_F_HARDWARE_CURRENT_CAPABILITIES,   current_capabilities_string);
diff --git a/cli/mmcli-output.c b/cli/mmcli-output.c
index 5822ff5..0242460 100644
--- a/cli/mmcli-output.c
+++ b/cli/mmcli-output.c
@@ -96,7 +96,9 @@
     [MMC_F_GENERAL_DEVICE_ID]                 = { "modem.generic.device-identifier",                 "device id",                MMC_S_MODEM_GENERAL,           },
     [MMC_F_HARDWARE_MANUFACTURER]             = { "modem.generic.manufacturer",                      "manufacturer",             MMC_S_MODEM_HARDWARE,          },
     [MMC_F_HARDWARE_MODEL]                    = { "modem.generic.model",                             "model",                    MMC_S_MODEM_HARDWARE,          },
-    [MMC_F_HARDWARE_REVISION]                 = { "modem.generic.revision",                          "revision",                 MMC_S_MODEM_HARDWARE,          },
+    [MMC_F_HARDWARE_REVISION]                 = { "modem.generic.revision",                          "firmware revision",        MMC_S_MODEM_HARDWARE,          },
+    [MMC_F_HARDWARE_CARRIER_CONF]             = { "modem.generic.carrier-configuration",             "carrier config",           MMC_S_MODEM_HARDWARE,          },
+    [MMC_F_HARDWARE_CARRIER_CONF_REV]         = { "modem.generic.carrier-configuration-revision",    "carrier config revision",  MMC_S_MODEM_HARDWARE,          },
     [MMC_F_HARDWARE_HW_REVISION]              = { "modem.generic.hardware-revision",                 "h/w revision",             MMC_S_MODEM_HARDWARE,          },
     [MMC_F_HARDWARE_SUPPORTED_CAPABILITIES]   = { "modem.generic.supported-capabilities",            "supported",                MMC_S_MODEM_HARDWARE,          },
     [MMC_F_HARDWARE_CURRENT_CAPABILITIES]     = { "modem.generic.current-capabilities",              "current",                  MMC_S_MODEM_HARDWARE,          },
diff --git a/cli/mmcli-output.h b/cli/mmcli-output.h
index 4a9a9c4..7793f79 100644
--- a/cli/mmcli-output.h
+++ b/cli/mmcli-output.h
@@ -91,6 +91,8 @@
     MMC_F_HARDWARE_MANUFACTURER,
     MMC_F_HARDWARE_MODEL,
     MMC_F_HARDWARE_REVISION,
+    MMC_F_HARDWARE_CARRIER_CONF,
+    MMC_F_HARDWARE_CARRIER_CONF_REV,
     MMC_F_HARDWARE_HW_REVISION,
     MMC_F_HARDWARE_SUPPORTED_CAPABILITIES,
     MMC_F_HARDWARE_CURRENT_CAPABILITIES,
diff --git a/configure.ac b/configure.ac
index e7e7337..a6ebfd6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -376,7 +376,6 @@
 dnl
 
 AM_CONDITIONAL(QCDM_STANDALONE, test "yes" = "no")
-AM_CONDITIONAL(WMC_STANDALONE, test "yes" = "no")
 
 dnl-----------------------------------------------------------------------------
 dnl Protocol libs
@@ -395,13 +394,9 @@
 libqcdm/Makefile
 libqcdm/src/Makefile
 libqcdm/tests/Makefile
-libwmc/Makefile
-libwmc/src/Makefile
-libwmc/tests/Makefile
 src/Makefile
 src/tests/Makefile
 plugins/Makefile
-uml290/Makefile
 test/Makefile
 introspection/Makefile
 introspection/tests/Makefile
diff --git a/docs/reference/libmm-glib/libmm-glib-sections.txt b/docs/reference/libmm-glib/libmm-glib-sections.txt
index 41f3b0d..583b494 100644
--- a/docs/reference/libmm-glib/libmm-glib-sections.txt
+++ b/docs/reference/libmm-glib/libmm-glib-sections.txt
@@ -137,6 +137,10 @@
 mm_modem_dup_model
 mm_modem_get_revision
 mm_modem_dup_revision
+mm_modem_get_carrier_configuration
+mm_modem_dup_carrier_configuration
+mm_modem_get_carrier_configuration_revision
+mm_modem_dup_carrier_configuration_revision
 mm_modem_get_hardware_revision
 mm_modem_dup_hardware_revision
 mm_modem_get_drivers
@@ -2022,6 +2026,10 @@
 mm_gdbus_modem_dup_ports
 mm_gdbus_modem_get_revision
 mm_gdbus_modem_dup_revision
+mm_gdbus_modem_get_carrier_configuration
+mm_gdbus_modem_dup_carrier_configuration
+mm_gdbus_modem_get_carrier_configuration_revision
+mm_gdbus_modem_dup_carrier_configuration_revision
 mm_gdbus_modem_get_hardware_revision
 mm_gdbus_modem_dup_hardware_revision
 mm_gdbus_modem_get_signal_quality
@@ -2093,6 +2101,8 @@
 mm_gdbus_modem_set_primary_port
 mm_gdbus_modem_set_ports
 mm_gdbus_modem_set_revision
+mm_gdbus_modem_set_carrier_configuration
+mm_gdbus_modem_set_carrier_configuration_revision
 mm_gdbus_modem_set_hardware_revision
 mm_gdbus_modem_set_signal_quality
 mm_gdbus_modem_set_sim
diff --git a/introspection/org.freedesktop.ModemManager1.Modem.xml b/introspection/org.freedesktop.ModemManager1.Modem.xml
index 7ac7cdd..0fc5741 100644
--- a/introspection/org.freedesktop.ModemManager1.Modem.xml
+++ b/introspection/org.freedesktop.ModemManager1.Modem.xml
@@ -297,6 +297,20 @@
     <property name="Revision" type="s" access="read" />
 
     <!--
+        CarrierConfiguration:
+
+        The description of the carrier-specific configuration (MCFG) in use by the modem.
+    -->
+    <property name="CarrierConfiguration" type="s" access="read" />
+
+    <!--
+        CarrierConfigurationRevision:
+
+        The revision identification of the carrier-specific configuration (MCFG) in use by the modem.
+    -->
+    <property name="CarrierConfigurationRevision" type="s" access="read" />
+
+    <!--
         HardwareRevision:
 
         The revision identification of the hardware, as reported by the modem.
diff --git a/libmm-glib/mm-modem.c b/libmm-glib/mm-modem.c
index 80cb280..9aab453 100644
--- a/libmm-glib/mm-modem.c
+++ b/libmm-glib/mm-modem.c
@@ -503,6 +503,88 @@
 /*****************************************************************************/
 
 /**
+ * mm_modem_get_carrier_configuration:
+ * @self: A #MMModem.
+ *
+ * Gets the carrier-specific configuration (MCFG) in use, as reported by this #MMModem.
+ *
+ * <warning>The returned value is only valid until the property changes so
+ * it is only safe to use this function on the thread where
+ * @self was constructed. Use mm_modem_dup_carrier_configuration() if on another
+ * thread.</warning>
+ *
+ * Returns: (transfer none): The carrier configuration, or %NULL if none available. Do not free the returned value, it belongs to @self.
+ */
+const gchar *
+mm_modem_get_carrier_configuration (MMModem *self)
+{
+    g_return_val_if_fail (MM_IS_MODEM (self), NULL);
+
+    RETURN_NON_EMPTY_CONSTANT_STRING (
+        mm_gdbus_modem_get_carrier_configuration (MM_GDBUS_MODEM (self)));
+}
+
+/**
+ * mm_modem_dup_carrier_configuration:
+ * @self: A #MMModem.
+ *
+ * Gets a copy of the carrier-specific configuration (MCFG) in use, as reported by this #MMModem.
+ *
+ * Returns: (transfer full): The carrier configuration, or %NULL if none available. The returned value should be freed with g_free().
+ */
+gchar *
+mm_modem_dup_carrier_configuration (MMModem *self)
+{
+    g_return_val_if_fail (MM_IS_MODEM (self), NULL);
+
+    RETURN_NON_EMPTY_STRING (
+        mm_gdbus_modem_dup_carrier_configuration (MM_GDBUS_MODEM (self)));
+}
+
+/*****************************************************************************/
+
+/**
+ * mm_modem_get_carrier_configuration_revision:
+ * @self: A #MMModem.
+ *
+ * Gets the carrier-specific configuration revision in use, as reported by this #MMModem.
+ *
+ * <warning>The returned value is only valid until the property changes so
+ * it is only safe to use this function on the thread where
+ * @self was constructed. Use mm_modem_dup_carrier_configuration() if on another
+ * thread.</warning>
+ *
+ * Returns: (transfer none): The carrier configuration revision, or %NULL if none available. Do not free the returned value, it belongs to @self.
+ */
+const gchar *
+mm_modem_get_carrier_configuration_revision (MMModem *self)
+{
+    g_return_val_if_fail (MM_IS_MODEM (self), NULL);
+
+    RETURN_NON_EMPTY_CONSTANT_STRING (
+        mm_gdbus_modem_get_carrier_configuration_revision (MM_GDBUS_MODEM (self)));
+}
+
+/**
+ * mm_modem_dup_carrier_configuration_revision:
+ * @self: A #MMModem.
+ *
+ * Gets a copy of the carrier-specific configuration revision in use, as reported by this #MMModem.
+ *
+ * Returns: (transfer full): The carrier configuration revision, or %NULL if none available. The returned value should be freed with g_free().
+ */
+gchar *
+mm_modem_dup_carrier_configuration_revision (MMModem *self)
+{
+    g_return_val_if_fail (MM_IS_MODEM (self), NULL);
+
+    RETURN_NON_EMPTY_STRING (
+        mm_gdbus_modem_dup_carrier_configuration_revision (MM_GDBUS_MODEM (self)));
+}
+
+/*****************************************************************************/
+
+/**
  * mm_modem_get_hardware_revision:
  * @self: A #MMModem.
  *
diff --git a/libmm-glib/mm-modem.h b/libmm-glib/mm-modem.h
index 1b51b6c..e494ced 100644
--- a/libmm-glib/mm-modem.h
+++ b/libmm-glib/mm-modem.h
@@ -103,6 +103,11 @@
 const gchar       *mm_modem_get_revision             (MMModem *self);
 gchar             *mm_modem_dup_revision             (MMModem *self);
 
+const gchar       *mm_modem_get_carrier_configuration          (MMModem *self);
+gchar             *mm_modem_dup_carrier_configuration          (MMModem *self);
+const gchar       *mm_modem_get_carrier_configuration_revision (MMModem *self);
+gchar             *mm_modem_dup_carrier_configuration_revision (MMModem *self);
+
 const gchar       *mm_modem_get_hardware_revision    (MMModem *self);
 gchar             *mm_modem_dup_hardware_revision    (MMModem *self);
 
diff --git a/libwmc/AUTHORS b/libwmc/AUTHORS
deleted file mode 100644
index e69de29..0000000
--- a/libwmc/AUTHORS
+++ /dev/null
diff --git a/libwmc/ChangeLog b/libwmc/ChangeLog
deleted file mode 100644
index e69de29..0000000
--- a/libwmc/ChangeLog
+++ /dev/null
diff --git a/libwmc/Makefile.am b/libwmc/Makefile.am
deleted file mode 100644
index 77f28d7..0000000
--- a/libwmc/Makefile.am
+++ /dev/null
@@ -1,2 +0,0 @@
-SUBDIRS=src tests
-
diff --git a/libwmc/NEWS b/libwmc/NEWS
deleted file mode 100644
index e69de29..0000000
--- a/libwmc/NEWS
+++ /dev/null
diff --git a/libwmc/README b/libwmc/README
deleted file mode 100644
index e69de29..0000000
--- a/libwmc/README
+++ /dev/null
diff --git a/libwmc/autogen.sh b/libwmc/autogen.sh
deleted file mode 100755
index df15fce..0000000
--- a/libwmc/autogen.sh
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/bin/sh
-# Run this to generate all the initial makefiles, etc.
-# NOTE
-# This autogen.sh is only used when building libwmc separately from ModemManager
-
-srcdir=`dirname $0`
-test -z "$srcdir" && srcdir=.
-REQUIRED_AUTOMAKE_VERSION=1.7
-PKG_NAME=libwmc
-
-(test -f $srcdir/configure.ac \
-  && test -f $srcdir/src/com.c) || {
-    echo -n "**Error**: Directory "\`$srcdir\'" does not look like the"
-    echo " top-level $PKG_NAME directory"
-    exit 1
-}
-
-(cd $srcdir;
-    autoreconf --install --symlink &&
-    autoreconf &&
-    ./configure --enable-maintainer-mode $@
-)
diff --git a/libwmc/configure.ac b/libwmc/configure.ac
deleted file mode 100644
index 4d2b90c..0000000
--- a/libwmc/configure.ac
+++ /dev/null
@@ -1,48 +0,0 @@
-# NOTE
-# This configure.ac is only used when building libqcdm separately from
-# ModemManager.
-#
-
-AC_PREREQ(2.52)
-
-AC_INIT(libwmc, 0.1, dcbw@redhat.com, libwmc)
-AM_INIT_AUTOMAKE([1.9 subdir-objects tar-ustar no-dist-gzip dist-bzip2])
-m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
-AM_MAINTAINER_MODE
-
-AC_CONFIG_MACRO_DIR([m4])
-
-AC_CONFIG_HEADERS(config.h)
-
-dnl Define _GNU_SOURCE for various things like strcasestr()
-AC_GNU_SOURCE
-
-dnl Required programs
-AC_PROG_CC
-AM_PROG_CC_C_O
-AC_PROG_INSTALL
-AC_PROG_LIBTOOL
-
-dnl
-dnl Tests
-dnl
-AC_ARG_WITH(tests, AS_HELP_STRING([--with-tests], [Build libwmc tests]))
-AM_CONDITIONAL(WITH_TESTS, test "x$with_tests" = "xyes")
-case $with_tests in
-    yes)
-        PKG_CHECK_MODULES(MM, glib-2.0 >= 2.20)
-	AC_SUBST(MM_CFLAGS)
-	AC_SUBST(MM_LIBS)
-        ;;
-    *) ;;
-esac
-
-AM_CONDITIONAL(WMC_STANDALONE, test "yes" = "yes")
-
-AC_CONFIG_FILES([
-Makefile
-src/Makefile
-tests/Makefile
-])
-AC_OUTPUT
-
diff --git a/libwmc/src/Makefile.am b/libwmc/src/Makefile.am
deleted file mode 100644
index b662f89..0000000
--- a/libwmc/src/Makefile.am
+++ /dev/null
@@ -1,25 +0,0 @@
-AM_CFLAGS = $(CODE_COVERAGE_CFLAGS)
-AM_LDFLAGS = $(CODE_COVERAGE_LDFLAGS)
-
-noinst_LTLIBRARIES = libwmc.la
-
-libwmc_la_CPPFLAGS = \
-	$(MM_CFLAGS)
-
-libwmc_la_SOURCES = \
-	protocol.h \
-	result-private.h \
-	errors.c \
-	errors.h \
-	utils.c \
-	utils.h \
-	result.c \
-	result.h \
-	com.c \
-	com.h \
-	commands.c \
-	commands.h
-
-libwmc_la_LIBADD = \
-	$(MM_LIBS)
-
diff --git a/libwmc/src/com.c b/libwmc/src/com.c
deleted file mode 100644
index f27d49a..0000000
--- a/libwmc/src/com.c
+++ /dev/null
@@ -1,56 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*
- * Copyright (C) 2011 Red Hat, Inc.
- *
- * This program is free software: you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <errno.h>
-#include <termios.h>
-#include <fcntl.h>
-#include <string.h>
-
-#include "com.h"
-#include "errors.h"
-
-int
-wmc_port_setup (int fd)
-{
-    struct termios stbuf;
-
-    errno = 0;
-    memset (&stbuf, 0, sizeof (stbuf));
-    if (tcgetattr (fd, &stbuf) != 0) {
-        wmc_err (0, "tcgetattr() error: %d", errno);
-        return -WMC_ERROR_SERIAL_CONFIG_FAILED;
-    }
-
-    stbuf.c_cflag &= ~(CBAUD | CSIZE | CSTOPB | CLOCAL | PARENB);
-    stbuf.c_iflag &= ~(HUPCL | IUTF8 | IUCLC | ISTRIP | IXON | IXOFF | IXANY | ICRNL);
-    stbuf.c_oflag &= ~(OPOST | OCRNL | ONLCR | OLCUC | ONLRET);
-    stbuf.c_lflag &= ~(ICANON | ISIG | IEXTEN | ECHO | ECHOE | ECHOK | ECHONL);
-    stbuf.c_lflag &= ~(NOFLSH | TOSTOP | ECHOPRT | ECHOCTL | ECHOKE);
-    stbuf.c_cc[VMIN] = 1;
-    stbuf.c_cc[VTIME] = 0;
-    stbuf.c_cc[VEOF] = 1;
-    stbuf.c_cflag |= (B115200 | CS8 | CREAD | 0 | 0);  /* No parity, 1 stop bit */
-
-    errno = 0;
-    if (tcsetattr (fd, TCSANOW, &stbuf) < 0) {
-        wmc_err (0, "tcgetattr() error: %d", errno);
-        return -WMC_ERROR_SERIAL_CONFIG_FAILED;
-    }
-
-    return 0;
-}
-
diff --git a/libwmc/src/com.h b/libwmc/src/com.h
deleted file mode 100644
index 219a016..0000000
--- a/libwmc/src/com.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*
- * Copyright (C) 2011 Red Hat, Inc.
- *
- * This program is free software: you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef LIBWMC_COM_H
-#define LIBWMC_COM_H
-
-int wmc_port_setup (int fd);
-
-#endif  /* LIBWMC_COM_H */
diff --git a/libwmc/src/commands.c b/libwmc/src/commands.c
deleted file mode 100644
index 4c23460..0000000
--- a/libwmc/src/commands.c
+++ /dev/null
@@ -1,466 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*
- * Copyright (C) 2011 Red Hat, Inc.
- *
- * This program is free software: you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <string.h>
-#include <time.h>
-
-#include "commands.h"
-#include "errors.h"
-#include "result-private.h"
-#include "utils.h"
-#include "protocol.h"
-
-
-/**********************************************************************/
-
-static int
-check_command (const char *buf, size_t len, uint8_t cmd, size_t min_len)
-{
-    if (len < 1) {
-        wmc_err (0, "Zero-length response");
-        return -WMC_ERROR_RESPONSE_BAD_LENGTH;
-    }
-
-    if ((uint8_t) buf[0] != WMC_CMD_MARKER) {
-        wmc_err (0, "Missing WMC command marker (expected 0x%02X, got 0x%02X)",
-                 WMC_CMD_MARKER, (uint8_t) buf[0]);
-        return -WMC_ERROR_RESPONSE_UNEXPECTED;
-    }
-
-    if ((uint8_t) buf[1] != cmd) {
-        wmc_err (0, "Unexpected WMC command response (expected 0x%02X, got 0x%02X)",
-                 (uint8_t) cmd, (uint8_t) buf[1]);
-        return -WMC_ERROR_RESPONSE_UNEXPECTED;
-    }
-
-    if (len < min_len) {
-        wmc_err (0, "WMC command %d response not long enough (got %zu, expected "
-                 "at least %zu).", cmd, len, min_len);
-        return -WMC_ERROR_RESPONSE_BAD_LENGTH;
-    }
-
-    return 0;
-}
-
-/**********************************************************************/
-
-/**
- * wmc_cmd_init_new:
- * @buf: buffer in which to store constructed command
- * @buflen: size of @buf
- * @wmc2: if %TRUE add additional data that later-model devices (UML290) want
- *
- * Returns: size of the constructed command on success, or 0 on failure
- */
-size_t
-wmc_cmd_init_new (char *buf, size_t buflen, int wmc2)
-{
-    wmc_return_val_if_fail (buf != NULL, 0);
-
-    if (wmc2) {
-        WmcCmdInit2 *cmd = (WmcCmdInit2 *) buf;
-        time_t now;
-        struct tm *tm;
-
-        wmc_return_val_if_fail (buflen >= sizeof (*cmd), 0);
-
-        now = time (NULL);
-        tm = localtime (&now);
-
-        memset (cmd, 0, sizeof (*cmd));
-        cmd->hdr.marker = WMC_CMD_MARKER;
-        cmd->hdr.cmd = WMC_CMD_INIT;
-        cmd->year = htole16 (tm->tm_year + 1900);
-        cmd->month = tm->tm_mon + 1;
-        cmd->day = htobe16 (tm->tm_mday);
-        cmd->hours = htobe16 (tm->tm_hour);
-        cmd->minutes = htobe16 (tm->tm_min);
-        cmd->seconds = htobe16 (tm->tm_sec);
-        return sizeof (*cmd);
-    } else {
-        WmcCmdHeader *cmd = (WmcCmdHeader *) buf;
-
-        wmc_return_val_if_fail (buflen >= sizeof (*cmd), 0);
-
-        memset (cmd, 0, sizeof (*cmd));
-        cmd->marker = WMC_CMD_MARKER;
-        cmd->cmd = WMC_CMD_INIT;
-        return sizeof (*cmd);
-    }
-}
-
-WmcResult *
-wmc_cmd_init_result (const char *buf, size_t buflen, int wmc2)
-{
-    wmc_return_val_if_fail (buf != NULL, NULL);
-
-    if (wmc2) {
-        if (check_command (buf, buflen, WMC_CMD_INIT, sizeof (WmcCmdInit2Rsp)) < 0)
-            return NULL;
-    } else {
-        if (check_command (buf, buflen, WMC_CMD_INIT, sizeof (WmcCmdHeader)) < 0)
-            return NULL;
-    }
-
-    return wmc_result_new ();
-}
-
-/**********************************************************************/
-
-size_t
-wmc_cmd_device_info_new (char *buf, size_t buflen)
-{
-    WmcCmdHeader *cmd = (WmcCmdHeader *) buf;
-
-    wmc_return_val_if_fail (buf != NULL, 0);
-    wmc_return_val_if_fail (buflen >= sizeof (*cmd), 0);
-
-    memset (cmd, 0, sizeof (*cmd));
-    cmd->marker = WMC_CMD_MARKER;
-    cmd->cmd = WMC_CMD_DEVICE_INFO;
-    return sizeof (*cmd);
-}
-
-WmcResult *
-wmc_cmd_device_info_result (const char *buf, size_t buflen)
-{
-    WmcResult *r = NULL;
-    WmcCmdDeviceInfoRsp *rsp = (WmcCmdDeviceInfoRsp *) buf;
-    WmcCmdDeviceInfo2Rsp *rsp2 = (WmcCmdDeviceInfo2Rsp *) buf;
-    WmcCmdDeviceInfo3Rsp *rsp3 = (WmcCmdDeviceInfo3Rsp *) buf;
-    char tmp[65];
-
-    wmc_return_val_if_fail (buf != NULL, NULL);
-
-    if (check_command (buf, buflen, WMC_CMD_DEVICE_INFO, sizeof (WmcCmdDeviceInfo3Rsp)) < 0) {
-        rsp3 = NULL;
-        if (check_command (buf, buflen, WMC_CMD_DEVICE_INFO, sizeof (WmcCmdDeviceInfo2Rsp)) < 0) {
-            rsp2 = NULL;
-            if (check_command (buf, buflen, WMC_CMD_DEVICE_INFO, sizeof (WmcCmdDeviceInfoRsp)) < 0)
-                return NULL;
-        }
-    }
-
-    r = wmc_result_new ();
-
-    /* Manf */
-    memset (tmp, 0, sizeof (tmp));
-    wmc_assert (sizeof (rsp->manf) <= sizeof (tmp));
-    memcpy (tmp, rsp->manf, sizeof (rsp->manf));
-    wmc_result_add_string (r, WMC_CMD_DEVICE_INFO_ITEM_MANUFACTURER, tmp);
-
-    /* Model */
-    memset (tmp, 0, sizeof (tmp));
-    wmc_assert (sizeof (rsp->model) <= sizeof (tmp));
-    memcpy (tmp, rsp->model, sizeof (rsp->model));
-    wmc_result_add_string (r, WMC_CMD_DEVICE_INFO_ITEM_MODEL, tmp);
-
-    /* Firmware revision */
-    memset (tmp, 0, sizeof (tmp));
-    wmc_assert (sizeof (rsp->fwrev) <= sizeof (tmp));
-    memcpy (tmp, rsp->fwrev, sizeof (rsp->fwrev));
-    wmc_result_add_string (r, WMC_CMD_DEVICE_INFO_ITEM_FW_REVISION, tmp);
-
-    /* Hardware revision */
-    memset (tmp, 0, sizeof (tmp));
-    wmc_assert (sizeof (rsp->hwrev) <= sizeof (tmp));
-    memcpy (tmp, rsp->hwrev, sizeof (rsp->hwrev));
-    wmc_result_add_string (r, WMC_CMD_DEVICE_INFO_ITEM_HW_REVISION, tmp);
-
-    /* MIN */
-    memset (tmp, 0, sizeof (tmp));
-    wmc_assert (sizeof (rsp->min) <= sizeof (tmp));
-    memcpy (tmp, rsp->min, sizeof (rsp->min));
-    wmc_result_add_string (r, WMC_CMD_DEVICE_INFO_ITEM_CDMA_MIN, tmp);
-
-    wmc_result_add_u32 (r, WMC_CMD_DEVICE_INFO_ITEM_HOME_SID, le16toh (rsp->home_sid));
-    wmc_result_add_u32 (r, WMC_CMD_DEVICE_INFO_ITEM_PRL_VERSION, le16toh (rsp->prlver));
-    wmc_result_add_u32 (r, WMC_CMD_DEVICE_INFO_ITEM_ERI_VERSION, le16toh (rsp->eriver));
-
-    if (rsp2) {
-        /* MEID */
-        memset (tmp, 0, sizeof (tmp));
-        wmc_assert (sizeof (rsp2->meid) <= sizeof (tmp));
-        memcpy (tmp, rsp2->meid, sizeof (rsp2->meid));
-        wmc_result_add_string (r, WMC_CMD_DEVICE_INFO_ITEM_MEID, tmp);
-
-        /* IMEI */
-        memset (tmp, 0, sizeof (tmp));
-        wmc_assert (sizeof (rsp2->imei) <= sizeof (tmp));
-        memcpy (tmp, rsp2->imei, sizeof (rsp2->imei));
-        wmc_result_add_string (r, WMC_CMD_DEVICE_INFO_ITEM_IMEI, tmp);
-
-        /* IMSI */
-        memset (tmp, 0, sizeof (tmp));
-        wmc_assert (sizeof (rsp2->iccid) <= sizeof (tmp));
-        memcpy (tmp, rsp2->iccid, sizeof (rsp2->iccid));
-        wmc_result_add_string (r, WMC_CMD_DEVICE_INFO_ITEM_ICCID, tmp);
-    }
-
-    if (rsp3) {
-        /* MCC */
-        memset (tmp, 0, sizeof (tmp));
-        wmc_assert (sizeof (rsp3->mcc) <= sizeof (tmp));
-        memcpy (tmp, rsp3->mcc, sizeof (rsp3->mcc));
-        wmc_result_add_string (r, WMC_CMD_DEVICE_INFO_ITEM_MCC, tmp);
-
-        /* MNC */
-        memset (tmp, 0, sizeof (tmp));
-        wmc_assert (sizeof (rsp3->mnc) <= sizeof (tmp));
-        memcpy (tmp, rsp3->mnc, sizeof (rsp3->mnc));
-        wmc_result_add_string (r, WMC_CMD_DEVICE_INFO_ITEM_MNC, tmp);
-    }
-
-    return r;
-}
-
-/**********************************************************************/
-
-size_t
-wmc_cmd_network_info_new (char *buf, size_t buflen)
-{
-    WmcCmdHeader *cmd = (WmcCmdHeader *) buf;
-
-    wmc_return_val_if_fail (buf != NULL, 0);
-    wmc_return_val_if_fail (buflen >= sizeof (*cmd), 0);
-
-    memset (cmd, 0, sizeof (*cmd));
-    cmd->marker = WMC_CMD_MARKER;
-    cmd->cmd = WMC_CMD_NET_INFO;
-    return sizeof (*cmd);
-}
-
-static wmcbool
-is_gsm_service (uint8_t service)
-{
-    return (service == WMC_SERVICE_GSM || service == WMC_SERVICE_GPRS || service == WMC_SERVICE_EDGE);
-}
-
-static wmcbool
-is_umts_service (uint8_t service)
-{
-    return (service == WMC_SERVICE_UMTS || service == WMC_SERVICE_HSDPA
-            || service == WMC_SERVICE_HSUPA || service == WMC_SERVICE_HSPA);
-}
-
-static wmcbool
-is_cdma_service (uint8_t service)
-{
-    return (service == WMC_SERVICE_IS95A || service == WMC_SERVICE_IS95B || service == WMC_SERVICE_1XRTT);
-}
-
-static wmcbool
-is_evdo_service (uint8_t service)
-{
-    return (service == WMC_SERVICE_EVDO_0 || service == WMC_SERVICE_EVDO_A || service == WMC_SERVICE_EVDO_A_EHRPD);
-}
-
-static wmcbool
-is_lte_service (uint8_t service)
-{
-    return (service == WMC_SERVICE_LTE);
-}
-
-static uint8_t
-sanitize_dbm (uint8_t in_dbm, uint8_t service)
-{
-    uint8_t cutoff;
-
-    /* 0x6A (-106 dBm) = no signal for GSM/GPRS/EDGE */
-    /* 0x7D (-125 dBm) = no signal for everything else */
-    cutoff = is_gsm_service (service) ? 0x6A : 0x7D;
-
-    return in_dbm >= cutoff ? 0 : in_dbm;
-}
-
-
-WmcResult *
-wmc_cmd_network_info_result (const char *buf, size_t buflen)
-{
-    WmcResult *r = NULL;
-    WmcCmdNetworkInfoRsp *rsp = (WmcCmdNetworkInfoRsp *) buf;
-    WmcCmdNetworkInfo2Rsp *rsp2 = (WmcCmdNetworkInfo2Rsp *) buf;
-    WmcCmdNetworkInfo3Rsp *rsp3 = (WmcCmdNetworkInfo3Rsp *) buf;
-    char tmp[65];
-    int err;
-    uint32_t mccmnc = 0, mcc, mnc;
-
-    wmc_return_val_if_fail (buf != NULL, NULL);
-
-    err = check_command (buf, buflen, WMC_CMD_NET_INFO, sizeof (WmcCmdNetworkInfo3Rsp));
-    if (err != WMC_SUCCESS) {
-        if (err != -WMC_ERROR_RESPONSE_BAD_LENGTH)
-            return NULL;
-        rsp3 = NULL;
-
-        err = check_command (buf, buflen, WMC_CMD_NET_INFO, sizeof (WmcCmdNetworkInfo2Rsp));
-        if (err != WMC_SUCCESS) {
-            if (err != -WMC_ERROR_RESPONSE_BAD_LENGTH)
-                return NULL;
-            rsp2 = NULL;
-
-            err = check_command (buf, buflen, WMC_CMD_NET_INFO, sizeof (WmcCmdNetworkInfoRsp));
-            if (err != WMC_SUCCESS)
-                return NULL;
-        }
-    }
-
-    r = wmc_result_new ();
-
-    wmc_result_add_u8 (r, WMC_CMD_NETWORK_INFO_ITEM_SERVICE, rsp->service);
-
-    if (rsp2) {
-        wmc_result_add_u8 (r, WMC_CMD_NETWORK_INFO_ITEM_2G_DBM, sanitize_dbm (rsp2->two_g_dbm, rsp->service));
-        wmc_result_add_u8 (r, WMC_CMD_NETWORK_INFO_ITEM_3G_DBM, sanitize_dbm (rsp2->three_g_dbm, WMC_SERVICE_NONE));
-
-        memset (tmp, 0, sizeof (tmp));
-        if (   (is_cdma_service (rsp->service) && sanitize_dbm (rsp2->two_g_dbm, rsp->service))
-            || (is_evdo_service (rsp->service) && sanitize_dbm (rsp2->three_g_dbm, rsp->service))) {
-            /* CDMA2000 operator name */
-            wmc_assert (sizeof (rsp2->cdma_opname) <= sizeof (tmp));
-            memcpy (tmp, rsp2->cdma_opname, sizeof (rsp2->cdma_opname));
-            wmc_result_add_string (r, WMC_CMD_NETWORK_INFO_ITEM_OPNAME, tmp);
-        } else {
-            if (   (is_gsm_service (rsp->service) && sanitize_dbm (rsp2->two_g_dbm, rsp->service))
-                || (is_umts_service (rsp->service) && sanitize_dbm (rsp2->three_g_dbm, rsp->service))) {
-                /* GSM/UMTS operator name */
-                wmc_assert (sizeof (rsp2->tgpp_opname) <= sizeof (tmp));
-                memcpy (tmp, rsp2->tgpp_opname, sizeof (rsp2->tgpp_opname));
-                wmc_result_add_string (r, WMC_CMD_NETWORK_INFO_ITEM_OPNAME, tmp);
-            }
-        }
-
-        /* MCC/MNC */
-        mccmnc = le32toh (rsp2->mcc_mnc);
-        if (mccmnc < 100000)
-            mccmnc *= 10;    /* account for possible 2-digit MNC */
-        mcc = mccmnc / 1000;
-        mnc = mccmnc - (mcc * 1000);
-
-        if (mcc > 100) {
-            memset (tmp, 0, sizeof (tmp));
-            snprintf (tmp, sizeof (tmp), "%u", mccmnc / 1000);
-            wmc_result_add_string (r, WMC_CMD_NETWORK_INFO_ITEM_MCC, tmp);
-
-            memset (tmp, 0, sizeof (tmp));
-            snprintf (tmp, sizeof (tmp), "%03u", mnc);
-            wmc_result_add_string (r, WMC_CMD_NETWORK_INFO_ITEM_MNC, tmp);
-        }
-    } else {
-        /* old format */
-        wmc_result_add_u8 (r, WMC_CMD_NETWORK_INFO_ITEM_2G_DBM, sanitize_dbm (rsp->two_g_dbm, rsp->service));
-    }
-
-    if (rsp3) {
-        wmc_result_add_u8 (r, WMC_CMD_NETWORK_INFO_ITEM_LTE_DBM, sanitize_dbm (rsp3->lte_dbm, WMC_SERVICE_NONE));
-
-        memset (tmp, 0, sizeof (tmp));
-        if (is_lte_service (rsp->service) && sanitize_dbm (rsp3->lte_dbm, rsp->service)) {
-            /* LTE operator name */
-            wmc_assert (sizeof (rsp2->tgpp_opname) <= sizeof (tmp));
-            memcpy (tmp, rsp2->tgpp_opname, sizeof (rsp2->tgpp_opname));
-            wmc_result_add_string (r, WMC_CMD_NETWORK_INFO_ITEM_OPNAME, tmp);
-        }
-    }
-
-    return r;
-}
-
-/**********************************************************************/
-
-size_t
-wmc_cmd_get_global_mode_new (char *buf, size_t buflen)
-{
-    WmcCmdGetGlobalMode *cmd = (WmcCmdGetGlobalMode *) buf;
-
-    wmc_return_val_if_fail (buf != NULL, 0);
-    wmc_return_val_if_fail (buflen >= sizeof (*cmd), 0);
-
-    memset (cmd, 0, sizeof (*cmd));
-    cmd->hdr.marker = WMC_CMD_MARKER;
-    cmd->hdr.cmd = WMC_CMD_GET_GLOBAL_MODE;
-    return sizeof (*cmd);
-}
-
-WmcResult *
-wmc_cmd_get_global_mode_result (const char *buf, size_t buflen)
-{
-    WmcResult *r = NULL;
-    WmcCmdGetGlobalModeRsp *rsp = (WmcCmdGetGlobalModeRsp *) buf;
-
-    wmc_return_val_if_fail (buf != NULL, NULL);
-
-    if (check_command (buf, buflen, WMC_CMD_GET_GLOBAL_MODE, sizeof (WmcCmdGetGlobalModeRsp)) < 0)
-        return NULL;
-
-    r = wmc_result_new ();
-    wmc_result_add_u8 (r, WMC_CMD_GET_GLOBAL_MODE_ITEM_MODE, rsp->mode);
-    return r;
-}
-
-/**********************************************************************/
-
-static wmcbool
-validate_mode (uint8_t mode)
-{
-    switch (mode) {
-    case WMC_NETWORK_MODE_AUTO_CDMA:
-    case WMC_NETWORK_MODE_CDMA_ONLY:
-    case WMC_NETWORK_MODE_EVDO_ONLY:
-    case WMC_NETWORK_MODE_AUTO_GSM:
-    case WMC_NETWORK_MODE_GPRS_ONLY:
-    case WMC_NETWORK_MODE_UMTS_ONLY:
-    case WMC_NETWORK_MODE_AUTO:
-    case WMC_NETWORK_MODE_LTE_ONLY:
-        return TRUE;
-    default:
-        break;
-    }
-    return FALSE;
-}
-
-size_t
-wmc_cmd_set_global_mode_new (char *buf, size_t buflen, uint8_t mode)
-{
-    WmcCmdSetGlobalMode *cmd = (WmcCmdSetGlobalMode *) buf;
-
-    wmc_return_val_if_fail (buf != NULL, 0);
-    wmc_return_val_if_fail (buflen >= sizeof (*cmd), 0);
-    wmc_return_val_if_fail (validate_mode (mode) == TRUE, 0);
-
-    memset (cmd, 0, sizeof (*cmd));
-    cmd->hdr.marker = WMC_CMD_MARKER;
-    cmd->hdr.cmd = WMC_CMD_SET_GLOBAL_MODE;
-    cmd->_unknown1 = 0x01;
-    cmd->mode = mode;
-    cmd->_unknown2 = 0x05;
-    cmd->_unknown3 = 0x00;
-    return sizeof (*cmd);
-}
-
-WmcResult *
-wmc_cmd_set_global_mode_result (const char *buf, size_t buflen)
-{
-    wmc_return_val_if_fail (buf != NULL, NULL);
-
-    if (check_command (buf, buflen, WMC_CMD_SET_GLOBAL_MODE, sizeof (WmcCmdGetGlobalModeRsp)) < 0)
-        return NULL;
-
-    return wmc_result_new ();
-}
-
-/**********************************************************************/
diff --git a/libwmc/src/commands.h b/libwmc/src/commands.h
deleted file mode 100644
index 75c1afd..0000000
--- a/libwmc/src/commands.h
+++ /dev/null
@@ -1,116 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*
- * Copyright (C) 2011 Red Hat, Inc.
- *
- * This program is free software: you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef LIBWMC_COMMANDS_H
-#define LIBWMC_COMMANDS_H
-
-#include "result.h"
-
-/**********************************************************************/
-
-/* Generic enums */
-
-/**********************************************************************/
-
-size_t      wmc_cmd_init_new    (char *buf, size_t buflen, int wmc2);
-
-WmcResult * wmc_cmd_init_result (const char *buf, size_t len, int wmc2);
-
-/**********************************************************************/
-
-#define WMC_CMD_DEVICE_INFO_ITEM_MANUFACTURER "manufacturer"
-#define WMC_CMD_DEVICE_INFO_ITEM_MODEL        "model"
-#define WMC_CMD_DEVICE_INFO_ITEM_FW_REVISION  "firmware-revision"
-#define WMC_CMD_DEVICE_INFO_ITEM_HW_REVISION  "hardware-revision"
-#define WMC_CMD_DEVICE_INFO_ITEM_CDMA_MIN     "cdma-min"
-#define WMC_CMD_DEVICE_INFO_ITEM_HOME_SID     "home-sid"
-#define WMC_CMD_DEVICE_INFO_ITEM_PRL_VERSION  "prl-version"
-#define WMC_CMD_DEVICE_INFO_ITEM_ERI_VERSION  "eri-version"
-#define WMC_CMD_DEVICE_INFO_ITEM_MEID         "meid"
-#define WMC_CMD_DEVICE_INFO_ITEM_IMEI         "imei"
-#define WMC_CMD_DEVICE_INFO_ITEM_ICCID        "iccid"
-#define WMC_CMD_DEVICE_INFO_ITEM_MCC          "mcc"
-#define WMC_CMD_DEVICE_INFO_ITEM_MNC          "mnc"
-
-size_t      wmc_cmd_device_info_new    (char *buf, size_t buflen);
-
-WmcResult * wmc_cmd_device_info_result (const char *buf, size_t len);
-
-/**********************************************************************/
-
-enum {
-    WMC_NETWORK_SERVICE_NONE = 0,
-    WMC_NETWORK_SERVICE_AMPS = 1,
-    WMC_NETWORK_SERVICE_IS95A = 2,
-    WMC_NETWORK_SERVICE_IS95B = 3,
-    WMC_NETWORK_SERVICE_GSM = 4,
-    WMC_NETWORK_SERVICE_GPRS = 5,
-    WMC_NETWORK_SERVICE_1XRTT = 6,
-    WMC_NETWORK_SERVICE_EVDO_0 = 7,
-    WMC_NETWORK_SERVICE_UMTS = 8,
-    WMC_NETWORK_SERVICE_EVDO_A = 9,
-    WMC_NETWORK_SERVICE_EDGE = 10,
-    WMC_NETWORK_SERVICE_HSDPA = 11,
-    WMC_NETWORK_SERVICE_HSUPA = 12,
-    WMC_NETWORK_SERVICE_HSPA = 13,
-    WMC_NETWORK_SERVICE_LTE = 14,
-    WMC_NETWORK_SERVICE_EVDO_A_EHRPD = 15
-};
-
-/* One of WMC_NETWORK_SERVICE_* */
-#define WMC_CMD_NETWORK_INFO_ITEM_SERVICE       "service"
-
-#define WMC_CMD_NETWORK_INFO_ITEM_2G_DBM   "2g-dbm"
-#define WMC_CMD_NETWORK_INFO_ITEM_3G_DBM   "3g-dbm"
-#define WMC_CMD_NETWORK_INFO_ITEM_LTE_DBM  "lte-dbm"
-#define WMC_CMD_NETWORK_INFO_ITEM_OPNAME   "opname"
-#define WMC_CMD_NETWORK_INFO_ITEM_MCC      "mcc"
-#define WMC_CMD_NETWORK_INFO_ITEM_MNC      "mnc"
-
-size_t      wmc_cmd_network_info_new    (char *buf, size_t buflen);
-
-WmcResult * wmc_cmd_network_info_result (const char *buf, size_t len);
-
-/**********************************************************************/
-
-enum {
-    WMC_NETWORK_MODE_AUTO_CDMA = 0x00,
-    WMC_NETWORK_MODE_CDMA_ONLY = 0x01,
-    WMC_NETWORK_MODE_EVDO_ONLY = 0x02,
-    WMC_NETWORK_MODE_AUTO_GSM  = 0x0A,
-    WMC_NETWORK_MODE_GPRS_ONLY = 0x0B,
-    WMC_NETWORK_MODE_UMTS_ONLY = 0x0C,
-    WMC_NETWORK_MODE_AUTO      = 0x14,
-    WMC_NETWORK_MODE_LTE_ONLY  = 0x1E,
-};
-
-/* One of WMC_NETWORK_MODE_* */
-#define WMC_CMD_GET_GLOBAL_MODE_ITEM_MODE   "mode"
-
-size_t      wmc_cmd_get_global_mode_new    (char *buf, size_t buflen);
-
-WmcResult * wmc_cmd_get_global_mode_result (const char *buf, size_t len);
-
-/**********************************************************************/
-
-size_t      wmc_cmd_set_global_mode_new    (char *buf, size_t buflen, uint8_t mode);
-
-WmcResult * wmc_cmd_set_global_mode_result (const char *buf, size_t len);
-
-/**********************************************************************/
-
-#endif  /* LIBWMC_COMMANDS_H */
diff --git a/libwmc/src/errors.c b/libwmc/src/errors.c
deleted file mode 100644
index 0403b22..0000000
--- a/libwmc/src/errors.c
+++ /dev/null
@@ -1,58 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*
- * Copyright (C) 2011 Red Hat, Inc.
- *
- * This program is free software: you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "errors.h"
-#include <stdlib.h>
-#include <string.h>
-
-void
-_wmc_log (const char *file,
-          int line,
-          const char *func,
-          int level,
-          int domain,
-          const char *format,
-          ...)
-{
-    va_list args;
-    char *message = NULL;
-    int n;
-    const char *prefix = "info";
-
-    wmc_return_if_fail (format != NULL);
-    wmc_return_if_fail (format[0] != '\0');
-
-    /* level & domain ignored for now */
-
-    if (getenv ("WMC_DEBUG") == NULL)
-        return;
-
-    va_start (args, format);
-    n = vasprintf (&message, format, args);
-    va_end (args);
-
-    if (level & LOGL_ERR)
-        prefix = "err";
-    else if (level & LOGL_DEBUG)
-        prefix = "dbg";
-
-    if (n >= 0) {
-        fprintf (stderr, "<%s> [%s:%u] %s(): %s\n", prefix, file, line, func, message);
-        free (message);
-    }
-}
-
diff --git a/libwmc/src/errors.h b/libwmc/src/errors.h
deleted file mode 100644
index 18a9979..0000000
--- a/libwmc/src/errors.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*
- * Copyright (C) 2011 Red Hat, Inc.
- *
- * This program is free software: you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef LIBWMC_ERRORS_H
-#define LIBWMC_ERRORS_H
-
-#include <config.h>
-#include <sys/types.h>
-#include <assert.h>
-#include <stdio.h>
-#include <stdarg.h>
-
-enum {
-	LOGL_ERR   = 0x00000001,
-	LOGL_WARN  = 0x00000002,
-	LOGL_INFO  = 0x00000004,
-	LOGL_DEBUG = 0x00000008
-};
-
-enum {
-    WMC_SUCCESS = 0,
-    WMC_ERROR_INVALID_ARGUMENTS = 1,
-    WMC_ERROR_SERIAL_CONFIG_FAILED = 2,
-    WMC_ERROR_VALUE_NOT_FOUND = 3,
-    WMC_ERROR_RESPONSE_UNEXPECTED = 4,
-    WMC_ERROR_RESPONSE_BAD_LENGTH = 5,
-};
-
-#define wmc_assert assert
-
-#define wmc_return_if_fail(e) \
-{ \
-    if (!(e)) { \
-        wmc_warn (0, "failed: " #e "\n"); \
-        return; \
-    } \
-}
-
-#define wmc_return_val_if_fail(e, v) \
-{ \
-    if (!(e)) { \
-        wmc_warn (0, "failed: " #e "\n"); \
-        return v; \
-    } \
-}
-
-void _wmc_log (const char *file,
-               int line,
-               const char *func,
-               int domain,
-               int level,
-               const char *format,
-               ...) __attribute__((__format__ (__printf__, 6, 7)));
-
-#define wmc_dbg(domain, ...) \
-	_wmc_log (__FILE__, __LINE__, __func__, domain, LOGL_DEBUG, ## __VA_ARGS__ )
-
-#define wmc_warn(domain, ...) \
-	_wmc_log (__FILE__, __LINE__, __func__, domain, LOGL_WARN, ## __VA_ARGS__ )
-
-#define wmc_err(domain, ...) \
-	_wmc_log (__FILE__, __LINE__, __func__, domain, LOGL_ERR, ## __VA_ARGS__ )
-
-#endif  /* LIBWMC_ERRORS_H */
diff --git a/libwmc/src/protocol.h b/libwmc/src/protocol.h
deleted file mode 100644
index 483edbc..0000000
--- a/libwmc/src/protocol.h
+++ /dev/null
@@ -1,462 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*
- * Copyright (C) 2011 Red Hat, Inc.
- *
- * This program is free software: you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef LIBWMC_PROTOCOL_H
-#define LIBWMC_PROTOCOL_H
-
-#define WMC_CMD_MARKER ((uint8_t) 0xC8)
-
-enum {
-    WMC_CMD_GET_GLOBAL_MODE = 0x03,
-    WMC_CMD_SET_GLOBAL_MODE = 0x04,
-    WMC_CMD_DEVICE_INFO = 0x06,
-    WMC_CMD_CONNECTION_INFO = 0x0A,
-    WMC_CMD_NET_INFO = 0x0B,
-    WMC_CMD_INIT = 0x0D,
-    WMC_CMD_FIELD_TEST = 0x0F,
-    WMC_CMD_SET_OPERATOR = 0x33,
-    WMC_CMD_GET_FIRST_OPERATOR = 0x34,
-    WMC_CMD_GET_NEXT_OPERATOR = 0x35,
-    WMC_CMD_GET_APN = 0x4D,
-};
-
-/* MCC/MNC representation
- *
- * Various commands accept or return an MCC/MNC.  When sending, convert
- * the MCC/MNC into a number using eg. atoi() and store it as an LE 32-bit
- * value.  3-digit MNCs appear to be sent as 3-digit only if the firmware
- * reports them as 3-digit.  For example:
- *
- * T-Mobile US: 310-260
- * mcc_mnc = 0x00007932 = 31026  (note the 2-digit-only MNC)
- *
- * AT&T: 310-410
- * mcc_mnc = 0x0004bc8a = 310410
- */
-
-
-/* Generic WMC command header */
-struct WmcCmdHeader {
-    uint8_t marker;  /* Always 0xC8 */
-    uint8_t cmd;
-} __attribute__ ((packed));
-typedef struct WmcCmdHeader WmcCmdHeader;
-
-/* Used on newer devices like the UML190 and later */
-struct WmcCmdInit2 {
-    WmcCmdHeader hdr;
-    uint16_t year;
-    uint8_t  month;
-    uint16_t day;        /* big endian */
-    uint16_t hours;      /* big endian */
-    uint16_t minutes;    /* big endian */
-    uint16_t seconds;    /* big endian */
-    uint8_t _unknown1[3];
-} __attribute__ ((packed));
-typedef struct WmcCmdInit2 WmcCmdInit2;
-
-struct WmcCmdInit2Rsp {
-    WmcCmdHeader hdr;
-    uint8_t _unknown1[4];
-} __attribute__ ((packed));
-typedef struct WmcCmdInit2Rsp WmcCmdInit2Rsp;
-
-struct WmcCmdDeviceInfoRsp {
-    WmcCmdHeader hdr;
-    uint8_t  _unknown1[27];
-    char      manf[64];
-    char      model[64];
-    char      fwrev[64];
-    char      hwrev[64];
-    uint8_t  _unknown2[64];
-    uint8_t  _unknown3[64];
-    char      min[10];        /* CDMA2000/IS-95 MIN */
-    uint8_t  _unknown4[12];
-    uint16_t home_sid;
-    uint8_t  _unknown5[2];
-    uint16_t prlver;
-    uint8_t  _unknown6[2];
-    uint16_t eriver;
-    uint8_t _unknown7[4];
-} __attribute__ ((packed));
-typedef struct WmcCmdDeviceInfoRsp WmcCmdDeviceInfoRsp;
-
-struct WmcCmdDeviceInfo2Rsp {
-    WmcCmdHeader hdr;
-    uint8_t _unknown1[27];
-    char     manf[64];
-    char     model[64];
-    char     fwrev[64];
-    char     hwrev[64];
-    uint8_t _unknown2[64];
-    uint8_t _unknown3[64];
-    uint8_t min[10];        /* CDMA2000/IS-95 MIN */
-    uint8_t _unknown4[12];
-    uint16_t home_sid;
-    uint8_t _unknown5[2];
-    uint16_t prlver;
-    uint8_t _unknown6[2];
-    uint16_t eriver;
-    uint8_t _unknown7[4];
-    uint8_t _unknown8[64];
-    uint8_t meid[14];
-    uint8_t _unknown10[6];  /* always zero */
-    uint8_t imei[16];
-    uint8_t _unknown11[6];  /* always zero */
-    uint8_t _unknown12[16];
-    uint8_t iccid[20];
-    uint8_t _unknown13[6];
-} __attribute__ ((packed));
-typedef struct WmcCmdDeviceInfo2Rsp WmcCmdDeviceInfo2Rsp;
-
-struct WmcCmdDeviceInfo3Rsp {
-    WmcCmdHeader hdr;
-    uint8_t _unknown1[27];
-    char     manf[64];
-    char     model[64];
-    char     fwrev[64];
-    char     hwrev[64];
-    uint8_t _unknown2[64];
-    uint8_t _unknown3[64];
-    uint8_t min[10];        /* CDMA2000/IS-95 MIN */
-    uint8_t _unknown4[12];
-    uint16_t home_sid;
-    uint8_t _unknown5[2];
-    uint16_t prlver;
-    uint8_t _unknown6[2];
-    uint16_t eri_ver;
-    uint8_t _unknown7[4];
-    uint8_t _unknown8[64];
-    uint8_t meid[14];
-    uint8_t _unknown10[6];  /* always zero */
-    uint8_t imei[16];
-    uint8_t _unknown11[6];  /* always zero */
-    uint8_t _unknown12[16];
-    uint8_t iccid[20];
-    uint8_t _unknown13[6];
-    uint8_t mcc[16];
-    uint8_t mnc[16];
-    uint8_t _unknown14[4];
-    uint8_t _unknown15[4];
-    uint8_t _unknown16[4];
-} __attribute__ ((packed));
-typedef struct WmcCmdDeviceInfo3Rsp WmcCmdDeviceInfo3Rsp;
-
-/*****************************************************/
-
-enum {
-    WMC_SERVICE_NONE = 0,
-    WMC_SERVICE_AMPS = 1,
-    WMC_SERVICE_IS95A = 2,
-    WMC_SERVICE_IS95B = 3,
-    WMC_SERVICE_GSM = 4,
-    WMC_SERVICE_GPRS = 5,
-    WMC_SERVICE_1XRTT = 6,
-    WMC_SERVICE_EVDO_0 = 7,
-    WMC_SERVICE_UMTS = 8,
-    WMC_SERVICE_EVDO_A = 9,
-    WMC_SERVICE_EDGE = 10,
-    WMC_SERVICE_HSDPA = 11,
-    WMC_SERVICE_HSUPA = 12,
-    WMC_SERVICE_HSPA = 13,
-    WMC_SERVICE_LTE = 14,
-    WMC_SERVICE_EVDO_A_EHRPD = 15,
-};
-
-/* PC5740 response */
-struct WmcCmdNetworkInfoRsp {
-    WmcCmdHeader hdr;
-    uint8_t  _unknown1;
-    uint8_t  _unknown2[3];    /* Always zero */
-    uint8_t  service;         /* One of WMC_SERVICE_* */
-    uint8_t  _unknown3;       /* Either 0x00 or 0x01 */
-    uint16_t ts_year;
-    uint8_t  ts_month;
-    uint16_t ts_day;          /* BE */
-    uint16_t ts_hours;        /* BE */
-    uint16_t ts_minutes;      /* BE */
-    uint16_t ts_seconds;      /* BE */
-    uint16_t counter1;        /* A timestamp/counter? */
-    uint16_t _unknown4;
-    uint8_t  _unknown5[3];    /* Always 0xFE 0xFF 0xFF */
-    uint8_t  two_g_dbm;       /* 0x7D = no signal */
-    uint8_t  _unknown6[37];   /* Always zero */
-} __attribute__ ((packed));
-typedef struct WmcCmdNetworkInfoRsp WmcCmdNetworkInfoRsp;
-
-/* UML190 response */
-struct WmcCmdNetworkInfo2Rsp {
-    WmcCmdHeader hdr;
-    uint8_t  _unknown1;       /* 0x00 on LTE, 0x07 or 0x1F on CDMA */
-    uint8_t  _unknown2[3];    /* Always zero */
-    uint8_t  service;         /* One of WMC_SERVICE_* */
-    uint8_t  _unknown3;
-    uint16_t ts_year;
-    uint8_t  ts_month;
-    uint16_t ts_day;          /* BE */
-    uint16_t ts_hours;        /* BE */
-    uint16_t ts_minutes;      /* BE */
-    uint16_t ts_seconds;      /* BE */
-    uint8_t  _unknown4;       /* always zero */
-    uint16_t uptime_secs;
-    uint8_t  _unknown5;
-    uint8_t  _unknown6[3];    /* always zero on LTE, 0xFE 0xFF 0xFF on CDMA */
-    uint8_t  two_g_dbm;       /* 0x7D = no CDMA signal, 0x6a = no GSM signal */
-    uint8_t  _unknown7[3];    /* Always zero */
-    uint8_t  cdma_opname[16]; /* Zero terminated? */
-    uint8_t  _unknown8[18];   /* Always zero */
-    uint8_t  three_g_dbm;     /* 0x7D = no signal */
-    uint8_t  _unknown9[3];    /* Always zero */
-    uint8_t  _unknown10;      /* 0x01 on LTE, 0x40 on CDMA */
-    uint8_t  _unknown11[3];   /* Always zero */
-    uint8_t  _unknown12;      /* Always 0x01 */
-    uint8_t  tgpp_opname[8];  /* 3GPP operator name (Zero terminated? Sometimes "MCC MNC" too */
-    uint8_t  _unknown13[4];   /* Always zero */
-    uint32_t _unknown14;      /* 43 75 3a 00 on GSM/WCDMA mode, zero on others  */
-    uint32_t _unknown15;      /* 49 7d 3a 00 on GSM/WCDMA mode, zero on others  */
-    uint8_t  _unknown16[44];  /* Always zero */
-    uint32_t mcc_mnc;         /* GSM/WCDMA only, see MCC/MNC format note */
-} __attribute__ ((packed));
-typedef struct WmcCmdNetworkInfo2Rsp WmcCmdNetworkInfo2Rsp;
-
-/* UML290 response */
-struct WmcCmdNetworkInfo3Rsp {
-    WmcCmdHeader hdr;
-    uint8_t  _unknown1;       /* 0x00 on LTE, 0x07 or 0x1F on CDMA */
-    uint8_t  _unknown2[3];    /* Always zero */
-    uint8_t  service;         /* One of WMC_SERVICE_* */
-    uint8_t  _unknown3;
-    uint16_t ts_year;
-    uint8_t  ts_month;
-    uint16_t ts_day;          /* BE */
-    uint16_t ts_hours;        /* BE */
-    uint16_t ts_minutes;      /* BE */
-    uint16_t ts_seconds;      /* BE */
-    uint8_t  _unknown4;       /* always zero */
-    uint16_t uptime_secs;
-    uint8_t  _unknown5;
-    uint8_t  _unknown6[3];    /* always zero on LTE, 0xFE 0xFF 0xFF on CDMA */
-    uint8_t  two_g_dbm;       /* 0x7D = no CDMA signal, 0x6a = no GSM signal */
-    uint8_t  _unknown7[3];    /* Always zero */
-    uint8_t  cdma_opname[16]; /* Zero terminated? */
-    uint8_t  _unknown8[18];   /* Always zero */
-    uint8_t  three_g_dbm;     /* 0x7D = no signal */
-    uint8_t  _unknown9[3];    /* Always zero */
-    uint8_t  _unknown10;      /* 0x01 on LTE, 0x40 on CDMA */
-    uint8_t  _unknown11[3];   /* Always zero */
-    uint8_t  _unknown12;      /* Always 0x01 */
-    uint8_t  tgpp_opname[8];   /* Zero terminated? Sometimes "MCC MNC" too */
-    uint8_t  _unknown13[4];   /* Always zero */
-    uint32_t _unknown14;      /* 43 75 3a 00 on GSM/WCDMA mode, zero on others  */
-    uint32_t _unknown15;      /* 49 7d 3a 00 on GSM/WCDMA mode, zero on others  */
-    uint8_t  _unknown16[44];  /* Always zero */
-    uint32_t mcc_mnc;         /* GSM/WCDMA only, see MCC/MNC format note */
-    uint8_t  lte_dbm;         /* 0x00 if not in LTE mode */
-    uint8_t  _unknown17[3];   /* Always zero */
-    uint8_t  _unknown18[4];
-} __attribute__ ((packed));
-typedef struct WmcCmdNetworkInfo3Rsp WmcCmdNetworkInfo3Rsp;
-
-/*****************************************************/
-
-enum {
-    WMC_CONNECTION_STATE_UNKNOWN = 0,
-    WMC_CONNECTION_STATE_IDLE = 1,
-    WMC_CONNECTION_STATE_CONNECTING = 2,
-    WMC_CONNECTION_STATE_AUTHENTICATING = 3,
-    WMC_CONNECTION_STATE_CONNECTED = 4,
-    WMC_CONNECTION_STATE_DORMANT = 5,
-    WMC_CONNECTION_STATE_UPDATING_NAM = 6,
-    WMC_CONNECTION_STATE_UPDATING_PRL = 7,
-    WMC_CONNECTION_STATE_DISCONNECTING = 8,
-    WMC_CONNECTION_STATE_ERROR = 9,
-    WMC_CONNECTION_STATE_UPDATING_UICC = 10,
-    WMC_CONNECTION_STATE_UPDATING_PLMN = 11
-};
-
-/* Used on UML190 */
-struct WmcCmdConnectionInfoRsp {
-    WmcCmdHeader hdr;
-    uint32_t rx_bytes;
-    uint32_t tx_bytes;
-    uint8_t  _unknown1[8];
-    uint8_t  state;           /* One of WMC_CONNECTION_STATE_* */
-    uint8_t  _unknown2[3];    /* Always 0xc0 0x0b 0x00 */
-} __attribute__ ((packed));
-typedef struct WmcCmdConnectionInfoRsp WmcCmdConnectionInfoRsp;
-
-/* Used on UML290 */
-struct WmcCmdConnectionInfo2Rsp {
-    WmcCmdHeader hdr;
-    uint32_t rx_bytes;
-    uint32_t tx_bytes;
-    uint8_t  _unknown1[8];
-    uint8_t  state;           /* One of WMC_CONNECTION_STATE_* */
-    uint8_t  _unknown2[3];    /* Always 0xc0 0x0b 0x00 */
-    uint8_t  _unknown3[4];    /* Always 0x01 0x00 0x00 0x00 */
-    uint8_t  ip4_address[16]; /* String format, ie "10.156.45.3" */
-    uint8_t  _unknown4[8];    /* Netmask? */
-    uint8_t  ip6_address[40]; /* String format */
-} __attribute__ ((packed));
-typedef struct WmcCmdConnection2InfoRsp WmcCmdConnection2InfoRsp;
-
-/*****************************************************/
-
-enum {
-    WMC_GLOBAL_MODE_AUTO_CDMA = 0x00,
-    WMC_GLOBAL_MODE_CDMA_ONLY = 0x01,
-    WMC_GLOBAL_MODE_EVDO_ONLY = 0x02,
-    WMC_GLOBAL_MODE_AUTO_GSM  = 0x0A,
-    WMC_GLOBAL_MODE_GPRS_ONLY = 0x0B,
-    WMC_GLOBAL_MODE_UMTS_ONLY = 0x0C,
-    WMC_GLOBAL_MODE_AUTO      = 0x14,
-    WMC_GLOBAL_MODE_LTE_ONLY  = 0x1E,
-};
-
-struct WmcCmdGetGlobalMode {
-    WmcCmdHeader hdr;
-    uint8_t _unknown1;  /* always 0 */
-} __attribute__ ((packed));
-typedef struct WmcCmdGetGlobalMode WmcCmdGetGlobalMode;
-
-struct WmcCmdGetGlobalModeRsp {
-    WmcCmdHeader hdr;
-    uint8_t _unknown1;  /* always 0x01 */
-    uint8_t mode;       /* one of WMC_GLOBAL_MODE_* */
-    uint8_t _unknown2;  /* always 0x05 */
-    uint8_t _unknown3;  /* always 0x00 */
-} __attribute__ ((packed));
-typedef struct WmcCmdGetGlobalModeRsp WmcCmdGetGlobalModeRsp;
-
-/*****************************************************/
-
-struct WmcCmdSetGlobalMode {
-    WmcCmdHeader hdr;
-    uint8_t _unknown1;  /* always 0x01 */
-    uint8_t mode;       /* one of WMC_GLOBAL_MODE_* */
-    uint8_t _unknown2;  /* always 0x05 */
-    uint8_t _unknown3;  /* always 0x00 */
-} __attribute__ ((packed));
-typedef struct WmcCmdSetGlobalMode WmcCmdSetGlobalMode;
-
-struct WmcCmdSetGlobalModeRsp {
-    WmcCmdHeader hdr;
-    uint8_t _unknown1;   /* always 0x01 */
-    uint32_t _unknown2;  /* always zero */
-} __attribute__ ((packed));
-typedef struct WmcCmdSetGlobalModeRsp WmcCmdSetGlobalModeRsp;
-
-/*****************************************************/
-
-struct WmcCmdSetOperator {
-    WmcCmdHeader hdr;
-    uint8_t automatic;      /* 0x00 = manual, 0x01 = auto */
-    uint8_t _unknown1;      /* always 0x50 */
-    uint8_t _unknown2[3];   /* always zero */
-    uint32_t mcc_mnc;       /* MCC/MNC for manual reg (see format note), zero for auto */
-    uint8_t _unknown3[56];  /* always zero */
-} __attribute__ ((packed));
-typedef struct WmcCmdSetOperator WmcCmdSetOperator;
-
-enum {
-    WMC_SET_OPERATOR_STATUS_OK = 0,
-    WMC_SET_OPERATOR_STATUS_REGISTERING = 0x63,
-    WMC_SET_OPERATOR_STATUS_FAILED = 0x68,
-};
-
-struct WmcCmdSetOperatorRsp {
-    WmcCmdHeader hdr;
-    uint8_t status;        /* one of WMC_SET_OPERATOR_STATUS_* */
-    uint8_t _unknown1[3];  /* always zero */
-} __attribute__ ((packed));
-typedef struct WmcCmdSetOperatorRsp WmcCmdSetOperatorRsp;
-
-/*****************************************************/
-
-enum {
-    WMC_OPERATOR_SERVICE_UNKNOWN = 0,
-    WMC_OPERATOR_SERVICE_GSM = 1,
-    WMC_OPERATOR_SERVICE_UMTS = 2,
-};
-
-/* Response for both GET_FIRST_OPERATOR and GET_NEXT_OPERATOR */
-struct WmcCmdGetOperatorRsp {
-    WmcCmdHeader hdr;
-    uint8_t  _unknown1;     /* Usually 0x50, sometimes 0x00 */
-    uint8_t  _unknown2[3];  /* always zero */
-    uint32_t mcc_mnc;       /* see format note */
-    uint8_t  opname[8];
-    uint8_t  _unknown3[56]; /* always zero */
-    uint8_t  stat;          /* follows 3GPP TS27.007 +COPS <stat> ? */
-    uint8_t  _unknown4[3];  /* always zero */
-    uint8_t  service;       /* one of WMC_OPERATOR_SERVICE_* */
-    uint8_t  _unknown5[3];  /* always zero */
-    uint8_t  _unknown6;     /* 0x63 (GET_FIRST_OP) might mean "wait" */
-    uint8_t  _unknown7;     /* 0x00 or 0x01 */
-    uint8_t  _unknown8[2];  /* always zero */
-} __attribute__ ((packed));
-typedef struct WmcCmdGetOperatorRsp WmcCmdGetOperatorRsp;
-
-/*****************************************************/
-
-enum {
-    WMC_FIELD_TEST_MOBILE_IP_MODE_MIP_OFF = 0,
-    WMC_FIELD_TEST_MOBILE_IP_MODE_MIP_PREF = 1,
-    WMC_FIELD_TEST_MOBILE_IP_MODE_MIP_ONLY = 2
-};
-
-/* Later devices return all zeros for this command */
-struct WmcCmdFieldTestRsp {
-    WmcCmdHeader hdr;
-    uint8_t  prl_requirements;
-    uint8_t  eri_support;
-    char      nam_name[7];
-    uint8_t  _unknown1;         /* always zero */
-    uint8_t  _unknown2[3];      /* always 0x0A 0x0A 0x0A */
-    uint8_t  _unknown3[5];      /* always zero */
-    uint8_t  _unknown4[10];     /* all 0x0F */
-    uint16_t home_sid;
-    uint16_t home_nid;
-    char      min1[7];
-    char      min2[3];
-    char      mcc[3];
-    char      imsi_s[10];
-    char      mnc[2];
-    uint16_t primary_cdma_chan_a;
-    uint16_t secondary_cdma_chan_a;
-    uint16_t primary_cdma_chan_b;
-    uint16_t secondary_cdma_chan_b;
-    uint8_t  accolc;
-    char      sw_version[64];
-    char      hw_version[64];
-    uint16_t prlver;
-    uint16_t eriver;
-    uint16_t nid;
-    uint8_t  last_call_end_reason;  /* ? */
-    uint8_t  rssi;
-    uint16_t channel;
-    uint8_t  prev;
-    uint16_t pn_offset;
-    uint8_t  sys_select_pref;
-    uint8_t  mip_pref;
-    uint8_t  hybrid_pref;
-} __attribute__ ((packed));
-typedef struct WmcCmdFieldTestRsp WmcCmdFieldTestRsp;
-
-/*****************************************************/
-
-#endif  /* LIBWMC_PROTOCOL_H */
diff --git a/libwmc/src/result-private.h b/libwmc/src/result-private.h
deleted file mode 100644
index 1e824e2..0000000
--- a/libwmc/src/result-private.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*
- * Copyright (C) 2011 Red Hat, Inc.
- *
- * This program is free software: you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef LIBWMC_RESULT_PRIVATE_H
-#define LIBWMC_RESULT_PRIVATE_H
-
-#include "result.h"
-
-WmcResult *wmc_result_new (void);
-
-void wmc_result_add_string (WmcResult *result,
-                            const char *key,
-                            const char *str);
-
-void wmc_result_add_u8     (WmcResult *result,
-                            const char *key,
-                            uint8_t num);
-
-void wmc_result_add_u32    (WmcResult *result,
-                            const char *key,
-                            uint32_t num);
-
-#endif  /* LIBWMC_RESULT_PRIVATE_H */
diff --git a/libwmc/src/result.c b/libwmc/src/result.c
deleted file mode 100644
index 950cb02..0000000
--- a/libwmc/src/result.c
+++ /dev/null
@@ -1,297 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*
- * Copyright (C) 2010 Red Hat, Inc.
- *
- * This program is free software: you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <string.h>
-#include <stdlib.h>
-
-#include "result.h"
-#include "result-private.h"
-#include "errors.h"
-
-/*********************************************************/
-
-typedef struct Val Val;
-
-typedef enum {
-    VAL_TYPE_NONE = 0,
-    VAL_TYPE_STRING = 1,
-    VAL_TYPE_U8 = 2,
-    VAL_TYPE_U32 = 3
-} ValType;
-
-struct Val {
-    char *key;
-    ValType type;
-    union {
-        char *s;
-        uint8_t u8;
-        uint32_t u32;
-    } u;
-    Val *next;
-};
-
-static void
-val_free (Val *v)
-{
-    if (v->type == VAL_TYPE_STRING) {
-        if (v->u.s)
-            free (v->u.s);
-    }
-    free (v->key);
-    memset (v, 0, sizeof (*v));
-    free (v);
-}
-
-static Val *
-val_new_string (const char *key, const char *value)
-{
-    Val *v;
-
-    wmc_return_val_if_fail (key != NULL, NULL);
-    wmc_return_val_if_fail (key[0] != '\0', NULL);
-    wmc_return_val_if_fail (value != NULL, NULL);
-
-    v = calloc (sizeof (Val), 1);
-    if (v == NULL)
-        return NULL;
-
-    v->key = strdup (key);
-    v->type = VAL_TYPE_STRING;
-    v->u.s = strdup (value);
-    return v;
-}
-
-static Val *
-val_new_u8 (const char *key, uint8_t u)
-{
-    Val *v;
-
-    wmc_return_val_if_fail (key != NULL, NULL);
-    wmc_return_val_if_fail (key[0] != '\0', NULL);
-
-    v = calloc (sizeof (Val), 1);
-    if (v == NULL)
-        return NULL;
-
-    v->key = strdup (key);
-    v->type = VAL_TYPE_U8;
-    v->u.u8 = u;
-    return v;
-}
-
-static Val *
-val_new_u32 (const char *key, uint32_t u)
-{
-    Val *v;
-
-    wmc_return_val_if_fail (key != NULL, NULL);
-    wmc_return_val_if_fail (key[0] != '\0', NULL);
-
-    v = calloc (sizeof (Val), 1);
-    if (v == NULL)
-        return NULL;
-
-    v->key = strdup (key);
-    v->type = VAL_TYPE_U32;
-    v->u.u32 = u;
-    return v;
-}
-
-/*********************************************************/
-
-struct WmcResult {
-    uint32_t refcount;
-    Val *first;
-};
-
-WmcResult *
-wmc_result_new (void)
-{
-    WmcResult *r;
-
-    r = calloc (sizeof (WmcResult), 1);
-    if (r)
-        r->refcount = 1;
-    return r;
-}
-
-WmcResult *
-wmc_result_ref (WmcResult *r)
-{
-    wmc_return_val_if_fail (r != NULL, NULL);
-    wmc_return_val_if_fail (r->refcount > 0, NULL);
-
-    r->refcount++;
-    return r;
-}
-
-static void
-wmc_result_free (WmcResult *r)
-{
-    Val *v, *n;
-
-    v = r->first;
-    while (v) {
-        n = v->next;
-        val_free (v);
-        v = n;
-    }
-    memset (r, 0, sizeof (*r));
-    free (r);
-}
-
-void
-wmc_result_unref (WmcResult *r)
-{
-    wmc_return_if_fail (r != NULL);
-    wmc_return_if_fail (r->refcount > 0);
-
-    r->refcount--;
-    if (r->refcount == 0)
-        wmc_result_free (r);
-}
-
-static Val *
-find_val (WmcResult *r, const char *key, ValType expected_type)
-{
-    Val *v, *n;
-
-    v = r->first;
-    while (v) {
-        n = v->next;
-        if (strcmp (v->key, key) == 0) {
-            /* Check type */
-            wmc_return_val_if_fail (v->type == expected_type, NULL);
-            return v;
-        }
-        v = n;
-    }
-    return NULL;
-}
-
-void
-wmc_result_add_string (WmcResult *r,
-                       const char *key,
-                       const char *str)
-{
-    Val *v;
-
-    wmc_return_if_fail (r != NULL);
-    wmc_return_if_fail (r->refcount > 0);
-    wmc_return_if_fail (key != NULL);
-    wmc_return_if_fail (str != NULL);
-
-    v = val_new_string (key, str);
-    wmc_return_if_fail (v != NULL);
-    v->next = r->first;
-    r->first = v;
-}
-
-int
-wmc_result_get_string (WmcResult *r,
-                       const char *key,
-                       const char **out_val)
-{
-    Val *v;
-
-    wmc_return_val_if_fail (r != NULL, -WMC_ERROR_INVALID_ARGUMENTS);
-    wmc_return_val_if_fail (r->refcount > 0, -WMC_ERROR_INVALID_ARGUMENTS);
-    wmc_return_val_if_fail (key != NULL, -WMC_ERROR_INVALID_ARGUMENTS);
-    wmc_return_val_if_fail (out_val != NULL, -WMC_ERROR_INVALID_ARGUMENTS);
-    wmc_return_val_if_fail (*out_val == NULL, -WMC_ERROR_INVALID_ARGUMENTS);
-
-    v = find_val (r, key, VAL_TYPE_STRING);
-    if (v == NULL)
-        return -WMC_ERROR_VALUE_NOT_FOUND;
-
-    *out_val = v->u.s;
-    return 0;
-}
-
-void
-wmc_result_add_u8 (WmcResult *r,
-                   const char *key,
-                   uint8_t num)
-{
-    Val *v;
-
-    wmc_return_if_fail (r != NULL);
-    wmc_return_if_fail (r->refcount > 0);
-    wmc_return_if_fail (key != NULL);
-
-    v = val_new_u8 (key, num);
-    wmc_return_if_fail (v != NULL);
-    v->next = r->first;
-    r->first = v;
-}
-
-int
-wmc_result_get_u8  (WmcResult *r,
-                    const char *key,
-                    uint8_t *out_val)
-{
-    Val *v;
-
-    wmc_return_val_if_fail (r != NULL, -WMC_ERROR_INVALID_ARGUMENTS);
-    wmc_return_val_if_fail (r->refcount > 0, -WMC_ERROR_INVALID_ARGUMENTS);
-    wmc_return_val_if_fail (key != NULL, -WMC_ERROR_INVALID_ARGUMENTS);
-    wmc_return_val_if_fail (out_val != NULL, -WMC_ERROR_INVALID_ARGUMENTS);
-
-    v = find_val (r, key, VAL_TYPE_U8);
-    if (v == NULL)
-        return -WMC_ERROR_VALUE_NOT_FOUND;
-
-    *out_val = v->u.u8;
-    return 0;
-}
-
-void
-wmc_result_add_u32 (WmcResult *r,
-                    const char *key,
-                    uint32_t num)
-{
-    Val *v;
-
-    wmc_return_if_fail (r != NULL);
-    wmc_return_if_fail (r->refcount > 0);
-    wmc_return_if_fail (key != NULL);
-
-    v = val_new_u32 (key, num);
-    wmc_return_if_fail (v != NULL);
-    v->next = r->first;
-    r->first = v;
-}
-
-int
-wmc_result_get_u32 (WmcResult *r,
-                    const char *key,
-                    uint32_t *out_val)
-{
-    Val *v;
-
-    wmc_return_val_if_fail (r != NULL, -WMC_ERROR_INVALID_ARGUMENTS);
-    wmc_return_val_if_fail (r->refcount > 0, -WMC_ERROR_INVALID_ARGUMENTS);
-    wmc_return_val_if_fail (key != NULL, -WMC_ERROR_INVALID_ARGUMENTS);
-    wmc_return_val_if_fail (out_val != NULL, -WMC_ERROR_INVALID_ARGUMENTS);
-
-    v = find_val (r, key, VAL_TYPE_U32);
-    if (v == NULL)
-        return -WMC_ERROR_VALUE_NOT_FOUND;
-
-    *out_val = v->u.u32;
-    return 0;
-}
diff --git a/libwmc/src/result.h b/libwmc/src/result.h
deleted file mode 100644
index 1c73711..0000000
--- a/libwmc/src/result.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*
- * Copyright (C) 2010 Red Hat, Inc.
- *
- * This program is free software: you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef LIBWMC_RESULT_H
-#define LIBWMC_RESULT_H
-
-#include <stdint.h>
-
-typedef struct WmcResult WmcResult;
-
-int wmc_result_get_string (WmcResult *r,
-                           const char *key,
-                           const char **out_val);
-
-int wmc_result_get_u8     (WmcResult *r,
-                           const char *key,
-                           uint8_t *out_val);
-
-int wmc_result_get_u32    (WmcResult *r,
-                           const char *key,
-                           uint32_t *out_val);
-
-WmcResult *wmc_result_ref     (WmcResult *r);
-
-void       wmc_result_unref   (WmcResult *r);
-
-#endif  /* LIBWMC_RESULT_H */
diff --git a/libwmc/src/utils.c b/libwmc/src/utils.c
deleted file mode 100644
index 5539eda..0000000
--- a/libwmc/src/utils.c
+++ /dev/null
@@ -1,459 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*
- * Copyright (C) 2010 Red Hat, Inc.
- *
- * This program is free software: you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <stdio.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <malloc.h>
-#include <fcntl.h>
-#include <string.h>
-
-#include "utils.h"
-#include "errors.h"
-
-/* QCDM protocol frames are pseudo Async HDLC frames which end with a 3-byte
- * trailer.  This trailer consists of the 16-bit CRC of the frame plus an ending
- * "async control character" whose value is 0x7E.  The frame *and* the CRC are
- * escaped before adding the trailing control character so that the control
- * character (0x7E) and the escape marker (0x7D) are never seen in the frame.
- */
-
-/* Table of CRCs for each possible byte, with a generator polynomial of 0x8408 */
-static const uint16_t crc_table[256] = {
-    0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
-    0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
-    0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
-    0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
-    0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
-    0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
-    0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
-    0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
-    0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
-    0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
-    0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
-    0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
-    0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
-    0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
-    0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
-    0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
-    0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
-    0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
-    0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
-    0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
-    0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
-    0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
-    0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
-    0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
-    0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
-    0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
-    0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
-    0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
-    0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
-    0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
-    0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
-    0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
-};
-
-/* Calculate the CRC for a buffer using a seed of 0xffff */
-uint16_t
-wmc_crc16 (const char *buffer, size_t len, uint16_t seed)
-{
-    uint16_t crc = seed ? seed : 0xFFFF;
-
-    while (len--)
-            crc = crc_table[(crc ^ *buffer++) & 0xff] ^ (crc >> 8);
-    return ~crc;
-}
-
-#define DIAG_ESC_CHAR     0x7D  /* Escape sequence 1st character value */
-#define DIAG_ESC_MASK     0x20  /* Escape sequence complement value */
-
-/* Performs DM escaping on inbuf putting the result into outbuf, and returns
- * the final length of the buffer.
- */
-size_t
-hdlc_escape (const char *inbuf,
-             size_t inbuf_len,
-             wmcbool escape_all_ctrl,
-             char *outbuf,
-             size_t outbuf_len)
-{
-    const char *src = inbuf;
-    char *dst = outbuf;
-    size_t i = inbuf_len;
-
-    wmc_return_val_if_fail (inbuf != NULL, 0);
-    wmc_return_val_if_fail (inbuf_len > 0, 0);
-    wmc_return_val_if_fail (outbuf != NULL, 0);
-    wmc_return_val_if_fail (outbuf_len > inbuf_len, 0);
-
-    /* Since escaping potentially doubles the # of bytes, short-circuit the
-     * length check if destination buffer is clearly large enough.  Note the
-     *
-     */
-    if (outbuf_len <= inbuf_len << 1) {
-        size_t outbuf_required = inbuf_len + 1; /* +1 for the trailing control char */
-
-        /* Each escaped character takes up two bytes in the output buffer */
-        while (i--) {
-            if (   *src == DIAG_CONTROL_CHAR
-                || *src == DIAG_ESC_CHAR
-                || (escape_all_ctrl && *src <= 0x20))
-                outbuf_required++;
-            src++;
-        }
-
-        if (outbuf_len < outbuf_required)
-            return 0;
-    }
-
-    /* Do the actual escaping.  Replace both the control character and
-     * the escape character in the source buffer with the following sequence:
-     *
-     * <escape_char> <src_byte ^ escape_mask>
-     */
-    src = inbuf;
-    i = inbuf_len;
-    while (i--) {
-        uint8_t byte = (uint8_t) *src++;
-
-        if (   byte == DIAG_CONTROL_CHAR
-            || byte == DIAG_ESC_CHAR
-            || (escape_all_ctrl && byte <= 0x20)) {
-            *dst++ = DIAG_ESC_CHAR;
-            *dst++ = byte ^ DIAG_ESC_MASK;
-        } else
-            *dst++ = byte;
-    }
-
-    return (dst - outbuf);
-}
-
-size_t
-hdlc_unescape (const char *inbuf,
-               size_t inbuf_len,
-               char *outbuf,
-               size_t outbuf_len,
-               wmcbool *escaping)
-{
-    size_t i, outsize;
-
-    wmc_return_val_if_fail (inbuf_len > 0, 0);
-    wmc_return_val_if_fail (outbuf_len >= inbuf_len, 0);
-    wmc_return_val_if_fail (escaping != NULL, 0);
-
-    for (i = 0, outsize = 0; i < inbuf_len; i++) {
-        if (*escaping) {
-            outbuf[outsize++] = inbuf[i] ^ DIAG_ESC_MASK;
-            *escaping = FALSE;
-        } else if (inbuf[i] == DIAG_ESC_CHAR)
-            *escaping = TRUE;
-        else
-            outbuf[outsize++] = inbuf[i];
-
-        /* About to overrun output buffer size */
-        if (outsize >= outbuf_len)
-            return 0;
-    }
-
-    return outsize;
-}
-
-/**
- * hdlc_encapsulate_buffer:
- * @inbuf: data buffer to encapsulate
- * @cmd_len: size of the data contained in @inbuf
- * @inbuf_len: total size of @inbuf itself (not just the data)
- * @crc_seed: if non-zero, CRC-16 seed to use; if 0, uses standard 0xFFFF
- * @add_trailer: if %TRUE, adds trailing 0x7E
- * @escape_all_ctrl: if %TRUE, escapes all control characters instead of only
- * special HDLC escape characters 0x7D and 0x7E
- * @outbuf: buffer in which to put the encapsulated data
- * @outbuf_len: total size of @outbuf
- *
- * Escapes and CRCs given data using HDLC-style mechanisms, and optionally adds
- * the trailing control character that denotes the end of the HDLC frame.
- *
- * Returns: size of the encapsulated data writted to @outbuf.
- **/
-size_t
-hdlc_encapsulate_buffer (char *inbuf,
-                         size_t cmd_len,
-                         size_t inbuf_len,
-                         uint16_t crc_seed,
-                         wmcbool add_trailer,
-                         wmcbool escape_all_ctrl,
-                         char *outbuf,
-                         size_t outbuf_len)
-{
-    uint16_t crc;
-    size_t escaped_len;
-
-    wmc_return_val_if_fail (inbuf != NULL, 0);
-    wmc_return_val_if_fail (cmd_len >= 1, 0);
-    wmc_return_val_if_fail (inbuf_len >= cmd_len + 2, 0); /* space for CRC */
-    wmc_return_val_if_fail (outbuf != NULL, 0);
-
-    /* Add the CRC */
-    crc = wmc_crc16 (inbuf, cmd_len, crc_seed ? crc_seed : 0xFFFF);
-    inbuf[cmd_len++] = crc & 0xFF;
-    inbuf[cmd_len++] = (crc >> 8) & 0xFF;
-
-    escaped_len = hdlc_escape (inbuf, cmd_len, escape_all_ctrl, outbuf, outbuf_len);
-    wmc_return_val_if_fail (outbuf_len > escaped_len, 0);
-
-    if (add_trailer)
-        outbuf[escaped_len++] = DIAG_CONTROL_CHAR;
-
-    return escaped_len;
-}
-
-#define AT_WMC_PREFIX "AT*WMC="
-
-/**
- * uml290_wmc_encapsulate:
- * @inbuf: data buffer to encapsulate
- * @cmd_len: size of the data contained in @inbuf
- * @inbuf_len: total size of @inbuf itself (not just the data)
- * @outbuf: buffer in which to put the encapsulated data
- * @outbuf_len: total size of @outbuf
- *
- * Escapes and CRCs given data using HDLC-style mechanisms with UML290 specific
- * quirks.
- *
- * Returns: size of the encapsulated data writted to @outbuf.
- */
-static size_t
-uml290_wmc_encapsulate (char *inbuf,
-                        size_t cmd_len,
-                        size_t inbuf_len,
-                        char *outbuf,
-                        size_t outbuf_len)
-{
-    size_t encap_len;
-    size_t estimated_out_len;
-
-    wmc_return_val_if_fail (inbuf != NULL, 0);
-    wmc_return_val_if_fail (cmd_len >= 1, 0);
-    wmc_return_val_if_fail (inbuf_len >= cmd_len + 2, 0); /* space for CRC */
-    wmc_return_val_if_fail (outbuf != NULL, 0);
-
-    estimated_out_len = cmd_len + strlen (AT_WMC_PREFIX);
-    estimated_out_len += 3;  /* CRC + trailer */
-    estimated_out_len += cmd_len * 2;  /* escaping */
-    wmc_return_val_if_fail (outbuf_len > estimated_out_len, 0);
-
-    memcpy (outbuf, AT_WMC_PREFIX, strlen (AT_WMC_PREFIX));
-
-    encap_len = hdlc_encapsulate_buffer (inbuf, cmd_len, inbuf_len, 0xAAFE,
-                                         FALSE, TRUE,
-                                         outbuf + strlen (AT_WMC_PREFIX),
-                                         outbuf_len);
-    if (encap_len > 0) {
-        encap_len += strlen (AT_WMC_PREFIX);
-        outbuf[encap_len++] = 0x0D;  /* trailer */
-    }
-
-    return encap_len;
-}
-
-/**
- * wmc_encapsulate:
- * @inbuf: data buffer to encapsulate
- * @cmd_len: size of the data contained in @inbuf
- * @inbuf_len: total size of @inbuf itself (not just the data)
- * @outbuf: buffer in which to put the encapsulated data
- * @outbuf_len: total size of @outbuf
- * @uml290: if %TRUE return buffer suitable for sending to UML290 devices
- *
- * Escapes and CRCs given data using HDLC-style mechanisms.
- *
- * Returns: size of the encapsulated data writted to @outbuf.
- */
-size_t
-wmc_encapsulate (char *inbuf,
-                 size_t cmd_len,
-                 size_t inbuf_len,
-                 char *outbuf,
-                 size_t outbuf_len,
-                 wmcbool uml290)
-{
-    wmc_return_val_if_fail (inbuf != NULL, 0);
-    wmc_return_val_if_fail (cmd_len >= 1, 0);
-    wmc_return_val_if_fail (inbuf_len >= cmd_len + 3, 0); /* space for CRC + trailer */
-    wmc_return_val_if_fail (outbuf != NULL, 0);
-
-    if (uml290)
-        return uml290_wmc_encapsulate (inbuf, cmd_len, inbuf_len, outbuf, outbuf_len);
-
-    /* Otherwise do normal WMC */
-    return hdlc_encapsulate_buffer (inbuf, cmd_len, inbuf_len,
-                                    0, TRUE, FALSE, outbuf, outbuf_len);
-}
-
-/**
- * hdlc_decapsulate_buffer:
- * @inbuf: buffer in which to look for an HDLC frame
- * @inbuf_len: length of valid data in @inbuf
- * @check_known_crc: if %TRUE, validate the CRC using @known_crc if the normal
- *  CRC check fails
- * @known_crc: if @check_known_crc is %TRUE, compare the frame's CRC against
- *  @known_crc if the normal CRC check fails.  @known_crc must be in Little
- *  Endian (LE) byte order.
- * @outbuf: buffer in which to put decapsulated data from the HDLC frame
- * @outbuf_len: max size of @outbuf
- * @out_decap_len: on success, size of the decapsulated data
- * @out_used: on either success or failure, amount of data used; caller should
- *  discard this much data from @inbuf before the next call to this function
- * @out_need_more: when TRUE, indicates that more data is required before
- *  a determination about a valid HDLC frame can be made; caller should add
- *  more data to @inbuf before calling this function again.
- *
- * Attempts to retrieve, unescape, and CRC-check an HDLC frame from the given
- * buffer.
- *
- * Returns: FALSE on error (packet was invalid or malformed, or the CRC check
- *  failed, etc) and places number of bytes to discard from @inbuf in @out_used.
- *  When TRUE, either more data is required (in which case @out_need_more will
- *  be TRUE), or a data packet was successfully retrieved from @inbuf and the
- *  decapsulated packet of length @out_decap_len was placed into @outbuf.  In
- *  all cases the caller should advance the buffer by the number of bytes
- *  returned in @out_used before calling this function again.
- **/
-wmcbool
-hdlc_decapsulate_buffer (const char *inbuf,
-                         size_t inbuf_len,
-                         wmcbool check_known_crc,
-                         uint16_t known_crc,
-                         char *outbuf,
-                         size_t outbuf_len,
-                         size_t *out_decap_len,
-                         size_t *out_used,
-                         wmcbool *out_need_more)
-{
-    wmcbool escaping = FALSE;
-    size_t i, pkt_len = 0, unesc_len;
-    uint16_t crc, pkt_crc;
-
-    wmc_return_val_if_fail (inbuf != NULL, FALSE);
-    wmc_return_val_if_fail (outbuf != NULL, FALSE);
-    wmc_return_val_if_fail (outbuf_len > 0, FALSE);
-    wmc_return_val_if_fail (out_decap_len != NULL, FALSE);
-    wmc_return_val_if_fail (out_used != NULL, FALSE);
-    wmc_return_val_if_fail (out_need_more != NULL, FALSE);
-
-    *out_decap_len = 0;
-    *out_used = 0;
-    *out_need_more = FALSE;
-
-    if (inbuf_len < 4) {
-        *out_need_more = TRUE;
-        return TRUE;
-    }
-
-    /* Find the async control character */
-    for (i = 0; i < inbuf_len; i++) {
-        if (inbuf[i] == DIAG_CONTROL_CHAR) {
-            /* If the control character shows up in a position before a valid
-             * QCDM packet length (4), the packet is malformed.
-             */
-            if (i < 3) {
-                /* Tell the caller to advance the buffer past the control char */
-                *out_used = i + 1;
-                return FALSE;
-            }
-
-            pkt_len = i;
-            break;
-        }
-    }
-
-    /* No control char yet, need more data */
-    if (!pkt_len) {
-        *out_need_more = TRUE;
-        return TRUE;
-    }
-
-    /* Unescape first; note that pkt_len */
-    unesc_len = hdlc_unescape (inbuf, pkt_len, outbuf, outbuf_len, &escaping);
-    if (!unesc_len) {
-        /* Tell the caller to advance the buffer past the control char */
-        *out_used = pkt_len + 1;
-        return FALSE;
-    }
-
-    if (escaping) {
-        *out_need_more = TRUE;
-        return TRUE;
-    }
-
-    /* Check the CRC of the packet's data */
-    crc = wmc_crc16 (outbuf, unesc_len - 2, 0);
-    pkt_crc = outbuf[unesc_len - 2] & 0xFF;
-    pkt_crc |= (outbuf[unesc_len - 1] & 0xFF) << 8;
-    if (crc != pkt_crc) {
-        if (!check_known_crc || (pkt_crc != known_crc)) {
-            *out_used = pkt_len + 1; /* packet + CRC + 0x7E */
-            return FALSE;
-        }
-    }
-
-    *out_used = pkt_len + 1; /* packet + CRC + 0x7E */
-    *out_decap_len = unesc_len - 2; /* decap_len should not include the CRC */
-    return TRUE;
-}
-
-/**
- * wmc_decapsulate:
- * @inbuf: buffer in which to look for an HDLC frame
- * @inbuf_len: length of valid data in @inbuf
- * @outbuf: buffer in which to put decapsulated data from the HDLC frame
- * @outbuf_len: max size of @outbuf
- * @out_decap_len: on success, size of the decapsulated data
- * @out_used: on either success or failure, amount of data used; caller should
- *  discard this much data from @inbuf before the next call to this function
- * @out_need_more: when TRUE, indicates that more data is required before
- *  a determination about a valid HDLC frame can be made; caller should add
- *  more data to @inbuf before calling this function again.
- * @uml290: if %TRUE decapsulate response from UML290 devices
- *
- * Attempts to retrieve, unescape, and CRC-check an HDLC frame from the given
- * buffer.
- *
- * Returns: FALSE on error (packet was invalid or malformed, or the CRC check
- *  failed, etc) and places number of bytes to discard from @inbuf in @out_used.
- *  When TRUE, either more data is required (in which case @out_need_more will
- *  be TRUE), or a data packet was successfully retrieved from @inbuf and the
- *  decapsulated packet of length @out_decap_len was placed into @outbuf.  In
- *  all cases the caller should advance the buffer by the number of bytes
- *  returned in @out_used before calling this function again.
- **/
-wmcbool
-wmc_decapsulate (const char *inbuf,
-                 size_t inbuf_len,
-                 char *outbuf,
-                 size_t outbuf_len,
-                 size_t *out_decap_len,
-                 size_t *out_used,
-                 wmcbool *out_need_more,
-                 wmcbool uml290)
-{
-    return hdlc_decapsulate_buffer (inbuf, inbuf_len,
-                                    uml290, uml290 ? 0x3030 : 0,
-                                    outbuf, outbuf_len,
-                                    out_decap_len, out_used, out_need_more);
-}
diff --git a/libwmc/src/utils.h b/libwmc/src/utils.h
deleted file mode 100644
index 0918c29..0000000
--- a/libwmc/src/utils.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*
- * Copyright (C) 2011 Red Hat, Inc.
- *
- * This program is free software: you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef LIBWMC_UTILS_H
-#define LIBWMC_UTILS_H
-
-#include <stdint.h>
-
-typedef uint8_t wmcbool;
-#ifndef TRUE
-#define TRUE ((uint8_t) 1)
-#endif
-#ifndef FALSE
-#define FALSE ((uint8_t) 0)
-#endif
-
-#define DIAG_CONTROL_CHAR 0x7E
-#define DIAG_TRAILER_LEN  3
-
-/* Utility and testcase functions */
-
-uint16_t wmc_crc16 (const char *buffer, size_t len, uint16_t seed);
-
-size_t hdlc_escape (const char *inbuf,
-                    size_t inbuf_len,
-                    wmcbool escape_all_ctrl,
-                    char *outbuf,
-                    size_t outbuf_len);
-
-size_t hdlc_unescape (const char *inbuf,
-                      size_t inbuf_len,
-                      char *outbuf,
-                      size_t outbuf_len,
-                      wmcbool *escaping);
-
-size_t hdlc_encapsulate_buffer (char *inbuf,
-                                size_t cmd_len,
-                                size_t inbuf_len,
-                                uint16_t crc_seed,
-                                wmcbool add_trailer,
-                                wmcbool escape_all_ctrl,
-                                char *outbuf,
-                                size_t outbuf_len);
-
-wmcbool hdlc_decapsulate_buffer (const char *inbuf,
-                                 size_t inbuf_len,
-                                 wmcbool check_known_crc,
-                                 uint16_t known_crc,
-                                 char *outbuf,
-                                 size_t outbuf_len,
-                                 size_t *out_decap_len,
-                                 size_t *out_used,
-                                 wmcbool *out_need_more);
-
-/* Functions for actual communication */
-
-size_t wmc_encapsulate (char *inbuf,
-                        size_t cmd_len,
-                        size_t inbuf_len,
-                        char *outbuf,
-                        size_t outbuf_len,
-                        wmcbool uml290);
-
-wmcbool wmc_decapsulate (const char *inbuf,
-                         size_t inbuf_len,
-                         char *outbuf,
-                         size_t outbuf_len,
-                         size_t *out_decap_len,
-                         size_t *out_used,
-                         wmcbool *out_need_more,
-                         wmcbool uml290);
-
-#endif  /* LIBWMC_UTILS_H */
diff --git a/libwmc/tests/Makefile.am b/libwmc/tests/Makefile.am
deleted file mode 100644
index 4622fbc..0000000
--- a/libwmc/tests/Makefile.am
+++ /dev/null
@@ -1,31 +0,0 @@
-include $(top_srcdir)/gtester.make
-
-AM_CFLAGS = $(CODE_COVERAGE_CFLAGS)
-AM_LDFLAGS = $(CODE_COVERAGE_LDFLAGS)
-
-noinst_PROGRAMS = test-wmc
-TEST_PROGS += $(noinst_PROGRAMS)
-
-test_wmc_SOURCES = \
-	test-wmc-crc.c \
-	test-wmc-crc.h \
-	test-wmc-escaping.c \
-	test-wmc-escaping.h \
-	test-wmc-utils.c \
-	test-wmc-utils.h \
-	test-wmc-com.c \
-	test-wmc-com.h \
-	test-wmc.c
-
-test_wmc_CPPFLAGS = \
-	$(MM_CFLAGS) \
-	-I$(top_srcdir)/libwmc/src \
-	-I$(top_srcdir)/src
-
-test_wmc_LDADD = $(MM_LIBS)
-
-if WMC_STANDALONE
-test_wmc_LDADD += $(top_builddir)/src/libwmc.la
-else
-test_wmc_LDADD += $(top_builddir)/libwmc/src/libwmc.la
-endif
diff --git a/libwmc/tests/test-wmc-com.c b/libwmc/tests/test-wmc-com.c
deleted file mode 100644
index 2c10057..0000000
--- a/libwmc/tests/test-wmc-com.c
+++ /dev/null
@@ -1,504 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*
- * Copyright (C) 2011 Red Hat, Inc.
- *
- * This program is free software: you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <glib.h>
-#include <string.h>
-#include <errno.h>
-#include <sys/ioctl.h>
-#include <fcntl.h>
-#include <termios.h>
-#include <unistd.h>
-#include <stdlib.h>
-
-#include "test-wmc-com.h"
-#include "com.h"
-#include "utils.h"
-#include "errors.h"
-#include "commands.h"
-
-/************************************************************/
-
-typedef struct {
-    char *port;
-    int fd;
-    struct termios old_t;
-    wmcbool debug;
-    wmcbool uml290;
-} TestComData;
-
-gpointer
-test_com_setup (const char *port, wmcbool uml290, wmcbool debug)
-{
-    TestComData *d;
-    int ret;
-
-    d = g_malloc0 (sizeof (TestComData));
-    g_assert (d);
-    d->uml290 = uml290;
-    d->debug = debug;
-
-    if (getenv ("SERIAL_DEBUG"))
-        d->debug = TRUE;
-
-    errno = 0;
-    d->fd = open (port, O_RDWR | O_EXCL | O_NONBLOCK | O_NOCTTY);
-    if (d->fd < 0)
-        g_warning ("%s: open failed: %d", port, errno);
-    g_assert (d->fd >= 0);
-
-    ret = ioctl (d->fd, TIOCEXCL);
-    if (ret) {
-        g_warning ("%s: lock failed: %d", port, errno);
-        close (d->fd);
-        d->fd = -1;
-    }
-    g_assert (ret == 0);
-
-    ret = ioctl (d->fd, TCGETA, &d->old_t);
-    if (ret) {
-        g_warning ("%s: old termios failed: (%d) %s", port, errno, strerror (errno));
-        close (d->fd);
-        d->fd = -1;
-    }
-    g_assert (ret == 0);
-
-    d->port = g_strdup (port);
-    return d;
-}
-
-void
-test_com_teardown (gpointer user_data)
-{
-    TestComData *d = user_data;
-
-    g_assert (d);
-
-    g_free (d->port);
-    close (d->fd);
-    g_free (d);
-}
-
-static void
-print_buf (const char *detail, const char *buf, size_t len)
-{
-    int i = 0, z;
-    wmcbool newline = FALSE;
-    char *f;
-    guint flen;
-
-    f = g_strdup_printf ("%s (%zu)  ", detail, len);
-    flen = strlen (f);
-    g_print ("%s", f);
-    for (i = 0; i < len; i++) {
-        g_print ("%02x ", buf[i] & 0xFF);
-        if (((i + 1) % 16) == 0) {
-            g_print ("\n");
-            z = flen;
-            while (z--)
-                g_print (" ");
-            newline = TRUE;
-        } else
-            newline = FALSE;
-    }
-
-    if (!newline)
-        g_print ("\n");
-}
-
-static wmcbool
-send_command (TestComData *d,
-              char *inbuf,
-              size_t inbuf_len,
-              size_t cmd_len)
-{
-    int status;
-    int eagain_count = 1000;
-    size_t i = 0, sendlen;
-    char sendbuf[600];
-
-    if (d->debug)
-        print_buf ("\nRAW>>>", inbuf, cmd_len);
-
-    /* Encapsulate the data for the device */
-    sendlen = wmc_encapsulate (inbuf, cmd_len, inbuf_len, sendbuf, sizeof (sendbuf), d->uml290);
-    if (sendlen <= 0) {
-        g_warning ("Failed to encapsulate WMC command");
-        return FALSE;
-    }
-
-    if (d->debug)
-        print_buf ("ENC>>>", sendbuf, sendlen);
-
-    while (i < sendlen) {
-        errno = 0;
-        status = write (d->fd, &sendbuf[i], 1);
-        if (status < 0) {
-            if (errno == EAGAIN) {
-                eagain_count--;
-                if (eagain_count <= 0)
-                    return FALSE;
-            } else
-                g_assert (errno == 0);
-        } else
-            i++;
-
-        usleep (1000);
-    }
-
-    return TRUE;
-}
-
-static size_t
-wait_reply (TestComData *d, char *buf, size_t len)
-{
-    fd_set in;
-    int result;
-    struct timeval timeout = { 1, 0 };
-    char readbuf[2048];
-    ssize_t bytes_read;
-    int total = 0, retries = 0;
-    size_t decap_len = 0;
-
-    FD_ZERO (&in);
-    FD_SET (d->fd, &in);
-    result = select (d->fd + 1, &in, NULL, NULL, &timeout);
-    if (result != 1 || !FD_ISSET (d->fd, &in))
-        return 0;
-
-    do {
-        errno = 0;
-        bytes_read = read (d->fd, &readbuf[total], 1);
-        if ((bytes_read == 0) || (errno == EAGAIN)) {
-            /* Haven't gotten the async control char yet */
-            if (retries > 20)
-                return 0; /* 2 seconds, give up */
-
-            /* Otherwise wait a bit and try again */
-            usleep (100000);
-            retries++;
-            continue;
-        } else if (bytes_read == 1) {
-            wmcbool more = FALSE, success;
-            size_t used = 0;
-
-            total++;
-            decap_len = 0;
-            success = wmc_decapsulate (readbuf, total, buf, len, &decap_len, &used, &more, d->uml290);
-
-            if (success && !more && d->debug)
-                print_buf ("RAW<<<", readbuf, total);
-
-            /* Discard used data */
-            if (used > 0) {
-                total -= used;
-                memmove (readbuf, &readbuf[used], total);
-            }
-
-            if (success && !more) {
-                /* Success; we have a packet */
-                break;
-            }
-        } else {
-            /* Some error occurred */
-            return 0;
-        }
-    } while (total < sizeof (readbuf));
-
-    if (d->debug)
-        print_buf ("DCP<<<", buf, decap_len);
-
-    return decap_len;
-}
-
-void
-test_com_port_init (void *f, void *data)
-{
-    TestComData *d = data;
-    int ret;
-
-    ret = wmc_port_setup (d->fd);
-    if (ret < 0)
-        g_warning ("%s: error setting up serial port: (%d)", d->port, ret);
-    g_assert_cmpint (ret, ==, 0);
-}
-
-void
-test_com_init (void *f, void *data)
-{
-    TestComData *d = data;
-    wmcbool success;
-    char buf[512];
-    gint len;
-    WmcResult *result;
-    size_t reply_len;
-
-    len = wmc_cmd_init_new (buf, sizeof (buf), d->uml290);
-    g_assert (len);
-
-    /* Send the command */
-    success = send_command (d, buf, sizeof (buf), len);
-    g_assert (success);
-
-    /* Get a response */
-    reply_len = wait_reply (d, buf, sizeof (buf));
-
-    /* Parse the response into a result structure */
-    result = wmc_cmd_init_result (buf, reply_len, d->uml290);
-    g_assert (result);
-
-    wmc_result_unref (result);
-}
-
-void
-test_com_device_info (void *f, void *data)
-{
-    TestComData *d = data;
-    wmcbool success;
-    char buf[2048];
-    const char *str, *str2;
-    gint len;
-    WmcResult *result;
-    size_t reply_len;
-    guint32 u32;
-
-    len = wmc_cmd_device_info_new (buf, sizeof (buf));
-    g_assert (len == 2);
-
-    /* Send the command */
-    success = send_command (d, buf, sizeof (buf), len);
-    g_assert (success);
-
-    /* Get a response */
-    reply_len = wait_reply (d, buf, sizeof (buf));
-
-    /* Parse the response into a result structure */
-    result = wmc_cmd_device_info_result (buf, reply_len);
-    g_assert (result);
-
-    g_print ("\n");
-
-    str = NULL;
-    wmc_result_get_string (result, WMC_CMD_DEVICE_INFO_ITEM_MANUFACTURER, &str);
-    g_message ("%s: Manuf:    %s", __func__, str);
-
-    str = NULL;
-    wmc_result_get_string (result, WMC_CMD_DEVICE_INFO_ITEM_MODEL, &str);
-    g_message ("%s: Model:    %s", __func__, str);
-
-    str = NULL;
-    wmc_result_get_string (result, WMC_CMD_DEVICE_INFO_ITEM_FW_REVISION, &str);
-    g_message ("%s: FW Rev:   %s", __func__, str);
-
-    str = NULL;
-    wmc_result_get_string (result, WMC_CMD_DEVICE_INFO_ITEM_HW_REVISION, &str);
-    g_message ("%s: HW Rev:   %s", __func__, str);
-
-    str = NULL;
-    wmc_result_get_string (result, WMC_CMD_DEVICE_INFO_ITEM_CDMA_MIN, &str);
-    g_message ("%s: CDMA MIN: %s", __func__, str);
-
-    u32 = 0;
-    wmc_result_get_u32 (result, WMC_CMD_DEVICE_INFO_ITEM_HOME_SID, &u32);
-    g_message ("%s: Home SID: %d", __func__, u32);
-
-    u32 = 0;
-    wmc_result_get_u32 (result, WMC_CMD_DEVICE_INFO_ITEM_PRL_VERSION, &u32);
-    g_message ("%s: PRL Ver:  %d", __func__, u32);
-
-    u32 = 0;
-    wmc_result_get_u32 (result, WMC_CMD_DEVICE_INFO_ITEM_ERI_VERSION, &u32);
-    g_message ("%s: ERI Ver:  %d", __func__, u32);
-
-    str = NULL;
-    wmc_result_get_string (result, WMC_CMD_DEVICE_INFO_ITEM_MEID, &str);
-    g_message ("%s: MEID:     %s", __func__, str ? str : "(none)");
-
-    str = NULL;
-    wmc_result_get_string (result, WMC_CMD_DEVICE_INFO_ITEM_IMEI, &str);
-    g_message ("%s: IMEI:     %s", __func__, str ? str : "(none)");
-
-    str = NULL;
-    wmc_result_get_string (result, WMC_CMD_DEVICE_INFO_ITEM_ICCID, &str);
-    g_message ("%s: ICCID:    %s", __func__, str ? str : "(none)");
-
-    str = NULL;
-    wmc_result_get_string (result, WMC_CMD_DEVICE_INFO_ITEM_MCC, &str);
-    str2 = NULL;
-    wmc_result_get_string (result, WMC_CMD_DEVICE_INFO_ITEM_MNC, &str2);
-    g_message ("%s: MCC/MNC:  %s %s", __func__,
-               str ? str : "(none)",
-               str2 ? str2 : "(none)");
-
-    wmc_result_unref (result);
-}
-
-static const char *
-service_to_string (uint8_t service)
-{
-    switch (service) {
-    case WMC_NETWORK_SERVICE_NONE:
-        return "none";
-    case WMC_NETWORK_SERVICE_AMPS:
-        return "AMPS";
-    case WMC_NETWORK_SERVICE_IS95A:
-        return "IS95-A";
-    case WMC_NETWORK_SERVICE_IS95B:
-        return "IS95-B";
-    case WMC_NETWORK_SERVICE_GSM:
-        return "GSM";
-    case WMC_NETWORK_SERVICE_GPRS:
-        return "GPRS";
-    case WMC_NETWORK_SERVICE_1XRTT:
-        return "1xRTT";
-    case WMC_NETWORK_SERVICE_EVDO_0:
-        return "EVDO r0";
-    case WMC_NETWORK_SERVICE_UMTS:
-        return "UMTS";
-    case WMC_NETWORK_SERVICE_EVDO_A:
-        return "EVDO rA";
-    case WMC_NETWORK_SERVICE_EDGE:
-        return "EDGE";
-    case WMC_NETWORK_SERVICE_HSDPA:
-        return "HSDPA";
-    case WMC_NETWORK_SERVICE_HSUPA:
-        return "HSUPA";
-    case WMC_NETWORK_SERVICE_HSPA:
-        return "HSPA";
-    case WMC_NETWORK_SERVICE_LTE:
-        return "LTE";
-    default:
-        return "unknown";
-    }
-}
-
-void
-test_com_network_info (void *f, void *data)
-{
-    TestComData *d = data;
-    wmcbool success;
-    char buf[1024];
-    const char *str;
-    uint8_t dbm, service;
-    gint len;
-    WmcResult *result;
-    size_t reply_len;
-
-    len = wmc_cmd_network_info_new (buf, sizeof (buf));
-    g_assert (len == 2);
-
-    /* Send the command */
-    success = send_command (d, buf, sizeof (buf), len);
-    g_assert (success);
-
-    /* Get a response */
-    reply_len = wait_reply (d, buf, sizeof (buf));
-
-    /* Parse the response into a result structure */
-    result = wmc_cmd_network_info_result (buf, reply_len);
-    g_assert (result);
-
-    g_print ("\n");
-
-    service = 0;
-    wmc_result_get_u8 (result, WMC_CMD_NETWORK_INFO_ITEM_SERVICE, &service);
-    g_message ("%s: Service: %d (%s)", __func__, service, service_to_string (service));
-
-    dbm = 0;
-    wmc_result_get_u8 (result, WMC_CMD_NETWORK_INFO_ITEM_2G_DBM, &dbm);
-    g_message ("%s: 2G dBm: -%d", __func__, dbm);
-
-    dbm = 0;
-    wmc_result_get_u8 (result, WMC_CMD_NETWORK_INFO_ITEM_3G_DBM, &dbm);
-    g_message ("%s: 3G dBm: -%d", __func__, dbm);
-
-    dbm = 0;
-    wmc_result_get_u8 (result, WMC_CMD_NETWORK_INFO_ITEM_LTE_DBM, &dbm);
-    g_message ("%s: LTE dBm: -%d", __func__, dbm);
-
-    str = NULL;
-    wmc_result_get_string (result, WMC_CMD_NETWORK_INFO_ITEM_OPNAME, &str);
-    g_message ("%s: Operator Name: %s", __func__, str ? str : "(none)");
-
-    str = NULL;
-    wmc_result_get_string (result, WMC_CMD_NETWORK_INFO_ITEM_MCC, &str);
-    g_message ("%s: MCC: %s", __func__, str ? str : "(none)");
-
-    str = NULL;
-    wmc_result_get_string (result, WMC_CMD_NETWORK_INFO_ITEM_MNC, &str);
-    g_message ("%s: MNC: %s", __func__, str ? str : "(none)");
-
-    wmc_result_unref (result);
-}
-
-static const char *
-mode_to_string (uint8_t service)
-{
-    switch (service) {
-    case WMC_NETWORK_MODE_AUTO_CDMA:
-        return "CDMA/EVDO";
-    case WMC_NETWORK_MODE_CDMA_ONLY:
-        return "CDMA only";
-    case WMC_NETWORK_MODE_EVDO_ONLY:
-        return "EVDO only";
-    case WMC_NETWORK_MODE_AUTO_GSM:
-        return "GSM/UMTS";
-    case WMC_NETWORK_MODE_GPRS_ONLY:
-        return "GSM/GPRS/EDGE only";
-    case WMC_NETWORK_MODE_UMTS_ONLY:
-        return "UMTS/HSPA only";
-    case WMC_NETWORK_MODE_AUTO:
-        return "Auto";
-    case WMC_NETWORK_MODE_LTE_ONLY:
-        return "LTE only";
-    default:
-        return "unknown";
-    }
-}
-
-void
-test_com_get_global_mode (void *f, void *data)
-{
-    TestComData *d = data;
-    wmcbool success;
-    char buf[1024];
-    uint8_t mode;
-    gint len;
-    WmcResult *result;
-    size_t reply_len;
-
-    len = wmc_cmd_get_global_mode_new (buf, sizeof (buf));
-    g_assert (len == 3);
-
-    /* Send the command */
-    success = send_command (d, buf, sizeof (buf), len);
-    g_assert (success);
-
-    /* Get a response */
-    reply_len = wait_reply (d, buf, sizeof (buf));
-
-    /* Parse the response into a result structure */
-    result = wmc_cmd_get_global_mode_result (buf, reply_len);
-    g_assert (result);
-
-    g_print ("\n");
-
-    mode = 0;
-    wmc_result_get_u8 (result, WMC_CMD_GET_GLOBAL_MODE_ITEM_MODE, &mode);
-    g_message ("%s: Mode: %d (%s)", __func__, mode, mode_to_string (mode));
-
-    wmc_result_unref (result);
-}
diff --git a/libwmc/tests/test-wmc-com.h b/libwmc/tests/test-wmc-com.h
deleted file mode 100644
index 3dc0a0d..0000000
--- a/libwmc/tests/test-wmc-com.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*
- * Copyright (C) 2011 Red Hat, Inc.
- *
- * This program is free software: you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef TEST_WMC_COM_H
-#define TEST_WMC_COM_H
-
-#include "utils.h"
-
-gpointer test_com_setup (const char *port, wmcbool uml290, wmcbool debug);
-void test_com_teardown (gpointer d);
-
-void test_com_port_init (void *f, void *data);
-
-void test_com_init (void *f, void *data);
-
-void test_com_device_info (void *f, void *data);
-
-void test_com_network_info (void *f, void *data);
-
-void test_com_get_global_mode (void *f, void *data);
-
-#endif  /* TEST_WMC_COM_H */
-
diff --git a/libwmc/tests/test-wmc-crc.c b/libwmc/tests/test-wmc-crc.c
deleted file mode 100644
index 2965011..0000000
--- a/libwmc/tests/test-wmc-crc.c
+++ /dev/null
@@ -1,65 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*
- * Copyright (C) 2010 Red Hat, Inc.
- *
- * This program is free software: you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <glib.h>
-#include <string.h>
-
-#include "test-wmc-crc.h"
-#include "utils.h"
-
-void
-test_crc16_2 (void *f, void *data)
-{
-    static const char buf[] = {
-        0x26, 0xb2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x00
-    };
-    guint16 crc;
-    guint16 expected = 0x6D69;
-
-    /* CRC check */
-    crc = wmc_crc16 (buf, sizeof (buf), 0);
-    g_assert (crc == expected);
-}
-
-void
-test_crc16_1 (void *f, void *data)
-{
-    static const char buf[] = {
-        0x4b, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
-        0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x3f,
-        0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-        0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff
-    };
-    guint16 crc;
-    guint16 expected = 0x097A;
-
-    /* CRC check */
-    crc = wmc_crc16 (buf, sizeof (buf), 0);
-    g_assert (crc == expected);
-}
-
diff --git a/libwmc/tests/test-wmc-crc.h b/libwmc/tests/test-wmc-crc.h
deleted file mode 100644
index 4ce2871..0000000
--- a/libwmc/tests/test-wmc-crc.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*
- * Copyright (C) 2010 Red Hat, Inc.
- *
- * This program is free software: you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef TEST_WMC_CRC_H
-#define TEST_WMC_CRC_H
-
-void test_crc16_2 (void *f, void *data);
-void test_crc16_1 (void *f, void *data);
-
-#endif  /* TEST_WMC_CRC_H */
-
diff --git a/libwmc/tests/test-wmc-escaping.c b/libwmc/tests/test-wmc-escaping.c
deleted file mode 100644
index 3c4cd21..0000000
--- a/libwmc/tests/test-wmc-escaping.c
+++ /dev/null
@@ -1,165 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*
- * Copyright (C) 2010 Red Hat, Inc.
- *
- * This program is free software: you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <glib.h>
-#include <string.h>
-
-#include "test-wmc-escaping.h"
-#include "utils.h"
-
-static const char data1[] = {
-    0x70, 0x68, 0x6f, 0x6e, 0x65, 0x66, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 
-    0x0a, 0x6e, 0x6f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 
-    0x6e, 0x74, 0x6f, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x0a, 0x70, 0x68, 0x6f, 
-    0x6e, 0x7e, 0x7e, 0x7e, 0x7d, 0x7d, 0x7e, 0x7d, 0x7e, 0x7d, 0x7e, 0x6e, 
-    0x6b, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x0a, 0x6f, 0x70, 
-    0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x6c, 
-    0x6c, 0x6f, 0x77, 0x65, 0x64, 0x0a, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 
-    0x69, 0x6f, 0x6e, 0x6e, 0x6f, 0x74, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 
-    0x74, 0x65, 0x64, 0x0a, 0x70, 0x68, 0x73, 0x69, 0x6d, 0x70, 0x69, 0x6e, 
-    0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x0a, 0x70, 0x68, 0x66, 
-    0x73, 0x69, 0x6d, 0x70, 0x69, 0x6e, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 
-    0x65, 0x64, 0x0a, 0x70, 0x68, 0x66, 0x73, 0x69, 0x6d, 0x70, 0x75, 0x6b, 
-    0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x0a, 0x73, 0x69, 0x6d, 
-    0x6e, 0x6f, 0x74, 0x69, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x65, 0x64, 0x0a, 
-    0x73, 0x69, 0x6d, 0x70, 0x69, 0x6e, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 
-    0x65, 0x64, 0x0a, 0x73, 0x69, 0x6d, 0x70, 0x75, 0x6b, 0x72, 0x65, 0x71, 
-    0x75, 0x69, 0x72, 0x65, 0x64, 0x0a, 0x73, 0x69, 0x6d, 0x66, 0x61, 0x69, 
-    0x6c, 0x75, 0x72, 0x65, 0x0a, 0x73, 0x69, 0x6d, 0x62, 0x75, 0x73, 0x79, 
-    0x0a, 0x73, 0x69, 0x6d, 0x77, 0x72, 0x6f, 0x6e, 0x67, 0x0a, 0x69, 0x6e, 
-    0x63, 0x6f, 0x72, 0x72, 0x65, 0x63, 0x74, 0x70, 0x61, 0x73, 0x73, 0x77, 
-    0x6f, 0x72, 0x64, 0x0a, 0x73, 0x69, 0x6d, 0x70, 0x69, 0x6e, 0x32, 0x72, 
-    0x65, 0x71, 0x75, 0x69
-};
-
-static const char expected1[] = {
-    0x70, 0x68, 0x6f, 0x6e, 0x65, 0x66, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 
-    0x0a, 0x6e, 0x6f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 
-    0x6e, 0x74, 0x6f, 0x70, 0x68, 0x6f, 0x6e, 0x65, 0x0a, 0x70, 0x68, 0x6f, 
-    0x6e, 0x7d, 0x5e, 0x7d, 0x5e, 0x7d, 0x5e, 0x7d, 0x5d, 0x7d, 0x5d, 0x7d, 
-    0x5e, 0x7d, 0x5d, 0x7d, 0x5e, 0x7d, 0x5d, 0x7d, 0x5e, 0x6e, 0x6b, 0x72, 
-    0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x0a, 0x6f, 0x70, 0x65, 0x72, 
-    0x61, 0x74, 0x69, 0x6f, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x6c, 0x6c, 0x6f, 
-    0x77, 0x65, 0x64, 0x0a, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 
-    0x6e, 0x6e, 0x6f, 0x74, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 
-    0x64, 0x0a, 0x70, 0x68, 0x73, 0x69, 0x6d, 0x70, 0x69, 0x6e, 0x72, 0x65, 
-    0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x0a, 0x70, 0x68, 0x66, 0x73, 0x69, 
-    0x6d, 0x70, 0x69, 0x6e, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 
-    0x0a, 0x70, 0x68, 0x66, 0x73, 0x69, 0x6d, 0x70, 0x75, 0x6b, 0x72, 0x65, 
-    0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x0a, 0x73, 0x69, 0x6d, 0x6e, 0x6f, 
-    0x74, 0x69, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x65, 0x64, 0x0a, 0x73, 0x69, 
-    0x6d, 0x70, 0x69, 0x6e, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 
-    0x0a, 0x73, 0x69, 0x6d, 0x70, 0x75, 0x6b, 0x72, 0x65, 0x71, 0x75, 0x69, 
-    0x72, 0x65, 0x64, 0x0a, 0x73, 0x69, 0x6d, 0x66, 0x61, 0x69, 0x6c, 0x75, 
-    0x72, 0x65, 0x0a, 0x73, 0x69, 0x6d, 0x62, 0x75, 0x73, 0x79, 0x0a, 0x73, 
-    0x69, 0x6d, 0x77, 0x72, 0x6f, 0x6e, 0x67, 0x0a, 0x69, 0x6e, 0x63, 0x6f, 
-    0x72, 0x72, 0x65, 0x63, 0x74, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 
-    0x64, 0x0a, 0x73, 0x69, 0x6d, 0x70, 0x69, 0x6e, 0x32, 0x72, 0x65, 0x71, 
-    0x75, 0x69
-};
-
-void
-test_escape1 (void *f, void *data)
-{
-    char escaped[1024];
-    size_t len;
-
-    /* Ensure that escaping in general works */
-    len = hdlc_escape (data1, sizeof (data1), FALSE, escaped, sizeof (escaped));
-    g_assert (len == 266);
-    g_assert (len == sizeof (expected1));
-    g_assert (memcmp (escaped, expected1, len) == 0);
-}
-
-static const char data2[] = {
-    0x4b, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
-    0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x3f,
-    0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff
-};
-
-void
-test_escape2 (void *f, void *data)
-{
-    char escaped[1024];
-    size_t len;
-
-    /* Ensure that escaping data that doesn't need escaping works */
-    len = hdlc_escape (data2, sizeof (data2), FALSE, escaped, sizeof (escaped));
-    g_assert (len == sizeof (data2));
-    g_assert (memcmp (escaped, data2, len) == 0);
-}
-
-static const char data_ctrl_src[] = {
-    0xc8, 0x0d, 0xda, 0x07, 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x19, 0x00,
-    0x04, 0x00, 0x01, 0x00, 0x07, 0x88
-};
-
-static const char data_ctrl_expected[] = {
-    0xc8, 0x7d, 0x2d, 0xda, 0x7d, 0x27, 0x7d, 0x2c, 0x7d, 0x20, 0x7d, 0x34,
-    0x7d, 0x20, 0x7d, 0x30, 0x7d, 0x20, 0x7d, 0x39, 0x7d, 0x20, 0x7d, 0x24,
-    0x7d, 0x20, 0x7d, 0x21, 0x7d, 0x20, 0x7d, 0x27, 0x88
-};
-
-void
-test_escape_ctrl (void *f, void *data)
-{
-    char escaped[1024];
-    size_t len;
-
-    len = hdlc_escape (data_ctrl_src, sizeof (data_ctrl_src), TRUE, escaped, sizeof (escaped));
-    g_assert (len == sizeof (data_ctrl_expected));
-    g_assert (memcmp (escaped, data_ctrl_expected, len) == 0);
-}
-
-void
-test_escape_unescape (void *f, void *data)
-{
-    char escaped[512];
-    char unescaped[512];
-    size_t len, unlen;
-    wmcbool escaping = FALSE;
-
-    /* Ensure that escaping data that needs escaping, and then unescaping it,
-     * produces the exact same data as was originally escaped.
-     */
-    len = hdlc_escape (data1, sizeof (data1), FALSE, escaped, sizeof (escaped));
-    unlen = hdlc_unescape (escaped, len, unescaped, sizeof (unescaped), &escaping);
-
-    g_assert (unlen == sizeof (data1));
-    g_assert (memcmp (unescaped, data1, unlen) == 0);
-}
-
-void
-test_escape_unescape_ctrl (void *f, void *data)
-{
-    char escaped[512];
-    char unescaped[512];
-    size_t len, unlen;
-    wmcbool escaping = FALSE;
-
-    /* Ensure that escaping data that needs escaping, and then unescaping it,
-     * produces the exact same data as was originally escaped.
-     */
-    len = hdlc_escape (data_ctrl_src, sizeof (data_ctrl_src), TRUE, escaped, sizeof (escaped));
-    g_assert (memcmp (escaped, data_ctrl_expected, len) == 0);
-
-    unlen = hdlc_unescape (escaped, len, unescaped, sizeof (unescaped), &escaping);
-    g_assert (unlen == sizeof (data_ctrl_src));
-    g_assert (memcmp (unescaped, data_ctrl_src, unlen) == 0);
-}
-
diff --git a/libwmc/tests/test-wmc-escaping.h b/libwmc/tests/test-wmc-escaping.h
deleted file mode 100644
index 144c37b..0000000
--- a/libwmc/tests/test-wmc-escaping.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*
- * Copyright (C) 2010 Red Hat, Inc.
- *
- * This program is free software: you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef TEST_WMC_ESCAPING_H
-#define TEST_WMC_ESCAPING_H
-
-void test_escape1 (void *f, void *data);
-void test_escape2 (void *f, void *data);
-void test_escape_ctrl (void *f, void *data);
-void test_escape_unescape (void *f, void *data);
-void test_escape_unescape_ctrl (void *f, void *data);
-
-#endif  /* TEST_WMC_ESCAPING_H */
-
diff --git a/libwmc/tests/test-wmc-utils.c b/libwmc/tests/test-wmc-utils.c
deleted file mode 100644
index 93c2a6a..0000000
--- a/libwmc/tests/test-wmc-utils.c
+++ /dev/null
@@ -1,223 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*
- * Copyright (C) 2010 Red Hat, Inc.
- *
- * This program is free software: you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <glib.h>
-#include <string.h>
-
-#include "test-wmc-utils.h"
-#include "utils.h"
-
-static const char decap_inbuf[] = {
-    0x40, 0x03, 0x00, 0x01, 0x00, 0x19, 0xf0, 0x00, 0x16, 0x00, 0x21, 0x00,
-    0x1c, 0x00, 0xd8, 0x00, 0x3f, 0x00, 0x56, 0x01, 0x3f, 0x00, 0x15, 0x00,
-    0x1a, 0x00, 0x11, 0x01, 0x3f, 0x00, 0x92, 0x01, 0x3f, 0x00, 0x39, 0x00,
-    0x3f, 0x00, 0x95, 0x01, 0x3f, 0x00, 0x12, 0x00, 0x3f, 0x00, 0x23, 0x01,
-    0x3f, 0x00, 0x66, 0x00, 0x3f, 0x00, 0x0b, 0x01, 0x3f, 0x00, 0xae, 0x00,
-    0x3f, 0x00, 0x02, 0x01, 0x3f, 0x00, 0xa8, 0x00, 0x3f, 0x00, 0x50, 0x01,
-    0x3f, 0x00, 0xf8, 0x01, 0x3f, 0x00, 0x57, 0x00, 0x3f, 0x00, 0x7d, 0x5e,
-    0x00, 0x3f, 0x00, 0x93, 0x00, 0x3f, 0x00, 0xbd, 0x00, 0x3f, 0x00, 0x77,
-    0x01, 0x3f, 0x00, 0xb7, 0x00, 0x3f, 0x00, 0xab, 0x00, 0x3f, 0x00, 0x33,
-    0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0xad, 0xde, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13,
-    0x13, 0x50, 0x1f, 0x00, 0x00, 0xff, 0xff, 0x00, 0xaa, 0x19, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb1, 0xc4, 0x7d, 0x5e,
-    0x7d, 0x5e, 0x7d, 0x5d, 0x5d, 0x04, 0x58, 0x1b, 0x5b, 0x1b, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x65, 0x69, 0x7e
-};
-
-void
-test_utils_decapsulate_basic_buffer (void *f, void *data)
-{
-    wmcbool success;
-    char outbuf[512];
-    size_t decap_len = 0;
-    size_t used = 0;
-    wmcbool more = FALSE;
-
-    success = hdlc_decapsulate_buffer (decap_inbuf, sizeof (decap_inbuf),
-                                       FALSE, 0, outbuf, sizeof (outbuf),
-                                       &decap_len, &used, &more);
-    g_assert (success);
-    g_assert (decap_len == 214);
-    g_assert (used == 221);
-    g_assert (more == FALSE);
-}
-
-
-static const char encap_outbuf[] = {
-    0x4b, 0x05, 0x08, 0x00, 0x01, 0xdd, 0x7e
-};
-
-void
-test_utils_encapsulate_basic_buffer (void *f, void *data)
-{
-    char cmdbuf[10];
-    char outbuf[512];
-    size_t encap_len = 0;
-
-    cmdbuf[0] = 0x4B;   /* DIAG_CMD_SUBSYS */
-    cmdbuf[1] = 0x05;   /* DIAG_SUBSYS_HDR */
-    cmdbuf[2] = 0x08;   /* first byte of DIAG_SUBSYS_HDR_STATE_INFO in LE */
-    cmdbuf[3] = 0x00;   /* second byte of DIAG_SUBSYS_HDR_STATE_INFO in LE */
-
-    encap_len = hdlc_encapsulate_buffer (cmdbuf, 4, sizeof (cmdbuf),
-                                         0, TRUE, FALSE,
-                                         &outbuf[0], sizeof (outbuf));
-    g_assert (encap_len == sizeof (encap_outbuf));
-    g_assert (memcmp (outbuf, encap_outbuf, encap_len) == 0);
-}
-
-static const char cns_inbuf[] = {
-    0x00, 0x0a, 0x6b, 0x74, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x7e
-};
-
-void
-test_utils_decapsulate_sierra_cns (void *f, void *data)
-{
-    wmcbool success;
-    char outbuf[512];
-    size_t decap_len = 0;
-    size_t used = 0;
-    wmcbool more = FALSE;
-
-    success = hdlc_decapsulate_buffer (cns_inbuf, sizeof (cns_inbuf),
-                                       FALSE, 0, outbuf, sizeof (outbuf),
-                                       &decap_len, &used, &more);
-    g_assert (success == FALSE);
-}
-
-
-static const char uml290_encap_src[] = {
-    0xc8, 0x0d, 0xda, 0x07, 0x0c, 0x00, 0x14, 0x00, 0x10, 0x00, 0x19, 0x00,
-    0x04, 0x00, 0x01, 0x00, 0x07, 0x88
-};
-
-static const char uml290_encap_outbuf[] = {
-    0x41, 0x54, 0x2a, 0x57, 0x4d, 0x43, 0x3d, 0xc8, 0x7d, 0x2d, 0xda, 0x7d,
-    0x27, 0x7d, 0x2c, 0x7d, 0x20, 0x7d, 0x34, 0x7d, 0x20, 0x7d, 0x30, 0x7d,
-    0x20, 0x7d, 0x39, 0x7d, 0x20, 0x7d, 0x24, 0x7d, 0x20, 0x7d, 0x21, 0x7d,
-    0x20, 0x7d, 0x27, 0x88, 0x0d
-};
-
-void
-test_utils_encapsulate_uml290_wmc1 (void *f, void *data)
-{
-    char inbuf[512];
-    char outbuf[512];
-    size_t encap_len = 0;
-
-    memcpy (inbuf, uml290_encap_src, sizeof (uml290_encap_src));
-    encap_len = wmc_encapsulate (inbuf, sizeof (uml290_encap_src),
-                                 sizeof (inbuf), outbuf, sizeof (outbuf), TRUE);
-    g_assert (encap_len == sizeof (uml290_encap_outbuf));
-    g_assert (memcmp (outbuf, uml290_encap_outbuf, encap_len) == 0);
-}
-
-static const char uml290_src[] = {
-    0xc8, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0xda, 0x07, 0x0c, 0x00,
-    0x14, 0x00, 0x12, 0x00, 0x19, 0x00, 0x06, 0x00, 0xc2, 0x02, 0x00, 0x00,
-    0x00, 0x00, 0x7d, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x7d, 0x5d, 0x00, 0x00, 0x00, 0x01, 0x00,
-    0x00, 0x00, 0x01, 0x56, 0x65, 0x72, 0x69, 0x7a, 0x6f, 0x6e, 0x20, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39,
-    0x00, 0x00, 0x00, 0x40, 0x06, 0x00, 0x00, 0x30, 0x30, 0x7e
-};
-
-static const char uml290_expected[] = {
-    0xc8, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0xda, 0x07, 0x0c, 0x00,
-    0x14, 0x00, 0x12, 0x00, 0x19, 0x00, 0x06, 0x00, 0xc2, 0x02, 0x00, 0x00,
-    0x00, 0x00, 0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x7d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
-    0x01, 0x56, 0x65, 0x72, 0x69, 0x7a, 0x6f, 0x6e, 0x20, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 0x00, 0x00,
-    0x00, 0x40, 0x06, 0x00, 0x00
-};
-
-void
-test_utils_decapsulate_uml290_wmc1 (void *f, void *data)
-{
-    wmcbool success;
-    char outbuf[512];
-    size_t decap_len = 0;
-    size_t used = 0;
-    wmcbool more = FALSE;
-
-    success = hdlc_decapsulate_buffer (uml290_src, sizeof (uml290_src),
-                                       TRUE, 0x3030, outbuf, sizeof (outbuf),
-                                       &decap_len, &used, &more);
-    g_assert (success == TRUE);
-    g_assert (more == 0);
-    g_assert_cmpint (used, ==, sizeof (uml290_src));
-    g_assert_cmpint (decap_len, ==, sizeof (uml290_expected));
-    g_assert_cmpint (memcmp (outbuf, uml290_expected, decap_len), ==, 0);
-}
-
-
-static const char pc5740_src[] = {
-    0xc8, 0x0b, 0x17, 0x00, 0x00, 0x00, 0x06, 0x00, 0xdb, 0x07, 0x06, 0x00,
-    0x11, 0x00, 0x0d, 0x00, 0x2d, 0x00, 0x10, 0x00, 0xe4, 0x03, 0xd4, 0xfe,
-    0xff, 0xff, 0x4e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x0e, 0x92, 0x7e
-};
-
-static const char pc5740_expected[] = {
-    0xc8, 0x0b, 0x17, 0x00, 0x00, 0x00, 0x06, 0x00, 0xdb, 0x07, 0x06, 0x00,
-    0x11, 0x00, 0x0d, 0x00, 0x2d, 0x00, 0x10, 0x00, 0xe4, 0x03, 0xd4, 0xfe,
-    0xff, 0xff, 0x4e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00
-};
-
-void
-test_utils_decapsulate_pc5740_wmc1 (void *f, void *data)
-{
-    wmcbool success;
-    char outbuf[512];
-    size_t decap_len = 0;
-    size_t used = 0;
-    wmcbool more = FALSE;
-
-    success = hdlc_decapsulate_buffer (pc5740_src, sizeof (pc5740_src),
-                                       FALSE, 0, outbuf, sizeof (outbuf),
-                                       &decap_len, &used, &more);
-    g_assert (success == TRUE);
-    g_assert (more == 0);
-    g_assert_cmpint (used, ==, sizeof (pc5740_src));
-    g_assert_cmpint (decap_len, ==, sizeof (pc5740_expected));
-    g_assert_cmpint (memcmp (outbuf, pc5740_expected, decap_len), ==, 0);
-}
-
diff --git a/libwmc/tests/test-wmc-utils.h b/libwmc/tests/test-wmc-utils.h
deleted file mode 100644
index 9642706..0000000
--- a/libwmc/tests/test-wmc-utils.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*
- * Copyright (C) 2010 Red Hat, Inc.
- *
- * This program is free software: you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef TEST_WMC_UTILS_H
-#define TEST_WMC_UTILS_H
-
-void test_utils_decapsulate_basic_buffer (void *f, void *data);
-
-void test_utils_encapsulate_basic_buffer (void *f, void *data);
-
-void test_utils_decapsulate_sierra_cns (void *f, void *data);
-
-void test_utils_encapsulate_uml290_wmc1 (void *f, void *data);
-
-void test_utils_decapsulate_uml290_wmc1 (void *f, void *data);
-
-void test_utils_decapsulate_pc5740_wmc1 (void *f, void *data);
-
-#endif  /* TEST_WMC_UTILS_H */
-
diff --git a/libwmc/tests/test-wmc.c b/libwmc/tests/test-wmc.c
deleted file mode 100644
index 1fc13ab..0000000
--- a/libwmc/tests/test-wmc.c
+++ /dev/null
@@ -1,110 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*
- * Copyright (C) 2010 Red Hat, Inc.
- *
- * This program is free software: you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <glib.h>
-#include <string.h>
-
-#include "test-wmc-crc.h"
-#include "test-wmc-escaping.h"
-#include "test-wmc-utils.h"
-#include "test-wmc-com.h"
-
-typedef struct {
-    gpointer com_data;
-} TestData;
-
-typedef GTestFixtureFunc TCFunc;
-
-#define TESTCASE(t, d) g_test_create_case (#t, 0, d, NULL, (TCFunc) t, NULL)
-
-static TestData *
-test_data_new (const char *port, gboolean uml290, gboolean debug)
-{
-    TestData *d;
-
-    d = g_malloc0 (sizeof (TestData));
-    g_assert (d);
-
-    if (port)
-        d->com_data = test_com_setup (port, uml290, debug);
-
-    return d;
-}
-
-static void
-test_data_free (TestData *d)
-{
-    if (d->com_data)
-        test_com_teardown (d->com_data);
-
-    g_free (d);
-}
-
-int main (int argc, char **argv)
-{
-    GTestSuite *suite;
-    TestData *data;
-    int i;
-    const char *port = NULL;
-    gint result;
-    gboolean uml290 = FALSE, debug = FALSE;
-
-    g_test_init (&argc, &argv, NULL);
-
-    /* See if we got passed a serial port for live testing */
-    for (i = 0; i < argc; i++) {
-        if (!strcmp (argv[i], "--port")) {
-            /* Make sure there's actually a port in the next arg */
-            g_assert (argc > i + 1);
-            port = argv[++i];
-        } else if (!strcmp (argv[i], "--uml290"))
-            uml290 = TRUE;
-        else if (!strcmp (argv[i], "--debug"))
-            debug = TRUE;
-    }
-
-    data = test_data_new (port, uml290, debug);
-
-    suite = g_test_get_root ();
-    g_test_suite_add (suite, TESTCASE (test_crc16_1, NULL));
-    g_test_suite_add (suite, TESTCASE (test_crc16_2, NULL));
-    g_test_suite_add (suite, TESTCASE (test_escape1, NULL));
-    g_test_suite_add (suite, TESTCASE (test_escape2, NULL));
-    g_test_suite_add (suite, TESTCASE (test_escape_ctrl, NULL));
-    g_test_suite_add (suite, TESTCASE (test_escape_unescape, NULL));
-    g_test_suite_add (suite, TESTCASE (test_escape_unescape_ctrl, NULL));
-    g_test_suite_add (suite, TESTCASE (test_utils_decapsulate_basic_buffer, NULL));
-    g_test_suite_add (suite, TESTCASE (test_utils_encapsulate_basic_buffer, NULL));
-    g_test_suite_add (suite, TESTCASE (test_utils_decapsulate_sierra_cns, NULL));
-    g_test_suite_add (suite, TESTCASE (test_utils_decapsulate_uml290_wmc1, NULL));
-    g_test_suite_add (suite, TESTCASE (test_utils_decapsulate_pc5740_wmc1, NULL));
-
-    /* Live tests */
-    if (port) {
-        g_test_suite_add (suite, TESTCASE (test_com_port_init, data->com_data));
-        g_test_suite_add (suite, TESTCASE (test_com_init, data->com_data));
-        g_test_suite_add (suite, TESTCASE (test_com_device_info, data->com_data));
-        g_test_suite_add (suite, TESTCASE (test_com_network_info, data->com_data));
-        g_test_suite_add (suite, TESTCASE (test_com_get_global_mode, data->com_data));
-    }
-
-    result = g_test_run ();
-
-    test_data_free (data);
-
-    return result;
-}
diff --git a/libwmc/uml290.txt b/libwmc/uml290.txt
deleted file mode 100644
index 5a6113a..0000000
--- a/libwmc/uml290.txt
+++ /dev/null
@@ -1,206 +0,0 @@
-This document describes information about the Pantech UML290 and the WMC
-protocol observed through USB packet capture and other investigation.
-
-
-Pantech UML290 Notes
---------------------------------------
-
-This device exposes 4 USB interfaces.  They are, in no particular order, a
-CDC-ACM compatible AT command port, a QCDM/Diag port, an WMC port, and a
-raw IP network port.  The modem's native command interface is the WMC port
-which the Windows driver uses for all normal communication.
-
-
-CDC-ACM AT Port
-----------------
-
-The modem's +GCAP response reports:
-
-+GCAP: +CIS707-A, CIS-856, CIS-856-A, +CGSM, +CLTE1
-
-and with recent firmware updates (L0290VWB333F.230 [Mar 15 2011 15:03:20] or
-later) the device does, in fact, appear to support common IS-707-A and ETSI
-27.007 GSM and LTE AT commands.  This interface does support PPP data but when
-PPP is used the device does not support handoffs between LTE and EVDO.
-
-To support seamless operation of devices between LTE and EVDO Verizon has
-upgraded their network to support the eHRPD protocol.  Older, non-LTE capable
-devices usually do not include support for eHRPD and use the standard HRPD
-protocols.  LTE-capable devices support both eHRPD and standard HRPD, but at
-least with the UML290, connections to the 3G EVDO network using direct PPP over
-the AT modem port do not use eHRPD.  Thus to successfully connect to the 3G
-EVDO network, the modem must be switched into standard HRPD mode by changing
-the value of the NV_HDRSCP_FORCE_AT_CONFIG_I NVRAM item using the the QCDM/Diag
-port and the DIAG protocol.  Use of HRPD only prevents connections to the LTE
-network.  It is possible that connections initiated using the WMC port and
-utilizing the "raw IP" network interface do not have this problem.
-
-
-QCDM/Diag Port
-----------------
-
-This port is a normal QCDM/Diag port and responds to DIAG commands.
-
-
-Raw IP Network Port
--------------------
-
-This USB interface is the normal network interface port the device uses in
-Windows for network communication.  It appears to operate in a "raw IP" mode
-where raw IP packets are sent and received over USB with no additional framing
-or encapsulation.  The IPv4 and IPv6 addresses for the interface are determined
-using WMC commands on the WMC port, not through the AT command port.  The AT
-command port only supports PPP-based communication.  More information about the
-"raw IP" mode may be available in the Qualcomm CodeAurora SMD/QMI drivers which
-implement a "raw IP" network communication mode for various MSM7xxx chipsets
-used in Android devices.
-
-
-WMC Port
------------
-
-This port accepts and responds to WMC protocol requests.  Instead of using plain
-WMC however, requests are prefixed with the string "AT*WMC=" and terminated with
-a newline (0x0D) character instead of the normal WMC frame termination
-character (0x7E).  The data in between is normal binary WMC data, except that
-all bytes less than 0x20 are escaped using normal HDLC/PPP escaping while a
-normal WMC request would only escape the special HDLC/PPP characters of 0x7E and
-0x7D.  Thus a UML290 request looks like this in hexadecimal:
-
-41542a574d433dc87d2a87b80d
-
-This "AT"-style framing has not been observed on other devices.
-
-
-
-WMC Protocol Framing
---------------------
-
-The protocol is a request/response style protocol though unsolicited responses
-are sometimes sent from the modem to the host.  There does not appear to be any
-sequence numbering in either the request or response packets.  WMC packets
-always begin with the frame start marker (0xC8).  The second byte is the command
-number, followed by the frame's data.  The frame ends with a three-byte trailer
-including a CRC-16 and a frame termination marker which differs between devices.
-Most older devices use the standard HDLC/PPP frame termination marker (0x7E),
-while some others (UML290) use a different termination marker as described
-below.  Thus a normal WMC packet looks like this:
-
-0xC8 <command number> <data> <CRC-16> 0x7E
-
-The entire frame (exclusive of the termination marker) is escaped using standard
-HDLC/PPP escaping mechanisms to ensure that the bytes 0x7E and 0x7D never appear
-in the packet.  Some devices (UML290) escape more than the standard HDLC escape
-characters.
-
-Frames can span multiple USB packets.  This behavior has been observed with the
-PC5740 in various responses, in which case the frame is simply split up between
-USB packets.  It has also been observed with some UML290 requests, where it
-appears that in addition to splitting the frame, each segment after the first
-is prefixed with 0x20.
-
-For example, a split response from a PC5740:
-
-* c8 06 0f 0f 0f 0f 0f 0f 0f 0f 0f 0f 00 00 00 00    ................
-  ...
-  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00       ...............
-
-* 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
-  ...
-  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00       ...............
-
-* 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
-  ...
-  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00       ...............
-
-* 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
-  ...
-  00 00 00 01                                        ....
-
-
-and an split request from a UML290:
-
-* c8 56 86 02 00 00 00 00 00 00 39 30 30 30 38 30    .V........900080
-  ...
-  00 00 00 00 00 00 00 00 00 00 00 00 00 00          ..............
-
-* 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ...............
-  ...
-  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
-
-* 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ...............
-  ...
-  00 00 00 00 00 00 00 00 00 00 5b 1c 0d             ..........[..
-
-
-
-Requests
----------------
-
-Requests are usually short, often only 4 or 5 bytes long, including the frame
-start marker (0xC8), the command number, the 16-bit CRC, and the frame termination
-marker.  Requests almost always receive a response from the modem containing the
-same command number.
-
-The UML290 uses different "AT"-style framing of requests, prefixing the
-request with "AT*WMC=" and using a frame termination marker of 0x0D instead
-of the standard 0x7E.  The UML290 also uses a different CRC-16 initial seed of
-0xAAFE instead of the standard 0xFFFF used on other devices and with HDLC
-framing in general.  For added lolz the UML290 HDLC-escapes all control
-characters in the request in addition to the standard 0x7D and 0x7E characters
-escaped in HDLC.
-
-Thus a normal WMC request (from a PC5740) looks like this:
-
-     c8          0a     77 a4        7e
-<frame start> <cmd no> <CRC-16> <terminator>
-
-while the same request from the UML290 looks like this:
-
-41542a574d433d       c8        7d2a    87 b8        0d
-  <AT*WMC=>    <frame start> <cmd no> <CRC-16> <terminator>
-
-Thus after removing all framing and escaping, this WMC request is a single
-byte (0x0A) which indicates the command number of the request.
-
-
-WMC Responses and Unsolicited Messages
---------------------------------------
-
-Responses begin with the WMC frame start marker (0xC8) and end with the standard
-HDLC/PPP frame terminator (0x7E) in all observed cases, even on the UML290.
-The data in between is HDLC/PPP escaped and there is a CRC-16 before the frame
-terminator.  Not all devices use the same CRC-16 calculation however; the
-UML290 always uses a CRC-16 of 0x3030, while the PC5740 includes a valid CRC-16
-using a standard polynomial of 0x8408 and an initial seed of 0xFFFF.  Responses
-may span multiple USB packets if they are large enough, but the frame terminator
-provides a convenient mechanism for detecting when the frame is complete.
-
-A standard WMC response (from a UML290) looks like this:
-
-c80d0000000030307e
-
-which translates to:
-
-c8 0d 00 00 00 00
-
-
-WMC Command Numbers
--------------------
-
-These command numbers have been observed and minimally investigated:
-
-0x06: request device information, including manufacturer, model, firmware
-      revision, hardware revision, MCC/MNC, serial number
-
-0x0A: request IP configuration when connected (IPv4 and IPv6) on the UML290; may
-      include elapsed connected time or traffic byte counts too.  Request has
-      been observed on the PC5740 but is significantly shorter.
-
-0x0B: get status including operator name, RSSI dBm, and possibly registration
-      status
-
-0x13: retrieve SMS messages
-
-0x4D: appears to request EPS bearer configuration; response includes the APN
-
diff --git a/m4/compiler_warnings.m4 b/m4/compiler_warnings.m4
index f498a28..35d005c 100644
--- a/m4/compiler_warnings.m4
+++ b/m4/compiler_warnings.m4
@@ -10,10 +10,10 @@
 	for option in -Wmissing-declarations -Wmissing-prototypes \
 		      -Wdeclaration-after-statement -Wstrict-prototypes \
 		      -Wno-unused-parameter -Wno-sign-compare \
-		      -Wno-deprecated-declarations \
-		      -Wno-unused-but-set-variable -Wformat-security; do
+		      -Wno-deprecated-declarations -Wno-unused-function \
+		      -Wunused-variable -Wformat-security; do
 		SAVE_CFLAGS="$CFLAGS"
-		CFLAGS="$CFLAGS $option"
+		CFLAGS="$CFLAGS $option -Werror"
 		AC_MSG_CHECKING([whether gcc understands $option])
 		AC_TRY_COMPILE([], [],
 			has_option=yes,
diff --git a/plugins/Makefile.am b/plugins/Makefile.am
index 99aa50f..016ef55 100644
--- a/plugins/Makefile.am
+++ b/plugins/Makefile.am
@@ -9,6 +9,7 @@
 	$(MM_CFLAGS) \
 	$(CODE_COVERAGE_CFLAGS) \
 	$(GUDEV_CFLAGS)	\
+	-DPKGDATADIR=\"${pkgdatadir}\" \
 	-I$(top_srcdir) \
 	-I$(top_srcdir)/src \
 	-I$(top_builddir)/src \
@@ -64,6 +65,9 @@
 # Clean files
 CLEANFILES =
 
+# Data files
+dist_pkgdata_DATA =
+
 ################################################################################
 # common service test support
 ################################################################################
@@ -1074,7 +1078,12 @@
 
 dist_udevrules_DATA += dell/77-mm-dell-port-types.rules
 
-AM_CFLAGS += -DTESTUDEVRULESDIR_DELL=\"${srcdir}/dell\"
+dist_pkgdata_DATA += dell/mm-dell-dw5821e-carrier-mapping.conf
+
+AM_CFLAGS += \
+	-DTESTUDEVRULESDIR_DELL=\"${srcdir}/dell\" \
+	-DTESTKEYFILE_DELL_DW5821E=\"${srcdir}/dell/mm-dell-dw5821e-carrier-mapping.conf\" \
+	$(NULL)
 
 ################################################################################
 # plugin: quectel
@@ -1129,5 +1138,17 @@
 	$(NULL)
 
 ################################################################################
+# keyfile tester
+################################################################################
+
+noinst_PROGRAMS += test-keyfiles
+test_keyfiles_SOURCES = \
+	tests/test-keyfiles.c \
+	$(NULL)
+test_keyfiles_LDADD = \
+	$(top_builddir)/libmm-glib/libmm-glib.la \
+	$(NULL)
+
+################################################################################
 
 TEST_PROGS += $(noinst_PROGRAMS)
diff --git a/plugins/dell/mm-broadband-modem-dell-dw5821e.c b/plugins/dell/mm-broadband-modem-dell-dw5821e.c
index 07607a3..7622cf1 100644
--- a/plugins/dell/mm-broadband-modem-dell-dw5821e.c
+++ b/plugins/dell/mm-broadband-modem-dell-dw5821e.c
@@ -386,9 +386,11 @@
                          MM_BASE_MODEM_PLUGIN,     plugin,
                          MM_BASE_MODEM_VENDOR_ID,  vendor_id,
                          MM_BASE_MODEM_PRODUCT_ID, product_id,
-                         MM_IFACE_MODEM_SIM_HOT_SWAP_SUPPORTED, TRUE,
-                         MM_IFACE_MODEM_SIM_HOT_SWAP_CONFIGURED, FALSE,
-                         MM_IFACE_MODEM_PERIODIC_SIGNAL_CHECK_DISABLED, TRUE,
+                         MM_IFACE_MODEM_SIM_HOT_SWAP_SUPPORTED,              TRUE,
+                         MM_IFACE_MODEM_SIM_HOT_SWAP_CONFIGURED,             FALSE,
+                         MM_IFACE_MODEM_PERIODIC_SIGNAL_CHECK_DISABLED,      TRUE,
+                         MM_IFACE_MODEM_LOCATION_ALLOW_GPS_UNMANAGED_ALWAYS, TRUE,
+                         MM_IFACE_MODEM_CARRIER_CONFIG_MAPPING,              PKGDATADIR "/mm-dell-dw5821e-carrier-mapping.conf",
                          NULL);
 }
 
diff --git a/plugins/dell/mm-dell-dw5821e-carrier-mapping.conf b/plugins/dell/mm-dell-dw5821e-carrier-mapping.conf
new file mode 100644
index 0000000..ec14553
--- /dev/null
+++ b/plugins/dell/mm-dell-dw5821e-carrier-mapping.conf
@@ -0,0 +1,281 @@
+
+#
+# DW5821e carrier mapping table
+#
+# This table maps the MCCMNC of the SIM card with the corresponding
+# configuration description as reported by the QMI PDC service in
+# this module.
+#
+
+[dell dw5821e]
+
+# AT&T
+302220=ATT
+302221=ATT
+31030=ATT
+31070=ATT
+31090=ATT
+310150=ATT
+310170=ATT
+310280=ATT
+310380=ATT
+310410=ATT
+310560=ATT
+310680=ATT
+311180=ATT
+
+# FirstNet
+312670=A2
+313100=A2
+313110=A2
+313120=A2
+313130=A2
+313140=A2
+
+# Verizon
+310590=Verizon
+310890=Verizon
+311270=Verizon
+311480=Verizon
+
+# Vodafone
+20205=Vodafone
+20404=Vodafone
+20601=Vodafone
+20810=Vodafone
+21401=Vodafone
+21670=Vodafone
+21910=Vodafone
+22005=Vodafone
+22210=Vodafone
+22601=Vodafone
+23003=Vodafone
+23201=Vodafone
+23415=Vodafone
+23801=Vodafone
+24405=Vodafone
+24602=Vodafone
+24705=Vodafone
+24802=Vodafone
+25001=Vodafone
+26202=Vodafone
+26209=Vodafone
+26801=Vodafone
+27077=Vodafone
+27201=Vodafone
+27402=Vodafone
+27602=Vodafone
+27801=Vodafone
+28001=Vodafone
+28401=Vodafone
+28602=Vodafone
+28802=Vodafone
+29340=Vodafone
+29403=Vodafone
+40004=Vodafone
+40401=Vodafone
+40405=Vodafone
+40411=Vodafone
+40413=Vodafone
+40415=Vodafone
+40420=Vodafone
+40427=Vodafone
+40430=Vodafone
+40443=Vodafone
+40446=Vodafone
+40460=Vodafone
+40484=Vodafone
+40486=Vodafone
+40488=Vodafone
+40566=Vodafone
+40567=Vodafone
+405750=Vodafone
+405751=Vodafone
+405752=Vodafone
+405753=Vodafone
+405754=Vodafone
+405755=Vodafone
+405756=Vodafone
+41302=Vodafone
+42403=Vodafone
+42602=Vodafone
+42702=Vodafone
+50213=Vodafone
+50219=Vodafone
+50503=Vodafone
+52503=Vodafone
+52505=Vodafone
+53001=Vodafone
+54201=Vodafone
+60202=Vodafone
+62002=Vodafone
+63001=Vodafone
+63902=Vodafone
+64004=Vodafone
+64304=Vodafone
+64710=Vodafone
+65101=Vodafone
+65501=Vodafone
+73001=Vodafone
+90128=Vodafone
+
+# Orange
+20610=Orange
+20801=Orange
+20802=Orange
+21403=Orange
+22610=Orange
+23101=Orange
+23430=Orange
+23433=Orange
+23434=Orange
+25901=Orange
+26003=Orange
+27099=Orange
+28310=Orange
+
+# Telefonica Movistar
+21405=Telefonica
+21407=Telefonica
+
+# Swisscom
+22801=Swisscom
+29501=Swisscom
+
+# Telstra
+50501=Telstra
+50506=Telstra
+50571=Telstra
+50572=Telstra
+
+# Sprint
+310120=Sprint
+
+# Optus
+50202=Optus
+
+# NTT DoCoMo
+44002=Docomo
+44003=Docomo
+44009=Docomo
+44010=Docomo
+44011=Docomo
+44012=Docomo
+44013=Docomo
+44014=Docomo
+44015=Docomo
+44016=Docomo
+44017=Docomo
+44018=Docomo
+44019=Docomo
+44022=Docomo
+44023=Docomo
+44024=Docomo
+44025=Docomo
+44026=Docomo
+44027=Docomo
+44028=Docomo
+44029=Docomo
+44030=Docomo
+44031=Docomo
+44032=Docomo
+44033=Docomo
+44034=Docomo
+44035=Docomo
+44036=Docomo
+44037=Docomo
+44038=Docomo
+44039=Docomo
+44049=Docomo
+44058=Docomo
+44060=Docomo
+44061=Docomo
+44062=Docomo
+44063=Docomo
+44064=Docomo
+44065=Docomo
+44066=Docomo
+44067=Docomo
+44068=Docomo
+44069=Docomo
+44087=Docomo
+44099=Docomo
+44140=Docomo
+44141=Docomo
+44142=Docomo
+44143=Docomo
+44144=Docomo
+44145=Docomo
+44190=Docomo
+44101=Docomo
+44192=Docomo
+44193=Docomo
+44194=Docomo
+44198=Docomo
+44199=Docomo
+
+# KDDI
+44007=KDDI
+44008=KDDI
+44050=KDDI
+44051=KDDI
+44052=KDDI
+44053=KDDI
+44054=KDDI
+44055=KDDI
+44056=KDDI
+44070=KDDI
+44071=KDDI
+44072=KDDI
+44073=KDDI
+44074=KDDI
+44075=KDDI
+44076=KDDI
+44077=KDDI
+44078=KDDI
+44079=KDDI
+44080=KDDI
+44081=KDDI
+44082=KDDI
+44083=KDDI
+44084=KDDI
+44085=KDDI
+44086=KDDI
+44088=KDDI
+44089=KDDI
+44150=KDDI
+44151=KDDI
+44170=KDDI
+
+# SoftBank
+44000=SBM
+44004=SBM
+44006=SBM
+44020=SBM
+44021=SBM
+44040=SBM
+44041=SBM
+44042=SBM
+44043=SBM
+44044=SBM
+44045=SBM
+44046=SBM
+44047=SBM
+44048=SBM
+44090=SBM
+44092=SBM
+44093=SBM
+44094=SBM
+44095=SBM
+44096=SBM
+44097=SBM
+44098=SBM
+44101=SBM
+44161=SBM
+44162=SBM
+44163=SBM
+44164=SBM
+44165=SBM
+
+# Others
+generic=GCF
diff --git a/plugins/tests/test-keyfiles.c b/plugins/tests/test-keyfiles.c
new file mode 100644
index 0000000..9604643
--- /dev/null
+++ b/plugins/tests/test-keyfiles.c
@@ -0,0 +1,82 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details:
+ *
+ * Copyright (C) 2018 Aleksander Morgado <aleksander@aleksander.es>
+ */
+
+#include <glib.h>
+#include <glib-object.h>
+#include <string.h>
+#include <stdio.h>
+#include <locale.h>
+
+#define _LIBMM_INSIDE_MM
+#include <libmm-glib.h>
+
+#include "mm-log.h"
+
+/************************************************************/
+
+static void
+common_test (const gchar *keyfile_path)
+{
+    GKeyFile *keyfile;
+    GError   *error = NULL;
+    gboolean  ret;
+
+    keyfile = g_key_file_new ();
+    ret = g_key_file_load_from_file (keyfile, keyfile_path, G_KEY_FILE_NONE, &error);
+    g_assert_no_error (error);
+    g_assert (ret);
+    g_key_file_unref (keyfile);
+}
+
+/************************************************************/
+
+static void
+test_dell_dw5821e (void)
+{
+    common_test (TESTKEYFILE_DELL_DW5821E);
+}
+
+/************************************************************/
+
+void
+_mm_log (const char *loc,
+         const char *func,
+         guint32 level,
+         const char *fmt,
+         ...)
+{
+#if defined ENABLE_TEST_MESSAGE_TRACES
+    /* Dummy log function */
+    va_list args;
+    gchar *msg;
+
+    va_start (args, fmt);
+    msg = g_strdup_vprintf (fmt, args);
+    va_end (args);
+    g_print ("%s\n", msg);
+    g_free (msg);
+#endif
+}
+
+int main (int argc, char **argv)
+{
+    setlocale (LC_ALL, "");
+
+    g_test_init (&argc, &argv, NULL);
+
+    g_test_add_func ("/MM/test-keyfiles/dell/dw5821e", test_dell_dw5821e);
+
+    return g_test_run ();
+}
diff --git a/plugins/ublox/77-mm-ublox-port-types.rules b/plugins/ublox/77-mm-ublox-port-types.rules
index e3e434a..9f8263e 100644
--- a/plugins/ublox/77-mm-ublox-port-types.rules
+++ b/plugins/ublox/77-mm-ublox-port-types.rules
@@ -46,7 +46,7 @@
 ATTRS{idVendor}=="1546", ATTRS{idProduct}=="110a", ENV{.MM_USBIFNUM}=="08", ENV{ID_MM_PORT_IGNORE}="1"
 ATTRS{idVendor}=="1546", ATTRS{idProduct}=="110a", ENV{.MM_USBIFNUM}=="0a", ENV{ID_MM_PORT_IGNORE}="1"
 
-# LISA-U2 port types
+# LISA-U2 / SARA-U2 port types
 #  ttyACM0 (if #0): primary
 #  ttyACM1 (if #2): secondary
 #  ttyACM2 (if #4): tertiary
@@ -59,4 +59,13 @@
 ATTRS{idVendor}=="1546", ATTRS{idProduct}=="1102", ENV{.MM_USBIFNUM}=="0a", ENV{ID_MM_PORT_IGNORE}="1"
 ATTRS{idVendor}=="1546", ATTRS{idProduct}=="1102", ENV{.MM_USBIFNUM}=="0c", ENV{ID_MM_PORT_IGNORE}="1"
 
+# LISA-U2 / SARA-U2 (alternative configuration) port types
+#  ttyACM0 (if #0): primary
+#  ttyACM1 (if #2): GNSS Tunneling (ignore)
+#  ttyACM2 (if #4): Primary Log for diagnostics (ignore)
+#  ttyACM3 (if #6): SAP (SIM Access Profile) (ignore)
+ATTRS{idVendor}=="1546", ATTRS{idProduct}=="1104", ENV{.MM_USBIFNUM}=="02", ENV{ID_MM_PORT_IGNORE}="1"
+ATTRS{idVendor}=="1546", ATTRS{idProduct}=="1104", ENV{.MM_USBIFNUM}=="04", ENV{ID_MM_PORT_IGNORE}="1"
+ATTRS{idVendor}=="1546", ATTRS{idProduct}=="1104", ENV{.MM_USBIFNUM}=="06", ENV{ID_MM_PORT_IGNORE}="1"
+
 LABEL="mm_ublox_port_types_end"
diff --git a/plugins/via/mm-broadband-modem-via.c b/plugins/via/mm-broadband-modem-via.c
index 1959fd9..968e62d 100644
--- a/plugins/via/mm-broadband-modem-via.c
+++ b/plugins/via/mm-broadband-modem-via.c
@@ -111,6 +111,7 @@
                                                                     &results->skip_at_cdma1x_serving_system_step,
                                                                     &results->skip_detailed_registration_state,
                                                                     &error)) {
+        g_free (results);
         g_task_return_error (task, error);
     } else {
         /* Skip +CSS */
diff --git a/src/mm-base-manager.c b/src/mm-base-manager.c
index 62c586c..55382e3 100644
--- a/src/mm-base-manager.c
+++ b/src/mm-base-manager.c
@@ -1236,7 +1236,7 @@
 {
     InhibitDeviceContext *ctx;
 
-    ctx = g_new0 (InhibitDeviceContext, 1);
+    ctx = g_slice_new0 (InhibitDeviceContext);
     ctx->self = g_object_ref (manager);
     ctx->invocation = g_object_ref (invocation);
     ctx->uid = g_strdup (uid);
diff --git a/src/mm-broadband-bearer.c b/src/mm-broadband-bearer.c
index 16acb2b..aa6654e 100644
--- a/src/mm-broadband-bearer.c
+++ b/src/mm-broadband-bearer.c
@@ -261,10 +261,8 @@
 static void
 cdma_connect_context_dial (GTask *task)
 {
-    MMBroadbandBearer      *self;
     DetailedConnectContext *ctx;
 
-    self = g_task_get_source_object (task);
     ctx = g_task_get_task_data (task);
 
     mm_base_modem_at_command_full (ctx->modem,
diff --git a/src/mm-broadband-modem-mbim.c b/src/mm-broadband-modem-mbim.c
index fa62485..1cc4ec2 100644
--- a/src/mm-broadband-modem-mbim.c
+++ b/src/mm-broadband-modem-mbim.c
@@ -238,44 +238,47 @@
 static void
 complete_current_capabilities (GTask *task)
 {
-    MMBroadbandModemMbim           *self;
     LoadCurrentCapabilitiesContext *ctx;
     MMModemCapability               result = 0;
 
-    self = g_task_get_source_object (task);
     ctx  = g_task_get_task_data (task);
 
 #if defined WITH_QMI && QMI_MBIM_QMUX_SUPPORTED
-    /* Warn if the MBIM loaded capabilities isn't a subset of the QMI loaded ones */
-    if (ctx->current_qmi && ctx->current_mbim) {
-        gchar *mbim_caps_str;
-        gchar *qmi_caps_str;
+    {
+        MMBroadbandModemMbim *self;
 
-        mbim_caps_str = mm_common_build_capabilities_string ((const MMModemCapability *)&(ctx->current_mbim), 1);
-        qmi_caps_str = mm_common_build_capabilities_string ((const MMModemCapability *)&(ctx->current_qmi), 1);
+        self = g_task_get_source_object (task);
+        /* Warn if the MBIM loaded capabilities isn't a subset of the QMI loaded ones */
+        if (ctx->current_qmi && ctx->current_mbim) {
+            gchar *mbim_caps_str;
+            gchar *qmi_caps_str;
 
-        if ((ctx->current_mbim & ctx->current_qmi) != ctx->current_mbim)
-            mm_warn ("MBIM reported current capabilities (%s) not found in QMI-over-MBIM reported ones (%s)",
-                     mbim_caps_str, qmi_caps_str);
-        else
-            mm_dbg ("MBIM reported current capabilities (%s) is a subset of the QMI-over-MBIM reported ones (%s)",
-                    mbim_caps_str, qmi_caps_str);
-        g_free (mbim_caps_str);
-        g_free (qmi_caps_str);
+            mbim_caps_str = mm_common_build_capabilities_string ((const MMModemCapability *)&(ctx->current_mbim), 1);
+            qmi_caps_str = mm_common_build_capabilities_string ((const MMModemCapability *)&(ctx->current_qmi), 1);
 
-        result = ctx->current_qmi;
-        self->priv->qmi_capability_and_mode_switching = TRUE;
-    } else if (ctx->current_qmi) {
-        result = ctx->current_qmi;
-        self->priv->qmi_capability_and_mode_switching = TRUE;
-    } else
-        result = ctx->current_mbim;
+            if ((ctx->current_mbim & ctx->current_qmi) != ctx->current_mbim)
+                mm_warn ("MBIM reported current capabilities (%s) not found in QMI-over-MBIM reported ones (%s)",
+                         mbim_caps_str, qmi_caps_str);
+            else
+                mm_dbg ("MBIM reported current capabilities (%s) is a subset of the QMI-over-MBIM reported ones (%s)",
+                        mbim_caps_str, qmi_caps_str);
+            g_free (mbim_caps_str);
+            g_free (qmi_caps_str);
 
-    /* If current capabilities loading is done via QMI, we can safely assume that all the other
-     * capability and mode related operations are going to be done via QMI as well, so that we
-     * don't mix both logics */
-    if (self->priv->qmi_capability_and_mode_switching)
-        mm_info ("QMI-based capability and mode switching support enabled");
+            result = ctx->current_qmi;
+            self->priv->qmi_capability_and_mode_switching = TRUE;
+        } else if (ctx->current_qmi) {
+            result = ctx->current_qmi;
+            self->priv->qmi_capability_and_mode_switching = TRUE;
+        } else
+            result = ctx->current_mbim;
+
+        /* If current capabilities loading is done via QMI, we can safely assume that all the other
+         * capability and mode related operations are going to be done via QMI as well, so that we
+         * don't mix both logics */
+        if (self->priv->qmi_capability_and_mode_switching)
+            mm_info ("QMI-based capability and mode switching support enabled");
+    }
 #else
     result = ctx->current_mbim;
 #endif
@@ -1874,8 +1877,7 @@
 typedef struct {
     MMPortMbim *mbim;
 #if defined WITH_QMI && QMI_MBIM_QMUX_SUPPORTED
-    QmiService qmi_services[32];
-    guint      qmi_service_index;
+    guint       qmi_service_index;
 #endif
 } InitializationStartedContext;
 
@@ -1933,6 +1935,14 @@
 
 #if defined WITH_QMI && QMI_MBIM_QMUX_SUPPORTED
 
+static const QmiService qmi_services[] = {
+    QMI_SERVICE_DMS,
+    QMI_SERVICE_NAS,
+    QMI_SERVICE_PDS,
+    QMI_SERVICE_LOC,
+    QMI_SERVICE_PDC,
+};
+
 static void allocate_next_qmi_client (GTask *task);
 
 static void
@@ -1947,7 +1957,7 @@
 
     if (!mm_port_mbim_allocate_qmi_client_finish (mbim, res, &error)) {
         mm_dbg ("Couldn't allocate QMI client for service '%s': %s",
-                qmi_service_get_string (ctx->qmi_services[ctx->qmi_service_index]),
+                qmi_service_get_string (qmi_services[ctx->qmi_service_index]),
                 error->message);
         g_error_free (error);
     }
@@ -1960,19 +1970,17 @@
 allocate_next_qmi_client (GTask *task)
 {
     InitializationStartedContext *ctx;
-    MMBroadbandModemMbim         *self;
 
-    self = g_task_get_source_object (task);
     ctx = g_task_get_task_data (task);
 
-    if (ctx->qmi_services[ctx->qmi_service_index] == QMI_SERVICE_UNKNOWN) {
+    if (ctx->qmi_service_index == G_N_ELEMENTS (qmi_services)) {
         parent_initialization_started (task);
         return;
     }
 
     /* Otherwise, allocate next client */
     mm_port_mbim_allocate_qmi_client (ctx->mbim,
-                                      ctx->qmi_services[ctx->qmi_service_index],
+                                      qmi_services[ctx->qmi_service_index],
                                       NULL,
                                       (GAsyncReadyCallback)mbim_port_allocate_qmi_client_ready,
                                       task);
@@ -2187,15 +2195,6 @@
         return;
     }
 
-#if defined WITH_QMI && QMI_MBIM_QMUX_SUPPORTED
-    /* Setup services to open */
-    ctx->qmi_services[0] = QMI_SERVICE_DMS;
-    ctx->qmi_services[1] = QMI_SERVICE_NAS;
-    ctx->qmi_services[2] = QMI_SERVICE_PDS;
-    ctx->qmi_services[3] = QMI_SERVICE_LOC;
-    ctx->qmi_services[4] = QMI_SERVICE_UNKNOWN;
-#endif
-
     /* Now open our MBIM port */
     mm_port_mbim_open (ctx->mbim,
 #if defined WITH_QMI && QMI_MBIM_QMUX_SUPPORTED
@@ -2610,12 +2609,9 @@
                                         GAsyncResult *res,
                                         GTask        *task)
 {
-    MMBroadbandModemMbim *self;
     MbimMessage          *response;
     GError               *error = NULL;
 
-    self = g_task_get_source_object (task);
-
     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);
@@ -2632,7 +2628,6 @@
                                                  GAsyncResult *res,
                                                  GTask        *task)
 {
-    MMBroadbandModemMbim        *self;
     MbimMessage                 *request;
     MbimMessage                 *response;
     GError                      *error = NULL;
@@ -2641,7 +2636,6 @@
     MbimLteAttachConfiguration **configurations = NULL;
     guint                        i;
 
-    self   = g_task_get_source_object (task);
     config = g_task_get_task_data (task);
 
     response = mbim_device_command_finish (device, res, &error);
@@ -5234,6 +5228,10 @@
     iface->load_supported_ip_families_finish = modem_load_supported_ip_families_finish;
 
 #if defined WITH_QMI && QMI_MBIM_QMUX_SUPPORTED
+    iface->load_carrier_config = mm_shared_qmi_load_carrier_config;
+    iface->load_carrier_config_finish = mm_shared_qmi_load_carrier_config_finish;
+    iface->setup_carrier_config = mm_shared_qmi_setup_carrier_config;
+    iface->setup_carrier_config_finish = mm_shared_qmi_setup_carrier_config_finish;
     iface->load_supported_bands = mm_shared_qmi_load_supported_bands;
     iface->load_supported_bands_finish = mm_shared_qmi_load_supported_bands_finish;
     iface->load_current_bands = mm_shared_qmi_load_current_bands;
diff --git a/src/mm-broadband-modem-qmi.c b/src/mm-broadband-modem-qmi.c
index ca274c4..7356a5e 100644
--- a/src/mm-broadband-modem-qmi.c
+++ b/src/mm-broadband-modem-qmi.c
@@ -8235,9 +8235,19 @@
 /*****************************************************************************/
 /* First initialization step */
 
+static const QmiService qmi_services[] = {
+    QMI_SERVICE_DMS,
+    QMI_SERVICE_NAS,
+    QMI_SERVICE_WMS,
+    QMI_SERVICE_PDS,
+    QMI_SERVICE_OMA,
+    QMI_SERVICE_UIM,
+    QMI_SERVICE_LOC,
+    QMI_SERVICE_PDC,
+};
+
 typedef struct {
     MMPortQmi *qmi;
-    QmiService services[32];
     guint service_index;
 } InitializationStartedContext;
 
@@ -8355,7 +8365,7 @@
 
     if (!mm_port_qmi_allocate_client_finish (qmi, res, &error)) {
         mm_dbg ("Couldn't allocate client for service '%s': %s",
-                qmi_service_get_string (ctx->services[ctx->service_index]),
+                qmi_service_get_string (qmi_services[ctx->service_index]),
                 error->message);
         g_error_free (error);
     }
@@ -8373,7 +8383,7 @@
     self = g_task_get_source_object (task);
     ctx = g_task_get_task_data (task);
 
-    if (ctx->services[ctx->service_index] == QMI_SERVICE_UNKNOWN) {
+    if (ctx->service_index == G_N_ELEMENTS (qmi_services)) {
         /* Done we are, track device removal and launch parent's callback */
         track_qmi_device_removed (self, ctx->qmi);
         parent_initialization_started (task);
@@ -8382,7 +8392,7 @@
 
     /* Otherwise, allocate next client */
     mm_port_qmi_allocate_client (ctx->qmi,
-                                 ctx->services[ctx->service_index],
+                                 qmi_services[ctx->service_index],
                                  MM_PORT_QMI_FLAG_DEFAULT,
                                  NULL,
                                  (GAsyncReadyCallback)qmi_port_allocate_client_ready,
@@ -8441,7 +8451,7 @@
                         gpointer user_data)
 {
     InitializationStartedContext *ctx;
-    GTask *task;
+    GTask                        *task;
 
     ctx = g_new0 (InitializationStartedContext, 1);
     ctx->qmi = mm_base_modem_get_port_qmi (MM_BASE_MODEM (self));
@@ -8467,16 +8477,6 @@
         return;
     }
 
-    /* Setup services to open */
-    ctx->services[0] = QMI_SERVICE_DMS;
-    ctx->services[1] = QMI_SERVICE_NAS;
-    ctx->services[2] = QMI_SERVICE_WMS;
-    ctx->services[3] = QMI_SERVICE_PDS;
-    ctx->services[4] = QMI_SERVICE_OMA;
-    ctx->services[5] = QMI_SERVICE_UIM;
-    ctx->services[6] = QMI_SERVICE_LOC;
-    ctx->services[7] = QMI_SERVICE_UNKNOWN;
-
     /* Now open our QMI port */
     mm_port_qmi_open (ctx->qmi,
                       TRUE,
@@ -8587,6 +8587,10 @@
     iface->load_power_state_finish = load_power_state_finish;
     iface->load_supported_ip_families = modem_load_supported_ip_families;
     iface->load_supported_ip_families_finish = modem_load_supported_ip_families_finish;
+    iface->load_carrier_config = mm_shared_qmi_load_carrier_config;
+    iface->load_carrier_config_finish = mm_shared_qmi_load_carrier_config_finish;
+    iface->setup_carrier_config = mm_shared_qmi_setup_carrier_config;
+    iface->setup_carrier_config_finish = mm_shared_qmi_setup_carrier_config_finish;
 
     /* Enabling/disabling */
     iface->modem_power_up = modem_power_up;
diff --git a/src/mm-broadband-modem.c b/src/mm-broadband-modem.c
index c748e90..0a51b4b 100644
--- a/src/mm-broadband-modem.c
+++ b/src/mm-broadband-modem.c
@@ -114,11 +114,13 @@
     PROP_MODEM_MESSAGING_SMS_LIST,
     PROP_MODEM_MESSAGING_SMS_PDU_MODE,
     PROP_MODEM_MESSAGING_SMS_DEFAULT_STORAGE,
+    PROP_MODEM_LOCATION_ALLOW_GPS_UNMANAGED_ALWAYS,
     PROP_MODEM_VOICE_CALL_LIST,
     PROP_MODEM_SIMPLE_STATUS,
     PROP_MODEM_SIM_HOT_SWAP_SUPPORTED,
     PROP_MODEM_SIM_HOT_SWAP_CONFIGURED,
     PROP_MODEM_PERIODIC_SIGNAL_CHECK_DISABLED,
+    PROP_MODEM_CARRIER_CONFIG_MAPPING,
     PROP_FLOW_CONTROL,
     PROP_LAST
 };
@@ -146,6 +148,7 @@
     MMBaseSim *modem_sim;
     MMBearerList *modem_bearer_list;
     MMModemState modem_state;
+    gchar *carrier_config_mapping;
     /* Implementation helpers */
     MMModemCharset modem_current_charset;
     gboolean modem_cind_support_checked;
@@ -203,6 +206,7 @@
     /*<--- Modem Location interface --->*/
     /* Properties */
     GObject *modem_location_dbus_skeleton;
+    gboolean modem_location_allow_gps_unmanaged_always;
 
     /*<--- Modem Messaging interface --->*/
     /* Properties */
@@ -11167,6 +11171,9 @@
     case PROP_MODEM_MESSAGING_SMS_DEFAULT_STORAGE:
         self->priv->modem_messaging_sms_default_storage = g_value_get_enum (value);
         break;
+    case PROP_MODEM_LOCATION_ALLOW_GPS_UNMANAGED_ALWAYS:
+        self->priv->modem_location_allow_gps_unmanaged_always = g_value_get_boolean (value);
+        break;
     case PROP_MODEM_VOICE_CALL_LIST:
         g_clear_object (&self->priv->modem_voice_call_list);
         self->priv->modem_voice_call_list = g_value_dup_object (value);
@@ -11184,6 +11191,9 @@
     case PROP_MODEM_PERIODIC_SIGNAL_CHECK_DISABLED:
         self->priv->periodic_signal_check_disabled = g_value_get_boolean (value);
         break;
+    case PROP_MODEM_CARRIER_CONFIG_MAPPING:
+        self->priv->carrier_config_mapping = g_value_dup_string (value);
+        break;
     case PROP_FLOW_CONTROL:
         self->priv->flow_control = g_value_get_flags (value);
         break;
@@ -11286,6 +11296,9 @@
     case PROP_MODEM_MESSAGING_SMS_DEFAULT_STORAGE:
         g_value_set_enum (value, self->priv->modem_messaging_sms_default_storage);
         break;
+    case PROP_MODEM_LOCATION_ALLOW_GPS_UNMANAGED_ALWAYS:
+        g_value_set_boolean (value, self->priv->modem_location_allow_gps_unmanaged_always);
+        break;
     case PROP_MODEM_VOICE_CALL_LIST:
         g_value_set_object (value, self->priv->modem_voice_call_list);
         break;
@@ -11301,6 +11314,9 @@
     case PROP_MODEM_PERIODIC_SIGNAL_CHECK_DISABLED:
         g_value_set_boolean (value, self->priv->periodic_signal_check_disabled);
         break;
+    case PROP_MODEM_CARRIER_CONFIG_MAPPING:
+        g_value_set_string (value, self->priv->carrier_config_mapping);
+        break;
     case PROP_FLOW_CONTROL:
         g_value_set_flags (value, self->priv->flow_control);
         break;
@@ -11354,6 +11370,8 @@
     if (self->priv->modem_3gpp_registration_regex)
         mm_3gpp_creg_regex_destroy (self->priv->modem_3gpp_registration_regex);
 
+    g_free (self->priv->carrier_config_mapping);
+
     G_OBJECT_CLASS (mm_broadband_modem_parent_class)->finalize (object);
 }
 
@@ -11810,6 +11828,10 @@
                                       MM_IFACE_MODEM_MESSAGING_SMS_DEFAULT_STORAGE);
 
     g_object_class_override_property (object_class,
+                                      PROP_MODEM_LOCATION_ALLOW_GPS_UNMANAGED_ALWAYS,
+                                      MM_IFACE_MODEM_LOCATION_ALLOW_GPS_UNMANAGED_ALWAYS);
+
+    g_object_class_override_property (object_class,
                                       PROP_MODEM_VOICE_CALL_LIST,
                                       MM_IFACE_MODEM_VOICE_CALL_LIST);
 
@@ -11829,6 +11851,10 @@
                                       PROP_MODEM_PERIODIC_SIGNAL_CHECK_DISABLED,
                                       MM_IFACE_MODEM_PERIODIC_SIGNAL_CHECK_DISABLED);
 
+    g_object_class_override_property (object_class,
+                                      PROP_MODEM_CARRIER_CONFIG_MAPPING,
+                                      MM_IFACE_MODEM_CARRIER_CONFIG_MAPPING);
+
     properties[PROP_FLOW_CONTROL] =
         g_param_spec_flags (MM_BROADBAND_MODEM_FLOW_CONTROL,
                             "Flow control",
diff --git a/src/mm-iface-modem-firmware.c b/src/mm-iface-modem-firmware.c
index 5cbe874..ecfa3b5 100644
--- a/src/mm-iface-modem-firmware.c
+++ b/src/mm-iface-modem-firmware.c
@@ -287,16 +287,27 @@
                      MMFirmwareUpdateSettings  *update_settings,
                      GError                   **error)
 {
-    const gchar *revision;
+    const gchar *firmware_revision;
+    const gchar *carrier_revision;
+    gchar       *combined;
 
-    revision = mm_iface_modem_get_revision (MM_IFACE_MODEM (self));
-    if (!revision) {
+    firmware_revision = mm_iface_modem_get_revision (MM_IFACE_MODEM (self));
+    if (!firmware_revision) {
         g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
                      "Unknown revision");
         return FALSE;
     }
 
-    mm_firmware_update_settings_set_version (update_settings, revision);
+    mm_iface_modem_get_carrier_config (MM_IFACE_MODEM (self), NULL, &carrier_revision);
+
+    if (!carrier_revision) {
+        mm_firmware_update_settings_set_version (update_settings, firmware_revision);
+        return TRUE;
+    }
+
+    combined = g_strdup_printf ("%s - %s", firmware_revision, carrier_revision);
+    mm_firmware_update_settings_set_version (update_settings, combined);
+    g_free (combined);
     return TRUE;
 }
 
@@ -311,6 +322,7 @@
     GPtrArray   *ids;
     MMPort      *primary = NULL;
     const gchar *subsystem;
+    const gchar *aux;
 
     vid = mm_base_modem_get_vendor_id (self);
     pid = mm_base_modem_get_product_id (self);
@@ -334,7 +346,16 @@
         return FALSE;
     }
 
+    mm_iface_modem_get_carrier_config (MM_IFACE_MODEM (self), &aux, NULL);
+
     ids = g_ptr_array_new_with_free_func ((GDestroyNotify)g_free);
+    if (aux) {
+        gchar *carrier;
+
+        carrier = g_ascii_strup (aux, -1);
+        g_ptr_array_add (ids, g_strdup_printf ("USB\\VID_%04X&PID_%04X&REV_%04X&CARRIER_%s", vid, pid, rid, carrier));
+        g_free (carrier);
+    }
     g_ptr_array_add (ids, g_strdup_printf ("USB\\VID_%04X&PID_%04X&REV_%04X", vid, pid, rid));
     g_ptr_array_add (ids, g_strdup_printf ("USB\\VID_%04X&PID_%04X", vid, pid));
     g_ptr_array_add (ids, g_strdup_printf ("USB\\VID_%04X", vid));
diff --git a/src/mm-iface-modem-location.c b/src/mm-iface-modem-location.c
index 2ccb643..2168140 100644
--- a/src/mm-iface-modem-location.c
+++ b/src/mm-iface-modem-location.c
@@ -692,6 +692,7 @@
     MMModemLocationSource currently_enabled;
     MMModemLocationSource source;
     gchar *str;
+    gboolean allow_gps_unmanaged_always = FALSE;
 
     ctx = g_new (SetupGatheringContext, 1);
 
@@ -699,7 +700,8 @@
     g_task_set_task_data (task, ctx, (GDestroyNotify)setup_gathering_context_free);
 
     g_object_get (self,
-                  MM_IFACE_MODEM_LOCATION_DBUS_SKELETON, &ctx->skeleton,
+                  MM_IFACE_MODEM_LOCATION_DBUS_SKELETON,              &ctx->skeleton,
+                  MM_IFACE_MODEM_LOCATION_ALLOW_GPS_UNMANAGED_ALWAYS, &allow_gps_unmanaged_always,
                   NULL);
     if (!ctx->skeleton) {
         g_task_return_new_error (task,
@@ -745,13 +747,16 @@
     }
 
     /* When standard GPS retrieval (RAW/NMEA) is enabled, we cannot enable the
-     * UNMANAGED setup, and viceversa. */
-    if ((ctx->to_enable & MM_MODEM_LOCATION_SOURCE_GPS_UNMANAGED &&
-         currently_enabled & (MM_MODEM_LOCATION_SOURCE_GPS_RAW | MM_MODEM_LOCATION_SOURCE_GPS_NMEA)) ||
-        (ctx->to_enable & (MM_MODEM_LOCATION_SOURCE_GPS_RAW | MM_MODEM_LOCATION_SOURCE_GPS_NMEA) &&
-         currently_enabled & MM_MODEM_LOCATION_SOURCE_GPS_UNMANAGED) ||
-        (ctx->to_enable & (MM_MODEM_LOCATION_SOURCE_GPS_RAW | MM_MODEM_LOCATION_SOURCE_GPS_NMEA) &&
-         ctx->to_enable & MM_MODEM_LOCATION_SOURCE_GPS_UNMANAGED)) {
+     * UNMANAGED setup, and viceversa, unless explicitly allowed to do so by the
+     * plugin implementation (e.g. if the RAW/NMEA sources don't use the same TTY
+     * as the GPS UNMANAGED setup. */
+    if (!allow_gps_unmanaged_always &&
+        ((ctx->to_enable & MM_MODEM_LOCATION_SOURCE_GPS_UNMANAGED &&
+          currently_enabled & (MM_MODEM_LOCATION_SOURCE_GPS_RAW | MM_MODEM_LOCATION_SOURCE_GPS_NMEA)) ||
+         (ctx->to_enable & (MM_MODEM_LOCATION_SOURCE_GPS_RAW | MM_MODEM_LOCATION_SOURCE_GPS_NMEA) &&
+          currently_enabled & MM_MODEM_LOCATION_SOURCE_GPS_UNMANAGED) ||
+         (ctx->to_enable & (MM_MODEM_LOCATION_SOURCE_GPS_RAW | MM_MODEM_LOCATION_SOURCE_GPS_NMEA) &&
+          ctx->to_enable & MM_MODEM_LOCATION_SOURCE_GPS_UNMANAGED))) {
         g_task_return_new_error (task,
                                  MM_CORE_ERROR,
                                  MM_CORE_ERROR_FAILED,
@@ -1887,6 +1892,14 @@
                               MM_GDBUS_TYPE_MODEM_LOCATION_SKELETON,
                               G_PARAM_READWRITE));
 
+    g_object_interface_install_property
+        (g_iface,
+         g_param_spec_boolean (MM_IFACE_MODEM_LOCATION_ALLOW_GPS_UNMANAGED_ALWAYS,
+                               "Allow unmanaged GPS always",
+                               "Whether to always allow GPS unmanaged, even when raw/nmea GPS sources are enabled",
+                               FALSE,
+                               G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
     initialized = TRUE;
 }
 
diff --git a/src/mm-iface-modem-location.h b/src/mm-iface-modem-location.h
index 9128f1e..c8b045a 100644
--- a/src/mm-iface-modem-location.h
+++ b/src/mm-iface-modem-location.h
@@ -27,7 +27,8 @@
 #define MM_IS_IFACE_MODEM_LOCATION(obj)            (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_IFACE_MODEM_LOCATION))
 #define MM_IFACE_MODEM_LOCATION_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), MM_TYPE_IFACE_MODEM_LOCATION, MMIfaceModemLocation))
 
-#define MM_IFACE_MODEM_LOCATION_DBUS_SKELETON "iface-modem-location-dbus-skeleton"
+#define MM_IFACE_MODEM_LOCATION_DBUS_SKELETON              "iface-modem-location-dbus-skeleton"
+#define MM_IFACE_MODEM_LOCATION_ALLOW_GPS_UNMANAGED_ALWAYS "iface-modem-location-allow-gps-unmanaged-always"
 
 typedef struct _MMIfaceModemLocation MMIfaceModemLocation;
 
diff --git a/src/mm-iface-modem.c b/src/mm-iface-modem.c
index 1ffcb96..66db38a 100644
--- a/src/mm-iface-modem.c
+++ b/src/mm-iface-modem.c
@@ -3942,6 +3942,7 @@
     INITIALIZATION_STEP_MANUFACTURER,
     INITIALIZATION_STEP_MODEL,
     INITIALIZATION_STEP_REVISION,
+    INITIALIZATION_STEP_CARRIER_CONFIG,
     INITIALIZATION_STEP_HARDWARE_REVISION,
     INITIALIZATION_STEP_EQUIPMENT_ID,
     INITIALIZATION_STEP_DEVICE_ID,
@@ -3952,6 +3953,7 @@
     INITIALIZATION_STEP_SIM_HOT_SWAP,
     INITIALIZATION_STEP_UNLOCK_REQUIRED,
     INITIALIZATION_STEP_SIM,
+    INITIALIZATION_STEP_SETUP_CARRIER_CONFIG,
     INITIALIZATION_STEP_OWN_NUMBERS,
     INITIALIZATION_STEP_CURRENT_MODES,
     INITIALIZATION_STEP_CURRENT_BANDS,
@@ -4334,6 +4336,53 @@
     interface_initialization_step (task);
 }
 
+static void
+setup_carrier_config_ready (MMIfaceModem *self,
+                            GAsyncResult *res,
+                            GTask        *task)
+{
+    InitializationContext *ctx;
+    GError                *error = NULL;
+
+    ctx = g_task_get_task_data (task);
+
+    if (!MM_IFACE_MODEM_GET_INTERFACE (self)->setup_carrier_config_finish (self, res, &error)) {
+        mm_warn ("couldn't setup carrier config: '%s'", error->message);
+        g_error_free (error);
+    }
+
+    /* Go on to next step */
+    ctx->step++;
+    interface_initialization_step (task);
+}
+
+static void
+load_carrier_config_ready (MMIfaceModem *self,
+                           GAsyncResult *res,
+                           GTask        *task)
+{
+    InitializationContext *ctx;
+    GError                *error = NULL;
+    gchar                 *name = NULL;
+    gchar                 *revision = NULL;
+
+    ctx = g_task_get_task_data (task);
+
+    if (!MM_IFACE_MODEM_GET_INTERFACE (self)->load_carrier_config_finish (self, res, &name, &revision, &error)) {
+        mm_warn ("couldn't load carrier config: '%s'", error->message);
+        g_error_free (error);
+    } else {
+        mm_gdbus_modem_set_carrier_configuration          (ctx->skeleton, name);
+        mm_gdbus_modem_set_carrier_configuration_revision (ctx->skeleton, revision);
+        g_free (name);
+        g_free (revision);
+    }
+
+    /* Go on to next step */
+    ctx->step++;
+    interface_initialization_step (task);
+}
+
 void
 mm_iface_modem_update_own_numbers (MMIfaceModem *self,
                                    const GStrv own_numbers)
@@ -4700,6 +4749,21 @@
         /* Fall down to next step */
         ctx->step++;
 
+    case INITIALIZATION_STEP_CARRIER_CONFIG:
+        /* Current carrier config is meant to be loaded only once during the whole
+         * lifetime of the modem. Therefore, if we already have them loaded,
+         * don't try to load them again. */
+        if (mm_gdbus_modem_get_carrier_configuration (ctx->skeleton) == NULL &&
+            MM_IFACE_MODEM_GET_INTERFACE (self)->load_carrier_config &&
+            MM_IFACE_MODEM_GET_INTERFACE (self)->load_carrier_config_finish) {
+            MM_IFACE_MODEM_GET_INTERFACE (self)->load_carrier_config (self,
+                                                                      (GAsyncReadyCallback)load_carrier_config_ready,
+                                                                      task);
+            return;
+        }
+        /* Fall down to next step */
+        ctx->step++;
+
     case INITIALIZATION_STEP_HARDWARE_REVISION:
         /* HardwareRevision is meant to be loaded only once during the whole
          * lifetime of the modem. Therefore, if we already have them loaded,
@@ -4899,6 +4963,49 @@
         /* Fall down to next step */
         ctx->step++;
 
+    case INITIALIZATION_STEP_SETUP_CARRIER_CONFIG:
+        /* Setup and perform automatic carrier config switching as soon as the
+         * SIM initialization has been performed, only applicable if there is
+         * actually a SIM found with a valid IMSI read */
+        if (!mm_iface_modem_is_cdma_only (self) &&
+            MM_IFACE_MODEM_GET_INTERFACE (self)->setup_carrier_config &&
+            MM_IFACE_MODEM_GET_INTERFACE (self)->setup_carrier_config_finish) {
+            MMBaseSim *sim = NULL;
+            gchar     *carrier_config_mapping = NULL;
+
+            g_object_get (self,
+                          MM_IFACE_MODEM_SIM, &sim,
+                          MM_IFACE_MODEM_CARRIER_CONFIG_MAPPING, &carrier_config_mapping,
+                          NULL);
+
+            /* If we have a SIM object, and carrier config switching is supported,
+             * validate whether we're already using the best config or not. */
+            if (!sim)
+                mm_dbg ("not setting up carrier config: SIM not found");
+            else if (!carrier_config_mapping)
+                mm_dbg ("not setting up carrier config: mapping file not configured");
+            else {
+                const gchar *imsi;
+
+                imsi = mm_gdbus_sim_get_imsi (MM_GDBUS_SIM (sim));
+                if (imsi) {
+                    MM_IFACE_MODEM_GET_INTERFACE (self)->setup_carrier_config (self,
+                                                                               imsi,
+                                                                               carrier_config_mapping,
+                                                                               (GAsyncReadyCallback)setup_carrier_config_ready,
+                                                                               task);
+                    g_object_unref (sim);
+                    g_free (carrier_config_mapping);
+                    return;
+                }
+                mm_warn ("couldn't setup carrier config: unknown IMSI");
+            }
+            g_clear_object (&sim);
+            g_free (carrier_config_mapping);
+        }
+        /* Fall down to next step */
+        ctx->step++;
+
     case INITIALIZATION_STEP_OWN_NUMBERS:
         /* Own numbers is meant to be loaded only once during the whole
          * lifetime of the modem. Therefore, if we already have them loaded,
@@ -5347,6 +5454,27 @@
     return revision;
 }
 
+gboolean
+mm_iface_modem_get_carrier_config (MMIfaceModem  *self,
+                                   const gchar  **name,
+                                   const gchar  **revision)
+{
+    MmGdbusModem *skeleton;
+
+    g_object_get (self,
+                  MM_IFACE_MODEM_DBUS_SKELETON, &skeleton,
+                  NULL);
+    if (!skeleton)
+        return FALSE;
+
+    if (name)
+        *name = mm_gdbus_modem_get_carrier_configuration (skeleton);
+    if (revision)
+        *revision = mm_gdbus_modem_get_carrier_configuration_revision (skeleton);
+    g_object_unref (skeleton);
+    return TRUE;
+}
+
 /*****************************************************************************/
 
 static void
@@ -5415,6 +5543,14 @@
                                FALSE,
                                G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
 
+    g_object_interface_install_property
+        (g_iface,
+         g_param_spec_string (MM_IFACE_MODEM_CARRIER_CONFIG_MAPPING,
+                              "Carrier config mapping table",
+                              "Path to the file including the carrier mapping for the module",
+                               NULL,
+                               G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
     initialized = TRUE;
 }
 
diff --git a/src/mm-iface-modem.h b/src/mm-iface-modem.h
index 5b1c891..51cb02b 100644
--- a/src/mm-iface-modem.h
+++ b/src/mm-iface-modem.h
@@ -39,6 +39,7 @@
 #define MM_IFACE_MODEM_SIM_HOT_SWAP_SUPPORTED  "iface-modem-sim-hot-swap-supported"
 #define MM_IFACE_MODEM_SIM_HOT_SWAP_CONFIGURED "iface-modem-sim-hot-swap-configured"
 #define MM_IFACE_MODEM_PERIODIC_SIGNAL_CHECK_DISABLED "iface-modem-periodic-signal-check-disabled"
+#define MM_IFACE_MODEM_CARRIER_CONFIG_MAPPING  "iface-modem-carrier-config-mapping"
 
 typedef struct _MMIfaceModem MMIfaceModem;
 
@@ -356,6 +357,26 @@
     gboolean (*setup_sim_hot_swap_finish) (MMIfaceModem *self,
                                             GAsyncResult *res,
                                             GError **error);
+
+    /* Load carrier config */
+    void     (* load_carrier_config)        (MMIfaceModem         *self,
+                                             GAsyncReadyCallback   callback,
+                                             gpointer              user_data);
+    gboolean (* load_carrier_config_finish) (MMIfaceModem         *self,
+                                             GAsyncResult         *res,
+                                             gchar               **carrier_config_name,
+                                             gchar               **carrier_config_revision,
+                                             GError              **error);
+
+    /* Setup carrier config based on IMSI */
+    void     (* setup_carrier_config)        (MMIfaceModem         *self,
+                                              const gchar          *imsi,
+                                              const gchar          *carrier_config_mapping,
+                                              GAsyncReadyCallback   callback,
+                                              gpointer              user_data);
+    gboolean (* setup_carrier_config_finish) (MMIfaceModem         *self,
+                                              GAsyncResult         *res,
+                                              GError              **error);
 };
 
 GType mm_iface_modem_get_type (void);
@@ -381,8 +402,11 @@
 gboolean mm_iface_modem_is_4g_only (MMIfaceModem *self);
 
 /* Helpers to query properties */
-const gchar *mm_iface_modem_get_model    (MMIfaceModem *self);
-const gchar *mm_iface_modem_get_revision (MMIfaceModem *self);
+const gchar *mm_iface_modem_get_model          (MMIfaceModem  *self);
+const gchar *mm_iface_modem_get_revision       (MMIfaceModem  *self);
+gboolean     mm_iface_modem_get_carrier_config (MMIfaceModem  *self,
+                                                const gchar  **name,
+                                                const gchar  **revision);
 
 /* Initialize Modem interface (async) */
 void     mm_iface_modem_initialize        (MMIfaceModem *self,
diff --git a/src/mm-modem-helpers.c b/src/mm-modem-helpers.c
index c999637..cf008d7 100644
--- a/src/mm-modem-helpers.c
+++ b/src/mm-modem-helpers.c
@@ -3626,6 +3626,7 @@
             list = g_list_append (list, info);
             g_match_info_next (match_info, &inner_error);
         } else {
+            mm_3gpp_pdu_info_free (info);
             inner_error = g_error_new (MM_CORE_ERROR,
                                        MM_CORE_ERROR_FAILED,
                                        "Error parsing +CMGL response: '%s'",
diff --git a/src/mm-port-probe.c b/src/mm-port-probe.c
index 9913001..c02f0b2 100644
--- a/src/mm-port-probe.c
+++ b/src/mm-port-probe.c
@@ -1676,29 +1676,29 @@
 mm_port_probe_get_port_type (MMPortProbe *self)
 {
     const gchar *subsys;
-    const gchar *name;
 
     g_return_val_if_fail (MM_IS_PORT_PROBE (self), FALSE);
 
     subsys = mm_kernel_device_get_subsystem (self->priv->port);
-    name = mm_kernel_device_get_name (self->priv->port);
 
     if (g_str_equal (subsys, "net"))
         return MM_PORT_TYPE_NET;
 
-#if defined WITH_QMI
-    if (g_str_has_prefix (subsys, "usb") &&
-        g_str_has_prefix (name, "cdc-wdm") &&
-        self->priv->is_qmi)
-        return MM_PORT_TYPE_QMI;
-#endif
+    if (g_str_has_prefix (subsys, "usb")) {
+        const gchar *name;
 
-#if defined WITH_MBIM
-    if (g_str_has_prefix (subsys, "usb") &&
-        g_str_has_prefix (name, "cdc-wdm") &&
-        self->priv->is_mbim)
-        return MM_PORT_TYPE_MBIM;
+        name = mm_kernel_device_get_name (self->priv->port);
+        if (g_str_has_prefix (name, "cdc-wdm")) {
+#if defined WITH_QMI
+            if (self->priv->is_qmi)
+                return MM_PORT_TYPE_QMI;
 #endif
+#if defined WITH_MBIM
+            if (self->priv->is_mbim)
+                return MM_PORT_TYPE_MBIM;
+#endif
+        }
+    }
 
     if (self->priv->flags & MM_PORT_PROBE_QCDM &&
         self->priv->is_qcdm)
diff --git a/src/mm-shared-qmi.c b/src/mm-shared-qmi.c
index f3a1a47..1e0ae78 100644
--- a/src/mm-shared-qmi.c
+++ b/src/mm-shared-qmi.c
@@ -35,6 +35,9 @@
 /* Default session id to use in LOC operations */
 #define DEFAULT_LOC_SESSION_ID 0x10
 
+/* Default description for the default configuration of the firmware */
+#define DEFAULT_CONFIG_DESCRIPTION "default"
+
 /*****************************************************************************/
 /* Private data context */
 
@@ -48,6 +51,22 @@
 } Feature;
 
 typedef struct {
+    GArray                  *id;
+    QmiPdcConfigurationType  config_type;
+    guint32                  token;
+    guint32                  version;
+    gchar                   *description;
+    guint32                  total_size;
+} ConfigInfo;
+
+static void
+config_info_clear (ConfigInfo *config_info)
+{
+    g_array_unref (config_info->id);
+    g_free (config_info->description);
+}
+
+typedef struct {
     /* Capabilities & modes helpers */
     MMModemCapability  current_capabilities;
     GArray            *supported_radio_interfaces;
@@ -67,11 +86,18 @@
     gchar                 **loc_assistance_data_servers;
     guint32                 loc_assistance_data_max_file_size;
     guint32                 loc_assistance_data_max_part_size;
+
+    /* Carrier config helpers */
+    gboolean  config_active_default;
+    GArray   *config_list;
+    gint      config_active_i;
 } Private;
 
 static void
 private_free (Private *priv)
 {
+    if (priv->config_list)
+        g_array_unref (priv->config_list);
     if (priv->supported_bands)
         g_array_unref (priv->supported_bands);
     if (priv->supported_radio_interfaces)
@@ -102,6 +128,7 @@
 
         priv->feature_nas_technology_preference = FEATURE_UNKNOWN;
         priv->feature_nas_system_selection_preference = FEATURE_UNKNOWN;
+        priv->config_active_i = -1;
 
         /* Setup parent class' MMIfaceModemLocation */
         g_assert (MM_SHARED_QMI_GET_INTERFACE (self)->peek_parent_location_interface);
@@ -371,14 +398,10 @@
 static void
 set_current_capabilities_system_selection_preference (GTask *task)
 {
-    MMSharedQmi                                    *self;
-    Private                                        *priv;
     SetCurrentCapabilitiesContext                  *ctx;
     QmiMessageNasSetSystemSelectionPreferenceInput *input;
     QmiNasRatModePreference                         pref;
 
-    self = g_task_get_source_object (task);
-    priv = get_private (MM_SHARED_QMI (self));
     ctx  = g_task_get_task_data (task);
 
     pref = mm_modem_capability_to_qmi_rat_mode_preference (ctx->capabilities);
@@ -892,12 +915,9 @@
                                                GAsyncResult *res,
                                                GTask        *task)
 {
-    SetCurrentModesContext                     *ctx;
     QmiMessageNasSetTechnologyPreferenceOutput *output = NULL;
     GError                                     *error = NULL;
 
-    ctx = g_task_get_task_data (task);
-
     output = qmi_client_nas_set_technology_preference_finish (client, res, &error);
     if (!output ||
         (!qmi_message_nas_set_technology_preference_output_get_result (output, &error) &&
@@ -966,12 +986,9 @@
                                                      GAsyncResult *res,
                                                      GTask        *task)
 {
-    SetCurrentModesContext                          *ctx;
     QmiMessageNasSetSystemSelectionPreferenceOutput *output = NULL;
     GError                                          *error = NULL;
 
-    ctx = g_task_get_task_data (task);
-
     output = qmi_client_nas_set_system_selection_preference_finish (client, res, &error);
     if (!output || !qmi_message_nas_set_system_selection_preference_output_get_result (output, &error))
         g_task_return_error (task, error);
@@ -989,11 +1006,9 @@
     MMIfaceModem                                   *self;
     SetCurrentModesContext                         *ctx;
     QmiMessageNasSetSystemSelectionPreferenceInput *input;
-    Private                                        *priv;
     QmiNasRatModePreference                         pref;
 
     self = g_task_get_source_object (task);
-    priv = get_private (MM_SHARED_QMI (self));
     ctx  = g_task_get_task_data (task);
 
     input = qmi_message_nas_set_system_selection_preference_input_new ();
@@ -1135,15 +1150,12 @@
                                  GAsyncResult *res,
                                  GTask        *task)
 {
-    LoadCurrentModesContext                    *ctx;
     LoadCurrentModesResult                     *result = NULL;
     QmiMessageNasGetTechnologyPreferenceOutput *output = NULL;
     GError                                     *error = NULL;
     MMModemMode                                 allowed;
     QmiNasRadioTechnologyPreference             preference_mask;
 
-    ctx = g_task_get_task_data (task);
-
     output = qmi_client_nas_get_technology_preference_finish (client, res, &error);
     if (!output || !qmi_message_nas_get_technology_preference_output_get_result (output, &error)) {
         g_task_return_error (task, error);
@@ -1199,15 +1211,12 @@
                                                       GAsyncResult *res,
                                                       GTask        *task)
 {
-    LoadCurrentModesContext                         *ctx;
     LoadCurrentModesResult                          *result = NULL;
     QmiMessageNasGetSystemSelectionPreferenceOutput *output = NULL;
     GError                                          *error = NULL;
     QmiNasRatModePreference                          mode_preference_mask = 0;
     MMModemMode                                      allowed;
 
-    ctx = g_task_get_task_data (task);
-
     output = qmi_client_nas_get_system_selection_preference_finish (client, res, &error);
     if (!output || !qmi_message_nas_get_system_selection_preference_output_get_result (output, &error)) {
         g_task_return_error (task, error);
@@ -1934,6 +1943,980 @@
 }
 
 /*****************************************************************************/
+/* Setup carrier config (Modem interface) */
+
+#define SETUP_CARRIER_CONFIG_STEP_TIMEOUT_SECS 10
+#define GENERIC_CONFIG_FALLBACK "generic"
+
+typedef enum {
+    SETUP_CARRIER_CONFIG_STEP_FIRST,
+    SETUP_CARRIER_CONFIG_STEP_FIND_REQUESTED,
+    SETUP_CARRIER_CONFIG_STEP_CHECK_CHANGE_NEEDED,
+    SETUP_CARRIER_CONFIG_STEP_UPDATE_CURRENT,
+    SETUP_CARRIER_CONFIG_STEP_ACTIVATE_CURRENT,
+    SETUP_CARRIER_CONFIG_STEP_LAST,
+} SetupCarrierConfigStep;
+
+
+typedef struct {
+    SetupCarrierConfigStep  step;
+    QmiClientPdc           *client;
+    GKeyFile               *keyfile;
+    gchar                  *imsi;
+
+    gint                    config_requested_i;
+    gchar                  *config_requested;
+
+    guint                   token;
+    guint                   timeout_id;
+    gulong                  set_selected_config_indication_id;
+    gulong                  activate_config_indication_id;
+} SetupCarrierConfigContext;
+
+/* Allow to cleanup action setup right away, without being tied
+ * to the lifecycle of the GTask */
+static void
+setup_carrier_config_context_cleanup_action (SetupCarrierConfigContext *ctx)
+{
+    if (ctx->activate_config_indication_id) {
+        g_signal_handler_disconnect (ctx->client, ctx->activate_config_indication_id);
+        ctx->activate_config_indication_id = 0;
+    }
+    if (ctx->set_selected_config_indication_id) {
+        g_signal_handler_disconnect (ctx->client, ctx->set_selected_config_indication_id);
+        ctx->set_selected_config_indication_id = 0;
+    }
+    if (ctx->timeout_id) {
+        g_source_remove (ctx->timeout_id);
+        ctx->timeout_id = 0;
+    }
+}
+
+static void
+setup_carrier_config_context_free (SetupCarrierConfigContext *ctx)
+{
+    setup_carrier_config_context_cleanup_action (ctx);
+
+    g_free (ctx->config_requested);
+    g_free (ctx->imsi);
+    g_key_file_unref (ctx->keyfile);
+    g_clear_object (&ctx->client);
+    g_slice_free (SetupCarrierConfigContext, ctx);
+}
+
+gboolean
+mm_shared_qmi_setup_carrier_config_finish (MMIfaceModem  *self,
+                                           GAsyncResult  *res,
+                                           GError       **error)
+{
+    return g_task_propagate_boolean (G_TASK (res), error);
+}
+
+static void setup_carrier_config_step (GTask *task);
+
+static void
+setup_carrier_config_abort (GTask  *task,
+                            GError *error)
+{
+    SetupCarrierConfigContext *ctx;
+
+    ctx = g_task_get_task_data (task);
+    setup_carrier_config_context_cleanup_action (ctx);
+    g_task_return_error (task, error);
+    g_object_unref (task);
+}
+
+static gboolean
+setup_carrier_config_timeout_no_error (GTask *task)
+{
+    SetupCarrierConfigContext *ctx;
+
+    ctx = g_task_get_task_data (task);
+    g_assert (ctx->timeout_id);
+    ctx->timeout_id = 0;
+
+    setup_carrier_config_context_cleanup_action (ctx);
+    ctx->step++;
+    setup_carrier_config_step (task);
+
+    return G_SOURCE_REMOVE;
+}
+
+static gboolean
+setup_carrier_config_timeout (GTask *task)
+{
+    SetupCarrierConfigContext *ctx;
+
+    ctx = g_task_get_task_data (task);
+    g_assert (ctx->timeout_id);
+    ctx->timeout_id = 0;
+
+    setup_carrier_config_abort (task, g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_ABORTED,
+                                                   "Operation timed out"));
+
+    return G_SOURCE_REMOVE;
+}
+
+static void
+activate_config_indication (QmiClientPdc                         *client,
+                            QmiIndicationPdcActivateConfigOutput *output,
+                            GTask                                *task)
+{
+    SetupCarrierConfigContext *ctx;
+    GError                    *error = NULL;
+    guint16                    error_code = 0;
+
+    ctx = g_task_get_task_data (task);
+
+    if (!qmi_indication_pdc_activate_config_output_get_indication_result (output, &error_code, &error)) {
+        setup_carrier_config_abort (task, error);
+        return;
+    }
+
+    if (error_code != 0) {
+        setup_carrier_config_abort (task, g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
+                                                       "couldn't activate config: %s",
+                                                       qmi_protocol_error_get_string ((QmiProtocolError) error_code)));
+        return;
+    }
+
+    /* Go on */
+    setup_carrier_config_context_cleanup_action (ctx);
+    ctx->step++;
+    setup_carrier_config_step (task);
+}
+
+static void
+activate_config_ready (QmiClientPdc *client,
+                       GAsyncResult *res,
+                       GTask        *task)
+{
+    QmiMessagePdcActivateConfigOutput *output;
+    SetupCarrierConfigContext         *ctx;
+    GError                            *error = NULL;
+
+    ctx = g_task_get_task_data (task);
+
+    output = qmi_client_pdc_activate_config_finish (client, res, &error);
+    if (!output || !qmi_message_pdc_activate_config_output_get_result (output, &error)) {
+        setup_carrier_config_abort (task, error);
+        goto out;
+    }
+
+    /* When we activate the config, if the operation is successful, we'll just
+     * see the modem going away completely. So, do not consider an error the timeout
+     * waiting for the Activate Config indication, as that is actually a good
+     * thing.
+     */
+    ctx->timeout_id = g_timeout_add_seconds (SETUP_CARRIER_CONFIG_STEP_TIMEOUT_SECS,
+                                             (GSourceFunc) setup_carrier_config_timeout_no_error,
+                                             task);
+    ctx->activate_config_indication_id = g_signal_connect (ctx->client,
+                                                           "activate-config",
+                                                           G_CALLBACK (activate_config_indication),
+                                                           task);
+out:
+    if (output)
+        qmi_message_pdc_activate_config_output_unref (output);
+}
+
+static void
+set_selected_config_indication (QmiClientPdc                            *client,
+                                QmiIndicationPdcSetSelectedConfigOutput *output,
+                                GTask                                   *task)
+{
+    SetupCarrierConfigContext *ctx;
+    GError                    *error = NULL;
+    guint16                    error_code = 0;
+
+    ctx = g_task_get_task_data (task);
+
+    if (!qmi_indication_pdc_set_selected_config_output_get_indication_result (output, &error_code, &error)) {
+        setup_carrier_config_abort (task, error);
+        return;
+    }
+
+    if (error_code != 0) {
+        setup_carrier_config_abort (task, g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
+                                                       "couldn't set selected config: %s",
+                                                       qmi_protocol_error_get_string ((QmiProtocolError) error_code)));
+        return;
+    }
+
+    /* Go on */
+    setup_carrier_config_context_cleanup_action (ctx);
+    ctx->step++;
+    setup_carrier_config_step (task);
+}
+
+static void
+set_selected_config_ready (QmiClientPdc *client,
+                           GAsyncResult *res,
+                           GTask        *task)
+{
+    QmiMessagePdcSetSelectedConfigOutput *output;
+    SetupCarrierConfigContext            *ctx;
+    GError                               *error = NULL;
+
+    ctx = g_task_get_task_data (task);
+
+    output = qmi_client_pdc_set_selected_config_finish (client, res, &error);
+    if (!output || !qmi_message_pdc_set_selected_config_output_get_result (output, &error)) {
+        setup_carrier_config_abort (task, error);
+        goto out;
+    }
+
+    ctx->timeout_id = g_timeout_add_seconds (SETUP_CARRIER_CONFIG_STEP_TIMEOUT_SECS,
+                                             (GSourceFunc) setup_carrier_config_timeout,
+                                             task);
+    ctx->set_selected_config_indication_id = g_signal_connect (ctx->client,
+                                                               "set-selected-config",
+                                                               G_CALLBACK (set_selected_config_indication),
+                                                               task);
+out:
+    if (output)
+        qmi_message_pdc_set_selected_config_output_unref (output);
+}
+
+static gint
+select_newest_carrier_config (MMSharedQmi *self,
+                              gint         config_a_i,
+                              gint         config_b_i)
+{
+    Private    *priv;
+    ConfigInfo *config_a;
+    ConfigInfo *config_b;
+
+    priv = get_private (self);
+    config_a = &g_array_index (priv->config_list, ConfigInfo, config_a_i);
+    config_b = &g_array_index (priv->config_list, ConfigInfo, config_b_i);
+
+    g_assert (!g_strcmp0 (config_a->description, config_b->description));
+
+    if (config_a->version > config_b->version)
+        return config_a_i;
+    if (config_b->version > config_a->version)
+        return config_b_i;
+    /* if both are equal, return the first one found always */
+    return config_a_i;
+}
+
+static void
+find_requested_carrier_config (GTask *task)
+{
+    SetupCarrierConfigContext *ctx;
+    MMSharedQmi               *self;
+    Private                   *priv;
+    gchar                      mccmnc[7];
+    gchar                     *group;
+    gint                       config_fallback_i = -1;
+    gchar                     *config_fallback = NULL;
+
+    ctx  = g_task_get_task_data (task);
+    self = MM_SHARED_QMI (g_task_get_source_object (task));
+    priv = get_private (self);
+
+    /* Only one group expected per file, so get the start one */
+    group = g_key_file_get_start_group (ctx->keyfile);
+
+    /* Match generic configuration */
+    config_fallback = g_key_file_get_string (ctx->keyfile, group, GENERIC_CONFIG_FALLBACK, NULL);
+    mm_dbg ("Fallback carrier configuration %sfound in group '%s'", config_fallback ? "" : "not ", group);
+
+    /* First, try to match 6 MCCMNC digits (3-digit MNCs) */
+    strncpy (mccmnc, ctx->imsi, 6);
+    mccmnc[6] = '\0';
+    ctx->config_requested = g_key_file_get_string (ctx->keyfile, group, mccmnc, NULL);
+    if (!ctx->config_requested) {
+        /* If not found, try to match 5 MCCMNC digits (2-digit MNCs) */
+        mccmnc[5] = '\0';
+        ctx->config_requested = g_key_file_get_string (ctx->keyfile, group, mccmnc, NULL);
+    }
+    mm_dbg ("Requested carrier configuration %sfound for '%s' in group '%s': %s",
+            ctx->config_requested ? "" : "not ", mccmnc, group, ctx->config_requested ? ctx->config_requested : "n/a");
+
+    if (!ctx->config_requested && !config_fallback) {
+        setup_carrier_config_abort (task, g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_NOT_FOUND,
+                                                       "no valid configuration found in group '%s'", group));
+        goto out;
+    }
+
+    /* Now, look for the configurations among the ones available in the device */
+    if (priv->config_list) {
+        guint i;
+
+        for (i = 0; i < priv->config_list->len; i++) {
+            ConfigInfo *config;
+
+            config = &g_array_index (priv->config_list, ConfigInfo, i);
+            if (ctx->config_requested && !g_strcmp0 (ctx->config_requested, config->description)) {
+                mm_dbg ("Requested carrier configuration '%s' is available (version 0x%08x, size %u bytes)",
+                        config->description, config->version, config->total_size);
+                if (ctx->config_requested_i < 0)
+                    ctx->config_requested_i = i;
+                else
+                    ctx->config_requested_i = select_newest_carrier_config (self, ctx->config_requested_i, i);
+            }
+            if (config_fallback && !g_strcmp0 (config_fallback, config->description)) {
+                mm_dbg ("Fallback carrier configuration '%s' is available (version 0x%08x, size %u bytes)",
+                        config->description, config->version, config->total_size);
+                if (config_fallback_i < 0)
+                    config_fallback_i = i;
+                else
+                    config_fallback_i = select_newest_carrier_config (self, config_fallback_i, i);
+            }
+        }
+    }
+
+    /* Fail operation if we didn't find the one we want */
+    if ((ctx->config_requested_i < 0) && (config_fallback_i < 0)) {
+        setup_carrier_config_abort (task, g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
+                                                       "carrier configurations (requested '%s', fallback '%s') are not available",
+                                                       ctx->config_requested, config_fallback));
+        goto out;
+    }
+
+    /* If the mapping expects a given config, but the config isn't installed,
+     * we fallback to generic */
+    if (ctx->config_requested_i < 0) {
+        ConfigInfo *config;
+
+        g_assert (config_fallback_i >= 0);
+
+        config = &g_array_index (priv->config_list, ConfigInfo, config_fallback_i);
+        mm_info ("Using fallback carrier configuration '%s' (version 0x%08x, size %u bytes)",
+                        config->description, config->version, config->total_size);
+
+        g_free (ctx->config_requested);
+        ctx->config_requested = config_fallback;
+        ctx->config_requested_i = config_fallback_i;
+        config_fallback = NULL;
+    } else {
+        ConfigInfo *config;
+
+        config = &g_array_index (priv->config_list, ConfigInfo, ctx->config_requested_i);
+        mm_dbg ("Using requested carrier configuration '%s' (version 0x%08x, size %u bytes)",
+                config->description, config->version, config->total_size);
+    }
+
+    ctx->step++;
+    setup_carrier_config_step (task);
+
+out:
+    g_free (config_fallback);
+    g_free (group);
+}
+
+static void
+setup_carrier_config_step (GTask *task)
+{
+    SetupCarrierConfigContext *ctx;
+    Private                   *priv;
+
+    ctx = g_task_get_task_data (task);
+    priv = get_private (g_task_get_source_object (task));
+
+    switch (ctx->step) {
+    case SETUP_CARRIER_CONFIG_STEP_FIRST:
+        ctx->step++;
+        /* fall-through */
+
+    case SETUP_CARRIER_CONFIG_STEP_FIND_REQUESTED:
+        find_requested_carrier_config (task);
+        return;
+
+    case SETUP_CARRIER_CONFIG_STEP_CHECK_CHANGE_NEEDED:
+        g_assert (ctx->config_requested_i >= 0);
+        g_assert (priv->config_active_i >= 0 || priv->config_active_default);
+        if (ctx->config_requested_i == priv->config_active_i) {
+            mm_info ("Carrier config switching not needed: already using '%s'", ctx->config_requested);
+            ctx->step = SETUP_CARRIER_CONFIG_STEP_LAST;
+            setup_carrier_config_step (task);
+            return;
+        }
+
+        ctx->step++;
+        /* fall-through */
+
+    case SETUP_CARRIER_CONFIG_STEP_UPDATE_CURRENT: {
+        QmiMessagePdcSetSelectedConfigInput *input;
+        ConfigInfo                          *requested_config;
+        ConfigInfo                          *active_config;
+        QmiConfigTypeAndId                   type_and_id;
+
+        requested_config = &g_array_index (priv->config_list, ConfigInfo, ctx->config_requested_i);
+        active_config = (priv->config_active_default ? NULL : &g_array_index (priv->config_list, ConfigInfo, priv->config_active_i));
+        mm_warn ("Carrier config switching needed: '%s' -> '%s'",
+                 active_config ? active_config->description : DEFAULT_CONFIG_DESCRIPTION, requested_config->description);
+
+        type_and_id.config_type = requested_config->config_type;;
+        type_and_id.id = requested_config->id;
+
+        input = qmi_message_pdc_set_selected_config_input_new ();
+        qmi_message_pdc_set_selected_config_input_set_type_with_id (input, &type_and_id, NULL);
+        qmi_message_pdc_set_selected_config_input_set_token (input, ctx->token++, NULL);
+        qmi_client_pdc_set_selected_config (ctx->client,
+                                            input,
+                                            10,
+                                            NULL,
+                                            (GAsyncReadyCallback)set_selected_config_ready,
+                                            task);
+        qmi_message_pdc_set_selected_config_input_unref (input);
+        return;
+    }
+
+    case SETUP_CARRIER_CONFIG_STEP_ACTIVATE_CURRENT: {
+        QmiMessagePdcActivateConfigInput *input;
+        ConfigInfo                       *requested_config;
+
+        requested_config = &g_array_index (priv->config_list, ConfigInfo, ctx->config_requested_i);
+
+        input = qmi_message_pdc_activate_config_input_new ();
+        qmi_message_pdc_activate_config_input_set_config_type (input, requested_config->config_type, NULL);
+        qmi_message_pdc_activate_config_input_set_token (input, ctx->token++, NULL);
+        qmi_client_pdc_activate_config (ctx->client,
+                                        input,
+                                        10,
+                                        NULL,
+                                        (GAsyncReadyCallback) activate_config_ready,
+                                        task);
+        qmi_message_pdc_activate_config_input_unref (input);
+        return;
+    }
+
+    case SETUP_CARRIER_CONFIG_STEP_LAST:
+        g_task_return_boolean (task, TRUE);
+        g_object_unref (task);
+        break;
+    }
+}
+
+void
+mm_shared_qmi_setup_carrier_config (MMIfaceModem        *self,
+                                    const gchar         *imsi,
+                                    const gchar         *carrier_config_mapping,
+                                    GAsyncReadyCallback  callback,
+                                    gpointer             user_data)
+{
+    SetupCarrierConfigContext *ctx;
+    GTask                     *task;
+    QmiClient                 *client = NULL;
+    GError                    *error = NULL;
+
+    g_assert (imsi);
+    g_assert (carrier_config_mapping);
+
+    task = g_task_new (self, NULL, callback, user_data);
+    ctx = g_slice_new0 (SetupCarrierConfigContext);
+    ctx->step = SETUP_CARRIER_CONFIG_STEP_FIRST;
+    ctx->imsi = g_strdup (imsi);
+    ctx->keyfile = g_key_file_new ();
+    ctx->config_requested_i = -1;
+    g_task_set_task_data (task, ctx, (GDestroyNotify)setup_carrier_config_context_free);
+
+    /* Load mapping keyfile */
+    if (!g_key_file_load_from_file (ctx->keyfile,
+                                    carrier_config_mapping,
+                                    G_KEY_FILE_NONE,
+                                    &error)) {
+        g_task_return_error (task, error);
+        g_object_unref (task);
+        return;
+    }
+
+    /* Load PDC client */
+    client = mm_shared_qmi_peek_client (MM_SHARED_QMI (self),
+                                        QMI_SERVICE_PDC,
+                                        MM_PORT_QMI_FLAG_DEFAULT,
+                                        NULL);
+    if (!client) {
+        g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
+                                 "QMI PDC not supported");
+        g_object_unref (task);
+        return;
+    }
+    ctx->client = g_object_ref (client);
+
+    setup_carrier_config_step (task);
+}
+
+/*****************************************************************************/
+/* Load carrier config (Modem interface) */
+
+#define LOAD_CARRIER_CONFIG_STEP_TIMEOUT_SECS 5
+
+typedef enum {
+    LOAD_CARRIER_CONFIG_STEP_FIRST,
+    LOAD_CARRIER_CONFIG_STEP_LIST_CONFIGS,
+    LOAD_CARRIER_CONFIG_STEP_QUERY_CURRENT,
+    LOAD_CARRIER_CONFIG_STEP_LAST,
+} LoadCarrierConfigStep;
+
+typedef struct {
+    LoadCarrierConfigStep step;
+
+    QmiClientPdc *client;
+
+    GArray       *config_list;
+    guint         configs_loaded;
+    gboolean      config_active_default;
+    gint          config_active_i;
+
+    guint         token;
+    guint         timeout_id;
+    gulong        list_configs_indication_id;
+    gulong        get_selected_config_indication_id;
+    gulong        get_config_info_indication_id;
+} LoadCarrierConfigContext;
+
+/* Allow to cleanup action load right away, without being tied
+ * to the lifecycle of the GTask */
+static void
+load_carrier_config_context_cleanup_action (LoadCarrierConfigContext *ctx)
+{
+    if (ctx->get_selected_config_indication_id) {
+        g_signal_handler_disconnect (ctx->client, ctx->get_selected_config_indication_id);
+        ctx->get_selected_config_indication_id = 0;
+    }
+    if (ctx->get_config_info_indication_id) {
+        g_signal_handler_disconnect (ctx->client, ctx->get_config_info_indication_id);
+        ctx->get_config_info_indication_id = 0;
+    }
+    if (ctx->list_configs_indication_id) {
+        g_signal_handler_disconnect (ctx->client, ctx->list_configs_indication_id);
+        ctx->list_configs_indication_id = 0;
+    }
+    if (ctx->timeout_id) {
+        g_source_remove (ctx->timeout_id);
+        ctx->timeout_id = 0;
+    }
+}
+
+static void
+load_carrier_config_context_free (LoadCarrierConfigContext *ctx)
+{
+    load_carrier_config_context_cleanup_action (ctx);
+
+    if (ctx->config_list)
+        g_array_unref (ctx->config_list);
+    g_clear_object (&ctx->client);
+    g_slice_free (LoadCarrierConfigContext, ctx);
+}
+
+gboolean
+mm_shared_qmi_load_carrier_config_finish (MMIfaceModem  *self,
+                                          GAsyncResult  *res,
+                                          gchar        **carrier_config_name,
+                                          gchar        **carrier_config_revision,
+                                          GError       **error)
+{
+    Private *priv;
+
+    if (!g_task_propagate_boolean (G_TASK (res), error))
+        return FALSE;
+
+    priv = get_private (MM_SHARED_QMI (self));
+    g_assert (priv->config_active_i >= 0 || priv->config_active_default);
+
+    if (priv->config_active_i >= 0) {
+        ConfigInfo *config;
+
+        config = &g_array_index (priv->config_list, ConfigInfo, priv->config_active_i);
+        *carrier_config_name = g_strdup (config->description);
+        *carrier_config_revision = g_strdup_printf ("%08X", config->version);
+    } else if (priv->config_active_default) {
+        *carrier_config_name = g_strdup (DEFAULT_CONFIG_DESCRIPTION);
+        *carrier_config_revision = NULL;
+    } else
+        g_assert_not_reached ();
+
+    return TRUE;
+}
+
+static void load_carrier_config_step (GTask *task);
+
+static void
+load_carrier_config_abort (GTask  *task,
+                           GError *error)
+{
+    LoadCarrierConfigContext *ctx;
+
+    ctx = g_task_get_task_data (task);
+    load_carrier_config_context_cleanup_action (ctx);
+    g_task_return_error (task, error);
+    g_object_unref (task);
+}
+
+static gboolean
+load_carrier_config_timeout (GTask *task)
+{
+    LoadCarrierConfigContext *ctx;
+
+    ctx = g_task_get_task_data (task);
+    g_assert (ctx->timeout_id);
+    ctx->timeout_id = 0;
+
+    load_carrier_config_abort (task, g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_ABORTED,
+                                                  "Operation timed out"));
+
+    return G_SOURCE_REMOVE;
+}
+
+static void
+get_selected_config_indication (QmiClientPdc                            *client,
+                                QmiIndicationPdcGetSelectedConfigOutput *output,
+                                GTask                                   *task)
+{
+    LoadCarrierConfigContext *ctx;
+    GArray                   *active_id = NULL;
+    GError                   *error = NULL;
+    guint16                   error_code = 0;
+    guint                     i;
+
+    ctx = g_task_get_task_data (task);
+
+    if (!qmi_indication_pdc_get_selected_config_output_get_indication_result (output, &error_code, &error)) {
+        load_carrier_config_abort (task, error);
+        return;
+    }
+
+    if (error_code != 0 &&
+        error_code != QMI_PROTOCOL_ERROR_NOT_PROVISIONED) { /* No configs active */
+        load_carrier_config_abort (task, g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
+                                                      "couldn't get selected config: %s",
+                                                      qmi_protocol_error_get_string ((QmiProtocolError) error_code)));
+        return;
+    }
+
+    qmi_indication_pdc_get_selected_config_output_get_active_id (output, &active_id, NULL);
+    if (!active_id) {
+        mm_dbg ("no carrier config currently selected (default in use)");
+        ctx->config_active_default = TRUE;
+        goto next;
+    }
+
+    g_assert (ctx->config_list);
+    g_assert (ctx->config_list->len);
+
+    for (i = 0; i < ctx->config_list->len; i++) {
+        ConfigInfo *config;
+
+        config = &g_array_index (ctx->config_list, ConfigInfo, i);
+        if ((config->id->len == active_id->len) &&
+            !memcmp (config->id->data, active_id->data, active_id->len)) {
+            ctx->config_active_i = i;
+            break;
+        }
+    }
+
+    if (i == ctx->config_list->len) {
+        load_carrier_config_abort (task, g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
+                                                      "couldn't find currently selected config"));
+        return;
+    }
+
+ next:
+
+    /* Go on */
+    load_carrier_config_context_cleanup_action (ctx);
+    ctx->step++;
+    load_carrier_config_step (task);
+}
+
+static void
+get_selected_config_ready (QmiClientPdc *client,
+                           GAsyncResult *res,
+                           GTask        *task)
+{
+    QmiMessagePdcGetSelectedConfigOutput *output;
+    LoadCarrierConfigContext             *ctx;
+    GError                               *error = NULL;
+
+    ctx = g_task_get_task_data (task);
+
+    output = qmi_client_pdc_get_selected_config_finish (client, res, &error);
+    if (!output || !qmi_message_pdc_get_selected_config_output_get_result (output, &error)) {
+        load_carrier_config_abort (task, error);
+        goto out;
+    }
+
+    ctx->timeout_id = g_timeout_add_seconds (LOAD_CARRIER_CONFIG_STEP_TIMEOUT_SECS,
+                                             (GSourceFunc) load_carrier_config_timeout,
+                                             task);
+    ctx->get_selected_config_indication_id = g_signal_connect (ctx->client,
+                                                               "get-selected-config",
+                                                               G_CALLBACK (get_selected_config_indication),
+                                                               task);
+
+out:
+    if (output)
+        qmi_message_pdc_get_selected_config_output_unref (output);
+}
+
+static void
+get_config_info_indication (QmiClientPdc                        *client,
+                            QmiIndicationPdcGetConfigInfoOutput *output,
+                            GTask                               *task)
+{
+    LoadCarrierConfigContext *ctx;
+    GError                   *error = NULL;
+    ConfigInfo               *current_config = NULL;
+    guint32                   token;
+    const gchar              *description;
+    int                       i;
+    guint16                   error_code = 0;
+
+    ctx = g_task_get_task_data (task);
+
+    if (!qmi_indication_pdc_get_config_info_output_get_indication_result (output, &error_code, &error)) {
+        load_carrier_config_abort (task, error);
+        return;
+    }
+
+    if (error_code != 0) {
+        load_carrier_config_abort (task, g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
+                                                      "couldn't get config info: %s",
+                                                      qmi_protocol_error_get_string ((QmiProtocolError) error_code)));
+        return;
+    }
+
+    if (!qmi_indication_pdc_get_config_info_output_get_token (output, &token, &error)) {
+        load_carrier_config_abort (task, error);
+        return;
+    }
+
+    /* Look for the current config in the list, match by token */
+    for (i = 0; i < ctx->config_list->len; i++) {
+        current_config = &g_array_index (ctx->config_list, ConfigInfo, i);
+        if (current_config->token == token)
+            break;
+    }
+
+    /* Ignore if not found in the list */
+    if (i == ctx->config_list->len)
+        return;
+
+    /* Ignore if already set */
+    if (current_config->description)
+        return;
+
+    /* Store total size, version and description of the current config */
+    if (!qmi_indication_pdc_get_config_info_output_get_total_size  (output, &current_config->total_size, &error) ||
+        !qmi_indication_pdc_get_config_info_output_get_version     (output, &current_config->version,    &error) ||
+        !qmi_indication_pdc_get_config_info_output_get_description (output, &description,                &error)) {
+        load_carrier_config_abort (task, error);
+        return;
+    }
+
+    current_config->description = g_strdup (description);
+    ctx->configs_loaded++;
+
+    /* If not all loaded, wait for more */
+    if (ctx->configs_loaded < ctx->config_list->len)
+        return;
+
+    /* Go on */
+    load_carrier_config_context_cleanup_action (ctx);
+    ctx->step++;
+    load_carrier_config_step (task);
+}
+
+static void
+list_configs_indication (QmiClientPdc                      *client,
+                         QmiIndicationPdcListConfigsOutput *output,
+                         GTask                             *task)
+{
+    LoadCarrierConfigContext *ctx;
+    GError                   *error = NULL;
+    GArray                   *configs = NULL;
+    int                       i;
+    guint16                   error_code = 0;
+
+    ctx = g_task_get_task_data (task);
+
+    if (!qmi_indication_pdc_list_configs_output_get_indication_result (output, &error_code, &error)) {
+        load_carrier_config_abort (task, error);
+        return;
+    }
+
+    if (error_code != 0) {
+        load_carrier_config_abort (task, g_error_new (MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
+                                                      "couldn't list configs: %s",
+                                                      qmi_protocol_error_get_string ((QmiProtocolError) error_code)));
+        return;
+    }
+
+    if (!qmi_indication_pdc_list_configs_output_get_configs (output, &configs, &error)) {
+        load_carrier_config_abort (task, error);
+        return;
+    }
+
+    /* If no configs are installed, the module is running with the default one */
+    if (!configs || !configs->len) {
+        ctx->config_active_default = TRUE;
+        ctx->step = LOAD_CARRIER_CONFIG_STEP_LAST;
+        load_carrier_config_step (task);
+        return;
+    }
+
+    /* Preallocate config list and request details for each */
+    mm_dbg ("found %u carrier configurations...", configs->len);
+    ctx->config_list = g_array_sized_new (FALSE, TRUE, sizeof (ConfigInfo), configs->len);
+    g_array_set_size (ctx->config_list, configs->len);
+    g_array_set_clear_func (ctx->config_list, (GDestroyNotify) config_info_clear);
+
+    ctx->get_config_info_indication_id = g_signal_connect (ctx->client,
+                                                           "get-config-info",
+                                                           G_CALLBACK (get_config_info_indication),
+                                                           task);
+
+    for (i = 0; i < configs->len; i++) {
+        ConfigInfo                                      *current_info;
+        QmiIndicationPdcListConfigsOutputConfigsElement *element;
+        QmiConfigTypeAndId                               type_with_id;
+        QmiMessagePdcGetConfigInfoInput                 *input;
+
+        element = &g_array_index (configs, QmiIndicationPdcListConfigsOutputConfigsElement, i);
+
+        current_info              = &g_array_index (ctx->config_list, ConfigInfo, i);
+        current_info->token       = ctx->token++;
+        current_info->id          = g_array_ref (element->id);
+        current_info->config_type = element->config_type;
+
+        input = qmi_message_pdc_get_config_info_input_new ();
+        type_with_id.config_type = element->config_type;
+        type_with_id.id = current_info->id;
+        qmi_message_pdc_get_config_info_input_set_type_with_id (input, &type_with_id, NULL);
+        qmi_message_pdc_get_config_info_input_set_token (input, current_info->token, NULL);
+        qmi_client_pdc_get_config_info (ctx->client, input, 10, NULL, NULL, NULL); /* ignore response! */
+        qmi_message_pdc_get_config_info_input_unref (input);
+    }
+}
+
+static void
+list_configs_ready (QmiClientPdc *client,
+                    GAsyncResult *res,
+                    GTask        *task)
+{
+    QmiMessagePdcListConfigsOutput *output;
+    LoadCarrierConfigContext       *ctx;
+    GError                         *error = NULL;
+
+    ctx = g_task_get_task_data (task);
+
+    output = qmi_client_pdc_list_configs_finish (client, res, &error);
+    if (!output || !qmi_message_pdc_list_configs_output_get_result (output, &error)) {
+        load_carrier_config_abort (task, error);
+        goto out;
+    }
+
+    ctx->timeout_id = g_timeout_add_seconds (LOAD_CARRIER_CONFIG_STEP_TIMEOUT_SECS,
+                                             (GSourceFunc) load_carrier_config_timeout,
+                                             task);
+    ctx->list_configs_indication_id = g_signal_connect (ctx->client,
+                                                        "list-configs",
+                                                        G_CALLBACK (list_configs_indication),
+                                                        task);
+out:
+    if (output)
+        qmi_message_pdc_list_configs_output_unref (output);
+}
+
+static void
+load_carrier_config_step (GTask *task)
+{
+    LoadCarrierConfigContext *ctx;
+    Private                  *priv;
+
+    ctx  = g_task_get_task_data (task);
+    priv = get_private (g_task_get_source_object (task));
+
+    switch (ctx->step) {
+    case LOAD_CARRIER_CONFIG_STEP_FIRST:
+        ctx->step++;
+        /* fall-through */
+
+    case LOAD_CARRIER_CONFIG_STEP_LIST_CONFIGS: {
+        QmiMessagePdcListConfigsInput *input;
+
+        input = qmi_message_pdc_list_configs_input_new ();
+        qmi_message_pdc_list_configs_input_set_config_type (input, QMI_PDC_CONFIGURATION_TYPE_SOFTWARE, NULL);
+        qmi_message_pdc_list_configs_input_set_token (input, ctx->token++, NULL);
+        qmi_client_pdc_list_configs (ctx->client,
+                                     input,
+                                     5,
+                                     NULL,
+                                     (GAsyncReadyCallback)list_configs_ready,
+                                     task);
+        qmi_message_pdc_list_configs_input_unref (input);
+        return;
+    }
+
+    case LOAD_CARRIER_CONFIG_STEP_QUERY_CURRENT: {
+        QmiMessagePdcGetSelectedConfigInput *input;
+
+        input = qmi_message_pdc_get_selected_config_input_new ();
+        qmi_message_pdc_get_selected_config_input_set_config_type (input, QMI_PDC_CONFIGURATION_TYPE_SOFTWARE, NULL);
+        qmi_message_pdc_get_selected_config_input_set_token (input, ctx->token++, NULL);
+        qmi_client_pdc_get_selected_config (ctx->client,
+                                            input,
+                                            5,
+                                            NULL,
+                                            (GAsyncReadyCallback)get_selected_config_ready,
+                                            task);
+        qmi_message_pdc_get_selected_config_input_unref (input);
+        return;
+    }
+
+    case LOAD_CARRIER_CONFIG_STEP_LAST:
+        /* We will now store the loaded information so that we can later on use it
+         * if needed during the automatic carrier config switching operation */
+        g_assert (!priv->config_list);
+        g_assert (priv->config_active_i < 0 && !priv->config_active_default);
+        g_assert (ctx->config_active_i >= 0 || ctx->config_active_default);
+        priv->config_list = g_array_ref (ctx->config_list);
+        priv->config_active_i = ctx->config_active_i;
+        priv->config_active_default = ctx->config_active_default;
+
+        g_task_return_boolean (task, TRUE);
+        g_object_unref (task);
+        break;
+    }
+}
+
+void
+mm_shared_qmi_load_carrier_config (MMIfaceModem        *self,
+                                   GAsyncReadyCallback  callback,
+                                   gpointer             user_data)
+{
+    LoadCarrierConfigContext *ctx;
+    GTask                    *task;
+    QmiClient                *client = NULL;
+
+
+    task = g_task_new (self, NULL, callback, user_data);
+    ctx = g_slice_new0 (LoadCarrierConfigContext);
+    ctx->step = LOAD_CARRIER_CONFIG_STEP_FIRST;
+    ctx->config_active_i = -1;
+    g_task_set_task_data (task, ctx, (GDestroyNotify)load_carrier_config_context_free);
+
+    /* Load PDC client */
+    client = mm_shared_qmi_peek_client (MM_SHARED_QMI (self),
+                                        QMI_SERVICE_PDC,
+                                        MM_PORT_QMI_FLAG_DEFAULT,
+                                        NULL);
+    if (!client) {
+        g_task_return_new_error (task, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
+                                 "QMI PDC not supported");
+        g_object_unref (task);
+        return;
+    }
+    ctx->client = g_object_ref (client);
+
+    load_carrier_config_step (task);
+}
+
+/*****************************************************************************/
 /* Location: Set SUPL server */
 
 typedef struct {
@@ -3067,7 +4050,6 @@
                                         GAsyncResult *res,
                                         GTask        *task)
 {
-    MMSharedQmi                                  *self;
     SetGpsOperationModeContext                   *ctx;
     QmiMessagePdsSetDefaultTrackingSessionInput  *input;
     QmiMessagePdsGetDefaultTrackingSessionOutput *output;
@@ -3093,7 +4075,6 @@
         return;
     }
 
-    self = g_task_get_source_object (task);
     ctx  = g_task_get_task_data (task);
 
     qmi_message_pds_get_default_tracking_session_output_get_info (
diff --git a/src/mm-shared-qmi.h b/src/mm-shared-qmi.h
index e728e60..093896e 100644
--- a/src/mm-shared-qmi.h
+++ b/src/mm-shared-qmi.h
@@ -147,6 +147,22 @@
 gboolean           mm_shared_qmi_factory_reset_finish               (MMIfaceModem         *self,
                                                                      GAsyncResult         *res,
                                                                      GError              **error);
+void               mm_shared_qmi_load_carrier_config                (MMIfaceModem         *self,
+                                                                     GAsyncReadyCallback   callback,
+                                                                     gpointer              user_data);
+gboolean           mm_shared_qmi_load_carrier_config_finish         (MMIfaceModem         *self,
+                                                                     GAsyncResult         *res,
+                                                                     gchar               **carrier_config_name,
+                                                                     gchar               **carrier_config_revision,
+                                                                     GError              **error);
+void               mm_shared_qmi_setup_carrier_config               (MMIfaceModem         *self,
+                                                                     const gchar          *imsi,
+                                                                     const gchar          *carrier_config_mapping,
+                                                                     GAsyncReadyCallback   callback,
+                                                                     gpointer              user_data);
+gboolean           mm_shared_qmi_setup_carrier_config_finish        (MMIfaceModem         *self,
+                                                                     GAsyncResult         *res,
+                                                                     GError              **error);
 
 /* Shared QMI location support */
 
diff --git a/uml290/Makefile.am b/uml290/Makefile.am
deleted file mode 100644
index b4fc8b5..0000000
--- a/uml290/Makefile.am
+++ /dev/null
@@ -1,10 +0,0 @@
-noinst_PROGRAMS = uml290mode
-
-uml290mode_CPPFLAGS = -I$(top_srcdir)
-
-uml290mode_LDADD = \
-	$(top_builddir)/libqcdm/src/libqcdm.la \
-	$(top_builddir)/libwmc/src/libwmc.la
-
-uml290mode_SOURCES = uml290mode.c
-
diff --git a/uml290/uml290mode.c b/uml290/uml290mode.c
deleted file mode 100644
index bf5a203..0000000
--- a/uml290/uml290mode.c
+++ /dev/null
@@ -1,721 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
-/* This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Copyright (C) 2012 Red Hat, Inc.
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <sys/ioctl.h>
-#include <fcntl.h>
-#include <termios.h>
-#include <assert.h>
-#include <unistd.h>
-
-#include "libwmc/src/utils.h"
-#include "libwmc/src/errors.h"
-#include "libwmc/src/commands.h"
-#include "libwmc/src/com.h"
-
-#include "libqcdm/src/utils.h"
-#include "libqcdm/src/errors.h"
-#include "libqcdm/src/commands.h"
-#include "libqcdm/src/com.h"
-
-static int debug = 0;
-
-static void
-print_buf (const char *detail, const char *buf, size_t len)
-{
-	int i = 0, z;
-	wmcbool newline = FALSE;
-	char tmp[500];
-	uint32_t flen;
-
-	flen = snprintf (tmp, sizeof (tmp) - 1, "%s (%zu)  ", detail, len);
-	fprintf (stdout, "%s", tmp);
-	for (i = 0; i < len; i++) {
-		fprintf (stdout, "%02x ", buf[i] & 0xFF);
-		if (((i + 1) % 16) == 0) {
-			fprintf (stdout, "\n");
-			z = flen;
-			while (z--)
-				fprintf (stdout, " ");
-			newline = TRUE;
-		} else
-			newline = FALSE;
-	}
-
-	if (!newline)
-		fprintf (stdout, "\n");
-}
-
-static int
-com_setup (const char *port)
-{
-	int ret, fd;
-
-	errno = 0;
-	fd = open (port, O_RDWR | O_EXCL | O_NONBLOCK | O_NOCTTY);
-	if (fd < 0) {
-		fprintf (stderr, "E: failed to open port %s\n", port);
-		return -1;
-	}
-
-	ret = ioctl (fd, TIOCEXCL);
-	if (ret) {
-		fprintf (stderr, "E: failed to lock port %s\n", port);
-		close (fd);
-		return -1;
-	}
-
-	return fd;
-}
-
-/******************************************************************/
-
-static wmcbool
-wmc_send (int fd, char *inbuf, size_t inbuf_len, size_t cmd_len)
-{
-	int status;
-	int eagain_count = 1000;
-	size_t i = 0, sendlen;
-	char sendbuf[600];
-
-	if (debug)
-		print_buf ("\nWMC:RAW>>>", inbuf, cmd_len);
-
-	/* Encapsulate the data for the device */
-	sendlen = wmc_encapsulate (inbuf, cmd_len, inbuf_len, sendbuf, sizeof (sendbuf), TRUE);
-	if (sendlen <= 0) {
-		fprintf (stderr, "E: failed to encapsulate WMC command\n");
-		return FALSE;
-	}
-
-	if (debug)
-		print_buf ("WMC:ENC>>>", sendbuf, sendlen);
-
-	while (i < sendlen) {
-		errno = 0;
-		status = write (fd, &sendbuf[i], 1);
-		if (status < 0) {
-			if (errno == EAGAIN) {
-				eagain_count--;
-				if (eagain_count <= 0)
-					return FALSE;
-			} else
-				assert (errno == 0);
-		} else
-			i++;
-
-		usleep (1000);
-	}
-
-	return TRUE;
-}
-
-static size_t
-wmc_wait_reply (int fd, char *buf, size_t len)
-{
-	fd_set in;
-	int result;
-	struct timeval timeout = { 1, 0 };
-	char readbuf[2048];
-	ssize_t bytes_read;
-	int total = 0, retries = 0;
-	size_t decap_len = 0;
-
-	FD_ZERO (&in);
-	FD_SET (fd, &in);
-	result = select (fd + 1, &in, NULL, NULL, &timeout);
-	if (result != 1 || !FD_ISSET (fd, &in))
-		return 0;
-
-	do {
-		errno = 0;
-		bytes_read = read (fd, &readbuf[total], 1);
-		if ((bytes_read == 0) || (errno == EAGAIN)) {
-			/* Haven't gotten the async control char yet */
-			if (retries > 20)
-				return 0; /* 2 seconds, give up */
-
-			/* Otherwise wait a bit and try again */
-			usleep (100000);
-			retries++;
-			continue;
-		} else if (bytes_read == 1) {
-			wmcbool more = FALSE, success;
-			size_t used = 0;
-
-			total++;
-			decap_len = 0;
-			success = wmc_decapsulate (readbuf, total, buf, len, &decap_len, &used, &more, TRUE);
-
-			if (success && !more && debug)
-				print_buf ("WMC:RAW<<<", readbuf, total);
-
-			/* Discard used data */
-			if (used > 0) {
-				total -= used;
-				memmove (readbuf, &readbuf[used], total);
-			}
-
-			if (success && !more) {
-				/* Success; we have a packet */
-				break;
-			}
-		} else {
-			/* Some error occurred */
-			return 0;
-		}
-	} while (total < sizeof (readbuf));
-
-	if (debug)
-		print_buf ("WMC:DEC<<<", buf, decap_len);
-
-	return decap_len;
-}
-
-static int
-wmc_set_global_mode (const char *port, uint8_t mode)
-{
-	int fd, err;
-	char buf[1024];
-	size_t len;
-	WmcResult *result;
-	size_t reply_len;
-
-	fd = com_setup (port);
-	if (fd < 0)
-		return -1;
-
-	err = wmc_port_setup (fd);
-	if (err) {
-		fprintf (stderr, "E: failed to set up WMC port %s: %d\n", port, err);
-		goto error;
-	}
-
-	len = wmc_cmd_set_global_mode_new (buf, sizeof (buf), mode);
-	assert (len);
-
-	/* Send the command */
-	if (!wmc_send (fd, buf, sizeof (buf), len)) {
-		fprintf (stderr, "E: failed to send WMC global mode command\n");
-		goto error;
-	}
-
-	reply_len = wmc_wait_reply (fd, buf, sizeof (buf));
-	if (!reply_len) {
-		fprintf (stderr, "E: failed to receive global mode command reply\n");
-		goto error;
-	}
-
-	/* Parse the response into a result structure */
-	result = wmc_cmd_set_global_mode_result (buf, reply_len);
-	if (!result) {
-		fprintf (stderr, "E: failed to parse global mode command reply\n");
-		goto error;
-	}
-	wmc_result_unref (result);
-
-	close (fd);
-	return 0;
-
-error:
-	close (fd);
-	return -1;
-}
-
-static const char *
-wmc_get_global_mode (const char *port)
-{
-	int fd, err;
-	char buf[1024];
-	size_t len;
-	WmcResult *result;
-	size_t reply_len;
-	uint8_t mode = 0;
-	const char *smode = NULL;
-
-	fd = com_setup (port);
-	if (fd < 0)
-		return NULL;
-
-	err = wmc_port_setup (fd);
-	if (err) {
-		fprintf (stderr, "E: failed to set up WMC port %s: %d\n", port, err);
-		goto error;
-	}
-
-	len = wmc_cmd_get_global_mode_new (buf, sizeof (buf));
-	assert (len);
-
-	/* Send the command */
-	if (!wmc_send (fd, buf, sizeof (buf), len)) {
-		fprintf (stderr, "E: failed to send WMC global mode command\n");
-		goto error;
-	}
-
-	reply_len = wmc_wait_reply (fd, buf, sizeof (buf));
-	if (!reply_len) {
-		fprintf (stderr, "E: failed to receive global mode command reply\n");
-		goto error;
-	}
-
-	/* Parse the response into a result structure */
-	result = wmc_cmd_get_global_mode_result (buf, reply_len);
-	if (!result) {
-		fprintf (stderr, "E: failed to parse global mode command reply\n");
-		goto error;
-	}
-	wmc_result_unref (result);
-
-    wmc_result_get_u8 (result, WMC_CMD_GET_GLOBAL_MODE_ITEM_MODE, &mode);
-    switch (mode) {
-    case WMC_NETWORK_MODE_AUTO_CDMA:
-        smode = "CDMA/EVDO";
-        break;
-    case WMC_NETWORK_MODE_CDMA_ONLY:
-        smode = "CDMA only";
-        break;
-    case WMC_NETWORK_MODE_EVDO_ONLY:
-        smode = "EVDO only";
-        break;
-    case WMC_NETWORK_MODE_AUTO_GSM:
-        smode = "GSM/UMTS";
-        break;
-    case WMC_NETWORK_MODE_GPRS_ONLY:
-        smode = "GSM/GPRS/EDGE only";
-        break;
-    case WMC_NETWORK_MODE_UMTS_ONLY:
-        smode = "UMTS/HSPA only";
-        break;
-    case WMC_NETWORK_MODE_AUTO:
-        smode = "Auto";
-        break;
-    case WMC_NETWORK_MODE_LTE_ONLY:
-        smode = "LTE only";
-        break;
-    default:
-		break;
-    }
-
-	close (fd);
-	return smode;
-
-error:
-	close (fd);
-	return NULL;
-}
-
-/******************************************************************/
-
-static qcdmbool
-qcdm_send (int fd, char *buf, size_t len)
-{
-	int status;
-	int eagain_count = 1000;
-	size_t i = 0;
-
-	if (debug)
-		print_buf ("DM:ENC>>>", buf, len);
-
-	while (i < len) {
-		errno = 0;
-		status = write (fd, &buf[i], 1);
-		if (status < 0) {
-			if (errno == EAGAIN) {
-				eagain_count--;
-				if (eagain_count <= 0)
-					return FALSE;
-			} else
-				assert (errno == 0);
-		} else
-			i++;
-
-		usleep (1000);
-	}
-
-	return TRUE;
-}
-
-static size_t
-qcdm_wait_reply (int fd, char *buf, size_t len)
-{
-	fd_set in;
-	int result;
-	struct timeval timeout = { 1, 0 };
-	char readbuf[1024];
-	ssize_t bytes_read;
-	int total = 0, retries = 0;
-	size_t decap_len = 0;
-
-	FD_ZERO (&in);
-	FD_SET (fd, &in);
-	result = select (fd + 1, &in, NULL, NULL, &timeout);
-	if (result != 1 || !FD_ISSET (fd, &in))
-		return 0;
-
-	do {
-		errno = 0;
-		bytes_read = read (fd, &readbuf[total], 1);
-		if ((bytes_read == 0) || (errno == EAGAIN)) {
-			/* Haven't gotten the async control char yet */
-			if (retries > 20)
-				return 0; /* 2 seconds, give up */
-
-			/* Otherwise wait a bit and try again */
-			usleep (100000);
-			retries++;
-			continue;
-		} else if (bytes_read == 1) {
-			qcdmbool more = FALSE;
-			qcdmbool success;
-			size_t used = 0;
-
-			total++;
-			decap_len = 0;
-			success = dm_decapsulate_buffer (readbuf, total, buf, len, &decap_len, &used, &more);
-
-			/* Discard used data */
-			if (used > 0) {
-				total -= used;
-				memmove (readbuf, &readbuf[used], total);
-			}
-
-			if (success && !more) {
-				/* Success; we have a packet */
-				break;
-			}
-		} else {
-			/* Some error occurred */
-			return 0;
-		}
-	} while (total < sizeof (readbuf));
-
-	if (debug)
-		print_buf ("QCDM:DEC<<", buf, decap_len);
-
-	return decap_len;
-}
-
-static int
-qcdm_set_hdr_pref (const char *port, uint8_t hdrpref)
-{
-	int fd, err;
-	char buf[512];
-	size_t len;
-	QcdmResult *result;
-	size_t reply_len;
-
-	fd = com_setup (port);
-	if (fd < 0)
-		return -1;
-
-	err = qcdm_port_setup (fd);
-	if (err != QCDM_SUCCESS) {
-		fprintf (stderr, "E: failed to set up DM port %s: %d\n", port, err);
-		goto error;
-	}
-
-	len = qcdm_cmd_nv_set_hdr_rev_pref_new (buf, sizeof (buf), hdrpref);
-	assert (len);
-
-	/* Send the command */
-	if (!qcdm_send (fd, buf, len)) {
-		fprintf (stderr, "E: failed to send QCDM HDR pref command\n");
-		goto error;
-	}
-
-	reply_len = qcdm_wait_reply (fd, buf, sizeof (buf));
-	if (!reply_len) {
-		fprintf (stderr, "E: failed to receive HDR pref command reply\n");
-		goto error;
-	}
-
-	/* Parse the response into a result structure */
-	err = QCDM_SUCCESS;
-	result = qcdm_cmd_nv_set_hdr_rev_pref_result (buf, reply_len, &err);
-	if (!result) {
-		fprintf (stderr, "E: failed to parse HDR pref command reply: %d\n", err);
-		goto error;
-	}
-
-	qcdm_result_unref (result);
-	close (fd);
-	return 0;
-
-error:
-	close (fd);
-	return -1;
-}
-
-static const char *
-qcdm_get_hdr_pref (const char *port)
-{
-	int fd, err;
-	char buf[512];
-	size_t len;
-	QcdmResult *result = NULL;
-	size_t reply_len;
-    uint8_t pref;
-    const char *spref = NULL;
-
-	fd = com_setup (port);
-	if (fd < 0)
-		return NULL;
-
-	err = qcdm_port_setup (fd);
-	if (err != QCDM_SUCCESS) {
-		fprintf (stderr, "E: failed to set up DM port %s: %d\n", port, err);
-		goto error;
-	}
-
-    len = qcdm_cmd_nv_get_hdr_rev_pref_new (buf, sizeof (buf));
-    assert (len > 0);
-
-	/* Send the command */
-	if (!qcdm_send (fd, buf, len)) {
-		fprintf (stderr, "E: failed to send QCDM HDR pref command\n");
-		goto error;
-	}
-
-	reply_len = qcdm_wait_reply (fd, buf, sizeof (buf));
-	if (!reply_len) {
-		fprintf (stderr, "E: failed to receive HDR pref command reply\n");
-		goto error;
-	}
-
-	/* Parse the response into a result structure */
-	err = QCDM_SUCCESS;
-	result = qcdm_cmd_nv_get_hdr_rev_pref_result (buf, reply_len, &err);
-	if (!result) {
-		fprintf (stderr, "E: failed to parse HDR pref command reply: %d\n", err);
-		goto error;
-	}
-
-    err = qcdm_result_get_u8 (result, QCDM_CMD_NV_GET_HDR_REV_PREF_ITEM_REV_PREF, &pref);
-	if (err != QCDM_SUCCESS)
-		goto error;
-
-    switch (pref) {
-    case QCDM_CMD_NV_HDR_REV_PREF_ITEM_REV_PREF_0:
-        spref = "rev0";
-        break;
-    case QCDM_CMD_NV_HDR_REV_PREF_ITEM_REV_PREF_A:
-        spref = "revA";
-        break;
-    case QCDM_CMD_NV_HDR_REV_PREF_ITEM_REV_PREF_EHRPD:
-        spref = "eHRPD";
-        break;
-    default:
-        break;
-    }
-
-	qcdm_result_unref (result);
-	close (fd);
-	return spref;
-
-error:
-	if (result)
-		qcdm_result_unref (result);
-	close (fd);
-	return NULL;
-}
-
-static int
-qcdm_set_mode (const char *port, uint8_t mode)
-{
-	int fd, err;
-	char buf[512];
-	size_t len;
-	QcdmResult *result;
-	size_t reply_len;
-
-	fd = com_setup (port);
-	if (fd < 0)
-		return -1;
-
-	err = qcdm_port_setup (fd);
-	if (err != QCDM_SUCCESS) {
-		fprintf (stderr, "E: failed to set up DM port %s: %d\n", port, err);
-		goto error;
-	}
-
-	len = qcdm_cmd_control_new (buf, sizeof (buf), mode);
-	assert (len);
-
-	/* Send the command */
-	if (!qcdm_send (fd, buf, len)) {
-		fprintf (stderr, "E: failed to send QCDM Control command\n");
-		goto error;
-	}
-
-	reply_len = qcdm_wait_reply (fd, buf, sizeof (buf));
-	if (!reply_len) {
-		fprintf (stderr, "E: failed to receive Control command reply\n");
-		goto error;
-	}
-
-	/* Parse the response into a result structure */
-	err = QCDM_SUCCESS;
-	result = qcdm_cmd_control_result (buf, reply_len, &err);
-	if (!result) {
-		fprintf (stderr, "E: failed to parse Control command reply: %d\n", err);
-		goto error;
-	}
-
-	qcdm_result_unref (result);
-	close (fd);
-	return 0;
-
-error:
-	close (fd);
-	return -1;
-}
-
-/******************************************************************/
-
-static void
-usage (const char *prog)
-{
-	fprintf (stderr, "Usage: %s <WMC port> <DM port> [<mode>] [--debug]\n", prog);
-	fprintf (stderr, "         <mode> = lte, auto-cdma, auto, cdma, evdo, auto-gsm, gprs, umts\n");
-	fprintf (stderr, "         If <mode> is missing, current mode will be printed.\n\n");
-}
-
-static wmcbool
-parse_mode (const char *s,
-            uint8_t *out_mode,
-            uint8_t *out_hdrpref,
-            wmcbool *out_set_evdo)
-{
-	if (strcasecmp (s, "lte") == 0) {
-		*out_mode = WMC_NETWORK_MODE_LTE_ONLY;
-		*out_hdrpref = QCDM_CMD_NV_HDR_REV_PREF_ITEM_REV_PREF_EHRPD;
-		*out_set_evdo = TRUE;
-		return TRUE;
-	}
-
-	if (strcasecmp (s, "auto-cdma") == 0) {
-		*out_mode = WMC_NETWORK_MODE_AUTO_CDMA;
-		*out_hdrpref = QCDM_CMD_NV_HDR_REV_PREF_ITEM_REV_PREF_A;
-		*out_set_evdo = TRUE;
-		return TRUE;
-	}
-
-	if (strcasecmp (s, "auto") == 0) {
-		*out_mode = WMC_NETWORK_MODE_AUTO;
-		*out_hdrpref = QCDM_CMD_NV_HDR_REV_PREF_ITEM_REV_PREF_EHRPD;
-		*out_set_evdo = TRUE;
-		return TRUE;
-	}
-
-	if (strcasecmp (s, "cdma") == 0) {
-		*out_mode = WMC_NETWORK_MODE_CDMA_ONLY;
-		*out_hdrpref = QCDM_CMD_NV_HDR_REV_PREF_ITEM_REV_PREF_A;
-		*out_set_evdo = TRUE;
-		return TRUE;
-	}
-
-	if (strcasecmp (s, "evdo") == 0) {
-		*out_mode = WMC_NETWORK_MODE_EVDO_ONLY;
-		*out_hdrpref = QCDM_CMD_NV_HDR_REV_PREF_ITEM_REV_PREF_A;
-		*out_set_evdo = TRUE;
-		return TRUE;
-	}
-
-	if (strcasecmp (s, "auto-gsm") == 0) {
-		*out_mode = WMC_NETWORK_MODE_AUTO_GSM;
-		*out_set_evdo = FALSE;
-		return TRUE;
-	}
-
-	if (strcasecmp (s, "gprs") == 0) {
-		*out_mode = WMC_NETWORK_MODE_GPRS_ONLY;
-		*out_set_evdo = FALSE;
-		return TRUE;
-	}
-
-	if (strcasecmp (s, "umts") == 0) {
-		*out_mode = WMC_NETWORK_MODE_UMTS_ONLY;
-		*out_set_evdo = FALSE;
-		return TRUE;
-	}
-
-	return FALSE;
-}
-
-
-int
-main (int argc, char *argv[])
-{
-	uint8_t mode = WMC_NETWORK_MODE_AUTO;
-	uint8_t hdrpref = QCDM_CMD_NV_HDR_REV_PREF_ITEM_REV_PREF_EHRPD;
-	const char *wmcport = argv[1];
-	const char *dmport = argv[2];
-	const char *msg = NULL;
-	wmcbool set_evdo = FALSE;
-	wmcbool set_mode = FALSE;
-
-	if (argc < 3 || argc > 5) {
-		usage (argv[0]);
-		return 1;
-	}
-
-	if (argc >= 4) {
-		if (strcasecmp (argv[3], "--debug") == 0)
-			debug = 1;
-		else {
-			set_mode = parse_mode (argv[3], &mode, &hdrpref, &set_evdo);
-			if (!set_mode) {
-				usage (argv[0]);
-				return 1;
-			}
-		}
-
-		if (argc >= 5 && strcasecmp (argv[4], "--debug") == 0)
-			debug = 1;
-	}
-
-	if (debug) {
-		putenv ("WMC_DEBUG=1");
-		putenv ("QCDM_DEBUG=1");
-	}
-
-	if (set_mode) {
-		if (wmc_set_global_mode (wmcport, mode))
-			return 1;
-		if (set_evdo && qcdm_set_hdr_pref (dmport, hdrpref))
-			return 1;
-
-		/* Send DM reset command */
-		qcdm_set_mode (dmport, QCDM_CMD_CONTROL_MODE_OFFLINE);
-		sleep (2);
-		qcdm_set_mode (dmport, QCDM_CMD_CONTROL_MODE_RESET);
-		sleep (2);
-
-		fprintf (stdout, "Success setting mode to '%s': replug your device.\n", argv[3]);
-	} else {
-		msg = wmc_get_global_mode (wmcport);
-		fprintf (stdout, "WMC Global Mode:   %s\n", msg ? msg : "(unknown)");
-		msg = qcdm_get_hdr_pref (dmport);
-		fprintf (stdout, "QCDM HDR Revision: %s\n", msg ? msg : "(unknown)");
-	}
-
-	return 0;
-}