Skip to content

Instantly share code, notes, and snippets.

@Komarev
Created June 2, 2016 08:49
Show Gist options
  • Save Komarev/7c35c977ffe0fec6f49acde760a1a0cd to your computer and use it in GitHub Desktop.
Save Komarev/7c35c977ffe0fec6f49acde760a1a0cd to your computer and use it in GitHub Desktop.
@WorkerThread
public static void writePage(NfcA nfca, byte offset, byte[] page)
throws NfcWritePageException {
byte[] cmd = new byte[] {COMMAND_WRITE_RECORD, offset, 0, 0, 0, 0};
try {
System.arraycopy(page, 0, cmd, 2, 4);
nfca.transceive(cmd);
} catch (Exception e) {
throw new NfcWritePageException(
"Write page error. Offset " + StringUtils.byteToHex(offset));
}
}
@WorkerThread
public static byte[] readPage(NfcA nfca, byte offset) throws NfcReadPageException {
byte[] result;
try {
result = nfca.transceive(new byte[] {COMMAND_READ_RECORD, offset});
} catch (Exception e) {
throw new NfcReadPageException(
"Read page error. Offset " + StringUtils.byteToHex(offset) + e.getMessage());
}
return result;
}
@WorkerThread
public static void prepareToIO(NfcA nfca) throws NfcOperationException {
byte[] buffer;
selectSector(nfca, SECTOR_3);
buffer = readPage(nfca, SECTOR_3_SESSION_REGISTER_PAGE_1_OFFSET);
if ((buffer[NC_REG_BYTE_NUMBER] & MASK_PTHRU_ON_OFF) != MASK_PTHRU_ON_OFF) {
throw new NfcControllerNotReady("Prepare IO: Controller not ready");
}
long startTime = System.currentTimeMillis() + READ_TIMEOUT_MS;
while (true) {
if (startTime < System.currentTimeMillis()) {
throw new NfcTimeoutException("Prepare IO: Timeout");
}
try {
buffer = readPage(nfca, SECTOR_3_SESSION_REGISTER_PAGE_1_OFFSET);
} catch (Exception e) {
continue;
}
if ((buffer[NC_REG_BYTE_NUMBER] & MASK_CONTROLLER_READY_TO_READ)
== MASK_CONTROLLER_READY_TO_READ) {
break;
}
}
}
@WorkerThread
public static void checkForOperationSuccess(NfcA nfca) throws NfcOperationException {
byte[] buffer;
long tryCounter = 0;
long failedFlagCounter = 0;
selectSector(nfca, SECTOR_3);
long startTime = System.currentTimeMillis() + READ_TIMEOUT_MS;
while (true) {
tryCounter++;
if (startTime < System.currentTimeMillis()) {
throw new NfcTimeoutException(
"Check for success timeout. Tries=" + Long.toString(tryCounter)
+ " failedFlagCount=" + Long.toString(failedFlagCounter));
}
buffer = readPage(nfca, SECTOR_3_SESSION_REGISTER_PAGE_2_OFFSET);
failedFlagCounter++;
if ((buffer[NS_REG_BYTE_NUMBER] & MASK_SRAM_RF_READY) == MASK_SRAM_RF_READY) {
break;
}
}
}
@WorkerThread
public static void writeOperationCommand(NfcA nfca, String command)
throws NfcOperationException {
selectSector(nfca, SECTOR_1);
try {
byte[] buffer = command.getBytes(ASCII);
int fullpagesCount = buffer.length / 4;
int charsInLastPage = buffer.length - fullpagesCount * 4;
for (int i = 0; i < fullpagesCount; i++) {
writePage(nfca, (byte) (SRAM_FIRST_PAGE_OFFSET + i),
Arrays.copyOfRange(buffer, i * 4, i * 4 + 4));
}
if (charsInLastPage > 0) {
writePage(nfca, (byte) (SRAM_FIRST_PAGE_OFFSET + fullpagesCount),
String.format(FORMAT_PAGE_STRING, command.substring(fullpagesCount * 4))
.getBytes(ASCII));
}
writePage(nfca, SRAM_LAST_PAGE_OFFSET, new byte[] {0x30, 0x30, 0x30, 0x30});
} catch (UnsupportedEncodingException e) {
throw new NfcWriteOperationException("Write operation exception");
}
}
@WorkerThread
public static String readOperationAnswer(NfcA nfca) throws NfcOperationException {
byte[] buffer;
selectSector(nfca, SECTOR_1);
List<Byte> sram = new ArrayList<>();
for (byte i = SRAM_FIRST_PAGE_OFFSET; i <= SRAM_LAST_PAGE_OFFSET; i++) {
buffer = readPage(nfca, i);
sram.add(buffer[0]);
sram.add(buffer[1]);
sram.add(buffer[2]);
sram.add(buffer[3]);
if (buffer[0] == END || buffer[1] == END || buffer[2] == END || buffer[3] == END) {
break;
}
}
byte[] result = new byte[sram.size()];
for (int i = 0; i < result.length; i++) {
result[i] = sram.get(i);
}
String resultMessage;
try {
resultMessage = new String(result, ASCII);
} catch (UnsupportedEncodingException e) {
resultMessage = "Unsupported encoding " + ASCII;
}
return resultMessage;
}
public static Observable<String> resetClock(NfcA nfca, long timestamp) {
return Observable.fromCallable(() -> {
prepareToIO(nfca);
writeOperationCommand(nfca,
NfcOperationFactory.getCommandForTimeSetup(timestamp));
checkForOperationSuccess(nfca);
return readOperationAnswer(nfca);
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment