Clean up and polish Mifare Classic tech.
- It's useful to have accessors at block level, so apps don't really have to know about the sector structure (and how many blocks there are in a sector). - There's no way to tell whether a read/write/ didn't work because of auth failure. The documentation should be changed to make this point clear. - Added increment/decrement commands, for atomic increment/decrement of value blocks. Change-Id: I590feacbcd1443f1be7a86ab046a5b1f33e2e04c
This commit is contained in:
committed by
Nick Pelly
parent
c8e8a12b3c
commit
ab82a5b9a8
@@ -161,7 +161,9 @@ public final class MifareClassic extends BasicTagTechnology {
|
|||||||
mSize = SIZE_4K;
|
mSize = SIZE_4K;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
// Unknown, not MIFARE
|
// Unknown mifare
|
||||||
|
mType = TYPE_UNKNOWN;
|
||||||
|
mSize = SIZE_UNKNOWN;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -226,9 +228,10 @@ public final class MifareClassic extends BasicTagTechnology {
|
|||||||
|
|
||||||
// Methods that require connect()
|
// Methods that require connect()
|
||||||
/**
|
/**
|
||||||
* Authenticate for a given sector.
|
* Authenticate for a given block.
|
||||||
|
* Note that this will authenticate the entire sector the block belongs to.
|
||||||
*/
|
*/
|
||||||
public boolean authenticateSector(int sector, byte[] key, boolean keyA) {
|
public boolean authenticateBlock(int block, byte[] key, boolean keyA) {
|
||||||
checkConnected();
|
checkConnected();
|
||||||
|
|
||||||
byte[] cmd = new byte[12];
|
byte[] cmd = new byte[12];
|
||||||
@@ -241,7 +244,7 @@ public final class MifareClassic extends BasicTagTechnology {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Second byte is block address
|
// Second byte is block address
|
||||||
cmd[1] = firstBlockInSector(sector);
|
cmd[1] = (byte) block;
|
||||||
|
|
||||||
// Next 4 bytes are last 4 bytes of UID
|
// Next 4 bytes are last 4 bytes of UID
|
||||||
byte[] uid = getTag().getId();
|
byte[] uid = getTag().getId();
|
||||||
@@ -260,6 +263,19 @@ public final class MifareClassic extends BasicTagTechnology {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Authenticate for a given sector.
|
||||||
|
*/
|
||||||
|
public boolean authenticateSector(int sector, byte[] key, boolean keyA) {
|
||||||
|
checkConnected();
|
||||||
|
|
||||||
|
byte addr = (byte) ((firstBlockInSector(sector)) & 0xff);
|
||||||
|
|
||||||
|
// Note that authenticating a block of a sector, will authenticate
|
||||||
|
// the entire sector.
|
||||||
|
return authenticateBlock(addr, key, keyA);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sector indexing starts at 0.
|
* Sector indexing starts at 0.
|
||||||
* Block indexing starts at 0, and resets in each sector.
|
* Block indexing starts at 0, and resets in each sector.
|
||||||
@@ -269,28 +285,69 @@ public final class MifareClassic extends BasicTagTechnology {
|
|||||||
checkConnected();
|
checkConnected();
|
||||||
|
|
||||||
byte addr = (byte) ((firstBlockInSector(sector) + block) & 0xff);
|
byte addr = (byte) ((firstBlockInSector(sector) + block) & 0xff);
|
||||||
byte[] blockread_cmd = { 0x30, addr }; // phHal_eMifareRead
|
return readBlock(addr);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads absolute block index.
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public byte[] readBlock(int block) throws IOException {
|
||||||
|
checkConnected();
|
||||||
|
|
||||||
|
byte addr = (byte) block;
|
||||||
|
byte[] blockread_cmd = { 0x30, addr };
|
||||||
|
|
||||||
// TODO deal with authentication problems
|
|
||||||
return transceive(blockread_cmd);
|
return transceive(blockread_cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
// public byte[] readSector(int sector);
|
/**
|
||||||
//TODO: define an enumeration for access control settings
|
* Writes absolute block index.
|
||||||
// public int readSectorAccessControl(int sector);
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public void writeBlock(int block, byte[] data) throws IOException {
|
||||||
|
checkConnected();
|
||||||
|
|
||||||
|
byte addr = (byte) block;
|
||||||
|
byte[] blockwrite_cmd = new byte[data.length + 2];
|
||||||
|
blockwrite_cmd[0] = (byte) 0xA0; // MF write command
|
||||||
|
blockwrite_cmd[1] = addr;
|
||||||
|
System.arraycopy(data, 0, blockwrite_cmd, 2, data.length);
|
||||||
|
|
||||||
|
transceive(blockwrite_cmd);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Writes relative block in sector.
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
* @throws NotAuthenticatedException
|
|
||||||
*/
|
*/
|
||||||
/*
|
public void writeBlock(int sector, int block, byte[] data) throws IOException {
|
||||||
public void writeBlock(int block, byte[] data);
|
checkConnected();
|
||||||
public void writeSector(int block, byte[] sector);
|
|
||||||
public void writeSectorAccessControl(int sector, int access);
|
byte addr = (byte) ((firstBlockInSector(sector) + block) & 0xff);
|
||||||
public void increment(int block);
|
|
||||||
public void decrement(int block);
|
writeBlock(addr, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void increment(int block) throws IOException {
|
||||||
|
checkConnected();
|
||||||
|
|
||||||
|
byte addr = (byte) block;
|
||||||
|
byte[] incr_cmd = { (byte) 0xC1, (byte) block };
|
||||||
|
|
||||||
|
transceive(incr_cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void decrement(int block) throws IOException {
|
||||||
|
checkConnected();
|
||||||
|
|
||||||
|
byte addr = (byte) block;
|
||||||
|
byte[] incr_cmd = { (byte) 0xC0, (byte) block };
|
||||||
|
|
||||||
|
transceive(incr_cmd);
|
||||||
|
}
|
||||||
|
|
||||||
*/
|
|
||||||
/**
|
/**
|
||||||
* Send data to a tag and receive the response.
|
* Send data to a tag and receive the response.
|
||||||
* <p>
|
* <p>
|
||||||
|
|||||||
Reference in New Issue
Block a user