cinterion: after SIM unlock, query SIM status until ready
This commit is contained in:
@@ -1230,6 +1230,120 @@ setup_flow_control (MMIfaceModem *self,
|
||||
result);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* After SIM unlock (Modem interface) */
|
||||
|
||||
#define MAX_AFTER_SIM_UNLOCK_RETRIES 15
|
||||
|
||||
typedef enum {
|
||||
CINTERION_SIM_STATUS_REMOVED = 0,
|
||||
CINTERION_SIM_STATUS_INSERTED = 1,
|
||||
CINTERION_SIM_STATUS_INIT_COMPLETED = 5,
|
||||
} CinterionSimStatus;
|
||||
|
||||
typedef struct {
|
||||
MMBroadbandModemCinterion *self;
|
||||
GSimpleAsyncResult *result;
|
||||
guint retries;
|
||||
guint timeout_id;
|
||||
} AfterSimUnlockContext;
|
||||
|
||||
static void
|
||||
after_sim_unlock_context_complete_and_free (AfterSimUnlockContext *ctx)
|
||||
{
|
||||
g_assert (ctx->timeout_id == 0);
|
||||
g_simple_async_result_complete (ctx->result);
|
||||
g_object_unref (ctx->result);
|
||||
g_object_unref (ctx->self);
|
||||
g_slice_free (AfterSimUnlockContext, ctx);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
after_sim_unlock_finish (MMIfaceModem *self,
|
||||
GAsyncResult *res,
|
||||
GError **error)
|
||||
{
|
||||
return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (res), error);
|
||||
}
|
||||
|
||||
static void after_sim_unlock_context_step (AfterSimUnlockContext *ctx);
|
||||
|
||||
static gboolean
|
||||
simstatus_timeout_cb (AfterSimUnlockContext *ctx)
|
||||
{
|
||||
ctx->timeout_id = 0;
|
||||
after_sim_unlock_context_step (ctx);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
simstatus_check_ready (MMBaseModem *self,
|
||||
GAsyncResult *res,
|
||||
AfterSimUnlockContext *ctx)
|
||||
{
|
||||
const gchar *response;
|
||||
|
||||
response = mm_base_modem_at_command_finish (MM_BASE_MODEM (self), res, NULL);
|
||||
if (response) {
|
||||
gchar *descr = NULL;
|
||||
guint val = 0;
|
||||
|
||||
if (mm_cinterion_parse_sind_response (response, &descr, NULL, &val, NULL) &&
|
||||
g_str_equal (descr, "simstatus") &&
|
||||
val == CINTERION_SIM_STATUS_INIT_COMPLETED) {
|
||||
/* SIM ready! */
|
||||
g_free (descr);
|
||||
g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE);
|
||||
after_sim_unlock_context_complete_and_free (ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
g_free (descr);
|
||||
}
|
||||
|
||||
/* Need to retry after 1 sec */
|
||||
g_assert (ctx->timeout_id == 0);
|
||||
ctx->timeout_id = g_timeout_add_seconds (1, (GSourceFunc)simstatus_timeout_cb, ctx);
|
||||
}
|
||||
|
||||
static void
|
||||
after_sim_unlock_context_step (AfterSimUnlockContext *ctx)
|
||||
{
|
||||
if (ctx->retries == 0) {
|
||||
/* Too much wait, go on anyway */
|
||||
g_simple_async_result_set_op_res_gboolean (ctx->result, TRUE);
|
||||
after_sim_unlock_context_complete_and_free (ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Recheck */
|
||||
ctx->retries--;
|
||||
mm_base_modem_at_command (MM_BASE_MODEM (ctx->self),
|
||||
"^SIND=\"simstatus\",1",
|
||||
3,
|
||||
FALSE,
|
||||
(GAsyncReadyCallback)simstatus_check_ready,
|
||||
ctx);
|
||||
}
|
||||
|
||||
static void
|
||||
after_sim_unlock (MMIfaceModem *self,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
AfterSimUnlockContext *ctx;
|
||||
|
||||
ctx = g_slice_new0 (AfterSimUnlockContext);
|
||||
ctx->self = g_object_ref (self);
|
||||
ctx->result = g_simple_async_result_new (G_OBJECT (self),
|
||||
callback,
|
||||
user_data,
|
||||
after_sim_unlock);
|
||||
ctx->retries = MAX_AFTER_SIM_UNLOCK_RETRIES;
|
||||
|
||||
after_sim_unlock_context_step (ctx);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
MMBroadbandModemCinterion *
|
||||
@@ -1290,6 +1404,8 @@ iface_modem_init (MMIfaceModem *iface)
|
||||
iface->load_access_technologies_finish = load_access_technologies_finish;
|
||||
iface->setup_flow_control = setup_flow_control;
|
||||
iface->setup_flow_control_finish = setup_flow_control_finish;
|
||||
iface->modem_after_sim_unlock = after_sim_unlock;
|
||||
iface->modem_after_sim_unlock_finish = after_sim_unlock_finish;
|
||||
iface->modem_power_down = modem_power_down;
|
||||
iface->modem_power_down_finish = modem_power_down_finish;
|
||||
iface->modem_power_off = modem_power_off;
|
||||
|
@@ -286,3 +286,50 @@ mm_cinterion_build_band (GArray *bands,
|
||||
*out_band = band;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Single ^SIND response parser */
|
||||
|
||||
gboolean
|
||||
mm_cinterion_parse_sind_response (const gchar *response,
|
||||
gchar **description,
|
||||
guint *mode,
|
||||
guint *value,
|
||||
GError **error)
|
||||
{
|
||||
GRegex *r;
|
||||
GMatchInfo *match_info;
|
||||
guint errors = 0;
|
||||
|
||||
if (!response) {
|
||||
g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Missing response");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
r = g_regex_new ("\\^SIND:\\s*(.*),(\\d+),(\\d+)(\\r\\n)?", 0, 0, NULL);
|
||||
g_assert (r != NULL);
|
||||
|
||||
if (g_regex_match_full (r, response, strlen (response), 0, 0, &match_info, NULL)) {
|
||||
if (description) {
|
||||
*description = mm_get_string_unquoted_from_match_info (match_info, 1);
|
||||
if (*description == NULL)
|
||||
errors++;
|
||||
}
|
||||
if (mode && !mm_get_uint_from_match_info (match_info, 2, mode))
|
||||
errors++;
|
||||
if (value && !mm_get_uint_from_match_info (match_info, 3, value))
|
||||
errors++;
|
||||
} else
|
||||
errors++;
|
||||
|
||||
if (match_info)
|
||||
g_match_info_free (match_info);
|
||||
g_regex_unref (r);
|
||||
|
||||
if (errors > 0) {
|
||||
g_set_error (error, MM_CORE_ERROR, MM_CORE_ERROR_FAILED, "Failed parsing ^SIND response");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@@ -43,4 +43,13 @@ gboolean mm_cinterion_build_band (GArray *bands,
|
||||
guint *out_band,
|
||||
GError **error);
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Single ^SIND response parser */
|
||||
|
||||
gboolean mm_cinterion_parse_sind_response (const gchar *response,
|
||||
gchar **description,
|
||||
guint *mode,
|
||||
guint *value,
|
||||
GError **error);
|
||||
|
||||
#endif /* MM_MODEM_HELPERS_CINTERION_H */
|
||||
|
@@ -210,6 +210,42 @@ test_scfg_response_3g (void)
|
||||
g_array_unref (expected_bands);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Test ^SIND responses */
|
||||
|
||||
static void
|
||||
common_test_sind_response (const gchar *response,
|
||||
const gchar *expected_description,
|
||||
guint expected_mode,
|
||||
guint expected_value)
|
||||
{
|
||||
GError *error = NULL;
|
||||
gboolean res;
|
||||
gchar *description;
|
||||
guint mode;
|
||||
guint value;
|
||||
|
||||
res = mm_cinterion_parse_sind_response (response,
|
||||
&description,
|
||||
&mode,
|
||||
&value,
|
||||
&error);
|
||||
g_assert_no_error (error);
|
||||
g_assert (res == TRUE);
|
||||
|
||||
g_assert_cmpstr (description, ==, expected_description);
|
||||
g_assert_cmpuint (mode, ==, expected_mode);
|
||||
g_assert_cmpuint (value, ==, expected_value);
|
||||
|
||||
g_free (description);
|
||||
}
|
||||
|
||||
static void
|
||||
test_sind_response_simstatus (void)
|
||||
{
|
||||
common_test_sind_response ("^SIND: simstatus,1,5", "simstatus", 1, 5);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void
|
||||
@@ -239,10 +275,11 @@ int main (int argc, char **argv)
|
||||
g_type_init ();
|
||||
g_test_init (&argc, &argv, NULL);
|
||||
|
||||
g_test_add_func ("/MM/cinterion/scfg", test_scfg);
|
||||
g_test_add_func ("/MM/cinterion/scfg/response/3g", test_scfg_response_3g);
|
||||
g_test_add_func ("/MM/cinterion/scfg/response/2g", test_scfg_response_2g);
|
||||
g_test_add_func ("/MM/cinterion/scfg/response/2g/ucs2", test_scfg_response_2g_ucs2);
|
||||
g_test_add_func ("/MM/cinterion/scfg", test_scfg);
|
||||
g_test_add_func ("/MM/cinterion/scfg/response/3g", test_scfg_response_3g);
|
||||
g_test_add_func ("/MM/cinterion/scfg/response/2g", test_scfg_response_2g);
|
||||
g_test_add_func ("/MM/cinterion/scfg/response/2g/ucs2", test_scfg_response_2g_ucs2);
|
||||
g_test_add_func ("/MM/cinterion/sind/response/simstatus", test_sind_response_simstatus);
|
||||
|
||||
return g_test_run ();
|
||||
}
|
||||
|
Reference in New Issue
Block a user