aboutsummaryrefslogtreecommitdiff
path: root/plugins/cinterion/mm-broadband-modem-cinterion.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/cinterion/mm-broadband-modem-cinterion.c')
-rw-r--r--plugins/cinterion/mm-broadband-modem-cinterion.c136
1 files changed, 136 insertions, 0 deletions
diff --git a/plugins/cinterion/mm-broadband-modem-cinterion.c b/plugins/cinterion/mm-broadband-modem-cinterion.c
index 09b4e13c..6e526ad3 100644
--- a/plugins/cinterion/mm-broadband-modem-cinterion.c
+++ b/plugins/cinterion/mm-broadband-modem-cinterion.c
@@ -40,6 +40,7 @@
#include "mm-modem-helpers-cinterion.h"
#include "mm-shared-cinterion.h"
#include "mm-broadband-bearer-cinterion.h"
+#include "mm-iface-modem-signal.h"
static void iface_modem_init (MMIfaceModem *iface);
static void iface_modem_3gpp_init (MMIfaceModem3gpp *iface);
@@ -47,6 +48,7 @@ static void iface_modem_messaging_init (MMIfaceModemMessaging *iface);
static void iface_modem_location_init (MMIfaceModemLocation *iface);
static void iface_modem_voice_init (MMIfaceModemVoice *iface);
static void iface_modem_time_init (MMIfaceModemTime *iface);
+static void iface_modem_signal_init (MMIfaceModemSignal *iface);
static void shared_cinterion_init (MMSharedCinterion *iface);
static MMIfaceModem *iface_modem_parent;
@@ -54,6 +56,7 @@ static MMIfaceModem3gpp *iface_modem_3gpp_parent;
static MMIfaceModemLocation *iface_modem_location_parent;
static MMIfaceModemVoice *iface_modem_voice_parent;
static MMIfaceModemTime *iface_modem_time_parent;
+static MMIfaceModemSignal *iface_modem_signal_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)
@@ -62,6 +65,7 @@ G_DEFINE_TYPE_EXTENDED (MMBroadbandModemCinterion, mm_broadband_modem_cinterion,
G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_LOCATION, iface_modem_location_init)
G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_VOICE, iface_modem_voice_init)
G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_TIME, iface_modem_time_init)
+ G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_SIGNAL, iface_modem_signal_init)
G_IMPLEMENT_INTERFACE (MM_TYPE_SHARED_CINTERION, shared_cinterion_init))
typedef enum {
@@ -90,6 +94,7 @@ struct _MMBroadbandModemCinterionPrivate {
/* Flags for feature support checks */
FeatureSupport swwan_support;
FeatureSupport sind_psinfo_support;
+ FeatureSupport smoni_support;
};
/*****************************************************************************/
@@ -1793,6 +1798,7 @@ mm_broadband_modem_cinterion_init (MMBroadbandModemCinterion *self)
/* Initialize private variables */
self->priv->sind_psinfo_support = FEATURE_SUPPORT_UNKNOWN;
self->priv->swwan_support = FEATURE_SUPPORT_UNKNOWN;
+ self->priv->smoni_support = FEATURE_SUPPORT_UNKNOWN;
self->priv->ciev_regex = g_regex_new ("\\r\\n\\+CIEV:\\s*([a-z]+),(\\d+)\\r\\n",
G_REGEX_RAW | G_REGEX_OPTIMIZE, 0, NULL);
@@ -1958,3 +1964,133 @@ mm_broadband_modem_cinterion_class_init (MMBroadbandModemCinterionClass *klass)
/* Virtual methods */
object_class->finalize = finalize;
}
+
+/*****************************************************************************/
+/* Check support (Signal interface) */
+
+static gboolean
+signal_check_support_finish (MMIfaceModemSignal *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ return g_task_propagate_boolean (G_TASK (res), error);
+}
+
+static void
+parent_signal_check_support_ready (MMIfaceModemSignal *self,
+ GAsyncResult *res,
+ GTask *task)
+{
+ gboolean parent_supported;
+
+ parent_supported = iface_modem_signal_parent->check_support_finish (self, res, NULL);
+ g_task_return_boolean (task, parent_supported);
+ g_object_unref (task);
+}
+
+static void
+check_smoni_support (MMBaseModem *_self,
+ GAsyncResult *res,
+ GTask *task)
+{
+ MMBroadbandModemCinterion *self = MM_BROADBAND_MODEM_CINTERION (_self);
+
+ /* Fetch the result to the SMONI test. If no response given (error triggered), assume unsupported */
+ if (mm_base_modem_at_command_finish (_self, res, NULL)) {
+ mm_obj_dbg (self, "SMONI supported");
+ self->priv->smoni_support = FEATURE_SUPPORTED;
+ g_task_return_boolean (task, TRUE); // otherwise the whole interface is not available
+ g_object_unref (task);
+ return;
+ }
+
+ mm_obj_dbg (self, "SMONI unsupported");
+ self->priv->smoni_support = FEATURE_NOT_SUPPORTED;
+
+ /* Otherwise, check if the parent CESQ-based implementation works */
+ g_assert (iface_modem_signal_parent->check_support && iface_modem_signal_parent->check_support_finish);
+ iface_modem_signal_parent->check_support (g_task_get_task_data (task),
+ (GAsyncReadyCallback)parent_signal_check_support_ready,
+ task);
+}
+
+static void
+signal_check_support (MMIfaceModemSignal *_self,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ MMBroadbandModemCinterion *self = MM_BROADBAND_MODEM_CINTERION (_self);
+
+ GTask *task = g_task_new (self, NULL, callback, user_data);
+ g_task_set_task_data (task, _self, NULL);
+
+ mm_base_modem_at_command (MM_BASE_MODEM (self),
+ "^SMONI=?",
+ 3,
+ FALSE,
+ (GAsyncReadyCallback) check_smoni_support,
+ task);
+}
+
+/*****************************************************************************/
+/* Load extended signal information (Signal interface) */
+
+static gboolean
+signal_load_values_finish (MMIfaceModemSignal *_self,
+ GAsyncResult *res,
+ MMSignal **cdma,
+ MMSignal **evdo,
+ MMSignal **gsm,
+ MMSignal **umts,
+ MMSignal **lte,
+ GError **error)
+{
+ MMBroadbandModemCinterion *self = MM_BROADBAND_MODEM_CINTERION (_self);
+ const gchar *response;
+
+ if (self->priv->smoni_support == FEATURE_NOT_SUPPORTED)
+ return iface_modem_signal_parent->load_values_finish (_self, res, cdma, evdo, gsm, umts, lte, error);
+
+ response = mm_base_modem_at_command_finish (MM_BASE_MODEM (_self), res, error);
+ if (!response || !mm_cinterion_smoni_response_to_signal_info (response, gsm, umts, lte, error))
+ return FALSE;
+
+ if (cdma)
+ *cdma = NULL;
+ if (evdo)
+ *evdo = NULL;
+
+ return TRUE;
+}
+
+static void
+signal_load_values (MMIfaceModemSignal *_self,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ MMBroadbandModemCinterion *self = MM_BROADBAND_MODEM_CINTERION (_self);
+ if (self->priv->smoni_support == FEATURE_SUPPORTED) {
+ mm_base_modem_at_command (MM_BASE_MODEM (_self),
+ "^SMONI",
+ 3,
+ FALSE,
+ callback,
+ user_data);
+ return;
+ }
+
+ /* ^SMONI not supported, fallback to the parent */
+ iface_modem_signal_parent->load_values (_self, cancellable, callback, user_data);
+}
+
+static void
+iface_modem_signal_init (MMIfaceModemSignal *iface)
+{
+ iface_modem_signal_parent = g_type_interface_peek_parent (iface);
+
+ iface->check_support = signal_check_support;
+ iface->check_support_finish = signal_check_support_finish;
+ iface->load_values = signal_load_values;
+ iface->load_values_finish = signal_load_values_finish;
+}