Hi,
2011/2/23 Andreas Westin <andreas.westin(a)stericsson.com>:
From: Jessica Nilsson <jessica.j.nilsson(a)stericsson.com>
---
 drivers/isimodem/sim.c | 2678 ++++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 2480 insertions(+), 198 deletions(-)
diff --git a/drivers/isimodem/sim.c b/drivers/isimodem/sim.c
index bfecbc9..117129b 100644
--- a/drivers/isimodem/sim.c
+++ b/drivers/isimodem/sim.c
@@ -3,6 +3,7 @@
 *  oFono - Open Source Telephony
 *
 *  Copyright (C) 2009-2010 Nokia Corporation and/or its subsidiary(-ies).
+ * Â Copyright (C) ST-Ericsson SA 2011.
 *
 *  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
@@ -33,22 +34,211 @@
 #include <gisi/message.h>
 #include <gisi/client.h>
+#include <gisi/iter.h>
 #include <ofono/log.h>
 #include <ofono/modem.h>
 #include <ofono/sim.h>
-#include "simutil.h"
+#include <ofono/dbus.h>
+#include "simutil.h"
 #include "isimodem.h"
 #include "isiutil.h"
 #include "sim.h"
+#include "uicc.h"
 #include "debug.h"
-#define SIM_MAX_SPN_LENGTH Â Â 16
+#define PIN_PROMPT
+#define STATUS_WORD_HANDLING
+
+#define SIM_MAX_SPN_LENGTH Â Â Â Â Â Â 16
+#define CLIENT_ID Â Â Â Â Â Â Â Â Â Â Â 1
+
+#define     ADF_USIM             0x7FFF
+#define     MAX_SIM_APPS           0x08
+#define     NOT_AVAILABLE          -1
+#define     NOT_ACTIVATED          -1
+
+/* File info parameters */
+enum file_info_params {
+ Â Â Â FCP_TEMPLATE = Â Â Â Â Â Â Â Â Â 0x62,
+ Â Â Â FCP_FILE_SIZE = Â Â Â Â Â Â Â Â 0x80,
+ Â Â Â FCP_FILE_DESC = Â Â Â Â Â Â Â Â 0x82,
+ Â Â Â FCP_FILE_ID = Â Â Â Â Â Â Â Â Â 0x83,
+ Â Â Â FCP_FILE_LIFECYCLE = Â Â Â Â Â Â 0x8A,
+ Â Â Â FCP_FILE_SECURITY_ARR = Â Â Â Â 0x8B,
+ Â Â Â FCP_FILE_SECURITY_COMPACT = Â Â 0x8C,
+ Â Â Â FCP_FILE_SECURITY_EXPANDED = Â Â 0xAB,
+ Â Â Â FCP_PIN_STATUS = Â Â Â Â Â Â Â Â 0xC6,
+};
+
+struct sim_applications {
+ Â Â Â int app_list[MAX_SIM_APPS];
+ Â Â Â int app_type[MAX_SIM_APPS];
+};
 struct sim_data {
    GIsiClient *client;
+ Â Â Â GIsiClient *primary;
+ Â Â Â GIsiClient *secondary;
+ Â Â Â gboolean iccid;
    gboolean registered;
+ Â Â Â gboolean uicc_app_started;
+ Â Â Â gboolean pin_state_received;
+ Â Â Â gboolean passwd_required;
+ Â Â Â int app_id;
+ Â Â Â int trying_app_id;
+ Â Â Â int app_type;
+ Â Â Â int trying_app_type;
+ Â Â Â uint8_t client_id;
+ Â Â Â uint8_t current_pin_id;
+ Â Â Â uint8_t pin1_id;
+ Â Â Â uint8_t pin2_id;
+ Â Â Â struct sim_applications *sim_application_list_p;
+};
+
+struct ofono_sim_local {
+ Â Â Â char *iccid;
+ Â Â Â char *imsi;
+ Â Â Â enum ofono_sim_phase phase;
+ Â Â Â unsigned char mnc_length;
+ Â Â Â GSList *own_numbers;
+ Â Â Â GSList *new_numbers;
+ Â Â Â GSList *service_numbers;
+ Â Â Â gboolean sdn_ready;
+ Â Â Â enum ofono_sim_state state;
+ Â Â Â enum ofono_sim_password_type pin_type;
+ Â Â Â gboolean locked_pins[OFONO_SIM_PASSWORD_INVALID];
+ Â Â Â char **language_prefs;
+ Â Â Â GQueue *simop_q;
+ Â Â Â gint simop_source;
+ Â Â Â unsigned char efmsisdn_length;
+ Â Â Â unsigned char efmsisdn_records;
+ Â Â Â unsigned char *efli;
+ Â Â Â unsigned char efli_length;
+ Â Â Â enum ofono_sim_cphs_phase cphs_phase;
+ Â Â Â unsigned char cphs_service_table[2];
+ Â Â Â struct ofono_watchlist *state_watches;
+ Â Â Â const struct ofono_sim_driver *driver;
+ Â Â Â void *driver_data;
+ Â Â Â struct ofono_atom *atom;
+ Â Â Â DBusMessage *pending;
+};
This is completely inappropriate; struct ofono_sim is private on purpose.
+
+struct sim_passwd_to_pin_id {
+ Â Â Â int8_t passwd_type;
+ Â Â Â int8_t pin_id;
+};
+
+static struct sim_passwd_to_pin_id const pin_ids[] = {
+ Â Â Â {OFONO_SIM_PASSWORD_NONE, 0},
+ Â Â Â {OFONO_SIM_PASSWORD_SIM_PIN, 1},
+ Â Â Â {OFONO_SIM_PASSWORD_PHSIM_PIN, 0},
+ Â Â Â {OFONO_SIM_PASSWORD_PHFSIM_PIN, 0},
+ Â Â Â {OFONO_SIM_PASSWORD_SIM_PIN2, -1},
+ Â Â Â {OFONO_SIM_PASSWORD_PHNET_PIN, 0x11},
+ Â Â Â {OFONO_SIM_PASSWORD_PHNETSUB_PIN, 0},
+ Â Â Â {OFONO_SIM_PASSWORD_PHSP_PIN, 0},
+ Â Â Â {OFONO_SIM_PASSWORD_PHCORP_PIN, 0},
+ Â Â Â {OFONO_SIM_PASSWORD_SIM_PUK, -1},
+ Â Â Â {OFONO_SIM_PASSWORD_PHFSIM_PUK, 0},
+ Â Â Â {OFONO_SIM_PASSWORD_SIM_PUK2, -1},
+ Â Â Â {OFONO_SIM_PASSWORD_PHNET_PUK, 0},
+ Â Â Â {OFONO_SIM_PASSWORD_PHNETSUB_PUK, 0},
+ Â Â Â {OFONO_SIM_PASSWORD_PHSP_PUK, 0},
+ Â Â Â {OFONO_SIM_PASSWORD_PHCORP_PUK, 0},
+ Â Â Â {OFONO_SIM_PASSWORD_INVALID, 0}
+};
+
+const uint8_t upin_id = 0x11;
+
+struct file_info {
+ Â Â Â int fileid;
+ Â Â Â int length;
+ Â Â Â int structure;
+ Â Â Â int record_length;
+ Â Â Â uint8_t access[3];
+ Â Â Â uint8_t file_status;
+};
+
+struct read_file_data {
+ Â Â Â struct file_info *info;
+ Â Â Â struct sim_data *sim_data;
+};
+
+static struct file_info const static_file_info[] = {
+ Â Â Â {
+ Â Â Â Â Â Â Â SIM_EFSPN_FILEID, 17, OFONO_SIM_FILE_STRUCTURE_TRANSPARENT,
+ Â Â Â Â Â Â Â 0, { 0x0e, 0xff, 0xee }
+ Â Â Â },
+ Â Â Â {
+ Â Â Â Â Â Â Â SIM_EF_ICCID_FILEID, 10, OFONO_SIM_FILE_STRUCTURE_TRANSPARENT,
+ Â Â Â Â Â Â Â 10, { 0x0f, 0xff, 0xee }
+ Â Â Â },
+ Â Â Â {
+ Â Â Â Â Â Â Â SIM_EFPL_FILEID, 1, OFONO_SIM_FILE_STRUCTURE_TRANSPARENT,
+ Â Â Â Â Â Â Â 1, { 0x0f, 0xff, 0xff }
+ Â Â Â }, /* not found */
+ Â Â Â {
+ Â Â Â Â Â Â Â SIM_EFLI_FILEID, 1, OFONO_SIM_FILE_STRUCTURE_TRANSPARENT,
+ Â Â Â Â Â Â Â 1, { 0x0f, 0xff, 0xff }
+ Â Â Â }, /* not found */
+ Â Â Â {
+ Â Â Â Â Â Â Â SIM_EFMSISDN_FILEID, 28, OFONO_SIM_FILE_STRUCTURE_FIXED,
+ Â Â Â Â Â Â Â 28, { 0x01, 0xff, 0xee }
+ Â Â Â },
+ Â Â Â {
+ Â Â Â Â Â Â Â SIM_EFAD_FILEID, 20, OFONO_SIM_FILE_STRUCTURE_TRANSPARENT,
+ Â Â Â Â Â Â Â 20, { 0x0e, 0xff, 0xee }
+ Â Â Â },
+ Â Â Â {
+ Â Â Â Â Â Â Â SIM_EFPHASE_FILEID, 1, OFONO_SIM_FILE_STRUCTURE_TRANSPARENT,
+ Â Â Â Â Â Â Â 1, { 0x0e, 0xff, 0xee }
+ Â Â Â },
+ Â Â Â {
+ Â Â Â Â Â Â Â SIM_EFPNN_FILEID, 4 * 18, OFONO_SIM_FILE_STRUCTURE_FIXED,
+ Â Â Â Â Â Â Â 18, { 0x0e, 0xff, 0xee }
+ Â Â Â }, /* 4 records, name 16 bytes */
+ Â Â Â {
+ Â Â Â Â Â Â Â SIM_EFOPL_FILEID, 4 * 24, OFONO_SIM_FILE_STRUCTURE_FIXED,
+ Â Â Â Â Â Â Â 24, { 0x0e, 0xff, 0xee }
+ Â Â Â }, /* 4 records, name 16 bytes */
+ Â Â Â {
+ Â Â Â Â Â Â Â SIM_EFMBI_FILEID, 5, OFONO_SIM_FILE_STRUCTURE_FIXED,
+ Â Â Â Â Â Â Â 5, { 0x0e, 0xff, 0xee }
+ Â Â Â },
+ Â Â Â {
+ Â Â Â Â Â Â Â SIM_EFMWIS_FILEID, 6, OFONO_SIM_FILE_STRUCTURE_FIXED,
+ Â Â Â Â Â Â Â 6, { 0x01, 0xff, 0xee }
+ Â Â Â },
+ Â Â Â {
+ Â Â Â Â Â Â Â SIM_EFSPDI_FILEID, 64, OFONO_SIM_FILE_STRUCTURE_TRANSPARENT,
+ Â Â Â Â Â Â Â 64, { 0x0e, 0xff, 0xee }
+ Â Â Â },
+ Â Â Â {
+ Â Â Â Â Â Â Â SIM_EFECC_FILEID, 5 * 3, OFONO_SIM_FILE_STRUCTURE_TRANSPARENT,
+ Â Â Â Â Â Â Â 3, { 0x0e, 0xff, 0xee }
+ Â Â Â }, /* Can be also FIXED in 3G */
+ Â Â Â {
+ Â Â Â Â Â Â Â SIM_EFCBMIR_FILEID, 8 * 4, OFONO_SIM_FILE_STRUCTURE_TRANSPARENT,
+ Â Â Â Â Â Â Â 4, { 0x01, 0xff, 0xee }
+ Â Â Â }, /* 8 records */
+ Â Â Â {
+ Â Â Â Â Â Â Â SIM_EFCBMI_FILEID, 8 * 2, OFONO_SIM_FILE_STRUCTURE_TRANSPARENT,
+ Â Â Â Â Â Â Â 2, { 0x01, 0xff, 0xee }
+ Â Â Â }, /* 8 records */
+ Â Â Â {
+ Â Â Â Â Â Â Â SIM_EFCBMID_FILEID, 8 * 2, OFONO_SIM_FILE_STRUCTURE_TRANSPARENT,
+ Â Â Â Â Â Â Â 2, { 0x01, 0xff, 0x11 }
+ Â Â Â }, /* 8 records */
+ Â Â Â {
+ Â Â Â Â Â Â Â SIM_EFSMSP_FILEID, 56, OFONO_SIM_FILE_STRUCTURE_FIXED,
+ Â Â Â Â Â Â Â 56, { 0x01, 0xff, 0xee }
+ Â Â Â },
+ Â Â Â {
+ Â Â Â Â Â Â Â SIM_EFIMSI_FILEID, 9, OFONO_SIM_FILE_STRUCTURE_TRANSPARENT,
+ Â Â Â Â Â Â Â 9, { 0x0e, 0xff, 0xee }
+ Â Â Â },
 };
 struct sim_imsi {
@@ -66,14 +256,275 @@ struct sim_spn {
    uint8_t disp_roam;
 };
-struct file_info {
- Â Â Â int fileid;
- Â Â Â int length;
- Â Â Â int structure;
- Â Â Â int record_length;
- Â Â Â uint8_t access[3];
- Â Â Â uint8_t file_status;
-};
+static uint8_t fileid_to_short_fileid(const int fileid)
+{
+ Â Â Â uint8_t ret;
+
+ Â Â Â /* SFI list from 3GPP TS 31.102 Annex H */
+ Â Â Â switch (fileid) {
+ Â Â Â case SIM_EFECC_FILEID:
+ Â Â Â Â Â Â Â ret = 01;
+ Â Â Â Â Â Â Â break;
+ Â Â Â case SIM_EFLI_FILEID:
+ Â Â Â Â Â Â Â ret = 02;
+ Â Â Â Â Â Â Â break;
+ Â Â Â case SIM_EFAD_FILEID:
+ Â Â Â Â Â Â Â ret = 03;
+ Â Â Â Â Â Â Â break;
+ Â Â Â case SIM_EFIMSI_FILEID:
+ Â Â Â Â Â Â Â ret = 07;
+ Â Â Â Â Â Â Â break;
+ Â Â Â case SIM_EFCBMID_FILEID:
+ Â Â Â Â Â Â Â ret = 0x0E;
+ Â Â Â Â Â Â Â break;
+ Â Â Â case SIM_EFPNN_FILEID:
+ Â Â Â Â Â Â Â ret = 0x19;
+ Â Â Â Â Â Â Â break;
+ Â Â Â case SIM_EFOPL_FILEID:
+ Â Â Â Â Â Â Â ret = 0x1A;
+ Â Â Â Â Â Â Â break;
+ Â Â Â default:
+ Â Â Â Â Â Â Â ret = UICC_SFI_NOT_PRESENT;
+ Â Â Â Â Â Â Â break;
+ Â Â Â }
+
+ Â Â Â return ret;
+}
+
+static int sim_applications_get_next_index(struct sim_applications *sa,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â int current_app)
+{
+ Â Â Â int i;
+
+ Â Â Â if (current_app >= (MAX_SIM_APPS - 1))
+ Â Â Â Â Â Â Â return NOT_AVAILABLE;
+
+ Â Â Â for (i = ++current_app; i < MAX_SIM_APPS; i++) {
+
+ Â Â Â Â Â Â Â if (sa->app_list[i] && (sa->app_type[i] !=
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â UICC_APPL_TYPE_UNKNOWN))
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â return i;
+ Â Â Â Â Â Â Â }
+
+ Â Â Â return NOT_AVAILABLE;
+}
+
+static uint8_t get_pin_id(struct sim_data *sd,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â uint8_t passwd_type,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â int8_t *index)
+{
+ Â Â Â const uint16_t MAX_INDEX = (sizeof(pin_ids)/sizeof(
+ Â Â Â Â Â Â Â Â Â Â Â struct sim_passwd_to_pin_id));
+ Â Â Â uint8_t i, pin_id;
+ Â Â Â *index = -1;
+
+ Â Â Â for (i = 0; i < Â MAX_INDEX; i++) {
+ Â Â Â Â Â Â Â if (pin_ids[i].passwd_type == passwd_type)
+ Â Â Â Â Â Â Â Â Â Â Â *index = i;
+ Â Â Â }
+
+ Â Â Â switch (passwd_type) {
+ Â Â Â case OFONO_SIM_PASSWORD_SIM_PIN:
+ Â Â Â case OFONO_SIM_PASSWORD_SIM_PUK:
+ Â Â Â Â Â Â Â return sd->pin1_id;
+ Â Â Â case OFONO_SIM_PASSWORD_SIM_PIN2:
+ Â Â Â case OFONO_SIM_PASSWORD_SIM_PUK2:
+ Â Â Â Â Â Â Â return sd->pin2_id;
+ Â Â Â default:
+
+ Â Â Â Â Â Â Â if (*index == -1)
+ Â Â Â Â Â Â Â Â Â Â Â pin_id = 0;
+ Â Â Â Â Â Â Â else
+ Â Â Â Â Â Â Â Â Â Â Â pin_id = pin_ids[*index].pin_id;
+
+ Â Â Â Â Â Â Â return pin_id;
+ Â Â Â }
+}
+
+static void update_locked_pin(struct ofono_sim_local *local_sim,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â uint8_t lock_type, uint8_t pinID)
+{
+ Â Â Â struct sim_data *sd = ofono_sim_get_data((struct ofono_sim *)local_sim);
+
+ Â Â Â switch (lock_type) {
+ Â Â Â case UICC_PIN_VERIFY_NEEDED:
+
+ Â Â Â Â Â Â Â if (pinID <= sd->pin1_id) {
+ Â Â Â Â Â Â Â Â Â Â Â local_sim->pin_type =
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â OFONO_SIM_PASSWORD_SIM_PIN;
+ Â Â Â Â Â Â Â Â Â Â Â local_sim->locked_pins[
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â OFONO_SIM_PASSWORD_SIM_PIN] = TRUE;
+ Â Â Â Â Â Â Â Â Â Â Â sd->passwd_required = TRUE;
+ Â Â Â Â Â Â Â } else if (pinID == sd->pin2_id) {
+ Â Â Â Â Â Â Â Â Â Â Â local_sim->pin_type =
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â OFONO_SIM_PASSWORD_SIM_PIN2;
+ Â Â Â Â Â Â Â Â Â Â Â local_sim->locked_pins[
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â OFONO_SIM_PASSWORD_SIM_PIN2] = TRUE;
+ Â Â Â Â Â Â Â Â Â Â Â sd->passwd_required = TRUE;
+ Â Â Â Â Â Â Â } else if (pinID == upin_id) {
+ Â Â Â Â Â Â Â Â Â Â Â local_sim->pin_type =
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â OFONO_SIM_PASSWORD_PHNET_PIN;
+ Â Â Â Â Â Â Â Â Â Â Â local_sim->locked_pins[
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â OFONO_SIM_PASSWORD_PHNET_PIN] = TRUE;
+ Â Â Â Â Â Â Â Â Â Â Â sd->passwd_required = TRUE;
+ Â Â Â Â Â Â Â }
+
+ Â Â Â Â Â Â Â break;
+ Â Â Â case UICC_PIN_UNBLOCK_NEEDED:
+
+ Â Â Â Â Â Â Â if (pinID == sd->pin1_id) {
+ Â Â Â Â Â Â Â Â Â Â Â local_sim->pin_type =
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â OFONO_SIM_PASSWORD_SIM_PUK;
+ Â Â Â Â Â Â Â Â Â Â Â local_sim->locked_pins[
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â OFONO_SIM_PASSWORD_SIM_PUK] = TRUE;
+ Â Â Â Â Â Â Â Â Â Â Â sd->passwd_required = TRUE;
+ Â Â Â Â Â Â Â } else if (pinID == sd->pin2_id) {
+ Â Â Â Â Â Â Â Â Â Â Â local_sim->pin_type =
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â OFONO_SIM_PASSWORD_SIM_PUK2;
+ Â Â Â Â Â Â Â Â Â Â Â local_sim->locked_pins[
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â OFONO_SIM_PASSWORD_SIM_PUK2] = TRUE;
+ Â Â Â Â Â Â Â Â Â Â Â sd->passwd_required = TRUE;
+ Â Â Â Â Â Â Â } else if (pinID == upin_id) {
+ Â Â Â Â Â Â Â Â Â Â Â local_sim->pin_type =
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â OFONO_SIM_PASSWORD_PHNET_PUK;
+ Â Â Â Â Â Â Â Â Â Â Â local_sim->locked_pins[
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â OFONO_SIM_PASSWORD_PHNET_PUK] = TRUE;
+ Â Â Â Â Â Â Â Â Â Â Â sd->passwd_required = TRUE;
+ Â Â Â Â Â Â Â }
+
+ Â Â Â Â Â Â Â break;
+ Â Â Â default:
+ Â Â Â Â Â Â Â break;
+ Â Â Â }
+}
Let's start from what exactly this is trying to do. You can't access
the sim atom's internal state, so there needs to be another way to do
whatever this is trying to do.
+static gboolean get_fileid_path(struct ofono_sim *sim,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â int *mf_path,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â int *df1_path,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â int *df2_path,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â unsigned char *df_len,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â int fileid)
+{
+ Â Â Â struct sim_data *sd = ofono_sim_get_data(sim);
+
+ Â Â Â switch (fileid) {
+ Â Â Â case SIM_EFPL_FILEID:
+ Â Â Â case SIM_EF_ICCID_FILEID:
+ Â Â Â Â Â Â Â *mf_path = SIM_MF_FILEID;
+ Â Â Â Â Â Â Â *df1_path = 0x0000;
+ Â Â Â Â Â Â Â *df2_path = 0x0000;
+ Â Â Â Â Â Â Â *df_len = 2;
+ Â Â Â Â Â Â Â break;
+ Â Â Â case SIM_EFSMSP_FILEID:
+ Â Â Â case SIM_EFSDN_FILEID:
+ Â Â Â case SIM_EFMSISDN_FILEID:
+ Â Â Â Â Â Â Â *mf_path = SIM_MF_FILEID;
+
+ Â Â Â Â Â Â Â if (UICC_APPL_TYPE_ICC_SIM == sd->app_type)
+ Â Â Â Â Â Â Â Â Â Â Â *df1_path = SIM_DFTELECOM_FILEID;
+ Â Â Â Â Â Â Â else
+ Â Â Â Â Â Â Â Â Â Â Â *df1_path = ADF_USIM;
+
+ Â Â Â Â Â Â Â *df2_path = 0x0000;
+ Â Â Â Â Â Â Â *df_len = 4;
+ Â Â Â Â Â Â Â break;
+ Â Â Â case SIM_EFLI_FILEID:
+ Â Â Â case SIM_EFSPN_FILEID:
+ Â Â Â case SIM_EFAD_FILEID:
+ Â Â Â case SIM_EFPNN_FILEID:
+ Â Â Â case SIM_EFOPL_FILEID:
+ Â Â Â case SIM_EFMBDN_FILEID:
+ Â Â Â case SIM_EFMBI_FILEID:
+ Â Â Â case SIM_EFMWIS_FILEID:
+ Â Â Â case SIM_EFSPDI_FILEID:
+ Â Â Â case SIM_EFECC_FILEID:
+ Â Â Â case SIM_EFCBMI_FILEID:
+ Â Â Â case SIM_EFCBMIR_FILEID:
+ Â Â Â case SIM_EFCBMID_FILEID:
+ Â Â Â case SIM_EFIMSI_FILEID:
+ Â Â Â case SIM_EFPHASE_FILEID: /* 3GPP TS 11.11 */
+ Â Â Â case SIM_EFARR_FILEID:
+ Â Â Â case SIM_EF_CPHS_INFORMATION_FILEID:
+ Â Â Â Â Â Â Â *mf_path = SIM_MF_FILEID;
+
+ Â Â Â Â Â Â Â if (UICC_APPL_TYPE_ICC_SIM == sd->app_type)
+ Â Â Â Â Â Â Â Â Â Â Â *df1_path = SIM_DFGSM_FILEID;
+ Â Â Â Â Â Â Â else
+ Â Â Â Â Â Â Â Â Â Â Â *df1_path = ADF_USIM;
+
+ Â Â Â Â Â Â Â *df2_path = 0x0000;
+ Â Â Â Â Â Â Â *df_len = 4;
+ Â Â Â Â Â Â Â break;
+ Â Â Â Â Â Â Â /* No info */
+ Â Â Â case SIM_EF_CPHS_MBDN_FILEID:
+ Â Â Â case SIM_EF_CPHS_MWIS_FILEID:
+ Â Â Â Â Â Â Â DBG("======== No path info for %04X", fileid);
+ Â Â Â Â Â Â Â return FALSE;
+ Â Â Â case SIM_EFADN_FILEID: /* Only for SIM */
+ Â Â Â case SIM_EFEXT1_FILEID: /* Only for SIM */
+ Â Â Â Â Â Â Â *mf_path = SIM_MF_FILEID;
+ Â Â Â Â Â Â Â *df1_path = SIM_DFTELECOM_FILEID;
+ Â Â Â Â Â Â Â *df2_path = 0x0000;
+ Â Â Â Â Â Â Â *df_len = 4;
+ Â Â Â Â Â Â Â break;
+ Â Â Â default:
+ Â Â Â Â Â Â Â *mf_path = SIM_MF_FILEID;
+ Â Â Â Â Â Â Â *df1_path = SIM_DFTELECOM_FILEID;
+ Â Â Â Â Â Â Â *df2_path = SIM_DFPHONEBOOK_FILEID;
+ Â Â Â Â Â Â Â *df_len = 6;
+ Â Â Â Â Â Â Â break;
+ Â Â Â }
+
+ Â Â Â return TRUE;
+}
+
+int get_app_id(GIsiModem *modem)
+{
+ Â Â Â struct ofono_sim *sim;
+
+ Â Â Â if (modem == NULL)
+ Â Â Â Â Â Â Â return -1;
+
+ Â Â Â sim = g_isi_modem_get_sim(modem);
+
+ Â Â Â if (sim) {
+ Â Â Â Â Â Â Â struct sim_data *sd = ofono_sim_get_data(sim);
+ Â Â Â Â Â Â Â return sd->app_id;
+ Â Â Â } else
+ Â Â Â Â Â Â Â return -1;
+}
+
+int get_app_type(GIsiModem *modem)
+{
+ Â Â Â struct ofono_sim *sim;
+
+ Â Â Â if (modem == NULL)
+ Â Â Â Â Â Â Â return -1;
+
+ Â Â Â sim = g_isi_modem_get_sim(modem);
+
+ Â Â Â if (sim) {
+ Â Â Â Â Â Â Â struct sim_data *sd = ofono_sim_get_data(sim);
+ Â Â Â Â Â Â Â return sd->app_type;
+ Â Â Â } else
+ Â Â Â Â Â Â Â return -1;
+}
+
+int get_client_id(GIsiModem *modem)
+{
+ Â Â Â struct ofono_sim *sim;
+
+ Â Â Â if (modem == NULL)
+ Â Â Â Â Â Â Â return -1;
+
+ Â Â Â sim = g_isi_modem_get_sim(modem);
+
+ Â Â Â if (sim) {
+ Â Â Â Â Â Â Â struct sim_data *sd = ofono_sim_get_data(sim);
+ Â Â Â Â Â Â Â return sd->client_id;
+ Â Â Â } else
+ Â Â Â Â Â Â Â return -1;
+}
What I meant was that this driver should keep track of all of the
instances of SIM drivers, e.g., using a modem->driver hash table. Then
the API would not require GIsiModem to store any pointers, instead,
you would use a pointer to the GIsiModem as key to the hash table.
In any case, I'd like this to be just have a single function call,
like a isi_uicc_properties() taking output params as arguments and
returning a gboolean.
That said, this would be a whole lot simpler to implement by having a
separate uiccutils.c that contains the necessary UICC_APPL_LIST and
UICC_APPL_HOST_ACTIVATE response decoders, and have both the SIM
driver and the SMS driver use that code. Because the SMS driver ends
up having a UICC client anyway, so all this intra-driver communication
is really there to save two response decoder functions being
copy-pasted, no? Not worth the trouble.
 /* Returns file info */
 static gboolean fake_file_info(gpointer user)
@@ -89,6 +540,286 @@ static gboolean fake_file_info(gpointer user)
    return FALSE;
 }
