From 380c95ddcb9cea8a73a700746dbc2141c8a3d61c Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Fri, 22 Jul 2011 08:18:02 -0500 Subject: atmodem: Implement generic CPIN polling --- drivers/atmodem/atutil.c | 102 +++++++++++++++++++++++++++++++++++++++++++++++ drivers/atmodem/atutil.h | 8 ++++ 2 files changed, 110 insertions(+) diff --git a/drivers/atmodem/atutil.c b/drivers/atmodem/atutil.c index 01f54608..73727bc2 100644 --- a/drivers/atmodem/atutil.c +++ b/drivers/atmodem/atutil.c @@ -35,6 +35,20 @@ #include "atutil.h" #include "vendor.h" +static const char *cpin_prefix[] = { "+CPIN:", NULL }; + +struct at_util_sim_state_query { + GAtChat *chat; + guint cpin_poll_source; + guint cpin_poll_count; + guint interval; + guint num_times; + at_util_sim_inserted_cb_t cb; + void *userdata; +}; + +static gboolean cpin_check(gpointer userdata); + void decode_at_error(struct ofono_error *error, const char *final) { if (!strcmp(final, "OK")) { @@ -484,3 +498,91 @@ gboolean at_util_parse_attr(GAtResult *result, const char *prefix, return TRUE; } + +static void cpin_check_cb(gboolean ok, GAtResult *result, gpointer userdata) +{ + struct at_util_sim_state_query *req = userdata; + struct ofono_error error; + + decode_at_error(&error, g_at_result_final_response(result)); + + if (error.type == OFONO_ERROR_TYPE_NO_ERROR) + goto done; + + /* + * If we got a generic error the AT port might not be ready, + * try again + */ + if (error.type == OFONO_ERROR_TYPE_FAILURE) + goto tryagain; + + /* If we got any other error besides CME, fail */ + if (error.type != OFONO_ERROR_TYPE_CME) + goto done; + + switch (error.error) { + case 10: + case 13: + goto done; + + case 14: + goto tryagain; + + default: + /* Assume SIM is present */ + ok = TRUE; + goto done; + } + +tryagain: + if (req->cpin_poll_count++ < req->num_times) { + req->cpin_poll_source = g_timeout_add_seconds(req->interval, + cpin_check, + req); + return; + } + +done: + if (req->cb) + req->cb(ok, req->userdata); +} + +static gboolean cpin_check(gpointer userdata) +{ + struct at_util_sim_state_query *req = userdata; + + req->cpin_poll_source = 0; + + g_at_chat_send(req->chat, "AT+CPIN?", cpin_prefix, + cpin_check_cb, req, NULL); + + return FALSE; +} + +struct at_util_sim_state_query *at_util_sim_state_query_new(GAtChat *chat, + guint interval, guint num_times, + at_util_sim_inserted_cb_t cb, + void *userdata) +{ + struct at_util_sim_state_query *req; + + req = g_new0(struct at_util_sim_state_query, 1); + + req->chat = chat; + req->interval = interval; + req->num_times = num_times; + req->cb = cb; + req->userdata = userdata; + + cpin_check(req); + + return req; +} + +void at_util_sim_state_query_free(struct at_util_sim_state_query *req) +{ + if (req->cpin_poll_source > 0) + g_source_remove(req->cpin_poll_source); + + g_free(req); +} diff --git a/drivers/atmodem/atutil.h b/drivers/atmodem/atutil.h index a27de862..952de2c6 100644 --- a/drivers/atmodem/atutil.h +++ b/drivers/atmodem/atutil.h @@ -48,6 +48,8 @@ enum at_util_charset { AT_UTIL_CHARSET_8859_H = 0x10000, }; +typedef void (*at_util_sim_inserted_cb_t)(gboolean present, void *userdata); + void decode_at_error(struct ofono_error *error, const char *final); gint at_util_call_compare_by_status(gconstpointer a, gconstpointer b); gint at_util_call_compare_by_phone_number(gconstpointer a, gconstpointer b); @@ -74,6 +76,12 @@ gboolean at_util_parse_cscs_query(GAtResult *result, gboolean at_util_parse_attr(GAtResult *result, const char *prefix, const char **out_attr); +struct at_util_sim_state_query *at_util_sim_state_query_new(GAtChat *chat, + guint interval, guint num_times, + at_util_sim_inserted_cb_t cb, + void *userdata); +void at_util_sim_state_query_free(struct at_util_sim_state_query *req); + struct cb_data { void *cb; void *data; -- cgit v1.2.3