All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH_v2 0/4] Use sim atom with cdma modems
@ 2011-11-21 10:54 Guillaume Zajac
  2011-11-21 10:54 ` [PATCH_v2 1/4] cdmamodem: Add sim driver implementation Guillaume Zajac
                   ` (3 more replies)
  0 siblings, 4 replies; 10+ messages in thread
From: Guillaume Zajac @ 2011-11-21 10:54 UTC (permalink / raw)
  To: ofono

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

Hi,

Changelog from v1:
	- Implement sim specific cdmamodem drivers.
	- If no read drivers are implemented, call callback with failure
	  to continue with sim initialization routines.
	- If SIM is embedded but AT+CPIN? answers SIM not inserted, continue
	  with sim_initialize_after_pin() to get the IMSI.

Kind regards,
Guillaume

Guillaume Zajac (4):
  cdmamodem: Add sim driver implementation
  simfs: Call callback with failure if driver is not implemented
  huaweicdma: Add SIM creation and set_online method driver
  sim: Get IMSI if sim state is OFONO_SIM_STATE_INSERTED

 Makefile.am                   |    3 +-
 drivers/cdmamodem/cdmamodem.c |    2 +
 drivers/cdmamodem/cdmamodem.h |    3 +
 drivers/cdmamodem/sim.c       |  582 +++++++++++++++++++++++++++++++++++++++++
 plugins/huaweicdma.c          |  283 +++++++++++++++++++-
 src/sim.c                     |    2 +
 src/simfs.c                   |    4 +-
 7 files changed, 870 insertions(+), 9 deletions(-)
 create mode 100644 drivers/cdmamodem/sim.c


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH_v2 1/4] cdmamodem: Add sim driver implementation
  2011-11-21 10:54 [PATCH_v2 0/4] Use sim atom with cdma modems Guillaume Zajac
