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;
23112fdf612db71a552fce063136bf2796df3b71ecMartijn Coenenimport android.util.Log;
246be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton
25ce3224cda51f946871daa1e11e3976e25c59e6faJeff Hamiltonimport java.io.IOException;
26ce3224cda51f946871daa1e11e3976e25c59e6faJeff Hamilton
276be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton/**
2874fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * Provides access to NFC-A (ISO 14443-3A) properties and I/O operations on a {@link Tag}.
296be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton *
3074fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * <p>Acquire a {@link NfcA} object using {@link #get}.
3174fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * <p>The primary NFC-A I/O operation is {@link #transceive}. Applications must
3274fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * implement their own protocol stack on top of {@link #transceive}.
3339cf3a445e507f219ecc8a476f6038f095d9d520Nick Pelly *
3439cf3a445e507f219ecc8a476f6038f095d9d520Nick Pelly * <p class="note"><strong>Note:</strong> Methods that perform I/O operations
3539cf3a445e507f219ecc8a476f6038f095d9d520Nick Pelly * require the {@link android.Manifest.permission#NFC} permission.
366be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton */
376be655c768a82716612c00fdd156254d8dc00f42Jeff Hamiltonpublic final class NfcA extends BasicTagTechnology {
38112fdf612db71a552fce063136bf2796df3b71ecMartijn Coenen    private static final String TAG = "NFC";
39112fdf612db71a552fce063136bf2796df3b71ecMartijn Coenen
406be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton    /** @hide */
416be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton    public static final String EXTRA_SAK = "sak";
426be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton    /** @hide */
436be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton    public static final String EXTRA_ATQA = "atqa";
446be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton
456be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton    private short mSak;
466be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton    private byte[] mAtqa;
476be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton
484e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton    /**
4974fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * Get an instance of {@link NfcA} for the given tag.
5074fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * <p>Returns null if {@link NfcA} was not enumerated in {@link Tag#getTechList}.
5174fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * This indicates the tag does not support NFC-A.
5274fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * <p>Does not cause any RF activity and does not block.
534e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton     *
5474fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * @param tag an NFC-A compatible tag
5574fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * @return NFC-A object
564e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton     */
574e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton    public static NfcA get(Tag tag) {
584e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton        if (!tag.hasTech(TagTechnology.NFC_A)) return null;
594e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton        try {
604e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton            return new NfcA(tag);
614e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton        } catch (RemoteException e) {
624e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton            return null;
634e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton        }
644e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton    }
654e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton
66ce3224cda51f946871daa1e11e3976e25c59e6faJeff Hamilton    /** @hide */
674e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton    public NfcA(Tag tag) throws RemoteException {
684e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton        super(tag, TagTechnology.NFC_A);
694e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton        Bundle extras = tag.getTechExtras(TagTechnology.NFC_A);
706be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton        mSak = extras.getShort(EXTRA_SAK);
716be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton        mAtqa = extras.getByteArray(EXTRA_ATQA);
726be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton    }
736be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton
746be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton    /**
7574fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * Return the ATQA/SENS_RES bytes from tag discovery.
7674fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     *
7774fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * <p>Does not cause any RF activity and does not block.
7874fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     *
7974fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * @return ATQA/SENS_RES bytes
806be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton     */
816be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton    public byte[] getAtqa() {
826be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton        return mAtqa;
836be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton    }
846be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton
856be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton    /**
8674fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * Return the SAK/SEL_RES bytes from tag discovery.
8774fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     *
8874fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * <p>Does not cause any RF activity and does not block.
8974fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     *
9074fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * @return SAK bytes
916be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton     */
926be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton    public short getSak() {
936be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton        return mSak;
946be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton    }
95ce3224cda51f946871daa1e11e3976e25c59e6faJeff Hamilton
96ce3224cda51f946871daa1e11e3976e25c59e6faJeff Hamilton    /**
9774fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * Send raw NFC-A commands to the tag and receive the response.
9874fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     *
9974fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * <p>Applications must not append the EoD (CRC) to the payload,
10074fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * it will be automatically calculated.
10174fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * <p>Applications must only send commands that are complete bytes,
10274fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * for example a SENS_REQ is not possible (these are used to
10374fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * manage tag polling and initialization).
10474fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     *
105faca12adc62d148505fadfd286e6a2752c197fa0Martijn Coenen     * <p>Use {@link #getMaxTransceiveLength} to retrieve the maximum number of bytes
106faca12adc62d148505fadfd286e6a2752c197fa0Martijn Coenen     * that can be sent with {@link #transceive}.
107faca12adc62d148505fadfd286e6a2752c197fa0Martijn Coenen     *
10874fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * <p>This is an I/O operation and will block until complete. It must
10974fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * not be called from the main application thread. A blocked call will be canceled with
11074fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * {@link IOException} if {@link #close} is called from another thread.
111ce3224cda51f946871daa1e11e3976e25c59e6faJeff Hamilton     *
11239cf3a445e507f219ecc8a476f6038f095d9d520Nick Pelly     * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
11339cf3a445e507f219ecc8a476f6038f095d9d520Nick Pelly     *
114ce3224cda51f946871daa1e11e3976e25c59e6faJeff Hamilton     * @param data bytes to send
115ce3224cda51f946871daa1e11e3976e25c59e6faJeff Hamilton     * @return bytes received in response
11674fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * @throws TagLostException if the tag leaves the field
11774fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * @throws IOException if there is an I/O failure, or this operation is canceled
118ce3224cda51f946871daa1e11e3976e25c59e6faJeff Hamilton     */
119ce3224cda51f946871daa1e11e3976e25c59e6faJeff Hamilton    public byte[] transceive(byte[] data) throws IOException {
120ce3224cda51f946871daa1e11e3976e25c59e6faJeff Hamilton        return transceive(data, true);
121ce3224cda51f946871daa1e11e3976e25c59e6faJeff Hamilton    }
122112fdf612db71a552fce063136bf2796df3b71ecMartijn Coenen
123112fdf612db71a552fce063136bf2796df3b71ecMartijn Coenen    /**
124faca12adc62d148505fadfd286e6a2752c197fa0Martijn Coenen     * Return the maximum number of bytes that can be sent with {@link #transceive}.
125faca12adc62d148505fadfd286e6a2752c197fa0Martijn Coenen     * @return the maximum number of bytes that can be sent with {@link #transceive}.
126faca12adc62d148505fadfd286e6a2752c197fa0Martijn Coenen     */
127faca12adc62d148505fadfd286e6a2752c197fa0Martijn Coenen    public int getMaxTransceiveLength() {
128faca12adc62d148505fadfd286e6a2752c197fa0Martijn Coenen        return getMaxTransceiveLengthInternal();
129faca12adc62d148505fadfd286e6a2752c197fa0Martijn Coenen    }
130faca12adc62d148505fadfd286e6a2752c197fa0Martijn Coenen
131faca12adc62d148505fadfd286e6a2752c197fa0Martijn Coenen    /**
13282328bfd40008d85917cc01a1b2eb8eed1f23ec4Nick Pelly     * Set the {@link #transceive} timeout in milliseconds.
13382328bfd40008d85917cc01a1b2eb8eed1f23ec4Nick Pelly     *
13482328bfd40008d85917cc01a1b2eb8eed1f23ec4Nick Pelly     * <p>The timeout only applies to {@link #transceive} on this object,
13582328bfd40008d85917cc01a1b2eb8eed1f23ec4Nick Pelly     * and is reset to a default value when {@link #close} is called.
13682328bfd40008d85917cc01a1b2eb8eed1f23ec4Nick Pelly     *
137112fdf612db71a552fce063136bf2796df3b71ecMartijn Coenen     * <p>Setting a longer timeout may be useful when performing
138112fdf612db71a552fce063136bf2796df3b71ecMartijn Coenen     * transactions that require a long processing time on the tag
139112fdf612db71a552fce063136bf2796df3b71ecMartijn Coenen     * such as key generation.
140112fdf612db71a552fce063136bf2796df3b71ecMartijn Coenen     *
141112fdf612db71a552fce063136bf2796df3b71ecMartijn Coenen     * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
142112fdf612db71a552fce063136bf2796df3b71ecMartijn Coenen     *
143112fdf612db71a552fce063136bf2796df3b71ecMartijn Coenen     * @param timeout timeout value in milliseconds
144112fdf612db71a552fce063136bf2796df3b71ecMartijn Coenen     */
145112fdf612db71a552fce063136bf2796df3b71ecMartijn Coenen    public void setTimeout(int timeout) {
146112fdf612db71a552fce063136bf2796df3b71ecMartijn Coenen        try {
147112fdf612db71a552fce063136bf2796df3b71ecMartijn Coenen            int err = mTag.getTagService().setTimeout(TagTechnology.NFC_A, timeout);
148112fdf612db71a552fce063136bf2796df3b71ecMartijn Coenen            if (err != ErrorCodes.SUCCESS) {
149112fdf612db71a552fce063136bf2796df3b71ecMartijn Coenen                throw new IllegalArgumentException("The supplied timeout is not valid");
150112fdf612db71a552fce063136bf2796df3b71ecMartijn Coenen            }
151112fdf612db71a552fce063136bf2796df3b71ecMartijn Coenen        } catch (RemoteException e) {
152112fdf612db71a552fce063136bf2796df3b71ecMartijn Coenen            Log.e(TAG, "NFC service dead", e);
153112fdf612db71a552fce063136bf2796df3b71ecMartijn Coenen        }
154112fdf612db71a552fce063136bf2796df3b71ecMartijn Coenen    }
15520e62c9f1466ace5771e244f03a995dc0939b11bMartijn Coenen
15620e62c9f1466ace5771e244f03a995dc0939b11bMartijn Coenen    /**
15782328bfd40008d85917cc01a1b2eb8eed1f23ec4Nick Pelly     * Get the current {@link #transceive} timeout in milliseconds.
15820e62c9f1466ace5771e244f03a995dc0939b11bMartijn Coenen     *
15920e62c9f1466ace5771e244f03a995dc0939b11bMartijn Coenen     * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
16020e62c9f1466ace5771e244f03a995dc0939b11bMartijn Coenen     *
16120e62c9f1466ace5771e244f03a995dc0939b11bMartijn Coenen     * @return timeout value in milliseconds
16220e62c9f1466ace5771e244f03a995dc0939b11bMartijn Coenen     */
16320e62c9f1466ace5771e244f03a995dc0939b11bMartijn Coenen    public int getTimeout() {
16420e62c9f1466ace5771e244f03a995dc0939b11bMartijn Coenen        try {
16520e62c9f1466ace5771e244f03a995dc0939b11bMartijn Coenen            return mTag.getTagService().getTimeout(TagTechnology.NFC_A);
16620e62c9f1466ace5771e244f03a995dc0939b11bMartijn Coenen        } catch (RemoteException e) {
16720e62c9f1466ace5771e244f03a995dc0939b11bMartijn Coenen            Log.e(TAG, "NFC service dead", e);
16820e62c9f1466ace5771e244f03a995dc0939b11bMartijn Coenen            return 0;
16920e62c9f1466ace5771e244f03a995dc0939b11bMartijn Coenen        }
17020e62c9f1466ace5771e244f03a995dc0939b11bMartijn Coenen    }
1716be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton}
172