---
 src/ussd.c |  125 ++++++++++++++++++++++++++++++++++++++++++++++++++++--------
 1 files changed, 109 insertions(+), 16 deletions(-)

diff --git a/src/ussd.c b/src/ussd.c
index 825d560..1441044 100644
--- a/src/ussd.c
+++ b/src/ussd.c
@@ -34,6 +34,7 @@
 #include "ofono.h"
 
 #include "common.h"
+#include "smsutil.h"
 
 #define SUPPLEMENTARY_SERVICES_INTERFACE "org.ofono.SupplementaryServices"
 
@@ -46,6 +47,15 @@ enum ussd_state {
        USSD_STATE_RESPONSE_SENT,
 };
 
+struct ussd_request {
+       struct ofono_ussd *ussd;
+       int dcs;
+       unsigned char *str;
+       int str_len;
+       ofono_ussd_request_cb_t cb;
+       void *user_data;
+};
+
 struct ofono_ussd {
        int state;
        DBusMessage *pending;
@@ -56,6 +66,7 @@ struct ofono_ussd {
        const struct ofono_ussd_driver *driver;
        void *driver_data;
        struct ofono_atom *atom;
+       struct ussd_request *req;
 };
 
 struct ssc_entry {
@@ -306,15 +317,55 @@ static void ussd_change_state(struct ofono_ussd *ussd, 
int state)
                        "State", DBUS_TYPE_STRING, &value);
 }
 
-void ofono_ussd_notify(struct ofono_ussd *ussd, int status, const char *str)
+static void ussd_request_finish(struct ofono_ussd *ussd, int error, int dcs,
+                                const unsigned char *str, int str_len)
+{
+       struct ussd_request *req = ussd->req;
+
+       if (req && req->cb){
+               req->cb(error, dcs, str, str_len, req->user_data);
+               g_free(req->str);
+               g_free(req);
+               ussd->req = NULL;
+       }
+}
+
+static int ussd_status_to_failure_code(int status)
+{
+       switch (status) {
+       case OFONO_USSD_STATUS_TIMED_OUT:
+               return OFONO_USSD_FAILURE_TIMED_OUT;
+       case OFONO_USSD_STATUS_NOT_SUPPORTED:
+               return OFONO_USSD_FAILURE_RETURN_ERROR;
+       }
+
+       return OFONO_USSD_FAILURE_NONE;
+}
+
+void ofono_ussd_notify(struct ofono_ussd *ussd, int status, int dcs,
+                       const unsigned char *str, int str_len)
 {
        DBusConnection *conn = ofono_dbus_get_connection();
        const char *ussdstr = "USSD";
+       const char *utf8_str = NULL;
        const char sig[] = { DBUS_TYPE_STRING, 0 };
        DBusMessage *reply;
        DBusMessageIter iter;
        DBusMessageIter variant;
 
+       if (ussd->req &&
+               (status == OFONO_USSD_STATUS_NOTIFY ||
+               status == OFONO_USSD_STATUS_TERMINATED ||
+               status == OFONO_USSD_STATUS_TIMED_OUT ||
+               status == OFONO_USSD_STATUS_NOT_SUPPORTED)){
+
+               ussd_request_finish(ussd, ussd_status_to_failure_code(status),
+                                   dcs, str, str_len);
+
+               ussd_change_state(ussd, USSD_STATE_IDLE);
+               return;
+       }
+
        if (status == OFONO_USSD_STATUS_NOT_SUPPORTED) {
                ussd_change_state(ussd, USSD_STATE_IDLE);
 
@@ -335,14 +386,13 @@ void ofono_ussd_notify(struct ofono_ussd *ussd, int 
status, const char *str)
                goto out;
        }
 
+       utf8_str = str ? ussd_decode(dcs, str_len, str) : "";
+
        /* TODO: Rework this in the Agent framework */
        if (ussd->state == USSD_STATE_ACTIVE) {
 
                reply = dbus_message_new_method_return(ussd->pending);
 
-               if (!str)
-                       str = "";
-
                dbus_message_iter_init_append(reply, &iter);
 
                dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING,
@@ -352,7 +402,7 @@ void ofono_ussd_notify(struct ofono_ussd *ussd, int status, 
const char *str)
                                                        &variant);
 
                dbus_message_iter_append_basic(&variant, DBUS_TYPE_STRING,
-                                               &str);
+                                       &utf8_str);
 
                dbus_message_iter_close_container(&iter, &variant);
 
@@ -364,11 +414,8 @@ void ofono_ussd_notify(struct ofono_ussd *ussd, int 
status, const char *str)
        } else if (ussd->state == USSD_STATE_RESPONSE_SENT) {
                reply = dbus_message_new_method_return(ussd->pending);
 
-               if (!str)
-                       str = "";
-
-               dbus_message_append_args(reply, DBUS_TYPE_STRING, &str,
-                                               DBUS_TYPE_INVALID);
+               dbus_message_append_args(reply, DBUS_TYPE_STRING, &utf8_str,
+                               DBUS_TYPE_INVALID);
 
                if (status == OFONO_USSD_STATUS_ACTION_REQUIRED)
                        ussd_change_state(ussd, USSD_STATE_USER_ACTION);
@@ -387,9 +434,6 @@ void ofono_ussd_notify(struct ofono_ussd *ussd, int status, 
const char *str)
                        signal_name = "NotificationReceived";
                }
 
