]> cvs.zerfleddert.de Git - proxmark3-svn/blame - armsrc/iso14443.c
Updated logic in lo_read.v so it's much tidier now, better timing.
[proxmark3-svn] / armsrc / iso14443.c
CommitLineData
6658905f 1//-----------------------------------------------------------------------------\r
2// Routines to support ISO 14443. This includes both the reader software and\r
3// the `fake tag' modes. At the moment only the Type B modulation is\r
4// supported.\r
5// Jonathan Westhues, split Nov 2006\r
6//-----------------------------------------------------------------------------\r
7#include <proxmark3.h>\r
8#include "apps.h"\r
30f2a7d3 9#include "../common/iso14443_crc.c"\r
6658905f 10\r
11\r
12//static void GetSamplesFor14443(BOOL weTx, int n);\r
13\r
14#define DMA_BUFFER_SIZE 256\r
15\r
16//=============================================================================\r
17// An ISO 14443 Type B tag. We listen for commands from the reader, using\r
18// a UART kind of thing that's implemented in software. When we get a\r
19// frame (i.e., a group of bytes between SOF and EOF), we check the CRC.\r
20// If it's good, then we can do something appropriate with it, and send\r
21// a response.\r
22//=============================================================================\r
23\r
24//-----------------------------------------------------------------------------\r
25// Code up a string of octets at layer 2 (including CRC, we don't generate\r
26// that here) so that they can be transmitted to the reader. Doesn't transmit\r
27// them yet, just leaves them ready to send in ToSend[].\r
28//-----------------------------------------------------------------------------\r
29static void CodeIso14443bAsTag(const BYTE *cmd, int len)\r
30{\r
31 int i;\r
32\r
33 ToSendReset();\r
34\r
35 // Transmit a burst of ones, as the initial thing that lets the\r
36 // reader get phase sync. This (TR1) must be > 80/fs, per spec,\r
37 // but tag that I've tried (a Paypass) exceeds that by a fair bit,\r
38 // so I will too.\r
39 for(i = 0; i < 20; i++) {\r
40 ToSendStuffBit(1);\r
41 ToSendStuffBit(1);\r
42 ToSendStuffBit(1);\r
43 ToSendStuffBit(1);\r
44 }\r
45\r
46 // Send SOF.\r
47 for(i = 0; i < 10; i++) {\r
48 ToSendStuffBit(0);\r
49 ToSendStuffBit(0);\r
50 ToSendStuffBit(0);\r
51 ToSendStuffBit(0);\r
52 }\r
53 for(i = 0; i < 2; i++) {\r
54 ToSendStuffBit(1);\r
55 ToSendStuffBit(1);\r
56 ToSendStuffBit(1);\r
57 ToSendStuffBit(1);\r
58 }\r
59\r
60 for(i = 0; i < len; i++) {\r
61 int j;\r
62 BYTE b = cmd[i];\r
63\r
64 // Start bit\r
65 ToSendStuffBit(0);\r
66 ToSendStuffBit(0);\r
67 ToSendStuffBit(0);\r
68 ToSendStuffBit(0);\r
69\r
70 // Data bits\r
71 for(j = 0; j < 8; j++) {\r
72 if(b & 1) {\r
73 ToSendStuffBit(1);\r
74 ToSendStuffBit(1);\r
75 ToSendStuffBit(1);\r
76 ToSendStuffBit(1);\r
77 } else {\r
78 ToSendStuffBit(0);\r
79 ToSendStuffBit(0);\r
80 ToSendStuffBit(0);\r
81 ToSendStuffBit(0);\r
82 }\r
83 b >>= 1;\r
84 }\r
85\r
86 // Stop bit\r
87 ToSendStuffBit(1);\r
88 ToSendStuffBit(1);\r
89 ToSendStuffBit(1);\r
90 ToSendStuffBit(1);\r
91 }\r
92\r
93 // Send SOF.\r
94 for(i = 0; i < 10; i++) {\r
95 ToSendStuffBit(0);\r
96 ToSendStuffBit(0);\r
97 ToSendStuffBit(0);\r
98 ToSendStuffBit(0);\r
99 }\r
100 for(i = 0; i < 10; i++) {\r
101 ToSendStuffBit(1);\r
102 ToSendStuffBit(1);\r
103 ToSendStuffBit(1);\r
104 ToSendStuffBit(1);\r
105 }\r
106\r
107 // Convert from last byte pos to length\r
108 ToSendMax++;\r
109\r
110 // Add a few more for slop\r
111 ToSendMax += 2;\r
112}\r
113\r
114//-----------------------------------------------------------------------------\r
115// The software UART that receives commands from the reader, and its state\r
116// variables.\r
117//-----------------------------------------------------------------------------\r
118static struct {\r
119 enum {\r
120 STATE_UNSYNCD,\r
121 STATE_GOT_FALLING_EDGE_OF_SOF,\r
122 STATE_AWAITING_START_BIT,\r
123 STATE_RECEIVING_DATA,\r
124 STATE_ERROR_WAIT\r
125 } state;\r
126 WORD shiftReg;\r
127 int bitCnt;\r
128 int byteCnt;\r
129 int byteCntMax;\r
130 int posCnt;\r
131 BYTE *output;\r
132} Uart;\r
133\r
134static BOOL Handle14443UartBit(int bit)\r
135{\r
136 switch(Uart.state) {\r
137 case STATE_UNSYNCD:\r
138 if(!bit) {\r
139 // we went low, so this could be the beginning\r
140 // of an SOF\r
141 Uart.state = STATE_GOT_FALLING_EDGE_OF_SOF;\r
142 Uart.posCnt = 0;\r
143 Uart.bitCnt = 0;\r
144 }\r
145 break;\r
146\r
147 case STATE_GOT_FALLING_EDGE_OF_SOF:\r
148 Uart.posCnt++;\r
149 if(Uart.posCnt == 2) {\r
150 if(bit) {\r
151 if(Uart.bitCnt >= 10) {\r
152 // we've seen enough consecutive\r
153 // zeros that it's a valid SOF\r
154 Uart.posCnt = 0;\r
155 Uart.byteCnt = 0;\r
156 Uart.state = STATE_AWAITING_START_BIT;\r
157 } else {\r
158 // didn't stay down long enough\r
159 // before going high, error\r
160 Uart.state = STATE_ERROR_WAIT;\r
161 }\r
162 } else {\r
163 // do nothing, keep waiting\r
164 }\r
165 Uart.bitCnt++;\r
166 }\r
167 if(Uart.posCnt >= 4) Uart.posCnt = 0;\r
168 if(Uart.bitCnt > 14) {\r
169 // Give up if we see too many zeros without\r
170 // a one, too.\r
171 Uart.state = STATE_ERROR_WAIT;\r
172 }\r
173 break;\r
174\r
175 case STATE_AWAITING_START_BIT:\r
176 Uart.posCnt++;\r
177 if(bit) {\r
178 if(Uart.posCnt > 25) {\r
179 // stayed high for too long between\r
180 // characters, error\r
181 Uart.state = STATE_ERROR_WAIT;\r
182 }\r
183 } else {\r
184 // falling edge, this starts the data byte\r
185 Uart.posCnt = 0;\r
186 Uart.bitCnt = 0;\r
187 Uart.shiftReg = 0;\r
188 Uart.state = STATE_RECEIVING_DATA;\r
189 }\r
190 break;\r
191\r
192 case STATE_RECEIVING_DATA:\r
193 Uart.posCnt++;\r
194 if(Uart.posCnt == 2) {\r
195 // time to sample a bit\r
196 Uart.shiftReg >>= 1;\r
197 if(bit) {\r
198 Uart.shiftReg |= 0x200;\r
199 }\r
200 Uart.bitCnt++;\r
201 }\r
202 if(Uart.posCnt >= 4) {\r
203 Uart.posCnt = 0;\r
204 }\r
205 if(Uart.bitCnt == 10) {\r
206 if((Uart.shiftReg & 0x200) && !(Uart.shiftReg & 0x001))\r
207 {\r
208 // this is a data byte, with correct\r
209 // start and stop bits\r
210 Uart.output[Uart.byteCnt] = (Uart.shiftReg >> 1) & 0xff;\r
211 Uart.byteCnt++;\r
212\r
213 if(Uart.byteCnt >= Uart.byteCntMax) {\r
214 // Buffer overflowed, give up\r
215 Uart.posCnt = 0;\r
216 Uart.state = STATE_ERROR_WAIT;\r
217 } else {\r
218 // so get the next byte now\r
219 Uart.posCnt = 0;\r
220 Uart.state = STATE_AWAITING_START_BIT;\r
221 }\r
222 } else if(Uart.shiftReg == 0x000) {\r
223 // this is an EOF byte\r
224 return TRUE;\r
225 } else {\r
226 // this is an error\r
227 Uart.posCnt = 0;\r
228 Uart.state = STATE_ERROR_WAIT;\r
229 }\r
230 }\r
231 break;\r
232\r
233 case STATE_ERROR_WAIT:\r
234 // We're all screwed up, so wait a little while\r
235 // for whatever went wrong to finish, and then\r
236 // start over.\r
237 Uart.posCnt++;\r
238 if(Uart.posCnt > 10) {\r
239 Uart.state = STATE_UNSYNCD;\r
240 }\r
241 break;\r
242\r
243 default:\r
244 Uart.state = STATE_UNSYNCD;\r
245 break;\r
246 }\r
247\r
248 return FALSE;\r
249}\r
250\r
251//-----------------------------------------------------------------------------\r
252// Receive a command (from the reader to us, where we are the simulated tag),\r
253// and store it in the given buffer, up to the given maximum length. Keeps\r
254// spinning, waiting for a well-framed command, until either we get one\r
255// (returns TRUE) or someone presses the pushbutton on the board (FALSE).\r
256//\r
257// Assume that we're called with the SSC (to the FPGA) and ADC path set\r
258// correctly.\r
259//-----------------------------------------------------------------------------\r
260static BOOL GetIso14443CommandFromReader(BYTE *received, int *len, int maxLen)\r
261{\r
262 BYTE mask;\r
263 int i, bit;\r
264\r
265 // Set FPGA mode to "simulated ISO 14443 tag", no modulation (listen\r
266 // only, since we are receiving, not transmitting).\r
267 FpgaWriteConfWord(\r
268 FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_NO_MODULATION);\r
269\r
270\r
271 // Now run a `software UART' on the stream of incoming samples.\r
272 Uart.output = received;\r
273 Uart.byteCntMax = maxLen;\r
274 Uart.state = STATE_UNSYNCD;\r
275\r
276 for(;;) {\r
277 WDT_HIT();\r
278\r
279 if(BUTTON_PRESS()) return FALSE;\r
280\r
281 if(SSC_STATUS & (SSC_STATUS_TX_READY)) {\r
282 SSC_TRANSMIT_HOLDING = 0x00;\r
283 }\r
284 if(SSC_STATUS & (SSC_STATUS_RX_READY)) {\r
285 BYTE b = (BYTE)SSC_RECEIVE_HOLDING;\r
286\r
287 mask = 0x80;\r
288 for(i = 0; i < 8; i++, mask >>= 1) {\r
289 bit = (b & mask);\r
290 if(Handle14443UartBit(bit)) {\r
291 *len = Uart.byteCnt;\r
292 return TRUE;\r
293 }\r
294 }\r
295 }\r
296 }\r
297}\r
298\r
299//-----------------------------------------------------------------------------\r
300// Main loop of simulated tag: receive commands from reader, decide what\r
301// response to send, and send it.\r
302//-----------------------------------------------------------------------------\r
303void SimulateIso14443Tag(void)\r
304{\r
305 static const BYTE cmd1[] = { 0x05, 0x00, 0x08, 0x39, 0x73 };\r
306 static const BYTE response1[] = {\r
307 0x50, 0x82, 0x0d, 0xe1, 0x74, 0x20, 0x38, 0x19, 0x22,\r
308 0x00, 0x21, 0x85, 0x5e, 0xd7\r
309 };\r
310\r
311 BYTE *resp;\r
312 int respLen;\r
313\r
314 BYTE *resp1 = (((BYTE *)BigBuf) + 800);\r
315 int resp1Len;\r
316\r
317 BYTE *receivedCmd = (BYTE *)BigBuf;\r
318 int len;\r
319\r
320 int i;\r
321\r
322 int cmdsRecvd = 0;\r
323\r
324 memset(receivedCmd, 0x44, 400);\r
325\r
326 CodeIso14443bAsTag(response1, sizeof(response1));\r
327 memcpy(resp1, ToSend, ToSendMax); resp1Len = ToSendMax;\r
328\r
329 // We need to listen to the high-frequency, peak-detected path.\r
330 SetAdcMuxFor(GPIO_MUXSEL_HIPKD);\r
331 FpgaSetupSsc();\r
332\r
333 cmdsRecvd = 0;\r
334\r
335 for(;;) {\r
336 BYTE b1, b2;\r
337\r
338 if(!GetIso14443CommandFromReader(receivedCmd, &len, 100)) {\r
339 DbpIntegers(cmdsRecvd, 0, 0);\r
340 DbpString("button press");\r
341 break;\r
342 }\r
343\r
344 // Good, look at the command now.\r
345\r
346 if(len == sizeof(cmd1) && memcmp(receivedCmd, cmd1, len)==0) {\r
347 resp = resp1; respLen = resp1Len;\r
348 } else {\r
349 DbpString("new cmd from reader:");\r
350 DbpIntegers(len, 0x1234, cmdsRecvd);\r
351 // And print whether the CRC fails, just for good measure\r
352 ComputeCrc14443(CRC_14443_B, receivedCmd, len-2, &b1, &b2);\r
353 if(b1 != receivedCmd[len-2] || b2 != receivedCmd[len-1]) {\r
354 // Not so good, try again.\r
355 DbpString("+++CRC fail");\r
356 } else {\r
357 DbpString("CRC passes");\r
358 }\r
359 break;\r
360 }\r
361\r
362 memset(receivedCmd, 0x44, 32);\r
363\r
364 cmdsRecvd++;\r
365\r
366 if(cmdsRecvd > 0x30) {\r
367 DbpString("many commands later...");\r
368 break;\r
369 }\r
370\r
371 if(respLen <= 0) continue;\r
372\r
373 // Modulate BPSK\r
374 FpgaWriteConfWord(\r
375 FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_MODULATE_BPSK);\r
376 SSC_TRANSMIT_HOLDING = 0xff;\r
377 FpgaSetupSsc();\r
378\r
379 // Transmit the response.\r
380 i = 0;\r
381 for(;;) {\r
382 if(SSC_STATUS & (SSC_STATUS_TX_READY)) {\r
383 BYTE b = resp[i];\r
384\r
385 SSC_TRANSMIT_HOLDING = b;\r
386\r
387 i++;\r
388 if(i > respLen) {\r
389 break;\r
390 }\r
391 }\r
392 if(SSC_STATUS & (SSC_STATUS_RX_READY)) {\r
393 volatile BYTE b = (BYTE)SSC_RECEIVE_HOLDING;\r
394 (void)b;\r
395 }\r
396 }\r
397 }\r
398}\r
399\r
400//=============================================================================\r
401// An ISO 14443 Type B reader. We take layer two commands, code them\r
402// appropriately, and then send them to the tag. We then listen for the\r
403// tag's response, which we leave in the buffer to be demodulated on the\r
404// PC side.\r
405//=============================================================================\r
406\r
407static struct {\r
408 enum {\r
409 DEMOD_UNSYNCD,\r
410 DEMOD_PHASE_REF_TRAINING,\r
411 DEMOD_AWAITING_FALLING_EDGE_OF_SOF,\r
412 DEMOD_GOT_FALLING_EDGE_OF_SOF,\r
413 DEMOD_AWAITING_START_BIT,\r
414 DEMOD_RECEIVING_DATA,\r
415 DEMOD_ERROR_WAIT\r
416 } state;\r
417 int bitCount;\r
418 int posCount;\r
419 int thisBit;\r
420 int metric;\r
421 int metricN;\r
422 WORD shiftReg;\r
423 BYTE *output;\r
424 int len;\r
425 int sumI;\r
426 int sumQ;\r
427} Demod;\r
428\r
429static BOOL Handle14443SamplesDemod(int ci, int cq)\r
430{\r
431 int v;\r
432\r
433 // The soft decision on the bit uses an estimate of just the\r
434 // quadrant of the reference angle, not the exact angle.\r
435#define MAKE_SOFT_DECISION() { \\r
436 if(Demod.sumI > 0) { \\r
437 v = ci; \\r
438 } else { \\r
439 v = -ci; \\r
440 } \\r
441 if(Demod.sumQ > 0) { \\r
442 v += cq; \\r
443 } else { \\r
444 v -= cq; \\r
445 } \\r
446 }\r
447\r
448 switch(Demod.state) {\r
449 case DEMOD_UNSYNCD:\r
450 v = ci;\r
451 if(v < 0) v = -v;\r
452 if(cq > 0) {\r
453 v += cq;\r
454 } else {\r
455 v -= cq;\r
456 }\r
457 if(v > 40) {\r
458 Demod.posCount = 0;\r
459 Demod.state = DEMOD_PHASE_REF_TRAINING;\r
460 Demod.sumI = 0;\r
461 Demod.sumQ = 0;\r
462 }\r
463 break;\r
464\r
465 case DEMOD_PHASE_REF_TRAINING:\r
466 if(Demod.posCount < 8) {\r
467 Demod.sumI += ci;\r
468 Demod.sumQ += cq;\r
469 } else if(Demod.posCount > 100) {\r
470 // error, waited too long\r
471 Demod.state = DEMOD_UNSYNCD;\r
472 } else {\r
473 MAKE_SOFT_DECISION();\r
474 if(v < 0) {\r
475 Demod.state = DEMOD_AWAITING_FALLING_EDGE_OF_SOF;\r
476 Demod.posCount = 0;\r
477 }\r
478 }\r
479 Demod.posCount++;\r
480 break;\r
481\r
482 case DEMOD_AWAITING_FALLING_EDGE_OF_SOF:\r
483 MAKE_SOFT_DECISION();\r
484 if(v < 0) {\r
485 Demod.state = DEMOD_GOT_FALLING_EDGE_OF_SOF;\r
486 Demod.posCount = 0;\r
487 } else {\r
488 if(Demod.posCount > 100) {\r
489 Demod.state = DEMOD_UNSYNCD;\r
490 }\r
491 }\r
492 Demod.posCount++;\r
493 break;\r
494\r
495 case DEMOD_GOT_FALLING_EDGE_OF_SOF:\r
496 MAKE_SOFT_DECISION();\r
497 if(v > 0) {\r
498 if(Demod.posCount < 12) {\r
499 Demod.state = DEMOD_UNSYNCD;\r
500 } else {\r
501 Demod.state = DEMOD_AWAITING_START_BIT;\r
502 Demod.posCount = 0;\r
503 Demod.len = 0;\r
504 Demod.metricN = 0;\r
505 Demod.metric = 0;\r
506 }\r
507 } else {\r
508 if(Demod.posCount > 100) {\r
509 Demod.state = DEMOD_UNSYNCD;\r
510 }\r
511 }\r
512 Demod.posCount++;\r
513 break;\r
514\r
515 case DEMOD_AWAITING_START_BIT:\r
516 MAKE_SOFT_DECISION();\r
517 if(v > 0) {\r
518 if(Demod.posCount > 10) {\r
519 Demod.state = DEMOD_UNSYNCD;\r
520 }\r
521 } else {\r
522 Demod.bitCount = 0;\r
523 Demod.posCount = 1;\r
524 Demod.thisBit = v;\r
525 Demod.shiftReg = 0;\r
526 Demod.state = DEMOD_RECEIVING_DATA;\r
527 }\r
528 break;\r
529\r
530 case DEMOD_RECEIVING_DATA:\r
531 MAKE_SOFT_DECISION();\r
532 if(Demod.posCount == 0) {\r
533 Demod.thisBit = v;\r
534 Demod.posCount = 1;\r
535 } else {\r
536 Demod.thisBit += v;\r
537\r
538 if(Demod.thisBit > 0) {\r
539 Demod.metric += Demod.thisBit;\r
540 } else {\r
541 Demod.metric -= Demod.thisBit;\r
542 }\r
543 (Demod.metricN)++;\r
544\r
545 Demod.shiftReg >>= 1;\r
546 if(Demod.thisBit > 0) {\r
547 Demod.shiftReg |= 0x200;\r
548 }\r
549\r
550 Demod.bitCount++;\r
551 if(Demod.bitCount == 10) {\r
552 WORD s = Demod.shiftReg;\r
553 if((s & 0x200) && !(s & 0x001)) {\r
554 BYTE b = (s >> 1);\r
555 Demod.output[Demod.len] = b;\r
556 Demod.len++;\r
557 Demod.state = DEMOD_AWAITING_START_BIT;\r
558 } else if(s == 0x000) {\r
559 // This is EOF\r
560 return TRUE;\r
561 Demod.state = DEMOD_UNSYNCD;\r
562 } else {\r
563 Demod.state = DEMOD_UNSYNCD;\r
564 }\r
565 }\r
566 Demod.posCount = 0;\r
567 }\r
568 break;\r
569\r
570 default:\r
571 Demod.state = DEMOD_UNSYNCD;\r
572 break;\r
573 }\r
574\r
575 return FALSE;\r
576}\r
577\r
fb25b483 578static void GetSamplesFor14443Demod(BOOL weTx, int n, BOOL quiet)\r
6658905f 579{\r
580 int max = 0;\r
581 BOOL gotFrame = FALSE;\r
582\r
583//# define DMA_BUFFER_SIZE 8\r
584 SBYTE *dmaBuf;\r
585\r
586 int lastRxCounter;\r
587 SBYTE *upTo;\r
588\r
589 int ci, cq;\r
590\r
591 int samples = 0;\r
592\r
593 // Clear out the state of the "UART" that receives from the tag.\r
594 memset(BigBuf, 0x44, 400);\r
595 Demod.output = (BYTE *)BigBuf;\r
596 Demod.len = 0;\r
597 Demod.state = DEMOD_UNSYNCD;\r
598\r
599 // And the UART that receives from the reader\r
600 Uart.output = (((BYTE *)BigBuf) + 1024);\r
601 Uart.byteCntMax = 100;\r
602 Uart.state = STATE_UNSYNCD;\r
603\r
604 // Setup for the DMA.\r
605 dmaBuf = (SBYTE *)(BigBuf + 32);\r
606 upTo = dmaBuf;\r
607 lastRxCounter = DMA_BUFFER_SIZE;\r
608 FpgaSetupSscDma((BYTE *)dmaBuf, DMA_BUFFER_SIZE);\r
609\r
610 // And put the FPGA in the appropriate mode\r
611 FpgaWriteConfWord(\r
612 FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ |\r
613 (weTx ? 0 : FPGA_HF_READER_RX_XCORR_SNOOP));\r
614\r
615 for(;;) {\r
616 int behindBy = lastRxCounter - PDC_RX_COUNTER(SSC_BASE);\r
617 if(behindBy > max) max = behindBy;\r
618\r
619 LED_D_ON();\r
620 while(((lastRxCounter-PDC_RX_COUNTER(SSC_BASE)) & (DMA_BUFFER_SIZE-1))\r
621 > 2)\r
622 {\r
623 ci = upTo[0];\r
624 cq = upTo[1];\r
625 upTo += 2;\r
626 if(upTo - dmaBuf > DMA_BUFFER_SIZE) {\r
627 upTo -= DMA_BUFFER_SIZE;\r
628 PDC_RX_NEXT_POINTER(SSC_BASE) = (DWORD)upTo;\r
629 PDC_RX_NEXT_COUNTER(SSC_BASE) = DMA_BUFFER_SIZE;\r
630 }\r
631 lastRxCounter -= 2;\r
632 if(lastRxCounter <= 0) {\r
633 lastRxCounter += DMA_BUFFER_SIZE;\r
634 }\r
635\r
636 samples += 2;\r
637\r
638 Handle14443UartBit(1);\r
639 Handle14443UartBit(1);\r
640\r
641 if(Handle14443SamplesDemod(ci, cq)) {\r
642 gotFrame = 1;\r
643 }\r
644 }\r
645 LED_D_OFF();\r
646\r
647 if(samples > 2000) {\r
648 break;\r
649 }\r
650 }\r
651 PDC_CONTROL(SSC_BASE) = PDC_RX_DISABLE;\r
fb25b483 652 if (!quiet) DbpIntegers(max, gotFrame, Demod.len);\r
6658905f 653}\r
654\r
655//-----------------------------------------------------------------------------\r
656// Read the tag's response. We just receive a stream of slightly-processed\r
657// samples from the FPGA, which we will later do some signal processing on,\r
658// to get the bits.\r
659//-----------------------------------------------------------------------------\r
660/*static void GetSamplesFor14443(BOOL weTx, int n)\r
661{\r
662 BYTE *dest = (BYTE *)BigBuf;\r
663 int c;\r
664\r
665 FpgaWriteConfWord(\r
666 FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ |\r
667 (weTx ? 0 : FPGA_HF_READER_RX_XCORR_SNOOP));\r
668\r
669 c = 0;\r
670 for(;;) {\r
671 if(SSC_STATUS & (SSC_STATUS_TX_READY)) {\r
672 SSC_TRANSMIT_HOLDING = 0x43;\r
673 }\r
674 if(SSC_STATUS & (SSC_STATUS_RX_READY)) {\r
675 SBYTE b;\r
676 b = (SBYTE)SSC_RECEIVE_HOLDING;\r
677\r
678 dest[c++] = (BYTE)b;\r
679\r
680 if(c >= n) {\r
681 break;\r
682 }\r
683 }\r
684 }\r
685}*/\r
686\r
687//-----------------------------------------------------------------------------\r
688// Transmit the command (to the tag) that was placed in ToSend[].\r
689//-----------------------------------------------------------------------------\r
690static void TransmitFor14443(void)\r
691{\r
692 int c;\r
693\r
694 FpgaSetupSsc();\r
695\r
696 while(SSC_STATUS & (SSC_STATUS_TX_READY)) {\r
697 SSC_TRANSMIT_HOLDING = 0xff;\r
698 }\r
699\r
700 FpgaWriteConfWord(\r
701 FPGA_MAJOR_MODE_HF_READER_TX | FPGA_HF_READER_TX_SHALLOW_MOD);\r
702\r
703 for(c = 0; c < 10;) {\r
704 if(SSC_STATUS & (SSC_STATUS_TX_READY)) {\r
705 SSC_TRANSMIT_HOLDING = 0xff;\r
706 c++;\r
707 }\r
708 if(SSC_STATUS & (SSC_STATUS_RX_READY)) {\r
709 volatile DWORD r = SSC_RECEIVE_HOLDING;\r
710 (void)r;\r
711 }\r
712 WDT_HIT();\r
713 }\r
714\r
715 c = 0;\r
716 for(;;) {\r
717 if(SSC_STATUS & (SSC_STATUS_TX_READY)) {\r
718 SSC_TRANSMIT_HOLDING = ToSend[c];\r
719 c++;\r
720 if(c >= ToSendMax) {\r
721 break;\r
722 }\r
723 }\r
724 if(SSC_STATUS & (SSC_STATUS_RX_READY)) {\r
725 volatile DWORD r = SSC_RECEIVE_HOLDING;\r
726 (void)r;\r
727 }\r
728 WDT_HIT();\r
729 }\r
730}\r
731\r
732//-----------------------------------------------------------------------------\r
733// Code a layer 2 command (string of octets, including CRC) into ToSend[],\r
734// so that it is ready to transmit to the tag using TransmitFor14443().\r
735//-----------------------------------------------------------------------------\r
736void CodeIso14443bAsReader(const BYTE *cmd, int len)\r
737{\r
738 int i, j;\r
739 BYTE b;\r
740\r
741 ToSendReset();\r
742\r
743 // Establish initial reference level\r
744 for(i = 0; i < 40; i++) {\r
745 ToSendStuffBit(1);\r
746 }\r
747 // Send SOF\r
748 for(i = 0; i < 10; i++) {\r
749 ToSendStuffBit(0);\r
750 }\r
751\r
752 for(i = 0; i < len; i++) {\r
753 // Stop bits/EGT\r
754 ToSendStuffBit(1);\r
755 ToSendStuffBit(1);\r
756 // Start bit\r
757 ToSendStuffBit(0);\r
758 // Data bits\r
759 b = cmd[i];\r
760 for(j = 0; j < 8; j++) {\r
761 if(b & 1) {\r
762 ToSendStuffBit(1);\r
763 } else {\r
764 ToSendStuffBit(0);\r
765 }\r
766 b >>= 1;\r
767 }\r
768 }\r
769 // Send EOF\r
770 ToSendStuffBit(1);\r
771 for(i = 0; i < 10; i++) {\r
772 ToSendStuffBit(0);\r
773 }\r
774 for(i = 0; i < 8; i++) {\r
775 ToSendStuffBit(1);\r
776 }\r
777\r
778 // And then a little more, to make sure that the last character makes\r
779 // it out before we switch to rx mode.\r
780 for(i = 0; i < 24; i++) {\r
781 ToSendStuffBit(1);\r
782 }\r
783\r
784 // Convert from last character reference to length\r
785 ToSendMax++;\r
786}\r
787\r
788//-----------------------------------------------------------------------------\r
789// Read an ISO 14443 tag. We send it some set of commands, and record the\r
fb25b483 790// responses.
791// The command name is misleading, it actually decodes the reponse in HEX
792// into the output buffer (read the result using hexsamples, not hisamples)\r
6658905f 793//-----------------------------------------------------------------------------\r
794void AcquireRawAdcSamplesIso14443(DWORD parameter)\r
795{\r
6658905f 796 BYTE cmd1[] = { 0x05, 0x00, 0x08, 0x39, 0x73 };\r
797\r
798 // Make sure that we start from off, since the tags are stateful;\r
799 // confusing things will happen if we don't reset them between reads.\r
800 LED_D_OFF();\r
801 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
802 SpinDelay(200);\r
803\r
804 SetAdcMuxFor(GPIO_MUXSEL_HIPKD);\r
805 FpgaSetupSsc();\r
806\r
807 // Now give it time to spin up.\r
808 FpgaWriteConfWord(\r
809 FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ);\r
810 SpinDelay(200);\r
811\r
812 CodeIso14443bAsReader(cmd1, sizeof(cmd1));\r
813 TransmitFor14443();\r
814 LED_A_ON();\r
fb25b483 815 GetSamplesFor14443Demod(TRUE, 2000, FALSE);\r
6658905f 816 LED_A_OFF();\r
817}\r
fb25b483 818
819//-----------------------------------------------------------------------------\r
820// Read a SRI512 ISO 14443 tag.\r
821//
822// SRI512 tags are just simple memory tags, here we're looking at making a dump
823// of the contents of the memory. No anticollision algorithm is done, we assume
824// we have a single tag in the field.
825//
826// I tried to be systematic and check every answer of the tag, every CRC, etc...\r
827//-----------------------------------------------------------------------------\r
828void ReadSRI512Iso14443(DWORD parameter)\r
829{\r
830 BYTE i = 0x00;
831\r
832 // Make sure that we start from off, since the tags are stateful;\r
833 // confusing things will happen if we don't reset them between reads.\r
834 LED_D_OFF();\r
835 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
836 SpinDelay(200);\r
837\r
838 SetAdcMuxFor(GPIO_MUXSEL_HIPKD);\r
839 FpgaSetupSsc();\r
840\r
841 // Now give it time to spin up.\r
842 FpgaWriteConfWord(\r
843 FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ);\r
844 SpinDelay(200);\r
845
846 // First command: wake up the tag using the INITIATE command\r
847 BYTE cmd1[] = { 0x06, 0x00, 0x97, 0x5b};\r
848 CodeIso14443bAsReader(cmd1, sizeof(cmd1));\r
849 TransmitFor14443();\r
850 LED_A_ON();\r
851 GetSamplesFor14443Demod(TRUE, 2000,TRUE);\r
852 LED_A_OFF();\r
853
854 if (Demod.len == 0) {
855 DbpString("No response from tag");
856 return;
857 } else {
858 DbpString("Randomly generated UID from tag (+ 2 byte CRC):");
859 DbpIntegers(Demod.output[0], Demod.output[1],Demod.output[2]);
860 }
861 // There is a response, SELECT the uid
862 DbpString("Now SELECT tag:");
863 cmd1[0] = 0x0E; // 0x0E is SELECT
864 cmd1[1] = Demod.output[0];
865 ComputeCrc14443(CRC_14443_B, cmd1, 2, &cmd1[2], &cmd1[3]);\r
866 CodeIso14443bAsReader(cmd1, sizeof(cmd1));\r
867 TransmitFor14443();\r
868 LED_A_ON();\r
869 GetSamplesFor14443Demod(TRUE, 2000,TRUE);\r
870 LED_A_OFF();\r
871 if (Demod.len != 3) {
872 DbpString("Expected 3 bytes from tag, got:");
873 DbpIntegers(Demod.len,0x0,0x0);
874 return;
875 }
876 // Check the CRC of the answer:
877 ComputeCrc14443(CRC_14443_B, Demod.output, 1 , &cmd1[2], &cmd1[3]);\r
878 if(cmd1[2] != Demod.output[1] || cmd1[3] != Demod.output[2]) {\r
879 DbpString("CRC Error reading select response.");
880 return;
881 }
882 // Check response from the tag: should be the same UID as the command we just sent:
883 if (cmd1[1] != Demod.output[0]) {
884 DbpString("Bad response to SELECT from Tag, aborting:");
885 DbpIntegers(cmd1[1],Demod.output[0],0x0);
886 return;
887 }
888 // Tag is now selected,
1a093c19 889 // First get the tag's UID:
890 cmd1[0] = 0x0B;
891 ComputeCrc14443(CRC_14443_B, cmd1, 1 , &cmd1[1], &cmd1[2]);
892 CodeIso14443bAsReader(cmd1, 3); // Only first three bytes for this one\r
893 TransmitFor14443();\r
894 LED_A_ON();\r
895 GetSamplesFor14443Demod(TRUE, 2000,TRUE);\r
896 LED_A_OFF();\r
897 if (Demod.len != 10) {
898 DbpString("Expected 10 bytes from tag, got:");
899 DbpIntegers(Demod.len,0x0,0x0);
900 return;
901 }
902 // The check the CRC of the answer (use cmd1 as temporary variable):
903 ComputeCrc14443(CRC_14443_B, Demod.output, 8, &cmd1[2], &cmd1[3]);\r
904 if(cmd1[2] != Demod.output[8] || cmd1[3] != Demod.output[9]) {\r
905 DbpString("CRC Error reading block! - Below: expected, got");
906 DbpIntegers( (cmd1[2]<<8)+cmd1[3], (Demod.output[8]<<8)+Demod.output[9],0);
907 // Do not return;, let's go on... (we should retry, maybe ?)
908 }
909 DbpString("Tag UID (64 bits):");
910 DbpIntegers((Demod.output[7]<<24) + (Demod.output[6]<<16) + (Demod.output[5]<<8) + Demod.output[4], (Demod.output[3]<<24) + (Demod.output[2]<<16) + (Demod.output[1]<<8) + Demod.output[0], 0);
911
912 // Now loop to read all 16 blocks, address from 0 to 15
fb25b483 913 DbpString("Tag memory dump, block 0 to 15");
914 cmd1[0] = 0x08;
915 i = 0x00;
916 for (;;) {
917 if (i == 0x10) {
918 DbpString("System area block (0xff):");
919 i = 0xff;
920 }
921 cmd1[1] = i;
922 ComputeCrc14443(CRC_14443_B, cmd1, 2, &cmd1[2], &cmd1[3]);\r
923 CodeIso14443bAsReader(cmd1, sizeof(cmd1));\r
924 TransmitFor14443();\r
925 LED_A_ON();\r
926 GetSamplesFor14443Demod(TRUE, 2000,TRUE);\r
927 LED_A_OFF();
928 if (Demod.len != 6) { // Check if we got an answer from the tag
929 DbpString("Expected 6 bytes from tag, got less...");
930 return;
931 }
932 // The check the CRC of the answer (use cmd1 as temporary variable):
933 ComputeCrc14443(CRC_14443_B, Demod.output, 4, &cmd1[2], &cmd1[3]);\r
934 if(cmd1[2] != Demod.output[4] || cmd1[3] != Demod.output[5]) {\r
1a093c19 935 DbpString("CRC Error reading block! - Below: expected, got");
fb25b483 936 DbpIntegers( (cmd1[2]<<8)+cmd1[3], (Demod.output[4]<<8)+Demod.output[5],0);
937 // Do not return;, let's go on... (we should retry, maybe ?)
938 }
939 // Now print out the memory location:
940 DbpString("Address , Contents, CRC");
1a093c19 941 DbpIntegers(i, (Demod.output[3]<<24) + (Demod.output[2]<<16) + (Demod.output[1]<<8) + Demod.output[0], (Demod.output[4]<<8)+Demod.output[5]);
fb25b483 942 if (i == 0xff) {
943 break;
944 }
945 i++;
946 }
947}\r
948
6658905f 949\r
950//=============================================================================\r
951// Finally, the `sniffer' combines elements from both the reader and\r
952// simulated tag, to show both sides of the conversation.\r
953//=============================================================================\r
954\r
955//-----------------------------------------------------------------------------\r
956// Record the sequence of commands sent by the reader to the tag, with\r
957// triggering so that we start recording at the point that the tag is moved\r
958// near the reader.\r
959//-----------------------------------------------------------------------------\r
960void SnoopIso14443(void)\r
961{\r
962 // We won't start recording the frames that we acquire until we trigger;\r
963 // a good trigger condition to get started is probably when we see a\r
964 // response from the tag.\r
965 BOOL triggered = FALSE;\r
966\r
967 // The command (reader -> tag) that we're working on receiving.\r
968 BYTE *receivedCmd = (((BYTE *)BigBuf) + 1024);\r
969 // The response (tag -> reader) that we're working on receiving.\r
970 BYTE *receivedResponse = (((BYTE *)BigBuf) + 1536);\r
971\r
972 // As we receive stuff, we copy it from receivedCmd or receivedResponse\r
973 // into trace, along with its length and other annotations.\r
974 BYTE *trace = (BYTE *)BigBuf;\r
975 int traceLen = 0;\r
976\r
977 // The DMA buffer, used to stream samples from the FPGA.\r
978//# define DMA_BUFFER_SIZE 256\r
979 SBYTE *dmaBuf = ((SBYTE *)BigBuf) + 2048;\r
980 int lastRxCounter;\r
981 SBYTE *upTo;\r
982 int ci, cq;\r
983 int maxBehindBy = 0;\r
984\r
985 // Count of samples received so far, so that we can include timing\r
986 // information in the trace buffer.\r
987 int samples = 0;\r
988\r
989 memset(trace, 0x44, 1000);\r
990\r
991 // Set up the demodulator for tag -> reader responses.\r
992 Demod.output = receivedResponse;\r
993 Demod.len = 0;\r
994 Demod.state = DEMOD_UNSYNCD;\r
995\r
996 // And the reader -> tag commands\r
997 memset(&Uart, 0, sizeof(Uart));\r
998 Uart.output = receivedCmd;\r
999 Uart.byteCntMax = 100;\r
1000 Uart.state = STATE_UNSYNCD;\r
1001\r
1002 // And put the FPGA in the appropriate mode\r
1003 FpgaWriteConfWord(\r
1004 FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ |\r
1005 FPGA_HF_READER_RX_XCORR_SNOOP);\r
1006 SetAdcMuxFor(GPIO_MUXSEL_HIPKD);\r
1007\r
1008 // Setup for the DMA.\r
1009 FpgaSetupSsc();\r
1010 upTo = dmaBuf;\r
1011 lastRxCounter = DMA_BUFFER_SIZE;\r
1012 FpgaSetupSscDma((BYTE *)dmaBuf, DMA_BUFFER_SIZE);\r
1013\r
1014 LED_A_ON();\r
1015\r
1016 // And now we loop, receiving samples.\r
1017 for(;;) {\r
1018 int behindBy = (lastRxCounter - PDC_RX_COUNTER(SSC_BASE)) &\r
1019 (DMA_BUFFER_SIZE-1);\r
1020 if(behindBy > maxBehindBy) {\r
1021 maxBehindBy = behindBy;\r
1022 if(behindBy > 100) {\r
1023 DbpString("blew circular buffer!");\r
1024 goto done;\r
1025 }\r
1026 }\r
1027 if(behindBy < 2) continue;\r
1028\r
1029 ci = upTo[0];\r
1030 cq = upTo[1];\r
1031 upTo += 2;\r
1032 lastRxCounter -= 2;\r
1033 if(upTo - dmaBuf > DMA_BUFFER_SIZE) {\r
1034 upTo -= DMA_BUFFER_SIZE;\r
1035 lastRxCounter += DMA_BUFFER_SIZE;\r
1036 PDC_RX_NEXT_POINTER(SSC_BASE) = (DWORD)upTo;\r
1037 PDC_RX_NEXT_COUNTER(SSC_BASE) = DMA_BUFFER_SIZE;\r
1038 }\r
1039\r
1040 samples += 2;\r
1041\r
1042#define HANDLE_BIT_IF_BODY \\r
1043 if(triggered) { \\r
1044 trace[traceLen++] = ((samples >> 0) & 0xff); \\r
1045 trace[traceLen++] = ((samples >> 8) & 0xff); \\r
1046 trace[traceLen++] = ((samples >> 16) & 0xff); \\r
1047 trace[traceLen++] = ((samples >> 24) & 0xff); \\r
1048 trace[traceLen++] = 0; \\r
1049 trace[traceLen++] = 0; \\r
1050 trace[traceLen++] = 0; \\r
1051 trace[traceLen++] = 0; \\r
1052 trace[traceLen++] = Uart.byteCnt; \\r
1053 memcpy(trace+traceLen, receivedCmd, Uart.byteCnt); \\r
1054 traceLen += Uart.byteCnt; \\r
1055 if(traceLen > 1000) break; \\r
1056 } \\r
1057 /* And ready to receive another command. */ \\r
1058 memset(&Uart, 0, sizeof(Uart)); \\r
1059 Uart.output = receivedCmd; \\r
1060 Uart.byteCntMax = 100; \\r
1061 Uart.state = STATE_UNSYNCD; \\r
1062 /* And also reset the demod code, which might have been */ \\r
1063 /* false-triggered by the commands from the reader. */ \\r
1064 memset(&Demod, 0, sizeof(Demod)); \\r
1065 Demod.output = receivedResponse; \\r
1066 Demod.state = DEMOD_UNSYNCD; \\r
1067\r
1068 if(Handle14443UartBit(ci & 1)) {\r
1069 HANDLE_BIT_IF_BODY\r
1070 }\r
1071 if(Handle14443UartBit(cq & 1)) {\r
1072 HANDLE_BIT_IF_BODY\r
1073 }\r
1074\r
1075 if(Handle14443SamplesDemod(ci, cq)) {\r
1076 // timestamp, as a count of samples\r
1077 trace[traceLen++] = ((samples >> 0) & 0xff);\r
1078 trace[traceLen++] = ((samples >> 8) & 0xff);\r
1079 trace[traceLen++] = ((samples >> 16) & 0xff);\r
1080 trace[traceLen++] = 0x80 | ((samples >> 24) & 0xff);\r
1081 // correlation metric (~signal strength estimate)\r
1082 if(Demod.metricN != 0) {\r
1083 Demod.metric /= Demod.metricN;\r
1084 }\r
1085 trace[traceLen++] = ((Demod.metric >> 0) & 0xff);\r
1086 trace[traceLen++] = ((Demod.metric >> 8) & 0xff);\r
1087 trace[traceLen++] = ((Demod.metric >> 16) & 0xff);\r
1088 trace[traceLen++] = ((Demod.metric >> 24) & 0xff);\r
1089 // length\r
1090 trace[traceLen++] = Demod.len;\r
1091 memcpy(trace+traceLen, receivedResponse, Demod.len);\r
1092 traceLen += Demod.len;\r
1093 if(traceLen > 1000) break;\r
1094\r
1095 triggered = TRUE;\r
1096 LED_A_OFF();\r
1097 LED_B_ON();\r
1098\r
1099 // And ready to receive another response.\r
1100 memset(&Demod, 0, sizeof(Demod));\r
1101 Demod.output = receivedResponse;\r
1102 Demod.state = DEMOD_UNSYNCD;\r
1103 }\r
1104\r
1105 if(BUTTON_PRESS()) {\r
1106 DbpString("cancelled");\r
1107 goto done;\r
1108 }\r
1109 }\r
1110\r
1111 DbpString("in done pt");\r
1112\r
1113 DbpIntegers(maxBehindBy, Uart.state, Uart.byteCnt);\r
1114 DbpIntegers(Uart.byteCntMax, traceLen, 0x23);\r
1115\r
1116done:\r
1117 PDC_CONTROL(SSC_BASE) = PDC_RX_DISABLE;\r
1118 LED_A_OFF();\r
1119 LED_B_OFF();\r
1120}\r
Impressum, Datenschutz