diff options
author | Som_SP <somashekhar.puttagangaiah@intel.com> | 2021-10-14 16:30:06 +0200 |
---|---|---|
committer | Aleksander Morgado <aleksander@aleksander.es> | 2021-10-20 22:09:57 +0200 |
commit | 92539fa71f015e5af08794e486b1c9853c9cf510 (patch) | |
tree | cc73ce374722e75a87380f87c08d914164076772 | |
parent | 925f0bae11c0b49a464237c5c98921ffd68157e2 (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.c | 294 | ||||
-rw-r--r-- | src/mm-iface-modem-signal.h | 23 |
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 */ |