summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDenis Kenzior <denkenz@gmail.com>2011-07-22 08:18:02 -0500
committerDenis Kenzior <denkenz@gmail.com>2011-07-22 08:22:52 -0500
commit380c95ddcb9cea8a73a700746dbc2141c8a3d61c (patch)
tree7b19fc39c3ee835116d9013a63d54daecde7acc7
parent4b3796cc6be08864fad2fc80a755c92d44d3ea8c (diff)
downloadofono-380c95ddcb9cea8a73a700746dbc2141c8a3d61c.tar.bz2
atmodem: Implement generic CPIN polling
-rw-r--r--drivers/atmodem/atutil.c102
-rw-r--r--drivers/atmodem/atutil.h8
2 files changed, 110 insertions, 0 deletions
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;