atmodem: Implement generic CPIN polling

This commit is contained in:
Denis Kenzior 2011-07-22 08:18:02 -05:00
parent 4b3796cc6b
commit 380c95ddcb
2 changed files with 110 additions and 0 deletions

View File

@ -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);
}

View File

@ -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;