[PATCH 2/4] broadband-modem: query +CMER format before enabling/disabling

Aleksander Morgado aleksander at aleksander.es
Sun May 21 12:54:39 UTC 2017


Don't blindly try '+CMER=3,0,0,1' to enable and '+CMER=0' to disable
Mobile Equipment Event Reporting. We now query the device for the
supported formats and use that info to build commands that will work.
---
 src/mm-broadband-modem.c | 116 +++++++++++++++++++++++++++++++++++++----------
 1 file changed, 91 insertions(+), 25 deletions(-)

diff --git a/src/mm-broadband-modem.c b/src/mm-broadband-modem.c
index 4a14d33d..5fcfccc5 100644
--- a/src/mm-broadband-modem.c
+++ b/src/mm-broadband-modem.c
@@ -150,6 +150,9 @@ struct _MMBroadbandModemPrivate {
     guint modem_cind_max_signal_quality;
     guint modem_cind_indicator_roaming;
     guint modem_cind_indicator_service;
+    MM3gppCmerMode modem_cmer_enable_mode;
+    MM3gppCmerMode modem_cmer_disable_mode;
+    MM3gppCmerInd modem_cmer_ind;
     MMFlowControl flow_control;
 
     /*<--- Modem 3GPP interface --->*/
@@ -2617,6 +2620,51 @@ set_unsolicited_events_handlers (MMBroadbandModem *self,
 }
 
 static void
+cmer_format_check_ready (MMBroadbandModem   *self,
+                         GAsyncResult       *res,
+                         GSimpleAsyncResult *simple)
+{
+    MM3gppCmerMode  supported_modes = MM_3GPP_CMER_MODE_NONE;
+    MM3gppCmerInd   supported_inds = MM_3GPP_CMER_IND_NONE;
+    GError         *error = NULL;
+    const gchar    *result;
+
+    result = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error);
+    if (error || !mm_3gpp_parse_cmer_test_response (result, &supported_modes, &supported_inds, &error)) {
+        mm_dbg ("+CMER check failed, marking indications as unsupported: '%s'", error->message);
+        g_error_free (error);
+        g_simple_async_result_set_op_res_gboolean (simple, TRUE);
+        g_simple_async_result_complete (simple);
+        g_object_unref (simple);
+        return;
+    }
+
+    /* Flag +CMER supported values */
+
+    if (supported_modes & MM_3GPP_CMER_MODE_FORWARD_URCS)
+        self->priv->modem_cmer_enable_mode = MM_3GPP_CMER_MODE_FORWARD_URCS;
+    else if (supported_modes & MM_3GPP_CMER_MODE_BUFFER_URCS_IF_LINK_RESERVED)
+        self->priv->modem_cmer_enable_mode = MM_3GPP_CMER_MODE_FORWARD_URCS;
+    else if (supported_modes & MM_3GPP_CMER_MODE_DISCARD_URCS_IF_LINK_RESERVED)
+        self->priv->modem_cmer_enable_mode = MM_3GPP_CMER_MODE_DISCARD_URCS_IF_LINK_RESERVED;
+
+    if (supported_modes & MM_3GPP_CMER_MODE_DISCARD_URCS)
+        self->priv->modem_cmer_disable_mode = MM_3GPP_CMER_MODE_DISCARD_URCS;
+
+    if (supported_inds & MM_3GPP_CMER_IND_ENABLE_NOT_CAUSED_BY_CIND)
+        self->priv->modem_cmer_ind = MM_3GPP_CMER_IND_ENABLE_NOT_CAUSED_BY_CIND;
+    else if (supported_inds & MM_3GPP_CMER_IND_ENABLE_ALL)
+        self->priv->modem_cmer_ind = MM_3GPP_CMER_IND_ENABLE_ALL;
+
+    /* Now, keep on setting up the ports */
+    set_unsolicited_events_handlers (self, TRUE);
+
+    g_simple_async_result_set_op_res_gboolean (simple, TRUE);
+    g_simple_async_result_complete (simple);
+    g_object_unref (simple);
+}
+
+static void
 cind_format_check_ready (MMBroadbandModem *self,
                          GAsyncResult *res,
                          GSimpleAsyncResult *simple)
