diff options
Diffstat (limited to 'libmm-glib')
-rw-r--r-- | libmm-glib/Makefile.am | 2 | ||||
-rw-r--r-- | libmm-glib/libmm-glib.h | 1 | ||||
-rw-r--r-- | libmm-glib/mm-common-helpers.c | 122 | ||||
-rw-r--r-- | libmm-glib/mm-common-helpers.h | 12 | ||||
-rw-r--r-- | libmm-glib/mm-helper-types.h | 44 | ||||
-rw-r--r-- | libmm-glib/mm-modem.c | 121 | ||||
-rw-r--r-- | libmm-glib/mm-modem.h | 8 |
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); |