aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am2
-rw-r--r--src/mm-broadband-modem.c63
-rw-r--r--src/mm-iface-modem-oma.c1252
-rw-r--r--src/mm-iface-modem-oma.h164
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 */