From 42c29c795f3e2ece561dc0755df1401eb8037614 Mon Sep 17 00:00:00 2001 From: Kristen Carlson Accardi Date: Mon, 4 Oct 2010 15:33:20 -0700 Subject: [PATCH] sim: implement GetIcon --- src/sim.c | 187 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 187 insertions(+) diff --git a/src/sim.c b/src/sim.c index 6f10d4c3..a671a8da 100644 --- a/src/sim.c +++ b/src/sim.c @@ -43,6 +43,7 @@ #include "simutil.h" #include "storage.h" #include "simfs.h" +#include "stkutil.h" static GSList *g_drivers = NULL; @@ -721,6 +722,190 @@ static DBusMessage *sim_enter_pin(DBusConnection *conn, DBusMessage *msg, return NULL; } +static void sim_get_image_cb(gboolean ok, const char *xpm, int xpm_len, + void *userdata) +{ + struct ofono_sim *sim = userdata; + DBusMessage *reply; + + if (!ok) + reply = __ofono_error_failed(sim->pending); + else { + reply = dbus_message_new_method_return(sim->pending); + dbus_message_append_args(reply, DBUS_TYPE_STRING, &xpm, + DBUS_TYPE_INVALID); + } + + __ofono_dbus_pending_reply(&sim->pending, reply); +} + +struct image_data { + struct ofono_sim *sim; + unsigned char width; + unsigned char height; + enum stk_img_scheme scheme; + unsigned short iidf_id; + unsigned short iidf_offset; + unsigned short iid_len; + void *image; + unsigned short clut_len; + gboolean need_clut; + gpointer user_data; + unsigned char id; +}; + +static void sim_iidf_read_cb(int ok, int length, int record, + const unsigned char *data, + int record_length, void *userdata) +{ + struct image_data *image = userdata; + unsigned short offset; + unsigned short num_entries; + char *xpm; + struct ofono_sim *sim = image->sim; + + if (!ok) { + sim_get_image_cb(ok, NULL, 0, image->user_data); + goto iidf_read_out; + } + + if (image->need_clut == FALSE) { + if (image->scheme == STK_IMG_SCHEME_BASIC) { + xpm = stk_image_to_xpm(data, image->iid_len, + image->scheme, NULL, 0); + } else { + xpm = stk_image_to_xpm(image->image, image->iid_len, + image->scheme, data, + image->clut_len); + } + + if (xpm == NULL) { + sim_get_image_cb(0, NULL, 0, image->user_data); + goto iidf_read_out; + } + + sim_fs_cache_image(sim->simfs, (const char *) xpm, + image->id); + + sim_get_image_cb(ok, xpm, strlen(xpm), image->user_data); + + g_free(xpm); + + goto iidf_read_out; + } + + offset = data[4] << 8 | data[5]; + num_entries = data[3]; + + if (num_entries == 0) + num_entries = 256; + + /* indicate that we're on our second read */ + image->need_clut = FALSE; + + image->clut_len = num_entries * 3; + + image->image = g_memdup(data, length); + + /* read the clut data */ + ofono_sim_read_bytes(image->sim, image->iidf_id, + offset, image->clut_len, + sim_iidf_read_cb, image); + + return; + +iidf_read_out: + g_free(image->image); + g_free(image); +} + +static void sim_get_image(struct ofono_sim *sim, unsigned char id, + gpointer user_data) +{ + struct image_data *data; + unsigned char *efimg; + char *image; + + /* icon ids should start at 1, our array starts at zero */ + if (id == 0) { + sim_get_image_cb(0, NULL, 0, user_data); + return; + } + + id--; + + image = sim_fs_get_cached_image(sim->simfs, id); + + if (image == NULL) + goto read_image; + + sim_get_image_cb(1, image, strlen(image), user_data); + + g_free(image); + + return; + +read_image: + + if (sim->efimg_length <= (id * 9)) { + sim_get_image_cb(0, NULL, 0, user_data); + return; + } + + efimg = &sim->efimg[id * 9]; + + data = g_try_new0(struct image_data, 1); + if (data == NULL) + return; + + data->width = efimg[0]; + data->height = efimg[1]; + data->scheme = efimg[2]; + data->iidf_id = efimg[3] << 8 | efimg[4]; + data->iidf_offset = efimg[5] << 8 | efimg[6]; + data->iid_len = efimg[7] << 8 | efimg[8]; + data->user_data = user_data; + data->sim = sim; + data->id = id; + + if (data->scheme == STK_IMG_SCHEME_BASIC) + data->need_clut = FALSE; + else + data->need_clut = TRUE; + + /* read the image data */ + ofono_sim_read_bytes(sim, data->iidf_id, + data->iidf_offset, data->iid_len, + sim_iidf_read_cb, data); +} + +static DBusMessage *sim_get_icon(DBusConnection *conn, + DBusMessage *msg, void *data) +{ + struct ofono_sim *sim = data; + unsigned char id; + + if (dbus_message_get_args(msg, NULL, DBUS_TYPE_BYTE, &id, + DBUS_TYPE_INVALID) == FALSE) + return __ofono_error_invalid_args(msg); + + /* zero means no icon */ + if (id == 0) + return __ofono_error_invalid_args(msg); + + if (sim->pending) + return __ofono_error_busy(msg); + + if (sim->efimg == NULL) + return __ofono_error_not_implemented(msg); + + sim->pending = dbus_message_ref(msg); + + sim_get_image(sim, id, sim); + + return NULL; +} + static DBusMessage *sim_reset_pin(DBusConnection *conn, DBusMessage *msg, void *data) { @@ -773,6 +958,8 @@ static GDBusMethodTable sim_methods[] = { G_DBUS_METHOD_FLAG_ASYNC }, { "UnlockPin", "ss", "", sim_unlock_pin, G_DBUS_METHOD_FLAG_ASYNC }, + { "GetIcon", "y", "s", sim_get_icon, + G_DBUS_METHOD_FLAG_ASYNC }, { } };