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