Open Source Telephony
 help / color / mirror / Atom feed
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

  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