Adding SIM PIN caching feature to oFono. oFono now caches the SIM PIN1 type
against the ICCID throughout its lifetime in a link list and enters
implicitly upon modem reset/crash.

Handles cases of incorrect pin and sim pin changed externally.

Adding to all modems by default.
---
 src/sim.c | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 114 insertions(+)

diff --git a/src/sim.c b/src/sim.c
index 129ff5d..28d9a00 100644
--- a/src/sim.c
+++ b/src/sim.c
@@ -141,6 +141,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;
@@ -176,6 +181,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];
@@ -473,6 +480,75 @@ done:
        return reply;
 }
 
+static struct cached_pin *pin_cache_lookup(const char *iccid)
+{
+       struct cached_pin *c;
+       GSList *l;
+
+       for (l = cached_pins; l; l = l->next) {
+               c = l->data;
+
+               if (g_strcmp0(iccid, c->id) == 0)
+                       return c;
+       }
+
+       return NULL;
+}
+
+static gboolean 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 TRUE;
+       }
+
+       cpins = g_new0(struct cached_pin, 1);
+
+       if (cpins == NULL)
+               return FALSE;
+
+       cpins->id = g_strdup(iccid);
+       cpins->pin = g_strdup(pin);
+       cached_pins = g_slist_prepend(cached_pins, cpins);
+
+       return TRUE;
+}
+
+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 PIN entry fails, then remove cached PIN*/
+       if (sim->initialized || error->type != OFONO_ERROR_TYPE_NO_ERROR) {
+               pin_cache_remove(sim->iccid);
+               goto recheck;
+       }
+
+       if (sim->pin_type == OFONO_SIM_PASSWORD_SIM_PIN ||
+                       sim->pin_type == OFONO_SIM_PASSWORD_SIM_PUK) {
+               sim->wait_initialized = true;
+               DBG("Waiting for ofono_sim_initialized_notify");
+               return;
+       }
+
+recheck:
+       __ofono_sim_recheck_pin(sim);
+}
+
 static void sim_pin_retries_query_cb(const struct ofono_error *error,
                                        int retries[OFONO_SIM_PASSWORD_INVALID],
                                        void *data)
@@ -681,6 +757,13 @@ 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) {
+               if (!pin_cache_update(sim->iccid, pin))
+                       ofono_error("Failed to cache PIN.");
+       }
+
        g_strfreev(locked_pins);
 
        sim_pin_retries_check(sim);
@@ -776,6 +859,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,
@@ -786,6 +877,12 @@ 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) {
+               if (!pin_cache_update(sim->iccid, new))
+                       ofono_error("Failed to cache PIN.");
+       }
+
        __ofono_dbus_pending_reply(&sim->pending,
                                dbus_message_new_method_return(sim->pending));
 
@@ -837,8 +934,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
@@ -850,6 +953,12 @@ 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) {
+               if (!pin_cache_update(sim->iccid, pin))
+                       ofono_error("Failed to cache PIN.");
+       }
+
        if (sim->pin_type == OFONO_SIM_PASSWORD_SIM_PIN ||
                        sim->pin_type == OFONO_SIM_PASSWORD_SIM_PUK) {
                sim->wait_initialized = true;
@@ -3023,6 +3132,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;
@@ -3067,6 +3177,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:
-- 
2.7.4

_______________________________________________
ofono mailing list
[email protected]
https://lists.ofono.org/mailman/listinfo/ofono

Reply via email to