[PATCH] cinterion: support changing modes in LTE capable devices

Aleksander Morgado aleksander at aleksander.es
Sun May 21 19:51:32 UTC 2017


---

Hey,

This patch implements some basic support for changing allowed modes for LTE capable Cinterion devices.

Comments?

---
 plugins/cinterion/mm-broadband-modem-cinterion.c | 162 +++++++++++------------
 1 file changed, 77 insertions(+), 85 deletions(-)

diff --git a/plugins/cinterion/mm-broadband-modem-cinterion.c b/plugins/cinterion/mm-broadband-modem-cinterion.c
index f59e3d0e..1ffc3bf3 100644
--- a/plugins/cinterion/mm-broadband-modem-cinterion.c
+++ b/plugins/cinterion/mm-broadband-modem-cinterion.c
@@ -972,20 +972,17 @@ modem_3gpp_cleanup_unsolicited_events (MMIfaceModem3gpp    *self,
 /* Load supported modes (Modem interface) */

 static GArray *
-load_supported_modes_finish (MMIfaceModem *self,
-                             GAsyncResult *res,
-                             GError **error)
+load_supported_modes_finish (MMIfaceModem  *self,
+                             GAsyncResult  *res,
+                             GError       **error)
 {
-    if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error))
-        return NULL;
-
-    return g_array_ref (g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res)));
+    return g_task_propagate_pointer (G_TASK (res), error);
 }

 static void
 parent_load_supported_modes_ready (MMIfaceModem *self,
                                    GAsyncResult *res,
-                                   GSimpleAsyncResult *simple)
+                                   GTask        *task)
 {
     GError *error = NULL;
     GArray *all;
@@ -995,9 +992,8 @@ parent_load_supported_modes_ready (MMIfaceModem *self,

     all = iface_modem_parent->load_supported_modes_finish (self, res, &error);
     if (!all) {
-        g_simple_async_result_take_error (simple, error);
-        g_simple_async_result_complete (simple);
-        g_object_unref (simple);
+        g_task_return_error (task, error);
+        g_object_unref (task);
         return;
     }

@@ -1012,19 +1008,30 @@ parent_load_supported_modes_ready (MMIfaceModem *self,
     mode.allowed = MM_MODEM_MODE_3G;
     mode.preferred = MM_MODEM_MODE_NONE;
     g_array_append_val (combinations, mode);
-    /* 2G and 3G */
-    mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G);
-    mode.preferred = MM_MODEM_MODE_NONE;
-    g_array_append_val (combinations, mode);
+
+    if (mm_iface_modem_is_4g (self)) {
+        /* 4G only */
+        mode.allowed = MM_MODEM_MODE_4G;
+        mode.preferred = MM_MODEM_MODE_NONE;
+        g_array_append_val (combinations, mode);
+        /* 2G, 3G and 4G */
+        mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G | MM_MODEM_MODE_4G);
+        mode.preferred = MM_MODEM_MODE_NONE;
+        g_array_append_val (combinations, mode);
+    } else {
+        /* 2G and 3G */
+        mode.allowed = (MM_MODEM_MODE_2G | MM_MODEM_MODE_3G);
+        mode.preferred = MM_MODEM_MODE_NONE;
+        g_array_append_val (combinations, mode);
+    }

     /* Filter out those unsupported modes */
     filtered = mm_filter_supported_modes (all, combinations);
     g_array_unref (all);
     g_array_unref (combinations);

-    g_simple_async_result_set_op_res_gpointer (simple, filtered, (GDestroyNotify) g_array_unref);
-    g_simple_async_result_complete (simple);
-    g_object_unref (simple);
+    g_task_return_pointer (task, filtered, (GDestroyNotify) g_array_unref);
+    g_object_unref (task);
 }

 static void
@@ -1036,102 +1043,87 @@ load_supported_modes (MMIfaceModem *self,
     iface_modem_parent->load_supported_modes (
         MM_IFACE_MODEM (self),
         (GAsyncReadyCallback)parent_load_supported_modes_ready,
-        g_simple_async_result_new (G_OBJECT (self),
-                                   callback,
-                                   user_data,
-                                   load_supported_modes));
+        g_task_new (self, NULL, callback, user_data));
 }

 /*****************************************************************************/
 /* Set current modes (Modem interface) */

 static gboolean
-set_current_modes_finish (MMIfaceModem *self,
-                          GAsyncResult *res,
-                          GError **error)
+set_current_modes_finish (MMIfaceModem  *self,
+                          GAsyncResult  *res,
+                          GError       **error)
 {
-    return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error);
+    return g_task_propagate_boolean (G_TASK (res), error);
 }

 static void
 allowed_access_technology_update_ready (MMBroadbandModemCinterion *self,
-                                        GAsyncResult *res,
-                                        GSimpleAsyncResult *operation_result)
+                                        GAsyncResult              *res,
+                                        GTask                     *task)
 {
     GError *error = NULL;

     mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, &error);
     if (error)
