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 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 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 @@ -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 ++ */ ++ ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include ++#define _LIBMM_INSIDE_MM ++#include ++ ++#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;isaved_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 ++ * ++ * Copyright (C) 2012 Google, Inc. ++ */ ++ ++#ifndef MM_BROADBAND_BEARER_XMM_NCM_H ++#define MM_BROADBAND_BEARER_XMM_NCM_H ++ ++#include ++#include ++ ++#define _LIBMM_INSIDE_MM ++#include ++ ++#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 ++ */ ++ ++#include ++ ++#include ++#include ++#include ++#include ++#include ++ ++#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 ++ */ ++ ++#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))