diff options
author | Andrzej Zaborowski <andrew.zaborowski@intel.com> | 2009-08-03 14:50:14 +0200 |
---|---|---|
committer | Denis Kenzior <denkenz@gmail.com> | 2009-08-04 15:08:11 -0500 |
commit | 203ed17cecba2ab21317b8ba35b50907d0684675 (patch) | |
tree | 1cd305186f91e60c4bf655684a842258dc681972 /src | |
parent | ba8ef5c3e4e453f66fc657e51e04cdf39fd1fc1c (diff) | |
download | ofono-203ed17cecba2ab21317b8ba35b50907d0684675.tar.bz2 |
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.
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 3 | ||||
-rw-r--r-- | src/message-waiting.c | 761 | ||||
-rw-r--r-- | src/message-waiting.h | 30 | ||||
-rw-r--r-- | src/ofono.h | 4 | ||||
-rw-r--r-- | src/simutil.h | 3 | ||||
-rw-r--r-- | src/sms.c | 30 | ||||
-rw-r--r-- | src/smsutil.h | 1 |
7 files changed, 822 insertions, 10 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 2e3e607d..4644c693 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 00000000..fcb4519d --- /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 00000000..c0e60bfb --- /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 3cb2d753..4e344306 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 6572e72f..c2b1e20c 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, }; @@ -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 89da973f..d362aa98 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 { |