ofono: implement USSD interface
all the information for ofono USSD iface comes from https://github.com/FuriLabs/ofono/blob/trixie/ofono/doc/supplementaryservices-api.txt the introspect for gdbo bindings comes from gdbus introspect -x Signed-off-by: Bardia Moshiri <bardia@furilabs.com> Part-of: <https://gitlab.gnome.org/GNOME/calls/-/merge_requests/742>
This commit is contained in:
committed by
Marge Bot
parent
c6f816687d
commit
524235b86c
@@ -26,8 +26,10 @@
|
|||||||
|
|
||||||
#include "calls-ofono-origin.h"
|
#include "calls-ofono-origin.h"
|
||||||
#include "calls-origin.h"
|
#include "calls-origin.h"
|
||||||
|
#include "calls-ussd.h"
|
||||||
#include "calls-ofono-call.h"
|
#include "calls-ofono-call.h"
|
||||||
#include "calls-message-source.h"
|
#include "calls-message-source.h"
|
||||||
|
#include "calls-util.h"
|
||||||
|
|
||||||
#include <glib/gi18n.h>
|
#include <glib/gi18n.h>
|
||||||
|
|
||||||
@@ -38,20 +40,27 @@ struct _CallsOfonoOrigin {
|
|||||||
GDBOModem *modem;
|
GDBOModem *modem;
|
||||||
gchar *name;
|
gchar *name;
|
||||||
GDBOVoiceCallManager *voice;
|
GDBOVoiceCallManager *voice;
|
||||||
|
GDBOSupplementaryServices *ussd;
|
||||||
gboolean sending_tones;
|
gboolean sending_tones;
|
||||||
GString *tone_queue;
|
GString *tone_queue;
|
||||||
GHashTable *calls;
|
GHashTable *calls;
|
||||||
|
|
||||||
|
CallsUssdState ussd_state;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void calls_ofono_origin_message_source_interface_init (CallsOriginInterface *iface);
|
static void calls_ofono_origin_message_source_interface_init (CallsOriginInterface *iface);
|
||||||
static void calls_ofono_origin_origin_interface_init (CallsOriginInterface *iface);
|
static void calls_ofono_origin_origin_interface_init (CallsOriginInterface *iface);
|
||||||
|
static void calls_ofono_origin_ussd_interface_init (CallsUssdInterface *iface);
|
||||||
|
|
||||||
G_DEFINE_TYPE_WITH_CODE (CallsOfonoOrigin, calls_ofono_origin, G_TYPE_OBJECT,
|
G_DEFINE_TYPE_WITH_CODE (CallsOfonoOrigin, calls_ofono_origin, G_TYPE_OBJECT,
|
||||||
G_IMPLEMENT_INTERFACE (CALLS_TYPE_MESSAGE_SOURCE,
|
G_IMPLEMENT_INTERFACE (CALLS_TYPE_MESSAGE_SOURCE,
|
||||||
calls_ofono_origin_message_source_interface_init)
|
calls_ofono_origin_message_source_interface_init)
|
||||||
|
G_IMPLEMENT_INTERFACE (CALLS_TYPE_USSD,
|
||||||
|
calls_ofono_origin_ussd_interface_init)
|
||||||
G_IMPLEMENT_INTERFACE (CALLS_TYPE_ORIGIN,
|
G_IMPLEMENT_INTERFACE (CALLS_TYPE_ORIGIN,
|
||||||
calls_ofono_origin_origin_interface_init))
|
calls_ofono_origin_origin_interface_init))
|
||||||
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
PROP_0,
|
PROP_0,
|
||||||
PROP_ID,
|
PROP_ID,
|
||||||
@@ -65,6 +74,238 @@ enum {
|
|||||||
static GParamSpec *props[PROP_LAST_PROP];
|
static GParamSpec *props[PROP_LAST_PROP];
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
ussd_initiate_cb (GObject *object,
|
||||||
|
GAsyncResult *result,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
g_autoptr (GTask) task = user_data;
|
||||||
|
GDBOSupplementaryServices *ussd = GDBO_SUPPLEMENTARY_SERVICES (object);
|
||||||
|
CallsOfonoOrigin *self = CALLS_OFONO_ORIGIN (user_data);
|
||||||
|
g_autoptr (GVariant) variant = NULL;
|
||||||
|
char *response = NULL;
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
|
g_assert (G_IS_TASK (task));
|
||||||
|
self = g_task_get_source_object (task);
|
||||||
|
|
||||||
|
g_assert (GDBO_IS_SUPPLEMENTARY_SERVICES (ussd));
|
||||||
|
g_assert (CALLS_IS_OFONO_ORIGIN (self));
|
||||||
|
|
||||||
|
gdbo_supplementary_services_call_initiate_finish (ussd, NULL,
|
||||||
|
&variant, result, &error);
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
g_task_return_error (task, error);
|
||||||
|
} else {
|
||||||
|
g_autoptr (GVariant) child = g_variant_get_child_value (variant, 0);
|
||||||
|
response = g_variant_dup_string (child, NULL);
|
||||||
|
self->ussd_state = CALLS_USSD_STATE_USER_RESPONSE;
|
||||||
|
g_task_return_pointer (task, response, g_free);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ussd_reinitiate_cb (GObject *object,
|
||||||
|
GAsyncResult *result,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
g_autoptr (GTask) task = user_data;
|
||||||
|
CallsUssd *ussd = CALLS_USSD (object);
|
||||||
|
CallsOfonoOrigin *self = CALLS_OFONO_ORIGIN (user_data);
|
||||||
|
GCancellable *cancellable;
|
||||||
|
GError *error = NULL;
|
||||||
|
const char *command;
|
||||||
|
|
||||||
|
g_assert (G_IS_TASK (task));
|
||||||
|
self = g_task_get_source_object (task);
|
||||||
|
|
||||||
|
g_assert (CALLS_IS_USSD (ussd));
|
||||||
|
g_assert (CALLS_IS_OFONO_ORIGIN (self));
|
||||||
|
|
||||||
|
calls_ussd_cancel_finish (ussd, result, &error);
|
||||||
|
cancellable = g_task_get_cancellable (task);
|
||||||
|
command = g_task_get_task_data (task);
|
||||||
|
|
||||||
|
if (error)
|
||||||
|
g_task_return_error (task, error);
|
||||||
|
else {
|
||||||
|
self->ussd_state = CALLS_USSD_STATE_ACTIVE;
|
||||||
|
gdbo_supplementary_services_call_initiate (self->ussd, command, cancellable,
|
||||||
|
ussd_initiate_cb, g_steal_pointer (&task));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ussd_respond_cb (GObject *object,
|
||||||
|
GAsyncResult *result,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
g_autoptr (GTask) task = user_data;
|
||||||
|
GDBOSupplementaryServices *ussd = GDBO_SUPPLEMENTARY_SERVICES (object);
|
||||||
|
CallsOfonoOrigin *self;
|
||||||
|
char *response = NULL;
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
|
g_assert (G_IS_TASK (task));
|
||||||
|
self = g_task_get_source_object (task);
|
||||||
|
|
||||||
|
g_assert (CALLS_IS_OFONO_ORIGIN (self));
|
||||||
|
g_assert (GDBO_IS_SUPPLEMENTARY_SERVICES (ussd));
|
||||||
|
|
||||||
|
gdbo_supplementary_services_call_respond_finish (ussd, &response, result, &error);
|
||||||
|
|
||||||
|
if (error)
|
||||||
|
g_task_return_error (task, error);
|
||||||
|
else
|
||||||
|
g_task_return_pointer (task, response, g_free);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ussd_cancel_cb (GObject *object,
|
||||||
|
GAsyncResult *result,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
g_autoptr (GTask) task = user_data;
|
||||||
|
GDBOSupplementaryServices *ussd = GDBO_SUPPLEMENTARY_SERVICES (object);
|
||||||
|
CallsOfonoOrigin *self;
|
||||||
|
GError *error = NULL;
|
||||||
|
gboolean response;
|
||||||
|
|
||||||
|
g_assert (G_IS_TASK (task));
|
||||||
|
self = g_task_get_source_object (task);
|
||||||
|
|
||||||
|
g_assert (CALLS_IS_OFONO_ORIGIN (self));
|
||||||
|
g_assert (GDBO_IS_SUPPLEMENTARY_SERVICES (ussd));
|
||||||
|
|
||||||
|
response = gdbo_supplementary_services_call_cancel_finish (ussd, result, &error);
|
||||||
|
self->ussd_state = CALLS_USSD_STATE_IDLE;
|
||||||
|
|
||||||
|
if (error)
|
||||||
|
g_task_return_error (task, error);
|
||||||
|
else
|
||||||
|
g_task_return_boolean (task, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
static CallsUssdState
|
||||||
|
calls_ofono_ussd_get_state (CallsUssd *ussd)
|
||||||
|
{
|
||||||
|
CallsOfonoOrigin *self = CALLS_OFONO_ORIGIN (ussd);
|
||||||
|
|
||||||
|
if (!self->ussd)
|
||||||
|
self->ussd_state = CALLS_USSD_STATE_UNKNOWN;
|
||||||
|
|
||||||
|
return self->ussd_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
calls_ofono_ussd_initiate_async (CallsUssd *ussd,
|
||||||
|
const char *command,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
g_autoptr (GTask) task = NULL;
|
||||||
|
CallsOfonoOrigin *self = CALLS_OFONO_ORIGIN (ussd);
|
||||||
|
CallsUssdState state;
|
||||||
|
|
||||||
|
g_return_if_fail (CALLS_IS_USSD (ussd));
|
||||||
|
|
||||||
|
task = g_task_new (self, cancellable, callback, user_data);
|
||||||
|
|
||||||
|
if (!self->ussd) {
|
||||||
|
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
|
||||||
|
"No USSD interface found");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (STR_IS_NULL_OR_EMPTY (command)) {
|
||||||
|
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||||
|
"USSD command empty");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
state = calls_ussd_get_state (CALLS_USSD (self));
|
||||||
|
g_task_set_task_data (task, g_strdup (command), g_free);
|
||||||
|
|
||||||
|
if (state == CALLS_USSD_STATE_ACTIVE ||
|
||||||
|
state == CALLS_USSD_STATE_USER_RESPONSE)
|
||||||
|
calls_ussd_cancel_async (CALLS_USSD (self), cancellable,
|
||||||
|
ussd_reinitiate_cb, g_steal_pointer (&task));
|
||||||
|
else {
|
||||||
|
self->ussd_state = CALLS_USSD_STATE_ACTIVE;
|
||||||
|
gdbo_supplementary_services_call_initiate (self->ussd, command, cancellable,
|
||||||
|
ussd_initiate_cb, g_steal_pointer (&task));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
calls_ofono_ussd_initiate_finish (CallsUssd *ussd,
|
||||||
|
GAsyncResult *result,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (CALLS_IS_USSD (ussd), NULL);
|
||||||
|
g_return_val_if_fail (G_IS_TASK (result), NULL);
|
||||||
|
|
||||||
|
return g_task_propagate_pointer (G_TASK (result), error);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
calls_ofono_ussd_respond_async (CallsUssd *ussd,
|
||||||
|
const char *response,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
CallsOfonoOrigin *self = CALLS_OFONO_ORIGIN (ussd);
|
||||||
|
GTask *task;
|
||||||
|
|
||||||
|
g_return_if_fail (CALLS_IS_USSD (ussd));
|
||||||
|
task = g_task_new (self, cancellable, callback, user_data);
|
||||||
|
gdbo_supplementary_services_call_respond (self->ussd, response, cancellable,
|
||||||
|
ussd_respond_cb, task);
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
calls_ofono_ussd_respond_finish (CallsUssd *ussd,
|
||||||
|
GAsyncResult *result,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (CALLS_IS_USSD (ussd), NULL);
|
||||||
|
g_return_val_if_fail (G_IS_TASK (result), NULL);
|
||||||
|
|
||||||
|
|
||||||
|
return g_task_propagate_pointer (G_TASK (result), error);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
calls_ofono_ussd_cancel_async (CallsUssd *ussd,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
CallsOfonoOrigin *self = CALLS_OFONO_ORIGIN (ussd);
|
||||||
|
GTask *task;
|
||||||
|
|
||||||
|
g_return_if_fail (CALLS_IS_USSD (ussd));
|
||||||
|
|
||||||
|
task = g_task_new (self, cancellable, callback, user_data);
|
||||||
|
gdbo_supplementary_services_call_cancel (self->ussd, cancellable,
|
||||||
|
ussd_cancel_cb, task);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
calls_ofono_ussd_cancel_finish (CallsUssd *ussd,
|
||||||
|
GAsyncResult *result,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (CALLS_IS_USSD (ussd), FALSE);
|
||||||
|
g_return_val_if_fail (G_IS_TASK (result), FALSE);
|
||||||
|
|
||||||
|
return g_task_propagate_boolean (G_TASK (result), error);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
dial_cb (GDBOVoiceCallManager *voice,
|
dial_cb (GDBOVoiceCallManager *voice,
|
||||||
GAsyncResult *res,
|
GAsyncResult *res,
|
||||||
@@ -479,6 +720,23 @@ voice_new_cb (GDBusConnection *connection,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
ussd_new_cb (GDBusConnection *connection,
|
||||||
|
GAsyncResult *res,
|
||||||
|
CallsOfonoOrigin *self)
|
||||||
|
{
|
||||||
|
g_autoptr (GError) error = NULL;
|
||||||
|
|
||||||
|
self->ussd = gdbo_supplementary_services_proxy_new_finish (res, &error);
|
||||||
|
if (!self->ussd) {
|
||||||
|
g_warning ("Error creating oFono"
|
||||||
|
" SupplementaryServices `%s' proxy: %s",
|
||||||
|
self->name, error->message);
|
||||||
|
CALLS_ERROR (self, error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
constructed (GObject *object)
|
constructed (GObject *object)
|
||||||
{
|
{
|
||||||
@@ -508,6 +766,14 @@ constructed (GObject *object)
|
|||||||
self);
|
self);
|
||||||
|
|
||||||
G_OBJECT_CLASS (calls_ofono_origin_parent_class)->constructed (object);
|
G_OBJECT_CLASS (calls_ofono_origin_parent_class)->constructed (object);
|
||||||
|
|
||||||
|
gdbo_supplementary_services_proxy_new (self->connection,
|
||||||
|
G_DBUS_PROXY_FLAGS_NONE,
|
||||||
|
g_dbus_proxy_get_name (modem_proxy),
|
||||||
|
g_dbus_proxy_get_object_path (modem_proxy),
|
||||||
|
NULL,
|
||||||
|
(GAsyncReadyCallback) ussd_new_cb,
|
||||||
|
self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -578,6 +844,19 @@ calls_ofono_origin_message_source_interface_init (CallsOriginInterface *iface)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
calls_ofono_origin_ussd_interface_init (CallsUssdInterface *iface)
|
||||||
|
{
|
||||||
|
iface->get_state = calls_ofono_ussd_get_state;
|
||||||
|
iface->initiate_async = calls_ofono_ussd_initiate_async;
|
||||||
|
iface->initiate_finish = calls_ofono_ussd_initiate_finish;
|
||||||
|
iface->respond_async = calls_ofono_ussd_respond_async;
|
||||||
|
iface->respond_finish = calls_ofono_ussd_respond_finish;
|
||||||
|
iface->cancel_async = calls_ofono_ussd_cancel_async;
|
||||||
|
iface->cancel_finish = calls_ofono_ussd_cancel_finish;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
calls_ofono_origin_origin_interface_init (CallsOriginInterface *iface)
|
calls_ofono_origin_origin_interface_init (CallsOriginInterface *iface)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
#define CALLS_OFONO_ORIGIN_H__
|
#define CALLS_OFONO_ORIGIN_H__
|
||||||
|
|
||||||
#include <libgdbofono/gdbo-modem.h>
|
#include <libgdbofono/gdbo-modem.h>
|
||||||
|
#include <libgdbofono/gdbo-ussd.h>
|
||||||
|
|
||||||
#include <glib-object.h>
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
|
|
||||||
gnome = import('gnome')
|
gnome = import('gnome')
|
||||||
dbus_interfaces = ['manager', 'modem', 'call']
|
dbus_interfaces = ['manager', 'modem', 'call', 'ussd']
|
||||||
|
|
||||||
gdbofono_src = []
|
gdbofono_src = []
|
||||||
gdbofono_headers = []
|
gdbofono_headers = []
|
||||||
|
|||||||
19
plugins/provider/ofono/libgdbofono/ussd.xml
Normal file
19
plugins/provider/ofono/libgdbofono/ussd.xml
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
|
||||||
|
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
|
||||||
|
<node>
|
||||||
|
|
||||||
|
<interface name="org.ofono.SupplementaryServices"><method name="Initiate"><arg name="command" type="s" direction="in"/>
|
||||||
|
<arg name="result_name" type="s" direction="out"/>
|
||||||
|
<arg name="value" type="v" direction="out"/>
|
||||||
|
</method><method name="Respond"><arg name="reply" type="s" direction="in"/>
|
||||||
|
<arg name="result" type="s" direction="out"/>
|
||||||
|
</method><method name="Cancel"></method><method name="GetProperties"><arg name="properties" type="a{sv}" direction="out"/>
|
||||||
|
</method><signal name="NotificationReceived"><arg name="message" type="s"/>
|
||||||
|
</signal>
|
||||||
|
<signal name="RequestReceived"><arg name="message" type="s"/>
|
||||||
|
</signal>
|
||||||
|
<signal name="PropertyChanged"><arg name="name" type="s"/>
|
||||||
|
<arg name="value" type="v"/>
|
||||||
|
</signal>
|
||||||
|
</interface>
|
||||||
|
</node>
|
||||||
Reference in New Issue
Block a user