aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAleksander Morgado <aleksander@aleksander.es>2017-12-28 18:41:51 +0100
committerAleksander Morgado <aleksander@aleksander.es>2018-01-20 15:41:07 +0100
commit22ffd3f3aa4d8c1fbc1f6ab765bcfaf83f3d1c7f (patch)
treee96e6ab4048fa77588e9e9f1e74fa2f14bd781fc /src
parentd4aaa436d9679524f910b13176d4af35bd6b14f8 (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.
Diffstat (limited to 'src')
-rw-r--r--src/mm-broadband-modem.c66
-rw-r--r--src/mm-modem-helpers.c45
-rw-r--r--src/mm-modem-helpers.h6
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);