16be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton/* 26be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton * Copyright (C) 2010 The Android Open Source Project 36be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton * 46be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton * Licensed under the Apache License, Version 2.0 (the "License"); 56be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton * you may not use this file except in compliance with the License. 66be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton * You may obtain a copy of the License at 76be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton * 86be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton * http://www.apache.org/licenses/LICENSE-2.0 96be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton * 106be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton * Unless required by applicable law or agreed to in writing, software 116be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton * distributed under the License is distributed on an "AS IS" BASIS, 126be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 136be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton * See the License for the specific language governing permissions and 146be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton * limitations under the License. 156be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton */ 166be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton 174e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamiltonpackage android.nfc.tech; 186be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton 19112fdf612db71a552fce063136bf2796df3b71ecMartijn Coenenimport android.nfc.ErrorCodes; 206be655c768a82716612c00fdd156254d8dc00f42Jeff Hamiltonimport android.nfc.Tag; 216be655c768a82716612c00fdd156254d8dc00f42Jeff Hamiltonimport android.os.Bundle; 226be655c768a82716612c00fdd156254d8dc00f42Jeff Hamiltonimport android.os.RemoteException; 23a701cf85a0167a6bb623343388a7dca6f2b61ac5Martijn Coenenimport android.util.Log; 246be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton 256be655c768a82716612c00fdd156254d8dc00f42Jeff Hamiltonimport java.io.IOException; 266be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton 276be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton/** 2874fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * Provides access to ISO-DEP (ISO 14443-4) properties and I/O operations on a {@link Tag}. 296be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton * 3039cf3a445e507f219ecc8a476f6038f095d9d520Nick Pelly * <p>Acquire an {@link IsoDep} object using {@link #get}. 3174fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * <p>The primary ISO-DEP I/O operation is {@link #transceive}. Applications must 3274fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * implement their own protocol stack on top of {@link #transceive}. 3374fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * <p>Tags that enumerate the {@link IsoDep} technology in {@link Tag#getTechList} 3474fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * will also enumerate 3574fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * {@link NfcA} or {@link NfcB} (since IsoDep builds on top of either of these). 3639cf3a445e507f219ecc8a476f6038f095d9d520Nick Pelly * 3739cf3a445e507f219ecc8a476f6038f095d9d520Nick Pelly * <p class="note"><strong>Note:</strong> Methods that perform I/O operations 3839cf3a445e507f219ecc8a476f6038f095d9d520Nick Pelly * require the {@link android.Manifest.permission#NFC} permission. 396be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton */ 406be655c768a82716612c00fdd156254d8dc00f42Jeff Hamiltonpublic final class IsoDep extends BasicTagTechnology { 41a701cf85a0167a6bb623343388a7dca6f2b61ac5Martijn Coenen private static final String TAG = "NFC"; 42a701cf85a0167a6bb623343388a7dca6f2b61ac5Martijn Coenen 43bc7180bba42307306d9dffa9299d836b381da9c0Martijn Coenen /** @hide */ 44a559aa4759309606cd201e7e39844c3363a72b24Martijn Coenen public static final String EXTRA_HI_LAYER_RESP = "hiresp"; 45bc7180bba42307306d9dffa9299d836b381da9c0Martijn Coenen /** @hide */ 46bc7180bba42307306d9dffa9299d836b381da9c0Martijn Coenen public static final String EXTRA_HIST_BYTES = "histbytes"; 47bc7180bba42307306d9dffa9299d836b381da9c0Martijn Coenen 48a559aa4759309606cd201e7e39844c3363a72b24Martijn Coenen private byte[] mHiLayerResponse = null; 49bc7180bba42307306d9dffa9299d836b381da9c0Martijn Coenen private byte[] mHistBytes = null; 506be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton 514e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton /** 5274fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * Get an instance of {@link IsoDep} for the given tag. 5374fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * <p>Does not cause any RF activity and does not block. 5474fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * <p>Returns null if {@link IsoDep} was not enumerated in {@link Tag#getTechList}. 5574fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * This indicates the tag does not support ISO-DEP. 564e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton * 5774fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * @param tag an ISO-DEP compatible tag 5874fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * @return ISO-DEP object 594e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton */ 604e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton public static IsoDep get(Tag tag) { 614e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton if (!tag.hasTech(TagTechnology.ISO_DEP)) return null; 624e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton try { 634e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton return new IsoDep(tag); 644e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton } catch (RemoteException e) { 654e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton return null; 664e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton } 674e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton } 6874fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly 69ce3224cda51f946871daa1e11e3976e25c59e6faJeff Hamilton /** @hide */ 704e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton public IsoDep(Tag tag) 716be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton throws RemoteException { 724e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton super(tag, TagTechnology.ISO_DEP); 734e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton Bundle extras = tag.getTechExtras(TagTechnology.ISO_DEP); 74bc7180bba42307306d9dffa9299d836b381da9c0Martijn Coenen if (extras != null) { 75a559aa4759309606cd201e7e39844c3363a72b24Martijn Coenen mHiLayerResponse = extras.getByteArray(EXTRA_HI_LAYER_RESP); 76bc7180bba42307306d9dffa9299d836b381da9c0Martijn Coenen mHistBytes = extras.getByteArray(EXTRA_HIST_BYTES); 77bc7180bba42307306d9dffa9299d836b381da9c0Martijn Coenen } 786be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton } 796be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton 806be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton /** 8174fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * Set the timeout of {@link #transceive} in milliseconds. 8274fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * <p>The timeout only applies to ISO-DEP {@link #transceive}, and is 8374fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * reset to a default value when {@link #close} is called. 8474fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * <p>Setting a longer timeout may be useful when performing 8574fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * transactions that require a long processing time on the tag 8674fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * such as key generation. 8739cf3a445e507f219ecc8a476f6038f095d9d520Nick Pelly * 8839cf3a445e507f219ecc8a476f6038f095d9d520Nick Pelly * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission. 8939cf3a445e507f219ecc8a476f6038f095d9d520Nick Pelly * 9074fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * @param timeout timeout value in milliseconds 91a701cf85a0167a6bb623343388a7dca6f2b61ac5Martijn Coenen */ 92a701cf85a0167a6bb623343388a7dca6f2b61ac5Martijn Coenen public void setTimeout(int timeout) { 93a701cf85a0167a6bb623343388a7dca6f2b61ac5Martijn Coenen try { 94112fdf612db71a552fce063136bf2796df3b71ecMartijn Coenen int err = mTag.getTagService().setTimeout(TagTechnology.ISO_DEP, timeout); 95112fdf612db71a552fce063136bf2796df3b71ecMartijn Coenen if (err != ErrorCodes.SUCCESS) { 96112fdf612db71a552fce063136bf2796df3b71ecMartijn Coenen throw new IllegalArgumentException("The supplied timeout is not valid"); 97112fdf612db71a552fce063136bf2796df3b71ecMartijn Coenen } 98a701cf85a0167a6bb623343388a7dca6f2b61ac5Martijn Coenen } catch (RemoteException e) { 99a701cf85a0167a6bb623343388a7dca6f2b61ac5Martijn Coenen Log.e(TAG, "NFC service dead", e); 100a701cf85a0167a6bb623343388a7dca6f2b61ac5Martijn Coenen } 101a701cf85a0167a6bb623343388a7dca6f2b61ac5Martijn Coenen } 102a701cf85a0167a6bb623343388a7dca6f2b61ac5Martijn Coenen 103a701cf85a0167a6bb623343388a7dca6f2b61ac5Martijn Coenen /** 10482328bfd40008d85917cc01a1b2eb8eed1f23ec4Nick Pelly * Get the current timeout for {@link #transceive} in milliseconds. 10520e62c9f1466ace5771e244f03a995dc0939b11bMartijn Coenen * 10620e62c9f1466ace5771e244f03a995dc0939b11bMartijn Coenen * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission. 10720e62c9f1466ace5771e244f03a995dc0939b11bMartijn Coenen * 10820e62c9f1466ace5771e244f03a995dc0939b11bMartijn Coenen * @return timeout value in milliseconds 10920e62c9f1466ace5771e244f03a995dc0939b11bMartijn Coenen */ 11020e62c9f1466ace5771e244f03a995dc0939b11bMartijn Coenen public int getTimeout() { 11120e62c9f1466ace5771e244f03a995dc0939b11bMartijn Coenen try { 11220e62c9f1466ace5771e244f03a995dc0939b11bMartijn Coenen return mTag.getTagService().getTimeout(TagTechnology.ISO_DEP); 11320e62c9f1466ace5771e244f03a995dc0939b11bMartijn Coenen } catch (RemoteException e) { 11420e62c9f1466ace5771e244f03a995dc0939b11bMartijn Coenen Log.e(TAG, "NFC service dead", e); 11520e62c9f1466ace5771e244f03a995dc0939b11bMartijn Coenen return 0; 11620e62c9f1466ace5771e244f03a995dc0939b11bMartijn Coenen } 11720e62c9f1466ace5771e244f03a995dc0939b11bMartijn Coenen } 11820e62c9f1466ace5771e244f03a995dc0939b11bMartijn Coenen 11920e62c9f1466ace5771e244f03a995dc0939b11bMartijn Coenen /** 12074fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * Return the ISO-DEP historical bytes for {@link NfcA} tags. 12174fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * <p>Does not cause any RF activity and does not block. 12274fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * <p>The historical bytes can be used to help identify a tag. They are present 12374fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * only on {@link IsoDep} tags that are based on {@link NfcA} RF technology. 12474fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * If this tag is not {@link NfcA} then null is returned. 12574fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * <p>In ISO 14443-4 terminology, the historical bytes are a subset of the RATS 12674fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * response. 12774fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * 12874fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * @return ISO-DEP historical bytes, or null if this is not a {@link NfcA} tag 1296be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton */ 1303dd6c458530476eccb33bc05c9c9cd83823bcf8dNick Pelly public byte[] getHistoricalBytes() { 1313dd6c458530476eccb33bc05c9c9cd83823bcf8dNick Pelly return mHistBytes; 1323dd6c458530476eccb33bc05c9c9cd83823bcf8dNick Pelly } 1336be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton 1346be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton /** 13574fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * Return the higher layer response bytes for {@link NfcB} tags. 13674fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * <p>Does not cause any RF activity and does not block. 13774fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * <p>The higher layer response bytes can be used to help identify a tag. 13874fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * They are present only on {@link IsoDep} tags that are based on {@link NfcB} 13974fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * RF technology. If this tag is not {@link NfcB} then null is returned. 14074fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * <p>In ISO 14443-4 terminology, the higher layer bytes are a subset of the 14174fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * ATTRIB response. 14274fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * 14374fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * @return ISO-DEP historical bytes, or null if this is not a {@link NfcB} tag 1446be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton */ 1453dd6c458530476eccb33bc05c9c9cd83823bcf8dNick Pelly public byte[] getHiLayerResponse() { 1463dd6c458530476eccb33bc05c9c9cd83823bcf8dNick Pelly return mHiLayerResponse; 1473dd6c458530476eccb33bc05c9c9cd83823bcf8dNick Pelly } 148ce3224cda51f946871daa1e11e3976e25c59e6faJeff Hamilton 149ce3224cda51f946871daa1e11e3976e25c59e6faJeff Hamilton /** 15074fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * Send raw ISO-DEP data to the tag and receive the response. 15174fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * 15274fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * <p>Applications must only send the INF payload, and not the start of frame and 15374fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * end of frame indicators. Applications do not need to fragment the payload, it 15474fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * will be automatically fragmented and defragmented by {@link #transceive} if 15574fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * it exceeds FSD/FSC limits. 15674fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * 157faca12adc62d148505fadfd286e6a2752c197fa0Martijn Coenen * <p>Use {@link #getMaxTransceiveLength} to retrieve the maximum number of bytes 158faca12adc62d148505fadfd286e6a2752c197fa0Martijn Coenen * that can be sent with {@link #transceive}. 159faca12adc62d148505fadfd286e6a2752c197fa0Martijn Coenen * 16074fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * <p>This is an I/O operation and will block until complete. It must 16174fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * not be called from the main application thread. A blocked call will be canceled with 16274fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * {@link IOException} if {@link #close} is called from another thread. 163ce3224cda51f946871daa1e11e3976e25c59e6faJeff Hamilton * 16439cf3a445e507f219ecc8a476f6038f095d9d520Nick Pelly * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission. 16539cf3a445e507f219ecc8a476f6038f095d9d520Nick Pelly * 16674fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * @param data command bytes to send, must not be null 16774fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * @return response bytes received, will not be null 16874fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * @throws TagLostException if the tag leaves the field 16974fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * @throws IOException if there is an I/O failure, or this operation is canceled 170ce3224cda51f946871daa1e11e3976e25c59e6faJeff Hamilton */ 171ce3224cda51f946871daa1e11e3976e25c59e6faJeff Hamilton public byte[] transceive(byte[] data) throws IOException { 172ce3224cda51f946871daa1e11e3976e25c59e6faJeff Hamilton return transceive(data, true); 173ce3224cda51f946871daa1e11e3976e25c59e6faJeff Hamilton } 174faca12adc62d148505fadfd286e6a2752c197fa0Martijn Coenen 175faca12adc62d148505fadfd286e6a2752c197fa0Martijn Coenen /** 176faca12adc62d148505fadfd286e6a2752c197fa0Martijn Coenen * Return the maximum number of bytes that can be sent with {@link #transceive}. 177faca12adc62d148505fadfd286e6a2752c197fa0Martijn Coenen * @return the maximum number of bytes that can be sent with {@link #transceive}. 178faca12adc62d148505fadfd286e6a2752c197fa0Martijn Coenen */ 179faca12adc62d148505fadfd286e6a2752c197fa0Martijn Coenen public int getMaxTransceiveLength() { 180faca12adc62d148505fadfd286e6a2752c197fa0Martijn Coenen return getMaxTransceiveLengthInternal(); 181faca12adc62d148505fadfd286e6a2752c197fa0Martijn Coenen } 182fa98cf0573b813c8b1a880496d847d0d7183d05dMartijn Coenen 183fa98cf0573b813c8b1a880496d847d0d7183d05dMartijn Coenen /** 184fa98cf0573b813c8b1a880496d847d0d7183d05dMartijn Coenen * <p>Standard APDUs have a 1-byte length field, allowing a maximum of 185fa98cf0573b813c8b1a880496d847d0d7183d05dMartijn Coenen * 255 payload bytes, which results in a maximum APDU length of 261 bytes. 186fa98cf0573b813c8b1a880496d847d0d7183d05dMartijn Coenen * 187fa98cf0573b813c8b1a880496d847d0d7183d05dMartijn Coenen * <p>Extended length APDUs have a 3-byte length field, allowing 65535 188fa98cf0573b813c8b1a880496d847d0d7183d05dMartijn Coenen * payload bytes. 189fa98cf0573b813c8b1a880496d847d0d7183d05dMartijn Coenen * 190fa98cf0573b813c8b1a880496d847d0d7183d05dMartijn Coenen * <p>Some NFC adapters, like the one used in the Nexus S and the Galaxy Nexus 191fa98cf0573b813c8b1a880496d847d0d7183d05dMartijn Coenen * do not support extended length APDUs. They are expected to be well-supported 192fa98cf0573b813c8b1a880496d847d0d7183d05dMartijn Coenen * in the future though. Use this method to check for extended length APDU 193fa98cf0573b813c8b1a880496d847d0d7183d05dMartijn Coenen * support. 194fa98cf0573b813c8b1a880496d847d0d7183d05dMartijn Coenen * 195fa98cf0573b813c8b1a880496d847d0d7183d05dMartijn Coenen * @return whether the NFC adapter on this device supports extended length APDUs. 196fa98cf0573b813c8b1a880496d847d0d7183d05dMartijn Coenen */ 197fa98cf0573b813c8b1a880496d847d0d7183d05dMartijn Coenen public boolean isExtendedLengthApduSupported() { 198fa98cf0573b813c8b1a880496d847d0d7183d05dMartijn Coenen try { 199fa98cf0573b813c8b1a880496d847d0d7183d05dMartijn Coenen return mTag.getTagService().getExtendedLengthApdusSupported(); 200fa98cf0573b813c8b1a880496d847d0d7183d05dMartijn Coenen } catch (RemoteException e) { 201fa98cf0573b813c8b1a880496d847d0d7183d05dMartijn Coenen Log.e(TAG, "NFC service dead", e); 202fa98cf0573b813c8b1a880496d847d0d7183d05dMartijn Coenen return false; 203fa98cf0573b813c8b1a880496d847d0d7183d05dMartijn Coenen } 204fa98cf0573b813c8b1a880496d847d0d7183d05dMartijn Coenen } 2056be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton} 206