Grundaufbau der App
[DHBWCampusApp.git] / app / src / main / java / com / codebutler / farebot / card / desfire / DesfireFileSettings.java
1 /*
2  * DesfireFileSettings.java
3  *
4  * Copyright (C) 2011 Eric Butler
5  *
6  * Authors:
7  * Eric Butler <eric@codebutler.com>
8  *
9  * This program is free software: you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 3 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21  */
22
23 package com.codebutler.farebot.card.desfire;
24
25 import java.io.ByteArrayInputStream;
26
27 import org.apache.commons.lang3.ArrayUtils;
28
29 import android.os.Parcel;
30 import android.os.Parcelable;
31
32 import com.codebutler.farebot.Utils;
33
34 public abstract class DesfireFileSettings implements Parcelable {
35     public final byte   fileType;
36     public final byte   commSetting;
37     public final byte[] accessRights;
38
39     /* DesfireFile Types */
40     static final byte STANDARD_DATA_FILE = (byte) 0x00;
41     static final byte BACKUP_DATA_FILE   = (byte) 0x01;
42     static final byte VALUE_FILE         = (byte) 0x02;
43     static final byte LINEAR_RECORD_FILE = (byte) 0x03;
44     static final byte CYCLIC_RECORD_FILE = (byte) 0x04;
45     
46     public static DesfireFileSettings Create (byte[] data) throws DesfireException {
47         byte fileType = (byte) data[0];
48
49         ByteArrayInputStream stream = new ByteArrayInputStream(data);
50
51         if (fileType == STANDARD_DATA_FILE || fileType == BACKUP_DATA_FILE)
52             return new StandardDesfireFileSettings(stream);
53         else if (fileType == LINEAR_RECORD_FILE || fileType == CYCLIC_RECORD_FILE)
54             return new RecordDesfireFileSettings(stream);
55         else if (fileType == VALUE_FILE)
56             return new ValueDesfireFileSettings(stream);
57         else
58             throw new DesfireException("Unknown file type: " + Integer.toHexString(fileType));
59     }
60
61     private DesfireFileSettings (ByteArrayInputStream stream) {
62         fileType    = (byte) stream.read();
63         commSetting = (byte) stream.read();
64
65         accessRights = new byte[2];
66         stream.read(accessRights, 0, accessRights.length);
67     }
68
69     private DesfireFileSettings (byte fileType, byte commSetting, byte[] accessRights) {
70         this.fileType     = fileType;
71         this.commSetting  = commSetting;
72         this.accessRights = accessRights;
73     }
74
75     public String getFileTypeName () {
76         switch (fileType) {
77             case STANDARD_DATA_FILE:
78                 return "Standard";
79             case BACKUP_DATA_FILE:
80                 return "Backup";
81             case VALUE_FILE:
82                 return "Value";
83             case LINEAR_RECORD_FILE:
84                 return "Linear Record";
85             case CYCLIC_RECORD_FILE:
86                 return "Cyclic Record";
87             default:
88                 return "Unknown";
89         }
90     }
91
92     public static final Parcelable.Creator<DesfireFileSettings> CREATOR = new Parcelable.Creator<DesfireFileSettings>() {
93         public DesfireFileSettings createFromParcel(Parcel source) {
94             byte fileType       = source.readByte();
95             byte commSetting    = source.readByte();
96             byte[] accessRights = new byte[source.readInt()];
97             source.readByteArray(accessRights);
98
99             if (fileType == STANDARD_DATA_FILE || fileType == BACKUP_DATA_FILE) {
100                 int fileSize = source.readInt();
101                 return new StandardDesfireFileSettings(fileType, commSetting, accessRights, fileSize);
102             } else if (fileType == LINEAR_RECORD_FILE || fileType == CYCLIC_RECORD_FILE) {
103                 int recordSize = source.readInt();
104                 int maxRecords = source.readInt();
105                 int curRecords = source.readInt();
106                 return new RecordDesfireFileSettings(fileType, commSetting, accessRights, recordSize, maxRecords, curRecords);
107             } else {
108                 return new UnsupportedDesfireFileSettings(fileType);
109             }
110         }
111
112         public DesfireFileSettings[] newArray(int size) {
113             return new DesfireFileSettings[size];
114         }
115     };
116
117     public void writeToParcel (Parcel parcel, int flags) {
118         parcel.writeByte(fileType);
119         parcel.writeByte(commSetting);
120         parcel.writeInt(accessRights.length);
121         parcel.writeByteArray(accessRights);
122     }
123
124     public int describeContents () {
125         return 0;
126     }
127
128     public static class StandardDesfireFileSettings extends DesfireFileSettings {
129         public final int fileSize;
130
131         private StandardDesfireFileSettings (ByteArrayInputStream stream) {
132             super(stream);
133             byte[] buf = new byte[3];
134             stream.read(buf, 0, buf.length);
135             ArrayUtils.reverse(buf);
136             fileSize = Utils.byteArrayToInt(buf);
137         }
138
139         StandardDesfireFileSettings (byte fileType, byte commSetting, byte[] accessRights, int fileSize) {
140             super(fileType, commSetting, accessRights);
141             this.fileSize = fileSize;
142         }
143
144         @Override
145         public void writeToParcel (Parcel parcel, int flags) {
146             super.writeToParcel(parcel, flags);
147             parcel.writeInt(fileSize);
148         }
149     }
150
151     public static class RecordDesfireFileSettings extends DesfireFileSettings {
152         public final int recordSize;
153         public final int maxRecords;
154         public final int curRecords;
155
156         public RecordDesfireFileSettings(ByteArrayInputStream stream) {
157             super(stream);
158
159             byte[] buf = new byte[3];
160             stream.read(buf, 0, buf.length);
161             ArrayUtils.reverse(buf);
162             recordSize = Utils.byteArrayToInt(buf);
163
164             buf = new byte[3];
165             stream.read(buf, 0, buf.length);
166             ArrayUtils.reverse(buf);
167             maxRecords = Utils.byteArrayToInt(buf);
168
169             buf = new byte[3];
170             stream.read(buf, 0, buf.length);
171             ArrayUtils.reverse(buf);
172             curRecords = Utils.byteArrayToInt(buf);
173         }
174
175         RecordDesfireFileSettings (byte fileType, byte commSetting, byte[] accessRights, int recordSize, int maxRecords, int curRecords) {
176             super(fileType, commSetting, accessRights);
177             this.recordSize = recordSize;
178             this.maxRecords = maxRecords;
179             this.curRecords = curRecords;
180         }
181
182         @Override
183         public void writeToParcel (Parcel parcel, int flags) {
184             super.writeToParcel(parcel, flags);
185             parcel.writeInt(recordSize);
186             parcel.writeInt(maxRecords);
187             parcel.writeInt(curRecords);
188         }
189     }
190
191
192
193
194     public static class ValueDesfireFileSettings extends DesfireFileSettings {
195         public final int lowerLimit;
196         public final int upperLimit;
197         public final int value;
198         public final byte limitedCreditEnabled;
199
200         public ValueDesfireFileSettings(ByteArrayInputStream stream) {
201             super(stream);
202
203             byte[] buf = new byte[4];
204             stream.read(buf, 0, buf.length);
205             ArrayUtils.reverse(buf);
206             lowerLimit = Utils.byteArrayToInt(buf);
207
208             buf = new byte[4];
209             stream.read(buf, 0, buf.length);
210             ArrayUtils.reverse(buf);
211             upperLimit = Utils.byteArrayToInt(buf);
212
213             buf = new byte[4];
214             stream.read(buf, 0, buf.length);
215             ArrayUtils.reverse(buf);
216             value = Utils.byteArrayToInt(buf);
217             
218
219             buf = new byte[1];
220             stream.read(buf, 0, buf.length);
221             limitedCreditEnabled = buf[0];
222             
223             //http://www.skyetek.com/docs/m2/desfire.pdf
224             //http://neteril.org/files/M075031_desfire.pdf
225         }
226
227         @Override
228         public void writeToParcel (Parcel parcel, int flags) {
229             super.writeToParcel(parcel, flags);
230             parcel.writeInt(lowerLimit);
231             parcel.writeInt(upperLimit);
232             parcel.writeInt(value);
233             parcel.writeByte(limitedCreditEnabled);
234         }
235     }
236     public static class UnsupportedDesfireFileSettings extends DesfireFileSettings {
237         public UnsupportedDesfireFileSettings(byte fileType) {
238             super(fileType, Byte.MIN_VALUE, new byte[0]);
239         }
240     }
241 }