NFC (二)讀寫MifareClassic協議的NFC卡


先了解一下MifareClassic協議

在android sdk 的文檔中,描述道 “all MifareClassic I/O operations will be supported, and MIFARE_CLASSIC NDEF tags will also be supported. In either case, NfcA will also be enumerated on the tag, because all MIFARE Classic tags are also NfcA.” 所以說NFCA協議是兼容MifareClassic 協議的, 我們可以通過NfcA在android的相關類來處理給予MifareClassic 的RFID卡。

 

一般來說,給予MifareClassic的射頻卡,一般內存大小有3種:

1K: 16個分區(sector),每個分區4個塊(block),每個塊(block) 16個byte數據

2K: 32個分區,每個分區4個塊(block),每個塊(block) 16個byte數據

4K:64個分區,每個分區4個塊(block),每個塊(block) 16個byte數據

 

對於所有基於MifareClassic的卡來說,每個區最后一個塊叫Trailer,16個byte, 主要來存放讀寫該區的key,可以有A,B兩個KEY,每個key長6byte,默認的key一般是FF 或 0,最后一個塊的內存結構如下:

Block 0  Data 16bytes
Block 1  Data 16 bytes
Block 2  Data 16 bytes
Block 3  Trailer 16 bytes
 
Trailer:
Key A: 6 bytes
Access Conditions: 4 bytes
Key B: 6 bytes 
 
所以在寫卡的內存的時候,一般不能寫每個sector的最后一個block,除非你有要修改KEY和訪問權限的需求。如果KEY A 被你不小心修改掉了,而你不知道修改成什么,那與之對應的那個sector你就沒有辦法訪問了。因為在MifareClassic中,如果你要讀取數據,那么必須要有這個數據地址所在的sector的權限,這個權限就是這個sector的trailer的keyA或KEY B。
 
讀數據的例子:
//tag 就是在上一篇中onNewIntent中獲取的tag
MifareClassic mc = MifareClassic.get(tag);
        short startAddress = 0;
        short endAddress = 5;

        byte[] data = new byte[(endAddress - startAddress + 1 ) * ByteCountPerBlock];
        
        try {            
            mc.connect();for (short i = startAddress; i <= endAddress; i++ ,time++) {
                boolean auth = false;
                short sectorAddress = getSectorAddress(i);
                auth = mc.authenticateSectorWithKeyA(sectorAddress, MifareClassic.KEY_DEFAULT);
                if (auth){
                    
                    //the last block of the sector is used for KeyA and KeyB cannot be overwritted
                    short readAddress = (short)(sectorAddress == 0 ? i : i + sectorAddress);
                    
                    byte[] response = mc.readBlock(readAddress);
                    CombineByteArray(data, response, time * ByteCountPerBlock);
                }
                else{
                    throw new NfcException(NfcErrorCode.TemporaryError,
                            "Authorization Error.");
                }
            }

            mc.close();
            
        }
        catch (NfcException ne) {
            throw ne;
        }
        catch (IOException e) {
            throw new NfcException(NfcErrorCode.TemporaryError,
                    "Get response, what it is not successfully.", e);
        }
        finally
        {
            try {
                mc.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

 

寫數據的例子:
 
//tag 就是在上一篇中onNewIntent中獲取的tag
MifareClassic mc = MifareClassic.get(tag);

            try {
                mc.connect();
                boolean auth = false;
                short sectorAddress = 0
                auth = mc.authenticateSectorWithKeyA(sectorAddress,
                        MifareClassic.KEY_DEFAULT);
                if (auth) {
                    //the last block of the sector is used for KeyA and KeyB cannot be overwritted
                    
                    mc.writeBlock(readAddress, dataTemp);

                    mc.close();
                } 
            }finally
            {
                try {
                    mc.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }

 

完整的代碼示例在這里下載

 

上一篇 NFC (一) 概述


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM