[MM] [PATCH] sim: retry SIM operations during initialization
- From: Ben Chan <benchan chromium org>
- To: networkmanager-list gnome org
- Subject: [MM] [PATCH] sim: retry SIM operations during initialization
- Date: Tue, 21 Aug 2012 22:28:26 -0700
This patch modifies the MMSim interface to validate the IMSI value
reported by AT+CIMI and retry the command upon an error. It also
modifies other SIM operations during the interface initialization to
retry upon an error.
---
src/mm-sim.c | 124 ++++++++++++++++++++++++++++++++++-----------------------
1 files changed, 74 insertions(+), 50 deletions(-)
diff --git a/src/mm-sim.c b/src/mm-sim.c
index 9cd31cc..eb0bb00 100644
--- a/src/mm-sim.c
+++ b/src/mm-sim.c
@@ -1066,15 +1066,48 @@ load_sim_identifier (MMSim *self,
/* IMSI */
static gchar *
+parse_imsi (const gchar *response,
+ GError **error)
+{
+ const gchar *s;
+ int len;
+ gboolean success;
+
+ if (response) {
+ success = TRUE;
+ for (s = response, len = 0; *s; ++s, ++len) {
+ /* IMSI is a number with 15 or less decimal digits. */
+ if (!isdigit (*s) || len > 15) {
+ success = FALSE;
+ break;
+ }
+ }
+ if (success)
+ return g_strdup (response);
+ }
+
+ g_set_error (error,
+ MM_CORE_ERROR,
+ MM_CORE_ERROR_FAILED,
+ "Invalid +CIMI response '%s'", response ? response : "<null>");
+ return NULL;
+}
+
+static gchar *
load_imsi_finish (MMSim *self,
GAsyncResult *res,
GError **error)
{
+ const gchar *result;
gchar *imsi;
if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error))
return NULL;
- imsi = g_strdup (g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res)));
+ result = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res));
+
+ imsi = parse_imsi (result, error);
+ if (!imsi)
+ return NULL;
mm_dbg ("loaded IMSI: %s", imsi);
return imsi;
@@ -1093,7 +1126,7 @@ load_imsi (MMSim *self,
MM_BASE_MODEM (self->priv->modem),
"+CIMI",
3,
- TRUE,
+ FALSE,
(GAsyncReadyCallback)load_imsi_command_ready,
g_simple_async_result_new (G_OBJECT (self),
callback,
@@ -1368,7 +1401,7 @@ struct _InitAsyncContext {
GCancellable *cancellable;
MMSim *self;
InitializationStep step;
- guint sim_identifier_tries;
+ guint step_tries;
};
static void
@@ -1381,6 +1414,21 @@ init_async_context_free (InitAsyncContext *ctx)
g_free (ctx);
}
+static void
+init_async_context_next_step (InitAsyncContext *ctx)
+{
+ ctx->step++;
+ ctx->step_tries = 0;
+}
+
+static gboolean
+interface_initialization_step_again (InitAsyncContext *ctx)
+{
+ interface_initialization_step (ctx);
+
+ return FALSE;
+}
+
MMSim *
mm_sim_new_finish (GAsyncResult *res,
GError **error)
@@ -1409,41 +1457,6 @@ initable_init_finish (GAsyncInitable *initable,
return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error);
}
-static void
-load_sim_identifier_ready (MMSim *self,
- GAsyncResult *res,
- InitAsyncContext *ctx)
-{
- GError *error = NULL;
- gchar *simid;
-
- simid = MM_SIM_GET_CLASS (ctx->self)->load_sim_identifier_finish (self, res, &error);
- if (!simid) {
- /* TODO: make the retries gobi-specific? */
-
- /* Try one more time... Gobi 1K cards may reply to the first
- * request with '+CRSM: 106,134,""' which is bogus because
- * subsequent requests work fine.
- */
- if (++ctx->sim_identifier_tries < 2) {
- g_clear_error (&error);
- interface_initialization_step (ctx);
- return;
- }
-
- mm_warn ("couldn't load SIM identifier: '%s'",
- error ? error->message : "unknown error");
- g_clear_error (&error);
- }
-
- mm_gdbus_sim_set_sim_identifier (MM_GDBUS_SIM (self), simid);
- g_free (simid);
-
- /* Go on to next step */
- ctx->step++;
- interface_initialization_step (ctx);
-}
-
#undef STR_REPLY_READY_FN
#define STR_REPLY_READY_FN(NAME,DISPLAY) \
static void \
@@ -1455,19 +1468,30 @@ load_sim_identifier_ready (MMSim *self,
gchar *val; \
\
val = MM_SIM_GET_CLASS (ctx->self)->load_##NAME##_finish (self, res, &error); \
- mm_gdbus_sim_set_##NAME (MM_GDBUS_SIM (self), val); \
- g_free (val); \
+ if (!val) { \
+ if (++ctx->step_tries < 3) { \
+ g_clear_error (&error); \
+ g_timeout_add_seconds (1, \
+ (GSourceFunc)interface_initialization_step_again, \
+ ctx); \
+ return; \
+ } \
\
- if (error) { \
- mm_warn ("couldn't load %s: '%s'", DISPLAY, error->message); \
- g_error_free (error); \
+ mm_warn ("couldn't load %s: '%s'", \
+ DISPLAY, \
+ error ? error->message : "unknown error"); \
+ g_clear_error (&error); \
} \
\
+ mm_gdbus_sim_set_##NAME (MM_GDBUS_SIM (self), val); \
+ g_free (val); \
+ \
/* Go on to next step */ \
- ctx->step++; \
+ init_async_context_next_step (ctx); \
interface_initialization_step (ctx); \
}
+STR_REPLY_READY_FN (sim_identifier, "SIM identifier")
STR_REPLY_READY_FN (imsi, "IMSI")
STR_REPLY_READY_FN (operator_identifier, "Operator identifier")
STR_REPLY_READY_FN (operator_name, "Operator name")
@@ -1478,7 +1502,7 @@ interface_initialization_step (InitAsyncContext *ctx)
switch (ctx->step) {
case INITIALIZATION_STEP_FIRST:
/* Fall down to next step */
- ctx->step++;
+ init_async_context_next_step (ctx);
case INITIALIZATION_STEP_SIM_IDENTIFIER:
/* SIM ID is meant to be loaded only once during the whole
@@ -1494,7 +1518,7 @@ interface_initialization_step (InitAsyncContext *ctx)
return;
}
/* Fall down to next step */
- ctx->step++;
+ init_async_context_next_step (ctx);
case INITIALIZATION_STEP_IMSI:
/* IMSI is meant to be loaded only once during the whole
@@ -1510,7 +1534,7 @@ interface_initialization_step (InitAsyncContext *ctx)
return;
}
/* Fall down to next step */
- ctx->step++;
+ init_async_context_next_step (ctx);
case INITIALIZATION_STEP_OPERATOR_ID:
/* Operator ID is meant to be loaded only once during the whole
@@ -1526,7 +1550,7 @@ interface_initialization_step (InitAsyncContext *ctx)
return;
}
/* Fall down to next step */
- ctx->step++;
+ init_async_context_next_step (ctx);
case INITIALIZATION_STEP_OPERATOR_NAME:
/* Operator Name is meant to be loaded only once during the whole
@@ -1542,7 +1566,7 @@ interface_initialization_step (InitAsyncContext *ctx)
return;
}
/* Fall down to next step */
- ctx->step++;
+ init_async_context_next_step (ctx);
case INITIALIZATION_STEP_LAST:
/* We are done without errors! */
@@ -1575,7 +1599,7 @@ common_init_async (GAsyncInitable *initable,
g_object_ref (cancellable) :
NULL);
ctx->step = INITIALIZATION_STEP_FIRST;
- ctx->sim_identifier_tries = 0;
+ ctx->step_tries = 0;
interface_initialization_step (ctx);
}
--
1.7.7.3
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]