PCSC4Java
0.2
Library PCSC for Java language.
|
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 }