diff options
author | Aleksander Morgado <aleksander@aleksander.es> | 2017-12-28 18:41:50 +0100 |
---|---|---|
committer | Aleksander Morgado <aleksander@aleksander.es> | 2018-01-20 15:41:07 +0100 |
commit | d4aaa436d9679524f910b13176d4af35bd6b14f8 (patch) | |
tree | 649e8b340e495b18d41afc1887dd10c834100c9b | |
parent | c5c9ab279d6362b2090010b4cad9ea49e9559423 (diff) |
modem-3gpp: allow loading and changing EPS UE mode of operation
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.
-rw-r--r-- | cli/mmcli-modem-3gpp.c | 76 | ||||
-rw-r--r-- | cli/mmcli-modem.c | 9 | ||||
-rw-r--r-- | docs/reference/api/ModemManager-sections.txt | 1 | ||||
-rw-r--r-- | docs/reference/libmm-glib/libmm-glib-sections.txt | 13 | ||||
-rw-r--r-- | include/ModemManager-enums.h | 18 | ||||
-rw-r--r-- | introspection/org.freedesktop.ModemManager1.Modem.Modem3gpp.xml | 19 | ||||
-rw-r--r-- | libmm-glib/mm-common-helpers.c | 22 | ||||
-rw-r--r-- | libmm-glib/mm-common-helpers.h | 3 | ||||
-rw-r--r-- | libmm-glib/mm-modem-3gpp.c | 53 | ||||
-rw-r--r-- | libmm-glib/mm-modem-3gpp.h | 14 | ||||
-rw-r--r-- | src/mm-iface-modem-3gpp.c | 177 | ||||
-rw-r--r-- | 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 + @@ -292,6 +298,45 @@ register_ready (MMModem3gpp *modem_3gpp, } 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) { /* Not the best thing to do, as we may be doing _get() calls twice, but @@ -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 @@ -1156,6 +1156,24 @@ typedef enum { /*< underscore_name=mm_modem_3gpp_ussd_session_state >*/ } 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. * @MM_FIRMWARE_IMAGE_TYPE_GENERIC: Generic firmware image. 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 @@ -86,6 +86,16 @@ </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: The <ulink url="http://en.wikipedia.org/wiki/Imei">IMEI</ulink> of the device. @@ -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 f5abc092..89023a46 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, @@ -1879,6 +2014,7 @@ typedef enum { INITIALIZATION_STEP_FIRST, INITIALIZATION_STEP_IMEI, INITIALIZATION_STEP_ENABLED_FACILITY_LOCKS, + INITIALIZATION_STEP_EPS_UE_MODE_OPERATION, INITIALIZATION_STEP_LAST } InitializationStep; @@ -1911,6 +2047,30 @@ sim_pin_lock_enabled_cb (MMBaseSim *self, } 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, GTask *task) @@ -2022,6 +2182,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! */ @@ -2034,7 +2206,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); |