[PATCH 1/2] modem-3gpp: allow loading and changing EPS UE mode of operation
Aleksander Morgado
aleksander at aleksander.es
Thu Dec 28 17:41:50 UTC 2017
The UE modes of operation for LTE are defined in 3GPP TS 24.301 (e.g.
section 4.3 in v10.3.0):
* PS mode 1: EPS only, 'voice centric'
* PS mode 2: EPS only, 'data centric'
* CS/PS mode 1: EPS and non-EPS, 'voice centric'
* CS/PS mode 2: EPS and non-EPS, 'data centric'
The mode specifies, among other things, how the UE should behave w.r.t
CS fallback depending on the capabilities reported by the network.
---
cli/mmcli-modem-3gpp.c | 76 +++++++++
cli/mmcli-modem.c | 9 +-
docs/reference/api/ModemManager-sections.txt | 1 +
docs/reference/libmm-glib/libmm-glib-sections.txt | 13 ++
include/ModemManager-enums.h | 18 +++
...g.freedesktop.ModemManager1.Modem.Modem3gpp.xml | 19 +++
libmm-glib/mm-common-helpers.c | 22 +++
libmm-glib/mm-common-helpers.h | 3 +
libmm-glib/mm-modem-3gpp.c | 53 ++++++
libmm-glib/mm-modem-3gpp.h | 14 ++
src/mm-iface-modem-3gpp.c | 177 ++++++++++++++++++++-
src/mm-iface-modem-3gpp.h | 17 ++
12 files changed, 418 insertions(+), 4 deletions(-)
diff --git a/cli/mmcli-modem-3gpp.c b/cli/mmcli-modem-3gpp.c
index a785d025..b687d88d 100644
--- a/cli/mmcli-modem-3gpp.c
+++ b/cli/mmcli-modem-3gpp.c
@@ -49,6 +49,7 @@ static Context *ctx;
static gboolean scan_flag;
static gboolean register_home_flag;
static gchar *register_in_operator_str;
+static gchar *set_eps_ue_mode_operation_str;
static gboolean ussd_status_flag;
static gchar *ussd_initiate_str;
static gchar *ussd_respond_str;
@@ -67,6 +68,10 @@ static GOptionEntry entries[] = {
"Request a given modem to register in the network of the given operator",
"[MCCMNC]"
},
+ { "3gpp-set-eps-ue-mode-operation", 0, 0, G_OPTION_ARG_STRING, &set_eps_ue_mode_operation_str,
+ "Set the UE mode of operation for EPS",
+ "[ps-1|ps-2|csps-1|csps-2]"
+ },
{ "3gpp-ussd-status", 0, 0, G_OPTION_ARG_NONE, &ussd_status_flag,
"Show status of any ongoing USSD session",
NULL
@@ -113,6 +118,7 @@ mmcli_modem_3gpp_options_enabled (void)
n_actions = (scan_flag +
register_home_flag +
!!register_in_operator_str +
+ !!set_eps_ue_mode_operation_str +
ussd_status_flag +
!!ussd_initiate_str +
!!ussd_respond_str +
@@ -291,6 +297,45 @@ register_ready (MMModem3gpp *modem_3gpp,
mmcli_async_operation_done ();
}
+static void
+set_eps_ue_mode_operation_process_reply (gboolean result,
+ const GError *error)
+{
+ if (!result) {
+ g_printerr ("error: couldn't set UE mode of operation for EPS: '%s'\n",
+ error ? error->message : "unknown error");
+ exit (EXIT_FAILURE);
+ }
+
+ g_print ("successfully set UE mode of operation for EPS\n");
+}
+
+static void
+set_eps_ue_mode_operation_ready (MMModem3gpp *modem,
+ GAsyncResult *result)
+{
+ gboolean operation_result;
+ GError *error = NULL;
+
+ operation_result = mm_modem_3gpp_set_eps_ue_mode_operation_finish (modem, result, &error);
+ set_eps_ue_mode_operation_process_reply (operation_result, error);
+
+ mmcli_async_operation_done ();
+}
+
+static void
+parse_eps_ue_mode_operation (MMModem3gppEpsUeModeOperation *uemode)
+{
+ GError *error = NULL;
+
+ *uemode = mm_common_get_eps_ue_mode_operation_from_string (set_eps_ue_mode_operation_str, &error);
+ if (error) {
+ g_printerr ("error: couldn't parse UE mode of operation for EPS: '%s'\n",
+ error->message);
+ exit (EXIT_FAILURE);
+ }
+}
+
static void
print_ussd_status (void)
{
@@ -438,6 +483,21 @@ get_modem_ready (GObject *source,
return;
}
+ /* Request to set UE mode of operation for EPS? */
+ if (set_eps_ue_mode_operation_str) {
+ MMModem3gppEpsUeModeOperation uemode;
+
+ parse_eps_ue_mode_operation (&uemode);
+
+ g_debug ("Asynchronously setting UE mode of operation for EPS...");
+ mm_modem_3gpp_set_eps_ue_mode_operation (ctx->modem_3gpp,
+ uemode,
+ ctx->cancellable,
+ (GAsyncReadyCallback)set_eps_ue_mode_operation_ready,
+ NULL);
+ return;
+ }
+
/* Request to initiate USSD session? */
if (ussd_initiate_str) {
ensure_modem_3gpp_ussd ();
@@ -538,6 +598,22 @@ mmcli_modem_3gpp_run_synchronous (GDBusConnection *connection)
return;
}
+ /* Request to set UE mode of operation for EPS? */
+ if (set_eps_ue_mode_operation_str) {
+ MMModem3gppEpsUeModeOperation uemode;
+ gboolean result;
+
+ parse_eps_ue_mode_operation (&uemode);
+
+ g_debug ("Synchronously setting UE mode of operation for EPS...");
+ result = mm_modem_3gpp_set_eps_ue_mode_operation_sync (ctx->modem_3gpp,
+ uemode,
+ NULL,
+ &error);
+ set_eps_ue_mode_operation_process_reply (result, error);
+ return;
+ }
+
/* Request to show USSD status? */
if (ussd_status_flag) {
ensure_modem_3gpp_ussd ();
diff --git a/cli/mmcli-modem.c b/cli/mmcli-modem.c
index a3c1152c..0f220f25 100644
--- a/cli/mmcli-modem.c
+++ b/cli/mmcli-modem.c
@@ -470,15 +470,18 @@ print_modem_info (void)
" | operator id: '%s'\n"
" | operator name: '%s'\n"
" | subscription: '%s'\n"
- " | registration: '%s'\n",
+ " | registration: '%s'\n"
+ " | EPS UE mode: '%s'\n",
VALIDATE_UNKNOWN (mm_modem_3gpp_get_imei (ctx->modem_3gpp)),
facility_locks,
VALIDATE_UNKNOWN (mm_modem_3gpp_get_operator_code (ctx->modem_3gpp)),
VALIDATE_UNKNOWN (mm_modem_3gpp_get_operator_name (ctx->modem_3gpp)),
mm_modem_3gpp_subscription_state_get_string (
- mm_modem_3gpp_get_subscription_state ((ctx->modem_3gpp))),
+ mm_modem_3gpp_get_subscription_state (ctx->modem_3gpp)),
mm_modem_3gpp_registration_state_get_string (
- mm_modem_3gpp_get_registration_state ((ctx->modem_3gpp))));
+ mm_modem_3gpp_get_registration_state (ctx->modem_3gpp)),
+ mm_modem_3gpp_eps_ue_mode_operation_get_string (
+ mm_modem_3gpp_get_eps_ue_mode_operation (ctx->modem_3gpp)));
g_free (facility_locks);
}
diff --git a/docs/reference/api/ModemManager-sections.txt b/docs/reference/api/ModemManager-sections.txt
index a60c3a41..497f6e38 100644
--- a/docs/reference/api/ModemManager-sections.txt
+++ b/docs/reference/api/ModemManager-sections.txt
@@ -22,6 +22,7 @@ MMModem3gppNetworkAvailability
MMModem3gppSubscriptionState
MMModem3gppRegistrationState
MMModem3gppUssdSessionState
+MMModem3gppEpsUeModeOperation
MMModemAccessTechnology
MMModemBand
MMModemCapability
diff --git a/docs/reference/libmm-glib/libmm-glib-sections.txt b/docs/reference/libmm-glib/libmm-glib-sections.txt
index fd790475..77df5a79 100644
--- a/docs/reference/libmm-glib/libmm-glib-sections.txt
+++ b/docs/reference/libmm-glib/libmm-glib-sections.txt
@@ -283,6 +283,9 @@ mm_modem_3gpp_register_sync
mm_modem_3gpp_scan
mm_modem_3gpp_scan_finish
mm_modem_3gpp_scan_sync
+mm_modem_3gpp_set_eps_ue_mode_operation
+mm_modem_3gpp_set_eps_ue_mode_operation_finish
+mm_modem_3gpp_set_eps_ue_mode_operation_sync
<SUBSECTION Standard>
MMModem3gppClass
MM_IS_MODEM_3GPP
@@ -1325,6 +1328,7 @@ mm_modem_3gpp_subscription_state_get_string
mm_modem_3gpp_facility_build_string_from_mask
mm_modem_3gpp_network_availability_get_string
mm_modem_3gpp_ussd_session_state_get_string
+mm_modem_3gpp_eps_ue_mode_operation_get_string
mm_modem_cdma_registration_state_get_string
mm_modem_cdma_activation_state_get_string
mm_modem_cdma_rm_protocol_get_string
@@ -1375,6 +1379,7 @@ mm_modem_3gpp_subscription_state_build_string_from_mask
mm_modem_3gpp_facility_get_string
mm_modem_3gpp_network_availability_build_string_from_mask
mm_modem_3gpp_ussd_session_state_build_string_from_mask
+mm_modem_3gpp_eps_ue_mode_operation_build_string_from_mask
mm_firmware_image_type_build_string_from_mask
mm_modem_port_type_build_string_from_mask
mm_oma_feature_get_string
@@ -1394,6 +1399,7 @@ MM_TYPE_MODEM_3GPP_NETWORK_AVAILABILITY
MM_TYPE_MODEM_3GPP_REGISTRATION_STATE
MM_TYPE_MODEM_3GPP_SUBSCRIPTION_STATE
MM_TYPE_MODEM_3GPP_USSD_SESSION_STATE
+MM_TYPE_MODEM_3GPP_EPS_UE_MODE_OPERATION
MM_TYPE_MODEM_ACCESS_TECHNOLOGY
MM_TYPE_MODEM_BAND
MM_TYPE_MODEM_CAPABILITY
@@ -1432,6 +1438,7 @@ mm_modem_3gpp_network_availability_get_type
mm_modem_3gpp_registration_state_get_type
mm_modem_3gpp_subscription_state_get_type
mm_modem_3gpp_ussd_session_state_get_type
+mm_modem_3gpp_eps_ue_mode_operation_get_type
mm_modem_access_technology_get_type
mm_modem_band_get_type
mm_modem_capability_get_type
@@ -1666,6 +1673,7 @@ mm_gdbus_modem3gpp_get_operator_name
mm_gdbus_modem3gpp_dup_operator_name
mm_gdbus_modem3gpp_get_enabled_facility_locks
mm_gdbus_modem3gpp_get_subscription_state
+mm_gdbus_modem3gpp_get_eps_ue_mode_operation
<SUBSECTION Methods>
mm_gdbus_modem3gpp_call_register
mm_gdbus_modem3gpp_call_register_finish
@@ -1673,9 +1681,13 @@ mm_gdbus_modem3gpp_call_register_sync
mm_gdbus_modem3gpp_call_scan
mm_gdbus_modem3gpp_call_scan_finish
mm_gdbus_modem3gpp_call_scan_sync
+mm_gdbus_modem3gpp_call_set_eps_ue_mode_operation
+mm_gdbus_modem3gpp_call_set_eps_ue_mode_operation_finish
+mm_gdbus_modem3gpp_call_set_eps_ue_mode_operation_sync
<SUBSECTION Private>
mm_gdbus_modem3gpp_complete_register
mm_gdbus_modem3gpp_complete_scan
+mm_gdbus_modem3gpp_complete_set_eps_ue_mode_operation
mm_gdbus_modem3gpp_interface_info
mm_gdbus_modem3gpp_override_properties
mm_gdbus_modem3gpp_set_enabled_facility_locks
@@ -1684,6 +1696,7 @@ mm_gdbus_modem3gpp_set_operator_code
mm_gdbus_modem3gpp_set_operator_name
mm_gdbus_modem3gpp_set_registration_state
mm_gdbus_modem3gpp_set_subscription_state
+mm_gdbus_modem3gpp_set_eps_ue_mode_operation
<SUBSECTION Standard>
MM_GDBUS_IS_MODEM3GPP
MM_GDBUS_MODEM3GPP
diff --git a/include/ModemManager-enums.h b/include/ModemManager-enums.h
index ff4779fd..8f05ec00 100644
--- a/include/ModemManager-enums.h
+++ b/include/ModemManager-enums.h
@@ -1155,6 +1155,24 @@ typedef enum { /*< underscore_name=mm_modem_3gpp_ussd_session_state >*/
MM_MODEM_3GPP_USSD_SESSION_STATE_USER_RESPONSE = 3,
} MMModem3gppUssdSessionState;
+/**
+ * MMModem3gppEpsUeModeOperation:
+ * @MM_MODEM_3GPP_EPS_UE_MODE_OPERATION_UNKNOWN: Unknown or not applicable.
+ * @MM_MODEM_3GPP_EPS_UE_MODE_OPERATION_PS_1: PS mode 1 of operation: EPS only, voice-centric.
+ * @MM_MODEM_3GPP_EPS_UE_MODE_OPERATION_PS_2: PS mode 2 of operation: EPS only, data-centric.
+ * @MM_MODEM_3GPP_EPS_UE_MODE_OPERATION_CSPS_1: CS/PS mode 1 of operation: EPS and non-EPS, voice-centric.
+ * @MM_MODEM_3GPP_EPS_UE_MODE_OPERATION_CSPS_2: CS/PS mode 2 of operation: EPS and non-EPS, data-centric.
+ *
+ * UE mode of operation for EPS, as per 3GPP TS 24.301.
+ */
+typedef enum { /*< underscore_name=mm_modem_3gpp_eps_ue_mode_operation >*/
+ MM_MODEM_3GPP_EPS_UE_MODE_OPERATION_UNKNOWN = 0,
+ MM_MODEM_3GPP_EPS_UE_MODE_OPERATION_PS_1 = 1,
+ MM_MODEM_3GPP_EPS_UE_MODE_OPERATION_PS_2 = 2,
+ MM_MODEM_3GPP_EPS_UE_MODE_OPERATION_CSPS_1 = 3,
+ MM_MODEM_3GPP_EPS_UE_MODE_OPERATION_CSPS_2 = 4,
+} MMModem3gppEpsUeModeOperation;
+
/**
* MMFirmwareImageType:
* @MM_FIRMWARE_IMAGE_TYPE_UNKNOWN: Unknown firmware type.
diff --git a/introspection/org.freedesktop.ModemManager1.Modem.Modem3gpp.xml b/introspection/org.freedesktop.ModemManager1.Modem.Modem3gpp.xml
index 6d082f70..1aaba4c0 100644
--- a/introspection/org.freedesktop.ModemManager1.Modem.Modem3gpp.xml
+++ b/introspection/org.freedesktop.ModemManager1.Modem.Modem3gpp.xml
@@ -85,6 +85,16 @@
<arg name="results" type="aa{sv}" direction="out" />
</method>
+ <!--
+ SetEpsUeModeOperation:
+ @mode: a <link linkend="MMModem3gppEpsUeModeOperation">MMModem3gppEpsUeModeOperation</link>.
+
+ Sets the UE mode of operation for EPS.
+ -->
+ <method name="SetEpsUeModeOperation">
+ <arg name="mode" type="u" direction="in" />
+ </method>
+
<!--
Imei:
@@ -145,5 +155,14 @@
-->
<property name="SubscriptionState" type="u" access="read" />
+ <!--
+ EpsUeModeOperation:
+
+ A <link linkend="MMModem3gppEpsUeModeOperation">MMModem3gppEpsUeModeOperation</link>
+ value representing the UE mode of operation for EPS, given as an unsigned integer
+ (signature <literal>"u"</literal>).
+ -->
+ <property name="EpsUeModeOperation" type="u" access="read" />
+
</interface>
</node>
diff --git a/libmm-glib/mm-common-helpers.c b/libmm-glib/mm-common-helpers.c
index f99e58d8..3a009ad3 100644
--- a/libmm-glib/mm-common-helpers.c
+++ b/libmm-glib/mm-common-helpers.c
@@ -758,6 +758,28 @@ mm_common_build_mode_combinations_default (void)
return g_variant_builder_end (&builder);
}
+MMModem3gppEpsUeModeOperation
+mm_common_get_eps_ue_mode_operation_from_string (const gchar *str,
+ GError **error)
+{
+ GEnumClass *enum_class;
+ guint i;
+
+ enum_class = G_ENUM_CLASS (g_type_class_ref (MM_TYPE_MODEM_3GPP_EPS_UE_MODE_OPERATION));
+
+ for (i = 0; enum_class->values[i].value_nick; i++) {
+ if (!g_ascii_strcasecmp (str, enum_class->values[i].value_nick))
+ return enum_class->values[i].value;
+ }
+
+ g_set_error (error,
+ MM_CORE_ERROR,
+ MM_CORE_ERROR_INVALID_ARGS,
+ "Couldn't match '%s' with a valid MMModem3gppEpsUeModeOperation value",
+ str);
+ return MM_MODEM_3GPP_EPS_UE_MODE_OPERATION_UNKNOWN;
+}
+
GArray *
mm_common_oma_pending_network_initiated_sessions_variant_to_garray (GVariant *variant)
{
diff --git a/libmm-glib/mm-common-helpers.h b/libmm-glib/mm-common-helpers.h
index 772068e9..229186ce 100644
--- a/libmm-glib/mm-common-helpers.h
+++ b/libmm-glib/mm-common-helpers.h
@@ -76,6 +76,9 @@ MMOmaFeature mm_common_get_oma_features_from_string (const gchar *str,
MMOmaSessionType mm_common_get_oma_session_type_from_string (const gchar *str,
GError **error);
+MMModem3gppEpsUeModeOperation mm_common_get_eps_ue_mode_operation_from_string (const gchar *str,
+ GError **error);
+
GArray *mm_common_ports_variant_to_garray (GVariant *variant);
MMModemPortInfo *mm_common_ports_variant_to_array (GVariant *variant,
guint *n_ports);
diff --git a/libmm-glib/mm-modem-3gpp.c b/libmm-glib/mm-modem-3gpp.c
index a926acc1..69edc276 100644
--- a/libmm-glib/mm-modem-3gpp.c
+++ b/libmm-glib/mm-modem-3gpp.c
@@ -280,6 +280,22 @@ mm_modem_3gpp_get_enabled_facility_locks (MMModem3gpp *self)
return mm_gdbus_modem3gpp_get_enabled_facility_locks (MM_GDBUS_MODEM3GPP (self));
}
+/**
+ * mm_modem_3gpp_get_eps_ue_mode_operation:
+ * @self: A #MMModem3gpp.
+ *
+ * Get the UE mode of operation for EPS.
+ *
+ * Returns: A #MMModem3gppEpsUeModeOperation.
+ */
+MMModem3gppEpsUeModeOperation
+mm_modem_3gpp_get_eps_ue_mode_operation (MMModem3gpp *self)
+{
+ g_return_val_if_fail (MM_IS_MODEM_3GPP (self), MM_MODEM_3GPP_EPS_UE_MODE_OPERATION_UNKNOWN);
+
+ return mm_gdbus_modem3gpp_get_eps_ue_mode_operation (MM_GDBUS_MODEM3GPP (self));
+}
+
/*****************************************************************************/
/**
@@ -590,6 +606,43 @@ mm_modem_3gpp_scan_sync (MMModem3gpp *self,
/*****************************************************************************/
+gboolean
+mm_modem_3gpp_set_eps_ue_mode_operation_finish (MMModem3gpp *self,
+ GAsyncResult *res,
+ GError **error)
+{
+ g_return_val_if_fail (MM_IS_MODEM_3GPP (self), FALSE);
+
+ return mm_gdbus_modem3gpp_call_set_eps_ue_mode_operation_finish (MM_GDBUS_MODEM3GPP (self), res, error);
+}
+
+void
+mm_modem_3gpp_set_eps_ue_mode_operation (MMModem3gpp *self,
+ MMModem3gppEpsUeModeOperation mode,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_return_if_fail (MM_IS_MODEM_3GPP (self));
+ g_return_if_fail (mode != MM_MODEM_3GPP_EPS_UE_MODE_OPERATION_UNKNOWN);
+
+ mm_gdbus_modem3gpp_call_set_eps_ue_mode_operation (MM_GDBUS_MODEM3GPP (self), (guint) mode, cancellable, callback, user_data);
+}
+
+gboolean
+mm_modem_3gpp_set_eps_ue_mode_operation_sync (MMModem3gpp *self,
+ MMModem3gppEpsUeModeOperation mode,
+ GCancellable *cancellable,
+ GError **error)
+{
+ g_return_val_if_fail (MM_IS_MODEM_3GPP (self), FALSE);
+ g_return_val_if_fail (mode != MM_MODEM_3GPP_EPS_UE_MODE_OPERATION_UNKNOWN, FALSE);
+
+ return mm_gdbus_modem3gpp_call_set_eps_ue_mode_operation_sync (MM_GDBUS_MODEM3GPP (self), (guint) mode, cancellable, error);
+}
+
+/*****************************************************************************/
+
static void
mm_modem_3gpp_init (MMModem3gpp *self)
{
diff --git a/libmm-glib/mm-modem-3gpp.h b/libmm-glib/mm-modem-3gpp.h
index 7cfe0115..a3b37f08 100644
--- a/libmm-glib/mm-modem-3gpp.h
+++ b/libmm-glib/mm-modem-3gpp.h
@@ -80,6 +80,7 @@ MMModem3gppSubscriptionState mm_modem_3gpp_get_subscription_state (MMModem3
MMModem3gppFacility mm_modem_3gpp_get_enabled_facility_locks (MMModem3gpp *self);
+MMModem3gppEpsUeModeOperation mm_modem_3gpp_get_eps_ue_mode_operation (MMModem3gpp *self);
void mm_modem_3gpp_register (MMModem3gpp *self,
const gchar *network_id,
@@ -120,6 +121,19 @@ GList *mm_modem_3gpp_scan_sync (MMModem3gpp *self,
GCancellable *cancellable,
GError **error);
+void mm_modem_3gpp_set_eps_ue_mode_operation (MMModem3gpp *self,
+ MMModem3gppEpsUeModeOperation mode,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean mm_modem_3gpp_set_eps_ue_mode_operation_finish (MMModem3gpp *self,
+ GAsyncResult *res,
+ GError **error);
+gboolean mm_modem_3gpp_set_eps_ue_mode_operation_sync (MMModem3gpp *self,
+ MMModem3gppEpsUeModeOperation mode,
+ GCancellable *cancellable,
+ GError **error);
+
G_END_DECLS
#endif /* _MM_MODEM_3GPP_H_ */
diff --git a/src/mm-iface-modem-3gpp.c b/src/mm-iface-modem-3gpp.c
index e1a61ced..7a9f7785 100644
--- a/src/mm-iface-modem-3gpp.c
+++ b/src/mm-iface-modem-3gpp.c
@@ -774,6 +774,141 @@ handle_scan (MmGdbusModem3gpp *skeleton,
/*****************************************************************************/
+typedef struct {
+ MmGdbusModem3gpp *skeleton;
+ GDBusMethodInvocation *invocation;
+ MMIfaceModem3gpp *self;
+ MMModem3gppEpsUeModeOperation mode;
+} HandleSetEpsUeModeOperationContext;
+
+static void
+handle_set_eps_ue_mode_operation_context_free (HandleSetEpsUeModeOperationContext *ctx)
+{
+ g_object_unref (ctx->skeleton);
+ g_object_unref (ctx->invocation);
+ g_object_unref (ctx->self);
+ g_slice_free (HandleSetEpsUeModeOperationContext, ctx);
+}
+
+static void
+after_set_load_eps_ue_mode_operation_ready (MMIfaceModem3gpp *self,
+ GAsyncResult *res,
+ HandleSetEpsUeModeOperationContext *ctx)
+{
+ MMModem3gppEpsUeModeOperation uemode;
+ GError *error = NULL;
+
+ uemode = MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->load_eps_ue_mode_operation_finish (self, res, &error);
+ if (error) {
+ g_dbus_method_invocation_take_error (ctx->invocation, error);
+ handle_set_eps_ue_mode_operation_context_free (ctx);
+ return;
+ }
+
+ if (uemode != ctx->mode) {
+ g_dbus_method_invocation_return_error_literal (ctx->invocation,
+ MM_CORE_ERROR,
+ MM_CORE_ERROR_FAILED,
+ "UE mode of operation for EPS wasn't updated");
+ handle_set_eps_ue_mode_operation_context_free (ctx);
+ return;
+ }
+
+ mm_gdbus_modem3gpp_set_eps_ue_mode_operation (ctx->skeleton, uemode);
+ mm_gdbus_modem3gpp_complete_set_eps_ue_mode_operation (ctx->skeleton, ctx->invocation);
+ handle_set_eps_ue_mode_operation_context_free (ctx);
+}
+
+static void
+handle_set_eps_ue_mode_operation_ready (MMIfaceModem3gpp *self,
+ GAsyncResult *res,
+ HandleSetEpsUeModeOperationContext *ctx)
+{
+ GError *error = NULL;
+
+ if (!MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->set_eps_ue_mode_operation_finish (self, res, &error)) {
+ g_dbus_method_invocation_take_error (ctx->invocation, error);
+ handle_set_eps_ue_mode_operation_context_free (ctx);
+ return;
+ }
+
+ if (MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->load_eps_ue_mode_operation &&
+ MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->load_eps_ue_mode_operation_finish) {
+ MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->load_eps_ue_mode_operation (
+ self,
+ (GAsyncReadyCallback)after_set_load_eps_ue_mode_operation_ready,
+ ctx);
+ return;
+ }
+
+ /* Assume we're ok */
+ mm_gdbus_modem3gpp_complete_set_eps_ue_mode_operation (ctx->skeleton, ctx->invocation);
+ handle_set_eps_ue_mode_operation_context_free (ctx);
+}
+
+static void
+handle_set_eps_ue_mode_operation_auth_ready (MMBaseModem *self,
+ GAsyncResult *res,
+ HandleSetEpsUeModeOperationContext *ctx)
+{
+ GError *error = NULL;
+
+ if (!mm_base_modem_authorize_finish (self, res, &error)) {
+ g_dbus_method_invocation_take_error (ctx->invocation, error);
+ handle_set_eps_ue_mode_operation_context_free (ctx);
+ return;
+ }
+
+ /* Check if we already are in the requested mode */
+ if (mm_gdbus_modem3gpp_get_eps_ue_mode_operation (ctx->skeleton) == ctx->mode) {
+ /* Nothing to do */
+ mm_gdbus_modem3gpp_complete_set_eps_ue_mode_operation (ctx->skeleton, ctx->invocation);
+ handle_set_eps_ue_mode_operation_context_free (ctx);
+ return;
+ }
+
+ /* If UE mode update is not implemented, report an error */
+ if (!MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->set_eps_ue_mode_operation ||
+ !MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->set_eps_ue_mode_operation_finish) {
+ g_dbus_method_invocation_return_error (ctx->invocation,
+ MM_CORE_ERROR,
+ MM_CORE_ERROR_UNSUPPORTED,
+ "Cannot set UE mode of operation for EPS: operation not supported");
+ handle_set_eps_ue_mode_operation_context_free (ctx);
+ return;
+ }
+
+ MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->set_eps_ue_mode_operation (
+ MM_IFACE_MODEM_3GPP (self),
+ ctx->mode,
+ (GAsyncReadyCallback)handle_set_eps_ue_mode_operation_ready,
+ ctx);
+}
+
+static gboolean
+handle_set_eps_ue_mode_operation (MmGdbusModem3gpp *skeleton,
+ GDBusMethodInvocation *invocation,
+ guint mode,
+ MMIfaceModem3gpp *self)
+{
+ HandleSetEpsUeModeOperationContext *ctx;
+
+ ctx = g_slice_new (HandleSetEpsUeModeOperationContext);
+ ctx->skeleton = g_object_ref (skeleton);
+ ctx->invocation = g_object_ref (invocation);
+ ctx->self = g_object_ref (self);
+ ctx->mode = mode;
+
+ mm_base_modem_authorize (MM_BASE_MODEM (self),
+ invocation,
+ MM_AUTHORIZATION_DEVICE_CONTROL,
+ (GAsyncReadyCallback)handle_set_eps_ue_mode_operation_auth_ready,
+ ctx);
+ return TRUE;
+}
+
+/*****************************************************************************/
+
gboolean
mm_iface_modem_3gpp_run_registration_checks_finish (MMIfaceModem3gpp *self,
GAsyncResult *res,
@@ -1861,6 +1996,7 @@ typedef enum {
INITIALIZATION_STEP_FIRST,
INITIALIZATION_STEP_IMEI,
INITIALIZATION_STEP_ENABLED_FACILITY_LOCKS,
+ INITIALIZATION_STEP_EPS_UE_MODE_OPERATION,
INITIALIZATION_STEP_LAST
} InitializationStep;
@@ -1892,6 +2028,30 @@ sim_pin_lock_enabled_cb (MMBaseSim *self,
mm_gdbus_modem3gpp_set_enabled_facility_locks (skeleton, facilities);
}
+static void
+load_eps_ue_mode_operation_ready (MMIfaceModem3gpp *self,
+ GAsyncResult *res,
+ GTask *task)
+{
+ InitializationContext *ctx;
+ MMModem3gppEpsUeModeOperation uemode;
+ GError *error = NULL;
+
+ ctx = g_task_get_task_data (task);
+
+ uemode = MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->load_eps_ue_mode_operation_finish (self, res, &error);
+ mm_gdbus_modem3gpp_set_eps_ue_mode_operation (ctx->skeleton, uemode);
+
+ if (error) {
+ mm_warn ("couldn't load UE mode of operation for EPS: '%s'", error->message);
+ g_error_free (error);
+ }
+
+ /* Go on to next step */
+ ctx->step++;
+ interface_initialization_step (task);
+}
+
static void
load_enabled_facility_locks_ready (MMIfaceModem3gpp *self,
GAsyncResult *res,
@@ -2004,6 +2164,18 @@ interface_initialization_step (GTask *task)
/* Fall down to next step */
ctx->step++;
+ case INITIALIZATION_STEP_EPS_UE_MODE_OPERATION:
+ if (MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->load_eps_ue_mode_operation &&
+ MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->load_eps_ue_mode_operation_finish) {
+ MM_IFACE_MODEM_3GPP_GET_INTERFACE (self)->load_eps_ue_mode_operation (
+ self,
+ (GAsyncReadyCallback)load_eps_ue_mode_operation_ready,
+ task);
+ return;
+ }
+ /* Fall down to next step */
+ ctx->step++;
+
case INITIALIZATION_STEP_LAST:
/* We are done without errors! */
@@ -2016,7 +2188,10 @@ interface_initialization_step (GTask *task)
"handle-scan",
G_CALLBACK (handle_scan),
self);
-
+ g_signal_connect (ctx->skeleton,
+ "handle-set-eps-ue-mode-operation",
+ G_CALLBACK (handle_set_eps_ue_mode_operation),
+ self);
/* Finally, export the new interface */
mm_gdbus_object_skeleton_set_modem3gpp (MM_GDBUS_OBJECT_SKELETON (self),
diff --git a/src/mm-iface-modem-3gpp.h b/src/mm-iface-modem-3gpp.h
index 6237b8aa..7b6d47e1 100644
--- a/src/mm-iface-modem-3gpp.h
+++ b/src/mm-iface-modem-3gpp.h
@@ -68,6 +68,14 @@ struct _MMIfaceModem3gpp {
GAsyncResult *res,
GError **error);
+ /* Loading of the UE mode of operation for EPS property */
+ void (* load_eps_ue_mode_operation) (MMIfaceModem3gpp *self,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+ MMModem3gppEpsUeModeOperation (* load_eps_ue_mode_operation_finish) (MMIfaceModem3gpp *self,
+ GAsyncResult *res,
+ GError **error);
+
/* Asynchronous setting up unsolicited events */
void (*setup_unsolicited_events) (MMIfaceModem3gpp *self,
GAsyncReadyCallback callback,
@@ -191,6 +199,15 @@ struct _MMIfaceModem3gpp {
GList * (*scan_networks_finish) (MMIfaceModem3gpp *self,
GAsyncResult *res,
GError **error);
+
+ /* Set UE mode of operation for EPS */
+ void (* set_eps_ue_mode_operation) (MMIfaceModem3gpp *self,
+ MMModem3gppEpsUeModeOperation mode,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+ gboolean (* set_eps_ue_mode_operation_finish) (MMIfaceModem3gpp *self,
+ GAsyncResult *res,
+ GError **error);
};
GType mm_iface_modem_3gpp_get_type (void);
--
2.15.0
More information about the ModemManager-devel
mailing list