static void test_3g_status_data(void) { unsigned char *response; long len; int flen, rlen, str; unsigned char access[3]; unsigned short efid; response = decode_hex(binary_ef, -1, &len, 0); sim_parse_3g_get_response(response, len, &flen, &rlen, &str, access, &efid); g_assert(flen == 10); g_assert(rlen == 0); g_assert(str == 0); g_assert(access[0] == 0x01); g_assert(access[1] == 0xff); g_assert(access[2] == 0x44); g_assert(efid == 0x2F05); g_free(response); response = decode_hex(record_ef, -1, &len, 0); sim_parse_3g_get_response(response, len, &flen, &rlen, &str, access, &efid); g_assert(flen == 0x80); g_assert(rlen == 0x20); g_assert(str == 1); g_assert(access[0] == 0x11); g_assert(access[1] == 0xff); g_assert(access[2] == 0x44); g_assert(efid == 0x6F40); g_free(response); }
static void ril_file_info_cb(struct ril_msg *message, gpointer user_data) { struct cb_data *cbd = user_data; ofono_sim_file_info_cb_t cb = cbd->cb; struct sim_data *sd = cbd->user; int sw1, sw2; char *hex_response; unsigned char *response = NULL; long len; gboolean ok = FALSE; int flen = 0, rlen = 0, str = 0; guchar access[3] = { 0x00, 0x00, 0x00 }; guchar file_status; /* Error, and no data */ if (message->error != RIL_E_SUCCESS && message->buf_len == 0) { ofono_error("%s: Reply failure: %s", __func__, ril_error_to_string(message->error)); goto error; } /* * The reply can have event data even when message->error is not zero * in mako. * */ if (parse_sim_io(sd->ril, message, &sw1, &sw2, &hex_response) == FALSE) goto error; if (hex_response != NULL) { response = decode_hex(hex_response, -1, &len, -1); g_free(hex_response); hex_response = NULL; if (response == NULL) goto error; } /* * SIM app file not found || USIM app file not found * See 3gpp TS 51.011, 9.4.4, and ETSI TS 102 221, 10.2.1.5.3 * This can happen with result SUCCESS (maguro) or GENERIC_FAILURE * (mako) */ if ((sw1 == 0x94 && sw2 == 0x04) || (sw1 == 0x6A && sw2 == 0x82)) { DBG("File not found. Error %s", ril_error_to_string(message->error)); goto error; } if (message->error != RIL_E_SUCCESS) { ofono_error("%s: Reply failure: %s, %02x, %02x", __func__, ril_error_to_string(message->error), sw1, sw2); goto error; } if ((sw1 != 0x90 && sw1 != 0x91 && sw1 != 0x92 && sw1 != 0x9f) || (sw1 == 0x90 && sw2 != 0x00)) { struct ofono_error error; ofono_error("Error reply, invalid values: sw1: %02x sw2: %02x", sw1, sw2); g_free(response); response = NULL; memset(&error, 0, sizeof(error)); error.type = OFONO_ERROR_TYPE_SIM; error.error = (sw1 << 8) | sw2; cb(&error, -1, -1, -1, NULL, EF_STATUS_INVALIDATED, cbd->data); return; } if (len < 0) goto error; if (response[0] == 0x62) { ok = sim_parse_3g_get_response(response, len, &flen, &rlen, &str, access, NULL); file_status = EF_STATUS_VALID; } else ok = sim_parse_2g_get_response(response, len, &flen, &rlen, &str, access, &file_status); g_free(response); if (!ok) goto error; CALLBACK_WITH_SUCCESS(cb, flen, str, rlen, access, file_status, cbd->data); return; error: g_free(response); CALLBACK_WITH_FAILURE(cb, -1, -1, -1, NULL, EF_STATUS_INVALIDATED, cbd->data); }
static void ril_file_info_cb(struct ril_msg *message, gpointer user_data) { struct cb_data *cbd = user_data; ofono_sim_file_info_cb_t cb = cbd->cb; struct sim_data *sd = cbd->user; struct ofono_error error; gboolean ok = FALSE; int sw1, sw2; int flen = 0, rlen = 0, str = 0; guchar access[3] = { 0x00, 0x00, 0x00 }; guchar file_status = EF_STATUS_VALID; struct reply_sim_io *reply = NULL; /* Error, and no data */ if (message->error != RIL_E_SUCCESS && message->buf_len == 0) { ofono_error("%s: Reply failure: %s", __func__, ril_error_to_string(message->error)); decode_ril_error(&error, "FAIL"); goto error; } /* * The reply can have event data even when message->error is not zero * in mako. */ reply = g_ril_reply_parse_sim_io(sd->ril, message); if (reply == NULL) { decode_ril_error(&error, "FAIL"); goto error; } sw1 = reply->sw1; sw2 = reply->sw2; /* * SIM app file not found || USIM app file not found * See 3gpp TS 51.011, 9.4.4, and ETSI TS 102 221, 10.2.1.5.3 * This can happen with result SUCCESS (maguro) or GENERIC_FAILURE * (mako) */ if ((sw1 == 0x94 && sw2 == 0x04) || (sw1 == 0x6A && sw2 == 0x82)) { DBG("File not found. Error %s", ril_error_to_string(message->error)); decode_ril_error(&error, "FAIL"); goto error; } if (message->error == RIL_E_SUCCESS) { decode_ril_error(&error, "OK"); } else { ofono_error("%s: Reply failure: %s, %02x, %02x", __func__, ril_error_to_string(message->error), sw1, sw2); decode_ril_error(&error, "FAIL"); goto error; } if ((sw1 != 0x90 && sw1 != 0x91 && sw1 != 0x92 && sw1 != 0x9f) || (sw1 == 0x90 && sw2 != 0x00)) { ofono_error("Error reply, invalid values: sw1: %02x sw2: %02x", sw1, sw2); /* TODO: fix decode_ril_error to take type & error */ error.type = OFONO_ERROR_TYPE_SIM; error.error = (sw1 << 8) | sw2; goto error; } if (reply->hex_len) { if (reply->hex_response[0] == 0x62) { ok = sim_parse_3g_get_response(reply->hex_response, reply->hex_len, &flen, &rlen, &str, access, NULL); } else { ok = sim_parse_2g_get_response(reply->hex_response, reply->hex_len, &flen, &rlen, &str, access, &file_status); } } if (!ok) { ofono_error("%s: parse response failed", __func__); decode_ril_error(&error, "FAIL"); goto error; } cb(&error, flen, str, rlen, access, file_status, cbd->data); g_ril_reply_free_sim_io(reply); return; error: g_ril_reply_free_sim_io(reply); cb(&error, -1, -1, -1, NULL, EF_STATUS_INVALIDATED, cbd->data); }
static void ril_file_info_cb(struct ril_msg *message, gpointer user_data) { struct cb_data *cbd = user_data; ofono_sim_file_info_cb_t cb = cbd->cb; struct sim_data *sd = cbd->user; struct ofono_error error; gboolean ok = FALSE; int sw1 = 0, sw2 = 0, response_len = 0; int flen = 0, rlen = 0, str = 0; guchar *response = NULL; guchar access[3] = { 0x00, 0x00, 0x00 }; guchar file_status = EF_STATUS_VALID; DBG(""); /* In case sim card has been removed prior to this callback has been * called we must not call the core call back method as otherwise the * core will crash. */ if (sd->removed == TRUE) { ofono_error("RIL_CARDSTATE_ABSENT"); return; } if (message->error == RIL_E_SUCCESS) { decode_ril_error(&error, "OK"); } else { DBG("Reply failure: %s", ril_error_to_string(message->error)); decode_ril_error(&error, "FAIL"); goto error; } if ((response = (guchar *) ril_util_parse_sim_io_rsp(sd->ril, message, &sw1, &sw2, &response_len)) == NULL) { ofono_error("Can't parse SIM IO response from RILD"); decode_ril_error(&error, "FAIL"); goto error; } if ((sw1 != 0x90 && sw1 != 0x91 && sw1 != 0x92 && sw1 != 0x9f) || (sw1 == 0x90 && sw2 != 0x00)) { ofono_error("invalid values: sw1: %02x sw2: %02x", sw1, sw2); memset(&error, 0, sizeof(error)); /* TODO: fix decode_ril_error to take type & error */ error.type = OFONO_ERROR_TYPE_SIM; error.error = (sw1 << 8) | sw2; goto error; } if (response_len) { if (response[0] == 0x62) { ok = sim_parse_3g_get_response( response, response_len, &flen, &rlen, &str, access, NULL); } else ok = sim_parse_2g_get_response( response, response_len, &flen, &rlen, &str, access, &file_status); } if (!ok) { ofono_error("parse response failed"); decode_ril_error(&error, "FAIL"); goto error; } cb(&error, flen, str, rlen, access, file_status, cbd->data); g_free(response); return; error: cb(&error, -1, -1, -1, NULL, EF_STATUS_INVALIDATED, cbd->data); g_free(response); }
static void test_ber_tlv_builder_3g_status(void) { unsigned char buf[512]; struct ber_tlv_builder top_builder, nested_builder; unsigned char *response; unsigned int len; int flen, rlen, str; unsigned char access[3]; unsigned short efid; /* Build a binary EF status response */ g_assert(ber_tlv_builder_init(&top_builder, buf, sizeof(buf))); g_assert(ber_tlv_builder_next(&top_builder, BER_TLV_DATA_TYPE_APPLICATION, BER_TLV_DATA_ENCODING_TYPE_CONSTRUCTED, 0x02)); g_assert(ber_tlv_builder_recurse(&top_builder, &nested_builder)); g_assert(ber_tlv_builder_next(&nested_builder, BER_TLV_DATA_TYPE_CONTEXT_SPECIFIC, BER_TLV_DATA_ENCODING_TYPE_PRIMITIVE, 0x02)); g_assert(ber_tlv_builder_set_length(&nested_builder, 2)); ber_tlv_builder_get_data(&nested_builder)[0] = 0x41; ber_tlv_builder_get_data(&nested_builder)[1] = 0x21; g_assert(ber_tlv_builder_next(&nested_builder, BER_TLV_DATA_TYPE_CONTEXT_SPECIFIC, BER_TLV_DATA_ENCODING_TYPE_PRIMITIVE, 0x03)); g_assert(ber_tlv_builder_set_length(&nested_builder, 2)); ber_tlv_builder_get_data(&nested_builder)[0] = 0x2f; ber_tlv_builder_get_data(&nested_builder)[1] = 0x05; g_assert(ber_tlv_builder_next(&nested_builder, BER_TLV_DATA_TYPE_CONTEXT_SPECIFIC, BER_TLV_DATA_ENCODING_TYPE_PRIMITIVE, 0x0a)); g_assert(ber_tlv_builder_set_length(&nested_builder, 1)); ber_tlv_builder_get_data(&nested_builder)[0] = 0x05; g_assert(ber_tlv_builder_next(&nested_builder, BER_TLV_DATA_TYPE_CONTEXT_SPECIFIC, BER_TLV_DATA_ENCODING_TYPE_PRIMITIVE, 0x0b)); g_assert(ber_tlv_builder_set_length(&nested_builder, 3)); ber_tlv_builder_get_data(&nested_builder)[0] = 0x2f; ber_tlv_builder_get_data(&nested_builder)[1] = 0x06; ber_tlv_builder_get_data(&nested_builder)[2] = 0x0f; g_assert(ber_tlv_builder_next(&nested_builder, BER_TLV_DATA_TYPE_CONTEXT_SPECIFIC, BER_TLV_DATA_ENCODING_TYPE_PRIMITIVE, 0x00)); g_assert(ber_tlv_builder_set_length(&nested_builder, 2)); ber_tlv_builder_get_data(&nested_builder)[0] = 0x00; ber_tlv_builder_get_data(&nested_builder)[1] = 0x0a; g_assert(ber_tlv_builder_next(&nested_builder, BER_TLV_DATA_TYPE_CONTEXT_SPECIFIC, BER_TLV_DATA_ENCODING_TYPE_PRIMITIVE, 0x08)); g_assert(ber_tlv_builder_set_length(&nested_builder, 1)); ber_tlv_builder_get_data(&nested_builder)[0] = 0x28; ber_tlv_builder_optimize(&nested_builder, NULL, NULL); ber_tlv_builder_optimize(&top_builder, &response, &len); sim_parse_3g_get_response(response, len, &flen, &rlen, &str, access, &efid); g_assert(flen == 10); g_assert(rlen == 0); g_assert(str == 0); g_assert(access[0] == 0x01); g_assert(access[1] == 0xff); g_assert(access[2] == 0x44); g_assert(efid == 0x2F05); /* Build a record-based EF status response */ g_assert(ber_tlv_builder_init(&top_builder, buf, sizeof(buf))); g_assert(ber_tlv_builder_next(&top_builder, BER_TLV_DATA_TYPE_APPLICATION, BER_TLV_DATA_ENCODING_TYPE_CONSTRUCTED, 0x02)); g_assert(ber_tlv_builder_recurse(&top_builder, &nested_builder)); g_assert(ber_tlv_builder_next(&nested_builder, BER_TLV_DATA_TYPE_CONTEXT_SPECIFIC, BER_TLV_DATA_ENCODING_TYPE_PRIMITIVE, 0x02)); g_assert(ber_tlv_builder_set_length(&nested_builder, 5)); ber_tlv_builder_get_data(&nested_builder)[0] = 0x42; ber_tlv_builder_get_data(&nested_builder)[1] = 0x21; ber_tlv_builder_get_data(&nested_builder)[2] = 0x00; ber_tlv_builder_get_data(&nested_builder)[3] = 0x20; ber_tlv_builder_get_data(&nested_builder)[4] = 0x04; g_assert(ber_tlv_builder_next(&nested_builder, BER_TLV_DATA_TYPE_CONTEXT_SPECIFIC, BER_TLV_DATA_ENCODING_TYPE_PRIMITIVE, 0x03)); g_assert(ber_tlv_builder_set_length(&nested_builder, 2)); ber_tlv_builder_get_data(&nested_builder)[0] = 0x6f; ber_tlv_builder_get_data(&nested_builder)[1] = 0x40; g_assert(ber_tlv_builder_next(&nested_builder, BER_TLV_DATA_TYPE_CONTEXT_SPECIFIC, BER_TLV_DATA_ENCODING_TYPE_PRIMITIVE, 0x0a)); g_assert(ber_tlv_builder_set_length(&nested_builder, 1)); ber_tlv_builder_get_data(&nested_builder)[0] = 0x05; g_assert(ber_tlv_builder_next(&nested_builder, BER_TLV_DATA_TYPE_CONTEXT_SPECIFIC, BER_TLV_DATA_ENCODING_TYPE_PRIMITIVE, 0x0b)); g_assert(ber_tlv_builder_set_length(&nested_builder, 3)); ber_tlv_builder_get_data(&nested_builder)[0] = 0x2f; ber_tlv_builder_get_data(&nested_builder)[1] = 0x06; ber_tlv_builder_get_data(&nested_builder)[2] = 0x07; g_assert(ber_tlv_builder_next(&nested_builder, BER_TLV_DATA_TYPE_CONTEXT_SPECIFIC, BER_TLV_DATA_ENCODING_TYPE_PRIMITIVE, 0x00)); g_assert(ber_tlv_builder_set_length(&nested_builder, 2)); ber_tlv_builder_get_data(&nested_builder)[0] = 0x00; ber_tlv_builder_get_data(&nested_builder)[1] = 0x80; g_assert(ber_tlv_builder_next(&nested_builder, BER_TLV_DATA_TYPE_CONTEXT_SPECIFIC, BER_TLV_DATA_ENCODING_TYPE_PRIMITIVE, 0x08)); ber_tlv_builder_optimize(&nested_builder, NULL, NULL); ber_tlv_builder_optimize(&top_builder, &response, &len); sim_parse_3g_get_response(response, len, &flen, &rlen, &str, access, &efid); g_assert(flen == 0x80); g_assert(rlen == 0x20); g_assert(str == 1); g_assert(access[0] == 0x11); g_assert(access[1] == 0xff); g_assert(access[2] == 0x44); g_assert(efid == 0x6F40); }
static void at_crsm_info_cb(gboolean ok, GAtResult *result, gpointer user_data) { struct cb_data *cbd = user_data; GAtResultIter iter; ofono_sim_file_info_cb_t cb = cbd->cb; struct ofono_error error; const guint8 *response; gint sw1, sw2, len; int flen, rlen; int str; unsigned char access[3]; unsigned char file_status; decode_at_error(&error, g_at_result_final_response(result)); if (!ok) { cb(&error, -1, -1, -1, NULL, EF_STATUS_INVALIDATED, cbd->data); return; } g_at_result_iter_init(&iter, result); if (!g_at_result_iter_next(&iter, "+CRSM:")) goto error; g_at_result_iter_next_number(&iter, &sw1); g_at_result_iter_next_number(&iter, &sw2); if (!g_at_result_iter_next_hexstring(&iter, &response, &len) || (sw1 != 0x90 && sw1 != 0x91 && sw1 != 0x92) || (sw1 == 0x90 && sw2 != 0x00)) { memset(&error, 0, sizeof(error)); error.type = OFONO_ERROR_TYPE_SIM; error.error = (sw1 << 8) | sw2; cb(&error, -1, -1, -1, NULL, EF_STATUS_INVALIDATED, cbd->data); return; } DBG("crsm_info_cb: %02x, %02x, %i", sw1, sw2, len); if (response[0] == 0x62) { ok = sim_parse_3g_get_response(response, len, &flen, &rlen, &str, access, NULL); file_status = EF_STATUS_VALID; } else ok = sim_parse_2g_get_response(response, len, &flen, &rlen, &str, access, &file_status); if (!ok) goto error; cb(&error, flen, str, rlen, access, file_status, cbd->data); return; error: CALLBACK_WITH_FAILURE(cb, -1, -1, -1, NULL, EF_STATUS_INVALIDATED, cbd->data); }