aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--plugins/cinterion/mm-broadband-modem-cinterion.c116
-rw-r--r--plugins/cinterion/mm-modem-helpers-cinterion.c47
-rw-r--r--plugins/cinterion/mm-modem-helpers-cinterion.h9
-rw-r--r--plugins/cinterion/tests/test-modem-helpers-cinterion.c45
4 files changed, 213 insertions, 4 deletions
diff --git a/plugins/cinterion/mm-broadband-modem-cinterion.c b/plugins/cinterion/mm-broadband-modem-cinterion.c
index 31110d56..6affd802 100644
--- a/plugins/cinterion/mm-broadband-modem-cinterion.c
+++ b/plugins/cinterion/mm-broadband-modem-cinterion.c
@@ -1231,6 +1231,120 @@ setup_flow_control (MMIfaceModem *self,
}
/*****************************************************************************/
+/* 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 *
mm_broadband_modem_cinterion_new (const gchar *device,
@@ -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;
diff --git a/plugins/cinterion/mm-modem-helpers-cinterion.c b/plugins/cinterion/mm-modem-helpers-cinterion.c
index 97eb7115..118cbb67 100644
--- a/plugins/cinterion/mm-modem-helpers-cinterion.c
+++ b/plugins/cinterion/mm-modem-helpers-cinterion.c
@@ -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;
+}
diff --git a/plugins/cinterion/mm-modem-helpers-cinterion.h b/plugins/cinterion/mm-modem-helpers-cinterion.h
index f4c982f6..ecc10460 100644
--- a/plugins/cinterion/mm-modem-helpers-cinterion.h
+++ b/plugins/cinterion/mm-modem-helpers-cinterion.h
@@ -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 */
diff --git a/plugins/cinterion/tests/test-modem-helpers-cinterion.c b/plugins/cinterion/tests/test-modem-helpers-cinterion.c
index 1ee71c9b..5dc4f960 100644
--- a/plugins/cinterion/tests/test-modem-helpers-cinterion.c
+++ b/plugins/cinterion/tests/test-modem-helpers-cinterion.c
@@ -211,6 +211,42 @@ test_scfg_response_3g (void)
}
/*****************************************************************************/
+/* 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
_mm_log (const char *loc,
@@ -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 ();
}