Loading api/current.xml +21 −10 Original line number Diff line number Diff line Loading @@ -103597,33 +103597,33 @@ visibility="public" > </field> <field name="TYPE_OTHER" <field name="TYPE_PLUS" type="int" transient="false" volatile="false" value="-1" value="1" static="true" final="true" deprecated="not deprecated" visibility="public" > </field> <field name="TYPE_PLUS" <field name="TYPE_PRO" type="int" transient="false" volatile="false" value="1" value="2" static="true" final="true" deprecated="not deprecated" visibility="public" > </field> <field name="TYPE_PRO" <field name="TYPE_UNKNOWN" type="int" transient="false" volatile="false" value="2" value="-1" static="true" final="true" deprecated="not deprecated" Loading Loading @@ -103663,7 +103663,7 @@ visibility="public" > </method> <method name="readBlock" <method name="readPages" return="byte[]" abstract="false" native="false" Loading @@ -103673,7 +103673,7 @@ deprecated="not deprecated" visibility="public" > <parameter name="page" type="int"> <parameter name="pageOffset" type="int"> </parameter> <exception name="IOException" type="java.io.IOException"> </exception> Loading Loading @@ -103703,13 +103703,24 @@ deprecated="not deprecated" visibility="public" > <parameter name="page" type="int"> <parameter name="pageOffset" type="int"> </parameter> <parameter name="data" type="byte[]"> </parameter> <exception name="IOException" type="java.io.IOException"> </exception> </method> <field name="PAGE_SIZE" type="int" transient="false" volatile="false" value="4" static="true" final="true" deprecated="not deprecated" visibility="public" > </field> <field name="TYPE_ULTRALIGHT" type="int" transient="false" Loading @@ -103736,7 +103747,7 @@ type="int" transient="false" volatile="false" value="10" value="-1" static="true" final="true" deprecated="not deprecated" core/java/android/nfc/tech/MifareClassic.java +10 −10 Original line number Diff line number Diff line Loading @@ -55,14 +55,14 @@ public final class MifareClassic extends BasicTagTechnology { public static final byte[] KEY_NFC_FORUM = {(byte)0xD3,(byte)0xF7,(byte)0xD3,(byte)0xF7,(byte)0xD3,(byte)0xF7}; /** A Mifare Classic compatible card of unknown type */ public static final int TYPE_UNKNOWN = -1; /** A MIFARE Classic tag */ public static final int TYPE_CLASSIC = 0; /** A MIFARE Plus tag */ public static final int TYPE_PLUS = 1; /** A MIFARE Pro tag */ public static final int TYPE_PRO = 2; /** A Mifare Classic compatible card that does not match the other types */ public static final int TYPE_OTHER = -1; /** The tag contains 16 sectors, each holding 4 blocks. */ public static final int SIZE_1K = 1024; Loading Loading @@ -360,12 +360,6 @@ public final class MifareClassic extends BasicTagTechnology { transceive(cmd.array(), false); } private void validateValueOperand(int value) { if (value < 0) { throw new IllegalArgumentException("value operand negative"); } } /** * Copy from temporary memory to value block. * @param blockIndex Loading Loading @@ -410,7 +404,7 @@ public final class MifareClassic extends BasicTagTechnology { return transceive(data, true); } private void validateSector(int sector) { private static void validateSector(int sector) { // Do not be too strict on upper bounds checking, since some cards // have more addressable memory than they report. For example, // Mifare Plus 2k cards will appear as Mifare Classic 1k cards when in Loading @@ -423,10 +417,16 @@ public final class MifareClassic extends BasicTagTechnology { } } private void validateBlock(int block) { private static void validateBlock(int block) { // Just looking for obvious out of bounds... if (block < 0 || block >= MAX_BLOCK_COUNT) { throw new IndexOutOfBoundsException("block out of bounds: " + block); } } private static void validateValueOperand(int value) { if (value < 0) { throw new IllegalArgumentException("value operand negative"); } } } core/java/android/nfc/tech/MifareUltralight.java +64 −20 Original line number Diff line number Diff line Loading @@ -21,24 +21,43 @@ import android.os.RemoteException; import java.io.IOException; //TOOD: Ultralight C 3-DES authentication, one-way counter /** * Technology class representing MIFARE Ultralight and MIFARE Ultralight C tags. * * <p>Support for this technology type is optional. If the NFC stack doesn't support this technology * MIFARE Ultralight class tags will still be scanned, but will only show the NfcA technology. * * <p>MIFARE Ultralight class tags have a series of 4 bytes pages that can be individually written * and read in chunks of 4 for a total read of 16 bytes. * <p>MIFARE Ultralight compatible tags have 4 byte pages. The read command * returns 4 pages (16 bytes) at a time, for speed. The write command operates * on a single page (4 bytes) to minimize EEPROM write cycles. * * <p>The original MIFARE Ultralight consists of a 64 byte EEPROM. The first * 4 pages are for the OTP area, manufacturer data, and locking bits. They are * readable and some bits are writable. The final 12 pages are the user * read/write area. For more information see the NXP data sheet MF0ICU1. * * <p>The MIFARE Ultralight C consists of a 192 byte EEPROM. The first 4 pages * are for OTP, manufacturer data, and locking bits. The next 36 pages are the * user read/write area. The next 4 pages are additional locking bits, counters * and authentication configuration and are readable. The final 4 pages are for * the authentication key and are not readable. For more information see the * NXP data sheet MF0ICU2. */ public final class MifareUltralight extends BasicTagTechnology { /** A MIFARE Ultralight compatible tag of unknown type */ public static final int TYPE_UNKNOWN = -1; /** A MIFARE Ultralight tag */ public static final int TYPE_ULTRALIGHT = 1; /** A MIFARE Ultralight C tag */ public static final int TYPE_ULTRALIGHT_C = 2; /** The tag type is unknown */ public static final int TYPE_UNKNOWN = 10; /** Size of a MIFARE Ultralight page in bytes */ public static final int PAGE_SIZE = 4; private static final int NXP_MANUFACTURER_ID = 0x04; private static final int MAX_PAGE_COUNT = 256; private int mType; Loading Loading @@ -68,48 +87,62 @@ public final class MifareUltralight extends BasicTagTechnology { if (a.getSak() == 0x00 && tag.getId()[0] == NXP_MANUFACTURER_ID) { // could be UL or UL-C //TODO: stack should use NXP AN1303 procedure to make a best guess // attempt at classifying Ultralight vs Ultralight C. mType = TYPE_ULTRALIGHT; } } /** Returns the type of the tag */ /** Returns the type of the tag. * <p>It is very hard to always accurately classify a MIFARE Ultralight * compatible tag as Ultralight original or Ultralight C. So consider * {@link #getType} a hint. */ public int getType() { return mType; } // Methods that require connect() /** * Reads a single 16 byte block from the given page offset. * * <p>This requires a that the tag be connected. * Read 4 pages (16 bytes). * <p>The MIFARE Ultralight protocol always reads 4 pages at a time. * <p>If the read spans past the last readable block, then the tag will * return pages that have been wrapped back to the first blocks. MIFARE * Ultralight tags have readable blocks 0x00 through 0x0F. So a read to * block offset 0x0E would return blocks 0x0E, 0x0F, 0x00, 0x01. MIFARE * Ultralight C tags have readable blocks 0x00 through 0x2B. So a read to * block 0x2A would return blocks 0x2A, 0x2B, 0x00, 0x01. * <p>This requires that the tag be connected. * * @return 4 pages (16 bytes) * @throws IOException */ public byte[] readBlock(int page) throws IOException { public byte[] readPages(int pageOffset) throws IOException { validatePageOffset(pageOffset); checkConnected(); byte[] blockread_cmd = { 0x30, (byte) page}; // phHal_eMifareRead return transceive(blockread_cmd, false); byte[] cmd = { 0x30, (byte) pageOffset}; return transceive(cmd, false); } /** * Writes a 4 byte page to the tag. * * <p>This requires a that the tag be connected. * Write 1 page (4 bytes). * <p>The MIFARE Ultralight protocol always writes 1 page at a time. * <p>This requires that the tag be connected. * * @param page The offset of the page to write * @param data The data to write * @throws IOException */ public void writePage(int page, byte[] data) throws IOException { public void writePage(int pageOffset, byte[] data) throws IOException { validatePageOffset(pageOffset); checkConnected(); byte[] pagewrite_cmd = new byte[data.length + 2]; pagewrite_cmd[0] = (byte) 0xA2; pagewrite_cmd[1] = (byte) page; System.arraycopy(data, 0, pagewrite_cmd, 2, data.length); byte[] cmd = new byte[data.length + 2]; cmd[0] = (byte) 0xA2; cmd[1] = (byte) pageOffset; System.arraycopy(data, 0, cmd, 2, data.length); transceive(pagewrite_cmd, false); transceive(cmd, false); } /** Loading @@ -127,4 +160,15 @@ public final class MifareUltralight extends BasicTagTechnology { public byte[] transceive(byte[] data) throws IOException { return transceive(data, true); } private static void validatePageOffset(int pageOffset) { // Do not be too strict on upper bounds checking, since some cards // may have more addressable memory than they report. // Note that issuing a command to an out-of-bounds block is safe - the // tag will wrap the read to an addressable area. This validation is a // helper to guard against obvious programming mistakes. if (pageOffset < 0 || pageOffset >= MAX_PAGE_COUNT) { throw new IndexOutOfBoundsException("page out of bounds: " + pageOffset); } } } Loading
api/current.xml +21 −10 Original line number Diff line number Diff line Loading @@ -103597,33 +103597,33 @@ visibility="public" > </field> <field name="TYPE_OTHER" <field name="TYPE_PLUS" type="int" transient="false" volatile="false" value="-1" value="1" static="true" final="true" deprecated="not deprecated" visibility="public" > </field> <field name="TYPE_PLUS" <field name="TYPE_PRO" type="int" transient="false" volatile="false" value="1" value="2" static="true" final="true" deprecated="not deprecated" visibility="public" > </field> <field name="TYPE_PRO" <field name="TYPE_UNKNOWN" type="int" transient="false" volatile="false" value="2" value="-1" static="true" final="true" deprecated="not deprecated" Loading Loading @@ -103663,7 +103663,7 @@ visibility="public" > </method> <method name="readBlock" <method name="readPages" return="byte[]" abstract="false" native="false" Loading @@ -103673,7 +103673,7 @@ deprecated="not deprecated" visibility="public" > <parameter name="page" type="int"> <parameter name="pageOffset" type="int"> </parameter> <exception name="IOException" type="java.io.IOException"> </exception> Loading Loading @@ -103703,13 +103703,24 @@ deprecated="not deprecated" visibility="public" > <parameter name="page" type="int"> <parameter name="pageOffset" type="int"> </parameter> <parameter name="data" type="byte[]"> </parameter> <exception name="IOException" type="java.io.IOException"> </exception> </method> <field name="PAGE_SIZE" type="int" transient="false" volatile="false" value="4" static="true" final="true" deprecated="not deprecated" visibility="public" > </field> <field name="TYPE_ULTRALIGHT" type="int" transient="false" Loading @@ -103736,7 +103747,7 @@ type="int" transient="false" volatile="false" value="10" value="-1" static="true" final="true" deprecated="not deprecated"
core/java/android/nfc/tech/MifareClassic.java +10 −10 Original line number Diff line number Diff line Loading @@ -55,14 +55,14 @@ public final class MifareClassic extends BasicTagTechnology { public static final byte[] KEY_NFC_FORUM = {(byte)0xD3,(byte)0xF7,(byte)0xD3,(byte)0xF7,(byte)0xD3,(byte)0xF7}; /** A Mifare Classic compatible card of unknown type */ public static final int TYPE_UNKNOWN = -1; /** A MIFARE Classic tag */ public static final int TYPE_CLASSIC = 0; /** A MIFARE Plus tag */ public static final int TYPE_PLUS = 1; /** A MIFARE Pro tag */ public static final int TYPE_PRO = 2; /** A Mifare Classic compatible card that does not match the other types */ public static final int TYPE_OTHER = -1; /** The tag contains 16 sectors, each holding 4 blocks. */ public static final int SIZE_1K = 1024; Loading Loading @@ -360,12 +360,6 @@ public final class MifareClassic extends BasicTagTechnology { transceive(cmd.array(), false); } private void validateValueOperand(int value) { if (value < 0) { throw new IllegalArgumentException("value operand negative"); } } /** * Copy from temporary memory to value block. * @param blockIndex Loading Loading @@ -410,7 +404,7 @@ public final class MifareClassic extends BasicTagTechnology { return transceive(data, true); } private void validateSector(int sector) { private static void validateSector(int sector) { // Do not be too strict on upper bounds checking, since some cards // have more addressable memory than they report. For example, // Mifare Plus 2k cards will appear as Mifare Classic 1k cards when in Loading @@ -423,10 +417,16 @@ public final class MifareClassic extends BasicTagTechnology { } } private void validateBlock(int block) { private static void validateBlock(int block) { // Just looking for obvious out of bounds... if (block < 0 || block >= MAX_BLOCK_COUNT) { throw new IndexOutOfBoundsException("block out of bounds: " + block); } } private static void validateValueOperand(int value) { if (value < 0) { throw new IllegalArgumentException("value operand negative"); } } }
core/java/android/nfc/tech/MifareUltralight.java +64 −20 Original line number Diff line number Diff line Loading @@ -21,24 +21,43 @@ import android.os.RemoteException; import java.io.IOException; //TOOD: Ultralight C 3-DES authentication, one-way counter /** * Technology class representing MIFARE Ultralight and MIFARE Ultralight C tags. * * <p>Support for this technology type is optional. If the NFC stack doesn't support this technology * MIFARE Ultralight class tags will still be scanned, but will only show the NfcA technology. * * <p>MIFARE Ultralight class tags have a series of 4 bytes pages that can be individually written * and read in chunks of 4 for a total read of 16 bytes. * <p>MIFARE Ultralight compatible tags have 4 byte pages. The read command * returns 4 pages (16 bytes) at a time, for speed. The write command operates * on a single page (4 bytes) to minimize EEPROM write cycles. * * <p>The original MIFARE Ultralight consists of a 64 byte EEPROM. The first * 4 pages are for the OTP area, manufacturer data, and locking bits. They are * readable and some bits are writable. The final 12 pages are the user * read/write area. For more information see the NXP data sheet MF0ICU1. * * <p>The MIFARE Ultralight C consists of a 192 byte EEPROM. The first 4 pages * are for OTP, manufacturer data, and locking bits. The next 36 pages are the * user read/write area. The next 4 pages are additional locking bits, counters * and authentication configuration and are readable. The final 4 pages are for * the authentication key and are not readable. For more information see the * NXP data sheet MF0ICU2. */ public final class MifareUltralight extends BasicTagTechnology { /** A MIFARE Ultralight compatible tag of unknown type */ public static final int TYPE_UNKNOWN = -1; /** A MIFARE Ultralight tag */ public static final int TYPE_ULTRALIGHT = 1; /** A MIFARE Ultralight C tag */ public static final int TYPE_ULTRALIGHT_C = 2; /** The tag type is unknown */ public static final int TYPE_UNKNOWN = 10; /** Size of a MIFARE Ultralight page in bytes */ public static final int PAGE_SIZE = 4; private static final int NXP_MANUFACTURER_ID = 0x04; private static final int MAX_PAGE_COUNT = 256; private int mType; Loading Loading @@ -68,48 +87,62 @@ public final class MifareUltralight extends BasicTagTechnology { if (a.getSak() == 0x00 && tag.getId()[0] == NXP_MANUFACTURER_ID) { // could be UL or UL-C //TODO: stack should use NXP AN1303 procedure to make a best guess // attempt at classifying Ultralight vs Ultralight C. mType = TYPE_ULTRALIGHT; } } /** Returns the type of the tag */ /** Returns the type of the tag. * <p>It is very hard to always accurately classify a MIFARE Ultralight * compatible tag as Ultralight original or Ultralight C. So consider * {@link #getType} a hint. */ public int getType() { return mType; } // Methods that require connect() /** * Reads a single 16 byte block from the given page offset. * * <p>This requires a that the tag be connected. * Read 4 pages (16 bytes). * <p>The MIFARE Ultralight protocol always reads 4 pages at a time. * <p>If the read spans past the last readable block, then the tag will * return pages that have been wrapped back to the first blocks. MIFARE * Ultralight tags have readable blocks 0x00 through 0x0F. So a read to * block offset 0x0E would return blocks 0x0E, 0x0F, 0x00, 0x01. MIFARE * Ultralight C tags have readable blocks 0x00 through 0x2B. So a read to * block 0x2A would return blocks 0x2A, 0x2B, 0x00, 0x01. * <p>This requires that the tag be connected. * * @return 4 pages (16 bytes) * @throws IOException */ public byte[] readBlock(int page) throws IOException { public byte[] readPages(int pageOffset) throws IOException { validatePageOffset(pageOffset); checkConnected(); byte[] blockread_cmd = { 0x30, (byte) page}; // phHal_eMifareRead return transceive(blockread_cmd, false); byte[] cmd = { 0x30, (byte) pageOffset}; return transceive(cmd, false); } /** * Writes a 4 byte page to the tag. * * <p>This requires a that the tag be connected. * Write 1 page (4 bytes). * <p>The MIFARE Ultralight protocol always writes 1 page at a time. * <p>This requires that the tag be connected. * * @param page The offset of the page to write * @param data The data to write * @throws IOException */ public void writePage(int page, byte[] data) throws IOException { public void writePage(int pageOffset, byte[] data) throws IOException { validatePageOffset(pageOffset); checkConnected(); byte[] pagewrite_cmd = new byte[data.length + 2]; pagewrite_cmd[0] = (byte) 0xA2; pagewrite_cmd[1] = (byte) page; System.arraycopy(data, 0, pagewrite_cmd, 2, data.length); byte[] cmd = new byte[data.length + 2]; cmd[0] = (byte) 0xA2; cmd[1] = (byte) pageOffset; System.arraycopy(data, 0, cmd, 2, data.length); transceive(pagewrite_cmd, false); transceive(cmd, false); } /** Loading @@ -127,4 +160,15 @@ public final class MifareUltralight extends BasicTagTechnology { public byte[] transceive(byte[] data) throws IOException { return transceive(data, true); } private static void validatePageOffset(int pageOffset) { // Do not be too strict on upper bounds checking, since some cards // may have more addressable memory than they report. // Note that issuing a command to an out-of-bounds block is safe - the // tag will wrap the read to an addressable area. This validation is a // helper to guard against obvious programming mistakes. if (pageOffset < 0 || pageOffset >= MAX_PAGE_COUNT) { throw new IndexOutOfBoundsException("page out of bounds: " + pageOffset); } } }