All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] Change sim_ops plugin interface to allow acces to linear fixed files
@ 2009-06-18  3:44 Andrzej Zaborowski
  2009-06-18  7:28 ` Denis Kenzior
  0 siblings, 1 reply; 4+ messages in thread
From: Andrzej Zaborowski @ 2009-06-18  3:44 UTC (permalink / raw)
  To: ofono

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

(iow record based files), both read and update access.
Implement writing sim files through AT.

Depends on "[PATCH] Use GET RESPONSE sim command to retrieve EF length."
---
 drivers/atmodem/sim.c |  199 +++++++++++++++++++++++++++++++++++++++++++------
 src/driver.h          |   31 ++++++--
 src/sim.c             |   16 ++--
 3 files changed, 210 insertions(+), 36 deletions(-)

diff --git a/drivers/atmodem/sim.c b/drivers/atmodem/sim.c
index a2aebb8..66e951e 100644
--- a/drivers/atmodem/sim.c
+++ b/drivers/atmodem/sim.c
@@ -41,20 +41,22 @@
 static const char *crsm_prefix[] = { "+CRSM:", NULL };
 static const char *cnum_prefix[] = { "+CNUM:", NULL };
 
-static void at_crsm_len_cb(gboolean ok, GAtResult *result, gpointer user_data)
+static void at_crsm_info_cb(gboolean ok, GAtResult *result, gpointer user_data)
 {
 	struct cb_data *cbd = user_data;
 	GAtResultIter iter;
-	ofono_sim_file_len_cb_t cb = cbd->cb;
+	ofono_sim_file_info_cb_t cb = cbd->cb;
 	struct ofono_error error;
 	const guint8 *response;
 	gint sw1, sw2, len;
+	int flen, rlen;
+	enum ofono_simfile_struct str;
 
-	dump_response("at_crsm_len_cb", ok, result);
+	dump_response("at_crsm_info_cb", ok, result);
 	decode_at_error(&error, g_at_result_final_response(result));
 
 	if (!ok) {
-		cb(&error, -1, cbd->data);
+		cb(&error, -1, -1, -1, cbd->data);
 		return;
 	}
 
@@ -63,29 +65,38 @@ static void at_crsm_len_cb(gboolean ok, GAtResult *result, gpointer user_data)
 	if (!g_at_result_iter_next(&iter, "+CRSM:")) {
 		DECLARE_FAILURE(e);
 
-		cb(&e, -1, cbd->data);
+		cb(&e, -1, -1, -1, cbd->data);
 		return;
 	}
 
 	g_at_result_iter_next_number(&iter, &sw1);
-	g_at_result_iter_next_number(&iter, &len);
+	g_at_result_iter_next_number(&iter, &sw2);
 
 	if (!g_at_result_iter_next_hexstring(&iter, &response, &len) ||
 		(sw1 != 0x90 && sw1 != 0x91 && sw1 != 0x92) ||
-		(sw1 == 0x90 && sw2 != 0x00) || len < 14) {
+		(sw1 == 0x90 && sw2 != 0x00) ||
+		len < 14 || response[6] != 0x04 ||
+		(response[13] == 0x01 && len < 15)) {
 		DECLARE_FAILURE(e);
 
-		cb(&e, -1, cbd->data);
+		cb(&e, -1, -1, -1, cbd->data);
 		return;
 	}
 
-	ofono_debug("crsm_len_cb: %02x, %02x, %i", sw1, sw2, len);
+	ofono_debug("crsm_info_cb: %02x, %02x, %i", sw1, sw2, len);
+
+	flen = (response[2] << 8) | response[3];
+	str = response[13];
+	if (str == 0x01)
+		rlen = response[14];
+	else
+		rlen = 0;
 
-	cb(&error, (response[2] << 8) | response[3], cbd->data);
+	cb(&error, flen, str, rlen, cbd->data);
 }
 
-static void at_sim_read_file_len(struct ofono_modem *modem, int fileid,
-					ofono_sim_file_len_cb_t cb,
+static void at_sim_read_info(struct ofono_modem *modem, int fileid,
+					ofono_sim_file_info_cb_t cb,
 					void *data)
 {
 	struct at_data *at = ofono_modem_userdata(modem);
@@ -97,7 +108,7 @@ static void at_sim_read_file_len(struct ofono_modem *modem, int fileid,
 
 	snprintf(buf, sizeof(buf), "AT+CRSM=192,%i,0,0,15", fileid);
 	if (g_at_chat_send(at->parser, buf, crsm_prefix,
-				at_crsm_len_cb, cbd, g_free) > 0)
+				at_crsm_info_cb, cbd, g_free) > 0)
 		return;
 
 error:
@@ -106,11 +117,12 @@ error:
 
 	{
 		DECLARE_FAILURE(error);
-		cb(&error, -1, data);
+		cb(&error, -1, -1, -1, data);
 	}
 }
 
-static void at_crsm_cb(gboolean ok, GAtResult *result, gpointer user_data)
+static void at_crsm_read_cb(gboolean ok, GAtResult *result,
+		gpointer user_data)
 {
 	struct cb_data *cbd = user_data;
 	GAtResultIter iter;
@@ -119,7 +131,7 @@ static void at_crsm_cb(gboolean ok, GAtResult *result, gpointer user_data)
 	const guint8 *response;
 	gint sw1, sw2, len;
 
-	dump_response("at_crsm_cb", ok, result);
+	dump_response("at_crsm_read_cb", ok, result);
 	decode_at_error(&error, g_at_result_final_response(result));
 
 	if (!ok) {
@@ -147,14 +159,14 @@ static void at_crsm_cb(gboolean ok, GAtResult *result, gpointer user_data)
 		return;
 	}
 
-	ofono_debug("crsm_cb: %02x, %02x, %d", sw1, sw2, len);
+	ofono_debug("crsm_read_cb: %02x, %02x, %d", sw1, sw2, len);
 
 	cb(&error, response, len, cbd->data);
 }
 
-static void at_sim_read_file(struct ofono_modem *modem, int fileid, int start,
-					int length, ofono_sim_read_cb_t cb,
-					void *data)
+static void at_sim_read_binary(struct ofono_modem *modem, int fileid,
+					int start, int length,
+					ofono_sim_read_cb_t cb, void *data)
 {
 	struct at_data *at = ofono_modem_userdata(modem);
 	struct cb_data *cbd = cb_data_new(modem, cb, data);
@@ -166,7 +178,34 @@ static void at_sim_read_file(struct ofono_modem *modem, int fileid, int start,
 	snprintf(buf, sizeof(buf), "AT+CRSM=176,%i,%i,%i,%i", fileid,
 			start >> 8, start & 0xff, length);
 	if (g_at_chat_send(at->parser, buf, crsm_prefix,
-				at_crsm_cb, cbd, g_free) > 0)
+				at_crsm_read_cb, cbd, g_free) > 0)
+		return;
+
+error:
+	if (cbd)
+		g_free(cbd);
+
+	{
+		DECLARE_FAILURE(error);
+		cb(&error, NULL, 0, data);
+	}
+}
+
+static void at_sim_read_record(struct ofono_modem *modem, int fileid,
+					int record, int length,
+					ofono_sim_read_cb_t cb, void *data)
+{
+	struct at_data *at = ofono_modem_userdata(modem);
+	struct cb_data *cbd = cb_data_new(modem, cb, data);
+	char buf[64];
+
+	if (!cbd)
+		goto error;
+
+	snprintf(buf, sizeof(buf), "AT+CRSM=178,%i,%i,4,%i", fileid,
+			record + 1, length);
+	if (g_at_chat_send(at->parser, buf, crsm_prefix,
+				at_crsm_read_cb, cbd, g_free) > 0)
 		return;
 
 error:
@@ -179,6 +218,117 @@ error:
 	}
 }
 
+static void at_crsm_update_cb(gboolean ok, GAtResult *result,
+		gpointer user_data)
+{
+	struct cb_data *cbd = user_data;
+	GAtResultIter iter;
+	ofono_generic_cb_t cb = cbd->cb;
+	struct ofono_error error;
+	gint sw1, sw2;
+
+	dump_response("at_crsm_update_cb", ok, result);
+	decode_at_error(&error, g_at_result_final_response(result));
+
+	if (!ok) {
+		cb(&error, cbd->data);
+		return;
+	}
+
+	g_at_result_iter_init(&iter, result);
+
+	if (!g_at_result_iter_next(&iter, "+CRSM:")) {
+		DECLARE_FAILURE(e);
+
+		cb(&e, cbd->data);
+		return;
+	}
+
+	g_at_result_iter_next_number(&iter, &sw1);
+	g_at_result_iter_next_number(&iter, &sw2);
+	if ((sw1 != 0x90 && sw1 != 0x91 && sw1 != 0x92 && sw1 != 0x9f) ||
+		(sw1 == 0x90 && sw2 != 0x00)) {
+		DECLARE_FAILURE(e);
+
+		cb(&e, cbd->data);
+		return;
+	}
+
+	ofono_debug("crsm_update_cb: %02x, %02x", sw1, sw2);
+
+	cb(&error, cbd->data);
+}
+
+static void at_sim_update_binary(struct ofono_modem *modem, int fileid,
+					int start, int length,
+					const unsigned char *value,
+					ofono_generic_cb_t cb, void *data)
+{
+	struct at_data *at = ofono_modem_userdata(modem);
+	struct cb_data *cbd = cb_data_new(modem, cb, data);
+	char *buf = g_try_new(char, 36 + length * 2);
+	int len, ret;
+
+	if (!cbd || !buf)
+		goto error;
+
+	len = sprintf(buf, "AT+CRSM=214,%i,%i,%i,%i,", fileid,
+			start >> 8, start & 0xff, length);
+	for (; length; length--)
+		len += sprintf(buf + len, "%02hhx", *value++);
+	ret = g_at_chat_send(at->parser, buf, crsm_prefix,
+				at_crsm_update_cb, cbd, g_free);
+
+	g_free(buf);
+
+	if (ret > 0)
+		return;
+
+error:
+	if (cbd)
+		g_free(cbd);
+
+	{
+		DECLARE_FAILURE(error);
+		cb(&error, data);
+	}
+}
+
+static void at_sim_update_record(struct ofono_modem *modem, int fileid,
+					int record, int length,
+					const unsigned char *value,
+					ofono_generic_cb_t cb, void *data)
+{
+	struct at_data *at = ofono_modem_userdata(modem);
+	struct cb_data *cbd = cb_data_new(modem, cb, data);
+	char *buf = g_try_new(char, 36 + length * 2);
+	int len, ret;
+
+	if (!cbd || !buf)
+		goto error;
+
+	len = sprintf(buf, "AT+CRSM=220,%i,%i,4,%i,", fileid,
+			record + 1, length);
+	for (; length; length--)
+		len += sprintf(buf + len, "%02hhx", *value++);
+	ret = g_at_chat_send(at->parser, buf, crsm_prefix,
+				at_crsm_update_cb, cbd, g_free);
+
+	g_free(buf);
+
+	if (ret > 0)
+		return;
+
+error:
+	if (cbd)
+		g_free(cbd);
+
+	{
+		DECLARE_FAILURE(error);
+		cb(&error, data);
+	}
+}
+
 static void at_cimi_cb(gboolean ok, GAtResult *result, gpointer user_data)
 {
 	struct cb_data *cbd = user_data;
@@ -317,8 +467,11 @@ error:
 }
 
 static struct ofono_sim_ops ops = {
-	.read_file_len 		= at_sim_read_file_len,
-	.read_file 		= at_sim_read_file,
+	.read_file_info		= at_sim_read_info,
+	.read_file_transparent	= at_sim_read_binary,
+	.read_file_linear	= at_sim_read_record,
+	.write_file_transparent	= at_sim_update_binary,
+	.write_file_linear	= at_sim_update_record,
 	.read_imsi		= at_read_imsi,
 	.read_own_numbers	= at_read_msisdn,
 };
diff --git a/src/driver.h b/src/driver.h
index 61504dd..36b9a08 100644
--- a/src/driver.h
+++ b/src/driver.h
@@ -98,6 +98,13 @@ struct ofono_own_number {
 	int itc;
 };
 
+/* 51.011 Section 9.3 */
+enum ofono_simfile_struct {
+	OFONO_SIM_FILE_TRANSPARENT = 0,
+	OFONO_SIM_FILE_FIXED = 1,
+	OFONO_SIM_FILE_CYCLIC = 3
+};
+
 /* Notification functions, the integer values here should map to
  * values obtained from the modem.  The enumerations are the same
  * as the values for the fields found in 3GPP TS 27.007
@@ -156,8 +163,10 @@ typedef void (*ofono_call_meter_puct_query_cb_t)(const struct ofono_error *error
 typedef void (*ofono_call_barring_cb_t)(const struct ofono_error *error,
 					int status, void *data);
 
-typedef void (*ofono_sim_file_len_cb_t)(const struct ofono_error *error,
-					int length, void *data);
+typedef void (*ofono_sim_file_info_cb_t)(const struct ofono_error *error,
+					int filelength,
+					enum ofono_simfile_struct structure,
+					int recordlength, void *data);
 
 typedef void (*ofono_sim_read_cb_t)(const struct ofono_error *error,
 					const unsigned char *sdata, int length,
@@ -363,10 +372,20 @@ int ofono_call_barring_register(struct ofono_modem *modem,
 void ofono_call_barring_unregister(struct ofono_modem *modem);
 
 struct ofono_sim_ops {
-	void (*read_file_len)(struct ofono_modem *modem, int fileid,
-			ofono_sim_file_len_cb_t cb, void *data);
-	void (*read_file)(struct ofono_modem *modem, int fileid, int start,
-			int length, ofono_sim_read_cb_t cb, void *data);
+	void (*read_file_info)(struct ofono_modem *modem, int fileid,
+			ofono_sim_file_info_cb_t cb, void *data);
+	void (*read_file_transparent)(struct ofono_modem *modem, int fileid,
+			int start, int length,
+			ofono_sim_read_cb_t cb, void *data);
+	void (*read_file_linear)(struct ofono_modem *modem, int fileid,
+			int record, int length,
+			ofono_sim_read_cb_t cb, void *data);
+	void (*write_file_transparent)(struct ofono_modem *modem, int fileid,
+			int start, int length, const unsigned char *value,
+			ofono_generic_cb_t cb, void *data);
+	void (*write_file_linear)(struct ofono_modem *modem, int fileid,
+			int record, int length, const unsigned char *value,
+			ofono_generic_cb_t cb, void *data);
 	void (*read_imsi)(struct ofono_modem *modem,
 			ofono_imsi_cb_t cb, void *data);
 	void (*read_own_numbers)(struct ofono_modem *modem,
diff --git a/src/sim.c b/src/sim.c
index acec7bb..9c85292 100644
--- a/src/sim.c
+++ b/src/sim.c
@@ -237,16 +237,18 @@ static void sim_spn_read_cb(const struct ofono_error *error,
 		sim_spn_notify(modem, l->data);
 }
 
-static void sim_spn_len_cb(const struct ofono_error *error,
-		int length, void *data)
+static void sim_spn_info_cb(const struct ofono_error *error,
+		int length, enum ofono_simfile_struct structure, int dummy,
+		void *data)
 {
 	struct ofono_modem *modem = data;
 	struct sim_manager_data *sim = modem->sim_manager;
 
-	if (error->type != OFONO_ERROR_TYPE_NO_ERROR || length <= 1)
+	if (error->type != OFONO_ERROR_TYPE_NO_ERROR || length <= 1 ||
+			structure != OFONO_SIM_FILE_TRANSPARENT)
 		return;
 
-	sim->ops->read_file(modem, SIM_EFSPN_FILEID, 0, length,
+	sim->ops->read_file_transparent(modem, SIM_EFSPN_FILEID, 0, length,
 			sim_spn_read_cb, modem);
 }
 
@@ -255,8 +257,8 @@ static gboolean sim_retrieve_spn(void *user_data)
 	struct ofono_modem *modem = user_data;
 	struct sim_manager_data *sim = modem->sim_manager;
 
-	sim->ops->read_file_len(modem, SIM_EFSPN_FILEID,
-			sim_spn_len_cb, modem);
+	sim->ops->read_file_info(modem, SIM_EFSPN_FILEID,
+			sim_spn_info_cb, modem);
 
 	return FALSE;
 }
@@ -341,7 +343,7 @@ static void initialize_sim_manager(struct ofono_modem *modem)
 
 	modem_add_interface(modem, SIM_MANAGER_INTERFACE);
 
-	if (modem->sim_manager->ops->read_file)
+	if (modem->sim_manager->ops->read_file_transparent)
 		g_timeout_add(0, sim_retrieve_spn, modem);
 
 	if (modem->sim_manager->ops->read_imsi)
-- 
1.6.0


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

* Re: [PATCH] Change sim_ops plugin interface to allow acces to linear fixed files
  2009-06-18  3:44 [PATCH] Change sim_ops plugin interface to allow acces to linear fixed files Andrzej Zaborowski
@ 2009-06-18  7:28 ` Denis Kenzior
  2009-06-21  1:30   ` [PATCH] Add write/read operations for cyclic files in SIM Andrzej Zaborowski
  0 siblings, 1 reply; 4+ messages in thread
From: Denis Kenzior @ 2009-06-18  7:28 UTC (permalink / raw)
  To: ofono

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

Hi,

On Wednesday 17 June 2009 22:44:44 Andrzej Zaborowski wrote:
> (iow record based files), both read and update access.
> Implement writing sim files through AT.
>
> Depends on "[PATCH] Use GET RESPONSE sim command to retrieve EF length."

Patch has been applied.  Can you also add capability to write to cyclic files?  
This can be useful to update EFoci and EFici.  This is essentially the same as 
write_file_linear except no record parameter is used.

Regards,
-Denis

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

* [PATCH] Add write/read operations for cyclic files in SIM.
  2009-06-18  7:28 ` Denis Kenzior