-               if (!str)
-                       str = "";
-
                g_dbus_emit_signal(conn, path,
                                SUPPLEMENTARY_SERVICES_INTERFACE, signal_name,
                                DBUS_TYPE_STRING, &str, DBUS_TYPE_INVALID);
@@ -436,6 +480,8 @@ static DBusMessage *ussd_initiate(DBusConnection *conn, 
DBusMessage *msg,
 {
        struct ofono_ussd *ussd = data;
        const char *str;
+       int dcs = -1;
+
 
        if (ussd->pending)
                return __ofono_error_busy(msg);
@@ -465,7 +511,8 @@ static DBusMessage *ussd_initiate(DBusConnection *conn, 
DBusMessage *msg,
 
        ussd->pending = dbus_message_ref(msg);
 
-       ussd->driver->request(ussd, str, ussd_callback, ussd);
+       ussd->driver->request(ussd, dcs, (const guint8*) str, strlen(str), 
+                          ussd_callback, ussd);
 
        return NULL;
 }
@@ -496,6 +543,7 @@ static DBusMessage *ussd_respond(DBusConnection *conn, 
DBusMessage *msg,
 {
        struct ofono_ussd *ussd = data;
        const char *str;
+       int dcs = -1;
 
        if (ussd->pending)
                return __ofono_error_busy(msg);
@@ -515,7 +563,8 @@ static DBusMessage *ussd_respond(DBusConnection *conn, 
DBusMessage *msg,
 
        ussd->pending = dbus_message_ref(msg);
 
-       ussd->driver->request(ussd, str, ussd_response_callback, ussd);
+       ussd->driver->request(ussd, dcs, (const guint8*) str, strlen(str),
+                          ussd_response_callback, ussd);
 
        return NULL;
 }
@@ -543,7 +592,10 @@ static void ussd_cancel_callback(const struct ofono_error 
*error, void *data)
        reply = dbus_message_new_method_return(ussd->cancel);
        __ofono_dbus_pending_reply(&ussd->cancel, reply);
 
-       ussd_change_state(ussd, USSD_STATE_IDLE);
+    if (ussd->req)
+        ussd_request_finish(ussd, -1, USSD_STATE_USER_ACTION, NULL, -1);
+
+    ussd_change_state(ussd, USSD_STATE_IDLE);
 }
 
 static DBusMessage *ussd_cancel(DBusConnection *conn, DBusMessage *msg,
@@ -741,3 +793,44 @@ void *ofono_ussd_get_data(struct ofono_ussd *ussd)
 {
        return ussd->driver_data;
 }
+
+static void ussd_request_callback(const struct ofono_error *error, void *data)
+{
+       struct ofono_ussd *ussd = data;
+
+       if (error->type != OFONO_ERROR_TYPE_NO_ERROR)
+               ussd_request_finish(ussd, OFONO_USSD_FAILURE_RETURN_ERROR, -1, 
NULL, -1);
+       else
+               ussd_change_state(ussd,USSD_STATE_ACTIVE);
+}
+
+gboolean __ofono_ussd_is_busy(struct ofono_ussd *ussd)
+{
+       if (ussd->pending || ussd->state != USSD_STATE_IDLE || ussd->req)
+               return TRUE;
+       return FALSE;
+}
+
+int __ofono_ussd_initiate(struct ofono_ussd *ussd, int dcs,
+                          const unsigned char *str, int str_len,
+                          ofono_ussd_request_cb_t cb, void *user_data)
+{
+       struct ussd_request *req;
+
+       if (!ussd->driver->request)
+               return -ENOSYS;
+
+       req = g_try_new0(struct ussd_request, 1);
+       req->dcs = dcs;
+       req->str = g_memdup(str, str_len);
+       req->str_len = str_len;
+       req->cb = cb;
+       req->user_data = user_data;
+
+       ussd->req = req;
+
+       ussd->driver->request(ussd, dcs, str, str_len, ussd_request_callback,
+                         ussd);
+
+       return 0;
+}
-- 
1.7.0.4



----------------------------------------------------------------
Please note: This e-mail may contain confidential information
intended solely for the addressee. If you have received this
e-mail in error, please do not disclose it to anyone, notify
the sender promptly, and delete the message from your system.
Thank you.



----------------------------------------------------------------
Please note: This e-mail may contain confidential information
intended solely for the addressee. If you have received this
e-mail in error, please do not disclose it to anyone, notify
the sender promptly, and delete the message from your system.
Thank you.

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

Reply via email to