diff --git a/src/ofono.h b/src/ofono.h index 9107d81c..9cebdcef 100644 --- a/src/ofono.h +++ b/src/ofono.h @@ -418,6 +418,7 @@ unsigned char *__ofono_sim_session_get_aid( struct ofono_sim_aid_session *session); const char *__ofono_sim_get_impi(struct ofono_sim *sim); +void __ofono_sim_clear_cached_pins(struct ofono_sim *sim); #include diff --git a/src/sim.c b/src/sim.c index 886f2910..c01925e9 100644 --- a/src/sim.c +++ b/src/sim.c @@ -143,6 +143,11 @@ struct ofono_sim { bool wait_initialized : 1; }; +struct cached_pin { + char *id; + char *pin; +}; + struct msisdn_set_request { struct ofono_sim *sim; int pending; @@ -178,6 +183,8 @@ static void sim_own_numbers_update(struct ofono_sim *sim); static GSList *g_drivers = NULL; +static GSList *cached_pins = NULL; + static const char *sim_passwd_name(enum ofono_sim_password_type type) { return passwd_name[type]; @@ -475,6 +482,68 @@ done: return reply; } +static struct cached_pin *pin_cache_lookup(const char *iccid) +{ + struct cached_pin *c; + GSList *l; + + if (cached_pins == NULL) + return NULL; + + for (l = cached_pins; l; l = l->next) { + c = l->data; + + if (g_strcmp0(iccid, c->id) == 0) + return c; + } + + return NULL; +} + +static void pin_cache_update(const char *iccid, const char *pin) +{ + struct cached_pin *pin_cached = pin_cache_lookup(iccid); + struct cached_pin *cpins; + + if (pin_cached != NULL) { + g_free(pin_cached->pin); + pin_cached->pin = g_strdup(pin); + return; + } + + cpins = g_new0(struct cached_pin, 1); + + cpins->id = g_strdup(iccid); + cpins->pin = g_strdup(pin); + cached_pins = g_slist_prepend(cached_pins, cpins); +} + +static void pin_cache_remove(const char *iccid) +{ + struct cached_pin *pin_cached = pin_cache_lookup(iccid); + + if (pin_cached == NULL) + return; + + cached_pins = g_slist_remove(cached_pins, pin_cached); +} + +static void pin_cache_enter_cb(const struct ofono_error *error, void *data) +{ + struct ofono_sim *sim = data; + + if (error->type != OFONO_ERROR_TYPE_NO_ERROR) { + pin_cache_remove(sim->iccid); + + __ofono_sim_recheck_pin(sim); + + return; + } + + sim->wait_initialized = true; + DBG("Waiting for ofono_sim_initialized_notify"); +} + static void sim_pin_retries_query_cb(const struct ofono_error *error, int retries[OFONO_SIM_PASSWORD_INVALID], void *data) @@ -683,6 +752,11 @@ static void sim_locked_cb(struct ofono_sim *sim, gboolean locked) OFONO_SIM_MANAGER_INTERFACE, "LockedPins", DBUS_TYPE_STRING, &locked_pins); + + /* Cache pin only for SIM PIN type */ + if (g_strcmp0(typestr, "pin") == 0) + pin_cache_update(sim->iccid, pin); + g_strfreev(locked_pins); sim_pin_retries_check(sim); @@ -778,6 +852,14 @@ static DBusMessage *sim_unlock_pin(DBusConnection *conn, DBusMessage *msg, static void sim_change_pin_cb(const struct ofono_error *error, void *data) { struct ofono_sim *sim = data; + const char *typestr; + const char *old; + const char *new; + + dbus_message_get_args(sim->pending, NULL, DBUS_TYPE_STRING, &typestr, + DBUS_TYPE_STRING, &old, + DBUS_TYPE_STRING, &new, + DBUS_TYPE_INVALID); if (error->type != OFONO_ERROR_TYPE_NO_ERROR) { __ofono_dbus_pending_reply(&sim->pending, @@ -788,6 +870,10 @@ static void sim_change_pin_cb(const struct ofono_error *error, void *data) return; } + /* Cache pin only for SIM PIN type */ + if (g_strcmp0(typestr, "pin") == 0) + pin_cache_update(sim->iccid, new); + __ofono_dbus_pending_reply(&sim->pending, dbus_message_new_method_return(sim->pending)); @@ -839,8 +925,14 @@ static DBusMessage *sim_change_pin(DBusConnection *conn, DBusMessage *msg, static void sim_enter_pin_cb(const struct ofono_error *error, void *data) { struct ofono_sim *sim = data; + const char *typestr; + const char *pin; DBusMessage *reply; + dbus_message_get_args(sim->pending, NULL, DBUS_TYPE_STRING, &typestr, + DBUS_TYPE_STRING, &pin, + DBUS_TYPE_INVALID); + if (error->type != OFONO_ERROR_TYPE_NO_ERROR) reply = __ofono_error_failed(sim->pending); else @@ -852,6 +944,10 @@ static void sim_enter_pin_cb(const struct ofono_error *error, void *data) if (sim->initialized || error->type != OFONO_ERROR_TYPE_NO_ERROR) goto recheck; + /* Cache pin only for SIM PIN type */ + if (g_strcmp0(typestr, "pin") == 0) + pin_cache_update(sim->iccid, pin); + if (sim->pin_type == OFONO_SIM_PASSWORD_SIM_PIN || sim->pin_type == OFONO_SIM_PASSWORD_SIM_PUK) { sim->wait_initialized = true; @@ -2751,6 +2847,8 @@ void ofono_sim_inserted_notify(struct ofono_sim *sim, ofono_bool_t inserted) sim->pin_retries[OFONO_SIM_PASSWORD_SIM_PIN2] = -1; sim->pin_retries[OFONO_SIM_PASSWORD_SIM_PUK2] = -1; + pin_cache_remove(sim->iccid); + sim_free_state(sim); } } @@ -3024,6 +3122,7 @@ static void sim_pin_query_cb(const struct ofono_error *error, struct ofono_sim *sim = data; DBusConnection *conn = ofono_dbus_get_connection(); const char *path = __ofono_atom_get_path(sim->atom); + struct cached_pin *cpins = pin_cache_lookup(sim->iccid); const char *pin_name; char **locked_pins; gboolean lock_changed; @@ -3068,6 +3167,10 @@ static void sim_pin_query_cb(const struct ofono_error *error, &pin_name); } + if (g_strcmp0(pin_name, "pin") == 0 && cpins != NULL) + sim->driver->send_passwd(sim, cpins->pin, + pin_cache_enter_cb, sim); + switch (pin_type) { case OFONO_SIM_PASSWORD_NONE: case OFONO_SIM_PASSWORD_SIM_PIN2: @@ -3301,6 +3404,14 @@ void ofono_sim_register(struct ofono_sim *sim) __ofono_atom_register(sim->atom, sim_unregister); } +void __ofono_sim_clear_cached_pins(struct ofono_sim *sim) +{ + if (cached_pins == NULL) + return; + + pin_cache_remove(sim->iccid); +} + void ofono_sim_remove(struct ofono_sim *sim) { __ofono_atom_free(sim->atom);