feat: atr in euicc info activity #126
9 changed files with 41 additions and 2 deletions
|
@ -30,6 +30,8 @@ class LocalProfileAssistantWrapper(orig: LocalProfileAssistant) :
|
||||||
override val euiccInfo2: EuiccInfo2?
|
override val euiccInfo2: EuiccInfo2?
|
||||||
get() = lpa.euiccInfo2
|
get() = lpa.euiccInfo2
|
||||||
|
|
||||||
|
override fun readATR() = lpa.readATR()
|
||||||
|
|
||||||
override fun setEs10xMss(mss: Byte) = lpa.setEs10xMss(mss)
|
override fun setEs10xMss(mss: Byte) = lpa.setEs10xMss(mss)
|
||||||
|
|
||||||
override fun enableProfile(iccid: String, refresh: Boolean): Boolean =
|
override fun enableProfile(iccid: String, refresh: Boolean): Boolean =
|
||||||
|
|
|
@ -26,6 +26,9 @@ class OmapiApduInterface(
|
||||||
override val valid: Boolean
|
override val valid: Boolean
|
||||||
get() = service.isConnected && (this::session.isInitialized && !session.isClosed)
|
get() = service.isConnected && (this::session.isInitialized && !session.isClosed)
|
||||||
|
|
||||||
|
override fun readATR() =
|
||||||
|
session.atr?.clone() ?: throw IllegalStateException("atr unavailable")
|
||||||
|
|
||||||
override fun connect() {
|
override fun connect() {
|
||||||
session = service.getUiccReaderCompat(port.logicalSlotIndex + 1).openSession()
|
session = service.getUiccReaderCompat(port.logicalSlotIndex + 1).openSession()
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,9 @@ class UsbApduInterface(
|
||||||
transceiver = UsbCcidTransceiver(conn, bulkIn, bulkOut, ccidDescription, verboseLoggingFlow)
|
transceiver = UsbCcidTransceiver(conn, bulkIn, bulkOut, ccidDescription, verboseLoggingFlow)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
transceiver.iccPowerOn()
|
// 6.1.1.1 PC_to_RDR_IccPowerOn (Page 20 of 40)
|
||||||
|
// https://www.usb.org/sites/default/files/DWG_Smart-Card_USB-ICC_ICCD_rev10.pdf
|
||||||
|
atr = transceiver.iccPowerOn().data
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
throw e
|
throw e
|
||||||
|
@ -99,6 +101,11 @@ class UsbApduInterface(
|
||||||
override val valid: Boolean
|
override val valid: Boolean
|
||||||
get() = channelId != -1
|
get() = channelId != -1
|
||||||
|
|
||||||
|
private var atr: ByteArray? = null
|
||||||
|
|
||||||
|
override fun readATR() =
|
||||||
|
atr?.clone() ?: throw IllegalStateException("atr unavailable")
|
||||||
|
|
||||||
private fun isSuccessResponse(resp: ByteArray): Boolean =
|
private fun isSuccessResponse(resp: ByteArray): Boolean =
|
||||||
resp.size >= 2 && resp[resp.size - 2] == 0x90.toByte() && resp[resp.size - 1] == 0x00.toByte()
|
resp.size >= 2 && resp[resp.size - 2] == 0x90.toByte() && resp[resp.size - 1] == 0x00.toByte()
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ import im.angry.openeuicc.common.R
|
||||||
import im.angry.openeuicc.core.EuiccChannel
|
import im.angry.openeuicc.core.EuiccChannel
|
||||||
import im.angry.openeuicc.core.EuiccChannelManager
|
import im.angry.openeuicc.core.EuiccChannelManager
|
||||||
import im.angry.openeuicc.util.*
|
import im.angry.openeuicc.util.*
|
||||||
|
import kotlinx.coroutines.flow.first
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import net.typeblog.lpac_jni.impl.PKID_GSMA_LIVE_CI
|
import net.typeblog.lpac_jni.impl.PKID_GSMA_LIVE_CI
|
||||||
import net.typeblog.lpac_jni.impl.PKID_GSMA_TEST_CI
|
import net.typeblog.lpac_jni.impl.PKID_GSMA_TEST_CI
|
||||||
|
@ -41,7 +42,7 @@ class EuiccInfoActivity : BaseEuiccAccessActivity(), OpenEuiccContextMarker {
|
||||||
@StringRes
|
@StringRes
|
||||||
val titleResId: Int,
|
val titleResId: Int,
|
||||||
val content: String?,
|
val content: String?,
|
||||||
val copiedToastResId: Int? = null
|
val copiedToastResId: Int? = null,
|
||||||
)
|
)
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
@ -133,6 +134,17 @@ class EuiccInfoActivity : BaseEuiccAccessActivity(), OpenEuiccContextMarker {
|
||||||
}
|
}
|
||||||
add(Item(R.string.euicc_info_ci_type, getString(resId)))
|
add(Item(R.string.euicc_info_ci_type, getString(resId)))
|
||||||
}
|
}
|
||||||
|
add(
|
||||||
|
Item(
|
||||||
|
R.string.euicc_info_atr,
|
||||||
|
try {
|
||||||
|
channel.lpa.readATR().encodeHex()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
getString(R.string.euicc_info_atr_unavailable)
|
||||||
|
},
|
||||||
|
copiedToastResId = R.string.toast_atr_copied,
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun formatByBoolean(b: Boolean, res: Pair<Int, Int>): String =
|
private fun formatByBoolean(b: Boolean, res: Pair<Int, Int>): String =
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
<string name="toast_profile_delete_confirm_text_mismatched">Confirmation string mismatch</string>
|
<string name="toast_profile_delete_confirm_text_mismatched">Confirmation string mismatch</string>
|
||||||
<string name="toast_iccid_copied">ICCID copied to clipboard</string>
|
<string name="toast_iccid_copied">ICCID copied to clipboard</string>
|
||||||
<string name="toast_eid_copied">EID copied to clipboard</string>
|
<string name="toast_eid_copied">EID copied to clipboard</string>
|
||||||
|
<string name="toast_atr_copied">ATR copied to clipboard</string>
|
||||||
|
|
||||||
<string name="usb_permission">Grant USB permission</string>
|
<string name="usb_permission">Grant USB permission</string>
|
||||||
<string name="usb_permission_needed">Permission is needed to access the USB smart card reader.</string>
|
<string name="usb_permission_needed">Permission is needed to access the USB smart card reader.</string>
|
||||||
|
@ -130,6 +131,8 @@
|
||||||
<string name="euicc_info_ci_gsma_live">GSMA Live CI</string>
|
<string name="euicc_info_ci_gsma_live">GSMA Live CI</string>
|
||||||
<string name="euicc_info_ci_gsma_test">GSMA Test CI</string>
|
<string name="euicc_info_ci_gsma_test">GSMA Test CI</string>
|
||||||
<string name="euicc_info_ci_unknown">Unknown eSIM CI</string>
|
<string name="euicc_info_ci_unknown">Unknown eSIM CI</string>
|
||||||
|
<string name="euicc_info_atr">ATR (Answer To Reset)</string>
|
||||||
|
<string name="euicc_info_atr_unavailable">ATR unavailable</string>
|
||||||
|
|
||||||
<string name="yes">Yes</string>
|
<string name="yes">Yes</string>
|
||||||
<string name="no">No</string>
|
<string name="no">No</string>
|
||||||
|
|
|
@ -25,6 +25,9 @@ class TelephonyManagerApduInterface(
|
||||||
// just that transactions might return errors or nonsense
|
// just that transactions might return errors or nonsense
|
||||||
get() = lastChannel != -1
|
get() = lastChannel != -1
|
||||||
|
|
||||||
|
override fun readATR() =
|
||||||
|
throw IllegalStateException("atr unavailable")
|
||||||
|
|
||||||
override fun connect() {
|
override fun connect() {
|
||||||
// Do nothing
|
// Do nothing
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,4 +16,9 @@ interface ApduInterface {
|
||||||
* callers should further check with the LPA to fully determine the validity of a channel
|
* callers should further check with the LPA to fully determine the validity of a channel
|
||||||
*/
|
*/
|
||||||
val valid: Boolean
|
val valid: Boolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read Answer To Reset
|
||||||
|
*/
|
||||||
|
fun readATR(): ByteArray
|
||||||
}
|
}
|
|
@ -23,6 +23,8 @@ interface LocalProfileAssistant {
|
||||||
// Extended EuiccInfo for use with LUIs, containing information such as firmware version
|
// Extended EuiccInfo for use with LUIs, containing information such as firmware version
|
||||||
val euiccInfo2: EuiccInfo2?
|
val euiccInfo2: EuiccInfo2?
|
||||||
|
|
||||||
|
fun readATR(): ByteArray
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the max segment size (mss) for all es10x commands. This can help with removable
|
* Set the max segment size (mss) for all es10x commands. This can help with removable
|
||||||
* eUICCs that may run at a baud rate too fast for the modem.
|
* eUICCs that may run at a baud rate too fast for the modem.
|
||||||
|
|
|
@ -187,6 +187,8 @@ class LocalProfileAssistantImpl(
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun readATR() = apduInterface.readATR()
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
override fun enableProfile(iccid: String, refresh: Boolean): Boolean =
|
override fun enableProfile(iccid: String, refresh: Boolean): Boolean =
|
||||||
LpacJni.es10cEnableProfile(contextHandle, iccid, refresh) == 0
|
LpacJni.es10cEnableProfile(contextHandle, iccid, refresh) == 0
|
||||||
|
|
Loading…
Add table
Reference in a new issue