1 |
d3bab6e9
|
henryk
|
/***************************************************************
|
2 |
|
|
*
|
3 |
|
|
* OpenPICC - ISO 14443 Layer 3 response pretender,
|
4 |
|
|
* proof of concept
|
5 |
|
|
*
|
6 |
|
|
* Copyright 2008 Henryk Plötz <henryk@ploetzli.ch>
|
7 |
|
|
*
|
8 |
|
|
***************************************************************
|
9 |
|
|
|
10 |
|
|
This program is free software; you can redistribute it and/or modify
|
11 |
|
|
it under the terms of the GNU General Public License as published by
|
12 |
|
|
the Free Software Foundation; version 2.
|
13 |
|
|
|
14 |
|
|
This program is distributed in the hope that it will be useful,
|
15 |
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
16 |
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
17 |
|
|
GNU General Public License for more details.
|
18 |
|
|
|
19 |
|
|
You should have received a copy of the GNU General Public License along
|
20 |
|
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
21 |
|
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
22 |
|
|
|
23 |
|
|
*/
|
24 |
|
|
|
25 |
|
|
#include <FreeRTOS.h>
|
26 |
|
|
#include <board.h>
|
27 |
|
|
#include <task.h>
|
28 |
|
|
#include <errno.h>
|
29 |
440a95fc
|
henryk
|
#include <string.h>
|
30 |
d3bab6e9
|
henryk
|
#include <stdlib.h>
|
31 |
|
|
|
32 |
|
|
#include "openpicc.h"
|
33 |
|
|
#include "ssc_buffer.h"
|
34 |
|
|
#include "iso14443.h"
|
35 |
|
|
#include "iso14443_layer2a.h"
|
36 |
|
|
#include "iso14443a_pretender.h"
|
37 |
|
|
#include "iso14443a_manchester.h"
|
38 |
|
|
#include "usb_print.h"
|
39 |
|
|
#include "cmd.h"
|
40 |
440a95fc
|
henryk
|
extern volatile int fdt_offset;
|
41 |
d3bab6e9
|
henryk
|
#include "led.h"
|
42 |
|
|
|
43 |
d2319ede
|
henryk
|
struct challenge_response {
|
44 |
|
|
u_int8_t UID[5];
|
45 |
|
|
u_int8_t nonce[4];
|
46 |
|
|
u_int8_t waiting_for_response;
|
47 |
|
|
struct {
|
48 |
|
|
u_int8_t data[8];
|
49 |
|
|
u_int8_t parity[2];
|
50 |
640d6922
|
henryk
|
size_t len;
|
51 |
d2319ede
|
henryk
|
} response;
|
52 |
|
|
};
|
53 |
|
|
|
54 |
|
|
struct challenge_response challenge_response;
|
55 |
|
|
|
56 |
d3bab6e9
|
henryk
|
static const iso14443_frame ATQA_FRAME = {
|
57 |
|
|
TYPE_A,
|
58 |
f7a420f2
|
henryk
|
FRAME_PREFILLED,
|
59 |
6304718e
|
henryk
|
{{STANDARD_FRAME, PARITY, ISO14443A_LAST_BIT_NONE, CRC_UNCALCULATED}},
|
60 |
d3bab6e9
|
henryk
|
2,
|
61 |
|
|
0, 0,
|
62 |
|
|
{4, 0},
|
63 |
|
|
{}
|
64 |
|
|
};
|
65 |
|
|
|
66 |
8ee27fd9
|
henryk
|
static const iso14443_frame ATS_FRAME = {
|
67 |
|
|
TYPE_A,
|
68 |
f7a420f2
|
henryk
|
FRAME_PREFILLED,
|
69 |
6304718e
|
henryk
|
{{STANDARD_FRAME, PARITY, ISO14443A_LAST_BIT_NONE, CRC_UNCALCULATED}},
|
70 |
8ee27fd9
|
henryk
|
3,
|
71 |
|
|
0, 0,
|
72 |
|
|
{0x08, 0xB6, 0xDD},
|
73 |
|
|
{}
|
74 |
|
|
};
|
75 |
|
|
|
76 |
714136e3
|
henryk
|
static iso14443_frame UID_FRAME, NONCE_FRAME;
|
77 |
640d6922
|
henryk
|
//static u_int8_t UID[] = {0xF4, 0xAC, 0xF9, 0xD7}; // bcc = 0x76
|
78 |
|
|
static u_int8_t UID[] = {0x00, 0x00, 0x00, 0x00};
|
79 |
714136e3
|
henryk
|
static u_int8_t nonce[] = {0x00, 0x00, 0x00, 0x00};
|
80 |
8ee27fd9
|
henryk
|
|
81 |
440a95fc
|
henryk
|
#define FRAME_SIZE(bytes) (2* (1+(9*bytes)+1) )
|
82 |
f7a420f2
|
henryk
|
#define BYTES_AND_BITS(bytes,bits) (bytes*9+bits)
|
83 |
2d8b2c30
|
henryk
|
#define GET_BASE_SIZE(type) ((size_t) &(((type*)0)->data))
|
84 |
440a95fc
|
henryk
|
|
85 |
2d8b2c30
|
henryk
|
static ssc_dma_tx_buffer_t *ATQA_BUFFER, *UID_BUFFER, *ATS_BUFFER, *NONCE_BUFFER;
|
86 |
|
|
|
87 |
|
|
static ssc_dma_tx_buffer_t *alloc_buffer_for_frame(const iso14443_frame *frame)
|
88 |
|
|
{
|
89 |
|
|
int datalen = FRAME_SIZE( BYTES_AND_BITS(frame->numbytes, frame->numbits) );
|
90 |
|
|
ssc_dma_tx_buffer_t *dst = pvPortMalloc( GET_BASE_SIZE(typeof(*dst)) + datalen );
|
91 |
|
|
if(dst == NULL) return NULL;
|
92 |
|
|
dst->len = datalen;
|
93 |
|
|
return dst;
|
94 |
|
|
}
|
95 |
d3bab6e9
|
henryk
|
|
96 |
f7a420f2
|
henryk
|
static void fast_receive_callback(ssc_dma_rx_buffer_t *buffer, iso14443_frame *frame, u_int8_t in_irq)
|
97 |
d3bab6e9
|
henryk
|
{
|
98 |
|
|
(void)buffer; (void)in_irq;
|
99 |
|
|
u_int32_t cv = *AT91C_TC2_CV;
|
100 |
|
|
|
101 |
8ee27fd9
|
henryk
|
ssc_dma_tx_buffer_t *tx_buffer=NULL;
|
102 |
d3bab6e9
|
henryk
|
int fdt = 0;
|
103 |
|
|
|
104 |
f7a420f2
|
henryk
|
switch(frame->parameters.a.last_bit) {
|
105 |
|
|
case ISO14443A_LAST_BIT_0:
|
106 |
|
|
fdt = 20;
|
107 |
|
|
break;
|
108 |
|
|
case ISO14443A_LAST_BIT_1:
|
109 |
|
|
fdt = 84;
|
110 |
|
|
break;
|
111 |
|
|
case ISO14443A_LAST_BIT_NONE:
|
112 |
|
|
fdt = 0;
|
113 |
|
|
break;
|
114 |
|
|
}
|
115 |
|
|
|
116 |
00488946
|
henryk
|
|
117 |
|
|
if(cv < 870) /* Anticollision is time-critical, do not even try to send if we're too late anyway */
|
118 |
|
|
switch(BYTES_AND_BITS(frame->numbytes,frame->numbits)) {
|
119 |
4911b074
|
henryk
|
case BYTES_AND_BITS(0, 7): /* REQA or WUPA (7 bits) */
|
120 |
|
|
if(frame->data[0] == 0x26 || frame->data[0] == 0x52)
|
121 |
2d8b2c30
|
henryk
|
tx_buffer = ATQA_BUFFER;
|
122 |
00488946
|
henryk
|
fdt += 9*128;
|
123 |
|
|
break;
|
124 |
|
|
case BYTES_AND_BITS(2, 0): /* ANTICOL (2 bytes) */
|
125 |
4911b074
|
henryk
|
if(frame->data[0] == 0x93 && frame->data[1] == 0x20)
|
126 |
2d8b2c30
|
henryk
|
tx_buffer = UID_BUFFER;
|
127 |
00488946
|
henryk
|
fdt += 9*128;
|
128 |
|
|
break;
|
129 |
|
|
case BYTES_AND_BITS(9, 0): /* SELECT (9 bytes) */
|
130 |
4911b074
|
henryk
|
if(frame->data[0] == 0x93 && frame->data[1] == 0x70 && frame->parameters.a.crc &&
|
131 |
|
|
( *((u_int32_t*)&frame->data[2]) == *((u_int32_t*)&UID) ) )
|
132 |
2d8b2c30
|
henryk
|
tx_buffer = ATS_BUFFER;
|
133 |
00488946
|
henryk
|
fdt += 9*128;
|
134 |
|
|
break;
|
135 |
|
|
}
|
136 |
|
|
|
137 |
|
|
if(tx_buffer == NULL)
|
138 |
|
|
switch(BYTES_AND_BITS(frame->numbytes, frame->numbits)) {
|
139 |
|
|
case BYTES_AND_BITS(4, 0):
|
140 |
|
|
if( (frame->data[0] & 0xfe) == 0x60 && frame->parameters.a.crc) {
|
141 |
|
|
/* AUTH1A or AUTH1B */
|
142 |
2d8b2c30
|
henryk
|
if(NONCE_BUFFER == NULL) {
|
143 |
|
|
NONCE_BUFFER = alloc_buffer_for_frame(&NONCE_FRAME);
|
144 |
|
|
}
|
145 |
|
|
if(NONCE_BUFFER != NULL) {
|
146 |
|
|
int ret = manchester_encode(NONCE_BUFFER->data, NONCE_BUFFER->len, &NONCE_FRAME);
|
147 |
|
|
if(ret < 0) {
|
148 |
|
|
} else {
|
149 |
|
|
NONCE_BUFFER->len = ret;
|
150 |
|
|
tx_buffer = NONCE_BUFFER;
|
151 |
|
|
}
|
152 |
00488946
|
henryk
|
}
|
153 |
|
|
|
154 |
|
|
/*fdt += ((cv / 128) + 10) * 128;*/
|
155 |
|
|
fdt += 50*128; /* 52 ok, 26 not, 39 not, 45 not, 48 not, 50 ok, 49 not */
|
156 |
|
|
}
|
157 |
|
|
break;
|
158 |
|
|
}
|
159 |
d3bab6e9
|
henryk
|
|
160 |
|
|
/* Add some extra room to the fdt for testing */
|
161 |
440a95fc
|
henryk
|
//fdt += 3*128;
|
162 |
|
|
fdt += fdt_offset;
|
163 |
|
|
|
164 |
8ee27fd9
|
henryk
|
if(tx_buffer != NULL) {
|
165 |
e2e37bea
|
henryk
|
tx_buffer->state = SSC_FULL;
|
166 |
8ee27fd9
|
henryk
|
if( iso14443_transmit(tx_buffer, fdt, 1, 0) < 0) {
|
167 |
|
|
usb_print_string_f("Tx failed ", 0);
|
168 |
440a95fc
|
henryk
|
}
|
169 |
d3bab6e9
|
henryk
|
}
|
170 |
|
|
|
171 |
d2319ede
|
henryk
|
#if 0
|
172 |
d3bab6e9
|
henryk
|
u_int32_t cv2 = *AT91C_TC2_CV;
|
173 |
00488946
|
henryk
|
usb_print_string_f("\r\n",0);
|
174 |
|
|
if(tx_buffer == &NONCE_BUFFER) usb_print_string_f("---> ",0);
|
175 |
d3bab6e9
|
henryk
|
int old=usb_print_set_default_flush(0);
|
176 |
|
|
DumpUIntToUSB(cv);
|
177 |
|
|
DumpStringToUSB(":");
|
178 |
|
|
DumpUIntToUSB(cv2);
|
179 |
|
|
usb_print_set_default_flush(old);
|
180 |
d2319ede
|
henryk
|
#endif
|
181 |
00488946
|
henryk
|
|
182 |
|
|
switch(BYTES_AND_BITS(frame->numbytes,frame->numbits)) {
|
183 |
|
|
case BYTES_AND_BITS(4, 0):
|
184 |
|
|
if(frame->parameters.a.crc && frame->data[0] == 0x50 && frame->data[1] == 0x00) {
|
185 |
|
|
/* HLTA */
|
186 |
|
|
UID[3]++;
|
187 |
|
|
if(UID[3]==0) {
|
188 |
|
|
UID[2]++;
|
189 |
|
|
if(UID[2]==0) {
|
190 |
|
|
UID[1]++;
|
191 |
|
|
if(UID[1]==0) {
|
192 |
|
|
UID[0]++;
|
193 |
|
|
}
|
194 |
|
|
}
|
195 |
|
|
}
|
196 |
|
|
set_UID(UID, sizeof(UID));
|
197 |
|
|
}
|
198 |
|
|
break;
|
199 |
|
|
}
|
200 |
|
|
|
201 |
d2319ede
|
henryk
|
if(tx_buffer) usb_print_string_f("\r\n",0);
|
202 |
2d8b2c30
|
henryk
|
if(tx_buffer == UID_BUFFER) {
|
203 |
d2319ede
|
henryk
|
memcpy(&challenge_response.UID, UID_FRAME.data, 5);
|
204 |
|
|
usb_print_string_f("uid", 0);
|
205 |
2d8b2c30
|
henryk
|
} else if(tx_buffer == NONCE_BUFFER) {
|
206 |
d2319ede
|
henryk
|
memcpy(&challenge_response.nonce, NONCE_FRAME.data, 4);
|
207 |
|
|
challenge_response.waiting_for_response = 1;
|
208 |
|
|
usb_print_string_f("nonce", 0);
|
209 |
|
|
} else if(challenge_response.waiting_for_response) {
|
210 |
|
|
challenge_response.waiting_for_response = 0;
|
211 |
640d6922
|
henryk
|
if(frame->numbytes != 8) {
|
212 |
|
|
usb_print_string_f("tilt ",0);
|
213 |
|
|
}
|
214 |
|
|
challenge_response.response.len = frame->numbytes + (frame->numbits+7)/8;
|
215 |
|
|
memcpy(&challenge_response.response.data, frame->data, challenge_response.response.len);
|
216 |
|
|
memcpy(&challenge_response.response.parity, frame->parity, 1);
|
217 |
|
|
|
218 |
d2319ede
|
henryk
|
int old=usb_print_set_default_flush(0);
|
219 |
|
|
DumpStringToUSB("[[");
|
220 |
|
|
DumpBufferToUSB((char*)challenge_response.UID, 5);
|
221 |
|
|
DumpStringToUSB(" ");
|
222 |
|
|
DumpBufferToUSB((char*)challenge_response.nonce, 4);
|
223 |
|
|
DumpStringToUSB(" ");
|
224 |
640d6922
|
henryk
|
DumpBufferToUSB((char*)challenge_response.response.data, challenge_response.response.len);
|
225 |
d2319ede
|
henryk
|
DumpStringToUSB("]]");
|
226 |
|
|
usb_print_set_default_flush(old);
|
227 |
|
|
}
|
228 |
|
|
//usb_print_string_f("%", 0);
|
229 |
d3bab6e9
|
henryk
|
}
|
230 |
|
|
|
231 |
714136e3
|
henryk
|
static void prepare_frame(iso14443_frame *frame, int len)
|
232 |
00488946
|
henryk
|
{
|
233 |
714136e3
|
henryk
|
memset(frame, 0, sizeof(*frame));
|
234 |
|
|
frame->type = TYPE_A;
|
235 |
|
|
frame->parameters.a.format = STANDARD_FRAME;
|
236 |
|
|
frame->parameters.a.parity = PARITY;
|
237 |
|
|
frame->parameters.a.last_bit = ISO14443A_LAST_BIT_NONE;
|
238 |
|
|
frame->parameters.a.crc = CRC_UNCALCULATED;
|
239 |
00488946
|
henryk
|
|
240 |
714136e3
|
henryk
|
frame->numbytes = len;
|
241 |
|
|
}
|
242 |
|
|
|
243 |
|
|
int set_UID(u_int8_t *uid, size_t len)
|
244 |
|
|
{
|
245 |
|
|
prepare_frame(&UID_FRAME, len+1);
|
246 |
00488946
|
henryk
|
|
247 |
|
|
u_int8_t bcc = 0;
|
248 |
|
|
unsigned int i;
|
249 |
|
|
for(i=0; i<len; i++) {
|
250 |
|
|
UID_FRAME.data[i] = uid[i];
|
251 |
|
|
bcc ^= uid[i];
|
252 |
|
|
}
|
253 |
|
|
UID_FRAME.data[i] = bcc;
|
254 |
|
|
UID_FRAME.state = FRAME_PREFILLED;
|
255 |
714136e3
|
henryk
|
memcpy(UID, uid, len);
|
256 |
00488946
|
henryk
|
|
257 |
2d8b2c30
|
henryk
|
if(UID_BUFFER == NULL) {
|
258 |
|
|
UID_BUFFER = alloc_buffer_for_frame(&UID_FRAME);
|
259 |
|
|
if(UID_BUFFER == NULL) return -ENOMEM;
|
260 |
|
|
}
|
261 |
|
|
memset(UID_BUFFER->data, 0, UID_BUFFER->len);
|
262 |
|
|
|
263 |
|
|
int ret = manchester_encode(UID_BUFFER->data, UID_BUFFER->len, &UID_FRAME);
|
264 |
00488946
|
henryk
|
if(ret < 0) return ret;
|
265 |
2d8b2c30
|
henryk
|
else UID_BUFFER->len = ret;
|
266 |
00488946
|
henryk
|
return 0;
|
267 |
|
|
}
|
268 |
|
|
|
269 |
640d6922
|
henryk
|
int get_UID(u_int8_t *uid, size_t len)
|
270 |
|
|
{
|
271 |
|
|
if(len < 4 || len > 4) return -1;
|
272 |
|
|
memcpy(uid, UID, len);
|
273 |
|
|
return 0;
|
274 |
|
|
}
|
275 |
|
|
|
276 |
714136e3
|
henryk
|
int set_nonce(u_int8_t *_nonce, size_t len)
|
277 |
|
|
{
|
278 |
|
|
prepare_frame(&NONCE_FRAME, len);
|
279 |
|
|
|
280 |
|
|
memcpy(&NONCE_FRAME.data, _nonce, len);
|
281 |
|
|
NONCE_FRAME.state = FRAME_PREFILLED;
|
282 |
|
|
memcpy(nonce, _nonce, len);
|
283 |
|
|
|
284 |
2d8b2c30
|
henryk
|
if(NONCE_BUFFER == NULL) {
|
285 |
|
|
NONCE_BUFFER = alloc_buffer_for_frame(&NONCE_FRAME);
|
286 |
|
|
if(NONCE_BUFFER == NULL) return -ENOMEM;
|
287 |
|
|
}
|
288 |
|
|
memset(NONCE_BUFFER->data, 0, NONCE_BUFFER->len);
|
289 |
|
|
|
290 |
|
|
int ret = manchester_encode(NONCE_BUFFER->data, NONCE_BUFFER->len, &NONCE_FRAME);
|
291 |
714136e3
|
henryk
|
if(ret < 0) return ret;
|
292 |
2d8b2c30
|
henryk
|
else NONCE_BUFFER->len = ret;
|
293 |
714136e3
|
henryk
|
return 0;
|
294 |
|
|
}
|
295 |
|
|
|
296 |
640d6922
|
henryk
|
int get_nonce(u_int8_t *_nonce, size_t len)
|
297 |
|
|
{
|
298 |
|
|
if(len < 4 || len > 4) return -1;
|
299 |
|
|
memcpy(_nonce, nonce, len);
|
300 |
|
|
return 0;
|
301 |
|
|
}
|
302 |
|
|
|
303 |
d3bab6e9
|
henryk
|
void iso14443a_pretender (void *pvParameters)
|
304 |
|
|
{
|
305 |
|
|
(void)pvParameters;
|
306 |
|
|
int res;
|
307 |
|
|
|
308 |
|
|
/* Delay until USB print etc. are ready */
|
309 |
|
|
int i;
|
310 |
|
|
for(i=0; i<=1000; i++) {
|
311 |
|
|
vLedSetBrightness(LED_RED, i);
|
312 |
|
|
vLedSetBrightness(LED_GREEN, i);
|
313 |
|
|
vTaskDelay(1*portTICK_RATE_MS);
|
314 |
|
|
}
|
315 |
|
|
|
316 |
|
|
for(i=0; i<=1000; i+=4) {
|
317 |
|
|
vLedSetBrightness(LED_GREEN, 1000-i);
|
318 |
|
|
vTaskDelay(1*portTICK_RATE_MS);
|
319 |
|
|
}
|
320 |
|
|
|
321 |
8ee27fd9
|
henryk
|
int ret;
|
322 |
2d8b2c30
|
henryk
|
#define PREFILL_BUFFER(dst, src) dst = alloc_buffer_for_frame(&src); \
|
323 |
|
|
if(dst == 0) goto prefill_failed; \
|
324 |
|
|
ret = manchester_encode(dst->data, dst->len, &src); \
|
325 |
|
|
if(ret < 0) goto prefill_failed; else dst->len = ret;
|
326 |
8ee27fd9
|
henryk
|
|
327 |
|
|
PREFILL_BUFFER(ATQA_BUFFER, ATQA_FRAME);
|
328 |
00488946
|
henryk
|
//PREFILL_BUFFER(UID_BUFFER, UID_FRAME);
|
329 |
8ee27fd9
|
henryk
|
PREFILL_BUFFER(ATS_BUFFER, ATS_FRAME);
|
330 |
714136e3
|
henryk
|
//PREFILL_BUFFER(NONCE_BUFFER, NONCE_FRAME);
|
331 |
8ee27fd9
|
henryk
|
|
332 |
00488946
|
henryk
|
set_UID(UID, sizeof(UID));
|
333 |
714136e3
|
henryk
|
set_nonce(nonce, sizeof(nonce));
|
334 |
00488946
|
henryk
|
|
335 |
8ee27fd9
|
henryk
|
if(0) {
|
336 |
|
|
prefill_failed:
|
337 |
440a95fc
|
henryk
|
usb_print_string("Buffer prefilling failed\n\r");
|
338 |
|
|
while(1) {
|
339 |
|
|
for(i=1000; i<=3000; i++) {
|
340 |
|
|
vLedSetBrightness(LED_GREEN, abs(1000-(i%2000)));
|
341 |
|
|
vTaskDelay(1*portTICK_RATE_MS);
|
342 |
|
|
}
|
343 |
|
|
}
|
344 |
|
|
}
|
345 |
|
|
|
346 |
d3bab6e9
|
henryk
|
do {
|
347 |
|
|
res = iso14443_layer2a_init(1);
|
348 |
|
|
if(res < 0) {
|
349 |
68e28147
|
henryk
|
usb_print_string("Pretender: Initialization failed: -");
|
350 |
|
|
DumpUIntToUSB(-res);
|
351 |
|
|
usb_print_string("\n\r");
|
352 |
d3bab6e9
|
henryk
|
for(i=0; i<=10000; i++) {
|
353 |
|
|
vLedSetBrightness(LED_RED, abs(1000-(i%2000)));
|
354 |
|
|
vTaskDelay(1*portTICK_RATE_MS);
|
355 |
|
|
}
|
356 |
|
|
}
|
357 |
|
|
} while(res < 0);
|
358 |
|
|
|
359 |
|
|
|
360 |
|
|
usb_print_string("Waiting for carrier. ");
|
361 |
|
|
while(iso14443_wait_for_carrier(1000 * portTICK_RATE_MS) != 0) {
|
362 |
|
|
}
|
363 |
|
|
usb_print_string("Carrier detected.\n\r");
|
364 |
|
|
|
365 |
|
|
for(i=0; i<=1000; i+=4) {
|
366 |
|
|
vLedSetBrightness(LED_RED, 1000-i);
|
367 |
|
|
vTaskDelay(1*portTICK_RATE_MS);
|
368 |
|
|
}
|
369 |
|
|
|
370 |
|
|
vTaskDelay(250*portTICK_RATE_MS);
|
371 |
|
|
vLedSetGreen(0);
|
372 |
|
|
vLedSetRed(0);
|
373 |
|
|
|
374 |
|
|
int current_detected = 0, last_detected = 0;
|
375 |
|
|
portTickType last_switched = 0;
|
376 |
|
|
#define DETECTED_14443A_3 1
|
377 |
|
|
#define DETECTED_14443A_4 2
|
378 |
|
|
#define DETECTED_MIFARE 4
|
379 |
|
|
|
380 |
|
|
while(true) {
|
381 |
f7a420f2
|
henryk
|
iso14443_frame *frame = 0;
|
382 |
|
|
res = iso14443_receive(fast_receive_callback, &frame, 1000 * portTICK_RATE_MS);
|
383 |
d3bab6e9
|
henryk
|
if(res >= 0) {
|
384 |
f7a420f2
|
henryk
|
switch(BYTES_AND_BITS(frame->numbytes, frame->numbits) ) {
|
385 |
|
|
case BYTES_AND_BITS(0, 7): /* REQA (7 bits) */
|
386 |
d3bab6e9
|
henryk
|
current_detected |= DETECTED_14443A_3;
|
387 |
|
|
break;
|
388 |
f7a420f2
|
henryk
|
case BYTES_AND_BITS(2, 0): /* ANTICOL (2 bytes) */
|
389 |
|
|
case BYTES_AND_BITS(9, 0): /* SELECT (9 bytes) */
|
390 |
d3bab6e9
|
henryk
|
current_detected |= DETECTED_14443A_3;
|
391 |
|
|
break;
|
392 |
f7a420f2
|
henryk
|
case BYTES_AND_BITS(4, 0): /* AUTH1A (or any other four byte frame) */
|
393 |
|
|
case BYTES_AND_BITS(8, 0): /* AUTH2 (8 bytes) */
|
394 |
d3bab6e9
|
henryk
|
current_detected |= DETECTED_MIFARE;
|
395 |
|
|
break;
|
396 |
|
|
}
|
397 |
|
|
|
398 |
|
|
portENTER_CRITICAL();
|
399 |
f7a420f2
|
henryk
|
frame->state = FRAME_FREE;
|
400 |
d3bab6e9
|
henryk
|
portEXIT_CRITICAL();
|
401 |
|
|
} else {
|
402 |
|
|
if(res != -ETIMEDOUT) {
|
403 |
|
|
usb_print_string("Receive error: ");
|
404 |
|
|
switch(res) {
|
405 |
|
|
case -ENETDOWN: usb_print_string("PLL is not locked or PLL lock lost\n\r"); break;
|
406 |
|
|
case -EBUSY: usb_print_string("A Tx is currently running or pending, can't receive\n\r"); break;
|
407 |
|
|
case -EALREADY: usb_print_string("There's already an iso14443_receive() invocation running\n\r"); break;
|
408 |
|
|
}
|
409 |
|
|
vTaskDelay(1000 * portTICK_RATE_MS); // FIXME Proper error handling, e.g. wait for Tx end in case of EBUSY
|
410 |
|
|
} else if(0) {
|
411 |
|
|
DumpStringToUSB("\n\r");
|
412 |
|
|
DumpTimeToUSB(xTaskGetTickCount());
|
413 |
|
|
usb_print_string(": -- Mark --");
|
414 |
|
|
}
|
415 |
|
|
}
|
416 |
|
|
|
417 |
|
|
if( last_switched < xTaskGetTickCount()-(1000*portTICK_RATE_MS) ) {
|
418 |
|
|
last_detected = current_detected;
|
419 |
|
|
current_detected = 0;
|
420 |
|
|
last_switched = xTaskGetTickCount();
|
421 |
|
|
}
|
422 |
440a95fc
|
henryk
|
|
423 |
|
|
#if 0
|
424 |
d3bab6e9
|
henryk
|
if(last_detected & (DETECTED_14443A_3 | DETECTED_14443A_4 | DETECTED_MIFARE)) {
|
425 |
|
|
if(last_detected & DETECTED_MIFARE) {
|
426 |
|
|
vLedSetGreen(0);
|
427 |
|
|
vLedSetRed(1);
|
428 |
|
|
} else if(last_detected & DETECTED_14443A_4) {
|
429 |
|
|
vLedSetGreen(1);
|
430 |
|
|
vLedSetRed(0);
|
431 |
|
|
} else {
|
432 |
|
|
vLedSetGreen(1);
|
433 |
|
|
vLedSetRed(1);
|
434 |
|
|
}
|
435 |
|
|
} else {
|
436 |
|
|
vLedSetGreen(0);
|
437 |
|
|
vLedSetRed(0);
|
438 |
|
|
}
|
439 |
440a95fc
|
henryk
|
#endif
|
440 |
d3bab6e9
|
henryk
|
}
|
441 |
|
|
}
|