/**
*
* @author Sebastien Riou
*/
package uk.co.nimp.smartcard;
import com.atolsystems.atolutilities.*;
import javax.smartcardio.ATR;
public class AnswerToReset {
protected ATR data;
protected Integer tA1;
protected Integer tD1Index;
protected Integer tA2Index;
protected Boolean hasTa2;
protected Integer tA2;
public static final int fiTable[]={372, 372, 558, 744, 1116, 1488, 1860, -1,
-1, 512, 768, 1024, 1536, 2048, -1,-1};
public static final int diTable[]={-1, 1, 2, 4, 8, 16, 32, 64,
12, 20, -1, -1, -1, -1, -1, -1};
@Override
public boolean equals(Object obj) {
if(false==(obj instanceof AnswerToReset))
return false;
AnswerToReset theOther=(AnswerToReset) obj;
return theOther.data.equals(data);
}
@Override
public int hashCode() {
int hash = 7;
hash = 59 * hash + (this.data != null ? this.data.hashCode() : 0);
return hash;
}
public static int fiDi2cyclesPerEtu(int fiDi){
return fiDi2cyclesPerEtu(fiDi>>4, fiDi & 0x0F);
}
public static int fiDi2cyclesPerEtu(int fi, int di){
int fiValue=fiTable[fi];
int diValue=diTable[di];
if(fiValue<0)
throw new RuntimeException("unknown Fi parameter: 0x"+Integer.toHexString(fi));
if(diValue<0)
throw new RuntimeException("unknown Di parameter: 0x"+Integer.toHexString(di));
if((fiValue%diValue)>0)
throw new RuntimeException("Fi/Di is not an integer value");
return fiValue/diValue;
}
public AnswerToReset(AnswerToReset atr) {
this.data = new ATR(atr.getData());
}
public AnswerToReset(byte[] data) {
this.data = new ATR(data);
}
public AnswerToReset(byte[] data, int offset, int length) {
byte[] actualData = new byte[length];
for (int i = 0; i < length; i++) {
actualData[i] = data[i + offset];
}
this.data = new ATR(actualData);
}
public AnswerToReset() {
}
protected void init(){
tD1Index=null;
tA2Index=null;
tA2=null;
}
/**
* Get the value of data
*
* @return the value of data
*/
public byte[] getData() {
return data.getBytes();
}
public byte[] getHistoricalBytes() {
return data.getHistoricalBytes();
}
/**
* Set the value of data
*
* @param data new value of data
*/
public void setData(byte[] data) {
this.data = new ATR(data);
}
/**
* Get the value of data at specified index
*
* @param index
* @return the value of data at specified index
*/
public byte getData(int index) {
return data.getBytes()[index];
}
@Override
public String toString() {
return AStringUtilities.bytesToHex(data.getBytes());
}
public boolean isDirectConvention() {
return (data.getBytes()[0] == 0x3B);
}
public int getT0() {
return data.getBytes()[1];
}
public boolean hasTa1(){
boolean out = false;
int t0 = data.getBytes()[1];
if (0x10 == (t0 & 0x10)) {
tA1 = 0xFF & data.getBytes()[2];
out=true;
}else{
tA1=0x11;
}
return out;
}
public int getTa1(){
if (null == tA1) {
hasTa1();
}
return tA1;
}
public boolean hasTa2() {
if(null!=hasTa2)
return hasTa2;
boolean out = false;
int t0 = data.getBytes()[1];
if (0x80 == (t0 & 0x80)) {
int n = t0 & 0x70;
tD1Index = 2 + Integer.bitCount(n);
int tD1 = data.getBytes()[tD1Index];
if (0x10 == (tD1 & 0x10)) {
//TA2 is present
out = true;
}
}
hasTa2=out;
return out;
}
public int getTd1Index() {
if (null == tD1Index) {
int T0 = data.getBytes()[1];
if (0x00 == (T0 & 0x80)) {
tD1Index = -64;
} else {
int n = T0 & 0x70;
tD1Index = 2 + Integer.bitCount(n);
}
}
return tD1Index;
}
public int getTa2Index() {
if(false==hasTa2())
return -63;
if (null == tA2Index) {
tA2Index = getTd1Index() + 1;
}
return tA2Index;
}
public int getTa2() {
if(false==hasTa2())
tA2=0x00;
if (null == tA2) {
if (getTa2Index() > 0) {
tA2 = 0xFF & data.getBytes()[tA2Index];
} else {
tA2 = 0x00;//default value
}
}
return tA2;
}
public boolean isInSpecificMode() {
boolean out = true;
if (0x80 == (getTa2() & 0x80)) {
out = false;
}
return out;
}
public int getSupportedFiDi() {
if (0x00 == (getTa2() & 0x10)) {
return getTa1();
}
return 0x11;
}
public boolean acceptPps(){
boolean out=false;
/*if(0x00 == (getTa2() & 0x10)) {
out=true;
}*/
out=!hasTa2();
return out;
}
}