@ 2011-11-21 10:54 ` Guillaume Zajac
  2011-11-27 12:02   ` Denis Kenzior
  2011-11-21 10:54 ` [PATCH_v2 2/4] simfs: Call callback with failure if driver is not implemented Guillaume Zajac
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 10+ messages in thread
From: Guillaume Zajac @ 2011-11-21 10:54 UTC (permalink / raw)
  To: ofono

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

---
 Makefile.am                   |    3 +-
 drivers/cdmamodem/cdmamodem.c |    2 +
 drivers/cdmamodem/cdmamodem.h |    3 +
 drivers/cdmamodem/sim.c       |  582 +++++++++++++++++++++++++++++++++++++++++
 4 files changed, 589 insertions(+), 1 deletions(-)
 create mode 100644 drivers/cdmamodem/sim.c

diff --git a/Makefile.am b/Makefile.am
index 337aeb7..db39000 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -273,7 +273,8 @@ builtin_sources += drivers/cdmamodem/cdmamodem.h \
 			drivers/cdmamodem/cdmamodem.c \
 			drivers/cdmamodem/voicecall.c \
 			drivers/cdmamodem/devinfo.c \
-			drivers/cdmamodem/connman.c
+			drivers/cdmamodem/connman.c \
+			drivers/cdmamodem/sim.c
 
 builtin_modules += huaweicdmamodem
 builtin_sources += drivers/huaweicdmamodem/huaweicdmamodem.h \
diff --git a/drivers/cdmamodem/cdmamodem.c b/drivers/cdmamodem/cdmamodem.c
index 50908e3..771b408 100644
--- a/drivers/cdmamodem/cdmamodem.c
+++ b/drivers/cdmamodem/cdmamodem.c
@@ -37,6 +37,7 @@ static int cdmamodem_init(void)
 	cdma_voicecall_init();
 	cdma_devinfo_init();
 	cdma_connman_init();
+	cdma_sim_init();
 
 	return 0;
 }
@@ -46,6 +47,7 @@ static void cdmamodem_exit(void)
 	cdma_voicecall_exit();
 	cdma_devinfo_exit();
 	cdma_connman_exit();
+	cdma_sim_exit();
 }
 
 OFONO_PLUGIN_DEFINE(cdmamodem, "CDMA AT modem driver", VERSION,
diff --git a/drivers/cdmamodem/cdmamodem.h b/drivers/cdmamodem/cdmamodem.h
index 3554705..53b617d 100644
--- a/drivers/cdmamodem/cdmamodem.h
+++ b/drivers/cdmamodem/cdmamodem.h
@@ -20,6 +20,7 @@
  */
 
 #include <drivers/atmodem/atutil.h>
+#include <drivers/atmodem/vendor.h>
 
 extern void cdma_voicecall_init(void);
 extern void cdma_voicecall_exit(void);
@@ -27,3 +28,5 @@ extern void cdma_devinfo_init(void);
 extern void cdma_devinfo_exit(void);
 extern void cdma_connman_init(void);
 extern void cdma_connman_exit(void);
+extern void cdma_sim_init(void);
+extern void cdma_sim_exit(void);
diff --git a/drivers/cdmamodem/sim.c b/drivers/cdmamodem/sim.c
new file mode 100644
index 0000000..26cd572
--- /dev/null
+++ b/drivers/cdmamodem/sim.c
@@ -0,0 +1,582 @@
+/*
+ *
+ *  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
+
+#define _GNU_SOURCE
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+
+#include <glib.h>
+
+#include <ofono/log.h>
+#include <ofono/modem.h>
+#include <ofono/sim.h>
+
+#include "gatchat.h"
+#include "gatresult.h"
+
+#include "cdmamodem.h"
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+struct sim_data {
+	GAtChat *chat;
+	unsigned int vendor;
+	guint ready_id;
+};
+
+static const char *cpin_prefix[] = { "+CPIN:", NULL };
+static const char *clck_prefix[] = { "+CLCK:", NULL };
+static const char *huawei_cpin_prefix[] = { "^CPIN:", NULL };
+static const char *cpinr_prefixes[] = { "+CPINR:", "+CPINRE:", NULL };
+static const char *none_prefix[] = { NULL };
+
+static void cdma_cimi_cb(gboolean ok, GAtResult *result, gpointer user_data)
+{
+	struct cb_data *cbd = user_data;
+	GAtResultIter iter;
+	ofono_sim_imsi_cb_t cb = cbd->cb;
+	struct ofono_error error;
+	const char *imsi;
+	int i;
+
+	decode_at_error(&error, g_at_result_final_response(result));
+
+	if (!ok) {
+		cb(&error, NULL, cbd->data);
+		return;
+	}
+
+	g_at_result_iter_init(&iter, result);
+
+	for (i = 0; i < g_at_result_num_response_lines(result); i++)
+		g_at_result_iter_next(&iter, NULL);
+
+	imsi = g_at_result_iter_raw_line(&iter);
+
+	DBG("cimi_cb: %s", imsi);
+
+	cb(&error, imsi, cbd->data);
+}
+
+static void cdma_read_imsi(struct ofono_sim *sim, ofono_sim_imsi_cb_t cb,
+			void *data)
+{
+	struct sim_data *sd = ofono_sim_get_data(sim);
+	struct cb_data *cbd = cb_data_new(cb, data);
+
+	if (g_at_chat_send(sd->chat, "AT+CIMI", NULL,
+				cdma_cimi_cb, cbd, g_free) > 0)
+		return;
+
+	g_free(cbd);
+
+	CALLBACK_WITH_FAILURE(cb, NULL, data);
+}
+
+static struct {
+	enum ofono_sim_password_type type;
+	const char *name;
+} const cdma_sim_name[] = {
+	{ OFONO_SIM_PASSWORD_NONE,		"READY"		},
+	{ OFONO_SIM_PASSWORD_SIM_PIN,		"SIM PIN"	},
+	{ OFONO_SIM_PASSWORD_SIM_PUK,		"SIM PUK"	},
+	{ OFONO_SIM_PASSWORD_PHSIM_PIN,		"PH-SIM PIN"	},
+	{ OFONO_SIM_PASSWORD_PHFSIM_PIN,	"PH-FSIM PIN"	},
+	{ OFONO_SIM_PASSWORD_PHFSIM_PUK,	"PH-FSIM PUK"	},
+	{ OFONO_SIM_PASSWORD_SIM_PIN2,		"SIM PIN2"	},
+	{ OFONO_SIM_PASSWORD_SIM_PUK2,		"SIM PUK2"	},
+	{ OFONO_SIM_PASSWORD_PHNET_PIN,		"PH-NET PIN"	},
+	{ OFONO_SIM_PASSWORD_PHNET_PUK,		"PH-NET PUK"	},
+	{ OFONO_SIM_PASSWORD_PHNETSUB_PIN,	"PH-NETSUB PIN"	},
+	{ OFONO_SIM_PASSWORD_PHNETSUB_PUK,	"PH-NETSUB PUK"	},
+	{ OFONO_SIM_PASSWORD_PHSP_PIN,		"PH-SP PIN"	},
+	{ OFONO_SIM_PASSWORD_PHSP_PUK,		"PH-SP PUK"	},
+	{ OFONO_SIM_PASSWORD_PHCORP_PIN,	"PH-CORP PIN"	},
+	{ OFONO_SIM_PASSWORD_PHCORP_PUK,	"PH-CORP PUK"	},
+};
+
+#define BUILD_PIN_RETRIES_ARRAY(passwd_types, passwd_types_cnt, retry)	\
+	for (i = 0; i < OFONO_SIM_PASSWORD_INVALID; i++)		\
+		retry[i] = -1;						\
+									\
+	for (i = 0; i < passwd_types_cnt; i++) {			\
+		int val;						\
+									\
+		if (!g_at_result_iter_next_number(&iter, &val))		\
+			goto error;					\
+									\
+		retry[passwd_types[i]] = val;				\
+									\
+		DBG("retry counter id=%d, val=%d", passwd_types[i],	\
+					retry[passwd_types[i]]);	\
+	}								\
+
+static void huawei_cpin_cb(gboolean ok, GAtResult *result, gpointer user_data)
+{
+	struct cb_data *cbd = user_data;
+	ofono_sim_pin_retries_cb_t cb = cbd->cb;
+	const char *final = g_at_result_final_response(result);
+	GAtResultIter iter;
+	struct ofono_error error;
+	int retries[OFONO_SIM_PASSWORD_INVALID];
+	size_t i;
+	static enum ofono_sim_password_type password_types[] = {
+		OFONO_SIM_PASSWORD_SIM_PUK,
+		OFONO_SIM_PASSWORD_SIM_PIN,
+		OFONO_SIM_PASSWORD_SIM_PUK2,
+		OFONO_SIM_PASSWORD_SIM_PIN2,
+	};
+
+	decode_at_error(&error, final);
+
+	if (!ok) {
+		cb(&error, NULL, cbd->data);
+		return;
+	}
+
+	g_at_result_iter_init(&iter, result);
+
+	if (!g_at_result_iter_next(&iter, "^CPIN:"))
+		goto error;
+
+	/* Skip status since we are not interested in this */
+	if (!g_at_result_iter_skip_next(&iter))
+		goto error;
+
+	/* Skip "overall counter" since we'll grab each one individually */
+	if (!g_at_result_iter_skip_next(&iter))
+		goto error;
+
+	BUILD_PIN_RETRIES_ARRAY(password_types, ARRAY_SIZE(password_types),
+				retries);
+
+	cb(&error, retries, cbd->data);
+
+	return;
+
+error:
+	CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
+}
+
+static void cdma_cpinr_cb(gboolean ok, GAtResult *result, gpointer user_data)
+{
+	struct cb_data *cbd = user_data;
+	ofono_sim_pin_retries_cb_t cb = cbd->cb;
+	GAtResultIter iter;
+	struct ofono_error error;
+	int retries[OFONO_SIM_PASSWORD_INVALID];
+	size_t len = sizeof(cdma_sim_name) / sizeof(*cdma_sim_name);
+	size_t i;
+
+	decode_at_error(&error, g_at_result_final_response(result));
+
+	if (!ok) {
+		cb(&error, NULL, cbd->data);
+		return;
+	}
+
+	for (i = 0; i < OFONO_SIM_PASSWORD_INVALID; i++)
+		retries[i] = -1;
+
+	g_at_result_iter_init(&iter, result);
+
+	/* Ignore +CPINRE results... */
+	while (g_at_result_iter_next(&iter, "+CPINR:")) {
+		const char *name;
+		int val;
+
+		if (!g_at_result_iter_next_unquoted_string(&iter, &name))
+			continue;
+
+		if (!g_at_result_iter_next_number(&iter, &val))
+			continue;
+
+		for (i = 1; i < len; i++) {
+			if (!strcmp(name, cdma_sim_name[i].name)) {
+				retries[i] = val;
+				break;
+			}
+		}
+	}
+
+	cb(&error, retries, cbd->data);
+}
+
+static void cdma_pin_retries_query(struct ofono_sim *sim,
+					ofono_sim_pin_retries_cb_t cb,
+					void *data)
+{
+	struct sim_data *sd = ofono_sim_get_data(sim);
+	struct cb_data *cbd = cb_data_new(cb, data);
+
+	DBG("");
+
+	switch (sd->vendor) {
+	case OFONO_VENDOR_HUAWEI:
+		if (g_at_chat_send(sd->chat, "AT^CPIN?", huawei_cpin_prefix,
+					huawei_cpin_cb, cbd, g_free) > 0)
+			return;
+		break;
+	default:
+		if (g_at_chat_send(sd->chat, "AT+CPINR", cpinr_prefixes,
+					cdma_cpinr_cb, cbd, g_free) > 0)
+			return;
+		break;
+	}
+
+	g_free(cbd);
+
+	CALLBACK_WITH_FAILURE(cb, NULL, data);
+}
+
+static void cdma_cpin_cb(gboolean ok, GAtResult *result, gpointer user_data)
+{
+	struct cb_data *cbd = user_data;
+	GAtResultIter iter;
+	ofono_sim_passwd_cb_t cb = cbd->cb;
+	struct ofono_error error;
+	const char *pin_required;
+	int pin_type = OFONO_SIM_PASSWORD_INVALID;
+	int i;
+	int len = sizeof(cdma_sim_name) / sizeof(*cdma_sim_name);
+	const char *final = g_at_result_final_response(result);
+
+	decode_at_error(&error, final);
+
+	if (!ok) {
+		cb(&error, -1, cbd->data);
+		return;
+	}
+
+	g_at_result_iter_init(&iter, result);
+
+	if (!g_at_result_iter_next(&iter, "+CPIN:")) {
+		CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
+		return;
+	}
+
+	g_at_result_iter_next_unquoted_string(&iter, &pin_required);
+
+
+	for (i = 0; i < len; i++) {
+		if (strcmp(pin_required, cdma_sim_name[i].name))
+			continue;
+
+		pin_type = cdma_sim_name[i].type;
+		break;
+	}
+
+	if (pin_type == OFONO_SIM_PASSWORD_INVALID) {
+		CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
+		return;
+	}
+
+	DBG("crsm_pin_cb: %s", pin_required);
+
+	cb(&error, pin_type, cbd->data);
+}
+
+static void cdma_pin_query(struct ofono_sim *sim, ofono_sim_passwd_cb_t cb,
+			void *data)
+{
+	struct sim_data *sd = ofono_sim_get_data(sim);
+	struct cb_data *cbd = cb_data_new(cb, data);
+
+	cbd->user = sim;
+
+	if (g_at_chat_send(sd->chat, "AT+CPIN?", cpin_prefix,
+				cdma_cpin_cb, cbd, g_free) > 0)
+		return;
+
+	g_free(cbd);
+
+	CALLBACK_WITH_FAILURE(cb, -1, data);
+}
+
+static void cdma_pin_send_cb(gboolean ok, GAtResult *result,
+				gpointer user_data)
+{
+	struct cb_data *cbd = user_data;
+	ofono_sim_lock_unlock_cb_t cb = cbd->cb;
+	struct ofono_error error;
+
+	decode_at_error(&error, g_at_result_final_response(result));
+	cb(&error, cbd->data);
+
+	g_free(cbd);
+}
+
+static void cdma_pin_send(struct ofono_sim *sim, const char *passwd,
+			ofono_sim_lock_unlock_cb_t cb, void *data)
+{
+	struct sim_data *sd = ofono_sim_get_data(sim);
+	struct cb_data *cbd = cb_data_new(cb, data);
+	char buf[64];
+	int ret;
+
+	cbd->user = sd;
+
+	snprintf(buf, sizeof(buf), "AT+CPIN=\"%s\"", passwd);
+
+	ret = g_at_chat_send(sd->chat, buf, none_prefix,
+				cdma_pin_send_cb, cbd, NULL);
+
+	memset(buf, 0, sizeof(buf));
+
+	if (ret > 0)
+		return;
+
+	g_free(cbd);
+
+	CALLBACK_WITH_FAILURE(cb, data);
+}
+
+static void cdma_pin_send_puk(struct ofono_sim *sim, const char *puk,
+				const char *passwd,
+				ofono_sim_lock_unlock_cb_t cb, void *data)
+{
+	struct sim_data *sd = ofono_sim_get_data(sim);
+	struct cb_data *cbd = cb_data_new(cb, data);
+	char buf[64];
+	int ret;
+
+	cbd->user = sd;
+
+	snprintf(buf, sizeof(buf), "AT+CPIN=\"%s\",\"%s\"", puk, passwd);
+
+	ret = g_at_chat_send(sd->chat, buf, none_prefix,
+				cdma_pin_send_cb, cbd, NULL);
+
+	memset(buf, 0, sizeof(buf));
+
+	if (ret > 0)
+		return;
+
+	g_free(cbd);
+
+	CALLBACK_WITH_FAILURE(cb, data);
+}
+
+static void cdma_lock_unlock_cb(gboolean ok, GAtResult *result,
+				gpointer user_data)
+{
+	struct cb_data *cbd = user_data;
+	ofono_sim_lock_unlock_cb_t cb = cbd->cb;
+	struct ofono_error error;
+
+	decode_at_error(&error, g_at_result_final_response(result));
+
+	cb(&error, cbd->data);
+}
+
+static const char *const cdma_clck_cpwd_fac[] = {
+	[OFONO_SIM_PASSWORD_SIM_PIN] = "SC",
+	[OFONO_SIM_PASSWORD_SIM_PIN2] = "P2",
+	[OFONO_SIM_PASSWORD_PHSIM_PIN] = "PS",
+	[OFONO_SIM_PASSWORD_PHFSIM_PIN] = "PF",
+	[OFONO_SIM_PASSWORD_PHNET_PIN] = "PN",
+	[OFONO_SIM_PASSWORD_PHNETSUB_PIN] = "PU",
+	[OFONO_SIM_PASSWORD_PHSP_PIN] = "PP",
+	[OFONO_SIM_PASSWORD_PHCORP_PIN] = "PC",
+};
+
+static void cdma_pin_enable(struct ofono_sim *sim,
+				enum ofono_sim_password_type passwd_type,
+				int enable, const char *passwd,
+				ofono_sim_lock_unlock_cb_t cb, void *data)
+{
+	struct sim_data *sd = ofono_sim_get_data(sim);
+	struct cb_data *cbd = cb_data_new(cb, data);
+	char buf[64];
+	int ret;
+	unsigned int len = sizeof(cdma_clck_cpwd_fac) / sizeof(*cdma_clck_cpwd_fac);
+
+	if (passwd_type >= len || cdma_clck_cpwd_fac[passwd_type] == NULL)
+		goto error;
+
+	snprintf(buf, sizeof(buf), "AT+CLCK=\"%s\",%i,\"%s\"",
+			cdma_clck_cpwd_fac[passwd_type], enable ? 1 : 0, passwd);
+
+	ret = g_at_chat_send(sd->chat, buf, none_prefix,
+				cdma_lock_unlock_cb, cbd, g_free);
+
+	memset(buf, 0, sizeof(buf));
+
+	if (ret > 0)
+		return;
+
+error:
+	g_free(cbd);
+
+	CALLBACK_WITH_FAILURE(cb, data);
+}
+
+static void cdma_change_passwd(struct ofono_sim *sim,
+			enum ofono_sim_password_type passwd_type,
+			const char *old_passwd, const char *new_passwd,
+			ofono_sim_lock_unlock_cb_t cb, void *data)
+{
+	struct sim_data *sd = ofono_sim_get_data(sim);
+	struct cb_data *cbd = cb_data_new(cb, data);
+	char buf[64];
+	int ret;
+	unsigned int len = sizeof(cdma_clck_cpwd_fac) / sizeof(*cdma_clck_cpwd_fac);
+
+	if (passwd_type >= len ||
+			cdma_clck_cpwd_fac[passwd_type] == NULL)
+		goto error;
+
+	snprintf(buf, sizeof(buf), "AT+CPWD=\"%s\",\"%s\",\"%s\"",
+			cdma_clck_cpwd_fac[passwd_type], old_passwd, new_passwd);
+
+	ret = g_at_chat_send(sd->chat, buf, none_prefix,
+				cdma_lock_unlock_cb, cbd, g_free);
+
+	memset(buf, 0, sizeof(buf));
+
+	if (ret > 0)
+		return;
+
+error:
+	g_free(cbd);
+
+	CALLBACK_WITH_FAILURE(cb, data);
+}
+
+static void cdma_lock_status_cb(gboolean ok, GAtResult *result,
+		gpointer user_data)
+{
+	struct cb_data *cbd = user_data;
+	GAtResultIter iter;
+	ofono_sim_locked_cb_t cb = cbd->cb;
+	struct ofono_error error;
+	int locked;
+
+	decode_at_error(&error, g_at_result_final_response(result));
+
+	if (!ok) {
+		cb(&error, -1, cbd->data);
+		return;
+	}
+
+	g_at_result_iter_init(&iter, result);
+
+	if (!g_at_result_iter_next(&iter, "+CLCK:")) {
+		CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
+		return;
+	}
+
+	g_at_result_iter_next_number(&iter, &locked);
+
+	DBG("lock_status_cb: %i", locked);
+
+	cb(&error, locked, cbd->data);
+}
+
+static void cdma_pin_query_enabled(struct ofono_sim *sim,
+				enum ofono_sim_password_type passwd_type,
+				ofono_sim_locked_cb_t cb, void *data)
+{
+	struct sim_data *sd = ofono_sim_get_data(sim);
+	struct cb_data *cbd = cb_data_new(cb, data);
+	char buf[64];
+	unsigned int len = sizeof(cdma_clck_cpwd_fac) / sizeof(*cdma_clck_cpwd_fac);
+
+	if (passwd_type >= len || cdma_clck_cpwd_fac[passwd_type] == NULL)
+		goto error;
+
+	snprintf(buf, sizeof(buf), "AT+CLCK=\"%s\",2",
+			cdma_clck_cpwd_fac[passwd_type]);
+
+	if (g_at_chat_send(sd->chat, buf, clck_prefix,
+				cdma_lock_status_cb, cbd, g_free) > 0)
+		return;
+
+error:
+	g_free(cbd);
+
+	CALLBACK_WITH_FAILURE(cb, -1, data);
+}
+
+static gboolean cdma_sim_register(gpointer user)
+{
+	struct ofono_sim *sim = user;
+
+	ofono_sim_register(sim);
+
+	return FALSE;
+}
+
+static int cdma_sim_probe(struct ofono_sim *sim, unsigned int vendor,
+				void *data)
+{
+	GAtChat *chat = data;
+	struct sim_data *sd;
+
+	sd = g_new0(struct sim_data, 1);
+	sd->chat = g_at_chat_clone(chat);
+	sd->vendor = vendor;
+
+	ofono_sim_set_data(sim, sd);
+	g_idle_add(cdma_sim_register, sim);
+
+	return 0;
+}
+
+static void cdma_sim_remove(struct ofono_sim *sim)
+{
+	struct sim_data *sd = ofono_sim_get_data(sim);
+
+	ofono_sim_set_data(sim, NULL);
+
+	g_at_chat_unref(sd->chat);
+	g_free(sd);
+}
+
+static struct ofono_sim_driver driver = {
+	.name			= "cdmamodem",
+	.probe			= cdma_sim_probe,
+	.remove			= cdma_sim_remove,
+	.read_imsi		= cdma_read_imsi,
+	.query_passwd_state	= cdma_pin_query,
+	.query_pin_retries	= cdma_pin_retries_query,
+	.send_passwd		= cdma_pin_send,
+	.reset_passwd		= cdma_pin_send_puk,
+	.lock			= cdma_pin_enable,
+	.change_passwd		= cdma_change_passwd,
+	.query_locked		= cdma_pin_query_enabled,
+};
+
+void cdma_sim_init(void)
+{
+	ofono_sim_driver_register(&driver);
+}
+
+void cdma_sim_exit(void)
+{
+	ofono_sim_driver_unregister(&driver);
+}
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH_v2 2/4] simfs: Call callback with failure if driver is not implemented
  2011-11-21 10:54 [PATCH_v2 0/4] Use sim atom with cdma modems Guillaume Zajac
  2011-11-21 10:54 ` [PATCH_v2 1/4] cdmamodem: Add sim driver implementation Guillaume Zajac
