---
 src/stk.c |  255 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 244 insertions(+), 11 deletions(-)

diff --git a/src/stk.c b/src/stk.c
index b752e49..cf28a96 100644
--- a/src/stk.c
+++ b/src/stk.c
@@ -77,6 +77,7 @@ struct ofono_stk {
 
        struct stk_menu *default_menu;
        struct stk_menu *current_menu; /* For Select Item menus */
+       const char *display_text;
        int timeout;
 };
 
@@ -355,6 +356,8 @@ static void emit_menu_changed(struct ofono_stk *stk)
                menu = stk->default_menu;
        if (stk->current_menu)
                menu = stk->current_menu;
+       if (stk->display_text)
+               menu = &no_menu;
 
        if (stk->cmd_timeout && stk->current_menu)
                ofono_dbus_signal_property_changed(conn, path,
@@ -425,6 +428,78 @@ static gboolean select_item_timeout(gpointer user_data)
        return FALSE;
 }
 
+static void emit_text_changed(struct ofono_stk *stk)
+{
+       DBusConnection *conn = ofono_dbus_get_connection();
+       const char *path = __ofono_atom_get_path(stk->atom);
+       dbus_uint16_t timeout = stk->timeout;
+       const char *text = stk->display_text ?: "";
+       dbus_bool_t boolval;
+
+       if (stk->cmd_timeout && stk->display_text)
+               ofono_dbus_signal_property_changed(conn, path,
+                                               OFONO_SIM_APP_INTERFACE,
+                                               "Timeout",
+                                               DBUS_TYPE_UINT16, &timeout);
+
+       ofono_dbus_signal_property_changed(conn, path,
+                                               OFONO_SIM_APP_INTERFACE,
+                                               "Message", DBUS_TYPE_STRING,
+                                               &text);
+
+       boolval = stk->display_text &&
+               (stk->pending_cmd->qualifier & (1 << 7)) != 0;
+       ofono_dbus_signal_property_changed(conn, path,
+                                               OFONO_SIM_APP_INTERFACE,
+                                               "UserConfirmMessage",
+                                               DBUS_TYPE_BOOLEAN, &boolval);
+
+       boolval = stk->display_text &&
+               (stk->pending_cmd->qualifier & (1 << 0)) != 0;
+       ofono_dbus_signal_property_changed(conn, path,
+                                               OFONO_SIM_APP_INTERFACE,
+                                               "PriorityMessage",
+                                               DBUS_TYPE_BOOLEAN, &boolval);
+}
+
+static gboolean display_text_timeout(gpointer user_data)
+{
+       struct ofono_stk *stk = user_data;
+       struct stk_response rsp;
+
+       stk->cmd_timeout = 0;
+
+       if (stk->pending)
+               /* A command is currently executing, do nothing.  */
+               return FALSE;
+
+       ofono_debug("Display Text command timed out");
+
+       stk->display_text = NULL;
+
+       if (stk->pending_cmd->display_text.immediate_response == TRUE) {
+               /* Already responded */
+               stk_command_free(stk->pending_cmd);
+               stk->pending_cmd = NULL;
+
+               return FALSE;
+       }
+
+       memset(&rsp, 0, sizeof(rsp));
+       if (stk->pending_cmd->qualifier & (1 << 7))
+               rsp.result.type = STK_RESULT_TYPE_NO_RESPONSE;
+
+       stk_respond(stk, &rsp, stk_command_cb);
+
+       emit_text_changed(stk);
+
+       /* If manu was overridden by text, now re-show it */
+       if (stk->default_menu)
+               emit_menu_changed(stk);
+
+       return FALSE;
+}
+
 static DBusMessage *stk_get_properties(DBusConnection *conn,
                                        DBusMessage *msg, void *data)
 {
@@ -440,6 +515,8 @@ static DBusMessage *stk_get_properties(DBusConnection *conn,
 
        if (stk->current_menu)
                menu = stk->current_menu;
+       if (stk->display_text)
+               menu = NULL;
 
        reply = dbus_message_new_method_return(msg);
        if (!reply)
@@ -451,13 +528,26 @@ static DBusMessage *stk_get_properties(DBusConnection 
*conn,
                                        OFONO_PROPERTIES_ARRAY_SIGNATURE,
                                        &dict);
 
-       if (!menu)
-               goto done;
-
-       if (stk->cmd_timeout && stk->current_menu)
+       if (stk->cmd_timeout && (stk->current_menu || stk->display_text))
                ofono_dbus_dict_append(&dict, "Timeout",
                                        DBUS_TYPE_UINT16, &timeout);
 
+       if (stk->display_text) {
+               ofono_dbus_dict_append(&dict, "Message",
+                                       DBUS_TYPE_STRING, &stk->display_text);
+
+               boolval = (stk->pending_cmd->qualifier & (1 << 7)) != 0;
+               ofono_dbus_dict_append(&dict, "UserConfirmMessage",
+                                       DBUS_TYPE_BOOLEAN, &boolval);
+
+               boolval = (stk->pending_cmd->qualifier & (1 << 0)) != 0;
+               ofono_dbus_dict_append(&dict, "PriorityMessage",
+                                       DBUS_TYPE_BOOLEAN, &boolval);
+       }
+
+       if (!menu)
+               goto done;
+
        items = stk_menu_items_strlist(menu);
        ofono_dbus_dict_append_array(&dict, "MenuItems",
                                        DBUS_TYPE_STRING, &items);
@@ -511,7 +601,7 @@ static DBusMessage *stk_set_property(DBusConnection *conn,
 
        dbus_message_iter_recurse(&iter, &var);
 
-       if (stk->cmd_timeout && stk->current_menu &&
+       if (stk->cmd_timeout && (stk->current_menu && stk->display_text) &&
                        !strcmp(property, "Timeout")) {
                if (dbus_message_iter_get_arg_type(&var) != DBUS_TYPE_UINT16)
                        return __ofono_error_invalid_args(msg);
@@ -522,10 +612,18 @@ static DBusMessage *stk_set_property(DBusConnection *conn,
 
                stk->timeout = timeout;
 
-               g_source_remove(stk->cmd_timeout);
-               stk->cmd_timeout = g_timeout_add_seconds(stk->timeout,
+               if (stk->current_menu) {
+                       g_source_remove(stk->cmd_timeout);
+                       stk->cmd_timeout = g_timeout_add_seconds(stk->timeout,
                                                        select_item_timeout,
                                                        stk);
+               } else if (stk->display_text && stk->pending_cmd->display_text.
+                               duration.interval == 0) {
+                       g_source_remove(stk->cmd_timeout);
+                       stk->cmd_timeout = g_timeout_add_seconds(stk->timeout,
+                                                       display_text_timeout,
+                                                       stk);
+               }
 
                ofono_dbus_signal_property_changed(conn, path,
                                                OFONO_SIM_APP_INTERFACE,
@@ -562,6 +660,37 @@ static void select_item_cancel(struct ofono_stk *stk)
        emit_menu_changed(stk);
 }
 
+static void display_text_cancel(struct ofono_stk *stk)
+{
+       if (stk->pending)
+               stk->cancelled = TRUE;
+
+       if (stk->cmd_timeout) {
+               g_source_remove(stk->cmd_timeout);
+               stk->cmd_timeout = 0;
+       }
+
+       stk->display_text = NULL;
+
+       stk_command_free(stk->pending_cmd);
+       stk->pending_cmd = NULL;
+
+       emit_text_changed(stk);
+       emit_menu_changed(stk);
+}
+
+static void display_text_immediate_cb(const struct ofono_error *error,
+                                       struct ofono_stk *stk)
+{
+       if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
+               ofono_error("TERMINAL RESPONSE to Display Text failed: %s",
+                               telephony_error_to_str(error));
+               return;
+       }
+
+       DBG("TERMINAL RESPONSE to Display Text reported no errors");
+}
+
 static void select_item_cb(const struct ofono_error *error,
                                struct ofono_stk *stk)
 {
@@ -591,7 +720,7 @@ static void select_item_cb(const struct ofono_error *error,
        emit_menu_changed(stk);
 
 out:
-       if (error->type == OFONO_ERROR_TYPE_NO_ERROR)
+       if (error->type != OFONO_ERROR_TYPE_NO_ERROR)
                reply = __ofono_error_failed(stk->pending);
        else
                reply = dbus_message_new_method_return(stk->pending);
@@ -657,6 +786,8 @@ static DBusMessage *stk_menu_select(DBusConnection *conn, 
DBusMessage *msg,
 
        if (stk->pending)
                return __ofono_error_busy(msg);
+       if (stk->pending_cmd && !stk->current_menu)
+               return __ofono_error_busy(msg);
 
        if (!dbus_message_iter_init(msg, &iter))
                return __ofono_error_invalid_args(msg);
@@ -705,6 +836,47 @@ static DBusMessage *stk_get_help(DBusConnection *conn,
        return stk_menu_select(conn, msg, data, TRUE);
 }
 
+static void display_text_cb(const struct ofono_error *error,
+                               struct ofono_stk *stk)
+{
+       DBusMessage *reply;
+
+       if (stk->cancelled == TRUE)
+               /* Command cancelled */
+               goto out;
+
+       if (stk->cmd_timeout) {
+               /*
+                * If the command has not timed out yet, return error and
+                * the user may then retry the command.  Otherwise assume
+                * the text is no longer valid.
+                */
+               if (error->type != OFONO_ERROR_TYPE_NO_ERROR)
+                       goto out;
+
+               g_source_remove(stk->cmd_timeout);
+       }
+
+       stk->display_text = NULL;
+
+       if (error)
+               stk_command_cb(error, stk);
+
+       emit_text_changed(stk);
+       emit_menu_changed(stk);
+
+out:
+       if (!error)
+               return;
+
+       if (error->type != OFONO_ERROR_TYPE_NO_ERROR)
+               reply = __ofono_error_failed(stk->pending);
+       else
+               reply = dbus_message_new_method_return(stk->pending);
+
+       __ofono_dbus_pending_reply(&stk->pending, reply);
+}
+
 static DBusMessage *stk_back_or_terminate(DBusConnection *conn,
                                        DBusMessage *msg, void *data,
                                        enum stk_result_type type)
@@ -716,19 +888,34 @@ static DBusMessage *stk_back_or_terminate(DBusConnection 
*conn,
        if (stk->pending)
                return __ofono_error_busy(msg);
 
-       if (!stk->current_menu)
+       if (!stk->current_menu && !stk->display_text)
                return __ofono_error_failed(msg);
 
        if (dbus_message_iter_init(msg, &iter))
                return __ofono_error_invalid_args(msg);
 
        stk->cancelled = FALSE;
-       stk->pending = dbus_message_ref(msg);
 
        memset(&rsp, 0, sizeof(rsp));
        rsp.result.type = type;
 
-       stk_respond(stk, &rsp, select_item_cb);
+       if (stk->current_menu) {
+               stk->pending = dbus_message_ref(msg);
+
+               stk_respond(stk, &rsp, select_item_cb);
+       } else if (stk->display_text) {
+               if (stk->pending_cmd->display_text.immediate_response == TRUE) {
+                       if (type != STK_RESULT_TYPE_SUCCESS)
+                               return __ofono_error_failed(msg);
+
+                       display_text_cb(NULL, stk);
+                       return dbus_message_new_method_return(msg);
+               }
+
+               stk->pending = dbus_message_ref(msg);
+
+               stk_respond(stk, &rsp, display_text_cb);
+       }
 
        return NULL;
 }
@@ -747,6 +934,13 @@ static DBusMessage *stk_end_session(DBusConnection *conn,
                                        STK_RESULT_TYPE_USER_TERMINATED);
 }
 
+static DBusMessage *stk_confirm(DBusConnection *conn,
+                               DBusMessage *msg, void *data)
+{
+       return stk_back_or_terminate(conn, msg, data,
+                                       STK_RESULT_TYPE_SUCCESS);
+}
+
 static GDBusMethodTable stk_methods[] = {
        { "GetProperties",      "",     "a{sv}",        stk_get_properties },
        { "SetProperty",        "sv",   "",             stk_set_property },
@@ -758,6 +952,8 @@ static GDBusMethodTable stk_methods[] = {
                                G_DBUS_METHOD_FLAG_ASYNC },
        { "EndSession",         "",     "",             stk_end_session,
                                G_DBUS_METHOD_FLAG_ASYNC },
+       { "Confirm",            "",     "",             stk_confirm,
+                               G_DBUS_METHOD_FLAG_ASYNC },
        { }
 };
 
@@ -829,6 +1025,41 @@ out:
        return TRUE;
 }
 
+static gboolean handle_command_display_text(const struct stk_command *cmd,
+                                               struct stk_response *rsp,
+                                               struct ofono_stk *stk)
+{
+       int timeout = stk->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;
+               }
+       }
+
+       stk->display_text = cmd->display_text.text;
+
+       /* May need to hide the menu to display the message */
+       if (stk->default_menu)
+               emit_menu_changed(stk);
+
+       emit_text_changed(stk);
+
+       stk->cmd_timeout = g_timeout_add(timeout, display_text_timeout, stk);
+       stk->cancel_cmd = display_text_cancel;
+
+       if (cmd->display_text.immediate_response == TRUE)
+               stk_respond(stk, rsp, display_text_immediate_cb);
+
+       return FALSE;
+}
+
 int ofono_stk_driver_register(const struct ofono_stk_driver *d)
 {
        DBG("driver: %p, name: %s", d, d->name);
@@ -934,6 +1165,8 @@ struct ofono_stk *ofono_stk_create(struct ofono_modem 
*modem,
                                        handle_command_select_item);
        stk_command_handler_register(stk, STK_COMMAND_TYPE_SETUP_MENU,
                                        handle_command_set_up_menu);
+       stk_command_handler_register(stk, STK_COMMAND_TYPE_DISPLAY_TEXT,
+                                       handle_command_display_text);
 
        return stk;
 }
-- 
1.7.1.86.g0e460.dirty

_______________________________________________
ofono mailing list
[email protected]
http://lists.ofono.org/listinfo/ofono

Reply via email to