From: Denis Kenzior <denkenz@gmail.com>
To: ofono@ofono.org
Subject: Re: [sim-ready-nofify-v5 PATCH 2/3] atmodem/sim: use ofono_sim_ready_notify
Date: Wed, 09 Feb 2011 16:09:53 -0600 [thread overview]
Message-ID: <4D5310B1.8010007@gmail.com> (raw)
In-Reply-To: <1297168379-16400-3-git-send-email-Pekka.Pessi@nokia.com>
[-- Attachment #1: Type: text/plain, Size: 10323 bytes --]
Hi Pekka,
On 02/08/2011 06:32 AM, Pekka.Pessi(a)nokia.com wrote:
> From: Pekka Pessi <Pekka.Pessi@nokia.com>
>
> Schedule a call to ofono_sim_ready_notify after pin code query returns
> SIM READY.
>
> Vendor quirks:
> - IFX: register unsolicated +XSIM result code
> - MBM: register unsolicated *EPEV result code
> ---
> drivers/atmodem/sim.c | 166 ++++++++++++++++++++++++++++++++++--------------
> 1 files changed, 117 insertions(+), 49 deletions(-)
>
> diff --git a/drivers/atmodem/sim.c b/drivers/atmodem/sim.c
> index d9c0d8d..666edbe 100644
> --- a/drivers/atmodem/sim.c
> +++ b/drivers/atmodem/sim.c
> @@ -46,10 +46,14 @@
>
> #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
>
> +#define READY_TIMEOUT 5000
> +
> struct sim_data {
> GAtChat *chat;
> unsigned int vendor;
> guint ready_id;
> + guint ready_source;
> + ofono_bool_t ready;
> };
>
> static const char *crsm_prefix[] = { "+CRSM:", NULL };
> @@ -679,10 +683,55 @@ static void at_pin_retries_query(struct ofono_sim *sim,
> CALLBACK_WITH_FAILURE(cb, NULL, data);
> }
>
> +static void ready_unregister_and_notify(struct ofono_sim *sim)
> +{
> + struct sim_data *sd = ofono_sim_get_data(sim);
> +
> + DBG("");
> +
> + if (sd->ready_source > 0) {
> + g_source_remove(sd->ready_source);
> + sd->ready_source = 0;
> + }
> +
> + ofono_sim_ready_notify(sim);
> +}
> +
> +static gboolean ready_timeout(gpointer user_data)
> +{
> + struct ofono_sim *sim = user_data;
> + struct sim_data *sd = ofono_sim_get_data(sim);
> +
> + DBG("");
> +
> + sd->ready_source = 0;
> +
> + ofono_sim_ready_notify(sim);
> +
> + return FALSE;
> +}
> +
> +static void at_wait_for_ready(struct ofono_sim *sim)
> +{
> + struct sim_data *sd = ofono_sim_get_data(sim);
> + guint timeout;
> +
> + if (sd->ready_source > 0)
> + return;
> +
> + if (!sd->ready && sd->ready_id > 0)
> + timeout = READY_TIMEOUT;
> + else
> + timeout = 0;
> +
> + sd->ready_source = g_timeout_add(timeout, ready_timeout, sim);
> +}
> +
> static void at_cpin_cb(gboolean ok, GAtResult *result, gpointer user_data)
> {
> struct cb_data *cbd = user_data;
> - struct sim_data *sd = ofono_sim_get_data(cbd->user);
> + struct ofono_sim *sim = cbd->user;
> + struct sim_data *sd = ofono_sim_get_data(sim);
> GAtResultIter iter;
> ofono_sim_passwd_cb_t cb = cbd->cb;
> struct ofono_error error;
> @@ -729,6 +778,11 @@ static void at_cpin_cb(gboolean ok, GAtResult *result, gpointer user_data)
> return;
> }
>
> + if (pin_type == OFONO_SIM_PASSWORD_NONE)
> + at_wait_for_ready(sim);
> + else
> + sd->ready = FALSE;
> +
So all this logic seems to work by luck. oFono roughly does this:
pin_query:
send AT+CPIN?
if READY then set waiting_for_pin to none, and wait in
ofono_sim_ready_notify
if PIN then set waiting_for_pin to the pin, and wait in
ofono_sim_ready_notify
ofono_sim_ready_notify:
if waiting_for_pin is none proceed with initialization
otherwise go back to pin_query
Here's a log of this running on IFX:
ofonod[521]: Aux: > AT+CPIN?\r
ofonod[521]: Aux: < \r\n+CPIN: SIM PIN\r\n
ofonod[521]: Aux: < \r\nOK\r\n
ofonod[521]: drivers/atmodem/sim.c:at_cpin_cb() crsm_pin_cb: SIM PIN
....
ofonod[521]: Aux: > AT+CPIN="0000"\r
ofonod[521]: Aux: < \r\nOK\r\n
ofonod[521]: Aux: > AT+CPIN?\r
ofonod[521]: Aux: < \r\n+CME ERROR: 14\r\n
ofonod[521]: Querying PIN authentication state failed
....
ofonod[521]: Aux: < \r\n+XSIM: 7\r\n
ofonod[521]: drivers/atmodem/sim.c:at_xsim_notify()
ofonod[521]: drivers/atmodem/sim.c:ready_unregister_and_notify()
ofonod[521]: src/sim.c:ofono_sim_ready_notify()
ofonod[521]: plugins/ifx.c:xsim_notify() state 7
ofonod[521]: Aux: > AT+CPIN?\r
ofonod[521]: Aux: < \r\n+CPIN: READY\r\n
ofonod[521]: Aux: < \r\nOK\r\n
ofonod[521]: drivers/atmodem/sim.c:at_cpin_cb() crsm_pin_cb: READY
ofonod[521]: drivers/atmodem/sim.c:at_pin_retries_query()
ofonod[521]: drivers/atmodem/sim.c:ready_timeout()
ofonod[521]: src/sim.c:ofono_sim_ready_notify()
As you can see, we are in fact calling ofono_sim_ready_notify twice in
short succession. The only reason we're not stuck for 5 seconds the
second time around is that the xsim notification function sets ready to
TRUE. This is all pretty convoluted. I don't really like this@all.
Another case to consider is a cold boot quirked modem, PIN disabled. We
are highly likely to receive XSIM way before we even query the PIN. So
ready is false, ready_id is > 0 and we end up waiting for 5 seconds here
for no good reason.
> DBG("crsm_pin_cb: %s", pin_required);
>
> cb(&error, pin_type, cbd->data);
> @@ -753,13 +807,13 @@ static void at_pin_query(struct ofono_sim *sim, ofono_sim_passwd_cb_t cb,
>
> static void at_xsim_notify(GAtResult *result, gpointer user_data)
> {
> - struct cb_data *cbd = user_data;
> - struct sim_data *sd = cbd->user;
> - ofono_sim_lock_unlock_cb_t cb = cbd->cb;
> - struct ofono_error error = { .type = OFONO_ERROR_TYPE_NO_ERROR };
> + struct ofono_sim *sim = user_data;
> + struct sim_data *sd = ofono_sim_get_data(sim);
> GAtResultIter iter;
> int state;
>
> + DBG("");
> +
> g_at_result_iter_init(&iter, result);
>
> if (!g_at_result_iter_next(&iter, "+XSIM:"))
> @@ -776,65 +830,40 @@ static void at_xsim_notify(GAtResult *result, gpointer user_data)
> return;
> }
>
> - cb(&error, cbd->data);
> + sd->ready = TRUE;
>
> - g_at_chat_unregister(sd->chat, sd->ready_id);
> - sd->ready_id = 0;
> + if (sd->ready_source > 0)
> + ready_unregister_and_notify(sim);
> }
>
> static void at_epev_notify(GAtResult *result, gpointer user_data)
> {
> - struct cb_data *cbd = user_data;
> - struct sim_data *sd = cbd->user;
> - ofono_sim_lock_unlock_cb_t cb = cbd->cb;
> - struct ofono_error error = { .type = OFONO_ERROR_TYPE_NO_ERROR };
> + struct ofono_sim *sim = user_data;
> + struct sim_data *sd = ofono_sim_get_data(sim);
>
> - cb(&error, cbd->data);
> + DBG("");
>
> - g_at_chat_unregister(sd->chat, sd->ready_id);
> - sd->ready_id = 0;
> + sd->ready = TRUE;
> +
> + if (sd->ready_source > 0)
> + ready_unregister_and_notify(sim);
> }
>
> static void at_pin_send_cb(gboolean ok, GAtResult *result,
> gpointer user_data)
> {
> struct cb_data *cbd = user_data;
> - struct sim_data *sd = cbd->user;
> + struct ofono_sim *sim = cbd->user;
> + struct sim_data *sd = ofono_sim_get_data(sim);
> ofono_sim_lock_unlock_cb_t cb = cbd->cb;
> struct ofono_error error;
>
> - decode_at_error(&error, g_at_result_final_response(result));
> + if (ok && sd->ready_id)
> + at_wait_for_ready(sim);
Did you intend if (ok && sd_ready_id == 0) here?
Otherwise I don't see how non-quirked modems ever signal sim_ready or
why you would want to start a timer if you know a notification is coming
anyway.
>
> - if (!ok)
> - goto done;
> -
> - switch (sd->vendor) {
> - case OFONO_VENDOR_IFX:
> - /*
> - * On the IFX modem, AT+CPIN? can return READY too
> - * early and so use +XSIM notification to detect
> - * the ready state of the SIM.
> - */
> - sd->ready_id = g_at_chat_register(sd->chat, "+XSIM",
> - at_xsim_notify,
> - FALSE, cbd, g_free);
> - return;
> - case OFONO_VENDOR_MBM:
> - /*
> - * On the MBM modem, AT+CPIN? keeps returning SIM PIN
> - * for a moment after successful AT+CPIN="..", but then
> - * sends *EPEV when that changes.
> - */
> - sd->ready_id = g_at_chat_register(sd->chat, "*EPEV",
> - at_epev_notify,
> - FALSE, cbd, g_free);
> - return;
> - }
> + decode_at_error(&error, g_at_result_final_response(result));
>
> -done:
> cb(&error, cbd->data);
> -
> - g_free(cbd);
> }
>
> static void at_pin_send(struct ofono_sim *sim, const char *passwd,
> @@ -845,12 +874,14 @@ static void at_pin_send(struct ofono_sim *sim, const char *passwd,
> char buf[64];
> int ret;
>
> - cbd->user = sd;
> + cbd->user = sim;
> +
> + sd->ready = FALSE;
>
> snprintf(buf, sizeof(buf), "AT+CPIN=\"%s\"", passwd);
>
> ret = g_at_chat_send(sd->chat, buf, none_prefix,
> - at_pin_send_cb, cbd, NULL);
> + at_pin_send_cb, cbd, g_free);
>
> memset(buf, 0, sizeof(buf));
>
> @@ -871,12 +902,14 @@ static void at_pin_send_puk(struct ofono_sim *sim, const char *puk,
> char buf[64];
> int ret;
>
> - cbd->user = sd;
> + cbd->user = sim;
> +
> + sd->ready = FALSE;
>
> snprintf(buf, sizeof(buf), "AT+CPIN=\"%s\",\"%s\"", puk, passwd);
>
> ret = g_at_chat_send(sd->chat, buf, none_prefix,
> - at_pin_send_cb, cbd, NULL);
> + at_pin_send_cb, cbd, g_free);
>
> memset(buf, 0, sizeof(buf));
>
> @@ -1038,6 +1071,35 @@ static gboolean at_sim_register(gpointer user)
> return FALSE;
> }
>
> +static void at_register_ready(struct ofono_sim *sim)
> +{
> + struct sim_data *sd = ofono_sim_get_data(sim);
> +
> + switch (sd->vendor) {
> + case OFONO_VENDOR_IFX:
> + /*
> + * On the IFX modem, AT+CPIN? can return READY too
> + * early and so use +XSIM notification to detect
> + * the ready state of the SIM.
> + */
> + sd->ready_id = g_at_chat_register(sd->chat, "+XSIM",
> + at_xsim_notify,
> + FALSE, sim, NULL);
> + break;
> +
> + case OFONO_VENDOR_MBM:
> + /*
> + * On the MBM modem, AT+CPIN? keeps returning SIM PIN
> + * for a moment after successful AT+CPIN="..", but then
> + * sends *EPEV when that changes.
> + */
> + sd->ready_id = g_at_chat_register(sd->chat, "*EPEV",
> + at_epev_notify,
> + FALSE, sim, NULL);
> + break;
> + }
> +}
> +
> static int at_sim_probe(struct ofono_sim *sim, unsigned int vendor,
> void *data)
> {
> @@ -1060,6 +1122,9 @@ static int at_sim_probe(struct ofono_sim *sim, unsigned int vendor,
> }
>
> ofono_sim_set_data(sim, sd);
> +
> + at_register_ready(sim);
> +
> g_idle_add(at_sim_register, sim);
>
> return 0;
> @@ -1071,6 +1136,9 @@ static void at_sim_remove(struct ofono_sim *sim)
>
> ofono_sim_set_data(sim, NULL);
>
> + if (sd->ready_source > 0)
> + g_source_remove(sd->ready_source);
> +
> g_at_chat_unref(sd->chat);
> g_free(sd);
> }
Regards,
-Denis
next prev parent reply other threads:[~2011-02-09 22:09 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-02-08 12:32 [sim-ready-nofify-v5 PATCH 0/3] ofono_sim_ready_notify Pekka.Pessi
2011-02-08 12:32 ` [sim-ready-nofify-v5 PATCH 1/3] sim: add ofono_sim_ready_notify Pekka.Pessi
2011-02-08 12:32 ` [sim-ready-nofify-v5 PATCH 2/3] atmodem/sim: use ofono_sim_ready_notify Pekka.Pessi
2011-02-08 12:32 ` [sim-ready-nofify-v5 PATCH 3/3] isimodem/sim: added PIN and SIM state handling Pekka.Pessi
2011-02-09 22:09 ` Denis Kenzior [this message]
2011-02-15 15:30 ` [sim-ready-nofify-v5 PATCH 2/3] atmodem/sim: use ofono_sim_ready_notify Pekka Pessi
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4D5310B1.8010007@gmail.com \
--to=denkenz@gmail.com \
--cc=ofono@ofono.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox