1 |
616746c2
|
henryk
|
/***************************************************************
|
2 |
|
|
*
|
3 |
|
|
* OpenPICC - ISO 14443 Layer 3 Type A state machine
|
4 |
fa61e60d
|
henryk
|
* Handles initialization and anticollision
|
5 |
616746c2
|
henryk
|
*
|
6 |
|
|
* Copyright 2007 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 |
|
|
|
29 |
|
|
#include "openpicc.h"
|
30 |
|
|
#include "iso14443_layer3a.h"
|
31 |
|
|
#include "ssc_picc.h"
|
32 |
|
|
#include "pll.h"
|
33 |
|
|
#include "tc_fdt.h"
|
34 |
|
|
#include "tc_cdiv.h"
|
35 |
|
|
#include "tc_cdiv_sync.h"
|
36 |
|
|
#include "usb_print.h"
|
37 |
|
|
#include "cmd.h"
|
38 |
16d42d5f
|
henryk
|
#include "load_modulation.h"
|
39 |
|
|
#include "decoder.h"
|
40 |
|
|
#include "iso14443a_manchester.h"
|
41 |
202b56a4
|
henryk
|
#include "iso14443a_miller.h"
|
42 |
16d42d5f
|
henryk
|
#include "led.h"
|
43 |
616746c2
|
henryk
|
|
44 |
|
|
static enum ISO14443_STATES state = STARTING_UP;
|
45 |
16d42d5f
|
henryk
|
const iso14443_frame ATQA_FRAME = {
|
46 |
|
|
TYPE_A,
|
47 |
40bf6fbf
|
henryk
|
{{STANDARD_FRAME, PARITY, ISO14443A_LAST_BIT_NONE}},
|
48 |
202b56a4
|
henryk
|
2,
|
49 |
16d42d5f
|
henryk
|
0, 0,
|
50 |
|
|
{4, 0},
|
51 |
|
|
{}
|
52 |
|
|
};
|
53 |
|
|
|
54 |
6549d886
|
henryk
|
const iso14443_frame NULL_FRAME = {
|
55 |
|
|
TYPE_A,
|
56 |
40bf6fbf
|
henryk
|
{{STANDARD_FRAME, PARITY, ISO14443A_LAST_BIT_NONE}},
|
57 |
6549d886
|
henryk
|
4,
|
58 |
|
|
0, 0,
|
59 |
bdc39aad
|
henryk
|
//{0xF3, 0xFB, 0xAE, 0xED},
|
60 |
|
|
{0xFF, 0xFF, 0xFF, 0xFF},
|
61 |
|
|
//{0, 0, 0, 0},
|
62 |
6549d886
|
henryk
|
{}
|
63 |
|
|
};
|
64 |
|
|
|
65 |
f8981148
|
henryk
|
const u_int8_t ISO14443A_SHORT_FRAME_REQA[ISO14443A_SHORT_FRAME_COMPARE_LENGTH] = _ISO14443A_SHORT_FRAME_REQA;
|
66 |
|
|
const u_int8_t ISO14443A_SHORT_FRAME_WUPA[ISO14443A_SHORT_FRAME_COMPARE_LENGTH] = _ISO14443A_SHORT_FRAME_WUPA;
|
67 |
16d42d5f
|
henryk
|
|
68 |
616746c2
|
henryk
|
#define PLL_LOCK_HYSTERESIS portTICK_RATE_MS*5
|
69 |
|
|
|
70 |
|
|
#define LAYER3_DEBUG usb_print_string
|
71 |
|
|
|
72 |
ca286b29
|
henryk
|
#define INITIAL_STATE IDLE
|
73 |
|
|
//#define INITIAL_STATE ACTIVE
|
74 |
6549d886
|
henryk
|
|
75 |
bdc39aad
|
henryk
|
#if INITIAL_STATE == IDLE
|
76 |
|
|
#define INITIAL_FRAME ATQA_FRAME
|
77 |
|
|
#else
|
78 |
|
|
#define INITIAL_FRAME NULL_FRAME
|
79 |
|
|
#endif
|
80 |
|
|
|
81 |
6be69f0d
|
henryk
|
#if 1
|
82 |
91d960e6
|
henryk
|
#define SHORT_MODE SSC_MODE_14443A_SHORT
|
83 |
|
|
#define STANDARD_MODE SSC_MODE_14443A_STANDARD
|
84 |
|
|
#else
|
85 |
|
|
#define SHORT_MODE SSC_MODE_14443A
|
86 |
|
|
#define STANDARD_MODE SSC_MODE_14443A
|
87 |
|
|
#endif
|
88 |
|
|
|
89 |
d88d1207
|
henryk
|
#define ISO14443A_TRANSMIT_AT_NEXT_INTERVAL_0 -1
|
90 |
|
|
#define ISO14443A_TRANSMIT_AT_NEXT_INTERVAL_1 -2
|
91 |
|
|
|
92 |
|
|
/* Transmit a frame in ISO14443A mode from buffer buf at fdt carrier cycles
|
93 |
|
|
* after the end of the last modulation pause from the PCD with a clock divisor
|
94 |
|
|
* of div. Set fdt to ISO14443A_TRANSMIT_AT_NEXT_INTERVAL_0 or _1 to have the
|
95 |
|
|
* transmission start at the next possible interval. Use _0 when the last bit
|
96 |
|
|
* from the PCD was a 0 and _1 when it was a 1. */
|
97 |
|
|
void iso14443_transmit(ssc_dma_tx_buffer_t *buf, int fdt, int div)
|
98 |
|
|
{
|
99 |
|
|
tc_cdiv_set_divider(div);
|
100 |
202b56a4
|
henryk
|
if(fdt == ISO14443A_TRANSMIT_AT_NEXT_INTERVAL_0) {
|
101 |
|
|
fdt = tc_fdt_get_next_slot(ISO14443A_FDT_SHORT_0, ISO14443A_FDT_SLOTLEN);
|
102 |
|
|
} else if (fdt == ISO14443A_TRANSMIT_AT_NEXT_INTERVAL_1) {
|
103 |
|
|
fdt = tc_fdt_get_next_slot(ISO14443A_FDT_SHORT_1, ISO14443A_FDT_SLOTLEN);
|
104 |
|
|
}
|
105 |
fa61e60d
|
henryk
|
if(0) {
|
106 |
|
|
ssc_tx_fiq_fdt_cdiv = fdt -3*div -1;
|
107 |
|
|
tc_fdt_set(ssc_tx_fiq_fdt_cdiv -MAX_TF_FIQ_ENTRY_DELAY -MAX_TF_FIQ_OVERHEAD);
|
108 |
|
|
ssc_tx_fiq_fdt_ssc = fdt -div +1;
|
109 |
|
|
*AT91C_TC0_CCR = AT91C_TC_CLKDIS;
|
110 |
|
|
} else {
|
111 |
|
|
tc_fdt_set(fdt);
|
112 |
|
|
}
|
113 |
d88d1207
|
henryk
|
ssc_tx_start(buf);
|
114 |
|
|
}
|
115 |
|
|
|
116 |
f8981148
|
henryk
|
static void _is_reqa_or_wupa(enum ssc_mode ssc_mode, u_int8_t* samples, int *is_reqa, int *is_wupa)
|
117 |
|
|
{
|
118 |
|
|
if(ssc_mode == SSC_MODE_14443A_SHORT) {
|
119 |
|
|
*is_reqa = *is_wupa = 0;
|
120 |
|
|
ISO14443A_SHORT_TYPE sample = *(ISO14443A_SHORT_TYPE*)samples;
|
121 |
|
|
if(sample == REQA) {
|
122 |
|
|
*is_reqa = 1;
|
123 |
|
|
} else if(sample == WUPA) {
|
124 |
|
|
*is_wupa = 1;
|
125 |
|
|
}
|
126 |
|
|
} else if(ssc_mode == SSC_MODE_14443A) {
|
127 |
|
|
int i;
|
128 |
|
|
*is_reqa = *is_wupa = 1;
|
129 |
|
|
for(i=0; i<ISO14443A_SHORT_FRAME_COMPARE_LENGTH; i++) {
|
130 |
|
|
if(samples[i] != ISO14443A_SHORT_FRAME_REQA[i]) is_reqa = 0;
|
131 |
|
|
if(samples[i] != ISO14443A_SHORT_FRAME_WUPA[i]) is_wupa = 0;
|
132 |
|
|
}
|
133 |
|
|
} else {
|
134 |
|
|
*is_reqa = *is_wupa = 0;
|
135 |
|
|
}
|
136 |
|
|
}
|
137 |
|
|
|
138 |
ba63352b
|
henryk
|
static int atqa_sent = 0;
|
139 |
6549d886
|
henryk
|
/* Running in ISR mode */
|
140 |
|
|
void __ramfunc iso14443_layer3a_irq_ext(u_int32_t ssc_sr, enum ssc_mode ssc_mode, u_int8_t* samples)
|
141 |
|
|
{
|
142 |
|
|
(void)ssc_sr;
|
143 |
d88d1207
|
henryk
|
int fdt;
|
144 |
91d960e6
|
henryk
|
if((ssc_mode == SSC_MODE_14443A_SHORT || ssc_mode == SSC_MODE_14443A) && samples) {
|
145 |
f8981148
|
henryk
|
int is_reqa, is_wupa;
|
146 |
|
|
_is_reqa_or_wupa(ssc_mode, samples, &is_reqa, &is_wupa);
|
147 |
|
|
portBASE_TYPE send_atqa = is_reqa || is_wupa;
|
148 |
|
|
|
149 |
|
|
if(is_reqa) {
|
150 |
d88d1207
|
henryk
|
fdt = ISO14443A_FDT_SHORT_0;
|
151 |
6549d886
|
henryk
|
if(state == IDLE)
|
152 |
|
|
send_atqa = 1;
|
153 |
f8981148
|
henryk
|
} else if(is_wupa) {
|
154 |
d88d1207
|
henryk
|
fdt = ISO14443A_FDT_SHORT_1;
|
155 |
6549d886
|
henryk
|
if(state == IDLE || state == HALT)
|
156 |
|
|
send_atqa = 1;
|
157 |
|
|
}
|
158 |
|
|
|
159 |
|
|
if(send_atqa) {
|
160 |
|
|
vLedSetGreen(0);
|
161 |
e2e37bea
|
henryk
|
if(ssc_tx_buffer.state == SSC_PREFILLED && ssc_tx_buffer.source == &ATQA_FRAME) {
|
162 |
|
|
ssc_tx_buffer.state = SSC_PROCESSING;
|
163 |
5b7a3102
|
henryk
|
vLedSetGreen(1);
|
164 |
d88d1207
|
henryk
|
iso14443_transmit(&ssc_tx_buffer, fdt, 8);
|
165 |
ba63352b
|
henryk
|
atqa_sent = 1;
|
166 |
5b7a3102
|
henryk
|
vLedSetGreen(0);
|
167 |
6549d886
|
henryk
|
}
|
168 |
|
|
vLedSetGreen(1);
|
169 |
|
|
}
|
170 |
d88d1207
|
henryk
|
vLedSetGreen(0);
|
171 |
6549d886
|
henryk
|
}
|
172 |
|
|
}
|
173 |
|
|
|
174 |
5b7a3102
|
henryk
|
#define FALSE (0!=0)
|
175 |
|
|
static int prefill_buffer(ssc_dma_tx_buffer_t *dest, const iso14443_frame *src) {
|
176 |
|
|
portENTER_CRITICAL();
|
177 |
e2e37bea
|
henryk
|
if(dest->state == SSC_FREE) {
|
178 |
|
|
dest->state = SSC_PROCESSING;
|
179 |
5b7a3102
|
henryk
|
portEXIT_CRITICAL();
|
180 |
|
|
dest->source = (void*)src;
|
181 |
|
|
dest->len = sizeof(ssc_tx_buffer.data);
|
182 |
|
|
int ret = manchester_encode(dest->data,
|
183 |
|
|
dest->len,
|
184 |
67d9be99
|
henryk
|
src);
|
185 |
5b7a3102
|
henryk
|
if(ret>0) {
|
186 |
|
|
dest->len = ret;
|
187 |
|
|
portENTER_CRITICAL();
|
188 |
e2e37bea
|
henryk
|
dest->state = SSC_PREFILLED;
|
189 |
5b7a3102
|
henryk
|
portEXIT_CRITICAL();
|
190 |
|
|
} else {
|
191 |
|
|
portENTER_CRITICAL();
|
192 |
e2e37bea
|
henryk
|
dest->state = SSC_FREE;
|
193 |
5b7a3102
|
henryk
|
portEXIT_CRITICAL();
|
194 |
|
|
}
|
195 |
|
|
return ret > 0;
|
196 |
e2e37bea
|
henryk
|
} else if(dest->state == SSC_PREFILLED) {
|
197 |
5b7a3102
|
henryk
|
portEXIT_CRITICAL();
|
198 |
|
|
return dest->source == src;
|
199 |
|
|
} else {
|
200 |
|
|
portEXIT_CRITICAL();
|
201 |
|
|
return FALSE;
|
202 |
|
|
}
|
203 |
|
|
|
204 |
|
|
}
|
205 |
|
|
|
206 |
202b56a4
|
henryk
|
static iso14443_frame received_frame;
|
207 |
bdc39aad
|
henryk
|
|
208 |
|
|
static void enable_reception(enum ssc_mode mode) {
|
209 |
d88d1207
|
henryk
|
tc_fdt_set(0xff00);
|
210 |
bdc39aad
|
henryk
|
ssc_rx_mode_set(mode);
|
211 |
|
|
#ifdef FOUR_TIMES_OVERSAMPLING
|
212 |
|
|
tc_cdiv_set_divider(32);
|
213 |
|
|
#else
|
214 |
|
|
tc_cdiv_set_divider(64);
|
215 |
|
|
#endif
|
216 |
|
|
ssc_rx_start();
|
217 |
|
|
}
|
218 |
|
|
|
219 |
16d42d5f
|
henryk
|
extern void main_help_print_buffer(ssc_dma_rx_buffer_t *buffer, int *pktcount);
|
220 |
616746c2
|
henryk
|
void iso14443_layer3a_state_machine (void *pvParameters)
|
221 |
|
|
{
|
222 |
cee440c5
|
henryk
|
unsigned long int last_pll_lock_change = 0;
|
223 |
|
|
int pktcount=0, locked, last_was_locked=0;
|
224 |
616746c2
|
henryk
|
(void)pvParameters;
|
225 |
|
|
while(1) {
|
226 |
16d42d5f
|
henryk
|
ssc_dma_rx_buffer_t* buffer = NULL;
|
227 |
616746c2
|
henryk
|
portBASE_TYPE need_receive = 0, switch_on = 0;
|
228 |
|
|
|
229 |
8c1bae59
|
henryk
|
if(ssc_get_metric(SSC_ERRORS) > 0 && state != ERROR) {
|
230 |
6549d886
|
henryk
|
LAYER3_DEBUG("SSC overflow error, please debug\n\r");
|
231 |
|
|
state = ERROR;
|
232 |
|
|
}
|
233 |
|
|
|
234 |
616746c2
|
henryk
|
/* First let's see whether there is a reader */
|
235 |
cee440c5
|
henryk
|
locked = pll_is_locked();
|
236 |
|
|
unsigned long int now = xTaskGetTickCount();
|
237 |
616746c2
|
henryk
|
switch(state) {
|
238 |
|
|
case STARTING_UP: /* Fall through */
|
239 |
|
|
case ERROR:
|
240 |
|
|
// do nothing here
|
241 |
|
|
break;
|
242 |
|
|
case POWERED_OFF:
|
243 |
cee440c5
|
henryk
|
if(locked && now - last_pll_lock_change > PLL_LOCK_HYSTERESIS) {
|
244 |
|
|
/* Go to idle when in POWERED_OFF and pll
|
245 |
|
|
* was locked for at least
|
246 |
|
|
* PLL_LOCK_HYSTERESIS ticks */
|
247 |
|
|
switch_on = 1;
|
248 |
|
|
LAYER3_DEBUG("PLL locked, switching on \n\r");
|
249 |
|
|
}
|
250 |
616746c2
|
henryk
|
break;
|
251 |
|
|
default:
|
252 |
cee440c5
|
henryk
|
if(!locked && now - last_pll_lock_change > PLL_LOCK_HYSTERESIS) {
|
253 |
|
|
/* Power off when not powered off and pll
|
254 |
|
|
* was unlocked for at least PLL_LOCK_HYSTERESIS
|
255 |
|
|
* ticks */
|
256 |
|
|
state = POWERED_OFF;
|
257 |
|
|
ssc_rx_stop();
|
258 |
|
|
LAYER3_DEBUG("PLL lost lock, switching off \n\r");
|
259 |
|
|
continue;
|
260 |
|
|
}
|
261 |
616746c2
|
henryk
|
break;
|
262 |
|
|
}
|
263 |
cee440c5
|
henryk
|
if( (!locked && last_was_locked) || (locked && !last_was_locked) )
|
264 |
|
|
last_pll_lock_change = now;
|
265 |
|
|
last_was_locked = locked;
|
266 |
616746c2
|
henryk
|
|
267 |
|
|
switch(state) {
|
268 |
|
|
case STARTING_UP:
|
269 |
|
|
pll_init();
|
270 |
|
|
|
271 |
|
|
tc_cdiv_init();
|
272 |
|
|
tc_fdt_init();
|
273 |
6549d886
|
henryk
|
ssc_set_irq_extension((ssc_irq_ext_t)iso14443_layer3a_irq_ext);
|
274 |
616746c2
|
henryk
|
ssc_rx_init();
|
275 |
5b7a3102
|
henryk
|
ssc_tx_init();
|
276 |
616746c2
|
henryk
|
|
277 |
16d42d5f
|
henryk
|
load_mod_init();
|
278 |
|
|
load_mod_level(3);
|
279 |
|
|
|
280 |
|
|
|
281 |
616746c2
|
henryk
|
state = POWERED_OFF;
|
282 |
cee440c5
|
henryk
|
last_was_locked = 0;
|
283 |
|
|
vTaskDelay(200*portTICK_RATE_MS);
|
284 |
616746c2
|
henryk
|
break;
|
285 |
|
|
case POWERED_OFF:
|
286 |
|
|
if(switch_on == 1) {
|
287 |
bdc39aad
|
henryk
|
if(prefill_buffer(&ssc_tx_buffer, &INITIAL_FRAME)) {
|
288 |
67d9be99
|
henryk
|
LAYER3_DEBUG("Buffer prefilled\n\r");
|
289 |
|
|
DumpUIntToUSB(ssc_tx_buffer.state);
|
290 |
|
|
DumpStringToUSB(" ");
|
291 |
|
|
DumpUIntToUSB((unsigned int)ssc_tx_buffer.source);
|
292 |
|
|
DumpStringToUSB(" ");
|
293 |
bdc39aad
|
henryk
|
DumpUIntToUSB((unsigned int)&INITIAL_FRAME);
|
294 |
ace50086
|
henryk
|
DumpStringToUSB(" ");
|
295 |
|
|
DumpUIntToUSB(ssc_tx_buffer.len);
|
296 |
|
|
DumpStringToUSB(" ");
|
297 |
|
|
DumpBufferToUSB((char*)ssc_tx_buffer.data, ssc_tx_buffer.len);
|
298 |
67d9be99
|
henryk
|
DumpStringToUSB("\n\r");
|
299 |
5b7a3102
|
henryk
|
state=INITIAL_STATE;
|
300 |
|
|
if(INITIAL_STATE == IDLE)
|
301 |
91d960e6
|
henryk
|
enable_reception(SHORT_MODE);
|
302 |
5b7a3102
|
henryk
|
else if(INITIAL_STATE == ACTIVE)
|
303 |
91d960e6
|
henryk
|
enable_reception(STANDARD_MODE);
|
304 |
bdc39aad
|
henryk
|
else enable_reception(SSC_MODE_NONE);
|
305 |
5b7a3102
|
henryk
|
} else {
|
306 |
|
|
LAYER3_DEBUG("SSC TX overflow error, please debug");
|
307 |
|
|
state=ERROR;
|
308 |
|
|
}
|
309 |
616746c2
|
henryk
|
continue;
|
310 |
|
|
}
|
311 |
|
|
break;
|
312 |
|
|
case IDLE:
|
313 |
|
|
case HALT:
|
314 |
|
|
/* Wait for REQA or WUPA (HALT: only WUPA) */
|
315 |
|
|
need_receive = 1;
|
316 |
6549d886
|
henryk
|
case ACTIVE:
|
317 |
|
|
case ACTIVE_STAR:
|
318 |
|
|
need_receive = 1;
|
319 |
616746c2
|
henryk
|
default:
|
320 |
|
|
break;
|
321 |
|
|
}
|
322 |
|
|
|
323 |
|
|
if(need_receive) {
|
324 |
ba63352b
|
henryk
|
if(xQueueReceive(ssc_rx_queue, &buffer, portTICK_RATE_MS) && buffer != NULL) {
|
325 |
16d42d5f
|
henryk
|
vLedSetGreen(0);
|
326 |
dc757222
|
henryk
|
vLedBlinkGreen();
|
327 |
616746c2
|
henryk
|
portENTER_CRITICAL();
|
328 |
e2e37bea
|
henryk
|
buffer->state = SSC_PROCESSING;
|
329 |
616746c2
|
henryk
|
portEXIT_CRITICAL();
|
330 |
29ea5bbf
|
henryk
|
u_int32_t first_sample = *(u_int32_t*)buffer->data;
|
331 |
616746c2
|
henryk
|
|
332 |
bdc39aad
|
henryk
|
if(0) {
|
333 |
|
|
DumpStringToUSB("Frame: ");
|
334 |
|
|
DumpUIntToUSB(first_sample);
|
335 |
|
|
DumpStringToUSB(" ");
|
336 |
|
|
main_help_print_buffer(buffer, &pktcount);
|
337 |
|
|
}
|
338 |
|
|
vLedBlinkGreen();
|
339 |
bcc75d30
|
henryk
|
if(1) {
|
340 |
|
|
int i = usb_print_set_default_flush(0);
|
341 |
0df8e1e2
|
henryk
|
DumpStringToUSB("[");
|
342 |
|
|
DumpUIntToUSB((unsigned int)buffer);
|
343 |
|
|
DumpStringToUSB(":");
|
344 |
7c198cbf
|
henryk
|
DumpUIntToUSB(buffer->len_transfers);
|
345 |
bcc75d30
|
henryk
|
DumpStringToUSB(" ");
|
346 |
0df8e1e2
|
henryk
|
DumpUIntToUSB((unsigned int)buffer->data);
|
347 |
|
|
DumpStringToUSB("] ");
|
348 |
|
|
DumpBufferToUSB((char*)buffer->data, (buffer->len_transfers * buffer->reception_mode->transfersize_pdc)/8);
|
349 |
|
|
DumpStringToUSB(" Decoded: ");
|
350 |
f8981148
|
henryk
|
vLedBlinkGreen();
|
351 |
|
|
vLedSetGreen(1);
|
352 |
7c198cbf
|
henryk
|
iso14443a_decode_miller(&received_frame, buffer);
|
353 |
f8981148
|
henryk
|
vLedBlinkGreen();
|
354 |
|
|
vLedSetGreen(0);
|
355 |
bcc75d30
|
henryk
|
DumpBufferToUSB((char*)received_frame.data, received_frame.numbytes + (received_frame.numbits+7)/8);
|
356 |
40bf6fbf
|
henryk
|
DumpStringToUSB(" ");
|
357 |
|
|
DumpUIntToUSB(received_frame.parameters.a.last_bit);
|
358 |
bcc75d30
|
henryk
|
DumpStringToUSB("\n\r");
|
359 |
|
|
usb_print_set_default_flush(i);
|
360 |
|
|
}
|
361 |
ba894ea0
|
henryk
|
|
362 |
f8981148
|
henryk
|
int is_reqa=0, is_wupa=0;
|
363 |
616746c2
|
henryk
|
switch(state) {
|
364 |
|
|
case IDLE:
|
365 |
|
|
case HALT:
|
366 |
f8981148
|
henryk
|
if(buffer->data) _is_reqa_or_wupa(buffer->reception_mode->mode, buffer->data, &is_reqa, &is_wupa);
|
367 |
|
|
|
368 |
|
|
if(is_wupa || (state==IDLE && is_reqa)) {
|
369 |
29ea5bbf
|
henryk
|
/* Need to transmit ATQA */
|
370 |
|
|
LAYER3_DEBUG("Received ");
|
371 |
f8981148
|
henryk
|
LAYER3_DEBUG(is_wupa ? "WUPA" : "REQA");
|
372 |
ba63352b
|
henryk
|
if(atqa_sent) {
|
373 |
|
|
LAYER3_DEBUG(", woke up to send ATQA\n\r");
|
374 |
|
|
atqa_sent = 0;
|
375 |
6549d886
|
henryk
|
}
|
376 |
bdc39aad
|
henryk
|
/* For debugging, wait 1ms, then wait for another frame
|
377 |
|
|
* Normally we'd go to anticol from here*/
|
378 |
ba63352b
|
henryk
|
vTaskDelay(portTICK_RATE_MS);
|
379 |
|
|
if(prefill_buffer(&ssc_tx_buffer, &ATQA_FRAME)) {
|
380 |
91d960e6
|
henryk
|
enable_reception(SHORT_MODE);
|
381 |
ba63352b
|
henryk
|
}
|
382 |
29ea5bbf
|
henryk
|
} else {
|
383 |
|
|
/* Wait for another frame */
|
384 |
91d960e6
|
henryk
|
enable_reception(SHORT_MODE);
|
385 |
29ea5bbf
|
henryk
|
}
|
386 |
616746c2
|
henryk
|
break;
|
387 |
6549d886
|
henryk
|
case ACTIVE:
|
388 |
|
|
case ACTIVE_STAR:
|
389 |
|
|
/* Wait for another frame */
|
390 |
bdc39aad
|
henryk
|
if(0) {
|
391 |
91d960e6
|
henryk
|
ssc_rx_mode_set(STANDARD_MODE);
|
392 |
bdc39aad
|
henryk
|
ssc_rx_start();
|
393 |
|
|
} else {
|
394 |
|
|
//vTaskDelay(portTICK_RATE_MS);
|
395 |
e2e37bea
|
henryk
|
if(ssc_tx_buffer.source == &ATQA_FRAME) ssc_tx_buffer.state = SSC_FREE;
|
396 |
bdc39aad
|
henryk
|
if(prefill_buffer(&ssc_tx_buffer, &NULL_FRAME)) {
|
397 |
|
|
usb_print_string_f("Sending response ...",0);
|
398 |
e2e37bea
|
henryk
|
ssc_tx_buffer.state = SSC_PROCESSING;
|
399 |
f8981148
|
henryk
|
iso14443_transmit(&ssc_tx_buffer,
|
400 |
|
|
received_frame.parameters.a.last_bit==ISO14443A_LAST_BIT_0 ?
|
401 |
|
|
ISO14443A_TRANSMIT_AT_NEXT_INTERVAL_0 :
|
402 |
|
|
ISO14443A_TRANSMIT_AT_NEXT_INTERVAL_1,
|
403 |
|
|
8);
|
404 |
e2e37bea
|
henryk
|
while( ssc_tx_buffer.state != SSC_FREE ) {
|
405 |
bdc39aad
|
henryk
|
vTaskDelay(portTICK_RATE_MS);
|
406 |
|
|
}
|
407 |
|
|
usb_print_string("done\n\r");
|
408 |
|
|
usb_print_flush();
|
409 |
|
|
}
|
410 |
|
|
/* Wait for another frame */
|
411 |
91d960e6
|
henryk
|
enable_reception(STANDARD_MODE);
|
412 |
bdc39aad
|
henryk
|
}
|
413 |
616746c2
|
henryk
|
default:
|
414 |
|
|
break;
|
415 |
|
|
}
|
416 |
|
|
|
417 |
|
|
portENTER_CRITICAL();
|
418 |
e2e37bea
|
henryk
|
buffer->state = SSC_FREE;
|
419 |
616746c2
|
henryk
|
portEXIT_CRITICAL();
|
420 |
|
|
}
|
421 |
|
|
} else vTaskDelay(portTICK_RATE_MS);
|
422 |
|
|
}
|
423 |
|
|
}
|