cinterion: after SIM unlock, query SIM status until ready
This commit is contained in:
@@ -1230,6 +1230,120 @@ setup_flow_control (MMIfaceModem *self,
|
|||||||
result);
|
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 *
|
MMBroadbandModemCinterion *
|
||||||
@@ -1290,6 +1404,8 @@ iface_modem_init (MMIfaceModem *iface)
|
|||||||
iface->load_access_technologies_finish = load_access_technologies_finish;
|
iface->load_access_technologies_finish = load_access_technologies_finish;
|
||||||
iface->setup_flow_control = setup_flow_control;
|
iface->setup_flow_control = setup_flow_control;
|
||||||
iface->setup_flow_control_finish = setup_flow_control_finish;
|
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 = modem_power_down;
|
||||||
iface->modem_power_down_finish = modem_power_down_finish;
|
iface->modem_power_down_finish = modem_power_down_finish;
|
||||||
iface->modem_power_off = modem_power_off;
|
iface->modem_power_off = modem_power_off;
|
||||||
|
@@ -286,3 +286,50 @@ mm_cinterion_build_band (GArray *bands,
|
|||||||
*out_band = band;
|
*out_band = band;
|
||||||
return TRUE;
|
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,
|
guint *out_band,
|
||||||
GError **error);
|
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 */
|
#endif /* MM_MODEM_HELPERS_CINTERION_H */
|
||||||
|
@@ -210,6 +210,42 @@ test_scfg_response_3g (void)
|
|||||||
g_array_unref (expected_bands);
|
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
|
void
|
||||||
@@ -239,10 +275,11 @@ int main (int argc, char **argv)
|
|||||||
g_type_init ();
|
g_type_init ();
|
||||||
g_test_init (&argc, &argv, NULL);
|
g_test_init (&argc, &argv, NULL);
|
||||||
|
|
||||||
g_test_add_func ("/MM/cinterion/scfg", test_scfg);
|
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/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", 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/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 ();
|
return g_test_run ();
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user