aboutsummaryrefslogtreecommitdiff
path: root/libmm-glib
diff options
context:
space:
mode:
Diffstat (limited to 'libmm-glib')
-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
7 files changed, 302 insertions, 8 deletions
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);