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