aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksander Morgado <aleksander@lanedo.com>2013-05-29 12:41:49 +0200
committerAleksander Morgado <aleksander@lanedo.com>2013-06-05 19:15:14 +0200
commit45ceba76924f184ed9e12ba3d35e00a55ad3a197 (patch)
treec413d3e29a64eb86340e964ec48e67d8a66c6f76
parent212d00c529ee07131bf3b71a8759dca49292c059 (diff)
api,introspection: 'SupportedModes' is now a list of possible combinations
Instead of just a mask of MMModemMode values, we now provide a list of the allowed and preferred mode combinations supported by the modem. E.g.: $> sudo mmcli -m 0 ------------------------- Modes | supported: 'allowed: 2g; preferred: none | allowed: 3g; preferred: none | allowed: 2g, 3g; preferred: none | allowed: 2g, 3g; preferred: 2g | allowed: 2g, 3g; preferred: 3g | allowed: 4g; preferred: none | allowed: 2g, 3g, 4g; preferred: none'
-rw-r--r--cli/mmcli-modem.c16
-rw-r--r--docs/reference/libmm-glib/libmm-glib-sections.txt3
-rw-r--r--introspection/org.freedesktop.ModemManager1.Modem.xml23
-rw-r--r--libmm-glib/Makefile.am2
-rw-r--r--libmm-glib/libmm-glib.h1
-rw-r--r--libmm-glib/mm-common-helpers.c122
-rw-r--r--libmm-glib/mm-common-helpers.h12
-rw-r--r--libmm-glib/mm-helper-types.h44
-rw-r--r--libmm-glib/mm-modem.c121
-rw-r--r--libmm-glib/mm-modem.h8
-rw-r--r--plugins/cinterion/mm-broadband-modem-cinterion.c82
-rw-r--r--plugins/huawei/mm-broadband-modem-huawei.c93
-rw-r--r--plugins/icera/mm-broadband-modem-icera.c92
-rw-r--r--plugins/iridium/mm-broadband-modem-iridium.c17
-rw-r--r--plugins/linktop/mm-broadband-modem-linktop.c88
-rw-r--r--plugins/longcheer/mm-broadband-modem-longcheer.c106
-rw-r--r--plugins/mbm/mm-broadband-modem-mbm.c79
-rw-r--r--plugins/nokia/mm-broadband-modem-nokia.c41
-rw-r--r--plugins/novatel/mm-broadband-modem-novatel.c90
-rw-r--r--plugins/option/mm-broadband-modem-option.c92
-rw-r--r--plugins/sierra/mm-broadband-modem-sierra.c119
-rw-r--r--plugins/simtech/mm-broadband-modem-simtech.c109
-rw-r--r--plugins/wavecom/mm-broadband-modem-wavecom.c134
-rw-r--r--plugins/x22x/mm-broadband-modem-x22x.c84
-rw-r--r--plugins/zte/mm-broadband-modem-zte.c103
-rw-r--r--src/mm-broadband-modem-mbim.c70
-rw-r--r--src/mm-broadband-modem-qmi.c143
-rw-r--r--src/mm-broadband-modem.c23
-rw-r--r--src/mm-iface-modem.c206
-rw-r--r--src/mm-iface-modem.h19
-rw-r--r--src/mm-modem-helpers-qmi.c23
-rw-r--r--src/mm-modem-helpers-qmi.h2
-rw-r--r--src/mm-modem-helpers.c47
-rw-r--r--src/mm-modem-helpers.h3
-rw-r--r--src/tests/test-modem-helpers.c124
35 files changed, 2047 insertions, 294 deletions
diff --git a/cli/mmcli-modem.c b/cli/mmcli-modem.c
index e405307b..99233217 100644
--- a/cli/mmcli-modem.c
+++ b/cli/mmcli-modem.c
@@ -238,6 +238,8 @@ print_modem_info (void)
gchar *modem_capabilities_string;
gchar *current_capabilities_string;
gchar *access_technologies_string;
+ MMModemModeCombination *modes = NULL;
+ guint n_modes = 0;
gchar *supported_modes_string;
gchar *allowed_modes_string;
gchar *preferred_mode_string;
@@ -266,6 +268,9 @@ print_modem_info (void)
mm_modem_get_current_capabilities (ctx->modem));
access_technologies_string = mm_modem_access_technology_build_string_from_mask (
mm_modem_get_access_technologies (ctx->modem));
+ mm_modem_get_supported_modes (ctx->modem, &modes, &n_modes);
+ supported_modes_string = mm_common_build_mode_combinations_string (modes, n_modes);
+ g_free (modes);
mm_modem_get_current_bands (ctx->modem, &bands, &n_bands);
current_bands_string = mm_common_build_bands_string (bands, n_bands);
g_free (bands);
@@ -276,8 +281,6 @@ print_modem_info (void)
mm_modem_get_allowed_modes (ctx->modem));
preferred_mode_string = mm_modem_mode_build_string_from_mask (
mm_modem_get_preferred_mode (ctx->modem));
- supported_modes_string = mm_modem_mode_build_string_from_mask (
- mm_modem_get_supported_modes (ctx->modem));
supported_ip_families_string = mm_bearer_ip_family_build_string_from_mask (
mm_modem_get_supported_ip_families (ctx->modem));
@@ -310,6 +313,15 @@ print_modem_info (void)
else
prefixed_revision = NULL;
+ if (supported_modes_string) {
+ gchar *prefixed;
+
+ prefixed = mmcli_prefix_newlines (" | ",
+ supported_modes_string);
+ g_free (supported_modes_string);
+ supported_modes_string = prefixed;
+ }
+
/* Get signal quality info */
signal_quality = mm_modem_get_signal_quality (ctx->modem, &signal_quality_recent);
diff --git a/docs/reference/libmm-glib/libmm-glib-sections.txt b/docs/reference/libmm-glib/libmm-glib-sections.txt
index 358f613c..1d1704b4 100644
--- a/docs/reference/libmm-glib/libmm-glib-sections.txt
+++ b/docs/reference/libmm-glib/libmm-glib-sections.txt
@@ -73,6 +73,7 @@ mm_object_get_type
<FILE>mm-modem</FILE>
<TITLE>MMModem</TITLE>
MMModem
+MMModemModeCombination
<SUBSECTION Getters>
mm_modem_get_path
mm_modem_dup_path
@@ -106,6 +107,7 @@ mm_modem_get_max_bearers
mm_modem_get_max_active_bearers
mm_modem_get_own_numbers
mm_modem_dup_own_numbers
+mm_modem_peek_supported_modes
mm_modem_get_supported_modes
mm_modem_get_allowed_modes
mm_modem_get_preferred_mode
@@ -1455,6 +1457,7 @@ mm_gdbus_modem_get_supported_bands
mm_gdbus_modem_dup_supported_bands
mm_gdbus_modem_get_supported_ip_families
mm_gdbus_modem_get_supported_modes
+mm_gdbus_modem_dup_supported_modes
mm_gdbus_modem_get_unlock_required
mm_gdbus_modem_get_unlock_retries
mm_gdbus_modem_dup_unlock_retries
diff --git a/introspection/org.freedesktop.ModemManager1.Modem.xml b/introspection/org.freedesktop.ModemManager1.Modem.xml
index 0f8364b7..7b43846e 100644
--- a/introspection/org.freedesktop.ModemManager1.Modem.xml
+++ b/introspection/org.freedesktop.ModemManager1.Modem.xml
@@ -410,14 +410,25 @@
<!--
SupportedModes:
- Bitmask of <link linkend="MMModemMode">MMModemMode</link> values,
- specifying the access technologies supported by the device.
+ This property exposes the supported mode combinations, given as an array of unsigned
+ integer pairs, where:
- For POTS devices, only the
- <link linkend="MM-MODEM-MODE-ANY:CAPS"><constant>MM_MODEM_MODE_ANY</constant></link>
- mode will be returned.
+ <variablelist>
+ <varlistentry>
+ <listitem>
+ The first integer is a bitmask of <link linkend="MMModemMode">MMModemMode</link> values,
+ specifying the allowed modes.
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <listitem>
+ The second integer is a single <link linkend="MMModemMode">MMModemMode</link>, which
+ specifies the preferred access technology, among the ones defined in the allowed modes.
+ </listitem>
+ </varlistentry>
+ </variablelist>
-->
- <property name="SupportedModes" type="u" access="read" />
+ <property name="SupportedModes" type="a(uu)" access="read" />
<!--
AllowedModes:
diff --git a/libmm-glib/Makefile.am b/libmm-glib/Makefile.am
index b0a83e0e..b189b913 100644
--- a/libmm-glib/Makefile.am
+++ b/libmm-glib/Makefile.am
@@ -5,6 +5,7 @@ lib_LTLIBRARIES = libmm-glib.la
libmm_glib_la_SOURCES = \
libmm-glib.h \
mm-helpers.h \
+ mm-helper-types.h \
mm-manager.h \
mm-manager.c \
mm-object.h \
@@ -77,6 +78,7 @@ libmm_glib_la_LIBADD = \
includedir = @includedir@/libmm-glib
include_HEADERS = \
libmm-glib.h \
+ mm-helper-types.h \
mm-manager.h \
mm-object.h \
mm-modem.h \
diff --git a/libmm-glib/libmm-glib.h b/libmm-glib/libmm-glib.h
index 468a3856..8b5e9200 100644
--- a/libmm-glib/libmm-glib.h
+++ b/libmm-glib/libmm-glib.h
@@ -52,6 +52,7 @@
# include <mm-common-helpers.h>
#endif
+#include <mm-helper-types.h>
#include <mm-simple-status.h>
#include <mm-simple-connect-properties.h>
#include <mm-sms-properties.h>
diff --git a/libmm-glib/mm-common-helpers.c b/libmm-glib/mm-common-helpers.c
index aabc070c..2b158354 100644
--- a/libmm-glib/mm-common-helpers.c
+++ b/libmm-glib/mm-common-helpers.c
@@ -73,6 +73,38 @@ mm_common_build_sms_storages_string (const MMSmsStorage *storages,
return g_string_free (str, FALSE);
}
+gchar *
+mm_common_build_mode_combinations_string (const MMModemModeCombination *modes,
+ guint n_modes)
+{
+ gboolean first = TRUE;
+ GString *str;
+ guint i;
+
+ if (!modes || !n_modes)
+ return g_strdup ("none");
+
+ str = g_string_new ("");
+ for (i = 0; i < n_modes; i++) {
+ gchar *allowed;
+ gchar *preferred;
+
+ allowed = mm_modem_mode_build_string_from_mask (modes[i].allowed);
+ preferred = mm_modem_mode_build_string_from_mask (modes[i].preferred);
+ g_string_append_printf (str, "%sallowed: %s; preferred: %s",
+ first ? "" : "\n",
+ allowed,
+ preferred);
+ g_free (allowed);
+ g_free (preferred);
+
+ if (first)
+ first = FALSE;
+ }
+
+ return g_string_free (str, FALSE);
+}
+
GArray *
mm_common_sms_storages_variant_to_garray (GVariant *variant)
{
@@ -357,6 +389,96 @@ mm_common_bands_garray_cmp (GArray *a, GArray *b)
return !different;
}
+GArray *
+mm_common_mode_combinations_variant_to_garray (GVariant *variant)
+{
+ GArray *array = NULL;
+
+ if (variant) {
+ GVariantIter iter;
+ guint n;
+
+ g_variant_iter_init (&iter, variant);
+ n = g_variant_iter_n_children (&iter);
+
+ if (n > 0) {
+ MMModemModeCombination mode;
+
+ array = g_array_sized_new (FALSE, FALSE, sizeof (MMModemModeCombination), n);
+ while (g_variant_iter_loop (&iter, "(uu)", &mode.allowed, &mode.preferred))
+ g_array_append_val (array, mode);
+ }
+ }
+
+ /* If nothing set, fallback to default */
+ if (!array) {
+ MMModemModeCombination default_mode;
+
+ default_mode.allowed = MM_MODEM_MODE_ANY;
+ default_mode.preferred = MM_MODEM_MODE_NONE;
+ array = g_array_sized_new (FALSE, FALSE, sizeof (MMModemModeCombination), 1);
+ g_array_append_val (array, default_mode);
+ }
+
+ return array;
+}
+
+MMModemModeCombination *
+mm_common_mode_combinations_variant_to_array (GVariant *variant,
+ guint *n_modes)
+{
+ GArray *array;
+
+ array = mm_common_mode_combinations_variant_to_garray (variant);
+ if (n_modes)
+ *n_modes = array->len;
+ return (MMModemModeCombination *) g_array_free (array, FALSE);
+}
+
+GVariant *
+mm_common_mode_combinations_array_to_variant (const MMModemModeCombination *modes,
+ guint n_modes)
+{
+ if (n_modes > 0) {
+ GVariantBuilder builder;
+ guint i;
+
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(uu)"));
+
+ for (i = 0; i < n_modes; i++)
+ g_variant_builder_add_value (&builder,
+ g_variant_new ("(uu)",
+ ((guint32)modes[i].allowed),
+ ((guint32)modes[i].preferred)));
+ return g_variant_builder_end (&builder);
+ }
+
+ return mm_common_build_mode_combinations_default ();
+}
+
+GVariant *
+mm_common_mode_combinations_garray_to_variant (GArray *array)
+{
+ if (array)
+ return mm_common_mode_combinations_array_to_variant ((const MMModemModeCombination *)array->data,
+ array->len);
+
+ return mm_common_mode_combinations_array_to_variant (NULL, 0);
+}
+
+GVariant *
+mm_common_build_mode_combinations_default (void)
+{
+ GVariantBuilder builder;
+
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(uu)"));
+ g_variant_builder_add_value (&builder,
+ g_variant_new ("(uu)",
+ MM_MODEM_MODE_ANY,
+ MM_MODEM_MODE_NONE));
+ return g_variant_builder_end (&builder);
+}
+
gboolean
mm_common_get_boolean_from_string (const gchar *value,
GError **error)
diff --git a/libmm-glib/mm-common-helpers.h b/libmm-glib/mm-common-helpers.h
index d23fc73e..45df4f4c 100644
--- a/libmm-glib/mm-common-helpers.h
+++ b/libmm-glib/mm-common-helpers.h
@@ -17,6 +17,7 @@
#include <glib.h>
#include <ModemManager.h>
+#include "mm-helper-types.h"
#if !defined (__LIBMM_GLIB_H_INSIDE__) && !defined (LIBMM_GLIB_COMPILATION)
#error "Only <libmm-glib.h> can be included directly."
@@ -31,6 +32,9 @@ gchar *mm_common_build_bands_string (const MMModemBand *bands,
gchar *mm_common_build_sms_storages_string (const MMSmsStorage *storages,
guint n_storages);
+gchar *mm_common_build_mode_combinations_string (const MMModemModeCombination *modes,
+ guint n_modes);
+
MMModemMode mm_common_get_modes_from_string (const gchar *str,
GError **error);
void mm_common_get_bands_from_string (const gchar *str,
@@ -67,6 +71,14 @@ GVariant *mm_common_build_bands_unknown (void);
gboolean mm_common_bands_garray_cmp (GArray *a, GArray *b);
+GArray *mm_common_mode_combinations_variant_to_garray (GVariant *variant);
+MMModemModeCombination *mm_common_mode_combinations_variant_to_array (GVariant *variant,
+ guint *n_modes);
+GVariant *mm_common_mode_combinations_array_to_variant (const MMModemModeCombination *modes,
+ guint n_modes);
+GVariant *mm_common_mode_combinations_garray_to_variant (GArray *array);
+GVariant *mm_common_build_mode_combinations_default (void);
+
typedef gboolean (*MMParseKeyValueForeachFn) (const gchar *key,
const gchar *value,
gpointer user_data);
diff --git a/libmm-glib/mm-helper-types.h b/libmm-glib/mm-helper-types.h
new file mode 100644
index 00000000..129b01d4
--- /dev/null
+++ b/libmm-glib/mm-helper-types.h
@@ -0,0 +1,44 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * libmm -- Access modem status & information from glib applications
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2013 Aleksander Morgado <aleksander@gnu.org>
+ */
+
+#include <ModemManager.h>
+
+#if !defined (__LIBMM_GLIB_H_INSIDE__) && !defined (LIBMM_GLIB_COMPILATION)
+#error "Only <libmm-glib.h> can be included directly."
+#endif
+
+#ifndef _MM_HELPER_TYPES_H_
+#define _MM_HELPER_TYPES_H_
+
+/**
+ * MMModemModeCombination:
+ * @allowed: Mask of #MMModemMode values specifying allowed modes.
+ * @preferred: A single #MMModemMode value specifying the preferred mode.
+ *
+ * #MMModemModeCombination is a simple struct holding a pair of #MMModemMode values.
+ */
+typedef struct _MMModemModeCombination {
+ MMModemMode allowed;
+ MMModemMode preferred;
+} MMModemModeCombination;
+
+#endif /* _MM_HELPER_TYPES_H_ */
diff --git a/libmm-glib/mm-modem.c b/libmm-glib/mm-modem.c
index af0f9fe1..2f916f5b 100644
--- a/libmm-glib/mm-modem.c
+++ b/libmm-glib/mm-modem.c
@@ -49,6 +49,11 @@ struct _MMModemPrivate {
guint unlock_retries_id;
MMUnlockRetries *unlock_retries;
+ /* Supported Modes */
+ GMutex supported_modes_mutex;
+ guint supported_modes_id;
+ GArray *supported_modes;
+
/* Supported Bands */
GMutex supported_bands_mutex;
guint supported_bands_id;
@@ -910,22 +915,120 @@ mm_modem_get_signal_quality (MMModem *self,
/*****************************************************************************/
+static void
+supported_modes_updated (MMModem *self,
+ GParamSpec *pspec)
+{
+ g_mutex_lock (&self->priv->supported_modes_mutex);
+ {
+ GVariant *dictionary;
+
+ if (self->priv->supported_modes)
+ g_array_unref (self->priv->supported_modes);
+
+ dictionary = mm_gdbus_modem_get_supported_modes (MM_GDBUS_MODEM (self));
+ self->priv->supported_modes = (dictionary ?
+ mm_common_mode_combinations_variant_to_garray (dictionary) :
+ NULL);
+ }
+ g_mutex_unlock (&self->priv->supported_modes_mutex);
+}
+
+static gboolean
+ensure_internal_supported_modes (MMModem *self,
+ MMModemModeCombination **dup_modes,
+ guint *dup_modes_n)
+{
+ gboolean ret;
+
+ g_mutex_lock (&self->priv->supported_modes_mutex);
+ {
+ /* If this is the first time ever asking for the array, setup the
+ * update listener and the initial array, if any. */
+ if (!self->priv->supported_modes_id) {
+ GVariant *dictionary;
+
+ dictionary = mm_gdbus_modem_dup_supported_modes (MM_GDBUS_MODEM (self));
+ if (dictionary) {
+ self->priv->supported_modes = mm_common_mode_combinations_variant_to_garray (dictionary);
+ g_variant_unref (dictionary);
+ }
+
+ /* No need to clear this signal connection when freeing self */
+ self->priv->supported_modes_id =
+ g_signal_connect (self,
+ "notify::supported-modes",
+ G_CALLBACK (supported_modes_updated),
+ NULL);
+ }
+
+ if (!self->priv->supported_modes)
+ ret = FALSE;
+ else {
+ ret = TRUE;
+
+ if (dup_modes && dup_modes_n) {
+ *dup_modes_n = self->priv->supported_modes->len;
+ if (self->priv->supported_modes->len > 0) {
+ *dup_modes = g_malloc (sizeof (MMModemModeCombination) * self->priv->supported_modes->len);
+ memcpy (*dup_modes, self->priv->supported_modes->data, sizeof (MMModemModeCombination) * self->priv->supported_modes->len);
+ } else
+ *dup_modes = NULL;
+ }
+ }
+ }
+ g_mutex_unlock (&self->priv->supported_modes_mutex);
+
+ return ret;
+}
+
/**
* mm_modem_get_supported_modes:
* @self: A #MMModem.
+ * @modes: (out) (array length=n_modes): Return location for the array of #MMModemModeCombination structs. The returned array should be freed with g_free() when no longer needed.
+ * @n_modes: (out): Return location for the number of values in @modes.
*
- * Gets the list of modes specifying the access technologies supported by the #MMModem.
+ * Gets the list of supported mode combinations.
+ *
+ * Returns: %TRUE if @modes and @n_modes are set, %FALSE otherwise.
+ */
+gboolean
+mm_modem_get_supported_modes (MMModem *self,
+ MMModemModeCombination **modes,
+ guint *n_modes)
+{
+ g_return_val_if_fail (MM_IS_MODEM (self), FALSE);
+ g_return_val_if_fail (modes != NULL, FALSE);
+ g_return_val_if_fail (n_modes != NULL, FALSE);
+
+ return ensure_internal_supported_modes (self, modes, n_modes);
+}
+
+/**
+ * mm_modem_peek_supported_modes:
+ * @self: A #MMModem.
+ * @modes: (out) (array length=n_modes): Return location for the array of #MMModemModeCombination values. Do not free the returned array, it is owned by @self.
+ * @n_modes: (out): Return location for the number of values in @modes.
*
- * For POTS devices, only #MM_MODEM_MODE_ANY will be returned.
+ * Gets the list of supported mode combinations.
*
- * Returns: A bitmask of #MMModemMode values.
+ * Returns: %TRUE if @modes and @n_modes are set, %FALSE otherwise.
*/
-MMModemMode
-mm_modem_get_supported_modes (MMModem *self)
+gboolean
+mm_modem_peek_supported_modes (MMModem *self,
+ const MMModemModeCombination **modes,
+ guint *n_modes)
{
- g_return_val_if_fail (MM_IS_MODEM (self), MM_MODEM_MODE_NONE);
+ g_return_val_if_fail (MM_IS_MODEM (self), FALSE);
+ g_return_val_if_fail (modes != NULL, FALSE);
+ g_return_val_if_fail (n_modes != NULL, FALSE);
- return (MMModemMode) mm_gdbus_modem_get_supported_modes (MM_GDBUS_MODEM (self));
+ if (!ensure_internal_supported_modes (self, NULL, NULL))
+ return FALSE;
+
+ *n_modes = self->priv->supported_modes->len;
+ *modes = (MMModemModeCombination *)self->priv->supported_modes->data;
+ return TRUE;
}
/*****************************************************************************/
@@ -2533,6 +2636,7 @@ mm_modem_init (MMModem *self)
MM_TYPE_MODEM,
MMModemPrivate);
g_mutex_init (&self->priv->unlock_retries_mutex);
+ g_mutex_init (&self->priv->supported_modes_mutex);
g_mutex_init (&self->priv->supported_bands_mutex);
g_mutex_init (&self->priv->current_bands_mutex);
}
@@ -2543,9 +2647,12 @@ finalize (GObject *object)
MMModem *self = MM_MODEM (object);
g_mutex_clear (&self->priv->unlock_retries_mutex);
+ g_mutex_clear (&self->priv->supported_modes_mutex);
g_mutex_clear (&self->priv->supported_bands_mutex);
g_mutex_clear (&self->priv->current_bands_mutex);
+ if (self->priv->supported_modes)
+ g_array_unref (self->priv->supported_modes);
if (self->priv->supported_bands)
g_array_unref (self->priv->supported_bands);
if (self->priv->current_bands)
diff --git a/libmm-glib/mm-modem.h b/libmm-glib/mm-modem.h
index 2ba6d82e..aeabb84f 100644
--- a/libmm-glib/mm-modem.h
+++ b/libmm-glib/mm-modem.h
@@ -34,6 +34,7 @@
#include "mm-unlock-retries.h"
#include "mm-sim.h"
#include "mm-bearer.h"
+#include "mm-helper-types.h"
G_BEGIN_DECLS
@@ -127,7 +128,12 @@ MMModemAccessTechnology mm_modem_get_access_technologies (MMModem *self);
guint mm_modem_get_signal_quality (MMModem *self,
gboolean *recent);
-MMModemMode mm_modem_get_supported_modes (MMModem *self);
+gboolean mm_modem_peek_supported_modes (MMModem *self,
+ const MMModemModeCombination **modes,
+ guint *n_modes);
+gboolean mm_modem_get_supported_modes (MMModem *self,
+ MMModemModeCombination **modes,
+ guint *n_modes);
MMModemMode mm_modem_get_allowed_modes (MMModem *self);
diff --git a/plugins/cinterion/mm-broadband-modem-cinterion.c b/plugins/cinterion/mm-broadband-modem-cinterion.c
index 921755ba..4c74774c 100644
--- a/plugins/cinterion/mm-broadband-modem-cinterion.c
+++ b/plugins/cinterion/mm-broadband-modem-cinterion.c
@@ -38,10 +38,12 @@ static void iface_modem_init (MMIfaceModem *iface);
static void iface_modem_3gpp_init (MMIfaceModem3gpp *iface);
static void iface_modem_messaging_init (MMIfaceModemMessaging *iface);
+static MMIfaceModem *iface_modem_parent;
+
G_DEFINE_TYPE_EXTENDED (MMBroadbandModemCinterion, mm_broadband_modem_cinterion, MM_TYPE_BROADBAND_MODEM, 0,
G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM, iface_modem_init)
G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_3GPP, iface_modem_3gpp_init)
- G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_MESSAGING, iface_modem_messaging_init));
+ G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_MESSAGING, iface_modem_messaging_init))
struct _MMBroadbandModemCinterionPrivate {
/* Flag to know if we should try AT^SIND or not to get psinfo */
@@ -514,6 +516,80 @@ load_access_technologies (MMIfaceModem *self,
}
/*****************************************************************************/
+/* Load supported modes (Modem interface) */
+
+static GArray *
+load_supported_modes_finish (MMIfaceModem *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error))
+ return NULL;
+
+ return g_array_ref (g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res)));
+}
+
+static void
+parent_load_supported_modes_ready (MMIfaceModem *self,
+ GAsyncResult *res,
+ GSimpleAsyncResult *simple)
+{
+ GError *error = NULL;
+ GArray *all;
+ GArray *combinations;
+ GArray *filtered;
+ MMModemModeCombination mode;
+
+ all = iface_modem_parent->load_supported_modes_finish (self, res, &error);
+ if (!all) {
+ g_simple_async_result_take_error (simple, error);
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+ return;
+ }
+
+ /* Build list of combinations */
+ combinations = g_array_sized_new (FALSE, FALSE, sizeof (MMModemModeCombination), 3);
+
+ /* 2G only */
+ mode.allowed = MM_MODEM_MODE_2G;
+ mode.preferred = MM_MODEM_MODE_NONE;
+ g_array_append_val (combinations, mode);
+ /* 3G only */
+ mode.allowed = MM_MODEM_MODE_3G;
+ mode.preferred = MM_MODEM_MODE_NONE;
+ g_array_append_val (combinations, mode);
+ /* 2G and 3G */
+ mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G);
+ mode.preferred = MM_MODEM_MODE_NONE;
+ g_array_append_val (combinations, mode);
+
+ /* Filter out those unsupported modes */
+ filtered = mm_filter_supported_modes (all, combinations);
+ g_array_unref (all);
+ g_array_unref (combinations);
+
+ g_simple_async_result_set_op_res_gpointer (simple, filtered, (GDestroyNotify) g_array_unref);
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+}
+
+static void
+load_supported_modes (MMIfaceModem *self,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ /* Run parent's loading */
+ iface_modem_parent->load_supported_modes (
+ MM_IFACE_MODEM (self),
+ (GAsyncReadyCallback)parent_load_supported_modes_ready,
+ g_simple_async_result_new (G_OBJECT (self),
+ callback,
+ user_data,
+ load_supported_modes));
+}
+
+/*****************************************************************************/
/* ALLOWED MODES */
static gboolean
@@ -1191,6 +1267,10 @@ finalize (GObject *object)
static void
iface_modem_init (MMIfaceModem *iface)
{
+ iface_modem_parent = g_type_interface_peek_parent (iface);
+
+ iface->load_supported_modes = load_supported_modes;
+ iface->load_supported_modes_finish = load_supported_modes_finish;
iface->set_allowed_modes = set_allowed_modes;
iface->set_allowed_modes_finish = set_allowed_modes_finish;
iface->load_supported_bands = load_supported_bands;
diff --git a/plugins/huawei/mm-broadband-modem-huawei.c b/plugins/huawei/mm-broadband-modem-huawei.c
index 19965b47..410032df 100644
--- a/plugins/huawei/mm-broadband-modem-huawei.c
+++ b/plugins/huawei/mm-broadband-modem-huawei.c
@@ -1075,6 +1075,90 @@ set_current_bands (MMIfaceModem *self,
}
/*****************************************************************************/
+/* Load supported modes (Modem interface) */
+
+static GArray *
+load_supported_modes_finish (MMIfaceModem *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error))
+ return NULL;
+
+ return g_array_ref (g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res)));
+}
+
+static void
+parent_load_supported_modes_ready (MMIfaceModem *self,
+ GAsyncResult *res,
+ GSimpleAsyncResult *simple)
+{
+ GError *error = NULL;
+ GArray *all;
+ GArray *combinations;
+ GArray *filtered;
+ MMModemModeCombination mode;
+
+ all = iface_modem_parent->load_supported_modes_finish (self, res, &error);
+ if (!all) {
+ g_simple_async_result_take_error (simple, error);
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+ return;
+ }
+
+ /* Build list of combinations */
+ combinations = g_array_sized_new (FALSE, FALSE, sizeof (MMModemModeCombination), 5);
+ /* 2G only */
+ mode.allowed = MM_MODEM_MODE_2G;
+ mode.preferred = MM_MODEM_MODE_NONE;
+ g_array_append_val (combinations, mode);
+ /* 3G only */
+ mode.allowed = MM_MODEM_MODE_3G;
+ mode.preferred = MM_MODEM_MODE_NONE;
+ g_array_append_val (combinations, mode);
+ /* 2G and 3G */
+ mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G);
+ mode.preferred = MM_MODEM_MODE_NONE;
+ g_array_append_val (combinations, mode);
+ /* CDMA modems don't support 'preferred' setups */
+ if (!mm_iface_modem_is_cdma_only (self)) {
+ /* 2G and 3G, 2G preferred */
+ mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G);
+ mode.preferred = MM_MODEM_MODE_2G;
+ g_array_append_val (combinations, mode);
+ /* 2G and 3G, 3G preferred */
+ mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G);
+ mode.preferred = MM_MODEM_MODE_3G;
+ g_array_append_val (combinations, mode);
+ }
+
+ /* Filter out those unsupported modes */
+ filtered = mm_filter_supported_modes (all, combinations);
+ g_array_unref (all);
+ g_array_unref (combinations);
+
+ g_simple_async_result_set_op_res_gpointer (simple, filtered, (GDestroyNotify) g_array_unref);
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+}
+
+static void
+load_supported_modes (MMIfaceModem *self,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ /* Run parent's loading */
+ iface_modem_parent->load_supported_modes (
+ MM_IFACE_MODEM (self),
+ (GAsyncReadyCallback)parent_load_supported_modes_ready,
+ g_simple_async_result_new (G_OBJECT (self),
+ callback,
+ user_data,
+ load_supported_modes));
+}
+
+/*****************************************************************************/
/* Load initial allowed/preferred modes (Modem interface) */
static gboolean
@@ -1091,7 +1175,7 @@ parse_prefmode (const gchar *response, MMModemMode *preferred, GError **error)
*preferred = MM_MODEM_MODE_3G;
return TRUE;
} else if (a == 8) {
- *preferred = MM_MODEM_MODE_2G | MM_MODEM_MODE_3G;
+ *preferred = MM_MODEM_MODE_NONE;
return TRUE;
}
@@ -1116,10 +1200,7 @@ load_allowed_modes_finish (MMIfaceModem *self,
return FALSE;
if (mm_iface_modem_is_cdma_only (self)) {
- /* CDMA-only devices always support 2G and 3G if they have 3G, so just
- * use the modes from GCAP as the list of allowed modes.
- */
- *allowed = mm_iface_modem_get_supported_modes (self);
+ *allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G);
return parse_prefmode (response, preferred, error);
}
@@ -2660,6 +2741,8 @@ iface_modem_init (MMIfaceModem *iface)
iface->load_current_bands_finish = load_current_bands_finish;
iface->set_current_bands = set_current_bands;
iface->set_current_bands_finish = set_current_bands_finish;
+ iface->load_supported_modes = load_supported_modes;
+ iface->load_supported_modes_finish = load_supported_modes_finish;
iface->load_allowed_modes = load_allowed_modes;
iface->load_allowed_modes_finish = load_allowed_modes_finish;
iface->set_allowed_modes = set_allowed_modes;
diff --git a/plugins/icera/mm-broadband-modem-icera.c b/plugins/icera/mm-broadband-modem-icera.c
index 7d8661bc..a9fdfe38 100644
--- a/plugins/icera/mm-broadband-modem-icera.c
+++ b/plugins/icera/mm-broadband-modem-icera.c
@@ -40,12 +40,13 @@ static void iface_modem_init (MMIfaceModem *iface);
static void iface_modem_3gpp_init (MMIfaceModem3gpp *iface);
static void iface_modem_time_init (MMIfaceModemTime *iface);
+static MMIfaceModem *iface_modem_parent;
static MMIfaceModem3gpp *iface_modem_3gpp_parent;
G_DEFINE_TYPE_EXTENDED (MMBroadbandModemIcera, mm_broadband_modem_icera, MM_TYPE_BROADBAND_MODEM, 0,
G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM, iface_modem_init)
G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_3GPP, iface_modem_3gpp_init)
- G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_TIME, iface_modem_time_init));
+ G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_TIME, iface_modem_time_init))
enum {
PROP_0,
@@ -67,6 +68,88 @@ struct _MMBroadbandModemIceraPrivate {
};
/*****************************************************************************/
+/* Load supported modes (Modem interface) */
+
+static GArray *
+load_supported_modes_finish (MMIfaceModem *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error))
+ return NULL;
+
+ return g_array_ref (g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res)));
+}
+
+static void
+parent_load_supported_modes_ready (MMIfaceModem *self,
+ GAsyncResult *res,
+ GSimpleAsyncResult *simple)
+{
+ GError *error = NULL;
+ GArray *all;
+ GArray *combinations;
+ GArray *filtered;
+ MMModemModeCombination mode;
+
+ all = iface_modem_parent->load_supported_modes_finish (self, res, &error);
+ if (!all) {
+ g_simple_async_result_take_error (simple, error);
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+ return;
+ }
+
+ /* Build list of combinations */
+ combinations = g_array_sized_new (FALSE, FALSE, sizeof (MMModemModeCombination), 5);
+
+ /* 2G only */
+ mode.allowed = MM_MODEM_MODE_2G;
+ mode.preferred = MM_MODEM_MODE_NONE;
+ g_array_append_val (combinations, mode);
+ /* 3G only */
+ mode.allowed = MM_MODEM_MODE_3G;
+ mode.preferred = MM_MODEM_MODE_NONE;
+ g_array_append_val (combinations, mode);
+ /* 2G and 3G */
+ mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G);
+ mode.preferred = MM_MODEM_MODE_NONE;
+ g_array_append_val (combinations, mode);
+ /* 2G and 3G, 2G preferred */
+ mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G);
+ mode.preferred = MM_MODEM_MODE_2G;
+ g_array_append_val (combinations, mode);
+ /* 2G and 3G, 3G preferred */
+ mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G);
+ mode.preferred = MM_MODEM_MODE_3G;
+ g_array_append_val (combinations, mode);
+
+ /* Filter out those unsupported modes */
+ filtered = mm_filter_supported_modes (all, combinations);
+ g_array_unref (all);
+ g_array_unref (combinations);
+
+ g_simple_async_result_set_op_res_gpointer (simple, filtered, (GDestroyNotify) g_array_unref);
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+}
+
+static void
+load_supported_modes (MMIfaceModem *self,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ /* Run parent's loading */
+ iface_modem_parent->load_supported_modes (
+ MM_IFACE_MODEM (self),
+ (GAsyncReadyCallback)parent_load_supported_modes_ready,
+ g_simple_async_result_new (G_OBJECT (self),
+ callback,
+ user_data,
+ load_supported_modes));
+}
+
+/*****************************************************************************/
/* Load initial allowed/preferred modes (Modem interface) */
static gboolean
@@ -201,7 +284,8 @@ modem_set_allowed_modes (MMIfaceModem *self,
icera_mode = 3;
else /* none preferred, so AUTO */
icera_mode = 5;
- }
+ } else if (allowed == MM_MODEM_MODE_ANY && preferred == MM_MODEM_MODE_NONE)
+ icera_mode = 5;
if (icera_mode < 0) {
gchar *allowed_str;
@@ -1769,6 +1853,10 @@ finalize (GObject *object)
static void
iface_modem_init (MMIfaceModem *iface)
{
+ iface_modem_parent = g_type_interface_peek_parent (iface);
+
+ iface->load_supported_modes = load_supported_modes;
+ iface->load_supported_modes_finish = load_supported_modes_finish;
iface->load_allowed_modes = modem_load_allowed_modes;
iface->load_allowed_modes_finish = modem_load_allowed_modes_finish;
iface->set_allowed_modes = modem_set_allowed_modes;
diff --git a/plugins/iridium/mm-broadband-modem-iridium.c b/plugins/iridium/mm-broadband-modem-iridium.c
index c3c81aaf..b26851b2 100644
--- a/plugins/iridium/mm-broadband-modem-iridium.c
+++ b/plugins/iridium/mm-broadband-modem-iridium.c
@@ -219,13 +219,12 @@ setup_flow_control (MMIfaceModem *self,
/*****************************************************************************/
/* Load supported modes (Modem inteface) */
-static MMModemMode
+static GArray *
load_supported_modes_finish (MMIfaceModem *self,
GAsyncResult *res,
GError **error)
{
- /* Report CS only, Iridium connections are circuit-switched */
- return MM_MODEM_MODE_CS;
+ return g_array_ref (g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res)));
}
static void
@@ -234,11 +233,23 @@ load_supported_modes (MMIfaceModem *self,
gpointer user_data)
{
GSimpleAsyncResult *result;
+ GArray *combinations;
+ MMModemModeCombination mode;
result = g_simple_async_result_new (G_OBJECT (self),
callback,
user_data,
load_supported_modes);
+
+ /* Build list of combinations */
+ combinations = g_array_sized_new (FALSE, FALSE, sizeof (MMModemModeCombination), 1);
+
+ /* Report CS only, Iridium connections are circuit-switched */
+ mode.allowed = MM_MODEM_MODE_CS;
+ mode.preferred = MM_MODEM_MODE_NONE;
+ g_array_append_val (combinations, mode);
+
+ g_simple_async_result_set_op_res_gpointer (result, combinations, (GDestroyNotify) g_array_unref);
g_simple_async_result_complete_in_idle (result);
g_object_unref (result);
}
diff --git a/plugins/linktop/mm-broadband-modem-linktop.c b/plugins/linktop/mm-broadband-modem-linktop.c
index 49722819..bcfa7daf 100644
--- a/plugins/linktop/mm-broadband-modem-linktop.c
+++ b/plugins/linktop/mm-broadband-modem-linktop.c
@@ -40,8 +40,84 @@
static void iface_modem_init (MMIfaceModem *iface);
+static MMIfaceModem *iface_modem_parent;
+
G_DEFINE_TYPE_EXTENDED (MMBroadbandModemLinktop, mm_broadband_modem_linktop, MM_TYPE_BROADBAND_MODEM, 0,
- G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM, iface_modem_init));
+ G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM, iface_modem_init))
+
+/*****************************************************************************/
+/* Load supported modes (Modem interface) */
+
+static GArray *
+load_supported_modes_finish (MMIfaceModem *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error))
+ return NULL;
+
+ return g_array_ref (g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res)));
+}
+
+static void
+parent_load_supported_modes_ready (MMIfaceModem *self,
+ GAsyncResult *res,
+ GSimpleAsyncResult *simple)
+{
+ GError *error = NULL;
+ GArray *all;
+ GArray *combinations;
+ GArray *filtered;
+ MMModemModeCombination mode;
+
+ all = iface_modem_parent->load_supported_modes_finish (self, res, &error);
+ if (!all) {
+ g_simple_async_result_take_error (simple, error);
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+ return;
+ }
+
+ /* Build list of combinations */
+ combinations = g_array_sized_new (FALSE, FALSE, sizeof (MMModemModeCombination), 3);
+
+ /* 2G only */
+ mode.allowed = MM_MODEM_MODE_2G;
+ mode.preferred = MM_MODEM_MODE_NONE;
+ g_array_append_val (combinations, mode);
+ /* 3G only */
+ mode.allowed = MM_MODEM_MODE_3G;
+ mode.preferred = MM_MODEM_MODE_NONE;
+ g_array_append_val (combinations, mode);
+ /* 2G and 3G */
+ mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G);
+ mode.preferred = MM_MODEM_MODE_NONE;
+ g_array_append_val (combinations, mode);
+
+ /* Filter out those unsupported modes */
+ filtered = mm_filter_supported_modes (all, combinations);
+ g_array_unref (all);
+ g_array_unref (combinations);
+
+ g_simple_async_result_set_op_res_gpointer (simple, filtered, (GDestroyNotify) g_array_unref);
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+}
+
+static void
+load_supported_modes (MMIfaceModem *self,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ /* Run parent's loading */
+ iface_modem_parent->load_supported_modes (
+ MM_IFACE_MODEM (self),
+ (GAsyncReadyCallback)parent_load_supported_modes_ready,
+ g_simple_async_result_new (G_OBJECT (self),
+ callback,
+ user_data,
+ load_supported_modes));
+}
/*****************************************************************************/
/* Load initial allowed/preferred modes (Modem interface) */
@@ -158,9 +234,11 @@ set_allowed_modes (MMIfaceModem *self,
else if (allowed == MM_MODEM_MODE_3G)
linktop_mode = LINKTOP_MODE_3G;
else if ((allowed == (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G)) &&
- (preferred == MM_MODEM_MODE_NONE)) {
+ (preferred == MM_MODEM_MODE_NONE))
+ linktop_mode = LINKTOP_MODE_ANY;
+ else if ((allowed == MM_MODEM_MODE_ANY &&
+ preferred == MM_MODEM_MODE_NONE))
linktop_mode = LINKTOP_MODE_ANY;
- }
if (linktop_mode < 0) {
gchar *allowed_str;
@@ -220,6 +298,10 @@ mm_broadband_modem_linktop_init (MMBroadbandModemLinktop *self)
static void
iface_modem_init (MMIfaceModem *iface)
{
+ iface_modem_parent = g_type_interface_peek_parent (iface);
+
+ iface->load_supported_modes = load_supported_modes;
+ iface->load_supported_modes_finish = load_supported_modes_finish;
iface->load_allowed_modes = load_allowed_modes;
iface->load_allowed_modes_finish = load_allowed_modes_finish;
iface->set_allowed_modes = set_allowed_modes;
diff --git a/plugins/longcheer/mm-broadband-modem-longcheer.c b/plugins/longcheer/mm-broadband-modem-longcheer.c
index 949d54d8..3abaaeaf 100644
--- a/plugins/longcheer/mm-broadband-modem-longcheer.c
+++ b/plugins/longcheer/mm-broadband-modem-longcheer.c
@@ -33,8 +33,88 @@
static void iface_modem_init (MMIfaceModem *iface);
+static MMIfaceModem *iface_modem_parent;
+
G_DEFINE_TYPE_EXTENDED (MMBroadbandModemLongcheer, mm_broadband_modem_longcheer, MM_TYPE_BROADBAND_MODEM, 0,
- G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM, iface_modem_init));
+ G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM, iface_modem_init))
+
+/*****************************************************************************/
+/* Load supported modes (Modem interface) */
+
+static GArray *
+load_supported_modes_finish (MMIfaceModem *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error))
+ return NULL;
+
+ return g_array_ref (g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res)));
+}
+
+static void
+parent_load_supported_modes_ready (MMIfaceModem *self,
+ GAsyncResult *res,
+ GSimpleAsyncResult *simple)
+{
+ GError *error = NULL;
+ GArray *all;
+ GArray *combinations;
+ GArray *filtered;
+ MMModemModeCombination mode;
+
+ all = iface_modem_parent->load_supported_modes_finish (self, res, &error);
+ if (!all) {
+ g_simple_async_result_take_error (simple, error);
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+ return;
+ }
+
+ /* Build list of combinations */
+ combinations = g_array_sized_new (FALSE, FALSE, sizeof (MMModemModeCombination), 4);
+
+ /* 2G only */
+ mode.allowed = MM_MODEM_MODE_2G;
+ mode.preferred = MM_MODEM_MODE_NONE;
+ g_array_append_val (combinations, mode);
+ /* 3G only */
+ mode.allowed = MM_MODEM_MODE_3G;
+ mode.preferred = MM_MODEM_MODE_NONE;
+ g_array_append_val (combinations, mode);
+ /* 2G and 3G, 2G preferred */
+ mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G);
+ mode.preferred = MM_MODEM_MODE_2G;
+ g_array_append_val (combinations, mode);
+ /* 2G and 3G, 3G preferred */
+ mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G);
+ mode.preferred = MM_MODEM_MODE_3G;
+ g_array_append_val (combinations, mode);
+
+ /* Filter out those unsupported modes */
+ filtered = mm_filter_supported_modes (all, combinations);
+ g_array_unref (all);
+ g_array_unref (combinations);
+
+ g_simple_async_result_set_op_res_gpointer (simple, filtered, (GDestroyNotify) g_array_unref);
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+}
+
+static void
+load_supported_modes (MMIfaceModem *self,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ /* Run parent's loading */
+ iface_modem_parent->load_supported_modes (
+ MM_IFACE_MODEM (self),
+ (GAsyncReadyCallback)parent_load_supported_modes_ready,
+ g_simple_async_result_new (G_OBJECT (self),
+ callback,
+ user_data,
+ load_supported_modes));
+}
/*****************************************************************************/
/* Load initial allowed/preferred modes (Modem interface) */
@@ -76,16 +156,16 @@ load_allowed_modes_finish (MMIfaceModem *self,
*allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G);
*preferred = MM_MODEM_MODE_3G;
return TRUE;
- case 4:
- /* GSM preferred */
- *allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G);
- *preferred = MM_MODEM_MODE_2G;
- return TRUE;
case 3:
/* GSM only */
*allowed = MM_MODEM_MODE_2G;
*preferred = MM_MODEM_MODE_NONE;
return TRUE;
+ case 4:
+ /* GSM preferred */
+ *allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G);
+ *preferred = MM_MODEM_MODE_2G;
+ return TRUE;
default:
break;
}
@@ -159,14 +239,14 @@ set_allowed_modes (MMIfaceModem *self,
mododr = 3;
else if (allowed == MM_MODEM_MODE_3G)
mododr = 1;
- else if (allowed == MM_MODEM_MODE_ANY || (allowed == (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G))) {
+ else if (allowed == (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G)) {
if (preferred == MM_MODEM_MODE_2G)
mododr = 4;
- else if (preferred == MM_MODEM_MODE_3G ||
- preferred == MM_MODEM_MODE_NONE ||
- preferred == MM_MODEM_MODE_ANY)
+ else if (preferred == MM_MODEM_MODE_3G)
mododr = 2;
- }
+ } else if (allowed == MM_MODEM_MODE_ANY && preferred == MM_MODEM_MODE_NONE)
+ /* Default to 3G preferred */
+ mododr = 2;
if (mododr == 0) {
gchar *allowed_str;
@@ -338,8 +418,12 @@ mm_broadband_modem_longcheer_init (MMBroadbandModemLongcheer *self)
static void
iface_modem_init (MMIfaceModem *iface)
{
+ iface_modem_parent = g_type_interface_peek_parent (iface);
+
iface->load_access_technologies = load_access_technologies;
iface->load_access_technologies_finish = load_access_technologies_finish;
+ iface->load_supported_modes = load_supported_modes;
+ iface->load_supported_modes_finish = load_supported_modes_finish;
iface->load_allowed_modes = load_allowed_modes;
iface->load_allowed_modes_finish = load_allowed_modes_finish;
iface->set_allowed_modes = set_allowed_modes;
diff --git a/plugins/mbm/mm-broadband-modem-mbm.c b/plugins/mbm/mm-broadband-modem-mbm.c
index f75a9a8d..e5eacaf0 100644
--- a/plugins/mbm/mm-broadband-modem-mbm.c
+++ b/plugins/mbm/mm-broadband-modem-mbm.c
@@ -45,6 +45,7 @@
static void iface_modem_init (MMIfaceModem *iface);
static void iface_modem_3gpp_init (MMIfaceModem3gpp *iface);
+static MMIfaceModem *iface_modem_parent;
static MMIfaceModem3gpp *iface_modem_3gpp_parent;
G_DEFINE_TYPE_EXTENDED (MMBroadbandModemMbm, mm_broadband_modem_mbm, MM_TYPE_BROADBAND_MODEM, 0,
@@ -191,6 +192,80 @@ modem_after_sim_unlock (MMIfaceModem *self,
}
/*****************************************************************************/
+/* Load supported modes (Modem interface) */
+
+static GArray *
+load_supported_modes_finish (MMIfaceModem *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error))
+ return NULL;
+
+ return g_array_ref (g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res)));
+}
+
+static void
+parent_load_supported_modes_ready (MMIfaceModem *self,
+ GAsyncResult *res,
+ GSimpleAsyncResult *simple)
+{
+ GError *error = NULL;
+ GArray *all;
+ GArray *combinations;
+ GArray *filtered;
+ MMModemModeCombination mode;
+
+ all = iface_modem_parent->load_supported_modes_finish (self, res, &error);
+ if (!all) {
+ g_simple_async_result_take_error (simple, error);
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+ return;
+ }
+
+ /* Build list of combinations */
+ combinations = g_array_sized_new (FALSE, FALSE, sizeof (MMModemModeCombination), 3);
+
+ /* 2G only */
+ mode.allowed = MM_MODEM_MODE_2G;
+ mode.preferred = MM_MODEM_MODE_NONE;
+ g_array_append_val (combinations, mode);
+ /* 3G only */
+ mode.allowed = MM_MODEM_MODE_3G;
+ mode.preferred = MM_MODEM_MODE_NONE;
+ g_array_append_val (combinations, mode);
+ /* 2G and 3G */
+ mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G);
+ mode.preferred = MM_MODEM_MODE_NONE;
+ g_array_append_val (combinations, mode);
+
+ /* Filter out those unsupported modes */
+ filtered = mm_filter_supported_modes (all, combinations);
+ g_array_unref (all);
+ g_array_unref (combinations);
+
+ g_simple_async_result_set_op_res_gpointer (simple, filtered, (GDestroyNotify) g_array_unref);
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+}
+
+static void
+load_supported_modes (MMIfaceModem *self,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ /* Run parent's loading */
+ iface_modem_parent->load_supported_modes (
+ MM_IFACE_MODEM (self),
+ (GAsyncReadyCallback)parent_load_supported_modes_ready,
+ g_simple_async_result_new (G_OBJECT (self),
+ callback,
+ user_data,
+ load_supported_modes));
+}
+
+/*****************************************************************************/
/* Load initial allowed/preferred modes (Modem interface) */
static gboolean
@@ -1237,12 +1312,16 @@ finalize (GObject *object)
static void
iface_modem_init (MMIfaceModem *iface)
{
+ iface_modem_parent = g_type_interface_peek_parent (iface);
+
iface->create_bearer = modem_create_bearer;
iface->create_bearer_finish = modem_create_bearer_finish;
iface->create_sim = create_sim;
iface->create_sim_finish = create_sim_finish;
iface->modem_after_sim_unlock = modem_after_sim_unlock;
iface->modem_after_sim_unlock_finish = modem_after_sim_unlock_finish;
+ iface->load_supported_modes = load_supported_modes;
+ iface->load_supported_modes_finish = load_supported_modes_finish;
iface->load_allowed_modes = load_allowed_modes;
iface->load_allowed_modes_finish = load_allowed_modes_finish;
iface->set_allowed_modes = set_allowed_modes;
diff --git a/plugins/nokia/mm-broadband-modem-nokia.c b/plugins/nokia/mm-broadband-modem-nokia.c
index 998683c1..a0f870b8 100644
--- a/plugins/nokia/mm-broadband-modem-nokia.c
+++ b/plugins/nokia/mm-broadband-modem-nokia.c
@@ -68,45 +68,6 @@ create_sim (MMIfaceModem *self,
}
/*****************************************************************************/
-/* Load supported modes (Modem interface) */
-
-static MMModemMode
-modem_load_supported_modes_finish (MMIfaceModem *self,
- GAsyncResult *res,
- GError **error)
-{
- return (MMModemMode)GPOINTER_TO_UINT (g_simple_async_result_get_op_res_gpointer (
- G_SIMPLE_ASYNC_RESULT (res)));
-}
-
-static void
-modem_load_supported_modes (MMIfaceModem *self,
- GAsyncReadyCallback callback,
- gpointer user_data)
-{
- GSimpleAsyncResult *result;
- MMModemMode mode;
-
- /* Nokia phones don't seem to like AT+WS46?, they just report 2G even if
- * 3G is supported, so we'll just assume they actually do 3G. */
- mode = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G);
-
- /* Then, if the modem has LTE caps, it does 4G */
- if (mm_iface_modem_is_3gpp_lte (MM_IFACE_MODEM (self)))
- mode |= MM_MODEM_MODE_4G;
-
- result = g_simple_async_result_new (G_OBJECT (self),
- callback,
- user_data,
- modem_load_supported_modes);
- g_simple_async_result_set_op_res_gpointer (result,
- GUINT_TO_POINTER (mode),
- NULL);
- g_simple_async_result_complete_in_idle (result);
- g_object_unref (result);
-}
-
-/*****************************************************************************/
/* Load access technologies (Modem interface) */
typedef struct {
@@ -407,8 +368,6 @@ iface_modem_init (MMIfaceModem *iface)
iface->modem_power_down = NULL;
iface->modem_power_down_finish = NULL;
- iface->load_supported_modes = modem_load_supported_modes;
- iface->load_supported_modes_finish = modem_load_supported_modes_finish;
iface->load_access_technologies = load_access_technologies;
iface->load_access_technologies_finish = load_access_technologies_finish;
}
diff --git a/plugins/novatel/mm-broadband-modem-novatel.c b/plugins/novatel/mm-broadband-modem-novatel.c
index 3d84509b..62f4a3a7 100644
--- a/plugins/novatel/mm-broadband-modem-novatel.c
+++ b/plugins/novatel/mm-broadband-modem-novatel.c
@@ -48,7 +48,89 @@ G_DEFINE_TYPE_EXTENDED (MMBroadbandModemNovatel, mm_broadband_modem_novatel, MM_
G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM, iface_modem_init)
G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_MESSAGING, iface_modem_messaging_init)
G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_CDMA, iface_modem_cdma_init)
- G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_TIME, iface_modem_time_init));
+ G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_TIME, iface_modem_time_init))
+
+/*****************************************************************************/
+/* Load supported modes (Modem interface) */
+
+static GArray *
+load_supported_modes_finish (MMIfaceModem *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error))
+ return NULL;
+
+ return g_array_ref (g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res)));
+}
+
+static void
+parent_load_supported_modes_ready (MMIfaceModem *self,
+ GAsyncResult *res,
+ GSimpleAsyncResult *simple)
+{
+ GError *error = NULL;
+ GArray *all;
+ GArray *combinations;
+ GArray *filtered;
+ MMModemModeCombination mode;
+
+ all = iface_modem_parent->load_supported_modes_finish (self, res, &error);
+ if (!all) {
+ g_simple_async_result_take_error (simple, error);
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+ return;
+ }
+
+ /* Build list of combinations */
+ combinations = g_array_sized_new (FALSE, FALSE, sizeof (MMModemModeCombination), 5);
+
+ /* 2G only */
+ mode.allowed = MM_MODEM_MODE_2G;
+ mode.preferred = MM_MODEM_MODE_NONE;
+ g_array_append_val (combinations, mode);
+ /* 3G only */
+ mode.allowed = MM_MODEM_MODE_3G;
+ mode.preferred = MM_MODEM_MODE_NONE;
+ g_array_append_val (combinations, mode);
+ /* 2G and 3G */
+ mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G);
+ mode.preferred = MM_MODEM_MODE_NONE;
+ g_array_append_val (combinations, mode);
+ /* 2G and 3G, 2G preferred */
+ mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G);
+ mode.preferred = MM_MODEM_MODE_2G;
+ g_array_append_val (combinations, mode);
+ /* 2G and 3G, 3G preferred */
+ mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G);
+ mode.preferred = MM_MODEM_MODE_3G;
+ g_array_append_val (combinations, mode);
+
+ /* Filter out those unsupported modes */
+ filtered = mm_filter_supported_modes (all, combinations);
+ g_array_unref (all);
+ g_array_unref (combinations);
+
+ g_simple_async_result_set_op_res_gpointer (simple, filtered, (GDestroyNotify) g_array_unref);
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+}
+
+static void
+load_supported_modes (MMIfaceModem *self,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ /* Run parent's loading */
+ iface_modem_parent->load_supported_modes (
+ MM_IFACE_MODEM (self),
+ (GAsyncReadyCallback)parent_load_supported_modes_ready,
+ g_simple_async_result_new (G_OBJECT (self),
+ callback,
+ user_data,
+ load_supported_modes));
+}
/*****************************************************************************/
/* Load initial allowed/preferred modes (Modem interface) */
@@ -275,6 +357,10 @@ set_allowed_modes (MMIfaceModem *self,
a = 1;
else if (preferred == MM_MODEM_MODE_3G)
a = 2;
+ } else if (allowed == MM_MODEM_MODE_ANY &&
+ preferred == MM_MODEM_MODE_NONE) {
+ b = 2;
+ a = 0;
}
if (a < 0 || b < 0) {
@@ -1149,6 +1235,8 @@ iface_modem_init (MMIfaceModem *iface)
{
iface_modem_parent = g_type_interface_peek_parent (iface);
+ iface->load_supported_modes = load_supported_modes;
+ iface->load_supported_modes_finish = load_supported_modes_finish;
iface->load_allowed_modes = load_allowed_modes;
iface->load_allowed_modes_finish = load_allowed_modes_finish;
iface->set_allowed_modes = set_allowed_modes;
diff --git a/plugins/option/mm-broadband-modem-option.c b/plugins/option/mm-broadband-modem-option.c
index 4c63f3db..42d9570e 100644
--- a/plugins/option/mm-broadband-modem-option.c
+++ b/plugins/option/mm-broadband-modem-option.c
@@ -35,11 +35,12 @@
static void iface_modem_init (MMIfaceModem *iface);
static void iface_modem_3gpp_init (MMIfaceModem3gpp *iface);
+static MMIfaceModem *iface_modem_parent;
static MMIfaceModem3gpp *iface_modem_3gpp_parent;
G_DEFINE_TYPE_EXTENDED (MMBroadbandModemOption, mm_broadband_modem_option, MM_TYPE_BROADBAND_MODEM, 0,
G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM, iface_modem_init)
- G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_3GPP, iface_modem_3gpp_init));
+ G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_3GPP, iface_modem_3gpp_init))
struct _MMBroadbandModemOptionPrivate {
/* Regex for access-technology related notifications */
@@ -57,6 +58,88 @@ struct _MMBroadbandModemOptionPrivate {
};
/*****************************************************************************/
+/* Load supported modes (Modem interface) */
+
+static GArray *
+load_supported_modes_finish (MMIfaceModem *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error))
+ return NULL;
+
+ return g_array_ref (g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res)));
+}
+
+static void
+parent_load_supported_modes_ready (MMIfaceModem *self,
+ GAsyncResult *res,
+ GSimpleAsyncResult *simple)
+{
+ GError *error = NULL;
+ GArray *all;
+ GArray *combinations;
+ GArray *filtered;
+ MMModemModeCombination mode;
+
+ all = iface_modem_parent->load_supported_modes_finish (self, res, &error);
+ if (!all) {
+ g_simple_async_result_take_error (simple, error);
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+ return;
+ }
+
+ /* Build list of combinations */
+ combinations = g_array_sized_new (FALSE, FALSE, sizeof (MMModemModeCombination), 5);
+
+ /* 2G only */
+ mode.allowed = MM_MODEM_MODE_2G;
+ mode.preferred = MM_MODEM_MODE_NONE;
+ g_array_append_val (combinations, mode);
+ /* 3G only */
+ mode.allowed = MM_MODEM_MODE_3G;
+ mode.preferred = MM_MODEM_MODE_NONE;
+ g_array_append_val (combinations, mode);
+ /* 2G and 3G */
+ mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G);
+ mode.preferred = MM_MODEM_MODE_NONE;
+ g_array_append_val (combinations, mode);
+ /* 2G and 3G, 2G preferred */
+ mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G);
+ mode.preferred = MM_MODEM_MODE_2G;
+ g_array_append_val (combinations, mode);
+ /* 2G and 3G, 3G preferred */
+ mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G);
+ mode.preferred = MM_MODEM_MODE_3G;
+ g_array_append_val (combinations, mode);
+
+ /* Filter out those unsupported modes */
+ filtered = mm_filter_supported_modes (all, combinations);
+ g_array_unref (all);
+ g_array_unref (combinations);
+
+ g_simple_async_result_set_op_res_gpointer (simple, filtered, (GDestroyNotify) g_array_unref);
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+}
+
+static void
+load_supported_modes (MMIfaceModem *self,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ /* Run parent's loading */
+ iface_modem_parent->load_supported_modes (
+ MM_IFACE_MODEM (self),
+ (GAsyncReadyCallback)parent_load_supported_modes_ready,
+ g_simple_async_result_new (G_OBJECT (self),
+ callback,
+ user_data,
+ load_supported_modes));
+}
+
+/*****************************************************************************/
/* Load initial allowed/preferred modes (Modem interface) */
static gboolean
@@ -186,7 +269,8 @@ set_allowed_modes (MMIfaceModem *self,
option_mode = 3;
else /* none preferred, so AUTO */
option_mode = 5;
- }
+ } else if (allowed == MM_MODEM_MODE_ANY && preferred == MM_MODEM_MODE_NONE)
+ option_mode = 5;
if (option_mode < 0) {
gchar *allowed_str;
@@ -1140,10 +1224,14 @@ mm_broadband_modem_option_init (MMBroadbandModemOption *self)
static void
iface_modem_init (MMIfaceModem *iface)
{
+ iface_modem_parent = g_type_interface_peek_parent (iface);
+
iface->modem_after_power_up = modem_after_power_up;
iface->modem_after_power_up_finish = modem_after_power_up_finish;
iface->load_access_technologies = load_access_technologies;
iface->load_access_technologies_finish = load_access_technologies_finish;
+ iface->load_supported_modes = load_supported_modes;
+ iface->load_supported_modes_finish = load_supported_modes_finish;
iface->load_allowed_modes = load_allowed_modes;
iface->load_allowed_modes_finish = load_allowed_modes_finish;
iface->set_allowed_modes = set_allowed_modes;
diff --git a/plugins/sierra/mm-broadband-modem-sierra.c b/plugins/sierra/mm-broadband-modem-sierra.c
index f8cfb743..46d2f3c3 100644
--- a/plugins/sierra/mm-broadband-modem-sierra.c
+++ b/plugins/sierra/mm-broadband-modem-sierra.c
@@ -514,6 +514,109 @@ load_access_technologies (MMIfaceModem *self,
}
/*****************************************************************************/
+/* Load supported modes (Modem interface) */
+
+static GArray *
+load_supported_modes_finish (MMIfaceModem *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error))
+ return NULL;
+
+ return g_array_ref (g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res)));
+}
+
+static void
+parent_load_supported_modes_ready (MMIfaceModem *self,
+ GAsyncResult *res,
+ GSimpleAsyncResult *simple)
+{
+ GError *error = NULL;
+ GArray *all;
+ GArray *combinations;
+ GArray *filtered;
+ MMModemModeCombination mode;
+
+ all = iface_modem_parent->load_supported_modes_finish (self, res, &error);
+ if (!all) {
+ g_simple_async_result_take_error (simple, error);
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+ return;
+ }
+
+ /* CDMA-only modems don't support changing modes, default to parent's */
+ if (!mm_iface_modem_is_3gpp (self)) {
+ g_simple_async_result_set_op_res_gpointer (simple, all, (GDestroyNotify) g_array_unref);
+ g_simple_async_result_complete_in_idle (simple);
+ g_object_unref (simple);
+ return;
+ }
+
+ /* Build list of combinations for 3GPP devices */
+ combinations = g_array_sized_new (FALSE, FALSE, sizeof (MMModemModeCombination), 5);
+
+ /* 2G only */
+ mode.allowed = MM_MODEM_MODE_2G;
+ mode.preferred = MM_MODEM_MODE_NONE;
+ g_array_append_val (combinations, mode);
+ /* 3G only */
+ mode.allowed = MM_MODEM_MODE_3G;
+ mode.preferred = MM_MODEM_MODE_NONE;
+ g_array_append_val (combinations, mode);
+ /* 2G and 3G */
+ mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G);
+ mode.preferred = MM_MODEM_MODE_NONE;
+ g_array_append_val (combinations, mode);
+
+ /* Non-LTE devices allow 2G/3G preferred modes */
+ if (!mm_iface_modem_is_3gpp_lte (self)) {
+ /* 2G and 3G, 2G preferred */
+ mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G);
+ mode.preferred = MM_MODEM_MODE_2G;
+ g_array_append_val (combinations, mode);
+ /* 2G and 3G, 3G preferred */
+ mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G);
+ mode.preferred = MM_MODEM_MODE_3G;
+ g_array_append_val (combinations, mode);
+ } else {
+ /* 4G only */
+ mode.allowed = MM_MODEM_MODE_4G;
+ mode.preferred = MM_MODEM_MODE_NONE;
+ g_array_append_val (combinations, mode);
+ /* 2G, 3G and 4G */
+ mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G);
+ mode.preferred = MM_MODEM_MODE_NONE;
+ g_array_append_val (combinations, mode);
+ }
+
+ /* Filter out those unsupported modes */
+ filtered = mm_filter_supported_modes (all, combinations);
+ g_array_unref (all);
+ g_array_unref (combinations);
+
+ g_simple_async_result_set_op_res_gpointer (simple, filtered, (GDestroyNotify) g_array_unref);
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+}
+
+static void
+load_supported_modes (MMIfaceModem *self,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ /* Run parent's loading */
+ iface_modem_parent->load_supported_modes (
+ MM_IFACE_MODEM (self),
+ (GAsyncReadyCallback)parent_load_supported_modes_ready,
+ g_simple_async_result_new (G_OBJECT (self),
+ callback,
+ user_data,
+ load_supported_modes));
+}
+
+/*****************************************************************************/
/* Load initial allowed/preferred modes (Modem interface) */
typedef struct {
@@ -569,7 +672,10 @@ selrat_query_ready (MMBaseModem *self,
if (mm_get_uint_from_match_info (match_info, 1, &mode) && mode <= 7) {
switch (mode) {
case 0:
- result.allowed = MM_MODEM_MODE_ANY;
+ result.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G);
+ result.preferred = MM_MODEM_MODE_NONE;
+ if (mm_iface_modem_is_3gpp_lte (MM_IFACE_MODEM (self)))
+ result.allowed |= MM_MODEM_MODE_4G;
result.preferred = MM_MODEM_MODE_NONE;
break;
case 1:
@@ -583,7 +689,7 @@ selrat_query_ready (MMBaseModem *self,
case 3:
/* in Sierra LTE devices, mode 3 is automatic, including LTE, no preference */
if (mm_iface_modem_is_3gpp_lte (MM_IFACE_MODEM (self))) {
- result.allowed = MM_MODEM_MODE_ANY;
+ result.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G);
result.preferred = MM_MODEM_MODE_NONE;
} else {
result.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G);
@@ -593,7 +699,7 @@ selrat_query_ready (MMBaseModem *self,
case 4:
/* in Sierra LTE devices, mode 4 is automatic, including LTE, no preference */
if (mm_iface_modem_is_3gpp_lte (MM_IFACE_MODEM (self))) {
- result.allowed = MM_MODEM_MODE_ANY;
+ result.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G);
result.preferred = MM_MODEM_MODE_NONE;
} else {
result.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G);
@@ -773,9 +879,10 @@ set_allowed_modes (MMIfaceModem *self,
idx = 0;
} else if (allowed == MM_MODEM_MODE_4G)
idx = 6;
- else if (allowed == (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G))
+ else if (allowed == (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G) &&
+ preferred == MM_MODEM_MODE_NONE)
idx = 7;
- else if (allowed == MM_MODEM_MODE_ANY)
+ else if (allowed == MM_MODEM_MODE_ANY && preferred == MM_MODEM_MODE_NONE)
idx = 0;
if (idx < 0) {
@@ -1556,6 +1663,8 @@ iface_modem_init (MMIfaceModem *iface)
mm_common_sierra_peek_parent_interfaces (iface);
+ iface->load_supported_modes = load_supported_modes;
+ iface->load_supported_modes_finish = load_supported_modes_finish;
iface->load_allowed_modes = load_allowed_modes;
iface->load_allowed_modes_finish = load_allowed_modes_finish;
iface->set_allowed_modes = set_allowed_modes;
diff --git a/plugins/simtech/mm-broadband-modem-simtech.c b/plugins/simtech/mm-broadband-modem-simtech.c
index 359dde50..f7353d88 100644
--- a/plugins/simtech/mm-broadband-modem-simtech.c
+++ b/plugins/simtech/mm-broadband-modem-simtech.c
@@ -37,11 +37,12 @@
static void iface_modem_init (MMIfaceModem *iface);
static void iface_modem_3gpp_init (MMIfaceModem3gpp *iface);
+static MMIfaceModem *iface_modem_parent;
static MMIfaceModem3gpp *iface_modem_3gpp_parent;
G_DEFINE_TYPE_EXTENDED (MMBroadbandModemSimtech, mm_broadband_modem_simtech, MM_TYPE_BROADBAND_MODEM, 0,
G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM, iface_modem_init)
- G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_3GPP, iface_modem_3gpp_init));
+ G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_3GPP, iface_modem_3gpp_init))
/*****************************************************************************/
/* Setup/Cleanup unsolicited events (3GPP interface) */
@@ -445,6 +446,87 @@ load_access_technologies (MMIfaceModem *self,
}
/*****************************************************************************/
+/* Load supported modes (Modem interface) */
+
+static GArray *
+load_supported_modes_finish (MMIfaceModem *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error))
+ return NULL;
+
+ return g_array_ref (g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res)));
+}
+
+static void
+parent_load_supported_modes_ready (MMIfaceModem *self,
+ GAsyncResult *res,
+ GSimpleAsyncResult *simple)
+{
+ GError *error = NULL;
+ GArray *all;
+ GArray *combinations;
+ GArray *filtered;
+ MMModemModeCombination mode;
+
+ all = iface_modem_parent->load_supported_modes_finish (self, res, &error);
+ if (!all) {
+ g_simple_async_result_take_error (simple, error);
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+ return;
+ }
+
+ /* Build list of combinations */
+ combinations = g_array_sized_new (FALSE, FALSE, sizeof (MMModemModeCombination), 5);
+ /* 2G only */
+ mode.allowed = MM_MODEM_MODE_2G;
+ mode.preferred = MM_MODEM_MODE_NONE;
+ g_array_append_val (combinations, mode);
+ /* 3G only */
+ mode.allowed = MM_MODEM_MODE_3G;
+ mode.preferred = MM_MODEM_MODE_NONE;
+ g_array_append_val (combinations, mode);
+ /* 2G and 3G */
+ mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G);
+ mode.preferred = MM_MODEM_MODE_NONE;
+ g_array_append_val (combinations, mode);
+ /* 2G and 3G, 2G preferred */
+ mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G);
+ mode.preferred = MM_MODEM_MODE_2G;
+ g_array_append_val (combinations, mode);
+ /* 2G and 3G, 3G preferred */
+ mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G);
+ mode.preferred = MM_MODEM_MODE_3G;
+ g_array_append_val (combinations, mode);
+
+ /* Filter out those unsupported modes */
+ filtered = mm_filter_supported_modes (all, combinations);
+ g_array_unref (all);
+ g_array_unref (combinations);
+
+ g_simple_async_result_set_op_res_gpointer (simple, filtered, (GDestroyNotify) g_array_unref);
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+}
+
+static void
+load_supported_modes (MMIfaceModem *self,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ /* Run parent's loading */
+ iface_modem_parent->load_supported_modes (
+ MM_IFACE_MODEM (self),
+ (GAsyncReadyCallback)parent_load_supported_modes_ready,
+ g_simple_async_result_new (G_OBJECT (self),
+ callback,
+ user_data,
+ load_supported_modes));
+}
+
+/*****************************************************************************/
/* Load initial allowed/preferred modes (Modem interface) */
typedef struct {
@@ -731,19 +813,28 @@ set_allowed_modes (MMIfaceModem *self,
user_data,
set_allowed_modes);
- ctx->nmp = 2; /* automatic mode preference */
- ctx->naop = 0; /* automatic acquisition order */
+ /* Defaults: automatic search */
+ ctx->nmp = 2;
+ ctx->naop = 0;
- if (allowed == MM_MODEM_MODE_2G)
+ if (allowed == MM_MODEM_MODE_ANY &&
+ preferred == MM_MODEM_MODE_NONE) {
+ /* defaults nmp and naop */
+ } else if (allowed == MM_MODEM_MODE_2G) {
ctx->nmp = 13;
- else if (allowed == MM_MODEM_MODE_3G)
+ ctx->naop = 0;
+ } else if (allowed == MM_MODEM_MODE_3G) {
ctx->nmp = 14;
- else if (allowed == (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G)) {
+ ctx->naop = 0;
+ } else if (allowed == (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G)) {
+ /* default nmp */
if (preferred == MM_MODEM_MODE_2G)
ctx->naop = 3;
else if (preferred == MM_MODEM_MODE_3G)
ctx->naop = 2;
- /* else, auto */
+ else
+ /* default naop */
+ ctx->naop = 0;
} else {
gchar *allowed_str;
gchar *preferred_str;
@@ -830,8 +921,12 @@ iface_modem_3gpp_init (MMIfaceModem3gpp *iface)
static void
iface_modem_init (MMIfaceModem *iface)
{
+ iface_modem_parent = g_type_interface_peek_parent (iface);
+
iface->load_access_technologies = load_access_technologies;
iface->load_access_technologies_finish = load_access_technologies_finish;
+ iface->load_supported_modes = load_supported_modes;
+ iface->load_supported_modes_finish = load_supported_modes_finish;
iface->load_allowed_modes = load_allowed_modes;
iface->load_allowed_modes_finish = load_allowed_modes_finish;
iface->set_allowed_modes = set_allowed_modes;
diff --git a/plugins/wavecom/mm-broadband-modem-wavecom.c b/plugins/wavecom/mm-broadband-modem-wavecom.c
index 6f487b42..1ee16e99 100644
--- a/plugins/wavecom/mm-broadband-modem-wavecom.c
+++ b/plugins/wavecom/mm-broadband-modem-wavecom.c
@@ -37,6 +37,8 @@
static void iface_modem_init (MMIfaceModem *iface);
+static MMIfaceModem *iface_modem_parent;
+
G_DEFINE_TYPE_EXTENDED (MMBroadbandModemWavecom, mm_broadband_modem_wavecom, MM_TYPE_BROADBAND_MODEM, 0,
G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM, iface_modem_init))
@@ -82,18 +84,17 @@ static const WavecomBand3G bands_3g[] = {
};
/*****************************************************************************/
-/* Supported modes (Modem interface) */
+/* Load supported modes (Modem interface) */
-static MMModemMode
+static GArray *
load_supported_modes_finish (MMIfaceModem *self,
GAsyncResult *res,
GError **error)
{
if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error))
- return MM_MODEM_MODE_NONE;
+ return NULL;
- return (MMModemMode) GPOINTER_TO_UINT (g_simple_async_result_get_op_res_gpointer (
- G_SIMPLE_ASYNC_RESULT (res)));
+ return g_array_ref (g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res)));
}
static void
@@ -101,9 +102,13 @@ supported_ms_classes_query_ready (MMBaseModem *self,
GAsyncResult *res,
GSimpleAsyncResult *simple)
{
+ GArray *all;
+ GArray *combinations;
+ GArray *filtered;
const gchar *response;
GError *error = NULL;
- MMModemMode mode;
+ MMModemModeCombination mode;
+ MMModemMode mode_all;
response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error);
if (!response) {
@@ -115,40 +120,71 @@ supported_ms_classes_query_ready (MMBaseModem *self,
}
response = mm_strip_tag (response, "+CGCLASS:");
- mode = MM_MODEM_MODE_NONE;
-
- if (strstr (response, WAVECOM_MS_CLASS_A_IDSTR)) {
- mm_dbg ("Modem supports Class A mobile station");
- mode |= MM_MODEM_MODE_3G;
- }
-
- if (strstr (response, WAVECOM_MS_CLASS_B_IDSTR)) {
- mm_dbg ("Modem supports Class B mobile station");
- mode |= (MM_MODEM_MODE_2G | MM_MODEM_MODE_CS);
- }
-
- if (strstr (response, WAVECOM_MS_CLASS_CG_IDSTR)) {
- mm_dbg ("Modem supports Class CG mobile station");
- mode |= MM_MODEM_MODE_2G;
- }
-
- if (strstr (response, WAVECOM_MS_CLASS_CC_IDSTR)) {
- mm_dbg ("Modem supports Class CC mobile station");
- mode |= MM_MODEM_MODE_CS;
- }
+ mode_all = MM_MODEM_MODE_NONE;
+ if (strstr (response, WAVECOM_MS_CLASS_A_IDSTR))
+ mode_all |= MM_MODEM_MODE_3G;
+ if (strstr (response, WAVECOM_MS_CLASS_B_IDSTR))
+ mode_all |= (MM_MODEM_MODE_2G | MM_MODEM_MODE_CS);
+ if (strstr (response, WAVECOM_MS_CLASS_CG_IDSTR))
+ mode_all |= MM_MODEM_MODE_2G;
+ if (strstr (response, WAVECOM_MS_CLASS_CC_IDSTR))
+ mode_all |= MM_MODEM_MODE_CS;
/* If none received, error */
- if (mode == MM_MODEM_MODE_NONE)
+ if (mode_all == MM_MODEM_MODE_NONE) {
g_simple_async_result_set_error (simple,
MM_CORE_ERROR,
MM_CORE_ERROR_FAILED,
"Couldn't get supported mobile station classes: '%s'",
response);
- else
- g_simple_async_result_set_op_res_gpointer (simple,
- GUINT_TO_POINTER (mode),
- NULL);
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+ return;
+ }
+ /* Build ALL mask */
+ all = g_array_sized_new (FALSE, FALSE, sizeof (MMModemModeCombination), 1);
+ mode.allowed = mode_all;
+ mode.preferred = MM_MODEM_MODE_NONE;
+ g_array_append_val (all, mode);
+
+ /* Build list of combinations */
+ combinations = g_array_sized_new (FALSE, FALSE, sizeof (MMModemModeCombination), 7);
+ /* CS only */
+ mode.allowed = MM_MODEM_MODE_CS;
+ mode.preferred = MM_MODEM_MODE_NONE;
+ g_array_append_val (combinations, mode);
+ /* 2G only */
+ mode.allowed = MM_MODEM_MODE_2G;
+ mode.preferred = MM_MODEM_MODE_NONE;
+ g_array_append_val (combinations, mode);
+ /* CS and 2G */
+ mode.allowed = (MM_MODEM_MODE_CS | MM_MODEM_MODE_2G);
+ mode.preferred = MM_MODEM_MODE_2G;
+ g_array_append_val (combinations, mode);
+ /* 3G only */
+ mode.allowed = MM_MODEM_MODE_3G;
+ mode.preferred = MM_MODEM_MODE_NONE;
+ g_array_append_val (combinations, mode);
+ /* 2G and 3G */
+ mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G);
+ mode.preferred = MM_MODEM_MODE_NONE;
+ g_array_append_val (combinations, mode);
+ /* 2G and 3G, 2G preferred */
+ mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G);
+ mode.preferred = MM_MODEM_MODE_2G;
+ g_array_append_val (combinations, mode);
+ /* 2G and 3G, 3G preferred */
+ mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G);
+ mode.preferred = MM_MODEM_MODE_3G;
+ g_array_append_val (combinations, mode);
+
+ /* Filter out those unsupported modes */
+ filtered = mm_filter_supported_modes (all, combinations);
+ g_array_unref (all);
+ g_array_unref (combinations);
+
+ g_simple_async_result_set_op_res_gpointer (simple, filtered, (GDestroyNotify) g_array_unref);
g_simple_async_result_complete (simple);
g_object_unref (simple);
}
@@ -158,20 +194,16 @@ load_supported_modes (MMIfaceModem *self,
GAsyncReadyCallback callback,
gpointer user_data)
{
- GSimpleAsyncResult *result;
-
- result = g_simple_async_result_new (G_OBJECT (self),
- callback,
- user_data,
- load_supported_modes);
-
mm_base_modem_at_command (
MM_BASE_MODEM (self),
"+CGCLASS=?",
3,
FALSE,
(GAsyncReadyCallback)supported_ms_classes_query_ready,
- result);
+ g_simple_async_result_new (G_OBJECT (self),
+ callback,
+ user_data,
+ load_supported_modes));
}
/*****************************************************************************/
@@ -387,8 +419,6 @@ load_allowed_modes (MMIfaceModem *self,
typedef struct {
MMBroadbandModemWavecom *self;
GSimpleAsyncResult *result;
- MMModemMode allowed;
- MMModemMode preferred;
gchar *cgclass_command;
gchar *wwsm_command;
} SetAllowedModesContext;
@@ -473,19 +503,27 @@ set_allowed_modes (MMIfaceModem *self,
callback,
user_data,
set_allowed_modes);
- ctx->allowed = allowed;
- ctx->preferred = preferred;
+
+ /* Handle ANY/NONE */
+ if (allowed == MM_MODEM_MODE_ANY && preferred == MM_MODEM_MODE_NONE) {
+ if (mm_iface_modem_is_3g (self)) {
+ allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G);
+ preferred = MM_MODEM_MODE_NONE;
+ } else {
+ allowed = (MM_MODEM_MODE_CS | MM_MODEM_MODE_2G);
+ preferred = MM_MODEM_MODE_2G;
+ }
+ }
if (allowed == MM_MODEM_MODE_CS)
ctx->cgclass_command = g_strdup ("+CGCLASS=" WAVECOM_MS_CLASS_CC_IDSTR);
else if (allowed == MM_MODEM_MODE_2G)
ctx->cgclass_command = g_strdup ("+CGCLASS=" WAVECOM_MS_CLASS_CG_IDSTR);
else if (allowed == (MM_MODEM_MODE_2G | MM_MODEM_MODE_CS) &&
- preferred == MM_MODEM_MODE_NONE)
+ preferred == MM_MODEM_MODE_2G)
ctx->cgclass_command = g_strdup ("+CGCLASS=" WAVECOM_MS_CLASS_B_IDSTR);
else if (allowed & MM_MODEM_MODE_3G) {
- if (allowed == (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G) ||
- allowed == (MM_MODEM_MODE_CS | MM_MODEM_MODE_2G | MM_MODEM_MODE_3G)) {
+ if (allowed == (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G)) {
if (preferred == MM_MODEM_MODE_2G)
ctx->wwsm_command = g_strdup ("+WWSM=2,1");
else if (preferred == MM_MODEM_MODE_3G)
@@ -1144,6 +1182,8 @@ mm_broadband_modem_wavecom_init (MMBroadbandModemWavecom *self)
static void
iface_modem_init (MMIfaceModem *iface)
{
+ iface_modem_parent = g_type_interface_peek_parent (iface);
+
iface->load_supported_modes = load_supported_modes;
iface->load_supported_modes_finish = load_supported_modes_finish;
iface->load_allowed_modes = load_allowed_modes;
diff --git a/plugins/x22x/mm-broadband-modem-x22x.c b/plugins/x22x/mm-broadband-modem-x22x.c
index 2120b6d2..3afb08cb 100644
--- a/plugins/x22x/mm-broadband-modem-x22x.c
+++ b/plugins/x22x/mm-broadband-modem-x22x.c
@@ -33,8 +33,83 @@
static void iface_modem_init (MMIfaceModem *iface);
+static MMIfaceModem *iface_modem_parent;
+
G_DEFINE_TYPE_EXTENDED (MMBroadbandModemX22x, mm_broadband_modem_x22x, MM_TYPE_BROADBAND_MODEM, 0,
- G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM, iface_modem_init));
+ G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM, iface_modem_init))
+
+/*****************************************************************************/
+/* Load supported modes (Modem interface) */
+
+static GArray *
+load_supported_modes_finish (MMIfaceModem *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error))
+ return NULL;
+
+ return g_array_ref (g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res)));
+}
+
+static void
+parent_load_supported_modes_ready (MMIfaceModem *self,
+ GAsyncResult *res,
+ GSimpleAsyncResult *simple)
+{
+ GError *error = NULL;
+ GArray *all;
+ GArray *combinations;
+ GArray *filtered;
+ MMModemModeCombination mode;
+
+ all = iface_modem_parent->load_supported_modes_finish (self, res, &error);
+ if (!all) {
+ g_simple_async_result_take_error (simple, error);
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+ return;
+ }
+ /* Build list of combinations for 3GPP devices */
+ combinations = g_array_sized_new (FALSE, FALSE, sizeof (MMModemModeCombination), 3);
+
+ /* 2G only */
+ mode.allowed = MM_MODEM_MODE_2G;
+ mode.preferred = MM_MODEM_MODE_NONE;
+ g_array_append_val (combinations, mode);
+ /* 3G only */
+ mode.allowed = MM_MODEM_MODE_3G;
+ mode.preferred = MM_MODEM_MODE_NONE;
+ g_array_append_val (combinations, mode);
+ /* 2G and 3G */
+ mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G);
+ mode.preferred = MM_MODEM_MODE_NONE;
+ g_array_append_val (combinations, mode);
+
+ /* Filter out those unsupported modes */
+ filtered = mm_filter_supported_modes (all, combinations);
+ g_array_unref (all);
+ g_array_unref (combinations);
+
+ g_simple_async_result_set_op_res_gpointer (simple, filtered, (GDestroyNotify) g_array_unref);
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+}
+
+static void
+load_supported_modes (MMIfaceModem *self,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ /* Run parent's loading */
+ iface_modem_parent->load_supported_modes (
+ MM_IFACE_MODEM (self),
+ (GAsyncReadyCallback)parent_load_supported_modes_ready,
+ g_simple_async_result_new (G_OBJECT (self),
+ callback,
+ user_data,
+ load_supported_modes));
+}
/*****************************************************************************/
/* Load initial allowed/preferred modes (Modem interface) */
@@ -168,7 +243,8 @@ set_allowed_modes (MMIfaceModem *self,
else if (allowed == MM_MODEM_MODE_ANY &&
preferred == MM_MODEM_MODE_NONE)
syssel = 0;
- else if (allowed == (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G))
+ else if (allowed == (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G) &&
+ preferred == MM_MODEM_MODE_NONE)
syssel = 0;
else {
gchar *allowed_str;
@@ -264,8 +340,12 @@ mm_broadband_modem_x22x_init (MMBroadbandModemX22x *self)
static void
iface_modem_init (MMIfaceModem *iface)
{
+ iface_modem_parent = g_type_interface_peek_parent (iface);
+
iface->load_access_technologies = load_access_technologies;
iface->load_access_technologies_finish = load_access_technologies_finish;
+ iface->load_supported_modes = load_supported_modes;
+ iface->load_supported_modes_finish = load_supported_modes_finish;
iface->load_allowed_modes = load_allowed_modes;
iface->load_allowed_modes_finish = load_allowed_modes_finish;
iface->set_allowed_modes = set_allowed_modes;
diff --git a/plugins/zte/mm-broadband-modem-zte.c b/plugins/zte/mm-broadband-modem-zte.c
index e7d190ad..d4f4f0f8 100644
--- a/plugins/zte/mm-broadband-modem-zte.c
+++ b/plugins/zte/mm-broadband-modem-zte.c
@@ -250,6 +250,100 @@ modem_power_down (MMIfaceModem *self,
}
/*****************************************************************************/
+/* Load supported modes (Modem interface) */
+
+static GArray *
+load_supported_modes_finish (MMIfaceModem *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error))
+ return NULL;
+
+ return g_array_ref (g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res)));
+}
+
+static void
+parent_load_supported_modes_ready (MMIfaceModem *self,
+ GAsyncResult *res,
+ GSimpleAsyncResult *simple)
+{
+ GError *error = NULL;
+ GArray *all;
+ GArray *combinations;
+ GArray *filtered;
+ MMModemModeCombination mode;
+
+ all = iface_modem_parent->load_supported_modes_finish (self, res, &error);
+ if (!all) {
+ g_simple_async_result_take_error (simple, error);
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+ return;
+ }
+
+ /* Build list of combinations */
+ combinations = g_array_sized_new (FALSE, FALSE, sizeof (MMModemModeCombination), 5);
+
+ /* 2G only */
+ mode.allowed = MM_MODEM_MODE_2G;
+ mode.preferred = MM_MODEM_MODE_NONE;
+ g_array_append_val (combinations, mode);
+ /* 3G only */
+ mode.allowed = MM_MODEM_MODE_3G;
+ mode.preferred = MM_MODEM_MODE_NONE;
+ g_array_append_val (combinations, mode);
+
+ if (!mm_iface_modem_is_3gpp_lte (self)) {
+ /* 2G and 3G */
+ mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G);
+ mode.preferred = MM_MODEM_MODE_NONE;
+ g_array_append_val (combinations, mode);
+ /* 2G and 3G, 2G preferred */
+ mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G);
+ mode.preferred = MM_MODEM_MODE_2G;
+ g_array_append_val (combinations, mode);
+ /* 2G and 3G, 3G preferred */
+ mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G);
+ mode.preferred = MM_MODEM_MODE_3G;
+ g_array_append_val (combinations, mode);
+ } else {
+ /* 4G only */
+ mode.allowed = MM_MODEM_MODE_4G;
+ mode.preferred = MM_MODEM_MODE_NONE;
+ g_array_append_val (combinations, mode);
+ /* 2G, 3G and 4G */
+ mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G);
+ mode.preferred = MM_MODEM_MODE_NONE;
+ g_array_append_val (combinations, mode);
+ }
+
+ /* Filter out those unsupported modes */
+ filtered = mm_filter_supported_modes (all, combinations);
+ g_array_unref (all);
+ g_array_unref (combinations);
+
+ g_simple_async_result_set_op_res_gpointer (simple, filtered, (GDestroyNotify) g_array_unref);
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+}
+
+static void
+load_supported_modes (MMIfaceModem *self,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ /* Run parent's loading */
+ iface_modem_parent->load_supported_modes (
+ MM_IFACE_MODEM (self),
+ (GAsyncReadyCallback)parent_load_supported_modes_ready,
+ g_simple_async_result_new (G_OBJECT (self),
+ callback,
+ user_data,
+ load_supported_modes));
+}
+
+/*****************************************************************************/
/* Load initial allowed/preferred modes (Modem interface) */
static gboolean
@@ -413,7 +507,12 @@ set_allowed_modes (MMIfaceModem *self,
pref_acq = 2;
else /* none preferred, so AUTO */
pref_acq = 0;
- } else if (allowed == (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G)) {
+ } else if (allowed == (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G) &&
+ preferred == MM_MODEM_MODE_NONE) {
+ cm_mode = 0;
+ pref_acq = 0;
+ } else if (allowed == MM_MODEM_MODE_ANY &&
+ preferred == MM_MODEM_MODE_NONE) {
cm_mode = 0;
pref_acq = 0;
} else if (allowed == MM_MODEM_MODE_4G) {
@@ -679,6 +778,8 @@ iface_modem_init (MMIfaceModem *iface)
iface->modem_power_down_finish = modem_power_down_finish;
iface->load_access_technologies = load_access_technologies;
iface->load_access_technologies_finish = load_access_technologies_finish;
+ iface->load_supported_modes = load_supported_modes;
+ iface->load_supported_modes_finish = load_supported_modes_finish;
iface->load_allowed_modes = load_allowed_modes;
iface->load_allowed_modes_finish = load_allowed_modes_finish;
iface->set_allowed_modes = set_allowed_modes;
diff --git a/src/mm-broadband-modem-mbim.c b/src/mm-broadband-modem-mbim.c
index cdb5ea64..5c9f3478 100644
--- a/src/mm-broadband-modem-mbim.c
+++ b/src/mm-broadband-modem-mbim.c
@@ -370,62 +370,74 @@ modem_load_device_identifier (MMIfaceModem *self,
/*****************************************************************************/
/* Supported modes loading (Modem interface) */
-static MMModemMode
-modem_load_supported_modes_finish (MMIfaceModem *_self,
+static GArray *
+modem_load_supported_modes_finish (MMIfaceModem *self,
GAsyncResult *res,
GError **error)
{
- MMModemMode mask;
+ return g_array_ref (g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res)));
+}
+
+static void
+modem_load_supported_modes (MMIfaceModem *_self,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
MMBroadbandModemMbim *self = MM_BROADBAND_MODEM_MBIM (_self);
+ GArray *combinations;
+ MMModemModeCombination mode;
+ GSimpleAsyncResult *result;
+ MMModemMode all;
+
+ /* Just complete */
+ result = g_simple_async_result_new (G_OBJECT (self),
+ callback,
+ user_data,
+ modem_load_supported_modes);
+
if (self->priv->caps_data_class == 0) {
- g_set_error (error,
- MM_CORE_ERROR,
- MM_CORE_ERROR_FAILED,
- "Data class not given in device capabilities");
- return MM_MODEM_MODE_NONE;
+ g_simple_async_result_set_error (result,
+ MM_CORE_ERROR,
+ MM_CORE_ERROR_FAILED,
+ "Data class not given in device capabilities");
+ g_simple_async_result_complete_in_idle (result);
+ g_object_unref (result);
+ return;
}
- mask = 0;
+ all = 0;
/* 3GPP... */
if (self->priv->caps_data_class & (MBIM_DATA_CLASS_GPRS |
MBIM_DATA_CLASS_EDGE))
- mask |= MM_MODEM_MODE_2G;
+ all |= MM_MODEM_MODE_2G;
if (self->priv->caps_data_class & (MBIM_DATA_CLASS_UMTS |
MBIM_DATA_CLASS_HSDPA |
MBIM_DATA_CLASS_HSUPA))
- mask |= MM_MODEM_MODE_3G;
+ all |= MM_MODEM_MODE_3G;
if (self->priv->caps_data_class & MBIM_DATA_CLASS_LTE)
- mask |= MM_MODEM_MODE_4G;
+ all |= MM_MODEM_MODE_4G;
/* 3GPP2... */
if (self->priv->caps_data_class & MBIM_DATA_CLASS_1XRTT)
- mask |= MM_MODEM_MODE_2G;
+ all |= MM_MODEM_MODE_2G;
if (self->priv->caps_data_class & (MBIM_DATA_CLASS_1XEVDO |
MBIM_DATA_CLASS_1XEVDO_REVA |
MBIM_DATA_CLASS_1XEVDV |
MBIM_DATA_CLASS_3XRTT |
MBIM_DATA_CLASS_1XEVDO_REVB))
- mask |= MM_MODEM_MODE_3G;
+ all |= MM_MODEM_MODE_3G;
if (self->priv->caps_data_class & MBIM_DATA_CLASS_UMB)
- mask |= MM_MODEM_MODE_4G;
+ all |= MM_MODEM_MODE_4G;
- return mask;
-}
-
-static void
-modem_load_supported_modes (MMIfaceModem *self,
- GAsyncReadyCallback callback,
- gpointer user_data)
-{
- GSimpleAsyncResult *result;
+ /* Build a mask with all supported modes */
+ combinations = g_array_sized_new (FALSE, FALSE, sizeof (MMModemModeCombination), 1);
+ mode.allowed = all;
+ mode.preferred = MM_MODEM_MODE_NONE;
+ g_array_append_val (combinations, mode);
- /* Just complete */
- result = g_simple_async_result_new (G_OBJECT (self),
- callback,
- user_data,
- modem_load_supported_modes);
+ g_simple_async_result_set_op_res_gpointer (result, combinations, (GDestroyNotify) g_array_unref);
g_simple_async_result_complete_in_idle (result);
g_object_unref (result);
}
diff --git a/src/mm-broadband-modem-qmi.c b/src/mm-broadband-modem-qmi.c
index 77d93754..853d940f 100644
--- a/src/mm-broadband-modem-qmi.c
+++ b/src/mm-broadband-modem-qmi.c
@@ -65,6 +65,9 @@ struct _MMBroadbandModemQmiPrivate {
gchar *meid;
gchar *esn;
+ /* Cached supported radio interfaces; in order to load supported modes */
+ GArray *supported_radio_interfaces;
+
/* Cached supported frequency bands; in order to handle ANY */
GArray *supported_bands;
@@ -554,6 +557,20 @@ modem_load_current_capabilities (MMIfaceModem *self,
/*****************************************************************************/
/* Modem Capabilities loading (Modem interface) */
+typedef struct {
+ MMBroadbandModemQmi *self;
+ GSimpleAsyncResult *result;
+} LoadModemCapabilitiesContext;
+
+static void
+load_modem_capabilities_context_complete_and_free (LoadModemCapabilitiesContext *ctx)
+{
+ g_simple_async_result_complete (ctx->result);
+ g_object_unref (ctx->result);
+ g_object_unref (ctx->self);
+ g_slice_free (LoadModemCapabilitiesContext, ctx);
+}
+
static MMModemCapability
modem_load_modem_capabilities_finish (MMIfaceModem *self,
GAsyncResult *res,
@@ -577,7 +594,7 @@ modem_load_modem_capabilities_finish (MMIfaceModem *self,
static void
dms_get_capabilities_ready (QmiClientDms *client,
GAsyncResult *res,
- GSimpleAsyncResult *simple)
+ LoadModemCapabilitiesContext *ctx)
{
QmiMessageDmsGetCapabilitiesOutput *output = NULL;
GError *error = NULL;
@@ -585,10 +602,10 @@ dms_get_capabilities_ready (QmiClientDms *client,
output = qmi_client_dms_get_capabilities_finish (client, res, &error);
if (!output) {
g_prefix_error (&error, "QMI operation failed: ");
- g_simple_async_result_take_error (simple, error);
+ g_simple_async_result_take_error (ctx->result, error);
} else if (!qmi_message_dms_get_capabilities_output_get_result (output, &error)) {
g_prefix_error (&error, "Couldn't get modem capabilities: ");
- g_simple_async_result_take_error (simple, error);
+ g_simple_async_result_take_error (ctx->result, error);
} else {
guint i;
guint mask = MM_MODEM_CAPABILITY_NONE;
@@ -609,7 +626,12 @@ dms_get_capabilities_ready (QmiClientDms *client,
i));
}
- g_simple_async_result_set_op_res_gpointer (simple,
+ /* Cache supported radio interfaces */
+ if (ctx->self->priv->supported_radio_interfaces)
+ g_array_unref (ctx->self->priv->supported_radio_interfaces);
+ ctx->self->priv->supported_radio_interfaces = g_array_ref (radio_interface_list);
+
+ g_simple_async_result_set_op_res_gpointer (ctx->result,
GUINT_TO_POINTER (mask),
NULL);
}
@@ -617,8 +639,7 @@ dms_get_capabilities_ready (QmiClientDms *client,
if (output)
qmi_message_dms_get_capabilities_output_unref (output);
- g_simple_async_result_complete (simple);
- g_object_unref (simple);
+ load_modem_capabilities_context_complete_and_free (ctx);
}
static void
@@ -626,7 +647,7 @@ modem_load_modem_capabilities (MMIfaceModem *self,
GAsyncReadyCallback callback,
gpointer user_data)
{
- GSimpleAsyncResult *result;
+ LoadModemCapabilitiesContext *ctx;
QmiClient *client = NULL;
if (!ensure_qmi_client (MM_BROADBAND_MODEM_QMI (self),
@@ -634,10 +655,12 @@ modem_load_modem_capabilities (MMIfaceModem *self,
callback, user_data))
return;
- result = g_simple_async_result_new (G_OBJECT (self),
- callback,
- user_data,
- modem_load_modem_capabilities);
+ ctx = g_slice_new (LoadModemCapabilitiesContext);
+ ctx->self = g_object_ref (self);
+ ctx->result = g_simple_async_result_new (G_OBJECT (self),
+ callback,
+ user_data,
+ modem_load_modem_capabilities);
mm_dbg ("loading modem capabilities...");
qmi_client_dms_get_capabilities (QMI_CLIENT_DMS (client),
@@ -645,7 +668,7 @@ modem_load_modem_capabilities (MMIfaceModem *self,
5,
NULL,
(GAsyncReadyCallback)dms_get_capabilities_ready,
- result);
+ ctx);
}
/*****************************************************************************/
@@ -1711,37 +1734,89 @@ set_current_bands (MMIfaceModem *_self,
/*****************************************************************************/
/* Load supported modes (Modem interface) */
-static MMModemMode
+static GArray *
modem_load_supported_modes_finish (MMIfaceModem *self,
GAsyncResult *res,
GError **error)
{
- return (MMModemMode)GPOINTER_TO_UINT (g_simple_async_result_get_op_res_gpointer (
- G_SIMPLE_ASYNC_RESULT (res)));
+ return g_array_ref (g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res)));
}
static void
-modem_load_supported_modes (MMIfaceModem *self,
+modem_load_supported_modes (MMIfaceModem *_self,
GAsyncReadyCallback callback,
gpointer user_data)
{
+ MMBroadbandModemQmi *self = MM_BROADBAND_MODEM_QMI (_self);
GSimpleAsyncResult *result;
- MMModemMode mode;
-
- /* For QMI-powered modems, it is safe to assume they do 2G and 3G */
- mode = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G);
-
- /* Then, if the modem has LTE caps, it does 4G */
- if (mm_iface_modem_is_3gpp_lte (MM_IFACE_MODEM (self)))
- mode |= MM_MODEM_MODE_4G;
+ GArray *all;
+ GArray *combinations;
+ GArray *filtered;
+ MMModemModeCombination mode;
+ guint i;
result = g_simple_async_result_new (G_OBJECT (self),
callback,
user_data,
modem_load_supported_modes);
- g_simple_async_result_set_op_res_gpointer (result,
- GUINT_TO_POINTER (mode),
- NULL);
+
+ if (!self->priv->supported_radio_interfaces) {
+ g_simple_async_result_set_error (result,
+ MM_CORE_ERROR,
+ MM_CORE_ERROR_FAILED,
+ "Cannot load supported modes, no radio interface list");
+ g_simple_async_result_complete_in_idle (result);
+ g_object_unref (result);
+ return;
+ }
+
+ /* Build all, based on the supported radio interfaces */
+ mode.allowed = MM_MODEM_MODE_NONE;
+ for (i = 0; i < self->priv->supported_radio_interfaces->len; i++)
+ mode.allowed |= mm_modem_mode_from_qmi_radio_interface (g_array_index (self->priv->supported_radio_interfaces,
+ QmiDmsRadioInterface,
+ i));
+ mode.preferred = MM_MODEM_MODE_NONE;
+ all = g_array_sized_new (FALSE, FALSE, sizeof (MMModemModeCombination), 1);
+ g_array_append_val (all, mode);
+
+ /* Build combinations */
+ combinations = g_array_sized_new (FALSE, FALSE, sizeof (MMModemModeCombination), 7);
+ /* 2G only */
+ mode.allowed = MM_MODEM_MODE_2G;
+ mode.preferred = MM_MODEM_MODE_NONE;
+ g_array_append_val (combinations, mode);
+ /* 3G only */
+ mode.allowed = MM_MODEM_MODE_3G;
+ mode.preferred = MM_MODEM_MODE_NONE;
+ g_array_append_val (combinations, mode);
+ /* 2G and 3G */
+ mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G);
+ mode.preferred = MM_MODEM_MODE_NONE;
+ g_array_append_val (combinations, mode);
+ /* 2G and 3G, 2G preferred */
+ mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G);
+ mode.preferred = MM_MODEM_MODE_2G;
+ g_array_append_val (combinations, mode);
+ /* 2G and 3G, 3G preferred */
+ mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G);
+ mode.preferred = MM_MODEM_MODE_3G;
+ g_array_append_val (combinations, mode);
+ /* 4G only */
+ mode.allowed = MM_MODEM_MODE_4G;
+ mode.preferred = MM_MODEM_MODE_NONE;
+ g_array_append_val (combinations, mode);
+ /* 2G, 3G and 4G */
+ mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G);
+ mode.preferred = MM_MODEM_MODE_NONE;
+ g_array_append_val (combinations, mode);
+
+ /* Filter out those unsupported modes */
+ filtered = mm_filter_supported_modes (all, combinations);
+ g_array_unref (all);
+ g_array_unref (combinations);
+
+ g_simple_async_result_set_op_res_gpointer (result, filtered, (GDestroyNotify) g_array_unref);
g_simple_async_result_complete_in_idle (result);
g_object_unref (result);
}
@@ -2842,8 +2917,16 @@ set_allowed_modes (MMIfaceModem *self,
callback,
user_data,
set_allowed_modes);
- ctx->allowed = allowed;
- ctx->preferred = preferred;
+
+ if (allowed == MM_MODEM_MODE_ANY && ctx->preferred == MM_MODEM_MODE_NONE) {
+ ctx->allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G);
+ ctx->preferred = MM_MODEM_MODE_NONE;
+ if (mm_iface_modem_is_3gpp_lte (self))
+ ctx->allowed |= MM_MODEM_MODE_4G;
+ } else {
+ ctx->allowed = allowed;
+ ctx->preferred = preferred;
+ }
/* System selection preference introduced in NAS 1.1 */
ctx->run_set_system_selection_preference = qmi_client_check_version (client, 1, 1);
@@ -8074,6 +8157,8 @@ finalize (GObject *object)
g_free (self->priv->current_operator_description);
if (self->priv->supported_bands)
g_array_unref (self->priv->supported_bands);
+ if (self->priv->supported_radio_interfaces)
+ g_array_unref (self->priv->supported_radio_interfaces);
G_OBJECT_CLASS (mm_broadband_modem_qmi_parent_class)->finalize (object);
}
diff --git a/src/mm-broadband-modem.c b/src/mm-broadband-modem.c
index 71045484..985ae354 100644
--- a/src/mm-broadband-modem.c
+++ b/src/mm-broadband-modem.c
@@ -1286,19 +1286,28 @@ load_supported_modes_context_complete_and_free (LoadSupportedModesContext *ctx)
g_simple_async_result_complete (ctx->result);
g_object_unref (ctx->result);
g_object_unref (ctx->self);
- g_free (ctx);
+ g_slice_free (LoadSupportedModesContext, ctx);
}
-static MMModemMode
+static GArray *
modem_load_supported_modes_finish (MMIfaceModem *self,
GAsyncResult *res,
GError **error)
{
+ GArray *modes;
+ MMModemModeCombination mode;
+
if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error))
- return MM_MODEM_MODE_NONE;
+ return NULL;
+
+ /* Build a mask with all supported modes */
+ modes = g_array_sized_new (FALSE, FALSE, sizeof (MMModemModeCombination), 1);
+ mode.allowed = (MMModemMode) GPOINTER_TO_UINT (g_simple_async_result_get_op_res_gpointer (
+ G_SIMPLE_ASYNC_RESULT (res)));
+ mode.preferred = MM_MODEM_MODE_NONE;
+ g_array_append_val (modes, mode);
- return (MMModemMode)GPOINTER_TO_UINT (g_simple_async_result_get_op_res_gpointer (
- G_SIMPLE_ASYNC_RESULT (res)));
+ return modes;
}
static void load_supported_modes_step (LoadSupportedModesContext *ctx);
@@ -1515,8 +1524,8 @@ modem_load_supported_modes (MMIfaceModem *self,
{
LoadSupportedModesContext *ctx;
- mm_dbg ("loading initial supported modes...");
- ctx = g_new0 (LoadSupportedModesContext, 1);
+ mm_dbg ("loading supported modes...");
+ ctx = g_slice_new0 (LoadSupportedModesContext);
ctx->self = g_object_ref (self);
ctx->result = g_simple_async_result_new (G_OBJECT (self),
callback,
diff --git a/src/mm-iface-modem.c b/src/mm-iface-modem.c
index 8e264629..135f18f0 100644
--- a/src/mm-iface-modem.c
+++ b/src/mm-iface-modem.c
@@ -2178,9 +2178,11 @@ mm_iface_modem_set_allowed_modes (MMIfaceModem *self,
GAsyncReadyCallback callback,
gpointer user_data)
{
+ GArray *supported;
SetAllowedModesContext *ctx;
- MMModemMode supported;
- MMModemMode not_supported;
+ MMModemMode current_allowed;
+ MMModemMode current_preferred;
+ guint i;
/* If setting allowed modes is not implemented, report an error */
if (!MM_IFACE_MODEM_GET_INTERFACE (self)->set_allowed_modes ||
@@ -2201,6 +2203,8 @@ mm_iface_modem_set_allowed_modes (MMIfaceModem *self,
callback,
user_data,
mm_iface_modem_set_allowed_modes);
+ ctx->allowed = allowed;
+ ctx->preferred = preferred;
g_object_get (self,
MM_IFACE_MODEM_DBUS_SKELETON, &ctx->skeleton,
NULL);
@@ -2214,43 +2218,58 @@ mm_iface_modem_set_allowed_modes (MMIfaceModem *self,
}
/* Get list of supported modes */
- supported = mm_gdbus_modem_get_supported_modes (ctx->skeleton);
-
- /* Whenever we get 'any', just reset to be equal to the list of supported modes */
- if (allowed == MM_MODEM_MODE_ANY)
- allowed = supported;
-
- ctx->allowed = allowed;
- ctx->preferred = preferred;
+ supported = mm_common_mode_combinations_variant_to_garray (
+ mm_gdbus_modem_get_supported_modes (ctx->skeleton));
- /* Check if we already are in the requested setup */
- if (mm_gdbus_modem_get_allowed_modes (ctx->skeleton) == allowed &&
- mm_gdbus_modem_get_preferred_mode (ctx->skeleton) == preferred) {
- g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE);
+ /* Don't allow mode switchin if only one item given in the supported list */
+ if (supported->len == 1) {
+ g_simple_async_result_set_error (ctx->result,
+ MM_CORE_ERROR,
+ MM_CORE_ERROR_UNSUPPORTED,
+ "Cannot change modes: only one combination supported");
+ g_array_unref (supported);
set_allowed_modes_context_complete_and_free (ctx);
return;
}
- /* Check if any of the modes being allowed is not supported */
- not_supported = ((supported ^ allowed) & allowed);
+ if (allowed == MM_MODEM_MODE_ANY &&
+ preferred == MM_MODEM_MODE_NONE) {
+ /* Allow allowed=ANY & preferred=NONE, all plugins should support it */
+ } else {
+ gboolean matched = FALSE;
+
+ /* Check if the given combination is supported */
+ for (i = 0; !matched && i < supported->len; i++) {
+ MMModemModeCombination *supported_mode;
+
+ supported_mode = &g_array_index (supported, MMModemModeCombination, i);
+ if ((supported_mode->allowed == MM_MODEM_MODE_ANY &&
+ supported_mode->preferred == MM_MODEM_MODE_NONE) ||
+ (supported_mode->allowed == allowed &&
+ supported_mode->preferred == preferred)) {
+ matched = TRUE;
+ }
+ }
- /* Ensure allowed is a subset of supported */
- if (not_supported) {
- gchar *not_supported_str;
- gchar *supported_str;
+ if (!matched) {
+ g_simple_async_result_set_error (ctx->result,
+ MM_CORE_ERROR,
+ MM_CORE_ERROR_UNSUPPORTED,
+ "The given combination of allowed and preferred modes is not supported");
+ g_array_unref (supported);
+ set_allowed_modes_context_complete_and_free (ctx);
+ return;
+ }
+ }
- not_supported_str = mm_modem_mode_build_string_from_mask (not_supported);
- supported_str = mm_modem_mode_build_string_from_mask (supported);
- g_simple_async_result_set_error (ctx->result,
- MM_CORE_ERROR,
- MM_CORE_ERROR_UNSUPPORTED,
- "Some of the allowed modes (%s) are not "
- "supported (%s)",
- not_supported_str,
- supported_str);
- g_free (supported_str);
- g_free (not_supported_str);
+ g_array_unref (supported);
+ /* Check if we already are in the requested setup */
+ current_allowed = mm_gdbus_modem_get_allowed_modes (ctx->skeleton);
+ current_preferred = mm_gdbus_modem_get_preferred_mode (ctx->skeleton);
+ if (current_allowed == allowed &&
+ current_preferred == preferred) {
+ g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE);
set_allowed_modes_context_complete_and_free (ctx);
return;
}
@@ -2275,6 +2294,8 @@ mm_iface_modem_set_allowed_modes (MMIfaceModem *self,
return;
}
+ ctx->allowed = allowed;
+ ctx->preferred = preferred;
MM_IFACE_MODEM_GET_INTERFACE (self)->set_allowed_modes (self,
allowed,
preferred,
@@ -3209,9 +3230,8 @@ load_allowed_modes_ready (MMIfaceModem *self,
mm_warn ("couldn't load current allowed/preferred modes: '%s'", error->message);
g_error_free (error);
- /* If errors getting allowed modes, assume allowed=supported,
- * and none preferred */
- allowed = mm_gdbus_modem_get_supported_modes (ctx->skeleton);
+ /* If errors getting allowed modes, assume ANY/NONE */
+ allowed = MM_MODEM_MODE_ANY;
preferred = MM_MODEM_MODE_NONE;
}
@@ -3364,10 +3384,9 @@ interface_enabling_step (EnablingContext *ctx)
return;
}
- /* If no way to get allowed modes, assume allowed=supported,
+ /* If no way to get allowed modes, assume allowed=any,
* and none preferred */
- mm_gdbus_modem_set_allowed_modes (ctx->skeleton,
- mm_gdbus_modem_get_supported_modes (ctx->skeleton));
+ mm_gdbus_modem_set_allowed_modes (ctx->skeleton, MM_MODEM_MODE_ANY);
mm_gdbus_modem_set_preferred_mode (ctx->skeleton, MM_MODEM_MODE_NONE);
/* Fall down to next step */
ctx->step++;
@@ -3652,13 +3671,13 @@ load_supported_modes_ready (MMIfaceModem *self,
InitializationContext *ctx)
{
GError *error = NULL;
- MMModemMode modes;
-
- modes = MM_IFACE_MODEM_GET_INTERFACE (self)->load_supported_modes_finish (self, res, &error);
+ GArray *modes_array;
- if (modes != MM_MODEM_MODE_NONE) {
- mm_gdbus_modem_set_supported_modes (ctx->skeleton, modes);
- mm_gdbus_modem_set_allowed_modes (ctx->skeleton, modes);
+ modes_array = MM_IFACE_MODEM_GET_INTERFACE (self)->load_supported_modes_finish (self, res, &error);
+ if (modes_array != NULL) {
+ mm_gdbus_modem_set_supported_modes (ctx->skeleton,
+ mm_common_mode_combinations_garray_to_variant (modes_array));
+ g_array_unref (modes_array);
}
if (error) {
@@ -4010,18 +4029,30 @@ interface_initialization_step (InitializationContext *ctx)
ctx->step++;
case INITIALIZATION_STEP_SUPPORTED_MODES:
- g_assert (MM_IFACE_MODEM_GET_INTERFACE (ctx->self)->load_supported_modes != NULL);
- g_assert (MM_IFACE_MODEM_GET_INTERFACE (ctx->self)->load_supported_modes_finish != NULL);
+ if (MM_IFACE_MODEM_GET_INTERFACE (ctx->self)->load_supported_modes != NULL &&
+ MM_IFACE_MODEM_GET_INTERFACE (ctx->self)->load_supported_modes_finish != NULL) {
+ GArray *supported_modes;
+ MMModemModeCombination *mode = NULL;
+
+ supported_modes = (mm_common_mode_combinations_variant_to_garray (
+ mm_gdbus_modem_get_supported_modes (ctx->skeleton)));
+
+ /* Supported modes are meant to be loaded only once during the whole
+ * lifetime of the modem. Therefore, if we already have them loaded,
+ * don't try to load them again. */
+ if (supported_modes->len == 1)
+ mode = &g_array_index (supported_modes, MMModemModeCombination, 0);
+ if (supported_modes->len == 0 ||
+ (mode && mode->allowed == MM_MODEM_MODE_ANY && mode->preferred == MM_MODEM_MODE_NONE)) {
+ MM_IFACE_MODEM_GET_INTERFACE (ctx->self)->load_supported_modes (
+ ctx->self,
+ (GAsyncReadyCallback)load_supported_modes_ready,
+ ctx);
+ g_array_unref (supported_modes);
+ return;
+ }
- /* Supported modes are meant to be loaded only once during the whole
- * lifetime of the modem. Therefore, if we already have them loaded,
- * don't try to load them again. */
- if (mm_gdbus_modem_get_supported_modes (ctx->skeleton) == MM_MODEM_MODE_NONE) {
- MM_IFACE_MODEM_GET_INTERFACE (ctx->self)->load_supported_modes (
- ctx->self,
- (GAsyncReadyCallback)load_supported_modes_ready,
- ctx);
- return;
+ g_array_unref (supported_modes);
}
/* Fall down to next step */
ctx->step++;
@@ -4257,7 +4288,7 @@ mm_iface_modem_initialize (MMIfaceModem *self,
mm_gdbus_modem_set_unlock_retries (skeleton, 0);
mm_gdbus_modem_set_access_technologies (skeleton, MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN);
mm_gdbus_modem_set_signal_quality (skeleton, g_variant_new ("(ub)", 0, FALSE));
- mm_gdbus_modem_set_supported_modes (skeleton, MM_MODEM_MODE_NONE);
+ mm_gdbus_modem_set_supported_modes (skeleton, mm_common_build_mode_combinations_default ());
mm_gdbus_modem_set_allowed_modes (skeleton, MM_MODEM_MODE_NONE);
mm_gdbus_modem_set_preferred_mode (skeleton, MM_MODEM_MODE_NONE);
mm_gdbus_modem_set_supported_bands (skeleton, mm_common_build_bands_unknown ());
@@ -4357,10 +4388,12 @@ mm_iface_modem_get_access_technologies (MMIfaceModem *self)
/*****************************************************************************/
-MMModemMode
-mm_iface_modem_get_supported_modes (MMIfaceModem *self)
+static gboolean
+find_supported_mode (MMIfaceModem *self,
+ MMModemMode mode,
+ gboolean *only)
{
- MMModemMode supported = MM_MODEM_MODE_NONE;
+ gboolean matched = FALSE;
MmGdbusModem *skeleton;
g_object_get (self,
@@ -4368,56 +4401,85 @@ mm_iface_modem_get_supported_modes (MMIfaceModem *self)
NULL);
if (skeleton) {
- supported = mm_gdbus_modem_get_supported_modes (skeleton);
+ GArray *supported;
+ guint i;
+ guint n_unmatched = 0;
+
+ supported = mm_common_mode_combinations_variant_to_garray (
+ mm_gdbus_modem_get_supported_modes (skeleton));
+
+ /* Check if the given mode is supported */
+ for (i = 0; i < supported->len; i++) {
+ MMModemModeCombination *supported_mode;
+
+ supported_mode = &g_array_index (supported, MMModemModeCombination, i);
+ if (supported_mode->allowed & mode) {
+ matched = TRUE;
+ if (supported_mode->allowed != mode)
+ n_unmatched++;
+ } else
+ n_unmatched++;
+
+ if (matched && (only == NULL || n_unmatched > 0))
+ break;
+ }
+
+ if (only)
+ *only = (n_unmatched == 0);
+
+ g_array_unref (supported);
g_object_unref (skeleton);
}
- return supported;
+ return matched;
}
gboolean
mm_iface_modem_is_2g (MMIfaceModem *self)
{
- return (mm_iface_modem_get_supported_modes (self) & MM_MODEM_MODE_2G);
+ return find_supported_mode (self, MM_MODEM_MODE_2G, NULL);
}
gboolean
mm_iface_modem_is_2g_only (MMIfaceModem *self)
{
- MMModemMode supported;
+ gboolean only;
- supported = mm_iface_modem_get_supported_modes (self);
- return !((MM_MODEM_MODE_2G ^ supported) & supported);
+ return (find_supported_mode (self, MM_MODEM_MODE_2G, &only) ?
+ only :
+ FALSE);
}
gboolean
mm_iface_modem_is_3g (MMIfaceModem *self)
{
- return (mm_iface_modem_get_supported_modes (self) & MM_MODEM_MODE_3G);
+ return find_supported_mode (self, MM_MODEM_MODE_3G, NULL);
}
gboolean
mm_iface_modem_is_3g_only (MMIfaceModem *self)
{
- MMModemMode supported;
+ gboolean only;
- supported = mm_iface_modem_get_supported_modes (self);
- return !((MM_MODEM_MODE_3G ^ supported) & supported);
+ return (find_supported_mode (self, MM_MODEM_MODE_3G, &only) ?
+ only :
+ FALSE);
}
gboolean
mm_iface_modem_is_4g (MMIfaceModem *self)
{
- return (mm_iface_modem_get_supported_modes (self) & MM_MODEM_MODE_4G);
+ return find_supported_mode (self, MM_MODEM_MODE_4G, NULL);
}
gboolean
mm_iface_modem_is_4g_only (MMIfaceModem *self)
{
- MMModemMode supported;
+ gboolean only;
- supported = mm_iface_modem_get_supported_modes (self);
- return !((MM_MODEM_MODE_4G ^ supported) & supported);
+ return (find_supported_mode (self, MM_MODEM_MODE_4G, &only) ?
+ only :
+ FALSE);
}
/*****************************************************************************/
diff --git a/src/mm-iface-modem.h b/src/mm-iface-modem.h
index f14f8cba..65b0243f 100644
--- a/src/mm-iface-modem.h
+++ b/src/mm-iface-modem.h
@@ -126,9 +126,9 @@ struct _MMIfaceModem {
void (*load_supported_modes) (MMIfaceModem *self,
GAsyncReadyCallback callback,
gpointer user_data);
- MMModemMode (*load_supported_modes_finish) (MMIfaceModem *self,
- GAsyncResult *res,
- GError **error);
+ GArray * (*load_supported_modes_finish) (MMIfaceModem *self,
+ GAsyncResult *res,
+ GError **error);
/* Loading of the AllowedModes and PreferredMode properties */
void (*load_allowed_modes) (MMIfaceModem *self,
@@ -328,13 +328,12 @@ gboolean mm_iface_modem_is_cdma (MMIfaceModem *self);
gboolean mm_iface_modem_is_cdma_only (MMIfaceModem *self);
/* Helpers to query supported modes */
-MMModemMode mm_iface_modem_get_supported_modes (MMIfaceModem *self);
-gboolean mm_iface_modem_is_2g (MMIfaceModem *self);
-gboolean mm_iface_modem_is_2g_only (MMIfaceModem *self);
-gboolean mm_iface_modem_is_3g (MMIfaceModem *self);
-gboolean mm_iface_modem_is_3g_only (MMIfaceModem *self);
-gboolean mm_iface_modem_is_4g (MMIfaceModem *self);
-gboolean mm_iface_modem_is_4g_only (MMIfaceModem *self);
+gboolean mm_iface_modem_is_2g (MMIfaceModem *self);
+gboolean mm_iface_modem_is_2g_only (MMIfaceModem *self);
+gboolean mm_iface_modem_is_3g (MMIfaceModem *self);
+gboolean mm_iface_modem_is_3g_only (MMIfaceModem *self);
+gboolean mm_iface_modem_is_4g (MMIfaceModem *self);
+gboolean mm_iface_modem_is_4g_only (MMIfaceModem *self);
/* Initialize Modem interface (async) */
void mm_iface_modem_initialize (MMIfaceModem *self,
diff --git a/src/mm-modem-helpers-qmi.c b/src/mm-modem-helpers-qmi.c
index efe3686d..b5267f8d 100644
--- a/src/mm-modem-helpers-qmi.c
+++ b/src/mm-modem-helpers-qmi.c
@@ -42,6 +42,29 @@ mm_modem_capability_from_qmi_radio_interface (QmiDmsRadioInterface network)
/*****************************************************************************/
+MMModemMode
+mm_modem_mode_from_qmi_radio_interface (QmiDmsRadioInterface network)
+{
+ switch (network) {
+ case QMI_DMS_RADIO_INTERFACE_CDMA20001X:
+ return MM_MODEM_MODE_2G;
+ case QMI_DMS_RADIO_INTERFACE_EVDO:
+ return MM_MODEM_MODE_3G;
+ case QMI_DMS_RADIO_INTERFACE_GSM:
+ return MM_MODEM_MODE_2G;
+ case QMI_DMS_RADIO_INTERFACE_UMTS:
+ return MM_MODEM_MODE_3G;
+ case QMI_DMS_RADIO_INTERFACE_LTE:
+ return MM_MODEM_MODE_4G;
+ default:
+ mm_warn ("Unhandled QMI radio interface (%u)",
+ (guint)network);
+ return MM_MODEM_MODE_NONE;
+ }
+}
+
+/*****************************************************************************/
+
/* pin1 TRUE for PIN1, FALSE for PIN2 */
MMModemLock
mm_modem_lock_from_qmi_uim_pin_status (QmiDmsUimPinStatus status,
diff --git a/src/mm-modem-helpers-qmi.h b/src/mm-modem-helpers-qmi.h
index 8da0fdd7..6eae632c 100644
--- a/src/mm-modem-helpers-qmi.h
+++ b/src/mm-modem-helpers-qmi.h
@@ -26,6 +26,8 @@
MMModemCapability mm_modem_capability_from_qmi_radio_interface (QmiDmsRadioInterface network);
+MMModemMode mm_modem_mode_from_qmi_radio_interface (QmiDmsRadioInterface network);
+
MMModemLock mm_modem_lock_from_qmi_uim_pin_status (QmiDmsUimPinStatus status,
gboolean pin1);
diff --git a/src/mm-modem-helpers.c b/src/mm-modem-helpers.c
index 46265d04..6d0acb20 100644
--- a/src/mm-modem-helpers.c
+++ b/src/mm-modem-helpers.c
@@ -248,6 +248,53 @@ mm_new_iso8601_time (guint year,
/*****************************************************************************/
+GArray *
+mm_filter_supported_modes (const GArray *all,
+ const GArray *supported_combinations)
+{
+ MMModemModeCombination all_item;
+ guint i;
+ GArray *filtered_combinations;
+ gboolean all_item_added = FALSE;
+
+ g_return_val_if_fail (all != NULL, NULL);
+ g_return_val_if_fail (all->len == 1, NULL);
+ g_return_val_if_fail (supported_combinations != NULL, NULL);
+
+ all_item = g_array_index (all, MMModemModeCombination, 0);
+ g_return_val_if_fail (all_item.allowed != MM_MODEM_MODE_NONE, NULL);
+
+ /* We will filter out all combinations which have modes not listed in 'all' */
+ filtered_combinations = g_array_sized_new (FALSE, FALSE, sizeof (MMModemModeCombination), supported_combinations->len);
+ for (i = 0; i < supported_combinations->len; i++) {
+ MMModemModeCombination *mode;
+
+ mode = &g_array_index (supported_combinations, MMModemModeCombination, i);
+ if (!(mode->allowed & ~all_item.allowed)) {
+ /* Compare only 'allowed', *not* preferred. If there is at least one item with allowed
+ * containing all supported modes, we're already good to go. This allows us to have a
+ * default with preferred != NONE (e.g. Wavecom 2G modem with allowed=CS+2G and
+ * preferred=2G */
+ if (all_item.allowed == mode->allowed)
+ all_item_added = TRUE;
+ g_array_append_val (filtered_combinations, *mode);
+ }
+ }
+
+ if (filtered_combinations->len == 0)
+ mm_warn ("All supported mode combinations were filtered out.");
+
+ /* Add default entry with the generic mask including all items */
+ if (!all_item_added) {
+ mm_dbg ("Adding an explicit item with all supported modes allowed");
+ g_array_append_val (filtered_combinations, all_item);
+ }
+
+ return filtered_combinations;
+}
+
+/*****************************************************************************/
+
/* +CREG: <stat> (GSM 07.07 CREG=1 unsolicited) */
#define CREG1 "\\+(CREG|CGREG|CEREG):\\s*0*([0-9])"
diff --git a/src/mm-modem-helpers.h b/src/mm-modem-helpers.h
index 80c31691..ce7c66d1 100644
--- a/src/mm-modem-helpers.h
+++ b/src/mm-modem-helpers.h
@@ -73,6 +73,9 @@ gchar *mm_new_iso8601_time (guint year,
gboolean have_offset,
gint offset_minutes);
+GArray *mm_filter_supported_modes (const GArray *all,
+ const GArray *supported_combinations);
+
/*****************************************************************************/
/* 3GPP specific helpers and utilities */
/*****************************************************************************/
diff --git a/src/tests/test-modem-helpers.c b/src/tests/test-modem-helpers.c
index 0d245b29..c61f190c 100644
--- a/src/tests/test-modem-helpers.c
+++ b/src/tests/test-modem-helpers.c
@@ -18,6 +18,7 @@
#include <string.h>
#include <stdlib.h>
+#include <libmm-glib.h>
#include "mm-modem-helpers.h"
#include "mm-log.h"
@@ -1931,6 +1932,127 @@ test_cdma_parse_gsn (void *f, gpointer d)
/*****************************************************************************/
+static gboolean
+find_mode_combination (GArray *modes,
+ MMModemMode allowed,
+ MMModemMode preferred)
+{
+ guint i;
+
+ for (i = 0; i < modes->len; i++) {
+ MMModemModeCombination *mode;
+
+ mode = &g_array_index (modes, MMModemModeCombination, i);
+ if (mode->allowed == allowed && mode->preferred == preferred)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static GArray *
+build_mode_all (MMModemMode all_mask)
+{
+ MMModemModeCombination all_item;
+ GArray *all;
+
+ all_item.allowed = all_mask;
+ all_item.preferred = MM_MODEM_MODE_NONE;
+ all = g_array_sized_new (FALSE, FALSE, sizeof (MMModemModeCombination), 1);
+ g_array_append_val (all, all_item);
+ return all;
+}
+
+static void
+test_supported_mode_filter (void *f, gpointer d)
+{
+ MMModemModeCombination mode;
+ GArray *all;
+ GArray *combinations;
+ GArray *filtered;
+
+ /* Build array of combinations */
+ combinations = g_array_sized_new (FALSE, FALSE, sizeof (MMModemModeCombination), 5);
+
+ /* 2G only */
+ mode.allowed = MM_MODEM_MODE_2G;
+ mode.preferred = MM_MODEM_MODE_NONE;
+ g_array_append_val (combinations, mode);
+ /* 3G only */
+ mode.allowed = MM_MODEM_MODE_3G;
+ mode.preferred = MM_MODEM_MODE_NONE;
+ g_array_append_val (combinations, mode);
+ /* 2G and 3G */
+ mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G);
+ mode.preferred = MM_MODEM_MODE_NONE;
+ g_array_append_val (combinations, mode);
+ /* 4G only */
+ mode.allowed = MM_MODEM_MODE_4G;
+ mode.preferred = MM_MODEM_MODE_NONE;
+ g_array_append_val (combinations, mode);
+ /* 3G and 4G */
+ mode.allowed = (MM_MODEM_MODE_3G | MM_MODEM_MODE_4G);
+ mode.preferred = MM_MODEM_MODE_NONE;
+ g_array_append_val (combinations, mode);
+ /* 2G, 3G and 4G */
+ mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G);
+ mode.preferred = MM_MODEM_MODE_NONE;
+ g_array_append_val (combinations, mode);
+
+ /* Only 2G supported */
+ all = build_mode_all (MM_MODEM_MODE_2G);
+ filtered = mm_filter_supported_modes (all, combinations);
+ g_assert_cmpuint (filtered->len, ==, 1);
+ g_assert (find_mode_combination (filtered, MM_MODEM_MODE_2G, MM_MODEM_MODE_NONE));
+ g_array_unref (filtered);
+ g_array_unref (all);
+
+ /* Only 3G supported */
+ all = build_mode_all (MM_MODEM_MODE_3G);
+ filtered = mm_filter_supported_modes (all, combinations);
+ g_assert_cmpuint (filtered->len, ==, 1);
+ g_assert (find_mode_combination (filtered, MM_MODEM_MODE_3G, MM_MODEM_MODE_NONE));
+ g_array_unref (filtered);
+ g_array_unref (all);
+
+ /* 2G and 3G supported */
+ all = build_mode_all (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G);
+ filtered = mm_filter_supported_modes (all, combinations);
+ g_assert_cmpuint (filtered->len, ==, 3);
+ g_assert (find_mode_combination (filtered, MM_MODEM_MODE_2G, MM_MODEM_MODE_NONE));
+ g_assert (find_mode_combination (filtered, MM_MODEM_MODE_3G, MM_MODEM_MODE_NONE));
+ g_assert (find_mode_combination (filtered, (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G), MM_MODEM_MODE_NONE));
+ g_array_unref (filtered);
+ g_array_unref (all);
+
+ /* 3G and 4G supported */
+ all = build_mode_all (MM_MODEM_MODE_3G | MM_MODEM_MODE_4G);
+ filtered = mm_filter_supported_modes (all, combinations);
+ g_assert_cmpuint (filtered->len, ==, 3);
+ g_assert (find_mode_combination (filtered, MM_MODEM_MODE_3G, MM_MODEM_MODE_NONE));
+ g_assert (find_mode_combination (filtered, MM_MODEM_MODE_4G, MM_MODEM_MODE_NONE));
+ g_assert (find_mode_combination (filtered, (MM_MODEM_MODE_3G | MM_MODEM_MODE_4G), MM_MODEM_MODE_NONE));
+ g_array_unref (filtered);
+ g_array_unref (all);
+
+ /* 2G, 3G and 4G supported */
+ all = build_mode_all (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G);
+ filtered = mm_filter_supported_modes (all, combinations);
+ g_assert_cmpuint (filtered->len, ==, 6);
+ g_assert (find_mode_combination (filtered, MM_MODEM_MODE_2G, MM_MODEM_MODE_NONE));
+ g_assert (find_mode_combination (filtered, MM_MODEM_MODE_3G, MM_MODEM_MODE_NONE));
+ g_assert (find_mode_combination (filtered, (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G), MM_MODEM_MODE_NONE));
+ g_assert (find_mode_combination (filtered, MM_MODEM_MODE_4G, MM_MODEM_MODE_NONE));
+ g_assert (find_mode_combination (filtered, (MM_MODEM_MODE_3G | MM_MODEM_MODE_4G), MM_MODEM_MODE_NONE));
+ g_assert (find_mode_combination (filtered, (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G), MM_MODEM_MODE_NONE));
+ g_array_unref (filtered);
+ g_array_unref (all);
+
+ g_array_unref (combinations);
+}
+
+/*****************************************************************************/
+
void
_mm_log (const char *loc,
const char *func,
@@ -2060,6 +2182,8 @@ int main (int argc, char **argv)
g_test_suite_add (suite, TESTCASE (test_cmgl_response_pantech, NULL));
g_test_suite_add (suite, TESTCASE (test_cmgl_response_pantech_multiple, NULL));
+ g_test_suite_add (suite, TESTCASE (test_supported_mode_filter, NULL));
+
result = g_test_run ();
reg_test_data_free (reg_data);