Implemented NFC Card Reader Code from https://git.sterul.com/student-projects/dhbw...
[DHBWCampusApp.git] / app / src / main / java / de / dhbwloe / campusapp / nfcreader / MifareDESFire / MifareDESFireWrapper.java
diff --git a/app/src/main/java/de/dhbwloe/campusapp/nfcreader/MifareDESFire/MifareDESFireWrapper.java b/app/src/main/java/de/dhbwloe/campusapp/nfcreader/MifareDESFire/MifareDESFireWrapper.java
new file mode 100644 (file)
index 0000000..7a151bc
--- /dev/null
@@ -0,0 +1,144 @@
+package de.dhbwloe.campusapp.nfcreader.MifareDESFire;
+
+import android.nfc.tech.IsoDep;
+import android.util.Log;
+
+import de.dhbwloe.campusapp.nfcreader.Hex;
+import de.dhbwloe.campusapp.nfcreader.UndefinedResponseException;
+
+import java.io.IOException;
+import java.util.ArrayList;
+
+/**
+ * Created by stefan on 21.01.16.
+ */
+public class MifareDESFireWrapper implements IsoDepWrapper  {
+    public final static String CODE_OK = "00";
+    public final static String CODE_MORE_DATA = "AF";
+    public final static String CODE_PERMISSION_DENIED = "9D";
+    public final static String CODE_APPLICATION_NOT_FOUND = "A0";
+    public final static String CODE_INVALID_COMMAND_LENGTH = "7E";
+
+    private IsoDep tag;
+    public static final String LOG_TAG = "MifareDESFireWrapper";
+
+    //TODO: Add all desfire functionality
+
+    public MifareDESFireWrapper(IsoDep tag) {
+        this.tag = tag;
+    }
+
+    /**
+     * @param applicationID Application id in following Format: "AD 00 03" (3 Hex digits)
+     * @throws UndefinedResponseException Thrown when the tag returns an undefined response
+     */
+    public void selectApplication(String applicationID) throws UndefinedResponseException, CommunicationError {
+        sendCommand("5A " + applicationID);
+    }
+
+    /**
+     * @param fileId The file id
+     * @return Returns the value of the value file
+     * @throws UndefinedResponseException Thrown when the tag returns an undefined response
+     */
+    public int readValueFile(String fileId) throws UndefinedResponseException, CommunicationError {
+        return Hex.hexToInteger(Hex.reverseByteOrder(this.sendCommand("6C " + fileId)));
+    }
+
+    /**
+     * @param fileId The file id
+     * @return Returns the FileSettings
+     * @throws UndefinedResponseException Thrown when the tag returns an undefined response
+     */
+    public FileSettings readFileSettings(String fileId) throws UndefinedResponseException, CommunicationError {
+        Byte[] data = sendCommand("F5 "+fileId);
+        FileSettings fileSettings = ValueFileSettings.createByRawData(data);
+        //TODO: Changeme
+        return fileSettings;
+    }
+
+    /**
+     * @return Returns the DesfireManufacturingData
+     * @throws UndefinedResponseException Thrown when the tag returns an undefined response
+     */
+    public DesfireManufacturingData readManufacturingData() throws UndefinedResponseException, CommunicationError {
+        Byte[] data = sendCommand("60");
+
+        if (data.length != 28)
+            throw new UndefinedResponseException();
+
+        return new DesfireManufacturingData(Hex.bytesToPrimitives(data));
+    }
+
+    /**
+     * @param command Command to send to the tag (Format example: "AF 00 01 EF 01"
+     * @return
+     * @throws UndefinedResponseException
+     */
+    public Byte[] sendCommand(String command) throws UndefinedResponseException, CommunicationError {
+        connect();
+        try {
+            ArrayList<Byte> fullResponse = new ArrayList<Byte>();
+            boolean receiving = true;
+            String responseCode = null;
+            Log.d(LOG_TAG, "Sending command: "+command);
+            while (receiving) {
+                Log.d(LOG_TAG, "Sending command: "+command);
+                byte[] rawResponse = tag.transceive(Hex.bytesToPrimitives(Hex.stringToHex(command)));
+                String response = Hex.hexToString(Hex.bytesToObjects(rawResponse));
+                responseCode = response.substring(0, 2);
+                appendSubArray(2, rawResponse, fullResponse);
+                Log.d(LOG_TAG, "Response code is: " + responseCode);
+                Log.v(LOG_TAG, "Response is: "+response);
+                if (!responseCode.equals(CODE_MORE_DATA)) {
+                    Log.d(LOG_TAG, "No more data to receive");
+                    receiving = false;
+                }
+                // Request more data
+                command = CODE_MORE_DATA;
+                Log.d(LOG_TAG, "More data to receive");
+            }
+
+            if (responseCode.equals(CODE_OK)) {
+                Log.d(LOG_TAG, "Received all data");
+                Log.v(LOG_TAG, "Full response is: " + fullResponse);
+                return fullResponse.toArray(new Byte[0]);
+            } else if (responseCode.equals(CODE_INVALID_COMMAND_LENGTH)) {
+                Log.e(LOG_TAG, "Invalid command length");
+                throw new CommunicationError("Invalid command length");
+
+            } else if (responseCode.equals(CODE_APPLICATION_NOT_FOUND)) {
+                Log.e(LOG_TAG, "Application not found");
+                throw  new CommunicationError("Application not found");
+            } else if(responseCode.equals(CODE_PERMISSION_DENIED)) {
+                Log.e(LOG_TAG, "Permission denied");
+                throw new CommunicationError("Permission denied");
+            }
+            else {
+                Log.e(LOG_TAG, "Undefined response code");
+                throw new UndefinedResponseException();
+            }
+
+
+
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    private void appendSubArray(int start, byte[] array, ArrayList<Byte> arrayList) {
+        for (int i=start-1; i<array.length; i++) {
+            arrayList.add(array[i]);
+        }
+    }
+
+    private void connect() {
+        if (!tag.isConnected())
+            try {
+                tag.connect();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+    }
+}