mirror of git://git.sysmocom.de/ofono
sim: Refactor iidf reading
Get rid of image_data since it can lead to potential memory leaks when sim is removed while the IIDF operations are in progress.
This commit is contained in:
parent
30a3c5a4ab
commit
a4d90fd4eb
180
src/sim.c
180
src/sim.c
|
@ -91,6 +91,8 @@ struct ofono_sim {
|
||||||
|
|
||||||
struct sim_fs *simfs;
|
struct sim_fs *simfs;
|
||||||
|
|
||||||
|
unsigned char *iidf_image;
|
||||||
|
|
||||||
DBusMessage *pending;
|
DBusMessage *pending;
|
||||||
const struct ofono_sim_driver *driver;
|
const struct ofono_sim_driver *driver;
|
||||||
void *driver_data;
|
void *driver_data;
|
||||||
|
@ -722,19 +724,21 @@ static DBusMessage *sim_enter_pin(DBusConnection *conn, DBusMessage *msg,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sim_get_image_cb(gboolean ok, const char *xpm, int xpm_len,
|
static void sim_get_image_cb(struct ofono_sim *sim,
|
||||||
void *userdata)
|
unsigned char id, char *xpm, gboolean cache)
|
||||||
{
|
{
|
||||||
struct ofono_sim *sim = userdata;
|
|
||||||
DBusMessage *reply;
|
DBusMessage *reply;
|
||||||
DBusMessageIter iter, array;
|
DBusMessageIter iter, array;
|
||||||
|
int xpm_len;
|
||||||
|
|
||||||
if (ok == FALSE) {
|
if (xpm == NULL) {
|
||||||
reply = __ofono_error_failed(sim->pending);
|
reply = __ofono_error_failed(sim->pending);
|
||||||
__ofono_dbus_pending_reply(&sim->pending, reply);
|
__ofono_dbus_pending_reply(&sim->pending, reply);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
xpm_len = strlen(xpm);
|
||||||
|
|
||||||
reply = dbus_message_new_method_return(sim->pending);
|
reply = dbus_message_new_method_return(sim->pending);
|
||||||
dbus_message_iter_init_append(reply, &iter);
|
dbus_message_iter_init_append(reply, &iter);
|
||||||
|
|
||||||
|
@ -746,133 +750,126 @@ static void sim_get_image_cb(gboolean ok, const char *xpm, int xpm_len,
|
||||||
dbus_message_iter_close_container(&iter, &array);
|
dbus_message_iter_close_container(&iter, &array);
|
||||||
|
|
||||||
__ofono_dbus_pending_reply(&sim->pending, reply);
|
__ofono_dbus_pending_reply(&sim->pending, reply);
|
||||||
|
|
||||||
|
if (cache)
|
||||||
|
sim_fs_cache_image(sim->simfs, (const char *) xpm, id);
|
||||||
|
|
||||||
|
g_free(xpm);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct image_data {
|
static void sim_iidf_read_clut_cb(int ok, int length, int record,
|
||||||
struct ofono_sim *sim;
|
const unsigned char *data,
|
||||||
unsigned char width;
|
int record_length, void *userdata)
|
||||||
unsigned char height;
|
{
|
||||||
enum stk_img_scheme scheme;
|
struct ofono_sim *sim = userdata;
|
||||||
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;
|
unsigned char id;
|
||||||
};
|
unsigned char *efimg;
|
||||||
|
unsigned short iidf_len;
|
||||||
|
unsigned short clut_len;
|
||||||
|
char *xpm;
|
||||||
|
|
||||||
|
DBG("ok: %d", ok);
|
||||||
|
|
||||||
|
dbus_message_get_args(sim->pending, NULL, DBUS_TYPE_BYTE, &id,
|
||||||
|
DBUS_TYPE_INVALID);
|
||||||
|
id -= 1;
|
||||||
|
efimg = &sim->efimg[id * 9];
|
||||||
|
|
||||||
|
if (!ok) {
|
||||||
|
sim_get_image_cb(sim, id, NULL, FALSE);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
iidf_len = efimg[7] << 8 | efimg[8];
|
||||||
|
|
||||||
|
if (sim->iidf_image[3] == 0)
|
||||||
|
clut_len = 256 * 3;
|
||||||
|
else
|
||||||
|
clut_len = sim->iidf_image[3] * 3;
|
||||||
|
|
||||||
|
xpm = stk_image_to_xpm(sim->iidf_image, iidf_len, efimg[2],
|
||||||
|
data, clut_len);
|
||||||
|
sim_get_image_cb(sim, id, xpm, TRUE);
|
||||||
|
|
||||||
|
done:
|
||||||
|
g_free(sim->iidf_image);
|
||||||
|
sim->iidf_image = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static void sim_iidf_read_cb(int ok, int length, int record,
|
static void sim_iidf_read_cb(int ok, int length, int record,
|
||||||
const unsigned char *data,
|
const unsigned char *data,
|
||||||
int record_length, void *userdata)
|
int record_length, void *userdata)
|
||||||
{
|
{
|
||||||
struct image_data *image = userdata;
|
struct ofono_sim *sim = userdata;
|
||||||
|
unsigned char id;
|
||||||
|
unsigned char *efimg;
|
||||||
|
unsigned short iidf_id;
|
||||||
unsigned short offset;
|
unsigned short offset;
|
||||||
unsigned short num_entries;
|
unsigned short clut_len;
|
||||||
char *xpm;
|
|
||||||
struct ofono_sim *sim = image->sim;
|
DBG("ok: %d", ok);
|
||||||
|
|
||||||
|
dbus_message_get_args(sim->pending, NULL, DBUS_TYPE_BYTE, &id,
|
||||||
|
DBUS_TYPE_INVALID);
|
||||||
|
id -= 1;
|
||||||
|
efimg = &sim->efimg[id * 9];
|
||||||
|
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
sim_get_image_cb(ok, NULL, 0, image->user_data);
|
sim_get_image_cb(sim, id, NULL, FALSE);
|
||||||
goto iidf_read_out;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (image->need_clut == FALSE) {
|
if (efimg[2] == STK_IMG_SCHEME_BASIC) {
|
||||||
if (image->scheme == STK_IMG_SCHEME_BASIC) {
|
char *xpm = stk_image_to_xpm(data, length, efimg[2], NULL, 0);
|
||||||
xpm = stk_image_to_xpm(data, image->iid_len,
|
sim_get_image_cb(sim, id, xpm, TRUE);
|
||||||
image->scheme, NULL, 0);
|
return;
|
||||||
} 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];
|
offset = data[4] << 8 | data[5];
|
||||||
num_entries = data[3];
|
|
||||||
|
|
||||||
if (num_entries == 0)
|
if (data[3] == 0)
|
||||||
num_entries = 256;
|
clut_len = 256 * 3;
|
||||||
|
else
|
||||||
|
clut_len = data[3] * 3;
|
||||||
|
|
||||||
/* indicate that we're on our second read */
|
iidf_id = efimg[3] << 8 | efimg[4];
|
||||||
image->need_clut = FALSE;
|
sim->iidf_image = g_memdup(data, length);
|
||||||
|
|
||||||
image->clut_len = num_entries * 3;
|
|
||||||
|
|
||||||
image->image = g_memdup(data, length);
|
|
||||||
|
|
||||||
/* read the clut data */
|
/* read the clut data */
|
||||||
ofono_sim_read_bytes(image->sim, image->iidf_id,
|
ofono_sim_read_bytes(sim, iidf_id, offset, clut_len,
|
||||||
offset, image->clut_len,
|
sim_iidf_read_clut_cb, sim);
|
||||||
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,
|
static void sim_get_image(struct ofono_sim *sim, unsigned char id,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
struct image_data *data;
|
|
||||||
unsigned char *efimg;
|
unsigned char *efimg;
|
||||||
char *image;
|
char *image;
|
||||||
|
unsigned short iidf_id;
|
||||||
|
unsigned short iidf_offset;
|
||||||
|
unsigned short iidf_len;
|
||||||
|
|
||||||
image = sim_fs_get_cached_image(sim->simfs, id);
|
image = sim_fs_get_cached_image(sim->simfs, id);
|
||||||
|
|
||||||
if (image != NULL) {
|
if (image != NULL) {
|
||||||
sim_get_image_cb(1, image, strlen(image), user_data);
|
sim_get_image_cb(sim, id, image, FALSE);
|
||||||
g_free(image);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sim->efimg_length <= (id * 9)) {
|
if (sim->efimg_length <= (id * 9)) {
|
||||||
sim_get_image_cb(0, NULL, 0, user_data);
|
sim_get_image_cb(sim, id, NULL, FALSE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
efimg = &sim->efimg[id * 9];
|
efimg = &sim->efimg[id * 9];
|
||||||
|
|
||||||
data = g_try_new0(struct image_data, 1);
|
iidf_id = efimg[3] << 8 | efimg[4];
|
||||||
if (data == NULL)
|
iidf_offset = efimg[5] << 8 | efimg[6];
|
||||||
return;
|
iidf_len = efimg[7] << 8 | efimg[8];
|
||||||
|
|
||||||
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 */
|
/* read the image data */
|
||||||
ofono_sim_read_bytes(sim, data->iidf_id,
|
ofono_sim_read_bytes(sim, iidf_id, iidf_offset, iidf_len,
|
||||||
data->iidf_offset, data->iid_len,
|
sim_iidf_read_cb, sim);
|
||||||
sim_iidf_read_cb, data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static DBusMessage *sim_get_icon(DBusConnection *conn,
|
static DBusMessage *sim_get_icon(DBusConnection *conn,
|
||||||
|
@ -1848,6 +1845,9 @@ static void sim_free_state(struct ofono_sim *sim)
|
||||||
sim->efimg = NULL;
|
sim->efimg = NULL;
|
||||||
sim->efimg_length = 0;
|
sim->efimg_length = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g_free(sim->iidf_image);
|
||||||
|
sim->iidf_image = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ofono_sim_inserted_notify(struct ofono_sim *sim, ofono_bool_t inserted)
|
void ofono_sim_inserted_notify(struct ofono_sim *sim, ofono_bool_t inserted)
|
||||||
|
|
Loading…
Reference in New Issue