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