summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDenis Kenzior <denkenz@gmail.com>2009-07-16 17:17:54 -0500
committerDenis Kenzior <denkenz@gmail.com>2009-07-16 17:22:04 -0500
commit8d47b8f36d6f02fd48ee75023f0ccd3717af50d1 (patch)
treeb042efec7b10df8c3aa276ee656b92cd2aa6c2bc
parent72345b417505d0078e6ecd7bc81819195f1c982d (diff)
downloadofono-8d47b8f36d6f02fd48ee75023f0ccd3717af50d1.tar.bz2
Refactor phonebook code
-rw-r--r--drivers/atmodem/phonebook.c457
1 files changed, 208 insertions, 249 deletions
diff --git a/drivers/atmodem/phonebook.c b/drivers/atmodem/phonebook.c
index c2fd21bb..d5befc63 100644
--- a/drivers/atmodem/phonebook.c
+++ b/drivers/atmodem/phonebook.c
@@ -46,23 +46,14 @@
#define CHARSET_SUPPORT (CHARSET_UTF8 | CHARSET_UCS2)
static const char *none_prefix[] = { NULL };
-static const char *entries_prefix[] = { "+CPBR:", NULL };
-static const char *charset_prefix[] = { "+CSCS:", NULL };
-
-static void at_select_storage(struct ofono_modem *modem,
- ofono_generic_cb_t cb, void *data);
-static void at_select_charset(struct ofono_modem *modem,
- ofono_generic_cb_t cb, void *data);
+static const char *cpbr_prefix[] = { "+CPBR:", NULL };
+static const char *cscs_prefix[] = { "+CSCS:", NULL };
+static const char *cpbs_prefix[] = { "+CPBS:", NULL };
struct pb_data {
- const char *storage;
int index_min, index_max;
- int charset_origin;
- const char *charset_origin_str;
- int charset_current;
- int charset_list;
- int charset_need_restore;
- int has_charset_info;
+ char *old_charset;
+ int supported;
};
static struct pb_data *phonebook_create()
@@ -73,28 +64,51 @@ static struct pb_data *phonebook_create()
static void phonebook_destroy(struct pb_data *data)
{
- g_free((char *)data->charset_origin_str);
+ if (data->old_charset)
+ g_free(data->old_charset);
g_free(data);
}
-static const char *ucs2_to_utf8(const char *str)
+static char *ucs2_to_utf8(const char *str)
{
long len;
unsigned char *ucs2;
- const char *utf8;
+ char *utf8;
ucs2 = decode_hex(str, -1, &len, 0);
- utf8 = g_convert(ucs2, len, "UTF-8//TRANSLIT", "UCS-2BE",
+ utf8 = g_convert((char *)ucs2, len, "UTF-8//TRANSLIT", "UCS-2BE",
NULL, NULL, NULL);
g_free(ucs2);
return utf8;
}
+static const char *best_charset(int supported)
+{
+ const char *charset = "Invalid";
+
+ if (supported & CHARSET_UCS2)
+ charset = "UCS2";
+
+ if (supported & CHARSET_UTF8)
+ charset = "UTF-8";
+
+ return charset;
+}
+
static void at_cpbr_notify(GAtResult *result, gpointer user_data)
{
struct cb_data *cbd = user_data;
struct ofono_modem *modem = cbd->modem;
struct at_data *at = ofono_modem_userdata(modem);
GAtResultIter iter;
+ int current;
+
+ dump_response("at_cbpr_notify", 1, result);
+
+ if (at->pb->supported & CHARSET_UCS2)
+ current = CHARSET_UCS2;
+
+ if (at->pb->supported & CHARSET_UTF8)
+ current = CHARSET_UTF8;
g_at_result_iter_init(&iter, result);
@@ -103,20 +117,14 @@ static void at_cpbr_notify(GAtResult *result, gpointer user_data)
const char *number;
int type;
const char *text;
- const char *text_utf8;
int hidden = -1;
const char *group = NULL;
- const char *group_utf8 = NULL;
const char *adnumber = NULL;
int adtype = -1;
const char *secondtext = NULL;
- const char *secondtext_utf8 = NULL;
const char *email = NULL;
- const char *email_utf8 = NULL;
const char *sip_uri = NULL;
- const char *sip_uri_utf8 = NULL;
const char *tel_uri = NULL;
- const char *tel_uri_utf8 = NULL;
if (!g_at_result_iter_next_number(&iter, &index))
continue;
@@ -140,7 +148,14 @@ static void at_cpbr_notify(GAtResult *result, gpointer user_data)
g_at_result_iter_next_string(&iter, &tel_uri);
/* charset_current is either CHARSET_UCS2 or CHARSET_UTF8 */
- if (at->pb->charset_current & CHARSET_UCS2) {
+ if (current == CHARSET_UCS2) {
+ char *text_utf8;
+ char *group_utf8 = NULL;
+ char *secondtext_utf8 = NULL;
+ char *email_utf8 = NULL;
+ char *sip_uri_utf8 = NULL;
+ char *tel_uri_utf8 = NULL;
+
text_utf8 = ucs2_to_utf8(text);
if (group)
group_utf8 = ucs2_to_utf8(group);
@@ -152,31 +167,47 @@ static void at_cpbr_notify(GAtResult *result, gpointer user_data)
sip_uri_utf8 = ucs2_to_utf8(sip_uri);
if (tel_uri)
tel_uri_utf8 = ucs2_to_utf8(tel_uri);
- } else {
- text_utf8 = text;
- group_utf8 = group;
- secondtext_utf8 = secondtext;
- email_utf8 = email;
- sip_uri_utf8 = sip_uri;
- tel_uri_utf8 = tel_uri;
- }
- ofono_phonebook_entry(cbd->modem, index, number, type,
+ ofono_phonebook_entry(cbd->modem, index, number, type,
text_utf8, hidden, group_utf8, adnumber,
adtype, secondtext_utf8, email_utf8,
sip_uri_utf8, tel_uri_utf8);
- if (at->pb->charset_current & CHARSET_UCS2) {
- g_free((char *)text_utf8);
- g_free((char *)group_utf8);
- g_free((char *)secondtext_utf8);
- g_free((char *)email_utf8);
- g_free((char *)sip_uri_utf8);
- g_free((char *)tel_uri_utf8);
+ g_free(text_utf8);
+ g_free(group_utf8);
+ g_free(secondtext_utf8);
+ g_free(email_utf8);
+ g_free(sip_uri_utf8);
+ g_free(tel_uri_utf8);
+ } else {
+ ofono_phonebook_entry(cbd->modem, index, number, type,
+ text, hidden, group, adnumber,
+ adtype, secondtext, email,
+ sip_uri, tel_uri);
+
}
}
}
+static void export_failed(struct cb_data *cbd)
+{
+ struct ofono_modem *modem = cbd->modem;
+ struct at_data *at = ofono_modem_userdata(modem);
+ ofono_generic_cb_t cb = cbd->cb;
+
+ {
+ DECLARE_FAILURE(error);
+ cb(&error, cbd->data);
+ }
+
+ g_free(cbd);
+
+ if (at->pb->old_charset) {
+ g_free(at->pb->old_charset);
+ at->pb->old_charset = NULL;
+ }
+}
+
static void at_read_entries_cb(gboolean ok, GAtResult *result,
gpointer user_data)
{
@@ -184,102 +215,94 @@ static void at_read_entries_cb(gboolean ok, GAtResult *result,
struct ofono_modem *modem = cbd->modem;
struct at_data *at = ofono_modem_userdata(modem);
ofono_generic_cb_t cb = cbd->cb;
+ const char *charset;
+ struct ofono_error error;
+ char buf[32];
- if (at->pb->charset_current != at->pb->charset_origin)
- at_select_charset(modem, cb, modem);
- else {
- struct ofono_error error;
- decode_at_error(&error, g_at_result_final_response(result));
- cb(&error, cbd->data);
+ decode_at_error(&error, g_at_result_final_response(result));
+ cb(&error, cbd->data);
+ g_free(cbd);
+
+ charset = best_charset(at->pb->supported);
+
+ if (strcmp(at->pb->old_charset, charset)) {
+ sprintf(buf, "AT+CSCS=\"%s\"", at->pb->old_charset);
+ g_at_chat_send(at->parser, buf, none_prefix, NULL, NULL, NULL);
}
+
+ g_free(at->pb->old_charset);
+ at->pb->old_charset = NULL;
}
-static void at_read_entries(struct ofono_modem *modem, ofono_generic_cb_t cb,
- void *data)
+static void at_read_entries(struct cb_data *cbd)
{
+ struct ofono_modem *modem = cbd->modem;
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", at->pb->index_min, at->pb->index_max);
- if (g_at_chat_send_listing(at->parser, buf, entries_prefix,
+ if (g_at_chat_send_listing(at->parser, buf, cpbr_prefix,
at_cpbr_notify, at_read_entries_cb,
- cbd, g_free) > 0)
+ cbd, NULL) > 0)
return;
-error:
- if (cbd)
- g_free(cbd);
-
- if (at->pb->charset_origin != at->pb->charset_current)
- /* restore the charset */
- at_select_charset(modem, cb, modem);
- else {
- DECLARE_FAILURE(error);
- cb(&error, data);
- }
+ /* If we get here, then most likely connection to the modem dropped
+ * and we can't really restore the charset anyway
+ */
+ export_failed(cbd);
}
-static void at_select_charset_cb(gboolean ok, GAtResult *result,
- gpointer user_data)
+static void at_set_charset_cb(gboolean ok, GAtResult *result,
+ gpointer user_data)
{
struct cb_data *cbd = user_data;
- struct ofono_modem *modem = cbd->modem;
- struct at_data *at = ofono_modem_userdata(modem);
- ofono_generic_cb_t cb = cbd->cb;
- struct ofono_error error;
- if (!ok)
- goto out;
-
- at->pb->charset_need_restore ^= 1;
- if (at->pb->charset_need_restore) {
- at_read_entries(modem, cb, modem);
+ if (!ok) {
+ export_failed(cbd);
return;
}
-out:
- decode_at_error(&error, g_at_result_final_response(result));
- cb(&error, cbd->data);
- return;
+ at_read_entries(cbd);
}
-static void at_select_charset(struct ofono_modem *modem,
- ofono_generic_cb_t cb, void *data)
+static void at_read_charset_cb(gboolean ok, GAtResult *result,
+ gpointer user_data)
{
+ struct cb_data *cbd = user_data;
+ struct ofono_modem *modem = cbd->modem;
struct at_data *at = ofono_modem_userdata(modem);
- struct cb_data *cbd = cb_data_new(modem, cb, data);
- char buf[32];
+ GAtResultIter iter;
const char *charset;
+ char buf[32];
- if (!cbd)
+ dump_response("at_read_charset_cb", ok, result);
+
+ if (!ok)
goto error;
- if (at->pb->charset_need_restore)
- charset = at->pb->charset_origin_str;
- else if (at->pb->charset_current == CHARSET_UTF8)
- charset = "UTF-8";
- else
- charset = "UCS2";
+ g_at_result_iter_init(&iter, result);
+
+ if (!g_at_result_iter_next(&iter, "+CSCS:"))
+ goto error;
- sprintf(buf, "AT+CSCS=%s", charset);
+ g_at_result_iter_next_string(&iter, &charset);
+
+ at->pb->old_charset = g_strdup(charset);
+
+ charset = best_charset(at->pb->supported);
+
+ if (!strcmp(at->pb->old_charset, charset)) {
+ at_read_entries(cbd);
+ return;
+ }
+
+ sprintf(buf, "AT+CSCS=\"%s\"", charset);
if (g_at_chat_send(at->parser, buf, none_prefix,
- at_select_charset_cb, cbd, g_free) > 0)
+ at_set_charset_cb, cbd, NULL) > 0)
return;
error:
- if (cbd)
- g_free(cbd);
-
- {
- DECLARE_FAILURE(error);
- if (at->pb->charset_need_restore)
- ofono_error("Phonebook: character can't be restored!");
- cb(&error, data);
- }
+ export_failed(cbd);
}
static void at_list_indices_cb(gboolean ok, GAtResult *result,
@@ -288,7 +311,6 @@ static void at_list_indices_cb(gboolean ok, GAtResult *result,
struct cb_data *cbd = user_data;
struct ofono_modem *modem = cbd->modem;
struct at_data *at = ofono_modem_userdata(modem);
- ofono_generic_cb_t cb = cbd->cb;
GAtResultIter iter;
if (!ok)
@@ -311,41 +333,12 @@ static void at_list_indices_cb(gboolean ok, GAtResult *result,
if (!g_at_result_iter_close_list(&iter))
goto error;
- if (at->pb->charset_origin != at->pb->charset_current)
- at_select_charset(modem, cb, modem);
- else
- at_read_entries(modem, cb, modem);
-
- return;
-
-error:
- {
- DECLARE_FAILURE(e);
- cb(&e, cbd->data);
- }
-}
-
-static void at_list_indices(struct ofono_modem *modem,
- ofono_generic_cb_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)
+ if (g_at_chat_send(at->parser, "AT+CSCS?", cscs_prefix,
+ at_read_charset_cb, cbd, NULL) > 0)
return;
error:
- if (cbd)
- g_free(cbd);
-
- {
- DECLARE_FAILURE(error);
- cb(&error, data);
- }
+ export_failed(cbd);
}
static void at_select_storage_cb(gboolean ok, GAtResult *result,
@@ -353,18 +346,22 @@ static void at_select_storage_cb(gboolean ok, GAtResult *result,
{
struct cb_data *cbd = user_data;
struct ofono_modem *modem = cbd->modem;
- ofono_generic_cb_t cb = cbd->cb;
+ struct at_data *at = ofono_modem_userdata(modem);
- if (!ok) {
- DECLARE_FAILURE(error);
- cb(&error, cbd->data);
+ dump_response("at_select_storage_cb", ok, result);
+
+ if (!ok)
+ goto error;
+
+ if (g_at_chat_send(at->parser, "AT+CPBR=?", cpbr_prefix,
+ at_list_indices_cb, cbd, NULL) > 0)
return;
- }
- at_list_indices(modem, cb, modem);
+error:
+ export_failed(cbd);
}
-static void at_select_storage(struct ofono_modem *modem,
+static void at_export_entries(struct ofono_modem *modem, const char *storage,
ofono_generic_cb_t cb, void *data)
{
struct at_data *at = ofono_modem_userdata(modem);
@@ -374,9 +371,9 @@ static void at_select_storage(struct ofono_modem *modem,
if (!cbd)
goto error;
- sprintf(buf, "AT+CPBS=%s", at->pb->storage);
+ sprintf(buf, "AT+CPBS=\"%s\"", storage);
if (g_at_chat_send(at->parser, buf, none_prefix,
- at_select_storage_cb, cbd, g_free) > 0)
+ at_select_storage_cb, cbd, NULL) > 0)
return;
error:
@@ -385,89 +382,80 @@ error:
{
DECLARE_FAILURE(error);
- cb(&error, cbd->data);
+ cb(&error, data);
}
}
-static void at_read_charset_cb(gboolean ok, GAtResult *result,
- gpointer user_data)
+static struct ofono_phonebook_ops ops = {
+ .export_entries = at_export_entries
+};
+
+static void phonebook_not_supported(struct ofono_modem *modem)
{
- struct cb_data *cbd = user_data;
- struct ofono_modem *modem = cbd->modem;
struct at_data *at = ofono_modem_userdata(modem);
- ofono_generic_cb_t cb = cbd->cb;
+
+ ofono_error("Phonebook not supported by this modem. If this is in "
+ "error please submit patches to support this hardware");
+ if (at->pb) {
+ phonebook_destroy(at->pb);
+ at->pb = NULL;
+ }
+}
+
+static void at_list_storages_cb(gboolean ok, GAtResult *result,
+ gpointer user_data)
+{
+ struct ofono_modem *modem = user_data;
+ gboolean sm_supported = FALSE;
+ gboolean me_supported = FALSE;
+ gboolean in_list = FALSE;
GAtResultIter iter;
- const char *charset;
+ const char *storage;
+
+ dump_response("at_list_storages_cb", ok, result);
if (!ok)
goto error;
g_at_result_iter_init(&iter, result);
-
- if (!g_at_result_iter_next(&iter, "+CSCS:"))
+ if (!g_at_result_iter_next(&iter, "+CPBS:"))
goto error;
- g_at_result_iter_next_string(&iter, &charset);
- at->pb->charset_origin_str = g_strdup(charset);
- if (!strcmp(charset, "UCS2"))
- at->pb->charset_origin = CHARSET_UCS2;
- else if (!strcmp(charset, "UTF-8"))
- at->pb->charset_origin = CHARSET_UTF8;
-
- if (at->pb->charset_origin & CHARSET_SUPPORT)
- at->pb->charset_current = at->pb->charset_origin;
- else if (at->pb->charset_list & CHARSET_UTF8)
- at->pb->charset_current = CHARSET_UTF8;
- else
- at->pb->charset_current = CHARSET_UCS2;
-
- at_select_storage(modem, cb, modem);
- return;
+ /* Some modems don't report CPBS in a proper list */
+ if (g_at_result_iter_open_list(&iter))
+ in_list = TRUE;
-error:
- ofono_error("Phonebook: at_read_charset_cb failed");
- {
- DECLARE_FAILURE(error);
- cb(&error, cbd->data);
+ while (g_at_result_iter_next_string(&iter, &storage)) {
+ if (!strcmp(storage, "ME"))
+ me_supported = TRUE;
+ else if (!strcmp(storage, "SM"))
+ sm_supported = TRUE;
}
-}
-
-static void at_read_charset(struct ofono_modem *modem,
- ofono_generic_cb_t cb, void *data)
-{
- struct at_data *at = ofono_modem_userdata(modem);
- struct cb_data *cbd = cb_data_new(modem, cb, data);
- if (g_at_chat_send(at->parser, "AT+CSCS?", charset_prefix,
- at_read_charset_cb, cbd, g_free) > 0)
- return;
+ if (in_list && !g_at_result_iter_close_list(&iter))
+ goto error;
- {
- DECLARE_FAILURE(error);
- cb(&error, data);
- }
-}
+ if (!me_supported && !sm_supported)
+ goto error;
-static gboolean is_valid_charset_list(struct pb_data *pb)
-{
- if (!(pb->charset_list & CHARSET_SUPPORT)) {
- ofono_error("Phonebook: not a valid charset_list");
- return FALSE;
- }
+ ofono_phonebook_register(modem, &ops);
+ return;
- return TRUE;
+error:
+ phonebook_not_supported(modem);
}
static void at_list_charsets_cb(gboolean ok, GAtResult *result,
gpointer user_data)
{
- struct cb_data *cbd = user_data;
- struct ofono_modem *modem = cbd->modem;
+ struct ofono_modem *modem = user_data;
struct at_data *at = ofono_modem_userdata(modem);
- ofono_generic_cb_t cb = cbd->cb;
+ gboolean in_list = FALSE;
GAtResultIter iter;
const char *charset;
+ dump_response("at_list_charsets_cb", ok, result);
+
if (!ok)
goto error;
@@ -475,77 +463,48 @@ static void at_list_charsets_cb(gboolean ok, GAtResult *result,
if (!g_at_result_iter_next(&iter, "+CSCS:"))
goto error;
+ /* Some modems don't report CPBS in a proper list */
+ if (g_at_result_iter_open_list(&iter))
+ in_list = TRUE;
+
while (g_at_result_iter_next_string(&iter, &charset)) {
if (!strcmp(charset, "UTF-8"))
- at->pb->charset_list |= CHARSET_UTF8;
+ at->pb->supported |= CHARSET_UTF8;
else if (!strcmp(charset, "UCS2"))
- at->pb->charset_list |= CHARSET_UCS2;
+ at->pb->supported |= CHARSET_UCS2;
}
- if (!is_valid_charset_list(at->pb))
+ if (in_list && g_at_result_iter_close_list(&iter))
goto error;
- at_read_charset(modem, cb, modem);
- return;
-
-error:
- ofono_error("Phonebook: at_list_charsets_cb failed");
- {
- DECLARE_FAILURE(error);
- cb(&error, cbd->data);
- }
-}
-
-static void at_list_charsets(struct ofono_modem *modem,
- ofono_generic_cb_t cb, void *data)
-{
- struct at_data *at = ofono_modem_userdata(modem);
- struct cb_data *cbd = cb_data_new(modem, cb, data);
+ if (!(at->pb->supported & CHARSET_SUPPORT))
+ goto error;
- if (g_at_chat_send(at->parser, "AT+CSCS=?", charset_prefix,
- at_list_charsets_cb, cbd, g_free) > 0)
+ if (g_at_chat_send(at->parser, "AT+CPBS=?", cpbs_prefix,
+ at_list_storages_cb, modem, NULL) > 0)
return;
- {
- DECLARE_FAILURE(error);
- cb(&error, data);
- }
+error:
+ phonebook_not_supported(modem);
}
-static void at_export_entries(struct ofono_modem *modem, const char *storage,
- ofono_generic_cb_t cb, void *data)
+static void at_list_charsets(struct ofono_modem *modem)
{
struct at_data *at = ofono_modem_userdata(modem);
- at->pb->storage = storage;
-
- if (at->pb->has_charset_info) {
- if (!is_valid_charset_list(at->pb))
- goto error;
- at_select_storage(modem, cb, modem);
- } else {
- at->pb->has_charset_info = 1;
- at_list_charsets(modem, cb, data);
- }
- return;
+ if (g_at_chat_send(at->parser, "AT+CSCS=?", cscs_prefix,
+ at_list_charsets_cb, modem, NULL) > 0)
+ return;
-error:
- {
- DECLARE_FAILURE(error);
- cb(&error, data);
- }
+ phonebook_not_supported(modem);
}
-static struct ofono_phonebook_ops ops = {
- .export_entries = at_export_entries
-};
-
void at_phonebook_init(struct ofono_modem *modem)
{
struct at_data *at = ofono_modem_userdata(modem);
- ofono_phonebook_register(modem, &ops);
at->pb = phonebook_create();
+ at_list_charsets(modem);
}
void at_phonebook_exit(struct ofono_modem *modem)