]> git.zerfleddert.de Git - proxmark3-svn/blame - armsrc/iso15693.c
Unstable branch: ported iclass research from Pentura_Prox's previous proxmark implent...
[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{
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)) {
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;
f7e3ed82 302 uint8_t *dest = (uint8_t *)BigBuf;
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);
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)) {
f7e3ed82 317 int8_t b;
318 b = (int8_t)AT91C_BASE_SSC->SSC_RHR;
15c4dc5a 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) {
f7e3ed82 325 int8_t r;
15c4dc5a 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
f7e3ed82 338 dest[c++] = (uint8_t)r;
15c4dc5a 339
340 if(c >= 2000) {
341 break;
342 }
343 } else {
344 prev = b;
345 }
346
347 getNext = !getNext;
348 }
349 }
350
9455b51c 351 //////////////////////////////////////////
352 /////////// DEMODULATE ///////////////////
353 //////////////////////////////////////////
15c4dc5a 354
355 int i, j;
356 int max = 0, maxPos=0;
357
358 int skip = 4;
359
9455b51c 360 // if(GraphTraceLen < 1000) return; // THIS CHECKS FOR A BUFFER TO SMALL
15c4dc5a 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 }
9455b51c 373 // DbpString("SOF at %d, correlation %d", maxPos,max/(arraylen(FrameSOF)/skip));
15c4dc5a 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
9455b51c 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 }
15c4dc5a 419 }
9455b51c 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
15c4dc5a 425 }
9455b51c 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];
15c4dc5a 439 }
15c4dc5a 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
9455b51c 447
15c4dc5a 448// Now the GetISO15693 message from sniffing command
f7e3ed82 449static int GetIso15693AnswerFromSniff(uint8_t *receivedResponse, int maxLen, int *samples, int *elapsed)
15c4dc5a 450{
451 int c = 0;
f7e3ed82 452 uint8_t *dest = (uint8_t *)BigBuf;
15c4dc5a 453 int getNext = 0;
454
f7e3ed82 455 int8_t prev = 0;
15c4dc5a 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)) {
f7e3ed82 467 int8_t b;
468 b = (int8_t)AT91C_BASE_SSC->SSC_RHR;
15c4dc5a 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) {
f7e3ed82 475 int8_t r;
15c4dc5a 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
f7e3ed82 488 dest[c++] = (uint8_t)r;
15c4dc5a 489
490 if(c >= 20000) {
491 break;
492 }
493 } else {
494 prev = b;
495 }
496
497 getNext = !getNext;
498 }
499 }
500
9455b51c 501 //////////////////////////////////////////
502 /////////// DEMODULATE ///////////////////
503 //////////////////////////////////////////
15c4dc5a 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 {
9455b51c 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 }
15c4dc5a 569 }
9455b51c 570 if(mask != 0x01) {
571 DbpString("sniff: error, uneven octet! (discard extra bits!)");
572 /// DbpString(" mask=%02x", mask);
15c4dc5a 573 }
9455b51c 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];
15c4dc5a 587 }
15c4dc5a 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
9455b51c 594
595static void BuildIdentifyRequest(void);
15c4dc5a 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//-----------------------------------------------------------------------------
601void AcquireRawAdcSamplesIso15693(void)
602{
603 int c = 0;
f7e3ed82 604 uint8_t *dest = (uint8_t *)BigBuf;
15c4dc5a 605 int getNext = 0;
606
f7e3ed82 607 int8_t prev = 0;
15c4dc5a 608
7cc204bf 609 FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
15c4dc5a 610 BuildIdentifyRequest();
611
612 SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
613
614 // Give the tags time to energize
615 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
616 SpinDelay(100);
617
618 // Now send the command
619 FpgaSetupSsc();
620 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX);
621
622 c = 0;
623 for(;;) {
624 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
625 AT91C_BASE_SSC->SSC_THR = ToSend[c];
626 c++;
627 if(c == ToSendMax+3) {
628 break;
629 }
630 }
631 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
f7e3ed82 632 volatile uint32_t r = AT91C_BASE_SSC->SSC_RHR;
15c4dc5a 633 (void)r;
634 }
635 WDT_HIT();
636 }
637
638 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
639
640 c = 0;
641 getNext = FALSE;
642 for(;;) {
643 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
644 AT91C_BASE_SSC->SSC_THR = 0x43;
645 }
646 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
f7e3ed82 647 int8_t b;
648 b = (int8_t)AT91C_BASE_SSC->SSC_RHR;
15c4dc5a 649
9455b51c 650 // The samples are correlations against I and Q versions of the
651 // tone that the tag AM-modulates, so every other sample is I,
652 // every other is Q. We just want power, so abs(I) + abs(Q) is
653 // close to what we want.
654 if(getNext) {
655 int8_t r;
656
657 if(b < 0) {
658 r = -b;
659 } else {
660 r = b;
661 }
662 if(prev < 0) {
663 r -= prev;
664 } else {
665 r += prev;
666 }
667
668 dest[c++] = (uint8_t)r;
669
670 if(c >= 2000) {
671 break;
672 }
673 } else {
674 prev = b;
675 }
676
677 getNext = !getNext;
678 }
679 }
680}
681
682
683void RecordRawAdcSamplesIso15693(void)
684{
685 int c = 0;
686 uint8_t *dest = (uint8_t *)BigBuf;
687 int getNext = 0;
688
689 int8_t prev = 0;
690
7cc204bf 691 FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
9455b51c 692 // Setup SSC
693 FpgaSetupSsc();
694
695 // Start from off (no field generated)
696 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
697 SpinDelay(200);
698
699 SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
700
701 SpinDelay(100);
702
703 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
704
705 c = 0;
706 getNext = FALSE;
707 for(;;) {
708 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
709 AT91C_BASE_SSC->SSC_THR = 0x43;
710 }
711 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
712 int8_t b;
713 b = (int8_t)AT91C_BASE_SSC->SSC_RHR;
714
715 // The samples are correlations against I and Q versions of the
716 // tone that the tag AM-modulates, so every other sample is I,
717 // every other is Q. We just want power, so abs(I) + abs(Q) is
718 // close to what we want.
719 if(getNext) {
720 int8_t r;
721
722 if(b < 0) {
723 r = -b;
724 } else {
725 r = b;
726 }
727 if(prev < 0) {
728 r -= prev;
729 } else {
730 r += prev;
731 }
732
733 dest[c++] = (uint8_t)r;
734
735 if(c >= 7000) {
736 break;
737 }
738 } else {
739 prev = b;
740 }
741
742 getNext = !getNext;
743 WDT_HIT();
744 }
745 }
746 Dbprintf("fin record");
747}
748
749
750// Initialize the proxmark as iso15k reader
e6304bca 751// (this might produces glitches that confuse some tags
9455b51c 752void Iso15693InitReader() {
753 LED_A_ON();
754 LED_B_ON();
755 LED_C_OFF();
756 LED_D_OFF();
757
7cc204bf 758 FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
9455b51c 759 // Setup SSC
e6304bca 760 // FpgaSetupSsc();
9455b51c 761
762 // Start from off (no field generated)
763 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
e6304bca 764 SpinDelay(10);
9455b51c 765
766 SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
767 FpgaSetupSsc();
768
769 // Give the tags time to energize
770 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
e6304bca 771 SpinDelay(250);
9455b51c 772
773 LED_A_ON();
774 LED_B_OFF();
775 LED_C_OFF();
776 LED_D_OFF();
777}
778
779///////////////////////////////////////////////////////////////////////
780// ISO 15693 Part 3 - Air Interface
781// This section basicly contains transmission and receiving of bits
782///////////////////////////////////////////////////////////////////////
783
784// Encode (into the ToSend buffers) an identify request, which is the first
785// thing that you must send to a tag to get a response.
786static void BuildIdentifyRequest(void)
787{
788 uint8_t cmd[5];
789
790 uint16_t crc;
791 // one sub-carrier, inventory, 1 slot, fast rate
792 // AFI is at bit 5 (1<<4) when doing an INVENTORY
793 cmd[0] = (1 << 2) | (1 << 5) | (1 << 1);
794 // inventory command code
795 cmd[1] = 0x01;
796 // no mask
797 cmd[2] = 0x00;
798 //Now the CRC
799 crc = Crc(cmd, 3);
800 cmd[3] = crc & 0xff;
801 cmd[4] = crc >> 8;
802
803 CodeIso15693AsReader(cmd, sizeof(cmd));
804}
805
806// uid is in transmission order (which is reverse of display order)
807static void BuildReadBlockRequest(uint8_t *uid, uint8_t blockNumber )
808{
809 uint8_t cmd[13];
810
811 uint16_t crc;
812 // If we set the Option_Flag in this request, the VICC will respond with the secuirty status of the block
813 // followed by teh block data
814 // one sub-carrier, inventory, 1 slot, fast rate
815 cmd[0] = (1 << 6)| (1 << 5) | (1 << 1); // no SELECT bit, ADDR bit, OPTION bit
816 // READ BLOCK command code
817 cmd[1] = 0x20;
818 // UID may be optionally specified here
819 // 64-bit UID
820 cmd[2] = uid[0];
821 cmd[3] = uid[1];
822 cmd[4] = uid[2];
823 cmd[5] = uid[3];
824 cmd[6] = uid[4];
825 cmd[7] = uid[5];
826 cmd[8] = uid[6];
827 cmd[9] = uid[7]; // 0xe0; // always e0 (not exactly unique)
828 // Block number to read
829 cmd[10] = blockNumber;//0x00;
830 //Now the CRC
831 crc = Crc(cmd, 11); // the crc needs to be calculated over 12 bytes
832 cmd[11] = crc & 0xff;
833 cmd[12] = crc >> 8;
834
835 CodeIso15693AsReader(cmd, sizeof(cmd));
836}
837
838// Now the VICC>VCD responses when we are simulating a tag
839 static void BuildInventoryResponse(void)
840{
841 uint8_t cmd[12];
842
843 uint16_t crc;
844 // one sub-carrier, inventory, 1 slot, fast rate
845 // AFI is at bit 5 (1<<4) when doing an INVENTORY
846 cmd[0] = 0; //(1 << 2) | (1 << 5) | (1 << 1);
847 cmd[1] = 0;
848 // 64-bit UID
849 cmd[2] = 0x32;
850 cmd[3]= 0x4b;
851 cmd[4] = 0x03;
852 cmd[5] = 0x01;
853 cmd[6] = 0x00;
854 cmd[7] = 0x10;
855 cmd[8] = 0x05;
856 cmd[9]= 0xe0;
857 //Now the CRC
858 crc = Crc(cmd, 10);
859 cmd[10] = crc & 0xff;
860 cmd[11] = crc >> 8;
861
862 CodeIso15693AsReader(cmd, sizeof(cmd));
863}
864
e6304bca 865// Universal Method for sending to and recv bytes from a tag
9455b51c 866// init ... should we initialize the reader?
867// speed ... 0 low speed, 1 hi speed
868// **recv will return you a pointer to the received data
869// If you do not need the answer use NULL for *recv[]
870// return: lenght of received data
871int SendDataTag(uint8_t *send, int sendlen, int init, int speed, uint8_t **recv) {
872
873 int samples = 0;
874 int tsamples = 0;
875 int wait = 0;
876 int elapsed = 0;
877
878 LED_A_ON();
879 LED_B_ON();
880 LED_C_OFF();
881 LED_D_OFF();
882
883 int answerLen=0;
884 uint8_t *answer = (((uint8_t *)BigBuf) + 3660);
885 if (recv!=NULL) memset(BigBuf + 3660, 0, 100);
886
887 if (init) Iso15693InitReader();
888
889 if (!speed) {
890 // low speed (1 out of 256)
891 CodeIso15693AsReader256(send, sendlen);
892 } else {
893 // high speed (1 out of 4)
894 CodeIso15693AsReader(send, sendlen);
895 }
896
897 LED_A_ON();
898 LED_B_OFF();
899
900 TransmitTo15693Tag(ToSend,ToSendMax,&tsamples, &wait);
901 // Now wait for a response
902 if (recv!=NULL) {
903 LED_A_OFF();
904 LED_B_ON();
905 answerLen = GetIso15693AnswerFromTag(answer, 100, &samples, &elapsed) ;
906 *recv=answer;
907 }
908
909 LED_A_OFF();
910 LED_B_OFF();
911 LED_C_OFF();
912 LED_D_OFF();
913
914 return answerLen;
915}
15c4dc5a 916
15c4dc5a 917
9455b51c 918// --------------------------------------------------------------------
919// Debug Functions
920// --------------------------------------------------------------------
15c4dc5a 921
9455b51c 922// Decodes a message from a tag and displays its metadata and content
923#define DBD15STATLEN 48
924void DbdecodeIso15693Answer(int len, uint8_t *d) {
925 char status[DBD15STATLEN+1]={0};
926 uint16_t crc;
927
928 if (len>3) {
929 if (d[0]&(1<<3))
930 strncat(status,"ProtExt ",DBD15STATLEN);
931 if (d[0]&1) {
932 // error
933 strncat(status,"Error ",DBD15STATLEN);
934 switch (d[1]) {
935 case 0x01:
936 strncat(status,"01:notSupp",DBD15STATLEN);
15c4dc5a 937 break;
9455b51c 938 case 0x02:
939 strncat(status,"02:notRecog",DBD15STATLEN);
940 break;
941 case 0x03:
942 strncat(status,"03:optNotSupp",DBD15STATLEN);
943 break;
944 case 0x0f:
945 strncat(status,"0f:noInfo",DBD15STATLEN);
946 break;
947 case 0x10:
948 strncat(status,"10:dontExist",DBD15STATLEN);
949 break;
950 case 0x11:
951 strncat(status,"11:lockAgain",DBD15STATLEN);
952 break;
953 case 0x12:
954 strncat(status,"12:locked",DBD15STATLEN);
955 break;
956 case 0x13:
957 strncat(status,"13:progErr",DBD15STATLEN);
958 break;
959 case 0x14:
960 strncat(status,"14:lockErr",DBD15STATLEN);
961 break;
962 default:
963 strncat(status,"unknownErr",DBD15STATLEN);
15c4dc5a 964 }
9455b51c 965 strncat(status," ",DBD15STATLEN);
966 } else {
967 strncat(status,"NoErr ",DBD15STATLEN);
15c4dc5a 968 }
9455b51c 969
970 crc=Crc(d,len-2);
971 if ( (( crc & 0xff ) == d[len-2]) && (( crc >> 8 ) == d[len-1]) )
972 strncat(status,"CrcOK",DBD15STATLEN);
973 else
974 strncat(status,"CrcFail!",DBD15STATLEN);
975
976 Dbprintf("%s",status);
15c4dc5a 977 }
978}
979
9455b51c 980
981
982///////////////////////////////////////////////////////////////////////
983// Functions called via USB/Client
984///////////////////////////////////////////////////////////////////////
985
986void SetDebugIso15693(uint32_t debug) {
987 DEBUG=debug;
988 Dbprintf("Iso15693 Debug is now %s",DEBUG?"on":"off");
989 return;
990}
991
992
993
15c4dc5a 994//-----------------------------------------------------------------------------
995// Simulate an ISO15693 reader, perform anti-collision and then attempt to read a sector
996// all demodulation performed in arm rather than host. - greg
997//-----------------------------------------------------------------------------
f7e3ed82 998void ReaderIso15693(uint32_t parameter)
15c4dc5a 999{
1000 LED_A_ON();
1001 LED_B_ON();
1002 LED_C_OFF();
1003 LED_D_OFF();
1004
1005//DbpString(parameter);
1006
f7e3ed82 1007 //uint8_t *answer0 = (((uint8_t *)BigBuf) + 3560); // allow 100 bytes per reponse (way too much)
1008 uint8_t *answer1 = (((uint8_t *)BigBuf) + 3660); //
1009 uint8_t *answer2 = (((uint8_t *)BigBuf) + 3760);
1010 uint8_t *answer3 = (((uint8_t *)BigBuf) + 3860);
1011 //uint8_t *TagUID= (((uint8_t *)BigBuf) + 3960); // where we hold the uid for hi15reader
15c4dc5a 1012// int answerLen0 = 0;
1013 int answerLen1 = 0;
1014 int answerLen2 = 0;
1015 int answerLen3 = 0;
9455b51c 1016 int i=0; // counter
15c4dc5a 1017
1018 // Blank arrays
1019 memset(BigBuf + 3660, 0, 300);
1020
7cc204bf 1021 FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
15c4dc5a 1022 // Setup SSC
1023 FpgaSetupSsc();
1024
1025 // Start from off (no field generated)
1026 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
1027 SpinDelay(200);
1028
1029 SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
1030 FpgaSetupSsc();
1031
1032 // Give the tags time to energize
1033 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
1034 SpinDelay(200);
1035
1036 LED_A_ON();
1037 LED_B_OFF();
1038 LED_C_OFF();
1039 LED_D_OFF();
1040
1041 int samples = 0;
1042 int tsamples = 0;
1043 int wait = 0;
1044 int elapsed = 0;
1045
1046 // FIRST WE RUN AN INVENTORY TO GET THE TAG UID
1047 // THIS MEANS WE CAN PRE-BUILD REQUESTS TO SAVE CPU TIME
3803d529 1048 uint8_t TagUID[8] = {0, 0, 0, 0, 0, 0, 0, 0}; // where we hold the uid for hi15reader
15c4dc5a 1049
1050// BuildIdentifyRequest();
1051// //TransmitTo15693Tag(ToSend,ToSendMax+3,&tsamples, &wait);
1052// TransmitTo15693Tag(ToSend,ToSendMax,&tsamples, &wait); // No longer ToSendMax+3
1053// // Now wait for a response
1054// responseLen0 = GetIso15693AnswerFromTag(receivedAnswer0, 100, &samples, &elapsed) ;
1055// if (responseLen0 >=12) // we should do a better check than this
1056// {
1057// // really we should check it is a valid mesg
1058// // but for now just grab what we think is the uid
1059// TagUID[0] = receivedAnswer0[2];
1060// TagUID[1] = receivedAnswer0[3];
1061// TagUID[2] = receivedAnswer0[4];
1062// TagUID[3] = receivedAnswer0[5];
1063// TagUID[4] = receivedAnswer0[6];
1064// TagUID[5] = receivedAnswer0[7];
1065// TagUID[6] = receivedAnswer0[8]; // IC Manufacturer code
1066// DbpIntegers(TagUID[6],TagUID[5],TagUID[4]);
1067//}
1068
1069 // Now send the IDENTIFY command
1070 BuildIdentifyRequest();
1071 //TransmitTo15693Tag(ToSend,ToSendMax+3,&tsamples, &wait);
1072 TransmitTo15693Tag(ToSend,ToSendMax,&tsamples, &wait); // No longer ToSendMax+3
1073 // Now wait for a response
1074 answerLen1 = GetIso15693AnswerFromTag(answer1, 100, &samples, &elapsed) ;
1075
1076 if (answerLen1 >=12) // we should do a better check than this
1077 {
1078
1079 TagUID[0] = answer1[2];
1080 TagUID[1] = answer1[3];
1081 TagUID[2] = answer1[4];
1082 TagUID[3] = answer1[5];
1083 TagUID[4] = answer1[6];
1084 TagUID[5] = answer1[7];
1085 TagUID[6] = answer1[8]; // IC Manufacturer code
9455b51c 1086 TagUID[7] = answer1[9]; // always E0
15c4dc5a 1087
1088 // Now send the SELECT command
9455b51c 1089 // since the SELECT command is optional, we should not rely on it.
1090//// BuildSelectRequest(TagUID);
1091// TransmitTo15693Tag(ToSend,ToSendMax,&tsamples, &wait); // No longer ToSendMax+3
15c4dc5a 1092 // Now wait for a response
9455b51c 1093/// answerLen2 = GetIso15693AnswerFromTag(answer2, 100, &samples, &elapsed);
15c4dc5a 1094
1095 // Now send the MULTI READ command
1096// BuildArbitraryRequest(*TagUID,parameter);
9455b51c 1097/// BuildArbitraryCustomRequest(TagUID,parameter);
15c4dc5a 1098// BuildReadBlockRequest(*TagUID,parameter);
1099// BuildSysInfoRequest(*TagUID);
1100 //TransmitTo15693Tag(ToSend,ToSendMax+3,&tsamples, &wait);
9455b51c 1101/// TransmitTo15693Tag(ToSend,ToSendMax,&tsamples, &wait); // No longer ToSendMax+3
15c4dc5a 1102 // Now wait for a response
9455b51c 1103/// answerLen3 = GetIso15693AnswerFromTag(answer3, 100, &samples, &elapsed) ;
15c4dc5a 1104
1105 }
1106
9455b51c 1107 Dbprintf("%d octets read from IDENTIFY request:", answerLen1);
1108 DbdecodeIso15693Answer(answerLen1,answer1);
d19929cb 1109 Dbhexdump(answerLen1,answer1,true);
9455b51c 1110
1111 // UID is reverse
1112 if (answerLen1>=12)
1113 //Dbprintf("UID = %*D",8,TagUID," ");
1114 Dbprintf("UID = %02hX%02hX%02hX%02hX%02hX%02hX%02hX%02hX",TagUID[7],TagUID[6],TagUID[5],
1115 TagUID[4],TagUID[3],TagUID[2],TagUID[1],TagUID[0]);
1116
1117
1118 Dbprintf("%d octets read from SELECT request:", answerLen2);
1119 DbdecodeIso15693Answer(answerLen2,answer2);
d19929cb 1120 Dbhexdump(answerLen2,answer2,true);
9455b51c 1121
1122 Dbprintf("%d octets read from XXX request:", answerLen3);
1123 DbdecodeIso15693Answer(answerLen3,answer3);
d19929cb 1124 Dbhexdump(answerLen3,answer3,true);
9455b51c 1125
1126
1127 // read all pages
1128 if (answerLen1>=12 && DEBUG) {
1129 i=0;
1130 while (i<32) { // sanity check, assume max 32 pages
1131 BuildReadBlockRequest(TagUID,i);
1132 TransmitTo15693Tag(ToSend,ToSendMax,&tsamples, &wait);
1133 answerLen2 = GetIso15693AnswerFromTag(answer2, 100, &samples, &elapsed);
1134 if (answerLen2>0) {
1135 Dbprintf("READ SINGLE BLOCK %d returned %d octets:",i,answerLen2);
1136 DbdecodeIso15693Answer(answerLen2,answer2);
d19929cb 1137 Dbhexdump(answerLen2,answer2,true);
9455b51c 1138 if ( *((uint32_t*) answer2) == 0x07160101 ) break; // exit on NoPageErr
1139 }
1140 i++;
1141 }
1142 }
15c4dc5a 1143
1144// str2[0]=0;
1145// for(i = 0; i < responseLen3; i++) {
1146// itoa(str1,receivedAnswer3[i]);
9455b51c 1147// strncat(str2,str1,8);
15c4dc5a 1148// }
1149// DbpString(str2);
1150
1151 LED_A_OFF();
1152 LED_B_OFF();
1153 LED_C_OFF();
1154 LED_D_OFF();
1155}
1156
15c4dc5a 1157// Simulate an ISO15693 TAG, perform anti-collision and then print any reader commands
1158// all demodulation performed in arm rather than host. - greg
f7e3ed82 1159void SimTagIso15693(uint32_t parameter)
15c4dc5a 1160{
1161 LED_A_ON();
1162 LED_B_ON();
1163 LED_C_OFF();
1164 LED_D_OFF();
1165
f7e3ed82 1166 uint8_t *answer1 = (((uint8_t *)BigBuf) + 3660); //
15c4dc5a 1167 int answerLen1 = 0;
1168
1169 // Blank arrays
1170 memset(answer1, 0, 100);
1171
7cc204bf 1172 FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
15c4dc5a 1173 // Setup SSC
1174 FpgaSetupSsc();
1175
1176 // Start from off (no field generated)
1177 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
1178 SpinDelay(200);
1179
1180 SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
1181 FpgaSetupSsc();
1182
1183 // Give the tags time to energize
1184// FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR); // NO GOOD FOR SIM TAG!!!!
1185 SpinDelay(200);
1186
1187 LED_A_OFF();
1188 LED_B_OFF();
1189 LED_C_ON();
1190 LED_D_OFF();
1191
1192 int samples = 0;
1193 int tsamples = 0;
1194 int wait = 0;
1195 int elapsed = 0;
1196
1197 answerLen1 = GetIso15693AnswerFromSniff(answer1, 100, &samples, &elapsed) ;
1198
1199 if (answerLen1 >=1) // we should do a better check than this
1200 {
1201 // Build a suitable reponse to the reader INVENTORY cocmmand
1202 BuildInventoryResponse();
1203 TransmitTo15693Reader(ToSend,ToSendMax, &tsamples, &wait);
1204 }
1205
1206 Dbprintf("%d octets read from reader command: %x %x %x %x %x %x %x %x %x", answerLen1,
1207 answer1[0], answer1[1], answer1[2],
1208 answer1[3], answer1[4], answer1[5],
1209 answer1[6], answer1[7], answer1[8]);
1210
1211 LED_A_OFF();
1212 LED_B_OFF();
1213 LED_C_OFF();
1214 LED_D_OFF();
1215}
9455b51c 1216
1217
1218// Since there is no standardized way of reading the AFI out of a tag, we will brute force it
1219// (some manufactures offer a way to read the AFI, though)
1220void BruteforceIso15693Afi(uint32_t speed)
1221{
1222 uint8_t data[20];
1223 uint8_t *recv=data;
1224 int datalen=0, recvlen=0;
1225
1226 Iso15693InitReader();
1227
1228 // first without AFI
1229 // Tags should respond wihtout AFI and with AFI=0 even when AFI is active
1230
1231 data[0]=ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH |
1232 ISO15_REQ_INVENTORY | ISO15_REQINV_SLOT1;
1233 data[1]=ISO15_CMD_INVENTORY;
1234 data[2]=0; // mask length
1235 datalen=AddCrc(data,3);
1236 recvlen=SendDataTag(data,datalen,0,speed,&recv);
1237 WDT_HIT();
1238 if (recvlen>=12) {
1239 Dbprintf("NoAFI UID=%s",sprintUID(NULL,&recv[2]));
1240 }
1241
1242 // now with AFI
1243
1244 data[0]=ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH |
1245 ISO15_REQ_INVENTORY | ISO15_REQINV_AFI | ISO15_REQINV_SLOT1;
1246 data[1]=ISO15_CMD_INVENTORY;
1247 data[2]=0; // AFI
1248 data[3]=0; // mask length
1249
1250 for (int i=0;i<256;i++) {
1251 data[2]=i & 0xFF;
1252 datalen=AddCrc(data,4);
1253 recvlen=SendDataTag(data,datalen,0,speed,&recv);
1254 WDT_HIT();
1255 if (recvlen>=12) {
1256 Dbprintf("AFI=%i UID=%s",i,sprintUID(NULL,&recv[2]));
1257 }
1258 }
1259 Dbprintf("AFI Bruteforcing done.");
1260
1261}
1262
1263// Allows to directly send commands to the tag via the client
1264void DirectTag15693Command(uint32_t datalen,uint32_t speed, uint32_t recv, uint8_t data[]) {
1265
1266 int recvlen=0;
1267 uint8_t *recvbuf=(uint8_t *)BigBuf;
902cb3c0 1268// UsbCommand n;
9455b51c 1269
1270 if (DEBUG) {
1271 Dbprintf("SEND");
d19929cb 1272 Dbhexdump(datalen,data,true);
9455b51c 1273 }
1274
1275 recvlen=SendDataTag(data,datalen,1,speed,(recv?&recvbuf:NULL));
1276
1277 if (recv) {
902cb3c0 1278// n.cmd=/* CMD_ISO_15693_COMMAND_DONE */ CMD_ACK;
1279// n.arg[0]=recvlen>48?48:recvlen;
1280// memcpy(n.d.asBytes, recvbuf, 48);
9455b51c 1281 LED_B_ON();
902cb3c0 1282 cmd_send(CMD_ACK,recvlen>48?48:recvlen,0,0,recvbuf,48);
1283// UsbSendPacket((uint8_t *)&n, sizeof(n));
9455b51c 1284 LED_B_OFF();
1285
1286 if (DEBUG) {
1287 Dbprintf("RECV");
1288 DbdecodeIso15693Answer(recvlen,recvbuf);
d19929cb 1289 Dbhexdump(recvlen,recvbuf,true);
9455b51c 1290 }
1291 }
1292
1293}
1294
1295
1296
1297
1298// --------------------------------------------------------------------
1299// -- Misc & deprecated functions
1300// --------------------------------------------------------------------
1301
e6304bca 1302/*
9455b51c 1303
1304// do not use; has a fix UID
1305static void __attribute__((unused)) BuildSysInfoRequest(uint8_t *uid)
1306{
1307 uint8_t cmd[12];
1308
1309 uint16_t crc;
1310 // If we set the Option_Flag in this request, the VICC will respond with the secuirty status of the block
1311 // followed by teh block data
1312 // one sub-carrier, inventory, 1 slot, fast rate
1313 cmd[0] = (1 << 5) | (1 << 1); // no SELECT bit
1314 // System Information command code
1315 cmd[1] = 0x2B;
1316 // UID may be optionally specified here
1317 // 64-bit UID
1318 cmd[2] = 0x32;
1319 cmd[3]= 0x4b;
1320 cmd[4] = 0x03;
1321 cmd[5] = 0x01;
1322 cmd[6] = 0x00;
1323 cmd[7] = 0x10;
1324 cmd[8] = 0x05;
1325 cmd[9]= 0xe0; // always e0 (not exactly unique)
1326 //Now the CRC
1327 crc = Crc(cmd, 10); // the crc needs to be calculated over 2 bytes
1328 cmd[10] = crc & 0xff;
1329 cmd[11] = crc >> 8;
1330
1331 CodeIso15693AsReader(cmd, sizeof(cmd));
1332}
1333
9455b51c 1334
1335// do not use; has a fix UID
1336static void __attribute__((unused)) BuildReadMultiBlockRequest(uint8_t *uid)
1337{
1338 uint8_t cmd[14];
1339
1340 uint16_t crc;
1341 // If we set the Option_Flag in this request, the VICC will respond with the secuirty status of the block
1342 // followed by teh block data
1343 // one sub-carrier, inventory, 1 slot, fast rate
1344 cmd[0] = (1 << 5) | (1 << 1); // no SELECT bit
1345 // READ Multi BLOCK command code
1346 cmd[1] = 0x23;
1347 // UID may be optionally specified here
1348 // 64-bit UID
1349 cmd[2] = 0x32;
1350 cmd[3]= 0x4b;
1351 cmd[4] = 0x03;
1352 cmd[5] = 0x01;
1353 cmd[6] = 0x00;
1354 cmd[7] = 0x10;
1355 cmd[8] = 0x05;
1356 cmd[9]= 0xe0; // always e0 (not exactly unique)
1357 // First Block number to read
1358 cmd[10] = 0x00;
1359 // Number of Blocks to read
1360 cmd[11] = 0x2f; // read quite a few
1361 //Now the CRC
1362 crc = Crc(cmd, 12); // the crc needs to be calculated over 2 bytes
1363 cmd[12] = crc & 0xff;
1364 cmd[13] = crc >> 8;
1365
1366 CodeIso15693AsReader(cmd, sizeof(cmd));
1367}
1368
1369// do not use; has a fix UID
1370static void __attribute__((unused)) BuildArbitraryRequest(uint8_t *uid,uint8_t CmdCode)
1371{
1372 uint8_t cmd[14];
1373
1374 uint16_t crc;
1375 // If we set the Option_Flag in this request, the VICC will respond with the secuirty status of the block
1376 // followed by teh block data
1377 // one sub-carrier, inventory, 1 slot, fast rate
1378 cmd[0] = (1 << 5) | (1 << 1); // no SELECT bit
1379 // READ BLOCK command code
1380 cmd[1] = CmdCode;
1381 // UID may be optionally specified here
1382 // 64-bit UID
1383 cmd[2] = 0x32;
1384 cmd[3]= 0x4b;
1385 cmd[4] = 0x03;
1386 cmd[5] = 0x01;
1387 cmd[6] = 0x00;
1388 cmd[7] = 0x10;
1389 cmd[8] = 0x05;
1390 cmd[9]= 0xe0; // always e0 (not exactly unique)
1391 // Parameter
1392 cmd[10] = 0x00;
1393 cmd[11] = 0x0a;
1394
1395// cmd[12] = 0x00;
1396// cmd[13] = 0x00; //Now the CRC
1397 crc = Crc(cmd, 12); // the crc needs to be calculated over 2 bytes
1398 cmd[12] = crc & 0xff;
1399 cmd[13] = crc >> 8;
1400
1401 CodeIso15693AsReader(cmd, sizeof(cmd));
1402}
1403
1404// do not use; has a fix UID
1405static void __attribute__((unused)) BuildArbitraryCustomRequest(uint8_t uid[], uint8_t CmdCode)
1406{
1407 uint8_t cmd[14];
1408
1409 uint16_t crc;
1410 // If we set the Option_Flag in this request, the VICC will respond with the secuirty status of the block
1411 // followed by teh block data
1412 // one sub-carrier, inventory, 1 slot, fast rate
1413 cmd[0] = (1 << 5) | (1 << 1); // no SELECT bit
1414 // READ BLOCK command code
1415 cmd[1] = CmdCode;
1416 // UID may be optionally specified here
1417 // 64-bit UID
1418 cmd[2] = 0x32;
1419 cmd[3]= 0x4b;
1420 cmd[4] = 0x03;
1421 cmd[5] = 0x01;
1422 cmd[6] = 0x00;
1423 cmd[7] = 0x10;
1424 cmd[8] = 0x05;
1425 cmd[9]= 0xe0; // always e0 (not exactly unique)
1426 // Parameter
1427 cmd[10] = 0x05; // for custom codes this must be manufcturer code
1428 cmd[11] = 0x00;
1429
1430// cmd[12] = 0x00;
1431// cmd[13] = 0x00; //Now the CRC
1432 crc = Crc(cmd, 12); // the crc needs to be calculated over 2 bytes
1433 cmd[12] = crc & 0xff;
1434 cmd[13] = crc >> 8;
1435
1436 CodeIso15693AsReader(cmd, sizeof(cmd));
1437}
1438
1439
1440
1441
e6304bca 1442*/
9455b51c 1443
1444
Impressum, Datenschutz