@ 2011-11-21 10:54 ` Guillaume Zajac
  2011-11-27 12:04   ` Denis Kenzior
  2011-11-21 10:54 ` [PATCH_v2 3/4] huaweicdma: Add SIM creation and set_online method driver Guillaume Zajac
  2011-11-21 10:54 ` [PATCH_v2 4/4] sim: Get IMSI if sim state is OFONO_SIM_STATE_INSERTED Guillaume Zajac
  3 siblings, 1 reply; 10+ messages in thread
From: Guillaume Zajac @ 2011-11-21 10:54 UTC (permalink / raw)
  To: ofono

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

---
 src/simfs.c |    4 +++-
 1 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/src/simfs.c b/src/simfs.c
index 875e194..58dc41d 100644
--- a/src/simfs.c
+++ b/src/simfs.c
@@ -901,8 +901,10 @@ int sim_fs_read(struct ofono_sim_context *context, int id,
 	if (fs->driver == NULL)
 		return -EINVAL;
 
-	if (fs->driver->read_file_info == NULL)
+	if (fs->driver->read_file_info == NULL) {
+		cb(0, 0, 0, NULL, 0, data);
 		return -ENOSYS;
+	}
 
 	if (fs->op_q == NULL)
 		fs->op_q = g_queue_new();
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH_v2 3/4] huaweicdma: Add SIM creation and set_online method driver
  2011-11-21 10:54 [PATCH_v2 0/4] Use sim atom with cdma modems Guillaume Zajac
  2011-11-21 10:54 ` [PATCH_v2 1/4] cdmamodem: Add sim driver implementation Guillaume Zajac
  2011-11-21 10:54 ` [PATCH_v2 2/4] simfs: Call callback with failure if driver is not implemented Guillaume Zajac
