|
@@ -9,6 +9,7 @@ import kotlinx.coroutines.flow.Flow
|
|
|
import kotlinx.coroutines.flow.first
|
|
import kotlinx.coroutines.flow.first
|
|
|
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,
|
|
@@ -20,12 +21,8 @@ class OmapiApduInterface(
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private lateinit var session: Session
|
|
private lateinit var session: Session
|
|
|
- private val channels = arrayOf<Channel?>(
|
|
|
|
|
- null,
|
|
|
|
|
- null,
|
|
|
|
|
- null,
|
|
|
|
|
- null,
|
|
|
|
|
- )
|
|
|
|
|
|
|
+ private val index = AtomicInteger(0)
|
|
|
|
|
+ private val channels = mutableMapOf<Int, Channel>()
|
|
|
|
|
|
|
|
override val valid: Boolean
|
|
override val valid: Boolean
|
|
|
get() = service.isConnected && (this::session.isInitialized && !session.isClosed)
|
|
get() = service.isConnected && (this::session.isInitialized && !session.isClosed)
|
|
@@ -44,21 +41,20 @@ 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)
|
|
|
|
|
- check(index != -1) { "No free logical channel slots" }
|
|
|
|
|
- synchronized(channels) { channels[index] = channel }
|
|
|
|
|
- return index
|
|
|
|
|
|
|
+ val handle = index.incrementAndGet()
|
|
|
|
|
+ synchronized(channels) { channels[handle] = channel }
|
|
|
|
|
+ return handle
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
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" }
|
|
|
if (channel.isOpen) channel.close()
|
|
if (channel.isOpen) channel.close()
|
|
|
- synchronized(channels) { channels[handle] = null }
|
|
|
|
|
|
|
+ synchronized(channels) { channels.remove(handle) }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
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() }) {
|