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