NFC.IsmbSnepConnectionTarget.java Source code

Java tutorial

Introduction

Here is the source code for NFC.IsmbSnepConnectionTarget.java

Source

/*
 * IsmbSnepConnectionTarget
 * 
 * Copyright (C) 2013  Antonio Lotito <lotito@ismb.it>
 * 
 * This file is part of ISMB-SNEP-JAVA LIBRARY.
 * 
 * ISMB-SNEP-JAVA LIBRARY is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or(at your option) any later version.
 * 
 * ISMB-SNEP-JAVA LIBRARY is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *  
 * See the GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License along with ISMB-SNEP-JAVA-LIBRARY. If not, see http://www.gnu.org/licenses/.
*/

package NFC;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.OutputStream;

import javax.smartcardio.Card;
import javax.smartcardio.CardChannel;
import javax.smartcardio.CardException;
import javax.smartcardio.CardTerminal;
import javax.smartcardio.CommandAPDU;
import javax.smartcardio.ResponseAPDU;

import org.apache.commons.io.IOUtils;

import Arduino.SerialClass;
import Utils.Authentication;

@SuppressWarnings("restriction")
public class IsmbSnepConnectionTarget {

    //USEFUL APDU COMMANDS 
    private final static byte TG_GET_DATA = (byte) 0x86;
    //private final static byte TG_GET_DATA = (byte) 0x86;
    private final static byte TG_INIT_AS_TARGET = (byte) 0x8c;
    private final static byte TG_SET_DATA = (byte) 0x8e;

    private CardTerminal terminal;
    private CardChannel ch;
    private Card card;
    //  Enable debugMode to print info about the communication
    private boolean debugMode = false;

    public static BufferedReader input;
    public static OutputStream output;

    //Set debug mode
    public void setDebugMode() {
        debugMode = true;
    }

    //Unset debug mode
    public void unsetDebugMode() {
        debugMode = false;
    }

    /**
     * Initialize SNEP Connection
     *
     * @param t
     *            a valid card terminal
     *
     * @throws IsmbSnepException
     *             if the terminal is incorrect
     */
    public IsmbSnepConnectionTarget(CardTerminal t) throws IsmbSnepException {
        if (t == null) {
            throw new IsmbSnepException("invalid card terminal");
        }
        terminal = t;
        try {
            //if (terminal.isCardPresent()) { 
            if (terminal.waitForCardPresent(5000)) {
                card = terminal.connect("*");
                System.out.println("card: " + card);
                ch = card.getBasicChannel();
                System.out.println("Protocol:" + card.getProtocol());
            } else {
                throw new IsmbSnepException("Device not supported, only ACS ACR122 is supported now");
            }
        } catch (CardException e) {
            throw new IsmbSnepException("problem with connecting to reader");
        }
    }

    /**
     * Sends and receives APDUs to and from the controller
     *
     * @param instr
     *            Instruction
     * @param param
     *            Payload to send
     *
     * @return The response payload 
     */
    private byte[] transceive(byte instr, byte[] payload) throws IsmbSnepException {

        if (ch == null) {
            throw new IsmbSnepException("channel not open");
        }
        int payloadLength = (payload != null) ? payload.length : 0;
        byte[] instruction = { (byte) 0xd4, instr };

        //ACR122 header
        byte[] header = { (byte) 0xff, (byte) 0x00, (byte) 0x00, (byte) 0x00,
                (byte) (instruction.length + payloadLength) };

        /* construct the command */
        byte[] cmd = Util.appendToByteArray(header, instruction, 0, instruction.length);
        cmd = Util.appendToByteArray(cmd, payload);

        if (debugMode)
            Util.debugAPDUs(cmd, null);

        try {
            CommandAPDU c = new CommandAPDU(cmd);
            ResponseAPDU r = ch.transmit(c);

            byte[] ra = r.getBytes();

            if (debugMode)
                Util.debugAPDUs(null, ra);

            /* check whether APDU command was accepted by the Controller */
            if (r.getSW1() == 0x63 && r.getSW2() == 0x27) {
                throw new CardException("wrong checksum from contactless response");
            } else if (r.getSW1() == 0x63 && r.getSW2() == 0x7f) {
                throw new CardException("wrong PN53x command");
            } else if (r.getSW1() != 0x90 && r.getSW2() != 0x00) {
                throw new CardException("unknown error");
            }
            return Util.subByteArray(ra, 2, ra.length - 4);
        } catch (CardException e) {

            throw new IsmbSnepException("problem with transmitting data");
        }
    }