@ 2011-11-21 10:54 ` Guillaume Zajac
  2011-11-27 14:29   ` Denis Kenzior
  2011-11-21 10:54 ` [PATCH_v2 4/4] sim: Get IMSI if sim state is OFONO_SIM_STATE_INSERTED Guillaume Zajac
  3 siblings, 1 reply; 10+ messages in thread
From: Guillaume Zajac @ 2011-11-21 10:54 UTC (permalink / raw)
  To: ofono

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

---
 plugins/huaweicdma.c |  283 ++++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 276 insertions(+), 7 deletions(-)

diff --git a/plugins/huaweicdma.c b/plugins/huaweicdma.c
index 4c83114..0fd9ef2 100644
--- a/plugins/huaweicdma.c
+++ b/plugins/huaweicdma.c
@@ -37,10 +37,28 @@
 #include <ofono/cdma-netreg.h>
 #include <ofono/cdma-connman.h>
 #include <ofono/log.h>
+#include <ofono.h>
+
+#include <drivers/atmodem/atutil.h>
+#include <drivers/atmodem/vendor.h>
+
+static const char *none_prefix[] = { NULL };
+static const char *sysinfo_prefix[] = { "^SYSINFO:", NULL };
+
+enum {
+	SIM_STATE_VALID =		1,
+	SIM_STATE_EMBEDDED =		240,
+	SIM_STATE_NOT_EXISTENT =	255,
+};
 
 struct huaweicdma_data {
 	GAtChat *modem;
 	GAtChat *pcui;
+	gboolean have_sim;
+	int sim_state;
+	guint sysinfo_poll_source;
+	guint sysinfo_poll_count;
+	struct cb_data *online_cbd;
 };
 
 static void huaweicdma_debug(const char *str, void *data)
@@ -79,6 +97,122 @@ static void huaweicdma_remove(struct ofono_modem *modem)
 	g_free(data);
 }
 
+static void simst_notify(GAtResult *result, gpointer user_data)
+{
+	struct ofono_modem *modem = user_data;
+	struct huaweicdma_data *data = ofono_modem_get_data(modem);
+	GAtResultIter iter;
+	int sim_state;
+
+	g_at_result_iter_init(&iter, result);
+
+	if (!g_at_result_iter_next(&iter, "^SIMST:"))
+		return;
+
+	if (!g_at_result_iter_next_number(&iter, &sim_state))
+		return;
+
+	DBG("%d -> %d", data->sim_state, sim_state);
+
+	data->sim_state = sim_state;
+}
+
+static gboolean parse_sysinfo_result(GAtResult *result, int *srv_status,
+					int *srv_domain, int *sim_state)
+{
+	GAtResultIter iter;
+
+	g_at_result_iter_init(&iter, result);
+
+	if (!g_at_result_iter_next(&iter, "^SYSINFO:"))
+		return FALSE;
+
+	if (!g_at_result_iter_next_number(&iter, srv_status))
+		return FALSE;
+
+	if (!g_at_result_iter_next_number(&iter, srv_domain))
+		return FALSE;
+
+	if (!g_at_result_iter_skip_next(&iter))
+		return FALSE;
+
+	if (!g_at_result_iter_skip_next(&iter))
+		return FALSE;
+
+	if (!g_at_result_iter_next_number(&iter, sim_state))
+		return FALSE;
+
+	return TRUE;
+}
+
+static void shutdown_device(struct huaweicdma_data *data)
+{
+	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->pcui);
+	g_at_chat_unregister_all(data->pcui);
+
+	g_at_chat_unref(data->pcui);
+	data->pcui = NULL;
+}
+
+static gboolean sysinfo_enable_check(gpointer user_data);
+
+static void sysinfo_enable_cb(gboolean ok, GAtResult *result,
+						gpointer user_data)
+{
+	struct ofono_modem *modem = user_data;
+	struct huaweicdma_data *data = ofono_modem_get_data(modem);
+	int srv_status, srv_domain, sim_state;
+
+	if (!ok)
+		goto failure;
+
+	if (parse_sysinfo_result(result, &srv_status, &srv_domain,
+						&sim_state) == FALSE)
+		goto failure;
+
+	DBG("%d -> %d", data->sim_state, sim_state);
+
+	data->sim_state = sim_state;
+
+	if (sim_state == SIM_STATE_NOT_EXISTENT) {
+		data->sysinfo_poll_count++;
+
+		if (data->sysinfo_poll_count > 5)
+			goto failure;
+
+		data->sysinfo_poll_source = g_timeout_add_seconds(1,
+						sysinfo_enable_check, modem);
+		return;
+	}
+
+	data->have_sim = TRUE;
+	ofono_modem_set_powered(modem, TRUE);
+	return;
+
+failure:
+	shutdown_device(data);
+	ofono_modem_set_powered(modem, FALSE);
+}
+
+static gboolean sysinfo_enable_check(gpointer user_data)
+{
+	struct ofono_modem *modem = user_data;
+	struct huaweicdma_data *data = ofono_modem_get_data(modem);
+
+	data->sysinfo_poll_source = 0;
+
+	g_at_chat_send(data->pcui, "AT^SYSINFO", sysinfo_prefix,
+					sysinfo_enable_cb, modem, NULL);
+
+	return FALSE;
+}
+
 static void cfun_enable(gboolean ok, GAtResult *result, gpointer user_data)
 {
 	struct ofono_modem *modem = user_data;
@@ -87,14 +221,18 @@ static void cfun_enable(gboolean ok, GAtResult *result, gpointer user_data)
 	DBG("");
 
 	if (!ok) {
-		g_at_chat_unref(data->modem);
-		data->modem = NULL;
-
-		g_at_chat_unref(data->pcui);
-		data->pcui = NULL;
+		shutdown_device(data);
+		ofono_modem_set_powered(modem, FALSE);
+		return;
 	}
 
-	ofono_modem_set_powered(modem, ok);
+	/* Follow sim state changes */
+	g_at_chat_register(data->pcui, "^SIMST:", simst_notify,
+						FALSE, modem, NULL);
+
+	data->sysinfo_poll_count = 0;
+
+	sysinfo_enable_check(modem);
 }
 
 static GAtChat *open_device(struct ofono_modem *modem,
@@ -150,6 +288,8 @@ static int huaweicdma_enable(struct ofono_modem *modem)
 	g_at_chat_send(data->modem, "ATE0 &C0 +CMEE=1", NULL, NULL, NULL, NULL);
 	g_at_chat_send(data->pcui, "ATE0 &C0 +CMEE=1", NULL, NULL, NULL, NULL);
 
+	data->sim_state = SIM_STATE_NOT_EXISTENT;
+
 	g_at_chat_send(data->pcui, "AT+CFUN=1", NULL,
 					cfun_enable, modem, NULL);
 
@@ -191,18 +331,146 @@ static int huaweicdma_disable(struct ofono_modem *modem)
 	return -EINPROGRESS;
 }
 
+
+static gboolean sysinfo_online_check(gpointer user_data);
+
+static void sysinfo_online_cb(gboolean ok, GAtResult *result,
+						gpointer user_data)
+{
+	struct huaweicdma_data *data = user_data;
+	ofono_modem_online_cb_t cb = data->online_cbd->cb;
+	int srv_status, srv_domain, sim_state;
+
+	if (!ok)
+		goto failure;
+
+	if (parse_sysinfo_result(result, &srv_status, &srv_domain,
+							&sim_state) == FALSE)
+		goto failure;
+
+	DBG("%d -> %d", data->sim_state, sim_state);
+
+	data->sim_state = sim_state;
+
+	/* Valid service status and at minimum PS domain */
+	if (srv_status > 0 && srv_domain > 1) {
+		CALLBACK_WITH_SUCCESS(cb, data->online_cbd->data);
+		goto done;
+	}
+
+	switch (sim_state) {
+	case SIM_STATE_VALID:
+	case SIM_STATE_EMBEDDED:
+		CALLBACK_WITH_SUCCESS(cb, data->online_cbd->data);
+		goto done;
+	}
+
+	data->sysinfo_poll_count++;
+
+	if (data->sysinfo_poll_count > 15)
+		goto failure;
+
+	data->sysinfo_poll_source = g_timeout_add_seconds(2,
+						sysinfo_online_check, data);
+	return;
+
+failure:
+	CALLBACK_WITH_FAILURE(cb, data->online_cbd->data);
+
+done:
+	g_free(data->online_cbd);
+	data->online_cbd = NULL;
+}
+
+static gboolean sysinfo_online_check(gpointer user_data)
+{
+	struct huaweicdma_data *data = user_data;
+
+	data->sysinfo_poll_source = 0;
+
+	g_at_chat_send(data->pcui, "AT^SYSINFO", sysinfo_prefix,
+					sysinfo_online_cb, data, NULL);
+
+	return FALSE;
+}
+
+static void set_online_cb(gboolean ok, GAtResult *result, gpointer user_data)
+{
+	struct ofono_modem *modem = user_data;
+	struct huaweicdma_data *data = ofono_modem_get_data(modem);
+
+	if (!ok) {
+		ofono_modem_online_cb_t cb = data->online_cbd->cb;
+
+		CALLBACK_WITH_FAILURE(cb, data->online_cbd->data);
+
+		g_free(data->online_cbd);
+		data->online_cbd = NULL;
+		return;
+	}
+
+	data->sysinfo_poll_count = 0;
+
+	sysinfo_online_check(data);
+}
+
+static void set_offline_cb(gboolean ok, GAtResult *result, gpointer user_data)
+{
+	struct cb_data *cbd = user_data;
+	ofono_modem_online_cb_t cb = cbd->cb;
+	struct ofono_error error;
+
+	decode_at_error(&error, g_at_result_final_response(result));
+	cb(&error, cbd->data);
+}
+
+static void huaweicdma_set_online(struct ofono_modem *modem,
+				ofono_bool_t online,
+				ofono_modem_online_cb_t cb, void *user_data)
+{
+	struct huaweicdma_data *data = ofono_modem_get_data(modem);
+
+	DBG("modem %p %s", modem, online ? "online" : "offline");
+
+	if (online == TRUE) {
+		data->online_cbd = cb_data_new(cb, user_data);
+
+		if (g_at_chat_send(data->pcui, "AT+CFUN=1", none_prefix,
+					set_online_cb, modem, NULL) > 0)
+			return;
+
+		g_free(data->online_cbd);
+		data->online_cbd = NULL;
+	} else {
+		struct cb_data *cbd = cb_data_new(cb, user_data);
+
+		if (g_at_chat_send(data->pcui, "AT+CFUN=4", none_prefix,
+					set_offline_cb, cbd, g_free) > 0)
+			return;
+
+		g_free(cbd);
+	}
+
+	CALLBACK_WITH_FAILURE(cb, user_data);
+}
+
 static void huaweicdma_pre_sim(struct ofono_modem *modem)
 {
 	struct huaweicdma_data *data = ofono_modem_get_data(modem);
+	struct ofono_sim *sim;
 
 	DBG("%p", modem);
 
 	ofono_devinfo_create(modem, 0, "cdmamodem", data->pcui);
+	sim = ofono_sim_create(modem, OFONO_VENDOR_HUAWEI,
+					"cdmamodem", data->pcui);
+
+	if (sim && data->have_sim == TRUE)
+		ofono_sim_inserted_notify(sim, TRUE);
 }
 
 static void huaweicdma_post_sim(struct ofono_modem *modem)
 {
-	DBG("%p", modem);
 }
 
 static void huaweicdma_post_online(struct ofono_modem *modem)
@@ -222,6 +490,7 @@ static struct ofono_modem_driver huaweicdma_driver = {
 	.remove		= huaweicdma_remove,
 	.enable		= huaweicdma_enable,
 	.disable	= huaweicdma_disable,
+	.set_online	= huaweicdma_set_online,
 	.pre_sim	= huaweicdma_pre_sim,
 	.post_sim	= huaweicdma_post_sim,
 	.post_online	= huaweicdma_post_online,
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH_v2 4/4] sim: Get IMSI if sim state is OFONO_SIM_STATE_INSERTED
  2011-11-21 10:54 [PATCH_v2 0/4] Use sim atom with cdma modems Guillaume Zajac
                   ` (2 preceding siblings ...)
  2011-11-21 10:54 ` [PATCH_v2 3/4] huaweicdma: Add SIM creation and set_online method driver Guillaume Zajac
@ 2011-11-21 10:54 ` Guillaume Zajac
  2011-11-27 12:08   ` Denis Kenzior
  3 siblings, 1 reply; 10+ messages in thread
From: Guillaume Zajac @ 2011-11-21 10:54 UTC (permalink / raw)
  To: ofono

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

In case of CDAM modem sim can be embedded so that at AT+CPIN? query
answer is +CME ERROR: 10 sim not inserted.
We have to ignore this error and try to initialize the sim to
retrieve the IMSI.
---
 src/sim.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/src/sim.c b/src/sim.c
index d1d55c5..2c6fbe2 100644
--- a/src/sim.c
+++ b/src/sim.c
@@ -2406,6 +2406,8 @@ checkdone:
 		sim_initialize_after_pin(sim);
 		break;
 	default:
+		if (sim->state == OFONO_SIM_STATE_INSERTED)
+			sim_initialize_after_pin(sim);
 		break;
 	}
 }
-- 
1.7.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH_v2 1/4] cdmamodem: Add sim driver implementation
  2011-11-21 10:54 ` [PATCH_v2 1/4] cdmamodem: Add sim driver implementation Guillaume Zajac
