diff options
author | Aleksander Morgado <aleksander@aleksander.es> | 2017-12-28 18:41:51 +0100 |
---|---|---|
committer | Aleksander Morgado <aleksander@aleksander.es> | 2018-01-20 15:41:07 +0100 |
commit | 22ffd3f3aa4d8c1fbc1f6ab765bcfaf83f3d1c7f (patch) | |
tree | e96e6ab4048fa77588e9e9f1e74fa2f14bd781fc | |
parent | d4aaa436d9679524f910b13176d4af35bd6b14f8 (diff) |
broadband-modem: implement support for the +CEMODE command
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.
-rw-r--r-- | src/mm-broadband-modem.c | 66 | ||||
-rw-r--r-- | src/mm-modem-helpers.c | 45 | ||||
-rw-r--r-- | src/mm-modem-helpers.h | 6 |
3 files changed, 117 insertions, 0 deletions
diff --git a/src/mm-broadband-modem.c b/src/mm-broadband-modem.c index 24625735..ecefcf28 100644 --- a/src/mm-broadband-modem.c +++ b/src/mm-broadband-modem.c @@ -3936,6 +3936,68 @@ modem_3gpp_load_subscription_state (MMIfaceModem3gpp *self, } /*****************************************************************************/ +/* 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) */ static gboolean @@ -11038,6 +11100,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; @@ -11072,6 +11136,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 dce7e795..111cc38e 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 db2888b1..54dcce73 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); |