* [PATCH 1/5] stk: Add agent registration and logic.
@ 2010-07-22 11:42 Andrzej Zaborowski
2010-07-22 11:42 ` [PATCH 2/5] stk: Add menu related utilities Andrzej Zaborowski
` (3 more replies)
0 siblings, 4 replies; 6+ messages in thread
From: Andrzej Zaborowski @ 2010-07-22 11:42 UTC (permalink / raw)
To: ofono
[-- Attachment #1: Type: text/plain, Size: 12175 bytes --]
This patch adds a skeleton that command implementations use in the
subsequent patches.
Icons and text attributes are not implemented in this series, I'll
send them separately. There are slight differences from
doc/stk-api.txt, for example org.ofono.Error.EndSession can be used
to terminate either a user-initiated or UICC-initiated session.
Should we change the ".Error" part to something like ".Navigation",
since these are not error conditions and may be confusing?
---
src/stk.c | 396 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 396 insertions(+), 0 deletions(-)
diff --git a/src/stk.c b/src/stk.c
index 556dc68..3ccb7e9 100644
--- a/src/stk.c
+++ b/src/stk.c
@@ -46,6 +46,28 @@ struct stk_timer {
time_t start;
};
+enum stk_agent_result {
+ STK_AGENT_RESULT_OK,
+ STK_AGENT_RESULT_BACK,
+ STK_AGENT_RESULT_TERMINATE,
+ STK_AGENT_RESULT_HELP,
+ STK_AGENT_RESULT_TIMEOUT,
+ STK_AGENT_RESULT_CANCEL,
+};
+
+struct stk_app_agent {
+ char *path;
+ char *bus;
+ DBusMessage *msg;
+ DBusPendingCall *call;
+ guint watch;
+ guint cmd_timeout;
+ void (*cmd_send)(struct ofono_stk *stk, DBusMessage *call);
+ void (*cmd_cb)(struct ofono_stk *stk, enum stk_agent_result result,
+ DBusMessage *reply);
+ struct ofono_stk *stk;
+};
+
struct ofono_stk {
const struct ofono_stk_driver *driver;
void *driver_data;
@@ -57,6 +79,10 @@ struct ofono_stk {
struct stk_timer timers[8];
guint timers_source;
+ int timeout;
+ int short_timeout;
+ struct stk_app_agent *primary_agent;
+ struct stk_app_agent *default_agent;
struct sms_submit_req *sms_submit_req;
char *idle_mode_text;
};
@@ -76,6 +102,10 @@ struct sms_submit_req {
#define ENVELOPE_RETRIES_DEFAULT 5
+#define OFONO_NAVIGATION_PREFIX OFONO_SERVICE ".Error"
+#define OFONO_NAVIGATION_GOBACK OFONO_NAVIGATION_PREFIX ".GoBack"
+#define OFONO_NAVIGATION_TERMINATED OFONO_NAVIGATION_PREFIX ".EndSession"
+
static void envelope_queue_run(struct ofono_stk *stk);
static void timers_update(struct ofono_stk *stk);
@@ -255,8 +285,361 @@ static DBusMessage *stk_get_properties(DBusConnection *conn,
return reply;
}
+static void app_agent_request_send_cancel(struct stk_app_agent *agent)
+{
+ DBusConnection *conn = ofono_dbus_get_connection();
+ DBusMessage *message;
+
+ message = dbus_message_new_method_call(agent->bus, agent->path,
+ OFONO_SIM_APP_INTERFACE,
+ "Cancel");
+ if (message == NULL)
+ return;
+
+ dbus_message_set_no_reply(message, TRUE);
+
+ g_dbus_send_message(conn, message);
+}
+
+static void app_agent_request_end(struct stk_app_agent *agent)
+{
+ agent->cmd_send = NULL;
+ agent->cmd_cb = NULL;
+
+ if (agent->cmd_timeout) {
+ g_source_remove(agent->cmd_timeout);
+ agent->cmd_timeout = 0;
+ }
+
+ if (agent->msg) {
+ dbus_message_unref(agent->msg);
+ agent->msg = NULL;
+ }
+
+ if (agent->call) {
+ dbus_pending_call_cancel(agent->call);
+ dbus_pending_call_unref(agent->call);
+ agent->call = NULL;
+ }
+}
+
+static void app_agent_request_cancel(struct stk_app_agent *agent)
+{
+ if (!agent->cmd_send)
+ return;
+
+ agent->cmd_cb(agent->stk, STK_AGENT_RESULT_CANCEL, NULL);
+
+ app_agent_request_end(agent);
+
+ app_agent_request_send_cancel(agent);
+}
+
+static void stk_agent_request_cancel(struct ofono_stk *stk)
+{
+ if (stk->primary_agent)
+ app_agent_request_cancel(stk->primary_agent);
+
+ if (stk->default_agent)
+ app_agent_request_cancel(stk->default_agent);
+}
+
+static gboolean app_agent_request_timeout(gpointer user_data)
+{
+ struct stk_app_agent *agent = user_data;
+
+ agent->cmd_timeout = 0;
+
+ agent->cmd_cb(agent->stk, STK_AGENT_RESULT_TIMEOUT, NULL);
+
+ app_agent_request_end(agent);
+
+ app_agent_request_send_cancel(agent);
+
+ return FALSE;
+}
+
+static void app_agent_request_terminate(struct stk_app_agent *agent)
+{
+ agent->cmd_cb(agent->stk, STK_AGENT_RESULT_TERMINATE, NULL);
+
+ app_agent_request_end(agent);
+}
+
+static void app_agent_remove(void *user_data)
+{
+ DBusConnection *conn = ofono_dbus_get_connection();
+ struct stk_app_agent *agent = user_data;
+
+ if (agent->watch) {
+ DBusMessage *message;
+
+ if (agent->cmd_cb) {
+ app_agent_request_terminate(agent);
+
+ app_agent_request_send_cancel(agent);
+ }
+
+ message = dbus_message_new_method_call(agent->bus, agent->path,
+ OFONO_SIM_APP_INTERFACE,
+ "Release");
+ if (message) {
+ dbus_message_set_no_reply(message, TRUE);
+
+ g_dbus_send_message(conn, message);
+ }
+
+ g_dbus_remove_watch(conn, agent->watch);
+ agent->watch = 0;
+ } else {
+ if (agent->cmd_cb)
+ app_agent_request_terminate(agent);
+ }
+
+ if (agent->stk->primary_agent == agent)
+ agent->stk->primary_agent = NULL;
+ if (agent->stk->default_agent == agent)
+ agent->stk->default_agent = NULL;
+
+ if (agent->remove_agent_source) {
+ g_source_remove(agent->remove_agent_source);
+ agent->remove_agent_source = 0;
+ }
+
+ g_free(agent->path);
+ g_free(agent->bus);
+ g_free(agent);
+}
+
+static gboolean app_agent_remove_cb(gpointer user_data)
+{
+ struct stk_app_agent *agent = user_data;
+
+ agent->remove_agent_source = 0;
+
+ app_agent_remove(user_data);
+
+ return FALSE;
+}
+
+static void app_agent_request_reply_handle(DBusPendingCall *call, void *data)
+{
+ struct stk_app_agent *agent = data;
+ DBusError err;
+ DBusMessage *reply = dbus_pending_call_steal_reply(call);
+ enum stk_agent_result result = STK_AGENT_RESULT_OK;
+
+ dbus_error_init(&err);
+ if (dbus_set_error_from_message(&err, reply)) {
+ ofono_error("SimAppAgent %s replied with error %s, %s",
+ agent->path, err.name, err.message);
+
+ if (g_str_has_prefix(err.name, OFONO_NAVIGATION_GOBACK))
+ result = STK_AGENT_RESULT_BACK;
+ else
+ result = STK_AGENT_RESULT_TERMINATE;
+
+ dbus_error_free(&err);
+ }
+
+ agent->cmd_cb(agent->stk, result, reply);
+
+ app_agent_request_end(agent);
+
+ dbus_message_unref(reply);
+
+ if (result != STK_AGENT_RESULT_TERMINATE)
+ return;
+
+ if (agent->stk->primary_agent != agent)
+ return;
+
+ app_agent_remove(agent);
+}
+
+static gboolean app_agent_request_send(struct stk_app_agent *agent)
+{
+ DBusConnection *conn = ofono_dbus_get_connection();
+
+ /*
+ * The cmd_send callback needs to set the method name to
+ * something different than "Cancel".
+ */
+ agent->msg = dbus_message_new_method_call(agent->bus, agent->path,
+ OFONO_SIM_APP_INTERFACE,
+ "Cancel");
+ if (agent->msg == NULL) {
+ ofono_error("Couldn't make a DBusMessage");
+ return FALSE;
+ }
+
+ agent->cmd_send(agent->stk, agent->msg);
+
+ if (dbus_connection_send_with_reply(conn,
+ agent->msg, &agent->call, INT_MAX) == FALSE ||
+ agent->call == NULL) {
+ dbus_message_unref(agent->msg);
+ agent->msg = NULL;
+
+ ofono_error("Couldn't send a method call");
+ return FALSE;
+ }
+
+ dbus_pending_call_set_notify(agent->call,
+ app_agent_request_reply_handle,
+ agent, NULL);
+
+ return TRUE;
+}
+
+static void app_agent_request_start(struct ofono_stk *stk,
+ void (*send)(struct ofono_stk *stk,
+ DBusMessage *call),
+ void (*cb)(struct ofono_stk *stk,
+ enum stk_agent_result result,
+ DBusMessage *reply),
+ int timeout)
+{
+ struct stk_app_agent *agent = stk->default_agent;
+
+ if (stk->primary_agent)
+ agent = stk->primary_agent;
+
+ if (agent == NULL) {
+ cb(stk, STK_AGENT_RESULT_TERMINATE, NULL);
+
+ return;
+ }
+
+ if (agent->cmd_cb)
+ app_agent_request_cancel(agent);
+
+ agent->cmd_send = send;
+ agent->cmd_cb = cb;
+
+ if (!app_agent_request_send(agent)) {
+ app_agent_request_terminate(agent);
+
+ return;
+ }
+
+ /* Use the timeout value specified in the command or the default. */
+ if (timeout == 0)
+ timeout = stk->timeout * 1000;
+
+ if (timeout < 0)
+ return;
+
+ agent->cmd_timeout = g_timeout_add(timeout, app_agent_request_timeout,
+ agent);
+}
+
+static void app_agent_disconnect_cb(DBusConnection *conn, void *user_data)
+{
+ struct stk_app_agent *agent = user_data;
+
+ ofono_debug("Agent exited without calling Unregister");
+
+ agent->watch = 0;
+
+ app_agent_remove(user_data);
+}
+
+static struct stk_app_agent *app_agent_create(struct ofono_stk *stk,
+ const char *path,
+ const char *sender)
+{
+ struct stk_app_agent *agent = g_try_new0(struct stk_app_agent, 1);
+ DBusConnection *conn = ofono_dbus_get_connection();
+
+ if (!agent)
+ return NULL;
+
+ agent->path = g_strdup(path);
+ agent->bus = g_strdup(sender);
+ agent->stk = stk;
+
+ agent->watch = g_dbus_add_disconnect_watch(conn, sender,
+ app_agent_disconnect_cb,
+ agent, NULL);
+
+ return agent;
+}
+
+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);
+
+ stk->default_agent = app_agent_create(stk, agent_path,
+ dbus_message_get_sender(msg));
+ if (!stk->default_agent)
+ return __ofono_error_failed(msg);
+
+ 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 (strcmp(stk->default_agent->path, agent_path))
+ return __ofono_error_failed(msg);
+ if (strcmp(stk->default_agent->bus, agent_bus))
+ return __ofono_error_failed(msg);
+
+ app_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->primary_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 NULL;
+}
+
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 +959,11 @@ 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->primary_agent) {
+ app_agent_remove(stk->primary_agent);
+ stk->primary_agent = NULL;
+ }
}
void ofono_stk_proactive_command_notify(struct ofono_stk *stk,
@@ -687,6 +1075,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->primary_agent)
+ app_agent_remove(stk->primary_agent);
+
+ if (stk->default_agent)
+ app_agent_remove(stk->default_agent);
+
if (stk->pending_cmd) {
stk_command_free(stk->pending_cmd);
stk->pending_cmd = NULL;
@@ -778,6 +1172,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();
}
--
1.7.1.86.g0e460.dirty
^ permalink raw reply related [flat|nested] 6+ messages in thread* [PATCH 2/5] stk: Add menu related utilities.
2010-07-22 11:42 [PATCH 1/5] stk: Add agent registration and logic Andrzej Zaborowski
@ 2010-07-22 11:42 ` Andrzej Zaborowski
2010-07-23 19:10 ` Denis Kenzior
2010-07-22 11:42 ` [PATCH 3/5] stk: Handle the main menu Andrzej Zaborowski
` (2 subsequent siblings)
3 siblings, 1 reply; 6+ messages in thread
From: Andrzej Zaborowski @ 2010-07-22 11:42 UTC (permalink / raw)
To: ofono
[-- Attachment #1: Type: text/plain, Size: 3586 bytes --]
---
src/stk.c | 104 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 104 insertions(+), 0 deletions(-)
diff --git a/src/stk.c b/src/stk.c
index 3ccb7e9..22cf99b 100644
--- a/src/stk.c
+++ b/src/stk.c
@@ -55,6 +55,17 @@ enum stk_agent_result {
STK_AGENT_RESULT_CANCEL,
};
+struct stk_menu {
+ char *title;
+ GSList *items;
+ struct stk_items_next_action_indicator next_action;
+ int default_item;
+ struct stk_text_attribute title_attr;
+ struct stk_item_text_attribute_list item_attrs;
+ gboolean soft_key;
+ gboolean has_help;
+};
+
struct stk_app_agent {
char *path;
char *bus;
@@ -247,6 +258,99 @@ static void stk_command_cb(const struct ofono_error *error, void *data)
DBG("TERMINAL RESPONSE to a command reported no errors");
}
+static struct stk_menu *stk_menu_create(const char *title,
+ const struct stk_text_attribute *title_attr, GSList *items,
+ const struct stk_item_text_attribute_list *item_attrs,
+ const struct stk_items_next_action_indicator *next_action,
+ int default_id, gboolean soft_key, gboolean has_help)
+{
+ struct stk_menu *ret = g_new(struct stk_menu, 1);
+ GSList *l;
+ int i;
+
+ ret->title = g_strdup(title ?: "");
+ ret->items = g_slist_copy((GSList *) items);
+ ret->default_item = -1;
+ memcpy(&ret->next_action, next_action, sizeof(ret->next_action));
+ memcpy(&ret->title_attr, title_attr, sizeof(ret->title_attr));
+ memcpy(&ret->item_attrs, item_attrs, sizeof(ret->item_attrs));
+ ret->soft_key = soft_key;
+ ret->has_help = has_help;
+
+ for (l = ret->items, i = 0; l; l = l->next, i++) {
+ struct stk_item *j = g_memdup(l->data, sizeof(*j));
+
+ j->text = g_strdup(j->text);
+ l->data = j;
+
+ if (j->id == default_id)
+ ret->default_item = i;
+ }
+
+ return ret;
+}
+
+static void stk_menu_free(struct stk_menu *menu)
+{
+ GSList *l;
+
+ for (l = menu->items; l; l = l->next) {
+ struct stk_item *i = l->data;
+
+ g_free(i->text);
+ g_free(i);
+ }
+
+ g_slist_free(menu->items);
+ g_free(menu->title);
+ g_free(menu);
+}
+
+static void append_menu_items(DBusMessageIter *iter, struct stk_menu *menu)
+{
+ DBusMessageIter variant, array, entry;
+ GSList *l;
+
+ dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
+ "a(sy)", &variant);
+
+ dbus_message_iter_open_container(&variant, DBUS_TYPE_ARRAY,
+ "(sy)", &array);
+
+ for (l = menu->items; l; l = l->next) {
+ struct stk_item *item = l->data;
+ unsigned char icon_id = 0;
+
+ dbus_message_iter_open_container(&array, DBUS_TYPE_STRUCT,
+ NULL, &entry);
+
+ dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING,
+ &item->text);
+ dbus_message_iter_append_basic(&entry, DBUS_TYPE_BYTE,
+ &icon_id);
+
+ dbus_message_iter_close_container(&array, &entry);
+ }
+
+ dbus_message_iter_close_container(&variant, &array);
+
+ dbus_message_iter_close_container(iter, &variant);
+}
+
+static void append_menu(DBusMessage *msg, struct stk_menu *menu)
+{
+ dbus_int16_t default_item = menu->default_item;
+ unsigned char icon_id = 0;
+ DBusMessageIter iter;
+
+ dbus_message_iter_init_append(msg, &iter);
+
+ dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &menu->title);
+ dbus_message_iter_append_basic(&iter, DBUS_TYPE_BYTE, &icon_id);
+ append_menu_items(&iter, menu);
+ dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT16, &default_item);
+}
+
static void stk_alpha_id_set(struct ofono_stk *stk, const char *text)
{
/* TODO */
--
1.7.1.86.g0e460.dirty
^ permalink raw reply related [flat|nested] 6+ messages in thread* Re: [PATCH 2/5] stk: Add menu related utilities.
2010-07-22 11:42 ` [PATCH 2/5] stk: Add menu related utilities Andrzej Zaborowski
@ 2010-07-23 19:10 ` Denis Kenzior
0 siblings, 0 replies; 6+ messages in thread
From: Denis Kenzior @ 2010-07-23 19:10 UTC (permalink / raw)
To: ofono
[-- Attachment #1: Type: text/plain, Size: 562 bytes --]
Hi Andrew,
> +static struct stk_menu *stk_menu_create(const char *title,
> + const struct stk_text_attribute *title_attr, GSList *items,
> + const struct stk_item_text_attribute_list *item_attrs,
> + const struct stk_items_next_action_indicator *next_action,
> + int default_id, gboolean soft_key, gboolean has_help)
> +{
I suggest breaking up this giant constructor with many arguments into
two functions. One that takes a setup_menu object and one that takes a
select_item object. Then fills in the items appropriately.
Regards,
-Denis
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 3/5] stk: Handle the main menu.
2010-07-22 11:42 [PATCH 1/5] stk: Add agent registration and logic Andrzej Zaborowski
2010-07-22 11:42 ` [PATCH 2/5] stk: Add menu related utilities Andrzej Zaborowski
@ 2010-07-22 11:42 ` Andrzej Zaborowski
2010-07-22 11:42 ` [PATCH 4/5] stk: Handle the Select Item proactive command Andrzej Zaborowski
2010-07-22 11:42 ` [PATCH 5/5] stk: Handle the Display Text " Andrzej Zaborowski
3 siblings, 0 replies; 6+ messages in thread
From: Andrzej Zaborowski @ 2010-07-22 11:42 UTC (permalink / raw)
To: ofono
[-- Attachment #1: Type: text/plain, Size: 7425 bytes --]
---
src/stk.c | 183 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 181 insertions(+), 2 deletions(-)
diff --git a/src/stk.c b/src/stk.c
index 22cf99b..17daa00 100644
--- a/src/stk.c
+++ b/src/stk.c
@@ -86,6 +86,7 @@ struct ofono_stk {
struct stk_command *pending_cmd;
void (*cancel_cmd)(struct ofono_stk *stk);
GQueue *envelope_q;
+ DBusMessage *pending;
struct stk_timer timers[8];
guint timers_source;
@@ -94,6 +95,8 @@ struct ofono_stk {
int short_timeout;
struct stk_app_agent *primary_agent;
struct stk_app_agent *default_agent;
+ struct stk_menu *main_menu;
+ gboolean in_session;
struct sms_submit_req *sms_submit_req;
char *idle_mode_text;
};
@@ -351,6 +354,65 @@ static void append_menu(DBusMessage *msg, struct stk_menu *menu)
dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT16, &default_item);
}
+static void emit_menu_changed(struct ofono_stk *stk)
+{
+ static struct stk_menu no_menu = {
+ .title = "",
+ .items = NULL,
+ .has_help = FALSE,
+ .default_item = -1,
+ };
+ DBusConnection *conn = ofono_dbus_get_connection();
+ const char *path = __ofono_atom_get_path(stk->atom);
+ struct stk_menu *menu = &no_menu;
+ DBusMessage *signal;
+ DBusMessageIter iter;
+ char *name = "MainMenu";
+
+ if (stk->main_menu && !stk->in_session)
+ menu = stk->main_menu;
+
+ ofono_dbus_signal_property_changed(conn, path,
+ OFONO_STK_INTERFACE,
+ "MainMenuTitle",
+ DBUS_TYPE_STRING, &menu->title);
+
+ signal = dbus_message_new_signal(path, OFONO_STK_INTERFACE,
+ "PropertyChanged");
+ if (!signal) {
+ ofono_error("Unable to allocate new %s.PropertyChanged signal",
+ OFONO_SIM_APP_INTERFACE);
+
+ return;
+ }
+
+ dbus_message_iter_init_append(signal, &iter);
+
+ dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &name);
+
+ append_menu_items(&iter, menu);
+
+ g_dbus_send_message(conn, signal);
+}
+
+static void dict_append_menu(DBusMessageIter *dict, struct stk_menu *menu)
+{
+ DBusMessageIter entry;
+ const char *key = "MainMenu";
+
+ ofono_dbus_dict_append(dict, "MainMenuTitle",
+ DBUS_TYPE_STRING, &menu->title);
+
+ dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY,
+ NULL, &entry);
+
+ dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
+
+ append_menu_items(&entry, menu);
+
+ dbus_message_iter_close_container(dict, &entry);
+}
+
static void stk_alpha_id_set(struct ofono_stk *stk, const char *text)
{
/* TODO */
@@ -384,6 +446,9 @@ static DBusMessage *stk_get_properties(DBusConnection *conn,
ofono_dbus_dict_append(&dict, "IdleModeText",
DBUS_TYPE_STRING, &idle_mode_text);
+ if (stk->main_menu && !stk->in_session)
+ dict_append_menu(&dict, stk->main_menu);
+
dbus_message_iter_close_container(&iter, &dict);
return reply;
@@ -717,14 +782,69 @@ static DBusMessage *stk_unregister_agent(DBusConnection *conn,
return dbus_message_new_method_return(msg);
}
+static void menu_selection_envelope_cb(struct ofono_stk *stk, gboolean ok,
+ const unsigned char *data, int len)
+{
+ unsigned char selection;
+ const char *agent_path;
+ DBusMessage *reply;
+
+ if (!ok) {
+ ofono_error("Sending Menu Selection to UICC failed");
+
+ reply = __ofono_error_failed(stk->pending);
+
+ goto out;
+ }
+
+ if (len)
+ ofono_error("Menu Selection returned %i bytes of unwanted data",
+ len);
+
+ DBG("Menu Selection envelope submission gave no error");
+
+ if (dbus_message_get_args(stk->pending, NULL,
+ DBUS_TYPE_BYTE, &selection,
+ DBUS_TYPE_OBJECT_PATH, &agent_path,
+ DBUS_TYPE_INVALID) == FALSE) {
+ reply = __ofono_error_failed(stk->pending);
+
+ goto out;
+ }
+
+ stk->primary_agent = app_agent_create(stk, agent_path,
+ dbus_message_get_sender(stk->pending));
+ if (!stk->primary_agent) {
+ reply = __ofono_error_failed(stk->pending);
+
+ goto out;
+ }
+
+ reply = dbus_message_new_method_return(stk->pending);
+
+ if (!stk->in_session) {
+ stk->in_session = TRUE;
+ emit_menu_changed(stk);
+ }
+
+out:
+ __ofono_dbus_pending_reply(&stk->pending, reply);
+}
+
static DBusMessage *stk_select_item(DBusConnection *conn,
DBusMessage *msg, void *data)
{
struct ofono_stk *stk = data;
const char *agent_path;
unsigned char selection;
+ struct stk_envelope e;
+ struct stk_menu *menu = stk->main_menu;
+ struct stk_item *item = NULL;
- if (stk->primary_agent)
+ if (stk->pending)
+ return __ofono_error_busy(msg);
+
+ if (stk->primary_agent || !menu)
return __ofono_error_busy(msg);
if (dbus_message_get_args(msg, NULL,
@@ -733,7 +853,20 @@ static DBusMessage *stk_select_item(DBusConnection *conn,
DBUS_TYPE_INVALID) == FALSE)
return __ofono_error_invalid_args(msg);
- /* TODO */
+ item = g_slist_nth_data(menu->items, selection);
+ if (!item)
+ return __ofono_error_invalid_format(msg);
+
+ memset(&e, 0, sizeof(e));
+ e.type = STK_ENVELOPE_TYPE_MENU_SELECTION;
+ e.src = STK_DEVICE_IDENTITY_TYPE_KEYPAD,
+ e.menu_selection.item_id = item->id;
+ e.menu_selection.help_request = FALSE;
+
+ if (stk_send_envelope(stk, &e, menu_selection_envelope_cb, 0))
+ return __ofono_error_failed(msg);
+
+ stk->pending = dbus_message_ref(msg);
return NULL;
}
@@ -1047,6 +1180,38 @@ static gboolean handle_command_poll_interval(const struct stk_command *cmd,
return TRUE;
}
+static gboolean handle_command_set_up_menu(const struct stk_command *cmd,
+ struct stk_response *rsp,
+ struct ofono_stk *stk)
+{
+ gboolean soft_key = (cmd->qualifier & (1 << 0)) != 0;
+ gboolean has_help = (cmd->qualifier & (1 << 7)) != 0;
+
+ if (stk->main_menu) {
+ stk_menu_free(stk->main_menu);
+ stk->main_menu = NULL;
+ }
+
+ if (cmd->setup_menu.items == NULL)
+ goto out;
+
+ stk->main_menu = stk_menu_create(cmd->setup_menu.alpha_id,
+ &cmd->setup_menu.text_attr,
+ cmd->setup_menu.items,
+ &cmd->setup_menu.item_text_attr_list,
+ &cmd->setup_menu.next_act,
+ 0, soft_key, has_help);
+
+ if (!stk->main_menu)
+ rsp->result.type = STK_RESULT_TYPE_DATA_NOT_UNDERSTOOD;
+
+out:
+ if (!stk->in_session)
+ emit_menu_changed(stk);
+
+ return TRUE;
+}
+
static void stk_proactive_command_cancel(struct ofono_stk *stk)
{
if (!stk->pending_cmd)
@@ -1068,6 +1233,11 @@ void ofono_stk_proactive_session_end_notify(struct ofono_stk *stk)
app_agent_remove(stk->primary_agent);
stk->primary_agent = NULL;
}
+
+ if (stk->in_session) {
+ stk->in_session = FALSE;
+ emit_menu_changed(stk);
+ }
}
void ofono_stk_proactive_command_notify(struct ofono_stk *stk,
@@ -1128,6 +1298,10 @@ void ofono_stk_proactive_command_notify(struct ofono_stk *stk,
respond = handle_command_poll_interval(stk->pending_cmd,
&rsp, stk);
break;
+ case STK_COMMAND_TYPE_SETUP_MENU:
+ respond = handle_command_set_up_menu(stk->pending_cmd,
+ &rsp, stk);
+ break;
}
if (respond)
@@ -1200,6 +1374,11 @@ static void stk_unregister(struct ofono_atom *atom)
stk->timers_source = 0;
}
+ if (stk->main_menu) {
+ stk_menu_free(stk->main_menu);
+ stk->main_menu = NULL;
+ }
+
g_queue_foreach(stk->envelope_q, (GFunc) g_free, NULL);
g_queue_free(stk->envelope_q);
--
1.7.1.86.g0e460.dirty
^ permalink raw reply related [flat|nested] 6+ messages in thread* [PATCH 4/5] stk: Handle the Select Item proactive command.
2010-07-22 11:42 [PATCH 1/5] stk: Add agent registration and logic Andrzej Zaborowski
2010-07-22 11:42 ` [PATCH 2/5] stk: Add menu related utilities Andrzej Zaborowski
2010-07-22 11:42 ` [PATCH 3/5] stk: Handle the main menu Andrzej Zaborowski
@ 2010-07-22 11:42 ` Andrzej Zaborowski
2010-07-22 11:42 ` [PATCH 5/5] stk: Handle the Display Text " Andrzej Zaborowski
3 siblings, 0 replies; 6+ messages in thread
From: Andrzej Zaborowski @ 2010-07-22 11:42 UTC (permalink / raw)
To: ofono
[-- Attachment #1: Type: text/plain, Size: 3730 bytes --]
---
src/stk.c | 115 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 114 insertions(+), 1 deletions(-)
diff --git a/src/stk.c b/src/stk.c
index 17daa00..563bedd 100644
--- a/src/stk.c
+++ b/src/stk.c
@@ -95,7 +95,7 @@ struct ofono_stk {
int short_timeout;
struct stk_app_agent *primary_agent;
struct stk_app_agent *default_agent;
- struct stk_menu *main_menu;
+ struct stk_menu *main_menu, *select_item_menu;
gboolean in_session;
struct sms_submit_req *sms_submit_req;
char *idle_mode_text;
@@ -1212,6 +1212,115 @@ out:
return TRUE;
}
+static void request_menu_send(struct ofono_stk *stk, DBusMessage *call)
+{
+ struct stk_menu *menu = stk->select_item_menu;
+
+ dbus_message_set_member(call, "RequestSelection");
+
+ append_menu(call, menu);
+}
+
+static void request_menu_cb(struct ofono_stk *stk,
+ enum stk_agent_result result,
+ DBusMessage *reply)
+{
+ enum stk_result_type type;
+ unsigned char selection;
+ struct stk_menu *menu = stk->select_item_menu;
+ struct stk_item *item = NULL;
+ struct stk_response rsp;
+ struct ofono_error error = { .type = OFONO_ERROR_TYPE_FAILURE };
+
+ switch (result) {
+ case STK_AGENT_RESULT_OK:
+ type = STK_RESULT_TYPE_SUCCESS;
+ break;
+
+ case STK_AGENT_RESULT_BACK:
+ type = STK_RESULT_TYPE_GO_BACK;
+ goto send;
+
+ case STK_AGENT_RESULT_TIMEOUT:
+ type = STK_RESULT_TYPE_NO_RESPONSE;
+ goto send;
+
+ case STK_AGENT_RESULT_TERMINATE:
+ default:
+ type = STK_RESULT_TYPE_USER_TERMINATED;
+ goto send;
+
+ case STK_AGENT_RESULT_CANCEL:
+ goto out;
+ }
+
+ if (dbus_message_get_args(reply, NULL,
+ DBUS_TYPE_BYTE, &selection,
+ DBUS_TYPE_INVALID) == FALSE) {
+ type = STK_RESULT_TYPE_USER_TERMINATED;
+
+ ofono_error("Can't parse the reply to SelectItem()");
+ goto send;
+ }
+
+ item = g_slist_nth_data(menu->items, selection);
+ if (!item) {
+ type = STK_RESULT_TYPE_USER_TERMINATED;
+ ofono_error("Invalid item selected");
+ }
+
+send:
+ memset(&rsp, 0, sizeof(rsp));
+ rsp.result.type = type;
+
+ if (item)
+ rsp.select_item.item_id = item->id;
+
+ if (stk_respond(stk, &rsp, stk_command_cb))
+ stk_command_cb(&error, stk);
+
+out:
+ stk_menu_free(menu);
+ stk->select_item_menu = NULL;
+}
+
+static gboolean handle_command_select_item(const struct stk_command *cmd,
+ struct stk_response *rsp,
+ struct ofono_stk *stk)
+{
+ gboolean soft_key = (cmd->qualifier & (1 << 2)) != 0;
+ gboolean has_help = (cmd->qualifier & (1 << 7)) != 0;
+
+ stk->select_item_menu = stk_menu_create(
+ cmd->select_item.alpha_id,
+ &cmd->select_item.text_attr,
+ cmd->select_item.items,
+ &cmd->select_item.item_text_attr_list,
+ &cmd->select_item.next_act,
+ cmd->select_item.item_id,
+ soft_key, has_help);
+
+ if (!stk->select_item_menu) {
+ rsp->result.type = STK_RESULT_TYPE_DATA_NOT_UNDERSTOOD;
+
+ return TRUE;
+ }
+
+ if (!stk->in_session) {
+ stk->in_session = TRUE;
+
+ if (stk->main_menu)
+ emit_menu_changed(stk);
+ }
+
+ app_agent_request_start(stk,
+ request_menu_send, request_menu_cb, 0);
+
+ stk->cancel_cmd = stk_agent_request_cancel;
+
+ return FALSE;
+}
+
static void stk_proactive_command_cancel(struct ofono_stk *stk)
{
if (!stk->pending_cmd)
@@ -1302,6 +1411,10 @@ void ofono_stk_proactive_command_notify(struct ofono_stk *stk,
respond = handle_command_set_up_menu(stk->pending_cmd,
&rsp, stk);
break;
+ case STK_COMMAND_TYPE_SELECT_ITEM:
+ respond = handle_command_select_item(stk->pending_cmd,
+ &rsp, stk);
+ break;
}
if (respond)
--
1.7.1.86.g0e460.dirty
^ permalink raw reply related [flat|nested] 6+ messages in thread* [PATCH 5/5] stk: Handle the Display Text proactive command.
2010-07-22 11:42 [PATCH 1/5] stk: Add agent registration and logic Andrzej Zaborowski
` (2 preceding siblings ...)
2010-07-22 11:42 ` [PATCH 4/5] stk: Handle the Select Item proactive command Andrzej Zaborowski
@ 2010-07-22 11:42 ` Andrzej Zaborowski
3 siblings, 0 replies; 6+ messages in thread
From: Andrzej Zaborowski @ 2010-07-22 11:42 UTC (permalink / raw)
To: ofono
[-- Attachment #1: Type: text/plain, Size: 5999 bytes --]
---
src/stk.c | 164 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
1 files changed, 158 insertions(+), 6 deletions(-)
diff --git a/src/stk.c b/src/stk.c
index 563bedd..f1717f0 100644
--- a/src/stk.c
+++ b/src/stk.c
@@ -77,6 +77,7 @@ struct stk_app_agent {
void (*cmd_cb)(struct ofono_stk *stk, enum stk_agent_result result,
DBusMessage *reply);
struct ofono_stk *stk;
+ guint remove_agent_source;
};
struct ofono_stk {
@@ -99,6 +100,7 @@ struct ofono_stk {
gboolean in_session;
struct sms_submit_req *sms_submit_req;
char *idle_mode_text;
+ gboolean session_ended;
};
struct envelope_op {
@@ -1321,6 +1323,125 @@ static gboolean handle_command_select_item(const struct stk_command *cmd,
return FALSE;
}
+static void request_text_send(struct ofono_stk *stk, DBusMessage *call)
+{
+ struct stk_command_display_text *dt = &stk->pending_cmd->display_text;
+ uint8_t qualifier = stk->pending_cmd->qualifier;
+ dbus_bool_t confirm = (qualifier & (1 << 7)) != 0;
+ dbus_bool_t priority = (qualifier & (1 << 0)) != 0;
+ unsigned char icon_id = 0;
+
+ dbus_message_set_member(call, "DisplayText");
+
+ dbus_message_append_args(call,
+ DBUS_TYPE_STRING, &dt->text,
+ DBUS_TYPE_BYTE, &icon_id,
+ DBUS_TYPE_BOOLEAN, &priority,
+ DBUS_TYPE_BOOLEAN, &confirm,
+ DBUS_TYPE_INVALID);
+}
+
+static void request_text_cb(struct ofono_stk *stk, enum stk_agent_result result,
+ DBusMessage *reply)
+{
+ gboolean confirm;
+ enum stk_result_type type = STK_RESULT_TYPE_SUCCESS;
+ struct stk_response rsp;
+ struct ofono_error error = { .type = OFONO_ERROR_TYPE_FAILURE };
+
+ /*
+ * Check if we have already responded to the proactive command
+ * because immediate response was requested.
+ */
+ if (!stk->pending_cmd || stk->pending_cmd->type !=
+ STK_COMMAND_TYPE_DISPLAY_TEXT ||
+ stk->pending_cmd->display_text.immediate_response) {
+ /*
+ * If session has ended in the meantime now is the time
+ * to go back to main menu or close the application
+ * window.
+ */
+ if (stk->session_ended && stk->primary_agent)
+ stk->primary_agent->remove_agent_source =
+ g_timeout_add(0, app_agent_remove_cb,
+ stk->primary_agent);
+
+ return;
+ }
+
+ switch (result) {
+ case STK_AGENT_RESULT_OK:
+ break;
+
+ case STK_AGENT_RESULT_BACK:
+ type = STK_RESULT_TYPE_GO_BACK;
+ goto send;
+
+ case STK_AGENT_RESULT_TIMEOUT:
+ confirm = (stk->pending_cmd->qualifier & (1 << 7)) != 0;
+ if (confirm)
+ type = STK_RESULT_TYPE_NO_RESPONSE;
+
+ goto send;
+
+ case STK_AGENT_RESULT_TERMINATE:
+ default:
+ type = STK_RESULT_TYPE_USER_TERMINATED;
+ goto send;
+
+ case STK_AGENT_RESULT_CANCEL:
+ return;
+ }
+
+ if (dbus_message_get_args(reply, NULL, DBUS_TYPE_INVALID) == FALSE) {
+ type = STK_RESULT_TYPE_USER_TERMINATED;
+
+ ofono_error("Reply not understood");
+ }
+
+send:
+ memset(&rsp, 0, sizeof(rsp));
+ rsp.result.type = type;
+
+ if (stk_respond(stk, &rsp, stk_command_cb))
+ stk_command_cb(&error, stk);
+}
+
+static gboolean handle_command_display_text(const struct stk_command *cmd,
+ struct stk_response *rsp,
+ struct ofono_stk *stk)
+{
+ int timeout = stk->short_timeout * 1000;
+
+ if (cmd->display_text.duration.interval) {
+ timeout = cmd->display_text.duration.interval;
+ switch (cmd->display_text.duration.unit) {
+ case STK_DURATION_TYPE_MINUTES:
+ timeout *= 60;
+ case STK_DURATION_TYPE_SECONDS:
+ timeout *= 10;
+ case STK_DURATION_TYPE_SECOND_TENTHS:
+ timeout *= 100;
+ }
+ }
+
+ if (!stk->in_session) {
+ stk->in_session = TRUE;
+
+ if (stk->main_menu)
+ emit_menu_changed(stk);
+ }
+
+ app_agent_request_start(stk,
+ request_text_send, request_text_cb, timeout);
+
+ stk->session_ended = FALSE;
+
+ stk->cancel_cmd = stk_agent_request_cancel;
+
+ return cmd->display_text.immediate_response;
+}
+
static void stk_proactive_command_cancel(struct ofono_stk *stk)
{
if (!stk->pending_cmd)
@@ -1338,15 +1459,42 @@ void ofono_stk_proactive_session_end_notify(struct ofono_stk *stk)
{
stk_proactive_command_cancel(stk);
- if (stk->primary_agent) {
- app_agent_remove(stk->primary_agent);
- stk->primary_agent = NULL;
- }
-
if (stk->in_session) {
stk->in_session = FALSE;
- emit_menu_changed(stk);
+
+ if (stk->main_menu)
+ emit_menu_changed(stk);
}
+
+ if (!stk->primary_agent)
+ return;
+
+ /*
+ * Go back to main menu, except when a DisplayText command has
+ * been issued with the Immediate Response flag set (TS 102.223
+ * Section 6.9):
+ * "If the text is to be sustained, the terminal shall display
+ * the text of applicable DISPLAY TEXT commands beyond the sending
+ * of the TERMINAL RESPONSE and possibly beyond the end of the
+ * proactive session.
+ *
+ * If a variable display timeout was indicated for a DISPLAY TEXT
+ * command, then the session releases the display back into terminal
+ * control no later then the period stated by the duration. If the
+ * text is to be sustained beyond an immediate response, the
+ * terminal shall display the text for a period that does not
+ * exceed the duration."
+ *
+ * For this case we set a flag and when the text stops being
+ * displayed we will make sure to go to main menu then.
+ */
+ if (!stk->pending_cmd && stk->primary_agent->cmd_cb) {
+ stk->session_ended = TRUE;
+
+ return;
+ }
+
+ app_agent_remove(stk->primary_agent);
}
void ofono_stk_proactive_command_notify(struct ofono_stk *stk,
@@ -1415,6 +1563,10 @@ void ofono_stk_proactive_command_notify(struct ofono_stk *stk,
respond = handle_command_select_item(stk->pending_cmd,
&rsp, stk);
break;
+ case STK_COMMAND_TYPE_DISPLAY_TEXT:
+ respond = handle_command_display_text(stk->pending_cmd,
+ &rsp, stk);
+ break;
}
if (respond)
--
1.7.1.86.g0e460.dirty
^ permalink raw reply related [flat|nested] 6+ messages in thread
end of thread, other threads:[~2010-07-23 19:10 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-07-22 11:42 [PATCH 1/5] stk: Add agent registration and logic Andrzej Zaborowski
2010-07-22 11:42 ` [PATCH 2/5] stk: Add menu related utilities Andrzej Zaborowski
2010-07-23 19:10 ` Denis Kenzior
2010-07-22 11:42 ` [PATCH 3/5] stk: Handle the main menu Andrzej Zaborowski
2010-07-22 11:42 ` [PATCH 4/5] stk: Handle the Select Item proactive command Andrzej Zaborowski
2010-07-22 11:42 ` [PATCH 5/5] stk: Handle the Display Text " Andrzej Zaborowski
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.