ccfile in xml
This commit is contained in:
32
app/src/main/java/fr/ar2000/ndefemulator/CCFile.kt
Normal file
32
app/src/main/java/fr/ar2000/ndefemulator/CCFile.kt
Normal file
@@ -0,0 +1,32 @@
|
||||
package fr.ar2000.ndefemulator
|
||||
|
||||
import android.util.Log
|
||||
import java.util.LinkedList
|
||||
|
||||
data class CCFile(var cclen: Int = 0,var t4tVno: Int = 0,var mle: Int = 0,var mlc: Int = 0, var tlv: ByteArray = ByteArray(1)) {
|
||||
fun toByteArray():ByteArray {
|
||||
val arr = LinkedList<Byte>()
|
||||
cclen.toByteArray(2).forEach { arr.add(it) }
|
||||
t4tVno.toByteArray(1).forEach { arr.add(it) }
|
||||
mle.toByteArray(2).forEach { arr.add(it) }
|
||||
mlc.toByteArray(2).forEach { arr.add(it) }
|
||||
tlv.forEach { arr.add(it) }
|
||||
if(arr.size != cclen) {
|
||||
Log.w("CCFile.kt","Incoherent CCLEN")
|
||||
}
|
||||
return arr.toByteArray()
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalStdlibApi::class)
|
||||
private fun Int.toByteArray(len: Int=1):ByteArray {
|
||||
var str = toHexString(HexFormat.UpperCase).drop(2)
|
||||
str = str.padStart(len*2,'0').takeLast(len*2)
|
||||
val res = ByteArray(len)
|
||||
var i = 0
|
||||
str.chunked(2).forEach {
|
||||
res[i] = Integer.decode("0x$it").toByte()
|
||||
i++
|
||||
}
|
||||
return res
|
||||
}
|
@@ -6,13 +6,13 @@ import android.nfc.NdefRecord
|
||||
import android.nfc.cardemulation.HostApduService
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import org.xmlpull.v1.XmlPullParser
|
||||
import java.io.UnsupportedEncodingException
|
||||
import java.math.BigInteger
|
||||
import java.util.*
|
||||
import kotlin.collections.HashMap
|
||||
import kotlin.collections.LinkedHashMap
|
||||
|
||||
/**
|
||||
* Created by Qifan on 05/12/2018.
|
||||
*/
|
||||
|
||||
class MyHostApduService : HostApduService() {
|
||||
|
||||
@@ -64,7 +64,7 @@ class MyHostApduService : HostApduService() {
|
||||
0x04.toByte(), // T field of the NDEF File Control TLV
|
||||
0x06.toByte(), // L field of the NDEF File Control TLV
|
||||
0xE1.toByte(), 0x04.toByte(), // File Identifier of NDEF file
|
||||
0xFF.toByte(), 0xFE.toByte(), // Maximum NDEF file size of 65534 bytes
|
||||
0x08.toByte(), 0x00.toByte(), // Maximum NDEF file size of 65534 bytes
|
||||
0x00.toByte(), // Read access without any security
|
||||
0xFF.toByte(), // Write access without any security
|
||||
0x90.toByte(), 0x00.toByte(), // A_OKAY
|
||||
@@ -135,6 +135,17 @@ class MyHostApduService : HostApduService() {
|
||||
// in the NFC Forum specification
|
||||
//
|
||||
Log.i(TAG, "processCommandApdu() | incoming commandApdu: " + commandApdu.toHex())
|
||||
val ApduDissect = HashMap<String,String>()
|
||||
ApduDissect["CLA"] = commandApdu.copyOfRange(0,1).toHex()
|
||||
ApduDissect["INS"] = commandApdu.copyOfRange(1,2).toHex()
|
||||
ApduDissect["P1"] = commandApdu.copyOfRange(2,3).toHex()
|
||||
ApduDissect["P2"] = commandApdu.copyOfRange(3,4).toHex()
|
||||
if(commandApdu.size > 5) {
|
||||
ApduDissect["Lc"] = commandApdu.copyOfRange(4, 5).toHex()
|
||||
ApduDissect["Data"] = commandApdu.copyOfRange(5, 5 + commandApdu[4].toInt()).toHex()
|
||||
}
|
||||
ApduDissect["Le"] = commandApdu.copyOfRange(commandApdu.size-1,commandApdu.size).toHex()
|
||||
Log.i(TAG,ApduDissect.toString())
|
||||
|
||||
//
|
||||
// First command: NDEF Tag Application select (Section 5.5.2 in NFC Forum spec)
|
||||
@@ -157,12 +168,54 @@ class MyHostApduService : HostApduService() {
|
||||
//
|
||||
if (READ_CAPABILITY_CONTAINER.contentEquals(commandApdu) && !READ_CAPABILITY_CONTAINER_CHECK
|
||||
) {
|
||||
Log.i(
|
||||
TAG,
|
||||
"READ_CAPABILITY_CONTAINER triggered. Our Response: " + READ_CAPABILITY_CONTAINER_RESPONSE.toHex(),
|
||||
)
|
||||
Log.i(TAG, "READ_CAPABILITY_CONTAINER triggered. Our Response: " + READ_CAPABILITY_CONTAINER_RESPONSE.toHex(),)
|
||||
READ_CAPABILITY_CONTAINER_CHECK = true
|
||||
return READ_CAPABILITY_CONTAINER_RESPONSE
|
||||
val xrp = resources.getXml(R.xml.ccfile)
|
||||
val parentTag = Stack<String>()
|
||||
var currentTag = ""
|
||||
val ccFile = CCFile()
|
||||
val ccHashMap = LinkedHashMap<String,String>()
|
||||
while(xrp.eventType != XmlPullParser.END_DOCUMENT) {
|
||||
when (xrp.eventType) {
|
||||
XmlPullParser.START_TAG -> {
|
||||
parentTag.push(currentTag)
|
||||
currentTag = xrp.name
|
||||
}
|
||||
XmlPullParser.TEXT -> {
|
||||
ccHashMap[currentTag] = xrp.text
|
||||
}
|
||||
XmlPullParser.END_TAG -> currentTag = parentTag.pop()
|
||||
XmlPullParser.END_DOCUMENT -> {
|
||||
xrp.close()
|
||||
break
|
||||
}
|
||||
}
|
||||
xrp.next()
|
||||
}
|
||||
|
||||
ccFile.cclen = Integer.decode(ccHashMap["CCLEN"] ?: "0x00")
|
||||
ccFile.t4tVno = Integer.decode(ccHashMap["T4T_VNo"] ?: "0x00")
|
||||
ccFile.mle = Integer.decode(ccHashMap["MLe"] ?: "0x00")
|
||||
ccFile.mlc = Integer.decode(ccHashMap["MLc"] ?: "0x00")
|
||||
var tlv = ccHashMap["T"]?.drop(2)?:"00"
|
||||
tlv += ccHashMap["L"]?.drop(2)?:"00"
|
||||
tlv += ccHashMap["NDEF_FILE_ID"]?.drop(2) ?: "0000"
|
||||
tlv += ccHashMap["NDEF_FILE_SIZE"]?.drop(2) ?: "0000"
|
||||
tlv += ccHashMap["ENDEF_File_READ_AC"]?.drop(2) ?: "00"
|
||||
tlv += ccHashMap["ENDEF_File_WRITE_AC"]?.drop(2) ?: "00"
|
||||
val tlvByteList = LinkedList<Byte>()
|
||||
tlv.chunked(2).forEach {
|
||||
tlvByteList.add(Integer.decode("0x$it").toByte())
|
||||
}
|
||||
ccFile.tlv = tlvByteList.toByteArray()
|
||||
|
||||
val t = ccFile.toByteArray()
|
||||
|
||||
//return READ_CAPABILITY_CONTAINER_RESPONSE
|
||||
val msg = ByteArray(t.size+2)
|
||||
t.copyInto(msg)
|
||||
msg[t.size] = 0x90.toByte()
|
||||
return msg
|
||||
}
|
||||
|
||||
//
|
||||
|
4
app/src/main/res/values/const.xml
Normal file
4
app/src/main/res/values/const.xml
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="NDEF_AID">D2760000850101</string>
|
||||
</resources>
|
@@ -3,8 +3,7 @@
|
||||
android:description="@string/servicedesc"
|
||||
android:requireDeviceUnlock="false"
|
||||
android:requireDeviceScreenOn="false">
|
||||
<aid-group android:description="@string/aiddescription"
|
||||
android:category="other">
|
||||
<aid-filter android:name="D2760000850101" />
|
||||
<aid-group android:description="@string/aiddescription" android:category="other">
|
||||
<aid-filter android:name="@string/NDEF_AID" />
|
||||
</aid-group>
|
||||
</host-apdu-service>
|
23
app/src/main/res/xml/ccfile.xml
Normal file
23
app/src/main/res/xml/ccfile.xml
Normal file
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--4.4-->
|
||||
<CapabilityContainerFile>
|
||||
<!--Indicates the size of this CC (including this field).-->
|
||||
<CCLEN>0x000F</CCLEN>
|
||||
<!--Indicates the Mapping Version that is implemented on the T4T (see Section 4.5). Section 4.3.2 defines how the Reader/Writer needs to handle different Mapping Versions.-->
|
||||
<T4T_VNo>0x20</T4T_VNo>
|
||||
<!--Defines the maximum data size that can be read from the T4T using a single READ_BINARY Command.-->
|
||||
<MLe>0xFFFF</MLe>
|
||||
<!--Defines the maximum data size that can be sent to the T4T using a single Command.-->
|
||||
<MLc>0xFFFF</MLc>
|
||||
<!--Section 4.7.3 specifies the content of the NDEF-File_Ctrl_TLV block that contains information to control and manage the NDEF File for Mapping Version 2.0 (see Section 4.5).-->
|
||||
<NDEF-File_Ctrl_TLV>
|
||||
<T>0x04</T>
|
||||
<L>0x06</L>
|
||||
<V>
|
||||
<NDEF_FILE_ID>0xE104</NDEF_FILE_ID>
|
||||
<NDEF_FILE_SIZE>0x0800</NDEF_FILE_SIZE>
|
||||
<ENDEF_File_READ_AC>0x00</ENDEF_File_READ_AC>
|
||||
<ENDEF_File_WRITE_AC>0xFF</ENDEF_File_WRITE_AC>
|
||||
</V>
|
||||
</NDEF-File_Ctrl_TLV>
|
||||
</CapabilityContainerFile>
|
Reference in New Issue
Block a user