ProjectLaogai/app/src/main/java/com/codebutler/farebot/card/desfire/DesfireFileSettings.java

241 lines
8.3 KiB
Java

/*
* DesfireFileSettings.java
*
* Copyright (C) 2011 Eric Butler
*
* Authors:
* Eric Butler <eric@codebutler.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.codebutler.farebot.card.desfire;
import java.io.ByteArrayInputStream;
import org.apache.commons.lang3.ArrayUtils;
import android.os.Parcel;
import android.os.Parcelable;
import com.codebutler.farebot.Utils;
public abstract class DesfireFileSettings implements Parcelable {
public final byte fileType;
public final byte commSetting;
public final byte[] accessRights;
/* DesfireFile Types */
static final byte STANDARD_DATA_FILE = (byte) 0x00;
static final byte BACKUP_DATA_FILE = (byte) 0x01;
static final byte VALUE_FILE = (byte) 0x02;
static final byte LINEAR_RECORD_FILE = (byte) 0x03;
static final byte CYCLIC_RECORD_FILE = (byte) 0x04;
public static DesfireFileSettings Create (byte[] data) throws DesfireException {
byte fileType = (byte) data[0];
ByteArrayInputStream stream = new ByteArrayInputStream(data);
if (fileType == STANDARD_DATA_FILE || fileType == BACKUP_DATA_FILE)
return new StandardDesfireFileSettings(stream);
else if (fileType == LINEAR_RECORD_FILE || fileType == CYCLIC_RECORD_FILE)
return new RecordDesfireFileSettings(stream);
else if (fileType == VALUE_FILE)
return new ValueDesfireFileSettings(stream);
else
throw new DesfireException("Unknown file type: " + Integer.toHexString(fileType));
}
private DesfireFileSettings (ByteArrayInputStream stream) {
fileType = (byte) stream.read();
commSetting = (byte) stream.read();
accessRights = new byte[2];
stream.read(accessRights, 0, accessRights.length);
}
private DesfireFileSettings (byte fileType, byte commSetting, byte[] accessRights) {
this.fileType = fileType;
this.commSetting = commSetting;
this.accessRights = accessRights;
}
public String getFileTypeName () {
switch (fileType) {
case STANDARD_DATA_FILE:
return "Standard";
case BACKUP_DATA_FILE:
return "Backup";
case VALUE_FILE:
return "Value";
case LINEAR_RECORD_FILE:
return "Linear Record";
case CYCLIC_RECORD_FILE:
return "Cyclic Record";
default:
return "Unknown";
}
}
public static final Parcelable.Creator<DesfireFileSettings> CREATOR = new Parcelable.Creator<DesfireFileSettings>() {
public DesfireFileSettings createFromParcel(Parcel source) {
byte fileType = source.readByte();
byte commSetting = source.readByte();
byte[] accessRights = new byte[source.readInt()];
source.readByteArray(accessRights);
if (fileType == STANDARD_DATA_FILE || fileType == BACKUP_DATA_FILE) {
int fileSize = source.readInt();
return new StandardDesfireFileSettings(fileType, commSetting, accessRights, fileSize);
} else if (fileType == LINEAR_RECORD_FILE || fileType == CYCLIC_RECORD_FILE) {
int recordSize = source.readInt();
int maxRecords = source.readInt();
int curRecords = source.readInt();
return new RecordDesfireFileSettings(fileType, commSetting, accessRights, recordSize, maxRecords, curRecords);
} else {
return new UnsupportedDesfireFileSettings(fileType);
}
}
public DesfireFileSettings[] newArray(int size) {
return new DesfireFileSettings[size];
}
};
public void writeToParcel (Parcel parcel, int flags) {
parcel.writeByte(fileType);
parcel.writeByte(commSetting);
parcel.writeInt(accessRights.length);
parcel.writeByteArray(accessRights);
}
public int describeContents () {
return 0;
}
public static class StandardDesfireFileSettings extends DesfireFileSettings {
public final int fileSize;
private StandardDesfireFileSettings (ByteArrayInputStream stream) {
super(stream);
byte[] buf = new byte[3];
stream.read(buf, 0, buf.length);
ArrayUtils.reverse(buf);
fileSize = Utils.byteArrayToInt(buf);
}
StandardDesfireFileSettings (byte fileType, byte commSetting, byte[] accessRights, int fileSize) {
super(fileType, commSetting, accessRights);
this.fileSize = fileSize;
}
@Override
public void writeToParcel (Parcel parcel, int flags) {
super.writeToParcel(parcel, flags);
parcel.writeInt(fileSize);
}
}
public static class RecordDesfireFileSettings extends DesfireFileSettings {
public final int recordSize;
public final int maxRecords;
public final int curRecords;
public RecordDesfireFileSettings(ByteArrayInputStream stream) {
super(stream);
byte[] buf = new byte[3];
stream.read(buf, 0, buf.length);
ArrayUtils.reverse(buf);
recordSize = Utils.byteArrayToInt(buf);
buf = new byte[3];
stream.read(buf, 0, buf.length);
ArrayUtils.reverse(buf);
maxRecords = Utils.byteArrayToInt(buf);
buf = new byte[3];
stream.read(buf, 0, buf.length);
ArrayUtils.reverse(buf);
curRecords = Utils.byteArrayToInt(buf);
}
RecordDesfireFileSettings (byte fileType, byte commSetting, byte[] accessRights, int recordSize, int maxRecords, int curRecords) {
super(fileType, commSetting, accessRights);
this.recordSize = recordSize;
this.maxRecords = maxRecords;
this.curRecords = curRecords;
}
@Override
public void writeToParcel (Parcel parcel, int flags) {
super.writeToParcel(parcel, flags);
parcel.writeInt(recordSize);
parcel.writeInt(maxRecords);
parcel.writeInt(curRecords);
}
}
public static class ValueDesfireFileSettings extends DesfireFileSettings {
public final int lowerLimit;
public final int upperLimit;
public final int value;
public final byte limitedCreditEnabled;
public ValueDesfireFileSettings(ByteArrayInputStream stream) {
super(stream);
byte[] buf = new byte[4];
stream.read(buf, 0, buf.length);
ArrayUtils.reverse(buf);
lowerLimit = Utils.byteArrayToInt(buf);
buf = new byte[4];
stream.read(buf, 0, buf.length);
ArrayUtils.reverse(buf);
upperLimit = Utils.byteArrayToInt(buf);
buf = new byte[4];
stream.read(buf, 0, buf.length);
ArrayUtils.reverse(buf);
value = Utils.byteArrayToInt(buf);
buf = new byte[1];
stream.read(buf, 0, buf.length);
limitedCreditEnabled = buf[0];
//http://www.skyetek.com/docs/m2/desfire.pdf
//http://neteril.org/files/M075031_desfire.pdf
}
@Override
public void writeToParcel (Parcel parcel, int flags) {
super.writeToParcel(parcel, flags);
parcel.writeInt(lowerLimit);
parcel.writeInt(upperLimit);
parcel.writeInt(value);
parcel.writeByte(limitedCreditEnabled);
}
}
public static class UnsupportedDesfireFileSettings extends DesfireFileSettings {
public UnsupportedDesfireFileSettings(byte fileType) {
super(fileType, Byte.MIN_VALUE, new byte[0]);
}
}
}