mirror of git://git.sysmocom.de/ofono
Export phonebook as vCard 3.0 format
This commit is contained in:
parent
ac4aeac3d6
commit
f00af45270
|
@ -10,13 +10,13 @@ builtin_sources += atmodem/atmodem.c atmodem/at.h \
|
|||
atmodem/call-forwarding.c atmodem/call-meter.c \
|
||||
atmodem/network-registration.c atmodem/sim.c \
|
||||
atmodem/ussd.c atmodem/voicecall.c \
|
||||
atmodem/call-barring.c
|
||||
atmodem/call-barring.c atmodem/phonebook.c
|
||||
|
||||
builtin_modules += phonet
|
||||
builtin_sources += phonet/phonet.c
|
||||
|
||||
noinst_LTLIBRARIES = libbuiltin.la
|
||||
|
||||
|
||||
libbuiltin_la_SOURCES = $(builtin_sources)
|
||||
libbuiltin_la_LDFLAGS =
|
||||
libbuiltin_la_CFLAGS = $(AM_CFLAGS) $(builtin_cflags) \
|
||||
|
|
|
@ -94,3 +94,6 @@ extern void at_sim_exit(struct ofono_modem *modem);
|
|||
|
||||
extern void at_sms_init(struct ofono_modem *modem);
|
||||
extern void at_sms_exit(struct ofono_modem *modem);
|
||||
|
||||
extern void at_phonebook_init(struct ofono_modem *modem);
|
||||
extern void at_phonebook_exit(struct ofono_modem *modem);
|
||||
|
|
|
@ -101,6 +101,7 @@ static void interface_exit(struct at_data *at)
|
|||
at_call_barring_exit(at->modem);
|
||||
at_ussd_exit(at->modem);
|
||||
at_sim_exit(at->modem);
|
||||
at_phonebook_exit(at->modem);
|
||||
}
|
||||
|
||||
static void manager_free(gpointer user)
|
||||
|
@ -351,6 +352,7 @@ static void create_cb(GIOChannel *io, gboolean success, gpointer user)
|
|||
at_call_meter_init(at->modem);
|
||||
at_call_barring_init(at->modem);
|
||||
at_sms_init(at->modem);
|
||||
at_phonebook_init(at->modem);
|
||||
|
||||
at->io = io;
|
||||
at->driver = g_strdup(driver);
|
||||
|
|
|
@ -0,0 +1,303 @@
|
|||
/*
|
||||
* oFono - GSM 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 as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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 _GNU_SOURCE
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include <ofono/log.h>
|
||||
#include "driver.h"
|
||||
#include "util.h"
|
||||
|
||||
#include "gatchat.h"
|
||||
#include "gatresult.h"
|
||||
|
||||
#include "at.h"
|
||||
|
||||
|
||||
#define INDEX_INVALID -1
|
||||
|
||||
static const char *none_prefix[] = { NULL };
|
||||
static const char *entries_prefix[] = { "+CPBR:", NULL };
|
||||
|
||||
static void at_read_entries_cb(gboolean ok, GAtResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
struct cb_data *cbd = user_data;
|
||||
ofono_phonebook_export_entries_t cb = cbd->cb;
|
||||
struct ofono_error error;
|
||||
GAtResultIter iter;
|
||||
int num_entries_max = 0;
|
||||
int num_entries_real;
|
||||
int num;
|
||||
struct ofono_phonebook_entry *entries;
|
||||
|
||||
decode_at_error(&error, g_at_result_final_response(result));
|
||||
if (!ok) {
|
||||
cb(&error, 0, NULL, cbd->data);
|
||||
return;
|
||||
}
|
||||
|
||||
g_at_result_iter_init(&iter, result);
|
||||
|
||||
while (g_at_result_iter_next(&iter, "+CPBR:"))
|
||||
num_entries_max += 1;
|
||||
|
||||
entries = g_new(struct ofono_phonebook_entry, num_entries_max);
|
||||
|
||||
g_at_result_iter_init(&iter, result);
|
||||
for (num_entries_real = 0; g_at_result_iter_next(&iter, "+CPBR:");) {
|
||||
int index, type, hidden, adtype;
|
||||
const char *number, *text, *group, *adnumber,
|
||||
*secondtext, *email, *sip_uri, *tel_uri;
|
||||
|
||||
if (!g_at_result_iter_next_number(&iter, &index))
|
||||
continue;
|
||||
entries[num_entries_real].index = index;
|
||||
|
||||
if (!g_at_result_iter_next_string(&iter, &number))
|
||||
continue;
|
||||
entries[num_entries_real].number = g_strdup(number);
|
||||
|
||||
if (!g_at_result_iter_next_number(&iter, &type)) {
|
||||
g_free(entries[num_entries_real].number);
|
||||
continue;
|
||||
}
|
||||
entries[num_entries_real].type = type;
|
||||
|
||||
if (!g_at_result_iter_next_string(&iter, &text)) {
|
||||
g_free(entries[num_entries_real].number);
|
||||
continue;
|
||||
}
|
||||
entries[num_entries_real].text = g_strdup(text);
|
||||
|
||||
if (!g_at_result_iter_next_number(&iter, &hidden))
|
||||
hidden = -1;
|
||||
entries[num_entries_real].hidden = hidden;
|
||||
|
||||
if (!g_at_result_iter_next_string(&iter, &group))
|
||||
group = NULL;
|
||||
entries[num_entries_real].group = g_strdup(group);
|
||||
|
||||
if (!g_at_result_iter_next_string(&iter, &adnumber))
|
||||
adnumber = NULL;
|
||||
entries[num_entries_real].adnumber = g_strdup(adnumber);
|
||||
|
||||
if (!g_at_result_iter_next_number(&iter, &adtype))
|
||||
adtype = -1;
|
||||
entries[num_entries_real].adtype = adtype;
|
||||
|
||||
if (!g_at_result_iter_next_string(&iter, &secondtext))
|
||||
secondtext = NULL;
|
||||
entries[num_entries_real].secondtext = g_strdup(secondtext);
|
||||
|
||||
if (!g_at_result_iter_next_string(&iter, &email))
|
||||
email = NULL;
|
||||
entries[num_entries_real].email = g_strdup(email);
|
||||
|
||||
if (!g_at_result_iter_next_string(&iter, &sip_uri))
|
||||
sip_uri = NULL;
|
||||
entries[num_entries_real].sip_uri = g_strdup(sip_uri);
|
||||
|
||||
if (!g_at_result_iter_next_string(&iter, &tel_uri))
|
||||
tel_uri = NULL;
|
||||
entries[num_entries_real].tel_uri = g_strdup(tel_uri);
|
||||
|
||||
num_entries_real++;
|
||||
}
|
||||
cb(&error, num_entries_real, entries, cbd->data);
|
||||
|
||||
for (num = 0; num < num_entries_real; num++) {
|
||||
g_free(entries[num].number);
|
||||
g_free(entries[num].text);
|
||||
g_free(entries[num].group);
|
||||
g_free(entries[num].adnumber);
|
||||
g_free(entries[num].secondtext);
|
||||
g_free(entries[num].email);
|
||||
g_free(entries[num].sip_uri);
|
||||
g_free(entries[num].tel_uri);
|
||||
}
|
||||
g_free(entries);
|
||||
entries = NULL;
|
||||
}
|
||||
|
||||
static void at_read_entries(struct ofono_modem *modem, int index_min,
|
||||
int index_max, ofono_phonebook_export_entries_t cb,
|
||||
void *data)
|
||||
{
|
||||
struct at_data *at = ofono_modem_userdata(modem);
|
||||
struct cb_data *cbd = cb_data_new(modem, cb, data);
|
||||
char buf[32];
|
||||
|
||||
if (!cbd)
|
||||
goto error;
|
||||
|
||||
sprintf(buf, "AT+CPBR=%d,%d", index_min, index_max);
|
||||
if (g_at_chat_send(at->parser, buf, entries_prefix,
|
||||
at_read_entries_cb, cbd, g_free) > 0)
|
||||
return;
|
||||
|
||||
error:
|
||||
if (cbd)
|
||||
g_free(cbd);
|
||||
|
||||
{
|
||||
DECLARE_FAILURE(error);
|
||||
cb(&error, 0, NULL, data);
|
||||
}
|
||||
}
|
||||
|
||||
static void at_list_indices_cb(gboolean ok, GAtResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
struct cb_data *cbd = user_data;
|
||||
struct ofono_modem *modem = cbd->modem;
|
||||
ofono_phonebook_export_entries_t cb = cbd->cb;
|
||||
struct ofono_error error;
|
||||
GAtResultIter iter;
|
||||
const char *indices;
|
||||
int index_min = 0, index_max = 0;
|
||||
int i = 0, integer_index = 0;
|
||||
|
||||
decode_at_error(&error, g_at_result_final_response(result));
|
||||
if (!ok) {
|
||||
cb(&error, 0, NULL, cbd->data);
|
||||
return;
|
||||
}
|
||||
|
||||
g_at_result_iter_init(&iter, result);
|
||||
if (!g_at_result_iter_next(&iter, "+CPBR:")) {
|
||||
DECLARE_FAILURE(e);
|
||||
cb(&e, 0, NULL, cbd->data);
|
||||
return;
|
||||
}
|
||||
|
||||
indices = g_at_result_iter_raw_line(&iter);
|
||||
/* retrieve index_min and index_max from indices
|
||||
* which seems like "(1-150),32,16"
|
||||
*/
|
||||
while (indices[i] != ')') {
|
||||
if (indices[i] == '(')
|
||||
integer_index = 1;
|
||||
else if (indices[i] == '-')
|
||||
integer_index = 2;
|
||||
if ((indices[i] >= '0') && (indices[i] <= '9')) {
|
||||
if (integer_index == 1)
|
||||
index_min = index_min*10 + (indices[i] - '0');
|
||||
else if (integer_index == 2)
|
||||
index_max = index_max*10 + (indices[i] - '0');
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
at_read_entries(modem, index_min, index_max, cb, modem);
|
||||
}
|
||||
|
||||
static void at_list_indices(struct ofono_modem *modem,
|
||||
ofono_phonebook_export_entries_t cb, void *data)
|
||||
{
|
||||
struct at_data *at = ofono_modem_userdata(modem);
|
||||
struct cb_data *cbd = cb_data_new(modem, cb, data);
|
||||
|
||||
if (!cbd)
|
||||
goto error;
|
||||
|
||||
if (g_at_chat_send(at->parser, "AT+CPBR=?", entries_prefix,
|
||||
at_list_indices_cb, cbd, g_free) > 0)
|
||||
return;
|
||||
|
||||
error:
|
||||
if (cbd)
|
||||
g_free(cbd);
|
||||
|
||||
{
|
||||
DECLARE_FAILURE(error);
|
||||
cb(&error, 0, NULL, data);
|
||||
}
|
||||
}
|
||||
|
||||
static void at_select_storage_cb(gboolean ok, GAtResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
struct cb_data *cbd = user_data;
|
||||
struct ofono_modem *modem = cbd->modem;
|
||||
ofono_phonebook_export_entries_t cb = cbd->cb;
|
||||
struct ofono_error error;
|
||||
|
||||
decode_at_error(&error, g_at_result_final_response(result));
|
||||
if (!ok) {
|
||||
cb(&error, 0, NULL, cbd->data);
|
||||
return;
|
||||
} else
|
||||
at_list_indices(modem, cb, modem);
|
||||
}
|
||||
|
||||
static void at_select_storage(struct ofono_modem *modem, char *storage,
|
||||
ofono_phonebook_export_entries_t cb, void *data)
|
||||
{
|
||||
struct at_data *at = ofono_modem_userdata(modem);
|
||||
struct cb_data *cbd = cb_data_new(modem, cb, data);
|
||||
char buf[32];
|
||||
|
||||
if (!cbd)
|
||||
goto error;
|
||||
|
||||
sprintf(buf, "AT+CPBS=%s", storage);
|
||||
if (g_at_chat_send(at->parser, buf, none_prefix,
|
||||
at_select_storage_cb, cbd, g_free) > 0)
|
||||
return;
|
||||
|
||||
error:
|
||||
if (cbd)
|
||||
g_free(cbd);
|
||||
|
||||
{
|
||||
DECLARE_FAILURE(error);
|
||||
cb(&error, 0, NULL, data);
|
||||
}
|
||||
}
|
||||
|
||||
static void at_export_entries(struct ofono_modem *modem, char *storage,
|
||||
ofono_phonebook_export_entries_t cb, void *data)
|
||||
{
|
||||
at_select_storage(modem, storage, cb, modem);
|
||||
}
|
||||
|
||||
static struct ofono_phonebook_ops ops = {
|
||||
.export_entries = at_export_entries
|
||||
};
|
||||
|
||||
void at_phonebook_init(struct ofono_modem *modem)
|
||||
{
|
||||
ofono_phonebook_register(modem, &ops);
|
||||
}
|
||||
|
||||
void at_phonebook_exit(struct ofono_modem *modem)
|
||||
{
|
||||
ofono_phonebook_unregister(modem);
|
||||
}
|
|
@ -12,7 +12,8 @@ ofonod_SOURCES = main.c ofono.h log.c plugin.c \
|
|||
manager.c dbus-gsm.h dbus-gsm.c util.h util.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
|
||||
smsutil.h smsutil.c cssn.h cssn.c call-barring.c sim.h sim.c \
|
||||
phonebook.c
|
||||
|
||||
ofonod_LDADD = $(top_builddir)/plugins/libbuiltin.la \
|
||||
$(top_builddir)/drivers/libbuiltin.la \
|
||||
|
|
29
src/driver.h
29
src/driver.h
|
@ -102,6 +102,21 @@ struct ofono_own_number {
|
|||
int itc;
|
||||
};
|
||||
|
||||
struct ofono_phonebook_entry {
|
||||
int index;
|
||||
char *number;
|
||||
int type;
|
||||
char *text;
|
||||
int hidden;
|
||||
char *group;
|
||||
char *adnumber;
|
||||
int adtype;
|
||||
char *secondtext;
|
||||
char *email;
|
||||
char *sip_uri;
|
||||
char *tel_uri;
|
||||
};
|
||||
|
||||
/* Notification functions, the integer values here should map to
|
||||
* values obtained from the modem. The enumerations are the same
|
||||
* as the values for the fields found in 3GPP TS 27.007
|
||||
|
@ -177,6 +192,10 @@ typedef void (*ofono_sca_query_cb_t)(const struct ofono_error *error,
|
|||
const struct ofono_phone_number *ph,
|
||||
void *data);
|
||||
|
||||
typedef void (*ofono_phonebook_export_entries_t)(
|
||||
const struct ofono_error *error, int num_entries,
|
||||
const struct ofono_phonebook_entry *entries, void *data);
|
||||
|
||||
struct ofono_modem_attribute_ops {
|
||||
void (*query_manufacturer)(struct ofono_modem *modem,
|
||||
ofono_modem_attribute_query_cb_t cb, void *data);
|
||||
|
@ -397,3 +416,13 @@ void ofono_sms_deliver_notify(struct ofono_modem *modem, unsigned char *pdu,
|
|||
int len, int tpdu_len);
|
||||
void ofono_sms_status_notify(struct ofono_modem *modem, unsigned char *pdu,
|
||||
int len, int tpdu_len);
|
||||
|
||||
struct ofono_phonebook_ops {
|
||||
void (*export_entries)(struct ofono_modem *modem, char *storage,
|
||||
ofono_phonebook_export_entries_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);
|
||||
|
||||
|
|
|
@ -41,6 +41,7 @@ struct ofono_modem {
|
|||
struct cssn_data *cssn;
|
||||
struct sim_manager_data *sim_manager;
|
||||
struct sms_manager_data *sms_manager;
|
||||
struct phonebook_data *phonebook;
|
||||
};
|
||||
|
||||
struct ofono_modem *modem_create(int id, struct ofono_modem_attribute_ops *ops);
|
||||
|
|
|
@ -0,0 +1,318 @@
|
|||
/*
|
||||
* oFono - GSM 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 as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* 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 _GNU_SOURCE
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <dbus/dbus.h>
|
||||
#include <glib.h>
|
||||
#include <gdbus.h>
|
||||
|
||||
#include "ofono.h"
|
||||
|
||||
#include "dbus-gsm.h"
|
||||
#include "modem.h"
|
||||
#include "driver.h"
|
||||
#include "common.h"
|
||||
|
||||
|
||||
#define PHONEBOOK_SERVICES_INTERFACE "org.ofono.Phonebook"
|
||||
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
|
||||
#define LEN_MAX 128
|
||||
#define TYPE_INTERNATIONAL 145
|
||||
|
||||
struct phonebook_data {
|
||||
struct ofono_phonebook_ops *ops;
|
||||
DBusMessage *pending;
|
||||
int storage_support_index; /* go through all supported storage */
|
||||
int cached;
|
||||
GString entries_vcard; /* entries with vcard 3.0 format */
|
||||
};
|
||||
|
||||
static DBusMessage *export_entries_one_storage(DBusConnection *conn,
|
||||
DBusMessage *msg, void *data);
|
||||
|
||||
static const char *storage_support[] = { "\"SM\"", "\"ME\"", NULL };
|
||||
|
||||
static struct phonebook_data *phonebook_create()
|
||||
{
|
||||
struct phonebook_data *phonebook;
|
||||
phonebook = g_try_new0(struct phonebook_data, 1);
|
||||
return phonebook;
|
||||
}
|
||||
|
||||
static void phonebook_destroy(gpointer data)
|
||||
{
|
||||
struct ofono_modem *modem = data;
|
||||
struct phonebook_data *phonebook = modem->phonebook;
|
||||
g_free(phonebook);
|
||||
modem->phonebook = NULL;
|
||||
}
|
||||
|
||||
/* according to RFC 2425, the output string may need folding */
|
||||
static void vcard_printf(GString *str, const char *fmt, ...)
|
||||
{
|
||||
char buf[1024];
|
||||
va_list ap;
|
||||
int len_temp, line_number, i;
|
||||
unsigned int line_delimit = 75;
|
||||
|
||||
va_start(ap, fmt);
|
||||
vsnprintf(buf, sizeof(buf), fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
line_number = strlen(buf) / line_delimit + 1;
|
||||
|
||||
for (i = 0; i < line_number; i++) {
|
||||
len_temp = MIN(line_delimit, strlen(buf) - line_delimit * i);
|
||||
g_string_append_len(str, buf + line_delimit * i, len_temp);
|
||||
if (i != line_number - 1)
|
||||
g_string_append(str, "\r\n ");
|
||||
}
|
||||
|
||||
g_string_append(str, "\r\n");
|
||||
}
|
||||
|
||||
/* According to RFC 2426, we need escape following characters:
|
||||
* '\n', '\r', ';', ',', '\'.
|
||||
*/
|
||||
static void add_slash(char *dest, char *src, int len_max, int len)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i = 0, j = 0; i < len && j < len_max; i++, j++) {
|
||||
switch (src[i]) {
|
||||
case '\n':
|
||||
dest[j++] = '\\';
|
||||
dest[j] = 'n';
|
||||
break;
|
||||
case '\r':
|
||||
dest[j++] = '\\';
|
||||
dest[j] = 'r';
|
||||
break;
|
||||
case '\\':
|
||||
case ';':
|
||||
case ',':
|
||||
dest[j++] = '\\';
|
||||
default:
|
||||
dest[j] = src[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
dest[j] = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
static void vcard_printf_number(GString *entries_vcard_pointer, int type,
|
||||
char *number, int prefer)
|
||||
{
|
||||
char *pref = "", *intl = "";
|
||||
char buf[128];
|
||||
if (prefer)
|
||||
pref = "PREF,";
|
||||
if ((type == TYPE_INTERNATIONAL) && (number[0] != '+'))
|
||||
intl = "+";
|
||||
|
||||
sprintf(buf, "TEL;TYPE=\%sVOICE:\%s\%s", pref, intl, number);
|
||||
vcard_printf(entries_vcard_pointer, buf, number);
|
||||
}
|
||||
|
||||
|
||||
static void entry_to_vcard(GString *entries_vcard_pointer,
|
||||
struct ofono_phonebook_entry *entry)
|
||||
{
|
||||
char field[LEN_MAX];
|
||||
vcard_printf(entries_vcard_pointer, "BEGIN:VCARD");
|
||||
vcard_printf(entries_vcard_pointer, "VERSION:3.0");
|
||||
add_slash(field, entry->text, LEN_MAX, strlen(entry->text));
|
||||
vcard_printf(entries_vcard_pointer, "FN:%s", field);
|
||||
vcard_printf_number(entries_vcard_pointer, entry->type,
|
||||
entry->number, 1);
|
||||
if (entry->group) {
|
||||
add_slash(field, entry->group, LEN_MAX, strlen(entry->group));
|
||||
vcard_printf(entries_vcard_pointer, "CATEGORIES:%s", field);
|
||||
}
|
||||
if (entry->adtype && entry->adnumber) {
|
||||
vcard_printf_number(entries_vcard_pointer, entry->adtype,
|
||||
entry->adnumber, 0);
|
||||
}
|
||||
if (entry->email) {
|
||||
add_slash(field, entry->email, LEN_MAX, strlen(entry->email));
|
||||
vcard_printf(entries_vcard_pointer,
|
||||
"EMAIL;TYPE=INTERNET:%s", field);
|
||||
}
|
||||
if (entry->sip_uri) {
|
||||
add_slash(field, entry->sip_uri, LEN_MAX,
|
||||
strlen(entry->sip_uri));
|
||||
vcard_printf(entries_vcard_pointer, "IMPP;TYPE=SIP:%s", field);
|
||||
}
|
||||
vcard_printf(entries_vcard_pointer, "END:VCARD");
|
||||
vcard_printf(entries_vcard_pointer, "");
|
||||
}
|
||||
|
||||
static DBusMessage *generate_export_entries_reply(struct ofono_modem *modem)
|
||||
{
|
||||
struct phonebook_data *phonebook = modem->phonebook;
|
||||
DBusMessage *reply;
|
||||
DBusMessageIter iter;
|
||||
DBusConnection *conn = dbus_gsm_connection();
|
||||
|
||||
reply = dbus_message_new_method_return(phonebook->pending);
|
||||
if (!reply)
|
||||
return NULL;
|
||||
|
||||
dbus_message_iter_init_append(reply, &iter);
|
||||
dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING,
|
||||
&(phonebook->entries_vcard));
|
||||
g_dbus_send_message(conn, reply);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void export_entries_one_storage_cb(const struct ofono_error *error,
|
||||
int num_entries, const struct ofono_phonebook_entry *entries, void *data)
|
||||
{
|
||||
struct ofono_modem *modem = data;
|
||||
struct phonebook_data *phonebook = modem->phonebook;
|
||||
DBusConnection *conn = dbus_gsm_connection();
|
||||
|
||||
if (error->type != OFONO_ERROR_TYPE_NO_ERROR)
|
||||
ofono_error("export_entries_one_storage_cb with %s failed",
|
||||
storage_support[phonebook->storage_support_index]);
|
||||
else {
|
||||
int num = 0;
|
||||
GString *entries_vcard_pointer = &(phonebook->entries_vcard);
|
||||
for (num = 0; num < num_entries; num++)
|
||||
entry_to_vcard(entries_vcard_pointer,
|
||||
(struct ofono_phonebook_entry *)&entries[num]);
|
||||
}
|
||||
|
||||
phonebook->storage_support_index++;
|
||||
export_entries_one_storage(conn, phonebook->pending, modem);
|
||||
return;
|
||||
}
|
||||
|
||||
static DBusMessage *export_entries_one_storage(DBusConnection *conn,
|
||||
DBusMessage *msg, void *data)
|
||||
{
|
||||
struct ofono_modem *modem = data;
|
||||
struct phonebook_data *phonebook = modem->phonebook;
|
||||
|
||||
if (storage_support[phonebook->storage_support_index] != NULL)
|
||||
phonebook->ops->export_entries(modem,
|
||||
(char *)storage_support[phonebook->storage_support_index],
|
||||
export_entries_one_storage_cb, modem);
|
||||
else {
|
||||
phonebook->cached = 1;
|
||||
generate_export_entries_reply(modem);
|
||||
dbus_message_unref(phonebook->pending);
|
||||
phonebook->pending = NULL;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static DBusMessage *export_entries(DBusConnection *conn, DBusMessage *msg,
|
||||
void *data)
|
||||
{
|
||||
struct ofono_modem *modem = data;
|
||||
struct phonebook_data *phonebook = modem->phonebook;
|
||||
|
||||
if (phonebook->pending) {
|
||||
DBusMessage *reply;
|
||||
reply = dbus_gsm_busy(phonebook->pending);
|
||||
g_dbus_send_message(conn, reply);
|
||||
return NULL;
|
||||
}
|
||||
phonebook->pending = dbus_message_ref(msg);
|
||||
|
||||
if (phonebook->cached) {
|
||||
generate_export_entries_reply(modem);
|
||||
dbus_message_unref(phonebook->pending);
|
||||
phonebook->pending = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
g_string_set_size(&(phonebook->entries_vcard), 0);
|
||||
phonebook->storage_support_index = 0;
|
||||
export_entries_one_storage(conn, msg, data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static GDBusMethodTable phonebook_methods[] = {
|
||||
{ "ExportEntries", "", "s", export_entries,
|
||||
G_DBUS_METHOD_FLAG_ASYNC },
|
||||
{ }
|
||||
};
|
||||
|
||||
static GDBusSignalTable phonebook_signals[] = {
|
||||
{ }
|
||||
};
|
||||
|
||||
int ofono_phonebook_register(struct ofono_modem *modem,
|
||||
struct ofono_phonebook_ops *ops)
|
||||
{
|
||||
DBusConnection *conn = dbus_gsm_connection();
|
||||
|
||||
if (modem == NULL)
|
||||
return -1;
|
||||
|
||||
if (ops == NULL)
|
||||
return -1;
|
||||
|
||||
modem->phonebook = phonebook_create();
|
||||
|
||||
if (modem->phonebook == NULL)
|
||||
return -1;
|
||||
|
||||
modem->phonebook->ops = ops;
|
||||
|
||||
if (!g_dbus_register_interface(conn, modem->path,
|
||||
PHONEBOOK_SERVICES_INTERFACE,
|
||||
phonebook_methods, phonebook_signals,
|
||||
NULL, modem, phonebook_destroy)) {
|
||||
ofono_error("Could not register Phonebook %s", modem->path);
|
||||
|
||||
phonebook_destroy(modem->phonebook);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
modem_add_interface(modem, PHONEBOOK_SERVICES_INTERFACE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ofono_phonebook_unregister(struct ofono_modem *modem)
|
||||
{
|
||||
DBusConnection *conn = dbus_gsm_connection();
|
||||
|
||||
if (modem->phonebook == NULL)
|
||||
return;
|
||||
|
||||
modem_remove_interface(modem, PHONEBOOK_SERVICES_INTERFACE);
|
||||
g_dbus_unregister_interface(conn, modem->path,
|
||||
PHONEBOOK_SERVICES_INTERFACE);
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
#!/usr/bin/python
|
||||
|
||||
import gobject
|
||||
|
||||
import dbus
|
||||
import dbus.mainloop.glib
|
||||
|
||||
if __name__ == "__main__":
|
||||
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
|
||||
|
||||
bus = dbus.SystemBus()
|
||||
|
||||
manager = dbus.Interface(bus.get_object('org.ofono', '/'),
|
||||
'org.ofono.Manager')
|
||||
|
||||
try:
|
||||
modems = manager.GetProperties()['Modems']
|
||||
except dbus.DBusException, e:
|
||||
print "Unable to get the Modems property %s" % e
|
||||
|
||||
phonebook = dbus.Interface(bus.get_object('org.ofono', modems[0]),
|
||||
'org.ofono.Phonebook')
|
||||
|
||||
print "export entries for the first time"
|
||||
print phonebook.ExportEntries()
|
||||
print "export entries for the second time, which should return from cache"
|
||||
print phonebook.ExportEntries()
|
||||
|
||||
mainloop = gobject.MainLoop()
|
||||
mainloop.run()
|
Loading…
Reference in New Issue