@ 2011-11-27 12:02   ` Denis Kenzior
  2011-11-29 14:20     ` Guillaume Zajac
  0 siblings, 1 reply; 10+ messages in thread
From: Denis Kenzior @ 2011-11-27 12:02 UTC (permalink / raw)
  To: ofono

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

Hi Guillaume,

On 11/21/2011 04:54 AM, Guillaume Zajac wrote:
> ---
>  Makefile.am                   |    3 +-
>  drivers/cdmamodem/cdmamodem.c |    2 +
>  drivers/cdmamodem/cdmamodem.h |    3 +
>  drivers/cdmamodem/sim.c       |  582 +++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 589 insertions(+), 1 deletions(-)
>  create mode 100644 drivers/cdmamodem/sim.c
> 

I really don't like us copy-pasting this much code for no good reason.
Let me toy with a few ideas, but the obvious start would be to refactor
this code into a library.

Regards,
-Denis

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH_v2 2/4] simfs: Call callback with failure if driver is not implemented
  2011-11-21 10:54 ` [PATCH_v2 2/4] simfs: Call callback with failure if driver is not implemented Guillaume Zajac
@ 2011-11-27 12:04   ` Denis Kenzior
  0 siblings, 0 replies; 10+ messages in thread
From: Denis Kenzior @ 2011-11-27 12:04 UTC (permalink / raw)
  To: ofono

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

