]> git.zerfleddert.de Git - proxmark3-svn/blame_incremental - armsrc/iso15693.c
Add 'hf 15 csetuid' command to set UID on ISO15693 Magic tags (#842)
[proxmark3-svn] / armsrc / iso15693.c
... / ...
CommitLineData
1//-----------------------------------------------------------------------------
2// Jonathan Westhues, split Nov 2006
3// Modified by Greg Jones, Jan 2009
4// Modified by Adrian Dabrowski "atrox", Mar-Sept 2010,Oct 2011
5// Modified by piwi, Oct 2018
6//
7// This code is licensed to you under the terms of the GNU GPL, version 2 or,
8// at your option, any later version. See the LICENSE.txt file for the text of
9// the license.
10//-----------------------------------------------------------------------------
11// Routines to support ISO 15693. This includes both the reader software and
12// the `fake tag' modes.
13//-----------------------------------------------------------------------------
14
15// The ISO 15693 describes two transmission modes from reader to tag, and four
16// transmission modes from tag to reader. As of Oct 2018 this code supports
17// both reader modes and the high speed variant with one subcarrier from card to reader.
18// As long as the card fully support ISO 15693 this is no problem, since the
19// reader chooses both data rates, but some non-standard tags do not.
20// For card simulation, the code supports both high and low speed modes with one subcarrier.
21//
22// VCD (reader) -> VICC (tag)
23// 1 out of 256:
24// data rate: 1,66 kbit/s (fc/8192)
25// used for long range
26// 1 out of 4:
27// data rate: 26,48 kbit/s (fc/512)
28// used for short range, high speed
29//
30// VICC (tag) -> VCD (reader)
31// Modulation:
32// ASK / one subcarrier (423,75 khz)
33// FSK / two subcarriers (423,75 khz && 484,28 khz)
34// Data Rates / Modes:
35// low ASK: 6,62 kbit/s
36// low FSK: 6.67 kbit/s
37// high ASK: 26,48 kbit/s
38// high FSK: 26,69 kbit/s
39//-----------------------------------------------------------------------------
40
41
42// Random Remarks:
43// *) UID is always used "transmission order" (LSB), which is reverse to display order
44
45// TODO / BUGS / ISSUES:
46// *) signal decoding is unable to detect collisions.
47// *) add anti-collision support for inventory-commands
48// *) read security status of a block
49// *) sniffing and simulation do not support two subcarrier modes.
50// *) remove or refactor code under "deprecated"
51// *) document all the functions
52
53#include "iso15693.h"
54
55#include "proxmark3.h"
56#include "util.h"
57#include "apps.h"
58#include "string.h"
59#include "iso15693tools.h"
60#include "protocols.h"
61#include "cmd.h"
62#include "BigBuf.h"
63#include "fpgaloader.h"
64
65#define arraylen(x) (sizeof(x)/sizeof((x)[0]))
66
67static int DEBUG = 0;
68
69///////////////////////////////////////////////////////////////////////
70// ISO 15693 Part 2 - Air Interface
71// This section basicly contains transmission and receiving of bits
72///////////////////////////////////////////////////////////////////////
73
74#define Crc(data,datalen) Iso15693Crc(data,datalen)
75#define AddCrc(data,datalen) Iso15693AddCrc(data,datalen)
76#define sprintUID(target,uid) Iso15693sprintUID(target,uid)
77
78// buffers
79#define ISO15693_DMA_BUFFER_SIZE 2048 // must be a power of 2
80#define ISO15693_MAX_RESPONSE_LENGTH 36 // allows read single block with the maximum block size of 256bits. Read multiple blocks not supported yet
81#define ISO15693_MAX_COMMAND_LENGTH 45 // allows write single block with the maximum block size of 256bits. Write multiple blocks not supported yet
82
83// timing. Delays in SSP_CLK ticks.
84// SSP_CLK runs at 13,56MHz / 32 = 423.75kHz when simulating a tag
85#define DELAY_READER_TO_ARM_SIM 8
86#define DELAY_ARM_TO_READER_SIM 1
87#define DELAY_ISO15693_VCD_TO_VICC_SIM 132 // 132/423.75kHz = 311.5us from end of command EOF to start of tag response
88//SSP_CLK runs at 13.56MHz / 4 = 3,39MHz when acting as reader
89#define DELAY_ISO15693_VCD_TO_VICC_READER 1056 // 1056/3,39MHz = 311.5us from end of command EOF to start of tag response
90#define DELAY_ISO15693_VICC_TO_VCD_READER 1017 // 1017/3.39MHz = 300us between end of tag response and next reader command
91
92// ---------------------------
93// Signal Processing
94// ---------------------------
95
96// prepare data using "1 out of 4" code for later transmission
97// resulting data rate is 26.48 kbit/s (fc/512)
98// cmd ... data
99// n ... length of data
100static void CodeIso15693AsReader(uint8_t *cmd, int n)
101{
102 int i, j;
103
104 ToSendReset();
105
106 // Give it a bit of slack at the beginning
107 for(i = 0; i < 24; i++) {
108 ToSendStuffBit(1);
109 }
110
111 // SOF for 1of4
112 ToSendStuffBit(0);
113 ToSendStuffBit(1);
114 ToSendStuffBit(1);
115 ToSendStuffBit(1);
116 ToSendStuffBit(1);
117 ToSendStuffBit(0);
118 ToSendStuffBit(1);
119 ToSendStuffBit(1);
120 for(i = 0; i < n; i++) {
121 for(j = 0; j < 8; j += 2) {
122 int these = (cmd[i] >> j) & 3;
123 switch(these) {
124 case 0:
125 ToSendStuffBit(1);
126 ToSendStuffBit(0);
127 ToSendStuffBit(1);
128 ToSendStuffBit(1);
129 ToSendStuffBit(1);
130 ToSendStuffBit(1);
131 ToSendStuffBit(1);
132 ToSendStuffBit(1);
133 break;
134 case 1:
135 ToSendStuffBit(1);
136 ToSendStuffBit(1);
137 ToSendStuffBit(1);
138 ToSendStuffBit(0);
139 ToSendStuffBit(1);
140 ToSendStuffBit(1);
141 ToSendStuffBit(1);
142 ToSendStuffBit(1);
143 break;
144 case 2:
145 ToSendStuffBit(1);
146 ToSendStuffBit(1);
147 ToSendStuffBit(1);
148 ToSendStuffBit(1);
149 ToSendStuffBit(1);
150 ToSendStuffBit(0);
151 ToSendStuffBit(1);
152 ToSendStuffBit(1);
153 break;
154 case 3:
155 ToSendStuffBit(1);
156 ToSendStuffBit(1);
157 ToSendStuffBit(1);
158 ToSendStuffBit(1);
159 ToSendStuffBit(1);
160 ToSendStuffBit(1);
161 ToSendStuffBit(1);
162 ToSendStuffBit(0);
163 break;
164 }
165 }
166 }
167 // EOF
168 ToSendStuffBit(1);
169 ToSendStuffBit(1);
170 ToSendStuffBit(0);
171 ToSendStuffBit(1);
172
173 // Fill remainder of last byte with 1
174 for(i = 0; i < 4; i++) {
175 ToSendStuffBit(1);
176 }
177
178 ToSendMax++;
179}
180
181// encode data using "1 out of 256" scheme
182// data rate is 1,66 kbit/s (fc/8192)
183// is designed for more robust communication over longer distances
184static void CodeIso15693AsReader256(uint8_t *cmd, int n)
185{
186 int i, j;
187
188 ToSendReset();
189
190 // Give it a bit of slack at the beginning
191 for(i = 0; i < 24; i++) {
192 ToSendStuffBit(1);
193 }
194
195 // SOF for 1of256
196 ToSendStuffBit(0);
197 ToSendStuffBit(1);
198 ToSendStuffBit(1);
199 ToSendStuffBit(1);
200 ToSendStuffBit(1);
201 ToSendStuffBit(1);
202 ToSendStuffBit(1);
203 ToSendStuffBit(0);
204
205 for(i = 0; i < n; i++) {
206 for (j = 0; j<=255; j++) {
207 if (cmd[i]==j) {
208 ToSendStuffBit(1);
209 ToSendStuffBit(0);
210 } else {
211 ToSendStuffBit(1);
212 ToSendStuffBit(1);
213 }
214 }
215 }
216 // EOF
217 ToSendStuffBit(1);
218 ToSendStuffBit(1);
219 ToSendStuffBit(0);
220 ToSendStuffBit(1);
221
222 // Fill remainder of last byte with 1
223 for(i = 0; i < 4; i++) {
224 ToSendStuffBit(1);
225 }
226
227 ToSendMax++;
228}
229
230
231static void CodeIso15693AsTag(uint8_t *cmd, int n)
232{
233 ToSendReset();
234
235 // SOF
236 ToSendStuffBit(0);
237 ToSendStuffBit(0);
238 ToSendStuffBit(0);
239 ToSendStuffBit(1);
240 ToSendStuffBit(1);
241 ToSendStuffBit(1);
242 ToSendStuffBit(0);
243 ToSendStuffBit(1);
244
245 // data
246 for(int i = 0; i < n; i++) {
247 for(int j = 0; j < 8; j++) {
248 if ((cmd[i] >> j) & 0x01) {
249 ToSendStuffBit(0);
250 ToSendStuffBit(1);
251 } else {
252 ToSendStuffBit(1);
253 ToSendStuffBit(0);
254 }
255 }
256 }
257
258 // EOF
259 ToSendStuffBit(1);
260 ToSendStuffBit(0);
261 ToSendStuffBit(1);
262 ToSendStuffBit(1);
263 ToSendStuffBit(1);
264 ToSendStuffBit(0);
265 ToSendStuffBit(0);
266 ToSendStuffBit(0);
267
268 ToSendMax++;
269}
270
271
272// Transmit the command (to the tag) that was placed in cmd[].
273static void TransmitTo15693Tag(const uint8_t *cmd, int len, uint32_t start_time)
274{
275 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER | FPGA_HF_READER_MODE_SEND_FULL_MOD);
276 FpgaSetupSsc(FPGA_MAJOR_MODE_HF_READER);
277
278 while (GetCountSspClk() < start_time) ;
279
280 LED_B_ON();
281 for(int c = 0; c < len; c++) {
282 uint8_t data = cmd[c];
283 for (int i = 0; i < 8; i++) {
284 uint16_t send_word = (data & 0x80) ? 0x0000 : 0xffff;
285 while (!(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY))) ;
286 AT91C_BASE_SSC->SSC_THR = send_word;
287 while (!(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY))) ;
288 AT91C_BASE_SSC->SSC_THR = send_word;
289 data <<= 1;
290 }
291 WDT_HIT();
292 }
293 LED_B_OFF();
294}
295
296
297//-----------------------------------------------------------------------------
298// Transmit the tag response (to the reader) that was placed in cmd[].
299//-----------------------------------------------------------------------------
300static void TransmitTo15693Reader(const uint8_t *cmd, size_t len, uint32_t start_time, bool slow)
301{
302 // don't use the FPGA_HF_SIMULATOR_MODULATE_424K_8BIT minor mode. It would spoil GetCountSspClk()
303 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_MODULATE_424K);
304
305 uint8_t shift_delay = start_time & 0x00000007;
306 uint8_t bitmask = 0x00;
307 for (int i = 0; i < shift_delay; i++) {
308 bitmask |= (0x01 << i);
309 }
310
311 while (GetCountSspClk() < (start_time & 0xfffffff8)) ;
312
313 AT91C_BASE_SSC->SSC_THR = 0x00; // clear TXRDY
314
315 LED_C_ON();
316 uint8_t bits_to_shift = 0x00;
317 for(size_t c = 0; c <= len; c++) {
318 uint8_t bits_to_send = bits_to_shift << (8 - shift_delay) | (c==len?0x00:cmd[c]) >> shift_delay;
319 bits_to_shift = cmd[c] & bitmask;
320 for (int i = 7; i >= 0; i--) {
321 for (int j = 0; j < (slow?4:1); ) {
322 if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) {
323 if (bits_to_send >> i & 0x01) {
324 AT91C_BASE_SSC->SSC_THR = 0xff;
325 } else {
326 AT91C_BASE_SSC->SSC_THR = 0x00;
327 }
328 j++;
329 }
330 WDT_HIT();
331 }
332 }
333 }
334 LED_C_OFF();
335}
336
337
338//=============================================================================
339// An ISO 15693 decoder for tag responses (one subcarrier only).
340// Uses cross correlation to identify each bit and EOF.
341// This function is called 8 times per bit (every 2 subcarrier cycles).
342// Subcarrier frequency fs is 424kHz, 1/fs = 2,36us,
343// i.e. function is called every 4,72us
344// LED handling:
345// LED C -> ON once we have received the SOF and are expecting the rest.
346// LED C -> OFF once we have received EOF or are unsynced
347//
348// Returns: true if we received a EOF
349// false if we are still waiting for some more
350//=============================================================================
351
352#define NOISE_THRESHOLD 160 // don't try to correlate noise
353
354typedef struct DecodeTag {
355 enum {
356 STATE_TAG_SOF_LOW,
357 STATE_TAG_SOF_HIGH,
358 STATE_TAG_SOF_HIGH_END,
359 STATE_TAG_RECEIVING_DATA,
360 STATE_TAG_EOF
361 } state;
362 int bitCount;
363 int posCount;
364 enum {
365 LOGIC0,
366 LOGIC1,
367 SOF_PART1,
368 SOF_PART2
369 } lastBit;
370 uint16_t shiftReg;
371 uint16_t max_len;
372 uint8_t *output;
373 int len;
374 int sum1, sum2;
375} DecodeTag_t;
376
377
378static int inline __attribute__((always_inline)) Handle15693SamplesFromTag(uint16_t amplitude, DecodeTag_t *DecodeTag)
379{
380 switch(DecodeTag->state) {
381 case STATE_TAG_SOF_LOW:
382 // waiting for 12 times low (11 times low is accepted as well)
383 if (amplitude < NOISE_THRESHOLD) {
384 DecodeTag->posCount++;
385 } else {
386 if (DecodeTag->posCount > 10) {
387 DecodeTag->posCount = 1;
388 DecodeTag->sum1 = 0;
389 DecodeTag->state = STATE_TAG_SOF_HIGH;
390 } else {
391 DecodeTag->posCount = 0;
392 }
393 }
394 break;
395
396 case STATE_TAG_SOF_HIGH:
397 // waiting for 10 times high. Take average over the last 8
398 if (amplitude > NOISE_THRESHOLD) {
399 DecodeTag->posCount++;
400 if (DecodeTag->posCount > 2) {
401 DecodeTag->sum1 += amplitude; // keep track of average high value
402 }
403 if (DecodeTag->posCount == 10) {
404 DecodeTag->sum1 >>= 4; // calculate half of average high value (8 samples)
405 DecodeTag->state = STATE_TAG_SOF_HIGH_END;
406 }
407 } else { // high phase was too short
408 DecodeTag->posCount = 1;
409 DecodeTag->state = STATE_TAG_SOF_LOW;
410 }
411 break;
412
413 case STATE_TAG_SOF_HIGH_END:
414 // waiting for a falling edge
415 if (amplitude < DecodeTag->sum1) { // signal drops below 50% average high: a falling edge
416 DecodeTag->lastBit = SOF_PART1; // detected 1st part of SOF (12 samples low and 12 samples high)
417 DecodeTag->shiftReg = 0;
418 DecodeTag->bitCount = 0;
419 DecodeTag->len = 0;
420 DecodeTag->sum1 = amplitude;
421 DecodeTag->sum2 = 0;
422 DecodeTag->posCount = 2;
423 DecodeTag->state = STATE_TAG_RECEIVING_DATA;
424 LED_C_ON();
425 } else {
426 DecodeTag->posCount++;
427 if (DecodeTag->posCount > 13) { // high phase too long
428 DecodeTag->posCount = 0;
429 DecodeTag->state = STATE_TAG_SOF_LOW;
430 LED_C_OFF();
431 }
432 }
433 break;
434
435 case STATE_TAG_RECEIVING_DATA:
436 if (DecodeTag->posCount == 1) {
437 DecodeTag->sum1 = 0;
438 DecodeTag->sum2 = 0;
439 }
440 if (DecodeTag->posCount <= 4) {
441 DecodeTag->sum1 += amplitude;
442 } else {
443 DecodeTag->sum2 += amplitude;
444 }
445 if (DecodeTag->posCount == 8) {
446 int32_t corr_1 = DecodeTag->sum2 - DecodeTag->sum1;
447 int32_t corr_0 = -corr_1;
448 int32_t corr_EOF = (DecodeTag->sum1 + DecodeTag->sum2) / 2;
449 if (corr_EOF > corr_0 && corr_EOF > corr_1) {
450 if (DecodeTag->lastBit == LOGIC0) { // this was already part of EOF
451 DecodeTag->state = STATE_TAG_EOF;
452 } else {
453 DecodeTag->posCount = 0;
454 DecodeTag->state = STATE_TAG_SOF_LOW;
455 LED_C_OFF();
456 }
457 } else if (corr_1 > corr_0) {
458 // logic 1
459 if (DecodeTag->lastBit == SOF_PART1) { // still part of SOF
460 DecodeTag->lastBit = SOF_PART2; // SOF completed
461 } else {
462 DecodeTag->lastBit = LOGIC1;
463 DecodeTag->shiftReg >>= 1;
464 DecodeTag->shiftReg |= 0x80;
465 DecodeTag->bitCount++;
466 if (DecodeTag->bitCount == 8) {
467 DecodeTag->output[DecodeTag->len] = DecodeTag->shiftReg;
468 DecodeTag->len++;
469 if (DecodeTag->len > DecodeTag->max_len) {
470 // buffer overflow, give up
471 DecodeTag->posCount = 0;
472 DecodeTag->state = STATE_TAG_SOF_LOW;
473 LED_C_OFF();
474 }
475 DecodeTag->bitCount = 0;
476 DecodeTag->shiftReg = 0;
477 }
478 }
479 } else {
480 // logic 0
481 if (DecodeTag->lastBit == SOF_PART1) { // incomplete SOF
482 DecodeTag->posCount = 0;
483 DecodeTag->state = STATE_TAG_SOF_LOW;
484 LED_C_OFF();
485 } else {
486 DecodeTag->lastBit = LOGIC0;
487 DecodeTag->shiftReg >>= 1;
488 DecodeTag->bitCount++;
489 if (DecodeTag->bitCount == 8) {
490 DecodeTag->output[DecodeTag->len] = DecodeTag->shiftReg;
491 DecodeTag->len++;
492 if (DecodeTag->len > DecodeTag->max_len) {
493 // buffer overflow, give up
494 DecodeTag->posCount = 0;
495 DecodeTag->state = STATE_TAG_SOF_LOW;
496 LED_C_OFF();
497 }
498 DecodeTag->bitCount = 0;
499 DecodeTag->shiftReg = 0;
500 }
501 }
502 }
503 DecodeTag->posCount = 0;
504 }
505 DecodeTag->posCount++;
506 break;
507
508 case STATE_TAG_EOF:
509 if (DecodeTag->posCount == 1) {
510 DecodeTag->sum1 = 0;
511 DecodeTag->sum2 = 0;
512 }
513 if (DecodeTag->posCount <= 4) {
514 DecodeTag->sum1 += amplitude;
515 } else {
516 DecodeTag->sum2 += amplitude;
517 }
518 if (DecodeTag->posCount == 8) {
519 int32_t corr_1 = DecodeTag->sum2 - DecodeTag->sum1;
520 int32_t corr_0 = -corr_1;
521 int32_t corr_EOF = (DecodeTag->sum1 + DecodeTag->sum2) / 2;
522 if (corr_EOF > corr_0 || corr_1 > corr_0) {
523 DecodeTag->posCount = 0;
524 DecodeTag->state = STATE_TAG_SOF_LOW;
525 LED_C_OFF();
526 } else {
527 LED_C_OFF();
528 return true;
529 }
530 }
531 DecodeTag->posCount++;
532 break;
533
534 }
535
536 return false;
537}
538
539
540static void DecodeTagInit(DecodeTag_t *DecodeTag, uint8_t *data, uint16_t max_len)
541{
542 DecodeTag->posCount = 0;
543 DecodeTag->state = STATE_TAG_SOF_LOW;
544 DecodeTag->output = data;
545 DecodeTag->max_len = max_len;
546}
547
548
549static void DecodeTagReset(DecodeTag_t *DecodeTag)
550{
551 DecodeTag->posCount = 0;
552 DecodeTag->state = STATE_TAG_SOF_LOW;
553}
554
555
556/*
557 * Receive and decode the tag response, also log to tracebuffer
558 */
559static int GetIso15693AnswerFromTag(uint8_t* response, uint16_t max_len, int timeout)
560{
561 int samples = 0;
562 bool gotFrame = false;
563
564 uint16_t *dmaBuf = (uint16_t*)BigBuf_malloc(ISO15693_DMA_BUFFER_SIZE*sizeof(uint16_t));
565
566 // the Decoder data structure
567 DecodeTag_t DecodeTag = { 0 };
568 DecodeTagInit(&DecodeTag, response, max_len);
569
570 // wait for last transfer to complete
571 while (!(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXEMPTY));
572
573 // And put the FPGA in the appropriate mode
574 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER | FPGA_HF_READER_SUBCARRIER_424_KHZ | FPGA_HF_READER_MODE_RECEIVE_AMPLITUDE);
575
576 // Setup and start DMA.
577 FpgaSetupSsc(FPGA_MAJOR_MODE_HF_READER);
578 FpgaSetupSscDma((uint8_t*) dmaBuf, ISO15693_DMA_BUFFER_SIZE);
579 uint16_t *upTo = dmaBuf;
580
581 for(;;) {
582 uint16_t behindBy = ((uint16_t*)AT91C_BASE_PDC_SSC->PDC_RPR - upTo) & (ISO15693_DMA_BUFFER_SIZE-1);
583
584 if (behindBy == 0) continue;
585
586 uint16_t tagdata = *upTo++;
587
588 if(upTo >= dmaBuf + ISO15693_DMA_BUFFER_SIZE) { // we have read all of the DMA buffer content.
589 upTo = dmaBuf; // start reading the circular buffer from the beginning
590 if(behindBy > (9*ISO15693_DMA_BUFFER_SIZE/10)) {
591 Dbprintf("About to blow circular buffer - aborted! behindBy=%d", behindBy);
592 break;
593 }
594 }
595 if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_ENDRX)) { // DMA Counter Register had reached 0, already rotated.
596 AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) dmaBuf; // refresh the DMA Next Buffer and
597 AT91C_BASE_PDC_SSC->PDC_RNCR = ISO15693_DMA_BUFFER_SIZE; // DMA Next Counter registers
598 }
599
600 samples++;
601
602 if (Handle15693SamplesFromTag(tagdata, &DecodeTag)) {
603 gotFrame = true;
604 break;
605 }
606
607 if (samples > timeout && DecodeTag.state < STATE_TAG_RECEIVING_DATA) {
608 DecodeTag.len = 0;
609 break;
610 }
611
612 }
613
614 FpgaDisableSscDma();
615 BigBuf_free();
616
617 if (DEBUG) Dbprintf("samples = %d, gotFrame = %d, Decoder: state = %d, len = %d, bitCount = %d, posCount = %d",
618 samples, gotFrame, DecodeTag.state, DecodeTag.len, DecodeTag.bitCount, DecodeTag.posCount);
619
620 if (DecodeTag.len > 0) {
621 LogTrace(DecodeTag.output, DecodeTag.len, 0, 0, NULL, false);
622 }
623
624 return DecodeTag.len;
625}
626
627
628//=============================================================================
629// An ISO15693 decoder for reader commands.
630//
631// This function is called 4 times per bit (every 2 subcarrier cycles).
632// Subcarrier frequency fs is 848kHz, 1/fs = 1,18us, i.e. function is called every 2,36us
633// LED handling:
634// LED B -> ON once we have received the SOF and are expecting the rest.
635// LED B -> OFF once we have received EOF or are in error state or unsynced
636//
637// Returns: true if we received a EOF
638// false if we are still waiting for some more
639//=============================================================================
640
641typedef struct DecodeReader {
642 enum {
643 STATE_READER_UNSYNCD,
644 STATE_READER_AWAIT_1ST_RISING_EDGE_OF_SOF,
645 STATE_READER_AWAIT_2ND_FALLING_EDGE_OF_SOF,
646 STATE_READER_AWAIT_2ND_RISING_EDGE_OF_SOF,
647 STATE_READER_AWAIT_END_OF_SOF_1_OUT_OF_4,
648 STATE_READER_RECEIVE_DATA_1_OUT_OF_4,
649 STATE_READER_RECEIVE_DATA_1_OUT_OF_256
650 } state;
651 enum {
652 CODING_1_OUT_OF_4,
653 CODING_1_OUT_OF_256
654 } Coding;
655 uint8_t shiftReg;
656 uint8_t bitCount;
657 int byteCount;
658 int byteCountMax;
659 int posCount;
660 int sum1, sum2;
661 uint8_t *output;
662} DecodeReader_t;
663
664
665static void DecodeReaderInit(DecodeReader_t* DecodeReader, uint8_t *data, uint16_t max_len)
666{
667 DecodeReader->output = data;
668 DecodeReader->byteCountMax = max_len;
669 DecodeReader->state = STATE_READER_UNSYNCD;
670 DecodeReader->byteCount = 0;
671 DecodeReader->bitCount = 0;
672 DecodeReader->posCount = 1;
673 DecodeReader->shiftReg = 0;
674}
675
676
677static void DecodeReaderReset(DecodeReader_t* DecodeReader)
678{
679 DecodeReader->state = STATE_READER_UNSYNCD;
680}
681
682
683static int inline __attribute__((always_inline)) Handle15693SampleFromReader(uint8_t bit, DecodeReader_t *restrict DecodeReader)
684{
685 switch(DecodeReader->state) {
686 case STATE_READER_UNSYNCD:
687 if(!bit) {
688 // we went low, so this could be the beginning of a SOF
689 DecodeReader->posCount = 1;
690 DecodeReader->state = STATE_READER_AWAIT_1ST_RISING_EDGE_OF_SOF;
691 }
692 break;
693
694 case STATE_READER_AWAIT_1ST_RISING_EDGE_OF_SOF:
695 DecodeReader->posCount++;
696 if(bit) { // detected rising edge
697 if(DecodeReader->posCount < 4) { // rising edge too early (nominally expected at 5)
698 DecodeReaderReset(DecodeReader);
699 } else { // SOF
700 DecodeReader->state = STATE_READER_AWAIT_2ND_FALLING_EDGE_OF_SOF;
701 }
702 } else {
703 if(DecodeReader->posCount > 5) { // stayed low for too long
704 DecodeReaderReset(DecodeReader);
705 } else {
706 // do nothing, keep waiting
707 }
708 }
709 break;
710
711 case STATE_READER_AWAIT_2ND_FALLING_EDGE_OF_SOF:
712 DecodeReader->posCount++;
713 if(!bit) { // detected a falling edge
714 if (DecodeReader->posCount < 20) { // falling edge too early (nominally expected at 21 earliest)
715 DecodeReaderReset(DecodeReader);
716 } else if (DecodeReader->posCount < 23) { // SOF for 1 out of 4 coding
717 DecodeReader->Coding = CODING_1_OUT_OF_4;
718 DecodeReader->state = STATE_READER_AWAIT_2ND_RISING_EDGE_OF_SOF;
719 } else if (DecodeReader->posCount < 28) { // falling edge too early (nominally expected at 29 latest)
720 DecodeReaderReset(DecodeReader);
721 } else { // SOF for 1 out of 4 coding
722 DecodeReader->Coding = CODING_1_OUT_OF_256;
723 DecodeReader->state = STATE_READER_AWAIT_2ND_RISING_EDGE_OF_SOF;
724 }
725 } else {
726 if(DecodeReader->posCount > 29) { // stayed high for too long
727 DecodeReaderReset(DecodeReader);
728 } else {
729 // do nothing, keep waiting
730 }
731 }
732 break;
733
734 case STATE_READER_AWAIT_2ND_RISING_EDGE_OF_SOF:
735 DecodeReader->posCount++;
736 if (bit) { // detected rising edge
737 if (DecodeReader->Coding == CODING_1_OUT_OF_256) {
738 if (DecodeReader->posCount < 32) { // rising edge too early (nominally expected at 33)
739 DecodeReaderReset(DecodeReader);
740 } else {
741 DecodeReader->posCount = 1;
742 DecodeReader->bitCount = 0;
743 DecodeReader->byteCount = 0;
744 DecodeReader->sum1 = 1;
745 DecodeReader->state = STATE_READER_RECEIVE_DATA_1_OUT_OF_256;
746 LED_B_ON();
747 }
748 } else { // CODING_1_OUT_OF_4
749 if (DecodeReader->posCount < 24) { // rising edge too early (nominally expected at 25)
750 DecodeReaderReset(DecodeReader);
751 } else {
752 DecodeReader->state = STATE_READER_AWAIT_END_OF_SOF_1_OUT_OF_4;
753 }
754 }
755 } else {
756 if (DecodeReader->Coding == CODING_1_OUT_OF_256) {
757 if (DecodeReader->posCount > 34) { // signal stayed low for too long
758 DecodeReaderReset(DecodeReader);
759 } else {
760 // do nothing, keep waiting
761 }
762 } else { // CODING_1_OUT_OF_4
763 if (DecodeReader->posCount > 26) { // signal stayed low for too long
764 DecodeReaderReset(DecodeReader);
765 } else {
766 // do nothing, keep waiting
767 }
768 }
769 }
770 break;
771
772 case STATE_READER_AWAIT_END_OF_SOF_1_OUT_OF_4:
773 DecodeReader->posCount++;
774 if (bit) {
775 if (DecodeReader->posCount == 33) {
776 DecodeReader->posCount = 1;
777 DecodeReader->bitCount = 0;
778 DecodeReader->byteCount = 0;
779 DecodeReader->sum1 = 1;
780 DecodeReader->state = STATE_READER_RECEIVE_DATA_1_OUT_OF_4;
781 LED_B_ON();
782 } else {
783 // do nothing, keep waiting
784 }
785 } else { // unexpected falling edge
786 DecodeReaderReset(DecodeReader);
787 }
788 break;
789
790 case STATE_READER_RECEIVE_DATA_1_OUT_OF_4:
791 DecodeReader->posCount++;
792 if (DecodeReader->posCount == 1) {
793 DecodeReader->sum1 = bit;
794 } else if (DecodeReader->posCount <= 4) {
795 DecodeReader->sum1 += bit;
796 } else if (DecodeReader->posCount == 5) {
797 DecodeReader->sum2 = bit;
798 } else {
799 DecodeReader->sum2 += bit;
800 }
801 if (DecodeReader->posCount == 8) {
802 DecodeReader->posCount = 0;
803 int corr10 = DecodeReader->sum1 - DecodeReader->sum2;
804 int corr01 = DecodeReader->sum2 - DecodeReader->sum1;
805 int corr11 = (DecodeReader->sum1 + DecodeReader->sum2) / 2;
806 if (corr01 > corr11 && corr01 > corr10) { // EOF
807 LED_B_OFF(); // Finished receiving
808 DecodeReaderReset(DecodeReader);
809 if (DecodeReader->byteCount != 0) {
810 return true;
811 }
812 }
813 if (corr10 > corr11) { // detected a 2bit position
814 DecodeReader->shiftReg >>= 2;
815 DecodeReader->shiftReg |= (DecodeReader->bitCount << 6);
816 }
817 if (DecodeReader->bitCount == 15) { // we have a full byte
818 DecodeReader->output[DecodeReader->byteCount++] = DecodeReader->shiftReg;
819 if (DecodeReader->byteCount > DecodeReader->byteCountMax) {
820 // buffer overflow, give up
821 LED_B_OFF();
822 DecodeReaderReset(DecodeReader);
823 }
824 DecodeReader->bitCount = 0;
825 DecodeReader->shiftReg = 0;
826 } else {
827 DecodeReader->bitCount++;
828 }
829 }
830 break;
831
832 case STATE_READER_RECEIVE_DATA_1_OUT_OF_256:
833 DecodeReader->posCount++;
834 if (DecodeReader->posCount == 1) {
835 DecodeReader->sum1 = bit;
836 } else if (DecodeReader->posCount <= 4) {
837 DecodeReader->sum1 += bit;
838 } else if (DecodeReader->posCount == 5) {
839 DecodeReader->sum2 = bit;
840 } else {
841 DecodeReader->sum2 += bit;
842 }
843 if (DecodeReader->posCount == 8) {
844 DecodeReader->posCount = 0;
845 int corr10 = DecodeReader->sum1 - DecodeReader->sum2;
846 int corr01 = DecodeReader->sum2 - DecodeReader->sum1;
847 int corr11 = (DecodeReader->sum1 + DecodeReader->sum2) / 2;
848 if (corr01 > corr11 && corr01 > corr10) { // EOF
849 LED_B_OFF(); // Finished receiving
850 DecodeReaderReset(DecodeReader);
851 if (DecodeReader->byteCount != 0) {
852 return true;
853 }
854 }
855 if (corr10 > corr11) { // detected the bit position
856 DecodeReader->shiftReg = DecodeReader->bitCount;
857 }
858 if (DecodeReader->bitCount == 255) { // we have a full byte
859 DecodeReader->output[DecodeReader->byteCount++] = DecodeReader->shiftReg;
860 if (DecodeReader->byteCount > DecodeReader->byteCountMax) {
861 // buffer overflow, give up
862 LED_B_OFF();
863 DecodeReaderReset(DecodeReader);
864 }
865 }
866 DecodeReader->bitCount++;
867 }
868 break;
869
870 default:
871 LED_B_OFF();
872 DecodeReaderReset(DecodeReader);
873 break;
874 }
875
876 return false;
877}
878
879
880//-----------------------------------------------------------------------------
881// Receive a command (from the reader to us, where we are the simulated tag),
882// and store it in the given buffer, up to the given maximum length. Keeps
883// spinning, waiting for a well-framed command, until either we get one
884// (returns true) or someone presses the pushbutton on the board (false).
885//
886// Assume that we're called with the SSC (to the FPGA) and ADC path set
887// correctly.
888//-----------------------------------------------------------------------------
889
890static int GetIso15693CommandFromReader(uint8_t *received, size_t max_len, uint32_t *eof_time)
891{
892 int samples = 0;
893 bool gotFrame = false;
894 uint8_t b;
895
896 uint8_t *dmaBuf = BigBuf_malloc(ISO15693_DMA_BUFFER_SIZE);
897
898 // the decoder data structure
899 DecodeReader_t DecodeReader = {0};
900 DecodeReaderInit(&DecodeReader, received, max_len);
901
902 // wait for last transfer to complete
903 while (!(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXEMPTY));
904
905 LED_D_OFF();
906 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_NO_MODULATION);
907
908 // clear receive register and wait for next transfer
909 uint32_t temp = AT91C_BASE_SSC->SSC_RHR;
910 (void) temp;
911 while (!(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY)) ;
912
913 uint32_t bit_time = GetCountSspClk() & 0xfffffff8;
914
915 // Setup and start DMA.
916 FpgaSetupSscDma(dmaBuf, ISO15693_DMA_BUFFER_SIZE);
917 uint8_t *upTo = dmaBuf;
918
919 for(;;) {
920 uint16_t behindBy = ((uint8_t*)AT91C_BASE_PDC_SSC->PDC_RPR - upTo) & (ISO15693_DMA_BUFFER_SIZE-1);
921
922 if (behindBy == 0) continue;
923
924 b = *upTo++;
925 if(upTo >= dmaBuf + ISO15693_DMA_BUFFER_SIZE) { // we have read all of the DMA buffer content.
926 upTo = dmaBuf; // start reading the circular buffer from the beginning
927 if(behindBy > (9*ISO15693_DMA_BUFFER_SIZE/10)) {
928 Dbprintf("About to blow circular buffer - aborted! behindBy=%d", behindBy);
929 break;
930 }
931 }
932 if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_ENDRX)) { // DMA Counter Register had reached 0, already rotated.
933 AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) dmaBuf; // refresh the DMA Next Buffer and
934 AT91C_BASE_PDC_SSC->PDC_RNCR = ISO15693_DMA_BUFFER_SIZE; // DMA Next Counter registers
935 }
936
937 for (int i = 7; i >= 0; i--) {
938 if (Handle15693SampleFromReader((b >> i) & 0x01, &DecodeReader)) {
939 *eof_time = bit_time + samples - DELAY_READER_TO_ARM_SIM; // end of EOF
940 gotFrame = true;
941 break;
942 }
943 samples++;
944 }
945
946 if (gotFrame) {
947 break;
948 }
949
950 if (BUTTON_PRESS()) {
951 DecodeReader.byteCount = 0;
952 break;
953 }
954
955 WDT_HIT();
956 }
957
958
959 FpgaDisableSscDma();
960 BigBuf_free_keep_EM();
961
962 if (DEBUG) Dbprintf("samples = %d, gotFrame = %d, Decoder: state = %d, len = %d, bitCount = %d, posCount = %d",
963 samples, gotFrame, DecodeReader.state, DecodeReader.byteCount, DecodeReader.bitCount, DecodeReader.posCount);
964
965 if (DecodeReader.byteCount > 0) {
966 LogTrace(DecodeReader.output, DecodeReader.byteCount, 0, *eof_time, NULL, true);
967 }
968
969 return DecodeReader.byteCount;
970}
971
972
973// Encode (into the ToSend buffers) an identify request, which is the first
974// thing that you must send to a tag to get a response.
975static void BuildIdentifyRequest(void)
976{
977 uint8_t cmd[5];
978
979 uint16_t crc;
980 // one sub-carrier, inventory, 1 slot, fast rate
981 // AFI is at bit 5 (1<<4) when doing an INVENTORY
982 cmd[0] = (1 << 2) | (1 << 5) | (1 << 1);
983 // inventory command code
984 cmd[1] = 0x01;
985 // no mask
986 cmd[2] = 0x00;
987 //Now the CRC
988 crc = Crc(cmd, 3);
989 cmd[3] = crc & 0xff;
990 cmd[4] = crc >> 8;
991
992 CodeIso15693AsReader(cmd, sizeof(cmd));
993}
994
995
996//-----------------------------------------------------------------------------
997// Start to read an ISO 15693 tag. We send an identify request, then wait
998// for the response. The response is not demodulated, just left in the buffer
999// so that it can be downloaded to a PC and processed there.
1000//-----------------------------------------------------------------------------
1001void AcquireRawAdcSamplesIso15693(void)
1002{
1003 LEDsoff();
1004 LED_A_ON();
1005
1006 uint8_t *dest = BigBuf_get_addr();
1007
1008 FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
1009 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER);
1010 FpgaSetupSsc(FPGA_MAJOR_MODE_HF_READER);
1011 SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
1012
1013 BuildIdentifyRequest();
1014
1015 // Give the tags time to energize
1016 LED_D_ON();
1017 SpinDelay(100);
1018
1019 // Now send the command
1020 TransmitTo15693Tag(ToSend, ToSendMax, 0);
1021
1022 // wait for last transfer to complete
1023 while (!(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXEMPTY)) ;
1024
1025 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER | FPGA_HF_READER_SUBCARRIER_424_KHZ | FPGA_HF_READER_MODE_RECEIVE_AMPLITUDE);
1026
1027 for(int c = 0; c < 4000; ) {
1028 if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
1029 uint16_t r = AT91C_BASE_SSC->SSC_RHR;
1030 dest[c++] = r >> 5;
1031 }
1032 }
1033
1034 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
1035 LEDsoff();
1036}
1037
1038
1039void SnoopIso15693(void)
1040{
1041 LED_A_ON();
1042 FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
1043 BigBuf_free();
1044
1045 clear_trace();
1046 set_tracing(true);
1047
1048 // The DMA buffer, used to stream samples from the FPGA
1049 uint16_t* dmaBuf = (uint16_t*)BigBuf_malloc(ISO15693_DMA_BUFFER_SIZE*sizeof(uint16_t));
1050 uint16_t *upTo;
1051
1052 // Count of samples received so far, so that we can include timing
1053 // information in the trace buffer.
1054 int samples = 0;
1055
1056 DecodeTag_t DecodeTag = {0};
1057 uint8_t response[ISO15693_MAX_RESPONSE_LENGTH];
1058 DecodeTagInit(&DecodeTag, response, sizeof(response));
1059
1060 DecodeReader_t DecodeReader = {0};;
1061 uint8_t cmd[ISO15693_MAX_COMMAND_LENGTH];
1062 DecodeReaderInit(&DecodeReader, cmd, sizeof(cmd));
1063
1064 // Print some debug information about the buffer sizes
1065 if (DEBUG) {
1066 Dbprintf("Snooping buffers initialized:");
1067 Dbprintf(" Trace: %i bytes", BigBuf_max_traceLen());
1068 Dbprintf(" Reader -> tag: %i bytes", ISO15693_MAX_COMMAND_LENGTH);
1069 Dbprintf(" tag -> Reader: %i bytes", ISO15693_MAX_RESPONSE_LENGTH);
1070 Dbprintf(" DMA: %i bytes", ISO15693_DMA_BUFFER_SIZE * sizeof(uint16_t));
1071 }
1072 Dbprintf("Snoop started. Press PM3 Button to stop.");
1073
1074 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER | FPGA_HF_READER_MODE_SNOOP_AMPLITUDE);
1075 SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
1076
1077 // Setup for the DMA.
1078 FpgaSetupSsc(FPGA_MAJOR_MODE_HF_READER);
1079 upTo = dmaBuf;
1080 FpgaSetupSscDma((uint8_t*) dmaBuf, ISO15693_DMA_BUFFER_SIZE);
1081
1082 bool TagIsActive = false;
1083 bool ReaderIsActive = false;
1084 bool ExpectTagAnswer = false;
1085
1086 // And now we loop, receiving samples.
1087 for(;;) {
1088 uint16_t behindBy = ((uint16_t*)AT91C_BASE_PDC_SSC->PDC_RPR - upTo) & (ISO15693_DMA_BUFFER_SIZE-1);
1089
1090 if (behindBy == 0) continue;
1091
1092 uint16_t snoopdata = *upTo++;
1093
1094 if(upTo >= dmaBuf + ISO15693_DMA_BUFFER_SIZE) { // we have read all of the DMA buffer content.
1095 upTo = dmaBuf; // start reading the circular buffer from the beginning
1096 if(behindBy > (9*ISO15693_DMA_BUFFER_SIZE/10)) {
1097 Dbprintf("About to blow circular buffer - aborted! behindBy=%d, samples=%d", behindBy, samples);
1098 break;
1099 }
1100 if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_ENDRX)) { // DMA Counter Register had reached 0, already rotated.
1101 AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) dmaBuf; // refresh the DMA Next Buffer and
1102 AT91C_BASE_PDC_SSC->PDC_RNCR = ISO15693_DMA_BUFFER_SIZE; // DMA Next Counter registers
1103 WDT_HIT();
1104 if(BUTTON_PRESS()) {
1105 DbpString("Snoop stopped.");
1106 break;
1107 }
1108 }
1109 }
1110 samples++;
1111
1112 if (!TagIsActive) { // no need to try decoding reader data if the tag is sending
1113 if (Handle15693SampleFromReader(snoopdata & 0x02, &DecodeReader)) {
1114 FpgaDisableSscDma();
1115 ExpectTagAnswer = true;
1116 LogTrace(DecodeReader.output, DecodeReader.byteCount, samples, samples, NULL, true);
1117 /* And ready to receive another command. */
1118 DecodeReaderReset(&DecodeReader);
1119 /* And also reset the demod code, which might have been */
1120 /* false-triggered by the commands from the reader. */
1121 DecodeTagReset(&DecodeTag);
1122 upTo = dmaBuf;
1123 FpgaSetupSscDma((uint8_t*) dmaBuf, ISO15693_DMA_BUFFER_SIZE);
1124 }
1125 if (Handle15693SampleFromReader(snoopdata & 0x01, &DecodeReader)) {
1126 FpgaDisableSscDma();
1127 ExpectTagAnswer = true;
1128 LogTrace(DecodeReader.output, DecodeReader.byteCount, samples, samples, NULL, true);
1129 /* And ready to receive another command. */
1130 DecodeReaderReset(&DecodeReader);
1131 /* And also reset the demod code, which might have been */
1132 /* false-triggered by the commands from the reader. */
1133 DecodeTagReset(&DecodeTag);
1134 upTo = dmaBuf;
1135 FpgaSetupSscDma((uint8_t*) dmaBuf, ISO15693_DMA_BUFFER_SIZE);
1136 }
1137 ReaderIsActive = (DecodeReader.state >= STATE_READER_AWAIT_2ND_RISING_EDGE_OF_SOF);
1138 }
1139
1140 if (!ReaderIsActive && ExpectTagAnswer) { // no need to try decoding tag data if the reader is currently sending or no answer expected yet
1141 if (Handle15693SamplesFromTag(snoopdata >> 2, &DecodeTag)) {
1142 FpgaDisableSscDma();
1143 //Use samples as a time measurement
1144 LogTrace(DecodeTag.output, DecodeTag.len, samples, samples, NULL, false);
1145 // And ready to receive another response.
1146 DecodeTagReset(&DecodeTag);
1147 DecodeReaderReset(&DecodeReader);
1148 ExpectTagAnswer = false;
1149 upTo = dmaBuf;
1150 FpgaSetupSscDma((uint8_t*) dmaBuf, ISO15693_DMA_BUFFER_SIZE);
1151 }
1152 TagIsActive = (DecodeTag.state >= STATE_TAG_RECEIVING_DATA);
1153 }
1154
1155 }
1156
1157 FpgaDisableSscDma();
1158 BigBuf_free();
1159
1160 LEDsoff();
1161
1162 DbpString("Snoop statistics:");
1163 Dbprintf(" ExpectTagAnswer: %d", ExpectTagAnswer);
1164 Dbprintf(" DecodeTag State: %d", DecodeTag.state);
1165 Dbprintf(" DecodeTag byteCnt: %d", DecodeTag.len);
1166 Dbprintf(" DecodeReader State: %d", DecodeReader.state);
1167 Dbprintf(" DecodeReader byteCnt: %d", DecodeReader.byteCount);
1168 Dbprintf(" Trace length: %d", BigBuf_get_traceLen());
1169}
1170
1171
1172// Initialize the proxmark as iso15k reader
1173static void Iso15693InitReader() {
1174 FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
1175 // Setup SSC
1176 // FpgaSetupSsc();
1177
1178 // Start from off (no field generated)
1179 LED_D_OFF();
1180 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
1181 SpinDelay(10);
1182
1183 SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
1184 FpgaSetupSsc(FPGA_MAJOR_MODE_HF_READER);
1185
1186 // Give the tags time to energize
1187 LED_D_ON();
1188 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER);
1189 SpinDelay(250);
1190}
1191
1192///////////////////////////////////////////////////////////////////////
1193// ISO 15693 Part 3 - Air Interface
1194// This section basically contains transmission and receiving of bits
1195///////////////////////////////////////////////////////////////////////
1196
1197
1198// uid is in transmission order (which is reverse of display order)
1199static void BuildReadBlockRequest(uint8_t *uid, uint8_t blockNumber )
1200{
1201 uint8_t cmd[13];
1202
1203 uint16_t crc;
1204 // If we set the Option_Flag in this request, the VICC will respond with the security status of the block
1205 // followed by the block data
1206 cmd[0] = ISO15693_REQ_OPTION | ISO15693_REQ_ADDRESS | ISO15693_REQ_DATARATE_HIGH;
1207 // READ BLOCK command code
1208 cmd[1] = ISO15693_READBLOCK;
1209 // UID may be optionally specified here
1210 // 64-bit UID
1211 cmd[2] = uid[0];
1212 cmd[3] = uid[1];
1213 cmd[4] = uid[2];
1214 cmd[5] = uid[3];
1215 cmd[6] = uid[4];
1216 cmd[7] = uid[5];
1217 cmd[8] = uid[6];
1218 cmd[9] = uid[7]; // 0xe0; // always e0 (not exactly unique)
1219 // Block number to read
1220 cmd[10] = blockNumber;
1221 //Now the CRC
1222 crc = Crc(cmd, 11); // the crc needs to be calculated over 11 bytes
1223 cmd[11] = crc & 0xff;
1224 cmd[12] = crc >> 8;
1225
1226 CodeIso15693AsReader(cmd, sizeof(cmd));
1227}
1228
1229
1230// Now the VICC>VCD responses when we are simulating a tag
1231static void BuildInventoryResponse(uint8_t *uid)
1232{
1233 uint8_t cmd[12];
1234
1235 uint16_t crc;
1236
1237 cmd[0] = 0; // No error, no protocol format extension
1238 cmd[1] = 0; // DSFID (data storage format identifier). 0x00 = not supported
1239 // 64-bit UID
1240 cmd[2] = uid[7]; //0x32;
1241 cmd[3] = uid[6]; //0x4b;
1242 cmd[4] = uid[5]; //0x03;
1243 cmd[5] = uid[4]; //0x01;
1244 cmd[6] = uid[3]; //0x00;
1245 cmd[7] = uid[2]; //0x10;
1246 cmd[8] = uid[1]; //0x05;
1247 cmd[9] = uid[0]; //0xe0;
1248 //Now the CRC
1249 crc = Crc(cmd, 10);
1250 cmd[10] = crc & 0xff;
1251 cmd[11] = crc >> 8;
1252
1253 CodeIso15693AsTag(cmd, sizeof(cmd));
1254}
1255
1256// Universal Method for sending to and recv bytes from a tag
1257// init ... should we initialize the reader?
1258// speed ... 0 low speed, 1 hi speed
1259// *recv will contain the tag's answer
1260// return: lenght of received data
1261int SendDataTag(uint8_t *send, int sendlen, bool init, int speed, uint8_t *recv, uint16_t max_recv_len, uint32_t start_time) {
1262
1263 LED_A_ON();
1264 LED_B_OFF();
1265 LED_C_OFF();
1266
1267 if (init) Iso15693InitReader();
1268
1269 int answerLen=0;
1270
1271 if (!speed) {
1272 // low speed (1 out of 256)
1273 CodeIso15693AsReader256(send, sendlen);
1274 } else {
1275 // high speed (1 out of 4)
1276 CodeIso15693AsReader(send, sendlen);
1277 }
1278
1279 TransmitTo15693Tag(ToSend, ToSendMax, start_time);
1280
1281 // Now wait for a response
1282 if (recv != NULL) {
1283 answerLen = GetIso15693AnswerFromTag(recv, max_recv_len, DELAY_ISO15693_VCD_TO_VICC_READER * 2);
1284 }
1285
1286 LED_A_OFF();
1287
1288 return answerLen;
1289}
1290
1291
1292// --------------------------------------------------------------------
1293// Debug Functions
1294// --------------------------------------------------------------------
1295
1296// Decodes a message from a tag and displays its metadata and content
1297#define DBD15STATLEN 48
1298void DbdecodeIso15693Answer(int len, uint8_t *d) {
1299 char status[DBD15STATLEN+1]={0};
1300 uint16_t crc;
1301
1302 if (len > 3) {
1303 if (d[0] & ISO15693_RES_EXT)
1304 strncat(status,"ProtExt ", DBD15STATLEN);
1305 if (d[0] & ISO15693_RES_ERROR) {
1306 // error
1307 strncat(status,"Error ", DBD15STATLEN);
1308 switch (d[1]) {
1309 case 0x01:
1310 strncat(status,"01:notSupp", DBD15STATLEN);
1311 break;
1312 case 0x02:
1313 strncat(status,"02:notRecog", DBD15STATLEN);
1314 break;
1315 case 0x03:
1316 strncat(status,"03:optNotSupp", DBD15STATLEN);
1317 break;
1318 case 0x0f:
1319 strncat(status,"0f:noInfo", DBD15STATLEN);
1320 break;
1321 case 0x10:
1322 strncat(status,"10:doesn'tExist", DBD15STATLEN);
1323 break;
1324 case 0x11:
1325 strncat(status,"11:lockAgain", DBD15STATLEN);
1326 break;
1327 case 0x12:
1328 strncat(status,"12:locked", DBD15STATLEN);
1329 break;
1330 case 0x13:
1331 strncat(status,"13:progErr", DBD15STATLEN);
1332 break;
1333 case 0x14:
1334 strncat(status,"14:lockErr", DBD15STATLEN);
1335 break;
1336 default:
1337 strncat(status,"unknownErr", DBD15STATLEN);
1338 }
1339 strncat(status," ", DBD15STATLEN);
1340 } else {
1341 strncat(status,"NoErr ", DBD15STATLEN);
1342 }
1343
1344 crc=Crc(d,len-2);
1345 if ( (( crc & 0xff ) == d[len-2]) && (( crc >> 8 ) == d[len-1]) )
1346 strncat(status,"CrcOK",DBD15STATLEN);
1347 else
1348 strncat(status,"CrcFail!",DBD15STATLEN);
1349
1350 Dbprintf("%s",status);
1351 }
1352}
1353
1354
1355
1356///////////////////////////////////////////////////////////////////////
1357// Functions called via USB/Client
1358///////////////////////////////////////////////////////////////////////
1359
1360void SetDebugIso15693(uint32_t debug) {
1361 DEBUG=debug;
1362 Dbprintf("Iso15693 Debug is now %s",DEBUG?"on":"off");
1363 return;
1364}
1365
1366
1367//---------------------------------------------------------------------------------------
1368// Simulate an ISO15693 reader, perform anti-collision and then attempt to read a sector.
1369// all demodulation performed in arm rather than host. - greg
1370//---------------------------------------------------------------------------------------
1371void ReaderIso15693(uint32_t parameter)
1372{
1373 LEDsoff();
1374 LED_A_ON();
1375
1376 set_tracing(true);
1377
1378 int answerLen = 0;
1379 uint8_t TagUID[8] = {0x00};
1380
1381 FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
1382
1383 uint8_t answer[ISO15693_MAX_RESPONSE_LENGTH];
1384
1385 SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
1386 // Setup SSC
1387 FpgaSetupSsc(FPGA_MAJOR_MODE_HF_READER);
1388
1389 // Start from off (no field generated)
1390 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
1391 SpinDelay(200);
1392
1393 // Give the tags time to energize
1394 LED_D_ON();
1395 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER);
1396 SpinDelay(200);
1397 StartCountSspClk();
1398
1399
1400 // FIRST WE RUN AN INVENTORY TO GET THE TAG UID
1401 // THIS MEANS WE CAN PRE-BUILD REQUESTS TO SAVE CPU TIME
1402
1403 // Now send the IDENTIFY command
1404 BuildIdentifyRequest();
1405 TransmitTo15693Tag(ToSend, ToSendMax, 0);
1406
1407 // Now wait for a response
1408 answerLen = GetIso15693AnswerFromTag(answer, sizeof(answer), DELAY_ISO15693_VCD_TO_VICC_READER * 2) ;
1409 uint32_t start_time = GetCountSspClk() + DELAY_ISO15693_VICC_TO_VCD_READER;
1410
1411 if (answerLen >=12) // we should do a better check than this
1412 {
1413 TagUID[0] = answer[2];
1414 TagUID[1] = answer[3];
1415 TagUID[2] = answer[4];
1416 TagUID[3] = answer[5];
1417 TagUID[4] = answer[6];
1418 TagUID[5] = answer[7];
1419 TagUID[6] = answer[8]; // IC Manufacturer code
1420 TagUID[7] = answer[9]; // always E0
1421
1422 }
1423
1424 Dbprintf("%d octets read from IDENTIFY request:", answerLen);
1425 DbdecodeIso15693Answer(answerLen, answer);
1426 Dbhexdump(answerLen, answer, false);
1427
1428 // UID is reverse
1429 if (answerLen >= 12)
1430 Dbprintf("UID = %02hX%02hX%02hX%02hX%02hX%02hX%02hX%02hX",
1431 TagUID[7],TagUID[6],TagUID[5],TagUID[4],
1432 TagUID[3],TagUID[2],TagUID[1],TagUID[0]);
1433
1434
1435 // Dbprintf("%d octets read from SELECT request:", answerLen2);
1436 // DbdecodeIso15693Answer(answerLen2,answer2);
1437 // Dbhexdump(answerLen2,answer2,true);
1438
1439 // Dbprintf("%d octets read from XXX request:", answerLen3);
1440 // DbdecodeIso15693Answer(answerLen3,answer3);
1441 // Dbhexdump(answerLen3,answer3,true);
1442
1443 // read all pages
1444 if (answerLen >= 12 && DEBUG) {
1445 for (int i = 0; i < 32; i++) { // sanity check, assume max 32 pages
1446 BuildReadBlockRequest(TagUID, i);
1447 TransmitTo15693Tag(ToSend, ToSendMax, start_time);
1448 int answerLen = GetIso15693AnswerFromTag(answer, sizeof(answer), DELAY_ISO15693_VCD_TO_VICC_READER * 2);
1449 start_time = GetCountSspClk() + DELAY_ISO15693_VICC_TO_VCD_READER;
1450 if (answerLen > 0) {
1451 Dbprintf("READ SINGLE BLOCK %d returned %d octets:", i, answerLen);
1452 DbdecodeIso15693Answer(answerLen, answer);
1453 Dbhexdump(answerLen, answer, false);
1454 if ( *((uint32_t*) answer) == 0x07160101 ) break; // exit on NoPageErr
1455 }
1456 }
1457 }
1458
1459 // for the time being, switch field off to protect rdv4.0
1460 // note: this prevents using hf 15 cmd with s option - which isn't implemented yet anyway
1461 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
1462 LED_D_OFF();
1463
1464 LED_A_OFF();
1465}
1466
1467
1468// Simulate an ISO15693 TAG.
1469// For Inventory command: print command and send Inventory Response with given UID
1470// TODO: interpret other reader commands and send appropriate response
1471void SimTagIso15693(uint32_t parameter, uint8_t *uid)
1472{
1473 LEDsoff();
1474 LED_A_ON();
1475
1476 FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
1477 SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
1478 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_NO_MODULATION);
1479 FpgaSetupSsc(FPGA_MAJOR_MODE_HF_SIMULATOR);
1480
1481 StartCountSspClk();
1482
1483 uint8_t cmd[ISO15693_MAX_COMMAND_LENGTH];
1484
1485 // Build a suitable response to the reader INVENTORY command
1486 BuildInventoryResponse(uid);
1487
1488 // Listen to reader
1489 while (!BUTTON_PRESS()) {
1490 uint32_t eof_time = 0, start_time = 0;
1491 int cmd_len = GetIso15693CommandFromReader(cmd, sizeof(cmd), &eof_time);
1492
1493 if ((cmd_len >= 5) && (cmd[0] & ISO15693_REQ_INVENTORY) && (cmd[1] == ISO15693_INVENTORY)) { // TODO: check more flags
1494 bool slow = !(cmd[0] & ISO15693_REQ_DATARATE_HIGH);
1495 start_time = eof_time + DELAY_ISO15693_VCD_TO_VICC_SIM - DELAY_ARM_TO_READER_SIM;
1496 TransmitTo15693Reader(ToSend, ToSendMax, start_time, slow);
1497 }
1498
1499 Dbprintf("%d bytes read from reader:", cmd_len);
1500 Dbhexdump(cmd_len, cmd, false);
1501 }
1502
1503 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
1504 LEDsoff();
1505}
1506
1507
1508// Since there is no standardized way of reading the AFI out of a tag, we will brute force it
1509// (some manufactures offer a way to read the AFI, though)
1510void BruteforceIso15693Afi(uint32_t speed)
1511{
1512 LEDsoff();
1513 LED_A_ON();
1514
1515 uint8_t data[6];
1516 uint8_t recv[ISO15693_MAX_RESPONSE_LENGTH];
1517
1518 int datalen=0, recvlen=0;
1519
1520 Iso15693InitReader();
1521 StartCountSspClk();
1522
1523 // first without AFI
1524 // Tags should respond without AFI and with AFI=0 even when AFI is active
1525
1526 data[0] = ISO15693_REQ_DATARATE_HIGH | ISO15693_REQ_INVENTORY | ISO15693_REQINV_SLOT1;
1527 data[1] = ISO15693_INVENTORY;
1528 data[2] = 0; // mask length
1529 datalen = AddCrc(data,3);
1530 recvlen = SendDataTag(data, datalen, false, speed, recv, sizeof(recv), 0);
1531 uint32_t start_time = GetCountSspClk() + DELAY_ISO15693_VICC_TO_VCD_READER;
1532 WDT_HIT();
1533 if (recvlen>=12) {
1534 Dbprintf("NoAFI UID=%s", sprintUID(NULL, &recv[2]));
1535 }
1536
1537 // now with AFI
1538
1539 data[0] = ISO15693_REQ_DATARATE_HIGH | ISO15693_REQ_INVENTORY | ISO15693_REQINV_AFI | ISO15693_REQINV_SLOT1;
1540 data[1] = ISO15693_INVENTORY;
1541 data[2] = 0; // AFI
1542 data[3] = 0; // mask length
1543
1544 for (int i = 0; i < 256; i++) {
1545 data[2] = i & 0xFF;
1546 datalen = AddCrc(data,4);
1547 recvlen = SendDataTag(data, datalen, false, speed, recv, sizeof(recv), start_time);
1548 start_time = GetCountSspClk() + DELAY_ISO15693_VICC_TO_VCD_READER;
1549 WDT_HIT();
1550 if (recvlen >= 12) {
1551 Dbprintf("AFI=%i UID=%s", i, sprintUID(NULL, &recv[2]));
1552 }
1553 }
1554 Dbprintf("AFI Bruteforcing done.");
1555
1556 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
1557 LEDsoff();
1558}
1559
1560// Allows to directly send commands to the tag via the client
1561void DirectTag15693Command(uint32_t datalen, uint32_t speed, uint32_t recv, uint8_t data[]) {
1562
1563 int recvlen = 0;
1564 uint8_t recvbuf[ISO15693_MAX_RESPONSE_LENGTH];
1565
1566 LED_A_ON();
1567
1568 if (DEBUG) {
1569 Dbprintf("SEND:");
1570 Dbhexdump(datalen, data, false);
1571 }
1572
1573 recvlen = SendDataTag(data, datalen, true, speed, (recv?recvbuf:NULL), sizeof(recvbuf), 0);
1574
1575 if (recv) {
1576 if (DEBUG) {
1577 Dbprintf("RECV:");
1578 Dbhexdump(recvlen, recvbuf, false);
1579 DbdecodeIso15693Answer(recvlen, recvbuf);
1580 }
1581
1582 cmd_send(CMD_ACK, recvlen>ISO15693_MAX_RESPONSE_LENGTH?ISO15693_MAX_RESPONSE_LENGTH:recvlen, 0, 0, recvbuf, ISO15693_MAX_RESPONSE_LENGTH);
1583
1584 }
1585
1586 // for the time being, switch field off to protect rdv4.0
1587 // note: this prevents using hf 15 cmd with s option - which isn't implemented yet anyway
1588 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
1589 LED_D_OFF();
1590
1591 LED_A_OFF();
1592}
1593
1594//-----------------------------------------------------------------------------
1595// Work with "magic Chinese" card.
1596//
1597//-----------------------------------------------------------------------------
1598
1599// Set the UID to the tag (based on Iceman work).
1600void SetTag15693Uid(uint8_t *uid)
1601{
1602 uint8_t cmd[4][9] = {0x00};
1603
1604 uint16_t crc;
1605
1606 int recvlen = 0;
1607 uint8_t recvbuf[ISO15693_MAX_RESPONSE_LENGTH];
1608
1609 LED_A_ON();
1610
1611 // Command 1 : 02213E00000000
1612 cmd[0][0] = 0x02;
1613 cmd[0][1] = 0x21;
1614 cmd[0][2] = 0x3e;
1615 cmd[0][3] = 0x00;
1616 cmd[0][4] = 0x00;
1617 cmd[0][5] = 0x00;
1618 cmd[0][6] = 0x00;
1619
1620 // Command 2 : 02213F69960000
1621 cmd[1][0] = 0x02;
1622 cmd[1][1] = 0x21;
1623 cmd[1][2] = 0x3f;
1624 cmd[1][3] = 0x69;
1625 cmd[1][4] = 0x96;
1626 cmd[1][5] = 0x00;
1627 cmd[1][6] = 0x00;
1628
1629 // Command 3 : 022138u8u7u6u5 (where uX = uid byte X)
1630 cmd[2][0] = 0x02;
1631 cmd[2][1] = 0x21;
1632 cmd[2][2] = 0x38;
1633 cmd[2][3] = uid[7];
1634 cmd[2][4] = uid[6];
1635 cmd[2][5] = uid[5];
1636 cmd[2][6] = uid[4];
1637
1638 // Command 4 : 022139u4u3u2u1 (where uX = uid byte X)
1639 cmd[3][0] = 0x02;
1640 cmd[3][1] = 0x21;
1641 cmd[3][2] = 0x39;
1642 cmd[3][3] = uid[3];
1643 cmd[3][4] = uid[2];
1644 cmd[3][5] = uid[1];
1645 cmd[3][6] = uid[0];
1646
1647 for (int i=0; i<4; i++) {
1648 // Add the CRC
1649 crc = Crc(cmd[i], 7);
1650 cmd[i][7] = crc & 0xff;
1651 cmd[i][8] = crc >> 8;
1652
1653 if (DEBUG) {
1654 Dbprintf("SEND:");
1655 Dbhexdump(sizeof(cmd[i]), cmd[i], false);
1656 }
1657
1658 recvlen = SendDataTag(cmd[i], sizeof(cmd[i]), true, 1, recvbuf, sizeof(recvbuf), 0);
1659
1660 if (DEBUG) {
1661 Dbprintf("RECV:");
1662 Dbhexdump(recvlen, recvbuf, false);
1663 DbdecodeIso15693Answer(recvlen, recvbuf);
1664 }
1665
1666 cmd_send(CMD_ACK, recvlen>ISO15693_MAX_RESPONSE_LENGTH?ISO15693_MAX_RESPONSE_LENGTH:recvlen, 0, 0, recvbuf, ISO15693_MAX_RESPONSE_LENGTH);
1667 }
1668
1669 LED_D_OFF();
1670
1671 LED_A_OFF();
1672}
1673
1674
1675
1676// --------------------------------------------------------------------
1677// -- Misc & deprecated functions
1678// --------------------------------------------------------------------
1679
1680/*
1681
1682// do not use; has a fix UID
1683static void __attribute__((unused)) BuildSysInfoRequest(uint8_t *uid)
1684{
1685 uint8_t cmd[12];
1686
1687 uint16_t crc;
1688 // If we set the Option_Flag in this request, the VICC will respond with the security status of the block
1689 // followed by the block data
1690 // one sub-carrier, inventory, 1 slot, fast rate
1691 cmd[0] = (1 << 5) | (1 << 1); // no SELECT bit
1692 // System Information command code
1693 cmd[1] = 0x2B;
1694 // UID may be optionally specified here
1695 // 64-bit UID
1696 cmd[2] = 0x32;
1697 cmd[3]= 0x4b;
1698 cmd[4] = 0x03;
1699 cmd[5] = 0x01;
1700 cmd[6] = 0x00;
1701 cmd[7] = 0x10;
1702 cmd[8] = 0x05;
1703 cmd[9]= 0xe0; // always e0 (not exactly unique)
1704 //Now the CRC
1705 crc = Crc(cmd, 10); // the crc needs to be calculated over 2 bytes
1706 cmd[10] = crc & 0xff;
1707 cmd[11] = crc >> 8;
1708
1709 CodeIso15693AsReader(cmd, sizeof(cmd));
1710}
1711
1712
1713// do not use; has a fix UID
1714static void __attribute__((unused)) BuildReadMultiBlockRequest(uint8_t *uid)
1715{
1716 uint8_t cmd[14];
1717
1718 uint16_t crc;
1719 // If we set the Option_Flag in this request, the VICC will respond with the security status of the block
1720 // followed by the block data
1721 // one sub-carrier, inventory, 1 slot, fast rate
1722 cmd[0] = (1 << 5) | (1 << 1); // no SELECT bit
1723 // READ Multi BLOCK command code
1724 cmd[1] = 0x23;
1725 // UID may be optionally specified here
1726 // 64-bit UID
1727 cmd[2] = 0x32;
1728 cmd[3]= 0x4b;
1729 cmd[4] = 0x03;
1730 cmd[5] = 0x01;
1731 cmd[6] = 0x00;
1732 cmd[7] = 0x10;
1733 cmd[8] = 0x05;
1734 cmd[9]= 0xe0; // always e0 (not exactly unique)
1735 // First Block number to read
1736 cmd[10] = 0x00;
1737 // Number of Blocks to read
1738 cmd[11] = 0x2f; // read quite a few
1739 //Now the CRC
1740 crc = Crc(cmd, 12); // the crc needs to be calculated over 2 bytes
1741 cmd[12] = crc & 0xff;
1742 cmd[13] = crc >> 8;
1743
1744 CodeIso15693AsReader(cmd, sizeof(cmd));
1745}
1746
1747// do not use; has a fix UID
1748static void __attribute__((unused)) BuildArbitraryRequest(uint8_t *uid,uint8_t CmdCode)
1749{
1750 uint8_t cmd[14];
1751
1752 uint16_t crc;
1753 // If we set the Option_Flag in this request, the VICC will respond with the security status of the block
1754 // followed by the block data
1755 // one sub-carrier, inventory, 1 slot, fast rate
1756 cmd[0] = (1 << 5) | (1 << 1); // no SELECT bit
1757 // READ BLOCK command code
1758 cmd[1] = CmdCode;
1759 // UID may be optionally specified here
1760 // 64-bit UID
1761 cmd[2] = 0x32;
1762 cmd[3]= 0x4b;
1763 cmd[4] = 0x03;
1764 cmd[5] = 0x01;
1765 cmd[6] = 0x00;
1766 cmd[7] = 0x10;
1767 cmd[8] = 0x05;
1768 cmd[9]= 0xe0; // always e0 (not exactly unique)
1769 // Parameter
1770 cmd[10] = 0x00;
1771 cmd[11] = 0x0a;
1772
1773// cmd[12] = 0x00;
1774// cmd[13] = 0x00; //Now the CRC
1775 crc = Crc(cmd, 12); // the crc needs to be calculated over 2 bytes
1776 cmd[12] = crc & 0xff;
1777 cmd[13] = crc >> 8;
1778
1779 CodeIso15693AsReader(cmd, sizeof(cmd));
1780}
1781
1782// do not use; has a fix UID
1783static void __attribute__((unused)) BuildArbitraryCustomRequest(uint8_t uid[], uint8_t CmdCode)
1784{
1785 uint8_t cmd[14];
1786
1787 uint16_t crc;
1788 // If we set the Option_Flag in this request, the VICC will respond with the security status of the block
1789 // followed by the block data
1790 // one sub-carrier, inventory, 1 slot, fast rate
1791 cmd[0] = (1 << 5) | (1 << 1); // no SELECT bit
1792 // READ BLOCK command code
1793 cmd[1] = CmdCode;
1794 // UID may be optionally specified here
1795 // 64-bit UID
1796 cmd[2] = 0x32;
1797 cmd[3]= 0x4b;
1798 cmd[4] = 0x03;
1799 cmd[5] = 0x01;
1800 cmd[6] = 0x00;
1801 cmd[7] = 0x10;
1802 cmd[8] = 0x05;
1803 cmd[9]= 0xe0; // always e0 (not exactly unique)
1804 // Parameter
1805 cmd[10] = 0x05; // for custom codes this must be manufacturer code
1806 cmd[11] = 0x00;
1807
1808// cmd[12] = 0x00;
1809// cmd[13] = 0x00; //Now the CRC
1810 crc = Crc(cmd, 12); // the crc needs to be calculated over 2 bytes
1811 cmd[12] = crc & 0xff;
1812 cmd[13] = crc >> 8;
1813
1814 CodeIso15693AsReader(cmd, sizeof(cmd));
1815}
1816
1817
1818
1819
1820*/
1821
1822
Impressum, Datenschutz