-        /* Let the error be critical. */
-        g_simple_async_result_take_error (operation_result, error);
+        g_task_return_error (task, error);
     else
-        g_simple_async_result_set_op_res_gboolean (operation_result, TRUE);
-    g_simple_async_result_complete (operation_result);
-    g_object_unref (operation_result);
+        g_task_return_boolean (task, TRUE);
+    g_object_unref (task);
 }

 static void
-set_current_modes (MMIfaceModem *_self,
-                   MMModemMode allowed,
-                   MMModemMode preferred,
-                   GAsyncReadyCallback callback,
-                   gpointer user_data)
+set_current_modes (MMIfaceModem        *_self,
+                   MMModemMode          allowed,
+                   MMModemMode          preferred,
+                   GAsyncReadyCallback  callback,
+                   gpointer             user_data)
 {
-    GSimpleAsyncResult *result;
     MMBroadbandModemCinterion *self = MM_BROADBAND_MODEM_CINTERION (_self);
+    gchar                     *command;
+    GTask                     *task;

     g_assert (preferred == MM_MODEM_MODE_NONE);

-    result = g_simple_async_result_new (G_OBJECT (self),
-                                        callback,
-                                        user_data,
-                                        set_current_modes);
-
-    /* For dual 2G/3G devices... */
-    if (mm_iface_modem_is_2g (_self) &&
-        mm_iface_modem_is_3g (_self)) {
-        gchar *command;
-
-        /* We will try to simulate the possible allowed modes here. The
-         * Cinterion devices do not seem to allow setting preferred access
-         * technology in 3G devices, but they allow restricting to a given
-         * one:
-         * - 2G-only is forced by forcing GERAN RAT (AcT=0)
-         * - 3G-only is forced by forcing UTRAN RAT (AcT=2)
-         * - for the remaining ones, we default to automatic selection of RAT,
-         *   which is based on the quality of the connection.
-         */
+    task = g_task_new (self, NULL, callback, user_data);

-        if (allowed == MM_MODEM_MODE_3G)
-            command = g_strdup ("+COPS=,,,2");
-        else if (allowed == MM_MODEM_MODE_2G)
-            command = g_strdup ("+COPS=,,,0");
-        else if (allowed == (MM_MODEM_MODE_3G | MM_MODEM_MODE_2G)) {
-            /* no AcT given, defaults to Auto. For this case, we cannot provide
-             * AT+COPS=,,, (i.e. just without a last value). Instead, we need to
-             * re-run the last manual/automatic selection command which succeeded,
-             * (or auto by default if none was launched) */
-            if (self->priv->manual_operator_id)
-                command = g_strdup_printf ("+COPS=1,2,\"%s\"", self->priv->manual_operator_id);
-            else
-                command = g_strdup ("+COPS=0");
-        } else
-            g_assert_not_reached ();
+    /* We will try to simulate the possible allowed modes here. The
+     * Cinterion devices do not seem to allow setting preferred access
+     * technology in devices, but they allow restricting to a given
+     * one:
+     * - 2G-only is forced by forcing GERAN RAT (AcT=0)
+     * - 3G-only is forced by forcing UTRAN RAT (AcT=2)
+     * - 4G-only is forced by forcing E-UTRAN RAT (AcT=7)
+     * - for the remaining ones, we default to automatic selection of RAT,
+     *   which is based on the quality of the connection.
+     */

-        mm_base_modem_at_command (
-            MM_BASE_MODEM (self),
-            command,
-            20,
-            FALSE,
-            (GAsyncReadyCallback)allowed_access_technology_update_ready,
-            result);
-        g_free (command);
-        return;
+    if (mm_iface_modem_is_4g (_self) && allowed == MM_MODEM_MODE_4G)
+        command = g_strdup ("+COPS=,,,7");
+    else if (mm_iface_modem_is_3g (_self) && allowed == MM_MODEM_MODE_3G)
+        command = g_strdup ("+COPS=,,,2");
+    else if (mm_iface_modem_is_2g (_self) && allowed == MM_MODEM_MODE_2G)
+        command = g_strdup ("+COPS=,,,0");
+    else {
+        /* For any other combination (e.g. ANY or  no AcT given, defaults to Auto. For this case, we cannot provide
+         * AT+COPS=,,, (i.e. just without a last value). Instead, we need to
+         * re-run the last manual/automatic selection command which succeeded,
+         * (or auto by default if none was launched) */
+        if (self->priv->manual_operator_id)
+            command = g_strdup_printf ("+COPS=1,2,\"%s\"", self->priv->manual_operator_id);
+        else
+            command = g_strdup ("+COPS=0");
     }

-    /* For 2G-only and 3G-only devices, we already stated that we don't
-     * support mode switching. */
-    g_assert_not_reached ();
+    mm_base_modem_at_command (
+        MM_BASE_MODEM (self),
+        command,
+        20,
+        FALSE,
+        (GAsyncReadyCallback)allowed_access_technology_update_ready,
+        task);
+
+    g_free (command);
 }

 /*****************************************************************************/
--
2.12.2


More information about the ModemManager-devel mailing list