+static gboolean check_response_status_with_cause(const GIsiMessage *msg,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â uint8_t msgid,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â uint8_t service,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â int cause,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â int pos)
+{
+ Â Â Â uint8_t type;
+ Â Â Â uint8_t msg_cause;
+
+ Â Â Â if (g_isi_msg_error(msg) < 0) {
+ Â Â Â Â Â Â Â DBG("Error: %s", strerror(-g_isi_msg_error(msg)));
+ Â Â Â Â Â Â Â return FALSE;
+ Â Â Â }
+
+ Â Â Â if (g_isi_msg_id(msg) != msgid) {
+ Â Â Â Â Â Â Â DBG("Unexpected msg: %s",
+ Â Â Â Â Â Â Â Â Â Â Â sim_message_id_name(g_isi_msg_id(msg)));
+ Â Â Â Â Â Â Â return FALSE;
+ Â Â Â }
+
+ Â Â Â if ((!g_isi_msg_data_get_byte(msg, 1, &msg_cause) ||
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â msg_cause != cause)) {
+ Â Â Â Â Â Â Â return FALSE;
+ Â Â Â }
+
+ Â Â Â if (!g_isi_msg_data_get_byte(msg, 0, &type) || type != service) {
+ Â Â Â Â Â Â Â DBG("Unexpected service: 0x%02X", type);
+ Â Â Â Â Â Â Â return FALSE;
+ Â Â Â }
+ Â Â Â return TRUE;
+}
+
+static gboolean check_response_status(const GIsiMessage *msg, uint8_t msgid,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â uint8_t service)
+{
+ Â Â Â int cause, pos;
+
+ Â Â Â if (g_isi_msg_version_major(msg) == 6 &&
+ Â Â Â Â Â Â Â Â Â Â Â g_isi_msg_version_minor(msg) >= 0) {
+ Â Â Â Â Â Â Â cause = UICC_STATUS_OK;
+ Â Â Â Â Â Â Â pos = 0;
+ Â Â Â } else {
+ Â Â Â Â Â Â Â cause = SIM_SERV_OK;
+ Â Â Â Â Â Â Â pos = 1;
+ Â Â Â }
+
+ Â Â Â return check_response_status_with_cause(msg, msgid, service, cause,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â pos);
+}
+
+
+static void handle_app_uicc_usim(GIsiSubBlockIter *iter,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â struct sim_data *sd,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â uint16_t *length,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â uint16_t *record_length,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â uint8_t *records, uint8_t *structure)
+{
+ Â Â Â uint8_t fcp;
+ Â Â Â uint8_t fcp_len;
+ Â Â Â uint8_t read = 0;
+ Â Â Â uint8_t id;
+ Â Â Â uint8_t item_len;
+ Â Â Â uint16_t file_id;
+ Â Â Â uint8_t desc;
+ Â Â Â uint8_t coding;
+ Â Â Â uint8_t pin_do_len;
+ Â Â Â uint8_t pin_len;
+ Â Â Â uint8_t pin_tag;
+ Â Â Â uint8_t pin_id;
+ Â Â Â uint8_t pin_tag_pos;
+
+
+ Â Â Â if (!g_isi_sb_iter_get_byte(iter, &fcp, 8))
+ Â Â Â Â Â Â Â return;
+
+ Â Â Â if (fcp != FCP_TEMPLATE)
+ Â Â Â Â Â Â Â return;
+
+ Â Â Â if (!g_isi_sb_iter_get_byte(iter, &fcp_len, 9))
+ Â Â Â Â Â Â Â return;
+
+ Â Â Â while (read < fcp_len) {
+ Â Â Â Â Â Â Â if (!g_isi_sb_iter_get_byte(iter, &id, read + 10))
+ Â Â Â Â Â Â Â Â Â Â Â return;
+ Â Â Â Â Â Â Â if (!g_isi_sb_iter_get_byte(iter, &item_len, read + 11))
+ Â Â Â Â Â Â Â Â Â Â Â return;
+
+ Â Â Â Â Â Â Â switch (id) {
+ Â Â Â Â Â Â Â case FCP_FILE_SIZE:
+ Â Â Â Â Â Â Â Â Â Â Â if (item_len == 2) {
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â g_isi_sb_iter_get_word(iter, length,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â read + 10 + 2);
+ Â Â Â Â Â Â Â Â Â Â Â }
+ Â Â Â Â Â Â Â Â Â Â Â break;
+ Â Â Â Â Â Â Â case FCP_FILE_ID:
+ Â Â Â Â Â Â Â Â Â Â Â if (item_len == 2) {
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â g_isi_sb_iter_get_word(iter, &file_id,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â read + 10 + 2);
+ Â Â Â Â Â Â Â Â Â Â Â }
+ Â Â Â Â Â Â Â Â Â Â Â break;
+ Â Â Â Â Â Â Â case FCP_FILE_DESC:
+ Â Â Â Â Â Â Â Â Â Â Â if (item_len >= 2) {
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â g_isi_sb_iter_get_byte(iter, &desc,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â read + 10 + 2);
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â g_isi_sb_iter_get_byte(iter, &coding,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â read + 10 + 3);
+ Â Â Â Â Â Â Â Â Â Â Â }
+
+ Â Â Â Â Â Â Â Â Â Â Â if (item_len >= 4) {
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â g_isi_sb_iter_get_word(iter, record_length,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â read + 10 + 4);
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â g_isi_sb_iter_get_byte(iter, records,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â read + 10 + 6);
+ Â Â Â Â Â Â Â Â Â Â Â }
+ Â Â Â Â Â Â Â Â Â Â Â break;
+ Â Â Â Â Â Â Â case FCP_PIN_STATUS:
+ Â Â Â Â Â Â Â Â Â Â Â g_isi_sb_iter_get_byte(iter, &pin_do_len,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â read + 10 + 3);
+ Â Â Â Â Â Â Â Â Â Â Â pin_tag_pos = read + 10 + 4 + pin_do_len;
+ Â Â Â Â Â Â Â Â Â Â Â g_isi_sb_iter_get_byte(iter, &pin_tag, pin_tag_pos);
+
+ Â Â Â Â Â Â Â Â Â Â Â while (pin_tag == 0x83) {
+
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â g_isi_sb_iter_get_byte(iter, &pin_len,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â pin_tag_pos + 1);
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â g_isi_sb_iter_get_byte(iter, &pin_id,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â pin_tag_pos + 2);
+
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â pin_tag_pos += 2 + pin_len;
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â g_isi_sb_iter_get_byte(iter, &pin_tag,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â pin_tag_pos);
+
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â if ((0x01 <= pin_id) && (pin_id <= 0x08))
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â sd->pin1_id = pin_id;
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â else if ((0x81 <= pin_id) && (pin_id <=
0x88))
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â sd->pin2_id = pin_id;
+
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â read += item_len + 2;
+ Â Â Â Â Â Â Â Â Â Â Â }
+ Â Â Â Â Â Â Â Â Â Â Â break;
+ Â Â Â Â Â Â Â case FCP_FILE_SECURITY_ARR:
+ Â Â Â Â Â Â Â case FCP_FILE_SECURITY_COMPACT:
+ Â Â Â Â Â Â Â case FCP_FILE_SECURITY_EXPANDED:
+
+ Â Â Â Â Â Â Â /* Not implemented, using
+ Â Â Â Â Â Â Â Â * static access rules as these
+ Â Â Â Â Â Â Â Â * are used only for caching
+ Â Â Â Â Â Â Â Â * See ETSI TS 102 221, ch
+ Â Â Â Â Â Â Â Â * 11.1.1.4.7 and
+ Â Â Â Â Â Â Â Â * Annexes E,F and G
+ Â Â Â Â Â Â Â Â */
+ Â Â Â Â Â Â Â case FCP_FILE_LIFECYCLE:
+ Â Â Â Â Â Â Â default:
+ Â Â Â Â Â Â Â Â Â Â Â DBG("FCP id %02X not supported", id);
+ Â Â Â Â Â Â Â Â Â Â Â break;
+ Â Â Â Â Â Â Â }
+
+ Â Â Â Â Â Â Â /*Data length + id size + len size */
+ Â Â Â Â Â Â Â read += item_len + 2;
+ Â Â Â }
+ Â Â Â if ((desc & 7) == 1)
+ Â Â Â Â Â Â Â *structure = OFONO_SIM_FILE_STRUCTURE_TRANSPARENT;
+ Â Â Â else if ((desc & 7) == 2)
+ Â Â Â Â Â Â Â *structure = OFONO_SIM_FILE_STRUCTURE_FIXED;
+ Â Â Â else if ((desc & 7) == 6)
+ Â Â Â Â Â Â Â *structure = OFONO_SIM_FILE_STRUCTURE_CYCLIC;
+}
+
+static void isi_file_info_resp(const GIsiMessage *msg, void *data)
+{
+ Â Â Â struct isi_cb_data *cbd = data;
+ Â Â Â ofono_sim_file_info_cb_t cb = cbd->cb;
+ Â Â Â uint16_t length = 0;
+ Â Â Â uint16_t record_length = 0;
+ Â Â Â uint8_t structure = -1;
+ Â Â Â uint8_t records = 0;
+ Â Â Â uint16_t file_id = 0;
+ Â Â Â uint8_t access[3] = {0, 0, 0};
+ Â Â Â uint8_t item_len = 0;
+ Â Â Â gboolean everything_ok = FALSE;
+ Â Â Â /*Access is read from static file info*/
+ Â Â Â struct read_file_data *fdata = cbd->user;
+ Â Â Â struct file_info const *info;
+ Â Â Â GIsiSubBlockIter iter;
+ Â Â Â struct sim_data *sd = NULL;
+ Â Â Â uint8_t sbcount = 0;
+
+ Â Â Â if (fdata != NULL) {
+ Â Â Â Â Â Â Â sd = fdata->sim_data;
+ Â Â Â Â Â Â Â info = fdata->info;
+ Â Â Â Â Â Â Â g_free(cbd->user);
+ Â Â Â Â Â Â Â cbd->user = NULL;
+ Â Â Â }
+
+ Â Â Â if (sd == NULL)
+ Â Â Â Â Â Â Â goto error;
+
+ Â Â Â if (!check_response_status(msg, UICC_APPL_CMD_RESP,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â UICC_APPL_FILE_INFO))
+ Â Â Â Â Â Â Â goto error;
+
+
+ Â Â Â if (info != NULL) {
+ Â Â Â Â Â Â Â access[0] = info->access[0];
+ Â Â Â Â Â Â Â access[1] = info->access[1];
+ Â Â Â Â Â Â Â access[2] = info->access[2];
+ Â Â Â }
+
+ Â Â Â g_isi_msg_data_get_byte(msg, 5, &sbcount);
+ Â Â Â g_isi_sb_iter_init_full(&iter, msg, 6, TRUE, sbcount);
+
+ Â Â Â while (g_isi_sb_iter_is_valid(&iter)) {
+ Â Â Â Â Â Â Â DBG("Sub-block %s",
+ Â Â Â Â Â Â Â Â Â Â Â uicc_subblock_name(g_isi_sb_iter_get_id(&iter)));
+
+ Â Â Â Â Â Â Â switch (g_isi_sb_iter_get_id(&iter)) {
+ Â Â Â Â Â Â Â case UICC_SB_FCI:
+ Â Â Â Â Â Â Â Â Â Â Â DBG("UICC_SB_FCI");
+ Â Â Â Â Â Â Â Â Â Â Â everything_ok = TRUE;
+
+ Â Â Â Â Â Â Â Â Â Â Â switch (sd->app_type) {
+ Â Â Â Â Â Â Â Â Â Â Â case UICC_APPL_TYPE_UICC_USIM:
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â DBG("UICC_APPL_TYPE_UICC_USIM");
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â handle_app_uicc_usim(&iter, sd,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â &length, &record_length,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â &records, &structure);
+
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â break;
+ Â Â Â Â Â Â Â Â Â Â Â case UICC_APPL_TYPE_ICC_SIM:
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â DBG("UICC_APPL_TYPE_ICC_SIM");
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â g_isi_sb_iter_get_word(&iter, &length, 10);
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â g_isi_sb_iter_get_word(&iter, &file_id, 12);
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â (void)g_isi_sb_iter_get_byte(&iter,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â &access[0],
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â 16);
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â (void)g_isi_sb_iter_get_byte(&iter,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â &access[0],
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â 17);
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â (void)g_isi_sb_iter_get_byte(&iter,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â &access[0],
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â 18);
This is reading three different bytes into access[0].
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â
(void)g_isi_sb_iter_get_byte(&iter,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â &item_len, 20);
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â (void)g_isi_sb_iter_get_byte(&iter,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â &structure,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â 21);
+
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â if (item_len == 2)
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â (void)g_isi_sb_iter_get_byte(&iter,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â (uint8_t *)&record_length,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â 22);
+
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â break;
+ Â Â Â Â Â Â Â Â Â Â Â default:
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â DBG("UICC application type %d not supported",
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â sd->app_type);
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â break;
+ Â Â Â Â Â Â Â Â Â Â Â }
+
+ Â Â Â Â Â Â Â Â Â Â Â break;
+ Â Â Â Â Â Â Â default:
+ Â Â Â Â Â Â Â Â Â Â Â DBG("Skipping SB");
+ Â Â Â Â Â Â Â Â Â Â Â break;
+ Â Â Â Â Â Â Â }
+
+ Â Â Â Â Â Â Â if (g_isi_sb_iter_next(&iter) == FALSE)
+ Â Â Â Â Â Â Â Â Â Â Â goto error;
+ Â Â Â }
+
+ Â Â Â if (everything_ok) {
+ Â Â Â Â Â Â Â CALLBACK_WITH_SUCCESS(cb, length, structure, record_length,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â access, '\n', cbd->data);
+ Â Â Â Â Â Â Â return;
+ Â Â Â }
+
+error:
+ Â Â Â DBG("Error reading file info");
+ Â Â Â CALLBACK_WITH_FAILURE(cb, 0, 0, 0, access, '\n', cbd->data);
+}
+
 static void isi_read_file_info(struct ofono_sim *sim, int fileid,
                ofono_sim_file_info_cb_t cb, void *data)
 {
@@ -98,276 +829,1700 @@ static void isi_read_file_info(struct ofono_sim *sim, int
fileid,
        { SIM_EF_ICCID_FILEID, 10, 0, 0, { 0x0f, 0xff, 0xff }, 1 },
    };
    int N = sizeof(info) / sizeof(info[0]);
+ Â Â Â struct sim_data *sd = ofono_sim_get_data(sim);
    struct isi_cb_data *cbd;
- Â Â Â for (i = 0; i < N; i++) {
- Â Â Â Â Â Â Â if (fileid == info[i].fileid) {
- Â Â Â Â Â Â Â Â Â Â Â cbd = isi_cb_data_new((void *) &info[i], cb, data);
- Â Â Â Â Â Â Â Â Â Â Â g_idle_add(fake_file_info, cbd);
+ Â Â Â if ((sd != NULL) && g_isi_client_resource(sd->client) == PN_UICC) {
+ Â Â Â Â Â Â Â /* Prepare for static file info used for access rights */
+ Â Â Â Â Â Â Â int i;
+ Â Â Â Â Â Â Â int mf_path = 0;
+ Â Â Â Â Â Â Â int df1_path = 0;
+ Â Â Â Â Â Â Â int df2_path = 0;
+ Â Â Â Â Â Â Â unsigned char df_len = 0;
+ Â Â Â Â Â Â Â struct read_file_data *fdata = g_try_malloc0(sizeof(
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â struct read_file_data));
+
+ Â Â Â Â Â Â Â N = sizeof(static_file_info) / sizeof(static_file_info[0]);
+ Â Â Â Â Â Â Â cbd = isi_cb_data_new(NULL, cb, data);
+ Â Â Â Â Â Â Â DBG("File info for ID=%04X app id %d", fileid, sd->app_id);
+
+ Â Â Â Â Â Â Â fdata->sim_data = sd;
+
+ Â Â Â Â Â Â Â for (i = 0; i < N; i++) {
+ Â Â Â Â Â Â Â Â Â Â Â if (fileid == static_file_info[i].fileid &&
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â cbd != NULL) {
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â fdata->info = (struct file_info *)
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â &static_file_info[i];
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â continue;
+ Â Â Â Â Â Â Â Â Â Â Â }
+ Â Â Â Â Â Â Â }
+ Â Â Â Â Â Â Â cbd->user = (void *) fdata;
Why go through all this trouble of searching for static file access
data before the response arrives? Why not simply do the lookup for the
access bytes in the response callback, and save all this trouble of
mallocing a second level of user data? The fileid is available in the
response messages, no?
+ Â Â Â Â Â Â Â if (!get_fileid_path(sim, &mf_path,
&df1_path,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â &df2_path, &df_len, fileid)) {
+ Â Â Â Â Â Â Â Â Â Â Â g_free(cbd);
+ Â Â Â Â Â Â Â Â Â Â Â goto error;
+ Â Â Â Â Â Â Â }
+ Â Â Â Â Â Â Â if (cbd) {
+ Â Â Â Â Â Â Â Â Â Â Â const unsigned char msg[] = {
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â UICC_APPL_CMD_REQ,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â UICC_APPL_FILE_INFO,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â sd->app_id,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â UICC_SESSION_ID_NOT_USED, /*Session ID*/
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â 0, /*Filler*/
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â 0, /*Filler*/
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â 1, /*number of subblocks*/
+ Â Â Â Â Â Â Â Â Â Â Â /* Subblock 1*/
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â UICC_SB_APPL_PATH >> 8,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â UICC_SB_APPL_PATH & 0xff,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â 0,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â 16, /*Sub block length*/
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â fileid >> 8, /* UICC elementary file ID*/
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â fileid & 0xFF,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â /* Elementary file short id*/
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â fileid_to_short_fileid(fileid),
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â 0, /*filler*/
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â df_len, /*DF Path length*/
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â 0, /*Filler*/
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â mf_path >> 8,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â mf_path & 0xff,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â df1_path >> 8, /*DF Path*/
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â df1_path & 0xFF,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â df2_path >> 8, /*DF Path*/
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â df2_path & 0xFF,
+ Â Â Â Â Â Â Â Â Â Â Â };
+ Â Â Â Â Â Â Â Â Â Â Â g_isi_client_send(sd->client, msg, sizeof(msg),
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â isi_file_info_resp, cbd, g_free);
            return;
        }
- Â Â Â }
+ Â Â Â } else {
+ Â Â Â Â Â Â Â for (i = 0; i < N; i++) {
+ Â Â Â Â Â Â Â Â Â Â Â if (fileid == info[i].fileid) {
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â cbd = isi_cb_data_new((void *) &info[i], cb,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â data);
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â g_idle_add(fake_file_info, cbd);
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â return;
+ Â Â Â Â Â Â Â Â Â Â Â }
+ Â Â Â Â Â Â Â }
I think this is a fine example why the UICC code doesn't belong in
this file. The original SIM driver is mostly a reverse abstraction of
a high-level API, whereas PN_UICC has more appropriate support for EF
access. These blocks of code have absolutely nothing in common, no
message decoding to share, etc.
They belong in separate files for sure.
+ Â Â Â }
+error:
    DBG("Fileid %04X not implemented", fileid);
    CALLBACK_WITH_FAILURE(cb, -1, -1, -1, NULL, 0, data);
 }
-static gboolean check_response_status(const GIsiMessage *msg, uint8_t msgid,
- Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â uint8_t service)
+static void spn_resp_cb(const GIsiMessage *msg, void *data)
 {
- Â Â Â uint8_t type;
- Â Â Â uint8_t cause;
+ Â Â Â struct isi_cb_data *cbd = data;
+ Â Â Â ofono_sim_read_cb_t cb = cbd->cb;
- Â Â Â if (g_isi_msg_error(msg) < 0) {
- Â Â Â Â Â Â Â DBG("Error: %s", strerror(-g_isi_msg_error(msg)));
- Â Â Â Â Â Â Â return FALSE;
- Â Â Â }
+ Â Â Â const struct sim_spn *resp = NULL;
+ Â Â Â size_t len = sizeof(struct sim_spn);
- Â Â Â if (g_isi_msg_id(msg) != msgid) {
- Â Â Â Â Â Â Â DBG("Unexpected msg: %s",
- Â Â Â Â Â Â Â Â Â Â Â sim_message_id_name(g_isi_msg_id(msg)));
- Â Â Â Â Â Â Â return FALSE;
- Â Â Â }
+ Â Â Â uint8_t spn[SIM_MAX_SPN_LENGTH + 1];
+ Â Â Â int i;
- Â Â Â if (!g_isi_msg_data_get_byte(msg, 1, &cause) || cause != SIM_SERV_OK) {
- Â Â Â Â Â Â Â DBG("Request failed: %s", sim_isi_cause_name(cause));
- Â Â Â Â Â Â Â return FALSE;
- Â Â Â }
+ Â Â Â if (!check_response_status(msg, SIM_SERV_PROV_NAME_RESP,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â SIM_ST_READ_SERV_PROV_NAME))
+ Â Â Â Â Â Â Â goto error;
- Â Â Â if (!g_isi_msg_data_get_byte(msg, 0, &type) || type != service) {
- Â Â Â Â Â Â Â DBG("Unexpected service: 0x%02X", type);
- Â Â Â Â Â Â Â return FALSE;
+ Â Â Â if (!g_isi_msg_data_get_struct(msg, 2, (const void **) &resp, len))
+ Â Â Â Â Â Â Â goto error;
+
+ Â Â Â /* Set display condition bits */
+ Â Â Â spn[0] = (resp->disp_home & 0x01) | ((resp->disp_roam & 0x01)
<< 1);
+
+ Â Â Â /* Convert from a NULL-terminated UCS-2 string to ASCII */
+ Â Â Â for (i = 0; i < SIM_MAX_SPN_LENGTH; i++) {
+ Â Â Â Â Â Â Â uint16_t c = resp->name[i] >> 8 | resp->name[i] << 8;
+
+ Â Â Â Â Â Â Â if (c == 0)
+ Â Â Â Â Â Â Â Â Â Â Â c = 0xFF;
+ Â Â Â Â Â Â Â else if (!g_ascii_isprint(c))
+ Â Â Â Â Â Â Â Â Â Â Â c = '?';
+
+ Â Â Â Â Â Â Â spn[i + 1] = c;
    }
- Â Â Â return TRUE;
+
+ Â Â Â CALLBACK_WITH_SUCCESS(cb, spn, sizeof(spn), cbd->data);
+ Â Â Â return;
+
+error:
+ Â Â Â CALLBACK_WITH_FAILURE(cb, NULL, 0, cbd->data);
 }
-static void spn_resp_cb(const GIsiMessage *msg, void *data)
+static gboolean isi_read_spn(struct ofono_sim *sim, struct isi_cb_data *cbd)
+{
+ Â Â Â struct sim_data *sd = ofono_sim_get_data(sim);
+
+ Â Â Â const uint8_t msg[] = {
+ Â Â Â Â Â Â Â SIM_SERV_PROV_NAME_REQ,
+ Â Â Â Â Â Â Â SIM_ST_READ_SERV_PROV_NAME,
+ Â Â Â Â Â Â Â 0
+ Â Â Â };
+
+ Â Â Â if (sd == NULL)
+ Â Â Â Â Â Â Â return FALSE;
+
+ Â Â Â return g_isi_client_send(sd->client, msg, sizeof(msg),
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â spn_resp_cb, cbd, g_free);
+}
+
+static void read_iccid_resp_cb(const GIsiMessage *msg, void *data)
+{
+ Â Â Â struct isi_cb_data *cbd = data;
+ Â Â Â ofono_sim_read_cb_t cb = cbd->cb;
+ Â Â Â struct sim_iccid *icc;
+ Â Â Â size_t len = sizeof(struct sim_iccid);
+
+ Â Â Â if (!check_response_status(msg, SIM_READ_FIELD_RESP, ICC))
+ Â Â Â Â Â Â Â goto error;
+
+ Â Â Â if (!g_isi_msg_data_get_struct(msg, 2, (const void **) &icc, len))
+ Â Â Â Â Â Â Â goto error;
+
+ Â Â Â CALLBACK_WITH_SUCCESS(cb, icc->id, 10, cbd->data);
+ Â Â Â return;
+
+error:
+ Â Â Â CALLBACK_WITH_FAILURE(cb, NULL, 0, cbd->data);
+}
+
+static gboolean isi_read_iccid(struct ofono_sim *sim, struct isi_cb_data *cbd)
+{
+ Â Â Â struct sim_data *sd = ofono_sim_get_data(sim);
+
+ Â Â Â const uint8_t req[] = {
+ Â Â Â Â Â Â Â SIM_READ_FIELD_REQ,
+ Â Â Â Â Â Â Â ICC,
+ Â Â Â };
+
+ Â Â Â if (sd == NULL)
+ Â Â Â Â Â Â Â return FALSE;
+
+ Â Â Â return g_isi_client_send(sd->client, req, sizeof(req),
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â read_iccid_resp_cb, cbd, g_free);
+}
+
+static void isi_read_file_transparent_resp(const GIsiMessage *msg, void *data)
+{
+ Â Â Â struct isi_cb_data *cbd = data;
+ Â Â Â ofono_sim_read_cb_t cb = cbd->cb;
+ Â Â Â uint32_t filelen = 0;
+ Â Â Â unsigned char filedata[256] = { 0xff };
+ Â Â Â gboolean everything_ok = FALSE;
+ Â Â Â GIsiSubBlockIter iter;
+ Â Â Â uint8_t sbcount = 0;
+
+ Â Â Â if (!check_response_status(msg, UICC_APPL_CMD_RESP,
+ Â Â Â Â Â Â Â Â Â Â Â UICC_APPL_READ_TRANSPARENT))
+ Â Â Â Â Â Â Â goto error;
+
+ Â Â Â g_isi_msg_data_get_byte(msg, 5, &sbcount);
+ Â Â Â g_isi_sb_iter_init_full(&iter, msg, 6, TRUE, sbcount);
+
+ Â Â Â while (g_isi_sb_iter_is_valid(&iter)) {
+ Â Â Â Â Â Â Â DBG("Sub-block %s",
+ Â Â Â Â Â Â Â Â Â Â Â uicc_subblock_name(g_isi_sb_iter_get_id(&iter)));
+
+ Â Â Â Â Â Â Â switch (g_isi_sb_iter_get_id(&iter)) {
+ Â Â Â Â Â Â Â case UICC_SB_FILE_DATA:
+ Â Â Â Â Â Â Â Â Â Â Â g_isi_sb_iter_get_dword(&iter, &filelen, 4);
+ Â Â Â Â Â Â Â Â Â Â Â memmove(&filedata, iter.start + 8, filelen);
+ Â Â Â Â Â Â Â Â Â Â Â everything_ok = TRUE;
+ Â Â Â Â Â Â Â Â Â Â Â break;
+ Â Â Â Â Â Â Â default:
+ Â Â Â Â Â Â Â Â Â Â Â break;
+ Â Â Â Â Â Â Â }
+
+ Â Â Â Â Â Â Â g_isi_sb_iter_next(&iter);
+ Â Â Â }
+
+ Â Â Â if (everything_ok) {
+ Â Â Â Â Â Â Â DBG("Transparent EF read: 1st byte %02x, len %d",
+ Â Â Â Â Â Â Â Â Â Â Â filedata[0], filelen);
+ Â Â Â Â Â Â Â CALLBACK_WITH_SUCCESS(cb, filedata, filelen, cbd->data);
+ Â Â Â Â Â Â Â return;
+ Â Â Â }
+
+error:
+ Â Â Â DBG("Error reading transparent EF");
+ Â Â Â CALLBACK_WITH_FAILURE(cb, NULL, 0, cbd->data);
+}
+
+static void isi_read_file_transparent(struct ofono_sim *sim, int fileid,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â int start, int length,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â ofono_sim_read_cb_t cb, void *data)
+{
+ Â Â Â struct sim_data *sd = ofono_sim_get_data(sim);
+ Â Â Â struct isi_cb_data *cbd;
+ Â Â Â gboolean done;
+
+ Â Â Â cbd = isi_cb_data_new(sim, cb, data);
+
+ Â Â Â if (cbd == NULL || sd == NULL)
+ Â Â Â Â Â Â Â goto error;
+
+ Â Â Â if (g_isi_client_resource(sd->client) == PN_UICC) {
+ Â Â Â Â Â Â Â int mf_path = 0;
+ Â Â Â Â Â Â Â int df1_path = 0;
+ Â Â Â Â Â Â Â int df2_path = 0;
+ Â Â Â Â Â Â Â unsigned char df_len = 0;
+
+ Â Â Â Â Â Â Â DBG("File ID=%04X, client %d, AID %d",
+ Â Â Â Â Â Â Â Â Â Â Â fileid, sd->client_id, sd->app_id);
+
+ Â Â Â Â Â Â Â if (get_fileid_path(sim, &mf_path, &df1_path,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â &df2_path, &df_len, fileid)) {
+ Â Â Â Â Â Â Â Â Â Â Â const unsigned char msg[] = {
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â UICC_APPL_CMD_REQ,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â UICC_APPL_READ_TRANSPARENT,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â sd->app_id,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â UICC_SESSION_ID_NOT_USED, /*Session ID*/
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â 0, /*Filler*/
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â 0, /*Filler*/
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â 3, /*number of subblocks*/
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â /* Subblock 1 */
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â UICC_SB_CLIENT >> 8,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â UICC_SB_CLIENT & 0xff,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â 0,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â 8, /*Sub block length*/
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â 0, 0, 0, /* Filler */
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â sd->client_id,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â /* Subblock 2*/
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â UICC_SB_TRANSPARENT >> 8,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â UICC_SB_TRANSPARENT & 0xff,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â 0, /*Sub block length*/
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â 8, /*Sub block length*/
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â 0, /*File offset (0=beginning)*/
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â 0, /*File offset (0=beginning)*/
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â 0, /*Data amount (0=all)*/
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â 0, /*Data amount (0=all)*/
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â /* Subblock 3 */
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â UICC_SB_APPL_PATH >> 8,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â UICC_SB_APPL_PATH & 0xff,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â 0,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â 16, /* Sub block length*/
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â fileid >> 8, /* UICC elementary file ID*/
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â fileid & 0xFF,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â /*Elementary file short id*/
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â fileid_to_short_fileid(fileid),
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â 0, /*filler*/
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â df_len, /*DF Path length*/
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â 0, /*Filler*/
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â mf_path >> 8,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â mf_path & 0xff,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â df1_path >> 8, /*DF Path*/
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â df1_path & 0xFF,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â df2_path >> 8, /*DF Path*/
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â df2_path & 0xFF
+ Â Â Â Â Â Â Â Â Â Â Â };
+ Â Â Â Â Â Â Â Â Â Â Â g_isi_client_send_with_timeout(
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â sd->client, msg, sizeof(msg), SIM_TIMEOUT,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â isi_read_file_transparent_resp, cbd, g_free);
+ Â Â Â Â Â Â Â Â Â Â Â return;
+ Â Â Â Â Â Â Â }
+ Â Â Â Â Â Â Â goto error;
+
+ Â Â Â } else {
+ Â Â Â Â Â Â Â switch (fileid) {
+ Â Â Â Â Â Â Â case SIM_EFSPN_FILEID:
+ Â Â Â Â Â Â Â Â Â Â Â done = isi_read_spn(sim, cbd);
+ Â Â Â Â Â Â Â Â Â Â Â break;
+
+ Â Â Â Â Â Â Â case SIM_EF_ICCID_FILEID:
+ Â Â Â Â Â Â Â Â Â Â Â done = isi_read_iccid(sim, cbd);
+ Â Â Â Â Â Â Â Â Â Â Â break;
+
+ Â Â Â Â Â Â Â default:
+ Â Â Â Â Â Â Â Â Â Â Â done = FALSE;
+ Â Â Â Â Â Â Â }
+
+ Â Â Â Â Â Â Â if (done)
+ Â Â Â Â Â Â Â Â Â Â Â return;
+ Â Â Â }
+
+ Â Â Â DBG("Fileid %04X not implemented", fileid);
+
+error:
+ Â Â Â CALLBACK_WITH_FAILURE(cb, NULL, 0, data);
+ Â Â Â g_free(cbd);
+}
+
+static void isi_read_file_linear_fixed_resp(const GIsiMessage *msg, void *data)
+{
+ Â Â Â struct isi_cb_data *cbd = data;
+ Â Â Â ofono_sim_read_cb_t cb = cbd->cb;
+ Â Â Â uint32_t filelen = 0;
+ Â Â Â unsigned char filedata[256] = { 0xff };
+ Â Â Â gboolean everything_ok = FALSE;
+ Â Â Â GIsiSubBlockIter iter;
+ Â Â Â uint8_t sbcount = 0;
+
+ Â Â Â if (!check_response_status(msg, UICC_APPL_CMD_RESP,
+ Â Â Â Â Â Â Â Â Â Â Â UICC_APPL_READ_LINEAR_FIXED))
+ Â Â Â Â Â Â Â goto error;
+
+ Â Â Â everything_ok = FALSE;
+ Â Â Â g_isi_msg_data_get_byte(msg, 5, &sbcount);
+ Â Â Â g_isi_sb_iter_init_full(&iter, msg, 6, TRUE, sbcount);
+
+ Â Â Â while (g_isi_sb_iter_is_valid(&iter)) {
+ Â Â Â Â Â Â Â DBG("Sub-block %s",
+ Â Â Â Â Â Â Â Â Â Â Â uicc_subblock_name(g_isi_sb_iter_get_id(&iter)));
+
+ Â Â Â Â Â Â Â switch (g_isi_sb_iter_get_id(&iter)) {
+ Â Â Â Â Â Â Â case UICC_SB_FILE_DATA:
+ Â Â Â Â Â Â Â Â Â Â Â g_isi_sb_iter_get_dword(&iter, &filelen, 4);
+ Â Â Â Â Â Â Â Â Â Â Â memmove(&filedata, iter.start + 8, filelen);
You're memmove():ing a static buffer of up to 2M bytes (filelen is a
32bit integer) into a static buffer 256 bytes long. That's not right.
There is a g_isi_sb_iter_get_struct() that we generally use in
situations like this, which among other things avoids useless copying
of bytes around in the stack.
+ Â Â Â Â Â Â Â Â Â Â Â everything_ok = TRUE;
+ Â Â Â Â Â Â Â Â Â Â Â break;
+ Â Â Â Â Â Â Â default:
+ Â Â Â Â Â Â Â Â Â Â Â break;
+ Â Â Â Â Â Â Â }
+
+ Â Â Â Â Â Â Â g_isi_sb_iter_next(&iter);
+ Â Â Â }
+
+ Â Â Â if (everything_ok) {
+ Â Â Â Â Â Â Â DBG("Linear fixed EF read: 1st byte %02x, len %d",
+ Â Â Â Â Â Â Â Â Â Â Â filedata[0], filelen);
+ Â Â Â Â Â Â Â CALLBACK_WITH_SUCCESS(cb, filedata, filelen, cbd->data);
+ Â Â Â Â Â Â Â return;
+ Â Â Â }
+
+error:
+ Â Â Â DBG("Error reading linear fixed EF");
+ Â Â Â CALLBACK_WITH_FAILURE(cb, NULL, 0, cbd->data);
+}
+
+static void isi_read_file_linear(struct ofono_sim *sim,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â int fileid,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â int record,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â int rec_length,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â ofono_sim_read_cb_t cb,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â void *data)
+{
+ Â Â Â struct sim_data *sd = ofono_sim_get_data(sim);
+ Â Â Â struct isi_cb_data *cbd = isi_cb_data_new(sim, cb, data);
+ Â Â Â int mf_path = 0;
+ Â Â Â int df1_path = 0;
+ Â Â Â int df2_path = 0;
+ Â Â Â unsigned char df_len = 0;
+ Â Â Â DBG("File ID=%04X, record %d, client %d AID %d",
+ Â Â Â Â Â Â Â fileid, record, sd->client_id, sd->app_id);
+ Â Â Â if (!get_fileid_path(sim, &mf_path,
+ Â Â Â Â Â Â Â Â Â Â Â &df1_path, &df2_path, &df_len, fileid))
+ Â Â Â Â Â Â Â goto error;
+ Â Â Â if ((cbd != NULL) && (sd != NULL)) {
+
+ Â Â Â Â Â Â Â const unsigned char msg[] = {
+ Â Â Â Â Â Â Â Â Â Â Â UICC_APPL_CMD_REQ,
+ Â Â Â Â Â Â Â Â Â Â Â UICC_APPL_READ_LINEAR_FIXED,
+ Â Â Â Â Â Â Â Â Â Â Â sd->app_id,
+ Â Â Â Â Â Â Â Â Â Â Â UICC_SESSION_ID_NOT_USED, /*Session ID*/
+ Â Â Â Â Â Â Â Â Â Â Â 0, /*Filler*/
+ Â Â Â Â Â Â Â Â Â Â Â 0, /*Filler*/
+ Â Â Â Â Â Â Â Â Â Â Â 3, /*number of subblocks*/
+ Â Â Â Â Â Â Â /* Subblock 1*/
+ Â Â Â Â Â Â Â Â Â Â Â UICC_SB_CLIENT >> 8,
+ Â Â Â Â Â Â Â Â Â Â Â UICC_SB_CLIENT & 0xff,
+ Â Â Â Â Â Â Â Â Â Â Â 0,
+ Â Â Â Â Â Â Â Â Â Â Â 8, /*Sub block length */
+ Â Â Â Â Â Â Â Â Â Â Â 0, 0, 0, /* Filler */
+ Â Â Â Â Â Â Â Â Â Â Â sd->client_id,
+ Â Â Â Â Â Â Â /* Subblock 2 */
+ Â Â Â Â Â Â Â Â Â Â Â UICC_SB_LINEAR_FIXED >> 8,
+ Â Â Â Â Â Â Â Â Â Â Â UICC_SB_LINEAR_FIXED & 0xff,
+ Â Â Â Â Â Â Â Â Â Â Â 0, /*Sub block length*/
+ Â Â Â Â Â Â Â Â Â Â Â 8, /*Sub block length*/
+ Â Â Â Â Â Â Â Â Â Â Â record, /*Record*/
+ Â Â Â Â Â Â Â Â Â Â Â 0, /*Record offset (0=beginning)*/
+ Â Â Â Â Â Â Â Â Â Â Â rec_length & 0xff, /*Data amount (0=all)*/
+ Â Â Â Â Â Â Â Â Â Â Â 0, /*Filler*/
+ Â Â Â Â Â Â Â /* Subblock 3*/
+ Â Â Â Â Â Â Â Â Â Â Â UICC_SB_APPL_PATH >> 8,
+ Â Â Â Â Â Â Â Â Â Â Â UICC_SB_APPL_PATH & 0xff,
+ Â Â Â Â Â Â Â Â Â Â Â 0,
+ Â Â Â Â Â Â Â Â Â Â Â 16, /*Sub block length*/
+ Â Â Â Â Â Â Â Â Â Â Â fileid >> 8, /* UICC elementary file ID*/
+ Â Â Â Â Â Â Â Â Â Â Â fileid & 0xFF,
+ Â Â Â Â Â Â Â Â Â Â Â /* Elementary file short file id*/
+ Â Â Â Â Â Â Â Â Â Â Â fileid_to_short_fileid(fileid),
+ Â Â Â Â Â Â Â Â Â Â Â 0, /*filler*/
+ Â Â Â Â Â Â Â Â Â Â Â df_len, /*DF Path length*/
+ Â Â Â Â Â Â Â Â Â Â Â 0, /*Filler*/
+ Â Â Â Â Â Â Â Â Â Â Â mf_path >> 8,
+ Â Â Â Â Â Â Â Â Â Â Â mf_path & 0xff,
+ Â Â Â Â Â Â Â Â Â Â Â df1_path >> 8, /*DF Path*/
+ Â Â Â Â Â Â Â Â Â Â Â df1_path & 0xFF,
+ Â Â Â Â Â Â Â Â Â Â Â df2_path >> 8, /*DF Path*/
+ Â Â Â Â Â Â Â Â Â Â Â df2_path & 0xFF
+ Â Â Â Â Â Â Â };
+ Â Â Â Â Â Â Â g_isi_client_send_with_timeout(
+ Â Â Â Â Â Â Â Â Â Â Â sd->client, msg, sizeof(msg), SIM_TIMEOUT,
+ Â Â Â Â Â Â Â Â Â Â Â isi_read_file_linear_fixed_resp, cbd, g_free);
+ Â Â Â Â Â Â Â return;
+ Â Â Â }
+
+error:
+ Â Â Â DBG("Not implemented (fileid = %04x)", fileid);
+ Â Â Â CALLBACK_WITH_FAILURE(cb, NULL, 0, data);
+ Â Â Â g_free(cbd);
+}
+
+static void isi_read_file_cyclic(struct ofono_sim *sim, int fileid,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â int record, int length,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â ofono_sim_read_cb_t cb, void *data)
+{
+ Â Â Â DBG("Fileid %04X not implemented", fileid);
+ Â Â Â CALLBACK_WITH_FAILURE(cb, NULL, 0, data);
+}
+
+static void isi_write_file_transparent(struct ofono_sim *sim, int fileid,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â int start, int length,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â const unsigned char *value,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â ofono_sim_write_cb_t cb, void *data)
+{
+ Â Â Â DBG("Fileid %04X not implemented", fileid);
+ Â Â Â CALLBACK_WITH_FAILURE(cb, data);
+}
+
+static void write_file_linear_cb(const GIsiMessage *msg, void *data)
+{
+ Â Â Â struct isi_cb_data *cbd = data;
+ Â Â Â ofono_sim_write_cb_t cb = cbd->cb;
+ Â Â Â DBG("");
+
+ Â Â Â if (check_response_status(msg, UICC_APPL_CMD_RESP,
+ Â Â Â Â Â Â Â Â Â Â Â UICC_APPL_UPDATE_LINEAR_FIXED))
+ Â Â Â Â Â Â Â CALLBACK_WITH_SUCCESS(cb, cbd->data);
+
+}
+
+static void isi_write_file_linear(struct ofono_sim *sim, int fileid,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â int record, int length,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â const unsigned char *value,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â ofono_sim_write_cb_t cb, void *data)
+{
+ Â Â Â struct sim_data *sd = ofono_sim_get_data(sim);
+ Â Â Â struct isi_cb_data *cbd = isi_cb_data_new(sim, cb, data);
+
+ Â Â Â if (g_isi_client_resource(sd->client) == PN_UICC) {
+ Â Â Â Â Â Â Â int mf_path = 0;
+ Â Â Â Â Â Â Â int df1_path = 0;
+ Â Â Â Â Â Â Â int df2_path = 0;
+ Â Â Â Â Â Â Â unsigned char df_len = 0;
+ Â Â Â Â Â Â Â size_t i = 0;
+ Â Â Â Â Â Â Â size_t sb_file_data_legth = (2 + 2 + 4 + length + 3) & ~3;
+ Â Â Â Â Â Â Â size_t fill_count = sb_file_data_legth - (2 + 2 + 4 + length);
+ Â Â Â Â Â Â Â uint8_t *fill_data = g_try_malloc0(fill_count);
+
+ Â Â Â Â Â Â Â DBG("");
+
+ Â Â Â Â Â Â Â if (!fill_data && fill_count > 0) {
+ Â Â Â Â Â Â Â Â Â Â Â g_free(fill_data);
+ Â Â Â Â Â Â Â Â Â Â Â goto error;
+ Â Â Â Â Â Â Â }
+ Â Â Â Â Â Â Â for (i = 0; i < fill_count; i++)
+ Â Â Â Â Â Â Â Â Â Â Â fill_data[i] = 0x00;
+
+ Â Â Â Â Â Â Â if (!sd->app_id || !sd->client_id || !sd || !sd->client ||
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â !cbd) {
+ Â Â Â Â Â Â Â Â Â Â Â DBG("Parameter error");
+ Â Â Â Â Â Â Â Â Â Â Â g_free(fill_data);
+ Â Â Â Â Â Â Â Â Â Â Â goto error;
+ Â Â Â Â Â Â Â }
+
+ Â Â Â Â Â Â Â if (get_fileid_path(sim, &mf_path, &df1_path,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â &df2_path, &df_len, fileid)) {
+ Â Â Â Â Â Â Â Â Â Â Â uint8_t msg[] = {
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â UICC_APPL_CMD_REQ,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â UICC_APPL_UPDATE_LINEAR_FIXED,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â sd->app_id,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â UICC_SESSION_ID_NOT_USED,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â 0x00, 0x00, /* fillers */
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â 0x04, /* nro of sub blocks */
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â /* 1st subblock */
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â UICC_SB_CLIENT >> 8,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â UICC_SB_CLIENT & 0xFF,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â 0x00, 0x08, /* subblock length */
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â 0x00, 0x00, 0x00, /* fillers */
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â sd->client_id,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â /* 2nd subblock */
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â UICC_SB_LINEAR_FIXED >> 8,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â UICC_SB_LINEAR_FIXED & 0xFF,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â 0x00, 0x08, /* subblock length */
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â record, /* the record in the file*/
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â 0x00, /* record offset (0 == beginning) */
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â 0x00, /* data amount, used only for reading */
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â 0x00, /* filler */
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â /* 3th subblock */
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â UICC_SB_APPL_PATH >> 8,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â UICC_SB_APPL_PATH & 0xFF,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â 0x00, 0x10, /* subblock length */
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â fileid >> 8, /* elementary file id */
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â fileid & 0xFF,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â fileid_to_short_fileid(fileid),
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â 0x00, /* filler */
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â df_len, /* path length */
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â 0x00, /* filler */
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â mf_path >> 8, /* DF Path MF */
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â mf_path & 0xFF,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â df1_path >> 8, /* DF Path */
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â df1_path & 0xFF,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â df2_path >> 8, /* DF Path */
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â df2_path & 0xFF,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â /* 4nd subblock */
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â UICC_SB_FILE_DATA >> 8,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â UICC_SB_FILE_DATA & 0xFF,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â sb_file_data_legth >> 8, /* subblock length */
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â sb_file_data_legth & 0xFF,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â length >> 24, /* data length */
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â length >> 16, /* need to be shifted */
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â length >> 8,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â length & 0xFF,
+ Â Â Â Â Â Â Â Â Â Â Â };
+
+ Â Â Â Â Â Â Â Â Â Â Â struct iovec iov[3] = {
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â { msg, sizeof(msg) },
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â { (uint8_t *)value, length },
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â { fill_data, fill_count },
+ Â Â Â Â Â Â Â Â Â Â Â };
+
+ Â Â Â Â Â Â Â Â Â Â Â if (!g_isi_client_vsend_with_timeout(sd->client, iov,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â 3, SIM_TIMEOUT, write_file_linear_cb,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â cbd, g_free)) {
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â g_free(fill_data);
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â goto error;
+ Â Â Â Â Â Â Â Â Â Â Â }
+
+ Â Â Â Â Â Â Â Â Â Â Â g_free(fill_data);
+ Â Â Â Â Â Â Â Â Â Â Â return;
+ Â Â Â Â Â Â Â }
+ Â Â Â }
+ Â Â Â DBG("Fileid %04X not implemented", fileid);
+error:
+ Â Â Â CALLBACK_WITH_FAILURE(cb, data);
+ Â Â Â g_free(cbd);
+}
+
+static void isi_write_file_cyclic(struct ofono_sim *sim, int fileid,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â int length, const unsigned char *value,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â ofono_sim_write_cb_t cb, void *data)
+{
+ Â Â Â DBG("Fileid %04X not implemented", fileid);
+ Â Â Â CALLBACK_WITH_FAILURE(cb, data);
+}
+static void uicc_read_imsi_resp(const struct ofono_error *error,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â const unsigned char *data,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â int len,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â void *user)
+{
+ Â Â Â struct isi_cb_data *cbd = user;
+ Â Â Â ofono_sim_imsi_cb_t cb = cbd->cb;
+ Â Â Â /* For coding see TS 24.008 */
+ Â Â Â char imsi[SIM_MAX_IMSI_LENGTH + 1];
+ Â Â Â int i = 1; /*Skip length, the 1st byte*/
+ Â Â Â int j = 0;
+ Â Â Â int octets;
+
+ Â Â Â if (data == NULL)
+ Â Â Â Â Â Â Â goto error;
+
+ Â Â Â octets = data[0];
+
+ Â Â Â if (octets != 8 || octets > len)
+ Â Â Â Â Â Â Â goto error;
+
+ Â Â Â /* Ignore the low-order semi-octet of the first byte */
+ Â Â Â imsi[j] = ((data[i] & 0xF0) >> 4) + '0';
+
+ Â Â Â for (i++, j++; i - 1 < octets && j < SIM_MAX_IMSI_LENGTH; i++) {
+ Â Â Â Â Â Â Â char nibble;
+ Â Â Â Â Â Â Â imsi[j++] = (data[i] & 0x0F) + '0';
+ Â Â Â Â Â Â Â nibble = (data[i] & 0xF0) >> 4;
+
+ Â Â Â Â Â Â Â if (nibble != 0x0F)
+ Â Â Â Â Â Â Â Â Â Â Â imsi[j++] = nibble + '0';
+ Â Â Â }
+
+ Â Â Â imsi[j] = '\0';
+ Â Â Â DBG("IMSI %s", imsi);
+ Â Â Â CALLBACK_WITH_SUCCESS(cb, imsi, cbd->data);
+ Â Â Â goto out;
+error:
+ Â Â Â CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
+out:
+ Â Â Â g_free(cbd);
+ Â Â Â return;
+}
+
+static void imsi_resp_cb(const GIsiMessage *msg, void *data)
+{
+ Â Â Â struct isi_cb_data *cbd = data;
+ Â Â Â ofono_sim_imsi_cb_t cb = cbd->cb;
+
+ Â Â Â struct sim_imsi *resp;
+ Â Â Â size_t len = sizeof(struct sim_imsi);
+
+ Â Â Â char imsi[SIM_MAX_IMSI_LENGTH + 1];
+ Â Â Â size_t i, j;
+
+ Â Â Â if (!g_isi_msg_data_get_struct(msg, 2, (const void **) &resp, len))
+ Â Â Â Â Â Â Â goto error;
+
+ Â Â Â /* Ignore the low-order semi-octet of the first byte */
+ Â Â Â imsi[0] = ((resp->imsi[0] & 0xF0) >> 4) + '0';
+
+ Â Â Â for (i = 1, j = 1; i < resp->length && j < SIM_MAX_IMSI_LENGTH;
i++) {
+ Â Â Â Â Â Â Â char nibble;
+
+ Â Â Â Â Â Â Â imsi[j++] = (resp->imsi[i] & 0x0F) + '0';
+ Â Â Â Â Â Â Â nibble = (resp->imsi[i] & 0xF0) >> 4;
+ Â Â Â Â Â Â Â if (nibble != 0x0F)
+ Â Â Â Â Â Â Â Â Â Â Â imsi[j++] = nibble + '0';
+ Â Â Â }
+
+ Â Â Â imsi[j] = '\0';
+ Â Â Â CALLBACK_WITH_SUCCESS(cb, imsi, cbd->data);
+ Â Â Â return;
+
+error:
+ Â Â Â CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
+}
+
+static void isi_read_imsi(struct ofono_sim *sim,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â ofono_sim_imsi_cb_t cb, void *data)
+{
+ Â Â Â struct sim_data *sd = ofono_sim_get_data(sim);
+ Â Â Â struct isi_cb_data *cbd = isi_cb_data_new(sim, cb, data);
+ Â Â Â size_t len;
+
+ Â Â Â const uint8_t msg[] = {
+ Â Â Â Â Â Â Â SIM_IMSI_REQ_READ_IMSI,
+ Â Â Â Â Â Â Â READ_IMSI
+ Â Â Â };
+
+ Â Â Â if (cbd == NULL || sd == NULL)
+ Â Â Â Â Â Â Â goto error;
+
+ Â Â Â if (g_isi_client_resource(sd->client) == PN_UICC) {
+ Â Â Â Â Â Â Â isi_read_file_transparent(sim, SIM_EFIMSI_FILEID, 0, 9,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â uicc_read_imsi_resp, cbd);
+ Â Â Â Â Â Â Â return;
+ Â Â Â }
+ Â Â Â len = sizeof(msg);
+
+
+ Â Â Â if (g_isi_client_send(sd->client, msg, len, imsi_resp_cb, cbd, g_free))
+ Â Â Â Â Â Â Â return;
+
+error:
+ Â Â Â CALLBACK_WITH_FAILURE(cb, NULL, data);
+ Â Â Â g_free(cbd);
+}
+
+static void uicc_application_activate_req(GIsiClient *client,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â void *opaque,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â unsigned char appl_type,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â unsigned char aid);
+
+
+static void uicc_application_activate_resp(const GIsiMessage *msg, void *data)
+{
+ Â Â Â struct ofono_sim *sim = data;
+ Â Â Â GIsiSubBlockIter iter;
+ Â Â Â uint8_t sbcount = 0;
+ Â Â Â uint8_t status;
+ Â Â Â struct sim_data *sd = ofono_sim_get_data(sim);
+
+ Â Â Â if (g_isi_msg_error(msg) < 0)
+ Â Â Â Â Â Â Â return;
+
+ Â Â Â if (g_isi_msg_id(msg) != UICC_APPLICATION_RESP)
+ Â Â Â Â Â Â Â return;
+
+ Â Â Â g_isi_msg_data_get_byte(msg, 1, &status);
+
+ Â Â Â if (status == UICC_STATUS_OK || status == UICC_STATUS_APPL_ACTIVE) {
+ Â Â Â Â Â Â Â if (!sd->uicc_app_started) {
+ Â Â Â Â Â Â Â Â Â Â Â sd->app_id = sd->trying_app_id;
+ Â Â Â Â Â Â Â Â Â Â Â sd->app_type = sd->trying_app_type;
+ Â Â Â Â Â Â Â Â Â Â Â sd->uicc_app_started = TRUE;
+ Â Â Â Â Â Â Â Â Â Â Â DBG("UICC application activated");
+ Â Â Â Â Â Â Â Â Â Â Â ofono_sim_inserted_notify(sim, TRUE);
+ Â Â Â Â Â Â Â Â Â Â Â ofono_sim_register(sim);
+ Â Â Â Â Â Â Â Â Â Â Â g_free(sd->sim_application_list_p);
+ Â Â Â Â Â Â Â }
+ Â Â Â } else {
+ Â Â Â Â Â Â Â int i = sim_applications_get_next_index(
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â sd->sim_application_list_p,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â sd->trying_app_id);
+
+ Â Â Â Â Â Â Â if (i == NOT_AVAILABLE) {
+ Â Â Â Â Â Â Â Â Â Â Â g_free(sd->sim_application_list_p);
+ Â Â Â Â Â Â Â Â Â Â Â return;
+ Â Â Â Â Â Â Â }
+
+ Â Â Â Â Â Â Â DBG("Activation Error, trying to activate APP with ID:%d", i);
+ Â Â Â Â Â Â Â uicc_application_activate_req(sd->client, sim,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â sd->sim_application_list_p->app_type[i],
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â sd->sim_application_list_p->app_list[i]);
+ Â Â Â Â Â Â Â return;
+ Â Â Â }
+
+ Â Â Â g_isi_msg_data_get_byte(msg, 5, &sbcount);
+ Â Â Â g_isi_sb_iter_init_full(&iter, msg, 6, TRUE, sbcount);
+
+ Â Â Â while (g_isi_sb_iter_is_valid(&iter)) {
Might as well have a for loop here, like elsewhere in the drivers.
+ Â Â Â Â Â Â Â DBG("Sub-block %s",
+ Â Â Â Â Â Â Â Â Â Â Â uicc_subblock_name(g_isi_sb_iter_get_id(&iter)));
+
+ Â Â Â Â Â Â Â switch (g_isi_sb_iter_get_id(&iter)) {
+ Â Â Â Â Â Â Â case UICC_SB_CLIENT: {
+ Â Â Â Â Â Â Â Â Â Â Â guint8 client = 0;
+ Â Â Â Â Â Â Â Â Â Â Â g_isi_sb_iter_get_byte(&iter, &client, 7);
+ Â Â Â Â Â Â Â Â Â Â Â DBG("Client id %d", client);
+ Â Â Â Â Â Â Â Â Â Â Â sd->client_id = client;
+ Â Â Â Â Â Â Â Â Â Â Â break;
+ Â Â Â Â Â Â Â }
+ Â Â Â Â Â Â Â case UICC_SB_FCI:
+ Â Â Â Â Â Â Â Â Â Â Â DBG("UICC_SB_FCI");
+
+ Â Â Â Â Â Â Â Â Â Â Â if (sd->app_type == UICC_APPL_TYPE_UICC_USIM) {
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â uint16_t length, record_length;
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â uint8_t records, structure;
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â handle_app_uicc_usim(&iter, sd, &length,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â &record_length, &records,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â &structure);
+ Â Â Â Â Â Â Â Â Â Â Â }
+
+ Â Â Â Â Â Â Â Â Â Â Â break;
+ Â Â Â Â Â Â Â case UICC_SB_CHV:
+ Â Â Â Â Â Â Â Â Â Â Â DBG("UICC_SB_CHV");
+
+ Â Â Â Â Â Â Â Â Â Â Â if (sd->app_type == UICC_APPL_TYPE_ICC_SIM) {
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â uint8_t chv_id = 0, pin_id = 0;
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â (void) g_isi_sb_iter_get_byte(&iter,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â &chv_id, 4);
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â (void) g_isi_sb_iter_get_byte(&iter,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â &pin_id, 5);
Not checking the return value is one thing, but how is the (void)
supposed to help here?
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â
DBG("UICC_APPL_TYPE_UICC_SIM");
+
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â if (chv_id == 1)
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â sd->pin1_id = pin_id;
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â else if (chv_id == 2)
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â sd->pin2_id = pin_id;
+ Â Â Â Â Â Â Â Â Â Â Â }
+
+ Â Â Â Â Â Â Â Â Â Â Â break;
+ Â Â Â Â Â Â Â default:
+ Â Â Â Â Â Â Â Â Â Â Â DBG("Skipping sub-block: %s (%zu bytes)",
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â uicc_subblock_name(g_isi_sb_iter_get_id(&iter)),
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â g_isi_sb_iter_get_len(&iter));
+ Â Â Â Â Â Â Â Â Â Â Â break;
+ Â Â Â Â Â Â Â }
+
+ Â Â Â Â Â Â Â (void)g_isi_sb_iter_next(&iter);
+ Â Â Â }
+}
+
+static void uicc_application_activate_req(GIsiClient *client,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â void *opaque,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â unsigned char appl_type,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â unsigned char aid)
+{
+ Â Â Â const unsigned char msg[] = {
+ Â Â Â Â Â Â Â UICC_APPLICATION_REQ,
+ Â Â Â Â Â Â Â UICC_APPL_HOST_ACTIVATE,
+ Â Â Â Â Â Â Â 2, /* number of subblocks*/
+ Â Â Â /* Subblock 1 */
+ Â Â Â Â Â Â Â UICC_SB_APPLICATION >> 8,
+ Â Â Â Â Â Â Â UICC_SB_APPLICATION & 0xff,
+ Â Â Â Â Â Â Â 0, /*subblock length*/
+ Â Â Â Â Â Â Â 8, /*subblock length*/
+ Â Â Â Â Â Â Â 0, /*filler*/
+ Â Â Â Â Â Â Â 0, /*filler*/
+ Â Â Â Â Â Â Â appl_type,
+ Â Â Â Â Â Â Â aid,
+ Â Â Â /* Subblock 2 */
+ Â Â Â Â Â Â Â UICC_SB_APPL_INFO >> 8,
+ Â Â Â Â Â Â Â UICC_SB_APPL_INFO & 0xff,
+ Â Â Â Â Â Â Â 0, /*subblock length*/
+ Â Â Â Â Â Â Â 8, /*subblock length*/
Hmm.. Maybe a macro for all of these 16bit identifiers and byte order
conversions?
+ Â Â Â Â Â Â Â 0, /*filler*/
+ Â Â Â Â Â Â Â 0, /*filler*/
+ Â Â Â Â Â Â Â 0, /*filler*/
+ Â Â Â Â Â Â Â /* whether the application initialization procedure
+ Â Â Â Â Â Â Â * Â will follow the activation or not */
+ Â Â Â Â Â Â Â UICC_APPL_START_UP_INIT_PROC
+ Â Â Â };
+
+ Â Â Â DBG("Appl type %d, AID %d", appl_type, aid);
+
+ Â Â Â g_isi_client_send_with_timeout(
+ Â Â Â Â Â Â Â client, msg, sizeof(msg), SIM_TIMEOUT,
+ Â Â Â Â Â Â Â uicc_application_activate_resp, opaque, NULL);
+}
+
+static void uicc_application_list_resp(const GIsiMessage *msg, void *data)
+{
+ Â Â Â struct ofono_sim *sim = data;
+ Â Â Â gboolean everything_ok = TRUE;
+ Â Â Â int index = NOT_AVAILABLE;
+ Â Â Â struct sim_data *sd = ofono_sim_get_data(sim);
+
+ Â Â Â if (!check_response_status(msg, UICC_APPLICATION_RESP,
+ Â Â Â Â Â Â Â Â Â Â Â UICC_APPL_LIST)) {
+ Â Â Â Â Â Â Â uint8_t status = 0;
+
+ Â Â Â Â Â Â Â g_isi_msg_data_get_byte(msg, 2, &status);
+ Â Â Â Â Â Â Â if (status != UICC_STATUS_FAIL)
+ Â Â Â Â Â Â Â Â Â Â Â return;
This returns if the request did *not* fail?
+ Â Â Â Â Â Â Â everything_ok = FALSE;
+ Â Â Â }
+
+ Â Â Â sd->sim_application_list_p = g_try_new0(struct sim_applications, 1);
+
+ Â Â Â if (everything_ok) {
+ Â Â Â Â Â Â Â GIsiSubBlockIter iter;
+ Â Â Â Â Â Â Â uint8_t sbcount = 0;
+ Â Â Â Â Â Â Â g_isi_msg_data_get_byte(msg, 5, &sbcount);
+ Â Â Â Â Â Â Â g_isi_sb_iter_init_full(&iter, msg, 6, TRUE, sbcount);
+
+ Â Â Â Â Â Â Â while (g_isi_sb_iter_is_valid(&iter)) {
+ Â Â Â Â Â Â Â Â Â Â Â DBG("Sub-block %s",
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â uicc_subblock_name(
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â g_isi_sb_iter_get_id(&iter)));
+
+ Â Â Â Â Â Â Â Â Â Â Â switch (g_isi_sb_iter_get_id(&iter)) {
+ Â Â Â Â Â Â Â Â Â Â Â case UICC_SB_APPL_DATA_OBJECT: {
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â guint8 appl_id = -1;
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â guint8 appl_type = -1;
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â guint8 status = -1;
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â gboolean ret;
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â ret = g_isi_sb_iter_get_byte(
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â &iter, &appl_type, 6);
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â ret = g_isi_sb_iter_get_byte(
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â &iter, &appl_id, 7);
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â (void) g_isi_sb_iter_get_byte(
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â &iter, &status, 8);
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â DBG("Appl type=%d, Appl id=%d, Appl
status=%d",
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â appl_type, appl_id, status);
+
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â sd->sim_application_list_p->app_list[appl_id] =
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â appl_id;
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â sd->sim_application_list_p->app_type[appl_id] =
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â appl_type;
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â break;
+ Â Â Â Â Â Â Â Â Â Â Â }
+ Â Â Â Â Â Â Â Â Â Â Â default:
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â DBG("Skipping sub-block: %s (%zu bytes)",
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â uicc_subblock_name(
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â g_isi_sb_iter_get_id(&iter)),
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â g_isi_sb_iter_get_len(&iter));
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â break;
+ Â Â Â Â Â Â Â Â Â Â Â }
+
+ Â Â Â Â Â Â Â Â Â Â Â g_isi_sb_iter_next(&iter);
+ Â Â Â Â Â Â Â }
+ Â Â Â }
+
+ Â Â Â if (!sd->uicc_app_started) {
+ Â Â Â Â Â Â Â index = sim_applications_get_next_index(
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â sd->sim_application_list_p,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â NOT_ACTIVATED);
+
+ Â Â Â Â Â Â Â if (index != NOT_AVAILABLE) {
+ Â Â Â Â Â Â Â Â Â Â Â DBG("Activating APP index:%d", index);
+ Â Â Â Â Â Â Â Â Â Â Â sd->trying_app_id =
+ Â Â Â Â Â Â Â Â Â Â Â Â sd->sim_application_list_p->app_list[index];
+ Â Â Â Â Â Â Â Â Â Â Â sd->trying_app_type =
+ Â Â Â Â Â Â Â Â Â Â Â Â sd->sim_application_list_p->app_type[index];
+ Â Â Â Â Â Â Â Â Â Â Â DBG("Activating APP ID: %d APP type: %d",
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â sd->trying_app_id, sd->trying_app_type);
+ Â Â Â Â Â Â Â Â Â Â Â uicc_application_activate_req(sd->client, sim,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â sd->sim_application_list_p->app_type[index],
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â sd->sim_application_list_p->app_list[index]);
+ Â Â Â Â Â Â Â } else
+ Â Â Â Â Â Â Â Â Â Â Â g_free(sd->sim_application_list_p);
+ Â Â Â }
+}
+
+static void uicc_application_list_req(GIsiClient *client,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â void *opaque)
+{
+ Â Â Â const unsigned char msg[] = {
+ Â Â Â Â Â Â Â UICC_APPLICATION_REQ,
+ Â Â Â Â Â Â Â UICC_APPL_LIST,
+ Â Â Â Â Â Â Â 0 /* number of subblocks*/
+ Â Â Â };
+ Â Â Â DBG("");
+
+ Â Â Â g_isi_client_send_with_timeout(
+ Â Â Â Â Â Â Â client, msg, sizeof(msg), SIM_TIMEOUT,
+ Â Â Â Â Â Â Â uicc_application_list_resp, opaque, NULL);
+}
+
+static void uicc_pin_enter_resp(const GIsiMessage *msg, void *data)
+{
+ Â Â Â struct isi_cb_data *cbd = data;
+ Â Â Â ofono_sim_lock_unlock_cb_t cb = cbd->cb;
+ Â Â Â struct ofono_sim_local *local_sim =
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â (struct ofono_sim_local *) cbd->user;
+ Â Â Â GIsiSubBlockIter iter;
+ Â Â Â struct sim_data *sd =
+ Â Â Â Â Â Â Â Â Â Â Â ofono_sim_get_data((struct ofono_sim *) local_sim);
+ Â Â Â uint8_t sbcount = 0;
+
+ Â Â Â if (g_isi_msg_error(msg) < 0)
+ Â Â Â Â Â Â Â goto error;
+
+ Â Â Â if (check_response_status(msg, UICC_PIN_RESP, UICC_PIN_VERIFY)) {
+ Â Â Â Â Â Â Â sd->passwd_required = FALSE;
+ Â Â Â Â Â Â Â CALLBACK_WITH_SUCCESS(cb, cbd->data);
+ Â Â Â Â Â Â Â goto out;
+ Â Â Â }
+
+ Â Â Â g_isi_msg_data_get_byte(msg, 5, &sbcount);
+ Â Â Â g_isi_sb_iter_init_full(&iter, msg, 6, TRUE, sbcount);
+
+ Â Â Â while (g_isi_sb_iter_is_valid(&iter)) {
+ Â Â Â Â Â Â Â DBG("Sub-block %s",
+ Â Â Â Â Â Â Â Â Â Â Â uicc_subblock_name(g_isi_sb_iter_get_id(&iter)));
+
+ Â Â Â Â Â Â Â switch (g_isi_sb_iter_get_id(&iter)) {
+ Â Â Â Â Â Â Â case UICC_SB_STATUS_WORD: {
+ Â Â Â Â Â Â Â Â Â Â Â uint16_t status;
+ Â Â Â Â Â Â Â Â Â Â Â g_isi_sb_iter_get_word(&iter, &status, 6);
+ Â Â Â Â Â Â Â Â Â Â Â DBG("APDU status word = %04X", status);
+
+ Â Â Â Â Â Â Â Â Â Â Â switch (status) {
+ Â Â Â Â Â Â Â Â Â Â Â case UICC_PIN_STATUS_AUTH_BLOCKED:
+ Â Â Â Â Â Â Â Â Â Â Â case UICC_PIN_STATUS_AUTH_FAILED:
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â DBG("Authentication method blocked");
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â update_locked_pin(local_sim,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â UICC_PIN_UNBLOCK_NEEDED,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â sd->current_pin_id);
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â break;
+ Â Â Â Â Â Â Â Â Â Â Â default:
+
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â if ((status & 0xfff0) ==
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â UICC_PIN_STATUS_AUTH_RETRIES)
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â DBG("Attempts left %d", status &
0xf);
+
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â break;
+ Â Â Â Â Â Â Â Â Â Â Â }
+
+ Â Â Â Â Â Â Â Â Â Â Â break;
+ Â Â Â Â Â Â Â }
+ Â Â Â Â Â Â Â default:
+ Â Â Â Â Â Â Â Â Â Â Â break;
+ Â Â Â Â Â Â Â }
+
+ Â Â Â Â Â Â Â g_isi_sb_iter_next(&iter);
+ Â Â Â }
+
+error:
+ Â Â Â CALLBACK_WITH_FAILURE(cb, cbd->data);
+out:
+ Â Â Â g_free(cbd);
+}
+
+static void uicc_pin_enter(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 isi_cb_data *cbd = isi_cb_data_new(sim, cb, data);
+ Â Â Â char pin[8] = {0, 0, 0, 0, 0, 0, 0, 0};
Writing '= { 0 }' is the same thing
+
+ Â Â Â sd->current_pin_id = sd->pin1_id; /* No way to enter PIN2 */
+
+ Â Â Â if (cbd && sd) {
+ Â Â Â Â Â Â Â unsigned char pinlen = strlen(passwd);
+ Â Â Â Â Â Â Â unsigned char msg[] = {
+ Â Â Â Â Â Â Â Â Â Â Â UICC_PIN_REQ,
+ Â Â Â Â Â Â Â Â Â Â Â UICC_PIN_VERIFY,
+ Â Â Â Â Â Â Â Â Â Â Â sd->app_id,
+ Â Â Â Â Â Â Â Â Â Â Â 0, /* Filler */
+ Â Â Â Â Â Â Â Â Â Â Â 0, /* Filler */
+ Â Â Â Â Â Â Â Â Â Â Â 0, /* Filler */
+ Â Â Â Â Â Â Â Â Â Â Â 1, /* number of subblocks */
+ Â Â Â Â Â Â Â Â Â Â Â /* Subblock 1 */
+ Â Â Â Â Â Â Â Â Â Â Â UICC_SB_PIN >> 8,
+ Â Â Â Â Â Â Â Â Â Â Â UICC_SB_PIN & 0xff,
+ Â Â Â Â Â Â Â Â Â Â Â 0,
+ Â Â Â Â Â Â Â Â Â Â Â 16, /* Max length */
+ Â Â Â Â Â Â Â Â Â Â Â sd->current_pin_id, /* PIN id */
+ Â Â Â Â Â Â Â Â Â Â Â UICC_PIN_OLD, /* PIN qualifier */
+ Â Â Â Â Â Â Â Â Â Â Â pinlen /* PIN length */
+ Â Â Â Â Â Â Â };
+ Â Â Â Â Â Â Â struct iovec iov[2] = {
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â { msg, sizeof(msg) },
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â { pin, 8 }
+ Â Â Â Â Â Â Â };
+
+ Â Â Â Â Â Â Â if ((pinlen < 4) || (pinlen > 8))
+ Â Â Â Â Â Â Â Â Â Â Â goto error;
+
+ Â Â Â Â Â Â Â memmove(pin, passwd, pinlen);
+
+ Â Â Â Â Â Â Â g_isi_client_vsend_with_timeout(sd->client, iov, 2,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â SIM_TIMEOUT, uicc_pin_enter_resp, cbd,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â g_free);
+ Â Â Â Â Â Â Â return;
+ Â Â Â }
+
+error:
+ Â Â Â CALLBACK_WITH_FAILURE(cb, data);
+ Â Â Â g_free(cbd);
+}
+
+static void uicc_pin_prompt(struct ofono_sim *sim,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â enum ofono_sim_password_type passwd_type,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â ofono_sim_passwd_cb_t cb,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â void *data,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â uint8_t service);
+
+
+static void uicc_pin_prompt_resp(const GIsiMessage *msg, void *data)
 {
    struct isi_cb_data *cbd = data;
- Â Â Â ofono_sim_read_cb_t cb = cbd->cb;
+ Â Â Â ofono_sim_passwd_cb_t cb = cbd->cb;
+ Â Â Â struct ofono_sim_local *local_sim =
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â (struct ofono_sim_local *) cbd->user;
+ Â Â Â struct sim_data *sd =
+ Â Â Â Â Â Â Â Â Â Â Â ofono_sim_get_data((struct ofono_sim *)local_sim);
+
+ Â Â Â unsigned char lock_type = -1;
+ Â Â Â GIsiSubBlockIter iter;
+ Â Â Â uint8_t status = UICC_STATUS_UNKNOWN;
+ Â Â Â uint8_t pin_attempts = -1;
+ Â Â Â uint8_t puk_attempts = -1;
+
+ Â Â Â if (!check_response_status(msg, UICC_PIN_RESP, UICC_PIN_PROMPT_VERIFY)
+ Â Â Â Â Â Â Â Â Â Â Â && !check_response_status(msg, UICC_PIN_RESP,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â UICC_PIN_INFO)) {
+
+ Â Â Â Â Â Â Â if (!check_response_status_with_cause(msg, UICC_PIN_RESP,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â UICC_PIN_PROMPT_VERIFY,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â UICC_STATUS_PIN_DISABLED, 1))
+ Â Â Â Â Â Â Â Â Â Â Â goto error;
+ Â Â Â }
My brain doesn't have a powerful enough logic unit to be able to parse this. ;)
- Â Â Â const struct sim_spn *resp = NULL;
- Â Â Â size_t len = sizeof(struct sim_spn);
+ Â Â Â g_isi_msg_data_get_byte(msg, 1, &status);
+
+ Â Â Â if (check_response_status(msg, UICC_PIN_RESP, UICC_PIN_PROMPT_VERIFY)) {
+ Â Â Â Â Â Â Â sd->pin_state_received = TRUE;
+ Â Â Â } else if (check_response_status(msg, UICC_PIN_RESP, UICC_PIN_INFO)) {
...especially after this.
+ Â Â Â Â Â Â Â uint8_t sbcount = 0;
+
+ Â Â Â Â Â Â Â sd->pin_state_received = TRUE;
+ Â Â Â Â Â Â Â g_isi_msg_data_get_byte(msg, 5, &sbcount);
+ Â Â Â Â Â Â Â g_isi_sb_iter_init_full(&iter, msg, 6, TRUE, sbcount);
+
+ Â Â Â Â Â Â Â while (g_isi_sb_iter_is_valid(&iter)) {
+ Â Â Â Â Â Â Â Â Â Â Â DBG("Sub-block %s",
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â uicc_subblock_name(g_isi_sb_iter_get_id(
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â &iter)));
+
+ Â Â Â Â Â Â Â Â Â Â Â switch (g_isi_sb_iter_get_id(&iter)) {
+ Â Â Â Â Â Â Â Â Â Â Â case UICC_SB_PIN_INFO:
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â g_isi_sb_iter_get_byte(&iter, &status, 4);
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â g_isi_sb_iter_get_byte(&iter,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â &pin_attempts, 5);
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â g_isi_sb_iter_get_byte(&iter,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â &puk_attempts, 6);
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â DBG("Status=%s, PIN attempts=%d, \
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â PUK attempts=%d",
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â uicc_status_name(status),
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â pin_attempts, puk_attempts);
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â break;
+ Â Â Â Â Â Â Â Â Â Â Â default:
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â break;
+ Â Â Â Â Â Â Â Â Â Â Â }
+
+ Â Â Â Â Â Â Â Â Â Â Â g_isi_sb_iter_next(&iter);
+ Â Â Â Â Â Â Â }
+ Â Â Â }
- Â Â Â uint8_t spn[SIM_MAX_SPN_LENGTH + 1];
- Â Â Â int i;
+ Â Â Â if ((status == UICC_STATUS_OK) ||
+ Â Â Â Â Â Â Â (status == UICC_STATUS_PIN_ENABLED)) {
+ Â Â Â Â Â Â Â /* PIN query on, indication should tell
+ Â Â Â Â Â Â Â Â * if it is verified or not
+ Â Â Â Â Â Â Â Â */
+ Â Â Â Â Â Â Â if (pin_attempts == 0) {
+ Â Â Â Â Â Â Â Â Â Â Â DBG("PIN blocked");
+ Â Â Â Â Â Â Â Â Â Â Â update_locked_pin(local_sim,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â UICC_PIN_UNBLOCK_NEEDED,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â sd->current_pin_id);
+ Â Â Â Â Â Â Â } else {
+ Â Â Â Â Â Â Â Â Â Â Â DBG("PIN query enabled");
+ Â Â Â Â Â Â Â Â Â Â Â update_locked_pin(local_sim,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â UICC_PIN_VERIFY_NEEDED,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â sd->current_pin_id);
+ Â Â Â Â Â Â Â }
- Â Â Â if (!check_response_status(msg, SIM_SERV_PROV_NAME_RESP,
- Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â SIM_ST_READ_SERV_PROV_NAME))
- Â Â Â Â Â Â Â goto error;
+ Â Â Â Â Â Â Â lock_type = local_sim->pin_type;
+ Â Â Â } else if (status == UICC_STATUS_PIN_DISABLED) {
+ Â Â Â Â Â Â Â if (pin_attempts == 0) {
+ Â Â Â Â Â Â Â Â Â Â Â DBG("PIN blocked");
+ Â Â Â Â Â Â Â Â Â Â Â update_locked_pin(local_sim,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â UICC_PIN_UNBLOCK_NEEDED,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â sd->current_pin_id);
+ Â Â Â Â Â Â Â Â Â Â Â lock_type = local_sim->pin_type;
+ Â Â Â Â Â Â Â } else {
+ Â Â Â Â Â Â Â Â Â Â Â DBG("PIN query disabled");
+ Â Â Â Â Â Â Â Â Â Â Â local_sim->locked_pins[OFONO_SIM_PASSWORD_SIM_PIN] =
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â FALSE;
+ Â Â Â Â Â Â Â Â Â Â Â local_sim->locked_pins[OFONO_SIM_PASSWORD_SIM_PIN2] =
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â FALSE;
+ Â Â Â Â Â Â Â Â Â Â Â lock_type = OFONO_SIM_PASSWORD_NONE;
+ Â Â Â Â Â Â Â }
+ Â Â Â }
- Â Â Â if (!g_isi_msg_data_get_struct(msg, 2, (const void **) &resp, len))
- Â Â Â Â Â Â Â goto error;
+ Â Â Â if (check_response_status(msg, UICC_PIN_RESP, UICC_PIN_PROMPT_VERIFY)) {
...and this.
+ Â Â Â Â Â Â Â uicc_pin_prompt(cbd->user,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â OFONO_SIM_PASSWORD_SIM_PIN,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â cb,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â cbd->data,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â UICC_PIN_INFO);
+ Â Â Â }
- Â Â Â /* Set display condition bits */
- Â Â Â spn[0] = (resp->disp_home & 0x01) | ((resp->disp_roam & 0x01)
<< 1);
+ Â Â Â CALLBACK_WITH_SUCCESS(cb, lock_type, cbd->data);
+ Â Â Â return;
+error:
+ Â Â Â DBG("PIN prompt verify failed");
+ Â Â Â CALLBACK_WITH_FAILURE(cb, -1, cbd->data);
+}
- Â Â Â /* Convert from a NULL-terminated UCS-2 string to ASCII */
- Â Â Â for (i = 0; i < SIM_MAX_SPN_LENGTH; i++) {
- Â Â Â Â Â Â Â uint16_t c = resp->name[i] >> 8 | resp->name[i] << 8;
+static void uicc_pin_prompt(struct ofono_sim *sim,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â enum ofono_sim_password_type passwd_type,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â ofono_sim_passwd_cb_t cb,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â void *data,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â uint8_t service)
+{
+ Â Â Â struct sim_data *sd = ofono_sim_get_data(sim);
+ Â Â Â struct isi_cb_data *cbd = isi_cb_data_new(sim, cb, data);
+ Â Â Â int8_t index;
+ Â Â Â unsigned char msg[] = {
+ Â Â Â Â Â Â Â UICC_PIN_REQ,
+ Â Â Â Â Â Â Â service,
+ Â Â Â Â Â Â Â 0, /*app id*/
+ Â Â Â Â Â Â Â 0, /*Filler*/
+ Â Â Â Â Â Â Â 0, /*Filler*/
+ Â Â Â Â Â Â Â 0, /*Filler*/
+ Â Â Â Â Â Â Â 1, /*number of subblocks*/
+ Â Â Â Â Â Â Â /* Subblock 1 */
+ Â Â Â Â Â Â Â UICC_SB_PIN_REF >> 8,
+ Â Â Â Â Â Â Â UICC_SB_PIN_REF & 0xff,
+ Â Â Â Â Â Â Â 0, /*Sub block length.*/
+ Â Â Â Â Â Â Â 8,
+ Â Â Â Â Â Â Â 0, /*PIN ID*/
+ Â Â Â Â Â Â Â 0, /*Filler*/
+ Â Â Â Â Â Â Â 0, /*Filler*/
+ Â Â Â Â Â Â Â 0 Â /*Filler*/
+ Â Â Â };
- Â Â Â Â Â Â Â if (c == 0)
- Â Â Â Â Â Â Â Â Â Â Â c = 0xFF;
- Â Â Â Â Â Â Â else if (!g_ascii_isprint(c))
- Â Â Â Â Â Â Â Â Â Â Â c = '?';
+ Â Â Â sd->current_pin_id = get_pin_id(sd, passwd_type, &index);
- Â Â Â Â Â Â Â spn[i + 1] = c;
+ Â Â Â if (cbd == NULL || sd == NULL) {
+ Â Â Â Â Â Â Â CALLBACK_WITH_FAILURE(cb, -1, data);
+ Â Â Â Â Â Â Â g_free(cbd);
+ Â Â Â Â Â Â Â return;
    }
- Â Â Â CALLBACK_WITH_SUCCESS(cb, spn, sizeof(spn), cbd->data);
- Â Â Â return;
+ Â Â Â if (sd->current_pin_id == 0) {
+ Â Â Â Â Â Â Â CALLBACK_WITH_FAILURE(cb, -1, data);
+ Â Â Â Â Â Â Â g_free(cbd);
+ Â Â Â Â Â Â Â return;
+ Â Â Â }
-error:
- Â Â Â CALLBACK_WITH_FAILURE(cb, NULL, 0, cbd->data);
+ Â Â Â msg[2] = sd->app_id;
+ Â Â Â msg[11] = sd->current_pin_id;
+
+ Â Â Â g_isi_client_send_with_timeout(sd->client, msg, sizeof(msg),
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â SIM_TIMEOUT, uicc_pin_prompt_resp,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â cbd, g_free);
 }
-static gboolean isi_read_spn(struct ofono_sim *sim, struct isi_cb_data *cbd)
+static void uicc_passwd_state_query(struct ofono_sim *sim,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â ofono_sim_passwd_cb_t cb,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â void *data)
 {
    struct sim_data *sd = ofono_sim_get_data(sim);
+ Â Â Â struct ofono_sim_local *local_sim = (struct ofono_sim_local *)sim;
- Â Â Â const uint8_t msg[] = {
- Â Â Â Â Â Â Â SIM_SERV_PROV_NAME_REQ,
- Â Â Â Â Â Â Â SIM_ST_READ_SERV_PROV_NAME,
- Â Â Â Â Â Â Â 0
- Â Â Â };
+ Â Â Â if (sd->pin_state_received) {
+ Â Â Â Â Â Â Â int lock_type = OFONO_SIM_PASSWORD_NONE;
- Â Â Â if (sd == NULL)
- Â Â Â Â Â Â Â return FALSE;
+ Â Â Â Â Â Â Â if (sd->passwd_required) {
+ Â Â Â Â Â Â Â Â Â Â Â /* These should be in priority order, highest last */
+ Â Â Â Â Â Â Â Â Â Â Â if (local_sim->locked_pins[
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â OFONO_SIM_PASSWORD_SIM_PIN] == TRUE)
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â lock_type = OFONO_SIM_PASSWORD_SIM_PIN;
- Â Â Â return g_isi_client_send(sd->client, msg, sizeof(msg),
- Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â spn_resp_cb, cbd, g_free);
+ Â Â Â Â Â Â Â Â Â Â Â if (local_sim->locked_pins[
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â OFONO_SIM_PASSWORD_SIM_PIN2] == TRUE)
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â lock_type = OFONO_SIM_PASSWORD_SIM_PIN2;
+
+ Â Â Â Â Â Â Â Â Â Â Â if (local_sim->locked_pins[
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â OFONO_SIM_PASSWORD_PHNET_PIN] == TRUE)
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â lock_type = OFONO_SIM_PASSWORD_PHNET_PIN;
+
+ Â Â Â Â Â Â Â Â Â Â Â if (local_sim->locked_pins[
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â OFONO_SIM_PASSWORD_SIM_PUK] == TRUE)
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â lock_type = OFONO_SIM_PASSWORD_SIM_PUK;
+
+ Â Â Â Â Â Â Â Â Â Â Â if (local_sim->locked_pins[
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â OFONO_SIM_PASSWORD_SIM_PUK2] == TRUE)
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â lock_type = OFONO_SIM_PASSWORD_SIM_PUK2;
+
+ Â Â Â Â Â Â Â Â Â Â Â if (local_sim->locked_pins[
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â OFONO_SIM_PASSWORD_PHNET_PUK] == TRUE)
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â lock_type = OFONO_SIM_PASSWORD_PHNET_PUK;
+ Â Â Â Â Â Â Â }
+
+ Â Â Â Â Â Â Â DBG("UICC lock type=%d", lock_type);
+ Â Â Â Â Â Â Â CALLBACK_WITH_SUCCESS(cb, lock_type, data);
+ Â Â Â } else {
+ Â Â Â Â Â Â Â if (sd->uicc_app_started) {
+ Â Â Â Â Â Â Â Â Â Â Â /* No indication received but UICC app is
+ Â Â Â Â Â Â Â Â Â Â Â Â * started, let's query the state
+ Â Â Â Â Â Â Â Â Â Â Â Â */
+ Â Â Â Â Â Â Â Â Â Â Â DBG("Querying PIN info");
+ Â Â Â Â Â Â Â Â Â Â Â uicc_pin_prompt(sim, OFONO_SIM_PASSWORD_SIM_PIN,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â cb, data, UICC_PIN_PROMPT_VERIFY);
+ Â Â Â Â Â Â Â Â Â Â Â return;
+ Â Â Â Â Â Â Â }
+
+ Â Â Â Â Â Â Â DBG("No UICC_PIN_IND received");
+ Â Â Â Â Â Â Â CALLBACK_WITH_FAILURE(cb, -1, data);
+ Â Â Â }
 }
-static void read_iccid_resp_cb(const GIsiMessage *msg, void *data)
+static void uicc_pin_enable_resp(const GIsiMessage *msg, void *data)
 {
    struct isi_cb_data *cbd = data;
- Â Â Â ofono_sim_read_cb_t cb = cbd->cb;
- Â Â Â struct sim_iccid *icc;
- Â Â Â size_t len = sizeof(struct sim_iccid);
+ Â Â Â ofono_sim_lock_unlock_cb_t cb = cbd->cb;
+ Â Â Â struct ofono_sim_local *local_sim =
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â (struct ofono_sim_local *) cbd->user;
+ Â Â Â struct sim_data *sd =
+ Â Â Â Â Â Â Â Â Â Â Â ofono_sim_get_data((struct ofono_sim *) local_sim);
- Â Â Â if (!check_response_status(msg, SIM_READ_FIELD_RESP, ICC))
- Â Â Â Â Â Â Â goto error;
+ Â Â Â GIsiSubBlockIter iter;
+ Â Â Â uint8_t sbcount = 0;
- Â Â Â if (!g_isi_msg_data_get_struct(msg, 2, (const void **) &icc, len))
+ Â Â Â if (g_isi_msg_error(msg) < 0)
        goto error;
- Â Â Â CALLBACK_WITH_SUCCESS(cb, icc->id, 10, cbd->data);
- Â Â Â return;
-
-error:
- Â Â Â CALLBACK_WITH_FAILURE(cb, NULL, 0, cbd->data);
-}
+ Â Â Â if (!check_response_status(msg, UICC_PIN_RESP, UICC_PIN_DISABLE) &&
+ Â Â Â Â Â Â Â Â Â Â Â !check_response_status(msg, UICC_PIN_RESP,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â UICC_PIN_ENABLE))
+ Â Â Â Â Â Â Â goto cont;
-static gboolean isi_read_iccid(struct ofono_sim *sim, struct isi_cb_data *cbd)
-{
- Â Â Â struct sim_data *sd = ofono_sim_get_data(sim);
+ Â Â Â DBG("PIN lock/unlock succeeded");
+ Â Â Â CALLBACK_WITH_SUCCESS(cb, cbd->data);
+ Â Â Â return;
- Â Â Â const uint8_t req[] = {
- Â Â Â Â Â Â Â SIM_READ_FIELD_REQ,
- Â Â Â Â Â Â Â ICC,
- Â Â Â };
+cont:
+ Â Â Â g_isi_msg_data_get_byte(msg, 5, &sbcount);
+ Â Â Â g_isi_sb_iter_init_full(&iter, msg, 6, TRUE, sbcount);
+
+ Â Â Â while (g_isi_sb_iter_is_valid(&iter)) {
+ Â Â Â Â Â Â Â DBG("Sub-block %s",
+ Â Â Â Â Â Â Â Â Â uicc_subblock_name(g_isi_sb_iter_get_id(&iter)));
+
+ Â Â Â Â Â Â Â switch (g_isi_sb_iter_get_id(&iter)) {
+ Â Â Â Â Â Â Â case UICC_SB_STATUS_WORD: {
+ Â Â Â Â Â Â Â Â Â Â Â uint16_t status;
+ Â Â Â Â Â Â Â Â Â Â Â g_isi_sb_iter_get_word(&iter, &status, 6);
+ Â Â Â Â Â Â Â Â Â Â Â DBG("APDU status word = %04X", status);
+
+ Â Â Â Â Â Â Â Â Â Â Â switch (status) {
+ Â Â Â Â Â Â Â Â Â Â Â case UICC_PIN_STATUS_AUTH_BLOCKED:
+ Â Â Â Â Â Â Â Â Â Â Â case UICC_PIN_STATUS_AUTH_FAILED:
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â DBG("Authentication method blocked");
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â update_locked_pin(local_sim,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â UICC_PIN_UNBLOCK_NEEDED,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â sd->current_pin_id);
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â break;
+ Â Â Â Â Â Â Â Â Â Â Â default:
+
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â if ((status & 0xfff0) ==
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â UICC_PIN_STATUS_AUTH_RETRIES)
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â DBG("Attempts left %d", status &
0xf);
+
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â break;
+ Â Â Â Â Â Â Â Â Â Â Â }
+ Â Â Â Â Â Â Â }
+ Â Â Â Â Â Â Â default:
+ Â Â Â Â Â Â Â Â Â Â Â break;
+ Â Â Â Â Â Â Â }
- Â Â Â if (sd == NULL)
- Â Â Â Â Â Â Â return FALSE;
+ Â Â Â Â Â Â Â g_isi_sb_iter_next(&iter);
+ Â Â Â }
- Â Â Â return g_isi_client_send(sd->client, req, sizeof(req),
- Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â read_iccid_resp_cb, cbd, g_free);
+error:
+ Â Â Â DBG("PIN lock/unlock failed");
+ Â Â Â CALLBACK_WITH_FAILURE(cb, cbd->data);
 }
-static void isi_read_file_transparent(struct ofono_sim *sim, int fileid,
- Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â int start, int length,
- Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â ofono_sim_read_cb_t cb, void *data)
+static void uicc_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 isi_cb_data *cbd;
- Â Â Â gboolean done;
+ Â Â Â struct sim_data *sd = ofono_sim_get_data(sim);
+ Â Â Â struct isi_cb_data *cbd = isi_cb_data_new(sim, cb, data);
+ Â Â Â int8_t index;
+ Â Â Â unsigned char service = 0;
- Â Â Â cbd = isi_cb_data_new(sim, cb, data);
- Â Â Â if (cbd == NULL)
+ Â Â Â if (cbd == NULL || sd == NULL)
        goto error;
- Â Â Â switch (fileid) {
- Â Â Â case SIM_EFSPN_FILEID:
- Â Â Â Â Â Â Â done = isi_read_spn(sim, cbd);
- Â Â Â Â Â Â Â break;
-
- Â Â Â case SIM_EF_ICCID_FILEID:
- Â Â Â Â Â Â Â done = isi_read_iccid(sim, cbd);
- Â Â Â Â Â Â Â break;
+ Â Â Â sd->current_pin_id = get_pin_id(sd, passwd_type, &index);
- Â Â Â default:
- Â Â Â Â Â Â Â done = FALSE;
- Â Â Â }
+ Â Â Â if (sd->current_pin_id == 0)
+ Â Â Â Â Â Â Â goto error;
- Â Â Â if (done)
+ Â Â Â if (enable)
+ Â Â Â Â Â Â Â service = UICC_PIN_ENABLE;
+ Â Â Â else
+ Â Â Â Â Â Â Â service = UICC_PIN_DISABLE;
+
+ Â Â Â if ((cbd) && (sd) && (sd->current_pin_id)) {
+
+ Â Â Â Â Â Â Â unsigned char pinlen = strlen(passwd);
+
+ Â Â Â Â Â Â Â unsigned char msg[] = {
+ Â Â Â Â Â Â Â Â Â Â Â UICC_PIN_REQ,
+ Â Â Â Â Â Â Â Â Â Â Â service,
+ Â Â Â Â Â Â Â Â Â Â Â sd->app_id,
+ Â Â Â Â Â Â Â Â Â Â Â 0, /*Filler*/
+ Â Â Â Â Â Â Â Â Â Â Â 0, /*Filler*/
+ Â Â Â Â Â Â Â Â Â Â Â 0, /*Filler*/
+ Â Â Â Â Â Â Â Â Â Â Â 1, /*number of subblocks*/
+ Â Â Â Â Â Â Â /* Subblock 1 */
+ Â Â Â Â Â Â Â Â Â Â Â UICC_SB_PIN >> 8,
+ Â Â Â Â Â Â Â Â Â Â Â UICC_SB_PIN & 0xff,
+ Â Â Â Â Â Â Â Â Â Â Â 0,
+ Â Â Â Â Â Â Â Â Â Â Â 16, /*Max length*/
+ Â Â Â Â Â Â Â Â Â Â Â sd->current_pin_id, /* PIN id */
+ Â Â Â Â Â Â Â Â Â Â Â UICC_PIN_OLD, /* PIN qualifier */
+ Â Â Â Â Â Â Â Â Â Â Â pinlen, /* PIN length */
+ Â Â Â Â Â Â Â Â Â Â Â 0,
+ Â Â Â Â Â Â Â Â Â Â Â 0,
+ Â Â Â Â Â Â Â Â Â Â Â 0,
+ Â Â Â Â Â Â Â Â Â Â Â 0,
+ Â Â Â Â Â Â Â Â Â Â Â 0,
+ Â Â Â Â Â Â Â Â Â Â Â 0,
+ Â Â Â Â Â Â Â Â Â Â Â 0,
+ Â Â Â Â Â Â Â Â Â Â Â 0,
+ Â Â Â Â Â Â Â Â Â Â Â 0
+ Â Â Â Â Â Â Â };
+
+ Â Â Â Â Â Â Â if ((pinlen < 4) || (pinlen > 8))
+ Â Â Â Â Â Â Â Â Â Â Â goto error;
+ Â Â Â Â Â Â Â memmove(&msg[14], passwd, pinlen);
+ Â Â Â Â Â Â Â g_isi_client_send_with_timeout(
+ Â Â Â Â Â Â Â Â Â Â Â sd->client, msg, sizeof(msg), SIM_TIMEOUT,
+ Â Â Â Â Â Â Â Â Â Â Â uicc_pin_enable_resp, cbd, g_free);
        return;
-
- Â Â Â DBG("Fileid %04X not implemented", fileid);
+ Â Â Â }
 error:
- Â Â Â CALLBACK_WITH_FAILURE(cb, NULL, 0, data);
+ Â Â Â CALLBACK_WITH_FAILURE(cb, data);
    g_free(cbd);
+ Â Â Â return;
 }
-static void isi_read_file_linear(struct ofono_sim *sim, int fileid,
- Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â int record, int length,
- Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â ofono_sim_read_cb_t cb, void *data)
+static void uicc_pin_change_resp(const GIsiMessage *msg, void *data)
 {
- Â Â Â DBG("Fileid %04X not implemented", fileid);
- Â Â Â CALLBACK_WITH_FAILURE(cb, NULL, 0, data);
-}
+ Â Â Â struct isi_cb_data *cbd = data;
+ Â Â Â ofono_sim_lock_unlock_cb_t cb = cbd->cb;
+ Â Â Â struct ofono_sim_local *local_sim =
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â (struct ofono_sim_local *) cbd->user;
+ Â Â Â struct sim_data *sd =
+ Â Â Â Â Â Â Â Â Â Â Â ofono_sim_get_data((struct ofono_sim *) local_sim);
-static void isi_read_file_cyclic(struct ofono_sim *sim, int fileid,
- Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â int record, int length,
- Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â ofono_sim_read_cb_t cb, void *data)
-{
- Â Â Â DBG("Fileid %04X not implemented", fileid);
- Â Â Â CALLBACK_WITH_FAILURE(cb, NULL, 0, data);
-}
+ Â Â Â GIsiSubBlockIter iter;
+ Â Â Â uint8_t sbcount = 0;
-static void isi_write_file_transparent(struct ofono_sim *sim, int fileid,
- Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â int start, int length,
- Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â const unsigned char *value,
- Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â ofono_sim_write_cb_t cb, void *data)
-{
- Â Â Â DBG("Fileid %04X not implemented", fileid);
- Â Â Â CALLBACK_WITH_FAILURE(cb, data);
-}
+ Â Â Â if (g_isi_msg_error(msg) < 0)
+ Â Â Â Â Â Â Â goto error;
-static void isi_write_file_linear(struct ofono_sim *sim, int fileid,
- Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â int record, int length,
- Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â const unsigned char *value,
- Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â ofono_sim_write_cb_t cb, void *data)
-{
- Â Â Â DBG("Fileid %04X not implemented", fileid);
- Â Â Â CALLBACK_WITH_FAILURE(cb, data);
+ Â Â Â if (!check_response_status(msg, UICC_PIN_RESP, UICC_PIN_CHANGE))
+ Â Â Â Â Â Â Â goto cont;
+
+ Â Â Â DBG("PIN change succeeded");
+ Â Â Â CALLBACK_WITH_SUCCESS(cb, cbd->data);
+ Â Â Â return;
+
+cont:
+ Â Â Â g_isi_msg_data_get_byte(msg, 5, &sbcount);
+ Â Â Â g_isi_sb_iter_init_full(&iter, msg, 6, TRUE, sbcount);
+
+ Â Â Â while (g_isi_sb_iter_is_valid(&iter)) {
+ Â Â Â Â Â Â Â DBG("Sub-block %s",
+ Â Â Â Â Â Â Â Â Â Â Â uicc_subblock_name(g_isi_sb_iter_get_id(&iter)));
+
+ Â Â Â Â Â Â Â switch (g_isi_sb_iter_get_id(&iter)) {
+ Â Â Â Â Â Â Â case UICC_SB_STATUS_WORD: {
+ Â Â Â Â Â Â Â Â Â Â Â uint16_t status;
+ Â Â Â Â Â Â Â Â Â Â Â g_isi_sb_iter_get_word(&iter, &status, 6);
+ Â Â Â Â Â Â Â Â Â Â Â DBG("APDU status word = %04X", status);
+
+ Â Â Â Â Â Â Â Â Â Â Â switch (status) {
+ Â Â Â Â Â Â Â Â Â Â Â case UICC_PIN_STATUS_AUTH_BLOCKED:
+ Â Â Â Â Â Â Â Â Â Â Â case UICC_PIN_STATUS_AUTH_FAILED:
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â DBG("Authentication method blocked");
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â update_locked_pin(local_sim,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â UICC_PIN_UNBLOCK_NEEDED,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â sd->current_pin_id);
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â break;
+ Â Â Â Â Â Â Â Â Â Â Â default:
+
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â if ((status & 0xfff0) ==
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â UICC_PIN_STATUS_AUTH_RETRIES)
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â DBG("Attempts left %d", status &
0xf);
+
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â break;
+ Â Â Â Â Â Â Â Â Â Â Â }
+
+ Â Â Â Â Â Â Â Â Â Â Â break;
+ Â Â Â Â Â Â Â }
+ Â Â Â Â Â Â Â default:
+ Â Â Â Â Â Â Â Â Â Â Â break;
+ Â Â Â Â Â Â Â }
+
+ Â Â Â Â Â Â Â g_isi_sb_iter_next(&iter);
+ Â Â Â }
+error:
+ Â Â Â DBG("PIN change failed");
+ Â Â Â CALLBACK_WITH_FAILURE(cb, cbd->data);
 }
-static void isi_write_file_cyclic(struct ofono_sim *sim, int fileid,
- Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â int length, const unsigned char *value,
- Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â ofono_sim_write_cb_t cb, void *data)
+static void uicc_change_pin(struct ofono_sim *sim,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â enum ofono_sim_password_type passwd_type,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â const char *old,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â const char *new,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â ofono_sim_lock_unlock_cb_t cb,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â void *data)
 {
- Â Â Â DBG("Fileid %04X not implemented", fileid);
+ Â Â Â struct sim_data *sd = ofono_sim_get_data(sim);
+ Â Â Â struct isi_cb_data *cbd = isi_cb_data_new(sim, cb, data);
+ Â Â Â int8_t index;
+ Â Â Â sd->current_pin_id = get_pin_id(sd, passwd_type, &index);
+ Â Â Â DBG("old=%s, new=%s, PINID=%02x",
+ Â Â Â Â Â Â Â old, new, sd->current_pin_id);
+
+ Â Â Â if ((cbd) && (sd) && (sd->current_pin_id)) {
+ Â Â Â Â Â Â Â unsigned char service = UICC_PIN_CHANGE;
+ Â Â Â Â Â Â Â unsigned char oldlen = strlen(old);
+ Â Â Â Â Â Â Â unsigned char newlen = strlen(new);
+
+ Â Â Â Â Â Â Â unsigned char msg[] = {
+ Â Â Â Â Â Â Â Â Â Â Â UICC_PIN_REQ,
+ Â Â Â Â Â Â Â Â Â Â Â service,
+ Â Â Â Â Â Â Â Â Â Â Â sd->app_id,
+ Â Â Â Â Â Â Â Â Â Â Â 0, /*Filler*/
+ Â Â Â Â Â Â Â Â Â Â Â 0, /*Filler*/
+ Â Â Â Â Â Â Â Â Â Â Â 0, /*Filler*/
+ Â Â Â Â Â Â Â Â Â Â Â 2, /*number of subblocks*/
+ Â Â Â Â Â Â Â /* Subblock 1 */
+ Â Â Â Â Â Â Â Â Â Â Â UICC_SB_PIN >> 8,
+ Â Â Â Â Â Â Â Â Â Â Â UICC_SB_PIN & 0xff,
+ Â Â Â Â Â Â Â Â Â Â Â 0,
+ Â Â Â Â Â Â Â Â Â Â Â 16, /* Must be fixed */
+ Â Â Â Â Â Â Â Â Â Â Â sd->current_pin_id, /* PIN id */
+ Â Â Â Â Â Â Â Â Â Â Â UICC_PIN_OLD, /* PIN qualifier */
+ Â Â Â Â Â Â Â Â Â Â Â oldlen, /* PIN length */
+ Â Â Â Â Â Â Â Â Â Â Â 0,
+ Â Â Â Â Â Â Â Â Â Â Â 0,
+ Â Â Â Â Â Â Â Â Â Â Â 0,
+ Â Â Â Â Â Â Â Â Â Â Â 0,
+ Â Â Â Â Â Â Â Â Â Â Â 0,
+ Â Â Â Â Â Â Â Â Â Â Â 0,
+ Â Â Â Â Â Â Â Â Â Â Â 0,
+ Â Â Â Â Â Â Â Â Â Â Â 0,
+ Â Â Â Â Â Â Â Â Â Â Â 0,
+ Â Â Â Â Â Â Â /* Subblock 2 */
+ Â Â Â Â Â Â Â Â Â Â Â UICC_SB_PIN >> 8,
+ Â Â Â Â Â Â Â Â Â Â Â UICC_SB_PIN & 0xff,
+ Â Â Â Â Â Â Â Â Â Â Â 0,
+ Â Â Â Â Â Â Â Â Â Â Â /* Sub block length:
+ Â Â Â Â Â Â Â Â Â Â Â * Â "header" size + 1 (=trailing filler) + PIN length
*/
+ Â Â Â Â Â Â Â Â Â Â Â 16,
+ Â Â Â Â Â Â Â Â Â Â Â sd->current_pin_id, /* PIN id */
+ Â Â Â Â Â Â Â Â Â Â Â UICC_PIN_NEW, /* PIN qualifier */
+ Â Â Â Â Â Â Â Â Â Â Â newlen, /* PIN length */
+ Â Â Â Â Â Â Â Â Â Â Â 0,
+ Â Â Â Â Â Â Â Â Â Â Â 0,
+ Â Â Â Â Â Â Â Â Â Â Â 0,
+ Â Â Â Â Â Â Â Â Â Â Â 0,
+ Â Â Â Â Â Â Â Â Â Â Â 0,
+ Â Â Â Â Â Â Â Â Â Â Â 0,
+ Â Â Â Â Â Â Â Â Â Â Â 0,
+ Â Â Â Â Â Â Â Â Â Â Â 0,
+ Â Â Â Â Â Â Â Â Â Â Â 0
+ Â Â Â Â Â Â Â };
+
+ Â Â Â Â Â Â Â if ((oldlen < 4) || (oldlen > 8))
+ Â Â Â Â Â Â Â Â Â Â Â goto error;
+
+ Â Â Â Â Â Â Â if ((newlen < 4) || (newlen > 8))
+ Â Â Â Â Â Â Â Â Â Â Â goto error;
+
+ Â Â Â Â Â Â Â memmove(&msg[14], old, oldlen);
+ Â Â Â Â Â Â Â memmove(&msg[30], new, newlen);
+ Â Â Â Â Â Â Â g_isi_client_send_with_timeout(
+ Â Â Â Â Â Â Â Â Â Â Â sd->client, msg, sizeof(msg), SIM_TIMEOUT,
+ Â Â Â Â Â Â Â Â Â Â Â uicc_pin_change_resp, cbd, g_free);
+ Â Â Â Â Â Â Â return;
+ Â Â Â }
+
+error:
+ Â Â Â DBG("Error");
    CALLBACK_WITH_FAILURE(cb, data);
+ Â Â Â g_free(cbd);
+ Â Â Â return;
 }
-static void imsi_resp_cb(const GIsiMessage *msg, void *data)
+static void uicc_pin_send_puk_resp(const GIsiMessage *msg, void *data)
 {
    struct isi_cb_data *cbd = data;
- Â Â Â ofono_sim_imsi_cb_t cb = cbd->cb;
+ Â Â Â ofono_sim_lock_unlock_cb_t cb = cbd->cb;
+ Â Â Â struct ofono_sim_local *local_sim =
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â (struct ofono_sim_local *) cbd->user;
+ Â Â Â GIsiSubBlockIter iter;
+ Â Â Â uint8_t sbcount = 0;
- Â Â Â struct sim_imsi *resp;
- Â Â Â size_t len = sizeof(struct sim_imsi);
+ Â Â Â if (g_isi_msg_error(msg) < 0)
+ Â Â Â Â Â Â Â goto error;
+ Â Â Â if (!check_response_status(msg, UICC_PIN_RESP, UICC_PIN_UNBLOCK))
+ Â Â Â Â Â Â Â goto cont;
+
+ Â Â Â DBG("PIN reset succeeded");
+ Â Â Â /* Only PIN1 can be reseted, turns PIN query on */
+ Â Â Â local_sim->locked_pins[OFONO_SIM_PASSWORD_SIM_PIN] = TRUE;
+ Â Â Â local_sim->locked_pins[OFONO_SIM_PASSWORD_SIM_PUK] = FALSE;
+ Â Â Â CALLBACK_WITH_SUCCESS(cb, cbd->data);
+ Â Â Â return;
- Â Â Â char imsi[SIM_MAX_IMSI_LENGTH + 1];
- Â Â Â size_t i, j;
+cont:
+ Â Â Â g_isi_msg_data_get_byte(msg, 5, &sbcount);
+ Â Â Â g_isi_sb_iter_init_full(&iter, msg, 6, TRUE, sbcount);
- Â Â Â if (!check_response_status(msg, SIM_IMSI_RESP_READ_IMSI, READ_IMSI))
- Â Â Â Â Â Â Â goto error;
+ Â Â Â while (g_isi_sb_iter_is_valid(&iter)) {
+ Â Â Â Â Â Â Â DBG("Sub-block %s",
+ Â Â Â Â Â Â Â Â Â Â Â uicc_subblock_name(g_isi_sb_iter_get_id(&iter)));
- Â Â Â if (!g_isi_msg_data_get_struct(msg, 2, (const void **) &resp, len))
- Â Â Â Â Â Â Â goto error;
+ Â Â Â Â Â Â Â switch (g_isi_sb_iter_get_id(&iter)) {
+ Â Â Â Â Â Â Â case UICC_SB_STATUS_WORD: {
+ Â Â Â Â Â Â Â Â Â Â Â uint16_t status;
+ Â Â Â Â Â Â Â Â Â Â Â g_isi_sb_iter_get_word(&iter, &status, 6);
+ Â Â Â Â Â Â Â Â Â Â Â DBG("APDU status word = %04X", status);
- Â Â Â /* Ignore the low-order semi-octet of the first byte */
- Â Â Â imsi[0] = ((resp->imsi[0] & 0xF0) >> 4) + '0';
+ Â Â Â Â Â Â Â Â Â Â Â switch (status) {
+ Â Â Â Â Â Â Â Â Â Â Â case UICC_PIN_STATUS_AUTH_BLOCKED:
+ Â Â Â Â Â Â Â Â Â Â Â case UICC_PIN_STATUS_AUTH_FAILED:
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â DBG("Authentication method blocked");
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â break;
+ Â Â Â Â Â Â Â Â Â Â Â default:
- Â Â Â for (i = 1, j = 1; i < resp->length && j < SIM_MAX_IMSI_LENGTH;
i++) {
- Â Â Â Â Â Â Â char nibble;
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â if ((status & 0xfff0) ==
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â UICC_PIN_STATUS_AUTH_RETRIES)
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â DBG("Attempts left %d", status &
0xf);
- Â Â Â Â Â Â Â imsi[j++] = (resp->imsi[i] & 0x0F) + '0';
- Â Â Â Â Â Â Â nibble = (resp->imsi[i] & 0xF0) >> 4;
- Â Â Â Â Â Â Â if (nibble != 0x0F)
- Â Â Â Â Â Â Â Â Â Â Â imsi[j++] = nibble + '0';
- Â Â Â }
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â break;
+ Â Â Â Â Â Â Â Â Â Â Â }
- Â Â Â imsi[j] = '\0';
- Â Â Â CALLBACK_WITH_SUCCESS(cb, imsi, cbd->data);
- Â Â Â return;
+ Â Â Â Â Â Â Â Â Â Â Â break;
+ Â Â Â Â Â Â Â }
+ Â Â Â Â Â Â Â default:
+ Â Â Â Â Â Â Â Â Â Â Â break;
+ Â Â Â Â Â Â Â }
+
+ Â Â Â Â Â Â Â g_isi_sb_iter_next(&iter);
+ Â Â Â }
 error:
- Â Â Â CALLBACK_WITH_FAILURE(cb, NULL, cbd->data);
+ Â Â Â DBG("PIN reset failed");
+ Â Â Â CALLBACK_WITH_FAILURE(cb, cbd->data);
 }
-static void isi_read_imsi(struct ofono_sim *sim,
- Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â ofono_sim_imsi_cb_t cb, void *data)
+static void uicc_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 isi_cb_data *cbd = isi_cb_data_new(sim, cb, data);
+ Â Â Â unsigned char service = UICC_PIN_UNBLOCK;
+ Â Â Â unsigned char pinlen = strlen(passwd);
+ Â Â Â uint8_t pin[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+ Â Â Â uint8_t pukcode[10] = { 0, 0, 0 , 0, 0, 0, 0, 0, 0, 0 };
+
+ Â Â Â uint8_t msg[] = {
+ Â Â Â Â Â Â Â UICC_PIN_REQ,
+ Â Â Â Â Â Â Â service,
+ Â Â Â Â Â Â Â sd->app_id,
+ Â Â Â Â Â Â Â 0, /*Filler*/
+ Â Â Â Â Â Â Â 0, /*Filler*/
+ Â Â Â Â Â Â Â 0, /*Filler*/
+ Â Â Â Â Â Â Â 2, /*number of subblocks*/
+ Â Â Â Â Â Â Â /* Subblock 1*/
+ Â Â Â Â Â Â Â UICC_SB_PIN >> 8,
+ Â Â Â Â Â Â Â UICC_SB_PIN & 0xff,
+ Â Â Â Â Â Â Â 0,
+ Â Â Â Â Â Â Â 16, /*sb length, must be fixed*/
+ Â Â Â Â Â Â Â sd->current_pin_id, /* PIN id*/
+ Â Â Â Â Â Â Â UICC_PIN_NEW, /* PIN qualifier*/
+ Â Â Â Â Â Â Â pinlen /* PIN length*/
+ Â Â Â };
+ Â Â Â uint8_t msg2[] = {
+ Â Â Â Â Â Â Â /* Subblock 2*/
+ Â Â Â Â Â Â Â UICC_SB_PUK >> 8,
+ Â Â Â Â Â Â Â UICC_SB_PUK & 0xff,
+ Â Â Â Â Â Â Â 0,
+ Â Â Â Â Â Â Â 16, /*Sub block length*/
+ Â Â Â Â Â Â Â sd->current_pin_id, /* PIN id*/
+ Â Â Â Â Â Â Â 8, /* PUK length*/
+ Â Â Â };
- Â Â Â const uint8_t msg[] = {
- Â Â Â Â Â Â Â SIM_IMSI_REQ_READ_IMSI,
- Â Â Â Â Â Â Â READ_IMSI
+ Â Â Â struct iovec iov[4] = {
+ Â Â Â Â Â Â Â Â Â Â Â { msg, sizeof(msg) },
+ Â Â Â Â Â Â Â Â Â Â Â { pin, 8 },
+ Â Â Â Â Â Â Â Â Â Â Â { msg2, sizeof(msg2) },
+ Â Â Â Â Â Â Â Â Â Â Â { pukcode, 10 }
    };
- Â Â Â size_t len = sizeof(msg);
    if (cbd == NULL || sd == NULL)
        goto error;
- Â Â Â if (g_isi_client_send(sd->client, msg, len, imsi_resp_cb, cbd, g_free))
- Â Â Â Â Â Â Â return;
+ Â Â Â if ((pinlen < 4) || (pinlen > 8))
+ Â Â Â Â Â Â Â goto error;
+
+ Â Â Â if (strlen(puk) != 8)
+ Â Â Â Â Â Â Â goto error;
+
+ Â Â Â sd->current_pin_id = sd->pin1_id; /* No way to reset PIN2 */
+
+ Â Â Â memmove(pin, passwd, pinlen);
+ Â Â Â memmove(pukcode, puk, 8);
+
+ Â Â Â g_isi_client_vsend_with_timeout(sd->client, iov, 4, SIM_TIMEOUT,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â uicc_pin_send_puk_resp, cbd,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â g_free);
+ Â Â Â return;
 error:
- Â Â Â CALLBACK_WITH_FAILURE(cb, NULL, data);
+ Â Â Â CALLBACK_WITH_FAILURE(cb, data);
    g_free(cbd);
+ Â Â Â return;
 }
 static void isi_sim_register(struct ofono_sim *sim)
@@ -414,34 +2569,125 @@ static void sim_ind_cb(const GIsiMessage *msg, void *data)
    struct sim_data *sd = ofono_sim_get_data(sim);
    uint8_t status;
- Â Â Â if (sd == NULL || g_isi_msg_id(msg) != SIM_IND || sd->registered)
- Â Â Â Â Â Â Â return;
+ Â Â Â if (g_isi_client_resource(sd->client) == PN_UICC) {
+ Â Â Â Â Â Â Â uint8_t service_type;
+ Â Â Â Â Â Â Â uint8_t pin_id;
+
+ Â Â Â Â Â Â Â g_isi_msg_data_get_byte(msg, 0, &service_type);
+ Â Â Â Â Â Â Â g_isi_msg_data_get_byte(msg, 1, &pin_id);
+
+ Â Â Â Â Â Â Â switch (g_isi_msg_id(msg)) {
+
+ Â Â Â Â Â Â Â case UICC_CARD_IND:
+ Â Â Â Â Â Â Â Â Â Â Â ofono_sim_inserted_notify(sim, TRUE);
+
+ Â Â Â Â Â Â Â Â Â Â Â if ((service_type == UICC_CARD_READY) &&
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â (!sd->uicc_app_started)) {
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â DBG("UICC_CARD_IND activation");
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â uicc_application_list_req(sd->client, sim);
+ Â Â Â Â Â Â Â Â Â Â Â }
+ Â Â Â Â Â Â Â Â Â Â Â break;
+ Â Â Â Â Â Â Â case UICC_PIN_IND:
+ Â Â Â Â Â Â Â Â Â Â Â sd->pin_state_received = TRUE;
+ Â Â Â Â Â Â Â Â Â Â Â sd->passwd_required = FALSE;
+
+ Â Â Â Â Â Â Â Â Â Â Â switch (service_type) {
+ Â Â Â Â Â Â Â Â Â Â Â case UICC_PIN_VERIFY_NEEDED:
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â update_locked_pin((
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â struct ofono_sim_local *)sim,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â UICC_PIN_VERIFY_NEEDED,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â pin_id);
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â break;
+ Â Â Â Â Â Â Â Â Â Â Â case UICC_PIN_UNBLOCK_NEEDED:
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â update_locked_pin((
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â struct ofono_sim_local *)sim,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â UICC_PIN_UNBLOCK_NEEDED,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â pin_id);
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â break;
+ Â Â Â Â Â Â Â Â Â Â Â case UICC_PIN_PERMANENTLY_BLOCKED:
+ Â Â Â Â Â Â Â Â Â Â Â case UICC_PIN_VERIFIED:
+ Â Â Â Â Â Â Â Â Â Â Â default:
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â break;
+ Â Â Â Â Â Â Â Â Â Â Â }
+
+ Â Â Â Â Â Â Â Â Â Â Â break;
+ Â Â Â Â Â Â Â case UICC_IND:
+ Â Â Â Â Â Â Â Â Â Â Â DBG("UICC IND RECEIVED");
+
+ Â Â Â Â Â Â Â Â Â Â Â if (service_type == UICC_START_UP_COMPLETE)
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â sd->passwd_required = FALSE;
+
+ Â Â Â Â Â Â Â Â Â Â Â break;
+ Â Â Â Â Â Â Â default:
+ Â Â Â Â Â Â Â Â Â Â Â break;
+ Â Â Â Â Â Â Â }
+ Â Â Â } else {
+ Â Â Â Â Â Â Â if (sd == NULL || g_isi_msg_id(msg) != SIM_IND ||
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â sd->registered)
+ Â Â Â Â Â Â Â Â Â Â Â return;
+
+ Â Â Â Â Â Â Â if (!g_isi_msg_data_get_byte(msg, 0, &status))
+ Â Â Â Â Â Â Â Â Â Â Â return;
+
+ Â Â Â Â Â Â Â switch (status) {
+ Â Â Â Â Â Â Â case SIM_ST_PIN:
+ Â Â Â Â Â Â Â Â Â Â Â isi_sim_register(sim);
+ Â Â Â Â Â Â Â Â Â Â Â break;
+
+ Â Â Â Â Â Â Â case SIM_ST_INFO:
+ Â Â Â Â Â Â Â Â Â Â Â isi_read_hplmn(sim);
+ Â Â Â Â Â Â Â Â Â Â Â break;
+ Â Â Â Â Â Â Â }
+ Â Â Â }
+}
+
+static void uicc_reachable_cb(const GIsiMessage *msg, void *data)
+{
+ Â Â Â struct ofono_sim *sim = data;
+ Â Â Â struct sim_data *sd = ofono_sim_get_data(sim);
+ Â Â Â GIsiModem *modem = g_isi_client_modem(sd->primary);
- Â Â Â if (!g_isi_msg_data_get_byte(msg, 0, &status))
+ Â Â Â if (g_isi_msg_error(msg) < 0)
        return;
- Â Â Â switch (status) {
- Â Â Â case SIM_ST_PIN:
- Â Â Â Â Â Â Â isi_sim_register(sim);
- Â Â Â Â Â Â Â break;
+ Â Â Â ISI_VERSION_DBG(msg);
- Â Â Â case SIM_ST_INFO:
- Â Â Â Â Â Â Â isi_read_hplmn(sim);
- Â Â Â Â Â Â Â break;
+ Â Â Â sd->client = sd->primary;
+ Â Â Â sd->uicc_app_started = FALSE;
+ Â Â Â sd->pin_state_received = FALSE;
+ Â Â Â sd->passwd_required = TRUE;
+ Â Â Â sd->current_pin_id = 0x01;
+ Â Â Â sd->pin1_id = 0x01;
+ Â Â Â sd->pin2_id = 0x81;
+
+ Â Â Â g_isi_modem_set_sim(modem, sim);
+
+ Â Â Â if (!sd->uicc_app_started) {
+ Â Â Â Â Â Â Â DBG("Let's check if we have UICC applications");
+ Â Â Â Â Â Â Â uicc_application_list_req(sd->client, sim);
    }
+ Â Â Â g_isi_client_destroy(sd->secondary);
 }
 static void sim_reachable_cb(const GIsiMessage *msg, void *data)
 {
    struct ofono_sim *sim = data;
+ Â Â Â struct sim_data *sd = ofono_sim_get_data(sim);
+ Â Â Â GIsiModem *modem = g_isi_client_modem(sd->secondary);
    if (g_isi_msg_error(msg) < 0)
        return;
    ISI_VERSION_DBG(msg);
+ Â Â Â sd->client = sd->secondary;
+
+ Â Â Â g_isi_modem_set_sim(modem, sim);
+
    /* Check if SIM is ready by reading HPLMN */
    isi_read_hplmn(sim);
+
+ Â Â Â g_isi_client_destroy(sd->primary);
 }
 static int isi_sim_probe(struct ofono_sim *sim, unsigned int vendor,
@@ -454,16 +2700,32 @@ static int isi_sim_probe(struct ofono_sim *sim, unsigned int
vendor,
    if (sd == NULL)
        return -ENOMEM;
- Â Â Â sd->client = g_isi_client_create(modem, PN_SIM);
- Â Â Â if (sd->client == NULL) {
+ Â Â Â sd->primary = g_isi_client_create(modem, PN_UICC);
+
+ Â Â Â if (sd->primary == NULL) {
+ Â Â Â Â Â Â Â g_free(sd);
+ Â Â Â Â Â Â Â return -ENOMEM;
+ Â Â Â }
+
+ Â Â Â sd->secondary = g_isi_client_create(modem, PN_SIM);
+
+ Â Â Â if (sd->secondary == NULL) {
        g_free(sd);
        return -ENOMEM;
    }
    ofono_sim_set_data(sim, sd);
- Â Â Â g_isi_client_ind_subscribe(sd->client, SIM_IND, sim_ind_cb, sim);
- Â Â Â g_isi_client_verify(sd->client, sim_reachable_cb, sim, NULL);
+ Â Â Â g_isi_client_ind_subscribe(sd->secondary, SIM_IND, sim_ind_cb, sim);
+
+ Â Â Â g_isi_client_ind_subscribe(sd->primary, UICC_IND, sim_ind_cb, sim);
+ Â Â Â g_isi_client_ind_subscribe(sd->primary, UICC_CARD_IND, sim_ind_cb, sim);
+ Â Â Â g_isi_client_ind_subscribe(sd->primary, UICC_PIN_IND, sim_ind_cb, sim);
+ Â Â Â g_isi_client_ind_subscribe(sd->primary, UICC_APPLICATION_IND,
+ Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â Â sim_ind_cb, sim);
+
+ Â Â Â g_isi_client_verify(sd->primary, uicc_reachable_cb, sim, NULL);
+ Â Â Â g_isi_client_verify(sd->secondary, sim_reachable_cb, sim, NULL);
    return 0;
 }
@@ -471,13 +2733,23 @@ static int isi_sim_probe(struct ofono_sim *sim, unsigned int
vendor,
 static void isi_sim_remove(struct ofono_sim *sim)
 {
    struct sim_data *data = ofono_sim_get_data(sim);
-
- Â Â Â ofono_sim_set_data(sim, NULL);
+ Â Â Â GIsiModem *modem = g_isi_client_modem(data->client);
    if (data == NULL)
        return;
- Â Â Â g_isi_client_destroy(data->client);
+ Â Â Â g_isi_modem_set_sim(modem, NULL);
+
+ Â Â Â if (g_isi_client_resource(data->client) == PN_UICC) {
+ Â Â Â Â Â Â Â data->uicc_app_started = FALSE;
+ Â Â Â Â Â Â Â data->pin_state_received = FALSE;
+ Â Â Â Â Â Â Â data->passwd_required = TRUE;
+
+ Â Â Â Â Â Â Â g_isi_client_destroy(data->client);
+ Â Â Â } else
+ Â Â Â Â Â Â Â g_isi_client_destroy(data->client);
+
+ Â Â Â ofono_sim_set_data(sim, NULL);
    g_free(data);
 }
@@ -493,8 +2765,18 @@ static struct ofono_sim_driver driver = {
    .write_file_linear    = isi_write_file_linear,
    .write_file_cyclic    = isi_write_file_cyclic,
    .read_imsi        = isi_read_imsi,
+    .query_passwd_state   = uicc_passwd_state_query,
+    .send_passwd       = uicc_pin_enter,
+    .reset_passwd      = uicc_pin_send_puk,
+    .change_passwd      = uicc_change_pin,
+    .lock          = uicc_pin_enable,
Here is another example why having UICC in this file is a bad idea.
Obviously, a modem without PN_UICC would not work correctly here.
I can take this patch, and push a refactored version of the code as a
separate uicc.c file that implements a "wgmodem2.5" SIM driver. That
is the most sensible way forward, I think. Unless you'd like to do
this work, and I think it is quite a bit of work still.
Those parts touching SIM atom private data are a different thing. We
really need to figure out what is happening there, and have a proper
solution.
Cheers,
Aki