Hi Guillaume,

On 11/21/2011 04:54 AM, Guillaume Zajac wrote:
> ---
>  src/simfs.c |    4 +++-
>  1 files changed, 3 insertions(+), 1 deletions(-)
> 

Patch has been applied, thanks.

Regards,
-Denis

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH_v2 4/4] sim: Get IMSI if sim state is OFONO_SIM_STATE_INSERTED
  2011-11-21 10:54 ` [PATCH_v2 4/4] sim: Get IMSI if sim state is OFONO_SIM_STATE_INSERTED Guillaume Zajac
@ 2011-11-27 12:08   ` Denis Kenzior
  0 siblings, 0 replies; 10+ messages in thread
From: Denis Kenzior @ 2011-11-27 12:08 UTC (permalink / raw)
  To: ofono

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

Hi Guillaume,

On 11/21/2011 04:54 AM, Guillaume Zajac wrote:
> In case of CDAM modem sim can be embedded so that at AT+CPIN? query
> answer is +CME ERROR: 10 sim not inserted.
> We have to ignore this error and try to initialize the sim to
> retrieve the IMSI.
> ---
>  src/sim.c |    2 ++
>  1 files changed, 2 insertions(+), 0 deletions(-)
> 
> diff --git a/src/sim.c b/src/sim.c
> index d1d55c5..2c6fbe2 100644
> --- a/src/sim.c
> +++ b/src/sim.c
> @@ -2406,6 +2406,8 @@ checkdone:
>  		sim_initialize_after_pin(sim);
>  		break;
>  	default:
> +		if (sim->state == OFONO_SIM_STATE_INSERTED)
> +			sim_initialize_after_pin(sim);

I'm almost certain this will break the GSM state machine.

What is meant by an 'embedded' SIM here?  Are you saying that the IMSI
query succeeds even if the SIM is not present?  If so, are you sure it
isn't a timing / race condition issue?

>  		break;
>  	}
>  }

Regards,
-Denis

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH_v2 3/4] huaweicdma: Add SIM creation and set_online method driver
  2011-11-21 10:54 ` [PATCH_v2 3/4] huaweicdma: Add SIM creation and set_online method driver Guillaume Zajac
@ 2011-11-27 14:29   ` Denis Kenzior
  0 siblings, 0 replies; 10+ messages in thread
From: Denis Kenzior @ 2011-11-27 14:29 UTC (permalink / raw)
  To: ofono

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

Hi Guillaume,

