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