标记错误地枚举为MIFARE Classic,SAK = 32

时间:2015-05-14 13:04:20

标签: android nfc mifare

我有索尼Xperia Z3。我正在使用它与MIFARE Classic智能卡进行交互。

使用原生MIFARE卡时,我可以正确读取卡片。

但是,如果我使用模拟的MIFARE Classic,我会得到一个不正确的SAK。当使用MifareClassic.get(tag)

时,我得到0x20(32)并且出现以下错误,而不是0x38
java.lang.RuntimeException: Tag incorrectly enumerated as MIFARE Classic, SAK = 32

我不知道为什么我的手机会错误地读取SAK。

在支持MIFARE作为Nexus S等的其他设备上正确读取相同的卡

知道这个例外的原因吗?

TA

2 个答案:

答案 0 :(得分:1)

在致电tag = cleanupTag(tag)之前,尝试将此补丁用作MifareClassic.get(tag) 有关详细信息,请参阅MifareClassicTool Sony Z3 issue

private Tag cleanupTag(Tag oTag){
    if (oTag == null)
        return null;

    String[] sTechList = oTag.getTechList();

    Parcel oParcel = Parcel.obtain();
    oTag.writeToParcel(oParcel, 0);
    oParcel.setDataPosition(0);

    int len = oParcel.readInt();
    byte[] id = null;
    if (len >= 0) {
        id = new byte[len];
        oParcel.readByteArray(id);
    }
    int[] oTechList = new int[oParcel.readInt()];
    oParcel.readIntArray(oTechList);
    Bundle[] oTechExtras = oParcel.createTypedArray(Bundle.CREATOR);
    int serviceHandle = oParcel.readInt();
    int isMock = oParcel.readInt();
    IBinder tagService;
    if (isMock == 0) {
        tagService = oParcel.readStrongBinder();
    } else {
        tagService = null;
    }
    oParcel.recycle();

    int nfca_idx = -1;
    int mc_idx = -1;
    short oSak = 0;
    short nSak = 0;

    for (int idx = 0; idx < sTechList.length; idx++) {
        if (sTechList[idx].equals(NfcA.class.getName())) {
            if (nfca_idx == -1) {
                nfca_idx = idx;
                if (oTechExtras[idx] != null
                        && oTechExtras[idx].containsKey("sak")) {
                    oSak = oTechExtras[idx].getShort("sak");
                    nSak = oSak;
                }
            } else {
                if (oTechExtras[idx] != null
                        && oTechExtras[idx].containsKey("sak")) {
                    nSak = (short) (nSak | oTechExtras[idx].getShort("sak"));
                }
            }
        } else if (sTechList[idx].equals(MifareClassic.class.getName())) {
            mc_idx = idx;
        }
    }

    boolean modified = false;

    if (oSak != nSak) {
        oTechExtras[nfca_idx].putShort("sak", nSak);
        modified = true;
    }

    if (nfca_idx != -1 && mc_idx != -1 && oTechExtras[mc_idx] == null) {
        oTechExtras[mc_idx] = oTechExtras[nfca_idx];
        modified = true;
    }

    if (!modified) {
        return oTag;
    }

    Parcel nParcel = Parcel.obtain();
    nParcel.writeInt(id.length);
    nParcel.writeByteArray(id);
    nParcel.writeInt(oTechList.length);
    nParcel.writeIntArray(oTechList);
    nParcel.writeTypedArray(oTechExtras, 0);
    nParcel.writeInt(serviceHandle);
    nParcel.writeInt(isMock);
    if (isMock == 0) {
        nParcel.writeStrongBinder(tagService);
    }
    nParcel.setDataPosition(0);

    Tag nTag = Tag.CREATOR.createFromParcel(nParcel);

    nParcel.recycle();

    return nTag;
}

答案 1 :(得分:0)

SAK值不是可用于区分不同NFC标签的神奇值。相反,它是一个掩码值,它定义了RF协议的一些功能。

不幸的是,谷歌Android代码使用SAK进行mifare卡识别,您可以在此处的代码中看到:MifareClassic.java

Xperia Z3中发生的情况可能是NFC控制器和NFC堆栈正确检测到标签为Mifare兼容并报告。一旦你尝试使用标签,就会遇到你提到的问题。

Nexus S可能正在运行MifareClassic.java代码的固定版本并避免此问题。

你能做些什么:从应用程序的角度来看,没什么。这是Android操作系统中的一个错误。如果您具有root访问权限,则可以通过艰难的方式完成并动态修补成员函数。