ussd: Add __ofono_ussd_initiate internal api
authorJeevaka Badrappan <jeevaka.badrappan@elektrobit.com>
Tue, 14 Sep 2010 21:31:52 +0000 (14:31 -0700)
committerDenis Kenzior <denkenz@gmail.com>
Wed, 15 Sep 2010 16:36:03 +0000 (11:36 -0500)
src/ofono.h
src/ussd.c

index f1c0973..f64f149 100644 (file)
@@ -258,6 +258,9 @@ typedef gboolean (*ofono_ussd_passwd_cb_t)(const char *sc,
                                        const char *old, const char *new,
                                        DBusMessage *msg, void *data);
 
+typedef void (*ofono_ussd_request_cb_t)(int error, int dcs,
+                                       const unsigned char *pdu, int len, void *data);
+
 gboolean __ofono_ussd_ssc_register(struct ofono_ussd *ussd, const char *sc,
                                        ofono_ussd_ssc_cb_t cb, void *data,
                                        ofono_destroy_func destroy);
@@ -269,6 +272,11 @@ gboolean __ofono_ussd_passwd_register(struct ofono_ussd *ussd, const char *sc,
 void __ofono_ussd_passwd_unregister(struct ofono_ussd *ussd, const char *sc);
 gboolean __ofono_ussd_is_busy(struct ofono_ussd *ussd);
 
+int __ofono_ussd_initiate(struct ofono_ussd *ussd, int dcs,
+                       const unsigned char *pdu, int len,
+                       ofono_ussd_request_cb_t cb, void *user_data);
+void __ofono_ussd_initiate_cancel(struct ofono_ussd *ussd);
+
 #include <ofono/netreg.h>
 
 typedef void (*ofono_netreg_status_notify_cb_t)(int status, int lac, int ci,
index 2319578..b7f85fa 100644 (file)
@@ -49,6 +49,15 @@ enum ussd_state {
        USSD_STATE_RESPONSE_SENT,
 };
 
+struct ussd_request {
+       struct ofono_ussd *ussd;
+       int dcs;
+       unsigned char *pdu;
+       int len;
+       ofono_ussd_request_cb_t cb;
+       void *user_data;
+};
+
 struct ofono_ussd {
        int state;
        DBusMessage *pending;
@@ -59,6 +68,7 @@ struct ofono_ussd {
        const struct ofono_ussd_driver *driver;
        void *driver_data;
        struct ofono_atom *atom;
+       struct ussd_request *req;
 };
 
 struct ssc_entry {
@@ -73,7 +83,7 @@ gboolean __ofono_ussd_is_busy(struct ofono_ussd *ussd)
        if (!ussd)
                return FALSE;
 
-       if (ussd->pending || ussd->state != USSD_STATE_IDLE)
+       if (ussd->pending || ussd->state != USSD_STATE_IDLE || ussd->req)
                return TRUE;
 
        return FALSE;
@@ -320,6 +330,31 @@ static void ussd_change_state(struct ofono_ussd *ussd, int state)
                        "State", DBUS_TYPE_STRING, &value);
 }
 
+static void ussd_request_finish(struct ofono_ussd *ussd, int error, int dcs,
+                               const unsigned char *pdu, int len)
+{
+       struct ussd_request *req = ussd->req;
+
+       if (req && req->cb)
+               req->cb(error, dcs, pdu, len, req->user_data);
+
+       g_free(req->pdu);
+       g_free(req);
+       ussd->req = NULL;
+}
+
+static int ussd_status_to_failure_code(int status)
+{
+       switch (status) {
+       case OFONO_USSD_STATUS_TIMED_OUT:
+               return -ETIMEDOUT;
+       case OFONO_USSD_STATUS_NOT_SUPPORTED:
+               return -ENOSYS;
+       }
+
+       return 0;
+}
+
 void ofono_ussd_notify(struct ofono_ussd *ussd, int status, int dcs,
                        const unsigned char *data, int data_len)
 {
@@ -332,6 +367,18 @@ void ofono_ussd_notify(struct ofono_ussd *ussd, int status, int dcs,
        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, data, data_len);
+
+               ussd_change_state(ussd, USSD_STATE_IDLE);
+               return;
+       }
+
        if (status == OFONO_USSD_STATUS_NOT_SUPPORTED) {
                ussd_change_state(ussd, USSD_STATE_IDLE);
 
@@ -465,10 +512,7 @@ static DBusMessage *ussd_initiate(DBusConnection *conn, DBusMessage *msg,
        unsigned char buf[160];
        long num_packed;
 
-       if (ussd->pending)
-               return __ofono_error_busy(msg);
-
-       if (ussd->state != USSD_STATE_IDLE)
+       if (__ofono_ussd_is_busy(ussd))
                return __ofono_error_busy(msg);
 
        if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &str,
@@ -581,6 +625,9 @@ 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);
 
+       if (ussd->req)
+               ussd_request_finish(ussd, -1, -ECANCELED, NULL, -1);
+
        ussd_change_state(ussd, USSD_STATE_IDLE);
 }
 
@@ -779,3 +826,47 @@ 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, error->error, -1, NULL, -1);
+       else
+               ussd_change_state(ussd, USSD_STATE_ACTIVE);
+}
+
+int __ofono_ussd_initiate(struct ofono_ussd *ussd, int dcs,
+                               const unsigned char *pdu, int len,
+                               ofono_ussd_request_cb_t cb, void *user_data)
+{
+       struct ussd_request *req;
+
+       if (!ussd->driver->request)
+               return -ENOSYS;
+
+       if (__ofono_ussd_is_busy(ussd))
+               return -EBUSY;
+
+       req = g_try_new0(struct ussd_request, 1);
+       req->dcs = dcs;
+       req->pdu = g_memdup(pdu, len);
+       req->len = len;
+       req->cb = cb;
+       req->user_data = user_data;
+
+       ussd->req = req;
+
+       ussd->driver->request(ussd, dcs, pdu, len, ussd_request_callback, ussd);
+
+       return 0;
+}
+
+void __ofono_ussd_initiate_cancel(struct ofono_ussd *ussd)
+{
+       if (!ussd->req || !ussd->req->cb)
+               return;
+
+       ussd->req->cb = NULL;
+}