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;
23a924973f22aedc580708625e4babb6deabc6b4d3Martijn Coenenimport android.util.Log;
246be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton
25ce3224cda51f946871daa1e11e3976e25c59e6faJeff Hamiltonimport java.io.IOException;
26ce3224cda51f946871daa1e11e3976e25c59e6faJeff Hamilton
276be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton/**
2874fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * Provides access to NFC-F (JIS 6319-4) properties and I/O operations on a {@link Tag}.
296be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton *
3074fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * <p>Acquire a {@link NfcF} object using {@link #get}.
3174fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * <p>The primary NFC-F 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 NfcF extends BasicTagTechnology {
38a924973f22aedc580708625e4babb6deabc6b4d3Martijn Coenen    private static final String TAG = "NFC";
39a924973f22aedc580708625e4babb6deabc6b4d3Martijn Coenen
40438feb9b3b7f79ab56abf47f817e6326fa8d7fe1Martijn Coenen    /** @hide */
41438feb9b3b7f79ab56abf47f817e6326fa8d7fe1Martijn Coenen    public static final String EXTRA_SC = "systemcode";
42438feb9b3b7f79ab56abf47f817e6326fa8d7fe1Martijn Coenen    /** @hide */
43438feb9b3b7f79ab56abf47f817e6326fa8d7fe1Martijn Coenen    public static final String EXTRA_PMM = "pmm";
44438feb9b3b7f79ab56abf47f817e6326fa8d7fe1Martijn Coenen
45438feb9b3b7f79ab56abf47f817e6326fa8d7fe1Martijn Coenen    private byte[] mSystemCode = null;
46438feb9b3b7f79ab56abf47f817e6326fa8d7fe1Martijn Coenen    private byte[] mManufacturer = null;
47438feb9b3b7f79ab56abf47f817e6326fa8d7fe1Martijn Coenen
484e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton    /**
4974fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * Get an instance of {@link NfcF} for the given tag.
5074fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * <p>Returns null if {@link NfcF} was not enumerated in {@link Tag#getTechList}.
5174fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * This indicates the tag does not support NFC-F.
5274fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * <p>Does not cause any RF activity and does not block.
534e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton     *
5474fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * @param tag an NFC-F compatible tag
5574fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * @return NFC-F object
564e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton     */
574e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton    public static NfcF get(Tag tag) {
584e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton        if (!tag.hasTech(TagTechnology.NFC_F)) return null;
594e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton        try {
604e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton            return new NfcF(tag);
614e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton        } catch (RemoteException e) {
624e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton            return null;
634e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton        }
644e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton    }
654e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton
66ce3224cda51f946871daa1e11e3976e25c59e6faJeff Hamilton    /** @hide */
674e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton    public NfcF(Tag tag) throws RemoteException {
684e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton        super(tag, TagTechnology.NFC_F);
694e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton        Bundle extras = tag.getTechExtras(TagTechnology.NFC_F);
70438feb9b3b7f79ab56abf47f817e6326fa8d7fe1Martijn Coenen        if (extras != null) {
71438feb9b3b7f79ab56abf47f817e6326fa8d7fe1Martijn Coenen            mSystemCode = extras.getByteArray(EXTRA_SC);
72438feb9b3b7f79ab56abf47f817e6326fa8d7fe1Martijn Coenen            mManufacturer = extras.getByteArray(EXTRA_PMM);
73438feb9b3b7f79ab56abf47f817e6326fa8d7fe1Martijn Coenen        }
74438feb9b3b7f79ab56abf47f817e6326fa8d7fe1Martijn Coenen    }
75438feb9b3b7f79ab56abf47f817e6326fa8d7fe1Martijn Coenen
7674fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly    /**
7774fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * Return the System Code bytes from tag discovery.
7874fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     *
7974fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * <p>Does not cause any RF activity and does not block.
8074fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     *
8174fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * @return System Code bytes
8274fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     */
83438feb9b3b7f79ab56abf47f817e6326fa8d7fe1Martijn Coenen    public byte[] getSystemCode() {
84438feb9b3b7f79ab56abf47f817e6326fa8d7fe1Martijn Coenen      return mSystemCode;
85438feb9b3b7f79ab56abf47f817e6326fa8d7fe1Martijn Coenen    }
86438feb9b3b7f79ab56abf47f817e6326fa8d7fe1Martijn Coenen
8774fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly    /**
8874fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * Return the Manufacturer bytes from tag discovery.
8974fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     *
9074fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * <p>Does not cause any RF activity and does not block.
9174fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     *
9274fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * @return Manufacturer bytes
9374fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     */
94438feb9b3b7f79ab56abf47f817e6326fa8d7fe1Martijn Coenen    public byte[] getManufacturer() {
95438feb9b3b7f79ab56abf47f817e6326fa8d7fe1Martijn Coenen      return mManufacturer;
966be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton    }
97ce3224cda51f946871daa1e11e3976e25c59e6faJeff Hamilton
98ce3224cda51f946871daa1e11e3976e25c59e6faJeff Hamilton    /**
9974fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * Send raw NFC-F commands to the tag and receive the response.
10074fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     *
10174fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * <p>Applications must not append the SoD (length) or EoD (CRC) to the payload,
10274fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * it will be automatically calculated.
10374fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     *
104faca12adc62d148505fadfd286e6a2752c197fa0Martijn Coenen     * <p>Use {@link #getMaxTransceiveLength} to retrieve the maximum amount of bytes
105faca12adc62d148505fadfd286e6a2752c197fa0Martijn Coenen     * that can be sent with {@link #transceive}.
106faca12adc62d148505fadfd286e6a2752c197fa0Martijn Coenen     *
10774fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * <p>This is an I/O operation and will block until complete. It must
10874fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * not be called from the main application thread. A blocked call will be canceled with
10974fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * {@link IOException} if {@link #close} is called from another thread.
110ce3224cda51f946871daa1e11e3976e25c59e6faJeff Hamilton     *
11139cf3a445e507f219ecc8a476f6038f095d9d520Nick Pelly     * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
11239cf3a445e507f219ecc8a476f6038f095d9d520Nick Pelly     *
113ce3224cda51f946871daa1e11e3976e25c59e6faJeff Hamilton     * @param data bytes to send
114ce3224cda51f946871daa1e11e3976e25c59e6faJeff Hamilton     * @return bytes received in response
11574fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * @throws TagLostException if the tag leaves the field
11674fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * @throws IOException if there is an I/O failure, or this operation is canceled
117ce3224cda51f946871daa1e11e3976e25c59e6faJeff Hamilton     */
118ce3224cda51f946871daa1e11e3976e25c59e6faJeff Hamilton    public byte[] transceive(byte[] data) throws IOException {
119ce3224cda51f946871daa1e11e3976e25c59e6faJeff Hamilton        return transceive(data, true);
120ce3224cda51f946871daa1e11e3976e25c59e6faJeff Hamilton    }
121a924973f22aedc580708625e4babb6deabc6b4d3Martijn Coenen
122a924973f22aedc580708625e4babb6deabc6b4d3Martijn Coenen    /**
123faca12adc62d148505fadfd286e6a2752c197fa0Martijn Coenen     * Return the maximum number of bytes that can be sent with {@link #transceive}.
124faca12adc62d148505fadfd286e6a2752c197fa0Martijn Coenen     * @return the maximum number of bytes that can be sent with {@link #transceive}.
125faca12adc62d148505fadfd286e6a2752c197fa0Martijn Coenen     */
126faca12adc62d148505fadfd286e6a2752c197fa0Martijn Coenen    public int getMaxTransceiveLength() {
127faca12adc62d148505fadfd286e6a2752c197fa0Martijn Coenen        return getMaxTransceiveLengthInternal();
128faca12adc62d148505fadfd286e6a2752c197fa0Martijn Coenen    }
129faca12adc62d148505fadfd286e6a2752c197fa0Martijn Coenen
130faca12adc62d148505fadfd286e6a2752c197fa0Martijn Coenen    /**
13182328bfd40008d85917cc01a1b2eb8eed1f23ec4Nick Pelly     * Set the {@link #transceive} timeout in milliseconds.
13282328bfd40008d85917cc01a1b2eb8eed1f23ec4Nick Pelly     *
13382328bfd40008d85917cc01a1b2eb8eed1f23ec4Nick Pelly     * <p>The timeout only applies to {@link #transceive} on this object,
13482328bfd40008d85917cc01a1b2eb8eed1f23ec4Nick Pelly     * and is reset to a default value when {@link #close} is called.
13582328bfd40008d85917cc01a1b2eb8eed1f23ec4Nick Pelly     *
136a924973f22aedc580708625e4babb6deabc6b4d3Martijn Coenen     * <p>Setting a longer timeout may be useful when performing
137a924973f22aedc580708625e4babb6deabc6b4d3Martijn Coenen     * transactions that require a long processing time on the tag
138a924973f22aedc580708625e4babb6deabc6b4d3Martijn Coenen     * such as key generation.
139a924973f22aedc580708625e4babb6deabc6b4d3Martijn Coenen     *
140a924973f22aedc580708625e4babb6deabc6b4d3Martijn Coenen     * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
141a924973f22aedc580708625e4babb6deabc6b4d3Martijn Coenen     *
142a924973f22aedc580708625e4babb6deabc6b4d3Martijn Coenen     * @param timeout timeout value in milliseconds
143a924973f22aedc580708625e4babb6deabc6b4d3Martijn Coenen     */
144a924973f22aedc580708625e4babb6deabc6b4d3Martijn Coenen    public void setTimeout(int timeout) {
145a924973f22aedc580708625e4babb6deabc6b4d3Martijn Coenen        try {
146112fdf612db71a552fce063136bf2796df3b71ecMartijn Coenen            int err = mTag.getTagService().setTimeout(TagTechnology.NFC_F, timeout);
147112fdf612db71a552fce063136bf2796df3b71ecMartijn Coenen            if (err != ErrorCodes.SUCCESS) {
148112fdf612db71a552fce063136bf2796df3b71ecMartijn Coenen                throw new IllegalArgumentException("The supplied timeout is not valid");
149112fdf612db71a552fce063136bf2796df3b71ecMartijn Coenen            }
150a924973f22aedc580708625e4babb6deabc6b4d3Martijn Coenen        } catch (RemoteException e) {
151a924973f22aedc580708625e4babb6deabc6b4d3Martijn Coenen            Log.e(TAG, "NFC service dead", e);
152a924973f22aedc580708625e4babb6deabc6b4d3Martijn Coenen        }
153a924973f22aedc580708625e4babb6deabc6b4d3Martijn Coenen    }
15420e62c9f1466ace5771e244f03a995dc0939b11bMartijn Coenen
15520e62c9f1466ace5771e244f03a995dc0939b11bMartijn Coenen    /**
15682328bfd40008d85917cc01a1b2eb8eed1f23ec4Nick Pelly     * Get the current {@link #transceive} timeout in milliseconds.
15720e62c9f1466ace5771e244f03a995dc0939b11bMartijn Coenen     *
15820e62c9f1466ace5771e244f03a995dc0939b11bMartijn Coenen     * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
15920e62c9f1466ace5771e244f03a995dc0939b11bMartijn Coenen     *
16020e62c9f1466ace5771e244f03a995dc0939b11bMartijn Coenen     * @return timeout value in milliseconds
16120e62c9f1466ace5771e244f03a995dc0939b11bMartijn Coenen     */
16220e62c9f1466ace5771e244f03a995dc0939b11bMartijn Coenen    public int getTimeout() {
16320e62c9f1466ace5771e244f03a995dc0939b11bMartijn Coenen        try {
16420e62c9f1466ace5771e244f03a995dc0939b11bMartijn Coenen            return mTag.getTagService().getTimeout(TagTechnology.NFC_F);
16520e62c9f1466ace5771e244f03a995dc0939b11bMartijn Coenen        } catch (RemoteException e) {
16620e62c9f1466ace5771e244f03a995dc0939b11bMartijn Coenen            Log.e(TAG, "NFC service dead", e);
16720e62c9f1466ace5771e244f03a995dc0939b11bMartijn Coenen            return 0;
16820e62c9f1466ace5771e244f03a995dc0939b11bMartijn Coenen        }
16920e62c9f1466ace5771e244f03a995dc0939b11bMartijn Coenen    }
1706be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton}
171