Skip to contentSkip to conversation

Read EF_ICCID property of SIM

PATCH In review Daniel Wagner 2 participants 10 messages Apr 26, 2010 – Apr 27, 2010

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 Read EF_ICCID property of SIM

Read out Intergrated Cicruit Card Identifier from SIM.
---
v0: initial version

 doc/sim-api.txt |    5 +++++
 include/types.h |    2 ++
 src/sim.c       |   29 +++++++++++++++++++++++++++++
 src/simutil.h   |    1 +
 4 files changed, 37 insertions(+), 0 deletions(-)
doc/sim-api.txt +5 -0
index fd02396..d608205 100644
@@ -115,3 +115,8 @@ Properties	string SubscriberIdentity [readonly, optional]
 
 			The list contains elements of the same format as the
 			PinRequired property.
+
+		string IntegratedCircuitCardIdentifier [readonly]
+
+			Contains the Intergrated Circuit Card Identifer (ICCID)
+			and is read directly from the SIM.
include/types.h +2 -0
index 7b08b8c..7b903bb 100644
@@ -36,6 +36,8 @@ extern "C" {
 
 typedef int		ofono_bool_t;
 
+#define OFONO_MAX_ICCID_LENGTH 20
+
 /* MCC is always three digits. MNC is either two or three digits */
 #define OFONO_MAX_MCC_LENGTH 3
 #define OFONO_MAX_MNC_LENGTH 3
src/sim.c +29 -0
index bf28f1e..1ce5751 100644
@@ -70,6 +70,7 @@ struct sim_file_op {
 };
 
 struct ofono_sim {
+	char *iccid;
 	char *imsi;
 	enum ofono_sim_phase phase;
 	unsigned char mnc_length;
@@ -288,6 +289,10 @@ static DBusMessage *sim_get_properties(DBusConnection *conn,
 	if (!present)
 		goto done;
 
+	if (sim->iccid)
+		ofono_dbus_dict_append(&dict, "IntegratedCircuitCardIdentifier",
+					DBUS_TYPE_STRING, &sim->iccid);
+		
 	if (sim->imsi)
 		ofono_dbus_dict_append(&dict, "SubscriberIdentity",
 					DBUS_TYPE_STRING, &sim->imsi);
@@ -1292,6 +1297,22 @@ static void sim_retrieve_efli_and_efpl(struct ofono_sim *sim)
 			sim_efpl_read_cb, sim);
 }
 
+static void sim_iccid_read_cb(const struct ofono_error *error,
+				const unsigned char *data, int len, void *user)
+{
+	struct ofono_sim *sim = user;
+	char number[OFONO_MAX_ICCID_LENGTH+ 1];
+
+	if (!error || error->type != OFONO_ERROR_TYPE_NO_ERROR || len != 10)
+		return;
+
+	extract_bcd_number(data, len, number);
+	number[OFONO_MAX_ICCID_LENGTH] = '\0';
+	sim->iccid = g_strdup(number);
+
+	DBG("ICCID %s", sim->iccid);
+}
+
 static void sim_efphase_read_cb(const struct ofono_error *error,
 				const unsigned char *data, int len, void *user)
 {
@@ -1320,6 +1341,9 @@ static void sim_determine_phase(struct ofono_sim *sim)
 
 static void sim_initialize(struct ofono_sim *sim)
 {
+	sim->driver->read_file_transparent(sim, SIM_EF_ICCID_FILEID, 0, 10,
+					   sim_iccid_read_cb, sim);
+
 	/* Perform SIM initialization according to 3GPP 31.102 Section 5.1.1.2
 	 * The assumption here is that if sim manager is being initialized,
 	 * then sim commands are implemented, and the sim manager is then
@@ -1843,6 +1867,11 @@ static void sim_free_state(struct ofono_sim *sim)
 		sim->simop_q = NULL;
 	}
 
+	if (sim->iccid) {
+		g_free(sim->iccid);
+		sim->iccid = NULL;
+	}
+
 	if (sim->imsi) {
 		g_free(sim->imsi);
 		sim->imsi = NULL;
src/simutil.h +1 -0
index 7590cca..d6c52fc 100644
@@ -21,6 +21,7 @@
 
 enum sim_fileid {
 	SIM_EFPL_FILEID = 0x2f05,
+	SIM_EF_ICCID_FILEID = 0x2fe2,
 	SIM_EFLI_FILEID = 0x6f05,
 	SIM_EF_CPHS_MWIS_FILEID = 0x6f11,
 	SIM_EF_CPHS_INFORMATION_FILEID = 0x6f16,
Signature · 1 line
1.6.6.1
#1 lore raw

Hi Daniel,

Quoted 15 lines

Read out Intergrated Cicruit Card Identifier from SIM.
---
v0: initial version

 doc/sim-api.txt |    5 +++++
 include/types.h |    2 ++
 src/sim.c       |   29 +++++++++++++++++++++++++++++
 src/simutil.h   |    1 +
 4 files changed, 37 insertions(+), 0 deletions(-)
doc/sim-api.txt +0 -0
index fd02396..d608205 100644

doc/sim-api.txt Properties string SubscriberIdentity [readonly, · line 119

Quoted 6 lines
doc/sim-api.txt +2 -0
@@ -115,3 +115,8 @@ Properties	string SubscriberIdentity [readonly,
 optional]
 
 			The list contains elements of the same format as the
 			PinRequired property.
+
+		string IntegratedCircuitCardIdentifier [readonly]

I'd like to name this CardIdentifier, ICCID is too ugly and the full name is just too long.

doc/sim-api.txt

Quoted 8 lines
doc/sim-api.txt +8 -0
+static void sim_iccid_read_cb(const struct ofono_error *error,
+				const unsigned char *data, int len, void *user)
+{
+	struct ofono_sim *sim = user;
+	char number[OFONO_MAX_ICCID_LENGTH+ 1];
+
+	if (!error || error->type != OFONO_ERROR_TYPE_NO_ERROR || len != 10)
+		return;

No need to check for error being NULL, we don't allow that.

doc/sim-api.txt

Quoted 8 lines
doc/sim-api.txt +8 -0
+
+	extract_bcd_number(data, len, number);
+	number[OFONO_MAX_ICCID_LENGTH] = '\0';
+	sim->iccid = g_strdup(number);
+
+	DBG("ICCID %s", sim->iccid);
+}
+

You might want to emit the property changed signal with the new ICCID value here.

doc/sim-api.txt static void sim_determine_phase(struct ofono_sim · line 1347

Quoted 11 lines

static void sim_efphase_read_cb(const struct ofono_error *error,

doc/sim-api.txt +3 -0
 				const unsigned char *data, int len, void *user)
 {
@@ -1320,6 +1341,9 @@ static void sim_determine_phase(struct ofono_sim
 *sim)
 
 static void sim_initialize(struct ofono_sim *sim)
 {
+	sim->driver->read_file_transparent(sim, SIM_EF_ICCID_FILEID, 0, 10,
+					   sim_iccid_read_cb, sim);
+

Please use the sim file queue like EFpl does, no need to invent your own solution. The phase check is a very specific case because we cache SIM files by phase of the SIM, so it needs to be known / guessed before the rest of sim file queue runs.

Regards,
-Denis

#2 lore raw

Hi Denis,

Quoted 11 lines

src/sim.c static void sim_retrieve_efli_and_efpl(struct ofono_sim *sim) · line 1315

Quoted 8 lines
src/sim.c +8 -0
+
+	extract_bcd_number(data, len, number);
+	number[OFONO_MAX_ICCID_LENGTH] = '\0';
+	sim->iccid = g_strdup(number);
+
+	DBG("ICCID %s", sim->iccid);
+}
+

You might want to emit the property changed signal with the new ICCID value here.

I had already the property update code there but there was some problem with dbus. I figured that it wasn't setup correctly yet. I'll look into that.

Quoted 6 lines
Quoted 6 lines

static void sim_efphase_read_cb(const struct ofono_error *error,

src/sim.c +0 -0
 				const unsigned char *data, int len, void *user)
 {
@@ -1320,6 +1341,9 @@ static void sim_determine_phase(struct ofono_sim
 *sim)
 
Quoted 8 lines

src/sim.c static void sim_determine_phase(struct ofono_sim *sim) · line 1346

Quoted 5 lines
src/sim.c +3 -0
 static void sim_initialize(struct ofono_sim *sim)
 {
+	sim->driver->read_file_transparent(sim, SIM_EF_ICCID_FILEID, 0, 10,
+					   sim_iccid_read_cb, sim);
+

Please use the sim file queue like EFpl does, no need to invent your own solution.

I used the ofono_sim_read function but that didn't work. On the terminal I saw only:

CRSM=192,12258

With read_file_transparent it is:

ofonod[2048]: Control:> AT+CRSM=176,12258,0,0,10\r
ofonod[2048]: Control:< \r\r\n+CRSM: 144,0,"989422024754212460F6"\r\n\r\nOK\r\n

Quoted 3 lines

The phase check is a very specific case because we cache SIM files by phase of the SIM, so it needs to be known / guessed before the rest of sim file queue runs.

Thanks for the info. I'll update the patch.

daniel

#3 lore raw
Quoted 6 lines · Daniel Wagner
Quoted 2 lines

Please use the sim file queue like EFpl does, no need to invent your own solution.

I used the ofono_sim_read function but that didn't work. On the terminal I saw only:

Quoted 6 lines

CRSM=192,12258

With read_file_transparent it is:

ofonod[2048]: Control:> AT+CRSM=176,12258,0,0,10\r
ofonod[2048]: Control:< \r\r\n+CRSM: 144,0,"989422024754212460F6"\r\n\r\nOK\r\n

I looked into this. It comes down to:

ofono_sim_read -> sim_op_next -> read_file_info

and since sim_op_next does not check what structure type it is, it always calles read_file_info (CRSM=192).

I'm not sure how to resolve this here. The problem is the callback given to sim_op_next has of course a different signature than read_file_transparent wants (ofono_sim_read_file_cb_t vs ofono_sim_read_cb_t)

Should I add something like:

int ofono_sim_read_transparent(struct ofono_sim *sim, int id,
enum ofono_sim_file_structure expected_type, ofono_sim_read_cb_t cb, void *data)

thanks,
daniel

#4 lore raw

Hi Daniel,

Quoted 27 lines · Daniel Wagner
Quoted 6 lines
Quoted 2 lines

Please use the sim file queue like EFpl does, no need to invent your own solution.

I used the ofono_sim_read function but that didn't work. On the terminal I saw only:

Quoted 7 lines

CRSM=192,12258

With read_file_transparent it is:

ofonod[2048]: Control:> AT+CRSM=176,12258,0,0,10\r ofonod[2048]: Control:< \r\r\n+CRSM:
144,0,"989422024754212460F6"\r\n\r\nOK\r\n

I looked into this. It comes down to:

ofono_sim_read -> sim_op_next -> read_file_info

and since sim_op_next does not check what structure type it is, it always calles read_file_info (CRSM=192).

I'm not sure how to resolve this here. The problem is the callback given to sim_op_next has of course a different signature than read_file_transparent wants (ofono_sim_read_file_cb_t vs ofono_sim_read_cb_t)

Quoted 6 lines

Should I add something like:

int ofono_sim_read_transparent(struct ofono_sim *sim, int id,
enum ofono_sim_file_structure expected_type, ofono_sim_read_cb_t cb, void *data)

ofono_sim_read handles transparent, cyclic and record based files. There should be no need to add anything. Just do exactly what e.g. EFli / EFpl functions do.

What modem are you using? Some of them are dumb and don't implement +CRSM 'GET RESPONSE' properly.

Regards,
-Denis

#5 lore raw

Hi Denis,

Quoted 31 lines · Denis Kenzior

Hi Daniel,

Quoted 29 lines · Daniel Wagner
Quoted 6 lines
Quoted 2 lines

Please use the sim file queue like EFpl does, no need to invent your own solution.

I used the ofono_sim_read function but that didn't work. On the terminal I saw only:

Quoted 7 lines

CRSM=192,12258

With read_file_transparent it is:

ofonod[2048]: Control:> AT+CRSM=176,12258,0,0,10\r ofonod[2048]: Control:< \r\r\n+CRSM:
144,0,"989422024754212460F6"\r\n\r\nOK\r\n

I looked into this. It comes down to:

ofono_sim_read -> sim_op_next -> read_file_info

and since sim_op_next does not check what structure type it is, it always calles read_file_info (CRSM=192).

I'm not sure how to resolve this here. The problem is the callback given to sim_op_next has of course a different signature than read_file_transparent wants (ofono_sim_read_file_cb_t vs ofono_sim_read_cb_t)

Should I add something like:

Quoted 8 lines
Quoted 4 lines

int ofono_sim_read_transparent(struct ofono_sim *sim, int id,
enum ofono_sim_file_structure expected_type, ofono_sim_read_cb_t cb, void *data)

ofono_sim_read handles transparent, cyclic and record based files. There should be no need to add anything. Just do exactly what e.g. EFli / EFpl functions do.

Ah, that's good to know. I following the EFli / EFpl templates:

static void sim_initialize(struct ofono_sim *sim)

{
	ofono_sim_read(sim, SIM_EF_ICCID_FILEID,
		OFONO_SIM_FILE_STRUCTURE_TRANSPARENT,
		sim_iccid_read_cb, sim);

...

I have not moved the call to
another place as you have suggested yet.

The debug output is:

ofonod[18879]: src/modem.c:ofono_modem_create() name: (null), type: hso ofonod[18879]: src/modem.c:set_modem_property() modem 0xc0f260 property Path ofonod[18879]: src/modem.c:set_modem_property() modem 0xc0f260 property Registered ofonod[18879]: src/modem.c:get_modem_property() modem 0xc0f260 property Registered ofonod[18879]: src/modem.c:get_modem_property() modem 0xc0f260 property ApplicationPort ofonod[18879]: src/modem.c:get_modem_property() modem 0xc0f260 property ControlPort ofonod[18879]: src/modem.c:get_modem_property() modem 0xc0f260 property NetworkInterface ofonod[18879]: src/modem.c:get_modem_property() modem 0xc0f260 property Path ofonod[18879]: src/modem.c:get_modem_property() modem 0xc0f260 property Registered ofonod[18879]: src/modem.c:set_modem_property() modem 0xc0f260 property ApplicationPort ofonod[18879]: src/modem.c:get_modem_property() modem 0xc0f260 property ApplicationPort ofonod[18879]: src/modem.c:get_modem_property() modem 0xc0f260 property ControlPort ofonod[18879]: src/modem.c:get_modem_property() modem 0xc0f260 property NetworkInterface ofonod[18879]: src/modem.c:get_modem_property() modem 0xc0f260 property Path ofonod[18879]: src/modem.c:get_modem_property() modem 0xc0f260 property Registered ofonod[18879]: src/modem.c:set_modem_property() modem 0xc0f260 property ControlPort ofonod[18879]: src/modem.c:get_modem_property() modem 0xc0f260 property ApplicationPort ofonod[18879]: src/modem.c:get_modem_property() modem 0xc0f260 property ControlPort ofonod[18879]: src/modem.c:get_modem_property() modem 0xc0f260 property NetworkInterface ofonod[18879]: src/modem.c:get_modem_property() modem 0xc0f260 property Path ofonod[18879]: src/modem.c:get_modem_property() modem 0xc0f260 property Registered ofonod[18879]: src/modem.c:set_modem_property() modem 0xc0f260 property NetworkInterface ofonod[18879]: src/modem.c:get_modem_property() modem 0xc0f260 property ApplicationPort ofonod[18879]: src/modem.c:get_modem_property() modem 0xc0f260 property ControlPort ofonod[18879]: src/modem.c:get_modem_property() modem 0xc0f260 property NetworkInterface ofonod[18879]: src/modem.c:set_modem_property() modem 0xc0f260 property Registered ofonod[18879]: src/modem.c:unregister_property() property 0xc0ffb0 ofonod[18879]: plugins/hso.c:hso_probe() 0xc0f260
ofonod[18879]: src/modem.c:get_modem_property() modem 0xc0f260 property Path ofonod[18879]: src/modem.c:get_modem_property() modem 0xc0f260 property Registered ofonod[18879]: plugins/hso.c:hso_enable() 0xc0f260
ofonod[18879]: src/modem.c:get_modem_property() modem 0xc0f260 property ControlPort ofonod[18879]: src/modem.c:get_modem_property() modem 0xc0f260 property ApplicationPort ofonod[18879]: Control:> ATE0\r
ofonod[18879]: App:> ATE0\r
ofonod[18879]: App:< \r\nOK\r\n
ofonod[18879]: Control:< \r\nOK\r\n
ofonod[18879]: Control:> AT+CFUN=1\r
ofonod[18879]: Control:< \r\nOK\r\n
ofonod[18879]: plugins/hso.c:cfun_enable()
ofonod[18879]: plugins/hso.c:hso_pre_sim() 0xc0f260
ofonod[18879]: src/sim.c:ofono_sim_add_state_watch() 0xc0f500 ofonod[18879]: src/sim.c:ofono_sim_add_state_watch() 0xc0f500 ofonod[18879]: Control:> AT+CGMI\r
ofonod[18879]: Control:< \r\nOption N.V.\r\n\r\nOK\r\n
ofonod[18879]: Control:> AT+CRSM=176,28590,0,0,1\r
ofonod[18879]: Control:< \r\r\n+CRSM: 144,0,"03"\r\n\r\nOK\r\n ofonod[18879]: drivers/atmodem/sim.c:at_crsm_read_cb() crsm_read_cb: 90, 00, 1 ofonod[18879]: Control:> AT+CRSM=192,12258\r
ofonod[18879]: Control:< \r\r\n+CRSM: 111,0\r\n\r\nOK\r\n
ofonod[18879]: Control:> AT+CGMM\r
ofonod[18879]: Control:< \r\nGlobeTrotter HSUPA Modem\r\n\r\nOK\r\n ofonod[18879]: Control:> AT+CPIN?\r
ofonod[18879]: Control:< \r\n+CPIN: SIM PIN\r\n\r\nOK\r\n
ofonod[18879]: drivers/atmodem/sim.c:at_cpin_cb() crsm_pin_cb: SIM PIN ofonod[18879]: Control:> AT+CRSM=192,28421\r
ofonod[18879]: Control:< \r\r\n+CRSM: 111,0\r\n\r\nOK\r\n
ofonod[18879]: Control:> AT+CGMR\r
ofonod[18879]: Control:< \r\n2.12.0.0Hd (Date: Oct 29 2009, Time: 09:56:48)\r\n\r\nOK\r\n ofonod[18879]: Control:> AT+CRSM=192,12037\r
ofonod[18879]: Control:< \r\r\n+CRSM: 111,0\r\n\r\nOK\r\n
ofonod[18879]: Control:> AT+CGSN\r
ofonod[18879]: Control:< \r\n351721030157214,PK29997020\r\n\r\nOK\r\n

Quoted 2 lines

What modem are you using? Some of them are dumb and don't implement +CRSM 'GET RESPONSE' properly.

It's a Option iCON 451. I didn't check what "\r\r\n+CRSM:
144,0,"03"\r\n\r\nOK\r\n" exaclty means. I guess I have to check the standard.

cheers,
daniel

#6 lore raw
Quoted 3 lines

It's a Option iCON 451. I didn't check what "\r\r\n+CRSM:
144,0,"03"\r\n\r\nOK\r\n" exaclty means. I guess I have to check the standard.

(of course I did copy the wrong line)

ofonod[18879]: Control:< \r\r\n+CRSM: 111,0\r\n\r\nOK\r\n

#7 lore raw

Hi Daniel,

Quoted 8 lines
Quoted 3 lines

It's a Option iCON 451. I didn't check what "\r\r\n+CRSM:
144,0,"03"\r\n\r\nOK\r\n" exaclty means. I guess I have to check the standard.

(of course I did copy the wrong line)

ofonod[18879]: Control:< \r\r\n+CRSM: 111,0\r\n\r\nOK\r\n

Yes the Option Modems always return +CRSM: 111 -> Unspecified Error whenever we use 'GET RESPONSE'. It seems that this function is simply not implemented in their firmware, even though reading files directly from the SIM (in the case of EFphase or EFiccid) seems to work.

Unfortunately, with a few exceptions, we actually need to call 'GET RESPONSE' first to find the record size / file size before we can attempt to read the file. One way to do this might be to use +CSIM to walk the EF tree, but that is quite nasty.

This needs to be fixed for the Option driver. Perhaps someone here knows a way...

Regards,
-Denis

#8 lore raw

Hi Denis,

Quoted 6 lines
Quoted 6 lines
Quoted 3 lines

It's a Option iCON 451. I didn't check what "\r\r\n+CRSM:
144,0,"03"\r\n\r\nOK\r\n" exaclty means. I guess I have to check the standard.

(of course I did copy the wrong line)

Quoted 7 lines
Quoted 2 lines

ofonod[18879]: Control:< \r\r\n+CRSM: 111,0\r\n\r\nOK\r\n

Yes the Option Modems always return +CRSM: 111 -> Unspecified Error whenever we use 'GET RESPONSE'. It seems that this function is simply not implemented in their firmware, even though reading files directly from the SIM (in the case of EFphase or EFiccid) seems to work.

Aside from the Option modem I have a Huawei E160 around for testing:

ofonod[19115]: > AT+CRSM=192,12258\r ofonod[19115]: < AT+CRSM=192,12258\r ofonod[19115]: < \r\n+CME ERROR: SIM PIN required\r\n

Looks like it doesn't like the 'GET RESPONSE' either.

Quoted 4 lines

Unfortunately, with a few exceptions, we actually need to call 'GET RESPONSE' first to find the record size / file size before we can attempt to read the file. One way to do this might be to use +CSIM to walk the EF tree, but that is quite nasty.

To be honest I have not the slighest idea what you mean :)

Quoted 2 lines

This needs to be fixed for the Option driver. Perhaps someone here knows a way...

Well, if some one tells me what to do I work on it. But I'm a bit lost without help.

cheers,
daniel

#9 lore raw

Hi Daniel,

Quoted 15 lines

Hi Denis,

Quoted 4 lines
Quoted 4 lines
Quoted 3 lines

It's a Option iCON 451. I didn't check what "\r\r\n+CRSM:
144,0,"03"\r\n\r\nOK\r\n" exaclty means. I guess I have to check the standard.

Quoted 8 lines
Quoted 3 lines

(of course I did copy the wrong line)

ofonod[18879]: Control:< \r\r\n+CRSM: 111,0\r\n\r\nOK\r\n

Yes the Option Modems always return +CRSM: 111 -> Unspecified Error whenever we use 'GET RESPONSE'. It seems that this function is simply not implemented in their firmware, even though reading files directly from the SIM (in the case of EFphase or EFiccid) seems to work.

Quoted 9 lines

Aside from the Option modem I have a Huawei E160 around for testing:

ofonod[19115]: > AT+CRSM=192,12258\r ofonod[19115]: < AT+CRSM=192,12258\r ofonod[19115]: < \r\n+CME ERROR: SIM PIN required\r\n

Looks like it doesn't like the 'GET RESPONSE' either.

There are two possibilities here:
- The SIM is not per spec and actually requires PIN to be entered before
reading the EFiccid
- The Huawei firmware is not per spec and blocks the reading of EFiccid before
the SIM PIN has been entered

Since you managed to read the EFiccid on the Option hardware, I assume that this is a Huawei firmware bug...

Not really oFono's fault, welcome to the wonderful world of GSM hardware. Get yourself an MBM F3507/F3607, their firmware usually gets this right...

Quoted 5 lines
Quoted 2 lines

This needs to be fixed for the Option driver. Perhaps someone here knows a way...

Well, if some one tells me what to do I work on it. But I'm a bit lost without help.

Me too ;)

Regards,
-Denis