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
1 package de.dhbwloe.campusapp.nfcreader.MifareDESFire;
2
3 import android.nfc.tech.IsoDep;
4 import android.util.Log;
5
6 import de.dhbwloe.campusapp.nfcreader.Hex;
7 import de.dhbwloe.campusapp.nfcreader.UndefinedResponseException;
8
9 import java.io.IOException;
10 import java.util.ArrayList;
11
12 /**
13  * Created by stefan on 21.01.16.
14  */
15 public class MifareDESFireWrapper implements IsoDepWrapper  {
16     public final static String CODE_OK = "00";
17     public final static String CODE_MORE_DATA = "AF";
18     public final static String CODE_PERMISSION_DENIED = "9D";
19     public final static String CODE_APPLICATION_NOT_FOUND = "A0";
20     public final static String CODE_INVALID_COMMAND_LENGTH = "7E";
21
22     private IsoDep tag;
23     public static final String LOG_TAG = "MifareDESFireWrapper";
24
25     //TODO: Add all desfire functionality
26
27     public MifareDESFireWrapper(IsoDep tag) {
28         this.tag = tag;
29     }
30
31     /**
32      * @param applicationID Application id in following Format: "AD 00 03" (3 Hex digits)
33      * @throws UndefinedResponseException Thrown when the tag returns an undefined response
34      */
35     public void selectApplication(String applicationID) throws UndefinedResponseException, CommunicationError {
36         sendCommand("5A " + applicationID);
37     }
38
39     /**
40      * @param fileId The file id
41      * @return Returns the value of the value file
42      * @throws UndefinedResponseException Thrown when the tag returns an undefined response
43      */
44     public int readValueFile(String fileId) throws UndefinedResponseException, CommunicationError {
45         return Hex.hexToInteger(Hex.reverseByteOrder(this.sendCommand("6C " + fileId)));
46     }
47
48     /**
49      * @param fileId The file id
50      * @return Returns the FileSettings
51      * @throws UndefinedResponseException Thrown when the tag returns an undefined response
52      */
53     public FileSettings readFileSettings(String fileId) throws UndefinedResponseException, CommunicationError {
54         Byte[] data = sendCommand("F5 "+fileId);
55         FileSettings fileSettings = ValueFileSettings.createByRawData(data);
56         //TODO: Changeme
57         return fileSettings;
58     }
59
60     /**
61      * @return Returns the DesfireManufacturingData
62      * @throws UndefinedResponseException Thrown when the tag returns an undefined response
63      */
64     public DesfireManufacturingData readManufacturingData() throws UndefinedResponseException, CommunicationError {
65         Byte[] data = sendCommand("60");
66
67         if (data.length != 28)
68             throw new UndefinedResponseException();
69
70         return new DesfireManufacturingData(Hex.bytesToPrimitives(data));
71     }
72
73     /**
74      * @param command Command to send to the tag (Format example: "AF 00 01 EF 01"
75      * @return
76      * @throws UndefinedResponseException
77      */
78     public Byte[] sendCommand(String command) throws UndefinedResponseException, CommunicationError {
79         connect();
80         try {
81             ArrayList<Byte> fullResponse = new ArrayList<Byte>();
82             boolean receiving = true;
83             String responseCode = null;
84             Log.d(LOG_TAG, "Sending command: "+command);
85             while (receiving) {
86                 Log.d(LOG_TAG, "Sending command: "+command);
87                 byte[] rawResponse = tag.transceive(Hex.bytesToPrimitives(Hex.stringToHex(command)));
88                 String response = Hex.hexToString(Hex.bytesToObjects(rawResponse));
89                 responseCode = response.substring(0, 2);
90                 appendSubArray(2, rawResponse, fullResponse);
91                 Log.d(LOG_TAG, "Response code is: " + responseCode);
92                 Log.v(LOG_TAG, "Response is: "+response);
93                 if (!responseCode.equals(CODE_MORE_DATA)) {
94                     Log.d(LOG_TAG, "No more data to receive");
95                     receiving = false;
96                 }
97                 // Request more data
98                 command = CODE_MORE_DATA;
99                 Log.d(LOG_TAG, "More data to receive");
100             }
101
102             if (responseCode.equals(CODE_OK)) {
103                 Log.d(LOG_TAG, "Received all data");
104                 Log.v(LOG_TAG, "Full response is: " + fullResponse);
105                 return fullResponse.toArray(new Byte[0]);
106             } else if (responseCode.equals(CODE_INVALID_COMMAND_LENGTH)) {
107                 Log.e(LOG_TAG, "Invalid command length");
108                 throw new CommunicationError("Invalid command length");
109
110             } else if (responseCode.equals(CODE_APPLICATION_NOT_FOUND)) {
111                 Log.e(LOG_TAG, "Application not found");
112                 throw  new CommunicationError("Application not found");
113             } else if(responseCode.equals(CODE_PERMISSION_DENIED)) {
114                 Log.e(LOG_TAG, "Permission denied");
115                 throw new CommunicationError("Permission denied");
116             }
117             else {
118                 Log.e(LOG_TAG, "Undefined response code");
119                 throw new UndefinedResponseException();
120             }
121
122
123
124         } catch (IOException e) {
125             e.printStackTrace();
126         }
127         return null;
128     }
129
130     private void appendSubArray(int start, byte[] array, ArrayList<Byte> arrayList) {
131         for (int i=start-1; i<array.length; i++) {
132             arrayList.add(array[i]);
133         }
134     }
135
136     private void connect() {
137         if (!tag.isConnected())
138             try {
139                 tag.connect();
140             } catch (IOException e) {
141                 e.printStackTrace();
142             }
143     }
144 }