diff options
author | Aleksander Morgado <aleksander@lanedo.com> | 2012-01-23 17:59:17 +0100 |
---|---|---|
committer | Aleksander Morgado <aleksander@lanedo.com> | 2012-03-15 14:14:57 +0100 |
commit | 7210e6caf1cc54b43aff9b7d4e62489ab8188799 (patch) | |
tree | 5a6e9f64532df0852432e45bac2b928df5c3d115 /src/mm-iface-modem-3gpp-ussd.c | |
parent | f3ee74c1e871f23564d7e6c5198ed26a8dd35833 (diff) |
iface-modem-3gpp-ussd: handle USSD session initiate/respond/cancel
Diffstat (limited to 'src/mm-iface-modem-3gpp-ussd.c')
-rw-r--r-- | src/mm-iface-modem-3gpp-ussd.c | 205 |
1 files changed, 205 insertions, 0 deletions
diff --git a/src/mm-iface-modem-3gpp-ussd.c b/src/mm-iface-modem-3gpp-ussd.c index 6ec282bb..75907369 100644 --- a/src/mm-iface-modem-3gpp-ussd.c +++ b/src/mm-iface-modem-3gpp-ussd.c @@ -42,6 +42,197 @@ mm_iface_modem_3gpp_ussd_bind_simple_status (MMIfaceModem3gppUssd *self, /*****************************************************************************/ +typedef struct { + MmGdbusModem3gppUssd *skeleton; + GDBusMethodInvocation *invocation; + MMIfaceModem3gppUssd *self; +} DbusCallContext; + +static void +dbus_call_context_free (DbusCallContext *ctx) +{ + g_object_unref (ctx->skeleton); + g_object_unref (ctx->invocation); + g_object_unref (ctx->self); + g_free (ctx); +} + +static DbusCallContext * +dbus_call_context_new (MmGdbusModem3gppUssd *skeleton, + GDBusMethodInvocation *invocation, + MMIfaceModem3gppUssd *self) +{ + DbusCallContext *ctx; + + ctx = g_new (DbusCallContext, 1); + ctx->skeleton = g_object_ref (skeleton); + ctx->invocation = g_object_ref (invocation); + ctx->self = g_object_ref (self); + return ctx; +} + +/*****************************************************************************/ + +static void +cancel_ready (MMIfaceModem3gppUssd *self, + GAsyncResult *res, + DbusCallContext *ctx) +{ + GError *error = NULL; + + if (!MM_IFACE_MODEM_3GPP_USSD_GET_INTERFACE (self)->cancel_finish (self, + res, + &error)) + g_dbus_method_invocation_take_error (ctx->invocation, + error); + else + mm_gdbus_modem3gpp_ussd_complete_cancel (ctx->skeleton, + ctx->invocation); + dbus_call_context_free (ctx); +} + +static gboolean +handle_cancel (MmGdbusModem3gppUssd *skeleton, + GDBusMethodInvocation *invocation, + const gchar *command, + MMIfaceModem3gppUssd *self) +{ + g_assert (MM_IFACE_MODEM_3GPP_USSD_GET_INTERFACE (self)->cancel != NULL); + g_assert (MM_IFACE_MODEM_3GPP_USSD_GET_INTERFACE (self)->cancel_finish != NULL); + + MM_IFACE_MODEM_3GPP_USSD_GET_INTERFACE (self)->cancel ( + self, + (GAsyncReadyCallback)cancel_ready, + dbus_call_context_new (skeleton, + invocation, + self)); + return TRUE; +} + +static void +respond_send_ready (MMIfaceModem3gppUssd *self, + GAsyncResult *res, + DbusCallContext *ctx) +{ + GError *error = NULL; + const gchar *reply; + + reply = MM_IFACE_MODEM_3GPP_USSD_GET_INTERFACE (self)->send_finish (self, + res, + &error); + if (!reply) + g_dbus_method_invocation_take_error (ctx->invocation, + error); + else + mm_gdbus_modem3gpp_ussd_complete_respond (ctx->skeleton, + ctx->invocation, + reply); + dbus_call_context_free (ctx); +} + +static gboolean +handle_respond (MmGdbusModem3gppUssd *skeleton, + GDBusMethodInvocation *invocation, + const gchar *command, + MMIfaceModem3gppUssd *self) +{ + g_assert (MM_IFACE_MODEM_3GPP_USSD_GET_INTERFACE (self)->send != NULL); + g_assert (MM_IFACE_MODEM_3GPP_USSD_GET_INTERFACE (self)->send_finish != NULL); + + switch (mm_gdbus_modem3gpp_ussd_get_state (skeleton)) { + case MM_MODEM_3GPP_USSD_SESSION_STATE_ACTIVE: + case MM_MODEM_3GPP_USSD_SESSION_STATE_IDLE: + g_dbus_method_invocation_return_error (invocation, + MM_CORE_ERROR, + MM_CORE_ERROR_WRONG_STATE, + "Cannot respond USSD: " + "no active session"); + break; + + case MM_MODEM_3GPP_USSD_SESSION_STATE_USER_RESPONSE: + MM_IFACE_MODEM_3GPP_USSD_GET_INTERFACE (self)->send ( + self, + command, + (GAsyncReadyCallback)respond_send_ready, + dbus_call_context_new (skeleton, + invocation, + self)); + break; + + case MM_MODEM_3GPP_USSD_SESSION_STATE_UNKNOWN: + default: + /* We should never have a DBus request when in UNKNOWN state */ + g_assert_not_reached (); + break; + } + + return TRUE; +} + +/*****************************************************************************/ + +static void +initiate_send_ready (MMIfaceModem3gppUssd *self, + GAsyncResult *res, + DbusCallContext *ctx) +{ + GError *error = NULL; + const gchar *reply; + + reply = MM_IFACE_MODEM_3GPP_USSD_GET_INTERFACE (self)->send_finish (self, + res, + &error); + if (!reply) + g_dbus_method_invocation_take_error (ctx->invocation, + error); + else + mm_gdbus_modem3gpp_ussd_complete_initiate (ctx->skeleton, + ctx->invocation, + reply); + dbus_call_context_free (ctx); +} + +static gboolean +handle_initiate (MmGdbusModem3gppUssd *skeleton, + GDBusMethodInvocation *invocation, + const gchar *command, + MMIfaceModem3gppUssd *self) +{ + g_assert (MM_IFACE_MODEM_3GPP_USSD_GET_INTERFACE (self)->send != NULL); + g_assert (MM_IFACE_MODEM_3GPP_USSD_GET_INTERFACE (self)->send_finish != NULL); + + switch (mm_gdbus_modem3gpp_ussd_get_state (skeleton)) { + case MM_MODEM_3GPP_USSD_SESSION_STATE_ACTIVE: + case MM_MODEM_3GPP_USSD_SESSION_STATE_USER_RESPONSE: + g_dbus_method_invocation_return_error (invocation, + MM_CORE_ERROR, + MM_CORE_ERROR_WRONG_STATE, + "Cannot initiate USSD: " + "a session is already active"); + break; + + case MM_MODEM_3GPP_USSD_SESSION_STATE_IDLE: + MM_IFACE_MODEM_3GPP_USSD_GET_INTERFACE (self)->send ( + self, + command, + (GAsyncReadyCallback)initiate_send_ready, + dbus_call_context_new (skeleton, + invocation, + self)); + break; + + case MM_MODEM_3GPP_USSD_SESSION_STATE_UNKNOWN: + default: + /* We should never have a DBus request when in UNKNOWN state */ + g_assert_not_reached (); + break; + } + + return TRUE; +} + +/*****************************************************************************/ + gchar * mm_iface_modem_3gpp_ussd_encode (MMIfaceModem3gppUssd *self, const gchar *command, @@ -542,6 +733,20 @@ interface_initialization_step (InitializationContext *ctx) case INITIALIZATION_STEP_LAST: /* We are done without errors! */ + /* Handle method invocations */ + g_signal_connect (ctx->skeleton, + "handle-initiate", + G_CALLBACK (handle_initiate), + ctx->self); + g_signal_connect (ctx->skeleton, + "handle-respond", + G_CALLBACK (handle_respond), + ctx->self); + g_signal_connect (ctx->skeleton, + "handle-cancel", + G_CALLBACK (handle_cancel), + ctx->self); + /* Finally, export the new interface */ mm_gdbus_object_skeleton_set_modem3gpp_ussd (MM_GDBUS_OBJECT_SKELETON (ctx->self), MM_GDBUS_MODEM3GPP_USSD (ctx->skeleton)); |