On 11/21/2011 04:54 AM, Guillaume Zajac wrote:
> ---
>  plugins/huaweicdma.c |  283 ++++++++++++++++++++++++++++++++++++++++++++++++--
>  1 files changed, 276 insertions(+), 7 deletions(-)
> 
> diff --git a/plugins/huaweicdma.c b/plugins/huaweicdma.c
> index 4c83114..0fd9ef2 100644
> --- a/plugins/huaweicdma.c
> +++ b/plugins/huaweicdma.c
> @@ -37,10 +37,28 @@
>  #include <ofono/cdma-netreg.h>
>  #include <ofono/cdma-connman.h>
>  #include <ofono/log.h>
> +#include <ofono.h>
> +
> +#include <drivers/atmodem/atutil.h>
> +#include <drivers/atmodem/vendor.h>
> +
> +static const char *none_prefix[] = { NULL };
> +static const char *sysinfo_prefix[] = { "^SYSINFO:", NULL };
> +
> +enum {
> +	SIM_STATE_VALID =		1,
> +	SIM_STATE_EMBEDDED =		240,
> +	SIM_STATE_NOT_EXISTENT =	255,
> +};
>  
>  struct huaweicdma_data {
>  	GAtChat *modem;
>  	GAtChat *pcui;
> +	gboolean have_sim;
> +	int sim_state;
> +	guint sysinfo_poll_source;
> +	guint sysinfo_poll_count;

You forgot to clean these up in huaweicdma_remove

> +	struct cb_data *online_cbd;
>  };
>  
>  static void huaweicdma_debug(const char *str, void *data)
> @@ -79,6 +97,122 @@ static void huaweicdma_remove(struct ofono_modem *modem)
>  	g_free(data);
>  }
>  
> +static void simst_notify(GAtResult *result, gpointer user_data)
> +{
> +	struct ofono_modem *modem = user_data;
> +	struct huaweicdma_data *data = ofono_modem_get_data(modem);
> +	GAtResultIter iter;
> +	int sim_state;
> +
> +	g_at_result_iter_init(&iter, result);
> +
> +	if (!g_at_result_iter_next(&iter, "^SIMST:"))
> +		return;
> +
> +	if (!g_at_result_iter_next_number(&iter, &sim_state))
> +		return;
> +
> +	DBG("%d -> %d", data->sim_state, sim_state);
> +
> +	data->sim_state = sim_state;
> +}
> +
> +static gboolean parse_sysinfo_result(GAtResult *result, int *srv_status,
> +					int *srv_domain, int *sim_state)
> +{
> +	GAtResultIter iter;
> +
> +	g_at_result_iter_init(&iter, result);
> +
> +	if (!g_at_result_iter_next(&iter, "^SYSINFO:"))
> +		return FALSE;
> +
> +	if (!g_at_result_iter_next_number(&iter, srv_status))
> +		return FALSE;
> +
> +	if (!g_at_result_iter_next_number(&iter, srv_domain))
> +		return FALSE;
> +
> +	if (!g_at_result_iter_skip_next(&iter))
> +		return FALSE;
> +
> +	if (!g_at_result_iter_skip_next(&iter))
> +		return FALSE;
> +
> +	if (!g_at_result_iter_next_number(&iter, sim_state))
> +		return FALSE;

This is an obvious candidate to refactor into a library

> +
> +	return TRUE;
> +}
> +
> +static void shutdown_device(struct huaweicdma_data *data)
> +{
> +	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->pcui);
> +	g_at_chat_unregister_all(data->pcui);
> +
> +	g_at_chat_unref(data->pcui);
> +	data->pcui = NULL;
> +}
> +
> +static gboolean sysinfo_enable_check(gpointer user_data);
> +
> +static void sysinfo_enable_cb(gboolean ok, GAtResult *result,
> +						gpointer user_data)
> +{
> +	struct ofono_modem *modem = user_data;
> +	struct huaweicdma_data *data = ofono_modem_get_data(modem);
> +	int srv_status, srv_domain, sim_state;
> +
> +	if (!ok)
> +		goto failure;
> +
> +	if (parse_sysinfo_result(result, &srv_status, &srv_domain,
> +						&sim_state) == FALSE)
> +		goto failure;
> +
> +	DBG("%d -> %d", data->sim_state, sim_state);
> +
> +	data->sim_state = sim_state;
> +
> +	if (sim_state == SIM_STATE_NOT_EXISTENT) {
> +		data->sysinfo_poll_count++;
> +
> +		if (data->sysinfo_poll_count > 5)
> +			goto failure;
> +
> +		data->sysinfo_poll_source = g_timeout_add_seconds(1,
> +						sysinfo_enable_check, modem);
> +		return;
> +	}
> +
> +	data->have_sim = TRUE;
> +	ofono_modem_set_powered(modem, TRUE);
> +	return;
> +
> +failure:
> +	shutdown_device(data);
> +	ofono_modem_set_powered(modem, FALSE);
> +}
> +
> +static gboolean sysinfo_enable_check(gpointer user_data)
> +{
> +	struct ofono_modem *modem = user_data;
> +	struct huaweicdma_data *data = ofono_modem_get_data(modem);
> +
> +	data->sysinfo_poll_source = 0;
> +
> +	g_at_chat_send(data->pcui, "AT^SYSINFO", sysinfo_prefix,
> +					sysinfo_enable_cb, modem, NULL);
> +
> +	return FALSE;
> +}
> +
>  static void cfun_enable(gboolean ok, GAtResult *result, gpointer user_data)
>  {
>  	struct ofono_modem *modem = user_data;
> @@ -87,14 +221,18 @@ static void cfun_enable(gboolean ok, GAtResult *result, gpointer user_data)
>  	DBG("");
>  
>  	if (!ok) {
> -		g_at_chat_unref(data->modem);
> -		data->modem = NULL;
> -
> -		g_at_chat_unref(data->pcui);
> -		data->pcui = NULL;
> +		shutdown_device(data);
> +		ofono_modem_set_powered(modem, FALSE);
> +		return;
>  	}
>  
> -	ofono_modem_set_powered(modem, ok);
> +	/* Follow sim state changes */
> +	g_at_chat_register(data->pcui, "^SIMST:", simst_notify,
> +						FALSE, modem, NULL);
> +
> +	data->sysinfo_poll_count = 0;
> +
> +	sysinfo_enable_check(modem);
>  }
>  
>  static GAtChat *open_device(struct ofono_modem *modem,
> @@ -150,6 +288,8 @@ static int huaweicdma_enable(struct ofono_modem *modem)
>  	g_at_chat_send(data->modem, "ATE0 &C0 +CMEE=1", NULL, NULL, NULL, NULL);
>  	g_at_chat_send(data->pcui, "ATE0 &C0 +CMEE=1", NULL, NULL, NULL, NULL);
>  
> +	data->sim_state = SIM_STATE_NOT_EXISTENT;
> +
>  	g_at_chat_send(data->pcui, "AT+CFUN=1", NULL,
>  					cfun_enable, modem, NULL);
>  
> @@ -191,18 +331,146 @@ static int huaweicdma_disable(struct ofono_modem *modem)
>  	return -EINPROGRESS;
>  }
>  
> +
> +static gboolean sysinfo_online_check(gpointer user_data);
> +
> +static void sysinfo_online_cb(gboolean ok, GAtResult *result,
> +						gpointer user_data)
> +{
> +	struct huaweicdma_data *data = user_data;
> +	ofono_modem_online_cb_t cb = data->online_cbd->cb;
> +	int srv_status, srv_domain, sim_state;
> +
> +	if (!ok)
> +		goto failure;
> +
> +	if (parse_sysinfo_result(result, &srv_status, &srv_domain,
> +							&sim_state) == FALSE)
> +		goto failure;
> +
> +	DBG("%d -> %d", data->sim_state, sim_state);
> +
> +	data->sim_state = sim_state;
> +
> +	/* Valid service status and at minimum PS domain */
> +	if (srv_status > 0 && srv_domain > 1) {
> +		CALLBACK_WITH_SUCCESS(cb, data->online_cbd->data);
> +		goto done;
> +	}

Why are you checking this here? PS domain is a GSM specific thing and
should have no bearing.

> +
> +	switch (sim_state) {
> +	case SIM_STATE_VALID:
> +	case SIM_STATE_EMBEDDED:
> +		CALLBACK_WITH_SUCCESS(cb, data->online_cbd->data);
> +		goto done;
> +	}

Why are we not handling the EMBEDDED state elsewhere, e.g. to tell the
core that no SIM is to be expected?

> +
> +	data->sysinfo_poll_count++;
> +
> +	if (data->sysinfo_poll_count > 15)
> +		goto failure;
> +
> +	data->sysinfo_poll_source = g_timeout_add_seconds(2,
> +						sysinfo_online_check, data);
> +	return;
> +
> +failure:
> +	CALLBACK_WITH_FAILURE(cb, data->online_cbd->data);
> +
> +done:
> +	g_free(data->online_cbd);
> +	data->online_cbd = NULL;
> +}
> +
> +static gboolean sysinfo_online_check(gpointer user_data)
> +{
> +	struct huaweicdma_data *data = user_data;
> +
> +	data->sysinfo_poll_source = 0;
> +
> +	g_at_chat_send(data->pcui, "AT^SYSINFO", sysinfo_prefix,
> +					sysinfo_online_cb, data, NULL);
> +
> +	return FALSE;
> +}
> +
> +static void set_online_cb(gboolean ok, GAtResult *result, gpointer user_data)
> +{
> +	struct ofono_modem *modem = user_data;
> +	struct huaweicdma_data *data = ofono_modem_get_data(modem);
> +
> +	if (!ok) {
> +		ofono_modem_online_cb_t cb = data->online_cbd->cb;
> +
> +		CALLBACK_WITH_FAILURE(cb, data->online_cbd->data);
> +
> +		g_free(data->online_cbd);
> +		data->online_cbd = NULL;
> +		return;
> +	}
> +
> +	data->sysinfo_poll_count = 0;
> +
> +	sysinfo_online_check(data);
> +}
> +
> +static void set_offline_cb(gboolean ok, GAtResult *result, gpointer user_data)
> +{
> +	struct cb_data *cbd = user_data;
> +	ofono_modem_online_cb_t cb = cbd->cb;
> +	struct ofono_error error;
> +
> +	decode_at_error(&error, g_at_result_final_response(result));
> +	cb(&error, cbd->data);
> +}
> +
> +static void huaweicdma_set_online(struct ofono_modem *modem,
> +				ofono_bool_t online,
> +				ofono_modem_online_cb_t cb, void *user_data)
> +{
> +	struct huaweicdma_data *data = ofono_modem_get_data(modem);
> +
> +	DBG("modem %p %s", modem, online ? "online" : "offline");
> +
> +	if (online == TRUE) {
> +		data->online_cbd = cb_data_new(cb, user_data);
> +
> +		if (g_at_chat_send(data->pcui, "AT+CFUN=1", none_prefix,
> +					set_online_cb, modem, NULL) > 0)
> +			return;
> +
> +		g_free(data->online_cbd);
> +		data->online_cbd = NULL;
> +	} else {
> +		struct cb_data *cbd = cb_data_new(cb, user_data);
> +
> +		if (g_at_chat_send(data->pcui, "AT+CFUN=4", none_prefix,
> +					set_offline_cb, cbd, g_free) > 0)
> +			return;
> +
> +		g_free(cbd);
> +	}
> +
> +	CALLBACK_WITH_FAILURE(cb, user_data);
> +}
> +
>  static void huaweicdma_pre_sim(struct ofono_modem *modem)
>  {
>  	struct huaweicdma_data *data = ofono_modem_get_data(modem);
> +	struct ofono_sim *sim;
>  
>  	DBG("%p", modem);
>  
>  	ofono_devinfo_create(modem, 0, "cdmamodem", data->pcui);
> +	sim = ofono_sim_create(modem, OFONO_VENDOR_HUAWEI,
> +					"cdmamodem", data->pcui);
> +
> +	if (sim && data->have_sim == TRUE)
> +		ofono_sim_inserted_notify(sim, TRUE);
>  }
>  
>  static void huaweicdma_post_sim(struct ofono_modem *modem)
>  {
> -	DBG("%p", modem);
>  }
>  
>  static void huaweicdma_post_online(struct ofono_modem *modem)
> @@ -222,6 +490,7 @@ static struct ofono_modem_driver huaweicdma_driver = {
>  	.remove		= huaweicdma_remove,
>  	.enable		= huaweicdma_enable,
>  	.disable	= huaweicdma_disable,
> +	.set_online	= huaweicdma_set_online,
>  	.pre_sim	= huaweicdma_pre_sim,
>  	.post_sim	= huaweicdma_post_sim,
>  	.post_online	= huaweicdma_post_online,

Regards,
-Denis

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH_v2 1/4] cdmamodem: Add sim driver implementation
  2011-11-27 12:02   ` Denis Kenzior
@ 2011-11-29 14:20     ` Guillaume Zajac
  0 siblings, 0 replies; 10+ messages in thread
