All of lore.kernel.org
 help / color / mirror / Atom feed
From: Viallard Anthony <viallard@syscom-instruments.com>
To: ofono@ofono.org
Subject: SIMCOM support
Date: Thu, 24 Jan 2013 13:48:43 +0100	[thread overview]
Message-ID: <51012DAB.9000108@syscom-instruments.com> (raw)

[-- Attachment #1: Type: text/plain, Size: 2120 bytes --]

Hello ofono guys,

I've got a embedded device with SIM5216E modem. Based on the previous 
work done by my colleague Jean-Christian de Rivaz (you can see previous 
talk on this mailing list about this modem "Some experiments with the 
SIMCOM SIM5216E modem on a ARM926 board"), the simcom AT doc, my 
MacGyver kit and my resourcefulness, i do a patch for ofono to support 
this modem (and maybe others models).

I attach the patch to this email.

While making this patch, I wondered about that :

    * After entering a pin code, ofono goes too fast and checks too 
early the sim pin status with "CPIN?". The ME responds "CME Error : 14 
(SIM busy)" and ofono stops here. Ofono doesn't send more CPIN? or 
intercept the "+CPIN: READY" that the modem send after a while when SIM 
is back online. So, I use the same workaround that for ZTE : sending 
severals AT+CPIN? commands during 20 seconds until having "+CPIN: 
READY". It works well but as my modem sends the "+CPIN: READY" from its 
own, I think I can use another mechanism more "standard" in ofono, isn't 
it ?

    * I want to save power when i doesn't need the modem. So, i guess it 
is the purpose of the "org.ofono.Modem.SetProperty" dbus method and the 
setting "Powered". When I set "Powered" to "False", I see ofono calls 
the "disable" callback of "struct ofono_modem_driver", so I think its 
here I must write the famous CFUN command(s) to put modem down. In the 
AT doc for SIMCOM, I have severals CFUN values for, i think, disable 
purpose :

0 – minimum functionality
4 – disable phone both transmit and receive RF circuits
7 – Offline Mode

For now, i do a CFUN=4 but maybe i need to do more and add CFUN=7 ? Or 
maybe use CFUN=0 ?

Can the "disable" callback be called by ofono in other case and so, i 
must only do a CFUN=4 ?

    * I would like to do a reset of the modem at start and at end of 
ofono life (with AT+CFUN=6 or AT+CRESET). The purpose is having a modem 
always in init state for ofono and the others programs. Do you think its 
a good idea ?

Best regards,
Anthony Viallard.



[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: ofono-simcom-support.patch --]
[-- Type: text/x-patch, Size: 10584 bytes --]

Add SIMCOM support.

I develop this with the SIM5216E chipset. SMS and GPRS work.
I don't do the voice call part because i don't need it.

Signed-off-by: Anthony Viallard <homer242 at gmail.com>
--- ofono-1.6.orig/Makefile.am	2012-04-20 21:06:29.000000000 +0200
+++ ofono-1.6/Makefile.am	2013-01-21 17:17:48.089627277 +0100
@@ -371,6 +371,9 @@ builtin_sources += plugins/samsung.c
 builtin_modules += sim900
 builtin_sources += plugins/sim900.c
 
+builtin_modules += simcom
+builtin_sources += plugins/simcom.c
+
 if BLUETOOTH
 builtin_modules += bluetooth
 builtin_sources += plugins/bluetooth.c plugins/bluetooth.h
--- ofono-1.6.orig/drivers/atmodem/sms.c	2012-04-20 21:06:29.000000000 +0200
+++ ofono-1.6/drivers/atmodem/sms.c	2013-01-21 16:48:44.460627485 +0100
@@ -805,6 +807,7 @@ static gboolean build_cnmi_string(char *
 	case OFONO_VENDOR_NOVATEL:
 	case OFONO_VENDOR_HUAWEI:
 	case OFONO_VENDOR_ZTE:
+	case OFONO_VENDOR_SIMCOM:
 		/* MSM devices advertise support for mode 2, but return an
 		 * error if we attempt to actually use it. */
 		mode = "1";
diff -pruN ofono-1.6.orig/drivers/atmodem/sim.c ofono-1.6/drivers/atmodem/sim.c
--- ofono-1.6.orig/drivers/atmodem/sim.c	2013-01-23 11:38:22.959609087 +0100
+++ ofono-1.6/drivers/atmodem/sim.c	2013-01-23 11:57:52.602608948 +0100
@@ -1023,10 +1023,16 @@ static void at_pin_send_cb(gboolean ok,
 							FALSE, cbd, g_free);
 		return;
 	case OFONO_VENDOR_ZTE:
+	case OFONO_VENDOR_SIMCOM:
 		/*
 		 * On ZTE modems, after pin is entered, SIM state is checked
 		 * by polling CPIN as their modem doesn't provide unsolicited
 		 * notification of SIM readiness.
+		 *
+		 * On SIMCOM modems, SIM is busy after pin is entered (we've
+		 * got an "+CME ERROR: 14" at "AT+CPIN?" request) and ofono
+		 * don't catch the "+CPIN: READY" message sent by the modem
+		 * when SIM is ready. So, use extra CPIN to check the state.
 		 */
 		sd->sim_state_query = at_util_sim_state_query_new(sd->chat,
 						2, 20, sim_state_cb, cbd,
diff -purN ofono-1.6/drivers/atmodem/network-registration.c ofono-patched/drivers/atmodem/network-registration.c
--- ofono-1.6/drivers/atmodem/network-registration.c	2013-01-18 15:04:03.598659165 +0100
+++ ofono-patched/drivers/atmodem/network-registration.c	2013-01-18 14:54:03.256659236 +0100
@@ -1411,6 +1411,14 @@ static void at_creg_set_cb(gboolean ok,
 	}
 
 	switch (nd->vendor) {
+	case OFONO_VENDOR_SIMCOM:
+		/* Register for CSQ changes */
+		g_at_chat_send(nd->chat, "AT+AUTOCSQ=1,1", none_prefix,
+				NULL, NULL, NULL);
+
+		g_at_chat_register(nd->chat, "+CSQ:",
+ 				   csq_notify, FALSE, netreg, NULL);
+ 		break;
 	case OFONO_VENDOR_PHONESIM:
 		g_at_chat_register(nd->chat, "+CSQ:",
 					csq_notify, FALSE, netreg, NULL);
@@ -1534,7 +1537,6 @@ static void at_creg_set_cb(gboolean ok,
 		break;
 	case OFONO_VENDOR_NOKIA:
 	case OFONO_VENDOR_SAMSUNG:
-	case OFONO_VENDOR_SIMCOM:
 		/* Signal strength reporting via CIND is not supported */
 		break;
 	default:
--- /dev/null	2013-01-16 10:54:41.551089567 +0100
+++ ofono-1.6/plugins/simcom.c	2013-01-23 10:43:05.631609483 +0100
@@ -0,0 +1,308 @@
+/*
+ *
+ *  oFono - Open Source Telephony
+ *
+ *  Copyright (C) 2008-2011  Intel Corporation. All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include <stdlib.h>
+
+#include <glib.h>
+#include <gatchat.h>
+#include <gattty.h>
+
+#define OFONO_API_SUBJECT_TO_CHANGE
+#include <ofono/plugin.h>
+#include <ofono/modem.h>
+#include <ofono/devinfo.h>
+#include <ofono/netreg.h>
+#include <ofono/sim.h>
+#include <ofono/cbs.h>
+#include <ofono/sms.h>
+#include <ofono/ussd.h>
+#include <ofono/gprs.h>
+#include <ofono/gprs-context.h>
+#include <ofono/radio-settings.h>
+#include <ofono/phonebook.h>
+#include <ofono/log.h>
+
+#include <drivers/atmodem/atutil.h>
+#include <drivers/atmodem/vendor.h>
+
+static const char *none_prefix[] = { NULL };
+
+struct simcom_data {
+	GAtChat *modem;
+	GAtChat *data;
+};
+
+/* Callback and helpers functions */
+static void simcom_debug(const char *str, void *user_data)
+{
+	const char *prefix = user_data;
+
+	ofono_info("%s%s", prefix, str);
+}
+
+static void cfun_enable(gboolean ok, GAtResult *result, gpointer user_data)
+{
+	struct ofono_modem *modem = user_data;
+	struct simcom_data *data = ofono_modem_get_data(modem);
+
+	DBG("");
+
+	if (!ok) {
+		g_at_chat_unref(data->modem);
+		data->modem = NULL;
+
+		g_at_chat_unref(data->data);
+		data->data = NULL;
+
+		ofono_modem_set_powered(modem, FALSE);
+		return;
+	}
+
+	ofono_modem_set_powered(modem, TRUE);
+}
+
+static void cfun_disable(gboolean ok, GAtResult *result, gpointer user_data)
+{
+	struct ofono_modem *modem = user_data;
+	struct simcom_data *data = ofono_modem_get_data(modem);
+
+	DBG("");
+
+	g_at_chat_unref(data->data);
+	data->data = NULL;
+
+	if (ok)
+		ofono_modem_set_powered(modem, FALSE);
+}
+
+static GAtChat *open_device(struct ofono_modem *modem,
+			    const char *key,
+			    char *debug)
+{
+	const char *device;
+	GIOChannel *channel;
+	GAtSyntax *syntax;
+	GAtChat *chat;
+	/* GHashTable *options; */
+
+	device = ofono_modem_get_string(modem, key);
+	if (device == NULL)
+		return NULL;
+
+	DBG("%s %s", key, device);
+
+	/* options = g_hash_table_new(g_str_hash, g_str_equal); */
+	/* if (options == NULL) */
+	/* 	return NULL; */
+
+	/* g_hash_table_insert(options, "Baud", "115200"); */
+	/* g_hash_table_insert(options, "Parity", "none"); */
+	/* g_hash_table_insert(options, "StopBits", "1"); */
+	/* g_hash_table_insert(options, "DataBits", "8"); */
+	/* g_hash_table_insert(options, "XonXoff", "off"); */
+	/* g_hash_table_insert(options, "RtsCts", "on"); */
+	/* g_hash_table_insert(options, "Local", "on"); */
+	/* g_hash_table_insert(options, "Read", "on"); */
+
+	channel = g_at_tty_open(device, NULL);
+
+	/* g_hash_table_destroy(options); */
+
+	if (channel == NULL)
+		return NULL;
+
+	syntax = g_at_syntax_new_gsm_permissive();
+	chat = g_at_chat_new(channel, syntax);
+	g_at_syntax_unref(syntax);
+
+	g_io_channel_unref(channel);
+
+	if (chat == NULL)
+		return NULL;
+
+	if (getenv("OFONO_AT_DEBUG"))
+		g_at_chat_set_debug(chat, simcom_debug, debug);
+
+	return chat;
+}
+
+/* Modem interface function */
+static int simcom_probe(struct ofono_modem *modem)
+{
+	struct simcom_data *data;
+
+	DBG("%p", modem);
+
+	data = g_try_new0(struct simcom_data, 1);
+	if (data == NULL)
+		return -ENOMEM;
+
+	ofono_modem_set_data(modem, data);
+
+	return 0;
+}
+
+static void simcom_remove(struct ofono_modem *modem)
+{
+	struct simcom_data *data = ofono_modem_get_data(modem);
+
+	DBG("%p", modem);
+
+	ofono_modem_set_data(modem, NULL);
+
+	/* Cleanup after hot-unplug */
+	g_at_chat_unref(data->data);
+
+	g_free(data);
+}
+
+static int simcom_enable(struct ofono_modem *modem)
+{
+	struct simcom_data *data = ofono_modem_get_data(modem);
+
+	DBG("%p", modem);
+
+	data->modem = open_device(modem, "Modem", "Modem: ");
+	if (data->modem == NULL)
+		return -EINVAL;
+
+	data->data = open_device(modem, "Data", "Data: ");
+	if (data->data == NULL) {
+		g_at_chat_unref(data->modem);
+		data->modem = NULL;
+		return -EIO;
+	}
+
+	g_at_chat_set_slave(data->modem, data->data);
+
+	g_at_chat_blacklist_terminator(data->data,
+					G_AT_CHAT_TERMINATOR_NO_CARRIER);
+
+	/* init modem */
+	g_at_chat_send(data->modem, "ATE0 +CMEE=1", NULL, NULL, NULL, NULL);
+	g_at_chat_send(data->data, "ATE0 +CMEE=1", NULL, NULL, NULL, NULL);
+
+	g_at_chat_send(data->data, "AT+CFUN=1", none_prefix,
+		       cfun_enable, modem, NULL);
+
+	return -EINPROGRESS;
+}
+
+static int simcom_disable(struct ofono_modem *modem)
+{
+	struct simcom_data *data = ofono_modem_get_data(modem);
+
+	DBG("%p", modem);
+
+	g_at_chat_cancel_all(data->modem);
+	g_at_chat_unregister_all(data->modem);
+
+	g_at_chat_unref(data->modem);
+	data->modem = NULL;
+
+	g_at_chat_cancel_all(data->data);
+	g_at_chat_unregister_all(data->data);
+
+	g_at_chat_send(data->data, "AT+CFUN=4", none_prefix,
+		       cfun_disable, modem, NULL);
+
+	return -EINPROGRESS;
+}
+
+static void simcom_pre_sim(struct ofono_modem *modem)
+{
+	struct simcom_data *data = ofono_modem_get_data(modem);
+	struct ofono_sim *sim;
+
+	DBG("%p", modem);
+
+	ofono_devinfo_create(modem, 0, "atmodem", data->data);
+	sim = ofono_sim_create(modem, OFONO_VENDOR_SIMCOM, "atmodem",
+				data->data);
+
+	if (sim)
+		ofono_sim_inserted_notify(sim, TRUE);
+}
+
+static void simcom_post_sim(struct ofono_modem *modem)
+{
+	struct simcom_data *data = ofono_modem_get_data(modem);
+	struct ofono_message_waiting *mw;
+	struct ofono_gprs *gprs;
+	struct ofono_gprs_context *gc;
+
+	DBG("%p", modem);
+
+	ofono_phonebook_create(modem, 0, "atmodem", data->data);
+
+	ofono_sms_create(modem, OFONO_VENDOR_SIMCOM, "atmodem",
+				data->data);
+
+	/* gprs things */
+	gprs = ofono_gprs_create(modem, 0, "atmodem", data->data);
+	gc = ofono_gprs_context_create(modem, 0, "atmodem", data->modem);
+
+	if(gprs && gc)
+	{
+		ofono_gprs_add_context(gprs, gc);
+	}
+}
+
+static void simcom_post_online(struct ofono_modem *modem)
+{
+	struct simcom_data *data = ofono_modem_get_data(modem);
+
+	DBG("%p", modem);
+
+	ofono_netreg_create(modem, OFONO_VENDOR_SIMCOM, "atmodem", data->data);
+	ofono_cbs_create(modem, 0, "atmodem", data->data);
+	ofono_ussd_create(modem, 0, "atmodem", data->data);
+}
+
+static struct ofono_modem_driver simcom_driver = {
+	.name		= "simcom",
+	.probe		= simcom_probe,
+	.remove		= simcom_remove,
+	.enable		= simcom_enable,
+	.disable	= simcom_disable,
+	.pre_sim	= simcom_pre_sim,
+	.post_sim	= simcom_post_sim,
+	.post_online	= simcom_post_online,
+};
+
+static int simcom_init(void)
+{
+	return ofono_modem_driver_register(&simcom_driver);
+}
+
+static void simcom_exit(void)
+{
+	ofono_modem_driver_unregister(&simcom_driver);
+}
+
+OFONO_PLUGIN_DEFINE(simcom, "SIMCOM modem driver", VERSION,
+		    OFONO_PLUGIN_PRIORITY_DEFAULT,
+		    simcom_init, simcom_exit)

             reply	other threads:[~2013-01-24 12:48 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-01-24 12:48 Viallard Anthony [this message]
2013-01-24 16:21 ` SIMCOM support Denis Kenzior
2013-01-24 17:13   ` Viallard Anthony
2013-01-24 18:21     ` Denis Kenzior
2013-01-25  9:01       ` Renat Zaripov
  -- strict thread matches above, loose matches on Subject: below --
2013-07-19 13:33 Viallard Anthony
2013-07-19 13:55 ` Jesper Larsen

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=51012DAB.9000108@syscom-instruments.com \
    --to=viallard@syscom-instruments.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.