除了探测特定页码并检查它们是否存在之外,以编程方式检测 NFC 芯片(MIFARE Ultralight 或 NTAGxxx)的内存大小或页数的最简单方法是什么?
ATR 中是否有返回的特定字节或存储在芯片内存的保护区中的某个位置,以判断它是特定的 NTAGxxx 芯片,还是页数或字节数?
除了探测特定页码并检查它们是否存在之外,以编程方式检测 NFC 芯片(MIFARE Ultralight 或 NTAGxxx)的内存大小或页数的最简单方法是什么?
ATR 中是否有返回的特定字节或存储在芯片内存的保护区中的某个位置,以判断它是特定的 NTAGxxx 芯片,还是页数或字节数?
通常,您只能通过广泛的指纹识别和使用读取命令进行探测来确定这一点。
指纹:这意味着您需要有一个制造商特定特征的数据库(例如,从数据表中收集,不幸的是,更多的是从经验测试中收集,因为这些信息没有(公开?或根本没有?)记录在案对于大多数标签),您可以检查您的标签。
探测:
这样你就可以找到最后一个可读的页面地址,它不一定是标签内存的“真实”末端(例如,末端可能有受保护的页面)。
如果您的 Ultralight 和 NTAG 标签是 EV1 标签(即它们实现了 Ultralight EV1 命令集),则公开一个 GET_VERSION 命令,您可以使用它来检索存储大小信息。版本信息与所有现有标签指纹的数据库(您可以从 Ultraight/NTAG 数据表中获取该信息)相结合,将使您能够可靠地1确定标签类型,从而确定内存大小。
1 ) 除了一些以“NTAG”出售的仿冒芯片,它们模仿真正的NTAG芯片的参数,但似乎有内存大小、缺乏命令支持等与他们模仿的芯片不匹配的参数。
对于遵循 NFC Forum Type 2 标签操作规范的 NFC 标签,您还可以依赖编码到功能容器中的标签内存大小。但是,此内存大小不一定是物理内存大小。
我认为,从接受的答案来看,下面的代码是有意义的,
int numberOfPages = 0;
int tagType = ulTag.getType();
if(tagType == MifareUltralight.TYPE_ULTRALIGHT) {
numberOfPages = 16;
} else if(tagType == MifareUltralight.TYPE_ULTRALIGHT_C) {
numberOfPages = 47;
}
getMaxTransceiveLength() 用于检索使用 transceive(byte[]) 可以发送的最大字节数。收发命令分别使用前 3 个字节作为标志、命令和页码。
我们需要检查以下代码是否有效?
int totalBytes = ulTag.getMaxTransceiveLength() + 3;
int totalPages = totalBytes / ulTag.PAGE_SIZE;
对于 MIFARE ULTRALIGHT,您可以通过这种方式检查版本。
public static final int OFFSET_128_BYTE = 0x025;
public static final int OFFSET_48_BYTE = 0x010;
public static int checkType(MifareUltralight mrfid){
int cfgOffset = -1;
byte[] response = null;
byte[] writeResponse = null;
try {
response = mrfid.transceive(new byte[]{
(byte) 0x60 // GET_VERSION
});
} catch (TagLostException tle) {
Utility.log("setPasswordAndEnable GET_VERSION, TagLostException ... ");
return cfgOffset;
} catch (IOException ioe) {
Utility.log("setPasswordAndEnable GET_VERSION, IOException ... ");
return cfgOffset;
}
if ((response != null) && (response.length >= 8)) {
// success
if ((response[0] == (byte) 0x00) && (response[1] == (byte) 0x04)) {
// tag is from NXP
if (response[2] == (byte) 0x03) {
// MIFARE Ultralight
if ((response[4] == (byte) 0x01) && (response[5] == (byte) 0x00)) {
// MIFARE Ultralight EV1 (V0)
switch (response[6]) {
case (byte) 0x0B:
// MF0UL11
cfgOffset = OFFSET_48_BYTE;
break;
case (byte) 0x0E:
// MF0UL21
cfgOffset = OFFSET_128_BYTE;
break;
default:
// unknown
break;
}
}
}
}
}
return cfgOffset;
}