From: Guillaume Zajac @ 2011-11-29 14:20 UTC (permalink / raw)
  To: ofono

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

Hi Denis,

On 27/11/2011 13:02, Denis Kenzior wrote:
> Hi Guillaume,
>
> On 11/21/2011 04:54 AM, Guillaume Zajac wrote:
>> ---
>>   Makefile.am                   |    3 +-
>>   drivers/cdmamodem/cdmamodem.c |    2 +
>>   drivers/cdmamodem/cdmamodem.h |    3 +
>>   drivers/cdmamodem/sim.c       |  582 +++++++++++++++++++++++++++++++++++++++++
>>   4 files changed, 589 insertions(+), 1 deletions(-)
>>   create mode 100644 drivers/cdmamodem/sim.c
>>
> I really don't like us copy-pasting this much code for no good reason.
> Let me toy with a few ideas, but the obvious start would be to refactor
> this code into a library.

Ok I will create a library to factorize the code.
I will send you a first version of the library used only by AT modems.
If it sounds ok I will create the CDMA sim driver using this library.

Kind regards,
Guillaume

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2011-11-29 14:20 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-11-21 10:54 [PATCH_v2 0/4] Use sim atom with cdma modems Guillaume Zajac
2011-11-21 10:54 ` [PATCH_v2 1/4] cdmamodem: Add sim driver implementation Guillaume Zajac
2011-11-27 12:02   ` Denis Kenzior
2011-11-29 14:20     ` Guillaume Zajac
2011-11-21 10:54 ` [PATCH_v2 2/4] simfs: Call callback with failure if driver is not implemented Guillaume Zajac
2011-11-27 12:04   ` Denis Kenzior
2011-11-21 10:54 ` [PATCH_v2 3/4] huaweicdma: Add SIM creation and set_online method driver Guillaume Zajac
2011-11-27 14:29   ` Denis Kenzior
2011-11-21 10:54 ` [PATCH_v2 4/4] sim: Get IMSI if sim state is OFONO_SIM_STATE_INSERTED Guillaume Zajac
2011-11-27 12:08   ` Denis Kenzior

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.