]> git.zerfleddert.de Git - proxmark3-svn/blame - client/cmdhf14a.c
fixed iso14443a-4 similation, got rid of many ugly memory allocation issues
[proxmark3-svn] / client / cmdhf14a.c
CommitLineData
a553f267 1//-----------------------------------------------------------------------------
f89c7050 2// 2011, Merlok
534983d7 3// Copyright (C) 2010 iZsh <izsh at fail0verflow.com>, Hagen Fritsch
a553f267 4//
5// This code is licensed to you under the terms of the GNU GPL, version 2 or,
6// at your option, any later version. See the LICENSE.txt file for the text of
7// the license.
8//-----------------------------------------------------------------------------
9// High frequency ISO14443A commands
10//-----------------------------------------------------------------------------
11
7fe9b0b7 12#include <stdio.h>
590f8ff9 13#include <stdlib.h>
7fe9b0b7 14#include <string.h>
f397b5cc 15#include <unistd.h>
20f9a2a1 16#include "util.h"
7fe9b0b7 17#include "iso14443crc.h"
18#include "data.h"
28fdb04f 19//#include "proxusb.h"
902cb3c0 20#include "proxmark3.h"
7fe9b0b7 21#include "ui.h"
22#include "cmdparser.h"
23#include "cmdhf14a.h"
534983d7 24#include "common.h"
20f9a2a1 25#include "cmdmain.h"
902cb3c0 26#include "mifare.h"
7fe9b0b7 27
28static int CmdHelp(const char *Cmd);
5f6d6c90 29static void waitCmd(uint8_t iLen);
7fe9b0b7 30
31int CmdHF14AList(const char *Cmd)
32{
33 uint8_t got[1920];
db09cb3a 34 GetFromBigBuf(got,sizeof(got),0);
902cb3c0 35 WaitForResponse(CMD_ACK,NULL);
7fe9b0b7 36
37 PrintAndLog("recorded activity:");
38 PrintAndLog(" ETU :rssi: who bytes");
39 PrintAndLog("---------+----+----+-----------");
40
41 int i = 0;
42 int prev = -1;
43
44 for (;;) {
45 if(i >= 1900) {
46 break;
47 }
48
49 bool isResponse;
50 int timestamp = *((uint32_t *)(got+i));
51 if (timestamp & 0x80000000) {
52 timestamp &= 0x7fffffff;
53 isResponse = 1;
54 } else {
55 isResponse = 0;
56 }
57
58 int metric = 0;
59 int parityBits = *((uint32_t *)(got+i+4));
60 // 4 bytes of additional information...
61 // maximum of 32 additional parity bit information
62 //
63 // TODO:
64 // at each quarter bit period we can send power level (16 levels)
65 // or each half bit period in 256 levels.
66
67
68 int len = got[i+8];
69
70 if (len > 100) {
71 break;
72 }
73 if (i + len >= 1900) {
74 break;
75 }
76
77 uint8_t *frame = (got+i+9);
78
79 // Break and stick with current result if buffer was not completely full
80 if (frame[0] == 0x44 && frame[1] == 0x44 && frame[3] == 0x44) { break; }
81
82 char line[1000] = "";
83 int j;
84 for (j = 0; j < len; j++) {
85 int oddparity = 0x01;
86 int k;
87
88 for (k=0;k<8;k++) {
89 oddparity ^= (((frame[j] & 0xFF) >> k) & 0x01);
90 }
91
92 //if((parityBits >> (len - j - 1)) & 0x01) {
93 if (isResponse && (oddparity != ((parityBits >> (len - j - 1)) & 0x01))) {
94 sprintf(line+(j*4), "%02x! ", frame[j]);
95 }
96 else {
97 sprintf(line+(j*4), "%02x ", frame[j]);
98 }
99 }
100
101 char *crc;
102 crc = "";
103 if (len > 2) {
104 uint8_t b1, b2;
105 for (j = 0; j < (len - 1); j++) {
106 // gives problems... search for the reason..
107 /*if(frame[j] == 0xAA) {
108 switch(frame[j+1]) {
109 case 0x01:
110 crc = "[1] Two drops close after each other";
111 break;
112 case 0x02:
113 crc = "[2] Potential SOC with a drop in second half of bitperiod";
114 break;
115 case 0x03:
116 crc = "[3] Segment Z after segment X is not possible";
117 break;
118 case 0x04:
119 crc = "[4] Parity bit of a fully received byte was wrong";
120 break;
121 default:
122 crc = "[?] Unknown error";
123 break;
124 }
125 break;
126 }*/
127 }
128
129 if (strlen(crc)==0) {
130 ComputeCrc14443(CRC_14443_A, frame, len-2, &b1, &b2);
131 if (b1 != frame[len-2] || b2 != frame[len-1]) {
132 crc = (isResponse & (len < 6)) ? "" : " !crc";
133 } else {
134 crc = "";
135 }
136 }
137 } else {
138 crc = ""; // SHORT
139 }
140
141 char metricString[100];
142 if (isResponse) {
143 sprintf(metricString, "%3d", metric);
144 } else {
145 strcpy(metricString, " ");
146 }
147
148 PrintAndLog(" +%7d: %s: %s %s %s",
149 (prev < 0 ? 0 : (timestamp - prev)),
150 metricString,
151 (isResponse ? "TAG" : " "), line, crc);
152
153 prev = timestamp;
154 i += (len + 9);
155 }
f89c7050 156 return 0;
7fe9b0b7 157}
158
534983d7 159void iso14a_set_timeout(uint32_t timeout) {
160 UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_SET_TIMEOUT, 0, timeout}};
161 SendCommand(&c);
162}
163
7fe9b0b7 164int CmdHF14AReader(const char *Cmd)
165{
534983d7 166 UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT, 0, 0}};
167 SendCommand(&c);
902cb3c0 168
169 UsbCommand resp;
170 WaitForResponse(CMD_ACK,&resp);
171
79a73ab2 172 iso14a_card_select_t *card = (iso14a_card_select_t *)resp.d.asBytes;
534983d7 173
902cb3c0 174 if(resp.arg[0] == 0) {
534983d7 175 PrintAndLog("iso14443a card select failed");
176 return 0;
177 }
178
179 PrintAndLog("ATQA : %02x %02x", card->atqa[0], card->atqa[1]);
79a73ab2 180 PrintAndLog(" UID : %s", sprint_hex(card->uid, card->uidlen));
902cb3c0 181 PrintAndLog(" SAK : %02x [%d]", card->sak, resp.arg[0]);
713e7ffb 182
9ca155ba 183 switch (card->sak) {
79a73ab2 184 case 0x00: PrintAndLog("TYPE : NXP MIFARE Ultralight | Ultralight C"); break;
185 case 0x04: PrintAndLog("TYPE : NXP MIFARE (various !DESFire !DESFire EV1)"); break;
713e7ffb 186
79a73ab2 187 case 0x08: PrintAndLog("TYPE : NXP MIFARE CLASSIC 1k | Plus 2k"); break;
188 case 0x09: PrintAndLog("TYPE : NXP MIFARE Mini 0.3k"); break;
189 case 0x10: PrintAndLog("TYPE : NXP MIFARE Plus 2k"); break;
190 case 0x11: PrintAndLog("TYPE : NXP MIFARE Plus 4k"); break;
191 case 0x18: PrintAndLog("TYPE : NXP MIFARE Classic 4k | Plus 4k"); break;
192 case 0x20: PrintAndLog("TYPE : NXP MIFARE DESFire 4k | DESFire EV1 2k/4k/8k | Plus 2k/4k | JCOP 31/41"); break;
193 case 0x24: PrintAndLog("TYPE : NXP MIFARE DESFire | DESFire EV1"); break;
194 case 0x28: PrintAndLog("TYPE : JCOP31 or JCOP41 v2.3.1"); break;
195 case 0x38: PrintAndLog("TYPE : Nokia 6212 or 6131 MIFARE CLASSIC 4K"); break;
196 case 0x88: PrintAndLog("TYPE : Infineon MIFARE CLASSIC 1K"); break;
197 case 0x98: PrintAndLog("TYPE : Gemplus MPCOS"); break;
9ca155ba
M
198 default: ;
199 }
902cb3c0 200 if(resp.arg[0] == 1) {
561f7c11 201 bool ta1 = 0, tb1 = 0, tc1 = 0;
202 int pos;
203
534983d7 204 PrintAndLog(" ATS : %s", sprint_hex(card->ats, card->ats_len));
561f7c11 205 if (card->ats_len > 0) {
206 PrintAndLog(" - TL : length is %d bytes", card->ats[0]);
207 }
208 if (card->ats_len > 1) {
209 ta1 = (card->ats[1] & 0x10) == 0x10;
210 tb1 = (card->ats[1] & 0x20) == 0x20;
211 tc1 = (card->ats[1] & 0x40) == 0x40;
212 PrintAndLog(" - T0 : TA1 is%s present, TB1 is%s present, "
213 "TC1 is%s present, FSCI is %d",
214 (ta1 ? "" : " NOT"), (tb1 ? "" : " NOT"), (tc1 ? "" : " NOT"),
215 (card->ats[1] & 0x0f));
216 }
217 pos = 2;
218 if (ta1 && card->ats_len > pos) {
219 char dr[16], ds[16];
220 dr[0] = ds[0] = '\0';
221 if (card->ats[pos] & 0x10) strcat(ds, "2, ");
222 if (card->ats[pos] & 0x20) strcat(ds, "4, ");
223 if (card->ats[pos] & 0x40) strcat(ds, "8, ");
224 if (card->ats[pos] & 0x01) strcat(dr, "2, ");
225 if (card->ats[pos] & 0x02) strcat(dr, "4, ");
226 if (card->ats[pos] & 0x04) strcat(dr, "8, ");
227 if (strlen(ds) != 0) ds[strlen(ds) - 2] = '\0';
228 if (strlen(dr) != 0) dr[strlen(dr) - 2] = '\0';
229 PrintAndLog(" - TA1 : different divisors are%s supported, "
230 "DR: [%s], DS: [%s]",
231 (card->ats[pos] & 0x80 ? " NOT" : ""), dr, ds);
232 pos++;
233 }
234 if (tb1 && card->ats_len > pos) {
235 PrintAndLog(" - TB1 : SFGI = %d, FWI = %d",
236 (card->ats[pos] & 0x08),
237 (card->ats[pos] & 0x80) >> 4);
238 pos++;
239 }
240 if (tc1 && card->ats_len > pos) {
241 PrintAndLog(" - TC1 : NAD is%s supported, CID is%s supported",
242 (card->ats[pos] & 0x01) ? "" : " NOT",
243 (card->ats[pos] & 0x02) ? "" : " NOT");
244 pos++;
245 }
246 if (card->ats_len > pos) {
247 char *tip = "";
248 if (card->ats_len - pos > 7) {
249 if (memcmp(card->ats + pos, "\xC1\x05\x2F\x2F\x01\xBC\xD6", 7) == 0) {
250 tip = "-> MIFARE Plus X 2K or 4K";
251 } else if (memcmp(card->ats + pos, "\xC1\x05\x2F\x2F\x00\x35\xC7", 7) == 0) {
252 tip = "-> MIFARE Plus S 2K or 4K";
253 }
254 }
255 PrintAndLog(" - HB : %s%s", sprint_hex(card->ats + pos, card->ats_len - pos - 2), tip);
256 if (card->ats[pos] == 0xC1) {
257 PrintAndLog(" c1 -> Mifare or (multiple) virtual cards of various type");
258 PrintAndLog(" %02x -> Length is %d bytes",
259 card->ats[pos + 1], card->ats[pos + 1]);
260 switch (card->ats[pos + 2] & 0xf0) {
261 case 0x10:
262 PrintAndLog(" 1x -> MIFARE DESFire");
263 break;
264 case 0x20:
265 PrintAndLog(" 2x -> MIFARE Plus");
266 break;
267 }
268 switch (card->ats[pos + 2] & 0x0f) {
269 case 0x00:
270 PrintAndLog(" x0 -> <1 kByte");
271 break;
272 case 0x01:
273 PrintAndLog(" x0 -> 1 kByte");
274 break;
275 case 0x02:
276 PrintAndLog(" x0 -> 2 kByte");
277 break;
278 case 0x03:
279 PrintAndLog(" x0 -> 4 kByte");
280 break;
281 case 0x04:
282 PrintAndLog(" x0 -> 8 kByte");
283 break;
284 }
285 switch (card->ats[pos + 3] & 0xf0) {
286 case 0x00:
287 PrintAndLog(" 0x -> Engineering sample");
288 break;
289 case 0x20:
290 PrintAndLog(" 2x -> Released");
291 break;
292 }
293 switch (card->ats[pos + 3] & 0x0f) {
294 case 0x00:
295 PrintAndLog(" x0 -> Generation 1");
296 break;
297 case 0x01:
298 PrintAndLog(" x1 -> Generation 2");
299 break;
300 case 0x02:
301 PrintAndLog(" x2 -> Generation 3");
302 break;
303 }
304 switch (card->ats[pos + 4] & 0x0f) {
305 case 0x00:
306 PrintAndLog(" x0 -> Only VCSL supported");
307 break;
308 case 0x01:
309 PrintAndLog(" x1 -> VCS, VCSL, and SVC supported");
310 break;
311 case 0x0E:
312 PrintAndLog(" xE -> no VCS command supported");
313 break;
314 }
315 }
316 }
79a73ab2 317 } else {
318 PrintAndLog("proprietary non iso14443a-4 card found, RATS not supported");
319 }
534983d7 320
902cb3c0 321 return resp.arg[0];
7fe9b0b7 322}
323
db22dfe6 324// Collect ISO14443 Type A UIDs
325int CmdHF14ACUIDs(const char *Cmd)
326{
327 // requested number of UIDs
328 int n = atoi(Cmd);
329 // collect at least 1 (e.g. if no parameter was given)
330 n = n > 0 ? n : 1;
331
332 PrintAndLog("Collecting %d UIDs", n);
333 PrintAndLog("Start: %u", time(NULL));
334 // repeat n times
335 for (int i = 0; i < n; i++) {
336 // execute anticollision procedure
337 UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT, 0, 0}};
338 SendCommand(&c);
902cb3c0 339
340 UsbCommand resp;
341 WaitForResponse(CMD_ACK,&resp);
342
343 uint8_t *uid = resp.d.asBytes;
db22dfe6 344 iso14a_card_select_t *card = (iso14a_card_select_t *)(uid + 12);
345
346 // check if command failed
902cb3c0 347 if (resp.arg[0] == 0) {
db22dfe6 348 PrintAndLog("Card select failed.");
349 } else {
350 // check if UID is 4 bytes
351 if ((card->atqa[1] & 0xC0) == 0) {
352 PrintAndLog("%02X%02X%02X%02X",
353 *uid, *(uid + 1), *(uid + 2), *(uid + 3));
354 } else {
355 PrintAndLog("UID longer than 4 bytes");
356 }
357 }
358 }
359 PrintAndLog("End: %u", time(NULL));
360
361 return 1;
362}
363
7fe9b0b7 364// ## simulate iso14443a tag
365// ## greg - added ability to specify tag UID
366int CmdHF14ASim(const char *Cmd)
81cd0474 367{
368 UsbCommand c = {CMD_SIMULATE_TAG_ISO_14443a,{0,0,0}};
369
370 // Retrieve the tag type
371 uint8_t tagtype = param_get8ex(Cmd,0,0,10);
372
373 // When no argument was given, just print help message
374 if (tagtype == 0) {
375 PrintAndLog("");
376 PrintAndLog(" Emulating ISO/IEC 14443 type A tag with 4 or 7 byte UID");
377 PrintAndLog("");
378 PrintAndLog(" syntax: hf 14a sim <type> <uid>");
379 PrintAndLog(" types: 1 = MIFARE Classic");
380 PrintAndLog(" 2 = MIFARE Ultralight");
381 PrintAndLog(" 3 = MIFARE DESFIRE");
382 PrintAndLog(" 4 = ISO/IEC 14443-4");
383 PrintAndLog("");
384 return 1;
385 }
386
387 // Store the tag type
388 c.arg[0] = tagtype;
389
390 // Retrieve the full 4 or 7 byte long uid
391 uint64_t long_uid = param_get64ex(Cmd,1,0,16);
392
393 // Are we handling the (optional) second part uid?
394 if (long_uid > 0xffffffff) {
125a98a1 395 PrintAndLog("Emulating ISO/IEC 14443 type A tag with 7 byte UID (%014"llx")",long_uid);
81cd0474 396 // Store the second part
397 c.arg[2] = (long_uid & 0xffffffff);
398 long_uid >>= 32;
399 // Store the first part, ignore the first byte, it is replaced by cascade byte (0x88)
400 c.arg[1] = (long_uid & 0xffffff);
401 } else {
402 PrintAndLog("Emulating ISO/IEC 14443 type A tag with 4 byte UID (%08x)",long_uid);
403 // Only store the first part
404 c.arg[1] = long_uid & 0xffffffff;
405 }
406/*
407 // At lease save the mandatory first part of the UID
408 c.arg[0] = long_uid & 0xffffffff;
409
410
411 // At lease save the mandatory first part of the UID
412 c.arg[0] = long_uid & 0xffffffff;
413
414 if (c.arg[1] == 0) {
415 PrintAndLog("Emulating ISO/IEC 14443 type A tag with UID %01d %08x %08x",c.arg[0],c.arg[1],c.arg[2]);
416 }
417
418 switch (c.arg[0]) {
419 case 1: {
420 PrintAndLog("Emulating ISO/IEC 14443-3 type A tag with 4 byte UID");
421 UsbCommand c = {CMD_SIMULATE_TAG_ISO_14443a,param_get32ex(Cmd,0,0,10),param_get32ex(Cmd,1,0,16),param_get32ex(Cmd,2,0,16)};
422 } break;
423 case 2: {
424 PrintAndLog("Emulating ISO/IEC 14443-4 type A tag with 7 byte UID");
425 } break;
426 default: {
427 PrintAndLog("Error: unkown tag type (%d)",c.arg[0]);
428 PrintAndLog("syntax: hf 14a sim <uid>",c.arg[0]);
429 PrintAndLog(" type1: 4 ",c.arg[0]);
430
431 return 1;
432 } break;
433 }
434*/
435/*
7fe9b0b7 436 unsigned int hi = 0, lo = 0;
437 int n = 0, i = 0;
438 while (sscanf(&Cmd[i++], "%1x", &n ) == 1) {
439 hi= (hi << 4) | (lo >> 28);
440 lo= (lo << 4) | (n & 0xf);
441 }
81cd0474 442*/
443// UsbCommand c = {CMD_SIMULATE_TAG_ISO_14443a,param_get32ex(Cmd,0,0,10),param_get32ex(Cmd,1,0,16),param_get32ex(Cmd,2,0,16)};
444// PrintAndLog("Emulating ISO/IEC 14443 type A tag with UID %01d %08x %08x",c.arg[0],c.arg[1],c.arg[2]);
7fe9b0b7 445 SendCommand(&c);
446 return 0;
447}
448
5cd9ec01
M
449int CmdHF14ASnoop(const char *Cmd) {
450 int param = 0;
451
452 if (param_getchar(Cmd, 0) == 'h') {
453 PrintAndLog("It get data from the field and saves it into command buffer.");
454 PrintAndLog("Buffer accessible from command hf 14a list.");
455 PrintAndLog("Usage: hf 14a snoop [c][r]");
456 PrintAndLog("c - triggered by first data from card");
457 PrintAndLog("r - triggered by first 7-bit request from reader (REQ,WUP,...)");
458 PrintAndLog("sample: hf 14a snoop c r");
459 return 0;
460 }
461
462 for (int i = 0; i < 2; i++) {
463 char ctmp = param_getchar(Cmd, i);
464 if (ctmp == 'c' || ctmp == 'C') param |= 0x01;
465 if (ctmp == 'r' || ctmp == 'R') param |= 0x02;
466 }
467
468 UsbCommand c = {CMD_SNOOP_ISO_14443a, {param, 0, 0}};
7fe9b0b7 469 SendCommand(&c);
470 return 0;
471}
472
5f6d6c90 473int CmdHF14ACmdRaw(const char *cmd) {
474 UsbCommand c = {CMD_READER_ISO_14443a, {0, 0, 0}};
475 uint8_t reply=1;
476 uint8_t crc=0;
477 uint8_t power=0;
478 uint8_t active=0;
479 uint8_t active_select=0;
480 uint16_t numbits=0;
481 char buf[5]="";
482 int i=0;
483 uint8_t data[100];
484 unsigned int datalen=0, temp;
485
486 if (strlen(cmd)<2) {
487 PrintAndLog("Usage: hf 14a raw [-r] [-c] [-p] [-f] [-b] <number of bits> <0A 0B 0C ... hex>");
488 PrintAndLog(" -r do not read response");
489 PrintAndLog(" -c calculate and append CRC");
490 PrintAndLog(" -p leave the signal field ON after receive");
491 PrintAndLog(" -a active signal field ON without select");
492 PrintAndLog(" -s active signal field ON with select");
493 PrintAndLog(" -b number of bits to send. Useful for send partial byte");
494 return 0;
495 }
496
497 // strip
498 while (*cmd==' ' || *cmd=='\t') cmd++;
499
500 while (cmd[i]!='\0') {
501 if (cmd[i]==' ' || cmd[i]=='\t') { i++; continue; }
502 if (cmd[i]=='-') {
503 switch (cmd[i+1]) {
504 case 'r':
505 reply=0;
506 break;
507 case 'c':
508 crc=1;
509 break;
510 case 'p':
511 power=1;
512 break;
513 case 'a':
514 active=1;
515 break;
516 case 's':
517 active_select=1;
518 break;
519 case 'b':
520 sscanf(cmd+i+2,"%d",&temp);
521 numbits = temp & 0xFFFF;
522 i+=3;
523 while(cmd[i]!=' ' && cmd[i]!='\0') { i++; }
524 i-=2;
525 break;
526 default:
527 PrintAndLog("Invalid option");
528 return 0;
529 }
530 i+=2;
531 continue;
532 }
533 if ((cmd[i]>='0' && cmd[i]<='9') ||
534 (cmd[i]>='a' && cmd[i]<='f') ||
535 (cmd[i]>='A' && cmd[i]<='F') ) {
536 buf[strlen(buf)+1]=0;
537 buf[strlen(buf)]=cmd[i];
538 i++;
539
540 if (strlen(buf)>=2) {
541 sscanf(buf,"%x",&temp);
542 data[datalen]=(uint8_t)(temp & 0xff);
543 datalen++;
544 *buf=0;
545 }
546 continue;
547 }
548 PrintAndLog("Invalid char on input");
549 return 0;
550 }
551 if(crc && datalen>0)
552 {
553 uint8_t first, second;
554 ComputeCrc14443(CRC_14443_A, data, datalen, &first, &second);
555 data[datalen++] = first;
556 data[datalen++] = second;
557 }
558
559 if(active || active_select)
560 {
561 c.arg[0] |= ISO14A_CONNECT;
562 if(active)
563 c.arg[0] |= ISO14A_NO_SELECT;
564 }
565 if(power)
566 c.arg[0] |= ISO14A_NO_DISCONNECT;
567 if(datalen>0)
568 c.arg[0] |= ISO14A_RAW;
569
570 c.arg[1] = datalen;
571 c.arg[2] = numbits;
572 memcpy(c.d.asBytes,data,datalen);
573
574 SendCommand(&c);
575
576 if (reply) {
577 if(active_select)
578 waitCmd(1);
579 if(datalen>0)
580 waitCmd(0);
581 } // if reply
582 return 0;
583}
584
585static void waitCmd(uint8_t iSelect)
586{
587 uint8_t *recv;
588 UsbCommand resp;
589 char *hexout;
590
591 if (WaitForResponseTimeout(CMD_ACK,&resp,1000)) {
592 recv = resp.d.asBytes;
593 uint8_t iLen = iSelect ? resp.arg[1] : resp.arg[0];
594 PrintAndLog("received %i octets",iLen);
595 if(!iLen)
596 return;
597 hexout = (char *)malloc(iLen * 3 + 1);
598 if (hexout != NULL) {
599 uint8_t first, second;
600 for (int i = 0; i < iLen; i++) { // data in hex
601 sprintf(&hexout[i * 3], "%02hX ", recv[i]);
602 }
603 PrintAndLog("%s", hexout);
604 free(hexout);
605 } else {
606 PrintAndLog("malloc failed your client has low memory?");
607 }
608 } else {
609 PrintAndLog("timeout while waiting for reply.");
610 }
611}
612
7fe9b0b7 613static command_t CommandTable[] =
614{
5acd09bd 615 {"help", CmdHelp, 1, "This help"},
616 {"list", CmdHF14AList, 0, "List ISO 14443a history"},
617 {"reader", CmdHF14AReader, 0, "Act like an ISO14443 Type A reader"},
618 {"cuids", CmdHF14ACUIDs, 0, "<n> Collect n>0 ISO14443 Type A UIDs in one go"},
619 {"sim", CmdHF14ASim, 0, "<UID> -- Fake ISO 14443a tag"},
620 {"snoop", CmdHF14ASnoop, 0, "Eavesdrop ISO 14443 Type A"},
5f6d6c90 621 {"raw", CmdHF14ACmdRaw, 0, "Send raw hex data to tag"},
7fe9b0b7 622 {NULL, NULL, 0, NULL}
623};
624
902cb3c0 625int CmdHF14A(const char *Cmd) {
f397b5cc 626 // flush
902cb3c0 627 WaitForResponseTimeout(CMD_ACK,NULL,100);
f397b5cc
M
628
629 // parse
7fe9b0b7 630 CmdsParse(CommandTable, Cmd);
631 return 0;
632}
633
634int CmdHelp(const char *Cmd)
635{
636 CmdsHelp(CommandTable);
637 return 0;
638}
Impressum, Datenschutz