--- Makefile.am | 6 + plugins/history.c | 438 +++++++++++++++++++++++++++++++++++++++++++++ plugins/history_agent.c | 453 +++++++++++++++++++++++++++++++++++++++++++++++ plugins/history_agent.h | 103 +++++++++++ 4 files changed, 1000 insertions(+), 0 deletions(-) create mode 100755 plugins/history.c create mode 100644 plugins/history_agent.c create mode 100644 plugins/history_agent.h
diff --git a/Makefile.am b/Makefile.am index cd17fa2..530c2de 100644 --- a/Makefile.am +++ b/Makefile.am @@ -286,6 +286,12 @@ builtin_sources += plugins/ste.c builtin_modules += caif builtin_sources += plugins/caif.c + + +builtin_modules += history +builtin_sources += plugins/history_agent.h +builtin_sources += plugins/history_agent.c +builtin_sources += plugins/history.c endif if MAINTAINER_MODE diff --git a/plugins/history.c b/plugins/history.c new file mode 100755 index 0000000..f5d4ba0 --- /dev/null +++ b/plugins/history.c @@ -0,0 +1,438 @@ +/* + * + * oFono - Open Source Telephony + * + * Copyright (C) 2008-2010 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 + +#define OFONO_API_SUBJECT_TO_CHANGE +#include <errno.h> + +#include "gdbus/gdbus.h" +#include <ofono/history.h> +#include "plugins/history_agent.h" +#include "src/common.h" + +#define HISTORY_FILE_PATH "/var/cache/ofonohistory/" +#define HISTORY_FILE HISTORY_FILE_PATH"ofonohistorydata" +#define OFONO_MANAGER_PATH "/" +#define OFONO_HISTORY_INTERFACE "com.meego.TelephonyHistory" + +struct ofono_history { + struct history_agent *current_agent; + int timeout; +} *history; + + +static int history_plugin_probe(struct ofono_history_context *context) +{ + DBG("History Probe for modem: %p", context->modem); + return 0; +} + +static void history_plugin_remove(struct ofono_history_context *context) +{ + DBG("History Remove for modem: %p", context->modem); +} + +/** + * history_call_ended: + * ofono calls this method with the call information + */ + +static void history_plugin_call_ended(struct ofono_history_context *context, + const struct ofono_call *call, + time_t start, + time_t end) +{ + struct ofono_modem *modem; + const char *path; + struct history *v = g_try_new0(struct history, 1); + if (!v) + return; + + v->data.voice.type = VOICE; + + strcpy(v->data.voice.lineid, "Unknown"); + + if (call->type != 0) + return; + + DBG("Voice Call, %s", call->direction ? "Incoming" : "Outgoing"); + v->data.voice.type = call->direction; + + if (call->clip_validity == 0) + strcpy(v->data.voice.lineid, + phone_number_to_string(&call->phone_number)); + + v->data.voice.start_time = start; + v->data.voice.end_time = end; + + DBG("Call Ended on modem: %p", context->modem); + modem = context->modem; + path = ofono_modem_get_path(modem); + + v->data.voice.modem_path = g_try_malloc0(strlen(path) + 1); + if (v->data.voice.modem_path) + strcpy(v->data.voice.modem_path, path); + + if (!history) { + g_free(v); + return; + } + + history_agent_report_voicecall(v, history->current_agent, + history->timeout); +} + +/** + * history_call_missed: + * ofono calls this method with the call information + */ + +static void history_plugin_call_missed(struct ofono_history_context *context, + const struct ofono_call *call, + time_t when) +{ + struct ofono_modem *modem; + const char *modem_path; + + struct history *v = g_try_new0(struct history, 1); + if (!v) + return; + v->type = VOICE; + + strcpy(v->data.voice.lineid, "Unknown"); + + if (call->type != 0) + return; + + v->type = MISSED; + + if (call->clip_validity == 0) + strcpy(v->data.voice.lineid, + phone_number_to_string(&call->phone_number)); + + v->data.voice.start_time = when; + + v->data.voice.end_time = when; + + DBG("Call Missed on modem: %p", context->modem); + modem = context->modem; + modem_path = ofono_modem_get_path(modem); + + v->data.voice.modem_path = g_try_malloc0(strlen(modem_path) + 1); + if (v->data.voice.modem_path) + strcpy(v->data.voice.modem_path, modem_path); + if (!history) { + g_free(v); + return; + } + + history_agent_report_voicecall(v, history->current_agent, + history->timeout); +} + +static void history_plugin_sms_received(struct ofono_history_context *context, + const struct ofono_uuid *uuid, + const char *from, + const struct tm *remote, + const struct tm *local, + const char *text) +{ + char buf[128]; + struct ofono_modem *modem; + const char *modem_path; + + struct history *thistory = g_try_new0(struct history, 1); + if (!thistory) + return; + + thistory->data.text.type = TEXT; + + strcpy(thistory->data.text.uid, ofono_uuid_to_str(uuid)); + + strftime(buf, 127, "%a %d %b %Y %H:%M:%S %z", local); + buf[127] = '\0'; + DBG("Local Sent Time: %s", buf); + + thistory->data.text.localsenttime = *local; + + strftime(buf, 127, "%a %d %b %Y %H:%M:%S %z", remote); + buf[127] = '\0'; + DBG("Remote Sent Time: %s", buf); + thistory->data.text.remotesenttime = *remote; + + DBG("Text: %s", text); + + thistory->data.text.message = (char *) g_try_malloc0(strlen(text) + 1); + strcpy(thistory->data.text.message, text); + + DBG("From: %s:", from); + strcpy(thistory->data.text.lineid, from); + + thistory->data.text.type = INCOMING; + + thistory->data.text.status = OFONO_HISTORY_SMS_STATUS_SUBMITTED; + + DBG("Incoming SMS on modem: %p", context->modem); + modem = context->modem; + modem_path = ofono_modem_get_path(modem); + + thistory->data.text.modem_path = g_try_malloc0(strlen(modem_path) + 1); + if (thistory->data.text.modem_path) + strcpy(thistory->data.text.modem_path, modem_path); + + history_agent_report_textmessage(thistory, history->current_agent, + history->timeout); +} + +static void history_plugin_sms_send_status( + struct ofono_history_context *context, + const struct ofono_uuid *uuid, + time_t when, + enum ofono_history_sms_status s) +{ + char buf[128]; + struct ofono_modem *modem; + const char *modem_path; + + struct history *thistory = g_try_new0(struct history, 1); + if (!thistory) + return; + + thistory->type = TEXT; + + strcpy(thistory->data.text.uid, ofono_uuid_to_str(uuid)); + + thistory->data.text.localsenttime = *(localtime(&when)); + strftime(buf, 127, "%Y-%m-%dT%H:%M:%S%z", + &(thistory->data.text.localsenttime)); + buf[127] = '\0'; + thistory->data.text.type = OUTGOING; + + switch (s) { + case OFONO_HISTORY_SMS_STATUS_PENDING: + break; + case OFONO_HISTORY_SMS_STATUS_SUBMITTED: + + DBG("SMS %s submitted successfully", ofono_uuid_to_str(uuid)); + DBG("Submission Time: %s", buf); + + thistory->data.text.status = + OFONO_HISTORY_SMS_STATUS_SUBMITTED; + break; + case OFONO_HISTORY_SMS_STATUS_SUBMIT_FAILED: + + DBG("SMS %s submitted successfully", ofono_uuid_to_str(uuid)); + DBG("Failure Time: %s", buf); + + thistory->data.text.status = + OFONO_HISTORY_SMS_STATUS_SUBMIT_FAILED; + break; + default: + break; + }; + + modem = context->modem; + modem_path = ofono_modem_get_path(modem); + + thistory->data.text.modem_path = g_try_malloc0(strlen(modem_path) + + 1); + if (thistory->data.text.modem_path) + strcpy(thistory->data.text.modem_path, modem_path); + + history_agent_report_textmessage(thistory, history->current_agent, + history->timeout); +} + +static void history_plugin_sms_send_pending( + struct ofono_history_context *context, + const struct ofono_uuid *uuid, + const char *to, time_t when, + const char *text) +{ + char buf[128]; + struct ofono_modem *modem; + const char *modem_path; + + struct history *thistory = g_try_new0(struct history, 1); + if (!thistory) + return; + + thistory->type = TEXT; + + DBG("To: %s:", to); + strcpy(thistory->data.text.lineid, to); + + DBG("SMS %s submitted successfully", ofono_uuid_to_str(uuid)); + strcpy(thistory->data.text.uid, ofono_uuid_to_str(uuid)); + + thistory->data.text.localsenttime = *(localtime(&when)); + strftime(buf, 127, "%Y-%m-%dT%H:%M:%S%z", + &(thistory->data.text.localsenttime)); + buf[127] = '\0'; + DBG("Local Time: %s", buf); + + thistory->data.text.type = OUTGOING; + + DBG("Text: %s", text); + thistory->data.text.message = (char *) g_try_malloc0(strlen(text) + + 1); + if (thistory->data.text.message) + strcpy(thistory->data.text.message, text); + + thistory->data.text.status = OFONO_HISTORY_SMS_STATUS_PENDING; + + DBG("Sending SMS on modem: %p", context->modem); + modem = context->modem; + modem_path = ofono_modem_get_path(modem); + + thistory->data.text.modem_path = g_try_malloc0(strlen(modem_path) + + 1); + if (thistory->data.text.modem_path) + strcpy(thistory->data.text.modem_path, modem_path); + + history_agent_report_textmessage(thistory, history->current_agent, + history->timeout); +} + +static void history_notify(gpointer user_data) +{ + struct ofono_history *ohistory = user_data; + + DBG("History Agent Removed"); + + ohistory->current_agent = NULL; +} + +static DBusMessage *history_register_agent(DBusConnection *conn, + DBusMessage *msg, void *data) +{ + const char *agent_path; + if (dbus_message_get_args(msg, NULL, + DBUS_TYPE_OBJECT_PATH, &agent_path, + DBUS_TYPE_INVALID) == FALSE) + return __ofono_error_invalid_args(msg); + + if (!__ofono_dbus_valid_object_path(agent_path)) + return __ofono_error_invalid_format(msg); + + if (!history) + return __ofono_error_failed(msg); + + history->current_agent = history_agent_new(agent_path, + dbus_message_get_sender(msg), + FALSE); + + if (!history->current_agent) + return __ofono_error_failed(msg); + + DBG("History agent created"); + + history_agent_set_removed_notify(history->current_agent, + history_notify, history); + + return dbus_message_new_method_return(msg); +} + +static DBusMessage *history_unregister_agent(DBusConnection *conn, + DBusMessage *msg, void *data) +{ + const char *agent_path; + + const char *agent_bus = dbus_message_get_sender(msg); + + if (dbus_message_get_args(msg, NULL, + DBUS_TYPE_OBJECT_PATH, &agent_path, + DBUS_TYPE_INVALID) == FALSE) + return __ofono_error_invalid_args(msg); + + if (!history->current_agent) + return __ofono_error_failed(msg); + + if (!history_agent_matches(history->current_agent, agent_path, + agent_bus)) + return __ofono_error_failed(msg); + + history_agent_free(history->current_agent); + + return dbus_message_new_method_return(msg); +} + +static GDBusMethodTable history_methods[] = { + { "RegisterAgent", "o", "", history_register_agent }, + { "UnregisterAgent", "o", "", history_unregister_agent }, + { } +}; + +static struct ofono_history_driver history_driver = { + .name = "history plugin", + .probe = history_plugin_probe, + .remove = history_plugin_remove, + .call_ended = history_plugin_call_ended, + .call_missed = history_plugin_call_missed, + .sms_received = history_plugin_sms_received, + .sms_send_pending = history_plugin_sms_send_pending, + .sms_send_status = history_plugin_sms_send_status +}; + +static int history_plugin_init(void) +{ + DBusConnection *conn = ofono_dbus_get_connection(); + + if (!g_dbus_register_interface(conn, + OFONO_MANAGER_PATH, + OFONO_HISTORY_INTERFACE, + history_methods, + NULL, + NULL, /* Properties */ + NULL, /* Userdata */ + NULL)) { /* Destroy func */ + ofono_error("Could not create %s interface", + OFONO_HISTORY_INTERFACE); + + return -EIO; + } + + history = g_try_new0(struct ofono_history, 1); + + if (!history) + return -EIO; + + history->timeout = 600; /* 10 minutes */ + return ofono_history_driver_register(&history_driver); +} + +static void history_plugin_exit(void) +{ + DBusConnection *conn = ofono_dbus_get_connection(); + + g_dbus_unregister_interface(conn, OFONO_MANAGER_PATH, + OFONO_HISTORY_INTERFACE); + if (history) + g_free(history); + ofono_history_driver_unregister(&history_driver); +} + +OFONO_PLUGIN_DEFINE(history, "History Plugin", + OFONO_VERSION, OFONO_PLUGIN_PRIORITY_DEFAULT, + history_plugin_init, history_plugin_exit) diff --git a/plugins/history_agent.c b/plugins/history_agent.c new file mode 100644 index 0000000..d4d55ec --- /dev/null +++ b/plugins/history_agent.c @@ -0,0 +1,453 @@ +/* + * + * oFono - Open Source Telephony + * + * Copyright (C) 2008-2010 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 + +#define OFONO_API_SUBJECT_TO_CHANGE +#define MODEM_STRUCT_LEN 2 + +#include "plugins/history_agent.h" + +#define OFONO_HISTORY_AGENT "com.meego.TelephonyHistoryAgent" +#define ERROR_PREFIX OFONO_SERVICE ".Error" +#define FAILED_ERROR ERROR_PREFIX ".Failed" + +enum allowed_errors { + ALLOWED_ERROR_FAILED = 0x1 +}; + +struct history_agent { + char *path; + char *bus; + guint disconnect_watch; + ofono_bool_t remove_on_terminate; + ofono_destroy_func removed_cb; + void *removed_data; + DBusPendingCall *call; + void *user_data; +}; + +void history_agent_free(struct history_agent *agent) +{ + DBusConnection *conn = ofono_dbus_get_connection(); + + if (agent->disconnect_watch) { + history_agent_send_release(agent); + g_dbus_remove_watch(conn, agent->disconnect_watch); + agent->disconnect_watch = 0; + } + + if (agent->removed_cb) + agent->removed_cb(agent->removed_data); + + g_free(agent->path); + g_free(agent->bus); + g_free(agent); +} + +static void history_agent_disconnect_cb(DBusConnection *conn, void *user_data) +{ + DBG("Agent exited without unregister"); + + struct history_agent *agent = user_data; + + agent->disconnect_watch = 0; + + history_agent_free(agent); +} + +ofono_bool_t history_agent_matches(struct history_agent *agent, + const char *path, const char *sender) +{ + return !strcmp(agent->path, path) && !strcmp(agent->bus, sender); +} + +struct history_agent *history_agent_new(const char *path, const char *sender, + ofono_bool_t remove_on_terminate) +{ + DBusConnection *conn = ofono_dbus_get_connection(); + struct history_agent *agent = g_try_new0(struct history_agent, 1); + if (!agent) + return NULL; + + agent->path = g_strdup(path); + agent->bus = g_strdup(sender); + agent->remove_on_terminate = remove_on_terminate; + + agent->disconnect_watch = g_dbus_add_disconnect_watch(conn, sender, + history_agent_disconnect_cb, + agent, NULL); + return agent; +} + +static int check_error(struct history_agent *agent, DBusMessage *reply, + int allowed_errors, + enum HISTORY_AGENT_RESULT *out_result) +{ + DBusError err; + int result = 0; + + dbus_error_init(&err); + + if (dbus_set_error_from_message(&err, reply) == FALSE) { + *out_result = HISTORY_AGENT_RESULT_OK; + return 0; + } + + ofono_debug("HistoryAgent %s replied with error %s, %s", + agent->path, err.name, err.message); + + /* Timeout is always valid */ + if (g_str_equal(err.name, DBUS_ERROR_NO_REPLY)) { + /* Send a Cancel() to the agent since its taking too long */ + *out_result = HISTORY_AGENT_RESULT_TIMEOUT; + goto out; + } + + if ((allowed_errors & ALLOWED_ERROR_FAILED) && + g_str_equal(err.name, FAILED_ERROR)) { + *out_result = HISTORY_AGENT_RESULT_FAILED; + goto out; + } + + result = -EINVAL; +out: + dbus_error_free(&err); + return result; +} + +static void history_agent_send_no_reply(struct history_agent *agent, + const char *method) +{ + DBusConnection *conn = ofono_dbus_get_connection(); + DBusMessage *message; + + message = dbus_message_new_method_call(agent->bus, agent->path, + OFONO_HISTORY_AGENT, + method); + + if (message == NULL) + return; + + dbus_message_set_no_reply(message, TRUE); + + g_dbus_send_message(conn, message); +} + +static void history_agent_data_free(void *data) +{ + struct history *history = (struct history *)data; + if (history->type == TEXT) { + g_free(history->data.text.message); + g_free(history->data.text.modem_path); + } else { + g_free(history->data.voice.modem_path); + } + g_free(history); +} + +static const char *call_type_to_string(enum type tp) +{ + switch (tp) { + case INCOMING: + return "incoming"; + case OUTGOING: + return "outgoing"; + case MISSED: + return "missed"; + default: + return "unknown"; + } +} + +static const char *status_to_string(enum ofono_history_sms_status status) +{ + switch (status) { + case OFONO_HISTORY_SMS_STATUS_PENDING: + return "Pending"; + case OFONO_HISTORY_SMS_STATUS_SUBMITTED: + return "Submitted"; + case OFONO_HISTORY_SMS_STATUS_SUBMIT_FAILED: + return "Submit Failed"; + case OFONO_HISTORY_SMS_STATUS_DELIVERED: + return "Delivered"; + case OFONO_HISTORY_SMS_STATUS_DELIVER_FAILED: + return "Deliver Failed"; + default: + return "unknown"; + } +} + +static void data_delivery_cb(DBusPendingCall *call, void *data) +{ + struct history_agent *agent = data; + enum HISTORY_AGENT_RESULT result = -EINVAL; + + DBusMessage *reply = dbus_pending_call_steal_reply(call); + + if (check_error(agent, reply, + ALLOWED_ERROR_FAILED, + &result) == -EINVAL) { + g_print("Agent disappeared\n"); + /* TODO - persist agent->user_data */ + history_agent_data_free(agent->user_data); + } + + if (result == HISTORY_AGENT_RESULT_OK) { + g_print("Agent reply ok\n"); + history_agent_data_free(agent->user_data); + } + + if (result == HISTORY_AGENT_RESULT_TIMEOUT) { + g_print("Reply timedout\n"); + /* TODO - persist agent->user_data*/ + history_agent_data_free(agent->user_data); + } +} + +static char **get_modem_struct(const char *path) +{ + int i = 0; + char **ret; + + /* TODO - Figureout how to release this*/ + ret = g_try_new0(char *, 3); + if (!ret) + return NULL; + + ret[i++] = g_strdup("Modem"); + ret[i++] = g_strdup(path); + + return ret; +} + +static void append_texthistory_properties(struct text_history *h, + DBusMessageIter *array) +{ + const char *localtm, *senttm; + static char localsenttm[128], rsenttime[128]; + const char *phone; + const char *mesg; + const char *msgid; + DBusMessageIter dict; + char **modem_dict; + + dbus_message_iter_open_container(array, DBUS_TYPE_ARRAY, + OFONO_PROPERTIES_ARRAY_SIGNATURE, + &dict); + + strftime(localsenttm, 127, "%Y-%m-%dT%H:%M:%S%z", + (&h->localsenttime)); + localsenttm[127] = '\0'; + localtm = localsenttm; + + strftime(rsenttime, 127, "%Y-%m-%dT%H:%M:%S%z", + (&h->remotesenttime)); + rsenttime[127] = '\0'; + senttm = rsenttime; + + msgid = h->uid; + + ofono_dbus_dict_append(&dict, "Uid", DBUS_TYPE_STRING, &msgid); + + const char *type_str = call_type_to_string(h->type); + + ofono_dbus_dict_append(&dict, "Type", + DBUS_TYPE_STRING, &type_str); + + const char *status_str = status_to_string(h->status); + + ofono_dbus_dict_append(&dict, "Status", + DBUS_TYPE_STRING, &status_str); + + phone = h->lineid; + ofono_dbus_dict_append(&dict, "LineIdentification", DBUS_TYPE_STRING, + &phone); + + ofono_dbus_dict_append(&dict, "LocalSentTime", DBUS_TYPE_STRING, + &localtm); + + ofono_dbus_dict_append(&dict, "SentTime", DBUS_TYPE_STRING, + &senttm); + mesg = h->message; + ofono_dbus_dict_append(&dict, "Message", DBUS_TYPE_STRING, + &mesg); + + modem_dict = get_modem_struct(h->modem_path); + + ofono_dbus_dict_append_dict(&dict, "Information", DBUS_TYPE_STRING, + &modem_dict); + + dbus_message_iter_close_container(array, &dict); +} + +static void append_voicehistory_properties(struct voice_history *h, + DBusMessageIter *array) +{ + const char *sttime, *entime; + static char starttime[128], endtime[128]; + struct tm starttm, endtm; + const char *phone; + char **modem_dict; + DBusMessageIter dict; + + dbus_message_iter_open_container(array, DBUS_TYPE_ARRAY, + OFONO_PROPERTIES_ARRAY_SIGNATURE, + &dict); + + strftime(starttime, 127, "%Y-%m-%dT%H:%M:%S%z", + localtime_r(&h->start_time, &starttm)); + starttime[127] = '\0'; + sttime = starttime; + + strftime(endtime, 127, "%Y-%m-%dT%H:%M:%S%z", + localtime_r(&h->end_time, &endtm)); + endtime[127] = '\0'; + entime = endtime; + + ofono_dbus_dict_append(&dict, "Uid", DBUS_TYPE_UINT32, &h->uid); + + const char *type_str = call_type_to_string(h->type); + + ofono_dbus_dict_append(&dict, "Type", + DBUS_TYPE_STRING, &type_str); + + phone = h->lineid; + ofono_dbus_dict_append(&dict, "LineIdentification", DBUS_TYPE_STRING, + &phone); + + ofono_dbus_dict_append(&dict, "StartTime", DBUS_TYPE_STRING, + &sttime); + + ofono_dbus_dict_append(&dict, "EndTime", DBUS_TYPE_STRING, + &entime); + + modem_dict = get_modem_struct(h->modem_path); + + ofono_dbus_dict_append_dict(&dict, "Information", DBUS_TYPE_STRING, + &modem_dict); + + dbus_message_iter_close_container(array, &dict); +} + +int history_agent_report_voicecall(struct history *history, + struct history_agent *agent, int timeout) +{ + if (!agent) + /* TODO persist history */ + return -1; + + DBusMessage *msg ; + DBusMessageIter iter, array; + struct voice_history *vhistory = &(history->data.voice); + DBusConnection *conn = ofono_dbus_get_connection(); + + msg = dbus_message_new_method_call(agent->bus, + agent->path, + OFONO_HISTORY_AGENT, + "ReportVoiceCall"); + if (msg == NULL) + return -ENOMEM; + + dbus_message_iter_init_append(msg, &iter); + + dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, + DBUS_TYPE_ARRAY_AS_STRING + DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING + DBUS_TYPE_STRING_AS_STRING + DBUS_TYPE_VARIANT_AS_STRING + DBUS_DICT_ENTRY_END_CHAR_AS_STRING, + &array); + append_voicehistory_properties(vhistory, &array); + + dbus_message_iter_close_container(&iter, &array); + + agent->user_data = (void *)history; + + if (dbus_connection_send_with_reply(conn, msg, &agent->call, + timeout) == FALSE || + agent->call == NULL) + return -EIO; + + dbus_pending_call_set_notify(agent->call, data_delivery_cb, + agent, NULL); + return 0; +} + + +int history_agent_report_textmessage(struct history *history, + struct history_agent *agent, int timeout) +{ + if (!agent) + /* TODO Persist history */ + return -1; + + DBusMessage *msg ; + DBusMessageIter iter, array; + struct text_history *text_history = &(history->data.text); + DBusConnection *conn = ofono_dbus_get_connection(); + + msg = dbus_message_new_method_call(agent->bus, + agent->path, + OFONO_HISTORY_AGENT, + "ReportTextMessage"); + if (msg == NULL) + return -ENOMEM; + + dbus_message_iter_init_append(msg, &iter); + + dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, + DBUS_TYPE_ARRAY_AS_STRING + DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING + DBUS_TYPE_STRING_AS_STRING + DBUS_TYPE_VARIANT_AS_STRING + DBUS_DICT_ENTRY_END_CHAR_AS_STRING, + &array); + append_texthistory_properties(text_history, &array); + + dbus_message_iter_close_container(&iter, &array); + + agent->user_data = (void *)history; + + if (dbus_connection_send_with_reply(conn, msg, &agent->call, + timeout) == FALSE || + agent->call == NULL) + return -EIO; + + dbus_pending_call_set_notify(agent->call, data_delivery_cb, + agent, NULL); + return 0; +} + +void history_agent_send_release(struct history_agent *agent) +{ + history_agent_send_no_reply(agent, "Release"); +} + +void history_agent_set_removed_notify(struct history_agent *agent, + ofono_destroy_func destroy, + void *user_data) +{ + agent->removed_cb = destroy; + agent->removed_data = user_data; +} diff --git a/plugins/history_agent.h b/plugins/history_agent.h new file mode 100644 index 0000000..fe7049e --- /dev/null +++ b/plugins/history_agent.h @@ -0,0 +1,103 @@ +/* + * + * oFono - Open Source Telephony + * + * Copyright (C) 2008-2010 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 + +#define OFONO_API_SUBJECT_TO_CHANGE +#include <errno.h> +#include <string.h> + +#include "gdbus/gdbus.h" +#include <ofono/dbus.h> +#include <ofono/history.h> +#include <ofono/log.h> +#include <ofono/types.h> +#include "src/ofono.h" + +#define PHONE_NUMBER_LENGTH 64 +struct history_agent; + +enum history_type { + VOICE = 0, + TEXT +}; + +struct voice_history { + guint32 uid; + guint8 type; + char lineid[PHONE_NUMBER_LENGTH]; + time_t start_time; + time_t end_time; + char *modem_path; +}; + +struct text_history { + char uid[OFONO_SHA1_UUID_LEN * 2 + 1]; + guint8 type; + guint8 status; + char lineid[PHONE_NUMBER_LENGTH]; + struct tm localsenttime; + struct tm remotesenttime; + char *message; + char *modem_path; +}; + +struct history { + union { + struct voice_history voice; + struct text_history text; + } data; + enum history_type type; +}; + +enum HISTORY_AGENT_RESULT { + HISTORY_AGENT_RESULT_OK, + HISTORY_AGENT_RESULT_FAILED, + HISTORY_AGENT_RESULT_TIMEOUT +}; + +enum type { + OUTGOING = 0, + INCOMING, + MISSED +}; + +struct history_agent *history_agent_new(const char *path, const char *sender, + ofono_bool_t remove_on_terminate); + +void history_agent_free(struct history_agent *agent); + +ofono_bool_t history_agent_matches(struct history_agent *agent, + const char *path, const char *sender); + +int history_agent_report_voicecall(struct history *vhistory, + struct history_agent *agent, int timeout); + +int history_agent_report_textmessage(struct history *history, + struct history_agent *agent, int timeout); + +void history_agent_send_release(struct history_agent *agent); + +void history_agent_set_removed_notify(struct history_agent *agent, + ofono_destroy_func destroy, + void *user_data); -- 1.6.3.3 _______________________________________________ ofono mailing list ofono@ofono.org http://lists.ofono.org/listinfo/ofono