* [PATCH 4/4] Add a MessageWaiting interface to track message waiting indications.
@ 2009-07-30 8:05 Andrzej Zaborowski
2009-07-31 16:19 ` Denis Kenzior
0 siblings, 1 reply; 18+ messages in thread
From: Andrzej Zaborowski @ 2009-07-30 8:05 UTC (permalink / raw)
To: ofono
[-- Attachment #1: Type: text/plain, Size: 25288 bytes --]
Comments are welcome about how the interface should look. The state of the
indications is kept in memory and written back to the SIM after any
changes.
Patch is untested because write ofono_sim_write is unimplemented, I'll add
it as a separate patch. Should it take a callback parameter?
---
src/Makefile.am | 3 +-
src/driver.h | 3 +
src/message-waiting.c | 512 +++++++++++++++++++++++++++++++++++++++++++++++++
src/message-waiting.h | 33 ++++
src/modem.h | 1 +
src/simutil.h | 3 +
src/sms.c | 216 ++++++++++++++++++++-
src/smsutil.h | 1 +
8 files changed, 765 insertions(+), 7 deletions(-)
create mode 100644 src/message-waiting.c
create mode 100644 src/message-waiting.h
diff --git a/src/Makefile.am b/src/Makefile.am
index 2fb3f06..144b872 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -13,7 +13,8 @@ ofonod_SOURCES = main.c ofono.h log.c plugin.c \
network.c voicecall.c ussd.h ussd.c sms.c \
call-settings.c call-forwarding.c call-meter.c \
smsutil.h smsutil.c cssn.h cssn.c call-barring.c sim.h sim.c \
- phonebook.c history.c simutil.h simutil.c
+ phonebook.c history.c simutil.h simutil.c \
+ message-waiting.c message-waiting.h
ofonod_LDADD = $(top_builddir)/plugins/libbuiltin.la \
$(top_builddir)/drivers/libbuiltin.la \
diff --git a/src/driver.h b/src/driver.h
index 928c20a..51e5587 100644
--- a/src/driver.h
+++ b/src/driver.h
@@ -439,3 +439,6 @@ void ofono_phonebook_entry(struct ofono_modem *modem, int index,
const char *adnumber, int adtype,
const char *secondtext, const char *email,
const char *sip_uri, const char *tel_uri);
+
+int ofono_message_waiting_register(struct ofono_modem *modem);
+void ofono_message_waiting_unregister(struct ofono_modem *modem);
diff --git a/src/message-waiting.c b/src/message-waiting.c
new file mode 100644
index 0000000..564961a
--- /dev/null
+++ b/src/message-waiting.c
@@ -0,0 +1,512 @@
+/*
+ *
+ * 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
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include <stdio.h>
+
+#include <dbus/dbus.h>
+#include <glib.h>
+#include <gdbus.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "ofono.h"
+
+#include "dbus-gsm.h"
+#include "modem.h"
+#include "driver.h"
+#include "common.h"
+#include "util.h"
+#include "sim.h"
+#include "simutil.h"
+#include "smsutil.h"
+#include "message-waiting.h"
+
+#define MESSAGE_WAITING_INTERFACE "org.ofono.MessageWaiting"
+
+struct message_waiting_data {
+ int pending;
+
+ int messages[5];
+ int efmwis_length;
+ int efmbdn_length;
+
+ struct ofono_phone_number mailbox_number[5];
+
+ char *last_message;
+};
+
+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->last_message)
+ g_free(data->last_message);
+
+ g_free(data);
+
+ modem->network_registration = NULL;
+}
+
+static const char *mw_messages_property_name[5] = {
+ "VoicemailMessages",
+#if 0
+ "FaxMessages",
+ "EmailMessages",
+ "OtherMessages",
+ "VideomailMessages",
+#endif
+};
+
+static const char *mw_mailbox_property_name[5] = {
+ "VoicemailMailboxNumber",
+#if 0
+ "FaxMailboxNumber",
+ "EmailMailboxNumber",
+ "OtherMailboxNumber",
+ "VideomailMailboxNumber",
+#endif
+};
+
+static DBusMessage *mw_get_properties(DBusConnection *conn,
+ DBusMessage *msg, void *data)
+{
+ struct ofono_modem *modem = data;
+ struct message_waiting_data *mw = modem->message_waiting;
+ DBusMessage *reply;
+ DBusMessageIter iter;
+ DBusMessageIter dict;
+ int i;
+ unsigned char value;
+ const char *number;
+
+ reply = dbus_message_new_method_return(msg);
+ if (!reply)
+ return NULL;
+
+ dbus_message_iter_init_append(reply, &iter);
+
+ dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
+ PROPERTIES_ARRAY_SIGNATURE,
+ &dict);
+
+ for (i = 0; i < 5; i++)
+ if (mw_messages_property_name[i]) {
+ value = mw->messages[i];
+
+ dbus_gsm_dict_append(&dict,
+ mw_messages_property_name[i],
+ DBUS_TYPE_BYTE, &value);
+ }
+
+ for (i = 0; i < 5; i++)
+ if (mw_mailbox_property_name[i]) {
+ number = phone_number_to_string(&mw->mailbox_number[i]);
+
+ dbus_gsm_dict_append(&dict,
+ mw_mailbox_property_name[i],
+ DBUS_TYPE_STRING, &number);
+ }
+
+ dbus_gsm_dict_append(&dict, "LastNotificationText",
+ DBUS_TYPE_STRING, &mw->last_message);
+
+ dbus_message_iter_close_container(&iter, &dict);
+
+ return reply;
+}
+
+static gboolean mw_mwis_update(gpointer user);
+
+static DBusMessage *mw_set_property(DBusConnection *conn, DBusMessage *msg,
+ void *data)
+{
+ struct ofono_modem *modem = data;
+ struct message_waiting_data *mw = modem->message_waiting;
+ DBusMessageIter iter;
+ DBusMessageIter var;
+ const char *name;
+ int i;
+ unsigned char value;
+
+ if (mw->efmwis_length == 0)
+ return dbus_gsm_busy(msg);
+
+ if (!dbus_message_iter_init(msg, &iter))
+ return dbus_gsm_invalid_args(msg);
+
+ if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
+ return dbus_gsm_invalid_args(msg);
+
+ dbus_message_iter_get_basic(&iter, &name);
+
+ for (i = 0; i < 5; i++)
+ if (mw_messages_property_name[i] &&
+ !strcmp(name, mw_messages_property_name[i]))
+ break;
+ if (i == 5)
+ return dbus_gsm_invalid_args(msg);
+
+ dbus_message_iter_next(&iter);
+ if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
+ return dbus_gsm_invalid_args(msg);
+
+ dbus_message_iter_recurse(&iter, &var);
+ if (dbus_message_iter_get_arg_type(&var) != DBUS_TYPE_BYTE)
+ return dbus_gsm_invalid_format(msg);
+
+ dbus_message_iter_get_basic(&var, &value);
+
+ if (mw->messages[i] != value) {
+ mw->messages[i] = value;
+
+ if (!mw->pending)
+ mw->pending = g_timeout_add(0, mw_mwis_update, modem);
+
+ dbus_gsm_signal_property_changed(conn, modem->path,
+ MESSAGE_WAITING_INTERFACE,
+ mw_messages_property_name[i],
+ DBUS_TYPE_BYTE, &value);
+ }
+
+ return dbus_message_new_method_return(msg);
+}
+
+static GDBusMethodTable message_waiting_methods[] = {
+ { "GetProperties", "", "a{sv}", mw_get_properties },
+ { "SetProperty", "sv", "", mw_set_property, },
+ { }
+};
+
+static GDBusSignalTable message_waiting_signals[] = {
+ { "PropertyChanged", "sv" },
+ { }
+};
+
+static void mw_mwis_read_cb(struct ofono_modem *modem, int ok,
+ enum ofono_sim_file_structure structure, int total_length,
+ int record, const unsigned char *data, int record_length,
+ void *userdata)
+{
+ int i, status, messages[5];
+ unsigned char value;
+ DBusConnection *conn = dbus_gsm_connection();
+ struct message_waiting_data *mw = modem->message_waiting;
+
+ /* Handle only current identity (TODO: currently assumes first) */
+ if (record != 1)
+ return;
+
+ if (!ok ||
+ structure != OFONO_SIM_FILE_STRUCTURE_FIXED ||
+ record_length < 5) {
+ ofono_error("Unable to read waiting messages numbers "
+ "from SIM");
+ return;
+ }
+
+ status = data[0];
+ data++;
+
+ for (i = 0; i < 5 && i < record_length - 1; i++) {
+ messages[i] = ((status >> i) & 1) ? data[i] : 0;
+
+ if (mw->messages[i] != messages[i]) {
+ mw->messages[i] = messages[i];
+ value = messages[i];
+
+ if (!mw_messages_property_name[i])
+ continue;
+
+ dbus_gsm_signal_property_changed(conn, modem->path,
+ MESSAGE_WAITING_INTERFACE,
+ mw_messages_property_name[i],
+ DBUS_TYPE_BYTE, &value);
+ }
+ }
+
+ mw->efmwis_length = record_length;
+}
+
+static void mw_mbdn_read_cb(struct ofono_modem *modem, int ok,
+ enum ofono_sim_file_structure structure, int total_length,
+ int record, const unsigned char *data, int record_length,
+ void *userdata)
+{
+ int i, *ids = userdata;
+ DBusConnection *conn = dbus_gsm_connection();
+ struct message_waiting_data *mw = modem->message_waiting;
+
+ if (!ok ||
+ structure != OFONO_SIM_FILE_STRUCTURE_FIXED ||
+ record_length < 14 || total_length < record_length) {
+ ofono_error("Unable to read mailbox dialling numbers "
+ "from SIM");
+ g_free(ids);
+ return;
+ }
+
+ for (i = 0; i < 5; i++)
+ if (record == ids[i])
+ break;
+ if (i == 5)
+ goto final;
+
+ if (sim_adn_parse(data, record_length, &mw->mailbox_number[i]) ==
+ FALSE)
+ mw->mailbox_number[i].number[0] = '\0';
+
+ mw->efmbdn_length = record_length;
+
+final:
+ /* Is this the last MBDN record? */
+ if (record == total_length / record_length)
+ g_free(ids);
+}
+
+static void mw_mbi_read_cb(struct ofono_modem *modem, int ok,
+ enum ofono_sim_file_structure structure, int total_length,
+ int record, const unsigned char *data, int record_length,
+ void *userdata)
+{
+ int i, err, *ids = userdata;
+ DBusConnection *conn = dbus_gsm_connection();
+ struct message_waiting_data *mw = modem->message_waiting;
+
+ /* Handle only current identity (TODO: currently assumes first) */
+ if (record != 1)
+ return;
+
+ if (!ok ||
+ structure != OFONO_SIM_FILE_STRUCTURE_FIXED ||
+ record_length < 4) {
+ ofono_error("Unable to read mailbox identifies "
+ "from SIM");
+
+ g_free(ids);
+ return;
+ }
+
+ for (i = 0; i < 5 && i < record_length; i++)
+ ids[i] = data[i];
+
+ err = ofono_sim_read(modem, SIM_EFMBDN_FILEID, mw_mbdn_read_cb, ids);
+ if (err != 0) {
+ ofono_error("Unable to read EF-MBDN from SIM");
+
+ g_free(ids);
+ }
+}
+
+/* Loads MWI states from SIM */
+static gboolean mw_mwis_load(struct ofono_modem *modem)
+{
+ int err;
+ int *ids;
+
+ err = ofono_sim_read(modem, SIM_EFMWIS_FILEID, mw_mwis_read_cb, NULL);
+ if (err != 0)
+ return FALSE;
+
+ /* Alloc space for mailbox identifiers */
+ ids = g_malloc0(5);
+
+ err = ofono_sim_read(modem, SIM_EFMBI_FILEID, mw_mbi_read_cb, ids);
+ if (err != 0) {
+ g_free(ids);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/* Writes MWI states back to SIM */
+static gboolean mw_mwis_update(gpointer user)
+{
+ struct ofono_modem *modem = user;
+ struct message_waiting_data *mw = modem->message_waiting;
+ unsigned char *file;
+ int i;
+
+ mw->pending = 0;
+
+ if (mw->efmwis_length == 0)
+ return FALSE;
+
+ file = g_malloc0(mw->efmwis_length);
+
+ /* Fill in numbers of messages in bytes 1 to X of EF-MWIS */
+ for (i = 0; i < 5 && i < mw->efmwis_length - 1; i++)
+ file[i + 1] = mw->messages[i];
+
+ /* Fill in indicator state bits in byte 0 */
+ for (i = 0; i < 5 && i < mw->efmwis_length - 1; i++)
+ if (file[i + 1] > 0)
+ file[0] |= 1 << i;
+
+ if (ofono_sim_write(modem, SIM_EFMWIS_FILEID,
+ OFONO_SIM_FILE_STRUCTURE_FIXED, 1,
+ file, mw->efmwis_length) != 0) {
+ ofono_error("Writing MWI states to SIM failed");
+ }
+
+ g_free(file);
+
+ return FALSE;
+}
+
+void ofono_message_waiting_notify(struct ofono_modem *modem, int information,
+ enum sms_mwi_type type, int profile)
+{
+ struct message_waiting_data *mw = modem->message_waiting;
+ DBusConnection *conn = dbus_gsm_connection();
+ int invalidate = 0;
+ unsigned char value;
+
+ if (mw == NULL)
+ return;
+
+ /* Handle only current identity (TODO: currently assumes first) */
+ if (profile != 1)
+ return;
+
+ /* Ignore the unspecified type of notification. It probably means
+ * that the (voicemail) indication should become active but there's
+ * no way to know when to deactivate it. It's used for the obsolete
+ * Return Call type of indication in SMS PDUs which also carry text
+ * and we provide this text instead. */
+ if (information == MWI_UNSPECIFIED)
+ return;
+
+ if (information == MWI_MESSAGES_WAITING) {
+ if (mw->messages[type] == 0) {
+ mw->messages[type] = 1;
+ invalidate = 1;
+ }
+ } else if (information == MWI_NO_MESSAGES_WAITING) {
+ if (mw->messages[type] > 0) {
+ mw->messages[type] = 0;
+ invalidate = 1;
+ }
+ } else {
+ if (mw->messages[type] != information) {
+ mw->messages[type] = information;
+ invalidate = 1;
+ }
+ }
+
+ if (invalidate) {
+ if (mw_messages_property_name[type]) {
+ value = mw->messages[type];
+
+ dbus_gsm_signal_property_changed(conn, modem->path,
+ MESSAGE_WAITING_INTERFACE,
+ mw_messages_property_name[type],
+ DBUS_TYPE_BYTE, &value);
+ }
+
+ if (!mw->pending)
+ mw->pending = g_timeout_add(0, mw_mwis_update, modem);
+ }
+}
+
+void ofono_message_waiting_message(struct ofono_modem *modem, const char *msg)
+{
+ struct message_waiting_data *mw = modem->message_waiting;
+ DBusConnection *conn = dbus_gsm_connection();
+
+ if (!mw)
+ return;
+
+ if (mw->last_message && !strcmp(mw->last_message, msg))
+ return;
+
+ if (mw->last_message)
+ g_free(mw->last_message);
+
+ mw->last_message = g_strdup(msg);
+
+ dbus_gsm_signal_property_changed(conn, modem->path,
+ MESSAGE_WAITING_INTERFACE, "LastNotificationText",
+ DBUS_TYPE_STRING, &mw->last_message);
+}
+
+static void initialize_message_waiting(struct ofono_modem *modem)
+{
+ DBusConnection *conn = dbus_gsm_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);
+
+ modem_add_interface(modem, MESSAGE_WAITING_INTERFACE);
+}
+
+int ofono_message_waiting_register(struct ofono_modem *modem)
+{
+ if (modem == NULL)
+ return -1;
+
+ modem->message_waiting = message_waiting_create();
+
+ ofono_sim_ready_notify_register(modem, initialize_message_waiting);
+ if (ofono_sim_get_ready(modem))
+ initialize_message_waiting(modem);
+
+ return 0;
+}
+
+void ofono_message_waiting_unregister(struct ofono_modem *modem)
+{
+ DBusConnection *conn = dbus_gsm_connection();
+
+ g_dbus_unregister_interface(conn, modem->path,
+ MESSAGE_WAITING_INTERFACE);
+ modem_remove_interface(modem, MESSAGE_WAITING_INTERFACE);
+}
diff --git a/src/message-waiting.h b/src/message-waiting.h
new file mode 100644
index 0000000..cad4c40
--- /dev/null
+++ b/src/message-waiting.h
@@ -0,0 +1,33 @@
+/*
+ *
+ * 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
+ *
+ */
+
+enum mwi_information_type {
+ MWI_UNSPECIFIED = -1,
+ MWI_MESSAGES_WAITING = -2,
+ MWI_NO_MESSAGES_WAITING = -3,
+};
+
+/* information either a positive (or zero) message count or a
+ * partial information using one of mwi_information_type constants
+ */
+void ofono_message_waiting_notify(struct ofono_modem *modem, int information,
+ enum sms_mwi_type type, int profile);
+void ofono_message_waiting_message(struct ofono_modem *modem, const char *msg);
diff --git a/src/modem.h b/src/modem.h
index d322df8..90993ca 100644
--- a/src/modem.h
+++ b/src/modem.h
@@ -43,6 +43,7 @@ struct ofono_modem {
struct sim_manager_data *sim_manager;
struct sms_manager_data *sms_manager;
struct phonebook_data *phonebook;
+ struct message_waiting_data *message_waiting;
GSList *history_contexts;
};
diff --git a/src/simutil.h b/src/simutil.h
index 6572e72..c2b1e20 100644
--- a/src/simutil.h
+++ b/src/simutil.h
@@ -24,6 +24,9 @@ enum sim_fileid {
SIM_EFSPN_FILEID = 0x6f46,
SIM_EFPNN_FILEID = 0x6fc5,
SIM_EFOPL_FILEID = 0x6fc6,
+ SIM_EFMBDN_FILEID = 0x6fc7,
+ SIM_EFMBI_FILEID = 0x6fc9,
+ SIM_EFMWIS_FILEID = 0x6fca,
SIM_EFSPDI_FILEID = 0x6fcd,
};
diff --git a/src/sms.c b/src/sms.c
index ef039d9..caab2e0 100644
--- a/src/sms.c
+++ b/src/sms.c
@@ -39,6 +39,7 @@
#include "util.h"
#include "sim.h"
#include "smsutil.h"
+#include "message-waiting.h"
#define uninitialized_var(x) x = x
@@ -658,9 +659,196 @@ static void handle_deliver(struct ofono_modem *modem,
g_slist_free(l);
}
-static void handle_mwi(struct ofono_modem *modem, struct sms *mwi)
+static void handle_special_sms_iei(struct ofono_modem *modem,
+ const guint8 *iei, int *set, int *store)
{
- ofono_error("MWI information not yet handled");
+ enum sms_mwi_type type;
+ int profile;
+
+ /* Parse type & storage byte */
+ *set = 0;
+ if (iei[0] & (1 << 7))
+ *store = 1;
+
+ type = iei[0] & 0x1f;
+ if (type > SMS_MWI_TYPE_OTHER) {
+ if (type == (SMS_MWI_TYPE_OTHER | 4))
+ type = SMS_MWI_TYPE_VIDEO;
+ else
+ /* 23.040 9.2.3.24.2: "Terminals should be capable of
+ * receiving any values in octet 1, even including
+ * those marked as Reserved." Treat Reserved as
+ * "Other". */
+ type = SMS_MWI_TYPE_OTHER;
+ }
+
+ profile = ((iei[0] >> 5) & 3) + 1;
+
+ ofono_message_waiting_notify(modem, iei[1], type, profile);
+}
+
+static void handle_enhanced_voicemail_iei(struct ofono_modem *modem,
+ const guint8 *iei, int *set, int *store, int length)
+{
+ int profile, n;
+
+ if (length < 3)
+ return;
+
+ /* ENHANCED_VOICE_MAIL_PDU_TYPE */
+ if (!(iei[0] & 1)) {
+ /* 9.2.3.24.13.1 Enhanced Voice Mail Notification */
+
+ /* MULTIPLE_SUBSCRIBER_PROFILE */
+ profile = (iei[0] >> 2) & 3;
+
+ /* SM_STORAGE */
+ *set = 0;
+ if (iei[0] & (1 << 4))
+ *store = 1;
+
+ /* TODO: VM_MAILBOX_ACCESS_ADDRESS */
+ n = 2 + (iei[1] + 1) / 2;
+ if (length < n + 11)
+ return;
+
+ /* TODO: VM_MESSAGE_PRIORITY_INDICATION */
+
+ /* Other parameters currently not supported */
+
+ ofono_message_waiting_notify(modem, iei[2 + n],
+ SMS_MWI_TYPE_VOICE, profile);
+ } else {
+ /* 9.2.3.24.13.2 Enhanced Voice Delete Confirmation */
+
+ /* MULTIPLE_SUBSCRIBER_PROFILE */
+ profile = (iei[0] >> 2) & 3;
+
+ /* SM_STORAGE */
+ *set = 0;
+ if (iei[0] & (1 << 4))
+ *store = 1;
+
+ /* TODO: VM_MAILBOX_ACCESS_ADDRESS */
+ n = 2 + (iei[1] + 1) / 2;
+ if (length < n + 11)
+ return;
+
+ /* Other parameters currently not supported */
+
+ ofono_message_waiting_notify(modem, iei[2 + n],
+ SMS_MWI_TYPE_VOICE, profile);
+ }
+}
+
+static void handle_mwi(struct ofono_modem *modem,
+ struct sms *sms, gboolean *out_discard)
+{
+ gboolean active, discard;
+ enum sms_mwi_type type;
+ char *message;
+ int profile = 1;
+ GSList *sms_list;
+
+ /* "Store" bits are ORed if multiple MWI types are present
+ * but if neither Special SMS Message Indication nor DCS based
+ * indication is present, the bit must remain set. */
+ int set = 1, store = 0;
+
+ /* Check MWI types in the order from lowest to highest priority
+ * because they will override one another. */
+
+ if (sms->deliver.pid == SMS_PID_TYPE_RETURN_CALL) {
+ ofono_message_waiting_notify(modem, MWI_UNSPECIFIED,
+ SMS_MWI_TYPE_VOICE, profile);
+ }
+
+ if (sms_mwi_dcs_decode(sms->deliver.dcs, &type,
+ NULL, &active, &discard)) {
+ set = 0;
+ store = (discard == FALSE);
+
+ if (active)
+ ofono_message_waiting_notify(modem,
+ MWI_MESSAGES_WAITING, type, profile);
+ else
+ ofono_message_waiting_notify(modem,
+ MWI_NO_MESSAGES_WAITING, type, profile);
+ }
+
+ if (sms_dcs_decode(sms->deliver.dcs, NULL, NULL, NULL, NULL) &&
+ sms->deliver.udhi) {
+ guint8 special_iei[4], *evm_iei;
+ struct sms_udh_iter iter;
+ enum sms_iei iei;
+
+ if (!sms_udh_iter_init(sms, &iter))
+ goto final;
+
+ while ((iei = sms_udh_iter_get_ie_type(&iter)) !=
+ SMS_IEI_INVALID) {
+ switch (iei) {
+ case SMS_IEI_SPECIAL_MESSAGE_INDICATION:
+ if (sms_udh_iter_get_ie_length(&iter) != 2)
+ break;
+ sms_udh_iter_get_ie_data(&iter, special_iei);
+
+ handle_special_sms_iei(modem, special_iei,
+ &set, &store);
+ break;
+ }
+
+ sms_udh_iter_next(&iter);
+ }
+
+ /* Go through the UDH again because Enhanced Voice Mail
+ * Notification takes precedence over both DCS based
+ * indication and Special SMS Message indication
+ * (23.040 9.2.3.24.13.1). */
+
+ if (!sms_udh_iter_init(sms, &iter))
+ goto final;
+
+ while ((iei = sms_udh_iter_get_ie_type(&iter)) !=
+ SMS_IEI_INVALID) {
+ switch (iei) {
+ case SMS_IEI_ENHANCED_VOICE_MAIL_INFORMATION:
+ evm_iei = g_malloc0(
+ sms_udh_iter_get_ie_length(
+ &iter));
+ sms_udh_iter_get_ie_data(&iter, evm_iei);
+
+ handle_enhanced_voicemail_iei(modem, evm_iei,
+ &set, &store,
+ sms_udh_iter_get_ie_length(
+ &iter));
+
+ g_free(evm_iei);
+ break;
+ }
+
+ sms_udh_iter_next(&iter);
+ }
+ }
+
+final:
+ /* Only bother the Message Waiting interface with textual
+ * notifications that are not to be stored together with other
+ * Short Messages in ME. The other messages will be delivered
+ * to the user through normal SMS store. */
+ if (!store) {
+ sms_list = g_slist_append(NULL, sms);
+ message = sms_decode_text(sms_list);
+ g_slist_free(sms_list);
+
+ if (message) {
+ ofono_message_waiting_message(modem, message);
+ g_free(message);
+ }
+ }
+
+ if (out_discard)
+ *out_discard = !(set || store);
}
void ofono_sms_deliver_notify(struct ofono_modem *modem, unsigned char *pdu,
@@ -688,14 +876,18 @@ void ofono_sms_deliver_notify(struct ofono_modem *modem, unsigned char *pdu,
/* This is an older style MWI notification, process MWI
* headers and handle it like any other message */
if (sms.deliver.pid == SMS_PID_TYPE_RETURN_CALL) {
- handle_mwi(modem, &sms);
+ handle_mwi(modem, &sms, &discard);
+
+ if (discard)
+ return;
+
goto out;
}
/* 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(sms.deliver.dcs, NULL, NULL, NULL, &discard)) {
- handle_mwi(modem, &sms);
+ if (sms_mwi_dcs_decode(sms.deliver.dcs, NULL, NULL, NULL, NULL)) {
+ handle_mwi(modem, &sms, &discard);
if (discard)
return;
@@ -760,7 +952,14 @@ void ofono_sms_deliver_notify(struct ofono_modem *modem, unsigned char *pdu,
switch (iei) {
case SMS_IEI_SPECIAL_MESSAGE_INDICATION:
case SMS_IEI_ENHANCED_VOICE_MAIL_INFORMATION:
- handle_mwi(modem, &sms);
+ /* TODO: ignore if not in the very first
+ * segment of a concatenated SM so as not
+ * to repeat the indication. */
+ handle_mwi(modem, &sms, &discard);
+
+ if (discard)
+ return;
+
goto out;
case SMS_IEI_WCMP:
ofono_error("No support for WCMP, ignoring");
@@ -792,6 +991,9 @@ int ofono_sms_manager_register(struct ofono_modem *modem,
if (ops == NULL)
return -1;
+ if (ofono_message_waiting_register(modem))
+ return -1;
+
modem->sms_manager = sms_manager_create();
if (!modem->sms_manager)
@@ -827,4 +1029,6 @@ void ofono_sms_manager_unregister(struct ofono_modem *modem)
SMS_MANAGER_INTERFACE);
modem_remove_interface(modem, SMS_MANAGER_INTERFACE);
+
+ ofono_message_waiting_unregister(modem);
}
diff --git a/src/smsutil.h b/src/smsutil.h
index 89da973..d362aa9 100644
--- a/src/smsutil.h
+++ b/src/smsutil.h
@@ -158,6 +158,7 @@ enum sms_mwi_type {
SMS_MWI_TYPE_FAX = 1,
SMS_MWI_TYPE_EMAIL = 2,
SMS_MWI_TYPE_OTHER = 3,
+ SMS_MWI_TYPE_VIDEO = 4,
};
enum sms_pid_type {
--
1.6.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [PATCH 4/4] Add a MessageWaiting interface to track message waiting indications.
2009-07-30 8:05 [PATCH 4/4] Add a MessageWaiting interface to track message waiting indications Andrzej Zaborowski
@ 2009-07-31 16:19 ` Denis Kenzior
2009-08-01 23:09 ` Andrzej Zaborowski
0 siblings, 1 reply; 18+ messages in thread
From: Denis Kenzior @ 2009-07-31 16:19 UTC (permalink / raw)
To: ofono
[-- Attachment #1: Type: text/plain, Size: 4741 bytes --]
Hi,
> Comments are welcome about how the interface should look. The state of the
> indications is kept in memory and written back to the SIM after any
> changes.
>
> Patch is untested because write ofono_sim_write is unimplemented, I'll add
> it as a separate patch. Should it take a callback parameter?
Probably would be useful in case you want to notify an external app that
storing a file failed (e.g. update of MBDN / MSISDN). For other cases, maybe
less useful.
> diff --git a/src/driver.h b/src/driver.h
> index 928c20a..51e5587 100644
> --- a/src/driver.h
> +++ b/src/driver.h
> @@ -439,3 +439,6 @@ void ofono_phonebook_entry(struct ofono_modem *modem,
> int index, const char *adnumber, int adtype,
> const char *secondtext, const char *email,
> const char *sip_uri, const char *tel_uri);
> +
> +int ofono_message_waiting_register(struct ofono_modem *modem);
> +void ofono_message_waiting_unregister(struct ofono_modem *modem);
Lets keep this out of driver.h, there's nothing here that a driver can
provide. Put it in ofono.h or messagewaiting.h
> + if (mw->messages[i] != value) {
> + mw->messages[i] = value;
> +
> + if (!mw->pending)
> + mw->pending = g_timeout_add(0, mw_mwis_update, modem);
> +
> + dbus_gsm_signal_property_changed(conn, modem->path,
> + MESSAGE_WAITING_INTERFACE,
> + mw_messages_property_name[i],
> + DBUS_TYPE_BYTE, &value);
> + }
> +
> + return dbus_message_new_method_return(msg);
> +}
Ok, I'm a bit confused here. Are you sure that MWIs should have the ability
to be cleared out by the user? The way I understood it, the user dials the
voice mail system and the provider sends another MWI message which clears out
the status.
> +void ofono_message_waiting_message(struct ofono_modem *modem, const char
> *msg) +{
> + struct message_waiting_data *mw = modem->message_waiting;
> + DBusConnection *conn = dbus_gsm_connection();
> +
> + if (!mw)
> + return;
> +
> + if (mw->last_message && !strcmp(mw->last_message, msg))
> + return;
> +
> + if (mw->last_message)
> + g_free(mw->last_message);
> +
> + mw->last_message = g_strdup(msg);
> +
> + dbus_gsm_signal_property_changed(conn, modem->path,
> + MESSAGE_WAITING_INTERFACE, "LastNotificationText",
> + DBUS_TYPE_STRING, &mw->last_message);
> +}
> +
> +enum mwi_information_type {
> + MWI_UNSPECIFIED = -1,
> + MWI_MESSAGES_WAITING = -2,
> + MWI_NO_MESSAGES_WAITING = -3,
> +};
Is there a reason these are negative?
> --- a/src/modem.h
> +++ b/src/modem.h
> @@ -43,6 +43,7 @@ struct ofono_modem {
> struct sim_manager_data *sim_manager;
> struct sms_manager_data *sms_manager;
> struct phonebook_data *phonebook;
> + struct message_waiting_data *message_waiting;
>
> GSList *history_contexts;
> };
Please rebase, this file is now defunct
> +static void handle_mwi(struct ofono_modem *modem,
> + struct sms *sms, gboolean *out_discard)
> +{
> + gboolean active, discard;
> + enum sms_mwi_type type;
> + char *message;
> + int profile = 1;
> + GSList *sms_list;
> +
> + /* "Store" bits are ORed if multiple MWI types are present
> + * but if neither Special SMS Message Indication nor DCS based
> + * indication is present, the bit must remain set. */
> + int set = 1, store = 0;
What is this comment about, since I don't see any ORing going on below. Are
you trying to accommodate this piece of stupidity from 23.040 9.2.3.24.2?
"In the event of a conflict between this setting and the setting of the Data
Coding Scheme (see 3GPP TS 23.038 [9]) then the message shall be stored if
either the DCS indicates this, or Octet 1 above indicates this."
> +
> + /* Check MWI types in the order from lowest to highest priority
> + * because they will override one another. */
Can we instead process the different sources from highest to lowest instead and
bail out early? No sense in calling message_waiting_notify several times (and
possibly emitting spurious signals) when only once is required.
> + if (sms_dcs_decode(sms->deliver.dcs, NULL, NULL, NULL, NULL) &&
> + sms->deliver.udhi) {
This seems to be incorrect. An MWI DCS message can still contain enhanced
IEIs. Should this check just for UDHI instead?
> +final:
> + /* Only bother the Message Waiting interface with textual
> + * notifications that are not to be stored together with other
> + * Short Messages in ME. The other messages will be delivered
> + * to the user through normal SMS store. */
It sounds to me like we can completely ignore the text of such messages. The
network is basically saying: "the text isn't important, the contents are."
Regards,
-Denis
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 4/4] Add a MessageWaiting interface to track message waiting indications.
2009-07-31 16:19 ` Denis Kenzior
@ 2009-08-01 23:09 ` Andrzej Zaborowski
2009-08-03 16:32 ` Denis Kenzior
0 siblings, 1 reply; 18+ messages in thread
From: Andrzej Zaborowski @ 2009-08-01 23:09 UTC (permalink / raw)
To: ofono
[-- Attachment #1: Type: text/plain, Size: 4511 bytes --]
2009/7/31 Denis Kenzior <denkenz@gmail.com>:
>> + if (mw->messages[i] != value) {
>> + mw->messages[i] = value;
>> +
>> + if (!mw->pending)
>> + mw->pending = g_timeout_add(0, mw_mwis_update, modem);
>> +
>> + dbus_gsm_signal_property_changed(conn, modem->path,
>> + MESSAGE_WAITING_INTERFACE,
>> + mw_messages_property_name[i],
>> + DBUS_TYPE_BYTE, &value);
>> + }
>> +
>> + return dbus_message_new_method_return(msg);
>> +}
>
> Ok, I'm a bit confused here. Are you sure that MWIs should have the ability
> to be cleared out by the user? The way I understood it, the user dials the
> voice mail system and the provider sends another MWI message which clears out
> the status.
You're right, there's probably no point to provide this method. I
haven't found the exact statement in the docs saying that the provider
should send a new MWI but it's logical. Otherwise I thought the D-Bus
client might be able to tell somehow that the mailbox should now have
1 message less and want to update us.
>
>> +
>> +enum mwi_information_type {
>> + MWI_UNSPECIFIED = -1,
>> + MWI_MESSAGES_WAITING = -2,
>> + MWI_NO_MESSAGES_WAITING = -3,
>> +};
>
> Is there a reason these are negative?
So the caller can give the exact number of messages (zero or positive)
or partial information using one of the constants.
>
>> +static void handle_mwi(struct ofono_modem *modem,
>> + struct sms *sms, gboolean *out_discard)
>> +{
>> + gboolean active, discard;
>> + enum sms_mwi_type type;
>> + char *message;
>> + int profile = 1;
>> + GSList *sms_list;
>> +
>> + /* "Store" bits are ORed if multiple MWI types are present
>> + * but if neither Special SMS Message Indication nor DCS based
>> + * indication is present, the bit must remain set. */
>> + int set = 1, store = 0;
>
> What is this comment about, since I don't see any ORing going on below. Are
> you trying to accommodate this piece of stupidity from 23.040 9.2.3.24.2?
> "In the event of a conflict between this setting and the setting of the Data
> Coding Scheme (see 3GPP TS 23.038 [9]) then the message shall be stored if
> either the DCS indicates this, or Octet 1 above indicates this."
Yes. :-)
I'm thinking it's better to try to implement what's in the text so
when someone needs to know how ofono will react to something, you can
point at the specification, barring any TODOs in the code.
>
>> +
>> + /* Check MWI types in the order from lowest to highest priority
>> + * because they will override one another. */
>
> Can we instead process the different sources from highest to lowest instead and
> bail out early? No sense in calling message_waiting_notify several times (and
> possibly emitting spurious signals) when only once is required.
We can but then we won't comply with that 23.040 9.2.3.24.2 above.
There's also a tiny possibility someone might send us updates for the
different mailboxes (out of the 5 types defined) one using DCS and
another one in UDH. In the attached patch I left this as is and made
sure PropertyChanged is only sent from the time callback (bottom half)
which was my original intention. I can still change this.
>
>> + if (sms_dcs_decode(sms->deliver.dcs, NULL, NULL, NULL, NULL) &&
>> + sms->deliver.udhi) {
>
> This seems to be incorrect. An MWI DCS message can still contain enhanced
> IEIs. Should this check just for UDHI instead?
True, I had wrongly copied the condition from ofono_sms_deliver_notify.
>
>> +final:
>> + /* Only bother the Message Waiting interface with textual
>> + * notifications that are not to be stored together with other
>> + * Short Messages in ME. The other messages will be delivered
>> + * to the user through normal SMS store. */
>
> It sounds to me like we can completely ignore the text of such messages. The
> network is basically saying: "the text isn't important, the contents are."
Probably, although with the Return Call type of notification there's
no other information beside the text. I left it in the updated patch.
Regards
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0003-Add-a-MessageWaiting-interface-to-track-message-wait.patch --]
[-- Type: text/x-patch, Size: 23068 bytes --]
From 68f9bb3807a003f873ca3f33575013291b094e89 Mon Sep 17 00:00:00 2001
From: Andrzej Zaborowski <andrew.zaborowski@intel.com>
Date: Sat, 1 Aug 2009 15:40:58 +0200
Subject: [PATCH] Add a MessageWaiting interface for tracking message waiting indications.
The state of the indications is kept in memory and written back to
the SIM after any changes.
---
src/Makefile.am | 3 +-
src/message-waiting.c | 467 +++++++++++++++++++++++++++++++++++++++++++++++++
src/message-waiting.h | 33 ++++
src/ofono.h | 4 +
src/simutil.h | 3 +
src/sms.c | 218 ++++++++++++++++++++++-
src/smsutil.h | 1 +
7 files changed, 722 insertions(+), 7 deletions(-)
create mode 100644 src/message-waiting.c
create mode 100644 src/message-waiting.h
diff --git a/src/Makefile.am b/src/Makefile.am
index 2e3e607..4644c69 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -13,7 +13,8 @@ ofonod_SOURCES = main.c ofono.h log.c plugin.c \
network.c voicecall.c ussd.h ussd.c sms.c \
call-settings.c call-forwarding.c call-meter.c \
smsutil.h smsutil.c cssn.h cssn.c call-barring.c sim.h sim.c \
- phonebook.c history.c simutil.h simutil.c
+ phonebook.c history.c simutil.h simutil.c \
+ message-waiting.c message-waiting.h
ofonod_LDADD = $(top_builddir)/plugins/libbuiltin.la \
$(top_builddir)/drivers/libbuiltin.la \
diff --git a/src/message-waiting.c b/src/message-waiting.c
new file mode 100644
index 0000000..0e5c80b
--- /dev/null
+++ b/src/message-waiting.c
@@ -0,0 +1,467 @@
+/*
+ *
+ * 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
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include <stdio.h>
+
+#include <dbus/dbus.h>
+#include <glib.h>
+#include <gdbus.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "ofono.h"
+
+#include "driver.h"
+#include "common.h"
+#include "util.h"
+#include "sim.h"
+#include "simutil.h"
+#include "smsutil.h"
+#include "message-waiting.h"
+
+#define MESSAGE_WAITING_INTERFACE "org.ofono.MessageWaiting"
+
+struct message_waiting_data {
+ int pending;
+
+ int messages[5];
+ int efmwis_length;
+ int efmbdn_length;
+
+ struct ofono_phone_number mailbox_number[5];
+
+ char *last_message;
+ int messages_new[5];
+};
+
+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->last_message)
+ g_free(data->last_message);
+
+ g_free(data);
+
+ modem->message_waiting = NULL;
+}
+
+static const char *mw_messages_property_name[5] = {
+ "VoicemailMessages",
+#if 0
+ "FaxMessages",
+ "EmailMessages",
+ "OtherMessages",
+ "VideomailMessages",
+#endif
+};
+
+static const char *mw_mailbox_property_name[5] = {
+ "VoicemailMailboxNumber",
+#if 0
+ "FaxMailboxNumber",
+ "EmailMailboxNumber",
+ "OtherMailboxNumber",
+ "VideomailMailboxNumber",
+#endif
+};
+
+static DBusMessage *mw_get_properties(DBusConnection *conn,
+ DBusMessage *msg, void *data)
+{
+ struct ofono_modem *modem = data;
+ struct message_waiting_data *mw = modem->message_waiting;
+ DBusMessage *reply;
+ DBusMessageIter iter;
+ DBusMessageIter dict;
+ int i;
+ unsigned char value;
+ const char *number;
+
+ reply = dbus_message_new_method_return(msg);
+ if (!reply)
+ return NULL;
+
+ dbus_message_iter_init_append(reply, &iter);
+
+ dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
+ OFONO_PROPERTIES_ARRAY_SIGNATURE, &dict);
+
+ for (i = 0; i < 5; i++)
+ if (mw_messages_property_name[i]) {
+ value = mw->messages[i];
+
+ ofono_dbus_dict_append(&dict,
+ mw_messages_property_name[i],
+ DBUS_TYPE_BYTE, &value);
+ }
+
+ for (i = 0; i < 5; i++)
+ if (mw_mailbox_property_name[i]) {
+ number = phone_number_to_string(&mw->mailbox_number[i]);
+
+ ofono_dbus_dict_append(&dict,
+ mw_mailbox_property_name[i],
+ DBUS_TYPE_STRING, &number);
+ }
+
+ ofono_dbus_dict_append(&dict, "LastNotificationText",
+ DBUS_TYPE_STRING, &mw->last_message);
+
+ dbus_message_iter_close_container(&iter, &dict);
+
+ return reply;
+}
+
+static GDBusMethodTable message_waiting_methods[] = {
+ { "GetProperties", "", "a{sv}", mw_get_properties },
+ { }
+};
+
+static GDBusSignalTable message_waiting_signals[] = {
+ { "PropertyChanged", "sv" },
+ { }
+};
+
+static void mw_mwis_read_cb(struct ofono_modem *modem, int ok,
+ enum ofono_sim_file_structure structure, int total_length,
+ int record, const unsigned char *data, int record_length,
+ void *userdata)
+{
+ int i, status, messages[5];
+ unsigned char value;
+ DBusConnection *conn = ofono_dbus_get_connection();
+ struct message_waiting_data *mw = modem->message_waiting;
+
+ /* Handle only current identity (TODO: currently assumes first) */
+ if (record != 1)
+ return;
+
+ if (!ok ||
+ structure != OFONO_SIM_FILE_STRUCTURE_FIXED ||
+ record_length < 5) {
+ ofono_error("Unable to read waiting messages numbers "
+ "from SIM");
+
+ mw->efmwis_length = -1;
+
+ return;
+ }
+
+ status = data[0];
+ data++;
+
+ for (i = 0; i < 5 && i < record_length - 1; i++) {
+ messages[i] = ((status >> i) & 1) ? data[i] : 0;
+
+ if (mw->messages[i] != messages[i]) {
+ mw->messages[i] = messages[i];
+ value = messages[i];
+
+ if (!mw_messages_property_name[i])
+ continue;
+
+ ofono_dbus_signal_property_changed(conn, modem->path,
+ MESSAGE_WAITING_INTERFACE,
+ mw_messages_property_name[i],
+ DBUS_TYPE_BYTE, &value);
+ }
+ }
+
+ mw->efmwis_length = record_length;
+}
+
+static void mw_mbdn_read_cb(struct ofono_modem *modem, int ok,
+ enum ofono_sim_file_structure structure, int total_length,
+ int record, const unsigned char *data, int record_length,
+ void *userdata)
+{
+ int i, *ids = userdata;
+ DBusConnection *conn = ofono_dbus_get_connection();
+ struct message_waiting_data *mw = modem->message_waiting;
+
+ if (!ok ||
+ structure != OFONO_SIM_FILE_STRUCTURE_FIXED ||
+ record_length < 14 || total_length < record_length) {
+ ofono_error("Unable to read mailbox dialling numbers "
+ "from SIM");
+ g_free(ids);
+ return;
+ }
+
+ for (i = 0; i < 5; i++)
+ if (record == ids[i])
+ break;
+ if (i == 5)
+ goto final;
+
+ if (sim_adn_parse(data, record_length, &mw->mailbox_number[i]) ==
+ FALSE)
+ mw->mailbox_number[i].number[0] = '\0';
+
+ mw->efmbdn_length = record_length;
+
+final:
+ /* Is this the last MBDN record? */
+ if (record == total_length / record_length)
+ g_free(ids);
+}
+
+static void mw_mbi_read_cb(struct ofono_modem *modem, int ok,
+ enum ofono_sim_file_structure structure, int total_length,
+ int record, const unsigned char *data, int record_length,
+ void *userdata)
+{
+ int i, err, *ids = userdata;
+ struct message_waiting_data *mw = modem->message_waiting;
+
+ /* Handle only current identity (TODO: currently assumes first) */
+ if (record != 1)
+ return;
+
+ if (!ok ||
+ structure != OFONO_SIM_FILE_STRUCTURE_FIXED ||
+ record_length < 4) {
+ ofono_error("Unable to read mailbox identifies "
+ "from SIM");
+
+ g_free(ids);
+ return;
+ }
+
+ for (i = 0; i < 5 && i < record_length; i++)
+ ids[i] = data[i];
+
+ err = ofono_sim_read(modem, SIM_EFMBDN_FILEID, mw_mbdn_read_cb, ids);
+ if (err != 0) {
+ ofono_error("Unable to read EF-MBDN from SIM");
+
+ g_free(ids);
+ }
+}
+
+static void mw_mbdn_write_cb(struct ofono_modem *modem, int ok, void *userdata)
+{
+ if (!ok)
+ ofono_error("Writing new EF-MBDN failed");
+}
+
+/* Loads MWI states from SIM */
+static gboolean mw_mwis_load(struct ofono_modem *modem)
+{
+ int err;
+ int *ids;
+
+ err = ofono_sim_read(modem, SIM_EFMWIS_FILEID, mw_mwis_read_cb, NULL);
+ if (err != 0)
+ return FALSE;
+
+ /* Alloc space for mailbox identifiers */
+ ids = g_malloc0(5);
+
+ err = ofono_sim_read(modem, SIM_EFMBI_FILEID, mw_mbi_read_cb, ids);
+ if (err != 0) {
+ g_free(ids);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/* Writes MWI states back to SIM */
+static gboolean mw_mwis_update(gpointer user)
+{
+ struct ofono_modem *modem = user;
+ struct message_waiting_data *mw = modem->message_waiting;
+ DBusConnection *conn = ofono_dbus_get_connection();
+ unsigned char value;
+ unsigned char *file;
+ int i;
+
+ for (i = 0; i < 5; i++)
+ if (mw->messages[i] != mw->messages_new[i]) {
+ mw->messages[i] = mw->messages_new[i];
+
+ if (!mw_messages_property_name[i])
+ continue;
+
+ value = mw->messages[i];
+
+ ofono_dbus_signal_property_changed(conn, modem->path,
+ MESSAGE_WAITING_INTERFACE,
+ mw_messages_property_name[i],
+ DBUS_TYPE_BYTE, &value);
+ }
+
+ mw->pending = 0;
+
+ if (mw->efmwis_length < 1)
+ return FALSE;
+
+ file = g_malloc0(mw->efmwis_length);
+
+ /* Fill in numbers of messages in bytes 1 to X of EF-MWIS */
+ for (i = 0; i < 5 && i < mw->efmwis_length - 1; i++)
+ file[i + 1] = mw->messages[i];
+
+ /* Fill in indicator state bits in byte 0 */
+ for (i = 0; i < 5 && i < mw->efmwis_length - 1; i++)
+ if (file[i + 1] > 0)
+ file[0] |= 1 << i;
+
+ if (ofono_sim_write(modem, SIM_EFMWIS_FILEID, mw_mbdn_write_cb,
+ OFONO_SIM_FILE_STRUCTURE_FIXED, 1,
+ file, mw->efmwis_length, NULL) != 0) {
+ ofono_error("Queuing a EF-MWI write to SIM failed");
+ }
+
+ g_free(file);
+
+ return FALSE;
+}
+
+void ofono_message_waiting_notify(struct ofono_modem *modem, int information,
+ enum sms_mwi_type type, int profile)
+{
+ struct message_waiting_data *mw = modem->message_waiting;
+ int invalidate;
+
+ if (mw == NULL)
+ return;
+
+ /* Handle only current identity (TODO: currently assumes first) */
+ if (profile != 1)
+ return;
+
+ /* Ignore the unspecified type of notification. It probably means
+ * that the (voicemail) indication should become active but there's
+ * no way to know when to deactivate it. It's used for the obsolete
+ * Return Call type of indication in SMS PDUs which also carry text
+ * and we provide this text instead. */
+ if (information == MWI_UNSPECIFIED)
+ return;
+
+ memcpy(mw->messages_new, mw->messages, sizeof(mw->messages_new));
+
+ if (information == MWI_MESSAGES_WAITING) {
+ if (mw->messages[type] == 0) {
+ mw->messages_new[type] = 1;
+ invalidate = 1;
+ }
+ } else if (information == MWI_NO_MESSAGES_WAITING) {
+ if (mw->messages[type] > 0) {
+ mw->messages_new[type] = 0;
+ invalidate = 1;
+ }
+ } else {
+ if (mw->messages[type] != information) {
+ mw->messages_new[type] = information;
+ invalidate = 1;
+ }
+ }
+
+ if (invalidate && !mw->pending)
+ mw->pending = g_timeout_add(0, mw_mwis_update, modem);
+}
+
+void ofono_message_waiting_message(struct ofono_modem *modem, const char *msg)
+{
+ struct message_waiting_data *mw = modem->message_waiting;
+ DBusConnection *conn = ofono_dbus_get_connection();
+
+ if (!mw)
+ return;
+
+ if (mw->last_message && !strcmp(mw->last_message, msg))
+ return;
+
+ if (mw->last_message)
+ g_free(mw->last_message);
+
+ mw->last_message = g_strdup(msg);
+
+ ofono_dbus_signal_property_changed(conn, modem->path,
+ MESSAGE_WAITING_INTERFACE, "LastNotificationText",
+ DBUS_TYPE_STRING, &mw->last_message);
+}
+
+static void initialize_message_waiting(struct ofono_modem *modem)
+{
+ 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);
+}
+
+int ofono_message_waiting_register(struct ofono_modem *modem)
+{
+ if (modem == NULL)
+ return -1;
+
+ modem->message_waiting = message_waiting_create();
+
+ ofono_sim_ready_notify_register(modem, initialize_message_waiting);
+ if (ofono_sim_get_ready(modem))
+ initialize_message_waiting(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);
+}
diff --git a/src/message-waiting.h b/src/message-waiting.h
new file mode 100644
index 0000000..cad4c40
--- /dev/null
+++ b/src/message-waiting.h
@@ -0,0 +1,33 @@
+/*
+ *
+ * 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
+ *
+ */
+
+enum mwi_information_type {
+ MWI_UNSPECIFIED = -1,
+ MWI_MESSAGES_WAITING = -2,
+ MWI_NO_MESSAGES_WAITING = -3,
+};
+
+/* information either a positive (or zero) message count or a
+ * partial information using one of mwi_information_type constants
+ */
+void ofono_message_waiting_notify(struct ofono_modem *modem, int information,
+ enum sms_mwi_type type, int profile);
+void ofono_message_waiting_message(struct ofono_modem *modem, const char *msg);
diff --git a/src/ofono.h b/src/ofono.h
index 3cb2d75..4e34430 100644
--- a/src/ofono.h
+++ b/src/ofono.h
@@ -79,6 +79,7 @@ struct ofono_modem {
struct sim_manager_data *sim_manager;
struct sms_manager_data *sms_manager;
struct phonebook_data *phonebook;
+ struct message_waiting_data *message_waiting;
GSList *history_contexts;
};
@@ -99,3 +100,6 @@ 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);
+
+int ofono_message_waiting_register(struct ofono_modem *modem);
+void ofono_message_waiting_unregister(struct ofono_modem *modem);
diff --git a/src/simutil.h b/src/simutil.h
index 6572e72..c2b1e20 100644
--- a/src/simutil.h
+++ b/src/simutil.h
@@ -24,6 +24,9 @@ enum sim_fileid {
SIM_EFSPN_FILEID = 0x6f46,
SIM_EFPNN_FILEID = 0x6fc5,
SIM_EFOPL_FILEID = 0x6fc6,
+ SIM_EFMBDN_FILEID = 0x6fc7,
+ SIM_EFMBI_FILEID = 0x6fc9,
+ SIM_EFMWIS_FILEID = 0x6fca,
SIM_EFSPDI_FILEID = 0x6fcd,
};
diff --git a/src/sms.c b/src/sms.c
index 3a471e3..e844e41 100644
--- a/src/sms.c
+++ b/src/sms.c
@@ -36,6 +36,7 @@
#include "util.h"
#include "sim.h"
#include "smsutil.h"
+#include "message-waiting.h"
#define uninitialized_var(x) x = x
@@ -655,9 +656,198 @@ static void handle_deliver(struct ofono_modem *modem,
g_slist_free(l);
}
-static void handle_mwi(struct ofono_modem *modem, struct sms *mwi)
+static void handle_special_sms_iei(struct ofono_modem *modem,
+ const guint8 *iei, int *set, int *store)
{
- ofono_error("MWI information not yet handled");
+ enum sms_mwi_type type;
+ int profile;
+
+ /* Parse type & storage byte */
+ *set = 0;
+ if (iei[0] & (1 << 7))
+ *store = 1;
+
+ type = iei[0] & 0x1f;
+ if (type > SMS_MWI_TYPE_OTHER) {
+ if (type == (SMS_MWI_TYPE_OTHER | 4))
+ type = SMS_MWI_TYPE_VIDEO;
+ else
+ /* 23.040 9.2.3.24.2: "Terminals should be capable of
+ * receiving any values in octet 1, even including
+ * those marked as Reserved." Treat Reserved as
+ * "Other". */
+ type = SMS_MWI_TYPE_OTHER;
+ }
+
+ profile = ((iei[0] >> 5) & 3) + 1;
+
+ ofono_message_waiting_notify(modem, iei[1], type, profile);
+}
+
+static void handle_enhanced_voicemail_iei(struct ofono_modem *modem,
+ const guint8 *iei, int *set, int *store, int length)
+{
+ int profile, n;
+
+ if (length < 3)
+ return;
+
+ /* ENHANCED_VOICE_MAIL_PDU_TYPE */
+ if (!(iei[0] & 1)) {
+ /* 9.2.3.24.13.1 Enhanced Voice Mail Notification */
+
+ /* MULTIPLE_SUBSCRIBER_PROFILE */
+ profile = (iei[0] >> 2) & 3;
+
+ /* SM_STORAGE */
+ *set = 0;
+ if (iei[0] & (1 << 4))
+ *store = 1;
+
+ /* TODO: VM_MAILBOX_ACCESS_ADDRESS */
+ n = 2 + (iei[1] + 1) / 2;
+ if (length < n + 11)
+ return;
+
+ /* TODO: VM_MESSAGE_PRIORITY_INDICATION */
+
+ /* Other parameters currently not supported */
+
+ ofono_message_waiting_notify(modem, iei[2 + n],
+ SMS_MWI_TYPE_VOICE, profile);
+ } else {
+ /* 9.2.3.24.13.2 Enhanced Voice Delete Confirmation */
+
+ /* MULTIPLE_SUBSCRIBER_PROFILE */
+ profile = (iei[0] >> 2) & 3;
+
+ /* SM_STORAGE */
+ *set = 0;
+ if (iei[0] & (1 << 4))
+ *store = 1;
+
+ /* TODO: VM_MAILBOX_ACCESS_ADDRESS */
+ n = 2 + (iei[1] + 1) / 2;
+ if (length < n + 11)
+ return;
+
+ /* Other parameters currently not supported */
+
+ ofono_message_waiting_notify(modem, iei[2 + n],
+ SMS_MWI_TYPE_VOICE, profile);
+ }
+}
+
+static void handle_mwi(struct ofono_modem *modem,
+ struct sms *sms, gboolean *out_discard)
+{
+ gboolean active, discard;
+ enum sms_mwi_type type;
+ char *message;
+ int profile = 1;
+ GSList *sms_list;
+
+ /* 23.040 9.2.3.24.2 implies "Store" bits are ORed if multiple
+ * MWI types are present but if neither Special SMS Message
+ * Indication nor DCS based indication is present, the bit
+ * must remain set.
+ */
+ int set = 1, store = 0;
+
+ /* Check MWI types in the order from lowest to highest priority
+ * because they will override one another.
+ */
+
+ if (sms->deliver.pid == SMS_PID_TYPE_RETURN_CALL) {
+ ofono_message_waiting_notify(modem, MWI_UNSPECIFIED,
+ SMS_MWI_TYPE_VOICE, profile);
+ }
+
+ if (sms_mwi_dcs_decode(sms->deliver.dcs, &type,
+ NULL, &active, &discard)) {
+ set = 0;
+ store = (discard == FALSE);
+
+ if (active)
+ ofono_message_waiting_notify(modem,
+ MWI_MESSAGES_WAITING, type, profile);
+ else
+ ofono_message_waiting_notify(modem,
+ MWI_NO_MESSAGES_WAITING, type, profile);
+ }
+
+ if (sms->deliver.udhi) {
+ guint8 special_iei[4], *evm_iei;
+ struct sms_udh_iter iter;
+ enum sms_iei iei;
+
+ if (!sms_udh_iter_init(sms, &iter))
+ goto final;
+
+ while ((iei = sms_udh_iter_get_ie_type(&iter)) !=
+ SMS_IEI_INVALID) {
+ switch (iei) {
+ case SMS_IEI_SPECIAL_MESSAGE_INDICATION:
+ if (sms_udh_iter_get_ie_length(&iter) != 2)
+ break;
+ sms_udh_iter_get_ie_data(&iter, special_iei);
+
+ handle_special_sms_iei(modem, special_iei,
+ &set, &store);
+ break;
+ }
+
+ sms_udh_iter_next(&iter);
+ }
+
+ /* Go through the UDH again because Enhanced Voice Mail
+ * Notification takes precedence over both DCS based
+ * indication and Special SMS Message indication
+ * (23.040 9.2.3.24.13.1). */
+
+ if (!sms_udh_iter_init(sms, &iter))
+ goto final;
+
+ while ((iei = sms_udh_iter_get_ie_type(&iter)) !=
+ SMS_IEI_INVALID) {
+ switch (iei) {
+ case SMS_IEI_ENHANCED_VOICE_MAIL_INFORMATION:
+ evm_iei = g_malloc0(
+ sms_udh_iter_get_ie_length(
+ &iter));
+ sms_udh_iter_get_ie_data(&iter, evm_iei);
+
+ handle_enhanced_voicemail_iei(modem, evm_iei,
+ &set, &store,
+ sms_udh_iter_get_ie_length(
+ &iter));
+
+ g_free(evm_iei);
+ break;
+ }
+
+ sms_udh_iter_next(&iter);
+ }
+ }
+
+final:
+ /* Only bother the Message Waiting interface with textual
+ * notifications that are not to be stored together with other
+ * Short Messages in ME. The other messages will be delivered
+ * to the user through normal SMS store. */
+ if (!store) {
+ sms_list = g_slist_append(NULL, sms);
+ message = sms_decode_text(sms_list);
+ g_slist_free(sms_list);
+
+ if (message) {
+ ofono_message_waiting_message(modem, message);
+ g_free(message);
+ }
+ }
+
+ if (out_discard)
+ *out_discard = !(set || store);
}
void ofono_sms_deliver_notify(struct ofono_modem *modem, unsigned char *pdu,
@@ -685,14 +875,18 @@ void ofono_sms_deliver_notify(struct ofono_modem *modem, unsigned char *pdu,
/* This is an older style MWI notification, process MWI
* headers and handle it like any other message */
if (sms.deliver.pid == SMS_PID_TYPE_RETURN_CALL) {
- handle_mwi(modem, &sms);
+ handle_mwi(modem, &sms, &discard);
+
+ if (discard)
+ return;
+
goto out;
}
/* 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(sms.deliver.dcs, NULL, NULL, NULL, &discard)) {
- handle_mwi(modem, &sms);
+ if (sms_mwi_dcs_decode(sms.deliver.dcs, NULL, NULL, NULL, NULL)) {
+ handle_mwi(modem, &sms, &discard);
if (discard)
return;
@@ -757,7 +951,14 @@ void ofono_sms_deliver_notify(struct ofono_modem *modem, unsigned char *pdu,
switch (iei) {
case SMS_IEI_SPECIAL_MESSAGE_INDICATION:
case SMS_IEI_ENHANCED_VOICE_MAIL_INFORMATION:
- handle_mwi(modem, &sms);
+ /* TODO: ignore if not in the very first
+ * segment of a concatenated SM so as not
+ * to repeat the indication. */
+ handle_mwi(modem, &sms, &discard);
+
+ if (discard)
+ return;
+
goto out;
case SMS_IEI_WCMP:
ofono_error("No support for WCMP, ignoring");
@@ -789,6 +990,9 @@ int ofono_sms_manager_register(struct ofono_modem *modem,
if (ops == NULL)
return -1;
+ if (ofono_message_waiting_register(modem))
+ return -1;
+
modem->sms_manager = sms_manager_create();
if (!modem->sms_manager)
@@ -824,4 +1028,6 @@ void ofono_sms_manager_unregister(struct ofono_modem *modem)
SMS_MANAGER_INTERFACE);
ofono_modem_remove_interface(modem, SMS_MANAGER_INTERFACE);
+
+ ofono_message_waiting_unregister(modem);
}
diff --git a/src/smsutil.h b/src/smsutil.h
index 89da973..d362aa9 100644
--- a/src/smsutil.h
+++ b/src/smsutil.h
@@ -158,6 +158,7 @@ enum sms_mwi_type {
SMS_MWI_TYPE_FAX = 1,
SMS_MWI_TYPE_EMAIL = 2,
SMS_MWI_TYPE_OTHER = 3,
+ SMS_MWI_TYPE_VIDEO = 4,
};
enum sms_pid_type {
--
1.6.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [PATCH 4/4] Add a MessageWaiting interface to track message waiting indications.
2009-08-01 23:09 ` Andrzej Zaborowski
@ 2009-08-03 16:32 ` Denis Kenzior
2009-08-03 19:09 ` Andrzej Zaborowski
0 siblings, 1 reply; 18+ messages in thread
From: Denis Kenzior @ 2009-08-03 16:32 UTC (permalink / raw)
To: ofono
[-- Attachment #1: Type: text/plain, Size: 5194 bytes --]
Hi,
> 2009/7/31 Denis Kenzior <denkenz@gmail.com>:
> >> + if (mw->messages[i] != value) {
> >> + mw->messages[i] = value;
> >> +
> >> + if (!mw->pending)
> >> + mw->pending = g_timeout_add(0, mw_mwis_update,
> >> modem); +
> >> + dbus_gsm_signal_property_changed(conn, modem->path,
> >> + MESSAGE_WAITING_INTERFACE,
> >> + mw_messages_property_name[i],
> >> + DBUS_TYPE_BYTE, &value);
> >> + }
> >> +
> >> + return dbus_message_new_method_return(msg);
> >> +}
> >
> > Ok, I'm a bit confused here. Are you sure that MWIs should have the
> > ability to be cleared out by the user? The way I understood it, the user
> > dials the voice mail system and the provider sends another MWI message
> > which clears out the status.
>
> You're right, there's probably no point to provide this method. I
> haven't found the exact statement in the docs saying that the provider
> should send a new MWI but it's logical. Otherwise I thought the D-Bus
> client might be able to tell somehow that the mailbox should now have
> 1 message less and want to update us.
Ok, now you've taken out the method entirely. We still want to set the MBDN
:) So just add SetProperty that can set the MBDN.
>
> >> +
> >> +enum mwi_information_type {
> >> + MWI_UNSPECIFIED = -1,
> >> + MWI_MESSAGES_WAITING = -2,
> >> + MWI_NO_MESSAGES_WAITING = -3,
> >> +};
> >
> > Is there a reason these are negative?
>
> So the caller can give the exact number of messages (zero or positive)
> or partial information using one of the constants.
>
I'm still not sure what the point is, since you just set messages to 1 if
MWI_MESSAGES_WAITING and to 0 if MWI_NO_MESSAGES_WAITING. And MWI_UNSPECIFIED
is just simply ignored. Perhaps you want to break up the attributes into two:
FooMailWaiting -> True / False
FooMessages -> Number, with 0 in case we're not sure
Also, please move all the MWI parsing stuff to message-waiting.c since this
will allow us to extend the interface more readily. In particular I'd like to
eventually support Message ID, Message Calling Line Identity by exposing an
additional EnhancedMessageInfo interface.
Names are for illustration only at this point:
EnhancedMessages -> "/modem1/mwi/4344", "/modem1/mwi/2255"
EnhancedMessageInfo Properties:
RetentionDays
Priority
CallingParty
However, this one's lower priority.
> Yes. :-)
>
> I'm thinking it's better to try to implement what's in the text so
> when someone needs to know how ofono will react to something, you can
> point at the specification, barring any TODOs in the code.
>
Sure, it might be a good idea to quote the relevant parts of the spec.
> > Can we instead process the different sources from highest to lowest
> > instead and bail out early? No sense in calling message_waiting_notify
> > several times (and possibly emitting spurious signals) when only once is
> > required.
>
> We can but then we won't comply with that 23.040 9.2.3.24.2 above.
> There's also a tiny possibility someone might send us updates for the
> different mailboxes (out of the 5 types defined) one using DCS and
> another one in UDH. In the attached patch I left this as is and made
> sure PropertyChanged is only sent from the time callback (bottom half)
> which was my original intention. I can still change this.
I still don't understand why we can't do something like:
if sms_contains_enhanced_vm_iei(sms):
handle_enhanced_vm_info
return
if sms_contains_special_vm_iei(sms):
discard = extract_discard_from_iei_data
// Quote relevant part of the spec here
if mwi_dcs_decode(sms, ... ,dcsdiscard)
discard = discard || dcsdiscard
return
if mwi_dcs_decode:
handle simple DCS MWI
return
if "Return Call Message"
return
> >> +final:
> >> + /* Only bother the Message Waiting interface with textual
> >> + * notifications that are not to be stored together with other
> >> + * Short Messages in ME. The other messages will be delivered
> >> + * to the user through normal SMS store. */
> >
> > It sounds to me like we can completely ignore the text of such messages.
> > The network is basically saying: "the text isn't important, the contents
> > are."
>
> Probably, although with the Return Call type of notification there's
> no other information beside the text. I left it in the updated patch.
So I still say lets get rid of LastNotificationText entirely. Remember, most
likely scenario is that carriers will send something like:
.pid = Return Call
.dcs = mwi dcs
.uhdi = true
.udh = contains special iei, contains enhanced iei.
to cover all phase mobiles in some way.
The only case you're really covering here is if we get a pure Return Call
Message. This should not happen on any modern network, and we should not
give it to the MessageWaiting interface anyway, since there's nothing useful
it can do with it. Instead, we process it like any regular text SMS.
Regards,
-Denis
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 4/4] Add a MessageWaiting interface to track message waiting indications.
2009-08-03 16:32 ` Denis Kenzior
@ 2009-08-03 19:09 ` Andrzej Zaborowski
2009-08-03 19:29 ` Denis Kenzior
0 siblings, 1 reply; 18+ messages in thread
From: Andrzej Zaborowski @ 2009-08-03 19:09 UTC (permalink / raw)
To: ofono
[-- Attachment #1: Type: text/plain, Size: 4875 bytes --]
Hi,
2009/8/3 Denis Kenzior <denkenz@gmail.com>:
> Ok, now you've taken out the method entirely. We still want to set the MBDN
> :) So just add SetProperty that can set the MBDN.
Added. Note that the provider can also control the EF-MBDN on your
sim through the Enhanced Voicemail notifications (I'll send a patch
later for this and for writing EF-MBDN back to SIM after SetProperty).
>> So the caller can give the exact number of messages (zero or positive)
>> or partial information using one of the constants.
>>
>
> I'm still not sure what the point is, since you just set messages to 1 if
> MWI_MESSAGES_WAITING and to 0 if MWI_NO_MESSAGES_WAITING. And MWI_UNSPECIFIED
> is just simply ignored.
Yes, this way sms.c gives all the information it has available
(according to specs) in a call to ofono_message_waiting_notify, which
on the message-waiting.c side decides how this information will be
presented to D-Bus clients on MessageWaiting interface (this part
isn't in the specs). I agree this isn't very useful.
> Perhaps you want to break up the attributes into two:
>
> FooMailWaiting -> True / False
> FooMessages -> Number, with 0 in case we're not sure
We can do that although I think the setting to 0 or 1 when we're not
sure is a good enough approximation? The 1 being a little lie.
>
> Also, please move all the MWI parsing stuff to message-waiting.c since this
> will allow us to extend the interface more readily. In particular I'd like to
> eventually support Message ID, Message Calling Line Identity by exposing an
> additional EnhancedMessageInfo interface.
>
> Names are for illustration only at this point:
> EnhancedMessages -> "/modem1/mwi/4344", "/modem1/mwi/2255"
>
> EnhancedMessageInfo Properties:
>
> RetentionDays
> Priority
> CallingParty
Sounds like a good idea.
>> > Can we instead process the different sources from highest to lowest
>> > instead and bail out early? No sense in calling message_waiting_notify
>> > several times (and possibly emitting spurious signals) when only once is
>> > required.
>>
>> We can but then we won't comply with that 23.040 9.2.3.24.2 above.
>> There's also a tiny possibility someone might send us updates for the
>> different mailboxes (out of the 5 types defined) one using DCS and
>> another one in UDH. In the attached patch I left this as is and made
>> sure PropertyChanged is only sent from the time callback (bottom half)
>> which was my original intention. I can still change this.
>
> I still don't understand why we can't do something like:
>
> if sms_contains_enhanced_vm_iei(sms):
> handle_enhanced_vm_info
> return
>
> if sms_contains_special_vm_iei(sms):
> discard = extract_discard_from_iei_data
> // Quote relevant part of the spec here
> if mwi_dcs_decode(sms, ... ,dcsdiscard)
> discard = discard || dcsdiscard
> return
>
> if mwi_dcs_decode:
> handle simple DCS MWI
> return
>
> if "Return Call Message"
> return
Err, yes we can, but then we don't account for the little corner cases
like the two mentioned:
* Special Message Indication IEI says discard the message but DCS
says store it.
* Special IEI says there are 3 emails waiting and DCS says there's a
voicemail message.
>
>> >> +final:
>> >> + /* Only bother the Message Waiting interface with textual
>> >> + * notifications that are not to be stored together with other
>> >> + * Short Messages in ME. The other messages will be delivered
>> >> + * to the user through normal SMS store. */
>> >
>> > It sounds to me like we can completely ignore the text of such messages.
>> > The network is basically saying: "the text isn't important, the contents
>> > are."
>>
>> Probably, although with the Return Call type of notification there's
>> no other information beside the text. I left it in the updated patch.
>
> So I still say lets get rid of LastNotificationText entirely.
Ok, removed it.
> Remember, most
> likely scenario is that carriers will send something like:
>
> .pid = Return Call
> .dcs = mwi dcs
> .uhdi = true
> .udh = contains special iei, contains enhanced iei.
>
> to cover all phase mobiles in some way.
>
> The only case you're really covering here is if we get a pure Return Call
> Message.
Right.
> This should not happen on any modern network, and we should not
> give it to the MessageWaiting interface anyway, since there's nothing useful
> it can do with it.
It still gives us one piece of information: the message is concerning
waiting messages. So perhaps it should be that interface providing
the message and from there it can be displayed on the screen.
Regards
[-- Attachment #2: 0001-Add-a-MessageWaiting-interface-to-track-message-wait.patch --]
[-- Type: application/octet-stream, Size: 24630 bytes --]
From 1bfc2e2088edd9a393dcd0abdd2745c6e6cd8bc8 Mon Sep 17 00:00:00 2001
From: Andrzej Zaborowski <andrew.zaborowski@intel.com>
Date: Mon, 3 Aug 2009 11:36:38 +0200
Subject: [PATCH] Add a MessageWaiting interface to track message waiting indications.
The state of the indications is kept in memory and written back to
the SIM after any changes.
---
src/Makefile.am | 3 +-
src/message-waiting.c | 704 +++++++++++++++++++++++++++++++++++++++++++++++++
src/message-waiting.h | 35 +++
src/ofono.h | 4 +
src/simutil.h | 3 +
src/sms.c | 30 ++-
src/smsutil.h | 1 +
7 files changed, 770 insertions(+), 10 deletions(-)
create mode 100644 src/message-waiting.c
create mode 100644 src/message-waiting.h
diff --git a/src/Makefile.am b/src/Makefile.am
index 2e3e607..4644c69 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -13,7 +13,8 @@ ofonod_SOURCES = main.c ofono.h log.c plugin.c \
network.c voicecall.c ussd.h ussd.c sms.c \
call-settings.c call-forwarding.c call-meter.c \
smsutil.h smsutil.c cssn.h cssn.c call-barring.c sim.h sim.c \
- phonebook.c history.c simutil.h simutil.c
+ phonebook.c history.c simutil.h simutil.c \
+ message-waiting.c message-waiting.h
ofonod_LDADD = $(top_builddir)/plugins/libbuiltin.la \
$(top_builddir)/drivers/libbuiltin.la \
diff --git a/src/message-waiting.c b/src/message-waiting.c
new file mode 100644
index 0000000..854c7f1
--- /dev/null
+++ b/src/message-waiting.c
@@ -0,0 +1,704 @@
+/*
+ *
+ * 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
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include <stdio.h>
+
+#include <dbus/dbus.h>
+#include <glib.h>
+#include <gdbus.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "ofono.h"
+
+#include "driver.h"
+#include "common.h"
+#include "util.h"
+#include "sim.h"
+#include "simutil.h"
+#include "smsutil.h"
+#include "message-waiting.h"
+
+#define MESSAGE_WAITING_INTERFACE "org.ofono.MessageWaiting"
+
+struct message_waiting_data {
+ int pending;
+
+ int messages[5];
+ int efmwis_length;
+ int efmbdn_length;
+ int efmbdn_record_id[5];
+
+ struct ofono_phone_number mailbox_number[5];
+
+ int messages_new[5];
+ struct ofono_phone_number mailbox_number_new[5];
+};
+
+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;
+
+ g_free(data);
+
+ modem->message_waiting = NULL;
+}
+
+static const char *mw_messages_property_name[5] = {
+ "VoicemailMessages",
+#if 0
+ "FaxMessages",
+ "EmailMessages",
+ "OtherMessages",
+ "VideomailMessages",
+#endif
+};
+
+static const char *mw_mailbox_property_name[5] = {
+ "VoicemailMailboxNumber",
+#if 0
+ "FaxMailboxNumber",
+ "EmailMailboxNumber",
+ "OtherMailboxNumber",
+ "VideomailMailboxNumber",
+#endif
+};
+
+static DBusMessage *mw_get_properties(DBusConnection *conn,
+ DBusMessage *msg, void *data)
+{
+ struct ofono_modem *modem = data;
+ struct message_waiting_data *mw = modem->message_waiting;
+ DBusMessage *reply;
+ DBusMessageIter iter;
+ DBusMessageIter dict;
+ int i;
+ unsigned char value;
+ const char *number;
+
+ reply = dbus_message_new_method_return(msg);
+ if (!reply)
+ return NULL;
+
+ dbus_message_iter_init_append(reply, &iter);
+
+ dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
+ OFONO_PROPERTIES_ARRAY_SIGNATURE, &dict);
+
+ for (i = 0; i < 5; i++)
+ if (mw_messages_property_name[i]) {
+ value = mw->messages[i];
+
+ ofono_dbus_dict_append(&dict,
+ mw_messages_property_name[i],
+ DBUS_TYPE_BYTE, &value);
+ }
+
+ for (i = 0; i < 5; i++)
+ if (mw_mailbox_property_name[i]) {
+ number = phone_number_to_string(&mw->mailbox_number[i]);
+
+ ofono_dbus_dict_append(&dict,
+ mw_mailbox_property_name[i],
+ DBUS_TYPE_STRING, &number);
+ }
+
+ dbus_message_iter_close_container(&iter, &dict);
+
+ return reply;
+}
+
+static gboolean mw_update(gpointer user);
+
+static DBusMessage *mw_set_property(DBusConnection *conn, DBusMessage *msg,
+ void *data)
+{
+ struct ofono_modem *modem = data;
+ struct message_waiting_data *mw = modem->message_waiting;
+ DBusMessageIter iter;
+ DBusMessageIter var;
+ const char *name, *value;
+ int i;
+ struct ofono_phone_number new_number;
+
+ if (mw->efmbdn_length == 0)
+ return __ofono_error_busy(msg);
+
+ if (!dbus_message_iter_init(msg, &iter))
+ return __ofono_error_invalid_args(msg);
+
+ if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
+ return __ofono_error_invalid_args(msg);
+
+ dbus_message_iter_get_basic(&iter, &name);
+
+ for (i = 0; i < 5; i++)
+ if (mw_mailbox_property_name[i] &&
+ !strcmp(name, mw_mailbox_property_name[i]))
+ break;
+ if (i == 5)
+ return __ofono_error_invalid_args(msg);
+
+ dbus_message_iter_next(&iter);
+ if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
+ return __ofono_error_invalid_args(msg);
+
+ dbus_message_iter_recurse(&iter, &var);
+ if (dbus_message_iter_get_arg_type(&var) != DBUS_TYPE_STRING)
+ return __ofono_error_invalid_format(msg);
+
+ dbus_message_iter_get_basic(&var, &value);
+ if (!valid_phone_number_format(value))
+ return __ofono_error_invalid_format(msg);
+ string_to_phone_number(value, &new_number);
+
+ if (strcmp(mw->mailbox_number_new[i].number, new_number.number) ||
+ mw->mailbox_number_new[i].type != new_number.type) {
+ memcpy(&mw->mailbox_number_new[i], &new_number,
+ sizeof(struct ofono_phone_number));
+
+ if (!mw->pending)
+ mw->pending = g_timeout_add(0, mw_update, modem);
+ }
+
+ return dbus_message_new_method_return(msg);
+}
+
+static GDBusMethodTable message_waiting_methods[] = {
+ { "GetProperties", "", "a{sv}", mw_get_properties },
+ { "SetProperty", "sv", "", mw_set_property, },
+ { }
+};
+
+static GDBusSignalTable message_waiting_signals[] = {
+ { "PropertyChanged", "sv" },
+ { }
+};
+
+static void mw_mwis_read_cb(struct ofono_modem *modem, int ok,
+ enum ofono_sim_file_structure structure, int total_length,
+ int record, const unsigned char *data, int record_length,
+ void *userdata)
+{
+ int i, status, messages[5];
+ unsigned char value;
+ DBusConnection *conn = ofono_dbus_get_connection();
+ struct message_waiting_data *mw = modem->message_waiting;
+
+ /* Handle only current identity (TODO: currently assumes first) */
+ if (record != 1)
+ return;
+
+ if (!ok ||
+ structure != OFONO_SIM_FILE_STRUCTURE_FIXED ||
+ record_length < 5) {
+ ofono_error("Unable to read waiting messages numbers "
+ "from SIM");
+
+ mw->efmwis_length = -1;
+
+ return;
+ }
+
+ status = data[0];
+ data++;
+
+ for (i = 0; i < 5 && i < record_length - 1; i++) {
+ messages[i] = ((status >> i) & 1) ? data[i] : 0;
+
+ if (mw->messages[i] != messages[i]) {
+ mw->messages[i] = messages[i];
+ mw->messages_new[i] = messages[i];
+
+ value = messages[i];
+
+ if (!mw_messages_property_name[i])
+ continue;
+
+ ofono_dbus_signal_property_changed(conn, modem->path,
+ MESSAGE_WAITING_INTERFACE,
+ mw_messages_property_name[i],
+ DBUS_TYPE_BYTE, &value);
+ }
+ }
+
+ mw->efmwis_length = record_length;
+}
+
+static void mw_mbdn_read_cb(struct ofono_modem *modem, int ok,
+ enum ofono_sim_file_structure structure, int total_length,
+ int record, const unsigned char *data, int record_length,
+ void *userdata)
+{
+ int i;
+ DBusConnection *conn = ofono_dbus_get_connection();
+ struct message_waiting_data *mw = modem->message_waiting;
+ const char *value;
+
+ if (!ok ||
+ structure != OFONO_SIM_FILE_STRUCTURE_FIXED ||
+ record_length < 14 || total_length < record_length) {
+ ofono_error("Unable to read mailbox dialling numbers "
+ "from SIM");
+
+ mw->efmbdn_length = -1;
+
+ return;
+ }
+
+ for (i = 0; i < 5; i++)
+ if (record == mw->efmbdn_record_id[i])
+ break;
+ if (i == 5)
+ return;
+
+ if (sim_adn_parse(data, record_length, &mw->mailbox_number[i]) ==
+ FALSE) {
+ mw->mailbox_number[i].number[0] = '\0';
+ mw->mailbox_number_new[i].number[0] = '\0';
+ } else {
+ memcpy(&mw->mailbox_number_new[i], &mw->mailbox_number[i],
+ sizeof(struct ofono_phone_number));
+ }
+
+ if (mw_mailbox_property_name[i]) {
+ value = phone_number_to_string(&mw->mailbox_number[i]);
+
+ ofono_dbus_signal_property_changed(conn, modem->path,
+ MESSAGE_WAITING_INTERFACE,
+ mw_mailbox_property_name[i],
+ DBUS_TYPE_STRING, &value);
+ }
+
+ mw->efmbdn_length = record_length;
+}
+
+static void mw_mbi_read_cb(struct ofono_modem *modem, int ok,
+ enum ofono_sim_file_structure structure, int total_length,
+ int record, const unsigned char *data, int record_length,
+ void *userdata)
+{
+ int i, err;
+ struct message_waiting_data *mw = modem->message_waiting;
+
+ /* Handle only current identity (TODO: currently assumes first) */
+ if (record != 1)
+ return;
+
+ if (!ok ||
+ structure != OFONO_SIM_FILE_STRUCTURE_FIXED ||
+ record_length < 4) {
+ ofono_error("Unable to read mailbox identifies "
+ "from SIM");
+
+ return;
+ }
+
+ for (i = 0; i < 5 && i < record_length; i++)
+ mw->efmbdn_record_id[i] = data[i];
+
+ err = ofono_sim_read(modem, SIM_EFMBDN_FILEID, mw_mbdn_read_cb, NULL);
+ if (err != 0) {
+ ofono_error("Unable to read EF-MBDN from SIM");
+ }
+}
+
+static void mw_mbdn_write_cb(struct ofono_modem *modem, int ok, void *userdata)
+{
+ if (!ok)
+ ofono_error("Writing new EF-MBDN failed");
+}
+
+/* Loads MWI states and MBDN from SIM */
+static gboolean mw_mwis_load(struct ofono_modem *modem)
+{
+ int err;
+
+ err = ofono_sim_read(modem, SIM_EFMWIS_FILEID, mw_mwis_read_cb, NULL);
+ if (err != 0)
+ return FALSE;
+
+ err = ofono_sim_read(modem, SIM_EFMBI_FILEID, mw_mbi_read_cb, NULL);
+ if (err != 0)
+ return FALSE;
+
+ return TRUE;
+}
+
+/* Writes MWI states and/or MBDN back to SIM */
+static gboolean mw_update(gpointer user)
+{
+ struct ofono_modem *modem = user;
+ struct message_waiting_data *mw = modem->message_waiting;
+ DBusConnection *conn = ofono_dbus_get_connection();
+ unsigned char value;
+ unsigned char *file;
+ const char *str_value;
+ int i;
+
+ mw->pending = 0;
+
+ for (i = 0; i < 5; i++)
+ if (mw->messages[i] != mw->messages_new[i]) {
+ mw->messages[i] = mw->messages_new[i];
+
+ if (!mw_messages_property_name[i])
+ continue;
+
+ value = mw->messages[i];
+
+ ofono_dbus_signal_property_changed(conn, modem->path,
+ MESSAGE_WAITING_INTERFACE,
+ mw_messages_property_name[i],
+ DBUS_TYPE_BYTE, &value);
+ }
+ if (mw->efmwis_length < 1)
+ goto mbdn;
+
+ file = g_malloc0(mw->efmwis_length);
+
+ /* Fill in numbers of messages in bytes 1 to X of EF-MWIS */
+ for (i = 0; i < 5 && i < mw->efmwis_length - 1; i++)
+ file[i + 1] = mw->messages[i];
+
+ /* Fill in indicator state bits in byte 0 */
+ for (i = 0; i < 5 && i < mw->efmwis_length - 1; i++)
+ if (file[i + 1] > 0)
+ file[0] |= 1 << i;
+
+ if (ofono_sim_write(modem, SIM_EFMWIS_FILEID, mw_mbdn_write_cb,
+ OFONO_SIM_FILE_STRUCTURE_FIXED, 1,
+ file, mw->efmwis_length, NULL) != 0) {
+ ofono_error("Queuing a EF-MWI write to SIM failed");
+ }
+
+ g_free(file);
+
+mbdn:
+ for (i = 0; i < 5; i++)
+ if (strcmp(mw->mailbox_number_new[i].number,
+ mw->mailbox_number[i].number) ||
+ mw->mailbox_number_new[i].type !=
+ mw->mailbox_number[i].type) {
+ memcpy(&mw->mailbox_number[i],
+ &mw->mailbox_number_new[i],
+ sizeof(struct ofono_phone_number));
+
+ if (!mw_mailbox_property_name[i])
+ continue;
+
+ str_value = phone_number_to_string(
+ &mw->mailbox_number[i]);
+
+ ofono_dbus_signal_property_changed(conn, modem->path,
+ MESSAGE_WAITING_INTERFACE,
+ mw_mailbox_property_name[i],
+ DBUS_TYPE_STRING, &str_value);
+ }
+ if (mw->efmbdn_length < 1)
+ return FALSE;
+
+ return FALSE;
+}
+
+void ofono_message_waiting_notify(struct ofono_modem *modem, int information,
+ enum sms_mwi_type type, int profile)
+{
+ struct message_waiting_data *mw = modem->message_waiting;
+ int invalidate;
+
+ if (mw == NULL)
+ return;
+
+ /* Handle only current identity (TODO: currently assumes first) */
+ if (profile != 1)
+ return;
+
+ /* Ignore the unspecified type of notification. It probably means
+ * that the (voicemail) indication should become active but there's
+ * no way to know when to deactivate it. It's used for the obsolete
+ * Return Call type of indication in SMS PDUs which also carry text
+ * and we provide this text instead. */
+ if (information == MWI_UNSPECIFIED)
+ return;
+
+ if (information == MWI_MESSAGES_WAITING) {
+ if (mw->messages[type] == 0) {
+ mw->messages_new[type] = 1;
+ invalidate = 1;
+ }
+ } else if (information == MWI_NO_MESSAGES_WAITING) {
+ if (mw->messages[type] > 0) {
+ mw->messages_new[type] = 0;
+ invalidate = 1;
+ }
+ } else {
+ if (mw->messages[type] != information) {
+ mw->messages_new[type] = information;
+ invalidate = 1;
+ }
+ }
+
+ if (invalidate && !mw->pending)
+ mw->pending = g_timeout_add(0, mw_update, modem);
+}
+
+static void initialize_message_waiting(struct ofono_modem *modem)
+{
+ 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);
+}
+
+int ofono_message_waiting_register(struct ofono_modem *modem)
+{
+ if (modem == NULL)
+ return -1;
+
+ modem->message_waiting = message_waiting_create();
+
+ ofono_sim_ready_notify_register(modem, initialize_message_waiting);
+ if (ofono_sim_get_ready(modem))
+ initialize_message_waiting(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, int *set, int *store)
+{
+ enum sms_mwi_type type;
+ int profile;
+
+ /* Parse type & storage byte */
+ *set = 0;
+ if (iei[0] & (1 << 7))
+ *store = 1;
+
+ type = iei[0] & 0x1f;
+ if (type > SMS_MWI_TYPE_OTHER) {
+ if (type == (SMS_MWI_TYPE_OTHER | 4))
+ type = SMS_MWI_TYPE_VIDEO;
+ else
+ /* 23.040 9.2.3.24.2: "Terminals should be capable of
+ * receiving any values in octet 1, even including
+ * those marked as Reserved." Treat Reserved as
+ * "Other". */
+ type = SMS_MWI_TYPE_OTHER;
+ }
+
+ profile = ((iei[0] >> 5) & 3) + 1;
+
+ ofono_message_waiting_notify(modem, iei[1], type, profile);
+}
+
+static void handle_enhanced_voicemail_iei(struct ofono_modem *modem,
+ const guint8 *iei, int *set, int *store, int length)
+{
+ int profile, n;
+
+ if (length < 3)
+ return;
+
+ /* ENHANCED_VOICE_MAIL_PDU_TYPE */
+ if (!(iei[0] & 1)) {
+ /* 9.2.3.24.13.1 Enhanced Voice Mail Notification */
+
+ /* MULTIPLE_SUBSCRIBER_PROFILE */
+ profile = (iei[0] >> 2) & 3;
+
+ /* SM_STORAGE */
+ *set = 0;
+ if (iei[0] & (1 << 4))
+ *store = 1;
+
+ /* TODO: VM_MAILBOX_ACCESS_ADDRESS */
+ n = 2 + (iei[1] + 1) / 2;
+ if (length < n + 11)
+ return;
+
+ /* TODO: VM_MESSAGE_PRIORITY_INDICATION */
+
+ /* Other parameters currently not supported */
+
+ ofono_message_waiting_notify(modem, iei[2 + n],
+ SMS_MWI_TYPE_VOICE, profile);
+ } else {
+ /* 9.2.3.24.13.2 Enhanced Voice Delete Confirmation */
+
+ /* MULTIPLE_SUBSCRIBER_PROFILE */
+ profile = (iei[0] >> 2) & 3;
+
+ /* SM_STORAGE */
+ *set = 0;
+ if (iei[0] & (1 << 4))
+ *store = 1;
+
+ /* TODO: VM_MAILBOX_ACCESS_ADDRESS */
+ n = 2 + (iei[1] + 1) / 2;
+ if (length < n + 11)
+ return;
+
+ /* Other parameters currently not supported */
+
+ ofono_message_waiting_notify(modem, iei[2 + n],
+ SMS_MWI_TYPE_VOICE, profile);
+ }
+}
+
+void ofono_handle_sms_mwi(struct ofono_modem *modem,
+ struct sms *sms, gboolean *out_discard)
+{
+ gboolean active, discard;
+ enum sms_mwi_type type;
+ char *message;
+ int profile = 1;
+ GSList *sms_list;
+
+ /* 23.040 9.2.3.24.2 implies "Store" bits are ORed if multiple
+ * MWI types are present but if neither Special SMS Message
+ * Indication nor DCS based indication is present, the bit
+ * must remain set.
+ */
+ int set = 1, store = 0;
+
+ /* Check MWI types in the order from lowest to highest priority
+ * because they will override one another.
+ */
+
+ if (sms->deliver.pid == SMS_PID_TYPE_RETURN_CALL) {
+ ofono_message_waiting_notify(modem, MWI_UNSPECIFIED,
+ SMS_MWI_TYPE_VOICE, profile);
+ }
+
+ if (sms_mwi_dcs_decode(sms->deliver.dcs, &type,
+ NULL, &active, &discard)) {
+ set = 0;
+ store = (discard == FALSE);
+
+ if (active)
+ ofono_message_waiting_notify(modem,
+ MWI_MESSAGES_WAITING, type, profile);
+ else
+ ofono_message_waiting_notify(modem,
+ MWI_NO_MESSAGES_WAITING, type, profile);
+ }
+
+ if (sms->deliver.udhi) {
+ guint8 special_iei[4], *evm_iei;
+ struct sms_udh_iter iter;
+ enum sms_iei iei;
+
+ if (!sms_udh_iter_init(sms, &iter))
+ goto final;
+
+ while ((iei = sms_udh_iter_get_ie_type(&iter)) !=
+ SMS_IEI_INVALID) {
+ switch (iei) {
+ case SMS_IEI_SPECIAL_MESSAGE_INDICATION:
+ if (sms_udh_iter_get_ie_length(&iter) != 2)
+ break;
+ sms_udh_iter_get_ie_data(&iter, special_iei);
+
+ handle_special_sms_iei(modem, special_iei,
+ &set, &store);
+ break;
+ }
+
+ sms_udh_iter_next(&iter);
+ }
+
+ /* Go through the UDH again because Enhanced Voice Mail
+ * Notification takes precedence over both DCS based
+ * indication and Special SMS Message indication
+ * (23.040 9.2.3.24.13.1). */
+
+ if (!sms_udh_iter_init(sms, &iter))
+ goto final;
+
+ while ((iei = sms_udh_iter_get_ie_type(&iter)) !=
+ SMS_IEI_INVALID) {
+ switch (iei) {
+ case SMS_IEI_ENHANCED_VOICE_MAIL_INFORMATION:
+ evm_iei = g_malloc0(
+ sms_udh_iter_get_ie_length(
+ &iter));
+ sms_udh_iter_get_ie_data(&iter, evm_iei);
+
+ handle_enhanced_voicemail_iei(modem, evm_iei,
+ &set, &store,
+ sms_udh_iter_get_ie_length(
+ &iter));
+
+ g_free(evm_iei);
+ break;
+ }
+
+ sms_udh_iter_next(&iter);
+ }
+ }
+
+final:
+ if (out_discard)
+ *out_discard = !(set || store);
+}
diff --git a/src/message-waiting.h b/src/message-waiting.h
new file mode 100644
index 0000000..08a5843
--- /dev/null
+++ b/src/message-waiting.h
@@ -0,0 +1,35 @@
+/*
+ *
+ * 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
+ *
+ */
+
+enum mwi_information_type {
+ MWI_UNSPECIFIED = -1,
+ MWI_MESSAGES_WAITING = -2,
+ MWI_NO_MESSAGES_WAITING = -3,
+};
+
+/* information is either a positive (or zero) message count or a
+ * partial information using one of mwi_information_type constants
+ */
+void ofono_message_waiting_notify(struct ofono_modem *modem, int information,
+ enum sms_mwi_type type, int profile);
+
+void ofono_handle_sms_mwi(struct ofono_modem *modem,
+ struct sms *sms, gboolean *out_discard);
diff --git a/src/ofono.h b/src/ofono.h
index 3cb2d75..4e34430 100644
--- a/src/ofono.h
+++ b/src/ofono.h
@@ -79,6 +79,7 @@ struct ofono_modem {
struct sim_manager_data *sim_manager;
struct sms_manager_data *sms_manager;
struct phonebook_data *phonebook;
+ struct message_waiting_data *message_waiting;
GSList *history_contexts;
};
@@ -99,3 +100,6 @@ 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);
+
+int ofono_message_waiting_register(struct ofono_modem *modem);
+void ofono_message_waiting_unregister(struct ofono_modem *modem);
diff --git a/src/simutil.h b/src/simutil.h
index 6572e72..c2b1e20 100644
--- a/src/simutil.h
+++ b/src/simutil.h
@@ -24,6 +24,9 @@ enum sim_fileid {
SIM_EFSPN_FILEID = 0x6f46,
SIM_EFPNN_FILEID = 0x6fc5,
SIM_EFOPL_FILEID = 0x6fc6,
+ SIM_EFMBDN_FILEID = 0x6fc7,
+ SIM_EFMBI_FILEID = 0x6fc9,
+ SIM_EFMWIS_FILEID = 0x6fca,
SIM_EFSPDI_FILEID = 0x6fcd,
};
diff --git a/src/sms.c b/src/sms.c
index 3a471e3..84b98de 100644
--- a/src/sms.c
+++ b/src/sms.c
@@ -36,6 +36,7 @@
#include "util.h"
#include "sim.h"
#include "smsutil.h"
+#include "message-waiting.h"
#define uninitialized_var(x) x = x
@@ -655,11 +656,6 @@ static void handle_deliver(struct ofono_modem *modem,
g_slist_free(l);
}
-static void handle_mwi(struct ofono_modem *modem, struct sms *mwi)
-{
- ofono_error("MWI information not yet handled");
-}
-
void ofono_sms_deliver_notify(struct ofono_modem *modem, unsigned char *pdu,
int len, int tpdu_len)
{
@@ -685,14 +681,18 @@ void ofono_sms_deliver_notify(struct ofono_modem *modem, unsigned char *pdu,
/* This is an older style MWI notification, process MWI
* headers and handle it like any other message */
if (sms.deliver.pid == SMS_PID_TYPE_RETURN_CALL) {
- handle_mwi(modem, &sms);
+ ofono_handle_sms_mwi(modem, &sms, &discard);
+
+ if (discard)
+ return;
+
goto out;
}
/* 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(sms.deliver.dcs, NULL, NULL, NULL, &discard)) {
- handle_mwi(modem, &sms);
+ if (sms_mwi_dcs_decode(sms.deliver.dcs, NULL, NULL, NULL, NULL)) {
+ ofono_handle_sms_mwi(modem, &sms, &discard);
if (discard)
return;
@@ -757,7 +757,14 @@ void ofono_sms_deliver_notify(struct ofono_modem *modem, unsigned char *pdu,
switch (iei) {
case SMS_IEI_SPECIAL_MESSAGE_INDICATION:
case SMS_IEI_ENHANCED_VOICE_MAIL_INFORMATION:
- handle_mwi(modem, &sms);
+ /* 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, &sms, &discard);
+
+ if (discard)
+ return;
+
goto out;
case SMS_IEI_WCMP:
ofono_error("No support for WCMP, ignoring");
@@ -789,6 +796,9 @@ int ofono_sms_manager_register(struct ofono_modem *modem,
if (ops == NULL)
return -1;
+ if (ofono_message_waiting_register(modem))
+ return -1;
+
modem->sms_manager = sms_manager_create();
if (!modem->sms_manager)
@@ -824,4 +834,6 @@ void ofono_sms_manager_unregister(struct ofono_modem *modem)
SMS_MANAGER_INTERFACE);
ofono_modem_remove_interface(modem, SMS_MANAGER_INTERFACE);
+
+ ofono_message_waiting_unregister(modem);
}
diff --git a/src/smsutil.h b/src/smsutil.h
index 89da973..d362aa9 100644
--- a/src/smsutil.h
+++ b/src/smsutil.h
@@ -158,6 +158,7 @@ enum sms_mwi_type {
SMS_MWI_TYPE_FAX = 1,
SMS_MWI_TYPE_EMAIL = 2,
SMS_MWI_TYPE_OTHER = 3,
+ SMS_MWI_TYPE_VIDEO = 4,
};
enum sms_pid_type {
--
1.6.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [PATCH 4/4] Add a MessageWaiting interface to track message waiting indications.
2009-08-03 19:09 ` Andrzej Zaborowski
@ 2009-08-03 19:29 ` Denis Kenzior
2009-08-03 21:56 ` andrzej zaborowski
0 siblings, 1 reply; 18+ messages in thread
From: Denis Kenzior @ 2009-08-03 19:29 UTC (permalink / raw)
To: ofono
[-- Attachment #1: Type: text/plain, Size: 1904 bytes --]
Hi,
> > Perhaps you want to break up the attributes into two:
> >
> > FooMailWaiting -> True / False
> > FooMessages -> Number, with 0 in case we're not sure
>
> We can do that although I think the setting to 0 or 1 when we're not
> sure is a good enough approximation? The 1 being a little lie.
Lets go with two attributes. It should give the UI a chance to display the
indicators differently, depending on what the carrier supports.
> Err, yes we can, but then we don't account for the little corner cases
> like the two mentioned:
>
> * Special Message Indication IEI says discard the message but DCS
> says store it.
Sure we do,
if sms_contains_special_vm_iei(sms):
discard = extract_discard_from_iei_data
// Quote relevant part of the spec here
if mwi_dcs_decode(sms, ... ,dcsdiscard)
discard = discard || dcsdiscard <--- here
return
> * Special IEI says there are 3 emails waiting and DCS says there's a
> voicemail message.
While the spec doesn't really forbid this, its not really in the spirit of
what is intended: "The third level is described here, and provides the maximum
detail level for analysis by the mobile, i.e. an indication of the number and
type of messages waiting in systems connected to the PLMN."
I say we don't worry about this case, just assume that the network provider is
sane.
> > This should not happen on any modern network, and we should not
> > give it to the MessageWaiting interface anyway, since there's nothing
> > useful it can do with it.
>
> It still gives us one piece of information: the message is concerning
> waiting messages. So perhaps it should be that interface providing
> the message and from there it can be displayed on the screen.
Yes, so we leave the option to do something about it later, but for now pure
"return call" messages are useless.
Regards,
-Denis
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 4/4] Add a MessageWaiting interface to track message waiting indications.
2009-08-03 19:29 ` Denis Kenzior
@ 2009-08-03 21:56 ` andrzej zaborowski
2009-08-04 20:23 ` Denis Kenzior
0 siblings, 1 reply; 18+ messages in thread
From: andrzej zaborowski @ 2009-08-03 21:56 UTC (permalink / raw)
To: ofono
[-- Attachment #1: Type: text/plain, Size: 1010 bytes --]
2009/8/3 Denis Kenzior <denkenz@gmail.com>:
> Lets go with two attributes. It should give the UI a chance to display the
> indicators differently, depending on what the carrier supports.
Now changed.
>
>> Err, yes we can, but then we don't account for the little corner cases
>> like the two mentioned:
>>
>> * Special Message Indication IEI says discard the message but DCS
>> says store it.
>
> Sure we do,
> if sms_contains_special_vm_iei(sms):
> discard = extract_discard_from_iei_data
> // Quote relevant part of the spec here
> if mwi_dcs_decode(sms, ... ,dcsdiscard)
> discard = discard || dcsdiscard <--- here
> return
True, now the order of the checks is changed to what you suggested.
If there's an enhanced voicemail IEI then we don't check for other
types of mailboxes, such as email but I suppose it's okay because even
if they're used, they'll very rarely be all in the same message.
Regards
[-- Attachment #2: 0002-Add-a-MessageWaiting-interface-to-track-message-wait.patch --]
[-- Type: application/octet-stream, Size: 26069 bytes --]
From 9efe5da3654e152d6cb81c639a8ec5124904aa51 Mon Sep 17 00:00:00 2001
From: Andrzej Zaborowski <andrew.zaborowski@intel.com>
Date: Mon, 3 Aug 2009 14:50:14 +0200
Subject: [PATCH] Add a MessageWaiting interface to track message waiting indications.
The state of the indications is kept in memory and written back to
the SIM after any changes.
---
src/Makefile.am | 3 +-
src/message-waiting.c | 761 +++++++++++++++++++++++++++++++++++++++++++++++++
src/message-waiting.h | 30 ++
src/ofono.h | 4 +
src/simutil.h | 3 +
src/sms.c | 30 ++-
src/smsutil.h | 1 +
7 files changed, 822 insertions(+), 10 deletions(-)
create mode 100644 src/message-waiting.c
create mode 100644 src/message-waiting.h
diff --git a/src/Makefile.am b/src/Makefile.am
index 2e3e607..4644c69 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -13,7 +13,8 @@ ofonod_SOURCES = main.c ofono.h log.c plugin.c \
network.c voicecall.c ussd.h ussd.c sms.c \
call-settings.c call-forwarding.c call-meter.c \
smsutil.h smsutil.c cssn.h cssn.c call-barring.c sim.h sim.c \
- phonebook.c history.c simutil.h simutil.c
+ phonebook.c history.c simutil.h simutil.c \
+ message-waiting.c message-waiting.h
ofonod_LDADD = $(top_builddir)/plugins/libbuiltin.la \
$(top_builddir)/drivers/libbuiltin.la \
diff --git a/src/message-waiting.c b/src/message-waiting.c
new file mode 100644
index 0000000..fcb4519
--- /dev/null
+++ b/src/message-waiting.c
@@ -0,0 +1,761 @@
+/*
+ *
+ * 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
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include <stdio.h>
+
+#include <dbus/dbus.h>
+#include <glib.h>
+#include <gdbus.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "ofono.h"
+
+#include "driver.h"
+#include "common.h"
+#include "util.h"
+#include "sim.h"
+#include "simutil.h"
+#include "smsutil.h"
+#include "message-waiting.h"
+
+#define MESSAGE_WAITING_INTERFACE "org.ofono.MessageWaiting"
+
+struct mailbox_state {
+ gboolean indication;
+ int message_count;
+};
+
+struct message_waiting_data {
+ struct mailbox_state messages[5];
+ int efmwis_length;
+ int efmbdn_length;
+ int efmbdn_record_id[5];
+
+ struct ofono_phone_number mailbox_number[5];
+
+ int pending;
+ struct mailbox_state messages_new[5];
+ struct ofono_phone_number mailbox_number_new[5];
+};
+
+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;
+
+ g_free(data);
+
+ modem->message_waiting = NULL;
+}
+
+static const char *mw_message_waiting_property_name[5] = {
+ "VoicemailWaiting",
+#if 0
+ "FaxWaiting",
+ "EmailWaiting",
+ "OtherWaiting",
+ "VideomailWaiting",
+#endif
+};
+
+static const char *mw_message_count_property_name[5] = {
+ "VoicemailMessageCount",
+#if 0
+ "FaxMessageCount",
+ "EmailMessageCount",
+ "OtherMessageCount",
+ "VideomailMessageCount",
+#endif
+};
+
+static const char *mw_mailbox_property_name[5] = {
+ "VoicemailMailboxNumber",
+#if 0
+ "FaxMailboxNumber",
+ "EmailMailboxNumber",
+ "OtherMailboxNumber",
+ "VideomailMailboxNumber",
+#endif
+};
+
+static DBusMessage *mw_get_properties(DBusConnection *conn,
+ DBusMessage *msg, void *data)
+{
+ struct ofono_modem *modem = data;
+ struct message_waiting_data *mw = modem->message_waiting;
+ DBusMessage *reply;
+ DBusMessageIter iter;
+ DBusMessageIter dict;
+ int i;
+ dbus_bool_t indication;
+ unsigned char count;
+ const char *number;
+
+ reply = dbus_message_new_method_return(msg);
+ if (!reply)
+ return NULL;
+
+ dbus_message_iter_init_append(reply, &iter);
+
+ dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
+ OFONO_PROPERTIES_ARRAY_SIGNATURE, &dict);
+
+ for (i = 0; i < 5; i++) {
+ if (mw_message_waiting_property_name[i]) {
+ indication = mw->messages[i].indication;
+
+ ofono_dbus_dict_append(&dict,
+ mw_message_waiting_property_name[i],
+ DBUS_TYPE_BOOLEAN, &indication);
+ }
+
+ if (mw_message_count_property_name[i]) {
+ count = mw->messages[i].message_count;
+
+ ofono_dbus_dict_append(&dict,
+ mw_message_count_property_name[i],
+ DBUS_TYPE_BYTE, &count);
+ }
+
+ if (mw_mailbox_property_name[i]) {
+ number = phone_number_to_string(&mw->mailbox_number[i]);
+
+ ofono_dbus_dict_append(&dict,
+ mw_mailbox_property_name[i],
+ DBUS_TYPE_STRING, &number);
+ }
+ }
+
+ dbus_message_iter_close_container(&iter, &dict);
+
+ return reply;
+}
+
+static gboolean mw_update(gpointer user);
+
+static DBusMessage *mw_set_property(DBusConnection *conn, DBusMessage *msg,
+ void *data)
+{
+ struct ofono_modem *modem = data;
+ struct message_waiting_data *mw = modem->message_waiting;
+ DBusMessageIter iter;
+ DBusMessageIter var;
+ const char *name, *value;
+ int i;
+ struct ofono_phone_number new_number;
+
+ if (mw->efmbdn_length == 0)
+ return __ofono_error_busy(msg);
+
+ if (!dbus_message_iter_init(msg, &iter))
+ return __ofono_error_invalid_args(msg);
+
+ if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
+ return __ofono_error_invalid_args(msg);
+
+ dbus_message_iter_get_basic(&iter, &name);
+
+ for (i = 0; i < 5; i++)
+ if (mw_mailbox_property_name[i] &&
+ !strcmp(name, mw_mailbox_property_name[i]))
+ break;
+ if (i == 5)
+ return __ofono_error_invalid_args(msg);
+
+ dbus_message_iter_next(&iter);
+ if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
+ return __ofono_error_invalid_args(msg);
+
+ dbus_message_iter_recurse(&iter, &var);
+ if (dbus_message_iter_get_arg_type(&var) != DBUS_TYPE_STRING)
+ return __ofono_error_invalid_format(msg);
+
+ dbus_message_iter_get_basic(&var, &value);
+ if (!valid_phone_number_format(value))
+ return __ofono_error_invalid_format(msg);
+ string_to_phone_number(value, &new_number);
+
+ if (strcmp(mw->mailbox_number_new[i].number, new_number.number) ||
+ mw->mailbox_number_new[i].type != new_number.type) {
+ memcpy(&mw->mailbox_number_new[i], &new_number,
+ sizeof(struct ofono_phone_number));
+
+ if (!mw->pending)
+ mw->pending = g_timeout_add(0, mw_update, modem);
+ }
+
+ return dbus_message_new_method_return(msg);
+}
+
+static GDBusMethodTable message_waiting_methods[] = {
+ { "GetProperties", "", "a{sv}", mw_get_properties },
+ { "SetProperty", "sv", "", mw_set_property, },
+ { }
+};
+
+static GDBusSignalTable message_waiting_signals[] = {
+ { "PropertyChanged", "sv" },
+ { }
+};
+
+static void mw_mwis_read_cb(struct ofono_modem *modem, int ok,
+ enum ofono_sim_file_structure structure, int total_length,
+ int record, const unsigned char *data, int record_length,
+ void *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;
+
+ if (!ok ||
+ structure != OFONO_SIM_FILE_STRUCTURE_FIXED ||
+ record_length < 5) {
+ ofono_error("Unable to read waiting messages numbers "
+ "from SIM");
+
+ mw->efmwis_length = -1;
+
+ return;
+ }
+
+ /* Handle only current identity (TODO: currently assumes first) */
+ if (record != 1)
+ return;
+
+ status = data[0];
+ data++;
+
+ for (i = 0; i < 5 && i < record_length - 1; i++) {
+ info.indication = (status >> i) & 1;
+ info.message_count = info.indication ? data[0] : 0;
+
+ if (mw->messages[i].indication != info.indication ||
+ mw->messages[i].message_count !=
+ info.message_count) {
+ memcpy(&mw->messages[i], &info, sizeof(info));
+ memcpy(&mw->messages_new[i], &info, sizeof(info));
+
+ if (!mw_message_waiting_property_name[i])
+ continue;
+
+ indication = info.indication;
+ count = info.message_count;
+
+ ofono_dbus_signal_property_changed(conn, modem->path,
+ MESSAGE_WAITING_INTERFACE,
+ mw_message_waiting_property_name[i],
+ DBUS_TYPE_BOOLEAN, &indication);
+ ofono_dbus_signal_property_changed(conn, modem->path,
+ MESSAGE_WAITING_INTERFACE,
+ mw_message_count_property_name[i],
+ DBUS_TYPE_BYTE, &count);
+ }
+ }
+
+ mw->efmwis_length = record_length;
+}
+
+static void mw_mbdn_read_cb(struct ofono_modem *modem, int ok,
+ enum ofono_sim_file_structure structure, int total_length,
+ int record, const unsigned char *data, int record_length,
+ void *userdata)
+{
+ int i;
+ DBusConnection *conn = ofono_dbus_get_connection();
+ struct message_waiting_data *mw = modem->message_waiting;
+ const char *value;
+
+ if (!ok ||
+ structure != OFONO_SIM_FILE_STRUCTURE_FIXED ||
+ record_length < 14 || total_length < record_length) {
+ ofono_error("Unable to read mailbox dialling numbers "
+ "from SIM");
+
+ mw->efmbdn_length = -1;
+
+ return;
+ }
+
+ for (i = 0; i < 5; i++)
+ if (record == mw->efmbdn_record_id[i])
+ break;
+ if (i == 5)
+ return;
+
+ if (sim_adn_parse(data, record_length, &mw->mailbox_number[i]) ==
+ FALSE) {
+ mw->mailbox_number[i].number[0] = '\0';
+ mw->mailbox_number_new[i].number[0] = '\0';
+ } else {
+ memcpy(&mw->mailbox_number_new[i], &mw->mailbox_number[i],
+ sizeof(struct ofono_phone_number));
+ }
+
+ if (mw_mailbox_property_name[i]) {
+ value = phone_number_to_string(&mw->mailbox_number[i]);
+
+ ofono_dbus_signal_property_changed(conn, modem->path,
+ MESSAGE_WAITING_INTERFACE,
+ mw_mailbox_property_name[i],
+ DBUS_TYPE_STRING, &value);
+ }
+
+ mw->efmbdn_length = record_length;
+}
+
+static void mw_mbi_read_cb(struct ofono_modem *modem, int ok,
+ enum ofono_sim_file_structure structure, int total_length,
+ int record, const unsigned char *data, int record_length,
+ void *userdata)
+{
+ int i, err;
+ struct message_waiting_data *mw = modem->message_waiting;
+
+ if (!ok ||
+ structure != OFONO_SIM_FILE_STRUCTURE_FIXED ||
+ record_length < 4) {
+ ofono_error("Unable to read mailbox identifies "
+ "from SIM");
+
+ mw->efmbdn_length = -1;
+
+ return;
+ }
+
+ /* Handle only current identity (TODO: currently assumes first) */
+ if (record != 1)
+ return;
+
+ for (i = 0; i < 5 && i < record_length; i++)
+ mw->efmbdn_record_id[i] = data[i];
+
+ err = ofono_sim_read(modem, SIM_EFMBDN_FILEID, mw_mbdn_read_cb, NULL);
+ if (err != 0) {
+ ofono_error("Unable to read EF-MBDN from SIM");
+ }
+}
+
+static void mw_mbdn_write_cb(struct ofono_modem *modem, int ok, void *userdata)
+{
+ if (!ok)
+ ofono_error("Writing new EF-MBDN failed");
+}
+
+/* Loads MWI states and MBDN from SIM */
+static gboolean mw_mwis_load(struct ofono_modem *modem)
+{
+ int err;
+
+ err = ofono_sim_read(modem, SIM_EFMWIS_FILEID, mw_mwis_read_cb, NULL);
+ if (err != 0)
+ return FALSE;
+
+ err = ofono_sim_read(modem, SIM_EFMBI_FILEID, mw_mbi_read_cb, NULL);
+ if (err != 0)
+ return FALSE;
+
+ return TRUE;
+}
+
+/* Writes MWI states and/or MBDN back to SIM */
+static gboolean mw_update(gpointer user)
+{
+ struct ofono_modem *modem = user;
+ struct message_waiting_data *mw = modem->message_waiting;
+ DBusConnection *conn = ofono_dbus_get_connection();
+ dbus_bool_t indication;
+ unsigned char count;
+ const char *number;
+ int i;
+ unsigned char *file;
+
+ mw->pending = 0;
+
+ for (i = 0; i < 5; i++) {
+ if (mw->messages_new[i].message_count !=
+ mw->messages[i].message_count) {
+ mw->messages[i].message_count =
+ mw->messages_new[i].message_count;
+
+ if (!mw_message_count_property_name[i])
+ continue;
+
+ count = mw->messages[i].message_count;
+
+ ofono_dbus_signal_property_changed(conn, modem->path,
+ MESSAGE_WAITING_INTERFACE,
+ mw_message_count_property_name[i],
+ DBUS_TYPE_BYTE, &count);
+ }
+
+ if (mw->messages_new[i].indication !=
+ mw->messages[i].indication) {
+ mw->messages[i].indication =
+ mw->messages_new[i].indication;
+
+ if (!mw_message_waiting_property_name[i])
+ continue;
+
+ indication = mw->messages[i].indication;
+
+ ofono_dbus_signal_property_changed(conn, modem->path,
+ MESSAGE_WAITING_INTERFACE,
+ mw_message_waiting_property_name[i],
+ DBUS_TYPE_BOOLEAN, &indication);
+ }
+ }
+ if (mw->efmwis_length < 1)
+ goto mbdn;
+
+ file = g_malloc0(mw->efmwis_length);
+
+ /* Fill in numbers of messages in bytes 1 to X of EF-MWIS */
+ for (i = 0; i < 5 && i < mw->efmwis_length - 1; i++)
+ file[i + 1] = mw->messages[i].message_count;
+
+ /* Fill in indicator state bits in byte 0 */
+ for (i = 0; i < 5 && i < mw->efmwis_length - 1; i++)
+ if (mw->messages[i].indication)
+ file[0] |= 1 << i;
+
+ if (ofono_sim_write(modem, SIM_EFMWIS_FILEID, mw_mbdn_write_cb,
+ OFONO_SIM_FILE_STRUCTURE_FIXED, 1,
+ file, mw->efmwis_length, NULL) != 0) {
+ ofono_error("Queuing a EF-MWI write to SIM failed");
+ }
+
+ g_free(file);
+
+mbdn:
+ for (i = 0; i < 5; i++)
+ if (strcmp(mw->mailbox_number_new[i].number,
+ mw->mailbox_number[i].number) ||
+ mw->mailbox_number_new[i].type !=
+ mw->mailbox_number[i].type) {
+ memcpy(&mw->mailbox_number[i],
+ &mw->mailbox_number_new[i],
+ sizeof(struct ofono_phone_number));
+
+ if (!mw_mailbox_property_name[i])
+ continue;
+
+ number = phone_number_to_string(
+ &mw->mailbox_number[i]);
+
+ ofono_dbus_signal_property_changed(conn, modem->path,
+ MESSAGE_WAITING_INTERFACE,
+ mw_mailbox_property_name[i],
+ DBUS_TYPE_STRING, &number);
+ }
+ if (mw->efmbdn_length < 1)
+ return FALSE;
+
+ return FALSE;
+}
+
+void ofono_message_waiting_present_notify(struct ofono_modem *modem,
+ enum sms_mwi_type type, gboolean present, int profile)
+{
+ struct message_waiting_data *mw = modem->message_waiting;
+
+ if (mw == NULL)
+ return;
+
+ /* Handle only current identity (TODO: currently assumes first) */
+ if (profile != 1)
+ return;
+
+ present = !!present;
+ if (mw->messages_new[type].indication != present) {
+ mw->messages_new[type].indication = present;
+ if (!present)
+ mw->messages_new[type].message_count = 0;
+
+ if (!mw->pending)
+ mw->pending = g_timeout_add(0, mw_update, modem);
+ }
+}
+
+void ofono_message_waiting_count_notify(struct ofono_modem *modem,
+ enum sms_mwi_type type, int count, int profile)
+{
+ struct message_waiting_data *mw = modem->message_waiting;
+
+ if (mw == NULL)
+ return;
+
+ /* Handle only current identity (TODO: currently assumes first) */
+ if (profile != 1)
+ return;
+
+ if (mw->messages_new[type].message_count != count ||
+ mw->messages_new[type].indication != (count > 0)) {
+ mw->messages_new[type].message_count = count;
+ mw->messages_new[type].indication = (count > 0);
+
+ if (!mw->pending)
+ mw->pending = g_timeout_add(0, mw_update, modem);
+ }
+}
+
+static void initialize_message_waiting(struct ofono_modem *modem)
+{
+ 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);
+}
+
+int ofono_message_waiting_register(struct ofono_modem *modem)
+{
+ if (modem == NULL)
+ return -1;
+
+ modem->message_waiting = message_waiting_create();
+
+ ofono_sim_ready_notify_register(modem, initialize_message_waiting);
+ if (ofono_sim_get_ready(modem))
+ initialize_message_waiting(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)
+{
+ enum sms_mwi_type type;
+ int profile;
+
+ /* Parse type & storage byte */
+ if (discard)
+ *discard = (iei[0] & (1 << 7)) ? FALSE : TRUE;
+
+ type = iei[0] & 0x1f;
+ if (type > SMS_MWI_TYPE_OTHER) {
+ if (type == (SMS_MWI_TYPE_OTHER | 4))
+ type = SMS_MWI_TYPE_VIDEO;
+ else
+ /* 23.040 9.2.3.24.2: "Terminals should be capable of
+ * receiving any values in octet 1, even including
+ * those marked as Reserved." Treat Reserved as
+ * "Other". */
+ type = SMS_MWI_TYPE_OTHER;
+ }
+
+ profile = ((iei[0] >> 5) & 3) + 1;
+
+ ofono_message_waiting_count_notify(modem, iei[1], type, profile);
+}
+
+static void handle_enhanced_voicemail_iei(struct ofono_modem *modem,
+ const guint8 *iei, gboolean *discard, int length)
+{
+ int profile, n;
+
+ if (length < 3)
+ return;
+
+ /* ENHANCED_VOICE_MAIL_PDU_TYPE */
+ if (!(iei[0] & 1)) {
+ /* 9.2.3.24.13.1 Enhanced Voice Mail Notification */
+
+ /* MULTIPLE_SUBSCRIBER_PROFILE */
+ profile = (iei[0] >> 2) & 3;
+
+ /* SM_STORAGE */
+ if (discard)
+ *discard = (iei[0] & (1 << 4)) ? FALSE : TRUE;
+
+ /* TODO: VM_MAILBOX_ACCESS_ADDRESS */
+ n = 2 + (iei[1] + 1) / 2;
+ if (length < n + 11)
+ return;
+
+ /* TODO: VM_MESSAGE_PRIORITY_INDICATION */
+
+ /* Other parameters currently not supported */
+
+ ofono_message_waiting_count_notify(modem, iei[2 + n],
+ SMS_MWI_TYPE_VOICE, profile);
+ } else {
+ /* 9.2.3.24.13.2 Enhanced Voice Delete Confirmation */
+
+ /* MULTIPLE_SUBSCRIBER_PROFILE */
+ profile = (iei[0] >> 2) & 3;
+
+ /* SM_STORAGE */
+ if (discard)
+ *discard = (iei[0] & (1 << 4)) ? FALSE : TRUE;
+
+ /* TODO: VM_MAILBOX_ACCESS_ADDRESS */
+ n = 2 + (iei[1] + 1) / 2;
+ if (length < n + 11)
+ return;
+
+ /* Other parameters currently not supported */
+
+ ofono_message_waiting_count_notify(modem, iei[2 + n],
+ SMS_MWI_TYPE_VOICE, profile);
+ }
+}
+
+void ofono_handle_sms_mwi(struct ofono_modem *modem,
+ struct sms *sms, gboolean *out_discard)
+{
+ gboolean active, discard;
+ enum sms_mwi_type type;
+ int profile = 1, iei_found = 0;
+
+ if (out_discard)
+ *out_discard = FALSE;
+
+ /* Check MWI types in the order from highest priority to lowest
+ * because they must override one another.
+ */
+
+ if (sms->deliver.udhi) {
+ guint8 *evm_iei;
+ struct sms_udh_iter iter;
+ enum sms_iei iei;
+
+ if (!sms_udh_iter_init(sms, &iter))
+ return;
+
+ while ((iei = sms_udh_iter_get_ie_type(&iter)) !=
+ SMS_IEI_INVALID) {
+ switch (iei) {
+ case SMS_IEI_ENHANCED_VOICE_MAIL_INFORMATION:
+ evm_iei = g_malloc0(
+ sms_udh_iter_get_ie_length(
+ &iter));
+ sms_udh_iter_get_ie_data(&iter, evm_iei);
+
+ handle_enhanced_voicemail_iei(modem, evm_iei,
+ out_discard,
+ sms_udh_iter_get_ie_length(
+ &iter));
+
+ g_free(evm_iei);
+ return;
+ }
+
+ sms_udh_iter_next(&iter);
+ }
+ }
+
+ if (sms->deliver.udhi) {
+ guint8 special_iei[4];
+ struct sms_udh_iter iter;
+ enum sms_iei iei;
+
+ if (!sms_udh_iter_init(sms, &iter))
+ return;
+
+ while ((iei = sms_udh_iter_get_ie_type(&iter)) !=
+ SMS_IEI_INVALID) {
+ switch (iei) {
+ case SMS_IEI_SPECIAL_MESSAGE_INDICATION:
+ if (sms_udh_iter_get_ie_length(&iter) != 2)
+ break;
+ sms_udh_iter_get_ie_data(&iter, special_iei);
+
+ handle_special_sms_iei(modem, special_iei,
+ &discard);
+ if (out_discard)
+ *out_discard = *out_discard || discard;
+ iei_found = 1;
+ }
+
+ sms_udh_iter_next(&iter);
+ }
+
+ if (iei_found) {
+ /* 23.040 9.2.3.24.2 says "In the event of a
+ * conflict between this setting and the setting
+ * of the Data Coding Scheme (see 3GPP TS 23.038 [9])
+ * then the message shall be stored if either the DCS
+ * indicates this, or Octet 1 above indicates this."
+ */
+ if (sms_mwi_dcs_decode(sms->deliver.dcs, NULL,
+ NULL, NULL, &discard)) {
+ if (out_discard)
+ *out_discard = *out_discard || discard;
+ }
+
+ return;
+ }
+ }
+
+ if (sms_mwi_dcs_decode(sms->deliver.dcs, &type,
+ NULL, &active, out_discard)) {
+ ofono_message_waiting_present_notify(modem,
+ type, active, profile);
+
+ return;
+ }
+
+ if (sms->deliver.pid == SMS_PID_TYPE_RETURN_CALL)
+ return;
+}
diff --git a/src/message-waiting.h b/src/message-waiting.h
new file mode 100644
index 0000000..c0e60bf
--- /dev/null
+++ b/src/message-waiting.h
@@ -0,0 +1,30 @@
+/*
+ *
+ * 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
+ *
+ */
+
+void ofono_message_waiting_present_notify(struct ofono_modem *modem,
+ enum sms_mwi_type type,
+ gboolean present, int profile);
+void ofono_message_waiting_count_notify(struct ofono_modem *modem,
+ enum sms_mwi_type type, int count,
+ int profile);
+
+void ofono_handle_sms_mwi(struct ofono_modem *modem,
+ struct sms *sms, gboolean *out_discard);
diff --git a/src/ofono.h b/src/ofono.h
index 3cb2d75..4e34430 100644
--- a/src/ofono.h
+++ b/src/ofono.h
@@ -79,6 +79,7 @@ struct ofono_modem {
struct sim_manager_data *sim_manager;
struct sms_manager_data *sms_manager;
struct phonebook_data *phonebook;
+ struct message_waiting_data *message_waiting;
GSList *history_contexts;
};
@@ -99,3 +100,6 @@ 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);
+
+int ofono_message_waiting_register(struct ofono_modem *modem);
+void ofono_message_waiting_unregister(struct ofono_modem *modem);
diff --git a/src/simutil.h b/src/simutil.h
index 6572e72..c2b1e20 100644
--- a/src/simutil.h
+++ b/src/simutil.h
@@ -24,6 +24,9 @@ enum sim_fileid {
SIM_EFSPN_FILEID = 0x6f46,
SIM_EFPNN_FILEID = 0x6fc5,
SIM_EFOPL_FILEID = 0x6fc6,
+ SIM_EFMBDN_FILEID = 0x6fc7,
+ SIM_EFMBI_FILEID = 0x6fc9,
+ SIM_EFMWIS_FILEID = 0x6fca,
SIM_EFSPDI_FILEID = 0x6fcd,
};
diff --git a/src/sms.c b/src/sms.c
index 3a471e3..84b98de 100644
--- a/src/sms.c
+++ b/src/sms.c
@@ -36,6 +36,7 @@
#include "util.h"
#include "sim.h"
#include "smsutil.h"
+#include "message-waiting.h"
#define uninitialized_var(x) x = x
@@ -655,11 +656,6 @@ static void handle_deliver(struct ofono_modem *modem,
g_slist_free(l);
}
-static void handle_mwi(struct ofono_modem *modem, struct sms *mwi)
-{
- ofono_error("MWI information not yet handled");
-}
-
void ofono_sms_deliver_notify(struct ofono_modem *modem, unsigned char *pdu,
int len, int tpdu_len)
{
@@ -685,14 +681,18 @@ void ofono_sms_deliver_notify(struct ofono_modem *modem, unsigned char *pdu,
/* This is an older style MWI notification, process MWI
* headers and handle it like any other message */
if (sms.deliver.pid == SMS_PID_TYPE_RETURN_CALL) {
- handle_mwi(modem, &sms);
+ ofono_handle_sms_mwi(modem, &sms, &discard);
+
+ if (discard)
+ return;
+
goto out;
}
/* 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(sms.deliver.dcs, NULL, NULL, NULL, &discard)) {
- handle_mwi(modem, &sms);
+ if (sms_mwi_dcs_decode(sms.deliver.dcs, NULL, NULL, NULL, NULL)) {
+ ofono_handle_sms_mwi(modem, &sms, &discard);
if (discard)
return;
@@ -757,7 +757,14 @@ void ofono_sms_deliver_notify(struct ofono_modem *modem, unsigned char *pdu,
switch (iei) {
case SMS_IEI_SPECIAL_MESSAGE_INDICATION:
case SMS_IEI_ENHANCED_VOICE_MAIL_INFORMATION:
- handle_mwi(modem, &sms);
+ /* 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, &sms, &discard);
+
+ if (discard)
+ return;
+
goto out;
case SMS_IEI_WCMP:
ofono_error("No support for WCMP, ignoring");
@@ -789,6 +796,9 @@ int ofono_sms_manager_register(struct ofono_modem *modem,
if (ops == NULL)
return -1;
+ if (ofono_message_waiting_register(modem))
+ return -1;
+
modem->sms_manager = sms_manager_create();
if (!modem->sms_manager)
@@ -824,4 +834,6 @@ void ofono_sms_manager_unregister(struct ofono_modem *modem)
SMS_MANAGER_INTERFACE);
ofono_modem_remove_interface(modem, SMS_MANAGER_INTERFACE);
+
+ ofono_message_waiting_unregister(modem);
}
diff --git a/src/smsutil.h b/src/smsutil.h
index 89da973..d362aa9 100644
--- a/src/smsutil.h
+++ b/src/smsutil.h
@@ -158,6 +158,7 @@ enum sms_mwi_type {
SMS_MWI_TYPE_FAX = 1,
SMS_MWI_TYPE_EMAIL = 2,
SMS_MWI_TYPE_OTHER = 3,
+ SMS_MWI_TYPE_VIDEO = 4,
};
enum sms_pid_type {
--
1.6.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [PATCH 4/4] Add a MessageWaiting interface to track message waiting indications.
2009-08-03 21:56 ` andrzej zaborowski
@ 2009-08-04 20:23 ` Denis Kenzior
2009-08-05 14:18 ` andrzej zaborowski
0 siblings, 1 reply; 18+ messages in thread
From: Denis Kenzior @ 2009-08-04 20:23 UTC (permalink / raw)
To: ofono
[-- Attachment #1: Type: text/plain, Size: 332 bytes --]
Hi,
I've pushed this patch and heavily customized it afterwards to simplify the
logic a bit. Can you check that it is still working as intended?
Writing of MBDN fields is still missing. Can you send another patch for this?
Also one fo writing of MSISDN records in SimManager would be good as well.
Regards,
-Denis
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 4/4] Add a MessageWaiting interface to track message waiting indications.
2009-08-04 20:23 ` Denis Kenzior
@ 2009-08-05 14:18 ` andrzej zaborowski
2009-08-05 17:47 ` Denis Kenzior
0 siblings, 1 reply; 18+ messages in thread
From: andrzej zaborowski @ 2009-08-05 14:18 UTC (permalink / raw)
To: ofono
[-- Attachment #1: Type: text/plain, Size: 1000 bytes --]
2009/8/4 Denis Kenzior <denkenz@gmail.com>:
> I've pushed this patch and heavily customized it afterwards to simplify the
> logic a bit. Can you check that it is still working as intended?
It is kind of working but one of the things "simplified away" is using
the D-Bus interface even without working EF-MBDN or EF-MWIS files on
the SIM, i.e. if the write fails then the user never finds out there
was a notification.
Consistently with the change to return invalid_args on D-Bus type
mismatch, I'm attaching a diff to do the same thing for other
interfaces we have.
You might want to add G_DBUS_METHOD_FLAG_ASYNC to SetProperty
signature and remove mw_update declaration which is now unused. Also
the check in cache_info should probably be if (r < len).
>
> Writing of MBDN fields is still missing. Can you send another patch for this?
Sent separately.
> Also one fo writing of MSISDN records in SimManager would be good as well.
Will get on it today.
Regards
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Use-invalid_args-instead-of-invalid_format.patch --]
[-- Type: text/x-patch, Size: 2741 bytes --]
From 4096f07b8b08005866ee69188763e5885574ed8c Mon Sep 17 00:00:00 2001
From: Andrzej Zaborowski <andrew.zaborowski@intel.com>
Date: Wed, 5 Aug 2009 07:17:10 +0200
Subject: [PATCH] Use invalid_args instead of invalid_format
---
src/call-barring.c | 4 ++--
src/call-meter.c | 4 ++--
src/call-settings.c | 4 ++--
3 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/src/call-barring.c b/src/call-barring.c
index 36deaf7..386a127 100644
--- a/src/call-barring.c
+++ b/src/call-barring.c
@@ -882,13 +882,13 @@ static DBusMessage *cb_set_property(DBusConnection *conn, DBusMessage *msg,
dbus_message_iter_recurse(&iter, &var);
if (dbus_message_iter_get_arg_type(&var) != DBUS_TYPE_STRING)
- return __ofono_error_invalid_format(msg);
+ return __ofono_error_invalid_args(msg);
dbus_message_iter_get_basic(&var, &value);
if (!cb_lock_property_lookup(name, value, BEARER_CLASS_VOICE,
&lock, &cls, &mode))
- return __ofono_error_invalid_format(msg);
+ return __ofono_error_invalid_args(msg);
if (dbus_message_iter_next(&iter)) {
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
diff --git a/src/call-meter.c b/src/call-meter.c
index 421fe0c..6147540 100644
--- a/src/call-meter.c
+++ b/src/call-meter.c
@@ -584,7 +584,7 @@ static DBusMessage *cm_set_property(DBusConnection *conn, DBusMessage *msg,
return __ofono_error_invalid_args(msg);
if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
- return __ofono_error_invalid_args(msg);
+ return __ofono_error_invalid_args(msg);
dbus_message_iter_get_basic(&iter, &passwd);
@@ -596,7 +596,7 @@ static DBusMessage *cm_set_property(DBusConnection *conn, DBusMessage *msg,
continue;
if (dbus_message_iter_get_arg_type(&var) != property->type)
- return __ofono_error_invalid_format(msg);
+ return __ofono_error_invalid_args(msg);
return property->set(msg, modem, &var, passwd);
}
diff --git a/src/call-settings.c b/src/call-settings.c
index 18e8189..9fcb59e 100644
--- a/src/call-settings.c
+++ b/src/call-settings.c
@@ -1167,7 +1167,7 @@ static DBusMessage *cs_set_property(DBusConnection *conn, DBusMessage *msg,
const char *setting;
if (dbus_message_iter_get_arg_type(&var) != DBUS_TYPE_STRING)
- return __ofono_error_invalid_format(msg);
+ return __ofono_error_invalid_args(msg);
dbus_message_iter_get_basic(&var, &setting);
@@ -1176,7 +1176,7 @@ static DBusMessage *cs_set_property(DBusConnection *conn, DBusMessage *msg,
const char *setting;
if (dbus_message_iter_get_arg_type(&var) != DBUS_TYPE_STRING)
- return __ofono_error_invalid_format(msg);
+ return __ofono_error_invalid_args(msg);
dbus_message_iter_get_basic(&var, &setting);
--
1.6.1
^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [PATCH 4/4] Add a MessageWaiting interface to track message waiting indications.
2009-08-05 14:18 ` andrzej zaborowski
@ 2009-08-05 17:47 ` Denis Kenzior
2009-08-05 19:18 ` andrzej zaborowski
0 siblings, 1 reply; 18+ messages in thread
From: Denis Kenzior @ 2009-08-05 17:47 UTC (permalink / raw)
To: ofono
[-- Attachment #1: Type: text/plain, Size: 1008 bytes --]
Hi,
> It is kind of working but one of the things "simplified away" is using
> the D-Bus interface even without working EF-MBDN or EF-MWIS files on
> the SIM, i.e. if the write fails then the user never finds out there
> was a notification.
Sorry I don't quite follow. The mw_set_indicator function sets the value and
emits the signals regardless of whether the MWIS file could be written. Can
you explain some more?
For setting mailbox numbers, a working EF-MBDN is required since the only
alternative would be to store them on the filesystem.
>
> Consistently with the change to return invalid_args on D-Bus type
> mismatch, I'm attaching a diff to do the same thing for other
> interfaces we have.
Patch has been applied.
>
> You might want to add G_DBUS_METHOD_FLAG_ASYNC to SetProperty
> signature and remove mw_update declaration which is now unused. Also
> the check in cache_info should probably be if (r < len).
Yep, yep and yep. Thanks.
Regards,
-Denis
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 4/4] Add a MessageWaiting interface to track message waiting indications.
2009-08-05 17:47 ` Denis Kenzior
@ 2009-08-05 19:18 ` andrzej zaborowski
2009-08-05 19:35 ` Denis Kenzior
0 siblings, 1 reply; 18+ messages in thread
From: andrzej zaborowski @ 2009-08-05 19:18 UTC (permalink / raw)
To: ofono
[-- Attachment #1: Type: text/plain, Size: 801 bytes --]
2009/8/5 Denis Kenzior <denkenz@gmail.com>:
> Sorry I don't quite follow. The mw_set_indicator function sets the value and
> emits the signals regardless of whether the MWIS file could be written. Can
> you explain some more?
>
> For setting mailbox numbers, a working EF-MBDN is required since the only
> alternative would be to store them on the filesystem.
mw_set_indicator does the right thing, I missed this fact. But when a
mailbox number is set or received from network all clients get a
PropertyChanged and the new number can be retrieved from the interface
but only when the store succeeded, previously it would be available
regardless of MBDN on the card and the writing to card was secondary.
The number is kind of important if you want to hear the messages.
Regards
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 4/4] Add a MessageWaiting interface to track message waiting indications.
2009-08-05 19:18 ` andrzej zaborowski
@ 2009-08-05 19:35 ` Denis Kenzior
2009-08-07 3:25 ` andrzej zaborowski
0 siblings, 1 reply; 18+ messages in thread
From: Denis Kenzior @ 2009-08-05 19:35 UTC (permalink / raw)
To: ofono
[-- Attachment #1: Type: text/plain, Size: 1559 bytes --]
Hi Andrew,
> > For setting mailbox numbers, a working EF-MBDN is required since the only
> > alternative would be to store them on the filesystem.
>
> mw_set_indicator does the right thing, I missed this fact. But when a
> mailbox number is set or received from network all clients get a
> PropertyChanged and the new number can be retrieved from the interface
> but only when the store succeeded, previously it would be available
> regardless of MBDN on the card and the writing to card was secondary.
> The number is kind of important if you want to hear the messages.
So you're right that even if we get an enhanced voice mail notification message
the Mailbox number won't be signaled unless we have the SIM provisioned with
EF-MBI & EF-MBDN.
The problem is, if we don't have the SIM files available, then the next time
oFono is restarted this information is lost anyway until the next MWI
notification arrives. So you're back to not being able to dial the mailbox.
This is also an issue with the indications themselves. If we don't have EF-
MWIS provisioned, the information is lost when oFono is restarted. So we're
now inconsistent between MBDN/MWIS, so maybe we shouldn't update them either
in this case.
One solution is to always store this info on the filesystem and backup to SIM.
The other solution is to preserve current behavior, but to also expose the
enhanced notifications in a separate interface (as discussed previously) and
include any Mailbox numbers there.
Thoughts?
Regards,
-Denis
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 4/4] Add a MessageWaiting interface to track message waiting indications.
2009-08-05 19:35 ` Denis Kenzior
@ 2009-08-07 3:25 ` andrzej zaborowski
2009-08-10 16:35 ` Denis Kenzior
0 siblings, 1 reply; 18+ messages in thread
From: andrzej zaborowski @ 2009-08-07 3:25 UTC (permalink / raw)
To: ofono
[-- Attachment #1: Type: text/plain, Size: 1629 bytes --]
2009/8/5 Denis Kenzior <denkenz@gmail.com>:
> Hi Andrew,
>
>> > For setting mailbox numbers, a working EF-MBDN is required since the only
>> > alternative would be to store them on the filesystem.
>>
>> mw_set_indicator does the right thing, I missed this fact. But when a
>> mailbox number is set or received from network all clients get a
>> PropertyChanged and the new number can be retrieved from the interface
>> but only when the store succeeded, previously it would be available
>> regardless of MBDN on the card and the writing to card was secondary.
>> The number is kind of important if you want to hear the messages.
>
> So you're right that even if we get an enhanced voice mail notification message
> the Mailbox number won't be signaled unless we have the SIM provisioned with
> EF-MBI & EF-MBDN.
>
> The problem is, if we don't have the SIM files available, then the next time
> oFono is restarted this information is lost anyway until the next MWI
> notification arrives. So you're back to not being able to dial the mailbox.
>
> This is also an issue with the indications themselves. If we don't have EF-
> MWIS provisioned, the information is lost when oFono is restarted. So we're
> now inconsistent between MBDN/MWIS, so maybe we shouldn't update them either
> in this case.
True. (or update them both in this case)
It would make sense for the providers to resend the MWI information
everytime subscriber connects the network and then it would be less
problematic in case the information couldn't be written to SIM, but I
don't know if they ever do this.
Regards
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 4/4] Add a MessageWaiting interface to track message waiting indications.
2009-08-07 3:25 ` andrzej zaborowski
@ 2009-08-10 16:35 ` Denis Kenzior
2009-08-12 13:48 ` Aki Niemi
2009-08-19 13:44 ` Andrzej Zaborowski
0 siblings, 2 replies; 18+ messages in thread
From: Denis Kenzior @ 2009-08-10 16:35 UTC (permalink / raw)
To: ofono
[-- Attachment #1: Type: text/plain, Size: 2086 bytes --]
Hi Andrew,
> 2009/8/5 Denis Kenzior <denkenz@gmail.com>:
> > Hi Andrew,
> >
> >> > For setting mailbox numbers, a working EF-MBDN is required since the
> >> > only alternative would be to store them on the filesystem.
> >>
> >> mw_set_indicator does the right thing, I missed this fact. But when a
> >> mailbox number is set or received from network all clients get a
> >> PropertyChanged and the new number can be retrieved from the interface
> >> but only when the store succeeded, previously it would be available
> >> regardless of MBDN on the card and the writing to card was secondary.
> >> The number is kind of important if you want to hear the messages.
> >
> > So you're right that even if we get an enhanced voice mail notification
> > message the Mailbox number won't be signaled unless we have the SIM
> > provisioned with EF-MBI & EF-MBDN.
> >
> > The problem is, if we don't have the SIM files available, then the next
> > time oFono is restarted this information is lost anyway until the next
> > MWI notification arrives. So you're back to not being able to dial the
> > mailbox.
> >
> > This is also an issue with the indications themselves. If we don't have
> > EF- MWIS provisioned, the information is lost when oFono is restarted.
> > So we're now inconsistent between MBDN/MWIS, so maybe we shouldn't
> > update them either in this case.
>
> True. (or update them both in this case)
>
> It would make sense for the providers to resend the MWI information
> everytime subscriber connects the network and then it would be less
> problematic in case the information couldn't be written to SIM, but I
> don't know if they ever do this.
Probably they don't, there are also weird roaming cases to consider, where you
receive MWI, turn phone off, step on a plane and turn phone on with some other
network entirely.
Can we make the MWI interface smarter somehow? Perhaps by not enabling it
unless at least the EFmwis file is available, or by always storing the EFmwis
contents on the filesystem?
Regards,
-Denis
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 4/4] Add a MessageWaiting interface to track message waiting indications.
2009-08-10 16:35 ` Denis Kenzior
@ 2009-08-12 13:48 ` Aki Niemi
2009-08-12 16:13 ` Denis Kenzior
2009-08-19 13:44 ` Andrzej Zaborowski
1 sibling, 1 reply; 18+ messages in thread
From: Aki Niemi @ 2009-08-12 13:48 UTC (permalink / raw)
To: ofono
[-- Attachment #1: Type: text/plain, Size: 1338 bytes --]
2009/8/10 Denis Kenzior <denkenz@gmail.com>:
>> It would make sense for the providers to resend the MWI information
>> everytime subscriber connects the network and then it would be less
>> problematic in case the information couldn't be written to SIM, but I
>> don't know if they ever do this.
>
> Probably they don't, there are also weird roaming cases to consider, where you
> receive MWI, turn phone off, step on a plane and turn phone on with some other
> network entirely.
There is another case to consider when the SIM is moved to a
completely different phone. In fact, I think this is the original
reason to store the MWI flag to the SIM.
> Can we make the MWI interface smarter somehow? Perhaps by not enabling it
> unless at least the EFmwis file is available, or by always storing the EFmwis
> contents on the filesystem?
I think this makes sense. There is another, related issue with some
Nokia modems, though. They might not support low-level, EF access
directly, but have some higher level API for accessing things like the
MWI flag, HPLMN list and SPN. We might need to think about adding such
high-level API support to the driver API as (optional) ops --
especially if other modems behave similarly -- otherwise the ISI modem
driver may need some kluge to handing EF writes.
Cheers,
Aki
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 4/4] Add a MessageWaiting interface to track message waiting indications.
2009-08-12 13:48 ` Aki Niemi
@ 2009-08-12 16:13 ` Denis Kenzior
2009-08-14 12:07 ` Aki Niemi
0 siblings, 1 reply; 18+ messages in thread
From: Denis Kenzior @ 2009-08-12 16:13 UTC (permalink / raw)
To: ofono
[-- Attachment #1: Type: text/plain, Size: 2823 bytes --]
Hi Aki,
> 2009/8/10 Denis Kenzior <denkenz@gmail.com>:
> >> It would make sense for the providers to resend the MWI information
> >> everytime subscriber connects the network and then it would be less
> >> problematic in case the information couldn't be written to SIM, but I
> >> don't know if they ever do this.
> >
> > Probably they don't, there are also weird roaming cases to consider,
> > where you receive MWI, turn phone off, step on a plane and turn phone on
> > with some other network entirely.
>
> There is another case to consider when the SIM is moved to a
> completely different phone. In fact, I think this is the original
> reason to store the MWI flag to the SIM.
This is why we always attempt to write to the SIM for EFmwis. If the SIM
doesn't support this file, then there's nothing we can do to preserve the MWIS
information in the case you describe above.
There are other cases as well:
- EFmbdn & perhaps EFmbi
- EFmsisdn
- EFcbmid
- EFcbmir
- EFcfis
>
> > Can we make the MWI interface smarter somehow? Perhaps by not enabling
> > it unless at least the EFmwis file is available, or by always storing the
> > EFmwis contents on the filesystem?
>
> I think this makes sense. There is another, related issue with some
> Nokia modems, though. They might not support low-level, EF access
> directly, but have some higher level API for accessing things like the
> MWI flag, HPLMN list and SPN. We might need to think about adding such
> high-level API support to the driver API as (optional) ops --
> especially if other modems behave similarly -- otherwise the ISI modem
> driver may need some kluge to handing EF writes.
There is vast amount of information stored on the SIM that we need to expose.
Today oFono processes:
- EFspn
- EFpnn
- EFopl
- EFmbi
- EFmbdn
- EFmwis
- EFspdi
- EFmsisdn
We also eventually need to support:
- EFecc
- EFsdn
- EFad
- EFcbmid
- EFcbmir
- EFehplmn
- EFehplmnpi
- EFici
- EFict
- EFoci
- EFoct
- EFcfis
So there are two issues here:
- There is absolutely no standard data format for such vendor commands. So
coming up with a higher level API that supports all modems might be tricky.
The advantage of using low-level SIM access is that the command syntax & data
format is standard and should be supported by any modem out there. Of course,
as you point out, many don't.
- This presents the issue of having many more code paths to debug inside the
core and potentially many more plugin functions to implement.
I'd like to keep the core as clean and small as possible. What is your
feeling for the level of bloat such higher level APIs will introduce in
comparison to a giant if-else statement inside the driver itself?
Regards,
-Denis
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 4/4] Add a MessageWaiting interface to track message waiting indications.
2009-08-12 16:13 ` Denis Kenzior
@ 2009-08-14 12:07 ` Aki Niemi
0 siblings, 0 replies; 18+ messages in thread
From: Aki Niemi @ 2009-08-14 12:07 UTC (permalink / raw)
To: ofono
[-- Attachment #1: Type: text/plain, Size: 864 bytes --]
2009/8/12 Denis Kenzior <denkenz@gmail.com>:
> So there are two issues here:
> - There is absolutely no standard data format for such vendor commands. So
> coming up with a higher level API that supports all modems might be tricky.
Agree, this might be a problem. And in the worst case, might force
drivers to do data format conversions anyway.
> - This presents the issue of having many more code paths to debug inside the
> core and potentially many more plugin functions to implement.
>
> I'd like to keep the core as clean and small as possible. What is your
> feeling for the level of bloat such higher level APIs will introduce in
> comparison to a giant if-else statement inside the driver itself?
At least with the current set of EF types, I think we can manage
faking it in the driver code.
Cheers,
Aki
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 4/4] Add a MessageWaiting interface to track message waiting indications.
2009-08-10 16:35 ` Denis Kenzior
2009-08-12 13:48 ` Aki Niemi
@ 2009-08-19 13:44 ` Andrzej Zaborowski
1 sibling, 0 replies; 18+ messages in thread
From: Andrzej Zaborowski @ 2009-08-19 13:44 UTC (permalink / raw)
To: ofono
[-- Attachment #1: Type: text/plain, Size: 2480 bytes --]
Hi,
2009/8/10 Denis Kenzior <denkenz@gmail.com>:
>> 2009/8/5 Denis Kenzior <denkenz@gmail.com>:
>> >> mw_set_indicator does the right thing, I missed this fact. But when a
>> >> mailbox number is set or received from network all clients get a
>> >> PropertyChanged and the new number can be retrieved from the interface
>> >> but only when the store succeeded, previously it would be available
>> >> regardless of MBDN on the card and the writing to card was secondary.
>> >> The number is kind of important if you want to hear the messages.
>> >
>> > So you're right that even if we get an enhanced voice mail notification
>> > message the Mailbox number won't be signaled unless we have the SIM
>> > provisioned with EF-MBI & EF-MBDN.
>> >
>> > The problem is, if we don't have the SIM files available, then the next
>> > time oFono is restarted this information is lost anyway until the next
>> > MWI notification arrives. So you're back to not being able to dial the
>> > mailbox.
>> >
>> > This is also an issue with the indications themselves. If we don't have
>> > EF- MWIS provisioned, the information is lost when oFono is restarted.
>> > So we're now inconsistent between MBDN/MWIS, so maybe we shouldn't
>> > update them either in this case.
>>
>> True. (or update them both in this case)
>>
>> It would make sense for the providers to resend the MWI information
>> everytime subscriber connects the network and then it would be less
>> problematic in case the information couldn't be written to SIM, but I
>> don't know if they ever do this.
>
> Probably they don't, there are also weird roaming cases to consider, where you
> receive MWI, turn phone off, step on a plane and turn phone on with some other
> network entirely.
>
> Can we make the MWI interface smarter somehow? Perhaps by not enabling it
> unless at least the EFmwis file is available, or by always storing the EFmwis
> contents on the filesystem?
We could re-use the "sim cache" functions to cheaply save the state of
notifications to filesystem, like in the attached patch (only an
example). This is not ideal because the SIM might be used in a
different phone or with a different software stack between ofonod
runs, but seems better than not providing the information at all.
Really we don't lose anything even if we don't store the state and
provide the information (MWIS, MBDN) only for the duration of the
ofonod session.
Regards
^ permalink raw reply [flat|nested] 18+ messages in thread
end of thread, other threads:[~2009-08-19 13:44 UTC | newest]
Thread overview: 18+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-07-30 8:05 [PATCH 4/4] Add a MessageWaiting interface to track message waiting indications Andrzej Zaborowski
2009-07-31 16:19 ` Denis Kenzior
2009-08-01 23:09 ` Andrzej Zaborowski
2009-08-03 16:32 ` Denis Kenzior
2009-08-03 19:09 ` Andrzej Zaborowski
2009-08-03 19:29 ` Denis Kenzior
2009-08-03 21:56 ` andrzej zaborowski
2009-08-04 20:23 ` Denis Kenzior
2009-08-05 14:18 ` andrzej zaborowski
2009-08-05 17:47 ` Denis Kenzior
2009-08-05 19:18 ` andrzej zaborowski
2009-08-05 19:35 ` Denis Kenzior
2009-08-07 3:25 ` andrzej zaborowski
2009-08-10 16:35 ` Denis Kenzior
2009-08-12 13:48 ` Aki Niemi
2009-08-12 16:13 ` Denis Kenzior
2009-08-14 12:07 ` Aki Niemi
2009-08-19 13:44 ` Andrzej Zaborowski
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.