---
src/call-barring.c | 168 ++++++++++++++++++++++---------------
src/call-forwarding.c | 155 +++++++++++++++++++++-------------
src/call-settings.c | 220 +++++++++++++++++++++++++++----------------------
src/ofono.h | 15 +++-
src/stk.c | 98 ++++++++++++++++++++++
src/stkutil.c | 2 +
src/stkutil.h | 23 +++++
src/ussd.c | 78 ++++++++++++------
8 files changed, 504 insertions(+), 255 deletions(-)
diff --git a/src/call-barring.c b/src/call-barring.c
index d235211..f504d07 100644
--- a/src/call-barring.c
+++ b/src/call-barring.c
@@ -48,6 +48,7 @@ static void set_query_next_lock(struct ofono_call_barring *cb);
struct ofono_call_barring {
int flags;
DBusMessage *pending;
+ ofono_bool_t stk_pending;
int cur_locks[NUM_OF_BARRINGS];
int new_locks[NUM_OF_BARRINGS];
int query_start;
@@ -58,10 +59,12 @@ struct ofono_call_barring {
int ss_req_lock;
struct ofono_ssn *ssn;
struct ofono_ussd *ussd;
+ struct ofono_stk *stk;
unsigned int incoming_bar_watch;
unsigned int outgoing_bar_watch;
unsigned int ssn_watch;
unsigned int ussd_watch;
+ unsigned int stk_watch;
const struct ofono_call_barring_driver *driver;
void *driver_data;
struct ofono_atom *atom;
@@ -95,6 +98,36 @@ static struct call_barring_lock cb_locks[] = {
#define CB_ALL_OUTGOING 6
#define CB_ALL_INCOMING 7
+gboolean __ofono_call_barring_is_busy(struct ofono_call_barring *cb)
+{
+ if (!cb)
+ return FALSE;
+
+ if (cb->pending || cb->stk_pending)
+ return TRUE;
+
+ return FALSE;
+}
+
+static void reply_error(struct ofono_call_barring *cb,
+ const struct ofono_error *error)
+{
+ if (cb->pending)
+ __ofono_dbus_pending_reply(&cb->pending,
+ __ofono_error_failed(cb->pending));
+ else
+ __ofono_stk_send_ss_response(cb->stk, &cb->stk_pending, error);
+}
+
+static void set_pending(struct ofono_call_barring *cb,
+ struct ofono_ss_req *osr)
+{
+ if (osr->msg)
+ cb->pending = dbus_message_ref(osr->msg);
+ else
+ cb->stk_pending = TRUE;
+}
+
static inline void emit_barring_changed(struct ofono_call_barring *cb,
int start, int end,
const char *type, int cls)
@@ -293,9 +326,8 @@ static void cb_ss_query_next_lock_callback(const struct ofono_error
*error,
"successful, but query was not");
cb->flags &= ~CALL_BARRING_FLAG_CACHED;
+ reply_error(cb, error);
- __ofono_dbus_pending_reply(&cb->pending,
- __ofono_error_failed(cb->pending));
return;
}
@@ -307,7 +339,11 @@ static void cb_ss_query_next_lock_callback(const struct ofono_error
*error,
return;
}
- generate_ss_query_reply(cb);
+ if (cb->pending)
+ generate_ss_query_reply(cb);
+ else
+ __ofono_stk_send_ss_response(cb->stk, &cb->stk_pending, error);
+
update_barrings(cb, BEARER_CLASS_VOICE);
}
@@ -328,8 +364,7 @@ static void cb_ss_set_lock_callback(const struct ofono_error *error,
if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
DBG("Enabling/disabling Call Barring via SS failed");
- __ofono_dbus_pending_reply(&cb->pending,
- __ofono_error_failed(cb->pending));
+ reply_error(cb, error);
return;
}
@@ -359,25 +394,19 @@ static const char *cb_ss_service_to_fac(const char *svc)
return NULL;
}
-static gboolean cb_ss_control(int type, const char *sc,
+static int cb_ss_control(int type, const char *sc,
const char *sia, const char *sib,
const char *sic, const char *dn,
- DBusMessage *msg, void *data)
+ struct ofono_ss_req *osr, void *data)
{
struct ofono_call_barring *cb = data;
- DBusConnection *conn = ofono_dbus_get_connection();
int cls = BEARER_CLASS_DEFAULT;
const char *fac;
- DBusMessage *reply;
void *operation = NULL;
int i;
- if (cb->pending) {
- reply = __ofono_error_busy(msg);
- g_dbus_send_message(conn, reply);
-
- return TRUE;
- }
+ if (__ofono_call_barring_is_busy(cb))
+ return EBUSY;
DBG("Received call barring ss control request");
@@ -386,7 +415,7 @@ static gboolean cb_ss_control(int type, const char *sc,
fac = cb_ss_service_to_fac(sc);
if (!fac)
- return FALSE;
+ return -ENOENT;
cb_set_query_bounds(cb, fac, type == SS_CONTROL_TYPE_QUERY);
@@ -397,13 +426,13 @@ static gboolean cb_ss_control(int type, const char *sc,
cb->ss_req_lock = i;
if (strlen(sic) > 0)
- goto bad_format;
+ return EINVAL;
if (strlen(dn) > 0)
- goto bad_format;
+ return EINVAL;
if (type != SS_CONTROL_TYPE_QUERY && !is_valid_pin(sia, PIN_TYPE_NET))
- goto bad_format;
+ return EINVAL;
switch (type) {
case SS_CONTROL_TYPE_ACTIVATION:
@@ -419,12 +448,8 @@ static gboolean cb_ss_control(int type, const char *sc,
break;
}
- if (!operation) {
- reply = __ofono_error_not_implemented(msg);
- g_dbus_send_message(conn, reply);
-
- return TRUE;
- }
+ if (!operation)
+ return ENOSYS;
/* According to 27.007, AG, AC and AB only work with mode = 0
* We support query by querying all relevant types, since we must
@@ -433,7 +458,7 @@ static gboolean cb_ss_control(int type, const char *sc,
if ((!strcmp(fac, "AG") || !strcmp(fac, "AC") || !strcmp(fac,
"AB")) &&
(type == SS_CONTROL_TYPE_ACTIVATION ||
type == SS_CONTROL_TYPE_REGISTRATION))
- goto bad_format;
+ return EINVAL;
if (strlen(sib) > 0) {
long service_code;
@@ -442,16 +467,16 @@ static gboolean cb_ss_control(int type, const char *sc,
service_code = strtoul(sib, &end, 10);
if (end == sib || *end != '\0')
- goto bad_format;
+ return EINVAL;
cls = mmi_service_code_to_bearer_class(service_code);
if (cls == 0)
- goto bad_format;
+ return EINVAL;
}
cb->ss_req_cls = cls;
- cb->pending = dbus_message_ref(msg);
+ set_pending(cb, osr);
switch (type) {
case SS_CONTROL_TYPE_ACTIVATION:
@@ -472,44 +497,35 @@ static gboolean cb_ss_control(int type, const char *sc,
break;
}
- return TRUE;
-
-bad_format:
- reply = __ofono_error_invalid_format(msg);
- g_dbus_send_message(conn, reply);
- return TRUE;
+ return 0;
}
static void cb_set_passwd_callback(const struct ofono_error *error, void *data)
{
struct ofono_call_barring *cb = data;
- DBusMessage *reply;
- if (error->type == OFONO_ERROR_TYPE_NO_ERROR)
- reply = dbus_message_new_method_return(cb->pending);
- else {
- reply = __ofono_error_failed(cb->pending);
+ if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
DBG("Changing Call Barring password via SS failed");
+ reply_error(cb, error);
+ return;
}
- __ofono_dbus_pending_reply(&cb->pending, reply);
+ if (cb->pending)
+ __ofono_dbus_pending_reply(&cb->pending,
+ dbus_message_new_method_return(cb->pending));
+ else
+ __ofono_stk_send_ss_response(cb->stk, &cb->stk_pending, error);
}
-static gboolean cb_ss_passwd(const char *sc,
+static int cb_ss_passwd(const char *sc,
const char *old, const char *new,
- DBusMessage *msg, void *data)
+ struct ofono_ss_req *osr, void *data)
{
struct ofono_call_barring *cb = data;
- DBusConnection *conn = ofono_dbus_get_connection();
- DBusMessage *reply;
const char *fac;
- if (cb->pending) {
- reply = __ofono_error_busy(msg);
- g_dbus_send_message(conn, reply);
-
- return TRUE;
- }
+ if (__ofono_call_barring_is_busy(cb))
+ return EBUSY;
DBG("Received call barring ss password change request");
@@ -521,19 +537,16 @@ static gboolean cb_ss_passwd(const char *sc,
fac = cb_ss_service_to_fac(sc);
if (!fac)
- return FALSE;
+ return -ENOENT;
if (!is_valid_pin(old, PIN_TYPE_NET) || !is_valid_pin(new, PIN_TYPE_NET))
- goto bad_format;
+ return EINVAL;
+
+ set_pending(cb, osr);
- cb->pending = dbus_message_ref(msg);
cb->driver->set_passwd(cb, fac, old, new, cb_set_passwd_callback, cb);
- return TRUE;
-bad_format:
- reply = __ofono_error_invalid_format(msg);
- g_dbus_send_message(conn, reply);
- return TRUE;
+ return 0;
}
static void cb_register_ss_controls(struct ofono_call_barring *cb)
@@ -580,11 +593,6 @@ static void cb_unregister_ss_controls(struct ofono_call_barring *cb)
__ofono_ussd_passwd_unregister(cb->ussd, "353");
}
-gboolean __ofono_call_barring_is_busy(struct ofono_call_barring *cb)
-{
- return cb->pending ? TRUE : FALSE;
-}
-
static inline void cb_append_property(struct ofono_call_barring *cb,
DBusMessageIter *dict, int start,
int end, int cls, const char *property)
@@ -674,7 +682,7 @@ static DBusMessage *cb_get_properties(DBusConnection *conn,
DBusMessage *msg,
{
struct ofono_call_barring *cb = data;
- if (cb->pending || __ofono_ussd_is_busy(cb->ussd))
+ if (__ofono_call_barring_is_busy(cb) || __ofono_ussd_is_busy(cb->ussd))
return __ofono_error_busy(msg);
if (!cb->driver->query)
@@ -827,7 +835,7 @@ static DBusMessage *cb_set_property(DBusConnection *conn, DBusMessage
*msg,
int cls;
int mode;
- if (cb->pending || __ofono_ussd_is_busy(cb->ussd))
+ if (__ofono_call_barring_is_busy(cb) || __ofono_ussd_is_busy(cb->ussd))
return __ofono_error_busy(msg);
if (!dbus_message_iter_init(msg, &iter))
@@ -899,7 +907,7 @@ static DBusMessage *cb_disable_all(DBusConnection *conn, DBusMessage
*msg,
if (!cb->driver->set)
return __ofono_error_not_implemented(msg);
- if (cb->pending || __ofono_ussd_is_busy(cb->ussd))
+ if (__ofono_call_barring_is_busy(cb) || __ofono_ussd_is_busy(cb->ussd))
return __ofono_error_busy(msg);
if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &passwd,
@@ -946,7 +954,7 @@ static DBusMessage *cb_set_passwd(DBusConnection *conn, DBusMessage
*msg,
if (!cb->driver->set_passwd)
return __ofono_error_not_implemented(msg);
- if (cb->pending || __ofono_ussd_is_busy(cb->ussd))
+ if (__ofono_call_barring_is_busy(cb) || __ofono_ussd_is_busy(cb->ussd))
return __ofono_error_busy(msg);
if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &old_passwd,
@@ -1150,6 +1158,19 @@ static void ussd_watch(struct ofono_atom *atom,
cb_register_ss_controls(cb);
}
+static void stk_watch(struct ofono_atom *atom,
+ enum ofono_atom_watch_condition cond, void *data)
+{
+ struct ofono_call_barring *cb = data;
+
+ if (cond == OFONO_ATOM_WATCH_CONDITION_UNREGISTERED) {
+ cb->stk = NULL;
+ return;
+ }
+
+ cb->stk = __ofono_atom_get_data(atom);
+}
+
void ofono_call_barring_register(struct ofono_call_barring *cb)
{
DBusConnection *conn = ofono_dbus_get_connection();
@@ -1157,6 +1178,7 @@ void ofono_call_barring_register(struct ofono_call_barring *cb)
struct ofono_modem *modem = __ofono_atom_get_modem(cb->atom);
struct ofono_atom *ssn_atom;
struct ofono_atom *ussd_atom;
+ struct ofono_atom *stk_atom;
if (!g_dbus_register_interface(conn, path,
OFONO_CALL_BARRING_INTERFACE,
@@ -1188,6 +1210,16 @@ void ofono_call_barring_register(struct ofono_call_barring *cb)
ussd_watch(ussd_atom, OFONO_ATOM_WATCH_CONDITION_REGISTERED,
cb);
+ cb->stk_watch = __ofono_modem_add_atom_watch(modem,
+ OFONO_ATOM_TYPE_STK,
+ stk_watch, cb, NULL);
+
+ stk_atom = __ofono_modem_find_atom(modem, OFONO_ATOM_TYPE_STK);
+
+ if (stk_atom && __ofono_atom_get_registered(stk_atom))
+ stk_watch(stk_atom, OFONO_ATOM_WATCH_CONDITION_REGISTERED,
+ cb);
+
__ofono_atom_register(cb->atom, call_barring_unregister);
}
diff --git a/src/call-forwarding.c b/src/call-forwarding.c
index 5eae6cf..9161121 100644
--- a/src/call-forwarding.c
+++ b/src/call-forwarding.c
@@ -55,11 +55,14 @@ struct ofono_call_forwarding {
GSList *cf_conditions[4];
int flags;
DBusMessage *pending;
+ ofono_bool_t stk_pending;
int query_next;
int query_end;
struct cf_ss_request *ss_req;
struct ofono_ussd *ussd;
+ struct ofono_stk *stk;
unsigned int ussd_watch;
+ unsigned int stk_watch;
const struct ofono_call_forwarding_driver *driver;
void *driver_data;
struct ofono_atom *atom;
@@ -77,6 +80,36 @@ struct cf_ss_request {
GSList *cf_list[4];
};
+gboolean __ofono_call_forwarding_is_busy(struct ofono_call_forwarding *cf)
+{
+ if (!cf)
+ return FALSE;
+
+ if (cf->pending || cf->stk_pending)
+ return TRUE;
+
+ return FALSE;
+}
+
+static void reply_error(struct ofono_call_forwarding *cf,
+ const struct ofono_error *error)
+{
+ if (cf->pending)
+ __ofono_dbus_pending_reply(&cf->pending,
+ __ofono_error_failed(cf->pending));
+ else
+ __ofono_stk_send_ss_response(cf->stk, &cf->stk_pending, error);
+}
+
+static void set_pending(struct ofono_call_forwarding *cf,
+ struct ofono_ss_req *osr)
+{
+ if (osr->msg)
+ cf->pending = dbus_message_ref(osr->msg);
+ else
+ cf->stk_pending = TRUE;
+}
+
static gint cf_condition_compare(gconstpointer a, gconstpointer b)
{
const struct ofono_call_forwarding_condition *ca = a;
@@ -430,7 +463,8 @@ static DBusMessage *cf_get_properties(DBusConnection *conn,
DBusMessage *msg,
if (!cf->driver->query)
return __ofono_error_not_implemented(msg);
- if (cf->pending || __ofono_ussd_is_busy(cf->ussd))
+ if (__ofono_call_forwarding_is_busy(cf) ||
+ __ofono_ussd_is_busy(cf->ussd))
return __ofono_error_busy(msg);
cf->pending = dbus_message_ref(msg);
@@ -586,7 +620,8 @@ static DBusMessage *cf_set_property(DBusConnection *conn, DBusMessage
*msg,
int cls;
int type;
- if (cf->pending || __ofono_ussd_is_busy(cf->ussd))
+ if (__ofono_call_forwarding_is_busy(cf) ||
+ __ofono_ussd_is_busy(cf->ussd))
return __ofono_error_busy(msg);
if (!dbus_message_iter_init(msg, &iter))
@@ -704,7 +739,8 @@ static DBusMessage *cf_disable_all(DBusConnection *conn, DBusMessage
*msg,
if (!cf->driver->erasure)
return __ofono_error_not_implemented(msg);
- if (cf->pending || __ofono_ussd_is_busy(cf->ussd))
+ if (__ofono_call_forwarding_is_busy(cf) ||
+ __ofono_ussd_is_busy(cf->ussd))
return __ofono_error_busy(msg);
if (dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &strtype,
@@ -823,13 +859,11 @@ static void ss_set_query_cf_callback(const struct ofono_error
*error, int total,
{
struct ofono_call_forwarding *cf = data;
GSList *l;
- DBusMessage *reply;
if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
ofono_error("Setting succeeded, but query failed");
cf->flags &= ~CALL_FORWARDING_FLAG_CACHED;
- reply = __ofono_error_failed(cf->pending);
- __ofono_dbus_pending_reply(&cf->pending, reply);
+ reply_error(cf, error);
return;
}
@@ -840,8 +874,13 @@ static void ss_set_query_cf_callback(const struct ofono_error *error,
int total,
cf->ss_req->cf_list[cf->query_next] = l;
if (cf->query_next == cf->query_end) {
- reply = cf_ss_control_reply(cf, cf->ss_req);
- __ofono_dbus_pending_reply(&cf->pending, reply);
+ if (cf->pending)
+ __ofono_dbus_pending_reply(&cf->pending,
+ cf_ss_control_reply(cf, cf->ss_req));
+ else
+ __ofono_stk_send_ss_response(cf->stk, &cf->stk_pending,
+ error);
+
g_free(cf->ss_req);
cf->ss_req = NULL;
}
@@ -866,9 +905,7 @@ static void cf_ss_control_callback(const struct ofono_error *error,
void *data)
if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
DBG("Error occurred during cf ss control set/erasure");
-
- __ofono_dbus_pending_reply(&cf->pending,
- __ofono_error_failed(cf->pending));
+ reply_error(cf, error);
g_free(cf->ss_req);
cf->ss_req = NULL;
return;
@@ -877,30 +914,24 @@ static void cf_ss_control_callback(const struct ofono_error *error,
void *data)
ss_set_query_next_cf_cond(cf);
}
-static gboolean cf_ss_control(int type, const char *sc,
+static int cf_ss_control(int type, const char *sc,
const char *sia, const char *sib,
const char *sic, const char *dn,
- DBusMessage *msg, void *data)
+ struct ofono_ss_req *osr, void *data)
{
struct ofono_call_forwarding *cf = data;
- DBusConnection *conn = ofono_dbus_get_connection();
int cls = BEARER_CLASS_SS_DEFAULT;
int timeout = DEFAULT_NO_REPLY_TIMEOUT;
int cf_type;
- DBusMessage *reply;
struct ofono_phone_number ph;
void *operation = NULL;
/* Before we do anything, make sure we're actually initialized */
if (!cf)
- return FALSE;
+ return -ENOENT;
- if (cf->pending) {
- reply = __ofono_error_busy(msg);
- g_dbus_send_message(conn, reply);
-
- return TRUE;
- }
+ if (__ofono_call_forwarding_is_busy(cf))
+ return EBUSY;
DBG("Received call forwarding ss control request");
@@ -920,13 +951,13 @@ static gboolean cf_ss_control(int type, const char *sc,
else if (!strcmp(sc, "004"))
cf_type = CALL_FORWARDING_TYPE_ALL_CONDITIONAL;
else
- return FALSE;
+ return -ENOENT;
if (strlen(sia) &&
- (type == SS_CONTROL_TYPE_QUERY ||
- type == SS_CONTROL_TYPE_ERASURE ||
- type == SS_CONTROL_TYPE_DEACTIVATION))
- goto error;
+ (type == SS_CONTROL_TYPE_QUERY ||
+ type == SS_CONTROL_TYPE_ERASURE ||
+ type == SS_CONTROL_TYPE_DEACTIVATION))
+ return EINVAL;
/* Activation / Registration is figured context specific according to
* 22.030 Section 6.5.2 "The UE shall determine from the context
@@ -937,8 +968,8 @@ static gboolean cf_ss_control(int type, const char *sc,
type = SS_CONTROL_TYPE_REGISTRATION;
if (type == SS_CONTROL_TYPE_REGISTRATION &&
- !valid_phone_number_format(sia))
- goto error;
+ !valid_phone_number_format(sia))
+ return EINVAL;
if (strlen(sib) > 0) {
long service_code;
@@ -947,32 +978,32 @@ static gboolean cf_ss_control(int type, const char *sc,
service_code = strtoul(sib, &end, 10);
if (end == sib || *end != '\0')
- goto error;
+ return EINVAL;
cls = mmi_service_code_to_bearer_class(service_code);
if (cls == 0)
- goto error;
+ return EINVAL;
}
if (strlen(sic) > 0) {
char *end;
if (type != SS_CONTROL_TYPE_REGISTRATION)
- goto error;
+ return EINVAL;
if (cf_type != CALL_FORWARDING_TYPE_ALL &&
cf_type != CALL_FORWARDING_TYPE_ALL_CONDITIONAL &&
cf_type != CALL_FORWARDING_TYPE_NO_REPLY)
- goto error;
+ return EINVAL;
timeout = strtoul(sic, &end, 10);
if (end == sic || *end != '\0')
- goto error;
+ return EINVAL;
if (timeout < 1 || timeout > 30)
- goto error;
+ return EINVAL;
}
switch (type) {
@@ -993,27 +1024,19 @@ static gboolean cf_ss_control(int type, const char *sc,
break;
}
- if (!operation) {
- reply = __ofono_error_not_implemented(msg);
- g_dbus_send_message(conn, reply);
-
- return TRUE;
- }
+ if (!operation)
+ return ENOSYS;
cf->ss_req = g_try_new0(struct cf_ss_request, 1);
- if (!cf->ss_req) {
- reply = __ofono_error_failed(msg);
- g_dbus_send_message(conn, reply);
-
- return TRUE;
- }
+ if (!cf->ss_req)
+ return ENOMEM;
cf->ss_req->ss_type = type;
cf->ss_req->cf_type = cf_type;
cf->ss_req->cls = cls;
- cf->pending = dbus_message_ref(msg);
+ set_pending(cf, osr);
switch (cf->ss_req->cf_type) {
case CALL_FORWARDING_TYPE_ALL:
@@ -1062,12 +1085,7 @@ static gboolean cf_ss_control(int type, const char *sc,
break;
}
- return TRUE;
-
-error:
- reply = __ofono_error_invalid_format(msg);
- g_dbus_send_message(conn, reply);
- return TRUE;
+ return 0;
}
static void cf_register_ss_controls(struct ofono_call_forwarding *cf)
@@ -1092,11 +1110,6 @@ static void cf_unregister_ss_controls(struct ofono_call_forwarding
*cf)
__ofono_ussd_ssc_unregister(cf->ussd, "004");
}
-gboolean __ofono_call_forwarding_is_busy(struct ofono_call_forwarding *cf)
-{
- return cf->pending ? TRUE : FALSE;
-}
-
int ofono_call_forwarding_driver_register(const struct ofono_call_forwarding_driver *d)
{
DBG("driver: %p, name: %s", d, d->name);
@@ -1200,12 +1213,26 @@ static void ussd_watch(struct ofono_atom *atom,
cf_register_ss_controls(cf);
}
+static void stk_watch(struct ofono_atom *atom,
+ enum ofono_atom_watch_condition cond, void *data)
+{
+ struct ofono_call_forwarding *cf = data;
+
+ if (cond == OFONO_ATOM_WATCH_CONDITION_UNREGISTERED) {
+ cf->stk = NULL;
+ return;
+ }
+
+ cf->stk = __ofono_atom_get_data(atom);
+}
+
void ofono_call_forwarding_register(struct ofono_call_forwarding *cf)
{
DBusConnection *conn = ofono_dbus_get_connection();
const char *path = __ofono_atom_get_path(cf->atom);
struct ofono_modem *modem = __ofono_atom_get_modem(cf->atom);
struct ofono_atom *ussd_atom;
+ struct ofono_atom *stk_atom;
if (!g_dbus_register_interface(conn, path,
OFONO_CALL_FORWARDING_INTERFACE,
@@ -1229,6 +1256,16 @@ void ofono_call_forwarding_register(struct ofono_call_forwarding
*cf)
ussd_watch(ussd_atom, OFONO_ATOM_WATCH_CONDITION_REGISTERED,
cf);
+ cf->stk_watch = __ofono_modem_add_atom_watch(modem,
+ OFONO_ATOM_TYPE_STK,
+ stk_watch, cf, NULL);
+
+ stk_atom = __ofono_modem_find_atom(modem, OFONO_ATOM_TYPE_STK);
+
+ if (stk_atom && __ofono_atom_get_registered(stk_atom))
+ stk_watch(stk_atom, OFONO_ATOM_WATCH_CONDITION_REGISTERED,
+ cf);
+
__ofono_atom_register(cf->atom, call_forwarding_unregister);
}
diff --git a/src/call-settings.c b/src/call-settings.c
index 0c46a2a..4b8d71f 100644
--- a/src/call-settings.c
+++ b/src/call-settings.c
@@ -86,16 +86,49 @@ struct ofono_call_settings {
int cw;
int flags;
DBusMessage *pending;
+ ofono_bool_t stk_pending;
int ss_req_type;
int ss_req_cls;
enum call_setting_type ss_setting;
struct ofono_ussd *ussd;
+ struct ofono_stk *stk;
unsigned int ussd_watch;
+ unsigned int stk_watch;
const struct ofono_call_settings_driver *driver;
void *driver_data;
struct ofono_atom *atom;
};
+gboolean __ofono_call_settings_is_busy(struct ofono_call_settings *cs)
+{
+ if (!cs)
+ return FALSE;
+
+ if (cs->pending || cs->stk_pending)
+ return TRUE;
+
+ return FALSE;
+}
+
+static void reply_error(struct ofono_call_settings *cs,
+ const struct ofono_error *error)
+{
+ if (cs->pending)
+ __ofono_dbus_pending_reply(&cs->pending,
+ __ofono_error_failed(cs->pending));
+ else
+ __ofono_stk_send_ss_response(cs->stk, &cs->stk_pending, error);
+}
+
+static void set_pending(struct ofono_call_settings *cs,
+ struct ofono_ss_req *osr)
+{
+ if (osr->msg)
+ cs->pending = dbus_message_ref(osr->msg);
+ else
+ cs->stk_pending = TRUE;
+}
+
static const char *clip_status_to_string(int status)
{
switch (status) {
@@ -375,15 +408,17 @@ static void cw_ss_query_callback(const struct ofono_error *error,
int status,
DBG("setting CW via SS failed");
cs->flags &= ~CALL_SETTINGS_FLAG_CACHED;
- __ofono_dbus_pending_reply(&cs->pending,
- __ofono_error_failed(cs->pending));
+ reply_error(cs, error);
return;
}
set_cw(cs, status, BEARER_CLASS_VOICE);
- generate_cw_ss_query_reply(cs);
+ if (cs->pending)
+ generate_cw_ss_query_reply(cs);
+ else
+ __ofono_stk_send_ss_response(cs->stk, &cs->stk_pending, error);
}
static void cw_ss_set_callback(const struct ofono_error *error, void *data)
@@ -392,8 +427,7 @@ static void cw_ss_set_callback(const struct ofono_error *error, void
*data)
if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
DBG("setting CW via SS failed");
- __ofono_dbus_pending_reply(&cs->pending,
- __ofono_error_failed(cs->pending));
+ reply_error(cs, error);
return;
}
@@ -402,35 +436,29 @@ static void cw_ss_set_callback(const struct ofono_error *error, void
*data)
cw_ss_query_callback, cs);
}
-static gboolean cw_ss_control(int type,
- const char *sc, const char *sia,
+static int cw_ss_control(int type, const char *sc, const char *sia,
const char *sib, const char *sic,
- const char *dn, DBusMessage *msg, void *data)
+ const char *dn, struct ofono_ss_req *osr,
+ void *data)
{
struct ofono_call_settings *cs = data;
- DBusConnection *conn = ofono_dbus_get_connection();
int cls = BEARER_CLASS_SS_DEFAULT;
- DBusMessage *reply;
if (!cs)
- return FALSE;
+ return -ENOENT;
if (strcmp(sc, "43"))
- return FALSE;
+ return -ENOENT;
- if (cs->pending) {
- reply = __ofono_error_busy(msg);
- goto error;
- }
+ if (__ofono_call_settings_is_busy(cs))
+ return EBUSY;
if (strlen(sib) || strlen(sib) || strlen(dn))
- goto bad_format;
+ return EINVAL;
if ((type == SS_CONTROL_TYPE_QUERY && !cs->driver->cw_query) ||
- (type != SS_CONTROL_TYPE_QUERY && !cs->driver->cw_set)) {
- reply = __ofono_error_not_implemented(msg);
- goto error;
- }
+ (type != SS_CONTROL_TYPE_QUERY && !cs->driver->cw_set))
+ return ENOSYS;
if (strlen(sia) > 0) {
long service_code;
@@ -439,15 +467,15 @@ static gboolean cw_ss_control(int type,
service_code = strtoul(sia, &end, 10);
if (end == sia || *end != '\0')
- goto bad_format;
+ return EINVAL;
cls = mmi_service_code_to_bearer_class(service_code);
if (cls == 0)
- goto bad_format;
+ return EINVAL;
}
cs->ss_req_cls = cls;
- cs->pending = dbus_message_ref(msg);
+ set_pending(cs, osr);
/* For the default case use the more readily accepted value */
if (cls == BEARER_CLASS_SS_DEFAULT)
@@ -477,13 +505,7 @@ static gboolean cw_ss_control(int type,
break;
}
- return TRUE;
-
-bad_format:
- reply = __ofono_error_invalid_format(msg);
-error:
- g_dbus_send_message(conn, reply);
- return TRUE;
+ return 0;
}
static void generate_ss_query_reply(struct ofono_call_settings *cs,
@@ -528,8 +550,7 @@ static void clip_colp_colr_ss_query_cb(const struct ofono_error
*error,
if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
DBG("Error occurred during ss control query");
- __ofono_dbus_pending_reply(&cs->pending,
- __ofono_error_failed(cs->pending));
+ reply_error(cs, error);
return;
}
@@ -560,28 +581,26 @@ static void clip_colp_colr_ss_query_cb(const struct ofono_error
*error,
return;
};
- generate_ss_query_reply(cs, context, value);
+ if (cs->pending)
+ generate_ss_query_reply(cs, context, value);
+ else
+ __ofono_stk_send_ss_response(cs->stk, &cs->stk_pending, error);
}
-static gboolean clip_colp_colr_ss(int type,
- const char *sc, const char *sia,
+static int clip_colp_colr_ss(int type, const char *sc, const char *sia,
const char *sib, const char *sic,
- const char *dn, DBusMessage *msg, void *data)
+ const char *dn, struct ofono_ss_req *osr,
+ void *data)
{
struct ofono_call_settings *cs = data;
- DBusConnection *conn = ofono_dbus_get_connection();
void (*query_op)(struct ofono_call_settings *cs,
ofono_call_settings_status_cb_t cb, void *data);
if (!cs)
- return FALSE;
+ return -ENOENT;
- if (cs->pending) {
- DBusMessage *reply = __ofono_error_busy(msg);
- g_dbus_send_message(conn, reply);
-
- return TRUE;
- }
+ if (__ofono_call_settings_is_busy(cs))
+ return EBUSY;
if (!strcmp(sc, "30")) {
cs->ss_setting = CALL_SETTING_TYPE_CLIP;
@@ -593,31 +612,23 @@ static gboolean clip_colp_colr_ss(int type,
cs->ss_setting = CALL_SETTING_TYPE_COLR;
query_op = cs->driver->colr_query;
} else {
- return FALSE;
+ return -ENOENT;
}
if (type != SS_CONTROL_TYPE_QUERY || strlen(sia) || strlen(sib) ||
- strlen(sic) || strlen(dn)) {
- DBusMessage *reply = __ofono_error_invalid_format(msg);
- g_dbus_send_message(conn, reply);
-
- return TRUE;
- }
-
- if (!query_op) {
- DBusMessage *reply = __ofono_error_not_implemented(msg);
- g_dbus_send_message(conn, reply);
+ strlen(sic) || strlen(dn))
+ return EINVAL;
- return TRUE;
- }
+ if (!query_op)
+ return ENOSYS;
DBG("Received CLIP/COLR/COLP query ss control");
- cs->pending = dbus_message_ref(msg);
+ set_pending(cs, osr);
query_op(cs, clip_colp_colr_ss_query_cb, cs);
- return TRUE;
+ return 0;
}
static void clir_ss_query_callback(const struct ofono_error *error,
@@ -628,8 +639,7 @@ static void clir_ss_query_callback(const struct ofono_error *error,
if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
DBG("setting clir via SS failed");
- __ofono_dbus_pending_reply(&cs->pending,
- __ofono_error_failed(cs->pending));
+ reply_error(cs, error);
return;
}
@@ -664,7 +674,10 @@ static void clir_ss_query_callback(const struct ofono_error *error,
value = "unknown";
};
- generate_ss_query_reply(cs, "CallingLineRestriction", value);
+ if (cs->pending)
+ generate_ss_query_reply(cs, "CallingLineRestriction", value);
+ else
+ __ofono_stk_send_ss_response(cs->stk, &cs->stk_pending, error);
set_clir_network(cs, network);
set_clir_override(cs, override);
@@ -676,8 +689,8 @@ static void clir_ss_set_callback(const struct ofono_error *error, void
*data)
if (error->type != OFONO_ERROR_TYPE_NO_ERROR) {
DBG("setting clir via SS failed");
- __ofono_dbus_pending_reply(&cs->pending,
- __ofono_error_failed(cs->pending));
+
+ reply_error(cs, error);
return;
}
@@ -685,49 +698,37 @@ static void clir_ss_set_callback(const struct ofono_error *error,
void *data)
cs->driver->clir_query(cs, clir_ss_query_callback, cs);
}
-static gboolean clir_ss_control(int type,
- const char *sc, const char *sia,
+static int clir_ss_control(int type, const char *sc, const char *sia,
const char *sib, const char *sic,
- const char *dn, DBusMessage *msg, void *data)
+ const char *dn, struct ofono_ss_req *osr,
+ void *data)
{
struct ofono_call_settings *cs = data;
- DBusConnection *conn = ofono_dbus_get_connection();
if (!cs)
- return FALSE;
+ return -ENOENT;
if (strcmp(sc, "31"))
- return FALSE;
-
- if (cs->pending) {
- DBusMessage *reply = __ofono_error_busy(msg);
- g_dbus_send_message(conn, reply);
+ return -ENOENT;
- return TRUE;
- }
+ if (__ofono_call_settings_is_busy(cs))
+ return EBUSY;
/* This is the temporary form of CLIR, handled in voicecalls */
if (!strlen(sia) && !strlen(sib) & !strlen(sic) &&
- strlen(dn) && type != SS_CONTROL_TYPE_QUERY)
- return FALSE;
-
- if (strlen(sia) || strlen(sib) || strlen(sic) || strlen(dn)) {
- DBusMessage *reply = __ofono_error_invalid_format(msg);
- g_dbus_send_message(conn, reply);
+ strlen(dn) && type != SS_CONTROL_TYPE_QUERY)
+ return -ENOENT;
- return TRUE;
- }
+ if (strlen(sia) || strlen(sib) || strlen(sic) || strlen(dn))
+ return EINVAL;
if ((type == SS_CONTROL_TYPE_QUERY && !cs->driver->clir_query) ||
- (type != SS_CONTROL_TYPE_QUERY && !cs->driver->clir_set)) {
- DBusMessage *reply = __ofono_error_not_implemented(msg);
- g_dbus_send_message(conn, reply);
-
- return TRUE;
- }
+ (type != SS_CONTROL_TYPE_QUERY &&
+ !cs->driver->clir_set))
+ return ENOSYS;
cs->ss_setting = CALL_SETTING_TYPE_CLIR;
- cs->pending = dbus_message_ref(msg);
+ set_pending(cs, osr);
switch (type) {
case SS_CONTROL_TYPE_REGISTRATION:
@@ -750,7 +751,7 @@ static gboolean clir_ss_control(int type,
break;
};
- return TRUE;
+ return 0;
}
static void cs_register_ss_controls(struct ofono_call_settings *cs)
@@ -778,11 +779,6 @@ static void cs_unregister_ss_controls(struct ofono_call_settings
*cs)
__ofono_ussd_ssc_unregister(cs->ussd, "77");
}
-gboolean __ofono_call_settings_is_busy(struct ofono_call_settings *cs)
-{
- return cs->pending ? TRUE : FALSE;
-}
-
static DBusMessage *generate_get_properties_reply(struct ofono_call_settings *cs,
DBusMessage *msg)
{
@@ -955,7 +951,7 @@ static DBusMessage *cs_get_properties(DBusConnection *conn,
DBusMessage *msg,
{
struct ofono_call_settings *cs = data;
- if (cs->pending || __ofono_ussd_is_busy(cs->ussd))
+ if (__ofono_call_settings_is_busy(cs) || __ofono_ussd_is_busy(cs->ussd))
return __ofono_error_busy(msg);
if (cs->flags & CALL_SETTINGS_FLAG_CACHED)
@@ -1132,7 +1128,7 @@ static DBusMessage *cs_set_property(DBusConnection *conn,
DBusMessage *msg,
const char *property;
int cls;
- if (cs->pending || __ofono_ussd_is_busy(cs->ussd))
+ if (__ofono_call_settings_is_busy(cs) || __ofono_ussd_is_busy(cs->ussd))
return __ofono_error_busy(msg);
if (!dbus_message_iter_init(msg, &iter))
@@ -1290,12 +1286,26 @@ static void ussd_watch(struct ofono_atom *atom,
cs_register_ss_controls(cs);
}
+static void stk_watch(struct ofono_atom *atom,
+ enum ofono_atom_watch_condition cond, void *data)
+{
+ struct ofono_call_settings *cs = data;
+
+ if (cond == OFONO_ATOM_WATCH_CONDITION_UNREGISTERED) {
+ cs->stk = NULL;
+ return;
+ }
+
+ cs->stk = __ofono_atom_get_data(atom);
+}
+
void ofono_call_settings_register(struct ofono_call_settings *cs)
{
DBusConnection *conn = ofono_dbus_get_connection();
const char *path = __ofono_atom_get_path(cs->atom);
struct ofono_modem *modem = __ofono_atom_get_modem(cs->atom);
struct ofono_atom *ussd_atom;
+ struct ofono_atom *stk_atom;
if (!g_dbus_register_interface(conn, path,
OFONO_CALL_SETTINGS_INTERFACE,
@@ -1319,6 +1329,16 @@ void ofono_call_settings_register(struct ofono_call_settings *cs)
ussd_watch(ussd_atom, OFONO_ATOM_WATCH_CONDITION_REGISTERED,
cs);
+ cs->stk_watch = __ofono_modem_add_atom_watch(modem,
+ OFONO_ATOM_TYPE_STK,
+ stk_watch, cs, NULL);
+
+ stk_atom = __ofono_modem_find_atom(modem, OFONO_ATOM_TYPE_STK);
+
+ if (stk_atom && __ofono_atom_get_registered(stk_atom))
+ stk_watch(stk_atom, OFONO_ATOM_WATCH_CONDITION_REGISTERED,
+ cs);
+
__ofono_atom_register(cs->atom, call_settings_unregister);
}
diff --git a/src/ofono.h b/src/ofono.h
index f1c0973..50d4f96 100644
--- a/src/ofono.h
+++ b/src/ofono.h
@@ -166,6 +166,12 @@ gboolean __ofono_modem_remove_atom_watch(struct ofono_modem *modem,
void __ofono_atom_free(struct ofono_atom *atom);
+#include <gdbus.h>
+struct ofono_ss_req {
+ DBusMessage *msg;
+ gboolean stk;
+};
+
#include <ofono/call-barring.h>
gboolean __ofono_call_barring_is_busy(struct ofono_call_barring *cb);
@@ -228,6 +234,8 @@ unsigned int __ofono_sms_txq_submit(struct ofono_sms *sms, GSList
*list,
struct cbs;
void __ofono_cbs_sim_download(struct ofono_stk *stk, const struct cbs *msg);
+void __ofono_stk_send_ss_response(struct ofono_stk *stk, gboolean *stk_pending,
+ const struct ofono_error *error);
#include <ofono/ssn.h>
@@ -252,11 +260,11 @@ typedef gboolean (*ofono_ussd_ssc_cb_t)(int type,
const char *sc,
const char *sia, const char *sib,
const char *sic, const char *dn,
- DBusMessage *msg, void *data);
+ struct ofono_ss_req *osr, void *data);
typedef gboolean (*ofono_ussd_passwd_cb_t)(const char *sc,
const char *old, const char *new,
- DBusMessage *msg, void *data);
+ struct ofono_ss_req *osr, void *data);
gboolean __ofono_ussd_ssc_register(struct ofono_ussd *ussd, const char *sc,
ofono_ussd_ssc_cb_t cb, void *data,
@@ -268,6 +276,9 @@ gboolean __ofono_ussd_passwd_register(struct ofono_ussd *ussd, const
char *sc,
ofono_destroy_func destroy);
void __ofono_ussd_passwd_unregister(struct ofono_ussd *ussd, const char *sc);
gboolean __ofono_ussd_is_busy(struct ofono_ussd *ussd);
+int __ofono_ussd_recognized_control_string(struct ofono_ussd *ussd,
+ const char *ss_str,
+ struct ofono_ss_req *osr);
#include <ofono/netreg.h>
diff --git a/src/stk.c b/src/stk.c
index 04bfc65..e273914 100644
--- a/src/stk.c
+++ b/src/stk.c
@@ -648,6 +648,13 @@ static GDBusSignalTable stk_signals[] = {
{ }
};
+static gboolean set_result_type(struct stk_response *rsp,
+ enum stk_result_type type)
+{
+ rsp->result.type = type;
+ return TRUE;
+}
+
static gboolean handle_command_more_time(const struct stk_command *cmd,
struct stk_response *rsp,
struct ofono_stk *stk)
@@ -731,6 +738,92 @@ static gboolean handle_command_send_sms(const struct stk_command
*cmd,
return FALSE;
}
+void __ofono_stk_send_ss_response(struct ofono_stk *stk, gboolean *stk_pending,
+ const struct ofono_error *error)
+{
+ static struct ofono_error oe = { .type = OFONO_ERROR_TYPE_FAILURE };
+ struct stk_response rsp;
+ unsigned char addnl[2];
+
+ *stk_pending = FALSE;
+
+ memset(&rsp, 0, sizeof(rsp));
+
+ switch (error->type) {
+ case OFONO_ERROR_TYPE_NO_ERROR:
+ rsp.result.type = STK_RESULT_TYPE_SUCCESS;
+ break;
+ default:
+ rsp.result.type = STK_RESULT_TYPE_SS_RETURN_ERROR;
+ addnl[0] = (unsigned char) error->error;
+ addnl[1] = STK_RESULT_ADDNL_SS_PB_NO_SPECIFIC_CAUSE;
+ rsp.result.additional = addnl;
+ rsp.result.additional_len = 2;
+ break;
+ }
+
+ if (stk->pending_cmd->send_ss.alpha_id &&
+ stk->pending_cmd->send_ss.alpha_id[0])
+ stk_alpha_id_unset(stk);
+
+ if (stk_respond(stk, &rsp, stk_command_cb))
+ stk_command_cb(&oe, stk);
+}
+
+static gboolean handle_command_send_ss(const struct stk_command *cmd,
+ struct stk_response *rsp,
+ struct ofono_stk *stk)
+{
+ struct ofono_modem *modem = __ofono_atom_get_modem(stk->atom);
+ char *str = cmd->send_ss.ss.ss;
+ struct ofono_atom *ussd_atom;
+ struct ofono_ussd *ussd;
+ int result;
+ struct ofono_ss_req *osr;
+
+ ussd_atom = __ofono_modem_find_atom(modem, OFONO_ATOM_TYPE_USSD);
+
+ if (!ussd_atom || !__ofono_atom_get_registered(ussd_atom))
+ return set_result_type(rsp, STK_RESULT_TYPE_NOT_CAPABLE);
+
+ ussd = __ofono_atom_get_data(ussd_atom);
+
+ if (__ofono_ussd_is_busy(ussd))
+ return set_result_type(rsp, STK_RESULT_TYPE_TERMINAL_BUSY);
+
+ if (strlen(str) == 0)
+ return set_result_type(rsp,
+ STK_RESULT_TYPE_COMMAND_NOT_UNDERSTOOD);
+
+ osr = g_try_new0(struct ofono_ss_req, 1);
+ if (!osr)
+ return set_result_type(rsp, STK_RESULT_TYPE_NOT_CAPABLE);
+
+ osr->stk = TRUE;
+
+ result = __ofono_ussd_recognized_control_string(ussd, str, osr);
+ g_free(osr);
+
+ switch (result) {
+ case EBUSY:
+ return set_result_type(rsp, STK_RESULT_TYPE_TERMINAL_BUSY);
+ case ENOSYS:
+ case ENOMEM:
+ return set_result_type(rsp, STK_RESULT_TYPE_NOT_CAPABLE);
+ case 0:
+ break;
+ case EINVAL:
+ default:
+ return set_result_type(rsp,
+ STK_RESULT_TYPE_COMMAND_NOT_UNDERSTOOD);
+ }
+
+ if (cmd->send_ss.alpha_id && cmd->send_ss.alpha_id[0])
+ stk_alpha_id_set(stk, cmd->send_ss.alpha_id);
+
+ return FALSE;
+}
+
static gboolean handle_command_set_idle_text(const struct stk_command *cmd,
struct stk_response *rsp,
struct ofono_stk *stk)
@@ -1696,6 +1789,11 @@ void ofono_stk_proactive_command_notify(struct ofono_stk *stk,
&rsp, stk);
break;
+ case STK_COMMAND_TYPE_SEND_SS:
+ respond = handle_command_send_ss(stk->pending_cmd,
+ &rsp, stk);
+ break;
+
case STK_COMMAND_TYPE_SETUP_IDLE_MODE_TEXT:
respond = handle_command_set_idle_text(stk->pending_cmd,
&rsp, stk);
diff --git a/src/stkutil.c b/src/stkutil.c
index 3cfe06a..e21698b 100644
--- a/src/stkutil.c
+++ b/src/stkutil.c
@@ -5441,6 +5441,8 @@ const unsigned char *stk_pdu_from_response(const struct stk_response
*response,
&response->select_item.item_id,
NULL);
break;
+ case STK_COMMAND_TYPE_SEND_SS:
+ break;
case STK_COMMAND_TYPE_SETUP_CALL:
ok = build_setup_call(&builder, response);
break;
diff --git a/src/stkutil.h b/src/stkutil.h
index c432df8..2b8f53a 100644
--- a/src/stkutil.h
+++ b/src/stkutil.h
@@ -254,6 +254,8 @@ enum stk_result_type {
STK_RESULT_TYPE_COMMAND_NOT_UNDERSTOOD = 0x31,
STK_RESULT_TYPE_DATA_NOT_UNDERSTOOD = 0x32,
STK_RESULT_TYPE_COMMAND_ID_UNKNOWN = 0x33,
+ STK_RESULT_TYPE_SS_RETURN_ERROR = 0x34,
+ STK_RESULT_TYPE_SMS_RP_ERROR = 0x35,
STK_RESULT_TYPE_MINIMUM_NOT_MET = 0x36,
STK_RESULT_TYPE_USSD_RETURN_ERROR = 0x37,
STK_RESULT_TYPE_CALL_CONTROL_PERMANENT = 0x39,
@@ -263,6 +265,27 @@ enum stk_result_type {
STK_RESULT_TYPE_MMS_ERROR = 0x3D,
};
+enum stk_result_addnl_me_pb_fb {
+ STK_RESULT_ADDNL_ME_PB_NO_SPECIFIC_CAUSE = 0x00,
+ STK_RESULT_ADDNL_ME_PB_SCREEN_BUSY = 0x01,
+ STK_RESULT_ADDNL_ME_PB_BUSY_ON_CALL = 0x02,
+ STK_RESULT_ADDNL_ME_PB_NO_SERVICE = 0x04,
+ STK_RESULT_ADDNL_ME_PB_NO_ACCESS = 0x05,
+ STK_RESULT_ADDNL_ME_PB_NO_RADIO_RESOURCE = 0x06,
+ STK_RESULT_ADDNL_ME_PB_NOT_IN_SPEECH_CALL = 0x07,
+ STK_RESULT_ADDNL_ME_PB_BUSY_ON_SEND_DTMF = 0x09,
+ STK_RESULT_ADDNL_ME_PB_NO_NAA_ACTIVE = 0x0A
+};
+
+enum stk_result_addnl_me_pb_ob {
+ STK_RESULT_ADDNL_ME_PB_SS_BUSY = 0x03,
+ STK_RESULT_ADDNL_ME_PB_USSD_BUSY = 0x08
+};
+
+enum stk_result_addnl_ss_pb_ob {
+ STK_RESULT_ADDNL_SS_PB_NO_SPECIFIC_CAUSE = 0x00
+};
+
enum stk_tone_type {
STK_TONE_TYPE_DIAL_TONE = 0x01,
STK_TONE_TYPE_BUSY_TONE = 0x02,
diff --git a/src/ussd.c b/src/ussd.c
index fbb07d2..7e8d1c8 100644
--- a/src/ussd.c
+++ b/src/ussd.c
@@ -182,11 +182,10 @@ void __ofono_ussd_passwd_unregister(struct ofono_ussd *ussd, const
char *sc)
ussd->ss_passwd_list = g_slist_remove(ussd->ss_passwd_list, l->data);
}
-static gboolean recognized_passwd_change_string(struct ofono_ussd *ussd,
- int type, char *sc,
- char *sia, char *sib,
- char *sic, char *sid,
- char *dn, DBusMessage *msg)
+static int recognized_passwd_change_string(struct ofono_ussd *ussd, int type,
+ char *sc, char *sia, char *sib,
+ char *sic, char *sid, char *dn,
+ struct ofono_ss_req *osr)
{
GSList *l = ussd->ss_passwd_list;
@@ -196,42 +195,40 @@ static gboolean recognized_passwd_change_string(struct ofono_ussd
*ussd,
break;
default:
- return FALSE;
+ return -ENOENT;
}
if (strcmp(sc, "03") || strlen(dn))
- return FALSE;
+ return -ENOENT;
/* If SIC & SID don't match, then we just bail out here */
- if (strcmp(sic, sid)) {
- DBusConnection *conn = ofono_dbus_get_connection();
- DBusMessage *reply = __ofono_error_invalid_format(msg);
- g_dbus_send_message(conn, reply);
- return TRUE;
- }
+ if (strcmp(sic, sid))
+ return EINVAL;
while ((l = g_slist_find_custom(l, sia,
ssc_entry_find_by_service)) != NULL) {
struct ssc_entry *entry = l->data;
ofono_ussd_passwd_cb_t cb = entry->cb;
+ int result = cb(sia, sib, sic, osr, entry->user);
- if (cb(sia, sib, sic, msg, entry->user))
- return TRUE;
+ if (result >= 0)
+ return result;
l = l->next;
}
- return FALSE;
+ return -ENOENT;
}
-static gboolean recognized_control_string(struct ofono_ussd *ussd,
+int __ofono_ussd_recognized_control_string(struct ofono_ussd *ussd,
const char *ss_str,
- DBusMessage *msg)
+ struct ofono_ss_req *osr)
{
char *str = g_strdup(ss_str);
char *sc, *sia, *sib, *sic, *sid, *dn;
int type;
- gboolean ret = FALSE;
+ int ret = -ENOENT;
+ int result;
DBG("parsing control string");
@@ -245,9 +242,11 @@ static gboolean recognized_control_string(struct ofono_ussd *ussd,
/* A password change string needs to be treated separately
* because it uses a fourth SI and is thus not a valid
* control string. */
- if (recognized_passwd_change_string(ussd, type, sc,
- sia, sib, sic, sid, dn, msg)) {
- ret = TRUE;
+ result = recognized_passwd_change_string(ussd, type, sc,
+ sia, sib, sic, sid, dn, osr);
+
+ if (result >= 0) {
+ ret = result;
goto out;
}
@@ -259,8 +258,11 @@ static gboolean recognized_control_string(struct ofono_ussd *ussd,
struct ssc_entry *entry = l->data;
ofono_ussd_ssc_cb_t cb = entry->cb;
- if (cb(type, sc, sia, sib, sic, dn, msg, entry->user)) {
- ret = TRUE;
+ result = cb(type, sc, sia, sib, sic, dn, osr,
+ entry->user);
+
+ if (result >= 0) {
+ ret = result;
goto out;
}
@@ -447,6 +449,8 @@ static DBusMessage *ussd_initiate(DBusConnection *conn, DBusMessage
*msg,
{
struct ofono_ussd *ussd = data;
const char *str;
+ int result;
+ struct ofono_ss_req *osr;
if (ussd->pending)
return __ofono_error_busy(msg);
@@ -462,8 +466,30 @@ static DBusMessage *ussd_initiate(DBusConnection *conn, DBusMessage
*msg,
return __ofono_error_invalid_format(msg);
DBG("checking if this is a recognized control string");
- if (recognized_control_string(ussd, str, msg))
- return NULL;
+
+ osr = g_try_new0(struct ofono_ss_req, 1);
+ if (!osr)
+ return __ofono_error_failed(msg);
+
+ osr->msg = msg;
+
+ result = __ofono_ussd_recognized_control_string(ussd, str, osr);
+ g_free(osr);
+
+ if (result >= 0) {
+ switch (result) {
+ case EBUSY:
+ return __ofono_error_busy(msg);
+ case EINVAL:
+ return __ofono_error_invalid_format(msg);
+ case ENOSYS:
+ return __ofono_error_not_implemented(msg);
+ case ENOMEM:
+ return __ofono_error_failed(msg);
+ default:
+ return NULL;
+ }
+ }
DBG("No.., checking if this is a USSD string");
if (!valid_ussd_string(str))
--
1.7.0.4