From: Pekka Pessi <Pekka.Pessi(a)nokia.com>
Watch supplementary service notifications from barring services, remote
party putting call on hold, retrieving or join call into a multiparty
conference.
The barring indications augment the DisconnectReason and they contain
additional information about the reason why a call is rejected or why it
is not connected.
---
src/voicecall.c | 147 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 147 insertions(+), 0 deletions(-)
diff --git a/src/voicecall.c b/src/voicecall.c
index 6246787..e176e02 100644
--- a/src/voicecall.c
+++ b/src/voicecall.c
@@ -52,6 +52,12 @@ struct ofono_voicecall {
struct ofono_sim *sim;
unsigned int sim_watch;
unsigned int sim_state_watch;
+ struct ofono_ssn *ssn;
+ unsigned int ssn_watch;
+ unsigned int ssn_hold_watch;
+ unsigned int ssn_retrieve_watch;
+ unsigned int ssn_mpty_watch;
+ unsigned int ssn_wait_watch;
const struct ofono_voicecall_driver *driver;
void *driver_data;
struct ofono_atom *atom;
@@ -69,6 +75,7 @@ struct voicecall {
uint8_t icon_id;
gboolean untracked;
gboolean dial_result_handled;
+ dbus_bool_t mt_hold;
};
struct dial_request {
@@ -399,6 +406,8 @@ static void append_voicecall_properties(struct voicecall *v,
ofono_dbus_dict_append(dict, "Multiparty", DBUS_TYPE_BOOLEAN, &mpty);
+ ofono_dbus_dict_append(dict, "OnHold", DBUS_TYPE_BOOLEAN,
&v->mt_hold);
+
if (v->message)
ofono_dbus_dict_append(dict, "Information",
DBUS_TYPE_STRING, &v->message);
@@ -655,6 +664,19 @@ static const char *voicecall_build_path(struct ofono_voicecall *vc,
return path;
}
+static struct voicecall *voicecall_by_id(struct ofono_voicecall *vc, int id)
+{
+ GSList *l;
+
+ l = g_slist_find_custom(vc->call_list, GUINT_TO_POINTER(id),
+ call_compare_by_id);
+ if (l == NULL)
+ return NULL;
+
+ return l->data;
+}
+
+
static void voicecall_emit_disconnect_reason(struct voicecall *call,
enum ofono_disconnect_reason reason)
{
@@ -2181,6 +2203,19 @@ static void voicecall_unregister(struct ofono_atom *atom)
vc->sim_watch = 0;
}
+ if (vc->ssn_watch) {
+ __ofono_modem_remove_atom_watch(modem, vc->ssn_watch);
+ vc->ssn_watch = 0;
+ }
+
+ if (vc->ssn) {
+ __ofono_ssn_mt_watch_remove(vc->ssn, vc->ssn_hold_watch);
+ __ofono_ssn_mt_watch_remove(vc->ssn, vc->ssn_retrieve_watch);
+ __ofono_ssn_mt_watch_remove(vc->ssn, vc->ssn_mpty_watch);
+ __ofono_ssn_mt_watch_remove(vc->ssn, vc->ssn_wait_watch);
+ vc->ssn = NULL;
+ }
+
if (vc->dial_req)
dial_request_finish(vc);
@@ -2278,6 +2313,108 @@ struct ofono_voicecall *ofono_voicecall_create(struct ofono_modem
*modem,
return vc;
}
+static void ssn_mo_watch(int index, int mo_code, void *user)
+{
+ struct ofono_voicecall *vc = user;
+ struct voicecall *call;
+ DBusConnection *conn;
+ char const *path;
+ char const *member;
+
+ call = voicecall_by_id(vc, index);
+ if (call == NULL) {
+ ofono_error("Got MO SSN notify %u for unknown call", mo_code);
+ return;
+ }
+
+ conn = ofono_dbus_get_connection();
+ path = voicecall_build_path(vc, call->call);
+
+ switch (mo_code) {
+ case OFONO_SS_MO_CALL_WAITING:
+ member = "Waiting";
+ break;
+ case OFONO_SS_MO_INCOMING_BARRING:
+ member = "IncomingBarred";
+ break;
+ case OFONO_SS_MO_OUTGOING_BARRING:
+ member = "OutgoingBarred";
+ break;
+ default:
+ return;
+ }
+
+ g_dbus_emit_signal(conn, path, OFONO_VOICECALL_INTERFACE,
+ member, DBUS_TYPE_INVALID);
+}
+
+static void ssn_mt_watch(int index, int mt_code,
+ const struct ofono_phone_number *ph,
+ void *user)
+{
+ struct ofono_voicecall *vc = user;
+ struct voicecall *call;
+ DBusConnection *conn;
+ char const *path;
+ dbus_bool_t mt_hold;
+
+ call = voicecall_by_id(vc, index);
+ if (call == NULL) {
+ ofono_error("Got MT SSN notify %u for unknown call", mt_code);
+ return;
+ }
+
+ conn = ofono_dbus_get_connection();
+ path = voicecall_build_path(vc, call->call);
+
+ switch (mt_code) {
+ case OFONO_SS_MT_VOICECALL_ON_HOLD:
+ call->mt_hold = mt_hold = TRUE;
+ break;
+
+ case OFONO_SS_MT_VOICECALL_RETRIEVED:
+ call->mt_hold = mt_hold = FALSE;
+ break;
+
+ case OFONO_SS_MT_MULTIPARTY_VOICECALL:
+ g_dbus_emit_signal(conn, path, OFONO_VOICECALL_INTERFACE,
+ "JoinedMultiparty", DBUS_TYPE_INVALID);
+ return;
+
+ default:
+ return;
+ }
+
+ ofono_dbus_signal_property_changed(conn, path,
+ OFONO_VOICECALL_INTERFACE, "OnHold",
+ DBUS_TYPE_BOOLEAN, &mt_hold);
+}
+
+static void ssn_watch(struct ofono_atom *atom,
+ enum ofono_atom_watch_condition cond, void *data)
+{
+ struct ofono_voicecall *vc = data;
+
+ if (cond == OFONO_ATOM_WATCH_CONDITION_UNREGISTERED) {
+ vc->ssn = NULL;
+ return;
+ }
+
+ vc->ssn = __ofono_atom_get_data(atom);
+
+ vc->ssn_hold_watch = __ofono_ssn_mt_watch_add(vc->ssn,
+ OFONO_SS_MT_VOICECALL_ON_HOLD, ssn_mt_watch, vc, NULL);
+
+ vc->ssn_retrieve_watch = __ofono_ssn_mt_watch_add(vc->ssn,
+ OFONO_SS_MT_VOICECALL_RETRIEVED, ssn_mt_watch, vc, NULL);
+
+ vc->ssn_mpty_watch = __ofono_ssn_mt_watch_add(vc->ssn,
+ OFONO_SS_MT_MULTIPARTY_VOICECALL, ssn_mt_watch, vc, NULL);
+
+ vc->ssn_wait_watch = __ofono_ssn_mo_watch_add(vc->ssn,
+ OFONO_SS_MO_CALL_WAITING, ssn_mo_watch, vc, NULL);
+}
+
static void sim_state_watch(enum ofono_sim_state new_state, void *user)
{
struct ofono_voicecall *vc = user;
@@ -2338,6 +2475,7 @@ void ofono_voicecall_register(struct ofono_voicecall *vc)
struct ofono_modem *modem = __ofono_atom_get_modem(vc->atom);
const char *path = __ofono_atom_get_path(vc->atom);
struct ofono_atom *sim_atom;
+ struct ofono_atom *ssn_atom;
if (!g_dbus_register_interface(conn, path,
OFONO_VOICECALL_MANAGER_INTERFACE,
@@ -2367,6 +2505,15 @@ void ofono_voicecall_register(struct ofono_voicecall *vc)
if (sim_atom && __ofono_atom_get_registered(sim_atom))
sim_watch(sim_atom, OFONO_ATOM_WATCH_CONDITION_REGISTERED, vc);
+ vc->ssn_watch = __ofono_modem_add_atom_watch(modem,
+ OFONO_ATOM_TYPE_SSN,
+ ssn_watch, vc, NULL);
+
+ ssn_atom = __ofono_modem_find_atom(modem, OFONO_ATOM_TYPE_SIM);
+
+ if (ssn_atom && __ofono_atom_get_registered(ssn_atom))
+ ssn_watch(ssn_atom, OFONO_ATOM_WATCH_CONDITION_REGISTERED, vc);
+
__ofono_atom_register(vc->atom, voicecall_unregister);
}
--
1.7.1