]> git.zerfleddert.de Git - proxmark3-svn/blob - armsrc/iso15693.c
Reintegrated scripting-branch into trunk. yay
[proxmark3-svn] / armsrc / iso15693.c
1 //-----------------------------------------------------------------------------
2 // Jonathan Westhues, split Nov 2006
3 // Modified by Greg Jones, Jan 2009
4 // Modified by Adrian Dabrowski "atrox", Mar-Sept 2010,Oct 2011
5 //
6 // This code is licensed to you under the terms of the GNU GPL, version 2 or,
7 // at your option, any later version. See the LICENSE.txt file for the text of
8 // the license.
9 //-----------------------------------------------------------------------------
10 // Routines to support ISO 15693. This includes both the reader software and
11 // the `fake tag' modes, but at the moment I've implemented only the reader
12 // stuff, and that barely.
13 // Modified to perform modulation onboard in arm rather than on PC
14 // Also added additional reader commands (SELECT, READ etc.)
15 //-----------------------------------------------------------------------------
16 // The ISO 15693 describes two transmission modes from reader to tag, and 4
17 // transmission modes from tag to reader. As of Mar 2010 this code only
18 // supports one of each: "1of4" mode from reader to tag, and the highspeed
19 // variant with one subcarrier from card to reader.
20 // As long, as the card fully support ISO 15693 this is no problem, since the
21 // reader chooses both data rates, but some non-standard tags do not. Further for
22 // the simulation to work, we will need to support all data rates.
23 //
24 // VCD (reader) -> VICC (tag)
25 // 1 out of 256:
26 // data rate: 1,66 kbit/s (fc/8192)
27 // used for long range
28 // 1 out of 4:
29 // data rate: 26,48 kbit/s (fc/512)
30 // used for short range, high speed
31 //
32 // VICC (tag) -> VCD (reader)
33 // Modulation:
34 // ASK / one subcarrier (423,75 khz)
35 // FSK / two subcarriers (423,75 khz && 484,28 khz)
36 // Data Rates / Modes:
37 // low ASK: 6,62 kbit/s
38 // low FSK: 6.67 kbit/s
39 // high ASK: 26,48 kbit/s
40 // high FSK: 26,69 kbit/s
41 //-----------------------------------------------------------------------------
42 // added "1 out of 256" mode (for VCD->PICC) - atrox 20100911
43
44
45 // Random Remarks:
46 // *) UID is always used "transmission order" (LSB), which is reverse to display order
47
48 // TODO / BUGS / ISSUES:
49 // *) writing to tags takes longer: we miss the answer from the tag in most cases
50 // -> tweak the read-timeout times
51 // *) signal decoding from the card is still a bit shaky.
52 // *) signal decoding is unable to detect collissions.
53 // *) add anti-collission support for inventory-commands
54 // *) read security status of a block
55 // *) sniffing and simulation do only support one transmission mode. need to support
56 // all 8 transmission combinations
57 // *) remove or refactor code under "depricated"
58 // *) document all the functions
59
60
61 #include "proxmark3.h"
62 #include "util.h"
63 #include "apps.h"
64 #include "string.h"
65 #include "iso15693tools.h"
66 #include "cmd.h"
67
68 #define arraylen(x) (sizeof(x)/sizeof((x)[0]))
69
70 ///////////////////////////////////////////////////////////////////////
71 // ISO 15693 Part 2 - Air Interface
72 // This section basicly contains transmission and receiving of bits
73 ///////////////////////////////////////////////////////////////////////
74
75 #define FrameSOF Iso15693FrameSOF
76 #define Logic0 Iso15693Logic0
77 #define Logic1 Iso15693Logic1
78 #define FrameEOF Iso15693FrameEOF
79
80 #define Crc(data,datalen) Iso15693Crc(data,datalen)
81 #define AddCrc(data,datalen) Iso15693AddCrc(data,datalen)
82 #define sprintUID(target,uid) Iso15693sprintUID(target,uid)
83
84 int DEBUG=0;
85
86
87 // ---------------------------
88 // Signal Processing
89 // ---------------------------
90
91 // prepare data using "1 out of 4" code for later transmission
92 // resulting data rate is 26,48 kbit/s (fc/512)
93 // cmd ... data
94 // n ... length of data
95 static void CodeIso15693AsReader(uint8_t *cmd, int n)
96 {
97 int i, j;
98
99 ToSendReset();
100
101 // Give it a bit of slack at the beginning
102 for(i = 0; i < 24; i++) {
103 ToSendStuffBit(1);
104 }
105
106 // SOF for 1of4
107 ToSendStuffBit(0);
108 ToSendStuffBit(1);
109 ToSendStuffBit(1);
110 ToSendStuffBit(1);
111 ToSendStuffBit(1);
112 ToSendStuffBit(0);
113 ToSendStuffBit(1);
114 ToSendStuffBit(1);
115 for(i = 0; i < n; i++) {
116 for(j = 0; j < 8; j += 2) {
117 int these = (cmd[i] >> j) & 3;
118 switch(these) {
119 case 0:
120 ToSendStuffBit(1);
121 ToSendStuffBit(0);
122 ToSendStuffBit(1);
123 ToSendStuffBit(1);
124 ToSendStuffBit(1);
125 ToSendStuffBit(1);
126 ToSendStuffBit(1);
127 ToSendStuffBit(1);
128 break;
129 case 1:
130 ToSendStuffBit(1);
131 ToSendStuffBit(1);
132 ToSendStuffBit(1);
133 ToSendStuffBit(0);
134 ToSendStuffBit(1);
135 ToSendStuffBit(1);
136 ToSendStuffBit(1);
137 ToSendStuffBit(1);
138 break;
139 case 2:
140 ToSendStuffBit(1);
141 ToSendStuffBit(1);
142 ToSendStuffBit(1);
143 ToSendStuffBit(1);
144 ToSendStuffBit(1);
145 ToSendStuffBit(0);
146 ToSendStuffBit(1);
147 ToSendStuffBit(1);
148 break;
149 case 3:
150 ToSendStuffBit(1);
151 ToSendStuffBit(1);
152 ToSendStuffBit(1);
153 ToSendStuffBit(1);
154 ToSendStuffBit(1);
155 ToSendStuffBit(1);
156 ToSendStuffBit(1);
157 ToSendStuffBit(0);
158 break;
159 }
160 }
161 }
162 // EOF
163 ToSendStuffBit(1);
164 ToSendStuffBit(1);
165 ToSendStuffBit(0);
166 ToSendStuffBit(1);
167
168 // And slack at the end, too.
169 for(i = 0; i < 24; i++) {
170 ToSendStuffBit(1);
171 }
172 }
173
174 // encode data using "1 out of 256" sheme
175 // data rate is 1,66 kbit/s (fc/8192)
176 // is designed for more robust communication over longer distances
177 static void CodeIso15693AsReader256(uint8_t *cmd, int n)
178 {
179 int i, j;
180
181 ToSendReset();
182
183 // Give it a bit of slack at the beginning
184 for(i = 0; i < 24; i++) {
185 ToSendStuffBit(1);
186 }
187
188 // SOF for 1of256
189 ToSendStuffBit(0);
190 ToSendStuffBit(1);
191 ToSendStuffBit(1);
192 ToSendStuffBit(1);
193 ToSendStuffBit(1);
194 ToSendStuffBit(1);
195 ToSendStuffBit(1);
196 ToSendStuffBit(0);
197
198 for(i = 0; i < n; i++) {
199 for (j = 0; j<=255; j++) {
200 if (cmd[i]==j) {
201 ToSendStuffBit(1);
202 ToSendStuffBit(0);
203 } else {
204 ToSendStuffBit(1);
205 ToSendStuffBit(1);
206 }
207 }
208 }
209 // EOF
210 ToSendStuffBit(1);
211 ToSendStuffBit(1);
212 ToSendStuffBit(0);
213 ToSendStuffBit(1);
214
215 // And slack at the end, too.
216 for(i = 0; i < 24; i++) {
217 ToSendStuffBit(1);
218 }
219 }
220
221
222 // Transmit the command (to the tag) that was placed in ToSend[].
223 static void TransmitTo15693Tag(const uint8_t *cmd, int len, int *samples, int *wait)
224 {
225 int c;
226
227 // FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD);
228 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX);
229 if(*wait < 10) { *wait = 10; }
230
231 // for(c = 0; c < *wait;) {
232 // if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
233 // AT91C_BASE_SSC->SSC_THR = 0x00; // For exact timing!
234 // c++;
235 // }
236 // if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
237 // volatile uint32_t r = AT91C_BASE_SSC->SSC_RHR;
238 // (void)r;
239 // }
240 // WDT_HIT();
241 // }
242
243 c = 0;
244 for(;;) {
245 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
246 AT91C_BASE_SSC->SSC_THR = cmd[c];
247 c++;
248 if(c >= len) {
249 break;
250 }
251 }
252 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
253 volatile uint32_t r = AT91C_BASE_SSC->SSC_RHR;
254 (void)r;
255 }
256 WDT_HIT();
257 }
258 *samples = (c + *wait) << 3;
259 }
260
261 //-----------------------------------------------------------------------------
262 // Transmit the command (to the reader) that was placed in ToSend[].
263 //-----------------------------------------------------------------------------
264 static void TransmitTo15693Reader(const uint8_t *cmd, int len, int *samples, int *wait)
265 {
266 int c;
267
268 // FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX);
269 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR); // No requirement to energise my coils
270 if(*wait < 10) { *wait = 10; }
271
272 c = 0;
273 for(;;) {
274 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
275 AT91C_BASE_SSC->SSC_THR = cmd[c];
276 c++;
277 if(c >= len) {
278 break;
279 }
280 }
281 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
282 volatile uint32_t r = AT91C_BASE_SSC->SSC_RHR;
283 (void)r;
284 }
285 WDT_HIT();
286 }
287 *samples = (c + *wait) << 3;
288 }
289
290
291 // Read from Tag
292 // Parameters:
293 // receivedResponse
294 // maxLen
295 // samples
296 // elapsed
297 // returns:
298 // number of decoded bytes
299 static int GetIso15693AnswerFromTag(uint8_t *receivedResponse, int maxLen, int *samples, int *elapsed)
300 {
301 int c = 0;
302 uint8_t *dest = (uint8_t *)BigBuf;
303 int getNext = 0;
304
305 int8_t prev = 0;
306
307 // NOW READ RESPONSE
308 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
309 //spindelay(60); // greg - experiment to get rid of some of the 0 byte/failed reads
310 c = 0;
311 getNext = FALSE;
312 for(;;) {
313 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
314 AT91C_BASE_SSC->SSC_THR = 0x43;
315 }
316 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
317 int8_t b;
318 b = (int8_t)AT91C_BASE_SSC->SSC_RHR;
319
320 // The samples are correlations against I and Q versions of the
321 // tone that the tag AM-modulates, so every other sample is I,
322 // every other is Q. We just want power, so abs(I) + abs(Q) is
323 // close to what we want.
324 if(getNext) {
325 int8_t r;
326
327 if(b < 0) {
328 r = -b;
329 } else {
330 r = b;
331 }
332 if(prev < 0) {
333 r -= prev;
334 } else {
335 r += prev;
336 }
337
338 dest[c++] = (uint8_t)r;
339
340 if(c >= 2000) {
341 break;
342 }
343 } else {
344 prev = b;
345 }
346
347 getNext = !getNext;
348 }
349 }
350
351 //////////////////////////////////////////
352 /////////// DEMODULATE ///////////////////
353 //////////////////////////////////////////
354
355 int i, j;
356 int max = 0, maxPos=0;
357
358 int skip = 4;
359
360 // if(GraphTraceLen < 1000) return; // THIS CHECKS FOR A BUFFER TO SMALL
361
362 // First, correlate for SOF
363 for(i = 0; i < 100; i++) {
364 int corr = 0;
365 for(j = 0; j < arraylen(FrameSOF); j += skip) {
366 corr += FrameSOF[j]*dest[i+(j/skip)];
367 }
368 if(corr > max) {
369 max = corr;
370 maxPos = i;
371 }
372 }
373 // DbpString("SOF at %d, correlation %d", maxPos,max/(arraylen(FrameSOF)/skip));
374
375 int k = 0; // this will be our return value
376
377 // greg - If correlation is less than 1 then there's little point in continuing
378 if ((max/(arraylen(FrameSOF)/skip)) >= 1)
379 {
380
381 i = maxPos + arraylen(FrameSOF)/skip;
382
383 uint8_t outBuf[20];
384 memset(outBuf, 0, sizeof(outBuf));
385 uint8_t mask = 0x01;
386 for(;;) {
387 int corr0 = 0, corr1 = 0, corrEOF = 0;
388 for(j = 0; j < arraylen(Logic0); j += skip) {
389 corr0 += Logic0[j]*dest[i+(j/skip)];
390 }
391 for(j = 0; j < arraylen(Logic1); j += skip) {
392 corr1 += Logic1[j]*dest[i+(j/skip)];
393 }
394 for(j = 0; j < arraylen(FrameEOF); j += skip) {
395 corrEOF += FrameEOF[j]*dest[i+(j/skip)];
396 }
397 // Even things out by the length of the target waveform.
398 corr0 *= 4;
399 corr1 *= 4;
400
401 if(corrEOF > corr1 && corrEOF > corr0) {
402 // DbpString("EOF at %d", i);
403 break;
404 } else if(corr1 > corr0) {
405 i += arraylen(Logic1)/skip;
406 outBuf[k] |= mask;
407 } else {
408 i += arraylen(Logic0)/skip;
409 }
410 mask <<= 1;
411 if(mask == 0) {
412 k++;
413 mask = 0x01;
414 }
415 if((i+(int)arraylen(FrameEOF)) >= 2000) {
416 DbpString("ran off end!");
417 break;
418 }
419 }
420 if(mask != 0x01) { // this happens, when we miss the EOF
421 // TODO: for some reason this happens quite often
422 if (DEBUG) Dbprintf("error, uneven octet! (extra bits!) mask=%02x", mask);
423 if (mask<0x08) k--; // discard the last uneven octet;
424 // 0x08 is an assumption - but works quite often
425 }
426 // uint8_t str1 [8];
427 // itoa(k,str1);
428 // strncat(str1," octets read",8);
429
430 // DbpString( str1); // DbpString("%d octets", k);
431
432 // for(i = 0; i < k; i+=3) {
433 // //DbpString("# %2d: %02x ", i, outBuf[i]);
434 // DbpIntegers(outBuf[i],outBuf[i+1],outBuf[i+2]);
435 // }
436
437 for(i = 0; i < k; i++) {
438 receivedResponse[i] = outBuf[i];
439 }
440 } // "end if correlation > 0" (max/(arraylen(FrameSOF)/skip))
441 return k; // return the number of bytes demodulated
442
443 /// DbpString("CRC=%04x", Iso15693Crc(outBuf, k-2));
444
445 }
446
447
448 // Now the GetISO15693 message from sniffing command
449 static int GetIso15693AnswerFromSniff(uint8_t *receivedResponse, int maxLen, int *samples, int *elapsed)
450 {
451 int c = 0;
452 uint8_t *dest = (uint8_t *)BigBuf;
453 int getNext = 0;
454
455 int8_t prev = 0;
456
457 // NOW READ RESPONSE
458 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
459 //spindelay(60); // greg - experiment to get rid of some of the 0 byte/failed reads
460 c = 0;
461 getNext = FALSE;
462 for(;;) {
463 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
464 AT91C_BASE_SSC->SSC_THR = 0x43;
465 }
466 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
467 int8_t b;
468 b = (int8_t)AT91C_BASE_SSC->SSC_RHR;
469
470 // The samples are correlations against I and Q versions of the
471 // tone that the tag AM-modulates, so every other sample is I,
472 // every other is Q. We just want power, so abs(I) + abs(Q) is
473 // close to what we want.
474 if(getNext) {
475 int8_t r;
476
477 if(b < 0) {
478 r = -b;
479 } else {
480 r = b;
481 }
482 if(prev < 0) {
483 r -= prev;
484 } else {
485 r += prev;
486 }
487
488 dest[c++] = (uint8_t)r;
489
490 if(c >= 20000) {
491 break;
492 }
493 } else {
494 prev = b;
495 }
496
497 getNext = !getNext;
498 }
499 }
500
501 //////////////////////////////////////////
502 /////////// DEMODULATE ///////////////////
503 //////////////////////////////////////////
504
505 int i, j;
506 int max = 0, maxPos=0;
507
508 int skip = 4;
509
510 // if(GraphTraceLen < 1000) return; // THIS CHECKS FOR A BUFFER TO SMALL
511
512 // First, correlate for SOF
513 for(i = 0; i < 19000; i++) {
514 int corr = 0;
515 for(j = 0; j < arraylen(FrameSOF); j += skip) {
516 corr += FrameSOF[j]*dest[i+(j/skip)];
517 }
518 if(corr > max) {
519 max = corr;
520 maxPos = i;
521 }
522 }
523 // DbpString("SOF at %d, correlation %d", maxPos,max/(arraylen(FrameSOF)/skip));
524
525 int k = 0; // this will be our return value
526
527 // greg - If correlation is less than 1 then there's little point in continuing
528 if ((max/(arraylen(FrameSOF)/skip)) >= 1) // THIS SHOULD BE 1
529 {
530
531 i = maxPos + arraylen(FrameSOF)/skip;
532
533 uint8_t outBuf[20];
534 memset(outBuf, 0, sizeof(outBuf));
535 uint8_t mask = 0x01;
536 for(;;) {
537 int corr0 = 0, corr1 = 0, corrEOF = 0;
538 for(j = 0; j < arraylen(Logic0); j += skip) {
539 corr0 += Logic0[j]*dest[i+(j/skip)];
540 }
541 for(j = 0; j < arraylen(Logic1); j += skip) {
542 corr1 += Logic1[j]*dest[i+(j/skip)];
543 }
544 for(j = 0; j < arraylen(FrameEOF); j += skip) {
545 corrEOF += FrameEOF[j]*dest[i+(j/skip)];
546 }
547 // Even things out by the length of the target waveform.
548 corr0 *= 4;
549 corr1 *= 4;
550
551 if(corrEOF > corr1 && corrEOF > corr0) {
552 // DbpString("EOF at %d", i);
553 break;
554 } else if(corr1 > corr0) {
555 i += arraylen(Logic1)/skip;
556 outBuf[k] |= mask;
557 } else {
558 i += arraylen(Logic0)/skip;
559 }
560 mask <<= 1;
561 if(mask == 0) {
562 k++;
563 mask = 0x01;
564 }
565 if((i+(int)arraylen(FrameEOF)) >= 2000) {
566 DbpString("ran off end!");
567 break;
568 }
569 }
570 if(mask != 0x01) {
571 DbpString("sniff: error, uneven octet! (discard extra bits!)");
572 /// DbpString(" mask=%02x", mask);
573 }
574 // uint8_t str1 [8];
575 // itoa(k,str1);
576 // strncat(str1," octets read",8);
577
578 // DbpString( str1); // DbpString("%d octets", k);
579
580 // for(i = 0; i < k; i+=3) {
581 // //DbpString("# %2d: %02x ", i, outBuf[i]);
582 // DbpIntegers(outBuf[i],outBuf[i+1],outBuf[i+2]);
583 // }
584
585 for(i = 0; i < k; i++) {
586 receivedResponse[i] = outBuf[i];
587 }
588 } // "end if correlation > 0" (max/(arraylen(FrameSOF)/skip))
589 return k; // return the number of bytes demodulated
590
591 /// DbpString("CRC=%04x", Iso15693Crc(outBuf, k-2));
592 }
593
594
595 static void BuildIdentifyRequest(void);
596 //-----------------------------------------------------------------------------
597 // Start to read an ISO 15693 tag. We send an identify request, then wait
598 // for the response. The response is not demodulated, just left in the buffer
599 // so that it can be downloaded to a PC and processed there.
600 //-----------------------------------------------------------------------------
601 void AcquireRawAdcSamplesIso15693(void)
602 {
603 int c = 0;
604 uint8_t *dest = (uint8_t *)BigBuf;
605 int getNext = 0;
606
607 int8_t prev = 0;
608
609 BuildIdentifyRequest();
610
611 SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
612
613 // Give the tags time to energize
614 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
615 SpinDelay(100);
616
617 // Now send the command
618 FpgaSetupSsc();
619 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX);
620
621 c = 0;
622 for(;;) {
623 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
624 AT91C_BASE_SSC->SSC_THR = ToSend[c];
625 c++;
626 if(c == ToSendMax+3) {
627 break;
628 }
629 }
630 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
631 volatile uint32_t r = AT91C_BASE_SSC->SSC_RHR;
632 (void)r;
633 }
634 WDT_HIT();
635 }
636
637 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
638
639 c = 0;
640 getNext = FALSE;
641 for(;;) {
642 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
643 AT91C_BASE_SSC->SSC_THR = 0x43;
644 }
645 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
646 int8_t b;
647 b = (int8_t)AT91C_BASE_SSC->SSC_RHR;
648
649 // The samples are correlations against I and Q versions of the
650 // tone that the tag AM-modulates, so every other sample is I,
651 // every other is Q. We just want power, so abs(I) + abs(Q) is
652 // close to what we want.
653 if(getNext) {
654 int8_t r;
655
656 if(b < 0) {
657 r = -b;
658 } else {
659 r = b;
660 }
661 if(prev < 0) {
662 r -= prev;
663 } else {
664 r += prev;
665 }
666
667 dest[c++] = (uint8_t)r;
668
669 if(c >= 2000) {
670 break;
671 }
672 } else {
673 prev = b;
674 }
675
676 getNext = !getNext;
677 }
678 }
679 }
680
681
682 void RecordRawAdcSamplesIso15693(void)
683 {
684 int c = 0;
685 uint8_t *dest = (uint8_t *)BigBuf;
686 int getNext = 0;
687
688 int8_t prev = 0;
689
690 // Setup SSC
691 FpgaSetupSsc();
692
693 // Start from off (no field generated)
694 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
695 SpinDelay(200);
696
697 SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
698
699 SpinDelay(100);
700
701 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
702
703 c = 0;
704 getNext = FALSE;
705 for(;;) {
706 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
707 AT91C_BASE_SSC->SSC_THR = 0x43;
708 }
709 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
710 int8_t b;
711 b = (int8_t)AT91C_BASE_SSC->SSC_RHR;
712
713 // The samples are correlations against I and Q versions of the
714 // tone that the tag AM-modulates, so every other sample is I,
715 // every other is Q. We just want power, so abs(I) + abs(Q) is
716 // close to what we want.
717 if(getNext) {
718 int8_t r;
719
720 if(b < 0) {
721 r = -b;
722 } else {
723 r = b;
724 }
725 if(prev < 0) {
726 r -= prev;
727 } else {
728 r += prev;
729 }
730
731 dest[c++] = (uint8_t)r;
732
733 if(c >= 7000) {
734 break;
735 }
736 } else {
737 prev = b;
738 }
739
740 getNext = !getNext;
741 WDT_HIT();
742 }
743 }
744 Dbprintf("fin record");
745 }
746
747
748 // Initialize the proxmark as iso15k reader
749 // (this might produces glitches that confuse some tags
750 void Iso15693InitReader() {
751 LED_A_ON();
752 LED_B_ON();
753 LED_C_OFF();
754 LED_D_OFF();
755
756 // Setup SSC
757 // FpgaSetupSsc();
758
759 // Start from off (no field generated)
760 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
761 SpinDelay(10);
762
763 SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
764 FpgaSetupSsc();
765
766 // Give the tags time to energize
767 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
768 SpinDelay(250);
769
770 LED_A_ON();
771 LED_B_OFF();
772 LED_C_OFF();
773 LED_D_OFF();
774 }
775
776 ///////////////////////////////////////////////////////////////////////
777 // ISO 15693 Part 3 - Air Interface
778 // This section basicly contains transmission and receiving of bits
779 ///////////////////////////////////////////////////////////////////////
780
781 // Encode (into the ToSend buffers) an identify request, which is the first
782 // thing that you must send to a tag to get a response.
783 static void BuildIdentifyRequest(void)
784 {
785 uint8_t cmd[5];
786
787 uint16_t crc;
788 // one sub-carrier, inventory, 1 slot, fast rate
789 // AFI is at bit 5 (1<<4) when doing an INVENTORY
790 cmd[0] = (1 << 2) | (1 << 5) | (1 << 1);
791 // inventory command code
792 cmd[1] = 0x01;
793 // no mask
794 cmd[2] = 0x00;
795 //Now the CRC
796 crc = Crc(cmd, 3);
797 cmd[3] = crc & 0xff;
798 cmd[4] = crc >> 8;
799
800 CodeIso15693AsReader(cmd, sizeof(cmd));
801 }
802
803 // uid is in transmission order (which is reverse of display order)
804 static void BuildReadBlockRequest(uint8_t *uid, uint8_t blockNumber )
805 {
806 uint8_t cmd[13];
807
808 uint16_t crc;
809 // If we set the Option_Flag in this request, the VICC will respond with the secuirty status of the block
810 // followed by teh block data
811 // one sub-carrier, inventory, 1 slot, fast rate
812 cmd[0] = (1 << 6)| (1 << 5) | (1 << 1); // no SELECT bit, ADDR bit, OPTION bit
813 // READ BLOCK command code
814 cmd[1] = 0x20;
815 // UID may be optionally specified here
816 // 64-bit UID
817 cmd[2] = uid[0];
818 cmd[3] = uid[1];
819 cmd[4] = uid[2];
820 cmd[5] = uid[3];
821 cmd[6] = uid[4];
822 cmd[7] = uid[5];
823 cmd[8] = uid[6];
824 cmd[9] = uid[7]; // 0xe0; // always e0 (not exactly unique)
825 // Block number to read
826 cmd[10] = blockNumber;//0x00;
827 //Now the CRC
828 crc = Crc(cmd, 11); // the crc needs to be calculated over 12 bytes
829 cmd[11] = crc & 0xff;
830 cmd[12] = crc >> 8;
831
832 CodeIso15693AsReader(cmd, sizeof(cmd));
833 }
834
835 // Now the VICC>VCD responses when we are simulating a tag
836 static void BuildInventoryResponse(void)
837 {
838 uint8_t cmd[12];
839
840 uint16_t crc;
841 // one sub-carrier, inventory, 1 slot, fast rate
842 // AFI is at bit 5 (1<<4) when doing an INVENTORY
843 cmd[0] = 0; //(1 << 2) | (1 << 5) | (1 << 1);
844 cmd[1] = 0;
845 // 64-bit UID
846 cmd[2] = 0x32;
847 cmd[3]= 0x4b;
848 cmd[4] = 0x03;
849 cmd[5] = 0x01;
850 cmd[6] = 0x00;
851 cmd[7] = 0x10;
852 cmd[8] = 0x05;
853 cmd[9]= 0xe0;
854 //Now the CRC
855 crc = Crc(cmd, 10);
856 cmd[10] = crc & 0xff;
857 cmd[11] = crc >> 8;
858
859 CodeIso15693AsReader(cmd, sizeof(cmd));
860 }
861
862 // Universal Method for sending to and recv bytes from a tag
863 // init ... should we initialize the reader?
864 // speed ... 0 low speed, 1 hi speed
865 // **recv will return you a pointer to the received data
866 // If you do not need the answer use NULL for *recv[]
867 // return: lenght of received data
868 int SendDataTag(uint8_t *send, int sendlen, int init, int speed, uint8_t **recv) {
869
870 int samples = 0;
871 int tsamples = 0;
872 int wait = 0;
873 int elapsed = 0;
874
875 LED_A_ON();
876 LED_B_ON();
877 LED_C_OFF();
878 LED_D_OFF();
879
880 int answerLen=0;
881 uint8_t *answer = (((uint8_t *)BigBuf) + 3660);
882 if (recv!=NULL) memset(BigBuf + 3660, 0, 100);
883
884 if (init) Iso15693InitReader();
885
886 if (!speed) {
887 // low speed (1 out of 256)
888 CodeIso15693AsReader256(send, sendlen);
889 } else {
890 // high speed (1 out of 4)
891 CodeIso15693AsReader(send, sendlen);
892 }
893
894 LED_A_ON();
895 LED_B_OFF();
896
897 TransmitTo15693Tag(ToSend,ToSendMax,&tsamples, &wait);
898 // Now wait for a response
899 if (recv!=NULL) {
900 LED_A_OFF();
901 LED_B_ON();
902 answerLen = GetIso15693AnswerFromTag(answer, 100, &samples, &elapsed) ;
903 *recv=answer;
904 }
905
906 LED_A_OFF();
907 LED_B_OFF();
908 LED_C_OFF();
909 LED_D_OFF();
910
911 return answerLen;
912 }
913
914
915 // --------------------------------------------------------------------
916 // Debug Functions
917 // --------------------------------------------------------------------
918
919 // Decodes a message from a tag and displays its metadata and content
920 #define DBD15STATLEN 48
921 void DbdecodeIso15693Answer(int len, uint8_t *d) {
922 char status[DBD15STATLEN+1]={0};
923 uint16_t crc;
924
925 if (len>3) {
926 if (d[0]&(1<<3))
927 strncat(status,"ProtExt ",DBD15STATLEN);
928 if (d[0]&1) {
929 // error
930 strncat(status,"Error ",DBD15STATLEN);
931 switch (d[1]) {
932 case 0x01:
933 strncat(status,"01:notSupp",DBD15STATLEN);
934 break;
935 case 0x02:
936 strncat(status,"02:notRecog",DBD15STATLEN);
937 break;
938 case 0x03:
939 strncat(status,"03:optNotSupp",DBD15STATLEN);
940 break;
941 case 0x0f:
942 strncat(status,"0f:noInfo",DBD15STATLEN);
943 break;
944 case 0x10:
945 strncat(status,"10:dontExist",DBD15STATLEN);
946 break;
947 case 0x11:
948 strncat(status,"11:lockAgain",DBD15STATLEN);
949 break;
950 case 0x12:
951 strncat(status,"12:locked",DBD15STATLEN);
952 break;
953 case 0x13:
954 strncat(status,"13:progErr",DBD15STATLEN);
955 break;
956 case 0x14:
957 strncat(status,"14:lockErr",DBD15STATLEN);
958 break;
959 default:
960 strncat(status,"unknownErr",DBD15STATLEN);
961 }
962 strncat(status," ",DBD15STATLEN);
963 } else {
964 strncat(status,"NoErr ",DBD15STATLEN);
965 }
966
967 crc=Crc(d,len-2);
968 if ( (( crc & 0xff ) == d[len-2]) && (( crc >> 8 ) == d[len-1]) )
969 strncat(status,"CrcOK",DBD15STATLEN);
970 else
971 strncat(status,"CrcFail!",DBD15STATLEN);
972
973 Dbprintf("%s",status);
974 }
975 }
976
977
978
979 ///////////////////////////////////////////////////////////////////////
980 // Functions called via USB/Client
981 ///////////////////////////////////////////////////////////////////////
982
983 void SetDebugIso15693(uint32_t debug) {
984 DEBUG=debug;
985 Dbprintf("Iso15693 Debug is now %s",DEBUG?"on":"off");
986 return;
987 }
988
989
990
991 //-----------------------------------------------------------------------------
992 // Simulate an ISO15693 reader, perform anti-collision and then attempt to read a sector
993 // all demodulation performed in arm rather than host. - greg
994 //-----------------------------------------------------------------------------
995 void ReaderIso15693(uint32_t parameter)
996 {
997 LED_A_ON();
998 LED_B_ON();
999 LED_C_OFF();
1000 LED_D_OFF();
1001
1002 //DbpString(parameter);
1003
1004 //uint8_t *answer0 = (((uint8_t *)BigBuf) + 3560); // allow 100 bytes per reponse (way too much)
1005 uint8_t *answer1 = (((uint8_t *)BigBuf) + 3660); //
1006 uint8_t *answer2 = (((uint8_t *)BigBuf) + 3760);
1007 uint8_t *answer3 = (((uint8_t *)BigBuf) + 3860);
1008 //uint8_t *TagUID= (((uint8_t *)BigBuf) + 3960); // where we hold the uid for hi15reader
1009 // int answerLen0 = 0;
1010 int answerLen1 = 0;
1011 int answerLen2 = 0;
1012 int answerLen3 = 0;
1013 int i=0; // counter
1014
1015 // Blank arrays
1016 memset(BigBuf + 3660, 0, 300);
1017
1018 // Setup SSC
1019 FpgaSetupSsc();
1020
1021 // Start from off (no field generated)
1022 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
1023 SpinDelay(200);
1024
1025 SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
1026 FpgaSetupSsc();
1027
1028 // Give the tags time to energize
1029 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
1030 SpinDelay(200);
1031
1032 LED_A_ON();
1033 LED_B_OFF();
1034 LED_C_OFF();
1035 LED_D_OFF();
1036
1037 int samples = 0;
1038 int tsamples = 0;
1039 int wait = 0;
1040 int elapsed = 0;
1041
1042 // FIRST WE RUN AN INVENTORY TO GET THE TAG UID
1043 // THIS MEANS WE CAN PRE-BUILD REQUESTS TO SAVE CPU TIME
1044 uint8_t TagUID[8] = {0, 0, 0, 0, 0, 0, 0, 0}; // where we hold the uid for hi15reader
1045
1046 // BuildIdentifyRequest();
1047 // //TransmitTo15693Tag(ToSend,ToSendMax+3,&tsamples, &wait);
1048 // TransmitTo15693Tag(ToSend,ToSendMax,&tsamples, &wait); // No longer ToSendMax+3
1049 // // Now wait for a response
1050 // responseLen0 = GetIso15693AnswerFromTag(receivedAnswer0, 100, &samples, &elapsed) ;
1051 // if (responseLen0 >=12) // we should do a better check than this
1052 // {
1053 // // really we should check it is a valid mesg
1054 // // but for now just grab what we think is the uid
1055 // TagUID[0] = receivedAnswer0[2];
1056 // TagUID[1] = receivedAnswer0[3];
1057 // TagUID[2] = receivedAnswer0[4];
1058 // TagUID[3] = receivedAnswer0[5];
1059 // TagUID[4] = receivedAnswer0[6];
1060 // TagUID[5] = receivedAnswer0[7];
1061 // TagUID[6] = receivedAnswer0[8]; // IC Manufacturer code
1062 // DbpIntegers(TagUID[6],TagUID[5],TagUID[4]);
1063 //}
1064
1065 // Now send the IDENTIFY command
1066 BuildIdentifyRequest();
1067 //TransmitTo15693Tag(ToSend,ToSendMax+3,&tsamples, &wait);
1068 TransmitTo15693Tag(ToSend,ToSendMax,&tsamples, &wait); // No longer ToSendMax+3
1069 // Now wait for a response
1070 answerLen1 = GetIso15693AnswerFromTag(answer1, 100, &samples, &elapsed) ;
1071
1072 if (answerLen1 >=12) // we should do a better check than this
1073 {
1074
1075 TagUID[0] = answer1[2];
1076 TagUID[1] = answer1[3];
1077 TagUID[2] = answer1[4];
1078 TagUID[3] = answer1[5];
1079 TagUID[4] = answer1[6];
1080 TagUID[5] = answer1[7];
1081 TagUID[6] = answer1[8]; // IC Manufacturer code
1082 TagUID[7] = answer1[9]; // always E0
1083
1084 // Now send the SELECT command
1085 // since the SELECT command is optional, we should not rely on it.
1086 //// BuildSelectRequest(TagUID);
1087 // TransmitTo15693Tag(ToSend,ToSendMax,&tsamples, &wait); // No longer ToSendMax+3
1088 // Now wait for a response
1089 /// answerLen2 = GetIso15693AnswerFromTag(answer2, 100, &samples, &elapsed);
1090
1091 // Now send the MULTI READ command
1092 // BuildArbitraryRequest(*TagUID,parameter);
1093 /// BuildArbitraryCustomRequest(TagUID,parameter);
1094 // BuildReadBlockRequest(*TagUID,parameter);
1095 // BuildSysInfoRequest(*TagUID);
1096 //TransmitTo15693Tag(ToSend,ToSendMax+3,&tsamples, &wait);
1097 /// TransmitTo15693Tag(ToSend,ToSendMax,&tsamples, &wait); // No longer ToSendMax+3
1098 // Now wait for a response
1099 /// answerLen3 = GetIso15693AnswerFromTag(answer3, 100, &samples, &elapsed) ;
1100
1101 }
1102
1103 Dbprintf("%d octets read from IDENTIFY request:", answerLen1);
1104 DbdecodeIso15693Answer(answerLen1,answer1);
1105 Dbhexdump(answerLen1,answer1,true);
1106
1107 // UID is reverse
1108 if (answerLen1>=12)
1109 //Dbprintf("UID = %*D",8,TagUID," ");
1110 Dbprintf("UID = %02hX%02hX%02hX%02hX%02hX%02hX%02hX%02hX",TagUID[7],TagUID[6],TagUID[5],
1111 TagUID[4],TagUID[3],TagUID[2],TagUID[1],TagUID[0]);
1112
1113
1114 Dbprintf("%d octets read from SELECT request:", answerLen2);
1115 DbdecodeIso15693Answer(answerLen2,answer2);
1116 Dbhexdump(answerLen2,answer2,true);
1117
1118 Dbprintf("%d octets read from XXX request:", answerLen3);
1119 DbdecodeIso15693Answer(answerLen3,answer3);
1120 Dbhexdump(answerLen3,answer3,true);
1121
1122
1123 // read all pages
1124 if (answerLen1>=12 && DEBUG) {
1125 i=0;
1126 while (i<32) { // sanity check, assume max 32 pages
1127 BuildReadBlockRequest(TagUID,i);
1128 TransmitTo15693Tag(ToSend,ToSendMax,&tsamples, &wait);
1129 answerLen2 = GetIso15693AnswerFromTag(answer2, 100, &samples, &elapsed);
1130 if (answerLen2>0) {
1131 Dbprintf("READ SINGLE BLOCK %d returned %d octets:",i,answerLen2);
1132 DbdecodeIso15693Answer(answerLen2,answer2);
1133 Dbhexdump(answerLen2,answer2,true);
1134 if ( *((uint32_t*) answer2) == 0x07160101 ) break; // exit on NoPageErr
1135 }
1136 i++;
1137 }
1138 }
1139
1140 // str2[0]=0;
1141 // for(i = 0; i < responseLen3; i++) {
1142 // itoa(str1,receivedAnswer3[i]);
1143 // strncat(str2,str1,8);
1144 // }
1145 // DbpString(str2);
1146
1147 LED_A_OFF();
1148 LED_B_OFF();
1149 LED_C_OFF();
1150 LED_D_OFF();
1151 }
1152
1153 // Simulate an ISO15693 TAG, perform anti-collision and then print any reader commands
1154 // all demodulation performed in arm rather than host. - greg
1155 void SimTagIso15693(uint32_t parameter)
1156 {
1157 LED_A_ON();
1158 LED_B_ON();
1159 LED_C_OFF();
1160 LED_D_OFF();
1161
1162 uint8_t *answer1 = (((uint8_t *)BigBuf) + 3660); //
1163 int answerLen1 = 0;
1164
1165 // Blank arrays
1166 memset(answer1, 0, 100);
1167
1168 // Setup SSC
1169 FpgaSetupSsc();
1170
1171 // Start from off (no field generated)
1172 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
1173 SpinDelay(200);
1174
1175 SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
1176 FpgaSetupSsc();
1177
1178 // Give the tags time to energize
1179 // FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR); // NO GOOD FOR SIM TAG!!!!
1180 SpinDelay(200);
1181
1182 LED_A_OFF();
1183 LED_B_OFF();
1184 LED_C_ON();
1185 LED_D_OFF();
1186
1187 int samples = 0;
1188 int tsamples = 0;
1189 int wait = 0;
1190 int elapsed = 0;
1191
1192 answerLen1 = GetIso15693AnswerFromSniff(answer1, 100, &samples, &elapsed) ;
1193
1194 if (answerLen1 >=1) // we should do a better check than this
1195 {
1196 // Build a suitable reponse to the reader INVENTORY cocmmand
1197 BuildInventoryResponse();
1198 TransmitTo15693Reader(ToSend,ToSendMax, &tsamples, &wait);
1199 }
1200
1201 Dbprintf("%d octets read from reader command: %x %x %x %x %x %x %x %x %x", answerLen1,
1202 answer1[0], answer1[1], answer1[2],
1203 answer1[3], answer1[4], answer1[5],
1204 answer1[6], answer1[7], answer1[8]);
1205
1206 LED_A_OFF();
1207 LED_B_OFF();
1208 LED_C_OFF();
1209 LED_D_OFF();
1210 }
1211
1212
1213 // Since there is no standardized way of reading the AFI out of a tag, we will brute force it
1214 // (some manufactures offer a way to read the AFI, though)
1215 void BruteforceIso15693Afi(uint32_t speed)
1216 {
1217 uint8_t data[20];
1218 uint8_t *recv=data;
1219 int datalen=0, recvlen=0;
1220
1221 Iso15693InitReader();
1222
1223 // first without AFI
1224 // Tags should respond wihtout AFI and with AFI=0 even when AFI is active
1225
1226 data[0]=ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH |
1227 ISO15_REQ_INVENTORY | ISO15_REQINV_SLOT1;
1228 data[1]=ISO15_CMD_INVENTORY;
1229 data[2]=0; // mask length
1230 datalen=AddCrc(data,3);
1231 recvlen=SendDataTag(data,datalen,0,speed,&recv);
1232 WDT_HIT();
1233 if (recvlen>=12) {
1234 Dbprintf("NoAFI UID=%s",sprintUID(NULL,&recv[2]));
1235 }
1236
1237 // now with AFI
1238
1239 data[0]=ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH |
1240 ISO15_REQ_INVENTORY | ISO15_REQINV_AFI | ISO15_REQINV_SLOT1;
1241 data[1]=ISO15_CMD_INVENTORY;
1242 data[2]=0; // AFI
1243 data[3]=0; // mask length
1244
1245 for (int i=0;i<256;i++) {
1246 data[2]=i & 0xFF;
1247 datalen=AddCrc(data,4);
1248 recvlen=SendDataTag(data,datalen,0,speed,&recv);
1249 WDT_HIT();
1250 if (recvlen>=12) {
1251 Dbprintf("AFI=%i UID=%s",i,sprintUID(NULL,&recv[2]));
1252 }
1253 }
1254 Dbprintf("AFI Bruteforcing done.");
1255
1256 }
1257
1258 // Allows to directly send commands to the tag via the client
1259 void DirectTag15693Command(uint32_t datalen,uint32_t speed, uint32_t recv, uint8_t data[]) {
1260
1261 int recvlen=0;
1262 uint8_t *recvbuf=(uint8_t *)BigBuf;
1263 // UsbCommand n;
1264
1265 if (DEBUG) {
1266 Dbprintf("SEND");
1267 Dbhexdump(datalen,data,true);
1268 }
1269
1270 recvlen=SendDataTag(data,datalen,1,speed,(recv?&recvbuf:NULL));
1271
1272 if (recv) {
1273 // n.cmd=/* CMD_ISO_15693_COMMAND_DONE */ CMD_ACK;
1274 // n.arg[0]=recvlen>48?48:recvlen;
1275 // memcpy(n.d.asBytes, recvbuf, 48);
1276 LED_B_ON();
1277 cmd_send(CMD_ACK,recvlen>48?48:recvlen,0,0,recvbuf,48);
1278 // UsbSendPacket((uint8_t *)&n, sizeof(n));
1279 LED_B_OFF();
1280
1281 if (DEBUG) {
1282 Dbprintf("RECV");
1283 DbdecodeIso15693Answer(recvlen,recvbuf);
1284 Dbhexdump(recvlen,recvbuf,true);
1285 }
1286 }
1287
1288 }
1289
1290
1291
1292
1293 // --------------------------------------------------------------------
1294 // -- Misc & deprecated functions
1295 // --------------------------------------------------------------------
1296
1297 /*
1298
1299 // do not use; has a fix UID
1300 static void __attribute__((unused)) BuildSysInfoRequest(uint8_t *uid)
1301 {
1302 uint8_t cmd[12];
1303
1304 uint16_t crc;
1305 // If we set the Option_Flag in this request, the VICC will respond with the secuirty status of the block
1306 // followed by teh block data
1307 // one sub-carrier, inventory, 1 slot, fast rate
1308 cmd[0] = (1 << 5) | (1 << 1); // no SELECT bit
1309 // System Information command code
1310 cmd[1] = 0x2B;
1311 // UID may be optionally specified here
1312 // 64-bit UID
1313 cmd[2] = 0x32;
1314 cmd[3]= 0x4b;
1315 cmd[4] = 0x03;
1316 cmd[5] = 0x01;
1317 cmd[6] = 0x00;
1318 cmd[7] = 0x10;
1319 cmd[8] = 0x05;
1320 cmd[9]= 0xe0; // always e0 (not exactly unique)
1321 //Now the CRC
1322 crc = Crc(cmd, 10); // the crc needs to be calculated over 2 bytes
1323 cmd[10] = crc & 0xff;
1324 cmd[11] = crc >> 8;
1325
1326 CodeIso15693AsReader(cmd, sizeof(cmd));
1327 }
1328
1329
1330 // do not use; has a fix UID
1331 static void __attribute__((unused)) BuildReadMultiBlockRequest(uint8_t *uid)
1332 {
1333 uint8_t cmd[14];
1334
1335 uint16_t crc;
1336 // If we set the Option_Flag in this request, the VICC will respond with the secuirty status of the block
1337 // followed by teh block data
1338 // one sub-carrier, inventory, 1 slot, fast rate
1339 cmd[0] = (1 << 5) | (1 << 1); // no SELECT bit
1340 // READ Multi BLOCK command code
1341 cmd[1] = 0x23;
1342 // UID may be optionally specified here
1343 // 64-bit UID
1344 cmd[2] = 0x32;
1345 cmd[3]= 0x4b;
1346 cmd[4] = 0x03;
1347 cmd[5] = 0x01;
1348 cmd[6] = 0x00;
1349 cmd[7] = 0x10;
1350 cmd[8] = 0x05;
1351 cmd[9]= 0xe0; // always e0 (not exactly unique)
1352 // First Block number to read
1353 cmd[10] = 0x00;
1354 // Number of Blocks to read
1355 cmd[11] = 0x2f; // read quite a few
1356 //Now the CRC
1357 crc = Crc(cmd, 12); // the crc needs to be calculated over 2 bytes
1358 cmd[12] = crc & 0xff;
1359 cmd[13] = crc >> 8;
1360
1361 CodeIso15693AsReader(cmd, sizeof(cmd));
1362 }
1363
1364 // do not use; has a fix UID
1365 static void __attribute__((unused)) BuildArbitraryRequest(uint8_t *uid,uint8_t CmdCode)
1366 {
1367 uint8_t cmd[14];
1368
1369 uint16_t crc;
1370 // If we set the Option_Flag in this request, the VICC will respond with the secuirty status of the block
1371 // followed by teh block data
1372 // one sub-carrier, inventory, 1 slot, fast rate
1373 cmd[0] = (1 << 5) | (1 << 1); // no SELECT bit
1374 // READ BLOCK command code
1375 cmd[1] = CmdCode;
1376 // UID may be optionally specified here
1377 // 64-bit UID
1378 cmd[2] = 0x32;
1379 cmd[3]= 0x4b;
1380 cmd[4] = 0x03;
1381 cmd[5] = 0x01;
1382 cmd[6] = 0x00;
1383 cmd[7] = 0x10;
1384 cmd[8] = 0x05;
1385 cmd[9]= 0xe0; // always e0 (not exactly unique)
1386 // Parameter
1387 cmd[10] = 0x00;
1388 cmd[11] = 0x0a;
1389
1390 // cmd[12] = 0x00;
1391 // cmd[13] = 0x00; //Now the CRC
1392 crc = Crc(cmd, 12); // the crc needs to be calculated over 2 bytes
1393 cmd[12] = crc & 0xff;
1394 cmd[13] = crc >> 8;
1395
1396 CodeIso15693AsReader(cmd, sizeof(cmd));
1397 }
1398
1399 // do not use; has a fix UID
1400 static void __attribute__((unused)) BuildArbitraryCustomRequest(uint8_t uid[], uint8_t CmdCode)
1401 {
1402 uint8_t cmd[14];
1403
1404 uint16_t crc;
1405 // If we set the Option_Flag in this request, the VICC will respond with the secuirty status of the block
1406 // followed by teh block data
1407 // one sub-carrier, inventory, 1 slot, fast rate
1408 cmd[0] = (1 << 5) | (1 << 1); // no SELECT bit
1409 // READ BLOCK command code
1410 cmd[1] = CmdCode;
1411 // UID may be optionally specified here
1412 // 64-bit UID
1413 cmd[2] = 0x32;
1414 cmd[3]= 0x4b;
1415 cmd[4] = 0x03;
1416 cmd[5] = 0x01;
1417 cmd[6] = 0x00;
1418 cmd[7] = 0x10;
1419 cmd[8] = 0x05;
1420 cmd[9]= 0xe0; // always e0 (not exactly unique)
1421 // Parameter
1422 cmd[10] = 0x05; // for custom codes this must be manufcturer code
1423 cmd[11] = 0x00;
1424
1425 // cmd[12] = 0x00;
1426 // cmd[13] = 0x00; //Now the CRC
1427 crc = Crc(cmd, 12); // the crc needs to be calculated over 2 bytes
1428 cmd[12] = crc & 0xff;
1429 cmd[13] = crc >> 8;
1430
1431 CodeIso15693AsReader(cmd, sizeof(cmd));
1432 }
1433
1434
1435
1436
1437 */
1438
1439
Impressum, Datenschutz