diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/Makefile.am | 4 | ||||
-rw-r--r-- | drivers/atmodem/at.h | 3 | ||||
-rw-r--r-- | drivers/atmodem/atmodem.c | 2 | ||||
-rw-r--r-- | drivers/atmodem/phonebook.c | 303 |
4 files changed, 310 insertions, 2 deletions
diff --git a/drivers/Makefile.am b/drivers/Makefile.am index 9559ed5f..010e0d5a 100644 --- a/drivers/Makefile.am +++ b/drivers/Makefile.am @@ -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) \ diff --git a/drivers/atmodem/at.h b/drivers/atmodem/at.h index ec7fb80c..03002822 100644 --- a/drivers/atmodem/at.h +++ b/drivers/atmodem/at.h @@ -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); diff --git a/drivers/atmodem/atmodem.c b/drivers/atmodem/atmodem.c index 20b95a5f..51d0636a 100644 --- a/drivers/atmodem/atmodem.c +++ b/drivers/atmodem/atmodem.c @@ -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); diff --git a/drivers/atmodem/phonebook.c b/drivers/atmodem/phonebook.c new file mode 100644 index 00000000..d03b352c --- /dev/null +++ b/drivers/atmodem/phonebook.c @@ -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); +} |