diff options
Diffstat (limited to 'src/stk.c')
-rw-r--r-- | src/stk.c | 149 |
1 files changed, 149 insertions, 0 deletions
@@ -38,6 +38,7 @@ #include "common.h" #include "smsutil.h" #include "stkutil.h" +#include "stkagent.h" static GSList *g_drivers = NULL; @@ -57,6 +58,12 @@ struct ofono_stk { struct stk_timer timers[8]; guint timers_source; + int timeout; + int short_timeout; + guint remove_agent_source; + struct stk_agent *session_agent; + struct stk_agent *default_agent; + struct stk_agent *current_agent; /* Always equals one of the above */ struct sms_submit_req *sms_submit_req; char *idle_mode_text; }; @@ -255,8 +262,139 @@ static DBusMessage *stk_get_properties(DBusConnection *conn, return reply; } +static void stk_request_cancel(struct ofono_stk *stk) +{ + if (stk->session_agent) + stk_agent_request_cancel(stk->session_agent); + + if (stk->default_agent) + stk_agent_request_cancel(stk->default_agent); +} + +static void default_agent_notify(gpointer user_data) +{ + struct ofono_stk *stk = user_data; + + stk->default_agent = NULL; + + stk->current_agent = stk->session_agent; +} + +static void session_agent_notify(gpointer user_data) +{ + struct ofono_stk *stk = user_data; + + stk->session_agent = NULL; + + stk->current_agent = stk->default_agent; + + if (stk->remove_agent_source) { + g_source_remove(stk->remove_agent_source); + stk->remove_agent_source = 0; + } +} + +static gboolean session_agent_remove_cb(gpointer user_data) +{ + struct ofono_stk *stk = user_data; + + stk->remove_agent_source = 0; + + stk_agent_remove(stk->session_agent); + + return FALSE; +} + +/* Safely remove the agent even inside a callback */ +static void session_agent_remove(struct ofono_stk *stk) +{ + if (!stk->remove_agent_source) + stk->remove_agent_source = + g_timeout_add(0, session_agent_remove_cb, stk); +} + +static DBusMessage *stk_register_agent(DBusConnection *conn, + DBusMessage *msg, void *data) +{ + struct ofono_stk *stk = data; + const char *agent_path; + + if (stk->default_agent) + return __ofono_error_busy(msg); + + if (dbus_message_get_args(msg, NULL, + DBUS_TYPE_OBJECT_PATH, &agent_path, + DBUS_TYPE_INVALID) == FALSE) + return __ofono_error_invalid_args(msg); + + if (!__ofono_dbus_valid_object_path(agent_path)) + return __ofono_error_invalid_format(msg); + + stk->default_agent = stk_agent_new(agent_path, + dbus_message_get_sender(msg), + TRUE); + if (!stk->default_agent) + return __ofono_error_failed(msg); + + stk_agent_set_destroy_watch(stk->default_agent, + default_agent_notify, stk); + + if (!stk->session_agent) + stk->current_agent = stk->default_agent; + + return dbus_message_new_method_return(msg); +} + +static DBusMessage *stk_unregister_agent(DBusConnection *conn, + DBusMessage *msg, void *data) +{ + struct ofono_stk *stk = data; + const char *agent_path; + const char *agent_bus = dbus_message_get_sender(msg); + + if (dbus_message_get_args(msg, NULL, + DBUS_TYPE_OBJECT_PATH, &agent_path, + DBUS_TYPE_INVALID) == FALSE) + return __ofono_error_invalid_args(msg); + + if (!stk->default_agent) + return __ofono_error_failed(msg); + + if (!stk_agent_matches(stk->default_agent, agent_path, agent_bus)) + return __ofono_error_failed(msg); + + stk_agent_remove(stk->default_agent); + + return dbus_message_new_method_return(msg); +} + +static DBusMessage *stk_select_item(DBusConnection *conn, + DBusMessage *msg, void *data) +{ + struct ofono_stk *stk = data; + const char *agent_path; + unsigned char selection; + + if (stk->session_agent) + return __ofono_error_busy(msg); + + if (dbus_message_get_args(msg, NULL, + DBUS_TYPE_BYTE, &selection, + DBUS_TYPE_OBJECT_PATH, &agent_path, + DBUS_TYPE_INVALID) == FALSE) + return __ofono_error_invalid_args(msg); + + /* TODO */ + + return __ofono_error_not_implemented(msg); +} + static GDBusMethodTable stk_methods[] = { { "GetProperties", "", "a{sv}",stk_get_properties }, + { "SelectItem", "yo", "", stk_select_item, + G_DBUS_METHOD_FLAG_ASYNC }, + { "RegisterAgent", "o", "", stk_register_agent }, + { "UnregisterAgent", "o", "", stk_unregister_agent }, { } }; @@ -576,6 +714,9 @@ static void stk_proactive_command_cancel(struct ofono_stk *stk) void ofono_stk_proactive_session_end_notify(struct ofono_stk *stk) { stk_proactive_command_cancel(stk); + + if (stk->session_agent) + stk_agent_remove(stk->session_agent); } void ofono_stk_proactive_command_notify(struct ofono_stk *stk, @@ -687,6 +828,12 @@ static void stk_unregister(struct ofono_atom *atom) struct ofono_modem *modem = __ofono_atom_get_modem(atom); const char *path = __ofono_atom_get_path(atom); + if (stk->session_agent) + stk_agent_remove(stk->session_agent); + + if (stk->default_agent) + stk_agent_remove(stk->default_agent); + if (stk->pending_cmd) { stk_command_free(stk->pending_cmd); stk->pending_cmd = NULL; @@ -778,6 +925,8 @@ void ofono_stk_register(struct ofono_stk *stk) __ofono_atom_register(stk->atom, stk_unregister); + stk->timeout = 600; /* 10 minutes */ + stk->short_timeout = 20; /* 20 seconds */ stk->envelope_q = g_queue_new(); } |