    public void sendingProcedure() {
    }

    public void receivingProcedure() throws IOException {
        System.out.println("Called new Procedure to receive data .. TARGET MODE");

        try {
            //TG_INIT_AS_TARGET
            byte[] targetPayload = {
                    //(byte) 0x00,   //MODE
                    (byte) 0x02, //DEP ONLY
                    //(byte) 0x01, //PASSIVE MODE ONLY 
                    (byte) 0x00, (byte) 0x00, (byte) 0x00, //MIFARE PARAMS 
                    (byte) 0x00, (byte) 0x00, (byte) 0x40, //MIFARE PARAMS
                    (byte) 0x01, (byte) 0xfe, (byte) 0x0f, (byte) 0xbb, (byte) 0xba, (byte) 0xa6, //FELICA PARAMS 
                    (byte) 0xc9, (byte) 0x89, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, //FELICA PARAMS
                    (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0xff, (byte) 0xff, //FELICA PARAMS
                    (byte) 0x01, (byte) 0xfe, (byte) 0x0f, (byte) 0xbb, (byte) 0xba, //NFCID3t
                    (byte) 0xa6, (byte) 0xc9, (byte) 0x89, (byte) 0x00, (byte) 0x00, //NFCID3t                
                    (byte) 0x0F, //LEN Gt
                    (byte) 0x46, (byte) 0x66, (byte) 0x6D, //LLCP WORD 
                    (byte) 0x01, (byte) 0x01, (byte) 0x10, //VERSION NUMBER
                    (byte) 0x03, (byte) 0x02, (byte) 0x00, (byte) 0x01, //WELL KNOWN SERVICE LIST
                    (byte) 0x04, (byte) 0x01, (byte) 0x96 //LINK TIMEOUT
            };
            transceive(TG_INIT_AS_TARGET, targetPayload);
        } catch (IsmbSnepException e) {
            e.printStackTrace();
        }

        try {
            Thread.sleep(200);
        } catch (InterruptedException e1) {
            e1.printStackTrace();
        }

        try {
            //GETDATA
            transceive(TG_GET_DATA, null);
        } catch (IsmbSnepException e) {
            e.printStackTrace();
        }

        try {
            Thread.sleep(300);
        } catch (InterruptedException e1) {
            e1.printStackTrace();
        }

        //WAIT FOR A  Connect request                                 
        while (true) {
            try {
                byte[] targetPayload = { (byte) 0x00, (byte) 0x00, };
                transceive(TG_SET_DATA, targetPayload);
            } catch (IsmbSnepException e) {
                e.printStackTrace();
            }

            try {
                Thread.sleep(300);
            } catch (InterruptedException e1) {
                e1.printStackTrace();
            }

            try { //GETDATA
                byte[] array = transceive(TG_GET_DATA, null);

                if ((byte) array[1] == (byte) 0x11) { //RECEIVE SOMETHING SIMILAR TO 0x11 0x20      
                    break;
                }
            } catch (IsmbSnepException e) {
                e.printStackTrace();
            }

            try {
                Thread.sleep(300);
            } catch (InterruptedException e1) {
                e1.printStackTrace();
            }
        }
        //SEND CC - CONNECTION COMPLETE           
        try {
            byte[] targetPayload = { (byte) 0x81, (byte) 0x84 };
            transceive(TG_SET_DATA, targetPayload);
        } catch (IsmbSnepException e) {
            e.printStackTrace();
        }

        try {
            Thread.sleep(300);
        } catch (InterruptedException e1) {
            e1.printStackTrace();
        }

        //WAIT FOR A SNEP REQUEST
        while (true) {
            try {
                byte[] targetPayload = { (byte) 0x00, (byte) 0x00, };
                transceive(TG_SET_DATA, targetPayload);
            } catch (IsmbSnepException e) {
                e.printStackTrace();
            }

            try {
                Thread.sleep(300);
            } catch (InterruptedException e1) {
                e1.printStackTrace();
            }

            /**
             * The main part of communication between reader and arduino
             */
            try { //GETDATA
                byte[] array = transceive(TG_GET_DATA, null);
                System.out.println("Income data length: " + array.length);
                if (array.length > 5) {
                    //Initial a serial communication channel and pass this data to Arduino board
                    //String stringFromArray = Util.byteArrayToAsciiString(array);
                    String stringFromArray = IOUtils.toString(array, "UTF-8");
                    //System.out.println("Something received: \n"+ "   Hex:" + Util.bytesToHex(array) + "\n   ASCII:" + Util.byteArrayToAsciiString(array));
                    System.out.println("Something received: \n" + stringFromArray);
                    serialCommWithArduino(stringFromArray);

                    break;
                }
            } catch (IsmbSnepException e) {
                e.printStackTrace();
            }

            try {
                Thread.sleep(300);
            } catch (InterruptedException e1) {
                e1.printStackTrace();
            }
        }

        //SNEP REQUEST RECEIVED
        try {
            byte[] targetPayload = { (byte) 0x83, (byte) 0x44, (byte) 0x01 }; //Receive Ready   
            transceive(TG_SET_DATA, targetPayload);
        } catch (IsmbSnepException e) {
            e.printStackTrace();
        }

        try {
            Thread.sleep(300);
        } catch (InterruptedException e1) {
            e1.printStackTrace();
        }

        try { //GETDATA
            byte[] array = transceive(TG_GET_DATA, null);
        } catch (IsmbSnepException e) {
            e.printStackTrace();
        }

        try {
            Thread.sleep(300);
        } catch (InterruptedException e1) {
            e1.printStackTrace();
        }

        try {
            byte[] targetPayload = { (byte) 0x83, (byte) 0x04, (byte) 0x01, (byte) 0x10, (byte) 0x81, (byte) 0x00,
                    (byte) 0x00, (byte) 0x00, (byte) 0x00 //LENGTH
            };
            transceive(TG_SET_DATA, targetPayload);
        } catch (IsmbSnepException e) {
            e.printStackTrace();
        }

        //WAIT FOR RR
        try {
            Thread.sleep(600);
        } catch (InterruptedException e1) {
            e1.printStackTrace();
        }

        try { //GETDATA
            byte[] array = transceive(TG_GET_DATA, null);
        } catch (IsmbSnepException e) {
            e.printStackTrace();
        }

        try {
            byte[] targetPayload = { (byte) 0x00, (byte) 0x00, };
            transceive(TG_SET_DATA, targetPayload);
        } catch (IsmbSnepException e) {
            e.printStackTrace();
        }

        try { //GETDATA
            byte[] array = transceive(TG_GET_DATA, null);
        } catch (IsmbSnepException e) {
            e.printStackTrace();
        }

        try {
            Thread.sleep(300);
        } catch (InterruptedException e1) {
            e1.printStackTrace();
        }

        try {
            byte[] targetPayload = { (byte) 0x81, (byte) 0xC4, (byte) 0x00 }; //Disconnected Mode
            transceive(TG_SET_DATA, targetPayload);
        } catch (IsmbSnepException e) {
            e.printStackTrace();
        }

        try {
            Thread.sleep(300);
        } catch (InterruptedException e1) {
            e1.printStackTrace();
        }

        try { //GETDATA
            byte[] array = transceive(TG_GET_DATA, null);
        } catch (IsmbSnepException e) {
            e.printStackTrace();
        }

        try {
            Thread.sleep(300);
        } catch (InterruptedException e1) {
            e1.printStackTrace();
        }

    }

    private void serialCommWithArduino(String arg) {
        // TODO Auto-generated method stub
        try {
            SerialClass obj = new SerialClass();
            obj.initialize();
            //wait for arduino board's initialization, o.w. the board will fail to get input
            Thread.sleep(2000);

            int c = 0;
            String Token = arg.substring(arg.length() - 119);
            System.out.println("the full token is>> " + Token);
            c = Authentication.authenticate(Token);
            input = SerialClass.input;
            output = SerialClass.output;

            switch (c) {

            case 0:
                SerialClass.writeData("0");
                System.out.println("Authentication failed>> " + Token);
                break;
            case 1:
                SerialClass.writeData("1");
                System.out.println("the input beam is>> " + Token);
                break;
            case 3:
                System.exit(0);
            }

            String inputLine = input.readLine();
            System.out.println(inputLine);

            obj.close();
        } catch (Exception e) {

        }
    }
}