Evolve message waiting low level API
authorDenis Kenzior <denkenz@gmail.com>
Wed, 19 Aug 2009 02:07:44 +0000 (21:07 -0500)
committerDenis Kenzior <denkenz@gmail.com>
Wed, 19 Aug 2009 23:35:07 +0000 (18:35 -0500)
include/Makefile.am
include/message-waiting.h [new file with mode: 0644]
src/message-waiting.c
src/ofono.h
src/sms.c

index 133dda3..207ce7b 100644 (file)
@@ -4,7 +4,7 @@ includedir = @includedir@/ofono
 include_HEADERS = log.h plugin.h history.h dbus.h modem.h \
                        types.h call-barring.h call-forwarding.h \
                        call-meter.h call-settings.h phonebook.h \
-                       ssn.h ussd.h sms.h sim.h
+                       ssn.h ussd.h sms.h sim.h message-waiting.h
 
 nodist_include_HEADERS = version.h
 
diff --git a/include/message-waiting.h b/include/message-waiting.h
new file mode 100644 (file)
index 0000000..e0dd930
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ *
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2008-2009  Intel Corporation. All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef __OFONO_MESSAGE_WAITING_H
+#define __OFONO_MESSAGE_WAITING_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <ofono/types.h>
+
+struct ofono_message_waiting;
+
+struct ofono_message_waiting *ofono_message_waiting_create(struct ofono_modem *modem);
+void ofono_message_waiting_register(struct ofono_message_waiting *mw);
+void ofono_message_waiting_remove(struct ofono_message_waiting *mw);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __OFONO_MESSAGE_WAITING_H */
index b41705a..ff7df4c 100644 (file)
@@ -34,7 +34,6 @@
 
 #include "ofono.h"
 
-#include "driver.h"
 #include "common.h"
 #include "util.h"
 #include "simutil.h"
@@ -47,7 +46,7 @@ struct mailbox_state {
        unsigned char message_count;
 };
 