@ 2009-06-21  1:30   ` Andrzej Zaborowski
  2009-06-22 18:23     ` Denis Kenzior
  0 siblings, 1 reply; 4+ messages in thread
From: Andrzej Zaborowski @ 2009-06-21  1:30 UTC (permalink / raw)
  To: ofono

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

I added the read method for symmetry, it's currently same as for linear
fixed EFs.  It might make sense to make it read always the oldest record or
something, but that will be clear when there's a use case.  Or we can
remove it.
---
 drivers/atmodem/sim.c |   35 +++++++++++++++++++++++++++++++++++
 src/driver.h          |    6 ++++++
 2 files changed, 41 insertions(+), 0 deletions(-)

diff --git a/drivers/atmodem/sim.c b/drivers/atmodem/sim.c
index 620aefc..ab05a5b 100644
--- a/drivers/atmodem/sim.c
+++ b/drivers/atmodem/sim.c
@@ -328,6 +328,39 @@ error:
 	}
 }
 
+static void at_sim_update_cyclic(struct ofono_modem *modem, int fileid,
+					int length, const unsigned char *value,
+					ofono_generic_cb_t cb, void *data)
+{
+	struct at_data *at = ofono_modem_userdata(modem);
+	struct cb_data *cbd = cb_data_new(modem, cb, data);
+	char *buf = g_try_new(char, 36 + length * 2);
+	int len, ret;
+
+	if (!cbd || !buf)
+		goto error;
+
+	len = sprintf(buf, "AT+CRSM=220,%i,0,3,%i,", fileid, length);
+	for (; length; length--)
+		len += sprintf(buf + len, "%02hhx", *value++);
+	ret = g_at_chat_send(at->parser, buf, crsm_prefix,
+				at_crsm_update_cb, cbd, g_free);
+
+	g_free(buf);
+
+	if (ret > 0)
+		return;
+
+error:
+	if (cbd)
+		g_free(cbd);
+
+	{
+		DECLARE_FAILURE(error);
+		cb(&error, data);
+	}
+}
+
 static void at_cimi_cb(gboolean ok, GAtResult *result, gpointer user_data)
 {
 	struct cb_data *cbd = user_data;
@@ -383,8 +416,10 @@ static struct ofono_sim_ops ops = {
 	.read_file_info		= at_sim_read_info,
 	.read_file_transparent	= at_sim_read_binary,
 	.read_file_linear	= at_sim_read_record,
+	.read_file_cyclic	= at_sim_read_record,
 	.write_file_transparent	= at_sim_update_binary,
 	.write_file_linear	= at_sim_update_record,
+	.write_file_cyclic	= at_sim_update_cyclic,
 	.read_imsi		= at_read_imsi,
 };
 
diff --git a/src/driver.h b/src/driver.h
index 3eade28..f324c1c 100644
--- a/src/driver.h
+++ b/src/driver.h
@@ -378,12 +378,18 @@ struct ofono_sim_ops {
 	void (*read_file_linear)(struct ofono_modem *modem, int fileid,
 			int record, int length,
 			ofono_sim_read_cb_t cb, void *data);
+	void (*read_file_cyclic)(struct ofono_modem *modem, int fileid,
+			int record, int length,
+			ofono_sim_read_cb_t cb, void *data);
 	void (*write_file_transparent)(struct ofono_modem *modem, int fileid,
 			int start, int length, const unsigned char *value,
 			ofono_generic_cb_t cb, void *data);
 	void (*write_file_linear)(struct ofono_modem *modem, int fileid,
 			int record, int length, const unsigned char *value,
 			ofono_generic_cb_t cb, void *data);
+	void (*write_file_cyclic)(struct ofono_modem *modem, int fileid,
+			int length, const unsigned char *value,
+			ofono_generic_cb_t cb, void *data);
 	void (*read_imsi)(struct ofono_modem *modem,
 			ofono_imsi_cb_t cb, void *data);
 };
-- 
1.6.0


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

* Re: [PATCH] Add write/read operations for cyclic files in SIM.
  2009-06-21  1:30   ` [PATCH] Add write/read operations for cyclic files in SIM Andrzej Zaborowski
@ 2009-06-22 18:23     ` Denis Kenzior
  0 siblings, 0 replies; 4+ messages in thread
From: Denis Kenzior @ 2009-06-22 18:23 UTC (permalink / raw)
  To: ofono

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

Patch has been applied.  Thanks.

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

end of thread, other threads:[~2009-06-22 18:23 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-06-18  3:44 [PATCH] Change sim_ops plugin interface to allow acces to linear fixed files Andrzej Zaborowski
2009-06-18  7:28 ` Denis Kenzior
2009-06-21  1:30   ` [PATCH] Add write/read operations for cyclic files in SIM Andrzej Zaborowski
2009-06-22 18:23     ` 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.