From: Denis Kenzior <denkenz@gmail.com>
To: ofono@ofono.org
Subject: Re: [PATCH 3/3] telit: rework for HE910
Date: Mon, 08 Apr 2013 13:29:41 -0500 [thread overview]
Message-ID: <51630C95.4090805@gmail.com> (raw)
In-Reply-To: <1365063652-24286-4-git-send-email-jonas@southpole.se>
[-- Attachment #1: Type: text/plain, Size: 12208 bytes --]
Hi Jonas,
On 04/04/2013 03:20 AM, Jonas Bonn wrote:
> The Telit HE910 turns out to be a rather quirky device and the existing
> 'telit' driver doesn't really work as is. This patch is the result of
> many hours of trial-and-error and direct consultation with Telit in
> order to find an initialization sequence that works, doesn't lock up
> the modem, and fits the Ofono paradigm.
Is the HE910 sufficiently different that it might be easier to simply
write a dedicated driver for it? One can even have multiple drivers in
the telit.c file.
E.g. something like:
static struct ofono_modem_driver telit_driver = {
.name = "telit",
...
};
static struct ofono_modem_driver telit_he910_driver = {
...
};
>
> 1) The SIM status unsolicited messages need to be used in order to know
> when the SIM is sufficiently ready to allow certain ther commands to
> be able to complete without error. Unfortunately, these messages are
> not reliably issued in a way that allows them to always be caught. As
> such, the modem needs to be prodded to re-issue these messages by:
>
> i) Using SIMDET=0 to logically 'remove' the SIM before powering on
> the modem
> ii) Setting SIMDET=1 iff a SIM is physically inserted in order to have
> the QSS states re-issued
> iii) Finally, setting SIMDET=2 once the modem is powered up to re-enable
> the normal QSS unsolicited messages
>
> 2) CFUN state 4 powers off the modem (airplane mode), but it also powers
> off the SIM card. This doesn't fit well with the Ofono model as the
> GPRS atom won't be created unless the SIM card is usable. Consultation
> with Telit resulted in the following alternative:
>
It sounds like the concept of Online is not relevant. Maybe you should
simply not implement the .set_enable method. This way the modem
initialization logic in the core proceeds straight to post_online state...
> i) Set CFUN=1 when enabling the modem and set COPS=2 to take the modem
> 'offline'
> ii) Set COPS=0 when putting the modem 'online'
> iii) CFUN=4 may be used when disabling the modem. The telit driver
> previously used CFUN=0, but this is actually not an 'offline' state
> at all.
... which is better than trying to mess with COPS, since this has
potential side effects on the netreg atom.
>
> 3) The voicecall atom cannot be created until the SIM is ready.
>
Then move it to the post_sim or post_online state.
> 4) The CMER command will always fail
>
> 5) The CMER? command will always fail if ofono_sim_inserted_notify is
> called before QSS reaches state 3.
>
> The combination of using CFUN=1 when enabled works around another quirk
> in the modem: if the SIM is hotplugged (SIMIN signal toggles) when CFUN=4,
> the SIM logic actually wakes up and QSS messages may be issued. This is
> out of sync with the expected behaviour and is difficult to reconcile
> with the rest of the control flow in the ofono driver.
>
> The Telit HE910 has a propensity to lock up when echo is enabled. We
> have seen this primarily on the 'modem' port where the modem locks up
> after echoing back the command when there is pending command on the
> 'aux' port. The changed initialization flow of this patch makes this
> problem in general more difficult to hit, but as an additional measure
> this patch disables echo on the modem port completely.
>
> These changes have been tested with a Telit HE910 modem only. As the
> documentation for earlier Telit modems is almost identical, I expect
> this new control flow to work with those modems as well. That said, it
> would be good if that could be tested with someone with such a modem.
> ---
> plugins/telit.c | 138 ++++++++++++++++++++++++++++++++++++++++++++++----------
> 1 file changed, 114 insertions(+), 24 deletions(-)
>
> diff --git a/plugins/telit.c b/plugins/telit.c
> index f661ab9..2b625da 100644
> --- a/plugins/telit.c
> +++ b/plugins/telit.c
> @@ -63,6 +63,7 @@
> #endif
>
> static const char *none_prefix[] = { NULL };
> +static const char *simdet_prefix[]= { "#SIMDET:", NULL };
> #ifdef NEED_BLUETOOTH
> static const char *rsen_prefix[]= { "#RSEN:", NULL };
> #endif
> @@ -242,13 +243,32 @@ static void switch_sim_state_status(struct ofono_modem *modem, int status)
> }
> break;
> case 1: /* SIM inserted */
> - case 2: /* SIM inserted and PIN unlocked */
> + /* If PIN is required, we need to inform ofono that sim is inserted. */
> if (data->have_sim == FALSE) {
> ofono_sim_inserted_notify(data->sim, TRUE);
> data->have_sim = TRUE;
> }
> break;
> + case 2: /* SIM inserted and PIN unlocked */
> + /* The voicecall atom cannot be created until the SIM is
> + * unlocked and ready for use.
> + */
> + ofono_voicecall_create(modem, 0, "atmodem", data->chat);
> +
You can simply move this part to post_sim or post_online
> + /*
> + * Tell the modem not to automatically initiate auto-attach
> + * proceedures on its own. Again, this command requires a
> + * functional SIM in order to succeed.
> + */
> + g_at_chat_send(data->chat, "AT#AUTOATT=0", none_prefix,
> + NULL, NULL, NULL);
> +
> + break;
> case 3: /* SIM inserted, SMS and phonebook ready */
> + if (data->have_sim == FALSE) {
> + ofono_sim_inserted_notify(data->sim, TRUE);
> + data->have_sim = TRUE;
> + }
> if (data->sms_phonebook_added == FALSE) {
> ofono_phonebook_create(modem, 0, "atmodem", data->chat);
> ofono_sms_create(modem, 0, "atmodem", data->chat);
> @@ -279,6 +299,46 @@ static void telit_qss_notify(GAtResult *result, gpointer user_data)
> switch_sim_state_status(modem, status);
> }
>
> +static void simdet_query_cb(gboolean ok, GAtResult *result, gpointer user_data)
> +{
> + struct ofono_modem *modem = user_data;
> + struct telit_data *data = ofono_modem_get_data(modem);
> + struct ofono_modem *m = data->sap_modem ? : modem;
> + GAtResultIter iter;
> + int mode;
> + int inserted;
> +
> + DBG("%p", modem);
> +
> + if (!ok)
> + return;
> +
> + g_at_result_iter_init(&iter, result);
> +
> + if (!g_at_result_iter_next(&iter, "#SIMDET:"))
> + return;
> +
> + g_at_result_iter_next_number(&iter,&mode);
> + g_at_result_iter_next_number(&iter,&inserted);
> +
> + g_at_chat_send(data->chat, "AT#QSS=2", none_prefix, NULL, NULL, NULL);
> +
> + /* If the SIM is already physically present, we need to tell the
> + * modem so by setting SIMDET to 1 in order for it to regenerate
> + * the QSS messages corresponding to the current state
> + */
> + if (inserted) {
> + g_at_chat_send(data->chat, "AT#SIMDET=1", none_prefix,
> + NULL, NULL, NULL);
> + }
> +
> + /* Restore SIM presence detection via SIMIN pin */
> + g_at_chat_send(data->chat, "AT#SIMDET=2", none_prefix,
> + NULL, NULL, NULL);
> +
> + ofono_modem_set_powered(m, TRUE);
> +}
> +
> static void cfun_enable_cb(gboolean ok, GAtResult *result, gpointer user_data)
> {
> struct ofono_modem *modem = user_data;
> @@ -307,21 +367,14 @@ static void cfun_enable_cb(gboolean ok, GAtResult *result, gpointer user_data)
> data->have_sim = FALSE;
> data->sms_phonebook_added = FALSE;
>
> - ofono_modem_set_powered(m, TRUE);
> + /* Set modem 'offline' */
> + g_at_chat_send(data->chat, "AT+COPS=2", none_prefix, NULL, NULL, NULL);
>
> - /*
> - * Tell the modem not to automatically initiate auto-attach
> - * proceedures on its own.
> + /* Re-enabling QSS reporting requires that we manually poke the
> + * modem with its current state... this requires querying SIMDET
> */
> - g_at_chat_send(data->chat, "AT#AUTOATT=0", none_prefix,
> - NULL, NULL, NULL);
> -
> - /* Follow sim state */
> - g_at_chat_register(data->chat, "#QSS:", telit_qss_notify,
> - FALSE, modem, NULL);
> -
> - /* Enable sim state notification */
> - g_at_chat_send(data->chat, "AT#QSS=2", none_prefix, NULL, NULL, NULL);
> + g_at_chat_send(data->chat, "AT#SIMDET?", simdet_prefix,
> + simdet_query_cb, modem, NULL);
> }
>
> static int telit_enable(struct ofono_modem *modem)
> @@ -349,15 +402,52 @@ static int telit_enable(struct ofono_modem *modem)
> */
> g_at_chat_send(data->chat, "ATE0 +CMEE=1", none_prefix,
> NULL, NULL, NULL);
> + /* The Telit modem loses command responses when ECHO is on...
> + * it is a bug and Telit has been informed of it, but the
> + * easiest way forward for now is to just disable ECHO on
> + * the modem port.
> + */
> + g_at_chat_send(data->modem, "ATE0", none_prefix,
> + NULL, NULL, NULL);
>
> - /*
> - * Disable sim state notification so that we sure get a notification
> - * when we enable it again later and don't have to query it.
> + /* Telit is quirky, quirky, quirky; getting a reliable QSS
> + * indication at startup is tricky.
> + * - QSS transitions aren't necessarily sent when the SIM
> + * is first powered on
> + * - The QSS state, if 1, doesn't automatically transition
> + * to 2/3 when QSS mode=2 is set.
> + * In order to ensure that we get a reliable QSS indication,
> + * the SIM to needs to be logically (or physically) reinserted
> + * when the SIM core is powered up.
> + *
> + * The SIMIN pin will correctly trigger a QSS transition, but
> + * it's edge-triggered so that it won't trigger a QSS indication
> + * unless a SIM is physically reinserted; it's therefore necessary
> + * to do a "soft" reinsertion by way of the SIMDET command. The
> + * sequence that reliably works is:
> + * - set QSS=0
> + * - set SIMDET to 0 (SIM logically removed)
> + * - put modem into CFUN!=4 in order to power up the SIM
> + * - when modem is powered, set QSS=2
> + * - check SIMDET value to see if SIM is physically inserted
> + * or not; if yes, we need to manually trigger a QSS transition
> + * by doing a "soft insertion"; we do this by setting SIMDET=1
> + * (SIM logically inserted)
> + * - then we can set SIMDET=2 to enable SIM hotplug the rest
> + * of the way.
> */
> +
> + /* Follow sim state */
> g_at_chat_send(data->chat, "AT#QSS=0", none_prefix, NULL, NULL, NULL);
> + g_at_chat_send(data->chat, "AT#SIMDET=0", none_prefix,
> + NULL, NULL, NULL);
> + g_at_chat_register(data->chat, "#QSS:", telit_qss_notify,
> + FALSE, modem, NULL);
>
> - /* Set phone functionality */
> - g_at_chat_send(data->chat, "AT+CFUN=4", none_prefix,
> + /* Set modem to full functionality... this is required to have the
> + * SIM powered up which is pretty much a prerequisite for Ofono.
> + */
> + g_at_chat_send(data->chat, "AT+CFUN=1", none_prefix,
> cfun_enable_cb, modem, NULL);
>
> return -EINPROGRESS;
> @@ -437,7 +527,7 @@ static int telit_disable(struct ofono_modem *modem)
> g_at_chat_unregister_all(data->chat);
>
> /* Power down modem */
> - g_at_chat_send(data->chat, "AT+CFUN=0", none_prefix,
> + g_at_chat_send(data->chat, "AT+CFUN=4", none_prefix,
> cfun_disable_cb, modem, NULL);
>
> return -EINPROGRESS;
> @@ -565,9 +655,9 @@ static void telit_pre_sim(struct ofono_modem *modem)
> DBG("%p", modem);
>
> ofono_devinfo_create(modem, 0, "atmodem", data->chat);
> - data->sim = ofono_sim_create(modem, OFONO_VENDOR_TELIT, "atmodem",
> - data->chat);
> - ofono_voicecall_create(modem, 0, "atmodem", data->chat);
> + data->sim = ofono_sim_create(modem, OFONO_VENDOR_TELIT,
> + "atmodem", data->chat);
> +
> }
>
> static void telit_post_sim(struct ofono_modem *modem)
> @@ -604,7 +694,7 @@ static void telit_set_online(struct ofono_modem *modem, ofono_bool_t online,
> {
> struct telit_data *data = ofono_modem_get_data(modem);
> struct cb_data *cbd = cb_data_new(cb, user_data);
> - char const *command = online ? "AT+CFUN=1,0" : "AT+CFUN=4,0";
> + char const *command = online ? "AT+COPS=0" : "AT+COPS=2";
As mentioned before, I really don't like this due to potential side
effects with the netreg atom.
>
> DBG("modem %p %s", modem, online ? "online" : "offline");
>
Regards,
-Denis
next prev parent reply other threads:[~2013-04-08 18:29 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-04-04 8:20 [PATCH 0/3] Telit plugin rework for HE910 Jonas Bonn
2013-04-04 8:20 ` [PATCH 1/3] udevng: support telit modems using cdc-acm driver Jonas Bonn
2013-04-04 8:20 ` [PATCH 2/3] telit: allow plugin to be compiled without BT support Jonas Bonn
2013-04-04 8:20 ` [PATCH 3/3] telit: rework for HE910 Jonas Bonn
2013-04-08 18:29 ` Denis Kenzior [this message]
2013-04-05 8:58 ` [PATCH 0/3] Telit plugin " Etienne Mabille
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=51630C95.4090805@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