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

Aleksander Morgado aleksander at aleksander.es
Mon May 29 12:47:13 UTC 2017


On 21/05/17 21:51, Aleksander Morgado wrote:
> ---
> 
> Hey,
> 
> This patch implements some basic support for changing allowed modes for LTE capable Cinterion devices.
> 
> Comments?
> 

I rebased this patch on top of git master and merged it.

> ---
>  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
> 


-- 
Aleksander
https://aleksander.es


More information about the ModemManager-devel mailing list