]> git.zerfleddert.de Git - proxmark3-svn/blob - winsrc/command.cpp
Various traces from tags for testing and educational purposes
[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. bit length in argument.
1826 * Giving the bit length helps discriminate ripple effects
1827 * upon zero crossing for noisy traces.
1828 *
1829 * Second is convention: positive or negative (High mod means zero
1830 * or high mod means one)
1831 *
1832 * Updates the Graph trace with 0/1 values
1833 *
1834 * Arguments:
1835 * sl : bit length in terms of number of samples per bit
1836 * (use yellow/purple markers to compute).
1837 * c : 0 or 1
1838 */
1839
1840 static void Cmdaskdemod(char *str) {
1841 int i;
1842 int sign = 1;
1843 int n = 0;
1844 int c = 0;
1845 int t1 = 0;
1846
1847 // TODO: complain if we do not give 2 arguments here !
1848 sscanf(str, "%i %i", &n, &c);
1849 if (c == 0) {
1850 c = 1 ;
1851 } else {
1852 c = -1;
1853 }
1854
1855 if (GraphBuffer[0]*c > 0) {
1856 GraphBuffer[0] = 1;
1857 } else {
1858 GraphBuffer[0] = 0;
1859 }
1860 for(i=1;i<GraphTraceLen;i++) {
1861 /* Analyse signal within the symbol length */
1862 /* Decide if we crossed a zero */
1863 if (GraphBuffer[i]*sign < 0) {
1864 /* Crossed a zero, check if this is a ripple or not */
1865 if ( (i-t1) > n/4 ) {
1866 sign = -sign;
1867 t1=i;
1868 if (GraphBuffer[i]*c > 0){
1869 GraphBuffer[i]=1;
1870 } else {
1871 GraphBuffer[i]=0;
1872 }
1873 } else {
1874 /* This is a ripple, set the current sample value
1875 to the same as previous */
1876 GraphBuffer[i] = GraphBuffer[i-1];
1877 }
1878 } else {
1879 GraphBuffer[i] = GraphBuffer[i-1];
1880 }
1881 }
1882 RepaintGraphWindow();
1883 }
1884
1885 /* Print our clock rate */
1886 static void Cmddetectclockrate(char *str)
1887 {
1888 int clock = detectclock(0);
1889 PrintToScrollback("Auto-detected clock rate: %d", clock);
1890 }
1891
1892 /*
1893 * Detect clock rate
1894 */
1895 int detectclock(int peak)
1896 {
1897 int i;
1898 int clock = 0xFFFF;
1899 int lastpeak = 0;
1900
1901 /* Detect peak if we don't have one */
1902 if (!peak)
1903 for (i = 0; i < GraphTraceLen; i++)
1904 if (GraphBuffer[i] > peak)
1905 peak = GraphBuffer[i];
1906
1907 for (i = 1; i < GraphTraceLen; i++)
1908 {
1909 /* If this is the beginning of a peak */
1910 if (GraphBuffer[i-1] != GraphBuffer[i] && GraphBuffer[i] == peak)
1911 {
1912 /* Find lowest difference between peaks */
1913 if (lastpeak && i - lastpeak < clock)
1914 {
1915 clock = i - lastpeak;
1916 }
1917 lastpeak = i;
1918 }
1919 }
1920
1921 return clock;
1922 }
1923
1924 /* Get or auto-detect clock rate */
1925 int GetClock(char *str, int peak)
1926 {
1927 int clock;
1928
1929 sscanf(str, "%i", &clock);
1930 if (!strcmp(str, ""))
1931 clock = 0;
1932
1933 /* Auto-detect clock */
1934 if (!clock)
1935 {
1936 clock = detectclock(peak);
1937
1938 /* Only print this message if we're not looping something */
1939 if (!go)
1940 PrintToScrollback("Auto-detected clock rate: %d", clock);
1941 }
1942
1943 return clock;
1944 }
1945
1946 /*
1947 * Convert to a bitstream
1948 */
1949 static void Cmdbitstream(char *str) {
1950 int i, j;
1951 int bit;
1952 int gtl;
1953 int clock;
1954 int low = 0;
1955 int high = 0;
1956 int hithigh, hitlow, first;
1957
1958 /* Detect high and lows and clock */
1959 for (i = 0; i < GraphTraceLen; i++)
1960 {
1961 if (GraphBuffer[i] > high)
1962 high = GraphBuffer[i];
1963 else if (GraphBuffer[i] < low)
1964 low = GraphBuffer[i];
1965 }
1966
1967 /* Get our clock */
1968 clock = GetClock(str, high);
1969
1970 gtl = CmdClearGraph(0);
1971
1972 bit = 0;
1973 for (i = 0; i < (int)(gtl / clock); i++)
1974 {
1975 hithigh = 0;
1976 hitlow = 0;
1977 first = 1;
1978
1979 /* Find out if we hit both high and low peaks */
1980 for (j = 0; j < clock; j++)
1981 {
1982 if (GraphBuffer[(i * clock) + j] == high)
1983 hithigh = 1;
1984 else if (GraphBuffer[(i * clock) + j] == low)
1985 hitlow = 1;
1986
1987 /* it doesn't count if it's the first part of our read
1988 because it's really just trailing from the last sequence */
1989 if (first && (hithigh || hitlow))
1990 hithigh = hitlow = 0;
1991 else
1992 first = 0;
1993
1994 if (hithigh && hitlow)
1995 break;
1996 }
1997
1998 /* If we didn't hit both high and low peaks, we had a bit transition */
1999 if (!hithigh || !hitlow)
2000 bit ^= 1;
2001
2002 CmdAppendGraph(0, clock, bit);
2003 // for (j = 0; j < (int)(clock/2); j++)
2004 // GraphBuffer[(i * clock) + j] = bit ^ 1;
2005 // for (j = (int)(clock/2); j < clock; j++)
2006 // GraphBuffer[(i * clock) + j] = bit;
2007 }
2008
2009 RepaintGraphWindow();
2010 }
2011
2012 /* Modulate our data into manchester */
2013 static void Cmdmanchestermod(char *str)
2014 {
2015 int i, j;
2016 int clock;
2017 int bit, lastbit, wave;
2018
2019 /* Get our clock */
2020 clock = GetClock(str, 0);
2021
2022 wave = 0;
2023 lastbit = 1;
2024 for (i = 0; i < (int)(GraphTraceLen / clock); i++)
2025 {
2026 bit = GraphBuffer[i * clock] ^ 1;
2027
2028 for (j = 0; j < (int)(clock/2); j++)
2029 GraphBuffer[(i * clock) + j] = bit ^ lastbit ^ wave;
2030 for (j = (int)(clock/2); j < clock; j++)
2031 GraphBuffer[(i * clock) + j] = bit ^ lastbit ^ wave ^ 1;
2032
2033 /* Keep track of how we start our wave and if we changed or not this time */
2034 wave ^= bit ^ lastbit;
2035 lastbit = bit;
2036 }
2037
2038 RepaintGraphWindow();
2039 }
2040
2041 /*
2042 * Manchester demodulate a bitstream. The bitstream needs to be already in
2043 * the GraphBuffer as 0 and 1 values
2044 *
2045 * Give the clock rate as argument in order to help the sync - the algorithm
2046 * resyncs at each pulse anyway.
2047 *
2048 * Not optimized by any means, this is the 1st time I'm writing this type of
2049 * routine, feel free to improve...
2050 *
2051 * 1st argument: clock rate (as number of samples per clock rate)
2052 * Typical values can be 64, 32, 128...
2053 */
2054 static void Cmdmanchesterdemod(char *str) {
2055 int i, j;
2056 int bit;
2057 int clock;
2058 int lastval;
2059 int low = 0;
2060 int high = 0;
2061 int hithigh, hitlow, first;
2062 int lc = 0;
2063 int bitidx = 0;
2064 int bit2idx = 0;
2065 int warnings = 0;
2066
2067 /* Holds the decoded bitstream: each clock period contains 2 bits */
2068 /* later simplified to 1 bit after manchester decoding. */
2069 /* Add 10 bits to allow for noisy / uncertain traces without aborting */
2070 /* int BitStream[GraphTraceLen*2/clock+10]; */
2071
2072 /* But it does not work if compiling on WIndows: therefore we just allocate a */
2073 /* large array */
2074 int BitStream[MAX_GRAPH_TRACE_LEN];
2075
2076 /* Detect high and lows */
2077 for (i = 0; i < GraphTraceLen; i++)
2078 {
2079 if (GraphBuffer[i] > high)
2080 high = GraphBuffer[i];
2081 else if (GraphBuffer[i] < low)
2082 low = GraphBuffer[i];
2083 }
2084
2085 /* Get our clock */
2086 clock = GetClock(str, high);
2087
2088 int tolerance = clock/4;
2089
2090 /* Detect first transition */
2091 /* Lo-Hi (arbitrary) */
2092 for (i = 0; i < GraphTraceLen; i++)
2093 {
2094 if (GraphBuffer[i] == low)
2095 {
2096 lastval = i;
2097 break;
2098 }
2099 }
2100
2101 /* If we're not working with 1/0s, demod based off clock */
2102 if (high != 1)
2103 {
2104 bit = 0;
2105 for (i = 0; i < (int)(GraphTraceLen / clock); i++)
2106 {
2107 hithigh = 0;
2108 hitlow = 0;
2109 first = 1;
2110
2111 /* Find out if we hit both high and low peaks */
2112 for (j = 0; j < clock; j++)
2113 {
2114 if (GraphBuffer[(i * clock) + j] == high)
2115 hithigh = 1;
2116 else if (GraphBuffer[(i * clock) + j] == low)
2117 hitlow = 1;
2118
2119 /* it doesn't count if it's the first part of our read
2120 because it's really just trailing from the last sequence */
2121 if (first && (hithigh || hitlow))
2122 hithigh = hitlow = 0;
2123 else
2124 first = 0;
2125
2126 if (hithigh && hitlow)
2127 break;
2128 }
2129
2130 /* If we didn't hit both high and low peaks, we had a bit transition */
2131 if (!hithigh || !hitlow)
2132 bit ^= 1;
2133
2134 BitStream[bit2idx++] = bit;
2135 }
2136 }
2137
2138 /* standard 1/0 bitstream */
2139 else
2140 {
2141
2142 /* Then detect duration between 2 successive transitions */
2143 for (bitidx = 1; i < GraphTraceLen; i++)
2144 {
2145 if (GraphBuffer[i-1] != GraphBuffer[i])
2146 {
2147 lc = i-lastval;
2148 lastval = i;
2149
2150 // Error check: if bitidx becomes too large, we do not
2151 // have a Manchester encoded bitstream or the clock is really
2152 // wrong!
2153 if (bitidx > (GraphTraceLen*2/clock+8) ) {
2154 PrintToScrollback("Error: the clock you gave is probably wrong, aborting.");
2155 return;
2156 }
2157 // Then switch depending on lc length:
2158 // Tolerance is 1/4 of clock rate (arbitrary)
2159 if (abs(lc-clock/2) < tolerance) {
2160 // Short pulse : either "1" or "0"
2161 BitStream[bitidx++]=GraphBuffer[i-1];
2162 } else if (abs(lc-clock) < tolerance) {
2163 // Long pulse: either "11" or "00"
2164 BitStream[bitidx++]=GraphBuffer[i-1];
2165 BitStream[bitidx++]=GraphBuffer[i-1];
2166 } else {
2167 // Error
2168 warnings++;
2169 PrintToScrollback("Warning: Manchester decode error for pulse width detection.");
2170 PrintToScrollback("(too many of those messages mean either the stream is not Manchester encoded, or clock is wrong)");
2171
2172 if (warnings > 100)
2173 {
2174 PrintToScrollback("Error: too many detection errors, aborting.");
2175 return;
2176 }
2177 }
2178 }
2179 }
2180
2181 // At this stage, we now have a bitstream of "01" ("1") or "10" ("0"), parse it into final decoded bitstream
2182 // Actually, we overwrite BitStream with the new decoded bitstream, we just need to be careful
2183 // to stop output at the final bitidx2 value, not bitidx
2184 for (i = 0; i < bitidx; i += 2) {
2185 if ((BitStream[i] == 0) && (BitStream[i+1] == 1)) {
2186 BitStream[bit2idx++] = 1;
2187 } else if ((BitStream[i] == 1) && (BitStream[i+1] == 0)) {
2188 BitStream[bit2idx++] = 0;
2189 } else {
2190 // We cannot end up in this state, this means we are unsynchronized,
2191 // move up 1 bit:
2192 i++;
2193 warnings++;
2194 PrintToScrollback("Unsynchronized, resync...");
2195 PrintToScrollback("(too many of those messages mean the stream is not Manchester encoded)");
2196
2197 if (warnings > 100)
2198 {
2199 PrintToScrollback("Error: too many decode errors, aborting.");
2200 return;
2201 }
2202 }
2203 }
2204 }
2205
2206 PrintToScrollback("Manchester decoded bitstream");
2207 // Now output the bitstream to the scrollback by line of 16 bits
2208 for (i = 0; i < (bit2idx-16); i+=16) {
2209 PrintToScrollback("%i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i",
2210 BitStream[i],
2211 BitStream[i+1],
2212 BitStream[i+2],
2213 BitStream[i+3],
2214 BitStream[i+4],
2215 BitStream[i+5],
2216 BitStream[i+6],
2217 BitStream[i+7],
2218 BitStream[i+8],
2219 BitStream[i+9],
2220 BitStream[i+10],
2221 BitStream[i+11],
2222 BitStream[i+12],
2223 BitStream[i+13],
2224 BitStream[i+14],
2225 BitStream[i+15]);
2226 }
2227 }
2228
2229
2230
2231 /*
2232 * Usage ???
2233 */
2234 static void CmdHiddemod(char *str)
2235 {
2236 if(GraphTraceLen < 4800) {
2237 PrintToScrollback("too short; need at least 4800 samples");
2238 return;
2239 }
2240
2241 GraphTraceLen = 4800;
2242 int i;
2243 for(i = 0; i < GraphTraceLen; i++) {
2244 if(GraphBuffer[i] < 0) {
2245 GraphBuffer[i] = 0;
2246 } else {
2247 GraphBuffer[i] = 1;
2248 }
2249 }
2250 RepaintGraphWindow();
2251 }
2252
2253 static void CmdPlot(char *str)
2254 {
2255 ShowGraphWindow();
2256 }
2257
2258 static void CmdHide(char *str)
2259 {
2260 HideGraphWindow();
2261 }
2262
2263 static void CmdScale(char *str)
2264 {
2265 CursorScaleFactor = atoi(str);
2266 if(CursorScaleFactor == 0) {
2267 PrintToScrollback("bad, can't have zero scale");
2268 CursorScaleFactor = 1;
2269 }
2270 RepaintGraphWindow();
2271 }
2272
2273 static void CmdSave(char *str)
2274 {
2275 FILE *f = fopen(str, "w");
2276 if(!f) {
2277 PrintToScrollback("couldn't open '%s'", str);
2278 return;
2279 }
2280 int i;
2281 for(i = 0; i < GraphTraceLen; i++) {
2282 fprintf(f, "%d\n", GraphBuffer[i]);
2283 }
2284 fclose(f);
2285 PrintToScrollback("saved to '%s'", str);
2286 }
2287
2288 static void CmdLoad(char *str)
2289 {
2290 FILE *f = fopen(str, "r");
2291 if(!f) {
2292 PrintToScrollback("couldn't open '%s'", str);
2293 return;
2294 }
2295
2296 GraphTraceLen = 0;
2297 char line[80];
2298 while(fgets(line, sizeof(line), f)) {
2299 GraphBuffer[GraphTraceLen] = atoi(line);
2300 GraphTraceLen++;
2301 }
2302 fclose(f);
2303 PrintToScrollback("loaded %d samples", GraphTraceLen);
2304 RepaintGraphWindow();
2305 }
2306
2307 static void CmdHIDsimTAG(char *str)
2308 {
2309 unsigned int hi=0, lo=0;
2310 int n=0, i=0;
2311 UsbCommand c;
2312
2313 while (sscanf(&str[i++], "%1x", &n ) == 1) {
2314 hi=(hi<<4)|(lo>>28);
2315 lo=(lo<<4)|(n&0xf);
2316 }
2317
2318 PrintToScrollback("Emulating tag with ID %x%16x", hi, lo);
2319
2320 c.cmd = CMD_HID_SIM_TAG;
2321 c.ext1 = hi;
2322 c.ext2 = lo;
2323 SendCommand(&c, FALSE);
2324 }
2325
2326 static void CmdLcdReset(char *str)
2327 {
2328 UsbCommand c;
2329 c.cmd = CMD_LCD_RESET;
2330 c.ext1 = atoi(str);
2331 SendCommand(&c, FALSE);
2332 }
2333
2334 static void CmdLcd(char *str)
2335 {
2336 int i, j;
2337 UsbCommand c;
2338 c.cmd = CMD_LCD;
2339 sscanf(str, "%x %d", &i, &j);
2340 while (j--) {
2341 c.ext1 = i&0x1ff;
2342 SendCommand(&c, FALSE);
2343 }
2344 }
2345
2346
2347
2348 static void CmdTest(char *str)
2349 {
2350 }
2351
2352 /*
2353 * Sets the divisor for LF frequency clock: lets the user choose any LF frequency below
2354 * 600kHz.
2355 */
2356 static void CmdSetDivisor(char *str)
2357 {
2358 UsbCommand c;
2359 c.cmd = CMD_SET_LF_DIVISOR;
2360 c.ext1 = atoi(str);
2361 if (( c.ext1<0) || (c.ext1>255)) {
2362 PrintToScrollback("divisor must be between 19 and 255");
2363 } else {
2364 SendCommand(&c, FALSE);
2365 PrintToScrollback("Divisor set, expected freq=%dHz", 12000000/(c.ext1+1));
2366 }
2367 }
2368
2369 static void CmdSweepLF(char *str)
2370 {
2371 UsbCommand c;
2372 c.cmd = CMD_SWEEP_LF;
2373 SendCommand(&c, FALSE);
2374 }
2375
2376
2377 typedef void HandlerFunction(char *cmdline);
2378
2379 static struct {
2380 char *name;
2381 HandlerFunction *handler;
2382 int offline; // 1 if the command can be used when in offline mode
2383 char *docString;
2384 } CommandTable[] = {
2385 "tune", CmdTune,0, "measure antenna tuning",
2386 "tiread", CmdTiread,0, "read a TI-type 134 kHz tag",
2387 "tibits", CmdTibits,0, "get raw bits for TI-type LF tag",
2388 "tidemod", CmdTidemod,0, "demod raw bits for TI-type LF tag",
2389 "vchdemod", CmdVchdemod,0, "demod samples for VeriChip",
2390 "plot", CmdPlot,1, "show graph window",
2391 "hide", CmdHide,1, "hide graph window",
2392 "losim", CmdLosim,0, "simulate LF tag",
2393 "em410xsim", CmdEM410xsim,1, "simulate EM410x tag",
2394 "em410xread", CmdEM410xread,1, "extract ID from EM410x tag",
2395 "em410xwatch", CmdEM410xwatch,0, "watches for EM410x tags",
2396 "loread", CmdLoread,0, "read (125/134 kHz) LF ID-only tag",
2397 "losamples", CmdLosamples,0, "get raw samples for LF tag",
2398 "hisamples", CmdHisamples,0, "get raw samples for HF tag",
2399 "hisampless", CmdHisampless,0, "get signed raw samples, HF tag",
2400 "hisamplest", CmdHi14readt,0, "get samples HF, for testing",
2401 "higet", CmdHi14read_sim,0, "get samples HF, 'analog'",
2402 "bitsamples", CmdBitsamples,0, "get raw samples as bitstring",
2403 "hexsamples", CmdHexsamples,0, "dump big buffer as hex bytes",
2404 "hi15read", CmdHi15read,0, "read HF tag (ISO 15693)",
2405 "hi15reader", CmdHi15reader,0, "act like an ISO15693 reader", // new command greg
2406 "hi15sim", CmdHi15tag,0, "fake an ISO15693 tag", // new command greg
2407 "hi14read", CmdHi14read,0, "read HF tag (ISO 14443)",
2408 "sri512read", CmdSri512read,0, "Read contents of a SRI512 tag",
2409 "hi14areader", CmdHi14areader,0, "act like an ISO14443 Type A reader", // ## New reader command
2410 "hi15demod", CmdHi15demod,1, "demod ISO15693 from tag",
2411 "hi14bdemod", CmdHi14bdemod,1, "demod ISO14443 Type B from tag",
2412 "autocorr", CmdAutoCorr,1, "autocorrelation over window",
2413 "norm", CmdNorm,1, "normalize max/min to +/-500",
2414 "dec", CmdDec,1, "decimate",
2415 "hpf", CmdHpf,1, "remove DC offset from trace",
2416 "zerocrossings", CmdZerocrossings,1, "count time between zero-crossings",
2417 "ltrim", CmdLtrim,1, "trim from left of trace",
2418 "scale", CmdScale,1, "set cursor display scale",
2419 "flexdemod", CmdFlexdemod,1, "demod samples for FlexPass",
2420 "save", CmdSave,1, "save trace (from graph window)",
2421 "load", CmdLoad,1, "load trace (to graph window",
2422 "hisimlisten", CmdHisimlisten,0, "get HF samples as fake tag",
2423 "hi14sim", CmdHi14sim,0, "fake ISO 14443 tag",
2424 "hi14asim", CmdHi14asim,0, "fake ISO 14443a tag", // ## Simulate 14443a tag
2425 "hi14snoop", CmdHi14snoop,0, "eavesdrop ISO 14443",
2426 "hi14asnoop", CmdHi14asnoop,0, "eavesdrop ISO 14443 Type A", // ## New snoop command
2427 "hi14list", CmdHi14list,0, "list ISO 14443 history",
2428 "hi14alist", CmdHi14alist,0, "list ISO 14443a history", // ## New list command
2429 "hiddemod", CmdHiddemod,1, "HID Prox Card II (not optimal)",
2430 "hidfskdemod", CmdHIDdemodFSK,0, "HID FSK demodulator",
2431 "indalademod", CmdIndalademod,0, "demod samples for Indala",
2432 "askdemod", Cmdaskdemod,1, "Attempt to demodulate simple ASK tags",
2433 "bitstream", Cmdbitstream,1, "Convert waveform into a bitstream",
2434 "hidsimtag", CmdHIDsimTAG,0, "HID tag simulator",
2435 "mandemod", Cmdmanchesterdemod,1, "Try a Manchester demodulation on a binary stream",
2436 "manmod", Cmdmanchestermod,1, "Manchester modulate a binary stream",
2437 "detectclock", Cmddetectclockrate,1, "Detect clock rate",
2438 "fpgaoff", CmdFPGAOff,0, "set FPGA off", // ## FPGA Control
2439 "lcdreset", CmdLcdReset,0, "Hardware reset LCD",
2440 "lcd", CmdLcd,0, "Send command/data to LCD",
2441 "setlfdivisor", CmdSetDivisor,0, "Drive LF antenna at 12Mhz/(divisor+1)",
2442 "sweeplf", CmdSweepLF,0, "Sweep through LF freq range and store results in buffer",
2443 "reset", CmdReset,0, "Reset the Proxmark3",
2444 "quit", CmdQuit,1, "quit program"
2445 };
2446
2447
2448 //-----------------------------------------------------------------------------
2449 // Entry point into our code: called whenever the user types a command and
2450 // then presses Enter, which the full command line that they typed.
2451 //-----------------------------------------------------------------------------
2452 void CommandReceived(char *cmd)
2453 {
2454 int i;
2455
2456 PrintToScrollback("> %s", cmd);
2457
2458 if(strcmp(cmd, "help")==0) {
2459 if (offline) PrintToScrollback("Operating in OFFLINE mode (no device connected)");
2460 PrintToScrollback("\r\nAvailable commands:");
2461 for(i = 0; i < sizeof(CommandTable) / sizeof(CommandTable[0]); i++) {
2462 if (offline && (CommandTable[i].offline==0)) continue;
2463 char line[256];
2464 memset(line, ' ', sizeof(line));
2465 strcpy(line+2, CommandTable[i].name);
2466 line[strlen(line)] = ' ';
2467 sprintf(line+15, " -- %s", CommandTable[i].docString);
2468 PrintToScrollback("%s", line);
2469 }
2470 PrintToScrollback("");
2471 PrintToScrollback("and also: help, cls");
2472 return;
2473 }
2474
2475 for(i = 0; i < sizeof(CommandTable) / sizeof(CommandTable[0]); i++) {
2476 char *name = CommandTable[i].name;
2477 if(memcmp(cmd, name, strlen(name))==0 &&
2478 (cmd[strlen(name)] == ' ' || cmd[strlen(name)] == '\0'))
2479 {
2480 cmd += strlen(name);
2481 while(*cmd == ' ') {
2482 cmd++;
2483 }
2484 if (offline && (CommandTable[i].offline==0)) {
2485 PrintToScrollback("Offline mode, cannot use this command.");
2486 return;
2487 }
2488 (CommandTable[i].handler)(cmd);
2489 return;
2490 }
2491 }
2492 PrintToScrollback(">> bad command '%s'", cmd);
2493 }
2494
2495 //-----------------------------------------------------------------------------
2496 // Entry point into our code: called whenever we received a packet over USB
2497 // that we weren't necessarily expecting, for example a debug print.
2498 //-----------------------------------------------------------------------------
2499 void UsbCommandReceived(UsbCommand *c)
2500 {
2501 switch(c->cmd) {
2502 case CMD_DEBUG_PRINT_STRING: {
2503 char s[100];
2504 if(c->ext1 > 70 || c->ext1 < 0) {
2505 c->ext1 = 0;
2506 }
2507 memcpy(s, c->d.asBytes, c->ext1);
2508 s[c->ext1] = '\0';
2509 PrintToScrollback("#db# %s", s);
2510 break;
2511 }
2512
2513 case CMD_DEBUG_PRINT_INTEGERS:
2514 PrintToScrollback("#db# %08x, %08x, %08x\r\n", c->ext1, c->ext2, c->ext3);
2515 break;
2516
2517 case CMD_MEASURED_ANTENNA_TUNING: {
2518 int zLf, zHf;
2519 int vLf125, vLf134, vHf;
2520 vLf125 = c->ext1 & 0xffff;
2521 vLf134 = c->ext1 >> 16;
2522 vHf = c->ext2;
2523 zLf = c->ext3 & 0xffff;
2524 zHf = c->ext3 >> 16;
2525 PrintToScrollback("# LF antenna @ %3d mA / %5d mV [%d ohms] 125Khz",
2526 vLf125/zLf, vLf125, zLf);
2527 PrintToScrollback("# LF antenna @ %3d mA / %5d mV [%d ohms] 134Khz",
2528 vLf134/((zLf*125)/134), vLf134, (zLf*125)/134);
2529 PrintToScrollback("# HF antenna @ %3d mA / %5d mV [%d ohms] 13.56Mhz",
2530 vHf/zHf, vHf, zHf);
2531 break;
2532 }
2533 default:
2534 PrintToScrollback("unrecognized command %08x\n", c->cmd);
2535 break;
2536 }
2537 }
Impressum, Datenschutz