summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--plugins/huawei/mm-broadband-modem-huawei.c132
1 files changed, 131 insertions, 1 deletions
diff --git a/plugins/huawei/mm-broadband-modem-huawei.c b/plugins/huawei/mm-broadband-modem-huawei.c
index 82652617..1c32670c 100644
--- a/plugins/huawei/mm-broadband-modem-huawei.c
+++ b/plugins/huawei/mm-broadband-modem-huawei.c
@@ -42,6 +42,7 @@ static void iface_modem_3gpp_init (MMIfaceModem3gpp *iface);
static void iface_modem_3gpp_ussd_init (MMIfaceModem3gppUssd *iface);
static void iface_modem_cdma_init (MMIfaceModemCdma *iface);
+static MMIfaceModem *iface_modem_parent;
static MMIfaceModem3gpp *iface_modem_3gpp_parent;
static MMIfaceModemCdma *iface_modem_cdma_parent;
@@ -1216,7 +1217,6 @@ decode (MMIfaceModem3gppUssd *self,
}
/*****************************************************************************/
-/* Setup/Cleanup unsolicited events (CDMA interface) */
static void
huawei_1x_signal_changed (MMAtSerialPort *port,
@@ -1248,6 +1248,132 @@ huawei_evdo_signal_changed (MMAtSerialPort *port,
mm_iface_modem_update_signal_quality (MM_IFACE_MODEM (self), (guint)quality);
}
+/* Signal quality loading (Modem interface) */
+
+static guint
+modem_load_signal_quality_finish (MMIfaceModem *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error))
+ return 0;
+
+ return GPOINTER_TO_UINT (g_simple_async_result_get_op_res_gpointer (
+ G_SIMPLE_ASYNC_RESULT (res)));
+}
+
+static void
+parent_load_signal_quality_ready (MMIfaceModem *self,
+ GAsyncResult *res,
+ GSimpleAsyncResult *simple)
+{
+ GError *error = NULL;
+ guint signal_quality;
+
+ signal_quality = iface_modem_parent->load_signal_quality_finish (self, res, &error);
+ if (error)
+ g_simple_async_result_take_error (simple, error);
+ else
+ g_simple_async_result_set_op_res_gpointer (simple,
+ GUINT_TO_POINTER (signal_quality),
+ NULL);
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+}
+
+static void
+signal_ready (MMBaseModem *self,
+ GAsyncResult *res,
+ GSimpleAsyncResult *simple)
+{
+ const gchar *response, *command;
+ gchar buf[5];
+ guint quality = 0, i = 0;
+
+ response = mm_base_modem_at_command_finish (self, res, NULL);
+ if (!response) {
+ /* Fallback to parent's method */
+ iface_modem_parent->load_signal_quality (
+ MM_IFACE_MODEM (self),
+ (GAsyncReadyCallback)parent_load_signal_quality_ready,
+ simple);
+ return;
+ }
+
+ command = g_object_get_data (G_OBJECT (simple), "command");
+ g_assert (command);
+ response = mm_strip_tag (response, command);
+ /* 'command' won't include the trailing ':' in the response, so strip that */
+ while ((*response == ':') || isspace (*response))
+ response++;
+
+ /* Sanitize response for mm_get_uint_from_str() which wants only digits */
+ memset (buf, 0, sizeof (buf));
+ while (i < (sizeof (buf) - 1) && isdigit (*response))
+ buf[i++] = *response++;
+
+ if (mm_get_uint_from_str (buf, &quality)) {
+ quality = CLAMP (quality, 0, 100);
+ g_simple_async_result_set_op_res_gpointer (simple,
+ GUINT_TO_POINTER (quality),
+ NULL);
+ } else {
+ g_simple_async_result_set_error (simple,
+ MM_CORE_ERROR,
+ MM_CORE_ERROR_FAILED,
+ "Couldn't parse %s response: '%s'",
+ command, response);
+ }
+
+ g_simple_async_result_complete (simple);
+ g_object_unref (simple);
+}
+
+static void
+modem_load_signal_quality (MMIfaceModem *self,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *result;
+ MMModemCdmaRegistrationState evdo_state = MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN;
+ const char *command = "^CSQLVL";
+
+ mm_dbg ("loading signal quality...");
+ result = g_simple_async_result_new (G_OBJECT (self),
+ callback,
+ user_data,
+ modem_load_signal_quality);
+
+ /* 3GPP modems can just run parent's signal quality loading */
+ if (mm_iface_modem_is_3gpp (self)) {
+ iface_modem_parent->load_signal_quality (
+ self,
+ (GAsyncReadyCallback)parent_load_signal_quality_ready,
+ result);
+ return;
+ }
+
+ /* CDMA modems need custom signal quality loading */
+
+ g_object_get (G_OBJECT (self),
+ MM_IFACE_MODEM_CDMA_EVDO_REGISTRATION_STATE, &evdo_state,
+ NULL);
+ if (evdo_state > MM_MODEM_CDMA_REGISTRATION_STATE_UNKNOWN)
+ command = "^HDRCSQLVL";
+ g_object_set_data (G_OBJECT (result), "command", (gpointer) command);
+
+ mm_base_modem_at_command (
+ MM_BASE_MODEM (self),
+ command,
+ 3,
+ FALSE,
+ (GAsyncReadyCallback)signal_ready,
+ result);
+}
+
+/*****************************************************************************/
+/* Setup/Cleanup unsolicited events (CDMA interface) */
+
static void
set_cdma_unsolicited_events_handlers (MMBroadbandModemHuawei *self,
gboolean enable)
@@ -1732,6 +1858,8 @@ finalize (GObject *object)
static void
iface_modem_init (MMIfaceModem *iface)
{
+ iface_modem_parent = g_type_interface_peek_parent (iface);
+
iface->load_access_technologies = load_access_technologies;
iface->load_access_technologies_finish = load_access_technologies_finish;
iface->load_unlock_retries = load_unlock_retries;
@@ -1744,6 +1872,8 @@ iface_modem_init (MMIfaceModem *iface)
iface->load_allowed_modes_finish = load_allowed_modes_finish;
iface->set_allowed_modes = set_allowed_modes;
iface->set_allowed_modes_finish = set_allowed_modes_finish;
+ iface->load_signal_quality = modem_load_signal_quality;
+ iface->load_signal_quality_finish = modem_load_signal_quality_finish;
}
static void