]> git.zerfleddert.de Git - proxmark3-svn/blob - winsrc/command.cpp
- Restored the 'reset' command
[proxmark3-svn] / winsrc / command.cpp
1 //-----------------------------------------------------------------------------
2 // The actual command interpeter for what the user types at the command line.
3 // Jonathan Westhues, Sept 2005
4 // Edits by Gerhard de Koning Gans, Sep 2007 (##)
5 //-----------------------------------------------------------------------------
6 #include <windows.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <stdio.h>
10 #include <limits.h>
11 #include <math.h>
12
13 #include "prox.h"
14 #include "../common/iso14443_crc.c"
15
16 #define arraylen(x) (sizeof(x)/sizeof((x)[0]))
17
18 static int CmdHisamplest(char *str, int nrlow);
19
20 static void GetFromBigBuf(BYTE *dest, int bytes)
21 {
22 int n = bytes/4;
23
24 if(n % 48 != 0) {
25 PrintToScrollback("bad len in GetFromBigBuf");
26 return;
27 }
28
29 int i;
30 for(i = 0; i < n; i += 12) {
31 UsbCommand c;
32 c.cmd = CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K;
33 c.ext1 = i;
34 SendCommand(&c, FALSE);
35 ReceiveCommand(&c);
36 if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) {
37 PrintToScrollback("bad resp\n");
38 return;
39 }
40
41 memcpy(dest+(i*4), c.d.asBytes, 48);
42 }
43 }
44
45 static void CmdReset(char *str)
46 {
47 UsbCommand c;
48 c.cmd = CMD_HARDWARE_RESET;
49 SendCommand(&c, FALSE);
50 }
51
52
53 static void CmdQuit(char *str)
54 {
55 exit(0);
56 }
57
58 static void CmdHIDdemodFSK(char *str)
59 {
60 UsbCommand c;
61 c.cmd = CMD_HID_DEMOD_FSK;
62 SendCommand(&c, FALSE);
63 }
64
65 static void CmdTune(char *str)
66 {
67 UsbCommand c;
68 c.cmd = CMD_MEASURE_ANTENNA_TUNING;
69 SendCommand(&c, FALSE);
70 }
71
72 static void CmdHi15read(char *str)
73 {
74 UsbCommand c;
75 c.cmd = CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693;
76 SendCommand(&c, FALSE);
77 }
78
79 static void CmdHi14read(char *str)
80 {
81 UsbCommand c;
82 c.cmd = CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443;
83 c.ext1 = atoi(str);
84 SendCommand(&c, FALSE);
85 }
86
87
88 /* New command to read the contents of a SRI512 tag
89 * SRI512 tags are ISO14443-B modulated memory tags,
90 * this command just dumps the contents of the memory/
91 */
92 static void CmdSri512read(char *str)
93 {
94 UsbCommand c;
95 c.cmd = CMD_READ_SRI512_TAG;
96 c.ext1 = atoi(str);
97 SendCommand(&c, FALSE);
98 }
99
100 // ## New command
101 static void CmdHi14areader(char *str)
102 {
103 UsbCommand c;
104 c.cmd = CMD_READER_ISO_14443a;
105 c.ext1 = atoi(str);
106 SendCommand(&c, FALSE);
107 }
108
109 // ## New command
110 static void CmdHi15reader(char *str)
111 {
112 UsbCommand c;
113 c.cmd = CMD_READER_ISO_15693;
114 c.ext1 = atoi(str);
115 SendCommand(&c, FALSE);
116 }
117
118 // ## New command
119 static void CmdHi15tag(char *str)
120 {
121 UsbCommand c;
122 c.cmd = CMD_SIMTAG_ISO_15693;
123 c.ext1 = atoi(str);
124 SendCommand(&c, FALSE);
125 }
126
127 static void CmdHi14read_sim(char *str)
128 {
129 UsbCommand c;
130 c.cmd = CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443_SIM;
131 c.ext1 = atoi(str);
132 SendCommand(&c, FALSE);
133 }
134
135 static void CmdHi14readt(char *str)
136 {
137 UsbCommand c;
138 c.cmd = CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443;
139 c.ext1 = atoi(str);
140 SendCommand(&c, FALSE);
141
142 //CmdHisamplest(str);
143 while(CmdHisamplest(str,atoi(str))==0) {
144 c.cmd = CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443;
145 c.ext1 = atoi(str);
146 SendCommand(&c, FALSE);
147 }
148 RepaintGraphWindow();
149 }
150
151 static void CmdHisimlisten(char *str)
152 {
153 UsbCommand c;
154 c.cmd = CMD_SIMULATE_TAG_HF_LISTEN;
155 SendCommand(&c, FALSE);
156 }
157
158 static void CmdHi14sim(char *str)
159 {
160 UsbCommand c;
161 c.cmd = CMD_SIMULATE_TAG_ISO_14443;
162 SendCommand(&c, FALSE);
163 }
164
165
166
167 static void CmdHi14asim(char *str) // ## simulate iso14443a tag
168 { // ## greg - added ability to specify tag UID
169
170 unsigned int hi=0, lo=0;
171 int n=0, i=0;
172 UsbCommand c;
173
174 while (sscanf(&str[i++], "%1x", &n ) == 1) {
175 hi=(hi<<4)|(lo>>28);
176 lo=(lo<<4)|(n&0xf);
177 }
178
179 c.cmd = CMD_SIMULATE_TAG_ISO_14443a;
180 // c.ext should be set to *str or convert *str to the correct format for a uid
181 c.ext1 = hi;
182 c.ext2 = lo;
183 PrintToScrollback("Emulating 14443A TAG with UID %x%16x", hi, lo);
184 SendCommand(&c, FALSE);
185 }
186
187 static void CmdHi14snoop(char *str)
188 {
189 UsbCommand c;
190 c.cmd = CMD_SNOOP_ISO_14443;
191 SendCommand(&c, FALSE);
192 }
193
194 static void CmdHi14asnoop(char *str)
195 {
196 UsbCommand c;
197 c.cmd = CMD_SNOOP_ISO_14443a;
198 SendCommand(&c, FALSE);
199 }
200
201 static void CmdFPGAOff(char *str) // ## FPGA Control
202 {
203 UsbCommand c;
204 c.cmd = CMD_FPGA_MAJOR_MODE_OFF;
205 SendCommand(&c, FALSE);
206 }
207
208 static void CmdLosim(char *str)
209 {
210 int i;
211
212 for(i = 0; i < GraphTraceLen; i += 48) {
213 UsbCommand c;
214 int j;
215 for(j = 0; j < 48; j++) {
216 c.d.asBytes[j] = GraphBuffer[i+j];
217 }
218 c.cmd = CMD_DOWNLOADED_SIM_SAMPLES_125K;
219 c.ext1 = i;
220 SendCommand(&c, FALSE);
221 }
222
223 UsbCommand c;
224 c.cmd = CMD_SIMULATE_TAG_125K;
225 c.ext1 = GraphTraceLen;
226 SendCommand(&c, FALSE);
227 }
228
229 static void CmdLoread(char *str)
230 {
231 UsbCommand c;
232 // 'h' means higher-low-frequency, 134 kHz
233 if(*str == 'h') {
234 c.ext1 = 1;
235 } else if (*str == '\0') {
236 c.ext1 = 0;
237 } else {
238 PrintToScrollback("use 'loread' or 'loread h'");
239 return;
240 }
241 c.cmd = CMD_ACQUIRE_RAW_ADC_SAMPLES_125K;
242 SendCommand(&c, FALSE);
243 }
244
245 static void CmdLosamples(char *str)
246 {
247 int cnt = 0;
248 int i;
249 int n;
250
251 n=atoi(str);
252 if (n==0) n=128;
253 if (n>16000) n=16000;
254
255 for(i = 0; i < n; i += 12) {
256 UsbCommand c;
257 c.cmd = CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K;
258 c.ext1 = i;
259 SendCommand(&c, FALSE);
260 ReceiveCommand(&c);
261 if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) {
262 PrintToScrollback("bad resp\n");
263 return;
264 }
265 int j;
266 for(j = 0; j < 48; j++) {
267 GraphBuffer[cnt++] = ((int)c.d.asBytes[j]) - 128;
268 }
269 }
270 GraphTraceLen = n*4;
271 RepaintGraphWindow();
272 }
273
274 static void CmdBitsamples(char *str)
275 {
276 int cnt = 0;
277 int i;
278 int n;
279
280 n = 3072;
281 for(i = 0; i < n; i += 12) {
282 UsbCommand c;
283 c.cmd = CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K;
284 c.ext1 = i;
285 SendCommand(&c, FALSE);
286 ReceiveCommand(&c);
287 if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) {
288 PrintToScrollback("bad resp\n");
289 return;
290 }
291 int j, k;
292 for(j = 0; j < 48; j++) {
293 for(k = 0; k < 8; k++) {
294 if(c.d.asBytes[j] & (1 << (7 - k))) {
295 GraphBuffer[cnt++] = 1;
296 } else {
297 GraphBuffer[cnt++] = 0;
298 }
299 }
300 }
301 }
302 GraphTraceLen = cnt;
303 RepaintGraphWindow();
304 }
305
306 static void CmdHisamples(char *str)
307 {
308 int cnt = 0;
309 int i;
310 int n;
311 n = 1000;
312 for(i = 0; i < n; i += 12) {
313 UsbCommand c;
314 c.cmd = CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K;
315 c.ext1 = i;
316 SendCommand(&c, FALSE);
317 ReceiveCommand(&c);
318 if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) {
319 PrintToScrollback("bad resp\n");
320 return;
321 }
322 int j;
323 for(j = 0; j < 48; j++) {
324 GraphBuffer[cnt++] = (int)((BYTE)c.d.asBytes[j]);
325 }
326 }
327 GraphTraceLen = n*4;
328
329 RepaintGraphWindow();
330 }
331
332
333 static int CmdHisamplest(char *str, int nrlow)
334 {
335 int cnt = 0;
336 int t1, t2;
337 int i;
338 int n;
339 int hasbeennull;
340 int show;
341
342
343 n = 1000;
344 hasbeennull = 0;
345 for(i = 0; i < n; i += 12) {
346 UsbCommand c;
347 c.cmd = CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K;
348 c.ext1 = i;
349 SendCommand(&c, FALSE);
350 ReceiveCommand(&c);
351 if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) {
352 PrintToScrollback("bad resp\n");
353 return 0;
354 }
355 int j;
356 for(j = 0; j < 48; j++) {
357 t2 = (int)((BYTE)c.d.asBytes[j]);
358 if((t2 ^ 0xC0) & 0xC0) { hasbeennull++; }
359
360 show = 0;
361 switch(show) {
362 case 0:
363 // combined
364 t1 = (t2 & 0x80) ^ (t2 & 0x20);
365 t2 = ((t2 << 1) & 0x80) ^ ((t2 << 1) & 0x20);
366 break;
367
368 case 1:
369 // only reader
370 t1 = (t2 & 0x80);
371 t2 = ((t2 << 1) & 0x80);
372 break;
373
374 case 2:
375 // only tag
376 t1 = (t2 & 0x20);
377 t2 = ((t2 << 1) & 0x20);
378 break;
379
380 case 3:
381 // both, but tag with other algorithm
382 t1 = (t2 & 0x80) ^ (t2 & 0x08);
383 t2 = ((t2 << 1) & 0x80) ^ ((t2 << 1) & 0x08);
384 break;
385 }
386
387 GraphBuffer[cnt++] = t1;
388 GraphBuffer[cnt++] = t2;
389 }
390 }
391 GraphTraceLen = n*4;
392 // 1130
393 if(hasbeennull>nrlow || nrlow==0) {
394 PrintToScrollback("hasbeennull=%d", hasbeennull);
395 return 1;
396 }
397 else {
398 return 0;
399 }
400 }
401
402
403 static void CmdHexsamples(char *str)
404 {
405 int i;
406 int n;
407
408 if(atoi(str) == 0) {
409 n = 12;
410 } else {
411 n = atoi(str)/4;
412 }
413
414 for(i = 0; i < n; i += 12) {
415 UsbCommand c;
416 c.cmd = CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K;
417 c.ext1 = i;
418 SendCommand(&c, FALSE);
419 ReceiveCommand(&c);
420 if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) {
421 PrintToScrollback("bad resp\n");
422 return;
423 }
424 int j;
425 for(j = 0; j < 48; j += 8) {
426 PrintToScrollback("%02x %02x %02x %02x %02x %02x %02x %02x",
427 c.d.asBytes[j+0],
428 c.d.asBytes[j+1],
429 c.d.asBytes[j+2],
430 c.d.asBytes[j+3],
431 c.d.asBytes[j+4],
432 c.d.asBytes[j+5],
433 c.d.asBytes[j+6],
434 c.d.asBytes[j+7],
435 c.d.asBytes[j+8]
436 );
437 }
438 }
439 }
440
441 static void CmdHisampless(char *str)
442 {
443 int cnt = 0;
444 int i;
445 int n;
446
447 if(atoi(str) == 0) {
448 n = 1000;
449 } else {
450 n = atoi(str)/4;
451 }
452
453 for(i = 0; i < n; i += 12) {
454 UsbCommand c;
455 c.cmd = CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K;
456 c.ext1 = i;
457 SendCommand(&c, FALSE);
458 ReceiveCommand(&c);
459 if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) {
460 PrintToScrollback("bad resp\n");
461 return;
462 }
463 int j;
464 for(j = 0; j < 48; j++) {
465 GraphBuffer[cnt++] = (int)((signed char)c.d.asBytes[j]);
466 }
467 }
468 GraphTraceLen = cnt;
469
470 RepaintGraphWindow();
471 }
472
473 static WORD Iso15693Crc(BYTE *v, int n)
474 {
475 DWORD reg;
476 int i, j;
477
478 reg = 0xffff;
479 for(i = 0; i < n; i++) {
480 reg = reg ^ ((DWORD)v[i]);
481 for (j = 0; j < 8; j++) {
482 if (reg & 0x0001) {
483 reg = (reg >> 1) ^ 0x8408;
484 } else {
485 reg = (reg >> 1);
486 }
487 }
488 }
489
490 return (WORD)~reg;
491 }
492
493 static void CmdHi14bdemod(char *str)
494 {
495 int i, j, iold;
496 int isum, qsum;
497 int outOfWeakAt;
498 BOOL negateI, negateQ;
499
500 BYTE data[256];
501 int dataLen=0;
502
503 // As received, the samples are pairs, correlations against I and Q
504 // square waves. So estimate angle of initial carrier (or just
505 // quadrant, actually), and then do the demod.
506
507 // First, estimate where the tag starts modulating.
508 for(i = 0; i < GraphTraceLen; i += 2) {
509 if(abs(GraphBuffer[i]) + abs(GraphBuffer[i+1]) > 40) {
510 break;
511 }
512 }
513 if(i >= GraphTraceLen) {
514 PrintToScrollback("too weak to sync");
515 return;
516 }
517 PrintToScrollback("out of weak at %d", i);
518 outOfWeakAt = i;
519
520 // Now, estimate the phase in the initial modulation of the tag
521 isum = 0;
522 qsum = 0;
523 for(; i < (outOfWeakAt + 16); i += 2) {
524 isum += GraphBuffer[i+0];
525 qsum += GraphBuffer[i+1];
526 }
527 negateI = (isum < 0);
528 negateQ = (qsum < 0);
529
530 // Turn the correlation pairs into soft decisions on the bit.
531 j = 0;
532 for(i = 0; i < GraphTraceLen/2; i++) {
533 int si = GraphBuffer[j];
534 int sq = GraphBuffer[j+1];
535 if(negateI) si = -si;
536 if(negateQ) sq = -sq;
537 GraphBuffer[i] = si + sq;
538 j += 2;
539 }
540 GraphTraceLen = i;
541
542 i = outOfWeakAt/2;
543 while(GraphBuffer[i] > 0 && i < GraphTraceLen)
544 i++;
545 if(i >= GraphTraceLen) goto demodError;
546
547 iold = i;
548 while(GraphBuffer[i] < 0 && i < GraphTraceLen)
549 i++;
550 if(i >= GraphTraceLen) goto demodError;
551 if((i - iold) > 23) goto demodError;
552
553 PrintToScrollback("make it to demod loop");
554
555 for(;;) {
556 iold = i;
557 while(GraphBuffer[i] >= 0 && i < GraphTraceLen)
558 i++;
559 if(i >= GraphTraceLen) goto demodError;
560 if((i - iold) > 6) goto demodError;
561
562 WORD shiftReg = 0;
563 if(i + 20 >= GraphTraceLen) goto demodError;
564
565 for(j = 0; j < 10; j++) {
566 int soft = GraphBuffer[i] + GraphBuffer[i+1];
567
568 if(abs(soft) < ((abs(isum) + abs(qsum))/20)) {
569 PrintToScrollback("weak bit");
570 }
571
572 shiftReg >>= 1;
573 if(GraphBuffer[i] + GraphBuffer[i+1] >= 0) {
574 shiftReg |= 0x200;
575 }
576
577 i+= 2;
578 }
579
580 if( (shiftReg & 0x200) &&
581 !(shiftReg & 0x001))
582 {
583 // valid data byte, start and stop bits okay
584 PrintToScrollback(" %02x", (shiftReg >> 1) & 0xff);
585 data[dataLen++] = (shiftReg >> 1) & 0xff;
586 if(dataLen >= sizeof(data)) {
587 return;
588 }
589 } else if(shiftReg == 0x000) {
590 // this is EOF
591 break;
592 } else {
593 goto demodError;
594 }
595 }
596
597 BYTE first, second;
598 ComputeCrc14443(CRC_14443_B, data, dataLen-2, &first, &second);
599 PrintToScrollback("CRC: %02x %02x (%s)\n", first, second,
600 (first == data[dataLen-2] && second == data[dataLen-1]) ?
601 "ok" : "****FAIL****");
602
603 RepaintGraphWindow();
604 return;
605
606 demodError:
607 PrintToScrollback("demod error");
608 RepaintGraphWindow();
609 }
610
611 static void CmdHi14list(char *str)
612 {
613 BYTE got[960];
614 GetFromBigBuf(got, sizeof(got));
615
616 PrintToScrollback("recorded activity:");
617 PrintToScrollback(" time :rssi: who bytes");
618 PrintToScrollback("---------+----+----+-----------");
619
620 int i = 0;
621 int prev = -1;
622
623 for(;;) {
624 if(i >= 900) {
625 break;
626 }
627
628 BOOL isResponse;
629 int timestamp = *((DWORD *)(got+i));
630 if(timestamp & 0x80000000) {
631 timestamp &= 0x7fffffff;
632 isResponse = 1;
633 } else {
634 isResponse = 0;
635 }
636 int metric = *((DWORD *)(got+i+4));
637
638 int len = got[i+8];
639
640 if(len > 100) {
641 break;
642 }
643 if(i + len >= 900) {
644 break;
645 }
646
647 BYTE *frame = (got+i+9);
648
649 char line[1000] = "";
650 int j;
651 for(j = 0; j < len; j++) {
652 sprintf(line+(j*3), "%02x ", frame[j]);
653 }
654
655 char *crc;
656 if(len > 2) {
657 BYTE b1, b2;
658 ComputeCrc14443(CRC_14443_B, frame, len-2, &b1, &b2);
659 if(b1 != frame[len-2] || b2 != frame[len-1]) {
660 crc = "**FAIL CRC**";
661 } else {
662 crc = "";
663 }
664 } else {
665 crc = "(SHORT)";
666 }
667
668 char metricString[100];
669 if(isResponse) {
670 sprintf(metricString, "%3d", metric);
671 } else {
672 strcpy(metricString, " ");
673 }
674
675 PrintToScrollback(" +%7d: %s: %s %s %s",
676 (prev < 0 ? 0 : timestamp - prev),
677 metricString,
678 (isResponse ? "TAG" : " "), line, crc);
679
680 prev = timestamp;
681 i += (len + 9);
682 }
683 }
684
685 static void CmdHi14alist(char *str)
686 {
687 BYTE got[1920];
688 GetFromBigBuf(got, sizeof(got));
689
690 PrintToScrollback("recorded activity:");
691 PrintToScrollback(" ETU :rssi: who bytes");
692 PrintToScrollback("---------+----+----+-----------");
693
694 int i = 0;
695 int prev = -1;
696
697 for(;;) {
698 if(i >= 1900) {
699 break;
700 }
701
702 BOOL isResponse;
703 int timestamp = *((DWORD *)(got+i));
704 if(timestamp & 0x80000000) {
705 timestamp &= 0x7fffffff;
706 isResponse = 1;
707 } else {
708 isResponse = 0;
709 }
710
711 int metric = 0;
712 int parityBits = *((DWORD *)(got+i+4));
713 // 4 bytes of additional information...
714 // maximum of 32 additional parity bit information
715 //
716 // TODO:
717 // at each quarter bit period we can send power level (16 levels)
718 // or each half bit period in 256 levels.
719
720
721 int len = got[i+8];
722
723 if(len > 100) {
724 break;
725 }
726 if(i + len >= 1900) {
727 break;
728 }
729
730 BYTE *frame = (got+i+9);
731
732 // Break and stick with current result if buffer was not completely full
733 if(frame[0] == 0x44 && frame[1] == 0x44 && frame[3] == 0x44) { break; }
734
735 char line[1000] = "";
736 int j;
737 for(j = 0; j < len; j++) {
738 int oddparity = 0x01;
739 int k;
740
741 for(k=0;k<8;k++) {
742 oddparity ^= (((frame[j] & 0xFF) >> k) & 0x01);
743 }
744
745 //if((parityBits >> (len - j - 1)) & 0x01) {
746 if(isResponse && (oddparity != ((parityBits >> (len - j - 1)) & 0x01))) {
747 sprintf(line+(j*4), "%02x! ", frame[j]);
748 }
749 else {
750 sprintf(line+(j*4), "%02x ", frame[j]);
751 }
752 }
753
754 char *crc;
755 crc = "";
756 if(len > 2) {
757 BYTE b1, b2;
758 for(j = 0; j < (len - 1); j++) {
759 // gives problems... search for the reason..
760 /*if(frame[j] == 0xAA) {
761 switch(frame[j+1]) {
762 case 0x01:
763 crc = "[1] Two drops close after each other";
764 break;
765 case 0x02:
766 crc = "[2] Potential SOC with a drop in second half of bitperiod";
767 break;
768 case 0x03:
769 crc = "[3] Segment Z after segment X is not possible";
770 break;
771 case 0x04:
772 crc = "[4] Parity bit of a fully received byte was wrong";
773 break;
774 default:
775 crc = "[?] Unknown error";
776 break;
777 }
778 break;
779 }*/
780 }
781
782 if(strlen(crc)==0) {
783 ComputeCrc14443(CRC_14443_A, frame, len-2, &b1, &b2);
784 if(b1 != frame[len-2] || b2 != frame[len-1]) {
785 crc = (isResponse & (len < 6)) ? "" : " !crc";
786 } else {
787 crc = "";
788 }
789 }
790 } else {
791 crc = ""; // SHORT
792 }
793
794 char metricString[100];
795 if(isResponse) {
796 sprintf(metricString, "%3d", metric);
797 } else {
798 strcpy(metricString, " ");
799 }
800
801 PrintToScrollback(" +%7d: %s: %s %s %s",
802 (prev < 0 ? 0 : (timestamp - prev)),
803 metricString,
804 (isResponse ? "TAG" : " "), line, crc);
805
806 prev = timestamp;
807 i += (len + 9);
808 }
809 CommandFinished = 1;
810 }
811
812 static void CmdHi15demod(char *str)
813 {
814 // The sampling rate is 106.353 ksps/s, for T = 18.8 us
815
816 // SOF defined as
817 // 1) Unmodulated time of 56.64us
818 // 2) 24 pulses of 423.75khz
819 // 3) logic '1' (unmodulated for 18.88us followed by 8 pulses of 423.75khz)
820
821 static const int FrameSOF[] = {
822 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
823 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
824 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
825 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
826 -1, -1, -1, -1,
827 -1, -1, -1, -1,
828 1, 1, 1, 1,
829 1, 1, 1, 1
830 };
831 static const int Logic0[] = {
832 1, 1, 1, 1,
833 1, 1, 1, 1,
834 -1, -1, -1, -1,
835 -1, -1, -1, -1
836 };
837 static const int Logic1[] = {
838 -1, -1, -1, -1,
839 -1, -1, -1, -1,
840 1, 1, 1, 1,
841 1, 1, 1, 1
842 };
843
844 // EOF defined as
845 // 1) logic '0' (8 pulses of 423.75khz followed by unmodulated for 18.88us)
846 // 2) 24 pulses of 423.75khz
847 // 3) Unmodulated time of 56.64us
848
849 static const int FrameEOF[] = {
850 1, 1, 1, 1,
851 1, 1, 1, 1,
852 -1, -1, -1, -1,
853 -1, -1, -1, -1,
854 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
855 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
856 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
857 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
858 };
859
860 int i, j;
861 int max = 0, maxPos;
862
863 int skip = 4;
864
865 if(GraphTraceLen < 1000) return;
866
867 // First, correlate for SOF
868 for(i = 0; i < 100; i++) {
869 int corr = 0;
870 for(j = 0; j < arraylen(FrameSOF); j += skip) {
871 corr += FrameSOF[j]*GraphBuffer[i+(j/skip)];
872 }
873 if(corr > max) {
874 max = corr;
875 maxPos = i;
876 }
877 }
878 PrintToScrollback("SOF at %d, correlation %d", maxPos,
879 max/(arraylen(FrameSOF)/skip));
880
881 i = maxPos + arraylen(FrameSOF)/skip;
882 int k = 0;
883 BYTE outBuf[20];
884 memset(outBuf, 0, sizeof(outBuf));
885 BYTE mask = 0x01;
886 for(;;) {
887 int corr0 = 0, corr1 = 0, corrEOF = 0;
888 for(j = 0; j < arraylen(Logic0); j += skip) {
889 corr0 += Logic0[j]*GraphBuffer[i+(j/skip)];
890 }
891 for(j = 0; j < arraylen(Logic1); j += skip) {
892 corr1 += Logic1[j]*GraphBuffer[i+(j/skip)];
893 }
894 for(j = 0; j < arraylen(FrameEOF); j += skip) {
895 corrEOF += FrameEOF[j]*GraphBuffer[i+(j/skip)];
896 }
897 // Even things out by the length of the target waveform.
898 corr0 *= 4;
899 corr1 *= 4;
900
901 if(corrEOF > corr1 && corrEOF > corr0) {
902 PrintToScrollback("EOF at %d", i);
903 break;
904 } else if(corr1 > corr0) {
905 i += arraylen(Logic1)/skip;
906 outBuf[k] |= mask;
907 } else {
908 i += arraylen(Logic0)/skip;
909 }
910 mask <<= 1;
911 if(mask == 0) {
912 k++;
913 mask = 0x01;
914 }
915 if((i+(int)arraylen(FrameEOF)) >= GraphTraceLen) {
916 PrintToScrollback("ran off end!");
917 break;
918 }
919 }
920 if(mask != 0x01) {
921 PrintToScrollback("error, uneven octet! (discard extra bits!)");
922 PrintToScrollback(" mask=%02x", mask);
923 }
924 PrintToScrollback("%d octets", k);
925
926 for(i = 0; i < k; i++) {
927 PrintToScrollback("# %2d: %02x ", i, outBuf[i]);
928 }
929 PrintToScrollback("CRC=%04x", Iso15693Crc(outBuf, k-2));
930 }
931
932 static void CmdTiread(char *str)
933 {
934 UsbCommand c;
935 c.cmd = CMD_ACQUIRE_RAW_BITS_TI_TYPE;
936 SendCommand(&c, FALSE);
937 }
938
939 static void CmdTibits(char *str)
940 {
941 int cnt = 0;
942 int i;
943 for(i = 0; i < 1536; i += 12) {
944 UsbCommand c;
945 c.cmd = CMD_DOWNLOAD_RAW_BITS_TI_TYPE;
946 c.ext1 = i;
947 SendCommand(&c, FALSE);
948 ReceiveCommand(&c);
949 if(c.cmd != CMD_DOWNLOADED_RAW_BITS_TI_TYPE) {
950 PrintToScrollback("bad resp\n");
951 return;
952 }
953 int j;
954 for(j = 0; j < 12; j++) {
955 int k;
956 for(k = 31; k >= 0; k--) {
957 if(c.d.asDwords[j] & (1 << k)) {
958 GraphBuffer[cnt++] = 1;
959 } else {
960 GraphBuffer[cnt++] = -1;
961 }
962 }
963 }
964 }
965 GraphTraceLen = 1536*32;
966 RepaintGraphWindow();
967 }
968
969 static void CmdTidemod(char *cmdline)
970 {
971 /* MATLAB as follows:
972 f_s = 2000000; % sampling frequency
973 f_l = 123200; % low FSK tone
974 f_h = 134200; % high FSK tone
975
976 T_l = 119e-6; % low bit duration
977 T_h = 130e-6; % high bit duration
978
979 l = 2*pi*ones(1, floor(f_s*T_l))*(f_l/f_s);
980 h = 2*pi*ones(1, floor(f_s*T_h))*(f_h/f_s);
981
982 l = sign(sin(cumsum(l)));
983 h = sign(sin(cumsum(h)));
984 */
985 static const int LowTone[] = {
986 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1,
987 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1,
988 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1,
989 -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1,
990 -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1,
991 -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1,
992 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1,
993 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1,
994 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1,
995 -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1,
996 -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
997 -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1,
998 1, 1, 1, 1, 1, 1, 1, -1, -1, -1,
999 };
1000 static const int HighTone[] = {
1001 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1,
1002 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1,
1003 -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
1004 -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1,
1005 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1,
1006 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1,
1007 -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
1008 -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1009 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1,
1010 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1,
1011 -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
1012 -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1,
1013 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1,
1014 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1,
1015 };
1016
1017 int convLen = max(arraylen(HighTone), arraylen(LowTone));
1018
1019 int i;
1020 for(i = 0; i < GraphTraceLen - convLen; i++) {
1021 int j;
1022 int lowSum = 0, highSum = 0;;
1023 int lowLen = arraylen(LowTone);
1024 int highLen = arraylen(HighTone);
1025
1026 for(j = 0; j < lowLen; j++) {
1027 lowSum += LowTone[j]*GraphBuffer[i+j];
1028 }
1029 for(j = 0; j < highLen; j++) {
1030 highSum += HighTone[j]*GraphBuffer[i+j];
1031 }
1032 lowSum = abs((100*lowSum) / lowLen);
1033 highSum = abs((100*highSum) / highLen);
1034 GraphBuffer[i] = (highSum << 16) | lowSum;
1035 }
1036
1037 for(i = 0; i < GraphTraceLen - convLen - 16; i++) {
1038 int j;
1039 int lowTot = 0, highTot = 0;
1040 // 16 and 15 are f_s divided by f_l and f_h, rounded
1041 for(j = 0; j < 16; j++) {
1042 lowTot += (GraphBuffer[i+j] & 0xffff);
1043 }
1044 for(j = 0; j < 15; j++) {
1045 highTot += (GraphBuffer[i+j] >> 16);
1046 }
1047 GraphBuffer[i] = lowTot - highTot;
1048 }
1049
1050 GraphTraceLen -= (convLen + 16);
1051
1052 RepaintGraphWindow();
1053
1054 // Okay, so now we have unsliced soft decisions; find bit-sync, and then
1055 // get some bits.
1056
1057 int max = 0, maxPos = 0;
1058 for(i = 0; i < 6000; i++) {
1059 int j;
1060 int dec = 0;
1061 for(j = 0; j < 8*arraylen(LowTone); j++) {
1062 dec -= GraphBuffer[i+j];
1063 }
1064 for(; j < 8*arraylen(LowTone) + 8*arraylen(HighTone); j++) {
1065 dec += GraphBuffer[i+j];
1066 }
1067 if(dec > max) {
1068 max = dec;
1069 maxPos = i;
1070 }
1071 }
1072 GraphBuffer[maxPos] = 800;
1073 GraphBuffer[maxPos+1] = -800;
1074
1075 maxPos += 8*arraylen(LowTone);
1076 GraphBuffer[maxPos] = 800;
1077 GraphBuffer[maxPos+1] = -800;
1078 maxPos += 8*arraylen(HighTone);
1079
1080 GraphBuffer[maxPos] = 800;
1081 GraphBuffer[maxPos+1] = -800;
1082
1083 PrintToScrollback("actual data bits start at sample %d", maxPos);
1084
1085 PrintToScrollback("length %d/%d", arraylen(HighTone), arraylen(LowTone));
1086
1087 GraphBuffer[maxPos] = 800;
1088 GraphBuffer[maxPos+1] = -800;
1089
1090 BYTE bits[64+16+8+1];
1091 bits[sizeof(bits)-1] = '\0';
1092
1093 for(i = 0; i < arraylen(bits); i++) {
1094 int high = 0;
1095 int low = 0;
1096 int j;
1097 for(j = 0; j < arraylen(LowTone); j++) {
1098 low -= GraphBuffer[maxPos+j];
1099 }
1100 for(j = 0; j < arraylen(HighTone); j++) {
1101 high += GraphBuffer[maxPos+j];
1102 }
1103 if(high > low) {
1104 bits[i] = '1';
1105 maxPos += arraylen(HighTone);
1106 } else {
1107 bits[i] = '.';
1108 maxPos += arraylen(LowTone);
1109 }
1110 GraphBuffer[maxPos] = 800;
1111 GraphBuffer[maxPos+1] = -800;
1112 }
1113 PrintToScrollback("bits: '%s'", bits);
1114
1115 DWORD h = 0, l = 0;
1116 for(i = 0; i < 32; i++) {
1117 if(bits[i] == '1') {
1118 l |= (1<<i);
1119 }
1120 }
1121 for(i = 32; i < 64; i++) {
1122 if(bits[i] == '1') {
1123 h |= (1<<(i-32));
1124 }
1125 }
1126 PrintToScrollback("hex: %08x %08x", h, l);
1127 }
1128
1129 static void CmdNorm(char *str)
1130 {
1131 int i;
1132 int max = INT_MIN, min = INT_MAX;
1133 for(i = 10; i < GraphTraceLen; i++) {
1134 if(GraphBuffer[i] > max) {
1135 max = GraphBuffer[i];
1136 }
1137 if(GraphBuffer[i] < min) {
1138 min = GraphBuffer[i];
1139 }
1140 }
1141 if(max != min) {
1142 for(i = 0; i < GraphTraceLen; i++) {
1143 GraphBuffer[i] = (GraphBuffer[i] - ((max + min)/2))*1000/
1144 (max - min);
1145 }
1146 }
1147 RepaintGraphWindow();
1148 }
1149
1150 static void CmdDec(char *str)
1151 {
1152 int i;
1153 for(i = 0; i < (GraphTraceLen/2); i++) {
1154 GraphBuffer[i] = GraphBuffer[i*2];
1155 }
1156 GraphTraceLen /= 2;
1157 PrintToScrollback("decimated by 2");
1158 RepaintGraphWindow();
1159 }
1160
1161 static void CmdHpf(char *str)
1162 {
1163 int i;
1164 int accum = 0;
1165 for(i = 10; i < GraphTraceLen; i++) {
1166 accum += GraphBuffer[i];
1167 }
1168 accum /= (GraphTraceLen - 10);
1169 for(i = 0; i < GraphTraceLen; i++) {
1170 GraphBuffer[i] -= accum;
1171 }
1172
1173 RepaintGraphWindow();
1174 }
1175
1176 static void CmdZerocrossings(char *str)
1177 {
1178 int i;
1179 // Zero-crossings aren't meaningful unless the signal is zero-mean.
1180 CmdHpf("");
1181
1182 int sign = 1;
1183 int zc = 0;
1184 int lastZc = 0;
1185 for(i = 0; i < GraphTraceLen; i++) {
1186 if(GraphBuffer[i]*sign >= 0) {
1187 // No change in sign, reproduce the previous sample count.
1188 zc++;
1189 GraphBuffer[i] = lastZc;
1190 } else {
1191 // Change in sign, reset the sample count.
1192 sign = -sign;
1193 GraphBuffer[i] = lastZc;
1194 if(sign > 0) {
1195 lastZc = zc;
1196 zc = 0;
1197 }
1198 }
1199 }
1200
1201 RepaintGraphWindow();
1202 }
1203
1204 static void CmdLtrim(char *str)
1205 {
1206 int i;
1207 int ds = atoi(str);
1208
1209 for(i = ds; i < GraphTraceLen; i++) {
1210 GraphBuffer[i-ds] = GraphBuffer[i];
1211 }
1212 GraphTraceLen -= ds;
1213
1214 RepaintGraphWindow();
1215 }
1216
1217 static void CmdAutoCorr(char *str)
1218 {
1219 static int CorrelBuffer[MAX_GRAPH_TRACE_LEN];
1220
1221 int window = atoi(str);
1222
1223 if(window == 0) {
1224 PrintToScrollback("needs a window");
1225 return;
1226 }
1227
1228 if(window >= GraphTraceLen) {
1229 PrintToScrollback("window must be smaller than trace (%d samples)",
1230 GraphTraceLen);
1231 return;
1232 }
1233
1234 PrintToScrollback("performing %d correlations", GraphTraceLen - window);
1235
1236 int i;
1237 for(i = 0; i < GraphTraceLen - window; i++) {
1238 int sum = 0;
1239 int j;
1240 for(j = 0; j < window; j++) {
1241 sum += (GraphBuffer[j]*GraphBuffer[i+j]) / 256;
1242 }
1243 CorrelBuffer[i] = sum;
1244 }
1245 GraphTraceLen = GraphTraceLen - window;
1246 memcpy(GraphBuffer, CorrelBuffer, GraphTraceLen*sizeof(int));
1247
1248 RepaintGraphWindow();
1249 }
1250
1251 static void CmdVchdemod(char *str)
1252 {
1253 // Is this the entire sync pattern, or does this also include some
1254 // data bits that happen to be the same everywhere? That would be
1255 // lovely to know.
1256 static const int SyncPattern[] = {
1257 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1258 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1259 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1260 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1261 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1262 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1263 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1264 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1265 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1266 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1267 };
1268
1269 // So first, we correlate for the sync pattern, and mark that.
1270 int bestCorrel = 0, bestPos = 0;
1271 int i;
1272 // It does us no good to find the sync pattern, with fewer than
1273 // 2048 samples after it...
1274 for(i = 0; i < (GraphTraceLen-2048); i++) {
1275 int sum = 0;
1276 int j;
1277 for(j = 0; j < arraylen(SyncPattern); j++) {
1278 sum += GraphBuffer[i+j]*SyncPattern[j];
1279 }
1280 if(sum > bestCorrel) {
1281 bestCorrel = sum;
1282 bestPos = i;
1283 }
1284 }
1285 PrintToScrollback("best sync at %d [metric %d]", bestPos, bestCorrel);
1286
1287 char bits[257];
1288 bits[256] = '\0';
1289
1290 int worst = INT_MAX;
1291 int worstPos;
1292
1293 for(i = 0; i < 2048; i += 8) {
1294 int sum = 0;
1295 int j;
1296 for(j = 0; j < 8; j++) {
1297 sum += GraphBuffer[bestPos+i+j];
1298 }
1299 if(sum < 0) {
1300 bits[i/8] = '.';
1301 } else {
1302 bits[i/8] = '1';
1303 }
1304 if(abs(sum) < worst) {
1305 worst = abs(sum);
1306 worstPos = i;
1307 }
1308 }
1309 PrintToScrollback("bits:");
1310 PrintToScrollback("%s", bits);
1311 PrintToScrollback("worst metric: %d at pos %d", worst, worstPos);
1312
1313 if(strcmp(str, "clone")==0) {
1314 GraphTraceLen = 0;
1315 char *s;
1316 for(s = bits; *s; s++) {
1317 int j;
1318 for(j = 0; j < 16; j++) {
1319 GraphBuffer[GraphTraceLen++] = (*s == '1') ? 1 : 0;
1320 }
1321 }
1322 RepaintGraphWindow();
1323 }
1324 }
1325
1326 static void CmdIndalademod(char *str)
1327 {
1328 // Usage: recover 64bit UID by default, specify "224" as arg to recover a 224bit UID
1329
1330 int state = -1;
1331 int count = 0;
1332 int i, j;
1333 // worst case with GraphTraceLen=64000 is < 4096
1334 // under normal conditions it's < 2048
1335 BYTE rawbits[4096];
1336 int rawbit = 0;
1337 int worst = 0, worstPos = 0;
1338 PrintToScrollback("Expecting a bit less than %d raw bits", GraphTraceLen/32);
1339 for(i = 0; i < GraphTraceLen-1; i += 2) {
1340 count+=1;
1341 if((GraphBuffer[i] > GraphBuffer[i + 1]) && (state != 1)) {
1342 if (state == 0) {
1343 for(j = 0; j < count - 8; j += 16) {
1344 rawbits[rawbit++] = 0;
1345 }
1346 if ((abs(count - j)) > worst) {
1347 worst = abs(count - j);
1348 worstPos = i;
1349 }
1350 }
1351 state = 1;
1352 count=0;
1353 } else if((GraphBuffer[i] < GraphBuffer[i + 1]) && (state != 0)) {
1354 if (state == 1) {
1355 for(j = 0; j < count - 8; j += 16) {
1356 rawbits[rawbit++] = 1;
1357 }
1358 if ((abs(count - j)) > worst) {
1359 worst = abs(count - j);
1360 worstPos = i;
1361 }
1362 }
1363 state = 0;
1364 count=0;
1365 }
1366 }
1367 PrintToScrollback("Recovered %d raw bits", rawbit);
1368 PrintToScrollback("worst metric (0=best..7=worst): %d at pos %d", worst, worstPos);
1369
1370 // Finding the start of a UID
1371 int uidlen, long_wait;
1372 if(strcmp(str, "224") == 0) {
1373 uidlen=224;
1374 long_wait=30;
1375 } else {
1376 uidlen=64;
1377 long_wait=29;
1378 }
1379 int start;
1380 int first = 0;
1381 for(start = 0; start <= rawbit - uidlen; start++) {
1382 first = rawbits[start];
1383 for(i = start; i < start + long_wait; i++) {
1384 if(rawbits[i] != first) {
1385 break;
1386 }
1387 }
1388 if(i == (start + long_wait)) {
1389 break;
1390 }
1391 }
1392 if(start == rawbit - uidlen + 1) {
1393 PrintToScrollback("nothing to wait for");
1394 return;
1395 }
1396
1397 // Inverting signal if needed
1398 if(first == 1) {
1399 for(i = start; i < rawbit; i++) {
1400 rawbits[i] = !rawbits[i];
1401 }
1402 }
1403
1404 // Dumping UID
1405 BYTE bits[224];
1406 char showbits[225];
1407 showbits[uidlen]='\0';
1408 int bit;
1409 i = start;
1410 int times = 0;
1411 if(uidlen > rawbit) {
1412 PrintToScrollback("Warning: not enough raw bits to get a full UID");
1413 for(bit = 0; bit < rawbit; bit++) {
1414 bits[bit] = rawbits[i++];
1415 // As we cannot know the parity, let's use "." and "/"
1416 showbits[bit] = '.' + bits[bit];
1417 }
1418 showbits[bit+1]='\0';
1419 PrintToScrollback("Partial UID=%s", showbits);
1420 return;
1421 } else {
1422 for(bit = 0; bit < uidlen; bit++) {
1423 bits[bit] = rawbits[i++];
1424 showbits[bit] = '0' + bits[bit];
1425 }
1426 times = 1;
1427 }
1428 PrintToScrollback("UID=%s", showbits);
1429
1430 // Checking UID against next occurences
1431 for(; i + uidlen <= rawbit;) {
1432 int failed = 0;
1433 for(bit = 0; bit < uidlen; bit++) {
1434 if(bits[bit] != rawbits[i++]) {
1435 failed = 1;
1436 break;
1437 }
1438 }
1439 if (failed == 1) {
1440 break;
1441 }
1442 times += 1;
1443 }
1444 PrintToScrollback("Occurences: %d (expected %d)", times, (rawbit - start) / uidlen);
1445
1446 // Remodulating for tag cloning
1447 GraphTraceLen = 32*uidlen;
1448 i = 0;
1449 int phase = 0;
1450 for(bit = 0; bit < uidlen; bit++) {
1451 if(bits[bit] == 0) {
1452 phase = 0;
1453 } else {
1454 phase = 1;
1455 }
1456 int j;
1457 for(j = 0; j < 32; j++) {
1458 GraphBuffer[i++] = phase;
1459 phase = !phase;
1460 }
1461 }
1462
1463 RepaintGraphWindow();
1464 }
1465
1466 static void CmdFlexdemod(char *str)
1467 {
1468 int i;
1469 for(i = 0; i < GraphTraceLen; i++) {
1470 if(GraphBuffer[i] < 0) {
1471 GraphBuffer[i] = -1;
1472 } else {
1473 GraphBuffer[i] = 1;
1474 }
1475 }
1476
1477 #define LONG_WAIT 100
1478 int start;
1479 for(start = 0; start < GraphTraceLen - LONG_WAIT; start++) {
1480 int first = GraphBuffer[start];
1481 for(i = start; i < start + LONG_WAIT; i++) {
1482 if(GraphBuffer[i] != first) {
1483 break;
1484 }
1485 }
1486 if(i == (start + LONG_WAIT)) {
1487 break;
1488 }
1489 }
1490 if(start == GraphTraceLen - LONG_WAIT) {
1491 PrintToScrollback("nothing to wait for");
1492 return;
1493 }
1494
1495 GraphBuffer[start] = 2;
1496 GraphBuffer[start+1] = -2;
1497
1498 BYTE bits[64];
1499
1500 int bit;
1501 i = start;
1502 for(bit = 0; bit < 64; bit++) {
1503 int j;
1504 int sum = 0;
1505 for(j = 0; j < 16; j++) {
1506 sum += GraphBuffer[i++];
1507 }
1508 if(sum > 0) {
1509 bits[bit] = 1;
1510 } else {
1511 bits[bit] = 0;
1512 }
1513 PrintToScrollback("bit %d sum %d", bit, sum);
1514 }
1515
1516 for(bit = 0; bit < 64; bit++) {
1517 int j;
1518 int sum = 0;
1519 for(j = 0; j < 16; j++) {
1520 sum += GraphBuffer[i++];
1521 }
1522 if(sum > 0 && bits[bit] != 1) {
1523 PrintToScrollback("oops1 at %d", bit);
1524 }
1525 if(sum < 0 && bits[bit] != 0) {
1526 PrintToScrollback("oops2 at %d", bit);
1527 }
1528 }
1529
1530 GraphTraceLen = 32*64;
1531 i = 0;
1532 int phase = 0;
1533 for(bit = 0; bit < 64; bit++) {
1534 if(bits[bit] == 0) {
1535 phase = 0;
1536 } else {
1537 phase = 1;
1538 }
1539 int j;
1540 for(j = 0; j < 32; j++) {
1541 GraphBuffer[i++] = phase;
1542 phase = !phase;
1543 }
1544 }
1545
1546 RepaintGraphWindow();
1547 }
1548
1549 /*
1550 * Generic command to demodulate ASK. bit length in argument.
1551 * Giving the bit length helps discriminate ripple effects
1552 * upon zero crossing for noisy traces.
1553 *
1554 * Second is convention: positive or negative (High mod means zero
1555 * or high mod means one)
1556 *
1557 * Updates the Graph trace with 0/1 values
1558 *
1559 * Arguments:
1560 * sl : bit length in terms of number of samples per bit
1561 * (use yellow/purple markers to compute).
1562 * c : 0 or 1
1563 */
1564
1565 static void Cmdaskdemod(char *str) {
1566 int i;
1567 int sign = 1;
1568 int n = 0;
1569 int c = 0;
1570 int t1 = 0;
1571
1572 // TODO: complain if we do not give 2 arguments here !
1573 sscanf(str, "%i %i", &n, &c);
1574 if (c == 0) {
1575 c = 1 ;
1576 } else {
1577 c = -1;
1578 }
1579
1580 if (GraphBuffer[0]*c > 0) {
1581 GraphBuffer[0] = 1;
1582 } else {
1583 GraphBuffer[0] = 0;
1584 }
1585 for(i=1;i<GraphTraceLen;i++) {
1586 /* Analyse signal within the symbol length */
1587 /* Decide if we crossed a zero */
1588 if (GraphBuffer[i]*sign < 0) {
1589 /* Crossed a zero, check if this is a ripple or not */
1590 if ( (i-t1) > n/4 ) {
1591 sign = -sign;
1592 t1=i;
1593 if (GraphBuffer[i]*c > 0){
1594 GraphBuffer[i]=1;
1595 } else {
1596 GraphBuffer[i]=0;
1597 }
1598 } else {
1599 /* This is a ripple, set the current sample value
1600 to the same as previous */
1601 GraphBuffer[i] = GraphBuffer[i-1];
1602 }
1603 } else {
1604 GraphBuffer[i] = GraphBuffer[i-1];
1605 }
1606 }
1607 RepaintGraphWindow();
1608 }
1609
1610
1611 /*
1612 * Manchester demodulate a bitstream. The bitstream needs to be already in
1613 * the GraphBuffer as 0 and 1 values
1614 *
1615 * Give the clock rate as argument in order to help the sync - the algorithm
1616 * resyncs at each pulse anyway.
1617 *
1618 * Not optimized by any means, this is the 1st time I'm writing this type of
1619 * routine, feel free to improve...
1620 *
1621 * 1st argument: clock rate (as number of samples per clock rate)
1622 * Typical values can be 64, 32, 128...
1623 */
1624 static void Cmdmanchesterdemod(char *str) {
1625 int i;
1626 int clock;
1627 int lastval;
1628 int lc = 0;
1629 int bitidx = 0;
1630 int bit2idx = 0;
1631
1632
1633 sscanf(str, "%i", &clock);
1634
1635 int tolerance = clock/4;
1636 /* Holds the decoded bitstream: each clock period contains 2 bits */
1637 /* later simplified to 1 bit after manchester decoding. */
1638 /* Add 10 bits to allow for noisy / uncertain traces without aborting */
1639 /* int BitStream[GraphTraceLen*2/clock+10]; */
1640
1641 /* But it does not work if compiling on WIndows: therefore we just allocate a */
1642 /* large array */
1643 int BitStream[MAX_GRAPH_TRACE_LEN];
1644
1645 /* Detect first transition */
1646 /* Lo-Hi (arbitrary) */
1647 for(i=1;i<GraphTraceLen;i++) {
1648 if (GraphBuffer[i-1]<GraphBuffer[i]) {
1649 lastval = i;
1650 BitStream[0]=0; // Previous state = 0;
1651 break;
1652 }
1653 }
1654
1655 /* Then detect duration between 2 successive transitions */
1656 for(bitidx = 1 ;i<GraphTraceLen;i++) {
1657 if (GraphBuffer[i-1] != GraphBuffer[i]) {
1658 lc = i-lastval;
1659 lastval = i;
1660 // Error check: if bitidx becomes too large, we do not
1661 // have a Manchester encoded bitstream or the clock is really
1662 // wrong!
1663 if (bitidx > (GraphTraceLen*2/clock+8) ) {
1664 PrintToScrollback("Error: the clock you gave is probably wrong, aborting.");
1665 return;
1666 }
1667 // Then switch depending on lc length:
1668 // Tolerance is 1/4 of clock rate (arbitrary)
1669 if (abs(lc-clock/2) < tolerance) {
1670 // Short pulse : either "1" or "0"
1671 BitStream[bitidx++]=GraphBuffer[i-1];
1672 } else if (abs(lc-clock) < tolerance) {
1673 // Long pulse: either "11" or "00"
1674 BitStream[bitidx++]=GraphBuffer[i-1];
1675 BitStream[bitidx++]=GraphBuffer[i-1];
1676 } else {
1677 // Error
1678 PrintToScrollback("Warning: Manchester decode error for pulse width detection.");
1679 PrintToScrollback("(too many of those messages mean either the stream is not Manchester encoded, or clock is wrong)");
1680 }
1681 }
1682 }
1683
1684 // At this stage, we now have a bitstream of "01" ("1") or "10" ("0"), parse it into final decoded bitstream
1685 // Actually, we overwrite BitStream with the new decoded bitstream, we just need to be careful
1686 // to stop output at the final bitidx2 value, not bitidx
1687 for (i = 0; i < bitidx; i += 2) {
1688 if ((BitStream[i] == 0) && (BitStream[i+1] == 1)) {
1689 BitStream[bit2idx++] = 1;
1690 } else if ((BitStream[i] == 1) && (BitStream[i+1] == 0)) {
1691 BitStream[bit2idx++] = 0;
1692 } else {
1693 // We cannot end up in this state, this means we are unsynchronized,
1694 // move up 1 bit:
1695 i++;
1696 PrintToScrollback("Unsynchronized, resync...");
1697 PrintToScrollback("(too many of those messages mean the stream is not Manchester encoded)");
1698 }
1699 }
1700 PrintToScrollback("Manchester decoded bitstream \n---------");
1701 // Now output the bitstream to the scrollback by line of 16 bits
1702 for (i = 0; i < (bit2idx-16); i+=16) {
1703 PrintToScrollback("%i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i",
1704 BitStream[i],
1705 BitStream[i+1],
1706 BitStream[i+2],
1707 BitStream[i+3],
1708 BitStream[i+4],
1709 BitStream[i+5],
1710 BitStream[i+6],
1711 BitStream[i+7],
1712 BitStream[i+8],
1713 BitStream[i+9],
1714 BitStream[i+10],
1715 BitStream[i+11],
1716 BitStream[i+12],
1717 BitStream[i+13],
1718 BitStream[i+14],
1719 BitStream[i+15]);
1720 }
1721 }
1722
1723
1724
1725 /*
1726 * Usage ???
1727 */
1728 static void CmdHiddemod(char *str)
1729 {
1730 if(GraphTraceLen < 4800) {
1731 PrintToScrollback("too short; need at least 4800 samples");
1732 return;
1733 }
1734
1735 GraphTraceLen = 4800;
1736 int i;
1737 for(i = 0; i < GraphTraceLen; i++) {
1738 if(GraphBuffer[i] < 0) {
1739 GraphBuffer[i] = 0;
1740 } else {
1741 GraphBuffer[i] = 1;
1742 }
1743 }
1744 RepaintGraphWindow();
1745 }
1746
1747 static void CmdPlot(char *str)
1748 {
1749 ShowGraphWindow();
1750 }
1751
1752 static void CmdHide(char *str)
1753 {
1754 HideGraphWindow();
1755 }
1756
1757 static void CmdScale(char *str)
1758 {
1759 CursorScaleFactor = atoi(str);
1760 if(CursorScaleFactor == 0) {
1761 PrintToScrollback("bad, can't have zero scale");
1762 CursorScaleFactor = 1;
1763 }
1764 RepaintGraphWindow();
1765 }
1766
1767 static void CmdSave(char *str)
1768 {
1769 FILE *f = fopen(str, "w");
1770 if(!f) {
1771 PrintToScrollback("couldn't open '%s'", str);
1772 return;
1773 }
1774 int i;
1775 for(i = 0; i < GraphTraceLen; i++) {
1776 fprintf(f, "%d\n", GraphBuffer[i]);
1777 }
1778 fclose(f);
1779 PrintToScrollback("saved to '%s'", str);
1780 }
1781
1782 static void CmdLoad(char *str)
1783 {
1784 FILE *f = fopen(str, "r");
1785 if(!f) {
1786 PrintToScrollback("couldn't open '%s'", str);
1787 return;
1788 }
1789
1790 GraphTraceLen = 0;
1791 char line[80];
1792 while(fgets(line, sizeof(line), f)) {
1793 GraphBuffer[GraphTraceLen] = atoi(line);
1794 GraphTraceLen++;
1795 }
1796 fclose(f);
1797 PrintToScrollback("loaded %d samples", GraphTraceLen);
1798 RepaintGraphWindow();
1799 }
1800
1801 static void CmdHIDsimTAG(char *str)
1802 {
1803 unsigned int hi=0, lo=0;
1804 int n=0, i=0;
1805 UsbCommand c;
1806
1807 while (sscanf(&str[i++], "%1x", &n ) == 1) {
1808 hi=(hi<<4)|(lo>>28);
1809 lo=(lo<<4)|(n&0xf);
1810 }
1811
1812 PrintToScrollback("Emulating tag with ID %x%16x", hi, lo);
1813
1814 c.cmd = CMD_HID_SIM_TAG;
1815 c.ext1 = hi;
1816 c.ext2 = lo;
1817 SendCommand(&c, FALSE);
1818 }
1819
1820 static void CmdLcdReset(char *str)
1821 {
1822 UsbCommand c;
1823 c.cmd = CMD_LCD_RESET;
1824 c.ext1 = atoi(str);
1825 SendCommand(&c, FALSE);
1826 }
1827
1828 static void CmdLcd(char *str)
1829 {
1830 int i, j;
1831 UsbCommand c;
1832 c.cmd = CMD_LCD;
1833 sscanf(str, "%x %d", &i, &j);
1834 while (j--) {
1835 c.ext1 = i&0x1ff;
1836 SendCommand(&c, FALSE);
1837 }
1838 }
1839
1840
1841
1842 static void CmdTest(char *str)
1843 {
1844 }
1845
1846 /*
1847 * Sets the divisor for LF frequency clock: lets the user choose any LF frequency below
1848 * 600kHz.
1849 */
1850 static void CmdSetDivisor(char *str)
1851 {
1852 UsbCommand c;
1853 c.cmd = CMD_SET_LF_DIVISOR;
1854 c.ext1 = atoi(str);
1855 if (( c.ext1<0) || (c.ext1>255)) {
1856 PrintToScrollback("divisor must be between 19 and 255");
1857 } else {
1858 SendCommand(&c, FALSE);
1859 PrintToScrollback("Divisor set, expected freq=%dHz", 12000000/(c.ext1+1));
1860 }
1861 }
1862
1863 static void CmdSweepLF(char *str)
1864 {
1865 UsbCommand c;
1866 c.cmd = CMD_SWEEP_LF;
1867 SendCommand(&c, FALSE);
1868 }
1869
1870
1871 typedef void HandlerFunction(char *cmdline);
1872
1873 static struct {
1874 char *name;
1875 HandlerFunction *handler;
1876 int offline; // 1 if the command can be used when in offline mode
1877 char *docString;
1878 } CommandTable[] = {
1879 "tune", CmdTune,0, "measure antenna tuning",
1880 "tiread", CmdTiread,0, "read a TI-type 134 kHz tag",
1881 "tibits", CmdTibits,0, "get raw bits for TI-type LF tag",
1882 "tidemod", CmdTidemod,0, "demod raw bits for TI-type LF tag",
1883 "vchdemod", CmdVchdemod,0, "demod samples for VeriChip",
1884 "plot", CmdPlot,1, "show graph window",
1885 "hide", CmdHide,1, "hide graph window",
1886 "losim", CmdLosim,0, "simulate LF tag",
1887 "loread", CmdLoread,0, "read (125/134 kHz) LF ID-only tag",
1888 "losamples", CmdLosamples,0, "get raw samples for LF tag",
1889 "hisamples", CmdHisamples,0, "get raw samples for HF tag",
1890 "hisampless", CmdHisampless,0, "get signed raw samples, HF tag",
1891 "hisamplest", CmdHi14readt,0, "get samples HF, for testing",
1892 "higet", CmdHi14read_sim,0, "get samples HF, 'analog'",
1893 "bitsamples", CmdBitsamples,0, "get raw samples as bitstring",
1894 "hexsamples", CmdHexsamples,0, "dump big buffer as hex bytes",
1895 "hi15read", CmdHi15read,0, "read HF tag (ISO 15693)",
1896 "hi15reader", CmdHi15reader,0, "act like an ISO15693 reader", // new command greg
1897 "hi15sim", CmdHi15tag,0, "fake an ISO15693 tag", // new command greg
1898 "hi14read", CmdHi14read,0, "read HF tag (ISO 14443)",
1899 "sri512read", CmdSri512read,0, "Read contents of a SRI512 tag",
1900 "hi14areader", CmdHi14areader,0, "act like an ISO14443 Type A reader", // ## New reader command
1901 "hi15demod", CmdHi15demod,1, "demod ISO15693 from tag",
1902 "hi14bdemod", CmdHi14bdemod,1, "demod ISO14443 Type B from tag",
1903 "autocorr", CmdAutoCorr,1, "autocorrelation over window",
1904 "norm", CmdNorm,1, "normalize max/min to +/-500",
1905 "dec", CmdDec,1, "decimate",
1906 "hpf", CmdHpf,1, "remove DC offset from trace",
1907 "zerocrossings", CmdZerocrossings,1, "count time between zero-crossings",
1908 "ltrim", CmdLtrim,1, "trim from left of trace",
1909 "scale", CmdScale,1, "set cursor display scale",
1910 "flexdemod", CmdFlexdemod,1, "demod samples for FlexPass",
1911 "save", CmdSave,1, "save trace (from graph window)",
1912 "load", CmdLoad,1, "load trace (to graph window",
1913 "hisimlisten", CmdHisimlisten,0, "get HF samples as fake tag",
1914 "hi14sim", CmdHi14sim,0, "fake ISO 14443 tag",
1915 "hi14asim", CmdHi14asim,0, "fake ISO 14443a tag", // ## Simulate 14443a tag
1916 "hi14snoop", CmdHi14snoop,0, "eavesdrop ISO 14443",
1917 "hi14asnoop", CmdHi14asnoop,0, "eavesdrop ISO 14443 Type A", // ## New snoop command
1918 "hi14list", CmdHi14list,0, "list ISO 14443 history",
1919 "hi14alist", CmdHi14alist,0, "list ISO 14443a history", // ## New list command
1920 "hiddemod", CmdHiddemod,1, "HID Prox Card II (not optimal)",
1921 "hidfskdemod", CmdHIDdemodFSK,0, "HID FSK demodulator",
1922 "indalademod", CmdIndalademod,0, "demod samples for Indala",
1923 "askdemod", Cmdaskdemod,1, "Attempt to demodulate simple ASK tags",
1924 "hidsimtag", CmdHIDsimTAG,0, "HID tag simulator",
1925 "mandemod", Cmdmanchesterdemod,1, "Try a Manchester demodulation on a binary stream",
1926 "fpgaoff", CmdFPGAOff,0, "set FPGA off", // ## FPGA Control
1927 "lcdreset", CmdLcdReset,0, "Hardware reset LCD",
1928 "lcd", CmdLcd,0, "Send command/data to LCD",
1929 "setlfdivisor", CmdSetDivisor,0, "Drive LF antenna at 12Mhz/(divisor+1)",
1930 "sweeplf", CmdSweepLF,0, "Sweep through LF freq range and store results in buffer",
1931 "reset", CmdReset,0, "Reset the Proxmark3",
1932 "quit", CmdQuit,1, "quit program"
1933 };
1934
1935
1936 //-----------------------------------------------------------------------------
1937 // Entry point into our code: called whenever the user types a command and
1938 // then presses Enter, which the full command line that they typed.
1939 //-----------------------------------------------------------------------------
1940 void CommandReceived(char *cmd)
1941 {
1942 int i;
1943
1944 PrintToScrollback("> %s", cmd);
1945
1946 if(strcmp(cmd, "help")==0) {
1947 if (offline) PrintToScrollback("Operating in OFFLINE mode (no device connected)");
1948 PrintToScrollback("\r\nAvailable commands:");
1949 for(i = 0; i < sizeof(CommandTable) / sizeof(CommandTable[0]); i++) {
1950 if (offline && (CommandTable[i].offline==0)) continue;
1951 char line[256];
1952 memset(line, ' ', sizeof(line));
1953 strcpy(line+2, CommandTable[i].name);
1954 line[strlen(line)] = ' ';
1955 sprintf(line+15, " -- %s", CommandTable[i].docString);
1956 PrintToScrollback("%s", line);
1957 }
1958 PrintToScrollback("");
1959 PrintToScrollback("and also: help, cls");
1960 return;
1961 }
1962
1963 for(i = 0; i < sizeof(CommandTable) / sizeof(CommandTable[0]); i++) {
1964 char *name = CommandTable[i].name;
1965 if(memcmp(cmd, name, strlen(name))==0 &&
1966 (cmd[strlen(name)] == ' ' || cmd[strlen(name)] == '\0'))
1967 {
1968 cmd += strlen(name);
1969 while(*cmd == ' ') {
1970 cmd++;
1971 }
1972 if (offline && (CommandTable[i].offline==0)) {
1973 PrintToScrollback("Offline mode, cannot use this command.");
1974 return;
1975 }
1976 (CommandTable[i].handler)(cmd);
1977 return;
1978 }
1979 }
1980 PrintToScrollback(">> bad command '%s'", cmd);
1981 }
1982
1983 //-----------------------------------------------------------------------------
1984 // Entry point into our code: called whenever we received a packet over USB
1985 // that we weren't necessarily expecting, for example a debug print.
1986 //-----------------------------------------------------------------------------
1987 void UsbCommandReceived(UsbCommand *c)
1988 {
1989 switch(c->cmd) {
1990 case CMD_DEBUG_PRINT_STRING: {
1991 char s[100];
1992 if(c->ext1 > 70 || c->ext1 < 0) {
1993 c->ext1 = 0;
1994 }
1995 memcpy(s, c->d.asBytes, c->ext1);
1996 s[c->ext1] = '\0';
1997 PrintToScrollback("#db# %s", s);
1998 break;
1999 }
2000
2001 case CMD_DEBUG_PRINT_INTEGERS:
2002 PrintToScrollback("#db# %08x, %08x, %08x\r\n", c->ext1, c->ext2, c->ext3);
2003 break;
2004
2005 case CMD_MEASURED_ANTENNA_TUNING: {
2006 int zLf, zHf;
2007 int vLf125, vLf134, vHf;
2008 vLf125 = c->ext1 & 0xffff;
2009 vLf134 = c->ext1 >> 16;
2010 vHf = c->ext2;
2011 zLf = c->ext3 & 0xffff;
2012 zHf = c->ext3 >> 16;
2013 PrintToScrollback("# LF antenna @ %3d mA / %5d mV [%d ohms] 125Khz",
2014 vLf125/zLf, vLf125, zLf);
2015 PrintToScrollback("# LF antenna @ %3d mA / %5d mV [%d ohms] 134Khz",
2016 vLf134/((zLf*125)/134), vLf134, (zLf*125)/134);
2017 PrintToScrollback("# HF antenna @ %3d mA / %5d mV [%d ohms] 13.56Mhz",
2018 vHf/zHf, vHf, zHf);
2019 break;
2020 }
2021 default:
2022 PrintToScrollback("unrecognized command %08x\n", c->cmd);
2023 break;
2024 }
2025 }
Impressum, Datenschutz