I'm trying to read the content of a Mifare Ultralight card using the NFC contactless reader ACR122U Android SDK.
I am able to get following hex values
01 03 A0 0C 44 03 15 D1 01 11 54 02 65 6E 33 34
But I am unable to get my actual data. Please guide me how to extract byte array from above hex values.
So it seems that you read 4 pages starting at page 4 from this MIFARE Ultralight tag. Moreover, the tag seems to be formatted according to the NFC Forum Type 2 Tag Operation specification (available from the NFC Forum website).
A Type 2 Tag contains a series of tag-length-value (TLV) structures:
01 (Tag: Lock Control TLV)
03 (Length: 3 bytes)
A0 0C 44 (Value: Information on position and function of lock bytes)
03 (Tag: NDEF Message TLV)
15 (Length: 21 bytes)
D101115402656E3334... (Value: NDEF message)
You would have to issue a read command for the next 4 pages to obtain the remaining data of the NDEF message.
For now, we know, that the tag contains an NDEF message starting with
D101115402656E3334
This translates to
D1 (Header byte of record 1)
- Message begin is set (= first record of an NDEF message)
- Message end is set (= last record of an NDEF message)
- Short record flag is set (= Payload length field consists of 1 byte only)
- Type Name Format = 0x1 (= Type field contains an NFC Forum well-known type)
01 (Type length: 1 byte)
11 (Payload length: 17 bytes)
54 (Type: "T")
02656E3334... (Payload field)
The payload field of an NFC Forum Text record decodes like this:
02 (Status byte: Text is UTF-8 encoded, Language code has a length of 2 bytes)
656E (Language code: "en")
3334... (Text: "34"...)
Related
I am trying to print some currency with Citaq v8 (it has a termal printer), but it prints ?, because of the printer character set.
I have byte array (UTF-8) data to print. But the printer has default some character set. How can I change the default character set programatically(like using byte array)? I need to change printer charset settings.
Device: Citaq v8 (the device has a termal printer)
PS: I could not find any developer docs.
Perhaps UTF-8 is not supported as a character set/code table.
Even EPSON is supported only on some models.
FS ( C <Function 48>
Select character encode system
ASCII FS ( C pL pH fn m
Hex 1C 28 43 02 00 30 m
Decimal 28 40 67 2 0 48 m
TM-P20
1, 49 ASCII (ISCII) ISCII: Indian Script Code for Information Interchange
2, 50 UTF-8 Unicode encoding system
TM-m30II, TM-m30II-H, TM-m30II-NT
1, 49 1-byte character encoding Non-Unicode encoding method (ASCII [extended], Shift JIS, Big5, GB2312, GB18030, KS C, etc.)
2, 50 UTF-8 Unicode encoding system
You need to set the printer code page using the following two ESC/POS commands, and the character string to be requested for printing must be encoded and converted according to the code page before sending.
ESC t
Select character code table
ASCII ESC t n
Hex 1B 74 n
Decimal 27 116 n
ESC R
Select an international character set
ASCII ESC R n
Hex 1B 52 n
Decimal 27 82 n
Alternatively, you can create all the page contents to be printed with a Bitmap image and print it with one of the ESC/POS commands related to image printing.
However, it will be slow.
I am working on a Mobile Programming project. The Mobile program aims to write uri information like http://example.com as uri payload and wifi credentials so that when you tap nfc tag you can connect to wifi and open up uri in the browser.
I have tested to write two information into one nfc tag but it does not seem to provide two operations at the same time.
If the project is successful on tap onto nfc tag the mobile has to popup wifi connection and open uri in the browser.
If anyone has the clue i will be so pleased to follow!
NDEF message is composed of NDEF Records. In this case, the message should consist of 4 records namely:
URI Record Type representing http://example.com
Recommended Action Record
Title Record
Wifi Simple Configuration Record defined by Wi-Fi Alliance Mime Type being application/vnd.wfa.wsc (Android Code that writes such record)
NDEF message consisting of the first 3 records is as follows. Please update it to contain the 4th record yourself.
----------
Offset Content Length Explanation
0 0xD1 1 NDEF header. TNF = 0x01(Well Known Type). SR=1, MB=1, ME=1
1 0x02 1 Record name length (2 bytes)
2 0x30 1 Length of the Smart Poster data (48 bytes)
3 “Sp” 2 The record name
5 0x81 1 NDEF header. TNF = 0x01, SR=0, MB=1, ME=0
6 0x01 1 Record name length (1 byte)
7 0x00, 0x00, 0x00, 0x0C 4 The length of the URI payload (12 bytes) (long format)
11 “U” 1 Record type: “U”
12 0x03 1 Abbreviation: “http://”
13 “example.com” 11 The URI itself.
24 0x11 1 NDEF record header (SR=1, TNF=0x01)
25 0x03 1 The length of the record name
26 0x01 1 The length of the “act” payload.
27 “act” 3 Record type: “act”
30 0x00 1 Action = Launch browser
31 0x11 1 NDEF record header (SR=1, TNF=0x01)
32 0x01 1 Length of the record name
33 0x12 1 Length of the record payload (18 bytes)
34 “T” 1 Record type: “T” (=Text)
35 0x05 1 Status byte for the Text (UTF-8, five-byte code)
36 “en-US” 5 ISO Language code: US-English
41 “Hello, world” 12 The text: “Hello world”, encoded in UTF-8.
----------
To answer your question of whether its possible to get the Android reader to handle these multiple records we should look at the NFC Tag Dispatch system
This system creates an intent with
- action = NfcAdapter.ACTION_NDEF_DISCOVERED
- MimeType = mimetype of the first record
- Intent's Extra NfcAdapter.EXTRA_NDEF_MESSAGES contains complete Ndef message
Therefore, Android populates mimetype of first record only.
Its left to the application or service that picks up this intent to process all the NDEF records as needed.
I am creating an Android app that uses an ACS ACR1255 reader/writer to read from / write to an NFC tag.
I can read from it fine using this APDU command (which reads 16 bytes, starting at block 04h):
String APDU_COMMAND_READ_16_BYTES =
"FF" // Class: FFh
+ " B0" // Instruction: Read Binary Blocks
+ " 00" // P1: 00h
+ " 04" // P2: Block Number (the starting block)
+ " 10"; // Le: Number of bytes to read (10h = 16 bytes = 1 block)
However, I am not having much luck trying to write to the card. When I try this command:
String APDU_COMMAND_WRITE_16_BYTES =
"FF" // Class: FFh
+ " D0" // Instruction: Write Binary Blocks
+ " 00" // P1: 00h
+ " 04" // P2: Block Number (the starting block)
+ " 10" // Lc: Length of data field (10h = 16 bytes = 1 block)
+ " 01 02 03 04 05 06 07 08 01 02 03 04 05 06 07 08" // String of data units to be written
+ ""; // Le: Empty
...I get this response: 6A 81.
According to table 12 on this page, the 6A part means "Wrong parameter(s) P1-P2 (further qualification in SW2, see table 18)". However, table 18 says the 81 parts means "Function not supported".
So I'm not sure what's quite wrong. Could someone clarify for me what the problem is. What command do I need to successfully write to the tag?
NB - The tag in question is a MIFARE Ultralight EV1 MFOUL21. (And I can write to it fine using Android's MifareUltralight class.)
I've just found the solution in this Standard Instructions table. That table shows that as well as the WRITE BINARY (D0) instruction, there is also an UPDATE BINARY (D6) instruction.
My tag already had data on the block I was trying to write to, so I need to use UPDATE BINARY instead. So just changing my D0 to D6 has solved the problem.
Update
These resources may also help other newbies to APDU:
NFC Forum - Type 2 Tag Operation
Specification
ISO 7816-4 Section 6 - Basic Interindustry Commands
Complete list of APDU responses
I write a text to a Mifare Classic 1K tag using the NFC Tools app on my Android device (through the built-in NFC reader). This text is "moretto" (my last name).
Then, I'm trying to read this text (NDEF format) using the NFC reader ACR1255U with the library provided by ACS.
I am able to get following:
Read block 4: FF B0 00 04 10 response: 0000030ED1010A5402656E6D6F726574 9000
Read block 5: FF B0 00 05 10 response: 746FFE00000000000000000000000000 9000
I know that FE indicates the end of content and 6D6F726574746F is my text. But how do I identify where the text begins? I have difficulties to understand the TLV format described in the NXP documentation.
First of all, NXP's proprietary NDEF mapping for MIFARE Classic tags is specified in these two application notes:
NFC Type MIFARE Classic Tag Operation
MIFARE Classic as NFC Type MIFARE Classic Tag
As you already found (Unable to authenticate to a MIFARE Classic tag used as NDEF tag), the NDEF data is stored in the data blocks of certain sectors (the NDEF sectors, marked as such by means of the MIFARE Application Directory). Thus, the data relevant for NDEF is the combination of all data from these blocks.
E.g. if your NDEF sectors are sector 1 and 2, you would need to read blocks 4, 5, 6 (= blocks 0..2 of sector 1) and blocks 8, 9, 10 (= blocks 0..2 of sector 2) to aggregate the data of the NDEF tag.
In your case, the data from blocks 4 and 5 seems to be sufficient (since the end of tag data is marked in block 5, as you correctly found yourself). The relevant tag data in your case is
0000030E D1010A54 02656E6D 6F726574
746FFE00 00000000 00000000 00000000
The tag data itself is packed into TLV (tag-length-value) structures. A TLV block consists of a mandatory tag byte, a conditional length field, and an optional data field:
TLVs that don't have length and data fields:
+----------+
| TAG |
| (1 byte) |
+----------+
TLVs where the data field has a length from 0 to 254 bytes:
+----------+----------+-----------+
| TAG | LENGHT n | DATA |
| (1 byte) | (1 byte) | (n bytes) |
+----------+----------+-----------+
TLVs where the data field has a length from 255 to 65534 bytes:
+----------+----------+-----------+-----------+
| TAG | 0xFF | LENGHT n | DATA |
| (1 byte) | (1 byte) | (2 bytes) | (n bytes) |
+----------+----------+-----------+-----------+
The interesting tags in your specific case are:
NULL TLV: Tag = 0x00, no length field, no data field
Terminator TLV: Tag = 0xFE, no length field, no data field
NDEF Message TLV: Tag = 0x03, has field, has data field (may have zero length though)
Consequently, in your case the data decodes to:
00 NULL TLV (ignore, process next byte)
00 NULL TLV (ignore, process next byte)
03 NDEF Message TLV (contains your NDEF message)
0E Lenght = 14 bytes
D1010A5402656E6D6F726574746F Data = NDEF Message
FE Terminator TLV (stop processing the data)
An NDEF message can consist of 0, 1 or more NDEF records. In your case, the NDEF message decodes to the following:
D1 Record header (of first and only record)
Bit 7 = MB = 1: first record of NDEF message
Bit 6 = ME = 1: last record of NDEF message
Bit 5 = CF = 0: last or only record of chain
Bit 4 = SR = 1: short record length field
Bit 3 = IL = 0: no ID/ID length fields
Bit 2..0 = TNF = 0x1: Type field represents an NFC Forum
well-known type name
01 Type Length = 1 byte
0A Payload length = 10 bytes
54 Type field (decoded according to the setting of TNF)
"T" (in US-ASCII) = binary form of type name urn:nfc:wkt:T
02656E6D6F726574746F Payload field (decoded according to the value of the Type field)
Therefore, your NDEF message consists of one Text record (NFC FOrum well-known type with the data payload 02656E6D6F726574746F. This record payload decodes to:
02 Status byte
Bit 7 = 0: Text is UTF-8 encoded
Bit 6 = 0: Not used
Bit 5..0 = 0x02: Length of IANA language code field
656E IANA language code field
"en" (in US-ASCII) = Text is in English
6D6F726574746F Text
"moretto" (in UTF-8)
i am building android application which connect to nfc secure element and get data to the android device.for building secure element i used java card API.In the jcop tools send ATR command to reset the java card.This is the sending commands.
/card -a a000000003000000 -c com.ibm.jc.CardManager
resetCard with timeout: 0 (ms)
--Waiting for card...
ATR=3B F8 18 00 FF 81 31 FE 45 4A 43 4F 50 76 32 34 ;.....1.EJCOPv24
31 43 1C
ATR: T=1, FI=1/DI=8 (31clk/etu), N=-1, IFSC=254, BWI=4/CWI=5, Hist="JCOPv241"
=> 00 A4 04 00 08 A0 00 00 00 03 00 00 00 00
i am using jcop tools for that.Secure element part is complete.but my android application need to send more request to secure element at one second.I used create a tag and send data this way.
byte[] GET_STRING = {
(byte) 0x80, // CLA Class
0x04, // INS Instruction
0x00, // P1 Parameter 1
0x00, // P2 Parameter 2
0x10 // LE maximal number of bytes expected in result
};
result = tag.transceive(GET_STRING);
int len = result.length;
if (!(result[len-2]==(byte)0x90&&result[len-1]==(byte) 0x00))
throw new RuntimeException("could not retrieve msisdn");
byte[] data = new byte[len-2];
System.arraycopy(result, 0, data, 0, len-2);
String str = new String(data).trim();
tag.close()
But I need to know how to send ATR command using android isoDep connection. if it is not possible how to reset the java card after getting data.
Thanks
Sajith
Regarding your terminology:
On the contactless interface, you card does not have a reset sequence that produces an ATR. However, there is two comparable events on the contactless interface. One is turning the HF field off ann on. This causes a power-loss and consequently a hard reset of the card. The second one is to put the contactless card in HALT state and re-activate the card through the activation & selection procedure as specified in ISO/IEC 14443-3. This would typically also cause a card to reset its internal state.
Regarding your question of how to reset a contactless card that is connected through Android's IsoDep:
Hard reset: That's only possible through bringing the card out of the NFC device's read range and then scanning it again.
"Soft reset": On most devices this should be possible through closing and re-opening the connection using the IsoDep instance:
IsoDep isoDepTag = IsoDep.get(tag);
[...]
isoDepTag.close();
isoDepTag.connect();
[...]
However, you should be avare that some device (e.g. the Galaxy S4 in combination with certain Android versions) will not properly perform a soft reset (HALT + reactivation/selection) and, instead, just continue the previous connection.