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