]> git.zerfleddert.de Git - proxmark3-svn/blob - winsrc/command.cpp
with em410xread, retest if we read our bits the wrong way (1=0 and 0=1)
[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 #define BIT(x) GraphBuffer[x * clock]
18 #define BITS (GraphTraceLen / clock)
19
20 int go = 0;
21 static int CmdHisamplest(char *str, int nrlow);
22
23 static void GetFromBigBuf(BYTE *dest, int bytes)
24 {
25 int n = bytes/4;
26
27 if(n % 48 != 0) {
28 PrintToScrollback("bad len in GetFromBigBuf");
29 return;
30 }
31
32 int i;
33 for(i = 0; i < n; i += 12) {
34 UsbCommand c;
35 c.cmd = CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K;
36 c.ext1 = i;
37 SendCommand(&c, FALSE);
38 ReceiveCommand(&c);
39 if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) {
40 PrintToScrollback("bad resp");
41 return;
42 }
43
44 memcpy(dest+(i*4), c.d.asBytes, 48);
45 }
46 }
47
48 static void CmdReset(char *str)
49 {
50 UsbCommand c;
51 c.cmd = CMD_HARDWARE_RESET;
52 SendCommand(&c, FALSE);
53 }
54
55
56 static void CmdQuit(char *str)
57 {
58 exit(0);
59 }
60
61 static void CmdHIDdemodFSK(char *str)
62 {
63 UsbCommand c;
64 c.cmd = CMD_HID_DEMOD_FSK;
65 SendCommand(&c, FALSE);
66 }
67
68 static void CmdTune(char *str)
69 {
70 UsbCommand c;
71 c.cmd = CMD_MEASURE_ANTENNA_TUNING;
72 SendCommand(&c, FALSE);
73 }
74
75 static void CmdHi15read(char *str)
76 {
77 UsbCommand c;
78 c.cmd = CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693;
79 SendCommand(&c, FALSE);
80 }
81
82 static void CmdHi14read(char *str)
83 {
84 UsbCommand c;
85 c.cmd = CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443;
86 c.ext1 = atoi(str);
87 SendCommand(&c, FALSE);
88 }
89
90
91 /* New command to read the contents of a SRI512 tag
92 * SRI512 tags are ISO14443-B modulated memory tags,
93 * this command just dumps the contents of the memory/
94 */
95 static void CmdSri512read(char *str)
96 {
97 UsbCommand c;
98 c.cmd = CMD_READ_SRI512_TAG;
99 c.ext1 = atoi(str);
100 SendCommand(&c, FALSE);
101 }
102
103 // ## New command
104 static void CmdHi14areader(char *str)
105 {
106 UsbCommand c;
107 c.cmd = CMD_READER_ISO_14443a;
108 c.ext1 = atoi(str);
109 SendCommand(&c, FALSE);
110 }
111
112 // ## New command
113 static void CmdHi15reader(char *str)
114 {
115 UsbCommand c;
116 c.cmd = CMD_READER_ISO_15693;
117 c.ext1 = atoi(str);
118 SendCommand(&c, FALSE);
119 }
120
121 // ## New command
122 static void CmdHi15tag(char *str)
123 {
124 UsbCommand c;
125 c.cmd = CMD_SIMTAG_ISO_15693;
126 c.ext1 = atoi(str);
127 SendCommand(&c, FALSE);
128 }
129
130 static void CmdHi14read_sim(char *str)
131 {
132 UsbCommand c;
133 c.cmd = CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443_SIM;
134 c.ext1 = atoi(str);
135 SendCommand(&c, FALSE);
136 }
137
138 static void CmdHi14readt(char *str)
139 {
140 UsbCommand c;
141 c.cmd = CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443;
142 c.ext1 = atoi(str);
143 SendCommand(&c, FALSE);
144
145 //CmdHisamplest(str);
146 while(CmdHisamplest(str,atoi(str))==0) {
147 c.cmd = CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443;
148 c.ext1 = atoi(str);
149 SendCommand(&c, FALSE);
150 }
151 RepaintGraphWindow();
152 }
153
154 static void CmdHisimlisten(char *str)
155 {
156 UsbCommand c;
157 c.cmd = CMD_SIMULATE_TAG_HF_LISTEN;
158 SendCommand(&c, FALSE);
159 }
160
161 static void CmdHi14sim(char *str)
162 {
163 UsbCommand c;
164 c.cmd = CMD_SIMULATE_TAG_ISO_14443;
165 SendCommand(&c, FALSE);
166 }
167
168 static void CmdHi14asim(char *str) // ## simulate iso14443a tag
169 { // ## greg - added ability to specify tag UID
170
171 unsigned int hi=0, lo=0;
172 int n=0, i=0;
173 UsbCommand c;
174
175 while (sscanf(&str[i++], "%1x", &n ) == 1) {
176 hi=(hi<<4)|(lo>>28);
177 lo=(lo<<4)|(n&0xf);
178 }
179
180 c.cmd = CMD_SIMULATE_TAG_ISO_14443a;
181 // c.ext should be set to *str or convert *str to the correct format for a uid
182 c.ext1 = hi;
183 c.ext2 = lo;
184 PrintToScrollback("Emulating 14443A TAG with UID %x%16x", hi, lo);
185 SendCommand(&c, FALSE);
186 }
187
188 static void CmdHi14snoop(char *str)
189 {
190 UsbCommand c;
191 c.cmd = CMD_SNOOP_ISO_14443;
192 SendCommand(&c, FALSE);
193 }
194
195 static void CmdHi14asnoop(char *str)
196 {
197 UsbCommand c;
198 c.cmd = CMD_SNOOP_ISO_14443a;
199 SendCommand(&c, FALSE);
200 }
201
202 static void CmdFPGAOff(char *str) // ## FPGA Control
203 {
204 UsbCommand c;
205 c.cmd = CMD_FPGA_MAJOR_MODE_OFF;
206 SendCommand(&c, FALSE);
207 }
208
209 /* clear out our graph window */
210 int CmdClearGraph(int redraw)
211 {
212 int gtl = GraphTraceLen;
213 GraphTraceLen = 0;
214
215 if (redraw)
216 RepaintGraphWindow();
217
218 return gtl;
219 }
220
221 /* write a bit to the graph */
222 static void CmdAppendGraph(int redraw, int clock, int bit)
223 {
224 int i;
225
226 for (i = 0; i < (int)(clock/2); i++)
227 GraphBuffer[GraphTraceLen++] = bit ^ 1;
228
229 for (i = (int)(clock/2); i < clock; i++)
230 GraphBuffer[GraphTraceLen++] = bit;
231
232 if (redraw)
233 RepaintGraphWindow();
234 }
235
236 /* Function is equivalent of loread + losamples + em410xread
237 * looped until an EM410x tag is detected */
238 static void CmdEM410xwatch(char *str)
239 {
240 char *zero = "";
241 char *twok = "2000";
242 go = 1;
243
244 do
245 {
246 CmdLoread(zero);
247 CmdLosamples(twok);
248 CmdEM410xread(zero);
249 } while (go);
250 }
251
252 /* Read the ID of an EM410x tag.
253 * Format:
254 * 1111 1111 1 <-- standard non-repeatable header
255 * XXXX [row parity bit] <-- 10 rows of 5 bits for our 40 bit tag ID
256 * ....
257 * CCCC <-- each bit here is parity for the 10 bits above in corresponding column
258 * 0 <-- stop bit, end of tag
259 */
260 static void CmdEM410xread(char *str)
261 {
262 int i, j, clock, header, rows, bit, hithigh, hitlow, first, bit2idx, high, low;
263 int parity[4];
264 char id[11];
265 int retested = 0;
266 int BitStream[MAX_GRAPH_TRACE_LEN];
267 high = low = 0;
268
269 /* Detect high and lows and clock */
270 for (i = 0; i < GraphTraceLen; i++)
271 {
272 if (GraphBuffer[i] > high)
273 high = GraphBuffer[i];
274 else if (GraphBuffer[i] < low)
275 low = GraphBuffer[i];
276 }
277
278 /* get clock */
279 clock = GetClock(str, high);
280
281 /* parity for our 4 columns */
282 parity[0] = parity[1] = parity[2] = parity[3] = 0;
283 header = rows = 0;
284
285 /* manchester demodulate */
286 bit = bit2idx = 0;
287 for (i = 0; i < (int)(GraphTraceLen / clock); i++)
288 {
289 hithigh = 0;
290 hitlow = 0;
291 first = 1;
292
293 /* Find out if we hit both high and low peaks */
294 for (j = 0; j < clock; j++)
295 {
296 if (GraphBuffer[(i * clock) + j] == high)
297 hithigh = 1;
298 else if (GraphBuffer[(i * clock) + j] == low)
299 hitlow = 1;
300
301 /* it doesn't count if it's the first part of our read
302 because it's really just trailing from the last sequence */
303 if (first && (hithigh || hitlow))
304 hithigh = hitlow = 0;
305 else
306 first = 0;
307
308 if (hithigh && hitlow)
309 break;
310 }
311
312 /* If we didn't hit both high and low peaks, we had a bit transition */
313 if (!hithigh || !hitlow)
314 bit ^= 1;
315
316 BitStream[bit2idx++] = bit;
317 }
318
319 retest:
320 /* We go till 5 before the graph ends because we'll get that far below */
321 for (i = 1; i < bit2idx - 5; i++)
322 {
323 /* Step 2: We have our header but need our tag ID */
324 if (header == 9 && rows < 10)
325 {
326 /* Confirm parity is correct */
327 if ((BitStream[i] ^ BitStream[i+1] ^ BitStream[i+2] ^ BitStream[i+3]) == BitStream[i+4])
328 {
329 /* Read another byte! */
330 sprintf(id+rows, "%x", (8 * BitStream[i]) + (4 * BitStream[i+1]) + (2 * BitStream[i+2]) + (1 * BitStream[i+3]));
331 rows++;
332
333 /* Keep parity info */
334 parity[0] ^= BitStream[i];
335 parity[1] ^= BitStream[i+1];
336 parity[2] ^= BitStream[i+2];
337 parity[3] ^= BitStream[i+3];
338
339 /* Move 4 bits ahead */
340 i += 4;
341 }
342
343 /* Damn, something wrong! reset */
344 else
345 {
346 PrintToScrollback("Thought we had a valid tag but failed at word %d (i=%d)", rows + 1, i);
347
348 /* Start back rows * 5 + 9 header bits, -1 to not start at same place */
349 i -= 9 + (5 * rows) - 5;
350
351 rows = header = 0;
352 }
353 }
354
355 /* Step 3: Got our 40 bits! confirm column parity */
356 else if (rows == 10)
357 {
358 /* We need to make sure our 4 bits of parity are correct and we have a stop bit */
359 if (BitStream[i] == parity[0] && BitStream[i+1] == parity[1] &&
360 BitStream[i+2] == parity[2] && BitStream[i+3] == parity[3] &&
361 BitStream[i+4] == 0)
362 {
363 /* Sweet! */
364 PrintToScrollback("EM410x Tag ID: %s", id);
365
366 /* Stop any loops */
367 go = 0;
368 return;
369 }
370
371 /* Crap! Incorrect parity or no stop bit, start all over */
372 else
373 {
374 rows = header = 0;
375
376 /* Go back 59 bits (9 header bits + 10 rows at 4+1 parity) */
377 i -= 59;
378 }
379 }
380
381 /* Step 1: get our header */
382 else if (header < 9)
383 {
384 /* Need 9 consecutive 1's */
385 if (BitStream[i] == 1)
386 header++;
387
388 /* We don't have a header, not enough consecutive 1 bits */
389 else
390 header = 0;
391 }
392 }
393
394 /* if we've already retested after flipping bits, return */
395 if (retested++)
396 return;
397
398 /* if this didn't work, try flipping bits */
399 for (i = 0; i < bit2idx; i++)
400 BitStream[i] ^= 1;
401
402 goto retest;
403 }
404
405 /* emulate an EM410X tag
406 * Format:
407 * 1111 1111 1 <-- standard non-repeatable header
408 * XXXX [row parity bit] <-- 10 rows of 5 bits for our 40 bit tag ID
409 * ....
410 * CCCC <-- each bit here is parity for the 10 bits above in corresponding column
411 * 0 <-- stop bit, end of tag
412 */
413 static void CmdEM410xsim(char *str)
414 {
415 int i, n, j, h, binary[4], parity[4];
416 char *s = "0";
417
418 /* clock is 64 in EM410x tags */
419 int clock = 64;
420
421 /* clear our graph */
422 CmdClearGraph(0);
423
424 /* write it out a few times */
425 for (h = 0; h < 4; h++)
426 {
427 /* write 9 start bits */
428 for (i = 0; i < 9; i++)
429 CmdAppendGraph(0, clock, 1);
430
431 /* for each hex char */
432 parity[0] = parity[1] = parity[2] = parity[3] = 0;
433 for (i = 0; i < 10; i++)
434 {
435 /* read each hex char */
436 sscanf(&str[i], "%1x", &n);
437 for (j = 3; j >= 0; j--, n/= 2)
438 binary[j] = n % 2;
439
440 /* append each bit */
441 CmdAppendGraph(0, clock, binary[0]);
442 CmdAppendGraph(0, clock, binary[1]);
443 CmdAppendGraph(0, clock, binary[2]);
444 CmdAppendGraph(0, clock, binary[3]);
445
446 /* append parity bit */
447 CmdAppendGraph(0, clock, binary[0] ^ binary[1] ^ binary[2] ^ binary[3]);
448
449 /* keep track of column parity */
450 parity[0] ^= binary[0];
451 parity[1] ^= binary[1];
452 parity[2] ^= binary[2];
453 parity[3] ^= binary[3];
454 }
455
456 /* parity columns */
457 CmdAppendGraph(0, clock, parity[0]);
458 CmdAppendGraph(0, clock, parity[1]);
459 CmdAppendGraph(0, clock, parity[2]);
460 CmdAppendGraph(0, clock, parity[3]);
461
462 /* stop bit */
463 CmdAppendGraph(0, clock, 0);
464 }
465
466 /* modulate that biatch */
467 Cmdmanchestermod(s);
468
469 /* booyah! */
470 RepaintGraphWindow();
471
472 CmdLosim(s);
473 }
474
475 static void ChkBitstream(char *str)
476 {
477 int i;
478
479 /* convert to bitstream if necessary */
480 for (i = 0; i < (int)(GraphTraceLen / 2); i++)
481 {
482 if (GraphBuffer[i] > 1 || GraphBuffer[i] < 0)
483 {
484 Cmdbitstream(str);
485 break;
486 }
487 }
488 }
489
490 static void CmdLosim(char *str)
491 {
492 int i;
493 char *zero = "0";
494
495 /* convert to bitstream if necessary */
496 ChkBitstream(str);
497
498 for (i = 0; i < GraphTraceLen; i += 48) {
499 UsbCommand c;
500 int j;
501 for(j = 0; j < 48; j++) {
502 c.d.asBytes[j] = GraphBuffer[i+j];
503 }
504 c.cmd = CMD_DOWNLOADED_SIM_SAMPLES_125K;
505 c.ext1 = i;
506 SendCommand(&c, FALSE);
507 }
508
509 UsbCommand c;
510 c.cmd = CMD_SIMULATE_TAG_125K;
511 c.ext1 = GraphTraceLen;
512 SendCommand(&c, FALSE);
513 }
514
515 static void CmdLoread(char *str)
516 {
517 UsbCommand c;
518 // 'h' means higher-low-frequency, 134 kHz
519 if(*str == 'h') {
520 c.ext1 = 1;
521 } else if (*str == '\0') {
522 c.ext1 = 0;
523 } else {
524 PrintToScrollback("use 'loread' or 'loread h'");
525 return;
526 }
527 c.cmd = CMD_ACQUIRE_RAW_ADC_SAMPLES_125K;
528 SendCommand(&c, FALSE);
529 }
530
531 static void CmdLosamples(char *str)
532 {
533 int cnt = 0;
534 int i;
535 int n;
536
537 n=atoi(str);
538 if (n==0) n=128;
539 if (n>16000) n=16000;
540
541 for(i = 0; i < n; i += 12) {
542 UsbCommand c;
543 c.cmd = CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K;
544 c.ext1 = i;
545 SendCommand(&c, FALSE);
546 ReceiveCommand(&c);
547 if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) {
548 if (!go)
549 PrintToScrollback("bad resp");
550 return;
551 }
552 int j;
553 for(j = 0; j < 48; j++) {
554 GraphBuffer[cnt++] = ((int)c.d.asBytes[j]) - 128;
555 }
556 }
557 GraphTraceLen = n*4;
558 RepaintGraphWindow();
559 }
560
561 static void CmdBitsamples(char *str)
562 {
563 int cnt = 0;
564 int i;
565 int n;
566
567 n = 3072;
568 for(i = 0; i < n; i += 12) {
569 UsbCommand c;
570 c.cmd = CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K;
571 c.ext1 = i;
572 SendCommand(&c, FALSE);
573 ReceiveCommand(&c);
574 if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) {
575 PrintToScrollback("bad resp");
576 return;
577 }
578 int j, k;
579 for(j = 0; j < 48; j++) {
580 for(k = 0; k < 8; k++) {
581 if(c.d.asBytes[j] & (1 << (7 - k))) {
582 GraphBuffer[cnt++] = 1;
583 } else {
584 GraphBuffer[cnt++] = 0;
585 }
586 }
587 }
588 }
589 GraphTraceLen = cnt;
590 RepaintGraphWindow();
591 }
592
593 static void CmdHisamples(char *str)
594 {
595 int cnt = 0;
596 int i;
597 int n;
598 n = 1000;
599 for(i = 0; i < n; i += 12) {
600 UsbCommand c;
601 c.cmd = CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K;
602 c.ext1 = i;
603 SendCommand(&c, FALSE);
604 ReceiveCommand(&c);
605 if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) {
606 PrintToScrollback("bad resp");
607 return;
608 }
609 int j;
610 for(j = 0; j < 48; j++) {
611 GraphBuffer[cnt++] = (int)((BYTE)c.d.asBytes[j]);
612 }
613 }
614 GraphTraceLen = n*4;
615
616 RepaintGraphWindow();
617 }
618
619
620 static int CmdHisamplest(char *str, int nrlow)
621 {
622 int cnt = 0;
623 int t1, t2;
624 int i;
625 int n;
626 int hasbeennull;
627 int show;
628
629
630 n = 1000;
631 hasbeennull = 0;
632 for(i = 0; i < n; i += 12) {
633 UsbCommand c;
634 c.cmd = CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K;
635 c.ext1 = i;
636 SendCommand(&c, FALSE);
637 ReceiveCommand(&c);
638 if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) {
639 PrintToScrollback("bad resp");
640 return 0;
641 }
642 int j;
643 for(j = 0; j < 48; j++) {
644 t2 = (int)((BYTE)c.d.asBytes[j]);
645 if((t2 ^ 0xC0) & 0xC0) { hasbeennull++; }
646
647 show = 0;
648 switch(show) {
649 case 0:
650 // combined
651 t1 = (t2 & 0x80) ^ (t2 & 0x20);
652 t2 = ((t2 << 1) & 0x80) ^ ((t2 << 1) & 0x20);
653 break;
654
655 case 1:
656 // only reader
657 t1 = (t2 & 0x80);
658 t2 = ((t2 << 1) & 0x80);
659 break;
660
661 case 2:
662 // only tag
663 t1 = (t2 & 0x20);
664 t2 = ((t2 << 1) & 0x20);
665 break;
666
667 case 3:
668 // both, but tag with other algorithm
669 t1 = (t2 & 0x80) ^ (t2 & 0x08);
670 t2 = ((t2 << 1) & 0x80) ^ ((t2 << 1) & 0x08);
671 break;
672 }
673
674 GraphBuffer[cnt++] = t1;
675 GraphBuffer[cnt++] = t2;
676 }
677 }
678 GraphTraceLen = n*4;
679 // 1130
680 if(hasbeennull>nrlow || nrlow==0) {
681 PrintToScrollback("hasbeennull=%d", hasbeennull);
682 return 1;
683 }
684 else {
685 return 0;
686 }
687 }
688
689
690 static void CmdHexsamples(char *str)
691 {
692 int i;
693 int n;
694
695 if(atoi(str) == 0) {
696 n = 12;
697 } else {
698 n = atoi(str)/4;
699 }
700
701 for(i = 0; i < n; i += 12) {
702 UsbCommand c;
703 c.cmd = CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K;
704 c.ext1 = i;
705 SendCommand(&c, FALSE);
706 ReceiveCommand(&c);
707 if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) {
708 PrintToScrollback("bad resp");
709 return;
710 }
711 int j;
712 for(j = 0; j < 48; j += 8) {
713 PrintToScrollback("%02x %02x %02x %02x %02x %02x %02x %02x",
714 c.d.asBytes[j+0],
715 c.d.asBytes[j+1],
716 c.d.asBytes[j+2],
717 c.d.asBytes[j+3],
718 c.d.asBytes[j+4],
719 c.d.asBytes[j+5],
720 c.d.asBytes[j+6],
721 c.d.asBytes[j+7],
722 c.d.asBytes[j+8]
723 );
724 }
725 }
726 }
727
728 static void CmdHisampless(char *str)
729 {
730 int cnt = 0;
731 int i;
732 int n;
733
734 if(atoi(str) == 0) {
735 n = 1000;
736 } else {
737 n = atoi(str)/4;
738 }
739
740 for(i = 0; i < n; i += 12) {
741 UsbCommand c;
742 c.cmd = CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K;
743 c.ext1 = i;
744 SendCommand(&c, FALSE);
745 ReceiveCommand(&c);
746 if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) {
747 PrintToScrollback("bad resp");
748 return;
749 }
750 int j;
751 for(j = 0; j < 48; j++) {
752 GraphBuffer[cnt++] = (int)((signed char)c.d.asBytes[j]);
753 }
754 }
755 GraphTraceLen = cnt;
756
757 RepaintGraphWindow();
758 }
759
760 static WORD Iso15693Crc(BYTE *v, int n)
761 {
762 DWORD reg;
763 int i, j;
764
765 reg = 0xffff;
766 for(i = 0; i < n; i++) {
767 reg = reg ^ ((DWORD)v[i]);
768 for (j = 0; j < 8; j++) {
769 if (reg & 0x0001) {
770 reg = (reg >> 1) ^ 0x8408;
771 } else {
772 reg = (reg >> 1);
773 }
774 }
775 }
776
777 return (WORD)~reg;
778 }
779
780 static void CmdHi14bdemod(char *str)
781 {
782 int i, j, iold;
783 int isum, qsum;
784 int outOfWeakAt;
785 BOOL negateI, negateQ;
786
787 BYTE data[256];
788 int dataLen=0;
789
790 // As received, the samples are pairs, correlations against I and Q
791 // square waves. So estimate angle of initial carrier (or just
792 // quadrant, actually), and then do the demod.
793
794 // First, estimate where the tag starts modulating.
795 for(i = 0; i < GraphTraceLen; i += 2) {
796 if(abs(GraphBuffer[i]) + abs(GraphBuffer[i+1]) > 40) {
797 break;
798 }
799 }
800 if(i >= GraphTraceLen) {
801 PrintToScrollback("too weak to sync");
802 return;
803 }
804 PrintToScrollback("out of weak at %d", i);
805 outOfWeakAt = i;
806
807 // Now, estimate the phase in the initial modulation of the tag
808 isum = 0;
809 qsum = 0;
810 for(; i < (outOfWeakAt + 16); i += 2) {
811 isum += GraphBuffer[i+0];
812 qsum += GraphBuffer[i+1];
813 }
814 negateI = (isum < 0);
815 negateQ = (qsum < 0);
816
817 // Turn the correlation pairs into soft decisions on the bit.
818 j = 0;
819 for(i = 0; i < GraphTraceLen/2; i++) {
820 int si = GraphBuffer[j];
821 int sq = GraphBuffer[j+1];
822 if(negateI) si = -si;
823 if(negateQ) sq = -sq;
824 GraphBuffer[i] = si + sq;
825 j += 2;
826 }
827 GraphTraceLen = i;
828
829 i = outOfWeakAt/2;
830 while(GraphBuffer[i] > 0 && i < GraphTraceLen)
831 i++;
832 if(i >= GraphTraceLen) goto demodError;
833
834 iold = i;
835 while(GraphBuffer[i] < 0 && i < GraphTraceLen)
836 i++;
837 if(i >= GraphTraceLen) goto demodError;
838 if((i - iold) > 23) goto demodError;
839
840 PrintToScrollback("make it to demod loop");
841
842 for(;;) {
843 iold = i;
844 while(GraphBuffer[i] >= 0 && i < GraphTraceLen)
845 i++;
846 if(i >= GraphTraceLen) goto demodError;
847 if((i - iold) > 6) goto demodError;
848
849 WORD shiftReg = 0;
850 if(i + 20 >= GraphTraceLen) goto demodError;
851
852 for(j = 0; j < 10; j++) {
853 int soft = GraphBuffer[i] + GraphBuffer[i+1];
854
855 if(abs(soft) < ((abs(isum) + abs(qsum))/20)) {
856 PrintToScrollback("weak bit");
857 }
858
859 shiftReg >>= 1;
860 if(GraphBuffer[i] + GraphBuffer[i+1] >= 0) {
861 shiftReg |= 0x200;
862 }
863
864 i+= 2;
865 }
866
867 if( (shiftReg & 0x200) &&
868 !(shiftReg & 0x001))
869 {
870 // valid data byte, start and stop bits okay
871 PrintToScrollback(" %02x", (shiftReg >> 1) & 0xff);
872 data[dataLen++] = (shiftReg >> 1) & 0xff;
873 if(dataLen >= sizeof(data)) {
874 return;
875 }
876 } else if(shiftReg == 0x000) {
877 // this is EOF
878 break;
879 } else {
880 goto demodError;
881 }
882 }
883
884 BYTE first, second;
885 ComputeCrc14443(CRC_14443_B, data, dataLen-2, &first, &second);
886 PrintToScrollback("CRC: %02x %02x (%s)\n", first, second,
887 (first == data[dataLen-2] && second == data[dataLen-1]) ?
888 "ok" : "****FAIL****");
889
890 RepaintGraphWindow();
891 return;
892
893 demodError:
894 PrintToScrollback("demod error");
895 RepaintGraphWindow();
896 }
897
898 static void CmdHi14list(char *str)
899 {
900 BYTE got[960];
901 GetFromBigBuf(got, sizeof(got));
902
903 PrintToScrollback("recorded activity:");
904 PrintToScrollback(" time :rssi: who bytes");
905 PrintToScrollback("---------+----+----+-----------");
906
907 int i = 0;
908 int prev = -1;
909
910 for(;;) {
911 if(i >= 900) {
912 break;
913 }
914
915 BOOL isResponse;
916 int timestamp = *((DWORD *)(got+i));
917 if(timestamp & 0x80000000) {
918 timestamp &= 0x7fffffff;
919 isResponse = 1;
920 } else {
921 isResponse = 0;
922 }
923 int metric = *((DWORD *)(got+i+4));
924
925 int len = got[i+8];
926
927 if(len > 100) {
928 break;
929 }
930 if(i + len >= 900) {
931 break;
932 }
933
934 BYTE *frame = (got+i+9);
935
936 char line[1000] = "";
937 int j;
938 for(j = 0; j < len; j++) {
939 sprintf(line+(j*3), "%02x ", frame[j]);
940 }
941
942 char *crc;
943 if(len > 2) {
944 BYTE b1, b2;
945 ComputeCrc14443(CRC_14443_B, frame, len-2, &b1, &b2);
946 if(b1 != frame[len-2] || b2 != frame[len-1]) {
947 crc = "**FAIL CRC**";
948 } else {
949 crc = "";
950 }
951 } else {
952 crc = "(SHORT)";
953 }
954
955 char metricString[100];
956 if(isResponse) {
957 sprintf(metricString, "%3d", metric);
958 } else {
959 strcpy(metricString, " ");
960 }
961
962 PrintToScrollback(" +%7d: %s: %s %s %s",
963 (prev < 0 ? 0 : timestamp - prev),
964 metricString,
965 (isResponse ? "TAG" : " "), line, crc);
966
967 prev = timestamp;
968 i += (len + 9);
969 }
970 }
971
972 static void CmdHi14alist(char *str)
973 {
974 BYTE got[1920];
975 GetFromBigBuf(got, sizeof(got));
976
977 PrintToScrollback("recorded activity:");
978 PrintToScrollback(" ETU :rssi: who bytes");
979 PrintToScrollback("---------+----+----+-----------");
980
981 int i = 0;
982 int prev = -1;
983
984 for(;;) {
985 if(i >= 1900) {
986 break;
987 }
988
989 BOOL isResponse;
990 int timestamp = *((DWORD *)(got+i));
991 if(timestamp & 0x80000000) {
992 timestamp &= 0x7fffffff;
993 isResponse = 1;
994 } else {
995 isResponse = 0;
996 }
997
998 int metric = 0;
999 int parityBits = *((DWORD *)(got+i+4));
1000 // 4 bytes of additional information...
1001 // maximum of 32 additional parity bit information
1002 //
1003 // TODO:
1004 // at each quarter bit period we can send power level (16 levels)
1005 // or each half bit period in 256 levels.
1006
1007
1008 int len = got[i+8];
1009
1010 if(len > 100) {
1011 break;
1012 }
1013 if(i + len >= 1900) {
1014 break;
1015 }
1016
1017 BYTE *frame = (got+i+9);
1018
1019 // Break and stick with current result if buffer was not completely full
1020 if(frame[0] == 0x44 && frame[1] == 0x44 && frame[3] == 0x44) { break; }
1021
1022 char line[1000] = "";
1023 int j;
1024 for(j = 0; j < len; j++) {
1025 int oddparity = 0x01;
1026 int k;
1027
1028 for(k=0;k<8;k++) {
1029 oddparity ^= (((frame[j] & 0xFF) >> k) & 0x01);
1030 }
1031
1032 //if((parityBits >> (len - j - 1)) & 0x01) {
1033 if(isResponse && (oddparity != ((parityBits >> (len - j - 1)) & 0x01))) {
1034 sprintf(line+(j*4), "%02x! ", frame[j]);
1035 }
1036 else {
1037 sprintf(line+(j*4), "%02x ", frame[j]);
1038 }
1039 }
1040
1041 char *crc;
1042 crc = "";
1043 if(len > 2) {
1044 BYTE b1, b2;
1045 for(j = 0; j < (len - 1); j++) {
1046 // gives problems... search for the reason..
1047 /*if(frame[j] == 0xAA) {
1048 switch(frame[j+1]) {
1049 case 0x01:
1050 crc = "[1] Two drops close after each other";
1051 break;
1052 case 0x02:
1053 crc = "[2] Potential SOC with a drop in second half of bitperiod";
1054 break;
1055 case 0x03:
1056 crc = "[3] Segment Z after segment X is not possible";
1057 break;
1058 case 0x04:
1059 crc = "[4] Parity bit of a fully received byte was wrong";
1060 break;
1061 default:
1062 crc = "[?] Unknown error";
1063 break;
1064 }
1065 break;
1066 }*/
1067 }
1068
1069 if(strlen(crc)==0) {
1070 ComputeCrc14443(CRC_14443_A, frame, len-2, &b1, &b2);
1071 if(b1 != frame[len-2] || b2 != frame[len-1]) {
1072 crc = (isResponse & (len < 6)) ? "" : " !crc";
1073 } else {
1074 crc = "";
1075 }
1076 }
1077 } else {
1078 crc = ""; // SHORT
1079 }
1080
1081 char metricString[100];
1082 if(isResponse) {
1083 sprintf(metricString, "%3d", metric);
1084 } else {
1085 strcpy(metricString, " ");
1086 }
1087
1088 PrintToScrollback(" +%7d: %s: %s %s %s",
1089 (prev < 0 ? 0 : (timestamp - prev)),
1090 metricString,
1091 (isResponse ? "TAG" : " "), line, crc);
1092
1093 prev = timestamp;
1094 i += (len + 9);
1095 }
1096 CommandFinished = 1;
1097 }
1098
1099 static void CmdHi15demod(char *str)
1100 {
1101 // The sampling rate is 106.353 ksps/s, for T = 18.8 us
1102
1103 // SOF defined as
1104 // 1) Unmodulated time of 56.64us
1105 // 2) 24 pulses of 423.75khz
1106 // 3) logic '1' (unmodulated for 18.88us followed by 8 pulses of 423.75khz)
1107
1108 static const int FrameSOF[] = {
1109 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1110 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1111 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1112 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1113 -1, -1, -1, -1,
1114 -1, -1, -1, -1,
1115 1, 1, 1, 1,
1116 1, 1, 1, 1
1117 };
1118 static const int Logic0[] = {
1119 1, 1, 1, 1,
1120 1, 1, 1, 1,
1121 -1, -1, -1, -1,
1122 -1, -1, -1, -1
1123 };
1124 static const int Logic1[] = {
1125 -1, -1, -1, -1,
1126 -1, -1, -1, -1,
1127 1, 1, 1, 1,
1128 1, 1, 1, 1
1129 };
1130
1131 // EOF defined as
1132 // 1) logic '0' (8 pulses of 423.75khz followed by unmodulated for 18.88us)
1133 // 2) 24 pulses of 423.75khz
1134 // 3) Unmodulated time of 56.64us
1135
1136 static const int FrameEOF[] = {
1137 1, 1, 1, 1,
1138 1, 1, 1, 1,
1139 -1, -1, -1, -1,
1140 -1, -1, -1, -1,
1141 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1142 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1143 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1144 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
1145 };
1146
1147 int i, j;
1148 int max = 0, maxPos;
1149
1150 int skip = 4;
1151
1152 if(GraphTraceLen < 1000) return;
1153
1154 // First, correlate for SOF
1155 for(i = 0; i < 100; i++) {
1156 int corr = 0;
1157 for(j = 0; j < arraylen(FrameSOF); j += skip) {
1158 corr += FrameSOF[j]*GraphBuffer[i+(j/skip)];
1159 }
1160 if(corr > max) {
1161 max = corr;
1162 maxPos = i;
1163 }
1164 }
1165 PrintToScrollback("SOF at %d, correlation %d", maxPos,
1166 max/(arraylen(FrameSOF)/skip));
1167
1168 i = maxPos + arraylen(FrameSOF)/skip;
1169 int k = 0;
1170 BYTE outBuf[20];
1171 memset(outBuf, 0, sizeof(outBuf));
1172 BYTE mask = 0x01;
1173 for(;;) {
1174 int corr0 = 0, corr1 = 0, corrEOF = 0;
1175 for(j = 0; j < arraylen(Logic0); j += skip) {
1176 corr0 += Logic0[j]*GraphBuffer[i+(j/skip)];
1177 }
1178 for(j = 0; j < arraylen(Logic1); j += skip) {
1179 corr1 += Logic1[j]*GraphBuffer[i+(j/skip)];
1180 }
1181 for(j = 0; j < arraylen(FrameEOF); j += skip) {
1182 corrEOF += FrameEOF[j]*GraphBuffer[i+(j/skip)];
1183 }
1184 // Even things out by the length of the target waveform.
1185 corr0 *= 4;
1186 corr1 *= 4;
1187
1188 if(corrEOF > corr1 && corrEOF > corr0) {
1189 PrintToScrollback("EOF at %d", i);
1190 break;
1191 } else if(corr1 > corr0) {
1192 i += arraylen(Logic1)/skip;
1193 outBuf[k] |= mask;
1194 } else {
1195 i += arraylen(Logic0)/skip;
1196 }
1197 mask <<= 1;
1198 if(mask == 0) {
1199 k++;
1200 mask = 0x01;
1201 }
1202 if((i+(int)arraylen(FrameEOF)) >= GraphTraceLen) {
1203 PrintToScrollback("ran off end!");
1204 break;
1205 }
1206 }
1207 if(mask != 0x01) {
1208 PrintToScrollback("error, uneven octet! (discard extra bits!)");
1209 PrintToScrollback(" mask=%02x", mask);
1210 }
1211 PrintToScrollback("%d octets", k);
1212
1213 for(i = 0; i < k; i++) {
1214 PrintToScrollback("# %2d: %02x ", i, outBuf[i]);
1215 }
1216 PrintToScrollback("CRC=%04x", Iso15693Crc(outBuf, k-2));
1217 }
1218
1219 static void CmdTiread(char *str)
1220 {
1221 UsbCommand c;
1222 c.cmd = CMD_ACQUIRE_RAW_BITS_TI_TYPE;
1223 SendCommand(&c, FALSE);
1224 }
1225
1226 static void CmdTibits(char *str)
1227 {
1228 int cnt = 0;
1229 int i;
1230 for(i = 0; i < 1536; i += 12) {
1231 UsbCommand c;
1232 c.cmd = CMD_DOWNLOAD_RAW_BITS_TI_TYPE;
1233 c.ext1 = i;
1234 SendCommand(&c, FALSE);
1235 ReceiveCommand(&c);
1236 if(c.cmd != CMD_DOWNLOADED_RAW_BITS_TI_TYPE) {
1237 PrintToScrollback("bad resp");
1238 return;
1239 }
1240 int j;
1241 for(j = 0; j < 12; j++) {
1242 int k;
1243 for(k = 31; k >= 0; k--) {
1244 if(c.d.asDwords[j] & (1 << k)) {
1245 GraphBuffer[cnt++] = 1;
1246 } else {
1247 GraphBuffer[cnt++] = -1;
1248 }
1249 }
1250 }
1251 }
1252 GraphTraceLen = 1536*32;
1253 RepaintGraphWindow();
1254 }
1255
1256 static void CmdTidemod(char *cmdline)
1257 {
1258 /* MATLAB as follows:
1259 f_s = 2000000; % sampling frequency
1260 f_l = 123200; % low FSK tone
1261 f_h = 134200; % high FSK tone
1262
1263 T_l = 119e-6; % low bit duration
1264 T_h = 130e-6; % high bit duration
1265
1266 l = 2*pi*ones(1, floor(f_s*T_l))*(f_l/f_s);
1267 h = 2*pi*ones(1, floor(f_s*T_h))*(f_h/f_s);
1268
1269 l = sign(sin(cumsum(l)));
1270 h = sign(sin(cumsum(h)));
1271 */
1272 static const int LowTone[] = {
1273 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1,
1274 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1,
1275 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1,
1276 -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1,
1277 -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1,
1278 -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1,
1279 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1,
1280 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1,
1281 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1,
1282 -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1,
1283 -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,
1284 -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1,
1285 1, 1, 1, 1, 1, 1, 1, -1, -1, -1,
1286 };
1287 static const int HighTone[] = {
1288 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1,
1289 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1,
1290 -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
1291 -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1,
1292 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1,
1293 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1,
1294 -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
1295 -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,
1296 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1,
1297 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1,
1298 -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
1299 -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1,
1300 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1,
1301 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1,
1302 };
1303
1304 int convLen = max(arraylen(HighTone), arraylen(LowTone));
1305
1306 int i;
1307 for(i = 0; i < GraphTraceLen - convLen; i++) {
1308 int j;
1309 int lowSum = 0, highSum = 0;;
1310 int lowLen = arraylen(LowTone);
1311 int highLen = arraylen(HighTone);
1312
1313 for(j = 0; j < lowLen; j++) {
1314 lowSum += LowTone[j]*GraphBuffer[i+j];
1315 }
1316 for(j = 0; j < highLen; j++) {
1317 highSum += HighTone[j]*GraphBuffer[i+j];
1318 }
1319 lowSum = abs((100*lowSum) / lowLen);
1320 highSum = abs((100*highSum) / highLen);
1321 GraphBuffer[i] = (highSum << 16) | lowSum;
1322 }
1323
1324 for(i = 0; i < GraphTraceLen - convLen - 16; i++) {
1325 int j;
1326 int lowTot = 0, highTot = 0;
1327 // 16 and 15 are f_s divided by f_l and f_h, rounded
1328 for(j = 0; j < 16; j++) {
1329 lowTot += (GraphBuffer[i+j] & 0xffff);
1330 }
1331 for(j = 0; j < 15; j++) {
1332 highTot += (GraphBuffer[i+j] >> 16);
1333 }
1334 GraphBuffer[i] = lowTot - highTot;
1335 }
1336
1337 GraphTraceLen -= (convLen + 16);
1338
1339 RepaintGraphWindow();
1340
1341 // Okay, so now we have unsliced soft decisions; find bit-sync, and then
1342 // get some bits.
1343
1344 int max = 0, maxPos = 0;
1345 for(i = 0; i < 6000; i++) {
1346 int j;
1347 int dec = 0;
1348 for(j = 0; j < 8*arraylen(LowTone); j++) {
1349 dec -= GraphBuffer[i+j];
1350 }
1351 for(; j < 8*arraylen(LowTone) + 8*arraylen(HighTone); j++) {
1352 dec += GraphBuffer[i+j];
1353 }
1354 if(dec > max) {
1355 max = dec;
1356 maxPos = i;
1357 }
1358 }
1359 GraphBuffer[maxPos] = 800;
1360 GraphBuffer[maxPos+1] = -800;
1361
1362 maxPos += 8*arraylen(LowTone);
1363 GraphBuffer[maxPos] = 800;
1364 GraphBuffer[maxPos+1] = -800;
1365 maxPos += 8*arraylen(HighTone);
1366
1367 GraphBuffer[maxPos] = 800;
1368 GraphBuffer[maxPos+1] = -800;
1369
1370 PrintToScrollback("actual data bits start at sample %d", maxPos);
1371
1372 PrintToScrollback("length %d/%d", arraylen(HighTone), arraylen(LowTone));
1373
1374 GraphBuffer[maxPos] = 800;
1375 GraphBuffer[maxPos+1] = -800;
1376
1377 BYTE bits[64+16+8+1];
1378 bits[sizeof(bits)-1] = '\0';
1379
1380 for(i = 0; i < arraylen(bits); i++) {
1381 int high = 0;
1382 int low = 0;
1383 int j;
1384 for(j = 0; j < arraylen(LowTone); j++) {
1385 low -= GraphBuffer[maxPos+j];
1386 }
1387 for(j = 0; j < arraylen(HighTone); j++) {
1388 high += GraphBuffer[maxPos+j];
1389 }
1390 if(high > low) {
1391 bits[i] = '1';
1392 maxPos += arraylen(HighTone);
1393 } else {
1394 bits[i] = '.';
1395 maxPos += arraylen(LowTone);
1396 }
1397 GraphBuffer[maxPos] = 800;
1398 GraphBuffer[maxPos+1] = -800;
1399 }
1400 PrintToScrollback("bits: '%s'", bits);
1401
1402 DWORD h = 0, l = 0;
1403 for(i = 0; i < 32; i++) {
1404 if(bits[i] == '1') {
1405 l |= (1<<i);
1406 }
1407 }
1408 for(i = 32; i < 64; i++) {
1409 if(bits[i] == '1') {
1410 h |= (1<<(i-32));
1411 }
1412 }
1413 PrintToScrollback("hex: %08x %08x", h, l);
1414 }
1415
1416 static void CmdNorm(char *str)
1417 {
1418 int i;
1419 int max = INT_MIN, min = INT_MAX;
1420 for(i = 10; i < GraphTraceLen; i++) {
1421 if(GraphBuffer[i] > max) {
1422 max = GraphBuffer[i];
1423 }
1424 if(GraphBuffer[i] < min) {
1425 min = GraphBuffer[i];
1426 }
1427 }
1428 if(max != min) {
1429 for(i = 0; i < GraphTraceLen; i++) {
1430 GraphBuffer[i] = (GraphBuffer[i] - ((max + min)/2))*1000/
1431 (max - min);
1432 }
1433 }
1434 RepaintGraphWindow();
1435 }
1436
1437 static void CmdDec(char *str)
1438 {
1439 int i;
1440 for(i = 0; i < (GraphTraceLen/2); i++) {
1441 GraphBuffer[i] = GraphBuffer[i*2];
1442 }
1443 GraphTraceLen /= 2;
1444 PrintToScrollback("decimated by 2");
1445 RepaintGraphWindow();
1446 }
1447
1448 static void CmdHpf(char *str)
1449 {
1450 int i;
1451 int accum = 0;
1452 for(i = 10; i < GraphTraceLen; i++) {
1453 accum += GraphBuffer[i];
1454 }
1455 accum /= (GraphTraceLen - 10);
1456 for(i = 0; i < GraphTraceLen; i++) {
1457 GraphBuffer[i] -= accum;
1458 }
1459
1460 RepaintGraphWindow();
1461 }
1462
1463 static void CmdZerocrossings(char *str)
1464 {
1465 int i;
1466 // Zero-crossings aren't meaningful unless the signal is zero-mean.
1467 CmdHpf("");
1468
1469 int sign = 1;
1470 int zc = 0;
1471 int lastZc = 0;
1472 for(i = 0; i < GraphTraceLen; i++) {
1473 if(GraphBuffer[i]*sign >= 0) {
1474 // No change in sign, reproduce the previous sample count.
1475 zc++;
1476 GraphBuffer[i] = lastZc;
1477 } else {
1478 // Change in sign, reset the sample count.
1479 sign = -sign;
1480 GraphBuffer[i] = lastZc;
1481 if(sign > 0) {
1482 lastZc = zc;
1483 zc = 0;
1484 }
1485 }
1486 }
1487
1488 RepaintGraphWindow();
1489 }
1490
1491 static void CmdLtrim(char *str)
1492 {
1493 int i;
1494 int ds = atoi(str);
1495
1496 for(i = ds; i < GraphTraceLen; i++) {
1497 GraphBuffer[i-ds] = GraphBuffer[i];
1498 }
1499 GraphTraceLen -= ds;
1500
1501 RepaintGraphWindow();
1502 }
1503
1504 static void CmdAutoCorr(char *str)
1505 {
1506 static int CorrelBuffer[MAX_GRAPH_TRACE_LEN];
1507
1508 int window = atoi(str);
1509
1510 if(window == 0) {
1511 PrintToScrollback("needs a window");
1512 return;
1513 }
1514
1515 if(window >= GraphTraceLen) {
1516 PrintToScrollback("window must be smaller than trace (%d samples)",
1517 GraphTraceLen);
1518 return;
1519 }
1520
1521 PrintToScrollback("performing %d correlations", GraphTraceLen - window);
1522
1523 int i;
1524 for(i = 0; i < GraphTraceLen - window; i++) {
1525 int sum = 0;
1526 int j;
1527 for(j = 0; j < window; j++) {
1528 sum += (GraphBuffer[j]*GraphBuffer[i+j]) / 256;
1529 }
1530 CorrelBuffer[i] = sum;
1531 }
1532 GraphTraceLen = GraphTraceLen - window;
1533 memcpy(GraphBuffer, CorrelBuffer, GraphTraceLen*sizeof(int));
1534
1535 RepaintGraphWindow();
1536 }
1537
1538 static void CmdVchdemod(char *str)
1539 {
1540 // Is this the entire sync pattern, or does this also include some
1541 // data bits that happen to be the same everywhere? That would be
1542 // lovely to know.
1543 static const int SyncPattern[] = {
1544 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1545 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1546 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1547 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1548 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1549 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1550 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1551 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1552 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1553 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1554 };
1555
1556 // So first, we correlate for the sync pattern, and mark that.
1557 int bestCorrel = 0, bestPos = 0;
1558 int i;
1559 // It does us no good to find the sync pattern, with fewer than
1560 // 2048 samples after it...
1561 for(i = 0; i < (GraphTraceLen-2048); i++) {
1562 int sum = 0;
1563 int j;
1564 for(j = 0; j < arraylen(SyncPattern); j++) {
1565 sum += GraphBuffer[i+j]*SyncPattern[j];
1566 }
1567 if(sum > bestCorrel) {
1568 bestCorrel = sum;
1569 bestPos = i;
1570 }
1571 }
1572 PrintToScrollback("best sync at %d [metric %d]", bestPos, bestCorrel);
1573
1574 char bits[257];
1575 bits[256] = '\0';
1576
1577 int worst = INT_MAX;
1578 int worstPos;
1579
1580 for(i = 0; i < 2048; i += 8) {
1581 int sum = 0;
1582 int j;
1583 for(j = 0; j < 8; j++) {
1584 sum += GraphBuffer[bestPos+i+j];
1585 }
1586 if(sum < 0) {
1587 bits[i/8] = '.';
1588 } else {
1589 bits[i/8] = '1';
1590 }
1591 if(abs(sum) < worst) {
1592 worst = abs(sum);
1593 worstPos = i;
1594 }
1595 }
1596 PrintToScrollback("bits:");
1597 PrintToScrollback("%s", bits);
1598 PrintToScrollback("worst metric: %d at pos %d", worst, worstPos);
1599
1600 if(strcmp(str, "clone")==0) {
1601 GraphTraceLen = 0;
1602 char *s;
1603 for(s = bits; *s; s++) {
1604 int j;
1605 for(j = 0; j < 16; j++) {
1606 GraphBuffer[GraphTraceLen++] = (*s == '1') ? 1 : 0;
1607 }
1608 }
1609 RepaintGraphWindow();
1610 }
1611 }
1612
1613 static void CmdIndalademod(char *str)
1614 {
1615 // Usage: recover 64bit UID by default, specify "224" as arg to recover a 224bit UID
1616
1617 int state = -1;
1618 int count = 0;
1619 int i, j;
1620 // worst case with GraphTraceLen=64000 is < 4096
1621 // under normal conditions it's < 2048
1622 BYTE rawbits[4096];
1623 int rawbit = 0;
1624 int worst = 0, worstPos = 0;
1625 PrintToScrollback("Expecting a bit less than %d raw bits", GraphTraceLen/32);
1626 for(i = 0; i < GraphTraceLen-1; i += 2) {
1627 count+=1;
1628 if((GraphBuffer[i] > GraphBuffer[i + 1]) && (state != 1)) {
1629 if (state == 0) {
1630 for(j = 0; j < count - 8; j += 16) {
1631 rawbits[rawbit++] = 0;
1632 }
1633 if ((abs(count - j)) > worst) {
1634 worst = abs(count - j);
1635 worstPos = i;
1636 }
1637 }
1638 state = 1;
1639 count=0;
1640 } else if((GraphBuffer[i] < GraphBuffer[i + 1]) && (state != 0)) {
1641 if (state == 1) {
1642 for(j = 0; j < count - 8; j += 16) {
1643 rawbits[rawbit++] = 1;
1644 }
1645 if ((abs(count - j)) > worst) {
1646 worst = abs(count - j);
1647 worstPos = i;
1648 }
1649 }
1650 state = 0;
1651 count=0;
1652 }
1653 }
1654 PrintToScrollback("Recovered %d raw bits", rawbit);
1655 PrintToScrollback("worst metric (0=best..7=worst): %d at pos %d", worst, worstPos);
1656
1657 // Finding the start of a UID
1658 int uidlen, long_wait;
1659 if(strcmp(str, "224") == 0) {
1660 uidlen=224;
1661 long_wait=30;
1662 } else {
1663 uidlen=64;
1664 long_wait=29;
1665 }
1666 int start;
1667 int first = 0;
1668 for(start = 0; start <= rawbit - uidlen; start++) {
1669 first = rawbits[start];
1670 for(i = start; i < start + long_wait; i++) {
1671 if(rawbits[i] != first) {
1672 break;
1673 }
1674 }
1675 if(i == (start + long_wait)) {
1676 break;
1677 }
1678 }
1679 if(start == rawbit - uidlen + 1) {
1680 PrintToScrollback("nothing to wait for");
1681 return;
1682 }
1683
1684 // Inverting signal if needed
1685 if(first == 1) {
1686 for(i = start; i < rawbit; i++) {
1687 rawbits[i] = !rawbits[i];
1688 }
1689 }
1690
1691 // Dumping UID
1692 BYTE bits[224];
1693 char showbits[225];
1694 showbits[uidlen]='\0';
1695 int bit;
1696 i = start;
1697 int times = 0;
1698 if(uidlen > rawbit) {
1699 PrintToScrollback("Warning: not enough raw bits to get a full UID");
1700 for(bit = 0; bit < rawbit; bit++) {
1701 bits[bit] = rawbits[i++];
1702 // As we cannot know the parity, let's use "." and "/"
1703 showbits[bit] = '.' + bits[bit];
1704 }
1705 showbits[bit+1]='\0';
1706 PrintToScrollback("Partial UID=%s", showbits);
1707 return;
1708 } else {
1709 for(bit = 0; bit < uidlen; bit++) {
1710 bits[bit] = rawbits[i++];
1711 showbits[bit] = '0' + bits[bit];
1712 }
1713 times = 1;
1714 }
1715 PrintToScrollback("UID=%s", showbits);
1716
1717 // Checking UID against next occurences
1718 for(; i + uidlen <= rawbit;) {
1719 int failed = 0;
1720 for(bit = 0; bit < uidlen; bit++) {
1721 if(bits[bit] != rawbits[i++]) {
1722 failed = 1;
1723 break;
1724 }
1725 }
1726 if (failed == 1) {
1727 break;
1728 }
1729 times += 1;
1730 }
1731 PrintToScrollback("Occurences: %d (expected %d)", times, (rawbit - start) / uidlen);
1732
1733 // Remodulating for tag cloning
1734 GraphTraceLen = 32*uidlen;
1735 i = 0;
1736 int phase = 0;
1737 for(bit = 0; bit < uidlen; bit++) {
1738 if(bits[bit] == 0) {
1739 phase = 0;
1740 } else {
1741 phase = 1;
1742 }
1743 int j;
1744 for(j = 0; j < 32; j++) {
1745 GraphBuffer[i++] = phase;
1746 phase = !phase;
1747 }
1748 }
1749
1750 RepaintGraphWindow();
1751 }
1752
1753 static void CmdFlexdemod(char *str)
1754 {
1755 int i;
1756 for(i = 0; i < GraphTraceLen; i++) {
1757 if(GraphBuffer[i] < 0) {
1758 GraphBuffer[i] = -1;
1759 } else {
1760 GraphBuffer[i] = 1;
1761 }
1762 }
1763
1764 #define LONG_WAIT 100
1765 int start;
1766 for(start = 0; start < GraphTraceLen - LONG_WAIT; start++) {
1767 int first = GraphBuffer[start];
1768 for(i = start; i < start + LONG_WAIT; i++) {
1769 if(GraphBuffer[i] != first) {
1770 break;
1771 }
1772 }
1773 if(i == (start + LONG_WAIT)) {
1774 break;
1775 }
1776 }
1777 if(start == GraphTraceLen - LONG_WAIT) {
1778 PrintToScrollback("nothing to wait for");
1779 return;
1780 }
1781
1782 GraphBuffer[start] = 2;
1783 GraphBuffer[start+1] = -2;
1784
1785 BYTE bits[64];
1786
1787 int bit;
1788 i = start;
1789 for(bit = 0; bit < 64; bit++) {
1790 int j;
1791 int sum = 0;
1792 for(j = 0; j < 16; j++) {
1793 sum += GraphBuffer[i++];
1794 }
1795 if(sum > 0) {
1796 bits[bit] = 1;
1797 } else {
1798 bits[bit] = 0;
1799 }
1800 PrintToScrollback("bit %d sum %d", bit, sum);
1801 }
1802
1803 for(bit = 0; bit < 64; bit++) {
1804 int j;
1805 int sum = 0;
1806 for(j = 0; j < 16; j++) {
1807 sum += GraphBuffer[i++];
1808 }
1809 if(sum > 0 && bits[bit] != 1) {
1810 PrintToScrollback("oops1 at %d", bit);
1811 }
1812 if(sum < 0 && bits[bit] != 0) {
1813 PrintToScrollback("oops2 at %d", bit);
1814 }
1815 }
1816
1817 GraphTraceLen = 32*64;
1818 i = 0;
1819 int phase = 0;
1820 for(bit = 0; bit < 64; bit++) {
1821 if(bits[bit] == 0) {
1822 phase = 0;
1823 } else {
1824 phase = 1;
1825 }
1826 int j;
1827 for(j = 0; j < 32; j++) {
1828 GraphBuffer[i++] = phase;
1829 phase = !phase;
1830 }
1831 }
1832
1833 RepaintGraphWindow();
1834 }
1835
1836 /*
1837 * Generic command to demodulate ASK.
1838 *
1839 * Argument is convention: positive or negative (High mod means zero
1840 * or high mod means one)
1841 *
1842 * Updates the Graph trace with 0/1 values
1843 *
1844 * Arguments:
1845 * c : 0 or 1
1846 */
1847
1848 static void Cmdaskdemod(char *str) {
1849 int i;
1850 int n = 0;
1851 int c,high,low = 0;
1852
1853 // TODO: complain if we do not give 2 arguments here !
1854 sscanf(str, "%i", &c);
1855
1856 /* Detect high and lows and clock */
1857 for (i = 0; i < GraphTraceLen; i++)
1858 {
1859 if (GraphBuffer[i] > high)
1860 high = GraphBuffer[i];
1861 else if (GraphBuffer[i] < low)
1862 low = GraphBuffer[i];
1863 }
1864
1865 if (GraphBuffer[0] > 0) {
1866 GraphBuffer[0] = 1-c;
1867 } else {
1868 GraphBuffer[0] = c;
1869 }
1870 for(i=1;i<GraphTraceLen;i++) {
1871 /* Transitions are detected at each peak
1872 * Transitions are either:
1873 * - we're low: transition if we hit a high
1874 * - we're high: transition if we hit a low
1875 * (we need to do it this way because some tags keep high or
1876 * low for long periods, others just reach the peak and go
1877 * down)
1878 */
1879 if ((GraphBuffer[i]==high) && (GraphBuffer[i-1] == c)) {
1880 GraphBuffer[i]=1-c;
1881 } else if ((GraphBuffer[i]==low) && (GraphBuffer[i-1] == (1-c))){
1882 GraphBuffer[i] = c;
1883 } else {
1884 /* No transition */
1885 GraphBuffer[i] = GraphBuffer[i-1];
1886 }
1887 }
1888 RepaintGraphWindow();
1889 }
1890
1891 /* Print our clock rate */
1892 static void Cmddetectclockrate(char *str)
1893 {
1894 int clock = detectclock(0);
1895 PrintToScrollback("Auto-detected clock rate: %d", clock);
1896 }
1897
1898 /*
1899 * Detect clock rate
1900 */
1901 int detectclock(int peak)
1902 {
1903 int i;
1904 int clock = 0xFFFF;
1905 int lastpeak = 0;
1906
1907 /* Detect peak if we don't have one */
1908 if (!peak)
1909 for (i = 0; i < GraphTraceLen; i++)
1910 if (GraphBuffer[i] > peak)
1911 peak = GraphBuffer[i];
1912
1913 for (i = 1; i < GraphTraceLen; i++)
1914 {
1915 /* If this is the beginning of a peak */
1916 if (GraphBuffer[i-1] != GraphBuffer[i] && GraphBuffer[i] == peak)
1917 {
1918 /* Find lowest difference between peaks */
1919 if (lastpeak && i - lastpeak < clock)
1920 {
1921 clock = i - lastpeak;
1922 }
1923 lastpeak = i;
1924 }
1925 }
1926
1927 return clock;
1928 }
1929
1930 /* Get or auto-detect clock rate */
1931 int GetClock(char *str, int peak)
1932 {
1933 int clock;
1934
1935 sscanf(str, "%i", &clock);
1936 if (!strcmp(str, ""))
1937 clock = 0;
1938
1939 /* Auto-detect clock */
1940 if (!clock)
1941 {
1942 clock = detectclock(peak);
1943
1944 /* Only print this message if we're not looping something */
1945 if (!go)
1946 PrintToScrollback("Auto-detected clock rate: %d", clock);
1947 }
1948
1949 return clock;
1950 }
1951
1952 /*
1953 * Convert to a bitstream
1954 */
1955 static void Cmdbitstream(char *str) {
1956 int i, j;
1957 int bit;
1958 int gtl;
1959 int clock;
1960 int low = 0;
1961 int high = 0;
1962 int hithigh, hitlow, first;
1963
1964 /* Detect high and lows and clock */
1965 for (i = 0; i < GraphTraceLen; i++)
1966 {
1967 if (GraphBuffer[i] > high)
1968 high = GraphBuffer[i];
1969 else if (GraphBuffer[i] < low)
1970 low = GraphBuffer[i];
1971 }
1972
1973 /* Get our clock */
1974 clock = GetClock(str, high);
1975
1976 gtl = CmdClearGraph(0);
1977
1978 bit = 0;
1979 for (i = 0; i < (int)(gtl / clock); i++)
1980 {
1981 hithigh = 0;
1982 hitlow = 0;
1983 first = 1;
1984
1985 /* Find out if we hit both high and low peaks */
1986 for (j = 0; j < clock; j++)
1987 {
1988 if (GraphBuffer[(i * clock) + j] == high)
1989 hithigh = 1;
1990 else if (GraphBuffer[(i * clock) + j] == low)
1991 hitlow = 1;
1992
1993 /* it doesn't count if it's the first part of our read
1994 because it's really just trailing from the last sequence */
1995 if (first && (hithigh || hitlow))
1996 hithigh = hitlow = 0;
1997 else
1998 first = 0;
1999
2000 if (hithigh && hitlow)
2001 break;
2002 }
2003
2004 /* If we didn't hit both high and low peaks, we had a bit transition */
2005 if (!hithigh || !hitlow)
2006 bit ^= 1;
2007
2008 CmdAppendGraph(0, clock, bit);
2009 // for (j = 0; j < (int)(clock/2); j++)
2010 // GraphBuffer[(i * clock) + j] = bit ^ 1;
2011 // for (j = (int)(clock/2); j < clock; j++)
2012 // GraphBuffer[(i * clock) + j] = bit;
2013 }
2014
2015 RepaintGraphWindow();
2016 }
2017
2018 /* Modulate our data into manchester */
2019 static void Cmdmanchestermod(char *str)
2020 {
2021 int i, j;
2022 int clock;
2023 int bit, lastbit, wave;
2024
2025 /* Get our clock */
2026 clock = GetClock(str, 0);
2027
2028 wave = 0;
2029 lastbit = 1;
2030 for (i = 0; i < (int)(GraphTraceLen / clock); i++)
2031 {
2032 bit = GraphBuffer[i * clock] ^ 1;
2033
2034 for (j = 0; j < (int)(clock/2); j++)
2035 GraphBuffer[(i * clock) + j] = bit ^ lastbit ^ wave;
2036 for (j = (int)(clock/2); j < clock; j++)
2037 GraphBuffer[(i * clock) + j] = bit ^ lastbit ^ wave ^ 1;
2038
2039 /* Keep track of how we start our wave and if we changed or not this time */
2040 wave ^= bit ^ lastbit;
2041 lastbit = bit;
2042 }
2043
2044 RepaintGraphWindow();
2045 }
2046
2047 /*
2048 * Manchester demodulate a bitstream. The bitstream needs to be already in
2049 * the GraphBuffer as 0 and 1 values
2050 *
2051 * Give the clock rate as argument in order to help the sync - the algorithm
2052 * resyncs at each pulse anyway.
2053 *
2054 * Not optimized by any means, this is the 1st time I'm writing this type of
2055 * routine, feel free to improve...
2056 *
2057 * 1st argument: clock rate (as number of samples per clock rate)
2058 * Typical values can be 64, 32, 128...
2059 */
2060 static void Cmdmanchesterdemod(char *str) {
2061 int i, j;
2062 int bit;
2063 int clock;
2064 int lastval;
2065 int low = 0;
2066 int high = 0;
2067 int hithigh, hitlow, first;
2068 int lc = 0;
2069 int bitidx = 0;
2070 int bit2idx = 0;
2071 int warnings = 0;
2072
2073 /* Holds the decoded bitstream: each clock period contains 2 bits */
2074 /* later simplified to 1 bit after manchester decoding. */
2075 /* Add 10 bits to allow for noisy / uncertain traces without aborting */
2076 /* int BitStream[GraphTraceLen*2/clock+10]; */
2077
2078 /* But it does not work if compiling on WIndows: therefore we just allocate a */
2079 /* large array */
2080 int BitStream[MAX_GRAPH_TRACE_LEN];
2081
2082 /* Detect high and lows */
2083 for (i = 0; i < GraphTraceLen; i++)
2084 {
2085 if (GraphBuffer[i] > high)
2086 high = GraphBuffer[i];
2087 else if (GraphBuffer[i] < low)
2088 low = GraphBuffer[i];
2089 }
2090
2091 /* Get our clock */
2092 clock = GetClock(str, high);
2093
2094 int tolerance = clock/4;
2095
2096 /* Detect first transition */
2097 /* Lo-Hi (arbitrary) */
2098 for (i = 0; i < GraphTraceLen; i++)
2099 {
2100 if (GraphBuffer[i] == low)
2101 {
2102 lastval = i;
2103 break;
2104 }
2105 }
2106
2107 /* If we're not working with 1/0s, demod based off clock */
2108 if (high != 1)
2109 {
2110 bit = 0; /* We assume the 1st bit is zero, it may not be
2111 * the case: this routine (I think) has an init problem.
2112 * Ed.
2113 */
2114 for (; i < (int)(GraphTraceLen / clock); i++)
2115 {
2116 hithigh = 0;
2117 hitlow = 0;
2118 first = 1;
2119
2120 /* Find out if we hit both high and low peaks */
2121 for (j = 0; j < clock; j++)
2122 {
2123 if (GraphBuffer[(i * clock) + j] == high)
2124 hithigh = 1;
2125 else if (GraphBuffer[(i * clock) + j] == low)
2126 hitlow = 1;
2127
2128 /* it doesn't count if it's the first part of our read
2129 because it's really just trailing from the last sequence */
2130 if (first && (hithigh || hitlow))
2131 hithigh = hitlow = 0;
2132 else
2133 first = 0;
2134
2135 if (hithigh && hitlow)
2136 break;
2137 }
2138
2139 /* If we didn't hit both high and low peaks, we had a bit transition */
2140 if (!hithigh || !hitlow)
2141 bit ^= 1;
2142
2143 BitStream[bit2idx++] = bit;
2144 }
2145 }
2146
2147 /* standard 1/0 bitstream */
2148 else
2149 {
2150
2151 /* Then detect duration between 2 successive transitions */
2152 for (bitidx = 1; i < GraphTraceLen; i++)
2153 {
2154 if (GraphBuffer[i-1] != GraphBuffer[i])
2155 {
2156 lc = i-lastval;
2157 lastval = i;
2158
2159 // Error check: if bitidx becomes too large, we do not
2160 // have a Manchester encoded bitstream or the clock is really
2161 // wrong!
2162 if (bitidx > (GraphTraceLen*2/clock+8) ) {
2163 PrintToScrollback("Error: the clock you gave is probably wrong, aborting.");
2164 return;
2165 }
2166 // Then switch depending on lc length:
2167 // Tolerance is 1/4 of clock rate (arbitrary)
2168 if (abs(lc-clock/2) < tolerance) {
2169 // Short pulse : either "1" or "0"
2170 BitStream[bitidx++]=GraphBuffer[i-1];
2171 } else if (abs(lc-clock) < tolerance) {
2172 // Long pulse: either "11" or "00"
2173 BitStream[bitidx++]=GraphBuffer[i-1];
2174 BitStream[bitidx++]=GraphBuffer[i-1];
2175 } else {
2176 // Error
2177 warnings++;
2178 PrintToScrollback("Warning: Manchester decode error for pulse width detection.");
2179 PrintToScrollback("(too many of those messages mean either the stream is not Manchester encoded, or clock is wrong)");
2180
2181 if (warnings > 100)
2182 {
2183 PrintToScrollback("Error: too many detection errors, aborting.");
2184 return;
2185 }
2186 }
2187 }
2188 }
2189
2190 // At this stage, we now have a bitstream of "01" ("1") or "10" ("0"), parse it into final decoded bitstream
2191 // Actually, we overwrite BitStream with the new decoded bitstream, we just need to be careful
2192 // to stop output at the final bitidx2 value, not bitidx
2193 for (i = 0; i < bitidx; i += 2) {
2194 if ((BitStream[i] == 0) && (BitStream[i+1] == 1)) {
2195 BitStream[bit2idx++] = 1;
2196 } else if ((BitStream[i] == 1) && (BitStream[i+1] == 0)) {
2197 BitStream[bit2idx++] = 0;
2198 } else {
2199 // We cannot end up in this state, this means we are unsynchronized,
2200 // move up 1 bit:
2201 i++;
2202 warnings++;
2203 PrintToScrollback("Unsynchronized, resync...");
2204 PrintToScrollback("(too many of those messages mean the stream is not Manchester encoded)");
2205
2206 if (warnings > 100)
2207 {
2208 PrintToScrollback("Error: too many decode errors, aborting.");
2209 return;
2210 }
2211 }
2212 }
2213 }
2214
2215 PrintToScrollback("Manchester decoded bitstream");
2216 // Now output the bitstream to the scrollback by line of 16 bits
2217 for (i = 0; i < (bit2idx-16); i+=16) {
2218 PrintToScrollback("%i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i",
2219 BitStream[i],
2220 BitStream[i+1],
2221 BitStream[i+2],
2222 BitStream[i+3],
2223 BitStream[i+4],
2224 BitStream[i+5],
2225 BitStream[i+6],
2226 BitStream[i+7],
2227 BitStream[i+8],
2228 BitStream[i+9],
2229 BitStream[i+10],
2230 BitStream[i+11],
2231 BitStream[i+12],
2232 BitStream[i+13],
2233 BitStream[i+14],
2234 BitStream[i+15]);
2235 }
2236 }
2237
2238
2239
2240 /*
2241 * Usage ???
2242 */
2243 static void CmdHiddemod(char *str)
2244 {
2245 if(GraphTraceLen < 4800) {
2246 PrintToScrollback("too short; need at least 4800 samples");
2247 return;
2248 }
2249
2250 GraphTraceLen = 4800;
2251 int i;
2252 for(i = 0; i < GraphTraceLen; i++) {
2253 if(GraphBuffer[i] < 0) {
2254 GraphBuffer[i] = 0;
2255 } else {
2256 GraphBuffer[i] = 1;
2257 }
2258 }
2259 RepaintGraphWindow();
2260 }
2261
2262 static void CmdPlot(char *str)
2263 {
2264 ShowGraphWindow();
2265 }
2266
2267 static void CmdHide(char *str)
2268 {
2269 HideGraphWindow();
2270 }
2271
2272 static void CmdScale(char *str)
2273 {
2274 CursorScaleFactor = atoi(str);
2275 if(CursorScaleFactor == 0) {
2276 PrintToScrollback("bad, can't have zero scale");
2277 CursorScaleFactor = 1;
2278 }
2279 RepaintGraphWindow();
2280 }
2281
2282 static void CmdSave(char *str)
2283 {
2284 FILE *f = fopen(str, "w");
2285 if(!f) {
2286 PrintToScrollback("couldn't open '%s'", str);
2287 return;
2288 }
2289 int i;
2290 for(i = 0; i < GraphTraceLen; i++) {
2291 fprintf(f, "%d\n", GraphBuffer[i]);
2292 }
2293 fclose(f);
2294 PrintToScrollback("saved to '%s'", str);
2295 }
2296
2297 static void CmdLoad(char *str)
2298 {
2299 FILE *f = fopen(str, "r");
2300 if(!f) {
2301 PrintToScrollback("couldn't open '%s'", str);
2302 return;
2303 }
2304
2305 GraphTraceLen = 0;
2306 char line[80];
2307 while(fgets(line, sizeof(line), f)) {
2308 GraphBuffer[GraphTraceLen] = atoi(line);
2309 GraphTraceLen++;
2310 }
2311 fclose(f);
2312 PrintToScrollback("loaded %d samples", GraphTraceLen);
2313 RepaintGraphWindow();
2314 }
2315
2316 static void CmdHIDsimTAG(char *str)
2317 {
2318 unsigned int hi=0, lo=0;
2319 int n=0, i=0;
2320 UsbCommand c;
2321
2322 while (sscanf(&str[i++], "%1x", &n ) == 1) {
2323 hi=(hi<<4)|(lo>>28);
2324 lo=(lo<<4)|(n&0xf);
2325 }
2326
2327 PrintToScrollback("Emulating tag with ID %x%16x", hi, lo);
2328
2329 c.cmd = CMD_HID_SIM_TAG;
2330 c.ext1 = hi;
2331 c.ext2 = lo;
2332 SendCommand(&c, FALSE);
2333 }
2334
2335 static void CmdLcdReset(char *str)
2336 {
2337 UsbCommand c;
2338 c.cmd = CMD_LCD_RESET;
2339 c.ext1 = atoi(str);
2340 SendCommand(&c, FALSE);
2341 }
2342
2343 static void CmdLcd(char *str)
2344 {
2345 int i, j;
2346 UsbCommand c;
2347 c.cmd = CMD_LCD;
2348 sscanf(str, "%x %d", &i, &j);
2349 while (j--) {
2350 c.ext1 = i&0x1ff;
2351 SendCommand(&c, FALSE);
2352 }
2353 }
2354
2355
2356
2357 static void CmdTest(char *str)
2358 {
2359 }
2360
2361 /*
2362 * Sets the divisor for LF frequency clock: lets the user choose any LF frequency below
2363 * 600kHz.
2364 */
2365 static void CmdSetDivisor(char *str)
2366 {
2367 UsbCommand c;
2368 c.cmd = CMD_SET_LF_DIVISOR;
2369 c.ext1 = atoi(str);
2370 if (( c.ext1<0) || (c.ext1>255)) {
2371 PrintToScrollback("divisor must be between 19 and 255");
2372 } else {
2373 SendCommand(&c, FALSE);
2374 PrintToScrollback("Divisor set, expected freq=%dHz", 12000000/(c.ext1+1));
2375 }
2376 }
2377
2378 static void CmdSweepLF(char *str)
2379 {
2380 UsbCommand c;
2381 c.cmd = CMD_SWEEP_LF;
2382 SendCommand(&c, FALSE);
2383 }
2384
2385
2386 typedef void HandlerFunction(char *cmdline);
2387
2388 /* in alphabetic order */
2389 static struct {
2390 char *name;
2391 HandlerFunction *handler;
2392 int offline; // 1 if the command can be used when in offline mode
2393 char *docString;
2394 } CommandTable[] = {
2395 "askdemod", Cmdaskdemod,1, "<samples per bit> <0|1> -- Attempt to demodulate simple ASK tags",
2396 "autocorr", CmdAutoCorr,1, "<window length> -- Autocorrelation over window",
2397 "bitsamples", CmdBitsamples,0, " Get raw samples as bitstring",
2398 "bitstream", Cmdbitstream,1, "[clock rate] -- Convert waveform into a bitstream",
2399 "dec", CmdDec,1, " Decimate samples",
2400 "detectclock", Cmddetectclockrate,1, " Detect clock rate",
2401 "em410xsim", CmdEM410xsim,1, "<UID> -- Simulate EM410x tag",
2402 "em410xread", CmdEM410xread,1, "[clock rate] -- Extract ID from EM410x tag",
2403 "em410xwatch", CmdEM410xwatch,0, " Watches for EM410x tags",
2404 "exit", CmdQuit,1, " Exit program",
2405 "flexdemod", CmdFlexdemod,1, " Demodulate samples for FlexPass",
2406 "fpgaoff", CmdFPGAOff,0, " Set FPGA off", // ## FPGA Control
2407 "hexsamples", CmdHexsamples,0, "<blocks> -- Dump big buffer as hex bytes",
2408 "hi14alist", CmdHi14alist,0, " List ISO 14443a history", // ## New list command
2409 "hi14areader", CmdHi14areader,0, " Act like an ISO14443 Type A reader", // ## New reader command
2410 "hi14asim", CmdHi14asim,0, "<UID> -- Fake ISO 14443a tag", // ## Simulate 14443a tag
2411 "hi14asnoop", CmdHi14asnoop,0, " Eavesdrop ISO 14443 Type A", // ## New snoop command
2412 "hi14bdemod", CmdHi14bdemod,1, " Demodulate ISO14443 Type B from tag",
2413 "hi14list", CmdHi14list,0, " List ISO 14443 history",
2414 "hi14read", CmdHi14read,0, " Read HF tag (ISO 14443)",
2415 "hi14sim", CmdHi14sim,0, " Fake ISO 14443 tag",
2416 "hi14snoop", CmdHi14snoop,0, " Eavesdrop ISO 14443",
2417 "hi15demod", CmdHi15demod,1, " Demodulate ISO15693 from tag",
2418 "hi15read", CmdHi15read,0, " Read HF tag (ISO 15693)",
2419 "hi15reader", CmdHi15reader,0, " Act like an ISO15693 reader", // new command greg
2420 "hi15sim", CmdHi15tag,0, " Fake an ISO15693 tag", // new command greg
2421 "hiddemod", CmdHiddemod,1, " Demodulate HID Prox Card II (not optimal)",
2422 "hide", CmdHide,1, " Hide graph window",
2423 "hidfskdemod", CmdHIDdemodFSK,0, " Realtime HID FSK demodulator",
2424 "hidsimtag", CmdHIDsimTAG,0, "<ID> -- HID tag simulator",
2425 "higet", CmdHi14read_sim,0, "<samples> -- Get samples HF, 'analog'",
2426 "hisamples", CmdHisamples,0, " Get raw samples for HF tag",
2427 "hisampless", CmdHisampless,0, "<samples> -- Get signed raw samples, HF tag",
2428 "hisamplest", CmdHi14readt,0, " Get samples HF, for testing",
2429 "hisimlisten", CmdHisimlisten,0, " Get HF samples as fake tag",
2430 "hpf", CmdHpf,1, " Remove DC offset from trace",
2431 "indalademod", CmdIndalademod,0, "['224'] -- Demodulate samples for Indala",
2432 "lcd", CmdLcd,0, "<HEX command> <count> -- Send command/data to LCD",
2433 "lcdreset", CmdLcdReset,0, " Hardware reset LCD",
2434 "load", CmdLoad,1, "<filename> -- Load trace (to graph window",
2435 "loread", CmdLoread,0, "['h'] -- Read 125/134 kHz LF ID-only tag (option 'h' for 134)",
2436 "losamples", CmdLosamples,0, "[128 - 16000] -- Get raw samples for LF tag",
2437 "losim", CmdLosim,0, " Simulate LF tag",
2438 "ltrim", CmdLtrim,1, "<samples> -- Trim samples from left of trace",
2439 "mandemod", Cmdmanchesterdemod,1, "[clock rate] -- Try a Manchester demodulation on a binary stream",
2440 "manmod", Cmdmanchestermod,1, "[clock rate] -- Manchester modulate a binary stream",
2441 "norm", CmdNorm,1, " Normalize max/min to +/-500",
2442 "plot", CmdPlot,1, " Show graph window",
2443 "quit", CmdQuit,1, " Quit program",
2444 "reset", CmdReset,0, " Reset the Proxmark3",
2445 "save", CmdSave,1, "<filename> -- Save trace (from graph window)",
2446 "scale", CmdScale,1, "<int> -- Set cursor display scale",
2447 "setlfdivisor", CmdSetDivisor,0, "<19 - 255> -- Drive LF antenna at 12Mhz/(divisor+1)",
2448 "sri512read", CmdSri512read,0, "<int> -- Read contents of a SRI512 tag",
2449 "sweeplf", CmdSweepLF,0, " Sweep through LF freq range and store results in buffer",
2450 "tibits", CmdTibits,0, " Get raw bits for TI-type LF tag",
2451 "tidemod", CmdTidemod,0, " Demodulate raw bits for TI-type LF tag",
2452 "tiread", CmdTiread,0, " Read a TI-type 134 kHz tag",
2453 "tune", CmdTune,0, " Measure antenna tuning",
2454 "vchdemod", CmdVchdemod,0, "['clone'] -- Demodulate samples for VeriChip",
2455 "zerocrossings", CmdZerocrossings,1, " Count time between zero-crossings",
2456 };
2457
2458
2459 //-----------------------------------------------------------------------------
2460 // Entry point into our code: called whenever the user types a command and
2461 // then presses Enter, which the full command line that they typed.
2462 //-----------------------------------------------------------------------------
2463 void CommandReceived(char *cmd)
2464 {
2465 int i;
2466
2467 PrintToScrollback("> %s", cmd);
2468
2469 if(strcmp(cmd, "help")==0) {
2470 if (offline) PrintToScrollback("Operating in OFFLINE mode (no device connected)");
2471 PrintToScrollback("\r\nAvailable commands:");
2472 for(i = 0; i < sizeof(CommandTable) / sizeof(CommandTable[0]); i++) {
2473 if (offline && (CommandTable[i].offline==0)) continue;
2474 char line[256];
2475 memset(line, ' ', sizeof(line));
2476 strcpy(line+2, CommandTable[i].name);
2477 line[strlen(line)] = ' ';
2478 sprintf(line+15, " -- %s", CommandTable[i].docString);
2479 PrintToScrollback("%s", line);
2480 }
2481 PrintToScrollback("");
2482 PrintToScrollback("and also: help, cls");
2483 return;
2484 }
2485
2486 for(i = 0; i < sizeof(CommandTable) / sizeof(CommandTable[0]); i++) {
2487 char *name = CommandTable[i].name;
2488 if(memcmp(cmd, name, strlen(name))==0 &&
2489 (cmd[strlen(name)] == ' ' || cmd[strlen(name)] == '\0'))
2490 {
2491 cmd += strlen(name);
2492 while(*cmd == ' ') {
2493 cmd++;
2494 }
2495 if (offline && (CommandTable[i].offline==0)) {
2496 PrintToScrollback("Offline mode, cannot use this command.");
2497 return;
2498 }
2499 (CommandTable[i].handler)(cmd);
2500 return;
2501 }
2502 }
2503 PrintToScrollback(">> bad command '%s'", cmd);
2504 }
2505
2506 //-----------------------------------------------------------------------------
2507 // Entry point into our code: called whenever we received a packet over USB
2508 // that we weren't necessarily expecting, for example a debug print.
2509 //-----------------------------------------------------------------------------
2510 void UsbCommandReceived(UsbCommand *c)
2511 {
2512 switch(c->cmd) {
2513 case CMD_DEBUG_PRINT_STRING: {
2514 char s[100];
2515 if(c->ext1 > 70 || c->ext1 < 0) {
2516 c->ext1 = 0;
2517 }
2518 memcpy(s, c->d.asBytes, c->ext1);
2519 s[c->ext1] = '\0';
2520 PrintToScrollback("#db# %s", s);
2521 break;
2522 }
2523
2524 case CMD_DEBUG_PRINT_INTEGERS:
2525 PrintToScrollback("#db# %08x, %08x, %08x\r\n", c->ext1, c->ext2, c->ext3);
2526 break;
2527
2528 case CMD_MEASURED_ANTENNA_TUNING: {
2529 int zLf, zHf;
2530 int vLf125, vLf134, vHf;
2531 vLf125 = c->ext1 & 0xffff;
2532 vLf134 = c->ext1 >> 16;
2533 vHf = c->ext2;
2534 zLf = c->ext3 & 0xffff;
2535 zHf = c->ext3 >> 16;
2536 PrintToScrollback("# LF antenna @ %3d mA / %5d mV [%d ohms] 125Khz",
2537 vLf125/zLf, vLf125, zLf);
2538 PrintToScrollback("# LF antenna @ %3d mA / %5d mV [%d ohms] 134Khz",
2539 vLf134/((zLf*125)/134), vLf134, (zLf*125)/134);
2540 PrintToScrollback("# HF antenna @ %3d mA / %5d mV [%d ohms] 13.56Mhz",
2541 vHf/zHf, vHf, zHf);
2542 break;
2543 }
2544 default:
2545 PrintToScrollback("unrecognized command %08x\n", c->cmd);
2546 break;
2547 }
2548 }
Impressum, Datenschutz