summaryrefslogtreecommitdiffstats
path: root/master/fibocom-support
diff options
context:
space:
mode:
authorJames <>2021-02-20 18:33:43 +0000
committerJames <>2021-02-20 18:33:43 +0000
commit2839d30c0335f0215405644aaa35bbfd16f062e9 (patch)
treeaf826dab9c7649488bb6fc6d39e5ae6d6c7857a6 /master/fibocom-support
downloadmaster-04a21c2-pq-2839d30c0335f0215405644aaa35bbfd16f062e9.tar.gz
master-04a21c2-pq-2839d30c0335f0215405644aaa35bbfd16f062e9.tar.bz2
master-04a21c2-pq-2839d30c0335f0215405644aaa35bbfd16f062e9.zip
everything happyHEADmaster
Diffstat (limited to 'master/fibocom-support')
-rw-r--r--master/fibocom-support1502
1 files changed, 1502 insertions, 0 deletions
diff --git a/master/fibocom-support b/master/fibocom-support
new file mode 100644
index 0000000..890028e
--- /dev/null
+++ b/master/fibocom-support
@@ -0,0 +1,1502 @@
+diff --git a/feeds/packages/libs/libmbim/Makefile b/feeds/packages/libs/libmbim/Makefile
+index ac0e9b9..4b40f5e 100644
+--- a/feeds/packages/libs/libmbim/Makefile
++++ b/feeds/packages/libs/libmbim/Makefile
+@@ -8,12 +8,12 @@
+ include $(TOPDIR)/rules.mk
+
+ PKG_NAME:=libmbim
+-PKG_VERSION:=1.22.0
++PKG_VERSION:=1.24.0
+ PKG_RELEASE:=2
+
+ PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
+ PKG_SOURCE_URL:=https://www.freedesktop.org/software/libmbim
+-PKG_HASH:=5c0778eb1cd12c3604523134e55183f5147b0cae71150e875b583768f7aa1f38
++PKG_HASH:=3d495cec3becfd02731ceac67a5ad7e0f1b328395137024d7cb91d31f00e1196
+
+ PKG_MAINTAINER:=Nicholas Smith <nicholas.smith@telcoantennas.com.au>
+
+diff --git a/feeds/packages/libs/libqmi/Makefile b/feeds/packages/libs/libqmi/Makefile
+index e4aec6a..c118a99 100644
+--- a/feeds/packages/libs/libqmi/Makefile
++++ b/feeds/packages/libs/libqmi/Makefile
+@@ -8,12 +8,12 @@
+ include $(TOPDIR)/rules.mk
+
+ PKG_NAME:=libqmi
+-PKG_VERSION:=1.24.8
++PKG_VERSION:=1.26.0
+ PKG_RELEASE:=1
+
+ PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
+ PKG_SOURCE_URL:=https://www.freedesktop.org/software/libqmi
+-PKG_HASH:=c793db2c91d7928160341b357b26315d9c879ecb36699cb7a6b36054cba60893
++PKG_HASH:=7f0429e0ae58792e21512d09ca2412537840ea42696762795af1284a65fd6e40
+
+ PKG_MAINTAINER:=Nicholas Smith <nicholas.smith@telcoantennas.com.au>
+
+diff --git a/feeds/packages/libs/libqmi/patches/001-fix-nmea.patch b/feeds/packages/libs/libqmi/patches/001-fix-nmea.patch
+index 4bf445e..f7c3d10 100644
+--- a/feeds/packages/libs/libqmi/patches/001-fix-nmea.patch
++++ b/feeds/packages/libs/libqmi/patches/001-fix-nmea.patch
+@@ -1,10 +1,10 @@
+-Index: libqmi-1.24.8/build-aux/qmi-codegen/VariableString.py
++Index: libqmi-1.26.0/build-aux/qmi-codegen/VariableString.py
+ ===================================================================
+---- libqmi-1.24.8.orig/build-aux/qmi-codegen/VariableString.py
+-+++ libqmi-1.24.8/build-aux/qmi-codegen/VariableString.py
+-@@ -38,6 +38,11 @@ class VariableString(Variable):
+- self.private_format = 'gchar *'
++--- libqmi-1.26.0.orig/build-aux/qmi-codegen/VariableString.py
+++++ libqmi-1.26.0/build-aux/qmi-codegen/VariableString.py
++@@ -39,6 +39,11 @@ class VariableString(Variable):
+ self.public_format = self.private_format
++ self.element_type = 'utf8'
+
+ + if 'force-ascii' in dictionary:
+ + self.force_ascii = True
+@@ -14,7 +14,7 @@ Index: libqmi-1.24.8/build-aux/qmi-codegen/VariableString.py
+ if 'fixed-size' in dictionary:
+ self.is_fixed_size = True
+ # Fixed-size strings
+-@@ -104,8 +109,9 @@ class VariableString(Variable):
++@@ -105,8 +110,9 @@ class VariableString(Variable):
+ else:
+ translations['n_size_prefix_bytes'] = self.n_size_prefix_bytes
+ translations['max_size'] = self.max_size if self.max_size != '' else '0'
+@@ -25,7 +25,7 @@ Index: libqmi-1.24.8/build-aux/qmi-codegen/VariableString.py
+ '${lp} goto ${tlv_out};\n')
+ f.write(string.Template(template).substitute(translations))
+
+-@@ -151,12 +157,13 @@ class VariableString(Variable):
++@@ -152,12 +158,13 @@ class VariableString(Variable):
+ else:
+ translations['n_size_prefix_bytes'] = self.n_size_prefix_bytes
+ translations['max_size'] = self.max_size if self.max_size != '' else '0'
+@@ -33,18 +33,18 @@ Index: libqmi-1.24.8/build-aux/qmi-codegen/VariableString.py
+ template = (
+ '\n'
+ '${lp}{\n'
+- '${lp} gchar *tmp;\n'
++ '${lp} g_autofree gchar *tmp = NULL;\n'
+ '\n'
+ - '${lp} if (!qmi_message_tlv_read_string (message, init_offset, &offset, ${n_size_prefix_bytes}, ${max_size}, &tmp, &error))\n'
+ + '${lp} if (!qmi_message_tlv_read_${ascii}string (message, init_offset, &offset, ${n_size_prefix_bytes}, ${max_size}, &tmp, &error))\n'
+ '${lp} goto out;\n'
+ '${lp} g_string_append (printable, tmp);\n'
+- '${lp} g_free (tmp);\n'
+-Index: libqmi-1.24.8/data/qmi-service-pds.json
++ '${lp}}\n')
++Index: libqmi-1.26.0/data/qmi-service-pds.json
+ ===================================================================
+---- libqmi-1.24.8.orig/data/qmi-service-pds.json
+-+++ libqmi-1.24.8/data/qmi-service-pds.json
+-@@ -164,6 +164,7 @@
++--- libqmi-1.26.0.orig/data/qmi-service-pds.json
+++++ libqmi-1.26.0/data/qmi-service-pds.json
++@@ -162,6 +162,7 @@
+ "id" : "0x10",
+ "type" : "TLV",
+ "since" : "1.0",
+@@ -52,11 +52,11 @@ Index: libqmi-1.24.8/data/qmi-service-pds.json
+ "format" : "string",
+ "max-size" : "200" },
+ { "name" : "Extended NMEA Position",
+-Index: libqmi-1.24.8/src/libqmi-glib/qmi-message.c
++Index: libqmi-1.26.0/src/libqmi-glib/qmi-message.c
+ ===================================================================
+---- libqmi-1.24.8.orig/src/libqmi-glib/qmi-message.c
+-+++ libqmi-1.24.8/src/libqmi-glib/qmi-message.c
+-@@ -1260,15 +1260,15 @@ qmi_message_tlv_read_gdouble (QmiMessage
++--- libqmi-1.26.0.orig/src/libqmi-glib/qmi-message.c
+++++ libqmi-1.26.0/src/libqmi-glib/qmi-message.c
++@@ -1262,15 +1262,15 @@ qmi_message_tlv_read_gdouble (QmiMessage
+ *offset = *offset + 8;
+ return TRUE;
+ }
+@@ -76,7 +76,7 @@ Index: libqmi-1.24.8/src/libqmi-glib/qmi-message.c
+ {
+ const guint8 *ptr;
+ guint16 string_length;
+-@@ -1325,7 +1325,7 @@ qmi_message_tlv_read_string (QmiMessage
++@@ -1327,7 +1327,7 @@ qmi_message_tlv_read_string (QmiMessage
+ * but hey, the strings read using this method should all really be ASCII-7
+ * and we're trying to do our best to overcome modem firmware problems...
+ */
+@@ -85,7 +85,7 @@ Index: libqmi-1.24.8/src/libqmi-glib/qmi-message.c
+ *out = g_malloc (valid_string_length + 1);
+ memcpy (*out, ptr, valid_string_length);
+ (*out)[valid_string_length] = '\0';
+-@@ -1348,6 +1348,34 @@ qmi_message_tlv_read_string (QmiMessage
++@@ -1350,6 +1350,34 @@ qmi_message_tlv_read_string (QmiMessage
+ }
+
+ gboolean
+@@ -120,11 +120,11 @@ Index: libqmi-1.24.8/src/libqmi-glib/qmi-message.c
+ qmi_message_tlv_read_fixed_size_string (QmiMessage *self,
+ gsize tlv_offset,
+ gsize *offset,
+-Index: libqmi-1.24.8/src/libqmi-glib/qmi-message.h
++Index: libqmi-1.26.0/src/libqmi-glib/qmi-message.h
+ ===================================================================
+---- libqmi-1.24.8.orig/src/libqmi-glib/qmi-message.h
+-+++ libqmi-1.24.8/src/libqmi-glib/qmi-message.h
+-@@ -933,6 +933,14 @@ gboolean qmi_message_tlv_read_string (Qm
++--- libqmi-1.26.0.orig/src/libqmi-glib/qmi-message.h
+++++ libqmi-1.26.0/src/libqmi-glib/qmi-message.h
++@@ -898,6 +898,14 @@ gboolean qmi_message_tlv_read_string (Qm
+ gchar **out,
+ GError **error);
+
+@@ -139,11 +139,11 @@ Index: libqmi-1.24.8/src/libqmi-glib/qmi-message.h
+ /**
+ * qmi_message_tlv_read_fixed_size_string:
+ * @self: a #QmiMessage.
+-Index: libqmi-1.24.8/data/qmi-service-loc.json
++Index: libqmi-1.26.0/data/qmi-service-loc.json
+ ===================================================================
+---- libqmi-1.24.8.orig/data/qmi-service-loc.json
+-+++ libqmi-1.24.8/data/qmi-service-loc.json
+-@@ -323,6 +323,7 @@
++--- libqmi-1.26.0.orig/data/qmi-service-loc.json
+++++ libqmi-1.26.0/data/qmi-service-loc.json
++@@ -321,6 +321,7 @@
+ "id" : "0x01",
+ "type" : "TLV",
+ "since" : "1.22",
+diff --git a/feeds/packages/net/modemmanager/Makefile b/feeds/packages/net/modemmanager/Makefile
+index 213760d..7cb05fe 100644
+--- a/feeds/packages/net/modemmanager/Makefile
++++ b/feeds/packages/net/modemmanager/Makefile
+@@ -8,12 +8,12 @@
+ include $(TOPDIR)/rules.mk
+
+ PKG_NAME:=modemmanager
+-PKG_VERSION:=1.12.8
++PKG_VERSION:=1.14.10
+ PKG_RELEASE:=1
+
+ PKG_SOURCE:=ModemManager-$(PKG_VERSION).tar.xz
+ PKG_SOURCE_URL:=https://www.freedesktop.org/software/ModemManager
+-PKG_HASH:=68b53d0615ba0d3e2bbf386ed029dfe644a6a30a79ab8d85523527bb4e713aff
++PKG_HASH:=4ea60b375a761e17e7bb095bca894579ed0e8e33b273dc698b5cbe03947f357f
+ PKG_BUILD_DIR:=$(BUILD_DIR)/ModemManager-$(PKG_VERSION)
+
+ PKG_MAINTAINER:=Nicholas Smith <nicholas.smith@telcoantennas.com.au>
+@@ -23,7 +23,7 @@ PKG_LICENSE_FILES:=COPYING
+ PKG_FIXUP:=autoreconf
+ PKG_INSTALL:=1
+ PKG_BUILD_PARALLEL:=1
+-PKG_BUILD_DEPENDS:=glib2/host libxslt/host
++PKG_BUILD_DEPENDS:=glib2/host libxslt/host
+
+ include $(INCLUDE_DIR)/package.mk
+
+diff --git a/feeds/packages/net/modemmanager/files/modemmanager.proto b/feeds/packages/net/modemmanager/files/modemmanager.proto
+index 536073d..228e7ff 100755
+--- a/feeds/packages/net/modemmanager/files/modemmanager.proto
++++ b/feeds/packages/net/modemmanager/files/modemmanager.proto
+@@ -213,10 +213,8 @@ modemmanager_connected_method_static_ipv4() {
+ proto_set_keep 1
+ echo "adding IPv4 address ${address}, netmask ${mask}"
+ proto_add_ipv4_address "${address}" "${mask}"
+- [ -n "${gateway}" ] && {
+- echo "adding default IPv4 route via ${gateway}"
+- proto_add_ipv4_route "0.0.0.0" "0" "${gateway}" "${address}"
+- }
++ echo "adding default IPv4 route via ${gateway}"
++ proto_add_ipv4_route "0.0.0.0" "0" "${gateway}" "${address}"
+ [ -n "${dns1}" ] && {
+ echo "adding primary DNS at ${dns1}"
+ proto_add_dns_server "${dns1}"
+diff --git a/feeds/packages/net/modemmanager/patches/0001-fibocom-L860-GL-support.patch b/feeds/packages/net/modemmanager/patches/0001-fibocom-L860-GL-support.patch
+new file mode 100644
+index 0000000..21b8df3
+--- /dev/null
++++ b/feeds/packages/net/modemmanager/patches/0001-fibocom-L860-GL-support.patch
+@@ -0,0 +1,1237 @@
++diff --git a/plugins/fibocom/mm-plugin-fibocom.c b/plugins/fibocom/mm-plugin-fibocom.c
++index e2188561..3fa92b25 100644
++--- a/plugins/fibocom/mm-plugin-fibocom.c
+++++ b/plugins/fibocom/mm-plugin-fibocom.c
++@@ -102,8 +102,8 @@ G_MODULE_EXPORT MMPlugin *
++ mm_plugin_create (void)
++ {
++ static const gchar *subsystems[] = { "tty", "net", "usb", NULL };
++- static const guint16 vendor_ids[] = { 0x2cb7, 0 };
++- static const gchar *drivers[] = { "cdc_mbim", "qmi_wwan", NULL };
+++ static const guint16 vendor_ids[] = { 0x2cb7, 0x8087, 0 };
+++ static const gchar *drivers[] = { "cdc_mbim", "qmi_wwan", "cdc_ncm", NULL };
++
++ return MM_PLUGIN (
++ g_object_new (MM_TYPE_PLUGIN_FIBOCOM,
++diff --git a/plugins/Makefile.am b/plugins/Makefile.am
++index 59f79a4a..cf4921a7 100644
++--- a/plugins/Makefile.am
+++++ b/plugins/Makefile.am
++@@ -298,6 +298,10 @@ libmm_shared_xmm_la_SOURCES = \
++ xmm/mm-shared-xmm.c \
++ xmm/mm-broadband-modem-xmm.h \
++ xmm/mm-broadband-modem-xmm.c \
+++ xmm/mm-broadband-modem-xmm-ncm.h \
+++ xmm/mm-broadband-modem-xmm-ncm.c \
+++ xmm/mm-broadband-bearer-xmm-ncm.c \
+++ xmm/mm-broadband-bearer-xmm-ncm.h \
++ $(NULL)
++
++ if WITH_MBIM
++diff --git a/plugins/fibocom/mm-plugin-fibocom.c b/plugins/fibocom/mm-plugin-fibocom.c
++index 3fa92b25..f6dca923 100644
++--- a/plugins/fibocom/mm-plugin-fibocom.c
+++++ b/plugins/fibocom/mm-plugin-fibocom.c
++@@ -23,6 +23,7 @@
++ #include "mm-plugin-fibocom.h"
++ #include "mm-broadband-modem.h"
++ #include "mm-broadband-modem-xmm.h"
+++#include "mm-broadband-modem-xmm-ncm.h"
++
++ #if defined WITH_MBIM
++ #include "mm-broadband-modem-mbim.h"
++@@ -81,7 +82,7 @@ create_modem (MMPlugin *self,
++
++ if (mm_port_probe_list_is_xmm (probes)) {
++ mm_obj_dbg (self, "XMM-based Fibocom modem found...");
++- return MM_BASE_MODEM (mm_broadband_modem_xmm_new (uid,
+++ return MM_BASE_MODEM (mm_broadband_modem_xmm_ncm_new (uid,
++ drivers,
++ mm_plugin_get_name (self),
++ vendor,
++diff --git a/plugins/xmm/mm-broadband-bearer-xmm-ncm.c b/plugins/xmm/mm-broadband-bearer-xmm-ncm.c
++new file mode 100644
++index 00000000..e436369f
++--- /dev/null
+++++ b/plugins/xmm/mm-broadband-bearer-xmm-ncm.c
++@@ -0,0 +1,846 @@
+++/* -*- 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) 2008 - 2009 Novell, Inc.
+++ * Copyright (C) 2009 - 2012 Red Hat, Inc.
+++ * Copyright (C) 2011 - 2012 Google, Inc.
+++ * Copyright (C) 2016 Aleksander Morgado <aleksander@aleksander.es>
+++ */
+++
+++#include <config.h>
+++
+++#include <stdio.h>
+++#include <stdlib.h>
+++#include <unistd.h>
+++#include <string.h>
+++#include <ctype.h>
+++
+++#include <arpa/inet.h>
+++#include <netinet/in.h>
+++
+++#include <ModemManager.h>
+++#define _LIBMM_INSIDE_MM
+++#include <libmm-glib.h>
+++
+++#include "mm-base-modem-at.h"
+++#include "mm-broadband-bearer-xmm-ncm.h"
+++#include "mm-log-object.h"
+++#include "mm-modem-helpers.h"
+++
+++
+++G_DEFINE_TYPE (MMBroadbandBearerXmmNcm, mm_broadband_bearer_xmm_ncm, MM_TYPE_BROADBAND_BEARER)
+++
+++struct _MMBroadbandBearerXmmNcmPrivate {
+++ int fish;
+++};
+++
+++
+++typedef struct {
+++ MMBaseModem *modem;
+++ MMPortSerialAt *primary;
+++ MMPort *ncm;
+++ GError *saved_error;
+++ guint cid;
+++} Dial3gppContext;
+++
+++static void
+++dial_3gpp_context_free (Dial3gppContext *ctx)
+++{
+++ if (ctx->saved_error)
+++ g_error_free (ctx->saved_error);
+++ g_object_unref (ctx->primary);
+++ g_object_unref (ctx->modem);
+++ g_slice_free (Dial3gppContext, ctx);
+++}
+++
+++static MMPort *
+++dial_3gpp_finish (MMBroadbandBearer *self,
+++ GAsyncResult *res,
+++ GError **error)
+++{
+++ return g_task_propagate_pointer (G_TASK (res), error);
+++}
+++
+++static void
+++dial_extended_error_ready (MMBaseModem *modem,
+++ GAsyncResult *res,
+++ GTask *task)
+++{
+++ Dial3gppContext *ctx;
+++ const gchar *result;
+++ GError *error = NULL;
+++
+++ ctx = g_task_get_task_data (task);
+++
+++ /* Close the dialling port as we got an error */
+++// mm_port_serial_close (MM_PORT_SERIAL (ctx->dial_port));
+++
+++ /* If cancelled, complete */
+++ if (g_task_return_error_if_cancelled (task)) {
+++ g_object_unref (task);
+++ return;
+++ }
+++
+++ result = mm_base_modem_at_command_full_finish (modem, res, NULL);
+++ if (result &&
+++ g_str_has_prefix (result, "+CEER: ") &&
+++ strlen (result) > 7) {
+++ error = g_error_new (ctx->saved_error->domain,
+++ ctx->saved_error->code,
+++ "%s",
+++ &result[7]);
+++ g_error_free (ctx->saved_error);
+++ } else
+++ g_propagate_error (&error, ctx->saved_error);
+++
+++ ctx->saved_error = NULL;
+++
+++ /* Done with errors */
+++ g_task_return_error (task, error);
+++ g_object_unref (task);
+++}
+++
+++
+++
+++static void
+++cgdata_ready (MMBaseModem *modem,
+++ GAsyncResult *res,
+++ GTask *task)
+++{
+++ //MMBroadbandBearer *self;
+++ Dial3gppContext *ctx;
+++
+++ //self = g_task_get_source_object (task);
+++ ctx = g_task_get_task_data (task);
+++
+++ /* DO NOT check for cancellable here. If we got here without errors, the
+++ * bearer is really connected and therefore we need to reflect that in
+++ * the state machine. */
+++ mm_base_modem_at_command_full_finish (modem, res, &ctx->saved_error);
+++
+++ if (ctx->saved_error) {
+++ /* Try to get more information why it failed */
+++ mm_base_modem_at_command_full (ctx->modem,
+++ ctx->primary,
+++ "+CEER",
+++ 3,
+++ FALSE,
+++ FALSE, /* raw */
+++ NULL, /* cancellable */
+++ (GAsyncReadyCallback)dial_extended_error_ready,
+++ task);
+++ return;
+++ }
+++
+++ mm_port_set_connected (MM_PORT (ctx->ncm), TRUE);
+++ g_task_return_pointer (task,
+++ g_object_ref (ctx->ncm),
+++ g_object_unref);
+++}
+++static void
+++xdata_channel_ready (MMBaseModem *modem,
+++ GAsyncResult *res,
+++ GTask *task)
+++{
+++ //MMBroadbandBearer *self;
+++ Dial3gppContext *ctx;
+++ gchar *command;
+++
+++ //self = g_task_get_source_object (task);
+++ ctx = g_task_get_task_data (task);
+++
+++ /* DO NOT check for cancellable here. If we got here without errors, the
+++ * bearer is really connected and therefore we need to reflect that in
+++ * the state machine. */
+++ mm_base_modem_at_command_full_finish (modem, res, &ctx->saved_error);
+++
+++ if (ctx->saved_error) {
+++ /* Try to get more information why it failed */
+++ mm_base_modem_at_command_full (ctx->modem,
+++ ctx->primary,
+++ "+CEER",
+++ 3,
+++ FALSE,
+++ FALSE, /* raw */
+++ NULL, /* cancellable */
+++ (GAsyncReadyCallback)dial_extended_error_ready,
+++ task);
+++ return;
+++ }
+++
+++ command = g_strdup_printf ("+CGDATA=\"M-RAW_IP\",%d",ctx->cid);
+++ mm_base_modem_at_command_full (ctx->modem,
+++ ctx->primary,
+++ command,
+++ 60,
+++ FALSE,
+++ FALSE, /* raw */
+++ NULL, /* cancellable */
+++ (GAsyncReadyCallback)cgdata_ready,
+++ task);
+++ g_free(command);
+++}
+++
+++static MMPort *peek_port_by_if(MMBaseModem *modem,unsigned ifnum)
+++{
+++ GList *l;
+++
+++ for (l= mm_base_modem_peek_data_ports (modem); l; l = g_list_next(l)) {
+++ MMPort *p = (MMPort *) l->data;
+++ if (mm_kernel_device_get_property_as_int_hex (mm_port_peek_kernel_device (p), "ID_USB_INTERFACE_NUM") == ifnum)
+++ return p;
+++ }
+++
+++ return NULL;
+++}
+++
+++static unsigned get_net_port_index(MMBaseModem *modem, MMPort *port)
+++{
+++ unsigned i, ret=0;
+++ unsigned usb_iface_num;
+++
+++
+++ usb_iface_num = mm_kernel_device_get_property_as_int_hex (mm_port_peek_kernel_device (port), "ID_USB_INTERFACE_NUM");
+++
+++
+++ for (i=0;i<usb_iface_num;++i) {
+++ MMPort *p = peek_port_by_if(modem, i);
+++ if (p && (mm_port_get_port_type(p)==MM_PORT_TYPE_NET)) ret++;
+++ }
+++
+++ return ret;
+++}
+++
+++static void
+++cgact_enable_ready (MMBaseModem *modem,
+++ GAsyncResult *res,
+++ GTask *task)
+++{
+++ //MMBroadbandBearer *self;
+++ Dial3gppContext *ctx;
+++ gchar *command;
+++ guint usb_index;
+++
+++ //self = g_task_get_source_object (task);
+++ ctx = g_task_get_task_data (task);
+++
+++ /* DO NOT check for cancellable here. If we got here without errors, the
+++ * bearer is really connected and therefore we need to reflect that in
+++ * the state machine. */
+++ mm_base_modem_at_command_full_finish (modem, res, &ctx->saved_error);
+++
+++ if (ctx->saved_error) {
+++ /* Try to get more information why it failed */
+++ mm_base_modem_at_command_full (ctx->modem,
+++ ctx->primary,
+++ "+CEER",
+++ 3,
+++ FALSE,
+++ FALSE, /* raw */
+++ NULL, /* cancellable */
+++ (GAsyncReadyCallback)dial_extended_error_ready,
+++ task);
+++ return;
+++ }
+++
+++ usb_index=get_net_port_index(ctx->modem,ctx->ncm);
+++
+++ command = g_strdup_printf ("+XDATACHANNEL=1,1,\"/USBCDC/0\",\"/USBHS/NCM/%u\",2,%d",usb_index, ctx->cid);
+++ mm_base_modem_at_command_full (ctx->modem,
+++ ctx->primary,
+++ command,
+++ 60,
+++ FALSE,
+++ FALSE, /* raw */
+++ NULL, /* cancellable */
+++ (GAsyncReadyCallback)xdata_channel_ready,
+++ task);
+++ g_free(command);
+++}
+++
+++static void
+++xdns_config_ready (MMBaseModem *modem,
+++ GAsyncResult *res,
+++ GTask *task)
+++{
+++ GError *error = NULL;
+++ Dial3gppContext *ctx;
+++ gchar *command;
+++
+++ ctx = g_task_get_task_data (task);
+++
+++ (void) mm_base_modem_at_command_full_finish (modem, res, &error);
+++ if (error)
+++ g_error_free (error);
+++
+++ command = g_strdup_printf ("+CGACT=1,%d", ctx->cid);
+++ mm_base_modem_at_command_full (ctx->modem,
+++ ctx->primary,
+++ command,
+++ 60,
+++ FALSE,
+++ FALSE, /* raw */
+++ NULL, /* cancellable */
+++ (GAsyncReadyCallback)cgact_enable_ready,
+++ task);
+++ g_free(command);
+++}
+++
+++
+++
+++static void
+++dial_3gpp (MMBroadbandBearer *self,
+++ MMBaseModem *modem,
+++ MMPortSerialAt *primary,
+++ guint cid,
+++ GCancellable *cancellable,
+++ GAsyncReadyCallback callback,
+++ gpointer user_data)
+++{
+++ gchar *command;
+++ Dial3gppContext *ctx;
+++ GTask *task;
+++
+++ g_assert (primary != NULL);
+++
+++ ctx = g_slice_new0 (Dial3gppContext);
+++ ctx->modem = g_object_ref (modem);
+++ ctx->primary = g_object_ref (primary);
+++ ctx->cid=cid;
+++
+++ task = g_task_new (self, cancellable, callback, user_data);
+++ g_task_set_task_data (task, ctx, (GDestroyNotify)dial_3gpp_context_free);
+++
+++ ctx->ncm = mm_base_modem_peek_best_data_port (modem, MM_PORT_TYPE_NET);
+++
+++ command = g_strdup_printf ("+XDNS=%d,1", ctx->cid);
+++ mm_base_modem_at_command_full (MM_BASE_MODEM (ctx->modem),
+++ ctx->primary,
+++ command,
+++ 3,
+++ FALSE,
+++ FALSE, /* raw */
+++ NULL, /* cancellable */
+++ (GAsyncReadyCallback)xdns_config_ready,
+++ task);
+++ g_free (command);
+++}
+++
+++/*****************************************************************************/
+++
+++
+++static gboolean
+++validate_address (int family, const char *addr)
+++{
+++ struct in6_addr tmp6 = IN6ADDR_ANY_INIT;
+++
+++ if (inet_pton (family, addr, (void *) &tmp6) != 1)
+++{
+++g_message ("%s: famil '%s'", __func__, addr);
+++ return FALSE;
+++}
+++ if ((family == AF_INET6) && IN6_IS_ADDR_UNSPECIFIED (&tmp6))
+++ return FALSE;
+++ return TRUE;
+++}
+++
+++
+++static gboolean
+++parse_responses (int cid, const gchar *ip_str,const gchar *dns_str,
+++ MMBearerIpConfig **out_ip4_config,
+++ MMBearerIpConfig **out_ip6_config,
+++ GError **error)
+++{
+++ MMBearerIpConfig **ip_config = NULL;
+++ gboolean got_address = FALSE;
+++ GRegex *r;
+++ GMatchInfo *match_info = NULL;
+++ GError *match_error = NULL;
+++ int family = AF_INET;
+++
+++ g_return_val_if_fail (out_ip4_config, FALSE);
+++ g_return_val_if_fail (out_ip6_config, FALSE);
+++
+++ if (ip_str) {
+++ r = g_regex_new ("\\+CGPADDR:\\s*(\\d+),\\s*\"([0-9a-fA-F.:]+)\"", 0, 0, NULL);
+++ g_assert (r != NULL);
+++
+++ if (!g_regex_match_full (r, ip_str, -1, 0, 0, &match_info, &match_error)) {
+++ if (match_error) {
+++ g_propagate_error (error, match_error);
+++ g_prefix_error (error, "Could not parse +CGPADDR results: ");
+++ } else {
+++ g_set_error_literal (error,
+++ MM_CORE_ERROR,
+++ MM_CORE_ERROR_FAILED,
+++ "Couldn't match +CGPADDR reply");
+++ }
+++ goto done;
+++ }
+++
+++
+++ while (g_match_info_matches (match_info) && !got_address) {
+++ char *id = g_match_info_fetch (match_info, 1);
+++
+++ if (atoi(id) == cid) {
+++ char *str = g_match_info_fetch (match_info, 2);
+++
+++ if (strchr (str, ':')) {
+++ family = AF_INET6;
+++ ip_config = out_ip6_config;
+++ } else if (strchr (str, '.')) {
+++ family = AF_INET;
+++ ip_config = out_ip4_config;
+++ } else {
+++ g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
+++ "Failed to detect address family");
+++ }
+++
+++ if (ip_config &&validate_address (family, str)) {
+++ *ip_config = mm_bearer_ip_config_new ();
+++ mm_bearer_ip_config_set_method (*ip_config, MM_BEARER_IP_METHOD_STATIC);
+++ mm_bearer_ip_config_set_address (*ip_config, str);
+++ mm_bearer_ip_config_set_prefix (*ip_config, (family == AF_INET6) ? 128 : 32);
+++ got_address = TRUE;
+++ } else
+++ ip_config=NULL;
+++
+++ g_free (str);
+++ }
+++ g_free (id);
+++ g_match_info_next (match_info, NULL);
+++ }
+++
+++ g_match_info_free (match_info);
+++ match_info=NULL;
+++ g_regex_unref (r);
+++ r=NULL;
+++ }
+++
+++ if (!got_address) {
+++ g_set_error_literal (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
+++ "did not get IP configuration");
+++ return FALSE;
+++ }
+++
+++ if (dns_str) {
+++ r = g_regex_new ("\\+XDNS:\\s*(\\d+),\\s*\"([0-9a-fA-F.:]+)\"\\s*,\\s*\"([0-9a-fA-F.:]+)\"", 0, 0, NULL);
+++ g_assert (r != NULL);
+++
+++ if (!g_regex_match_full (r, dns_str, -1, 0, 0, &match_info, &match_error)) {
+++ if (match_error) {
+++ g_propagate_error (error, match_error);
+++ g_prefix_error (error, "Could not parse +XDNS results: ");
+++ } else {
+++ g_set_error_literal (error,
+++ MM_CORE_ERROR,
+++ MM_CORE_ERROR_FAILED,
+++ "Couldn't match +XDNS reply");
+++ }
+++ goto done;
+++ }
+++
+++
+++ while (g_match_info_matches (match_info)) {
+++ char *id = g_match_info_fetch (match_info, 1);
+++
+++ if (atoi(id) == cid) {
+++ gchar *dns[3]={0};
+++ dns[0] = g_match_info_fetch (match_info, 2);
+++ dns[1] = g_match_info_fetch (match_info, 3);
+++
+++ mm_bearer_ip_config_set_dns (*ip_config, (const gchar **) dns);
+++
+++ g_free (dns[1]);
+++ g_free (dns[0]);
+++ }
+++
+++ g_free (id);
+++ g_match_info_next (match_info, NULL);
+++ }
+++
+++ g_match_info_free (match_info);
+++ match_info=NULL;
+++ g_regex_unref (r);
+++ r=NULL;
+++ }
+++
+++
+++done:
+++ if (match_info) g_match_info_free (match_info);
+++ if (r) g_regex_unref (r);
+++ return !!*ip_config;
+++}
+++
+++
+++typedef struct {
+++ MMBaseModem *modem;
+++ MMPortSerialAt *primary;
+++ MMPort *data;
+++ MMBearerIpFamily family;
+++ gchar *cgpaddr_response;
+++ gchar *xdns_response;
+++ guint cid;
+++} GetIpConfig3gppContext;
+++
+++static void
+++get_ip_config_context_free (GetIpConfig3gppContext *ctx)
+++{
+++ g_object_unref (ctx->primary);
+++ g_object_unref (ctx->modem);
+++ g_object_unref (ctx->data);
+++
+++ if (ctx->cgpaddr_response) g_free(ctx->cgpaddr_response);
+++ if (ctx->xdns_response) g_free(ctx->xdns_response);
+++ g_free (ctx);
+++}
+++
+++static gboolean
+++get_ip_config_3gpp_finish (MMBroadbandBearer *self,
+++ GAsyncResult *res,
+++ MMBearerIpConfig **ipv4_config,
+++ MMBearerIpConfig **ipv6_config,
+++ GError **error)
+++{
+++ MMBearerConnectResult *configs;
+++ MMBearerIpConfig *ipv4, *ipv6;
+++
+++ configs = g_task_propagate_pointer (G_TASK (res), error);
+++ if (!configs)
+++ return FALSE;
+++
+++ ipv4 = mm_bearer_connect_result_peek_ipv4_config (configs);
+++ ipv6 = mm_bearer_connect_result_peek_ipv6_config (configs);
+++ g_assert (ipv4 || ipv6);
+++ if (ipv4_config && ipv4)
+++ *ipv4_config = g_object_ref (ipv4);
+++ if (ipv6_config && ipv6)
+++ *ipv6_config = g_object_ref (ipv6);
+++
+++ mm_bearer_connect_result_unref (configs);
+++ return TRUE;
+++}
+++
+++
+++static void
+++ip_config_ready (MMBaseModem *modem,
+++ GAsyncResult *res,
+++ GTask *task)
+++{
+++ GetIpConfig3gppContext *ctx;
+++ const gchar *response;
+++ GError *error = NULL;
+++ MMBearerConnectResult *connect_result;
+++ MMBearerIpConfig *ipv4_config=NULL;
+++ MMBearerIpConfig *ipv6_config=NULL;
+++
+++ ctx = g_task_get_task_data (task);
+++
+++
+++ response = mm_base_modem_at_command_full_finish (modem, res, &error);
+++ if (error) {
+++ g_error_free (error);
+++ } else {
+++ ctx->xdns_response=g_strdup(response);
+++ }
+++
+++ if (!ctx->cgpaddr_response) {
+++ /* Fall back to DHCP configuration; early devices don't support *E2IPCFG */
+++ if (ctx->family == MM_BEARER_IP_FAMILY_IPV4 || ctx->family == MM_BEARER_IP_FAMILY_IPV4V6) {
+++ ipv4_config = mm_bearer_ip_config_new ();
+++ mm_bearer_ip_config_set_method (ipv4_config, MM_BEARER_IP_METHOD_DHCP);
+++ }
+++ if (ctx->family == MM_BEARER_IP_FAMILY_IPV6 || ctx->family == MM_BEARER_IP_FAMILY_IPV4V6) {
+++ ipv6_config = mm_bearer_ip_config_new ();
+++ mm_bearer_ip_config_set_method (ipv6_config, MM_BEARER_IP_METHOD_DHCP);
+++ }
+++ } else {
+++ if (!parse_responses (ctx->cid, ctx->cgpaddr_response, ctx->xdns_response,
+++ &ipv4_config,
+++ &ipv6_config,
+++ &error)) {
+++ g_task_return_error (task, error);
+++ goto out;
+++ }
+++
+++ if (!ipv4_config && !ipv6_config) {
+++ g_task_return_new_error (task,
+++ MM_CORE_ERROR,
+++ MM_CORE_ERROR_FAILED,
+++ "Couldn't get IP config: couldn't parse response '%s'",
+++ response);
+++ goto out;
+++ }
+++ }
+++
+++
+++ connect_result = mm_bearer_connect_result_new (MM_PORT (ctx->data),
+++ ipv4_config,
+++ ipv6_config);
+++ g_task_return_pointer (task,
+++ connect_result,
+++ (GDestroyNotify)mm_bearer_connect_result_unref);
+++
+++out:
+++ g_clear_object (&ipv4_config);
+++ g_clear_object (&ipv6_config);
+++ g_object_unref (task);
+++}
+++
+++static void
+++cgpaddr_ready (MMBaseModem *modem,
+++ GAsyncResult *res,
+++ GTask *task)
+++{
+++ GetIpConfig3gppContext *ctx;
+++ const gchar *response;
+++ GError *error = NULL;
+++
+++ ctx = g_task_get_task_data (task);
+++
+++
+++ response = mm_base_modem_at_command_full_finish (modem, res, &error);
+++ if (error) {
+++ g_error_free (error);
+++ } else {
+++ ctx->cgpaddr_response=g_strdup(response);
+++ }
+++
+++
+++ mm_base_modem_at_command_full (MM_BASE_MODEM (ctx->modem),
+++ ctx->primary,
+++ "+XDNS?",
+++ 3,
+++ FALSE,
+++ FALSE, /* raw */
+++ NULL, /* cancellable */
+++ (GAsyncReadyCallback)ip_config_ready,
+++ task);
+++
+++}
+++
+++
+++static void
+++cgpiaf_config_ready (MMBaseModem *modem,
+++ GAsyncResult *res,
+++ GTask *task)
+++{
+++ GError *error = NULL;
+++ GetIpConfig3gppContext *ctx;
+++ gchar *command;
+++
+++ ctx = g_task_get_task_data (task);
+++
+++ (void) mm_base_modem_at_command_full_finish (modem, res, &error);
+++ if (error)
+++ g_error_free (error);
+++
+++ command = g_strdup_printf ("+CGPADDR=%d", ctx->cid);
+++ mm_base_modem_at_command_full (MM_BASE_MODEM (ctx->modem),
+++ ctx->primary,
+++ command,
+++ 3,
+++ FALSE,
+++ FALSE, /* raw */
+++ NULL, /* cancellable */
+++ (GAsyncReadyCallback)cgpaddr_ready,
+++ task);
+++ g_free(command);
+++}
+++
+++static void
+++get_ip_config_3gpp (MMBroadbandBearer *self,
+++ MMBroadbandModem *modem,
+++ MMPortSerialAt *primary,
+++ MMPortSerialAt *secondary,
+++ MMPort *data,
+++ guint cid,
+++ MMBearerIpFamily ip_family,
+++ GAsyncReadyCallback callback,
+++ gpointer user_data)
+++{
+++ GetIpConfig3gppContext *ctx;
+++ GTask *task;
+++
+++ ctx = g_new0 (GetIpConfig3gppContext, 1);
+++ ctx->modem = g_object_ref (modem);
+++ ctx->primary = g_object_ref (primary);
+++ ctx->data=g_object_ref(data);
+++ ctx->family = ip_family;
+++ ctx->cid=cid;
+++ ctx->xdns_response=NULL;
+++ ctx->cgpaddr_response=NULL;
+++
+++ task = g_task_new (self, NULL, callback, user_data);
+++ g_task_set_task_data (task, ctx, (GDestroyNotify)get_ip_config_context_free);
+++
+++
+++ mm_base_modem_at_command_full (MM_BASE_MODEM (modem),
+++ primary,
+++ "+CGPIAF=1,0,0,0",
+++ 3,
+++ FALSE,
+++ FALSE, /* raw */
+++ NULL, /* cancellable */
+++ (GAsyncReadyCallback)cgpiaf_config_ready,
+++ task);
+++
+++}
+++
+++/*****************************************************************************/
+++
+++
+++typedef struct {
+++ MMBaseModem *modem;
+++ MMPortSerialAt *primary;
+++ MMPort *data;
+++ GError *saved_error;
+++ guint cid;
+++} Disconnect3gppContext;
+++
+++static void
+++disconnect_3gpp_context_free (Disconnect3gppContext *ctx)
+++{
+++ if (ctx->saved_error)
+++ g_error_free (ctx->saved_error);
+++ g_object_unref (ctx->primary);
+++ g_object_unref (ctx->modem);
+++ g_object_unref (ctx->data);
+++ g_slice_free (Disconnect3gppContext, ctx);
+++}
+++
+++
+++static void
+++cgact_disable_ready (MMBaseModem *modem,
+++ GAsyncResult *res,
+++ GTask *task)
+++{
+++ //MMBroadbandBearer *self;
+++ Disconnect3gppContext *ctx;
+++
+++ //self = g_task_get_source_object (task);
+++ ctx = g_task_get_task_data (task);
+++
+++ /* DO NOT check for cancellable here. If we got here without errors, the
+++ * bearer is really connected and therefore we need to reflect that in
+++ * the state machine. */
+++ mm_base_modem_at_command_full_finish (modem, res, &ctx->saved_error);
+++
+++ mm_port_set_connected (MM_PORT (ctx->data), FALSE);
+++ g_task_return_boolean (task, TRUE);
+++}
+++
+++
+++static void
+++disconnect_3gpp (MMBroadbandBearer *self,
+++ MMBroadbandModem *modem,
+++ MMPortSerialAt *primary,
+++ MMPortSerialAt *secondary,
+++ MMPort *data,
+++ guint cid,
+++ GAsyncReadyCallback callback,
+++ gpointer user_data)
+++{
+++ gchar *command;
+++ Disconnect3gppContext *ctx;
+++ GTask *task;
+++
+++ g_assert (primary != NULL);
+++
+++ ctx = g_slice_new0 (Disconnect3gppContext);
+++ ctx->modem = g_object_ref (modem);
+++ ctx->primary = g_object_ref (primary);
+++ ctx->data=g_object_ref(data);
+++ ctx->cid=cid;
+++
+++ task = g_task_new (self, NULL, callback, user_data);
+++ g_task_set_task_data (task, ctx, (GDestroyNotify)disconnect_3gpp_context_free);
+++
+++ command = g_strdup_printf ("+CGACT=0,%d", cid);
+++ mm_base_modem_at_command_full (ctx->modem,
+++ ctx->primary,
+++ command,
+++ 60,
+++ FALSE,
+++ FALSE, /* raw */
+++ NULL, /* cancellable */
+++ (GAsyncReadyCallback)cgact_disable_ready,
+++ task);
+++ g_free (command);
+++}
+++
+++
+++/*****************************************************************************/
+++MMBaseBearer *
+++mm_broadband_bearer_xmm_ncm_new_finish (GAsyncResult *res,
+++ GError **error)
+++{
+++ GObject *bearer;
+++ GObject *source;
+++
+++ source = g_async_result_get_source_object (res);
+++ bearer = g_async_initable_new_finish (G_ASYNC_INITABLE (source), res, error);
+++ g_object_unref (source);
+++
+++ if (!bearer)
+++ return NULL;
+++
+++ /* Only export valid bearers */
+++ mm_base_bearer_export (MM_BASE_BEARER (bearer));
+++
+++ return MM_BASE_BEARER (bearer);
+++}
+++
+++void
+++mm_broadband_bearer_xmm_ncm_new (MMBroadbandModemXmmNcm *modem,
+++ MMBearerProperties *config,
+++ GCancellable *cancellable,
+++ GAsyncReadyCallback callback,
+++ gpointer user_data)
+++{
+++ g_async_initable_new_async (
+++ MM_TYPE_BROADBAND_BEARER_XMM_NCM,
+++ G_PRIORITY_DEFAULT,
+++ cancellable,
+++ callback,
+++ user_data,
+++ MM_BASE_BEARER_MODEM, modem,
+++ MM_BASE_BEARER_CONFIG, config,
+++ NULL);
+++}
+++
+++static void
+++mm_broadband_bearer_xmm_ncm_init (MMBroadbandBearerXmmNcm *self)
+++{
+++ /* Initialize private data */
+++ self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
+++ MM_TYPE_BROADBAND_BEARER,
+++ MMBroadbandBearerXmmNcmPrivate);
+++}
+++
+++static void
+++mm_broadband_bearer_xmm_ncm_class_init (MMBroadbandBearerXmmNcmClass *klass)
+++{
+++ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+++ //MMBaseBearerClass *base_bearer_class = MM_BASE_BEARER_CLASS (klass);
+++ MMBroadbandBearerClass *broadband_bearer_class = MM_BROADBAND_BEARER_CLASS (klass);
+++
+++ g_type_class_add_private (object_class, sizeof (MMBroadbandBearerXmmNcmPrivate));
+++
+++
+++ broadband_bearer_class->dial_3gpp = dial_3gpp;
+++ broadband_bearer_class->dial_3gpp_finish = dial_3gpp_finish;
+++ broadband_bearer_class->disconnect_3gpp = disconnect_3gpp;
+++
+++ broadband_bearer_class->get_ip_config_3gpp= get_ip_config_3gpp;
+++ broadband_bearer_class->get_ip_config_3gpp_finish= get_ip_config_3gpp_finish;
+++}
++diff --git a/plugins/xmm/mm-broadband-bearer-xmm-ncm.h b/plugins/xmm/mm-broadband-bearer-xmm-ncm.h
++new file mode 100644
++index 00000000..948c3683
++--- /dev/null
+++++ b/plugins/xmm/mm-broadband-bearer-xmm-ncm.h
++@@ -0,0 +1,62 @@
+++/* -*- 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:
+++ *
+++ * Author: Nathan Williams <njw@google.com>
+++ *
+++ * Copyright (C) 2012 Google, Inc.
+++ */
+++
+++#ifndef MM_BROADBAND_BEARER_XMM_NCM_H
+++#define MM_BROADBAND_BEARER_XMM_NCM_H
+++
+++#include <glib.h>
+++#include <glib-object.h>
+++
+++#define _LIBMM_INSIDE_MM
+++#include <libmm-glib.h>
+++
+++#include "mm-broadband-bearer.h"
+++#include "mm-broadband-modem-xmm-ncm.h"
+++
+++#define MM_TYPE_BROADBAND_BEARER_XMM_NCM (mm_broadband_bearer_xmm_ncm_get_type ())
+++#define MM_BROADBAND_BEARER_XMM_NCM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_BROADBAND_BEARER_XMM_NCM, MMBroadbandBearerXmmNcm))
+++#define MM_BROADBAND_BEARER_XMM_NCM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_BROADBAND_BEARER_XMM_NCM, MMBroadbandBearerXmmNcmClass))
+++#define MM_IS_BROADBAND_BEARER_XMM_NCM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_BROADBAND_BEARER_XMM_NCM))
+++#define MM_IS_BROADBAND_BEARER_XMM_NCM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_BROADBAND_BEARER_XMM_NCM))
+++#define MM_BROADBAND_BEARER_XMM_NCM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_BROADBAND_BEARER_XMM_NCM, MMBroadbandBearerXmmNcmClass))
+++
+++typedef struct _MMBroadbandBearerXmmNcm MMBroadbandBearerXmmNcm;
+++typedef struct _MMBroadbandBearerXmmNcmClass MMBroadbandBearerXmmNcmClass;
+++typedef struct _MMBroadbandBearerXmmNcmPrivate MMBroadbandBearerXmmNcmPrivate;
+++
+++struct _MMBroadbandBearerXmmNcm {
+++ MMBroadbandBearer parent;
+++ MMBroadbandBearerXmmNcmPrivate *priv;
+++};
+++
+++struct _MMBroadbandBearerXmmNcmClass {
+++ MMBroadbandBearerClass parent;
+++};
+++
+++GType mm_broadband_bearer_xmm_ncm_get_type (void);
+++
+++/* Default 3GPP bearer creation implementation */
+++void mm_broadband_bearer_xmm_ncm_new (MMBroadbandModemXmmNcm *modem,
+++ MMBearerProperties *properties,
+++ GCancellable *cancellable,
+++ GAsyncReadyCallback callback,
+++ gpointer user_data);
+++MMBaseBearer *mm_broadband_bearer_xmm_ncm_new_finish (GAsyncResult *res,
+++ GError **error);
+++
+++
+++#endif /* MM_BROADBAND_BEARER_XMM_NCM_H */
++diff --git a/plugins/xmm/mm-broadband-modem-xmm-ncm.c b/plugins/xmm/mm-broadband-modem-xmm-ncm.c
++new file mode 100644
++index 00000000..29f48de9
++--- /dev/null
+++++ b/plugins/xmm/mm-broadband-modem-xmm-ncm.c
++@@ -0,0 +1,195 @@
+++/* -*- 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 <config.h>
+++
+++#include <stdlib.h>
+++#include <stdio.h>
+++#include <string.h>
+++#include <unistd.h>
+++#include <ctype.h>
+++
+++#include "ModemManager.h"
+++#include "mm-iface-modem.h"
+++#include "mm-iface-modem-location.h"
+++#include "mm-broadband-modem-xmm-ncm.h"
+++#include "mm-broadband-bearer-xmm-ncm.h"
+++#include "mm-shared-xmm.h"
+++
+++
+++static void iface_modem_init (MMIfaceModem *iface);
+++static void shared_xmm_init (MMSharedXmm *iface);
+++static void iface_modem_signal_init (MMIfaceModemSignal *iface);
+++static void iface_modem_location_init (MMIfaceModemLocation *iface);
+++
+++static MMIfaceModemLocation *iface_modem_location_parent;
+++
+++G_DEFINE_TYPE_EXTENDED (MMBroadbandModemXmmNcm, mm_broadband_modem_xmm_ncm, MM_TYPE_BROADBAND_MODEM, 0,
+++ G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM, iface_modem_init)
+++ G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_SIGNAL, iface_modem_signal_init)
+++ G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_LOCATION, iface_modem_location_init)
+++ G_IMPLEMENT_INTERFACE (MM_TYPE_SHARED_XMM, shared_xmm_init))
+++
+++/*****************************************************************************/
+++/* Create Bearer (Modem interface) */
+++
+++static MMBaseBearer *
+++modem_create_bearer_finish (MMIfaceModem *self,
+++ GAsyncResult *res,
+++ GError **error)
+++{
+++ return g_task_propagate_pointer (G_TASK (res), error);
+++}
+++
+++static void
+++broadband_bearer_new_ready (GObject *source,
+++ GAsyncResult *res,
+++ GTask *task)
+++{
+++ MMBaseBearer *bearer = NULL;
+++ GError *error = NULL;
+++
+++ bearer = mm_broadband_bearer_xmm_ncm_new_finish (res, &error);
+++ if (!bearer)
+++ g_task_return_error (task, error);
+++ else
+++ g_task_return_pointer (task, bearer, g_object_unref);
+++ g_object_unref (task);
+++}
+++
+++static void
+++modem_create_bearer (MMIfaceModem *self,
+++ MMBearerProperties *properties,
+++ GAsyncReadyCallback callback,
+++ gpointer user_data)
+++{
+++ /* We just create a MMBroadbandBearer */
+++ mm_broadband_bearer_xmm_ncm_new (MM_BROADBAND_MODEM_XMM_NCM (self),
+++ properties,
+++ NULL, /* cancellable */
+++ (GAsyncReadyCallback)broadband_bearer_new_ready,
+++ g_task_new (self, NULL, callback, user_data));
+++}
+++
+++
+++
+++/*****************************************************************************/
+++
+++MMBroadbandModemXmmNcm *
+++mm_broadband_modem_xmm_ncm_new (const gchar *device,
+++ const gchar **drivers,
+++ const gchar *plugin,
+++ guint16 vendor_id,
+++ guint16 product_id)
+++{
+++ return g_object_new (MM_TYPE_BROADBAND_MODEM_XMM_NCM,
+++ MM_BASE_MODEM_DEVICE, device,
+++ MM_BASE_MODEM_DRIVERS, drivers,
+++ MM_BASE_MODEM_PLUGIN, plugin,
+++ MM_BASE_MODEM_VENDOR_ID, vendor_id,
+++ MM_BASE_MODEM_PRODUCT_ID, product_id,
+++ NULL);
+++}
+++
+++static void
+++mm_broadband_modem_xmm_ncm_init (MMBroadbandModemXmmNcm *self)
+++{
+++}
+++
+++static void
+++iface_modem_init (MMIfaceModem *iface)
+++{
+++ iface->load_supported_modes = mm_shared_xmm_load_supported_modes;
+++ iface->load_supported_modes_finish = mm_shared_xmm_load_supported_modes_finish;
+++ iface->load_current_modes = mm_shared_xmm_load_current_modes;
+++ iface->load_current_modes_finish = mm_shared_xmm_load_current_modes_finish;
+++ iface->set_current_modes = mm_shared_xmm_set_current_modes;
+++ iface->set_current_modes_finish = mm_shared_xmm_set_current_modes_finish;
+++
+++ iface->load_supported_bands = mm_shared_xmm_load_supported_bands;
+++ iface->load_supported_bands_finish = mm_shared_xmm_load_supported_bands_finish;
+++ iface->load_current_bands = mm_shared_xmm_load_current_bands;
+++ iface->load_current_bands_finish = mm_shared_xmm_load_current_bands_finish;
+++ iface->set_current_bands = mm_shared_xmm_set_current_bands;
+++ iface->set_current_bands_finish = mm_shared_xmm_set_current_bands_finish;
+++
+++ iface->load_power_state = mm_shared_xmm_load_power_state;
+++ iface->load_power_state_finish = mm_shared_xmm_load_power_state_finish;
+++ iface->modem_power_up = mm_shared_xmm_power_up;
+++ iface->modem_power_up_finish = mm_shared_xmm_power_up_finish;
+++ iface->modem_power_down = mm_shared_xmm_power_down;
+++ iface->modem_power_down_finish = mm_shared_xmm_power_down_finish;
+++ iface->modem_power_off = mm_shared_xmm_power_off;
+++ iface->modem_power_off_finish = mm_shared_xmm_power_off_finish;
+++ iface->reset = mm_shared_xmm_reset;
+++ iface->reset_finish = mm_shared_xmm_reset_finish;
+++
+++ iface->create_bearer = modem_create_bearer;
+++ iface->create_bearer_finish = modem_create_bearer_finish;
+++}
+++
+++
+++static void
+++iface_modem_location_init (MMIfaceModemLocation *iface)
+++{
+++ iface_modem_location_parent = g_type_interface_peek_parent (iface);
+++
+++ iface->load_capabilities = mm_shared_xmm_location_load_capabilities;
+++ iface->load_capabilities_finish = mm_shared_xmm_location_load_capabilities_finish;
+++ iface->enable_location_gathering = mm_shared_xmm_enable_location_gathering;
+++ iface->enable_location_gathering_finish = mm_shared_xmm_enable_location_gathering_finish;
+++ iface->disable_location_gathering = mm_shared_xmm_disable_location_gathering;
+++ iface->disable_location_gathering_finish = mm_shared_xmm_disable_location_gathering_finish;
+++ iface->load_supl_server = mm_shared_xmm_location_load_supl_server;
+++ iface->load_supl_server_finish = mm_shared_xmm_location_load_supl_server_finish;
+++ iface->set_supl_server = mm_shared_xmm_location_set_supl_server;
+++ iface->set_supl_server_finish = mm_shared_xmm_location_set_supl_server_finish;
+++}
+++
+++static MMBroadbandModemClass *
+++peek_parent_broadband_modem_class (MMSharedXmm *self)
+++{
+++ return MM_BROADBAND_MODEM_CLASS (mm_broadband_modem_xmm_ncm_parent_class);
+++}
+++
+++static MMIfaceModemLocation *
+++peek_parent_location_interface (MMSharedXmm *self)
+++{
+++ return iface_modem_location_parent;
+++}
+++
+++static void
+++iface_modem_signal_init (MMIfaceModemSignal *iface)
+++{
+++ iface->check_support = mm_shared_xmm_signal_check_support;
+++ iface->check_support_finish = mm_shared_xmm_signal_check_support_finish;
+++ iface->load_values = mm_shared_xmm_signal_load_values;
+++ iface->load_values_finish = mm_shared_xmm_signal_load_values_finish;
+++}
+++
+++static void
+++shared_xmm_init (MMSharedXmm *iface)
+++{
+++ iface->peek_parent_broadband_modem_class = peek_parent_broadband_modem_class;
+++ iface->peek_parent_location_interface = peek_parent_location_interface;
+++}
+++
+++static void
+++mm_broadband_modem_xmm_ncm_class_init (MMBroadbandModemXmmNcmClass *klass)
+++{
+++ MMBroadbandModemClass *broadband_modem_class = MM_BROADBAND_MODEM_CLASS (klass);
+++
+++ broadband_modem_class->setup_ports = mm_shared_xmm_setup_ports;
+++}
++diff --git a/plugins/xmm/mm-broadband-modem-xmm-ncm.h b/plugins/xmm/mm-broadband-modem-xmm-ncm.h
++new file mode 100644
++index 00000000..72645fc4
++--- /dev/null
+++++ b/plugins/xmm/mm-broadband-modem-xmm-ncm.h
++@@ -0,0 +1,47 @@
+++/* -*- 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>
+++ */
+++
+++#ifndef MM_BROADBAND_MODEM_XMM_NCM_H
+++#define MM_BROADBAND_MODEM_XMM_NCM_H
+++
+++#include "mm-broadband-modem.h"
+++
+++#define MM_TYPE_BROADBAND_MODEM_XMM_NCM (mm_broadband_modem_xmm_ncm_get_type ())
+++#define MM_BROADBAND_MODEM_XMM_NCM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_BROADBAND_MODEM_XMM_NCM, MMBroadbandModemXmmNcm))
+++#define MM_BROADBAND_MODEM_XMM_NCM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MM_TYPE_BROADBAND_MODEM_XMM_NCM, MMBroadbandModemXmmNcmClass))
+++#define MM_IS_BROADBAND_MODEM_XMM_NCM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_BROADBAND_MODEM_XMM_NCM))
+++#define MM_IS_BROADBAND_MODEM_XMM_NCM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MM_TYPE_BROADBAND_MODEM_XMM_NCM))
+++#define MM_BROADBAND_MODEM_XMM_NCM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MM_TYPE_BROADBAND_MODEM_XMM_NCM, MMBroadbandModemXmmNcmClass))
+++
+++typedef struct _MMBroadbandModemXmmNcm MMBroadbandModemXmmNcm;
+++typedef struct _MMBroadbandModemXmmNcmClass MMBroadbandModemXmmNcmClass;
+++
+++struct _MMBroadbandModemXmmNcm {
+++ MMBroadbandModem parent;
+++};
+++
+++struct _MMBroadbandModemXmmNcmClass{
+++ MMBroadbandModemClass parent;
+++};
+++
+++GType mm_broadband_modem_xmm_ncm_get_type (void);
+++
+++MMBroadbandModemXmmNcm *mm_broadband_modem_xmm_ncm_new (const gchar *device,
+++ const gchar **drivers,
+++ const gchar *plugin,
+++ guint16 vendor_id,
+++ guint16 product_id);
+++
+++#endif /* MM_BROADBAND_MODEM_XMM_NCM_H */
++diff --git a/plugins/xmm/mm-broadband-modem-xmm.c b/plugins/xmm/mm-broadband-modem-xmm.c
++index 35103d8b..1083ae2e 100644
++--- a/plugins/xmm/mm-broadband-modem-xmm.c
+++++ b/plugins/xmm/mm-broadband-modem-xmm.c
++@@ -25,6 +25,7 @@
++ #include "mm-iface-modem.h"
++ #include "mm-iface-modem-location.h"
++ #include "mm-broadband-modem-xmm.h"
+++#include "mm-broadband-bearer-xmm-ncm.h"
++ #include "mm-shared-xmm.h"
++
++
+diff --git a/tools/Makefile b/tools/Makefile
+index 3c37316..1c5116a 100644
+--- a/tools/Makefile
++++ b/tools/Makefile
+@@ -22,7 +22,7 @@ ifneq ($(CONFIG_SDK)$(CONFIG_PACKAGE_kmod-b43)$(CONFIG_PACKAGE_b43legacy-firmwar
+ endif
+
+ tools-$(BUILD_TOOLCHAIN) += gmp mpfr mpc libelf expat
+-tools-y += m4 libtool autoconf automake flex bison pkgconf mklibs zlib
++tools-y += m4 libtool autoconf autoconf-archive automake flex bison pkgconf mklibs zlib
+ tools-y += sstrip make-ext4fs e2fsprogs mtd-utils mkimage
+ tools-y += firmware-utils patch-image quilt padjffs2
+ tools-y += mm-macros missing-macros cmake bc findutils gengetopt patchelf
+diff --git a/tools/autoconf-archive/Makefile b/tools/autoconf-archive/Makefile
+new file mode 100644
+index 0000000..3cac07d
+--- /dev/null
++++ b/tools/autoconf-archive/Makefile
+@@ -0,0 +1,28 @@
++include $(TOPDIR)/rules.mk
++
++PKG_NAME:=autoconf-archive
++PKG_VERSION:=2019.01.06
++
++PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
++PKG_SOURCE_URL:=@GNU/autoconf-archive
++PKG_HASH:=17195c833098da79de5778ee90948f4c5d90ed1a0cf8391b4ab348e2ec511e3f
++
++include $(INCLUDE_DIR)/host-build.mk
++
++HOST_CONFIGURE_ARGS += \
++ --datarootdir=$(STAGING_DIR_HOST)/share
++
++define Host/Compile
++ export SHELL="$(BASH)"; $(MAKE) -C $(HOST_BUILD_DIR)
++endef
++
++define Host/Install
++ export SHELL="$(BASH)"; $(MAKE) -C $(HOST_BUILD_DIR) install
++endef
++
++define Host/Clean
++ -export SHELL="$(BASH)"; $(MAKE) -C $(HOST_BUILD_DIR) uninstall
++ $(call Host/Clean/Default)
++endef
++
++$(eval $(call HostBuild))