forked from PeterCxy/OpenEUICC
Compare commits
No commits in common. "9ddfd6203082cc4cb71175500a5161969cf3a2aa" and "fd4023194a1e387cfe4f76ae19f4adff6753de4a" have entirely different histories.
9ddfd62030
...
fd4023194a
8 changed files with 26 additions and 37 deletions
|
@ -1,7 +1,6 @@
|
||||||
package im.angry.openeuicc.core
|
package im.angry.openeuicc.core
|
||||||
|
|
||||||
import im.angry.openeuicc.util.*
|
import im.angry.openeuicc.util.*
|
||||||
import net.typeblog.lpac_jni.ApduInterface
|
|
||||||
import net.typeblog.lpac_jni.LocalProfileAssistant
|
import net.typeblog.lpac_jni.LocalProfileAssistant
|
||||||
|
|
||||||
interface EuiccChannel {
|
interface EuiccChannel {
|
||||||
|
@ -29,10 +28,5 @@ interface EuiccChannel {
|
||||||
*/
|
*/
|
||||||
val intrinsicChannelName: String?
|
val intrinsicChannelName: String?
|
||||||
|
|
||||||
/**
|
|
||||||
* The underlying APDU interface for this channel
|
|
||||||
*/
|
|
||||||
val apduInterface: ApduInterface
|
|
||||||
|
|
||||||
fun close()
|
fun close()
|
||||||
}
|
}
|
|
@ -1,7 +1,6 @@
|
||||||
package im.angry.openeuicc.core
|
package im.angry.openeuicc.core
|
||||||
|
|
||||||
import im.angry.openeuicc.util.UiccPortInfoCompat
|
import im.angry.openeuicc.util.*
|
||||||
import im.angry.openeuicc.util.decodeHex
|
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import net.typeblog.lpac_jni.ApduInterface
|
import net.typeblog.lpac_jni.ApduInterface
|
||||||
import net.typeblog.lpac_jni.LocalProfileAssistant
|
import net.typeblog.lpac_jni.LocalProfileAssistant
|
||||||
|
@ -12,7 +11,7 @@ class EuiccChannelImpl(
|
||||||
override val type: String,
|
override val type: String,
|
||||||
override val port: UiccPortInfoCompat,
|
override val port: UiccPortInfoCompat,
|
||||||
override val intrinsicChannelName: String?,
|
override val intrinsicChannelName: String?,
|
||||||
override val apduInterface: ApduInterface,
|
private val apduInterface: ApduInterface,
|
||||||
verboseLoggingFlow: Flow<Boolean>,
|
verboseLoggingFlow: Flow<Boolean>,
|
||||||
ignoreTLSCertificateFlow: Flow<Boolean>
|
ignoreTLSCertificateFlow: Flow<Boolean>
|
||||||
) : EuiccChannel {
|
) : EuiccChannel {
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package im.angry.openeuicc.core
|
package im.angry.openeuicc.core
|
||||||
|
|
||||||
import im.angry.openeuicc.util.*
|
import im.angry.openeuicc.util.*
|
||||||
import net.typeblog.lpac_jni.ApduInterface
|
|
||||||
import net.typeblog.lpac_jni.LocalProfileAssistant
|
import net.typeblog.lpac_jni.LocalProfileAssistant
|
||||||
|
|
||||||
class EuiccChannelWrapper(orig: EuiccChannel) : EuiccChannel {
|
class EuiccChannelWrapper(orig: EuiccChannel) : EuiccChannel {
|
||||||
|
@ -34,8 +33,6 @@ class EuiccChannelWrapper(orig: EuiccChannel) : EuiccChannel {
|
||||||
get() = channel.valid
|
get() = channel.valid
|
||||||
override val intrinsicChannelName: String?
|
override val intrinsicChannelName: String?
|
||||||
get() = channel.intrinsicChannelName
|
get() = channel.intrinsicChannelName
|
||||||
override val apduInterface: ApduInterface
|
|
||||||
get() = channel.apduInterface
|
|
||||||
override val atr: ByteArray?
|
override val atr: ByteArray?
|
||||||
get() = channel.atr
|
get() = channel.atr
|
||||||
|
|
||||||
|
|
|
@ -7,9 +7,9 @@ import android.util.Log
|
||||||
import im.angry.openeuicc.util.*
|
import im.angry.openeuicc.util.*
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.first
|
import kotlinx.coroutines.flow.first
|
||||||
import kotlinx.coroutines.flow.single
|
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import net.typeblog.lpac_jni.ApduInterface
|
import net.typeblog.lpac_jni.ApduInterface
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger
|
||||||
|
|
||||||
class OmapiApduInterface(
|
class OmapiApduInterface(
|
||||||
private val service: SEService,
|
private val service: SEService,
|
||||||
|
@ -21,12 +21,8 @@ class OmapiApduInterface(
|
||||||
}
|
}
|
||||||
|
|
||||||
private lateinit var session: Session
|
private lateinit var session: Session
|
||||||
private val channels = arrayOf<Channel?>(
|
private val channels = mutableMapOf<Int, Channel>()
|
||||||
null,
|
private val index = AtomicInteger(0)
|
||||||
null,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
)
|
|
||||||
|
|
||||||
override val valid: Boolean
|
override val valid: Boolean
|
||||||
get() = service.isConnected && (this::session.isInitialized && !session.isClosed)
|
get() = service.isConnected && (this::session.isInitialized && !session.isClosed)
|
||||||
|
@ -45,22 +41,23 @@ class OmapiApduInterface(
|
||||||
override fun logicalChannelOpen(aid: ByteArray): Int {
|
override fun logicalChannelOpen(aid: ByteArray): Int {
|
||||||
val channel = session.openLogicalChannel(aid)
|
val channel = session.openLogicalChannel(aid)
|
||||||
check(channel != null) { "Failed to open logical channel (${aid.encodeHex()})" }
|
check(channel != null) { "Failed to open logical channel (${aid.encodeHex()})" }
|
||||||
val index = channels.indexOf(null)
|
val id = index.addAndGet(1)
|
||||||
check(index != -1) { "No free logical channel slots" }
|
channels[id] = channel
|
||||||
synchronized(channels) { channels[index] = channel }
|
return id
|
||||||
return index
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun logicalChannelClose(handle: Int) {
|
override fun logicalChannelClose(handle: Int) {
|
||||||
val channel = channels.getOrNull(handle)
|
val channel = channels[handle]
|
||||||
check(channel != null) { "Invalid logical channel handle $handle" }
|
check(channel != null) { "Invalid logical channel handle $handle" }
|
||||||
|
channels.remove(handle)
|
||||||
if (channel.isOpen) channel.close()
|
if (channel.isOpen) channel.close()
|
||||||
synchronized(channels) { channels[handle] = null }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun transmit(handle: Int, tx: ByteArray): ByteArray {
|
override fun transmit(handle: Int, tx: ByteArray): ByteArray {
|
||||||
val channel = channels.getOrNull(handle)
|
val channel = channels[handle]
|
||||||
check(channel != null) { "Invalid logical channel handle $handle" }
|
check(channel != null) {
|
||||||
|
"Invalid logical channel handle $handle"
|
||||||
|
}
|
||||||
|
|
||||||
if (runBlocking { verboseLoggingFlow.first() }) {
|
if (runBlocking { verboseLoggingFlow.first() }) {
|
||||||
Log.d(TAG, "OMAPI APDU: ${tx.encodeHex()}")
|
Log.d(TAG, "OMAPI APDU: ${tx.encodeHex()}")
|
||||||
|
|
|
@ -17,12 +17,18 @@ interface ApduInterface {
|
||||||
*/
|
*/
|
||||||
val valid: Boolean
|
val valid: Boolean
|
||||||
|
|
||||||
fun <T> withLogicalChannel(aid: ByteArray, callback: ((ByteArray) -> ByteArray) -> T): T {
|
fun <T> openChannel(aid: ByteArray, callback: (TransmitProvider) -> T): T {
|
||||||
val handle = logicalChannelOpen(aid)
|
val handle = logicalChannelOpen(aid)
|
||||||
return try {
|
return try {
|
||||||
callback { tx -> transmit(handle, tx) }
|
callback(object : TransmitProvider {
|
||||||
|
override fun transmit(tx: ByteArray) = transmit(handle, tx)
|
||||||
|
})
|
||||||
} finally {
|
} finally {
|
||||||
logicalChannelClose(handle)
|
logicalChannelClose(handle)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface TransmitProvider {
|
||||||
|
fun transmit(tx: ByteArray): ByteArray
|
||||||
|
}
|
|
@ -53,23 +53,20 @@ apdu_interface_logical_channel_open(struct euicc_ctx *ctx, const uint8_t *aid, u
|
||||||
jint ret = (*env)->CallIntMethod(env, LPAC_JNI_CTX(ctx)->apdu_interface,
|
jint ret = (*env)->CallIntMethod(env, LPAC_JNI_CTX(ctx)->apdu_interface,
|
||||||
method_apdu_logical_channel_open, jbarr);
|
method_apdu_logical_channel_open, jbarr);
|
||||||
LPAC_JNI_EXCEPTION_RETURN;
|
LPAC_JNI_EXCEPTION_RETURN;
|
||||||
LPAC_JNI_CTX(ctx)->logical_channel_id = ret;
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void apdu_interface_logical_channel_close(struct euicc_ctx *ctx,
|
static void apdu_interface_logical_channel_close(struct euicc_ctx *ctx, uint8_t channel) {
|
||||||
__attribute__((unused)) uint8_t channel) {
|
|
||||||
LPAC_JNI_SETUP_ENV;
|
LPAC_JNI_SETUP_ENV;
|
||||||
jint logical_channel_id = LPAC_JNI_CTX(ctx)->logical_channel_id;
|
|
||||||
(*env)->CallVoidMethod(env, LPAC_JNI_CTX(ctx)->apdu_interface,
|
(*env)->CallVoidMethod(env, LPAC_JNI_CTX(ctx)->apdu_interface,
|
||||||
method_apdu_logical_channel_close, logical_channel_id);
|
method_apdu_logical_channel_close, channel);
|
||||||
(*env)->ExceptionClear(env);
|
(*env)->ExceptionClear(env);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
apdu_interface_transmit(struct euicc_ctx *ctx, uint8_t **rx, uint32_t *rx_len, const uint8_t *tx,
|
apdu_interface_transmit(struct euicc_ctx *ctx, uint8_t **rx, uint32_t *rx_len, const uint8_t *tx,
|
||||||
uint32_t tx_len) {
|
uint32_t tx_len) {
|
||||||
const int logic_channel = LPAC_JNI_CTX(ctx)->logical_channel_id;
|
const int logic_channel = ctx->apdu._internal.logic_channel;
|
||||||
LPAC_JNI_SETUP_ENV;
|
LPAC_JNI_SETUP_ENV;
|
||||||
jbyteArray txArr = (*env)->NewByteArray(env, tx_len);
|
jbyteArray txArr = (*env)->NewByteArray(env, tx_len);
|
||||||
(*env)->SetByteArrayRegion(env, txArr, 0, tx_len, (const jbyte *) tx);
|
(*env)->SetByteArrayRegion(env, txArr, 0, tx_len, (const jbyte *) tx);
|
||||||
|
|
|
@ -28,7 +28,7 @@ jint JNI_OnLoad(JavaVM *vm, void *reserved) {
|
||||||
string_constructor = (*env)->GetMethodID(env, string_class, "<init>",
|
string_constructor = (*env)->GetMethodID(env, string_class, "<init>",
|
||||||
"([BLjava/lang/String;)V");
|
"([BLjava/lang/String;)V");
|
||||||
|
|
||||||
const jchar _unused[1];
|
const char _unused[1];
|
||||||
empty_string = (*env)->NewString(env, _unused, 0);
|
empty_string = (*env)->NewString(env, _unused, 0);
|
||||||
empty_string = (*env)->NewGlobalRef(env, empty_string);
|
empty_string = (*env)->NewGlobalRef(env, empty_string);
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,6 @@ _Static_assert(sizeof(void *) <= sizeof(jlong),
|
||||||
"jlong must be big enough to hold a platform raw pointer");
|
"jlong must be big enough to hold a platform raw pointer");
|
||||||
|
|
||||||
struct lpac_jni_ctx {
|
struct lpac_jni_ctx {
|
||||||
jint logical_channel_id;
|
|
||||||
jobject apdu_interface;
|
jobject apdu_interface;
|
||||||
jobject http_interface;
|
jobject http_interface;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Reference in a new issue