diff options
author | Aleksander Morgado <aleksander@lanedo.com> | 2013-08-14 15:20:04 +0200 |
---|---|---|
committer | Aleksander Morgado <aleksander@lanedo.com> | 2013-09-09 10:18:23 +0200 |
commit | d37b21e116cf5b1f452ec150ef5254109f6f05be (patch) | |
tree | 6261af2a5fffa345772f9f9d84dd3163b0ff63f0 | |
parent | 8ab38ae96850da78c82ebd53ae037907c5b480a9 (diff) |
iface-modem-oma: new object interface to handle the OMA DBus interface
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/mm-broadband-modem.c | 63 | ||||
-rw-r--r-- | src/mm-iface-modem-oma.c | 1252 | ||||
-rw-r--r-- | src/mm-iface-modem-oma.h | 164 |
4 files changed, 1481 insertions, 0 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 28f70b50..7ed067d1 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -217,6 +217,8 @@ ModemManager_SOURCES = \ mm-iface-modem-firmware.c \ mm-iface-modem-signal.h \ mm-iface-modem-signal.c \ + mm-iface-modem-oma.h \ + mm-iface-modem-oma.c \ mm-broadband-modem.h \ mm-broadband-modem.c \ mm-serial-parsers.c \ diff --git a/src/mm-broadband-modem.c b/src/mm-broadband-modem.c index 53293509..3a9c8549 100644 --- a/src/mm-broadband-modem.c +++ b/src/mm-broadband-modem.c @@ -38,6 +38,7 @@ #include "mm-iface-modem-time.h" #include "mm-iface-modem-firmware.h" #include "mm-iface-modem-signal.h" +#include "mm-iface-modem-oma.h" #include "mm-broadband-bearer.h" #include "mm-bearer-list.h" #include "mm-sms-list.h" @@ -58,6 +59,7 @@ static void iface_modem_location_init (MMIfaceModemLocation *iface); static void iface_modem_messaging_init (MMIfaceModemMessaging *iface); static void iface_modem_time_init (MMIfaceModemTime *iface); static void iface_modem_signal_init (MMIfaceModemSignal *iface); +static void iface_modem_oma_init (MMIfaceModemOma *iface); static void iface_modem_firmware_init (MMIfaceModemFirmware *iface); G_DEFINE_TYPE_EXTENDED (MMBroadbandModem, mm_broadband_modem, MM_TYPE_BASE_MODEM, 0, @@ -70,6 +72,7 @@ G_DEFINE_TYPE_EXTENDED (MMBroadbandModem, mm_broadband_modem, MM_TYPE_BASE_MODEM G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_MESSAGING, iface_modem_messaging_init) G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_TIME, iface_modem_time_init) G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_SIGNAL, iface_modem_signal_init) + G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_OMA, iface_modem_oma_init) G_IMPLEMENT_INTERFACE (MM_TYPE_IFACE_MODEM_FIRMWARE, iface_modem_firmware_init)) enum { @@ -83,6 +86,7 @@ enum { PROP_MODEM_MESSAGING_DBUS_SKELETON, PROP_MODEM_TIME_DBUS_SKELETON, PROP_MODEM_SIGNAL_DBUS_SKELETON, + PROP_MODEM_OMA_DBUS_SKELETON, PROP_MODEM_FIRMWARE_DBUS_SKELETON, PROP_MODEM_SIM, PROP_MODEM_BEARER_LIST, @@ -192,6 +196,10 @@ struct _MMBroadbandModemPrivate { /* Properties */ GObject *modem_signal_dbus_skeleton; + /*<--- Modem OMA interface --->*/ + /* Properties */ + GObject *modem_oma_dbus_skeleton; + /*<--- Modem Firmware interface --->*/ /* Properties */ GObject *modem_firmware_dbus_skeleton; @@ -7934,6 +7942,7 @@ typedef enum { DISABLING_STEP_IFACE_SIMPLE, DISABLING_STEP_IFACE_FIRMWARE, DISABLING_STEP_IFACE_SIGNAL, + DISABLING_STEP_IFACE_OMA, DISABLING_STEP_IFACE_TIME, DISABLING_STEP_IFACE_MESSAGING, DISABLING_STEP_IFACE_LOCATION, @@ -8046,6 +8055,7 @@ INTERFACE_DISABLE_READY_FN (iface_modem_location, MM_IFACE_MODEM_LOCATION, FAL INTERFACE_DISABLE_READY_FN (iface_modem_messaging, MM_IFACE_MODEM_MESSAGING, FALSE) INTERFACE_DISABLE_READY_FN (iface_modem_signal, MM_IFACE_MODEM_SIGNAL, FALSE) INTERFACE_DISABLE_READY_FN (iface_modem_time, MM_IFACE_MODEM_TIME, FALSE) +INTERFACE_DISABLE_READY_FN (iface_modem_oma, MM_IFACE_MODEM_OMA, FALSE) static void bearer_list_disconnect_all_bearers_ready (MMBearerList *list, @@ -8155,6 +8165,18 @@ disabling_step (DisablingContext *ctx) /* Fall down to next step */ ctx->step++; + case DISABLING_STEP_IFACE_OMA: + if (ctx->self->priv->modem_oma_dbus_skeleton) { + mm_dbg ("Modem has OMA capabilities, disabling the OMA interface..."); + /* Disabling the Modem Oma interface */ + mm_iface_modem_oma_disable (MM_IFACE_MODEM_OMA (ctx->self), + (GAsyncReadyCallback)iface_modem_oma_disable_ready, + ctx); + return; + } + /* Fall down to next step */ + ctx->step++; + case DISABLING_STEP_IFACE_TIME: if (ctx->self->priv->modem_time_dbus_skeleton) { mm_dbg ("Modem has time capabilities, disabling the Time interface..."); @@ -8287,6 +8309,7 @@ typedef enum { ENABLING_STEP_IFACE_MESSAGING, ENABLING_STEP_IFACE_TIME, ENABLING_STEP_IFACE_SIGNAL, + ENABLING_STEP_IFACE_OMA, ENABLING_STEP_IFACE_FIRMWARE, ENABLING_STEP_IFACE_SIMPLE, ENABLING_STEP_LAST, @@ -8386,6 +8409,7 @@ INTERFACE_ENABLE_READY_FN (iface_modem_location, MM_IFACE_MODEM_LOCATION, FALS INTERFACE_ENABLE_READY_FN (iface_modem_messaging, MM_IFACE_MODEM_MESSAGING, FALSE) INTERFACE_ENABLE_READY_FN (iface_modem_signal, MM_IFACE_MODEM_SIGNAL, FALSE) INTERFACE_ENABLE_READY_FN (iface_modem_time, MM_IFACE_MODEM_TIME, FALSE) +INTERFACE_ENABLE_READY_FN (iface_modem_oma, MM_IFACE_MODEM_OMA, FALSE) static void enabling_started_ready (MMBroadbandModem *self, @@ -8568,6 +8592,19 @@ enabling_step (EnablingContext *ctx) /* Fall down to next step */ ctx->step++; + case ENABLING_STEP_IFACE_OMA: + if (ctx->self->priv->modem_oma_dbus_skeleton) { + mm_dbg ("Modem has OMA capabilities, enabling the OMA interface..."); + /* Enabling the Modem Oma interface */ + mm_iface_modem_oma_enable (MM_IFACE_MODEM_OMA (ctx->self), + ctx->cancellable, + (GAsyncReadyCallback)iface_modem_oma_enable_ready, + ctx); + return; + } + /* Fall down to next step */ + ctx->step++; + case ENABLING_STEP_IFACE_FIRMWARE: /* Fall down to next step */ ctx->step++; @@ -8679,6 +8716,7 @@ typedef enum { INITIALIZE_STEP_IFACE_MESSAGING, INITIALIZE_STEP_IFACE_TIME, INITIALIZE_STEP_IFACE_SIGNAL, + INITIALIZE_STEP_IFACE_OMA, INITIALIZE_STEP_IFACE_FIRMWARE, INITIALIZE_STEP_IFACE_SIMPLE, INITIALIZE_STEP_LAST, @@ -8875,6 +8913,7 @@ INTERFACE_INIT_READY_FN (iface_modem_location, MM_IFACE_MODEM_LOCATION, FALSE) INTERFACE_INIT_READY_FN (iface_modem_messaging, MM_IFACE_MODEM_MESSAGING, FALSE) INTERFACE_INIT_READY_FN (iface_modem_time, MM_IFACE_MODEM_TIME, FALSE) INTERFACE_INIT_READY_FN (iface_modem_signal, MM_IFACE_MODEM_SIGNAL, FALSE) +INTERFACE_INIT_READY_FN (iface_modem_oma, MM_IFACE_MODEM_OMA, FALSE) INTERFACE_INIT_READY_FN (iface_modem_firmware, MM_IFACE_MODEM_FIRMWARE, FALSE) static void @@ -8995,6 +9034,14 @@ initialize_step (InitializeContext *ctx) ctx); return; + case INITIALIZE_STEP_IFACE_OMA: + /* Initialize the Oma interface */ + mm_iface_modem_oma_initialize (MM_IFACE_MODEM_OMA (ctx->self), + ctx->cancellable, + (GAsyncReadyCallback)iface_modem_oma_initialize_ready, + ctx); + return; + case INITIALIZE_STEP_IFACE_FIRMWARE: /* Initialize the Firmware interface */ mm_iface_modem_firmware_initialize (MM_IFACE_MODEM_FIRMWARE (ctx->self), @@ -9240,6 +9287,10 @@ set_property (GObject *object, g_clear_object (&self->priv->modem_signal_dbus_skeleton); self->priv->modem_signal_dbus_skeleton = g_value_dup_object (value); break; + case PROP_MODEM_OMA_DBUS_SKELETON: + g_clear_object (&self->priv->modem_oma_dbus_skeleton); + self->priv->modem_oma_dbus_skeleton = g_value_dup_object (value); + break; case PROP_MODEM_FIRMWARE_DBUS_SKELETON: g_clear_object (&self->priv->modem_firmware_dbus_skeleton); self->priv->modem_firmware_dbus_skeleton = g_value_dup_object (value); @@ -9338,6 +9389,9 @@ get_property (GObject *object, case PROP_MODEM_SIGNAL_DBUS_SKELETON: g_value_set_object (value, self->priv->modem_signal_dbus_skeleton); break; + case PROP_MODEM_OMA_DBUS_SKELETON: + g_value_set_object (value, self->priv->modem_oma_dbus_skeleton); + break; case PROP_MODEM_FIRMWARE_DBUS_SKELETON: g_value_set_object (value, self->priv->modem_firmware_dbus_skeleton); break; @@ -9682,6 +9736,11 @@ iface_modem_signal_init (MMIfaceModemSignal *iface) } static void +iface_modem_oma_init (MMIfaceModemOma *iface) +{ +} + +static void iface_modem_firmware_init (MMIfaceModemFirmware *iface) { } @@ -9754,6 +9813,10 @@ mm_broadband_modem_class_init (MMBroadbandModemClass *klass) MM_IFACE_MODEM_SIGNAL_DBUS_SKELETON); g_object_class_override_property (object_class, + PROP_MODEM_OMA_DBUS_SKELETON, + MM_IFACE_MODEM_OMA_DBUS_SKELETON); + + g_object_class_override_property (object_class, PROP_MODEM_FIRMWARE_DBUS_SKELETON, MM_IFACE_MODEM_FIRMWARE_DBUS_SKELETON); diff --git a/src/mm-iface-modem-oma.c b/src/mm-iface-modem-oma.c new file mode 100644 index 00000000..deb12ea5 --- /dev/null +++ b/src/mm-iface-modem-oma.c @@ -0,0 +1,1252 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details: + * + * Copyright (C) 2013 Google, Inc. + */ + +#include <ModemManager.h> +#define _LIBMM_INSIDE_MM +#include <libmm-glib.h> + +#include "mm-iface-modem.h" +#include "mm-iface-modem-oma.h" +#include "mm-log.h" + +#define SUPPORT_CHECKED_TAG "oma-support-checked-tag" +#define SUPPORTED_TAG "oma-supported-tag" + +static GQuark support_checked_quark; +static GQuark supported_quark; + +/*****************************************************************************/ + +void +mm_iface_modem_oma_bind_simple_status (MMIfaceModemOma *self, + MMSimpleStatus *status) +{ +} + +/*****************************************************************************/ +/* Manage the list of pending network-initiated sessions */ + +static void +add_or_remove_pending_network_initiated_session (MMIfaceModemOma *self, + gboolean add, + MMOmaSessionType session_type, + guint session_id) +{ + MmGdbusModemOma *skeleton; + GVariant *variant; + GArray *array; + guint i; + + g_object_get (self, + MM_IFACE_MODEM_OMA_DBUS_SKELETON, &skeleton, + NULL); + if (!skeleton) + return; + + variant = mm_gdbus_modem_oma_get_pending_network_initiated_sessions (skeleton); + array = mm_common_oma_pending_network_initiated_sessions_variant_to_garray (variant); + + for (i = 0; i < array->len; i++) { + MMOmaPendingNetworkInitiatedSession *session; + + session = &g_array_index (array, MMOmaPendingNetworkInitiatedSession, i); + if (session->session_id == session_id) + break; + } + + /* If not in the array, and we want to add it, add it */ + if (add && i == array->len) { + MMOmaPendingNetworkInitiatedSession session; + + session.session_type = session_type; + session.session_id = session_id; + g_array_append_val (array, session); + + mm_gdbus_modem_oma_set_pending_network_initiated_sessions ( + skeleton, + mm_common_oma_pending_network_initiated_sessions_garray_to_variant (array)); + } + /* If found in the array, and we want to remove it, remove it */ + else if (!add && i < array->len) { + g_array_remove_index (array, i); + mm_gdbus_modem_oma_set_pending_network_initiated_sessions ( + skeleton, + mm_common_oma_pending_network_initiated_sessions_garray_to_variant (array)); + } + + g_object_unref (skeleton); + g_array_unref (array); +} + +void +mm_iface_modem_oma_add_pending_network_initiated_session (MMIfaceModemOma *self, + MMOmaSessionType session_type, + guint session_id) +{ + add_or_remove_pending_network_initiated_session (self, TRUE, session_type, session_id); +} + +/*****************************************************************************/ +/* New session state reported */ + +void +mm_iface_modem_oma_update_session_state (MMIfaceModemOma *self, + MMOmaSessionState new_session_state, + MMOmaSessionStateFailedReason session_state_failed_reason) +{ + MmGdbusModemOma *skeleton; + MMOmaSessionState old_session_state; + + /* Make sure proper state vs failed reasons are given */ + g_return_if_fail ((new_session_state != MM_OMA_SESSION_STATE_FAILED && + session_state_failed_reason == MM_OMA_SESSION_STATE_FAILED_REASON_UNKNOWN) || + (new_session_state == MM_OMA_SESSION_STATE_FAILED)); + + g_object_get (self, + MM_IFACE_MODEM_OMA_DBUS_SKELETON, &skeleton, + NULL); + if (!skeleton) + return; + + old_session_state = mm_gdbus_modem_oma_get_session_state (skeleton); + if (old_session_state != new_session_state) { + mm_info ("Modem %s: OMA session state changed (%s -> %s)", + g_dbus_object_get_object_path (G_DBUS_OBJECT (self)), + mm_oma_session_state_get_string (old_session_state), + mm_oma_session_state_get_string (new_session_state)); + + /* Flush current change before signaling the state change, + * so that clients get the proper state already in the + * state-changed callback */ + g_dbus_interface_skeleton_flush (G_DBUS_INTERFACE_SKELETON (skeleton)); + mm_gdbus_modem_oma_emit_session_state_changed ( + skeleton, + old_session_state, + new_session_state, + session_state_failed_reason); + } +} + +/*****************************************************************************/ +/* Handle Setup() */ + +typedef struct { + MmGdbusModemOma *skeleton; + GDBusMethodInvocation *invocation; + MMIfaceModemOma *self; + guint32 features; +} HandleSetupContext; + +static void +handle_setup_context_free (HandleSetupContext *ctx) +{ + g_object_unref (ctx->skeleton); + g_object_unref (ctx->invocation); + g_object_unref (ctx->self); + g_slice_free (HandleSetupContext, ctx); +} + +static void +setup_ready (MMIfaceModemOma *self, + GAsyncResult *res, + HandleSetupContext *ctx) +{ + GError *error = NULL; + + if (!MM_IFACE_MODEM_OMA_GET_INTERFACE (ctx->self)->setup_finish (self, res, &error)) + g_dbus_method_invocation_take_error (ctx->invocation, error); + else { + /* Update current features in the interface */ + mm_gdbus_modem_oma_set_features (ctx->skeleton, ctx->features); + mm_gdbus_modem_oma_complete_setup (ctx->skeleton, ctx->invocation); + } + + handle_setup_context_free (ctx); +} + +static void +handle_setup_auth_ready (MMBaseModem *self, + GAsyncResult *res, + HandleSetupContext *ctx) +{ + GError *error = NULL; + MMModemState modem_state; + gchar *str; + + if (!mm_base_modem_authorize_finish (self, res, &error)) { + g_dbus_method_invocation_take_error (ctx->invocation, error); + handle_setup_context_free (ctx); + return; + } + + modem_state = MM_MODEM_STATE_UNKNOWN; + g_object_get (self, + MM_IFACE_MODEM_STATE, &modem_state, + NULL); + if (modem_state < MM_MODEM_STATE_ENABLED) { + g_dbus_method_invocation_return_error (ctx->invocation, + MM_CORE_ERROR, + MM_CORE_ERROR_WRONG_STATE, + "Cannot setup OMA: " + "device not yet enabled"); + handle_setup_context_free (ctx); + return; + } + + if (!MM_IFACE_MODEM_OMA_GET_INTERFACE (ctx->self)->setup || + !MM_IFACE_MODEM_OMA_GET_INTERFACE (ctx->self)->setup_finish) { + g_dbus_method_invocation_return_error (ctx->invocation, + MM_CORE_ERROR, + MM_CORE_ERROR_UNSUPPORTED, + "Cannot setup OMA: " + "operation not supported"); + handle_setup_context_free (ctx); + return; + } + + str = mm_oma_feature_build_string_from_mask (ctx->features); + mm_dbg ("Setting up OMA features: '%s'", str); + g_free (str); + + MM_IFACE_MODEM_OMA_GET_INTERFACE (ctx->self)->setup ( + ctx->self, + ctx->features, + (GAsyncReadyCallback)setup_ready, + ctx); +} + +static gboolean +handle_setup (MmGdbusModemOma *skeleton, + GDBusMethodInvocation *invocation, + guint32 features, + MMIfaceModemOma *self) +{ + HandleSetupContext *ctx; + + ctx = g_slice_new0 (HandleSetupContext); + ctx->skeleton = g_object_ref (skeleton); + ctx->invocation = g_object_ref (invocation); + ctx->self = g_object_ref (self); + ctx->features = features; + + mm_base_modem_authorize (MM_BASE_MODEM (self), + invocation, + MM_AUTHORIZATION_DEVICE_CONTROL, + (GAsyncReadyCallback)handle_setup_auth_ready, + ctx); + return TRUE; +} + +/*****************************************************************************/ +/* Handle StartClientInitiatedSession() */ + +typedef struct { + MmGdbusModemOma *skeleton; + GDBusMethodInvocation *invocation; + MMIfaceModemOma *self; + MMOmaSessionType session_type; +} HandleStartClientInitiatedSessionContext; + +static void +handle_start_client_initiated_session_context_free (HandleStartClientInitiatedSessionContext *ctx) +{ + g_object_unref (ctx->skeleton); + g_object_unref (ctx->invocation); + g_object_unref (ctx->self); + g_slice_free (HandleStartClientInitiatedSessionContext, ctx); +} + +static void +start_client_initiated_session_ready (MMIfaceModemOma *self, + GAsyncResult *res, + HandleStartClientInitiatedSessionContext *ctx) +{ + GError *error = NULL; + + if (!MM_IFACE_MODEM_OMA_GET_INTERFACE (ctx->self)->start_client_initiated_session_finish (self, res, &error)) + g_dbus_method_invocation_take_error (ctx->invocation, error); + else { + /* Update interface info */ + mm_gdbus_modem_oma_set_session_type (ctx->skeleton, ctx->session_type); + mm_iface_modem_oma_update_session_state (self, MM_OMA_SESSION_STATE_STARTED, MM_OMA_SESSION_STATE_FAILED_REASON_UNKNOWN); + mm_gdbus_modem_oma_complete_start_client_initiated_session (ctx->skeleton, ctx->invocation); + } + + handle_start_client_initiated_session_context_free (ctx); +} + +static void +handle_start_client_initiated_session_auth_ready (MMBaseModem *self, + GAsyncResult *res, + HandleStartClientInitiatedSessionContext *ctx) +{ + GError *error = NULL; + MMModemState modem_state; + + if (!mm_base_modem_authorize_finish (self, res, &error)) { + g_dbus_method_invocation_take_error (ctx->invocation, error); + handle_start_client_initiated_session_context_free (ctx); + return; + } + + modem_state = MM_MODEM_STATE_UNKNOWN; + g_object_get (self, + MM_IFACE_MODEM_STATE, &modem_state, + NULL); + if (modem_state < MM_MODEM_STATE_ENABLED) { + g_dbus_method_invocation_return_error (ctx->invocation, + MM_CORE_ERROR, + MM_CORE_ERROR_WRONG_STATE, + "Cannot start client-initiated OMA session: " + "device not yet enabled"); + handle_start_client_initiated_session_context_free (ctx); + return; + } + + if (!MM_IFACE_MODEM_OMA_GET_INTERFACE (ctx->self)->start_client_initiated_session || + !MM_IFACE_MODEM_OMA_GET_INTERFACE (ctx->self)->start_client_initiated_session_finish) { + g_dbus_method_invocation_return_error (ctx->invocation, + MM_CORE_ERROR, + MM_CORE_ERROR_UNSUPPORTED, + "Cannot start client-initiated OMA session: " + "operation not supported"); + handle_start_client_initiated_session_context_free (ctx); + return; + } + + if (ctx->session_type != MM_OMA_SESSION_TYPE_CLIENT_INITIATED_DEVICE_CONFIGURE && + ctx->session_type != MM_OMA_SESSION_TYPE_CLIENT_INITIATED_PRL_UPDATE && + ctx->session_type != MM_OMA_SESSION_TYPE_CLIENT_INITIATED_HANDS_FREE_ACTIVATION) { + g_dbus_method_invocation_return_error (ctx->invocation, + MM_CORE_ERROR, + MM_CORE_ERROR_UNSUPPORTED, + "Cannot start client-initiated OMA session: " + "invalid session type specified (%s)", + mm_oma_session_type_get_string (ctx->session_type)); + handle_start_client_initiated_session_context_free (ctx); + return; + } + + mm_dbg ("Starting client-initiated OMA session (%s)", + mm_oma_session_type_get_string (ctx->session_type)); + MM_IFACE_MODEM_OMA_GET_INTERFACE (ctx->self)->start_client_initiated_session ( + ctx->self, + ctx->session_type, + (GAsyncReadyCallback)start_client_initiated_session_ready, + ctx); +} + +static gboolean +handle_start_client_initiated_session (MmGdbusModemOma *skeleton, + GDBusMethodInvocation *invocation, + guint32 session_type, + MMIfaceModemOma *self) +{ + HandleStartClientInitiatedSessionContext *ctx; + + ctx = g_slice_new0 (HandleStartClientInitiatedSessionContext); + ctx->skeleton = g_object_ref (skeleton); + ctx->invocation = g_object_ref (invocation); + ctx->self = g_object_ref (self); + ctx->session_type = session_type; + + mm_base_modem_authorize (MM_BASE_MODEM (self), + invocation, + MM_AUTHORIZATION_DEVICE_CONTROL, + (GAsyncReadyCallback)handle_start_client_initiated_session_auth_ready, + ctx); + return TRUE; +} + +/*****************************************************************************/ +/* Handle AcceptNetworkInitiatedSession() */ + +typedef struct { + MmGdbusModemOma *skeleton; + GDBusMethodInvocation *invocation; + MMIfaceModemOma *self; + guint session_id; + gboolean accept; +} HandleAcceptNetworkInitiatedSessionContext; + +static void +handle_accept_network_initiated_session_context_free (HandleAcceptNetworkInitiatedSessionContext *ctx) +{ + g_object_unref (ctx->skeleton); + g_object_unref (ctx->invocation); + g_object_unref (ctx->self); + g_slice_free (HandleAcceptNetworkInitiatedSessionContext, ctx); +} + +static MMOmaSessionType +get_pending_network_initiated_session_type (MMIfaceModemOma *self, + guint session_id) +{ + MMOmaSessionType session_type = MM_OMA_SESSION_TYPE_UNKNOWN; + MmGdbusModemOma *skeleton; + + g_object_get (self, + MM_IFACE_MODEM_OMA_DBUS_SKELETON, &skeleton, + NULL); + if (skeleton) { + GArray *array; + guint i; + + array = (mm_common_oma_pending_network_initiated_sessions_variant_to_garray ( + mm_gdbus_modem_oma_get_pending_network_initiated_sessions (skeleton))); + for (i = 0; i < array->len && session_type == MM_OMA_SESSION_TYPE_UNKNOWN; i++) { + MMOmaPendingNetworkInitiatedSession *session; + + session = &g_array_index (array, MMOmaPendingNetworkInitiatedSession, i); + if (session->session_id == session_id) + session_type = session->session_type; + } + + g_array_unref (array); + g_object_unref (skeleton); + } + + return session_type; +} + +static void +accept_network_initiated_session_ready (MMIfaceModemOma *self, + GAsyncResult *res, + HandleAcceptNetworkInitiatedSessionContext *ctx) +{ + GError *error = NULL; + + if (!MM_IFACE_MODEM_OMA_GET_INTERFACE (ctx->self)->accept_network_initiated_session_finish (self, res, &error)) + g_dbus_method_invocation_take_error (ctx->invocation, error); + else { + MMOmaSessionType session_type; + + /* Get session type */ + session_type = get_pending_network_initiated_session_type (self, ctx->session_id); + + /* If accepted or rejected, remove from pending */ + add_or_remove_pending_network_initiated_session (self, FALSE, session_type, ctx->session_id); + + /* If accepted, set as current */ + if (ctx->accept) { + mm_gdbus_modem_oma_set_session_type (ctx->skeleton, session_type); + mm_iface_modem_oma_update_session_state (self, MM_OMA_SESSION_STATE_STARTED, MM_OMA_SESSION_STATE_FAILED_REASON_UNKNOWN); + } + + mm_gdbus_modem_oma_complete_accept_network_initiated_session (ctx->skeleton, ctx->invocation); + } + + handle_accept_network_initiated_session_context_free (ctx); +} + +static void +handle_accept_network_initiated_session_auth_ready (MMBaseModem *self, + GAsyncResult *res, + HandleAcceptNetworkInitiatedSessionContext *ctx) +{ + GError *error = NULL; + MMModemState modem_state; + + if (!mm_base_modem_authorize_finish (self, res, &error)) { + g_dbus_method_invocation_take_error (ctx->invocation, error); + handle_accept_network_initiated_session_context_free (ctx); + return; + } + + modem_state = MM_MODEM_STATE_UNKNOWN; + g_object_get (self, + MM_IFACE_MODEM_STATE, &modem_state, + NULL); + if (modem_state < MM_MODEM_STATE_ENABLED) { + g_dbus_method_invocation_return_error (ctx->invocation, + MM_CORE_ERROR, + MM_CORE_ERROR_WRONG_STATE, + "Cannot accept network-initiated OMA session: " + "device not yet enabled"); + handle_accept_network_initiated_session_context_free (ctx); + return; + } + + if (!MM_IFACE_MODEM_OMA_GET_INTERFACE (ctx->self)->accept_network_initiated_session || + !MM_IFACE_MODEM_OMA_GET_INTERFACE (ctx->self)->accept_network_initiated_session_finish) { + g_dbus_method_invocation_return_error (ctx->invocation, + MM_CORE_ERROR, + MM_CORE_ERROR_UNSUPPORTED, + "Cannot accept network-initiated OMA session: " + "operation not supported"); + handle_accept_network_initiated_session_context_free (ctx); + return; + } + + mm_dbg ("%s network-initiated OMA session (%u)", + ctx->accept ? "Accepting" : "Rejecting", + ctx->session_id); + MM_IFACE_MODEM_OMA_GET_INTERFACE (ctx->self)->accept_network_initiated_session ( + ctx->self, + ctx->session_id, + ctx->accept, + (GAsyncReadyCallback)accept_network_initiated_session_ready, + ctx); +} + +static gboolean +handle_accept_network_initiated_session (MmGdbusModemOma *skeleton, + GDBusMethodInvocation *invocation, + guint32 session_id, + gboolean accept, + MMIfaceModemOma *self) +{ + HandleAcceptNetworkInitiatedSessionContext *ctx; + + ctx = g_slice_new0 (HandleAcceptNetworkInitiatedSessionContext); + ctx->skeleton = g_object_ref (skeleton); + ctx->invocation = g_object_ref (invocation); + ctx->self = g_object_ref (self); + ctx->session_id = session_id; + ctx->accept = accept; + + mm_base_modem_authorize (MM_BASE_MODEM (self), + invocation, + MM_AUTHORIZATION_DEVICE_CONTROL, + (GAsyncReadyCallback)handle_accept_network_initiated_session_auth_ready, + ctx); + return TRUE; +} + +/*****************************************************************************/ +/* Handle CancelSession() */ + +typedef struct { + MmGdbusModemOma *skeleton; + GDBusMethodInvocation *invocation; + MMIfaceModemOma *self; +} HandleCancelSessionContext; + +static void +handle_cancel_session_context_free (HandleCancelSessionContext *ctx) +{ + g_object_unref (ctx->skeleton); + g_object_unref (ctx->invocation); + g_object_unref (ctx->self); + g_slice_free (HandleCancelSessionContext, ctx); +} + +static void +cancel_session_ready (MMIfaceModemOma *self, + GAsyncResult *res, + HandleCancelSessionContext *ctx) +{ + GError *error = NULL; + + if (!MM_IFACE_MODEM_OMA_GET_INTERFACE (ctx->self)->cancel_session_finish (self, res, &error)) + g_dbus_method_invocation_take_error (ctx->invocation, error); + else { + /* Clear interface info when cancelled */ + mm_gdbus_modem_oma_set_session_type (ctx->skeleton, MM_OMA_SESSION_TYPE_UNKNOWN); + mm_iface_modem_oma_update_session_state (self, MM_OMA_SESSION_STATE_UNKNOWN, MM_OMA_SESSION_STATE_FAILED_REASON_UNKNOWN); + + mm_gdbus_modem_oma_complete_cancel_session (ctx->skeleton, ctx->invocation); + } + + handle_cancel_session_context_free (ctx); +} + +static void +handle_cancel_session_auth_ready (MMBaseModem *self, + GAsyncResult *res, + HandleCancelSessionContext *ctx) +{ + GError *error = NULL; + MMModemState modem_state; + + if (!mm_base_modem_authorize_finish (self, res, &error)) { + g_dbus_method_invocation_take_error (ctx->invocation, error); + handle_cancel_session_context_free (ctx); + return; + } + + modem_state = MM_MODEM_STATE_UNKNOWN; + g_object_get (self, + MM_IFACE_MODEM_STATE, &modem_state, + NULL); + if (modem_state < MM_MODEM_STATE_ENABLED) { + g_dbus_method_invocation_return_error (ctx->invocation, + MM_CORE_ERROR, + MM_CORE_ERROR_WRONG_STATE, + "Cannot cancel OMA session: " + "device not yet enabled"); + handle_cancel_session_context_free (ctx); + return; + } + + if (!MM_IFACE_MODEM_OMA_GET_INTERFACE (ctx->self)->cancel_session || + !MM_IFACE_MODEM_OMA_GET_INTERFACE (ctx->self)->cancel_session_finish) { + g_dbus_method_invocation_return_error (ctx->invocation, + MM_CORE_ERROR, + MM_CORE_ERROR_UNSUPPORTED, + "Cannot cancel OMA session: " + "operation not supported"); + handle_cancel_session_context_free (ctx); + return; + } + + mm_dbg ("Cancelling OMA session"); + MM_IFACE_MODEM_OMA_GET_INTERFACE (ctx->self)->cancel_session ( + ctx->self, + (GAsyncReadyCallback)cancel_session_ready, + ctx); +} + +static gboolean +handle_cancel_session (MmGdbusModemOma *skeleton, + GDBusMethodInvocation *invocation, + MMIfaceModemOma *self) +{ + HandleCancelSessionContext *ctx; + + ctx = g_slice_new0 (HandleCancelSessionContext); + ctx->skeleton = g_object_ref (skeleton); + ctx->invocation = g_object_ref (invocation); + ctx->self = g_object_ref (self); + + mm_base_modem_authorize (MM_BASE_MODEM (self), + invocation, + MM_AUTHORIZATION_DEVICE_CONTROL, + (GAsyncReadyCallback)handle_cancel_session_auth_ready, + ctx); + return TRUE; +} + +/*****************************************************************************/ + +typedef struct _DisablingContext DisablingContext; +static void interface_disabling_step (DisablingContext *ctx); + +typedef enum { + DISABLING_STEP_FIRST, + DISABLING_STEP_DISABLE_UNSOLICITED_EVENTS, + DISABLING_STEP_CLEANUP_UNSOLICITED_EVENTS, + DISABLING_STEP_LAST +} DisablingStep; + +struct _DisablingContext { + MMIfaceModemOma *self; + DisablingStep step; + GSimpleAsyncResult *result; + MmGdbusModemOma *skeleton; +}; + +static void +disabling_context_complete_and_free (DisablingContext *ctx) +{ + g_simple_async_result_complete_in_idle (ctx->result); + g_object_unref (ctx->self); + g_object_unref (ctx->result); + if (ctx->skeleton) + g_object_unref (ctx->skeleton); + g_free (ctx); +} + +gboolean +mm_iface_modem_oma_disable_finish (MMIfaceModemOma *self, + GAsyncResult *res, + GError **error) +{ + return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error); +} + +static void +disable_unsolicited_events_ready (MMIfaceModemOma *self, + GAsyncResult *res, + DisablingContext *ctx) +{ + GError *error = NULL; + + MM_IFACE_MODEM_OMA_GET_INTERFACE (self)->disable_unsolicited_events_finish (self, res, &error); + if (error) { + g_simple_async_result_take_error (ctx->result, error); + disabling_context_complete_and_free (ctx); + return; + } + + /* Go on to next step */ + ctx->step++; + interface_disabling_step (ctx); +} + +static void +cleanup_unsolicited_events_ready (MMIfaceModemOma *self, + GAsyncResult *res, + DisablingContext *ctx) +{ + GError *error = NULL; + + MM_IFACE_MODEM_OMA_GET_INTERFACE (self)->cleanup_unsolicited_events_finish (self, res, &error); + if (error) { + g_simple_async_result_take_error (ctx->result, error); + disabling_context_complete_and_free (ctx); + return; + } + + /* Go on to next step */ + ctx->step++; + interface_disabling_step (ctx); +} + +static void +interface_disabling_step (DisablingContext *ctx) +{ + switch (ctx->step) { + case DISABLING_STEP_FIRST: + /* Fall down to next step */ + ctx->step++; + + case DISABLING_STEP_DISABLE_UNSOLICITED_EVENTS: + /* Allow cleaning up unsolicited events */ + if (MM_IFACE_MODEM_OMA_GET_INTERFACE (ctx->self)->disable_unsolicited_events && + MM_IFACE_MODEM_OMA_GET_INTERFACE (ctx->self)->disable_unsolicited_events_finish) { + MM_IFACE_MODEM_OMA_GET_INTERFACE (ctx->self)->disable_unsolicited_events ( + ctx->self, + (GAsyncReadyCallback)disable_unsolicited_events_ready, + ctx); + return; + } + /* Fall down to next step */ + ctx->step++; + + case DISABLING_STEP_CLEANUP_UNSOLICITED_EVENTS: + /* Allow cleaning up unsolicited events */ + if (MM_IFACE_MODEM_OMA_GET_INTERFACE (ctx->self)->cleanup_unsolicited_events && + MM_IFACE_MODEM_OMA_GET_INTERFACE (ctx->self)->cleanup_unsolicited_events_finish) { + MM_IFACE_MODEM_OMA_GET_INTERFACE (ctx->self)->cleanup_unsolicited_events ( + ctx->self, + (GAsyncReadyCallback)cleanup_unsolicited_events_ready, + ctx); + return; + } + /* Fall down to next step */ + ctx->step++; + + case DISABLING_STEP_LAST: + /* We are done without errors! */ + g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE); + disabling_context_complete_and_free (ctx); + return; + } + + g_assert_not_reached (); +} + +void +mm_iface_modem_oma_disable (MMIfaceModemOma *self, + GAsyncReadyCallback callback, + gpointer user_data) +{ + DisablingContext *ctx; + + ctx = g_new0 (DisablingContext, 1); + ctx->self = g_object_ref (self); + ctx->result = g_simple_async_result_new (G_OBJECT (self), + callback, + user_data, + mm_iface_modem_oma_disable); + ctx->step = DISABLING_STEP_FIRST; + g_object_get (ctx->self, + MM_IFACE_MODEM_OMA_DBUS_SKELETON, &ctx->skeleton, + NULL); + if (!ctx->skeleton) { + g_simple_async_result_set_error (ctx->result, + MM_CORE_ERROR, + MM_CORE_ERROR_FAILED, + "Couldn't get interface skeleton"); + disabling_context_complete_and_free (ctx); + return; + } + + interface_disabling_step (ctx); +} + +/*****************************************************************************/ + +typedef struct _EnablingContext EnablingContext; +static void interface_enabling_step (EnablingContext *ctx); + +typedef enum { + ENABLING_STEP_FIRST, + ENABLING_STEP_LOAD_FEATURES, + ENABLING_STEP_SETUP_UNSOLICITED_EVENTS, + ENABLING_STEP_ENABLE_UNSOLICITED_EVENTS, + ENABLING_STEP_LAST +} EnablingStep; + +struct _EnablingContext { + MMIfaceModemOma *self; + EnablingStep step; + GSimpleAsyncResult *result; + GCancellable *cancellable; + MmGdbusModemOma *skeleton; +}; + +static void +enabling_context_complete_and_free (EnablingContext *ctx) +{ + g_simple_async_result_complete_in_idle (ctx->result); + g_object_unref (ctx->self); + g_object_unref (ctx->result); + g_object_unref (ctx->cancellable); + if (ctx->skeleton) + g_object_unref (ctx->skeleton); + g_free (ctx); +} + +static gboolean +enabling_context_complete_and_free_if_cancelled (EnablingContext *ctx) +{ + if (!g_cancellable_is_cancelled (ctx->cancellable)) + return FALSE; + + g_simple_async_result_set_error (ctx->result, + MM_CORE_ERROR, + MM_CORE_ERROR_CANCELLED, + "Interface enabling cancelled"); + enabling_context_complete_and_free (ctx); + return TRUE; +} + +gboolean +mm_iface_modem_oma_enable_finish (MMIfaceModemOma *self, + GAsyncResult *res, + GError **error) +{ + return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error); +} + +static void +load_features_ready (MMIfaceModemOma *self, + GAsyncResult *res, + EnablingContext *ctx) +{ + GError *error = NULL; + MMOmaFeature features; + + features = MM_IFACE_MODEM_OMA_GET_INTERFACE (self)->load_features_finish (self, res, &error); + if (error) { + g_simple_async_result_take_error (ctx->result, error); + enabling_context_complete_and_free (ctx); + return; + } + + /* Update in the interface */ + mm_gdbus_modem_oma_set_features (ctx->skeleton, features); + + /* Go on to next step */ + ctx->step++; + interface_enabling_step (ctx); +} + +static void +setup_unsolicited_events_ready (MMIfaceModemOma *self, + GAsyncResult *res, + EnablingContext *ctx) +{ + GError *error = NULL; + + MM_IFACE_MODEM_OMA_GET_INTERFACE (self)->setup_unsolicited_events_finish (self, res, &error); + if (error) { + g_simple_async_result_take_error (ctx->result, error); + enabling_context_complete_and_free (ctx); + return; + } + + /* Go on to next step */ + ctx->step++; + interface_enabling_step (ctx); +} + +static void +enable_unsolicited_events_ready (MMIfaceModemOma *self, + GAsyncResult *res, + EnablingContext *ctx) +{ + GError *error = NULL; + + /* Not critical! */ + if (!MM_IFACE_MODEM_OMA_GET_INTERFACE (self)->enable_unsolicited_events_finish (self, res, &error)) { + mm_dbg ("Couldn't enable unsolicited events: '%s'", error->message); + g_error_free (error); + } + + /* Go on with next step */ + ctx->step++; + interface_enabling_step (ctx); +} + +static void +interface_enabling_step (EnablingContext *ctx) +{ + /* Don't run new steps if we're cancelled */ + if (enabling_context_complete_and_free_if_cancelled (ctx)) + return; + + switch (ctx->step) { + case ENABLING_STEP_FIRST: + /* Fall down to next step */ + ctx->step++; + + case ENABLING_STEP_LOAD_FEATURES: + if (MM_IFACE_MODEM_OMA_GET_INTERFACE (ctx->self)->load_features && + MM_IFACE_MODEM_OMA_GET_INTERFACE (ctx->self)->load_features_finish) { + MM_IFACE_MODEM_OMA_GET_INTERFACE (ctx->self)->load_features ( + ctx->self, + (GAsyncReadyCallback)load_features_ready, + ctx); + return; + } + /* Fall down to next step */ + ctx->step++; + + case ENABLING_STEP_SETUP_UNSOLICITED_EVENTS: + /* Allow setting up unsolicited events */ + if (MM_IFACE_MODEM_OMA_GET_INTERFACE (ctx->self)->setup_unsolicited_events && + MM_IFACE_MODEM_OMA_GET_INTERFACE (ctx->self)->setup_unsolicited_events_finish) { + MM_IFACE_MODEM_OMA_GET_INTERFACE (ctx->self)->setup_unsolicited_events ( + ctx->self, + (GAsyncReadyCallback)setup_unsolicited_events_ready, + ctx); + return; + } + /* Fall down to next step */ + ctx->step++; + + case ENABLING_STEP_ENABLE_UNSOLICITED_EVENTS: + /* Allow setting up unsolicited events */ + if (MM_IFACE_MODEM_OMA_GET_INTERFACE (ctx->self)->enable_unsolicited_events && + MM_IFACE_MODEM_OMA_GET_INTERFACE (ctx->self)->enable_unsolicited_events_finish) { + MM_IFACE_MODEM_OMA_GET_INTERFACE (ctx->self)->enable_unsolicited_events ( + ctx->self, + (GAsyncReadyCallback)enable_unsolicited_events_ready, + ctx); + return; + } + /* Fall down to next step */ + ctx->step++; + + case ENABLING_STEP_LAST: + /* We are done without errors! */ + g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE); + enabling_context_complete_and_free (ctx); + return; + } + + g_assert_not_reached (); +} + +void +mm_iface_modem_oma_enable (MMIfaceModemOma *self, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + EnablingContext *ctx; + + ctx = g_new0 (EnablingContext, 1); + ctx->self = g_object_ref (self); + ctx->cancellable = g_object_ref (cancellable); + ctx->result = g_simple_async_result_new (G_OBJECT (self), + callback, + user_data, + mm_iface_modem_oma_enable); + ctx->step = ENABLING_STEP_FIRST; + g_object_get (ctx->self, + MM_IFACE_MODEM_OMA_DBUS_SKELETON, &ctx->skeleton, + NULL); + if (!ctx->skeleton) { + g_simple_async_result_set_error (ctx->result, + MM_CORE_ERROR, + MM_CORE_ERROR_FAILED, + "Couldn't get interface skeleton"); + enabling_context_complete_and_free (ctx); + return; + } + + interface_enabling_step (ctx); +} + +/*****************************************************************************/ + +typedef struct _InitializationContext InitializationContext; +static void interface_initialization_step (InitializationContext *ctx); + +typedef enum { + INITIALIZATION_STEP_FIRST, + INITIALIZATION_STEP_CHECK_SUPPORT, + INITIALIZATION_STEP_FAIL_IF_UNSUPPORTED, + INITIALIZATION_STEP_LAST +} InitializationStep; + +struct _InitializationContext { + MMIfaceModemOma *self; + MmGdbusModemOma *skeleton; + GSimpleAsyncResult *result; + GCancellable *cancellable; + InitializationStep step; +}; + +static void +initialization_context_complete_and_free (InitializationContext *ctx) +{ + g_simple_async_result_complete_in_idle (ctx->result); + g_object_unref (ctx->self); + g_object_unref (ctx->result); + g_object_unref (ctx->cancellable); + g_object_unref (ctx->skeleton); + g_free (ctx); +} + +static gboolean +initialization_context_complete_and_free_if_cancelled (InitializationContext *ctx) +{ + if (!g_cancellable_is_cancelled (ctx->cancellable)) + return FALSE; + + g_simple_async_result_set_error (ctx->result, + MM_CORE_ERROR, + MM_CORE_ERROR_CANCELLED, + "Interface initialization cancelled"); + initialization_context_complete_and_free (ctx); + return TRUE; +} + +static void +check_support_ready (MMIfaceModemOma *self, + GAsyncResult *res, + InitializationContext *ctx) +{ + GError *error = NULL; + + if (!MM_IFACE_MODEM_OMA_GET_INTERFACE (self)->check_support_finish (self, res, &error)) { + if (error) { + /* This error shouldn't be treated as critical */ + mm_dbg ("OMA support check failed: '%s'", error->message); + g_error_free (error); + } + } else { + /* OMA is supported! */ + g_object_set_qdata (G_OBJECT (self), + supported_quark, + GUINT_TO_POINTER (TRUE)); + } + + /* Go on to next step */ + ctx->step++; + interface_initialization_step (ctx); +} + +static void +interface_initialization_step (InitializationContext *ctx) +{ + /* Don't run new steps if we're cancelled */ + if (initialization_context_complete_and_free_if_cancelled (ctx)) + return; + + switch (ctx->step) { + case INITIALIZATION_STEP_FIRST: + /* Setup quarks if we didn't do it before */ + if (G_UNLIKELY (!support_checked_quark)) + support_checked_quark = (g_quark_from_static_string ( + SUPPORT_CHECKED_TAG)); + if (G_UNLIKELY (!supported_quark)) + supported_quark = (g_quark_from_static_string ( + SUPPORTED_TAG)); + + /* Fall down to next step */ + ctx->step++; + + case INITIALIZATION_STEP_CHECK_SUPPORT: + if (!GPOINTER_TO_UINT (g_object_get_qdata (G_OBJECT (ctx->self), + support_checked_quark))) { + /* Set the checked flag so that we don't run it again */ + g_object_set_qdata (G_OBJECT (ctx->self), + support_checked_quark, + GUINT_TO_POINTER (TRUE)); + /* Initially, assume we don't support it */ + g_object_set_qdata (G_OBJECT (ctx->self), + supported_quark, + GUINT_TO_POINTER (FALSE)); + + if (MM_IFACE_MODEM_OMA_GET_INTERFACE (ctx->self)->check_support && + MM_IFACE_MODEM_OMA_GET_INTERFACE (ctx->self)->check_support_finish) { + MM_IFACE_MODEM_OMA_GET_INTERFACE (ctx->self)->check_support ( + ctx->self, + (GAsyncReadyCallback)check_support_ready, + ctx); + return; + } + + /* If there is no implementation to check support, assume we DON'T + * support it. */ + } + /* Fall down to next step */ + ctx->step++; + + case INITIALIZATION_STEP_FAIL_IF_UNSUPPORTED: + if (!GPOINTER_TO_UINT (g_object_get_qdata (G_OBJECT (ctx->self), + supported_quark))) { + g_simple_async_result_set_error (ctx->result, + MM_CORE_ERROR, + MM_CORE_ERROR_UNSUPPORTED, + "OMA not supported"); + initialization_context_complete_and_free (ctx); + return; + } + /* Fall down to next step */ + ctx->step++; + + case INITIALIZATION_STEP_LAST: + /* We are done without errors! */ + + /* Handle method invocations */ + g_signal_connect (ctx->skeleton, + "handle-setup", + G_CALLBACK (handle_setup), + ctx->self); + g_signal_connect (ctx->skeleton, + "handle-start-client-initiated-session", + G_CALLBACK (handle_start_client_initiated_session), + ctx->self); + g_signal_connect (ctx->skeleton, + "handle-accept-network-initiated-session", + G_CALLBACK (handle_accept_network_initiated_session), + ctx->self); + g_signal_connect (ctx->skeleton, + "handle-cancel-session", + G_CALLBACK (handle_cancel_session), + ctx->self); + + /* Finally, export the new interface */ + mm_gdbus_object_skeleton_set_modem_oma (MM_GDBUS_OBJECT_SKELETON (ctx->self), + MM_GDBUS_MODEM_OMA (ctx->skeleton)); + + g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE); + initialization_context_complete_and_free (ctx); + return; + } + + g_assert_not_reached (); +} + +gboolean +mm_iface_modem_oma_initialize_finish (MMIfaceModemOma *self, + GAsyncResult *res, + GError **error) +{ + return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error); +} + +void +mm_iface_modem_oma_initialize (MMIfaceModemOma *self, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + InitializationContext *ctx; + MmGdbusModemOma *skeleton = NULL; + + /* Did we already create it? */ + g_object_get (self, + MM_IFACE_MODEM_OMA_DBUS_SKELETON, &skeleton, + NULL); + if (!skeleton) { + skeleton = mm_gdbus_modem_oma_skeleton_new (); + g_object_set (self, + MM_IFACE_MODEM_OMA_DBUS_SKELETON, skeleton, + NULL); + + /* Set all initial property defaults */ + mm_gdbus_modem_oma_set_features (skeleton, MM_OMA_FEATURE_NONE); + mm_gdbus_modem_oma_set_session_type (skeleton, MM_OMA_SESSION_TYPE_UNKNOWN); + mm_gdbus_modem_oma_set_session_state (skeleton, MM_OMA_SESSION_STATE_UNKNOWN); + mm_gdbus_modem_oma_set_pending_network_initiated_sessions (skeleton, mm_common_build_oma_pending_network_initiated_sessions_default ()); + } + + /* Perform async initialization here */ + + ctx = g_new0 (InitializationContext, 1); + ctx->self = g_object_ref (self); + ctx->cancellable = g_object_ref (cancellable); + ctx->result = g_simple_async_result_new (G_OBJECT (self), + callback, + user_data, + mm_iface_modem_oma_initialize); + ctx->step = INITIALIZATION_STEP_FIRST; + ctx->skeleton = skeleton; + + interface_initialization_step (ctx); +} + +void +mm_iface_modem_oma_shutdown (MMIfaceModemOma *self) +{ + /* Unexport DBus interface and remove the skeleton */ + mm_gdbus_object_skeleton_set_modem_oma (MM_GDBUS_OBJECT_SKELETON (self), NULL); + g_object_set (self, + MM_IFACE_MODEM_OMA_DBUS_SKELETON, NULL, + NULL); +} + +/*****************************************************************************/ + +static void +iface_modem_oma_init (gpointer g_iface) +{ + static gboolean initialized = FALSE; + + if (initialized) + return; + + /* Properties */ + g_object_interface_install_property + (g_iface, + g_param_spec_object (MM_IFACE_MODEM_OMA_DBUS_SKELETON, + "OMA DBus skeleton", + "DBus skeleton for the OMA interface", + MM_GDBUS_TYPE_MODEM_OMA_SKELETON, + G_PARAM_READWRITE)); + + initialized = TRUE; +} + +GType +mm_iface_modem_oma_get_type (void) +{ + static GType iface_modem_oma_type = 0; + + if (!G_UNLIKELY (iface_modem_oma_type)) { + static const GTypeInfo info = { + sizeof (MMIfaceModemOma), /* class_size */ + iface_modem_oma_init, /* base_init */ + NULL, /* base_finalize */ + }; + + iface_modem_oma_type = g_type_register_static (G_TYPE_INTERFACE, + "MMIfaceModemOma", + &info, + 0); + + g_type_interface_add_prerequisite (iface_modem_oma_type, MM_TYPE_IFACE_MODEM); + } + + return iface_modem_oma_type; +} diff --git a/src/mm-iface-modem-oma.h b/src/mm-iface-modem-oma.h new file mode 100644 index 00000000..3e3d00bc --- /dev/null +++ b/src/mm-iface-modem-oma.h @@ -0,0 +1,164 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details: + * + * Copyright (C) 2013 Google, Inc. + */ + +#ifndef MM_IFACE_MODEM_OMA_H +#define MM_IFACE_MODEM_OMA_H + +#include <glib-object.h> +#include <gio/gio.h> + +#define MM_TYPE_IFACE_MODEM_OMA (mm_iface_modem_oma_get_type ()) +#define MM_IFACE_MODEM_OMA(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MM_TYPE_IFACE_MODEM_OMA, MMIfaceModemOma)) +#define MM_IS_IFACE_MODEM_OMA(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MM_TYPE_IFACE_MODEM_OMA)) +#define MM_IFACE_MODEM_OMA_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), MM_TYPE_IFACE_MODEM_OMA, MMIfaceModemOma)) + +#define MM_IFACE_MODEM_OMA_DBUS_SKELETON "iface-modem-oma-dbus-skeleton" + +typedef struct _MMIfaceModemOma MMIfaceModemOma; + +struct _MMIfaceModemOma { + GTypeInterface g_iface; + + /* Check for Oma support (async) */ + void (* check_support) (MMIfaceModemOma *self, + GAsyncReadyCallback callback, + gpointer user_data); + gboolean (* check_support_finish) (MMIfaceModemOma *self, + GAsyncResult *res, + GError **error); + + /* Asynchronous setting up unsolicited events */ + void (* setup_unsolicited_events) (MMIfaceModemOma *self, + GAsyncReadyCallback callback, + gpointer user_data); + gboolean (* setup_unsolicited_events_finish) (MMIfaceModemOma *self, + GAsyncResult *res, + GError **error); + + /* Asynchronous cleaning up of unsolicited events */ + void (* cleanup_unsolicited_events) (MMIfaceModemOma *self, + GAsyncReadyCallback callback, + gpointer user_data); + gboolean (* cleanup_unsolicited_events_finish) (MMIfaceModemOma *self, + GAsyncResult *res, + GError **error); + + /* Asynchronous enabling unsolicited events */ + void (* enable_unsolicited_events) (MMIfaceModemOma *self, + GAsyncReadyCallback callback, + gpointer user_data); + gboolean (* enable_unsolicited_events_finish) (MMIfaceModemOma *self, + GAsyncResult *res, + GError **error); + + /* Asynchronous disabling unsolicited events */ + void (* disable_unsolicited_events) (MMIfaceModemOma *self, + GAsyncReadyCallback callback, + gpointer user_data); + gboolean (* disable_unsolicited_events_finish) (MMIfaceModemOma *self, + GAsyncResult *res, + GError **error); + + /* Get current features */ + void (* load_features) (MMIfaceModemOma *self, + GAsyncReadyCallback callback, + gpointer user_data); + MMOmaFeature (* load_features_finish) (MMIfaceModemOma *self, + GAsyncResult *res, + GError **error); + + /* Setup */ + void (* setup) (MMIfaceModemOma *self, + MMOmaFeature features, + GAsyncReadyCallback callback, + gpointer user_data); + gboolean (* setup_finish) (MMIfaceModemOma *self, + GAsyncResult *res, + GError **error); + + /* Start client-initiated session */ + void (* start_client_initiated_session) (MMIfaceModemOma *self, + MMOmaSessionType session_type, + GAsyncReadyCallback callback, + gpointer user_data); + gboolean (* start_client_initiated_session_finish) (MMIfaceModemOma *self, + GAsyncResult *res, + GError **error); + + /* Accept network-initiated session */ + void (* accept_network_initiated_session) (MMIfaceModemOma *self, + guint session_id, + gboolean accept, + GAsyncReadyCallback callback, + gpointer user_data); + gboolean (* accept_network_initiated_session_finish) (MMIfaceModemOma *self, + GAsyncResult *res, + GError **error); + + /* Cancel session */ + void (* cancel_session) (MMIfaceModemOma *self, + GAsyncReadyCallback callback, + gpointer user_data); + gboolean (* cancel_session_finish) (MMIfaceModemOma *self, + GAsyncResult *res, + GError **error); +}; + +GType mm_iface_modem_oma_get_type (void); + +/* Initialize Oma interface (async) */ +void mm_iface_modem_oma_initialize (MMIfaceModemOma *self, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +gboolean mm_iface_modem_oma_initialize_finish (MMIfaceModemOma *self, + GAsyncResult *res, + GError **error); + +/* Enable Oma interface (async) */ +void mm_iface_modem_oma_enable (MMIfaceModemOma *self, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +gboolean mm_iface_modem_oma_enable_finish (MMIfaceModemOma *self, + GAsyncResult *res, + GError **error); + +/* Disable Oma interface (async) */ +void mm_iface_modem_oma_disable (MMIfaceModemOma *self, + GAsyncReadyCallback callback, + gpointer user_data); +gboolean mm_iface_modem_oma_disable_finish (MMIfaceModemOma *self, + GAsyncResult *res, + GError **error); + +/* Shutdown Oma interface */ +void mm_iface_modem_oma_shutdown (MMIfaceModemOma *self); + +/* Bind properties for simple GetStatus() */ +void mm_iface_modem_oma_bind_simple_status (MMIfaceModemOma *self, + MMSimpleStatus *status); + +/* Report new pending network-initiated session */ +void mm_iface_modem_oma_add_pending_network_initiated_session (MMIfaceModemOma *self, + MMOmaSessionType session_type, + guint session_id); + +/* Report new session state */ +void mm_iface_modem_oma_update_session_state (MMIfaceModemOma *self, + MMOmaSessionState session_state, + MMOmaSessionStateFailedReason session_state_failed_reason); + +#endif /* MM_IFACE_MODEM_OMA_H */ |