From: Denis Kenzior <denkenz@gmail.com>
To: ofono@ofono.org
Subject: Re: [PATCH 4/6] sim: read EFiidf
Date: Wed, 25 Aug 2010 16:17:13 -0500 [thread overview]
Message-ID: <4C758859.5060001@gmail.com> (raw)
In-Reply-To: <1282734025-3375-5-git-send-email-kristen@linux.intel.com>
[-- Attachment #1: Type: text/plain, Size: 9714 bytes --]
Hi Kristen,
On 08/25/2010 06:00 AM, Kristen Carlson Accardi wrote:
> EFiidf can be larger than 256 bytes, so allow callers to read
> portions of the EFiidf from a specified offset. Cache EFiidf
> files as blocks of 256 bytes so that it's not necessary to
> read the entire (potentially large) file.
> ---
> src/sim.c | 201 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
> 1 files changed, 198 insertions(+), 3 deletions(-)
>
> diff --git a/src/sim.c b/src/sim.c
> index b273bdb..a9557fc 100644
> --- a/src/sim.c
> +++ b/src/sim.c
> @@ -47,6 +47,7 @@
> #define SIM_CACHE_PATH STORAGEDIR "/%s-%i/%04x"
> #define SIM_CACHE_PATH_LEN(imsilen) (strlen(SIM_CACHE_PATH) - 3 + imsilen)
> #define SIM_CACHE_HEADER_SIZE 6
> +#define SIM_IIDF_CACHE_PATH SIM_CACHE_PATH ".%02x"
>
> static GSList *g_drivers = NULL;
>
> @@ -55,16 +56,20 @@ static gboolean sim_op_retrieve_next(gpointer user);
> static void sim_own_numbers_update(struct ofono_sim *sim);
> static void sim_pin_check(struct ofono_sim *sim);
> static void sim_set_ready(struct ofono_sim *sim);
> +static gboolean sim_op_read_block(gpointer user_data);
>
> struct sim_file_op {
> int id;
> gboolean cache;
> enum ofono_sim_file_structure structure;
> + unsigned short offset;
> + int num_bytes;
> int length;
> int record_length;
> int current;
> gconstpointer cb;
> gboolean is_read;
> + gboolean is_image;
> void *buffer;
> void *userdata;
> };
> @@ -1666,9 +1671,13 @@ static void sim_op_info_cb(const struct ofono_error *error, int length,
> else
> op->record_length = record_length;
>
> - op->current = 1;
>
> - sim->simop_source = g_timeout_add(0, sim_op_retrieve_next, sim);
> + if (op->is_image)
> + sim->simop_source = g_timeout_add(0, sim_op_read_block, sim);
> + else {
> + op->current = 1;
> + sim->simop_source = g_timeout_add(0, sim_op_retrieve_next, sim);
> + }
>
> if (op->cache && imsi) {
> unsigned char fileinfo[6];
> @@ -1750,6 +1759,12 @@ static gboolean sim_op_check_cached(struct ofono_sim *sim)
> structure = fileinfo[3];
> record_length = (fileinfo[4] << 8) | fileinfo[5];
>
> + if (op->is_image) {
> + op->length = file_length;
> + ret = TRUE;
> + goto cleanup;
> + }
> +
> if (structure == OFONO_SIM_FILE_STRUCTURE_TRANSPARENT)
> record_length = file_length;
>
> @@ -1789,6 +1804,170 @@ cleanup:
> return ret;
> }
>
> +static void sim_op_read_block_cb(const struct ofono_error *error,
> + const unsigned char *data, int len, void *user)
> +{
> + struct ofono_sim *sim = user;
> + struct sim_file_op *op = g_queue_peek_head(sim->simop_q);
> + int start_block, end_block;
> + int start, length;
> + unsigned char *buf;
> +
> + if ((error->type != OFONO_ERROR_TYPE_NO_ERROR) || (len == 0)) {
> + sim_op_error(sim);
> + return;
> + }
> +
> + /* cache this block */
> + write_file(data, len, SIM_CACHE_MODE, SIM_IIDF_CACHE_PATH,
> + sim->imsi, sim->phase, op->id, op->current);
> +
> + /* buffer this block */
> + start_block = op->offset / 256;
> + end_block = (op->offset + (op->num_bytes - 1)) / 256;
> +
> + if (op->current == start_block) {
> + start = op->offset % 256;
> + buf = op->buffer;
> + } else {
> + start = 0;
> + buf = op->buffer + (op->current * 256);
> + }
> +
> + length = op->num_bytes % 256;
> +
> + if ((length == 0) || (op->current != end_block))
> + length = 256;
> +
> + memcpy(buf, &data[start], length);
> +
> + op->current++;
> +
> + sim->simop_source = g_timeout_add(0, sim_op_read_block, sim);
> +}
> +
> +static gboolean sim_op_check_cached_block(struct ofono_sim *sim)
> +{
> + struct sim_file_op *op = g_queue_peek_head(sim->simop_q);
> + char *path;
> + int fd;
> + char *imsi = sim->imsi;
> + int start_block, end_block;
> + int start, length, len;
> + unsigned char *buf;
> +
> + if (!imsi)
> + return FALSE;
> +
> + path = g_strdup_printf(SIM_IIDF_CACHE_PATH, imsi, sim->phase, op->id,
> + op->current);
My initial feeling is that we should treat blocks just like we treat
records today. We should not write them to separate files.
Can we unify the two approaches somehow? Perhaps by storing a bitmap in
the cache header, and update the bitmap every time we write the record /
block to the cache. We can use idmap.c for bitmap management easily
enough...
Andrew you know this part pretty well, what's your opinion?
> +
> + if (path == NULL)
> + return FALSE;
> +
> + fd = TFR(open(path, O_RDONLY));
> + g_free(path);
> +
> + if (fd == -1) {
> + if (errno != ENOENT)
> + DBG("Error %i opening cache file for "
> + "fileid %04x, IMSI %s",
> + errno, op->id, imsi);
> +
> + return FALSE;
> + }
> +
> + /* figure out where we should start reading from */
> + start_block = op->offset / 256;
> + end_block = (op->offset + (op->num_bytes - 1)) / 256;
> +
> + if (op->current == start_block) {
> + start = op->offset % 256;
> + buf = op->buffer;
> + } else {
> + start = 0;
> + buf = op->buffer + (op->current * 256);
> + }
> +
> + length = op->num_bytes % 256;
> +
> + if ((length == 0) || (op->current != end_block))
> + length = 256;
> +
> + /* lseek to the right place in the file */
> + TFR(lseek(fd, start, SEEK_CUR));
> +
> + len = TFR(read(fd, buf, length));
> +
> + if (len != length)
> + return FALSE;
> +
> + op->current++;
> +
> + sim->simop_source = g_timeout_add(0, sim_op_read_block, sim);
> +
> + return TRUE;
> +}
> +
> +static gboolean sim_op_read_block(gpointer user_data)
> +{
> + struct ofono_sim *sim = user_data;
> + struct sim_file_op *op = g_queue_peek_head(sim->simop_q);
> + int end_block;
> + ofono_sim_file_read_cb_t cb = op->cb;
> + int read_bytes;
> +
> + end_block = (op->offset + (op->num_bytes - 1)) / 256;
> +
> + if (op->current > end_block) {
> + cb(1, op->num_bytes, op->current, op->buffer,
> + op->record_length, op->userdata);
> +
> + op = g_queue_pop_head(sim->simop_q);
> +
> + g_free(op->buffer);
> +
> + sim_file_op_free(op);
> +
> + if (g_queue_get_length(sim->simop_q) > 0)
> + sim->simop_source = g_timeout_add(0, sim_op_next, sim);
> +
> + return FALSE;
> + }
> +
> + /* see if this block is cached */
> + if (sim_op_check_cached_block(sim) == TRUE)
> + return FALSE;
> +
> + if (op->length < ((op->current + 1) * 256))
> + read_bytes = op->length % 256;
> + else
> + read_bytes = 256;
> +
> + sim->driver->read_file_transparent(sim, op->id,
> + op->current * 256,
> + read_bytes,
> + sim_op_read_block_cb, sim);
> + return FALSE;
> +}
> +
> +static void sim_op_get_image(struct ofono_sim *sim)
> +{
> + struct sim_file_op *op = g_queue_peek_head(sim->simop_q);
> +
> + /* allocate space to buffer the data till we've collected it all */
> + op->buffer = g_try_malloc0(op->num_bytes);
> +
> + /* initialize current */
> + op->current = op->offset / 256;
> +
> + /* need to get the length of the file */
> + if (sim_op_check_cached(sim) == FALSE)
> + sim->driver->read_file_info(sim, op->id, sim_op_info_cb, sim);
> + else
> + sim->simop_source = g_timeout_add(0, sim_op_read_block, sim);
> +}
> +
> static gboolean sim_op_next(gpointer user_data)
> {
> struct ofono_sim *sim = user_data;
> @@ -1801,6 +1980,11 @@ static gboolean sim_op_next(gpointer user_data)
>
> op = g_queue_peek_head(sim->simop_q);
>
> + if (op->is_image) {
> + sim_op_get_image(sim);
> + return FALSE;
> + }
> +
> if (op->is_read == TRUE) {
> if (sim_op_check_cached(sim)) {
> op = g_queue_pop_head(sim->simop_q);
> @@ -1843,8 +2027,9 @@ static gboolean sim_op_next(gpointer user_data)
> return FALSE;
> }
>
> -int ofono_sim_read(struct ofono_sim *sim, int id,
> +static int ofono_sim_read_bytes(struct ofono_sim *sim, int id,
> enum ofono_sim_file_structure expected_type,
> + unsigned short offset, int num_bytes,
> ofono_sim_file_read_cb_t cb, void *data)
Please don't give static functions an ofono_ prefix. ofono_ prefix is
reserved for public API only. __ofono prefix is reserved for private API.
Lets make this into proper oFono public API and unify 'reading at
offset' and 'reading the entire file' types into a single architecture.
E.g. ofono_sim_read for a transparent file results in us reading all
blocks of that file and caching them. read_bytes only results in us
caching the blocks we read...
Reading of files at a certain offset is only supported for transparent
files, so passing expected_type is not needed.
Something like
ofono_sim_read_bytes(sim, id, offset, num_bytes, cb, data);
> {
> struct sim_file_op *op;
> @@ -1875,6 +2060,9 @@ int ofono_sim_read(struct ofono_sim *sim, int id,
> op->cb = cb;
> op->userdata = data;
> op->is_read = TRUE;
> + op->offset = offset;
> + op->num_bytes = num_bytes;
> + op->is_image = ((((id >> 8) & 0xFF) == 0x4F) && (id != 0x4F20));
Perhaps use num_bytes == -1 for 'read everything' type. Let us drop the
is_image flag completely.
>
> g_queue_push_tail(sim->simop_q, op);
>
> @@ -1884,6 +2072,13 @@ int ofono_sim_read(struct ofono_sim *sim, int id,
> return 0;
> }
>
> +int ofono_sim_read(struct ofono_sim *sim, int id,
> + enum ofono_sim_file_structure expected_type,
> + ofono_sim_file_read_cb_t cb, void *data)
> +{
> + return ofono_sim_read_bytes(sim, id, expected_type, 0, -1, cb, data);
> +}
> +
> int ofono_sim_write(struct ofono_sim *sim, int id,
> ofono_sim_file_write_cb_t cb,
> enum ofono_sim_file_structure structure, int record,
Regards,
-Denis
next prev parent reply other threads:[~2010-08-25 21:17 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-08-25 11:00 [PATCH v2 0/6] icon support patches Kristen Carlson Accardi
2010-08-25 11:00 ` [PATCH 1/6] simutil: add fileid for EFimg Kristen Carlson Accardi
2010-08-25 18:49 ` Denis Kenzior
2010-08-25 11:00 ` [PATCH 2/6] stkutil: change uint32_t to guint32 Kristen Carlson Accardi
2010-08-25 18:49 ` Denis Kenzior
2010-08-25 11:00 ` [PATCH 3/6] sim: read EFimg Kristen Carlson Accardi
2010-08-25 18:52 ` Denis Kenzior
2010-08-25 16:29 ` [PATCH 1/4] " Kristen Carlson Accardi
2010-08-25 23:39 ` Denis Kenzior
2010-08-26 14:20 ` Kristen Carlson Accardi
2010-08-26 23:45 ` Denis Kenzior
2010-08-25 11:00 ` [PATCH 4/6] sim: read EFiidf Kristen Carlson Accardi
2010-08-25 21:17 ` Denis Kenzior [this message]
2010-08-25 22:36 ` Kristen Carlson Accardi
2010-08-25 22:54 ` Denis Kenzior
2010-08-25 11:00 ` [PATCH 5/6] sim: implement GetIcon Kristen Carlson Accardi
2010-08-25 11:00 ` [PATCH 6/6] test: add get-icon script Kristen Carlson Accardi
-- strict thread matches above, loose matches on Subject: below --
2010-08-18 11:25 [PATCH v2 0/6] Icon support Kristen Carlson Accardi
2010-08-18 11:25 ` [PATCH 4/6] sim: read EFiidf Kristen Carlson Accardi
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4C758859.5060001@gmail.com \
--to=denkenz@gmail.com \
--cc=ofono@ofono.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.