struct sim_data {
GIsiClient *client;
- bool iccid;
bool registered;
};
-/* Returns fake (static) file info for EFSPN */
-static gboolean efspn_file_info(gpointer user)
+struct file_info {
+ int fileid, length, structure, record_length;
+ unsigned char access[3];
+};
+
+/* Returns file info */
+static gboolean fake_file_info(gpointer user)
{
struct isi_cb_data *cbd = user;
ofono_sim_file_info_cb_t cb = cbd->cb;
- unsigned char access[3] = { 0x0f, 0xff, 0xff };
-
- DBG("Returning dummy file_info for EFSPN");
- CALLBACK_WITH_SUCCESS(cb, 17, 0, 0, access, cbd->data);
+ struct file_info const *fi = cbd->user;
+ DBG("Returning static file_info for %04x", fi->fileid);
+ CALLBACK_WITH_SUCCESS(cb,
+ fi->length, fi->structure, fi->record_length,
+ fi->access, cbd->data);
g_free(cbd);
return FALSE;
}
static void isi_read_file_info(struct ofono_sim *sim, int fileid,
ofono_sim_file_info_cb_t cb, void *data)
{
- if (fileid == SIM_EFSPN_FILEID) {
- /* Fake response for EFSPN */
- struct isi_cb_data *cbd = isi_cb_data_new(NULL, cb, data);
- g_idle_add(efspn_file_info, cbd);
- return;
+ int i;
+ static struct file_info const info[] = {
+ { SIM_EFSPN_FILEID, 17, 0, 0, { 0x0f, 0xff, 0xff } },
+ { SIM_EF_ICCID_FILEID, 10, 0, 0, { 0x0f, 0xff, 0xff } },
+ };
+ int N = sizeof(info) / sizeof(info[0]);
+ 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);
+ return;
+ }
}
DBG("Not implemented (fileid = %04x)", fileid);
const unsigned char *msg = data;
struct isi_cb_data *cbd = opaque;
ofono_sim_read_cb_t cb = cbd->cb;
- unsigned char spn[17] = { 0xff };
+ unsigned char *spn = NULL, buffer[17];
int i;
if (!msg) {
DBG("ISI client error: %d", g_isi_client_error(client));
- goto error;
+ goto done;
}
- if (len < 39 || msg[0] != SIM_SERV_PROV_NAME_RESP)
+ if (len < 39 || msg[0] != SIM_SERV_PROV_NAME_RESP
+ || msg[1] != SIM_ST_READ_SERV_PROV_NAME)
return false;
- if (msg[1] != SIM_ST_READ_SERV_PROV_NAME)
- goto error;
-
if (msg[2] != SIM_SERV_OK) {
DBG("Request failed: %s (0x%02X)",
sim_isi_cause_name(msg[2]), msg[2]);
- goto error;
+ goto done;
}
+ spn = buffer;
+
/* Set display condition bits */
spn[0] = ((msg[38] & 1) << 1) + (msg[37] & 1);
c = '?';
spn[i + 1] = c;
}
- CALLBACK_WITH_SUCCESS(cb, spn, 17, cbd->data);
- goto out;
-error:
- DBG("Error reading SPN");
- CALLBACK_WITH_FAILURE(cb, NULL, 0, cbd->data);
+done:
+ if (spn)
+ CALLBACK_WITH_SUCCESS(cb, spn, 17, cbd->data);
+ else
+ CALLBACK_WITH_FAILURE(cb, NULL, 0, cbd->data);
-out:
g_free(cbd);
return true;
}
-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 bool isi_read_spn(struct ofono_sim *sim, struct isi_cb_data *cbd)
{
struct sim_data *sd = ofono_sim_get_data(sim);
- struct isi_cb_data *cbd = isi_cb_data_new(sim, cb, data);
const unsigned char msg[] = {
SIM_SERV_PROV_NAME_REQ,
0
};
- /* Hack support for EFSPN reading only */
- if (fileid != SIM_EFSPN_FILEID)
- goto error;
+ return g_isi_request_make(sd->client, msg, sizeof(msg),
+ SIM_TIMEOUT, spn_resp_cb, cbd) != NULL;
+}
- if (!cbd)
- goto error;
+static bool read_iccid_resp_cb(GIsiClient *client, const void *restrict data,
+ size_t len, uint16_t object, void *user)
+{
+ struct isi_cb_data *cbd = user;
+ ofono_sim_read_cb_t cb = cbd->cb;
+ const unsigned char *msg = data;
+ const unsigned char *iccid = NULL;
- if (g_isi_request_make(sd->client, msg, sizeof(msg),
- SIM_TIMEOUT, spn_resp_cb, cbd))
- return;
+ if (!msg) {
+ DBG("ISI client error: %d", g_isi_client_error(client));
+ goto done;
+ }
+
+ if (len < 3 || msg[0] != SIM_READ_FIELD_RESP || msg[1] != ICC)
+ return false;
+
+ if (msg[2] == SIM_SERV_OK && len >= 13)
+ iccid = msg + 3;
+ else
+ DBG("Error reading ICC ID");
+
+done:
+ if (iccid)
+ CALLBACK_WITH_SUCCESS(cb, iccid, 10, cbd->data);
+ else
+ CALLBACK_WITH_FAILURE(cb, NULL, 0, cbd->data);
+
+ g_free(cbd);
+ return true;
+}
+
+static bool isi_read_iccid(struct ofono_sim *sim, struct isi_cb_data *cbd)
+{
+ struct sim_data *sd = ofono_sim_get_data(sim);
+ const unsigned char req[] = { SIM_READ_FIELD_REQ, ICC };
+
+ return g_isi_request_make(sd->client, req, sizeof(req), SIM_TIMEOUT,
+ read_iccid_resp_cb, cbd) != NULL;
+}
+
+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 isi_cb_data *cbd = isi_cb_data_new(sim, cb, data);
+
+ DBG("fileid = %04x", fileid);
+
+ switch (fileid) {
+ case SIM_EFSPN_FILEID:
+ if (isi_read_spn(sim, cbd))
+ return;
+ break;
+
+ case SIM_EF_ICCID_FILEID:
+ if (isi_read_iccid(sim, cbd))
+ return;
+ break;
+
+ default:
+ DBG("Not implemented (fileid = %04x)", fileid);
+ }
-error:
- DBG("Not implemented (fileid = %04x)", fileid);
CALLBACK_WITH_FAILURE(cb, NULL, 0, data);
g_free(cbd);
}
}
}
-static bool read_iccid_resp_cb(GIsiClient *client, const void *restrict data,
- size_t len, uint16_t object, void *opaque)
-{
- struct ofono_sim *sim = opaque;
- struct sim_data *sd = ofono_sim_get_data(sim);
- const unsigned char *msg = data;
-
- if (!msg) {
- DBG("ISI client error: %d", g_isi_client_error(client));
- return true;
- }
-
- if (len < 3 || msg[0] != SIM_READ_FIELD_RESP || msg[1] != 0x66)
- return false;
-
- if (msg[2] == SIM_SERV_OK)
- sd->iccid = true;
-
- return true;
-}
-
-static void isi_read_iccid(struct ofono_sim *sim)
-{
- struct sim_data *sd = ofono_sim_get_data(sim);
-
- const unsigned char req[] = {
- SIM_READ_FIELD_REQ,
- 0x66 /* ICC ID */
- };
-
- g_isi_request_make(sd->client, req, sizeof(req), SIM_TIMEOUT,
- read_iccid_resp_cb, sim);
-}
-
static bool read_hplmn_resp_cb(GIsiClient *client, const void *restrict data,
size_t len, uint16_t object, void *opaque)
{
if (sd->registered)
return;
- if (!sd->iccid)
- isi_read_iccid(sim);
-
switch (msg[1]) {
case SIM_ST_PIN:
isi_sim_register(sim);
g_isi_subscribe(client, SIM_IND, sim_ind_cb, opaque);
/* Check if SIM is ready. */
- isi_read_iccid(sim);
isi_read_hplmn(sim);
}