@@ -2630,7 +2678,7 @@ cind_format_check_ready (MMBroadbandModem *self,
     if (error ||
         !(indicators = mm_3gpp_parse_cind_test_response (result, &error))) {
         /* unsupported indications */
-        mm_dbg ("Marking indications as unsupported: '%s'", error->message);
+        mm_dbg ("+CIND check failed, marking indications as unsupported: '%s'", error->message);
         g_error_free (error);
         g_simple_async_result_set_op_res_gboolean (simple, TRUE);
         g_simple_async_result_complete (simple);
@@ -2677,12 +2725,13 @@ cind_format_check_ready (MMBroadbandModem *self,
 
     g_hash_table_destroy (indicators);
 
-    /* Now, keep on setting up the ports */
-    set_unsolicited_events_handlers (self, TRUE);
-
-    g_simple_async_result_set_op_res_gboolean (simple, TRUE);
-    g_simple_async_result_complete (simple);
-    g_object_unref (simple);
+    /* Check +CMER required format */
+    mm_base_modem_at_command (MM_BASE_MODEM (self),
+                              "+CMER=?",
+                              3,
+                              TRUE,
+                              (GAsyncReadyCallback)cmer_format_check_ready,
+                              simple);
 }
 
 static void
@@ -2844,15 +2893,22 @@ modem_3gpp_enable_unsolicited_events (MMIfaceModem3gpp *_self,
 
     /* If supported, go on */
     if (self->priv->modem_cind_support_checked && self->priv->modem_cind_supported) {
-        UnsolicitedEventsContext *ctx;
-
-        ctx = g_new0 (UnsolicitedEventsContext, 1);
-        ctx->self = g_object_ref (self);
-        ctx->enable = TRUE;
-        ctx->command = g_strdup ("+CMER=3,0,0,1");
-        ctx->result = result;
-        run_unsolicited_events_setup (ctx);
-        return;
+        gchar *cmd;
+
+        /* If CMER command available, launch it */
+        cmd = mm_3gpp_build_cmer_set_request (self->priv->modem_cmer_enable_mode, self->priv->modem_cmer_ind);
+        if (cmd) {
+            UnsolicitedEventsContext *ctx;
+
+            ctx = g_new0 (UnsolicitedEventsContext, 1);
+            ctx->self = g_object_ref (self);
+            ctx->enable = TRUE;
+            ctx->command = cmd;
+            ctx->result = result;
+            run_unsolicited_events_setup (ctx);
+            return;
+        }
+        mm_dbg ("Skipping +CMER enable command: not supported");
     }
 
     g_simple_async_result_set_op_res_gboolean (result, TRUE);
@@ -2873,16 +2929,23 @@ modem_3gpp_disable_unsolicited_events (MMIfaceModem3gpp *_self,
                                         user_data,
                                         modem_3gpp_disable_unsolicited_events);
 
-    /* If supported, go on */
+    /* If CIND supported, go on */
     if (self->priv->modem_cind_support_checked && self->priv->modem_cind_supported) {
-        UnsolicitedEventsContext *ctx;
-
-        ctx = g_new0 (UnsolicitedEventsContext, 1);
-        ctx->self = g_object_ref (self);
-        ctx->command = g_strdup ("+CMER=0");
-        ctx->result = result;
-        run_unsolicited_events_setup (ctx);
-        return;
+        gchar *cmd;
+
+        /* If CMER command available, launch it */
+        cmd = mm_3gpp_build_cmer_set_request (self->priv->modem_cmer_disable_mode, MM_3GPP_CMER_IND_NONE);
+        if (cmd) {
+            UnsolicitedEventsContext *ctx;
+
+            ctx = g_new0 (UnsolicitedEventsContext, 1);
+            ctx->self = g_object_ref (self);
+            ctx->command = cmd;
+            ctx->result = result;
+            run_unsolicited_events_setup (ctx);
+            return;
+        }
+        mm_dbg ("Skipping +CMER disable command: not supported");
     }
 
     g_simple_async_result_set_op_res_gboolean (result, TRUE);
@@ -10693,6 +10756,9 @@ mm_broadband_modem_init (MMBroadbandModem *self)
     self->priv->current_sms_mem1_storage = MM_SMS_STORAGE_UNKNOWN;
     self->priv->current_sms_mem2_storage = MM_SMS_STORAGE_UNKNOWN;
     self->priv->sim_hot_swap_supported = FALSE;
+    self->priv->modem_cmer_enable_mode = MM_3GPP_CMER_MODE_NONE;
+    self->priv->modem_cmer_disable_mode = MM_3GPP_CMER_MODE_NONE;
+    self->priv->modem_cmer_ind = MM_3GPP_CMER_IND_NONE;
     self->priv->flow_control = MM_FLOW_CONTROL_NONE;
 }
 
-- 
2.12.2



More information about the ModemManager-devel mailing list