summaryrefslogtreecommitdiffstats
path: root/src/ussd.c
diff options
context:
space:
mode:
authorJeevaka Badrappan <jeevaka.badrappan@elektrobit.com>2010-09-14 14:31:52 -0700
committerDenis Kenzior <denkenz@gmail.com>2010-09-15 11:36:03 -0500
commit77361655c00142c22609a40c1905df90e53c810e (patch)
treea017f0005f6f1b4403b3afea81646da74da85534 /src/ussd.c
parent3114a907ffa33527643f69cda639728fc1ab4da7 (diff)
downloadofono-77361655c00142c22609a40c1905df90e53c810e.tar.bz2
ussd: Add __ofono_ussd_initiate internal api
Diffstat (limited to 'src/ussd.c')
-rw-r--r--src/ussd.c101
1 files changed, 96 insertions, 5 deletions
diff --git a/src/ussd.c b/src/ussd.c
index 23195784..b7f85fa4 100644
--- a/src/ussd.c
+++ b/src/ussd.c
@@ -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;
+}