IsoDep.java revision 74fe6c6b245ebe7d3b3d96962c32980d88dca4f5
1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.nfc.tech;
18
19import android.nfc.Tag;
20import android.os.Bundle;
21import android.os.RemoteException;
22import android.util.Log;
23
24import java.io.IOException;
25
26/**
27 * Provides access to ISO-DEP (ISO 14443-4) properties and I/O operations on a {@link Tag}.
28 *
29 * <p>Acquire a {@link IsoDep} object using {@link #get}.
30 * <p>The primary ISO-DEP I/O operation is {@link #transceive}. Applications must
31 * implement their own protocol stack on top of {@link #transceive}.
32 * <p>Tags that enumerate the {@link IsoDep} technology in {@link Tag#getTechList}
33 * will also enumerate
34 * {@link NfcA} or {@link NfcB} (since IsoDep builds on top of either of these).
35 */
36public final class IsoDep extends BasicTagTechnology {
37    private static final String TAG = "NFC";
38
39    /** @hide */
40    public static final String EXTRA_HI_LAYER_RESP = "hiresp";
41    /** @hide */
42    public static final String EXTRA_HIST_BYTES = "histbytes";
43
44    private byte[] mHiLayerResponse = null;
45    private byte[] mHistBytes = null;
46
47    /**
48     * Get an instance of {@link IsoDep} for the given tag.
49     * <p>Does not cause any RF activity and does not block.
50     * <p>Returns null if {@link IsoDep} was not enumerated in {@link Tag#getTechList}.
51     * This indicates the tag does not support ISO-DEP.
52     *
53     * @param tag an ISO-DEP compatible tag
54     * @return ISO-DEP object
55     */
56    public static IsoDep get(Tag tag) {
57        if (!tag.hasTech(TagTechnology.ISO_DEP)) return null;
58        try {
59            return new IsoDep(tag);
60        } catch (RemoteException e) {
61            return null;
62        }
63    }
64
65    /** @hide */
66    public IsoDep(Tag tag)
67            throws RemoteException {
68        super(tag, TagTechnology.ISO_DEP);
69        Bundle extras = tag.getTechExtras(TagTechnology.ISO_DEP);
70        if (extras != null) {
71            mHiLayerResponse = extras.getByteArray(EXTRA_HI_LAYER_RESP);
72            mHistBytes = extras.getByteArray(EXTRA_HIST_BYTES);
73        }
74    }
75
76    /**
77     * Set the timeout of {@link #transceive} in milliseconds.
78     * <p>The timeout only applies to ISO-DEP {@link #transceive}, and is
79     * reset to a default value when {@link #close} is called.
80     * <p>Setting a longer timeout may be useful when performing
81     * transactions that require a long processing time on the tag
82     * such as key generation.
83     * @param timeout timeout value in milliseconds
84     */
85    public void setTimeout(int timeout) {
86        try {
87            mTag.getTagService().setIsoDepTimeout(timeout);
88        } catch (RemoteException e) {
89            Log.e(TAG, "NFC service dead", e);
90        }
91    }
92
93    @Override
94    public void close() throws IOException {
95        try {
96            mTag.getTagService().resetIsoDepTimeout();
97        } catch (RemoteException e) {
98            Log.e(TAG, "NFC service dead", e);
99        }
100        super.close();
101    }
102
103    /**
104     * Return the ISO-DEP historical bytes for {@link NfcA} tags.
105     * <p>Does not cause any RF activity and does not block.
106     * <p>The historical bytes can be used to help identify a tag. They are present
107     * only on {@link IsoDep} tags that are based on {@link NfcA} RF technology.
108     * If this tag is not {@link NfcA} then null is returned.
109     * <p>In ISO 14443-4 terminology, the historical bytes are a subset of the RATS
110     * response.
111     *
112     * @return ISO-DEP historical bytes, or null if this is not a {@link NfcA} tag
113     */
114    public byte[] getHistoricalBytes() {
115        return mHistBytes;
116    }
117
118    /**
119     * Return the higher layer response bytes for {@link NfcB} tags.
120     * <p>Does not cause any RF activity and does not block.
121     * <p>The higher layer response bytes can be used to help identify a tag.
122     * They are present only on {@link IsoDep} tags that are based on {@link NfcB}
123     * RF technology. If this tag is not {@link NfcB} then null is returned.
124     * <p>In ISO 14443-4 terminology, the higher layer bytes are a subset of the
125     * ATTRIB response.
126     *
127     * @return ISO-DEP historical bytes, or null if this is not a {@link NfcB} tag
128     */
129    public byte[] getHiLayerResponse() {
130        return mHiLayerResponse;
131    }
132
133    /**
134     * Send raw ISO-DEP data to the tag and receive the response.
135     *
136     * <p>Applications must only send the INF payload, and not the start of frame and
137     * end of frame indicators. Applications do not need to fragment the payload, it
138     * will be automatically fragmented and defragmented by {@link #transceive} if
139     * it exceeds FSD/FSC limits.
140     *
141     * <p>This is an I/O operation and will block until complete. It must
142     * not be called from the main application thread. A blocked call will be canceled with
143     * {@link IOException} if {@link #close} is called from another thread.
144     *
145     * @param data command bytes to send, must not be null
146     * @return response bytes received, will not be null
147     * @throws TagLostException if the tag leaves the field
148     * @throws IOException if there is an I/O failure, or this operation is canceled
149     */
150    public byte[] transceive(byte[] data) throws IOException {
151        return transceive(data, true);
152    }
153}
154