PCSC4Java  0.2
Library PCSC for Java language.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
D:/Affaire/Perso/SmartCardToolBox/pcsc4java-framework-0.2/src/fr/redbilled/pcscforjava/ATR.java
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
00003  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
00004  *
00005  * This code is free software; you can redistribute it and/or modify it
00006  * under the terms of the GNU General Public License version 2 only, as
00007  * published by the Free Software Foundation.  Oracle designates this
00008  * particular file as subject to the "Classpath" exception as provided
00009  * by Oracle in the LICENSE file that accompanied this code.
00010  *
00011  * This code is distributed in the hope that it will be useful, but WITHOUT
00012  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00013  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00014  * version 2 for more details (a copy is included in the LICENSE file that
00015  * accompanied this code).
00016  *
00017  * You should have received a copy of the GNU General Public License version
00018  * 2 along with this work; if not, write to the Free Software Foundation,
00019  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
00020  *
00021  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
00022  * or visit www.oracle.com if you need additional information or have any
00023  * questions.
00024  */
00025 
00026 package fr.redbilled.pcscforjava;
00027 
00028 import java.util.*;
00029 
00045 public final class ATR implements java.io.Serializable {
00046 
00047     private static final long serialVersionUID = 6695383790847736493L;
00048 
00049     private byte[]          atr;
00050 
00051     private transient int   startHistorical, nHistorical;
00052     
00053     private String          sConvention;
00054     private byte            BTs;
00055     private byte            BT0;
00056     
00057     private boolean         bIsNegotiable;
00058     private boolean         bIsAbleToChangeSpecificNegotiableMode;
00059     private boolean         bAreTransmissionParametersImplicitlyKnownByTerminal;
00060     
00061     private ArrayList<Byte> aBTai;
00062     private ArrayList<Byte> aBTbi;
00063     private ArrayList<Byte> aBTci;
00064     private ArrayList<Byte> aBTdi;
00065     
00066     private ArrayList<Byte> aBProtocol;
00067     
00068     private ArrayList<String> asTaType;
00069     
00070     // TA1
00071     // Fi is used to determine the value of F, the clock rate conversion factor,
00072     // which may be used to modify the frequency of the clock provided by the
00073     // terminal subsequent to the ATR.
00074     byte                    BFi;
00075     // Di is used to determine the value of D, the bit rate adjustment factor,
00076     // which may be used to adjust the bit duration used subsequent to the ATR.
00077     byte                    BDi;
00078     
00079     // TB1
00080     // PI1 is used to determine the value of the programming voltage required by 
00081     // the ICC.
00082     // If PI1 = 0 then VPP is not connected in the ICC.
00083     byte                    BPi1;
00084     // II is used to determine the maximum programming current, Ipp, required
00085     // by the ICC. Not used if PI1 = 0.
00086     byte                    Bii;
00087     
00088     // TC1
00089     // N is used to indicate the extra guardtime that shall be aded to the
00090     // minimum duration between the leading edges of the start bits of two 
00091     // consecutives characters for subsequent exchanges from the terminal to the
00092     // ICC.
00093     byte                    BN;
00094     
00095     // TB2
00096     // PI2 is used to determine the value of programming 
00097     // voltage P required by the ICC. When present it overrides the value 
00098     // indicated by PI1 returned in TB1.
00099     byte                    BPi2;
00100     
00101     // TC2
00102     // WI is used to determine the maximum interval between the leading edge 
00103     // of the start bit of any character sent by the ICC and the leading edge 
00104     // of the start bit of the previous character sent either by the ICC or the 
00105     // terminal (the work waiting time).
00106     byte                    BWi;
00107     
00108     // The work waiting time is given by 960 * D * WI.
00109     long                    lWorkWaitingTime;
00110     
00111     // TA3
00112     // IFSI is used to determine the IFSC, and specifies the maximum length of
00113     // the information field (INF) of blocks that can be received by the card.
00114     byte                    BIfsi;
00115     
00116     // TB3
00117     // BWI is used to calculate the BWT
00118     byte                    BBwi;
00119     // CWI is used to calculate the CWT
00120     byte                    BCwi;
00121     
00122     // CI is used to determine the voltage class of the ICC.
00123     byte                    BCi;
00124     
00125     // Clock is used to indicate whether the card supports clock stop (!= 0x00)
00126     // or not (= 0x00) and, when supported, which state is preferred on the
00127     // electrical circuit CLK when the clock is stopped.
00128     byte                    BClock;
00129     
00130     // Indicate the block error detection.
00131     byte                    BBlockErrorDetection;
00132     
00133     // TCK is used to check the integrity of the data sent in the ATR.
00134     byte                    BTck;
00135     
00136     private int             iIndex;
00137     
00138     private byte            BVoltageClass;
00139     
00140     private String  m_psT[] = {"Half-duplex transmission of characters.",
00141         "Half-duplex transmission of blocks.", "RFU of full-duplex operations.",
00142         "RFU of full-duplex operations.", "Enhanced half-duplex transmission " +
00143         "of characters.", "RFU by ISO/IEC JTC 1/SC 17.",
00144         "RFU by ISO/IEC JTC 1/SC 17.", "RFU by ISO/IEC JTC 1/SC 17.",
00145         "RFU by ISO/IEC JTC 1/SC 17.", "RFU by ISO/IEC JTC 1/SC 17.",
00146         "RFU by ISO/IEC JTC 1/SC 17.", "RFU by ISO/IEC JTC 1/SC 17.",
00147         "RFU by ISO/IEC JTC 1/SC 17.", "RFU by ISO/IEC JTC 1/SC 17.",
00148         "Transmission protocols not standardized by ISO/IEC JTC 1/SC 17.",
00149         "Does not refer to a transmission protocol, but only qualifies global" +
00150         "interface bytes."};
00151     
00152     private final int       aiF[] = {
00153         372, 372, 558, 744, 1116, 1488, 1860, 0, 0, 512, 768, 1024, 1536, 2048,
00154         0, 0
00155     };
00156     
00157     private final double    afFMax[] = {
00158         4, 5, 6, 8, 12, 16, 20, 0, 0, 5, 7.5, 10, 15, 20, 0, 0};
00159     
00160     private final int       aiD[] = {
00161         0, 1, 2, 4, 8, 16, 32, 64, 12, 20, 0, 0, 0, 0, 0, 0};
00162     
00163     private int          iClockCardFrequency;
00164     
00171     public ATR(byte[] atr, int iClockCard) {
00172         aBTai = new ArrayList();
00173         aBTbi = new ArrayList();
00174         aBTci = new ArrayList();
00175         aBTdi = new ArrayList();
00176         
00177         aBProtocol = new ArrayList();
00178         
00179         asTaType = new ArrayList();
00180         
00181         bIsNegotiable = false;
00182         
00183         BVoltageClass = 0x01;
00184         
00185         iClockCardFrequency = iClockCard;
00186                 
00187         iIndex = 2; // Start after TS and T0
00188         
00189         this.atr = atr.clone();
00190         parse();
00191     }
00192     
00193     private boolean analyze_ts_t0()
00194     {
00195         switch(atr[0])
00196         {
00197             case 0x3B:
00198                 sConvention = "Direct";
00199                 break;
00200                 
00201             case 0x3F:
00202                 sConvention = "Inverse";
00203                 break;
00204             
00205             // Reject ICC returning ATR with TS different from 3F and 3B
00206             default:
00207                 return false;
00208         }
00209         
00210         BTs = atr[0];
00211         BT0 = atr[1];
00212         
00213         nHistorical = BT0 & 0x0F;
00214         
00215         return true;
00216     }
00217     
00218     private boolean analyze_tx1()
00219     {
00220         // TA1
00221         if((BT0 & 0x10) != 0)
00222         {
00223             bIsNegotiable = true;
00224             BFi = (byte) ((atr[iIndex] & 0xF0) >> 4);
00225             BDi = (byte) (atr[iIndex] & 0x0F);
00226             aBTai.add(atr[iIndex]);
00227             iIndex++;
00228         }
00229         else
00230         {
00231             // If TA1 absent the FiDi couple is equal to 0x11 (default value)
00232             BFi = 0x01;
00233             BDi = 0x01;
00234             aBTai.add(null);
00235         }
00236         
00237         // TB1
00238         if((BT0 & 0x20) != 0)
00239         {
00240             aBTbi.add(atr[iIndex]);
00241             BPi1 = (byte) (atr[iIndex] & 0x1F);
00242             Bii = (byte) (atr[iIndex] & 0x60);
00243             iIndex++;
00244         }
00245         else
00246         {
00247             BPi1 = 0x00;
00248             Bii = 0x00;
00249             aBTbi.add(null);
00250         }
00251                
00252         // TC1
00253         if((BT0 & 0x40) != 0)
00254         {
00255             aBTci.add(atr[iIndex]);
00256             BN = atr[iIndex];
00257             iIndex++;
00258         }
00259         else
00260         {
00261             BN = 0; // Indicates 12 etus if T = 0 and 11 etus if T = 1.
00262             aBTci.add(null);
00263         }
00264         
00265         // TD1
00266         if((BT0 & 0x80) != 0)
00267         {
00268             aBTdi.add(atr[iIndex]);
00269             aBProtocol.add((byte)(atr[iIndex] & 0x0F));
00270             iIndex++;
00271         }
00272         else
00273         {
00274             aBTdi.add(null);
00275             // If TD1 not present it is finished for the analyze.
00276             // It remains only historical bytes and TCK if present.
00277             startHistorical = iIndex;
00278             return false;
00279         }
00280         
00281         return true;
00282     }
00283     
00284     private boolean analyze_tx2()
00285     {
00286         int _iIndexForTDi = aBTdi.size() - 1;
00287         
00288         // TA2
00289         // The presence or absence of TA2 indicates whether the ICC will operate 
00290         // in specific mode or negotiable mode respectively following the ATR.
00291         if((aBTdi.get(_iIndexForTDi) & 0x10) != 0)
00292         {
00293             bIsNegotiable = false;
00294             
00295             if((atr[iIndex] & 0x80) != 0x00)
00296                 bIsAbleToChangeSpecificNegotiableMode = true;
00297             else
00298                 bIsAbleToChangeSpecificNegotiableMode = false;
00299             
00300             // The transmission parameters are defined by the interface characters
00301             // if b5 is set to 0, or are implicitly known by the terminal if
00302             // b5 is set to 1.
00303             if((atr[iIndex] & 0x10) != 0x00)
00304                 bAreTransmissionParametersImplicitlyKnownByTerminal = true;
00305             else
00306                 bAreTransmissionParametersImplicitlyKnownByTerminal = false;
00307             
00308             aBTai.add(atr[iIndex]);
00309             
00310             asTaType.add(m_psT[atr[iIndex] & 0x0F]);
00311             
00312             iIndex++;
00313         }
00314         else
00315         {
00316             // If TA2 absent
00317             // Be sure that the negotiable mode is true
00318             bIsNegotiable = true;
00319             aBTai.add(null);
00320         }
00321         
00322         // TB2
00323         if((aBTdi.get(_iIndexForTDi) & 0x20) != 0)
00324         {
00325             BPi2 = atr[iIndex];
00326             aBTbi.add(atr[iIndex]);
00327             
00328             iIndex++;
00329         }
00330         else
00331         {
00332             BPi1 = 0x00;
00333             Bii = 0x00;
00334             aBTbi.add(null);
00335         }
00336                
00337         // TC2
00338         // Specific to T = 0
00339         if((aBTdi.get(_iIndexForTDi) & 0x40) != 0)
00340         {
00341             aBTci.add(atr[iIndex]);
00342             BWi = atr[iIndex];
00343             iIndex++;
00344         }
00345         else
00346         {
00347             BWi = 0x0A;
00348             aBTci.add(null);
00349         }
00350         
00351         lWorkWaitingTime = 960 * BDi * BWi;
00352         
00353         // TD2
00354         if((aBTdi.get(_iIndexForTDi) & 0x80) != 0)
00355         {
00356             aBTdi.add(atr[iIndex]);
00357             aBProtocol.add((byte)(atr[iIndex] & 0x0F));
00358             iIndex++;
00359         }
00360         else
00361         {
00362             aBTdi.add(null);
00363             // If TD2 not present it is finished for the analyze.
00364             // It remains only historical bytes and TCK if present.
00365             startHistorical = iIndex;
00366             return false;
00367         }
00368         
00369         return true;
00370     }
00371     
00372     private boolean analyze_tx3()
00373     {
00374         int _iIndexForTDi = aBTdi.size() - 1;
00375         
00376         // TA3
00377         if((aBTdi.get(_iIndexForTDi) & 0x10) != 0)
00378         {
00379             // If TD2 returns T=1 TA3 returns the information field size integer
00380             // for the ICC (IFSI).
00381             if((aBTdi.get(_iIndexForTDi) & 0x0F) == 0x01)
00382             {
00383                 BIfsi = atr[iIndex];
00384             }
00385             else if((aBTdi.get(_iIndexForTDi) & 0x0F) == 0x0F)
00386             {
00387                 BIfsi = atr[iIndex];
00388                 BCi = (byte) (BIfsi & 0x3F);
00389                 BClock = (byte) (BIfsi & 0xC0);
00390             }
00391             
00392             BVoltageClass = (byte) (BIfsi & 0x3F);
00393             
00394             asTaType.add(m_psT[atr[iIndex] & 0x0F]);
00395             
00396             aBTai.add(atr[iIndex]);
00397             iIndex++;
00398         }
00399         else
00400         {
00401             // If TA3 absent
00402             aBTai.add(null);
00403         }
00404         
00405         // TB3
00406         if((aBTdi.get(_iIndexForTDi) & 0x20) != 0)
00407         {
00408             // If TD2 returns T=1 TB3 indicates the values of the CWI and the WI 
00409             // used to calucalte the CWT and BWT respectively.
00410             if((aBTdi.get(_iIndexForTDi) & 0x0F) == 0x01)
00411             {
00412                 BCwi = (byte)(atr[iIndex] & 0xF0);
00413                 BBwi = (byte)(atr[iIndex] & 0x0F);
00414             }
00415             aBTbi.add(atr[iIndex]);
00416             iIndex++;
00417         }
00418         else
00419         {
00420             aBTbi.add(null);
00421         }
00422                
00423         // TC3
00424         if((aBTdi.get(_iIndexForTDi) & 0x40) != 0)
00425         {
00426             // If TD2 returns T=1 TC3 indicates the type of block error 
00427             // detection code to be used.
00428             if((aBTdi.get(_iIndexForTDi) & 0x0F) == 0x01)
00429             {
00430                 BBlockErrorDetection = (byte)(atr[iIndex] & 0x01);
00431             }
00432             
00433             aBTci.add(atr[iIndex]);
00434             iIndex++;
00435         }
00436         else
00437         {
00438             BBlockErrorDetection = 0x00;
00439             aBTci.add(null);
00440         }
00441         
00442         // TD3
00443         if((aBTdi.get(_iIndexForTDi) & 0x80) != 0)
00444         {
00445             aBTdi.add(atr[iIndex]);
00446             aBProtocol.add((byte)(atr[iIndex] & 0x0F));
00447             iIndex++;
00448         }
00449         else
00450         {
00451             aBTdi.add(null);
00452             // If TD2 not present it is finished for the analyze.
00453             // It remains only historical bytes and TCK if present.
00454             startHistorical = iIndex;
00455             return false;
00456         }
00457         
00458         return true;
00459     }
00460     
00461     private boolean analyze_txi()
00462     {
00463         do
00464         {
00465             int _iIndexForTDi = aBTdi.size() - 1;
00466 
00467             // TAi
00468             if((aBTdi.get(_iIndexForTDi) & 0x10) != 0)
00469             {
00470                 if((aBTdi.get(_iIndexForTDi) & 0x0F) == 0x0F)
00471                 {
00472                     BCi = (byte) (atr[iIndex] & 0x3F);
00473                     BClock = (byte) (atr[iIndex] & 0xC0);
00474                 }
00475 
00476                 aBTai.add(atr[iIndex]);
00477                 
00478                 asTaType.add(m_psT[atr[iIndex] & 0x0F]);
00479                 
00480                 if(aBProtocol.get(aBProtocol.size()-1) == 0x0F)
00481                     BVoltageClass = (byte) (atr[iIndex] & 0x3F);
00482                 
00483                 iIndex++;
00484             }
00485             else
00486             {
00487                 aBTai.add(null);
00488             }
00489 
00490             // TBi
00491             if((aBTdi.get(_iIndexForTDi) & 0x20) != 0)
00492             {
00493                 aBTbi.add(atr[iIndex]);
00494                 iIndex++;
00495             }
00496             else
00497             {
00498                 aBTbi.add(null);
00499             }
00500 
00501             // TCi
00502             if((aBTdi.get(_iIndexForTDi) & 0x40) != 0)
00503             {
00504                 aBTci.add(atr[iIndex]);
00505                 iIndex++;
00506             }
00507             else
00508             {
00509                 aBTci.add(null);
00510             }
00511 
00512             // TDi
00513             if((aBTdi.get(_iIndexForTDi) & 0x80) != 0)
00514             {
00515                 aBTdi.add(atr[iIndex]);
00516                 aBProtocol.add((byte)(atr[iIndex] & 0x0F));
00517                 iIndex++;
00518             }
00519             else
00520             {
00521                 aBTdi.add(null);
00522                 // If TD2 not present it is finished for the analyze.
00523                 // It remains only historical bytes and TCK if present.
00524                 startHistorical = iIndex;
00525                 return false;
00526             }
00527         }
00528         while(true);
00529     }
00530 
00531     private void parse() 
00532     {
00533         // An ATR must contain at least TS and T0 which are mandatory bytes
00534         if(atr.length < 2) 
00535             return;
00536         
00537         // TS must be 0x3B or 0x3F T0 indicates the values of TX1
00538         if(analyze_ts_t0() == false)
00539             return;
00540         
00541         // Analyze TA1 TB1 TC1 TD1
00542         if(analyze_tx1() == false)
00543         {
00544             iIndex += nHistorical;
00545             
00546             // There is a TCK
00547             if(iIndex < atr.length)
00548                 BTck = atr[iIndex];
00549             
00550             return;
00551         }
00552         
00553         // Analyze TA2 TB2 TC2 TD2
00554         if(analyze_tx2() == false)
00555         {
00556             iIndex += nHistorical;
00557             
00558             // There is a TCK
00559             if(iIndex < atr.length)
00560                 BTck = atr[iIndex];
00561             
00562             return;
00563         }
00564         
00565         // Analyze TA3 TB3 TC3 TD3
00566         if(analyze_tx3() == false)
00567         {
00568             iIndex += nHistorical;
00569             
00570             // There is a TCK
00571             if(iIndex < atr.length)
00572                 BTck = atr[iIndex];
00573             
00574             return;
00575         }
00576         
00577         // Analyze TAi TBi TCi TDi
00578         if(analyze_txi() == false)
00579         {
00580             iIndex += nHistorical;
00581             
00582             // There is a TCK
00583             if(iIndex < atr.length)
00584                 BTck = atr[iIndex];
00585             
00586             return;
00587         }
00588     }
00589 
00595     public byte[] getBytes() {
00596         return atr.clone();
00597     }
00598 
00599     public String getConvention()
00600     {
00601         return sConvention;
00602     }
00603     
00604     public long getWorkWaitingTime()
00605     {
00606         return lWorkWaitingTime;
00607     }
00608     
00609     public boolean isNegotiableMode()
00610     {
00611         return bIsNegotiable;
00612     }
00613     
00614     public boolean isAbleToChangeFromSpecificToNegociableMode()
00615     {
00616         if(bIsNegotiable == false)
00617             return bIsAbleToChangeSpecificNegotiableMode;
00618         
00619         // Not applicable already in negotiable mode.
00620         return true;
00621     }
00622     
00623     public boolean areTransmissionParametersImplicitlyKnownByTerminal()
00624     {
00625         return bAreTransmissionParametersImplicitlyKnownByTerminal;
00626     }
00627     
00628     public ArrayList<Byte>  getListOfTA()
00629     {
00630         return aBTai;
00631     }
00632     
00633     public ArrayList<Byte>  getListOfTB()
00634     {
00635         return aBTbi;
00636     }
00637     
00638     public ArrayList<Byte>  getListOfTC()
00639     {
00640         return aBTci;
00641     }
00642     
00643     public ArrayList<Byte>  getListOfTD()
00644     {
00645         return aBTdi;
00646     }
00647     
00648     public ArrayList<Byte> getListOfProtocols()
00649     {
00650         return aBProtocol;
00651     }
00652     
00653     public ArrayList<String> getListOfTaTypes()
00654     {
00655         return asTaType;
00656     }
00657     
00658     public byte getII()
00659     {
00660         return Bii;
00661     }
00662             
00663     public byte getWI()
00664     {
00665         return BWi;
00666     }
00667 
00668     public byte getTS()
00669     {
00670         return BTs;
00671     }
00672 
00673     public byte getTCK()
00674     {
00675         return BTck;
00676     }
00677 
00678     public byte getT0()
00679     {
00680         return BT0;
00681     }
00682 
00683     public byte getPI2()
00684     {
00685         return BPi2;
00686     }
00687 
00688     public byte getPI1()
00689     {
00690         return BPi1;
00691     }
00692 
00693     public byte getN()
00694     {
00695         return BN;
00696     }
00697 
00698     public byte getIFSI()
00699     {
00700         return BIfsi;
00701     }
00702 
00703     public byte getFI()
00704     {
00705         return BFi;
00706     }
00707 
00708     public byte getDI()
00709     {
00710         return BDi;
00711     }
00712 
00713     public byte getCWI()
00714     {
00715         return BCwi;
00716     }
00717             
00718     public byte getBWI()
00719     {
00720         return BBwi;
00721     }
00722 
00723     public byte getBlockErrorDetection()
00724     {
00725         return BBlockErrorDetection;
00726     }
00727 
00728     public byte getClock()
00729     {
00730         return BClock;
00731     }
00732     
00733     public int getF()
00734     {
00735         return aiF[BFi];
00736     }
00737     
00738     public int getD()
00739     {
00740         return aiD[BDi];
00741     }
00742     
00743     public double getClkFMax()
00744     {
00745         return afFMax[BFi];
00746     }
00747     
00748     public double getClkF()
00749     {
00750         return iClockCardFrequency;
00751     }
00752     
00753     public double getDefaultBaudRate()
00754     {
00755         return Math.round(1 / (372 / 1 * 1.0 / getClkF()));
00756     }
00757     
00758     public double getBaudRate()
00759     {
00760         return Math.round(1 / (getF() / getD() * 1.0 / getClkF()));
00761     }
00762     
00763     public double getBlockWaitingTime()
00764     {
00765         return 11 +  (Math.pow(2, getBWI()) * 960 * getF() * getD() / getClkF());
00766     }
00767     
00768     public double getCharacterWaitingTime()
00769     {
00770         return 11 + Math.pow(2, getCWI());
00771     }
00772     
00773     public double getExtraGuardTime()
00774     {
00775         if(isSupportedProtocol(0x0F))
00776         {
00777             return 12 + getF() / getD() * 
00778                     (getN() / getClkF());
00779         }
00780         else
00781         {
00782             return 12 + getF() / getD() * 
00783                     (getN() / getClkF());
00784         }
00785     }
00786     
00787     public boolean isSupportedProtocol(int iProtocol)
00788     {
00789         int _i = 0;
00790         
00791         if((iProtocol != 0) && (iProtocol != 1) && (iProtocol != 0x0F))
00792             return false;
00793         
00794         while(_i < aBProtocol.size())
00795         {
00796             if(aBProtocol.get(_i) == iProtocol)
00797                 return true;
00798             _i++;
00799         }
00800         
00801         return false;
00802     }
00803     
00804     public byte getVoltageClass()
00805     {
00806         return BVoltageClass;
00807     }
00808     
00816     public byte[] getHistoricalBytes() {
00817         byte[] b = new byte[nHistorical];
00818         System.arraycopy(atr, startHistorical, b, 0, nHistorical);
00819         return b;
00820     }
00821     
00822     public boolean isTaPresent(int iIndex)
00823     {
00824         if((this.aBTai != null) && (this.aBTai.get(iIndex-1) != null))
00825             return true;
00826             
00827         return false;
00828     }
00829     
00830     public boolean isTbPresent(int iIndex)
00831     {
00832         if((this.aBTbi != null) && (this.aBTbi.get(iIndex-1) != null))
00833             return true;
00834             
00835         return false;
00836     }
00837     
00838     public boolean isTcPresent(int iIndex)
00839     {
00840         if((this.aBTci != null) && (this.aBTci.get(iIndex-1) != null))
00841             return true;
00842             
00843         return false;
00844     }
00845     
00846     public boolean isTdPresent(int iIndex)
00847     {
00848         if((this.aBTdi != null) && (this.aBTdi.get(iIndex-1) != null))
00849             return true;
00850             
00851         return false;
00852     }
00853 
00859     public String toString() {
00860         return "ATR: " + atr.length + " bytes";
00861     }
00862     
00871     public boolean equals(Object obj) {
00872         if (this == obj) {
00873             return true;
00874         }
00875         if (obj instanceof ATR == false) {
00876             return false;
00877         }
00878         ATR other = (ATR)obj;
00879         return Arrays.equals(this.atr, other.atr);
00880     }
00881 
00887     public int hashCode() {
00888         return Arrays.hashCode(atr);
00889     }
00890         
00901         public Object[] getDescription()
00902         {
00903                 return null;
00904         }
00905 
00906     private void readObject(java.io.ObjectInputStream in)
00907             throws java.io.IOException, ClassNotFoundException {
00908         atr = (byte[])in.readUnshared();
00909         parse();
00910     }
00911 
00912     
00913     
00914     // To be implement 
00915     // Voltage class
00916     // The first TB for T = 15 indicates the use of SPU by the card. The default
00917     // value is "SPU not used"
00918 }