Package org.nfctools.spi.arygon

Source Code of org.nfctools.spi.arygon.ArygonReaderWriter

/**
* Copyright 2011-2012 Adrian Stabiszewski, as@nfctools.org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*       http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.nfctools.spi.arygon;

import java.io.IOException;

import org.nfctools.mf.MfAccess;
import org.nfctools.mf.MfCardListener;
import org.nfctools.mf.MfException;
import org.nfctools.mf.MfLoginException;
import org.nfctools.mf.MfReaderWriter;
import org.nfctools.mf.block.Block;
import org.nfctools.mf.block.BlockResolver;
import org.nfctools.mf.block.MfBlock;
import org.nfctools.mf.block.TrailerBlock;
import org.nfctools.mf.card.MfCard;
import org.nfctools.utils.NfcUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ArygonReaderWriter implements MfReaderWriter {

  private Logger log = LoggerFactory.getLogger(getClass());

  private ArygonHighLevelReaderWriter nfcReaderWriter;
  private Thread pollingThread = null;
  private CardResolver cardResolver = new CardResolver();
  private BlockResolver mfBlockResolver = new BlockResolver();

  public ArygonReaderWriter(ArygonHighLevelReaderWriter nfcReaderWriter) {
    this.nfcReaderWriter = nfcReaderWriter;
  }

  @Override
  public MfBlock[] readBlock(MfAccess mfAccess) throws IOException {
    loginIfNotAuthenticated(mfAccess);
    MfBlock[] returnBlocks = new Block[mfAccess.getBlocksToRead()];
    for (int block = 0; block < mfAccess.getBlocksToRead(); block++) {
      String blockNumber = createBlockNumber(mfAccess, block);
      nfcReaderWriter.sendMessage(("0r" + blockNumber).getBytes());
      ArygonMessage message = nfcReaderWriter.receiveMessage();
      if (message.hasTamaErrorCode())
        throwException(mfAccess, message, "Cannot read.");

      byte[] rawData = new byte[message.getPayload().length - 4];
      System.arraycopy(message.getPayload(), 4, rawData, 0, message.getPayload().length - 4);
      returnBlocks[block] = mfBlockResolver.resolveBlock(mfAccess.getCard(), mfAccess.getSector(), block
          + mfAccess.getBlock(), rawData);
    }
    return returnBlocks;
  }

  private void throwException(MfAccess mfAccess, ArygonMessage message, String exceptionMessage) throws IOException {
    if (message.getTamaErrorCode() == 0x13) {
      reselectCard(mfAccess.getCard());
      throw new MfLoginException("Cannot login.");
    }
    else
      throw new MfException(exceptionMessage + " Sector: " + mfAccess.getSector() + ", Block: "
          + mfAccess.getBlock() + " Key: " + mfAccess.getKey().name() + ", Tama: "
          + new String(message.getPayload()) + " TamaCode: " + message.getTamaErrorCode());
  }

  private void loginIfNotAuthenticated(MfAccess mfAccess) throws IOException {
    loginIntoSector(mfAccess);
  }

  private void loginIntoSector(MfAccess mfAccess) throws IOException {
    String blockNumber = createBlockNumber(mfAccess, 0);
    String loginMessage = "0l" + blockNumber + "ff" + mfAccess.getKey().name()
        + NfcUtils.convertBinToASCII(mfAccess.getKeyValue());
    nfcReaderWriter.sendMessage(loginMessage.getBytes());
    ArygonMessage message = nfcReaderWriter.receiveMessage();
    if (message.hasTamaErrorCode()) {
      reselectCard(mfAccess.getCard());
      throw new MfLoginException("Login failed. Sector: " + mfAccess.getSector() + ", Block: "
          + mfAccess.getBlock() + " Key: " + mfAccess.getKey().name() + ", Tama: "
          + new String(message.getPayload()));
    }
  }

  @Override
  public void writeBlock(MfAccess mfAccess, MfBlock... mfBlock) throws IOException {
    loginIfNotAuthenticated(mfAccess);
    for (int x = 0; x < mfBlock.length; x++) {
      String blockNumber = createBlockNumber(mfAccess, x);

      if (mfAccess.getCard().isTrailerBlock(mfAccess.getSector(), mfAccess.getBlock() + x)) {
        if (!(mfBlock[x] instanceof TrailerBlock))
          throw new MfException("invalid block for trailer");
      }
      nfcReaderWriter.sendMessage(("0wb" + blockNumber + NfcUtils.convertBinToASCII(mfBlock[x].getData()))
          .getBytes());
      ArygonMessage message = nfcReaderWriter.receiveMessage();
      if (message.hasTamaErrorCode())
        throwException(mfAccess, message, "Cannot write.");
    }
  }

  private String createBlockNumber(MfAccess mfAccess, int blockOffset) {
    int blockNumber = mfAccess.getCard().getBlockNumber(mfAccess.getSector(), mfAccess.getBlock()) + blockOffset;
    String rb = Integer.toHexString(blockNumber).toUpperCase();
    if (rb.length() == 1)
      rb = "0" + rb;
    return rb;
  }

  @Override
  public void setCardIntoHalt(MfCard card) throws IOException {
    String targetId = "00";
    log.debug("Halting Card " + card.getId() + " / TargetId: " + targetId);
    nfcReaderWriter.sendMessage(("0h" + targetId).getBytes());
    ArygonMessage message = nfcReaderWriter.receiveMessage();
    if (message.hasTamaErrorCode())
      throw new MfException("Cannot send data.");
  }

  public void scanForCard() throws IOException {
    nfcReaderWriter.sendMessage("0s".getBytes());
  }

  public MfCard readCard() throws IOException {
    ArygonMessage message = nfcReaderWriter.receiveMessage();
    if (message.hasPayload()) {
      byte[] data = NfcUtils.convertHexAsciiToByteArray(message.getPayload());
      byte targetNumber = data[2];
      int type = data[5];
      byte nfcIdLength = data[6];
      byte[] cardId = new byte[nfcIdLength];
      System.arraycopy(data, 7, cardId, 0, nfcIdLength);

      return cardResolver.resolvecard(type, cardId, targetNumber);
    }
    else
      throw new MfException("no card");
  }

  @Override
  public void reselectCard(MfCard card) throws IOException {
    scanForCard();
    MfCard newcard = readCard();
    if (!NfcUtils.isEqualArray(card.getId(), newcard.getId()))
      throw new MfException("New card detected. Id does not match. (Expected: " + card + ", got: " + newcard
          + ")");
  }

  @Override
  public void setCardListener(MfCardListener cardListener) throws IOException {
    scanForCard();
    pollingThread = new Thread(new PollingCardScanner(nfcReaderWriter, cardListener, this));
    pollingThread.setDaemon(false);
    log.debug("Starting new thread " + pollingThread.getName());
    pollingThread.start();
  }

  @Override
  public boolean waitForCard(MfCardListener mfCardListener, int timeout) throws IOException {
    throw new UnsupportedOperationException(); // TODO
  }

  @Override
  public void removeCardListener() {
    if (pollingThread != null && pollingThread.isAlive()) {
      pollingThread.interrupt();
    }
  }
}
TOP

Related Classes of org.nfctools.spi.arygon.ArygonReaderWriter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.