MifareUltralight.java revision 4e21e1d21a877cce4db5ec8c5786604cc10f2d7e
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.RemoteException;
21
22import java.io.IOException;
23
24/**
25 * Technology class representing MIFARE Ultralight and MIFARE Ultralight C tags.
26 *
27 * <p>Support for this technology type is optional. If the NFC stack doesn't support this technology
28 * MIFARE Ultralight class tags will still be scanned, but will only show the NfcA technology.
29 *
30 * <p>MIFARE Ultralight class tags have a series of 4 bytes pages that can be individually written
31 * and read in chunks of 4 for a total read of 16 bytes.
32 */
33public final class MifareUltralight extends BasicTagTechnology {
34    /** A MIFARE Ultralight tag */
35    public static final int TYPE_ULTRALIGHT = 1;
36    /** A MIFARE Ultralight C tag */
37    public static final int TYPE_ULTRALIGHT_C = 2;
38    /** The tag type is unknown */
39    public static final int TYPE_UNKNOWN = 10;
40
41    private static final int NXP_MANUFACTURER_ID = 0x04;
42
43    private int mType;
44
45    /**
46     * Returns an instance of this tech for the given tag. If the tag doesn't support
47     * this tech type null is returned.
48     *
49     * @param tag The tag to get the tech from
50     */
51    public static MifareUltralight get(Tag tag) {
52        if (!tag.hasTech(TagTechnology.MIFARE_ULTRALIGHT)) return null;
53        try {
54            return new MifareUltralight(tag);
55        } catch (RemoteException e) {
56            return null;
57        }
58    }
59
60    /** @hide */
61    public MifareUltralight(Tag tag) throws RemoteException {
62        super(tag, TagTechnology.MIFARE_ULTRALIGHT);
63
64        // Check if this could actually be a Mifare
65        NfcA a = NfcA.get(tag);
66
67        mType = TYPE_UNKNOWN;
68
69        if (a.getSak() == 0x00 && tag.getId()[0] == NXP_MANUFACTURER_ID) {
70            // could be UL or UL-C
71            mType = TYPE_ULTRALIGHT;
72        }
73    }
74
75    /** Returns the type of the tag */
76    public int getType() {
77        return mType;
78    }
79
80    // Methods that require connect()
81    /**
82     * Reads a single 16 byte block from the given page offset.
83     *
84     * <p>This requires a that the tag be connected.
85     *
86     * @throws IOException
87     */
88    public byte[] readBlock(int page) throws IOException {
89        checkConnected();
90
91        byte[] blockread_cmd = { 0x30, (byte) page}; // phHal_eMifareRead
92        return transceive(blockread_cmd, false);
93    }
94
95    /**
96     * Writes a 4 byte page to the tag.
97     *
98     * <p>This requires a that the tag be connected.
99     *
100     * @param page The offset of the page to write
101     * @param data The data to write
102     * @throws IOException
103     */
104    public void writePage(int page, byte[] data) throws IOException {
105        checkConnected();
106
107        byte[] pagewrite_cmd = new byte[data.length + 2];
108        pagewrite_cmd[0] = (byte) 0xA2;
109        pagewrite_cmd[1] = (byte) page;
110        System.arraycopy(data, 0, pagewrite_cmd, 2, data.length);
111
112        transceive(pagewrite_cmd, false);
113    }
114
115    /**
116     * Send raw NfcA data to a tag and receive the response.
117     * <p>
118     * This method will block until the response is received. It can be canceled
119     * with {@link #close}.
120     * <p>Requires {@link android.Manifest.permission#NFC} permission.
121     * <p>This requires a that the tag be connected.
122     *
123     * @param data bytes to send
124     * @return bytes received in response
125     * @throws IOException if the target is lost or connection closed
126     */
127    public byte[] transceive(byte[] data) throws IOException {
128        return transceive(data, true);
129    }
130}
131