From: Pekka Pessi <pekka.pe...@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

_______________________________________________
ofono mailing list
ofono@ofono.org
http://lists.ofono.org/listinfo/ofono

Reply via email to