Skip to content

Commit c30b6d0

Browse files
author
Michael Haberler
committed
Type4 Tag reading support
works with Ruuvitag
1 parent 83ce827 commit c30b6d0

File tree

2 files changed

+204
-0
lines changed

2 files changed

+204
-0
lines changed

Diff for: src/Type4Tag.cpp

+177
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
#include <MFRC522v2.h>
2+
#include <Type4Tag.h>
3+
4+
Type4Tag::Type4Tag (MFRC522Extended *nfcShield) { nfc = nfcShield; }
5+
6+
Type4Tag::~Type4Tag () {}
7+
8+
NfcTag
9+
Type4Tag::read ()
10+
{
11+
StatusCode sc;
12+
uint16_t fileId, maxSize;
13+
uint8_t readAccess, writeAccess;
14+
uint16_t fileSize;
15+
uint8_t *buffer;
16+
17+
sc = SelectNdefTag_Application ();
18+
if (sc != StatusCode::STATUS_OK)
19+
goto fail;
20+
sc = SelectCapabilityContainer ();
21+
if (sc != StatusCode::STATUS_OK)
22+
goto fail;
23+
sc = readCCFile (fileId, maxSize, readAccess, writeAccess);
24+
if (sc != StatusCode::STATUS_OK)
25+
goto fail;
26+
sc = selectFile (fileId);
27+
if (sc != StatusCode::STATUS_OK)
28+
goto fail;
29+
sc = readFileLength (fileSize);
30+
if (sc != StatusCode::STATUS_OK)
31+
goto fail;
32+
buffer = (uint8_t *)calloc (maxSize, 1);
33+
sc = readFile (buffer, fileSize);
34+
if (sc == StatusCode::STATUS_OK)
35+
{
36+
NdefMessage msg (buffer, fileSize);
37+
free (buffer);
38+
return NfcTag (nfc->uid.uidByte, nfc->uid.size, NfcTag::TYPE_4,
39+
msg);
40+
}
41+
fail:
42+
return NfcTag (nfc->uid.uidByte, nfc->uid.size, NfcTag::TYPE_4);
43+
}
44+
45+
StatusCode
46+
Type4Tag::SelectNdefTag_Application ()
47+
{
48+
byte sendData[] = { 0x00, 0xA4, 0x04, 0x00, 0x07, 0xD2, 0x76,
49+
0x00, 0x00, 0x85, 0x01, 0x01, 0x00 };
50+
byte sendLen = sizeof (sendData);
51+
byte backData[2];
52+
byte backLen = 2;
53+
54+
StatusCode statusCode = nfc->TCL_Transceive (
55+
&nfc->tag, sendData, sizeof (sendData), backData, &backLen);
56+
if (statusCode != StatusCode::STATUS_OK)
57+
return statusCode;
58+
if (backLen < 2)
59+
return StatusCode::STATUS_INTERNAL_ERROR;
60+
61+
if (backData[backLen - 2] != 0x90 || backData[backLen - 1] != 0x00)
62+
return StatusCode::STATUS_ERROR;
63+
return StatusCode::STATUS_OK;
64+
}
65+
66+
StatusCode
67+
Type4Tag::SelectCapabilityContainer ()
68+
{
69+
byte sendData[] = { 0x00, 0xA4, 0x00, 0x0C, 0x02, 0xE1, 0x03 };
70+
byte backData[3] = { 0 };
71+
byte backLen = 3; // sizeof(backData);
72+
73+
StatusCode statusCode = nfc->TCL_Transceive (
74+
&nfc->tag, sendData, sizeof (sendData), backData, &backLen);
75+
if (statusCode != StatusCode::STATUS_OK)
76+
return statusCode;
77+
if (backLen < 2)
78+
return StatusCode::STATUS_INTERNAL_ERROR;
79+
if (backData[backLen - 2] != 0x90 || backData[backLen - 1] != 0x00)
80+
return StatusCode::STATUS_ERROR;
81+
82+
return StatusCode::STATUS_OK;
83+
}
84+
85+
StatusCode
86+
Type4Tag::readCCFile (uint16_t &fileId, uint16_t &maxSize, uint8_t &readAccess,
87+
uint8_t &writeAccess)
88+
{
89+
uint8_t readCmd[] = { 0x00, 0xB0, 0x00, 0x00, 0x0F };
90+
uint8_t response[17];
91+
uint8_t responseLen = sizeof (response);
92+
93+
StatusCode statusCode = nfc->TCL_Transceive (
94+
&nfc->tag, readCmd, sizeof (readCmd), response, &responseLen);
95+
if (statusCode != StatusCode::STATUS_OK)
96+
return statusCode;
97+
if (responseLen < 2)
98+
return StatusCode::STATUS_INTERNAL_ERROR;
99+
if (response[responseLen - 2] != 0x90 || response[responseLen - 1] != 0x00)
100+
return StatusCode::STATUS_ERROR;
101+
102+
fileId = (response[9] << 8) | response[10];
103+
maxSize = (response[11] << 8) | response[12];
104+
readAccess = response[13];
105+
writeAccess = response[14];
106+
return statusCode;
107+
}
108+
109+
StatusCode
110+
Type4Tag::selectFile (const uint16_t fileId)
111+
{
112+
uint8_t selectCmd[]
113+
= { 0x00, 0xA4, 0x00, 0x0C, 0x02, (fileId >> 8) & 0xff, fileId & 0xff };
114+
uint8_t response[3];
115+
uint8_t responseLen = sizeof (response);
116+
117+
StatusCode statusCode = nfc->TCL_Transceive (
118+
&nfc->tag, selectCmd, sizeof (selectCmd), response, &responseLen);
119+
if (statusCode != StatusCode::STATUS_OK)
120+
return statusCode;
121+
if (responseLen < 2)
122+
return StatusCode::STATUS_INTERNAL_ERROR;
123+
124+
if (response[responseLen - 2] != 0x90 || response[responseLen - 1] != 0x00)
125+
return StatusCode::STATUS_ERROR;
126+
return StatusCode::STATUS_OK;
127+
}
128+
129+
StatusCode
130+
Type4Tag::readFileLength (uint16_t &fileSize)
131+
{
132+
uint8_t cmd[] = { 0x00, 0xB0, 0x00, 0x00, 0x02 };
133+
uint8_t response[5];
134+
uint8_t responseLen = sizeof (response);
135+
136+
StatusCode statusCode = nfc->TCL_Transceive (&nfc->tag, cmd, sizeof (cmd),
137+
response, &responseLen);
138+
if (statusCode != StatusCode::STATUS_OK)
139+
return statusCode;
140+
if (responseLen < 2)
141+
return StatusCode::STATUS_INTERNAL_ERROR;
142+
if (response[responseLen - 2] != 0x90 || response[responseLen - 1] != 0x00)
143+
return StatusCode::STATUS_ERROR;
144+
145+
fileSize = (response[0] << 8) | response[1];
146+
return statusCode;
147+
}
148+
149+
StatusCode
150+
Type4Tag::readFile (uint8_t *response, const size_t fileLength)
151+
{
152+
StatusCode statusCode = StatusCode::STATUS_OK;
153+
uint8_t buffer[fileLength];
154+
uint8_t responseLen;
155+
bool success = true;
156+
size_t mtu = MFRC522::FIFO_SIZE - 6; // leave room for CRC etc
157+
size_t pos = 0;
158+
while ((pos < fileLength) && success)
159+
{
160+
uint8_t read_len
161+
= ((fileLength - pos) > mtu) ? mtu : (fileLength - pos);
162+
uint8_t readstart = pos;
163+
uint8_t readCmd[5] = { 0x00, 0xB0, (readstart >> 8) & 0xff,
164+
readstart & 0xff, read_len };
165+
responseLen = fileLength;
166+
statusCode = nfc->TCL_Transceive (
167+
&nfc->tag, readCmd, sizeof (readCmd), buffer, &responseLen);
168+
success = (statusCode == StatusCode::STATUS_OK);
169+
if (success)
170+
{
171+
memcpy (response, buffer + 2, responseLen - 2);
172+
response += (responseLen - 2);
173+
}
174+
pos += read_len;
175+
}
176+
return success ? StatusCode::STATUS_OK : statusCode;
177+
}

Diff for: src/Type4Tag.h

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#pragma once
2+
3+
#include <MFRC522Extended.h>
4+
#include <MFRC522v2.h>
5+
#include <Ndef.h>
6+
#include <NfcTag.h>
7+
8+
using StatusCode = MFRC522Constants::StatusCode;
9+
10+
class Type4Tag
11+
{
12+
13+
public:
14+
Type4Tag (MFRC522Extended *nfcShield);
15+
~Type4Tag ();
16+
NfcTag read ();
17+
18+
private:
19+
MFRC522Extended *nfc;
20+
StatusCode SelectNdefTag_Application ();
21+
StatusCode SelectCapabilityContainer ();
22+
StatusCode readCCFile (uint16_t &fileId, uint16_t &maxSize,
23+
uint8_t &readAccess, uint8_t &writeAccess);
24+
StatusCode selectFile (const uint16_t fileId);
25+
StatusCode readFileLength (uint16_t &fileSize);
26+
StatusCode readFile (uint8_t *response, const size_t fileLength);
27+
};

0 commit comments

Comments
 (0)