-struct message_waiting_data {
+struct ofono_message_waiting {
        struct mailbox_state messages[5];
        unsigned char efmwis_length;
        unsigned char efmbdn_length;
@@ -56,42 +55,16 @@ struct message_waiting_data {
        struct ofono_sim *sim;
        unsigned int sim_watch;
        unsigned int sim_ready_watch;
+       struct ofono_atom *atom;
 };
 
 struct mbdn_set_request {
-       struct ofono_modem *modem;
-       struct message_waiting_data *mw;
+       struct ofono_message_waiting *mw;
        int mailbox;
        struct ofono_phone_number number;
        DBusMessage *msg;
 };
 
-static struct message_waiting_data *message_waiting_create()
-{
-       return g_try_new0(struct message_waiting_data, 1);
-}
-
-static void message_waiting_destroy(gpointer userdata)
-{
-       struct ofono_modem *modem = userdata;
-       struct message_waiting_data *data = modem->message_waiting;
-
-       if (data->sim_watch) {
-               __ofono_modem_remove_atom_watch(modem, data->sim_watch);
-               data->sim_watch = 0;
-       }
-
-       if (data->sim_ready_watch) {
-               ofono_sim_remove_ready_watch(data->sim, data->sim_ready_watch);
-               data->sim_ready_watch = 0;
-               data->sim = NULL;
-       }
-
-       g_free(data);
-
-       modem->message_waiting = NULL;
-}
-
 static const char *mw_message_waiting_property_name[5] = {
        "VoicemailWaiting",
 #if 0
@@ -125,8 +98,7 @@ static const char *mw_mailbox_property_name[5] = {
 static DBusMessage *mw_get_properties(DBusConnection *conn,
                                        DBusMessage *msg, void *data)
 {
-       struct ofono_modem *modem = data;
-       struct message_waiting_data *mw = modem->message_waiting;
+       struct ofono_message_waiting *mw = data;
        DBusMessage *reply;
        DBusMessageIter iter;
        DBusMessageIter dict;
@@ -199,11 +171,12 @@ static void mbdn_set_cb(int ok, void *data)
 
        if (property) {
                DBusConnection *conn = ofono_dbus_get_connection();
+               const char *path = __ofono_atom_get_path(req->mw->atom);
                const char *number;
 
                number = phone_number_to_string(old);
 
-               ofono_dbus_signal_property_changed(conn, req->modem->path,
+               ofono_dbus_signal_property_changed(conn, path,
                                                MESSAGE_WAITING_INTERFACE,
                                                property, DBUS_TYPE_STRING,
                                                &number);
@@ -219,13 +192,13 @@ out:
        g_free(req);
 }
 
-static DBusMessage *set_mbdn(struct ofono_modem *modem, int mailbox,
+static DBusMessage *set_mbdn(struct ofono_message_waiting *mw, int mailbox,
                        const char *number, DBusMessage *msg)
 {
        struct mbdn_set_request *req;
        unsigned char efmbdn[255];
 
-       if (modem->message_waiting->efmbdn_record_id[mailbox] == 0) {
+       if (mw->efmbdn_record_id[mailbox] == 0) {
                if (msg)
                        return __ofono_error_failed(msg);
 
@@ -234,8 +207,7 @@ static DBusMessage *set_mbdn(struct ofono_modem *modem, int mailbox,
 
        req = g_new0(struct mbdn_set_request, 1);
 
-       req->modem = modem;
-       req->mw = modem->message_waiting;
+       req->mw = mw;
        req->mailbox = mailbox;
        string_to_phone_number(number, &req->number);
        req->msg = dbus_message_ref(msg);
@@ -258,8 +230,7 @@ static DBusMessage *set_mbdn(struct ofono_modem *modem, int mailbox,
 static DBusMessage *mw_set_property(DBusConnection *conn, DBusMessage *msg,
                                        void *data)
 {
-       struct ofono_modem *modem = data;
-       struct message_waiting_data *mw = modem->message_waiting;
+       struct ofono_message_waiting *mw = data;
        DBusMessageIter iter;
        DBusMessageIter var;
        const char *name, *value;
@@ -304,7 +275,7 @@ static DBusMessage *mw_set_property(DBusConnection *conn, DBusMessage *msg,
                if (g_str_equal(cur_number, value))
                        return dbus_message_new_method_return(msg);
 
-               return set_mbdn(modem, i, value, msg);
+               return set_mbdn(mw, i, value, msg);
        }
 
        return __ofono_error_invalid_args(msg);
@@ -327,13 +298,13 @@ static void mw_mwis_read_cb(int ok,
                int record, const unsigned char *data, int record_length,
                void *userdata)
 {
-       struct ofono_modem *modem = userdata;
+       struct ofono_message_waiting *mw = userdata;
        int i, status;
        struct mailbox_state info;
        dbus_bool_t indication;
        unsigned char count;
        DBusConnection *conn = ofono_dbus_get_connection();
-       struct message_waiting_data *mw = modem->message_waiting;
+       const char *path = __ofono_atom_get_path(mw->atom);
 
        if (!ok ||
                structure != OFONO_SIM_FILE_STRUCTURE_FIXED ||
@@ -368,12 +339,12 @@ static void mw_mwis_read_cb(int ok,
                        if (!mw_message_waiting_property_name[i])
                                continue;
 
-                       ofono_dbus_signal_property_changed(conn, modem->path,
+                       ofono_dbus_signal_property_changed(conn, path,
                                        MESSAGE_WAITING_INTERFACE,
                                        mw_message_waiting_property_name[i],
                                        DBUS_TYPE_BOOLEAN, &indication);
 
-                       ofono_dbus_signal_property_changed(conn, modem->path,
+                       ofono_dbus_signal_property_changed(conn, path,
                                        MESSAGE_WAITING_INTERFACE,
                                        mw_message_count_property_name[i],
                                        DBUS_TYPE_BYTE, &count);
@@ -388,10 +359,9 @@ static void mw_mbdn_read_cb(int ok,
                int record, const unsigned char *data, int record_length,
                void *userdata)
 {
-       struct ofono_modem *modem = userdata;
+       struct ofono_message_waiting *mw = userdata;
        int i;
        DBusConnection *conn = ofono_dbus_get_connection();
-       struct message_waiting_data *mw = modem->message_waiting;
        const char *value;
 
        if (!ok ||
@@ -415,9 +385,11 @@ static void mw_mbdn_read_cb(int ok,
                mw->mailbox_number[i].number[0] = '\0';
 
        if (mw_mailbox_property_name[i]) {
+               const char *path = __ofono_atom_get_path(mw->atom);
+
                value = phone_number_to_string(&mw->mailbox_number[i]);
 
-               ofono_dbus_signal_property_changed(conn, modem->path,
+               ofono_dbus_signal_property_changed(conn, path,
                                MESSAGE_WAITING_INTERFACE,
                                mw_mailbox_property_name[i],
                                DBUS_TYPE_STRING, &value);
@@ -431,9 +403,8 @@ static void mw_mbi_read_cb(int ok,
                int record, const unsigned char *data, int record_length,
                void *userdata)
 {
-       struct ofono_modem *modem = userdata;
+       struct ofono_message_waiting *mw = userdata;
        int i, err;
-       struct message_waiting_data *mw = modem->message_waiting;
 
        if (!ok ||
                structure != OFONO_SIM_FILE_STRUCTURE_FIXED ||
@@ -452,7 +423,7 @@ static void mw_mbi_read_cb(int ok,
        for (i = 0; i < 5 && i < record_length; i++)
                mw->efmbdn_record_id[i] = data[i];
 
-       err = ofono_sim_read(mw->sim, SIM_EFMBDN_FILEID, mw_mbdn_read_cb, modem);
+       err = ofono_sim_read(mw->sim, SIM_EFMBDN_FILEID, mw_mbdn_read_cb, mw);
 
        if (err != 0)
                ofono_error("Unable to read EF-MBDN from SIM");
@@ -464,30 +435,10 @@ static void mw_mwis_write_cb(int ok, void *userdata)
                ofono_error("Writing new EF-MBDN failed");
 }
 
-/* Loads MWI states and MBDN from SIM */
-static gboolean mw_mwis_load(struct ofono_modem *modem)
-{
-       struct message_waiting_data *mw = modem->message_waiting;
-       int err;
-
-       err = ofono_sim_read(mw->sim, SIM_EFMWIS_FILEID, mw_mwis_read_cb, modem);
-
-       if (err != 0)
-               return FALSE;
-
-       err = ofono_sim_read(mw->sim, SIM_EFMBI_FILEID, mw_mbi_read_cb, modem);
-
-       if (err != 0)
-               return FALSE;
-
-       return TRUE;
-}
-
-static void mw_set_indicator(struct ofono_modem *modem, int profile,
+static void mw_set_indicator(struct ofono_message_waiting *mw, int profile,
                                enum sms_mwi_type type,
                                gboolean present, unsigned char messages)
 {
-       struct message_waiting_data *mw = modem->message_waiting;
        DBusConnection *conn = ofono_dbus_get_connection();
        unsigned char efmwis[255];  /* Max record size */
        int i;
@@ -505,22 +456,25 @@ static void mw_set_indicator(struct ofono_modem *modem, int profile,
 
        if (mw->messages[type].indication != present) {
                dbus_bool_t indication;
+               const char *path = __ofono_atom_get_path(mw->atom);
 
                indication = present;
                mw->messages[type].indication = present;
 
                if (!mw_message_waiting_property_name[type])
-                       ofono_dbus_signal_property_changed(conn, modem->path,
+                       ofono_dbus_signal_property_changed(conn, path,
                                        MESSAGE_WAITING_INTERFACE,
                                        mw_message_waiting_property_name[type],
                                        DBUS_TYPE_BOOLEAN, &indication);
        }
 
        if (mw->messages[type].message_count != messages) {
+               const char *path = __ofono_atom_get_path(mw->atom);
+
                mw->messages[type].message_count = messages;
 
                if (!mw_message_waiting_property_name[type])
-                       ofono_dbus_signal_property_changed(conn, modem->path,
+                       ofono_dbus_signal_property_changed(conn, path,
                                        MESSAGE_WAITING_INTERFACE,
                                        mw_message_count_property_name[type],
                                        DBUS_TYPE_BYTE, &messages);
@@ -543,95 +497,13 @@ static void mw_set_indicator(struct ofono_modem *modem, int profile,
 
        if (ofono_sim_write(mw->sim, SIM_EFMWIS_FILEID, mw_mwis_write_cb,
                                OFONO_SIM_FILE_STRUCTURE_FIXED, 1,
-                               efmwis, mw->efmwis_length, modem) != 0) {
+                               efmwis, mw->efmwis_length, mw) != 0) {
                ofono_error("Queuing a EF-MWI write to SIM failed");
        }
 }
 
-static void initialize_message_waiting(void *user_data)
-{
-       struct ofono_modem *modem = user_data;
-       DBusConnection *conn = ofono_dbus_get_connection();
-
-       if (!mw_mwis_load(modem)) {
-               ofono_error("Could not register MessageWaiting interface");
-               message_waiting_destroy(modem);
-
-               return;
-       }
-
-       if (!g_dbus_register_interface(conn, modem->path,
-                                       MESSAGE_WAITING_INTERFACE,
-                                       message_waiting_methods,
-                                       message_waiting_signals,
-                                       NULL, modem,
-                                       message_waiting_destroy)) {
-               ofono_error("Could not register MessageWaiting interface");
-               message_waiting_destroy(modem);
-
-               return;
-       }
-
-       ofono_debug("MessageWaiting interface for modem: %s created",
-                       modem->path);
-
-       ofono_modem_add_interface(modem, MESSAGE_WAITING_INTERFACE);
-}
-
-static void sim_watch(struct ofono_atom *atom,
-                       enum ofono_atom_watch_condition cond, void *data)
-{
-       struct ofono_modem *modem = data;
-       struct message_waiting_data *mw = modem->message_waiting;
-
-       if (cond == OFONO_ATOM_WATCH_CONDITION_UNREGISTERED) {
-               mw->sim = NULL;
-               mw->sim_ready_watch = 0;
-               return;
-       }
-
-       mw->sim = __ofono_atom_get_data(atom);
-       mw->sim_ready_watch = ofono_sim_add_ready_watch(mw->sim,
-                               initialize_message_waiting, modem, NULL);
-
-       if (ofono_sim_get_ready(mw->sim))
-               initialize_message_waiting(modem);
-}
-
-int ofono_message_waiting_register(struct ofono_modem *modem)
-{
-       struct message_waiting_data *mw;
-       struct ofono_atom *sim_atom;
-
-       if (modem == NULL)
-               return -1;
-
-       mw = message_waiting_create();
-       modem->message_waiting = mw;
-
-       mw->sim_watch = __ofono_modem_add_atom_watch(modem,
-                                       OFONO_ATOM_TYPE_SIM,
-                                       sim_watch, modem, NULL);
-
-       sim_atom = __ofono_modem_find_atom(modem, OFONO_ATOM_TYPE_SIM);
-
-       if (sim_atom && __ofono_atom_get_registered(sim_atom))
-               sim_watch(sim_atom, OFONO_ATOM_WATCH_CONDITION_REGISTERED,
-                               modem);
-       return 0;
-}
-
-void ofono_message_waiting_unregister(struct ofono_modem *modem)
-{
-       DBusConnection *conn = ofono_dbus_get_connection();
-
-       g_dbus_unregister_interface(conn, modem->path,
-                                       MESSAGE_WAITING_INTERFACE);
-       ofono_modem_remove_interface(modem, MESSAGE_WAITING_INTERFACE);
-}
-
-static void handle_special_sms_iei(struct ofono_modem *modem,
-               const guint8 *iei, gboolean *discard)
+static void handle_special_sms_iei(struct ofono_message_waiting *mw,
+                                       const guint8 *iei, gboolean *discard)
 {
        enum sms_mwi_type type;
        int profile;
@@ -656,11 +528,12 @@ static void handle_special_sms_iei(struct ofono_modem *modem,
        set = iei[1] > 0 ? TRUE : FALSE;
        profile = ((iei[0] >> 5) & 3) + 1;
 
-       mw_set_indicator(modem, profile, type, set, iei[1]);
+       mw_set_indicator(mw, profile, type, set, iei[1]);
 }
 
-static void handle_enhanced_voicemail_iei(struct ofono_modem *modem,
-               const guint8 *iei, gboolean *discard, int length)
+static void handle_enhanced_voicemail_iei(struct ofono_message_waiting *mw,
+                                               const guint8 *iei,
+                                               gboolean *discard, int length)
 {
        int profile, n;
        gboolean set;
@@ -691,7 +564,7 @@ static void handle_enhanced_voicemail_iei(struct ofono_modem *modem,
                /* Other parameters currently not supported */
 
                set = iei[n + 2] > 0 ? TRUE : FALSE;
-               mw_set_indicator(modem, profile, SMS_MWI_TYPE_VOICE,
+               mw_set_indicator(mw, profile, SMS_MWI_TYPE_VOICE,
                                        set, iei[n + 2]);
        } else {
                /* 9.2.3.24.13.2 Enhanced Voice Delete Confirmation */
@@ -712,17 +585,17 @@ static void handle_enhanced_voicemail_iei(struct ofono_modem *modem,
                /* Other parameters currently not supported */
 
                set = iei[n + 2] > 0 ? TRUE : FALSE;
-               mw_set_indicator(modem, profile, SMS_MWI_TYPE_VOICE,
+               mw_set_indicator(mw, profile, SMS_MWI_TYPE_VOICE,
                                        set, iei[n + 2]);
        }
 
        if (mailbox_address.address[0] != '\0')
-               set_mbdn(modem, SMS_MWI_TYPE_VOICE,
+               set_mbdn(mw, SMS_MWI_TYPE_VOICE,
                                sms_address_to_string(&mailbox_address), NULL);
 }
 
-void ofono_handle_sms_mwi(struct ofono_modem *modem,
-               struct sms *sms, gboolean *out_discard)
+void __ofono_message_waiting_mwi(struct ofono_message_waiting *mw,
+                                       struct sms *sms, gboolean *out_discard)
 {
        gboolean active, discard;
        enum sms_mwi_type type;
@@ -749,7 +622,7 @@ void ofono_handle_sms_mwi(struct ofono_modem *modem,
                        case SMS_IEI_ENHANCED_VOICE_MAIL_INFORMATION:
                                sms_udh_iter_get_ie_data(&iter, evm_iei);
 
-                               handle_enhanced_voicemail_iei(modem, evm_iei,
+                               handle_enhanced_voicemail_iei(mw, evm_iei,
                                                out_discard,
                                                sms_udh_iter_get_ie_length(
                                                        &iter));
@@ -778,7 +651,7 @@ void ofono_handle_sms_mwi(struct ofono_modem *modem,
                                        break;
                                sms_udh_iter_get_ie_data(&iter, special_iei);
 
-                               handle_special_sms_iei(modem, special_iei,
+                               handle_special_sms_iei(mw, special_iei,
                                                &discard);
                                if (out_discard)
                                        *out_discard = *out_discard || discard;
@@ -810,7 +683,7 @@ void ofono_handle_sms_mwi(struct ofono_modem *modem,
 
        if (sms_mwi_dcs_decode(sms->deliver.dcs, &type,
                                NULL, &active, out_discard)) {
-               mw_set_indicator(modem, profile, type, active, 0);
+               mw_set_indicator(mw, profile, type, active, 0);
 
                return;
        }
@@ -818,3 +691,119 @@ void ofono_handle_sms_mwi(struct ofono_modem *modem,
        if (sms->deliver.pid == SMS_PID_TYPE_RETURN_CALL)
                return;
 }
+
+static void message_waiting_sim_ready(void *userdata)
+{
+       struct ofono_message_waiting *mw = userdata;
+
+       /* Loads MWI states and MBDN from SIM */
+       ofono_sim_read(mw->sim, SIM_EFMWIS_FILEID, mw_mwis_read_cb, mw);
+       ofono_sim_read(mw->sim, SIM_EFMBI_FILEID, mw_mbi_read_cb, mw);
+}
+
+static void message_waiting_unregister(struct ofono_atom *atom)
+{
+       struct ofono_message_waiting *mw = __ofono_atom_get_data(atom);
+       DBusConnection *conn = ofono_dbus_get_connection();
+       struct ofono_modem *modem = __ofono_atom_get_modem(atom);
+       const char *path = __ofono_atom_get_path(atom);
+
+       if (mw->sim_watch) {
+               __ofono_modem_remove_atom_watch(modem, mw->sim_watch);
+               mw->sim_watch = 0;
+       }
+
+       if (mw->sim_ready_watch) {
+               ofono_sim_remove_ready_watch(mw->sim, mw->sim_ready_watch);
+               mw->sim_ready_watch = 0;
+               mw->sim = NULL;
+       }
+
+       g_dbus_unregister_interface(conn, path,
+                                       MESSAGE_WAITING_INTERFACE);
+       ofono_modem_remove_interface(modem, MESSAGE_WAITING_INTERFACE);
+}
+
+static void sim_watch(struct ofono_atom *atom,
+                       enum ofono_atom_watch_condition cond, void *data)
+{
+       struct ofono_message_waiting *mw = data;
+
+       if (cond == OFONO_ATOM_WATCH_CONDITION_UNREGISTERED) {
+               mw->sim = NULL;
+               mw->sim_ready_watch = 0;
+               return;
+       }
+
+       mw->sim = __ofono_atom_get_data(atom);
+       mw->sim_ready_watch = ofono_sim_add_ready_watch(mw->sim,
+                               message_waiting_sim_ready, mw, NULL);
+
+       if (ofono_sim_get_ready(mw->sim))
+               message_waiting_sim_ready(mw);
+}
+
+void ofono_message_waiting_register(struct ofono_message_waiting *mw)
+{
+       DBusConnection *conn = ofono_dbus_get_connection();
+       const char *path = __ofono_atom_get_path(mw->atom);
+       struct ofono_modem *modem = __ofono_atom_get_modem(mw->atom);
+       struct ofono_atom *sim_atom;
+
+       if (!g_dbus_register_interface(conn, path,
+                                       MESSAGE_WAITING_INTERFACE,
+                                       message_waiting_methods,
+                                       message_waiting_signals,
+                                       NULL, mw, NULL)) {
+               ofono_error("Could not create %s interface",
+                               MESSAGE_WAITING_INTERFACE);
+               return;
+       }
+
+       ofono_modem_add_interface(modem, MESSAGE_WAITING_INTERFACE);
+
+       mw->sim_watch = __ofono_modem_add_atom_watch(modem,
+                                       OFONO_ATOM_TYPE_SIM,
+                                       sim_watch, mw, NULL);
+
+       sim_atom = __ofono_modem_find_atom(modem, OFONO_ATOM_TYPE_SIM);
+
+       if (sim_atom && __ofono_atom_get_registered(sim_atom))
+               sim_watch(sim_atom, OFONO_ATOM_WATCH_CONDITION_REGISTERED, mw);
+
+       __ofono_atom_register(mw->atom, message_waiting_unregister);
+}
+
+static void mw_remove(struct ofono_atom *atom)
+{
+       struct ofono_message_waiting *mw = __ofono_atom_get_data(atom);
+       struct ofono_modem *modem = __ofono_atom_get_modem(atom);
+
+       DBG("atom: %p", atom);
+
+       if (mw == NULL)
+               return;
+
+       g_free(mw);
+}
+
+struct ofono_message_waiting *ofono_message_waiting_create(struct ofono_modem *modem)
+{
+       struct ofono_message_waiting *mw;
+
+       mw = g_try_new0(struct ofono_message_waiting, 1);
+
+       if (mw == NULL)
+               return NULL;
+
+       mw->atom = __ofono_modem_add_atom(modem,
+                                       OFONO_ATOM_TYPE_MESSAGE_WAITING,
+                                       mw_remove, mw);
+
+       return mw;
+}
+
+void ofono_message_waiting_remove(struct ofono_message_waiting *mw)
+{
+       __ofono_atom_free(mw->atom);
+}
index cad840f..54c29f2 100644 (file)
@@ -99,6 +99,7 @@ enum ofono_atom_type {
        OFONO_ATOM_TYPE_VOICECALL = 10,
        OFONO_ATOM_TYPE_HISTORY = 11,
        OFONO_ATOM_TYPE_SSN = 12,
+       OFONO_ATOM_TYPE_MESSAGE_WAITING = 13,
 };
 
 enum ofono_atom_watch_condition {
@@ -196,9 +197,9 @@ void __ofono_history_call_ended(struct ofono_modem *modem,
 void __ofono_history_call_missed(struct ofono_modem *modem,
                                const struct ofono_call *call, time_t when);
 
+#include <ofono/message-waiting.h>
+
 struct sms;
 
-int ofono_message_waiting_register(struct ofono_modem *modem);
-void ofono_message_waiting_unregister(struct ofono_modem *modem);
-void ofono_handle_sms_mwi(struct ofono_modem *modem,
+void __ofono_message_waiting_mwi(struct ofono_message_waiting *mw,
                                struct sms *sms, gboolean *out_discard);
index 4c55ac2..1bb9d4c 100644 (file)
--- a/src/sms.c
+++ b/src/sms.c
@@ -55,6 +55,8 @@ struct ofono_sms {
        GQueue *txq;
        time_t last_mms;
        gint tx_source;
+       struct ofono_message_waiting *mw;
+       unsigned int mw_watch;
        const struct ofono_sms_driver *driver;
        void *driver_data;
        struct ofono_atom *atom;
@@ -616,13 +618,24 @@ static void handle_deliver(struct ofono_sms *sms, const struct sms *incoming)
        g_slist_free(l);
 }
 
+static inline gboolean handle_mwi(struct ofono_sms *sms, struct sms *s)
+{
+       gboolean discard;
+
+       if (sms->mw == NULL)
+               return FALSE;
+
+       __ofono_message_waiting_mwi(sms->mw, s, &discard);
+
+       return discard;
+}
+
 void ofono_sms_deliver_notify(struct ofono_sms *sms, unsigned char *pdu,
                                int len, int tpdu_len)
 {
        struct ofono_modem *modem = __ofono_atom_get_modem(sms->atom);
        struct sms s;
        enum sms_class cls;
-       gboolean discard;
 
        if (!sms_decode(pdu, len, FALSE, tpdu_len, &s)) {
                ofono_error("Unable to decode PDU");
@@ -642,9 +655,7 @@ void ofono_sms_deliver_notify(struct ofono_sms *sms, unsigned char *pdu,
        /* This is an older style MWI notification, process MWI
         * headers and handle it like any other message */
        if (s.deliver.pid == SMS_PID_TYPE_RETURN_CALL) {
-               ofono_handle_sms_mwi(modem, &s, &discard);
-
-               if (discard)
+               if (handle_mwi(sms, &s))
                        return;
 
                goto out;
@@ -653,9 +664,7 @@ void ofono_sms_deliver_notify(struct ofono_sms *sms, unsigned char *pdu,
        /* The DCS indicates this is an MWI notification, process it
         * and then handle the User-Data as any other message */
        if (sms_mwi_dcs_decode(s.deliver.dcs, NULL, NULL, NULL, NULL)) {
-               ofono_handle_sms_mwi(modem, &s, &discard);
-
-               if (discard)
+               if (handle_mwi(sms, &s))
                        return;
 
                goto out;
@@ -721,9 +730,7 @@ void ofono_sms_deliver_notify(struct ofono_sms *sms, unsigned char *pdu,
                                /* TODO: ignore if not in the very first
                                 * segment of a concatenated SM so as not
                                 * to repeat the indication.  */
-                               ofono_handle_sms_mwi(modem, &s, &discard);
-
-                               if (discard)
+                               if (handle_mwi(sms, &s))
                                        return;
 
                                goto out;
@@ -774,7 +781,11 @@ static void sms_unregister(struct ofono_atom *atom)
 
        g_dbus_unregister_interface(conn, path, SMS_MANAGER_INTERFACE);
        ofono_modem_remove_interface(modem, SMS_MANAGER_INTERFACE);
-       ofono_message_waiting_unregister(modem);
+
+       if (sms->mw_watch) {
+               __ofono_modem_remove_atom_watch(modem, sms->mw_watch);
+               sms->mw_watch = 0;
+       }
 }
 
 static void sms_remove(struct ofono_atom *atom)
@@ -847,11 +858,25 @@ struct ofono_sms *ofono_sms_create(struct ofono_modem *modem,
        return sms;
 }
 
+static void mw_watch(struct ofono_atom *atom,
+                       enum ofono_atom_watch_condition cond, void *data)
+{
+       struct ofono_sms *sms = data;
+
+       if (cond == OFONO_ATOM_WATCH_CONDITION_UNREGISTERED) {
+               sms->mw = NULL;
+               return;
+       }
+
+       sms->mw = __ofono_atom_get_data(atom);
+}
+
 void ofono_sms_register(struct ofono_sms *sms)
 {
        DBusConnection *conn = ofono_dbus_get_connection();
        struct ofono_modem *modem = __ofono_atom_get_modem(sms->atom);
        const char *path = __ofono_atom_get_path(sms->atom);
+       struct ofono_atom *mw_atom;
 
        if (!g_dbus_register_interface(conn, path,
                                        SMS_MANAGER_INTERFACE,
@@ -865,7 +890,15 @@ void ofono_sms_register(struct ofono_sms *sms)
 
        ofono_modem_add_interface(modem, SMS_MANAGER_INTERFACE);
 
-       ofono_message_waiting_register(modem);
+       sms->mw_watch = __ofono_modem_add_atom_watch(modem,
+                                       OFONO_ATOM_TYPE_MESSAGE_WAITING,
+                                       mw_watch, sms, NULL);
+
+       mw_atom = __ofono_modem_find_atom(modem,
+                                       OFONO_ATOM_TYPE_MESSAGE_WAITING);
+
+       if (mw_atom && __ofono_atom_get_registered(mw_atom))
+               mw_watch(mw_atom, OFONO_ATOM_WATCH_CONDITION_REGISTERED, sms);
 
        __ofono_atom_register(sms->atom, sms_unregister);
 }