[PATCH 2/2] broadband-modem: implement support for the +CEMODE command

Aleksander Morgado aleksander at aleksander.es
Sat Jan 20 14:43:57 UTC 2018


On 28/12/17 18:41, Aleksander Morgado wrote:
> The +CEMODE command is defined in 3GPP TS 27.007 (e.g. in section
> 10.1.28 in v11.0.0). This command allows querying or updating the
> current UE mode, as well as checking the supported modes.
> 
> We implement support for loading the current mode and updating it. It
> is assumed that the device does any additional operation needed by the
> setting update, e.g. un-registering from CS when selecting an EPS-only
> mode.

Pushed to git master.

> ---
>  src/mm-broadband-modem.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++
>  src/mm-modem-helpers.c   | 45 +++++++++++++++++++++++++++++++++
>  src/mm-modem-helpers.h   |  6 +++++
>  3 files changed, 117 insertions(+)
> 
> diff --git a/src/mm-broadband-modem.c b/src/mm-broadband-modem.c
> index f82122b1..1e3bae69 100644
> --- a/src/mm-broadband-modem.c
> +++ b/src/mm-broadband-modem.c
> @@ -3821,6 +3821,68 @@ modem_3gpp_load_subscription_state (MMIfaceModem3gpp *self,
>      g_object_unref (task);
>  }
>  
> +/*****************************************************************************/
> +/* UE mode of operation for EPS loading (3GPP interface) */
> +
> +static MMModem3gppEpsUeModeOperation
> +modem_3gpp_load_eps_ue_mode_operation_finish (MMIfaceModem3gpp  *self,
> +                                              GAsyncResult      *res,
> +                                              GError          **error)
> +{
> +    MMModem3gppEpsUeModeOperation  mode;
> +    const gchar                   *result;
> +
> +    result = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, error);
> +    if (!result || !mm_3gpp_parse_cemode_query_response (result, &mode, error))
> +        return MM_MODEM_3GPP_EPS_UE_MODE_OPERATION_UNKNOWN;
> +
> +    return mode;
> +}
> +
> +static void
> +modem_3gpp_load_eps_ue_mode_operation (MMIfaceModem3gpp    *self,
> +                                       GAsyncReadyCallback  callback,
> +                                       gpointer             user_data)
> +{
> +    mm_dbg ("loading UE mode of operation for EPS...");
> +    mm_base_modem_at_command (MM_BASE_MODEM (self),
> +                              "+CEMODE?",
> +                              3,
> +                              FALSE,
> +                              callback,
> +                              user_data);
> +}
> +
> +/*****************************************************************************/
> +/* UE mode of operation for EPS settin (3GPP interface) */
> +
> +static gboolean
> +modem_3gpp_set_eps_ue_mode_operation_finish (MMIfaceModem3gpp  *self,
> +                                             GAsyncResult      *res,
> +                                             GError          **error)
> +{
> +    return !!mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, error);
> +}
> +
> +static void
> +modem_3gpp_set_eps_ue_mode_operation (MMIfaceModem3gpp              *self,
> +                                      MMModem3gppEpsUeModeOperation  mode,
> +                                      GAsyncReadyCallback            callback,
> +                                      gpointer                       user_data)
> +{
> +    gchar *cmd;
> +
> +    mm_dbg ("updating UE mode of operation for EPS...");
> +    cmd = mm_3gpp_build_cemode_set_request (mode);
> +    mm_base_modem_at_command (MM_BASE_MODEM (self),
> +                              cmd,
> +                              3,
> +                              FALSE,
> +                              callback,
> +                              user_data);
> +    g_free (cmd);
> +}
> +
>  /*****************************************************************************/
>  /* Unsolicited registration messages handling (3GPP interface) */
>  
> @@ -10922,6 +10984,8 @@ iface_modem_3gpp_init (MMIfaceModem3gpp *iface)
>      iface->load_imei_finish = modem_3gpp_load_imei_finish;
>      iface->load_enabled_facility_locks = modem_3gpp_load_enabled_facility_locks;
>      iface->load_enabled_facility_locks_finish = modem_3gpp_load_enabled_facility_locks_finish;
> +    iface->load_eps_ue_mode_operation = modem_3gpp_load_eps_ue_mode_operation;
> +    iface->load_eps_ue_mode_operation_finish = modem_3gpp_load_eps_ue_mode_operation_finish;
>  
>      /* Enabling steps */
>      iface->setup_unsolicited_events = modem_3gpp_setup_unsolicited_events;
> @@ -10956,6 +11020,8 @@ iface_modem_3gpp_init (MMIfaceModem3gpp *iface)
>      iface->register_in_network_finish = modem_3gpp_register_in_network_finish;
>      iface->scan_networks = modem_3gpp_scan_networks;
>      iface->scan_networks_finish = modem_3gpp_scan_networks_finish;
> +    iface->set_eps_ue_mode_operation = modem_3gpp_set_eps_ue_mode_operation;
> +    iface->set_eps_ue_mode_operation_finish = modem_3gpp_set_eps_ue_mode_operation_finish;
>  }
>  
>  static void
> diff --git a/src/mm-modem-helpers.c b/src/mm-modem-helpers.c
> index b2806dfa..9ba8c750 100644
> --- a/src/mm-modem-helpers.c
> +++ b/src/mm-modem-helpers.c
> @@ -2485,6 +2485,51 @@ mm_3gpp_parse_cfun_query_generic_response (const gchar        *response,
>      }
>  }
>  
> +static MMModem3gppEpsUeModeOperation cemode_values[] = {
> +    [0] = MM_MODEM_3GPP_EPS_UE_MODE_OPERATION_PS_2,
> +    [1] = MM_MODEM_3GPP_EPS_UE_MODE_OPERATION_CSPS_1,
> +    [2] = MM_MODEM_3GPP_EPS_UE_MODE_OPERATION_CSPS_2,
> +    [3] = MM_MODEM_3GPP_EPS_UE_MODE_OPERATION_PS_1,
> +};
> +
> +gchar *
> +mm_3gpp_build_cemode_set_request (MMModem3gppEpsUeModeOperation mode)
> +{
> +    guint i;
> +
> +    g_return_val_if_fail (mode != MM_MODEM_3GPP_EPS_UE_MODE_OPERATION_UNKNOWN, NULL);
> +
> +    for (i = 0; i < G_N_ELEMENTS (cemode_values); i++) {
> +        if (mode == cemode_values[i])
> +            return g_strdup_printf ("+CEMODE=%u", i);
> +    }
> +
> +    g_assert_not_reached ();
> +    return NULL;
> +}
> +
> +gboolean
> +mm_3gpp_parse_cemode_query_response (const gchar                    *response,
> +                                     MMModem3gppEpsUeModeOperation  *out_mode,
> +                                     GError                        **error)
> +{
> +    guint value = 0;
> +
> +    response = mm_strip_tag (response, "+CEMODE:");
> +    if (mm_get_uint_from_str (response, &value) && value < G_N_ELEMENTS (cemode_values)) {
> +        if (out_mode)
> +            *out_mode = cemode_values[value];
> +        return TRUE;
> +    }
> +
> +    g_set_error (error,
> +                 MM_CORE_ERROR,
> +                 MM_CORE_ERROR_FAILED,
> +                 "Couldn't parse UE mode of operation: '%s' (value %u)",
> +                 response, value);
> +    return FALSE;
> +}
> +
>  /*************************************************************************/
>  
>  static MMSmsStorage
> diff --git a/src/mm-modem-helpers.h b/src/mm-modem-helpers.h
> index 524f05ae..d14eb17b 100644
> --- a/src/mm-modem-helpers.h
> +++ b/src/mm-modem-helpers.h
> @@ -328,6 +328,12 @@ gboolean mm_3gpp_cesq_response_to_signal_info (const gchar  *response,
>                                                 MMSignal    **out_lte,
>                                                 GError      **error);
>  
> +/* CEMODE? response parser */
> +gchar    *mm_3gpp_build_cemode_set_request    (MMModem3gppEpsUeModeOperation   mode);
> +gboolean  mm_3gpp_parse_cemode_query_response (const gchar                    *response,
> +                                               MMModem3gppEpsUeModeOperation  *out_mode,
> +                                               GError                        **error);
> +
>  /* Additional 3GPP-specific helpers */
>  
>  MMModem3gppFacility mm_3gpp_acronym_to_facility (const gchar *str);
> 


-- 
Aleksander
https://aleksander.es


More information about the ModemManager-devel mailing list