简体   繁体   English

如何检测NFC芯片的类型

[英]How to detect the type of an NFC chip

Does anyone know how I can find out via the Android NFC API which NFC chip is used in a tag which I am reading? 有谁知道我怎么能通过Android NFC API找出哪个NFC芯片用在我正在阅读的标签中? Ideally I like to get the both the chip model and the manufacturer. 理想情况下,我喜欢获得芯片型号和制造商。

Is that available somewhere in the Tag object? 可以在Tag对象的某处使用吗?

For clarification, I don't mean the reader chip in the phone, but the chip in the NFC tag. 为了澄清,我不是说手机中的读卡器芯片,而是NFC标签中的芯片。

I'm developing an application in Android for NFC read/write/authentication operations. 我正在Android中开发一个用于NFC读/写/身份验证操作的应用程序。 Here are some code parts you would like. 以下是您想要的一些代码部分。

Android has 3 main types determined for cards, those are Mifare Classic, Mifare Ultralight and Isodep (this is the type of Desfire and Desfire EV1). Android有三种主要类型的卡片,分别是Mifare Classic,Mifare Ultralight和Isodep(这是Desfire和Desfire EV1的类型)。 So, as I get a tag touched, I run this operation: 所以,当我触摸标签时,我运行此操作:

private String[] getTagInfo(Intent intent) {
    Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
    String prefix = "android.nfc.tech.";
    String[] info = new String[2];

    // UID
    byte[] uid = tag.getId();
    info[0] = "UID In Hex: " + Utils.convertByteArrayToHexString(uid) + "\n" +
              "UID In Dec: " + Utils.convertByteArrayToDecimal(uid) + "\n\n";

    // Tech List
    String[] techList = tag.getTechList();
    String techListConcat = "Technologies: ";
    for(int i = 0; i < techList.length; i++) {
        techListConcat += techList[i].substring(prefix.length()) + ",";
    }
    info[0] += techListConcat.substring(0, techListConcat.length() - 1) + "\n\n";

    // Mifare Classic/UltraLight Info
    info[0] += "Card Type: ";
    String type = "Unknown";
    for(int i = 0; i < techList.length; i++) {
        if(techList[i].equals(MifareClassic.class.getName())) {
            info[1] = "Mifare Classic";
            MifareClassic mifareClassicTag = MifareClassic.get(tag);

            // Type Info
            switch (mifareClassicTag.getType()) {
            case MifareClassic.TYPE_CLASSIC:
                type = "Classic";
                break;
            case MifareClassic.TYPE_PLUS:
                type = "Plus";
                break;
            case MifareClassic.TYPE_PRO:
                type = "Pro";
                break;
            }
            info[0] += "Mifare " + type + "\n";

            // Size Info
            info[0] += "Size: " + mifareClassicTag.getSize() + " bytes \n" +
                    "Sector Count: " + mifareClassicTag.getSectorCount() + "\n" +
                    "Block Count: " + mifareClassicTag.getBlockCount() + "\n";
        } else if(techList[i].equals(MifareUltralight.class.getName())) {
            info[1] = "Mifare UltraLight";
            MifareUltralight mifareUlTag = MifareUltralight.get(tag);

            // Type Info
            switch (mifareUlTag.getType()) {
            case MifareUltralight.TYPE_ULTRALIGHT:
                type = "Ultralight";
                break;
            case MifareUltralight.TYPE_ULTRALIGHT_C:
                type = "Ultralight C";
                break;
            }
            info[0] += "Mifare " + type + "\n";
        } else if(techList[i].equals(IsoDep.class.getName())) {
            info[1] = "IsoDep";
            IsoDep isoDepTag = IsoDep.get(tag);
            info[0] += "IsoDep \n";
        } else if(techList[i].equals(Ndef.class.getName())) {
            Ndef ndefTag = Ndef.get(tag);
            info[0] += "Is Writable: " + ndefTag.isWritable() + "\n" +
                    "Can Make ReadOnly: " + ndefTag.canMakeReadOnly() + "\n";
        } else if(techList[i].equals(NdefFormatable.class.getName())) {
            NdefFormatable ndefFormatableTag = NdefFormatable.get(tag);
        }
    } 

    return info;
}

However, this doesn't directly get the type of Desfire and Desfire EV1. 但是,这并没有直接获得Desfire和Desfire EV1的类型。 For that you need to send some bytes to card: 为此,您需要向卡发送一些字节:

static final byte GET_MANUFACTURING_DATA = (byte) 0x60;

public DesfireManufacturingData getManufacturingData() throws Exception {
    byte[] respBuffer = sendRequest(GET_MANUFACTURING_DATA);
    if (respBuffer.length != 28)
        throw new Exception("Invalid response");
    return new DesfireManufacturingData(respBuffer);
}

private byte[] sendRequest (byte command) throws Exception {
    return sendRequest(command, null);
}

private byte[] sendRequest (byte command, byte[] parameters) throws Exception {
    ByteArrayOutputStream output = new ByteArrayOutputStream();

    byte[] recvBuffer = mTagTech.transceive(Utils.wrapMessage(command, parameters));

    while (true) {
        if (recvBuffer[recvBuffer.length - 2] != (byte) 0x91)
            throw new Exception("Invalid response");

        output.write(recvBuffer, 0, recvBuffer.length - 2);

        byte status = recvBuffer[recvBuffer.length - 1];
        if (status == OPERATION_OK) {
            break;
        } else if (status == ADDITIONAL_FRAME) {
            recvBuffer = mTagTech.transceive(Utils.wrapMessage(GET_ADDITIONAL_FRAME, null));


        } else if (status == PERMISSION_DENIED) {
            throw new Exception("Permission denied");
        }else if (status == LENGTH_ERROR) {
            throw new Exception("Length Error");
        } 
        else if (status == AUTHENTICATION_ERROR) {
            throw new Exception("Authentication error");
        }else if (status == PARAMETER_ERROR) {
            throw new Exception("Parameter Error");
        }else if (status == DUPLICATE_ERROR) {
            throw new Exception("Duplicate Error");
        }else if (status == NO_SUCH_KEY) {
            throw new Exception("No such key");
        }else {
            throw new Exception("Unknown status code: " + Integer.toHexString(status & 0xFF));
        }
    }

    return output.toByteArray();
}

After you initialize the Manufacturing data, you can easily reach its parts. 初始化制造数据后,您可以轻松访问其零件。 DesfireManufacturingData class is for evaluating the response from the tag into meaningful parts, but I'll only give link of it: Desfire Manufacturing Data . DesfireManufacturingData类用于评估从标签到有意义部分的响应,但我只给出它的链接: Desfire制造数据 Also, I must say this is the most all-around project I have found in the Internet with open source, but it only has reading operations for Desfire tags, not write and authenticate. 另外,我必须说这是我在互联网上用开源找到的最全面的项目,但它只有Desfire标签的读取操作,而不是写入和验证。 Hope this helps! 希望这可以帮助!

If you have an Android device with NFC, there are various apps available that do exactly this (and more), for example NXP TagInfo or NFC TagInfo . 如果您的Android设备具有NFC,则可以使用各种应用程序来完成此操作(以及更多),例如NXP TagInfoNFC TagInfo

For PC with a desktop reader, perhaps RFIDIOt could be of use. 对于带有桌面阅读器的PC,也许RFIDIOt可能会有用。 For other platforms, similar apps may exist (or could be created), but I am not familiar with them. 对于其他平台,可能存在(或可能创建)类似的应用程序,但我不熟悉它们。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM