diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/isimodem/phonebook.c | 265 |
1 files changed, 132 insertions, 133 deletions
diff --git a/drivers/isimodem/phonebook.c b/drivers/isimodem/phonebook.c index 5ee43152..9eb9c079 100644 --- a/drivers/isimodem/phonebook.c +++ b/drivers/isimodem/phonebook.c @@ -30,6 +30,7 @@ #include <glib.h> #include <gisi/client.h> +#include <gisi/message.h> #include <gisi/iter.h> #include <ofono/log.h> @@ -46,9 +47,80 @@ struct pb_data { GIsiClient *client; }; -static int decode_read_response(const unsigned char *msg, size_t len, - struct ofono_phonebook *pb) +struct read_resp { + uint8_t service_type; + uint8_t sb_count; + uint8_t data[]; +}; + +static gboolean parse_adn(GIsiSubBlockIter *iter, uint16_t *location, + char **name, char **number) +{ + uint8_t namelen; + uint8_t numlen; + + if (!g_isi_sb_iter_get_word(iter, location, 4) || + !g_isi_sb_iter_get_byte(iter, &namelen, 6) || + !g_isi_sb_iter_get_byte(iter, &numlen, 7)) + return FALSE; + + if (!g_isi_sb_iter_get_alpha_tag(iter, name, namelen * 2, 8)) + return FALSE; + + if (!g_isi_sb_iter_get_alpha_tag(iter, number, numlen * 2, + 8 + namelen * 2)) { + g_free(*name); + return FALSE; + } + return TRUE; +} + +static gboolean parse_sne(GIsiSubBlockIter *iter, char **sne) +{ + uint8_t len; + + if (!g_isi_sb_iter_get_byte(iter, &len, 6)) + return FALSE; + + if (!g_isi_sb_iter_get_alpha_tag(iter, sne, len * 2, 8)) + return FALSE; + + return TRUE; +} + +static gboolean parse_anr(GIsiSubBlockIter *iter, char **anr) +{ + uint8_t len; + + if (!g_isi_sb_iter_get_byte(iter, &len, 6)) + return FALSE; + + if (!g_isi_sb_iter_get_alpha_tag(iter, anr, len * 2, 8)) + return FALSE; + + return TRUE; +} + +static gboolean parse_email(GIsiSubBlockIter *iter, char **email) { + uint8_t len; + + if (!g_isi_sb_iter_get_byte(iter, &len, 6)) + return FALSE; + + if (!g_isi_sb_iter_get_alpha_tag(iter, email, len * 2, 8)) + return FALSE; + + return TRUE; +} + +static gboolean decode_response(const GIsiMessage *msg, uint16_t *location, + void *data) +{ + struct ofono_phonebook *pb = data; + const struct read_resp *resp = g_isi_msg_data(msg); + size_t len = g_isi_msg_data_len(msg); + GIsiSubBlockIter iter; char *name = NULL; @@ -57,84 +129,48 @@ static int decode_read_response(const unsigned char *msg, size_t len, char *anr = NULL; char *email = NULL; - int location = -1; - guint8 status = 0; + uint8_t status = 0; + gboolean success = FALSE; - if (len < 3 || msg[0] != SIM_PB_RESP_SIM_PB_READ) - goto error; - - if (msg[1] != SIM_PB_READ) - goto error; + if (g_isi_msg_id(msg) != SIM_PB_RESP_SIM_PB_READ || + resp == NULL || len < sizeof(struct read_resp) || + resp->service_type != SIM_PB_READ) + return FALSE; - for (g_isi_sb_iter_init_full(&iter, msg, len, 3, TRUE, msg[2]); - g_isi_sb_iter_is_valid(&iter); - g_isi_sb_iter_next(&iter)) { + for (g_isi_sb_iter_init_full(&iter, msg, 2, TRUE, resp->sb_count); + g_isi_sb_iter_is_valid(&iter); + g_isi_sb_iter_next(&iter)) { switch (g_isi_sb_iter_get_id(&iter)) { + case SIM_PB_ADN: - case SIM_PB_ADN: { - guint16 loc; - guint8 namelen; - guint8 numberlen; - - if (!g_isi_sb_iter_get_word(&iter, &loc, 4) || - !g_isi_sb_iter_get_byte(&iter, &namelen, 6) || - !g_isi_sb_iter_get_byte(&iter, &numberlen, 7)) - goto error; - - if (!g_isi_sb_iter_get_alpha_tag(&iter, &name, - namelen * 2, 8)) - goto error; - - if (!g_isi_sb_iter_get_alpha_tag(&iter, &number, - numberlen * 2, 8 + namelen * 2)) + if (!parse_adn(&iter, location, &name, &number)) goto error; - - location = loc; + success = TRUE; break; - } - case SIM_PB_SNE: { - guint8 snelen; + case SIM_PB_SNE: - if (!g_isi_sb_iter_get_byte(&iter, &snelen, 6)) - goto error; - - if (!g_isi_sb_iter_get_alpha_tag(&iter, &sne, - snelen * 2, 8)) + if (!parse_sne(&iter, &sne)) goto error; break; - } - case SIM_PB_ANR: { - guint8 anrlen; + case SIM_PB_ANR: - if (!g_isi_sb_iter_get_byte(&iter, &anrlen, 6)) - goto error; - - if (!g_isi_sb_iter_get_alpha_tag(&iter, &anr, - anrlen * 2, 8)) + if (!parse_anr(&iter, &anr)) goto error; break; - } - case SIM_PB_EMAIL: { - guint8 emaillen; + case SIM_PB_EMAIL: - if (!g_isi_sb_iter_get_byte(&iter, &emaillen, 6)) - goto error; - - if (!g_isi_sb_iter_get_alpha_tag(&iter, &email, - emaillen * 2, 8)) + if (!parse_email(&iter, &email)) goto error; break; - } case SIM_PB_STATUS: if (!g_isi_sb_iter_get_byte(&iter, &status, 4)) goto error; - break; default: @@ -145,15 +181,9 @@ static int decode_read_response(const unsigned char *msg, size_t len, } } - if (status != SIM_SERV_OK) { - DBG("Request failed: %s (0x%02X)", - sim_isi_cause_name(status), status); - goto error; - } - - ofono_phonebook_entry(pb, -1, number, -1, name, -1, NULL, - anr, -1, sne, email, NULL, NULL); - + if (status == SIM_SERV_OK) + ofono_phonebook_entry(pb, -1, number, -1, name, -1, NULL, + anr, -1, sne, email, NULL, NULL); error: g_free(name); g_free(number); @@ -161,15 +191,15 @@ error: g_free(anr); g_free(email); - return location; + return success; } -static void read_next_entry(GIsiClient *client, int location, - GIsiResponseFunc read_cb, - struct isi_cb_data *cbd) +static void read_next_entry(GIsiClient *client, uint16_t location, + GIsiNotifyFunc notify, void *data) { + struct isi_cb_data *cbd = data; ofono_phonebook_cb_t cb = cbd->cb; - const unsigned char msg[] = { + const uint8_t msg[] = { SIM_PB_REQ_SIM_PB_READ, SIM_PB_READ, 2, /* number of subblocks */ @@ -195,8 +225,8 @@ static void read_next_entry(GIsiClient *client, int location, if (cbd == NULL) goto error; - if (g_isi_request_make(client, msg, sizeof(msg), SIM_TIMEOUT, - read_cb, cbd)) + if (g_isi_client_send(client, msg, sizeof(msg), SIM_TIMEOUT, + notify, cbd, NULL)) return; error: @@ -204,35 +234,28 @@ error: g_free(cbd); } -static gboolean read_resp_cb(GIsiClient *client, - const void *restrict data, size_t len, - uint16_t object, void *opaque) +static void read_resp_cb(const GIsiMessage *msg, void *data) { - const unsigned char *msg = data; - struct isi_cb_data *cbd = opaque; + struct isi_cb_data *cbd = data; + struct ofono_phonebook *pb = cbd->user; + struct pb_data *pbd = ofono_phonebook_get_data(pb); + ofono_phonebook_cb_t cb = cbd->cb; - int location; + uint16_t location; - if (!msg) { - DBG("ISI client error: %d", g_isi_client_error(client)); - goto error; + if (g_isi_msg_error(msg) < 0) { + CALLBACK_WITH_FAILURE(cb, cbd->data); + g_free(cbd); + return; } - location = decode_read_response(data, len, cbd->user); - if (location != -1) { - read_next_entry(client, location, read_resp_cb, cbd); - return TRUE; + if (decode_response(msg, &location, cbd->user)) { + read_next_entry(pbd->client, location, read_resp_cb, cbd); + return; } CALLBACK_WITH_SUCCESS(cb, cbd->data); - goto out; - -error: - CALLBACK_WITH_FAILURE(cb, cbd->data); - -out: g_free(cbd); - return TRUE; } static void isi_export_entries(struct ofono_phonebook *pb, const char *storage, @@ -240,7 +263,7 @@ static void isi_export_entries(struct ofono_phonebook *pb, const char *storage, { struct pb_data *pbd = ofono_phonebook_get_data(pb); struct isi_cb_data *cbd = isi_cb_data_new(pb, cb, data); - const unsigned char msg[] = { + const uint8_t msg[] = { SIM_PB_REQ_SIM_PB_READ, SIM_PB_READ, 2, /* number of subblocks */ @@ -259,65 +282,41 @@ static void isi_export_entries(struct ofono_phonebook *pb, const char *storage, 0, 0 /* filler */ }; - if (cbd == NULL || pbd == NULL) - goto error; - - if (strcmp(storage, "SM")) + if (cbd == NULL || pbd == NULL || strcmp(storage, "SM") != 0) goto error; - if (g_isi_request_make(pbd->client, msg, sizeof(msg), SIM_TIMEOUT, - read_resp_cb, cbd)) + if (g_isi_client_send(pbd->client, msg, sizeof(msg), SIM_TIMEOUT, + read_resp_cb, cbd, NULL)) return; error: - if (cbd) - g_free(cbd); - CALLBACK_WITH_FAILURE(cb, data); + g_free(cbd); } -static gboolean isi_phonebook_register(gpointer user) -{ - struct ofono_phonebook *pb = user; - - ofono_phonebook_register(pb); - - return FALSE; -} - -static void reachable_cb(GIsiClient *client, gboolean alive, uint16_t object, - void *opaque) +static void reachable_cb(const GIsiMessage *msg, void *data) { - struct ofono_phonebook *pb = opaque; - const char *debug = NULL; + struct ofono_phonebook *pb = data; - if (!alive) { - DBG("Unable to bootstrap phonebook driver"); + if (g_isi_msg_error(msg) < 0) return; - } - DBG("%s (v%03d.%03d) reachable", - pn_resource_name(g_isi_client_resource(client)), - g_isi_version_major(client), - g_isi_version_minor(client)); + ISI_VERSION_DBG(msg); - debug = getenv("OFONO_ISI_DEBUG"); - if (debug && (strcmp(debug, "all") == 0 || strcmp(debug, "sim") == 0)) - g_isi_client_set_debug(client, sim_debug, NULL); - - g_idle_add(isi_phonebook_register, pb); + ofono_phonebook_register(pb); } static int isi_phonebook_probe(struct ofono_phonebook *pb, unsigned int vendor, void *user) { - GIsiModem *idx = user; - struct pb_data *data = g_try_new0(struct pb_data, 1); + GIsiModem *modem = user; + struct pb_data *data; + data = g_try_new0(struct pb_data, 1); if (data == NULL) return -ENOMEM; - data->client = g_isi_client_create(idx, PN_SIM); + data->client = g_isi_client_create(modem, PN_SIM); if (data->client == NULL) { g_free(data); return -ENOMEM; @@ -325,8 +324,7 @@ static int isi_phonebook_probe(struct ofono_phonebook *pb, unsigned int vendor, ofono_phonebook_set_data(pb, data); - if (!g_isi_verify(data->client, reachable_cb, pb)) - DBG("Unable to verify reachability"); + g_isi_client_verify(data->client, reachable_cb, pb, NULL); return 0; } @@ -335,10 +333,11 @@ static void isi_phonebook_remove(struct ofono_phonebook *pb) { struct pb_data *data = ofono_phonebook_get_data(pb); + ofono_phonebook_set_data(pb, NULL); + if (data == NULL) return; - ofono_phonebook_set_data(pb, NULL); g_isi_client_destroy(data->client); g_free(data); } |