summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2010-09-25 11:32:40 +0900
committerMarcel Holtmann <marcel@holtmann.org>2010-09-25 11:32:40 +0900
commit25bb671d4e5986f5804b2675db75152d6c9ea33a (patch)
treebb178c545557026e87408ce43fb88ddc04d8d400
parent554344b45351cc2f5b221ef0d795132347d0271a (diff)
downloadofono-25bb671d4e5986f5804b2675db75152d6c9ea33a.tar.bz2
atmodem: Add special handling for Infineon SIM ready state
-rw-r--r--drivers/atmodem/sim.c77
1 files changed, 61 insertions, 16 deletions
diff --git a/drivers/atmodem/sim.c b/drivers/atmodem/sim.c
index 21bc933f..987dd7c1 100644
--- a/drivers/atmodem/sim.c
+++ b/drivers/atmodem/sim.c
@@ -44,8 +44,8 @@
struct sim_data {
GAtChat *chat;
unsigned int vendor;
- guint epev_id;
- guint epev_source;
+ guint ready_id;
+ guint ready_source;
};
static const char *crsm_prefix[] = { "+CRSM:", NULL };
@@ -522,18 +522,47 @@ error:
CALLBACK_WITH_FAILURE(cb, -1, data);
}
-static gboolean at_epev_unregister(gpointer user_data)
+static gboolean ready_notify_unregister(gpointer user_data)
{
struct sim_data *sd = user_data;
- sd->epev_source = 0;
+ sd->ready_source = 0;
- g_at_chat_unregister(sd->chat, sd->epev_id);
- sd->epev_id = 0;
+ g_at_chat_unregister(sd->chat, sd->ready_id);
+ sd->ready_id = 0;
return FALSE;
}
+static void at_xsim_notify(GAtResult *result, gpointer user_data)
+{
+ struct cb_data *cbd = user_data;
+ struct sim_data *sd = cbd->user;
+ ofono_sim_lock_unlock_cb_t cb = cbd->cb;
+ struct ofono_error error = { .type = OFONO_ERROR_TYPE_NO_ERROR };
+ GAtResultIter iter;
+ int state;
+
+ if (sd->ready_source > 0)
+ return;
+
+ g_at_result_iter_init(&iter, result);
+
+ if (!g_at_result_iter_next(&iter, "+XSIM:"))
+ return;
+
+ if (!g_at_result_iter_next_number(&iter, &state))
+ return;
+
+ /* check for state 3 (PIN verified – Ready) */
+ if (state != 3)
+ return;
+
+ cb(&error, cbd->data);
+
+ sd->ready_source = g_timeout_add(0, ready_notify_unregister, sd);
+}
+
static void at_epev_notify(GAtResult *result, gpointer user_data)
{
struct cb_data *cbd = user_data;
@@ -541,12 +570,12 @@ static void at_epev_notify(GAtResult *result, gpointer user_data)
ofono_sim_lock_unlock_cb_t cb = cbd->cb;
struct ofono_error error = { .type = OFONO_ERROR_TYPE_NO_ERROR };
- if (sd->epev_source)
+ if (sd->ready_source > 0)
return;
cb(&error, cbd->data);
- sd->epev_source = g_timeout_add(0, at_epev_unregister, sd);
+ sd->ready_source = g_timeout_add(0, ready_notify_unregister, sd);
}
static void at_pin_send_cb(gboolean ok, GAtResult *result,
@@ -559,17 +588,33 @@ static void at_pin_send_cb(gboolean ok, GAtResult *result,
decode_at_error(&error, g_at_result_final_response(result));
- /*
- * On the MBM modem, AT+CPIN? keeps returning SIM PIN for a moment
- * after successful AT+CPIN="..", but sends *EPEV when that changes.
- */
- if (ok && sd->vendor == OFONO_VENDOR_MBM) {
- sd->epev_id = g_at_chat_register(sd->chat, "*EPEV",
+ if (!ok)
+ goto done;
+
+ switch (sd->vendor) {
+ case OFONO_VENDOR_IFX:
+ /*
+ * On the IFX modem, AT+CPIN? can return READY too
+ * early and so use +XSIM notification to detect
+ * the ready state of the SIM.
+ */
+ sd->ready_id = g_at_chat_register(sd->chat, "+XSIM",
+ at_xsim_notify,
+ FALSE, cbd, g_free);
+ return;
+ case OFONO_VENDOR_MBM:
+ /*
+ * On the MBM modem, AT+CPIN? keeps returning SIM PIN
+ * for a moment after successful AT+CPIN="..", but then
+ * sends *EPEV when that changes.
+ */
+ sd->ready_id = g_at_chat_register(sd->chat, "*EPEV",
at_epev_notify,
FALSE, cbd, g_free);
return;
}
+done:
cb(&error, cbd->data);
g_free(cbd);
@@ -824,8 +869,8 @@ static void at_sim_remove(struct ofono_sim *sim)
ofono_sim_set_data(sim, NULL);
- if (sd->epev_source)
- g_source_remove(sd->epev_source);
+ if (sd->ready_source > 0)
+ g_source_remove(sd->ready_source);
g_at_chat_unref(sd->chat);
g_free(sd);