From a7a0cb1ed04bb75c8ee29f990fb818b806ace825 Mon Sep 17 00:00:00 2001 From: Andrzej Zaborowski Date: Thu, 3 Feb 2011 08:37:37 +0100 Subject: [PATCH] simfs: implement ofono_sim_context api --- src/call-forwarding.c | 16 +++++-- src/cbs.c | 14 ++++-- src/message-waiting.c | 37 +++++++++++----- src/network.c | 18 ++++++-- src/sim.c | 82 +++++++++++++++++++--------------- src/simfs.c | 100 +++++++++++++++++++++++++++++++++++++++--- src/simfs.h | 9 ++-- src/voicecall.c | 13 +++++- 8 files changed, 221 insertions(+), 68 deletions(-) diff --git a/src/call-forwarding.c b/src/call-forwarding.c index d300c699..ca6dad9e 100644 --- a/src/call-forwarding.c +++ b/src/call-forwarding.c @@ -61,6 +61,7 @@ struct ofono_call_forwarding { int query_end; struct cf_ss_request *ss_req; struct ofono_sim *sim; + struct ofono_sim_context *sim_context; unsigned char cfis_record_id; struct ofono_ussd *ussd; unsigned int ussd_watch; @@ -276,7 +277,7 @@ static void sim_set_cf_indicator(struct ofono_call_forwarding *cf) data[3] = 128; } - ofono_sim_write(cf->sim, SIM_EFCFIS_FILEID, + ofono_sim_write(cf->sim_context, SIM_EFCFIS_FILEID, sim_cfis_update_cb, OFONO_SIM_FILE_STRUCTURE_FIXED, cf->cfis_record_id, data, @@ -287,7 +288,7 @@ static void sim_set_cf_indicator(struct ofono_call_forwarding *cf) if (cf->flags & CALL_FORWARDING_FLAG_CPHS_CFF) { unsigned char cff_voice = cfu_voice ? 0x0A : 0x05; - ofono_sim_write(cf->sim, SIM_EF_CPHS_CFF_FILEID, + ofono_sim_write(cf->sim_context, SIM_EF_CPHS_CFF_FILEID, sim_cphs_cff_update_cb, OFONO_SIM_FILE_STRUCTURE_TRANSPARENT, 0, &cff_voice, sizeof(cff_voice), cf); @@ -1362,11 +1363,11 @@ static void sim_read_cf_indicator(struct ofono_call_forwarding *cf) if (__ofono_sim_service_available(cf->sim, SIM_UST_SERVICE_CFIS, SIM_SST_SERVICE_CFIS) == TRUE) - ofono_sim_read(cf->sim, SIM_EFCFIS_FILEID, + ofono_sim_read(cf->sim_context, SIM_EFCFIS_FILEID, OFONO_SIM_FILE_STRUCTURE_FIXED, sim_cfis_read_cb, cf); else - ofono_sim_read(cf->sim, SIM_EF_CPHS_CFF_FILEID, + ofono_sim_read(cf->sim_context, SIM_EF_CPHS_CFF_FILEID, OFONO_SIM_FILE_STRUCTURE_TRANSPARENT, sim_cphs_cff_read_cb, cf); } @@ -1401,6 +1402,11 @@ static void call_forwarding_unregister(struct ofono_atom *atom) g_dbus_unregister_interface(conn, path, OFONO_CALL_FORWARDING_INTERFACE); + if (cf->sim_context) { + ofono_sim_context_free(cf->sim_context); + cf->sim_context = NULL; + } + if (cf->ussd) cf_unregister_ss_controls(cf); @@ -1499,6 +1505,8 @@ void ofono_call_forwarding_register(struct ofono_call_forwarding *cf) if (sim_atom) { cf->sim = __ofono_atom_get_data(sim_atom); + cf->sim_context = ofono_sim_context_create(cf->sim); + sim_read_cf_indicator(cf); } diff --git a/src/cbs.c b/src/cbs.c index 03baed36..1220d0b9 100644 --- a/src/cbs.c +++ b/src/cbs.c @@ -57,6 +57,7 @@ struct ofono_cbs { GSList *topics; GSList *new_topics; struct ofono_sim *sim; + struct ofono_sim_context *sim_context; struct ofono_stk *stk; struct ofono_netreg *netreg; unsigned int netreg_watch; @@ -605,6 +606,11 @@ static void cbs_unregister(struct ofono_atom *atom) cbs->efcbmid_contents = NULL; } + if (cbs->sim_context) { + ofono_sim_context_free(cbs->sim_context); + cbs->sim_context = NULL; + } + cbs->sim = NULL; cbs->stk = NULL; @@ -908,10 +914,10 @@ static void cbs_got_imsi(struct ofono_cbs *cbs) */ if (topics_str == NULL || (cbs->topics == NULL && topics_str[0] != '\0')) { - ofono_sim_read(cbs->sim, SIM_EFCBMI_FILEID, + ofono_sim_read(cbs->sim_context, SIM_EFCBMI_FILEID, OFONO_SIM_FILE_STRUCTURE_TRANSPARENT, sim_cbmi_read_cb, cbs); - ofono_sim_read(cbs->sim, SIM_EFCBMIR_FILEID, + ofono_sim_read(cbs->sim_context, SIM_EFCBMIR_FILEID, OFONO_SIM_FILE_STRUCTURE_TRANSPARENT, sim_cbmir_read_cb, cbs); } @@ -919,7 +925,7 @@ static void cbs_got_imsi(struct ofono_cbs *cbs) if (topics_str) g_free(topics_str); - ofono_sim_read(cbs->sim, SIM_EFCBMID_FILEID, + ofono_sim_read(cbs->sim_context, SIM_EFCBMID_FILEID, OFONO_SIM_FILE_STRUCTURE_TRANSPARENT, sim_cbmid_read_cb, cbs); } @@ -1067,6 +1073,8 @@ void ofono_cbs_register(struct ofono_cbs *cbs) if (sim_atom) { cbs->sim = __ofono_atom_get_data(sim_atom); + cbs->sim_context = ofono_sim_context_create(cbs->sim); + if (ofono_sim_get_state(cbs->sim) == OFONO_SIM_STATE_READY) cbs_got_imsi(cbs); } diff --git a/src/message-waiting.c b/src/message-waiting.c index 48eecc19..c0293e7b 100644 --- a/src/message-waiting.c +++ b/src/message-waiting.c @@ -55,6 +55,7 @@ struct ofono_message_waiting { gboolean cphs_mbdn_not_provided; struct ofono_phone_number mailbox_number[5]; struct ofono_sim *sim; + struct ofono_sim_context *sim_context; struct ofono_atom *atom; }; @@ -202,7 +203,7 @@ static DBusMessage *set_cphs_mbdn(struct ofono_message_waiting *mw, sim_adn_build(efmbdn, req->mw->ef_cphs_mbdn_length, &req->number, NULL); - if (ofono_sim_write(mw->sim, SIM_EF_CPHS_MBDN_FILEID, + if (ofono_sim_write(mw->sim_context, SIM_EF_CPHS_MBDN_FILEID, sync ? cphs_mbdn_sync_cb : mbdn_set_cb, OFONO_SIM_FILE_STRUCTURE_FIXED, mw_mailbox_to_cphs_record[mailbox], @@ -300,10 +301,10 @@ static DBusMessage *set_mbdn(struct ofono_message_waiting *mw, int mailbox, sim_adn_build(efmbdn, req->mw->efmbdn_length, &req->number, NULL); - if (ofono_sim_write(req->mw->sim, SIM_EFMBDN_FILEID, mbdn_set_cb, - OFONO_SIM_FILE_STRUCTURE_FIXED, - req->mw->efmbdn_record_id[mailbox], - efmbdn, req->mw->efmbdn_length, req) == -1) { + if (ofono_sim_write(req->mw->sim_context, SIM_EFMBDN_FILEID, + mbdn_set_cb, OFONO_SIM_FILE_STRUCTURE_FIXED, + req->mw->efmbdn_record_id[mailbox], + efmbdn, req->mw->efmbdn_length, req) == -1) { g_free(req); if (msg) @@ -600,7 +601,7 @@ static void mw_mbi_read_cb(int ok, int total_length, int record, for (i = 0; i < 5 && i < record_length; i++) mw->efmbdn_record_id[i] = data[i]; - err = ofono_sim_read(mw->sim, SIM_EFMBDN_FILEID, + err = ofono_sim_read(mw->sim_context, SIM_EFMBDN_FILEID, OFONO_SIM_FILE_STRUCTURE_FIXED, mw_mbdn_read_cb, mw); @@ -615,7 +616,7 @@ out: st = ofono_sim_get_cphs_service_table(mw->sim); if (st && bit_field(st[0], 4, 2) == 3) - ofono_sim_read(mw->sim, SIM_EF_CPHS_MBDN_FILEID, + ofono_sim_read(mw->sim_context, SIM_EF_CPHS_MBDN_FILEID, OFONO_SIM_FILE_STRUCTURE_FIXED, mw_cphs_mbdn_read_cb, mw); } @@ -689,7 +690,8 @@ static void mw_set_indicator(struct ofono_message_waiting *mw, int profile, if (mw->messages[i].indication) efmwis[0] |= 1 << i; - if (ofono_sim_write(mw->sim, SIM_EFMWIS_FILEID, mw_mwis_write_cb, + if (ofono_sim_write(mw->sim_context, SIM_EFMWIS_FILEID, + mw_mwis_write_cb, OFONO_SIM_FILE_STRUCTURE_FIXED, 1, efmwis, mw->efmwis_length, mw) != 0) { ofono_error("Queuing a EF-MWI write to SIM failed"); @@ -707,7 +709,8 @@ try_cphs: efmwis[1] = mw->messages[1].indication ? 0xa : 0x5 | mw->messages[3].indication ? 0xa0 : 0x50; - if (ofono_sim_write(mw->sim, SIM_EF_CPHS_MWIS_FILEID, mw_mwis_write_cb, + if (ofono_sim_write(mw->sim_context, SIM_EF_CPHS_MWIS_FILEID, + mw_mwis_write_cb, OFONO_SIM_FILE_STRUCTURE_TRANSPARENT, 0, efmwis, mw->ef_cphs_mwis_length, mw) != 0) ofono_error("Queuing a EF-MWIS write to SIM failed (CPHS)"); @@ -918,6 +921,14 @@ static void message_waiting_unregister(struct ofono_atom *atom) DBusConnection *conn = ofono_dbus_get_connection(); struct ofono_modem *modem = __ofono_atom_get_modem(atom); const char *path = __ofono_atom_get_path(atom); + struct ofono_message_waiting *mw = __ofono_atom_get_data(atom); + + if (mw->sim_context) { + ofono_sim_context_free(mw->sim_context); + mw->sim_context = NULL; + } + + mw->sim = NULL; g_dbus_unregister_interface(conn, path, OFONO_MESSAGE_WAITING_INTERFACE); @@ -956,16 +967,18 @@ void ofono_message_waiting_register(struct ofono_message_waiting *mw) /* Assume that if sim atom exists, it is ready */ mw->sim = __ofono_atom_get_data(sim_atom); + mw->sim_context = ofono_sim_context_create(mw->sim); + /* Loads MWI states and MBDN from SIM */ - ofono_sim_read(mw->sim, SIM_EFMWIS_FILEID, + ofono_sim_read(mw->sim_context, SIM_EFMWIS_FILEID, OFONO_SIM_FILE_STRUCTURE_FIXED, mw_mwis_read_cb, mw); - ofono_sim_read(mw->sim, SIM_EFMBI_FILEID, + ofono_sim_read(mw->sim_context, SIM_EFMBI_FILEID, OFONO_SIM_FILE_STRUCTURE_FIXED, mw_mbi_read_cb, mw); /* Also read CPHS MWIS field */ - ofono_sim_read(mw->sim, SIM_EF_CPHS_MWIS_FILEID, + ofono_sim_read(mw->sim_context, SIM_EF_CPHS_MWIS_FILEID, OFONO_SIM_FILE_STRUCTURE_TRANSPARENT, mw_cphs_mwis_read_cb, mw); } diff --git a/src/network.c b/src/network.c index bf614724..d94f6961 100644 --- a/src/network.c +++ b/src/network.c @@ -75,6 +75,7 @@ struct ofono_netreg { struct sim_spdi *spdi; struct sim_eons *eons; struct ofono_sim *sim; + struct ofono_sim_context *sim_context; GKeyFile *settings; char *imsi; struct ofono_watchlist *status_watches; @@ -1471,7 +1472,7 @@ check: * is present. */ if (netreg->eons && !sim_eons_pnn_is_empty(netreg->eons)) - ofono_sim_read(netreg->sim, SIM_EFOPL_FILEID, + ofono_sim_read(netreg->sim_context, SIM_EFOPL_FILEID, OFONO_SIM_FILE_STRUCTURE_FIXED, sim_opl_read_cb, netreg); } @@ -1550,7 +1551,7 @@ static void sim_spn_read_cb(int ok, int length, int record, } netreg->spname = spn; - ofono_sim_read(netreg->sim, SIM_EFSPDI_FILEID, + ofono_sim_read(netreg->sim_context, SIM_EFSPDI_FILEID, OFONO_SIM_FILE_STRUCTURE_TRANSPARENT, sim_spdi_read_cb, netreg); @@ -1684,6 +1685,13 @@ static void netreg_unregister(struct ofono_atom *atom) netreg->settings = NULL; } + if (netreg->sim_context) { + ofono_sim_context_free(netreg->sim_context); + netreg->sim_context = NULL; + } + + netreg->sim = NULL; + g_dbus_unregister_interface(conn, path, OFONO_NETWORK_REGISTRATION_INTERFACE); ofono_modem_remove_interface(modem, @@ -1808,12 +1816,14 @@ void ofono_netreg_register(struct ofono_netreg *netreg) /* Assume that if sim atom exists, it is ready */ netreg->sim = __ofono_atom_get_data(sim_atom); + netreg->sim_context = ofono_sim_context_create(netreg->sim); + netreg_load_settings(netreg); - ofono_sim_read(netreg->sim, SIM_EFPNN_FILEID, + ofono_sim_read(netreg->sim_context, SIM_EFPNN_FILEID, OFONO_SIM_FILE_STRUCTURE_FIXED, sim_pnn_read_cb, netreg); - ofono_sim_read(netreg->sim, SIM_EFSPN_FILEID, + ofono_sim_read(netreg->sim_context, SIM_EFSPN_FILEID, OFONO_SIM_FILE_STRUCTURE_TRANSPARENT, sim_spn_read_cb, netreg); } diff --git a/src/sim.c b/src/sim.c index 41d7e1d0..52261c86 100644 --- a/src/sim.c +++ b/src/sim.c @@ -96,6 +96,7 @@ struct ofono_sim { struct ofono_watchlist *state_watches; struct sim_fs *simfs; + struct ofono_sim_context *context; unsigned char *iidf_image; @@ -495,7 +496,7 @@ static gboolean set_own_numbers(struct ofono_sim *sim, efmsisdn[sim->efmsisdn_length - 14] = 1; } - if (ofono_sim_write(req->sim, SIM_EFMSISDN_FILEID, + if (ofono_sim_write(req->sim->context, SIM_EFMSISDN_FILEID, msisdn_set_cb, OFONO_SIM_FILE_STRUCTURE_FIXED, record, efmsisdn, sim->efmsisdn_length, req) == 0) @@ -923,7 +924,7 @@ static void sim_iidf_read_cb(int ok, int length, int record, sim->iidf_image = g_memdup(data, length); /* read the clut data */ - ofono_sim_read_bytes(sim, iidf_id, offset, clut_len, + ofono_sim_read_bytes(sim->context, iidf_id, offset, clut_len, sim_iidf_read_clut_cb, sim); } @@ -955,7 +956,7 @@ static void sim_get_image(struct ofono_sim *sim, unsigned char id, iidf_len = efimg[7] << 8 | efimg[8]; /* read the image data */ - ofono_sim_read_bytes(sim, iidf_id, iidf_offset, iidf_len, + ofono_sim_read_bytes(sim->context, iidf_id, iidf_offset, iidf_len, sim_iidf_read_cb, sim); } @@ -1212,8 +1213,9 @@ check: static void sim_own_numbers_update(struct ofono_sim *sim) { - ofono_sim_read(sim, SIM_EFMSISDN_FILEID, OFONO_SIM_FILE_STRUCTURE_FIXED, - sim_msisdn_read_cb, sim); + ofono_sim_read(sim->context, SIM_EFMSISDN_FILEID, + OFONO_SIM_FILE_STRUCTURE_FIXED, sim_msisdn_read_cb, + sim); } static void sim_efimg_read_cb(int ok, int length, int record, @@ -1266,10 +1268,10 @@ static void sim_ready(enum ofono_sim_state new_state, void *user) sim_own_numbers_update(sim); - ofono_sim_read(sim, SIM_EFSDN_FILEID, OFONO_SIM_FILE_STRUCTURE_FIXED, - sim_sdn_read_cb, sim); - ofono_sim_read(sim, SIM_EFIMG_FILEID, OFONO_SIM_FILE_STRUCTURE_FIXED, - sim_efimg_read_cb, sim); + ofono_sim_read(sim->context, SIM_EFSDN_FILEID, + OFONO_SIM_FILE_STRUCTURE_FIXED, sim_sdn_read_cb, sim); + ofono_sim_read(sim->context, SIM_EFIMG_FILEID, + OFONO_SIM_FILE_STRUCTURE_FIXED, sim_efimg_read_cb, sim); } static void sim_imsi_cb(const struct ofono_error *error, const char *imsi, @@ -1385,7 +1387,7 @@ static gboolean check_bdn_status(struct ofono_sim *sim) */ if (sim_sst_is_active(sim->efsst, sim->efsst_length, SIM_SST_SERVICE_BDN)) { - sim_fs_read_info(sim->simfs, SIM_EFBDN_FILEID, + sim_fs_read_info(sim->context, SIM_EFBDN_FILEID, OFONO_SIM_FILE_STRUCTURE_FIXED, sim_efbdn_info_read_cb, sim); return TRUE; @@ -1439,7 +1441,7 @@ static void sim_efsst_read_cb(int ok, int length, int record, */ if (sim_sst_is_active(sim->efsst, sim->efsst_length, SIM_SST_SERVICE_FDN)) { - sim_fs_read_info(sim->simfs, SIM_EFADN_FILEID, + sim_fs_read_info(sim->context, SIM_EFADN_FILEID, OFONO_SIM_FILE_STRUCTURE_FIXED, sim_efadn_info_read_cb, sim); return; @@ -1529,7 +1531,7 @@ static void sim_efust_read_cb(int ok, int length, int record, SIM_UST_SERVICE_FDN) || sim_ust_is_available(sim->efust, sim->efust_length, SIM_UST_SERVICE_BDN)) { - ofono_sim_read(sim, SIM_EFEST_FILEID, + ofono_sim_read(sim->context, SIM_EFEST_FILEID, OFONO_SIM_FILE_STRUCTURE_TRANSPARENT, sim_efest_read_cb, sim); @@ -1590,7 +1592,7 @@ static void sim_efphase_read_cb(int ok, int length, int record, if (!ok || length != 1) { sim->phase = OFONO_SIM_PHASE_3G; - ofono_sim_read(sim, SIM_EFUST_FILEID, + ofono_sim_read(sim->context, SIM_EFUST_FILEID, OFONO_SIM_FILE_STRUCTURE_TRANSPARENT, sim_efust_read_cb, sim); @@ -1612,18 +1614,18 @@ static void sim_efphase_read_cb(int ok, int length, int record, return; } - ofono_sim_read(sim, SIM_EFSST_FILEID, + ofono_sim_read(sim->context, SIM_EFSST_FILEID, OFONO_SIM_FILE_STRUCTURE_TRANSPARENT, sim_efsst_read_cb, sim); } static void sim_initialize_after_pin(struct ofono_sim *sim) { - ofono_sim_read(sim, SIM_EFPHASE_FILEID, + ofono_sim_read(sim->context, SIM_EFPHASE_FILEID, OFONO_SIM_FILE_STRUCTURE_TRANSPARENT, sim_efphase_read_cb, sim); - ofono_sim_read(sim, SIM_EFAD_FILEID, + ofono_sim_read(sim->context, SIM_EFAD_FILEID, OFONO_SIM_FILE_STRUCTURE_TRANSPARENT, sim_ad_read_cb, sim); @@ -1631,7 +1633,7 @@ static void sim_initialize_after_pin(struct ofono_sim *sim) * Read CPHS-support bits, this is still part of the SIM * initialisation but no order is specified for it. */ - ofono_sim_read(sim, SIM_EF_CPHS_INFORMATION_FILEID, + ofono_sim_read(sim->context, SIM_EF_CPHS_INFORMATION_FILEID, OFONO_SIM_FILE_STRUCTURE_TRANSPARENT, sim_cphs_information_read_cb, sim); } @@ -1923,7 +1925,7 @@ static void sim_initialize(struct ofono_sim *sim) */ /* Grab the EFiccid which is always available */ - ofono_sim_read(sim, SIM_EF_ICCID_FILEID, + ofono_sim_read(sim->context, SIM_EF_ICCID_FILEID, OFONO_SIM_FILE_STRUCTURE_TRANSPARENT, sim_iccid_read_cb, sim); @@ -1937,47 +1939,51 @@ static void sim_initialize(struct ofono_sim *sim) * However we don't depend on the user interface and so * need to read both files now. */ - ofono_sim_read(sim, SIM_EFLI_FILEID, + ofono_sim_read(sim->context, SIM_EFLI_FILEID, OFONO_SIM_FILE_STRUCTURE_TRANSPARENT, sim_efli_read_cb, sim); - ofono_sim_read(sim, SIM_EFPL_FILEID, + ofono_sim_read(sim->context, SIM_EFPL_FILEID, OFONO_SIM_FILE_STRUCTURE_TRANSPARENT, sim_efpl_read_cb, sim); } -int ofono_sim_read_bytes(struct ofono_sim *sim, int id, +struct ofono_sim_context *ofono_sim_context_create(struct ofono_sim *sim) +{ + if (sim == NULL || sim->simfs == NULL) + return NULL; + + return sim_fs_context_new(sim->simfs); +} + +void ofono_sim_context_free(struct ofono_sim_context *context) +{ + return sim_fs_context_free(context); +} + +int ofono_sim_read_bytes(struct ofono_sim_context *context, int id, unsigned short offset, unsigned short num_bytes, ofono_sim_file_read_cb_t cb, void *data) { - if (sim == NULL) - return -1; - if (num_bytes == 0) return -1; - return sim_fs_read(sim->simfs, id, OFONO_SIM_FILE_STRUCTURE_TRANSPARENT, + return sim_fs_read(context, id, OFONO_SIM_FILE_STRUCTURE_TRANSPARENT, offset, num_bytes, cb, data); } -int ofono_sim_read(struct ofono_sim *sim, int id, +int ofono_sim_read(struct ofono_sim_context *context, int id, enum ofono_sim_file_structure expected_type, ofono_sim_file_read_cb_t cb, void *data) { - if (sim == NULL) - return -1; - - return sim_fs_read(sim->simfs, id, expected_type, 0, 0, cb, data); + return sim_fs_read(context, id, expected_type, 0, 0, cb, data); } -int ofono_sim_write(struct ofono_sim *sim, int id, +int ofono_sim_write(struct ofono_sim_context *context, int id, ofono_sim_file_write_cb_t cb, enum ofono_sim_file_structure structure, int record, const unsigned char *data, int length, void *userdata) { - if (sim == NULL) - return -1; - - return sim_fs_write(sim->simfs, id, cb, structure, record, data, length, + return sim_fs_write(context, id, cb, structure, record, data, length, userdata); } @@ -2264,6 +2270,11 @@ static void sim_remove(struct ofono_atom *atom) sim_free_state(sim); + if (sim->context) { + ofono_sim_context_free(sim->context); + sim->context = NULL; + } + sim_fs_free(sim->simfs); sim->simfs = NULL; @@ -2329,6 +2340,7 @@ void ofono_sim_register(struct ofono_sim *sim) ofono_modem_add_interface(modem, OFONO_SIM_MANAGER_INTERFACE); sim->state_watches = __ofono_watchlist_new(g_free); sim->simfs = sim_fs_new(sim, sim->driver); + sim->context = ofono_sim_context_create(sim); __ofono_atom_register(sim->atom, sim_unregister); diff --git a/src/simfs.c b/src/simfs.c index 6c0008a4..04594477 100644 --- a/src/simfs.c +++ b/src/simfs.c @@ -69,6 +69,7 @@ struct sim_fs_op { gconstpointer cb; gboolean is_read; void *userdata; + struct ofono_sim_context *context; }; static void sim_fs_op_free(struct sim_fs_op *node) @@ -108,6 +109,10 @@ void sim_fs_free(struct sim_fs *fs) g_free(fs); } +struct ofono_sim_context { + struct sim_fs *fs; +}; + struct sim_fs *sim_fs_new(struct ofono_sim *sim, const struct ofono_sim_driver *driver) { @@ -124,6 +129,44 @@ struct sim_fs *sim_fs_new(struct ofono_sim *sim, return fs; } +struct ofono_sim_context *sim_fs_context_new(struct sim_fs *fs) +{ + struct ofono_sim_context *context = + g_try_new0(struct ofono_sim_context, 1); + + if (context == NULL) + return NULL; + + context->fs = fs; + + return context; +} + +void sim_fs_context_free(struct ofono_sim_context *context) +{ + int n = 0; + struct sim_fs_op *op; + + while ((op = g_queue_peek_nth(context->fs->op_q, n)) != NULL) { + if (op->context != context) { + n += 1; + continue; + } + + if (n == 0) { + op->cb = NULL; + + n += 1; + continue; + } + + sim_fs_op_free(op); + g_queue_remove(context->fs->op_q, op); + } + + g_free(context); +} + static void sim_fs_end_current(struct sim_fs *fs) { struct sim_fs_op *op = g_queue_pop_head(fs->op_q); @@ -145,6 +188,11 @@ static void sim_fs_op_error(struct sim_fs *fs) { struct sim_fs_op *op = g_queue_peek_head(fs->op_q); + if (op->cb == NULL) { + sim_fs_end_current(fs); + return; + } + if (op->info_only == TRUE) ((sim_fs_read_info_cb_t) op->cb) (0, 0, 0, 0, op->userdata); @@ -204,6 +252,11 @@ static void sim_fs_op_write_cb(const struct ofono_error *error, void *data) struct sim_fs_op *op = g_queue_peek_head(fs->op_q); ofono_sim_file_write_cb_t cb = op->cb; + if (cb == NULL) { + sim_fs_end_current(fs); + return; + } + if (error->type == OFONO_ERROR_TYPE_NO_ERROR) cb(1, op->userdata); else @@ -250,6 +303,11 @@ static void sim_fs_op_read_block_cb(const struct ofono_error *error, memcpy(op->buffer + bufoff, data + dataoff, tocopy); cache_block(fs, op->current, 256, data, len); + if (op->cb == NULL) { + sim_fs_end_current(fs); + return; + } + op->current++; if (op->current > end_block) { @@ -274,6 +332,11 @@ static gboolean sim_fs_op_read_block(gpointer user_data) fs->op_source = 0; + if (op->cb == NULL) { + sim_fs_end_current(fs); + return FALSE; + } + start_block = op->offset / 256; end_block = (op->offset + (op->num_bytes - 1)) / 256; @@ -360,11 +423,16 @@ static void sim_fs_op_retrieve_cb(const struct ofono_error *error, return; } - cb(1, op->length, op->current, data, op->record_length, op->userdata); - cache_block(fs, op->current - 1, op->record_length, data, op->record_length); + if (cb == NULL) { + sim_fs_end_current(fs); + return; + } + + cb(1, op->length, op->current, data, op->record_length, op->userdata); + if (op->current < total) { op->current += 1; fs->op_source = g_idle_add(sim_fs_op_read_record, fs); @@ -383,6 +451,11 @@ static gboolean sim_fs_op_read_record(gpointer user) fs->op_source = 0; + if (op->cb == NULL) { + sim_fs_end_current(fs); + return FALSE; + } + while (fs->fd != -1 && op->current <= total) { int offset = (op->current - 1) / 8; int bit = 1 << ((op->current - 1) % 8); @@ -523,6 +596,11 @@ static void sim_fs_op_info_cb(const struct ofono_error *error, int length, return; } + if (op->cb == NULL) { + sim_fs_end_current(fs); + return; + } + op->structure = structure; op->length = length; @@ -663,6 +741,11 @@ static gboolean sim_fs_op_next(gpointer user_data) op = g_queue_peek_head(fs->op_q); + if (op->cb == NULL) { + sim_fs_end_current(fs); + return FALSE; + } + if (op->is_read == TRUE) { if (sim_fs_op_check_cached(fs)) return FALSE; @@ -697,10 +780,11 @@ static gboolean sim_fs_op_next(gpointer user_data) return FALSE; } -int sim_fs_read_info(struct sim_fs *fs, int id, +int sim_fs_read_info(struct ofono_sim_context *context, int id, enum ofono_sim_file_structure expected_type, sim_fs_read_info_cb_t cb, void *data) { + struct sim_fs *fs = context->fs; struct sim_fs_op *op; if (cb == NULL) @@ -725,6 +809,7 @@ int sim_fs_read_info(struct sim_fs *fs, int id, op->userdata = data; op->is_read = TRUE; op->info_only = TRUE; + op->context = context; g_queue_push_tail(fs->op_q, op); @@ -734,11 +819,12 @@ int sim_fs_read_info(struct sim_fs *fs, int id, return 0; } -int sim_fs_read(struct sim_fs *fs, int id, +int sim_fs_read(struct ofono_sim_context *context, int id, enum ofono_sim_file_structure expected_type, unsigned short offset, unsigned short num_bytes, ofono_sim_file_read_cb_t cb, void *data) { + struct sim_fs *fs = context->fs; struct sim_fs_op *op; if (cb == NULL) @@ -765,6 +851,7 @@ int sim_fs_read(struct sim_fs *fs, int id, op->offset = offset; op->num_bytes = num_bytes; op->info_only = FALSE; + op->context = context; g_queue_push_tail(fs->op_q, op); @@ -774,10 +861,12 @@ int sim_fs_read(struct sim_fs *fs, int id, return 0; } -int sim_fs_write(struct sim_fs *fs, int id, ofono_sim_file_write_cb_t cb, +int sim_fs_write(struct ofono_sim_context *context, int id, + ofono_sim_file_write_cb_t cb, enum ofono_sim_file_structure structure, int record, const unsigned char *data, int length, void *userdata) { + struct sim_fs *fs = context->fs; struct sim_fs_op *op; gconstpointer fn = NULL; @@ -819,6 +908,7 @@ int sim_fs_write(struct sim_fs *fs, int id, ofono_sim_file_write_cb_t cb, op->structure = structure; op->length = length; op->current = record; + op->context = context; g_queue_push_tail(fs->op_q, op); diff --git a/src/simfs.h b/src/simfs.h index 8c6f7610..d93d96e8 100644 --- a/src/simfs.h +++ b/src/simfs.h @@ -27,19 +27,21 @@ typedef void (*sim_fs_read_info_cb_t)(int ok, unsigned char file_status, struct sim_fs *sim_fs_new(struct ofono_sim *sim, const struct ofono_sim_driver *driver); +struct ofono_sim_context *sim_fs_context_new(struct sim_fs *fs); -int sim_fs_read(struct sim_fs *fs, int id, +int sim_fs_read(struct ofono_sim_context *context, int id, enum ofono_sim_file_structure expected_type, unsigned short offset, unsigned short num_bytes, ofono_sim_file_read_cb_t cb, void *data); -int sim_fs_read_info(struct sim_fs *fs, int id, +int sim_fs_read_info(struct ofono_sim_context *context, int id, enum ofono_sim_file_structure expected_type, sim_fs_read_info_cb_t cb, void *data); void sim_fs_check_version(struct sim_fs *fs); -int sim_fs_write(struct sim_fs *fs, int id, ofono_sim_file_write_cb_t cb, +int sim_fs_write(struct ofono_sim_context *context, int id, + ofono_sim_file_write_cb_t cb, enum ofono_sim_file_structure structure, int record, const unsigned char *data, int length, void *userdata); @@ -53,3 +55,4 @@ void sim_fs_image_cache_flush(struct sim_fs *fs); void sim_fs_image_cache_flush_file(struct sim_fs *fs, int id); void sim_fs_free(struct sim_fs *fs); +void sim_fs_context_free(struct ofono_sim_context *context); diff --git a/src/voicecall.c b/src/voicecall.c index 62467871..7632c0db 100644 --- a/src/voicecall.c +++ b/src/voicecall.c @@ -50,6 +50,7 @@ struct ofono_voicecall { GSList *new_en_list; /* Emergency numbers being read from SIM */ DBusMessage *pending; struct ofono_sim *sim; + struct ofono_sim_context *sim_context; unsigned int sim_watch; unsigned int sim_state_watch; const struct ofono_voicecall_driver *driver; @@ -2284,17 +2285,25 @@ static void sim_state_watch(enum ofono_sim_state new_state, void *user) switch (new_state) { case OFONO_SIM_STATE_INSERTED: + if (vc->sim_context == NULL) + vc->sim_context = ofono_sim_context_create(vc->sim); + /* Try both formats, only one or none will work */ - ofono_sim_read(vc->sim, SIM_EFECC_FILEID, + ofono_sim_read(vc->sim_context, SIM_EFECC_FILEID, OFONO_SIM_FILE_STRUCTURE_TRANSPARENT, ecc_g2_read_cb, vc); - ofono_sim_read(vc->sim, SIM_EFECC_FILEID, + ofono_sim_read(vc->sim_context, SIM_EFECC_FILEID, OFONO_SIM_FILE_STRUCTURE_FIXED, ecc_g3_read_cb, vc); break; case OFONO_SIM_STATE_NOT_PRESENT: /* TODO: Must release all non-emergency calls */ + if (vc->sim_context) { + ofono_sim_context_free(vc->sim_context); + vc->sim_context = NULL; + } + /* * Free the currently being read EN list, just in case the * SIM is removed when we're still reading them