diff --git a/include/Makefile.am b/include/Makefile.am index 413d6ada..9ea2af41 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -3,7 +3,7 @@ includedir = @includedir@/ofono include_HEADERS = log.h plugin.h history.h dbus.h modem.h \ types.h call-barring.h call-forwarding.h \ - call-meter.h call-settings.h + call-meter.h call-settings.h phonebook.h nodist_include_HEADERS = version.h diff --git a/include/phonebook.h b/include/phonebook.h new file mode 100644 index 00000000..a04747de --- /dev/null +++ b/include/phonebook.h @@ -0,0 +1,72 @@ +/* + * + * oFono - Open Telephony stack for Linux + * + * Copyright (C) 2008-2009 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef __OFONO_PHONEBOOK_H +#define __OFONO_PHONEBOOK_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +struct ofono_phonebook; + +typedef void (*ofono_phonebook_cb_t)(const struct ofono_error *error, + void *data); + +/* Export entries reports results through ofono_phonebook_entry, if an error + * occurs, ofono_phonebook_entry should not be called + */ +struct ofono_phonebook_driver { + const char *name; + int (*probe)(struct ofono_phonebook *pb); + int (*remove)(struct ofono_phonebook *pb); + void (*export_entries)(struct ofono_phonebook *pb, const char *storage, + ofono_phonebook_cb_t cb, void *data); +}; + +void ofono_phonebook_entry(struct ofono_phonebook *pb, int index, + const char *number, int type, + const char *text, int hidden, + const char *group, + const char *adnumber, int adtype, + const char *secondtext, const char *email, + const char *sip_uri, const char *tel_uri); + +int ofono_phonebook_driver_register(const struct ofono_phonebook_driver *d); +void ofono_phonebook_driver_unregister(const struct ofono_phonebook_driver *d); + +struct ofono_phonebook *ofono_phonebook_create(struct ofono_modem *modem, + const char *driver, + void *data); + +void ofono_phonebook_register(struct ofono_phonebook *pb); +void ofono_phonebook_remove(struct ofono_phonebook *pb); + +void ofono_phonebook_set_data(struct ofono_phonebook *pb, void *data); +void *ofono_phonebook_get_data(struct ofono_phonebook *pb); + +#ifdef __cplusplus +} +#endif + +#endif /* __OFONO_PHONEBOOK_H */ diff --git a/src/driver.h b/src/driver.h index e6e70ef5..5066c428 100644 --- a/src/driver.h +++ b/src/driver.h @@ -277,22 +277,3 @@ void ofono_sms_deliver_notify(struct ofono_modem *modem, unsigned char *pdu, void ofono_sms_status_notify(struct ofono_modem *modem, unsigned char *pdu, int len, int tpdu_len); -/* Export entries reports results through ofono_phonebook_entry, if an error - * occurs, ofono_phonebook_entry should not be called - */ -struct ofono_phonebook_ops { - void (*export_entries)(struct ofono_modem *modem, const char *storage, - ofono_generic_cb_t cb, void *data); -}; - -int ofono_phonebook_register(struct ofono_modem *modem, - struct ofono_phonebook_ops *ops); -void ofono_phonebook_unregister(struct ofono_modem *modem); - -void ofono_phonebook_entry(struct ofono_modem *modem, int index, - const char *number, int type, - const char *text, int hidden, - const char *group, - const char *adnumber, int adtype, - const char *secondtext, const char *email, - const char *sip_uri, const char *tel_uri); diff --git a/src/ofono.h b/src/ofono.h index daae4fd5..1ea2feb2 100644 --- a/src/ofono.h +++ b/src/ofono.h @@ -80,7 +80,6 @@ struct ofono_modem { struct cssn_data *cssn; 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; @@ -129,6 +128,7 @@ void __ofono_modem_remove_atom(struct ofono_modem *modem, #include #include #include +#include #include diff --git a/src/phonebook.c b/src/phonebook.c index 8afb2f0d..fc4c000b 100644 --- a/src/phonebook.c +++ b/src/phonebook.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -43,6 +44,8 @@ #define PHONEBOOK_FLAG_CACHED 0x1 +static GSList *g_drivers = NULL; + enum phonebook_number_type { TEL_TYPE_HOME, TEL_TYPE_MOBILE, @@ -51,13 +54,16 @@ enum phonebook_number_type { TEL_TYPE_OTHER, }; -struct phonebook_data { - struct ofono_phonebook_ops *ops; +struct ofono_phonebook { DBusMessage *pending; int storage_index; /* go through all supported storage */ int flags; GString *vcards; /* entries with vcard 3.0 format */ GSList *merge_list; /* cache the entries that may need a merge */ + const struct ofono_phonebook_driver *driver; + void *driver_data; + struct ofono_modem *modem; + struct ofono_atom *atom; }; struct phonebook_number { @@ -76,31 +82,7 @@ struct phonebook_person { }; static const char *storage_support[] = { "SM", "ME", NULL }; -static void export_phonebook(struct ofono_modem *modem); - -static struct phonebook_data *phonebook_create() -{ - struct phonebook_data *phonebook; - phonebook = g_try_new0(struct phonebook_data, 1); - - if (!phonebook) - return NULL; - - phonebook->vcards = g_string_new(NULL); - - return phonebook; -} - -static void phonebook_destroy(gpointer data) -{ - struct ofono_modem *modem = data; - struct phonebook_data *phonebook = modem->phonebook; - - g_string_free(phonebook->vcards, TRUE); - - g_free(phonebook); - modem->phonebook = NULL; -} +static void export_phonebook(struct ofono_phonebook *pb); /* according to RFC 2425, the output string may need folding */ static void vcard_printf(GString *str, const char *fmt, ...) @@ -290,20 +272,20 @@ static void destroy_merged_entry(struct phonebook_person *person) g_free(person); } -static DBusMessage *generate_export_entries_reply(struct ofono_modem *modem, +static DBusMessage *generate_export_entries_reply(struct ofono_phonebook *pb, DBusMessage *msg) { - struct phonebook_data *phonebook = modem->phonebook; DBusMessage *reply; DBusMessageIter iter; reply = dbus_message_new_method_return(msg); + if (!reply) return NULL; dbus_message_iter_init_append(reply, &iter); - dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, - phonebook->vcards); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, pb->vcards); + return reply; } @@ -364,7 +346,7 @@ static void merge_field_number(GSList **l, const char *number, int type, char c) *l = g_slist_append(*l, pn); } -void ofono_phonebook_entry(struct ofono_modem *modem, int index, +void ofono_phonebook_entry(struct ofono_phonebook *phonebook, int index, const char *number, int type, const char *text, int hidden, const char *group, @@ -372,8 +354,6 @@ void ofono_phonebook_entry(struct ofono_modem *modem, int index, const char *secondtext, const char *email, const char *sip_uri, const char *tel_uri) { - struct phonebook_data *phonebook = modem->phonebook; - /* There's really nothing to do */ if ((number == NULL || number[0] == '\0') && (text == NULL || text[0] == '\0')) @@ -434,8 +414,7 @@ void ofono_phonebook_entry(struct ofono_modem *modem, int index, static void export_phonebook_cb(const struct ofono_error *error, void *data) { - struct ofono_modem *modem = data; - struct phonebook_data *phonebook = modem->phonebook; + struct ofono_phonebook *phonebook = data; if (error->type != OFONO_ERROR_TYPE_NO_ERROR) ofono_error("export_entries_one_storage_cb with %s failed", @@ -451,23 +430,22 @@ static void export_phonebook_cb(const struct ofono_error *error, void *data) phonebook->merge_list = NULL; phonebook->storage_index++; - export_phonebook(modem); + export_phonebook(phonebook); return; } -static void export_phonebook(struct ofono_modem *modem) +static void export_phonebook(struct ofono_phonebook *phonebook) { - struct phonebook_data *phonebook = modem->phonebook; DBusMessage *reply; const char *pb = storage_support[phonebook->storage_index]; if (pb) { - phonebook->ops->export_entries(modem, pb, - export_phonebook_cb, modem); + phonebook->driver->export_entries(phonebook, pb, + export_phonebook_cb, phonebook); return; } - reply = generate_export_entries_reply(modem, phonebook->pending); + reply = generate_export_entries_reply(phonebook, phonebook->pending); if (!reply) { dbus_message_unref(phonebook->pending); @@ -481,8 +459,7 @@ static void export_phonebook(struct ofono_modem *modem) static DBusMessage *import_entries(DBusConnection *conn, DBusMessage *msg, void *data) { - struct ofono_modem *modem = data; - struct phonebook_data *phonebook = modem->phonebook; + struct ofono_phonebook *phonebook = data; DBusMessage *reply; if (phonebook->pending) { @@ -492,7 +469,7 @@ static DBusMessage *import_entries(DBusConnection *conn, DBusMessage *msg, } if (phonebook->flags & PHONEBOOK_FLAG_CACHED) { - reply = generate_export_entries_reply(modem, msg); + reply = generate_export_entries_reply(phonebook, msg); g_dbus_send_message(conn, reply); return NULL; } @@ -501,7 +478,7 @@ static DBusMessage *import_entries(DBusConnection *conn, DBusMessage *msg, phonebook->storage_index = 0; phonebook->pending = dbus_message_ref(msg); - export_phonebook(modem); + export_phonebook(phonebook); return NULL; } @@ -516,47 +493,118 @@ static GDBusSignalTable phonebook_signals[] = { { } }; -int ofono_phonebook_register(struct ofono_modem *modem, - struct ofono_phonebook_ops *ops) +int ofono_phonebook_driver_register(const struct ofono_phonebook_driver *d) { - DBusConnection *conn = ofono_dbus_get_connection(); + DBG("driver: %p, name: %s", d, d->name); - if (modem == NULL) - return -1; + if (d->probe == NULL) + return -EINVAL; - if (ops == NULL) - return -1; + g_drivers = g_slist_prepend(g_drivers, (void *)d); - modem->phonebook = phonebook_create(); - - if (modem->phonebook == NULL) - return -1; - - modem->phonebook->ops = ops; - - if (!g_dbus_register_interface(conn, modem->path, - PHONEBOOK_INTERFACE, - phonebook_methods, phonebook_signals, - NULL, modem, phonebook_destroy)) { - ofono_error("Could not register Phonebook %s", modem->path); - - phonebook_destroy(modem->phonebook); - - return -1; - } - - ofono_modem_add_interface(modem, PHONEBOOK_INTERFACE); return 0; } -void ofono_phonebook_unregister(struct ofono_modem *modem) +void ofono_phonebook_driver_unregister(const struct ofono_phonebook_driver *d) { + DBG("driver: %p, name: %s", d, d->name); + + g_drivers = g_slist_remove(g_drivers, (void *)d); +} + +static void phonebook_unregister(struct ofono_atom *atom) +{ + struct ofono_phonebook *pb = __ofono_atom_get_data(atom); + const char *path = ofono_modem_get_path(pb->modem); DBusConnection *conn = ofono_dbus_get_connection(); - if (modem->phonebook == NULL) + ofono_modem_remove_interface(pb->modem, PHONEBOOK_INTERFACE); + g_dbus_unregister_interface(conn, path, PHONEBOOK_INTERFACE); +} + +static void phonebook_remove(struct ofono_atom *atom) +{ + struct ofono_phonebook *pb = __ofono_atom_get_data(atom); + struct ofono_modem *modem = pb->modem; + + DBG("atom: %p", atom); + + if (pb == NULL) return; - ofono_modem_remove_interface(modem, PHONEBOOK_INTERFACE); - g_dbus_unregister_interface(conn, modem->path, - PHONEBOOK_INTERFACE); + if (pb->driver && pb->driver->remove) + pb->driver->remove(pb); + + g_string_free(pb->vcards, TRUE); + g_free(pb); +} + +struct ofono_phonebook *ofono_phonebook_create(struct ofono_modem *modem, + const char *driver, void *data) +{ + struct ofono_phonebook *pb; + GSList *l; + + if (driver == NULL) + return NULL; + + pb = g_try_new0(struct ofono_phonebook, 1); + + if (pb == NULL) + return NULL; + + pb->vcards = g_string_new(NULL); + pb->modem = modem; + pb->driver_data = data; + pb->atom = __ofono_modem_add_atom(modem, OFONO_ATOM_TYPE_PHONEBOOK, + phonebook_remove, pb); + + for (l = g_drivers; l; l = l->next) { + const struct ofono_phonebook_driver *drv = l->data; + + if (g_strcmp0(drv->name, driver)) + continue; + + if (drv->probe(pb) < 0) + continue; + + pb->driver = drv; + break; + } + + return pb; +} + +void ofono_phonebook_register(struct ofono_phonebook *pb) +{ + DBusConnection *conn = ofono_dbus_get_connection(); + const char *path = ofono_modem_get_path(pb->modem); + + if (!g_dbus_register_interface(conn, path, PHONEBOOK_INTERFACE, + phonebook_methods, phonebook_signals, + NULL, pb, NULL)) { + ofono_error("Could not create %s interface", + PHONEBOOK_INTERFACE); + + return; + } + + ofono_modem_add_interface(pb->modem, PHONEBOOK_INTERFACE); + + __ofono_atom_register(pb->atom, phonebook_unregister); +} + +void ofono_phonebook_remove(struct ofono_phonebook *pb) +{ + __ofono_modem_remove_atom(pb->modem, pb->atom); +} + +void ofono_phonebook_set_data(struct ofono_phonebook *pb, void *data) +{ + pb->driver_data = data; +} + +void *ofono_phonebook_get_data(struct ofono_phonebook *pb) +{ + return pb->driver_data; }