summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSom_SP <somashekhar.puttagangaiah@intel.com>2021-10-14 16:30:06 +0200
committerAleksander Morgado <aleksander@aleksander.es>2021-10-20 22:09:57 +0200
commit92539fa71f015e5af08794e486b1c9853c9cf510 (patch)
treecc73ce374722e75a87380f87c08d914164076772
parent925f0bae11c0b49a464237c5c98921ffd68157e2 (diff)
iface-modem-signal: implement support for SetupThresholds()
Also allow updating the per-access technology signal quality information via indications. Includes updates by Aleksander Morgado to fix coding style issues and some other GTask related problems.
-rw-r--r--src/mm-iface-modem-signal.c294
-rw-r--r--src/mm-iface-modem-signal.h23
2 files changed, 274 insertions, 43 deletions
diff --git a/src/mm-iface-modem-signal.c b/src/mm-iface-modem-signal.c
index 25d0840c..a2339f6b 100644
--- a/src/mm-iface-modem-signal.c
+++ b/src/mm-iface-modem-signal.c
@@ -10,7 +10,8 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details:
*
- * Copyright (C) 2013 Aleksander Morgado <aleksander@gnu.org>
+ * Copyright (C) 2013-2021 Aleksander Morgado <aleksander@aleksander.es>
+ * Copyright (C) 2021 Intel Corporation
*/
#include <ModemManager.h>
@@ -39,6 +40,61 @@ mm_iface_modem_signal_bind_simple_status (MMIfaceModemSignal *self,
/*****************************************************************************/
+void
+mm_iface_modem_signal_update (MMIfaceModemSignal *self,
+ MMSignal *cdma,
+ MMSignal *evdo,
+ MMSignal *gsm,
+ MMSignal *umts,
+ MMSignal *lte,
+ MMSignal *nr5g)
+{
+ g_autoptr(GVariant) dict_cdma = NULL;
+ g_autoptr(GVariant) dict_evdo = NULL;
+ g_autoptr(GVariant) dict_gsm = NULL;
+ g_autoptr(GVariant) dict_umts = NULL;
+ g_autoptr(GVariant) dict_lte = NULL;
+ g_autoptr(GVariant) dict_nr5g = NULL;
+ g_autoptr(MmGdbusModemSignalSkeleton) skeleton = NULL;
+
+ g_object_get (self,
+ MM_IFACE_MODEM_SIGNAL_DBUS_SKELETON, &skeleton,
+ NULL);
+ if (!skeleton) {
+ mm_obj_warn (self, "cannot update extended signal information: couldn't get interface skeleton");
+ return;
+ }
+
+ if (cdma)
+ dict_cdma = mm_signal_get_dictionary (cdma);
+ mm_gdbus_modem_signal_set_cdma (MM_GDBUS_MODEM_SIGNAL (skeleton), dict_cdma);
+
+ if (evdo)
+ dict_evdo = mm_signal_get_dictionary (evdo);
+ mm_gdbus_modem_signal_set_evdo (MM_GDBUS_MODEM_SIGNAL (skeleton), dict_evdo);
+
+ if (gsm)
+ dict_gsm = mm_signal_get_dictionary (gsm);
+ mm_gdbus_modem_signal_set_gsm (MM_GDBUS_MODEM_SIGNAL (skeleton), dict_gsm);
+
+ if (umts)
+ dict_umts = mm_signal_get_dictionary (umts);
+ mm_gdbus_modem_signal_set_umts (MM_GDBUS_MODEM_SIGNAL (skeleton), dict_umts);
+
+ if (lte)
+ dict_lte = mm_signal_get_dictionary (lte);
+ mm_gdbus_modem_signal_set_lte (MM_GDBUS_MODEM_SIGNAL (skeleton), dict_lte);
+
+ if (nr5g)
+ dict_nr5g = mm_signal_get_dictionary (nr5g);
+ mm_gdbus_modem_signal_set_nr5g (MM_GDBUS_MODEM_SIGNAL (skeleton), dict_nr5g);
+
+ /* Flush right away */
+ g_dbus_interface_skeleton_flush (G_DBUS_INTERFACE_SKELETON (skeleton));
+}
+
+/*****************************************************************************/
+
typedef struct {
guint rate;
guint timeout_source;
@@ -77,18 +133,11 @@ load_values_ready (MMIfaceModemSignal *self,
{
g_autoptr(GError) error = NULL;
g_autoptr(MMSignal) cdma = NULL;
- g_autoptr(GVariant) dict_cdma = NULL;
g_autoptr(MMSignal) evdo = NULL;
- g_autoptr(GVariant) dict_evdo = NULL;
g_autoptr(MMSignal) gsm = NULL;
- g_autoptr(GVariant) dict_gsm = NULL;
g_autoptr(MMSignal) umts = NULL;
- g_autoptr(GVariant) dict_umts = NULL;
g_autoptr(MMSignal) lte = NULL;
- g_autoptr(GVariant) dict_lte = NULL;
g_autoptr(MMSignal) nr5g = NULL;
- g_autoptr(GVariant) dict_nr5g = NULL;
- g_autoptr(MmGdbusModemSignalSkeleton) skeleton = NULL;
if (!MM_IFACE_MODEM_SIGNAL_GET_INTERFACE (self)->load_values_finish (
self,
@@ -105,40 +154,7 @@ load_values_ready (MMIfaceModemSignal *self,
return;
}
- g_object_get (self,
- MM_IFACE_MODEM_SIGNAL_DBUS_SKELETON, &skeleton,
- NULL);
- if (!skeleton) {
- mm_obj_warn (self, "cannot update extended signal information: couldn't get interface skeleton");
- return;
- }
-
- if (cdma)
- dict_cdma = mm_signal_get_dictionary (cdma);
- mm_gdbus_modem_signal_set_cdma (MM_GDBUS_MODEM_SIGNAL (skeleton), dict_cdma);
-
- if (evdo)
- dict_evdo = mm_signal_get_dictionary (evdo);
- mm_gdbus_modem_signal_set_evdo (MM_GDBUS_MODEM_SIGNAL (skeleton), dict_evdo);
-
- if (gsm)
- dict_gsm = mm_signal_get_dictionary (gsm);
- mm_gdbus_modem_signal_set_gsm (MM_GDBUS_MODEM_SIGNAL (skeleton), dict_gsm);
-
- if (umts)
- dict_umts = mm_signal_get_dictionary (umts);
- mm_gdbus_modem_signal_set_umts (MM_GDBUS_MODEM_SIGNAL (skeleton), dict_umts);
-
- if (lte)
- dict_lte = mm_signal_get_dictionary (lte);
- mm_gdbus_modem_signal_set_lte (MM_GDBUS_MODEM_SIGNAL (skeleton), dict_lte);
-
- if (nr5g)
- dict_nr5g = mm_signal_get_dictionary (nr5g);
- mm_gdbus_modem_signal_set_nr5g (MM_GDBUS_MODEM_SIGNAL (skeleton), dict_nr5g);
-
- /* Flush right away */
- g_dbus_interface_skeleton_flush (G_DBUS_INTERFACE_SKELETON (skeleton));
+ mm_iface_modem_signal_update (self, cdma, evdo, gsm, umts, lte, nr5g);
}
static gboolean
@@ -295,6 +311,196 @@ handle_setup (MmGdbusModemSignal *skeleton,
/*****************************************************************************/
+typedef struct {
+ GDBusMethodInvocation *invocation;
+ MmGdbusModemSignal *skeleton;
+ MMIfaceModemSignal *self;
+ GVariant *settings;
+ guint32 rssi_threshold;
+ gboolean error_rate_threshold;
+} HandleSetupThresholdsContext;
+
+static void
+handle_setup_thresholds_context_free (HandleSetupThresholdsContext *ctx)
+{
+ g_object_unref (ctx->invocation);
+ g_object_unref (ctx->skeleton);
+ g_object_unref (ctx->self);
+ if (ctx->settings)
+ g_variant_unref (ctx->settings);
+ g_slice_free (HandleSetupThresholdsContext, ctx);
+}
+
+static void
+setup_thresholds_ready (MMIfaceModemSignal *self,
+ GAsyncResult *res,
+ HandleSetupThresholdsContext *ctx)
+{
+ GError *error = NULL;
+
+ if (!MM_IFACE_MODEM_SIGNAL_GET_INTERFACE (ctx->self)->setup_thresholds_finish (ctx->self, res, &error))
+ g_dbus_method_invocation_take_error (ctx->invocation, error);
+ else {
+ /* Update the property with the latest threshold setting */
+ mm_gdbus_modem_signal_set_rssi_threshold (ctx->skeleton, ctx->rssi_threshold);
+ mm_gdbus_modem_signal_set_error_rate_threshold (ctx->skeleton, ctx->error_rate_threshold);
+ mm_gdbus_modem_signal_complete_setup_thresholds (ctx->skeleton, ctx->invocation);
+ }
+
+ handle_setup_thresholds_context_free (ctx);
+}
+
+static gboolean
+select_new_threshold_settings (HandleSetupThresholdsContext *ctx,
+ GError **error)
+{
+ GError *inner_error = NULL;
+ GVariantIter iter;
+ gchar *key;
+ GVariant *value;
+
+ if (!g_variant_is_of_type (ctx->settings, G_VARIANT_TYPE ("a{sv}"))) {
+ g_set_error (error,
+ MM_CORE_ERROR,
+ MM_CORE_ERROR_INVALID_ARGS,
+ "Cannot get threshold settings from dictionary: "
+ "invalid variant type received");
+ return FALSE;
+ }
+
+ g_variant_iter_init (&iter, ctx->settings);
+ while (!inner_error && g_variant_iter_next (&iter, "{sv}", &key, &value)) {
+ if (g_str_equal (key, "rssi-threshold"))
+ ctx->rssi_threshold = g_variant_get_uint32 (value);
+ else if (g_str_equal (key, "error-rate-threshold"))
+ ctx->error_rate_threshold = g_variant_get_boolean (value);
+ else {
+ /* Set inner error, will stop the loop */
+ inner_error = g_error_new (MM_CORE_ERROR,
+ MM_CORE_ERROR_INVALID_ARGS,
+ "Invalid settings dictionary, unexpected key '%s'",
+ key);
+ }
+
+ g_free (key);
+ g_variant_unref (value);
+ }
+
+ if (inner_error) {
+ g_propagate_error (error, inner_error);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static gboolean
+check_threshold_settings (HandleSetupThresholdsContext *ctx,
+ GError **error)
+{
+ MmGdbusModemSignal *skeleton;
+ MMModemState modem_state;
+ guint32 old_rssi_threshold;
+ gboolean old_error_threshold;
+
+ g_object_get (ctx->self,
+ MM_IFACE_MODEM_SIGNAL_DBUS_SKELETON, &skeleton,
+ MM_IFACE_MODEM_STATE, &modem_state,
+ NULL);
+
+ if (!skeleton) {
+ g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED,
+ "Couldn't get signal interface skeleton");
+ return FALSE;
+ }
+
+ if (modem_state < MM_MODEM_STATE_ENABLING) {
+ g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_WRONG_STATE,
+ "Modem in wrong state");
+ return FALSE;
+ }
+
+ /* Compare to old threshold values */
+ old_rssi_threshold = mm_gdbus_modem_signal_get_rssi_threshold(skeleton);
+ old_error_threshold = mm_gdbus_modem_signal_get_error_rate_threshold(skeleton);
+
+ /* Set older threshold values before reading dictionary. So that if only
+ * one value is passed then the other threshold will be maintained as set
+ * previously. */
+ ctx->rssi_threshold = old_rssi_threshold;
+ ctx->error_rate_threshold = old_error_threshold;
+
+ if (!select_new_threshold_settings (ctx, error))
+ return FALSE;
+
+ if ((ctx->rssi_threshold == old_rssi_threshold) && (ctx->error_rate_threshold == old_error_threshold)) {
+ /* Already there */
+ g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_INVALID_ARGS,
+ "Same threshold settings already configured");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void
+handle_setup_thresholds_auth_ready (MMBaseModem *self,
+ GAsyncResult *res,
+ HandleSetupThresholdsContext *ctx)
+{
+ GError *error = NULL;
+
+ if (!mm_base_modem_authorize_finish (self, res, &error)) {
+ g_dbus_method_invocation_take_error (ctx->invocation, error);
+ handle_setup_thresholds_context_free (ctx);
+ return;
+ }
+
+ if (!MM_IFACE_MODEM_SIGNAL_GET_INTERFACE (ctx->self)->setup_thresholds ||
+ !MM_IFACE_MODEM_SIGNAL_GET_INTERFACE (ctx->self)->setup_thresholds_finish) {
+ g_dbus_method_invocation_return_error (ctx->invocation, MM_CORE_ERROR, MM_CORE_ERROR_UNSUPPORTED,
+ "Cannot setup thresholds: operation not supported");
+ handle_setup_thresholds_context_free (ctx);
+ return;
+ }
+
+ if (!check_threshold_settings (ctx, &error)) {
+ g_dbus_method_invocation_take_error (ctx->invocation, error);
+ handle_setup_thresholds_context_free (ctx);
+ return;
+ }
+
+ MM_IFACE_MODEM_SIGNAL_GET_INTERFACE (ctx->self)->setup_thresholds (
+ ctx->self,
+ ctx->rssi_threshold,
+ ctx->error_rate_threshold,
+ (GAsyncReadyCallback)setup_thresholds_ready,
+ ctx);
+}
+
+static gboolean
+handle_setup_thresholds (MmGdbusModemSignal *skeleton,
+ GDBusMethodInvocation *invocation,
+ GVariant *settings,
+ MMIfaceModemSignal *self)
+{
+ HandleSetupThresholdsContext *ctx;
+
+ ctx = g_slice_new0 (HandleSetupThresholdsContext);
+ ctx->invocation = g_object_ref (invocation);
+ ctx->skeleton = g_object_ref (skeleton);
+ ctx->self = g_object_ref (self);
+ ctx->settings = g_variant_ref (settings);
+
+ mm_base_modem_authorize (MM_BASE_MODEM (self),
+ invocation,
+ MM_AUTHORIZATION_DEVICE_CONTROL,
+ (GAsyncReadyCallback)handle_setup_thresholds_auth_ready,
+ ctx);
+ return TRUE;
+}
+
+/*****************************************************************************/
+
gboolean
mm_iface_modem_signal_disable_finish (MMIfaceModemSignal *self,
GAsyncResult *res,
@@ -481,6 +687,10 @@ interface_initialization_step (GTask *task)
"handle-setup",
G_CALLBACK (handle_setup),
self);
+ g_signal_connect (ctx->skeleton,
+ "handle-setup-thresholds",
+ G_CALLBACK (handle_setup_thresholds),
+ self);
/* Finally, export the new interface */
mm_gdbus_object_skeleton_set_modem_signal (MM_GDBUS_OBJECT_SKELETON (self),
MM_GDBUS_MODEM_SIGNAL (ctx->skeleton));
diff --git a/src/mm-iface-modem-signal.h b/src/mm-iface-modem-signal.h
index dd7a6685..d359659d 100644
--- a/src/mm-iface-modem-signal.h
+++ b/src/mm-iface-modem-signal.h
@@ -10,7 +10,8 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details:
*
- * Copyright (C) 2013 Aleksander Morgado <aleksander@gnu.org>
+ * Copyright (C) 2013-2021 Aleksander Morgado <aleksander@aleksander.es>
+ * Copyright (C) 2021 Intel Corporation
*/
#ifndef MM_IFACE_MODEM_SIGNAL_H
@@ -56,6 +57,17 @@ struct _MMIfaceModemSignal {
MMSignal **lte,
MMSignal **nr5g,
GError **error);
+
+ /* Setup thresholds */
+ void (* setup_thresholds) (MMIfaceModemSignal *self,
+ guint32 rssi_threshold,
+ gboolean error_rate_threshold,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+ gboolean (* setup_thresholds_finish) (MMIfaceModemSignal *self,
+ GAsyncResult *res,
+ GError **error);
+
};
GType mm_iface_modem_signal_get_type (void);
@@ -94,4 +106,13 @@ void mm_iface_modem_signal_shutdown (MMIfaceModemSignal *self);
void mm_iface_modem_signal_bind_simple_status (MMIfaceModemSignal *self,
MMSimpleStatus *status);
+/* Allow signal quality updates via indications */
+void mm_iface_modem_signal_update (MMIfaceModemSignal *self,
+ MMSignal *cdma,
+ MMSignal *evdo,
+ MMSignal *gsm,
+ MMSignal *umts,
+ MMSignal *lte,
+ MMSignal *nr5g);
+
#endif /* MM_IFACE_MODEM_SIGNAL_H */