[PATCH 2/2] broadband-modem-mbim: implement initial signal quality loading

Ben Chan benchan at chromium.org
Mon Apr 23 23:24:42 UTC 2018


ModemManager currently relies on unsolicited MBIM_CID_SIGNAL_STATE
notifications to obtain signal quality updates, and it doesn't query the
initial signal quality. It's been observed that some MBIM modems issue a
MBIM_CID_SIGNAL_STATE notification only when there is a notable change
in RSSI. The signal quality may remain at 0 for quite some time. It's
more noticeable when simply restarting ModemManager after the modem has
been initialized and enabled once.

We could simply enable periodic signal check on an MBIM modem, but
that's less ideal as it may unnecessarily wake the modem up from USB
selective suspend (unless we use a much longer polling period).

To address the issue, this patch adds the implementation of
load_signal_quality to MMBroadbandModemMbim so that the signal quality
is initially polled via a solicited MBIM_CID_SIGNAL_STATE query. To
avoid the periodic signal check, we set the
MM_IFACE_MODEM_PERIODIC_SIGNAL_CHECK_DISABLED property to TRUE for
MMBroadbandModemMbim.
---
 src/mm-broadband-modem-mbim.c | 80 ++++++++++++++++++++++++++++++++++-
 1 file changed, 78 insertions(+), 2 deletions(-)

diff --git a/src/mm-broadband-modem-mbim.c b/src/mm-broadband-modem-mbim.c
index d6562088..09e1ffb7 100644
--- a/src/mm-broadband-modem-mbim.c
+++ b/src/mm-broadband-modem-mbim.c
@@ -1433,6 +1433,79 @@ modem_power_down (MMIfaceModem *self,
     mbim_message_unref (message);
 }
 
+/*****************************************************************************/
+/* Signal quality loading (Modem interface) */
+
+static guint
+modem_load_signal_quality_finish (MMIfaceModem *self,
+                                  GAsyncResult *res,
+                                  GError **error)
+{
+    gssize value;
+
+    value = g_task_propagate_int (G_TASK (res), error);
+    return value < 0 ? 0 : value;
+}
+
+static void
+signal_state_query_ready (MbimDevice *device,
+                          GAsyncResult *res,
+                          GTask *task)
+{
+    MbimMessage *response;
+    GError *error = NULL;
+    guint32 rssi;
+
+    response = mbim_device_command_finish (device, res, &error);
+    if (response &&
+        mbim_message_response_get_result (response, MBIM_MESSAGE_TYPE_COMMAND_DONE, &error) &&
+        mbim_message_signal_state_response_parse (
+            response,
+            &rssi,
+            NULL, /* error_rate */
+            NULL, /* signal_strength_interval */
+            NULL, /* rssi_threshold */
+            NULL, /* error_rate_threshold */
+            &error)) {
+        guint32 quality;
+
+        /* Normalize the quality. 99 means unknown, we default it to 0 */
+        quality = CLAMP (rssi == 99 ? 0 : rssi, 0, 31) * 100 / 31;
+
+        g_task_return_int (task, quality);
+    } else
+        g_task_return_error (task, error);
+
+    g_object_unref (task);
+
+    if (response)
+        mbim_message_unref (response);
+}
+
+static void
+modem_load_signal_quality (MMIfaceModem *self,
+                           GAsyncReadyCallback callback,
+                           gpointer user_data)
+{
+    MbimDevice *device;
+    MbimMessage *message;
+    GTask *task;
+
+    if (!peek_device (self, &device, callback, user_data))
+        return;
+
+    task = g_task_new (self, NULL, callback, user_data);
+
+    message = mbim_message_signal_state_query_new (NULL);
+    mbim_device_command (device,
+                         message,
+                         10,
+                         NULL,
+                         (GAsyncReadyCallback)signal_state_query_ready,
+                         task);
+    mbim_message_unref (message);
+}
+
 /*****************************************************************************/
 /* Create Bearer (Modem interface) */
 
@@ -3305,6 +3378,7 @@ mm_broadband_modem_mbim_new (const gchar *device,
                          MM_BASE_MODEM_PRODUCT_ID, product_id,
                          MM_IFACE_MODEM_SIM_HOT_SWAP_SUPPORTED, TRUE,
                          MM_IFACE_MODEM_SIM_HOT_SWAP_CONFIGURED, FALSE,
+                         MM_IFACE_MODEM_PERIODIC_SIGNAL_CHECK_DISABLED, TRUE,
                          NULL);
 }
 
@@ -3379,6 +3453,10 @@ iface_modem_init (MMIfaceModem *iface)
     iface->load_supported_ip_families = modem_load_supported_ip_families;
     iface->load_supported_ip_families_finish = modem_load_supported_ip_families_finish;
 
+    /* Additional actions */
+    iface->load_signal_quality = modem_load_signal_quality;
+    iface->load_signal_quality_finish = modem_load_signal_quality_finish;
+
     /* Unneeded things */
     iface->modem_after_power_up = NULL;
     iface->modem_after_power_up_finish = NULL;
@@ -3388,8 +3466,6 @@ iface_modem_init (MMIfaceModem *iface)
     iface->setup_flow_control_finish = NULL;
     iface->setup_charset = NULL;
     iface->setup_charset_finish = NULL;
-    iface->load_signal_quality = NULL;
-    iface->load_signal_quality_finish = NULL;
     iface->load_access_technologies = NULL;
     iface->load_access_technologies_finish = NULL;
 
-- 
2.17.0.484.g0c8726318c-goog



More information about the ModemManager-devel mailing list