]> git.zerfleddert.de Git - proxmark3-svn/blob - winsrc/command.cpp
02abdd4f690ac2990b72f7d26114d3c7f2cd21c4
[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 /* in alphabetic order */
2380 static struct {
2381 char *name;
2382 HandlerFunction *handler;
2383 int offline; // 1 if the command can be used when in offline mode
2384 char *docString;
2385 } CommandTable[] = {
2386 "askdemod", Cmdaskdemod,1, "<samples per bit> <0|1> -- Attempt to demodulate simple ASK tags",
2387 "autocorr", CmdAutoCorr,1, "<window length> -- Autocorrelation over window",
2388 "bitsamples", CmdBitsamples,0, " Get raw samples as bitstring",
2389 "bitstream", Cmdbitstream,1, "[clock rate] -- Convert waveform into a bitstream",
2390 "dec", CmdDec,1, " Decimate samples",
2391 "detectclock", Cmddetectclockrate,1, " Detect clock rate",
2392 "em410xsim", CmdEM410xsim,1, "<UID> -- Simulate EM410x tag",
2393 "em410xread", CmdEM410xread,1, "[clock rate] -- Extract ID from EM410x tag",
2394 "em410xwatch", CmdEM410xwatch,0, " Watches for EM410x tags",
2395 "exit", CmdQuit,1, " Exit program",
2396 "flexdemod", CmdFlexdemod,1, " Demodulate samples for FlexPass",
2397 "fpgaoff", CmdFPGAOff,0, " Set FPGA off", // ## FPGA Control
2398 "hexsamples", CmdHexsamples,0, "<blocks> -- Dump big buffer as hex bytes",
2399 "hi14alist", CmdHi14alist,0, " List ISO 14443a history", // ## New list command
2400 "hi14areader", CmdHi14areader,0, " Act like an ISO14443 Type A reader", // ## New reader command
2401 "hi14asim", CmdHi14asim,0, "<UID> -- Fake ISO 14443a tag", // ## Simulate 14443a tag
2402 "hi14asnoop", CmdHi14asnoop,0, " Eavesdrop ISO 14443 Type A", // ## New snoop command
2403 "hi14bdemod", CmdHi14bdemod,1, " Demodulate ISO14443 Type B from tag",
2404 "hi14list", CmdHi14list,0, " List ISO 14443 history",
2405 "hi14read", CmdHi14read,0, " Read HF tag (ISO 14443)",
2406 "hi14sim", CmdHi14sim,0, " Fake ISO 14443 tag",
2407 "hi14snoop", CmdHi14snoop,0, " Eavesdrop ISO 14443",
2408 "hi15demod", CmdHi15demod,1, " Demodulate ISO15693 from tag",
2409 "hi15read", CmdHi15read,0, " Read HF tag (ISO 15693)",
2410 "hi15reader", CmdHi15reader,0, " Act like an ISO15693 reader", // new command greg
2411 "hi15sim", CmdHi15tag,0, " Fake an ISO15693 tag", // new command greg
2412 "hiddemod", CmdHiddemod,1, " Demodulate HID Prox Card II (not optimal)",
2413 "hide", CmdHide,1, " Hide graph window",
2414 "hidfskdemod", CmdHIDdemodFSK,0, " Realtime HID FSK demodulator",
2415 "hidsimtag", CmdHIDsimTAG,0, "<ID> -- HID tag simulator",
2416 "higet", CmdHi14read_sim,0, "<samples> -- Get samples HF, 'analog'",
2417 "hisamples", CmdHisamples,0, " Get raw samples for HF tag",
2418 "hisampless", CmdHisampless,0, "<samples> -- Get signed raw samples, HF tag",
2419 "hisamplest", CmdHi14readt,0, " Get samples HF, for testing",
2420 "hisimlisten", CmdHisimlisten,0, " Get HF samples as fake tag",
2421 "hpf", CmdHpf,1, " Remove DC offset from trace",
2422 "indalademod", CmdIndalademod,0, "['224'] -- Demodulate samples for Indala",
2423 "lcd", CmdLcd,0, "<HEX command> <count> -- Send command/data to LCD",
2424 "lcdreset", CmdLcdReset,0, " Hardware reset LCD",
2425 "load", CmdLoad,1, "<filename> -- Load trace (to graph window",
2426 "loread", CmdLoread,0, "['h'] -- Read 125/134 kHz LF ID-only tag (option 'h' for 134)",
2427 "losamples", CmdLosamples,0, "[128 - 16000] -- Get raw samples for LF tag",
2428 "losim", CmdLosim,0, " Simulate LF tag",
2429 "ltrim", CmdLtrim,1, "<samples> -- Trim samples from left of trace",
2430 "mandemod", Cmdmanchesterdemod,1, "[clock rate] -- Try a Manchester demodulation on a binary stream",
2431 "manmod", Cmdmanchestermod,1, "[clock rate] -- Manchester modulate a binary stream",
2432 "norm", CmdNorm,1, " Normalize max/min to +/-500",
2433 "plot", CmdPlot,1, " Show graph window",
2434 "quit", CmdQuit,1, " Quit program",
2435 "reset", CmdReset,0, " Reset the Proxmark3",
2436 "save", CmdSave,1, "<filename> -- Save trace (from graph window)",
2437 "scale", CmdScale,1, "<int> -- Set cursor display scale",
2438 "setlfdivisor", CmdSetDivisor,0, "<19 - 255> -- Drive LF antenna at 12Mhz/(divisor+1)",
2439 "sri512read", CmdSri512read,0, "<int> -- Read contents of a SRI512 tag",
2440 "sweeplf", CmdSweepLF,0, " Sweep through LF freq range and store results in buffer",
2441 "tibits", CmdTibits,0, " Get raw bits for TI-type LF tag",
2442 "tidemod", CmdTidemod,0, " Demodulate raw bits for TI-type LF tag",
2443 "tiread", CmdTiread,0, " Read a TI-type 134 kHz tag",
2444 "tune", CmdTune,0, " Measure antenna tuning",
2445 "vchdemod", CmdVchdemod,0, "['clone'] -- Demodulate samples for VeriChip",
2446 "zerocrossings", CmdZerocrossings,1, " Count time between zero-crossings",
2447 };
2448
2449
2450 //-----------------------------------------------------------------------------
2451 // Entry point into our code: called whenever the user types a command and
2452 // then presses Enter, which the full command line that they typed.
2453 //-----------------------------------------------------------------------------
2454 void CommandReceived(char *cmd)
2455 {
2456 int i;
2457
2458 PrintToScrollback("> %s", cmd);
2459
2460 if(strcmp(cmd, "help")==0) {
2461 if (offline) PrintToScrollback("Operating in OFFLINE mode (no device connected)");
2462 PrintToScrollback("\r\nAvailable commands:");
2463 for(i = 0; i < sizeof(CommandTable) / sizeof(CommandTable[0]); i++) {
2464 if (offline && (CommandTable[i].offline==0)) continue;
2465 char line[256];
2466 memset(line, ' ', sizeof(line));
2467 strcpy(line+2, CommandTable[i].name);
2468 line[strlen(line)] = ' ';
2469 sprintf(line+15, " -- %s", CommandTable[i].docString);
2470 PrintToScrollback("%s", line);
2471 }
2472 PrintToScrollback("");
2473 PrintToScrollback("and also: help, cls");
2474 return;
2475 }
2476
2477 for(i = 0; i < sizeof(CommandTable) / sizeof(CommandTable[0]); i++) {
2478 char *name = CommandTable[i].name;
2479 if(memcmp(cmd, name, strlen(name))==0 &&
2480 (cmd[strlen(name)] == ' ' || cmd[strlen(name)] == '\0'))
2481 {
2482 cmd += strlen(name);
2483 while(*cmd == ' ') {
2484 cmd++;
2485 }
2486 if (offline && (CommandTable[i].offline==0)) {
2487 PrintToScrollback("Offline mode, cannot use this command.");
2488 return;
2489 }
2490 (CommandTable[i].handler)(cmd);
2491 return;
2492 }
2493 }
2494 PrintToScrollback(">> bad command '%s'", cmd);
2495 }
2496
2497 //-----------------------------------------------------------------------------
2498 // Entry point into our code: called whenever we received a packet over USB
2499 // that we weren't necessarily expecting, for example a debug print.
2500 //-----------------------------------------------------------------------------
2501 void UsbCommandReceived(UsbCommand *c)
2502 {
2503 switch(c->cmd) {
2504 case CMD_DEBUG_PRINT_STRING: {
2505 char s[100];
2506 if(c->ext1 > 70 || c->ext1 < 0) {
2507 c->ext1 = 0;
2508 }
2509 memcpy(s, c->d.asBytes, c->ext1);
2510 s[c->ext1] = '\0';
2511 PrintToScrollback("#db# %s", s);
2512 break;
2513 }
2514
2515 case CMD_DEBUG_PRINT_INTEGERS:
2516 PrintToScrollback("#db# %08x, %08x, %08x\r\n", c->ext1, c->ext2, c->ext3);
2517 break;
2518
2519 case CMD_MEASURED_ANTENNA_TUNING: {
2520 int zLf, zHf;
2521 int vLf125, vLf134, vHf;
2522 vLf125 = c->ext1 & 0xffff;
2523 vLf134 = c->ext1 >> 16;
2524 vHf = c->ext2;
2525 zLf = c->ext3 & 0xffff;
2526 zHf = c->ext3 >> 16;
2527 PrintToScrollback("# LF antenna @ %3d mA / %5d mV [%d ohms] 125Khz",
2528 vLf125/zLf, vLf125, zLf);
2529 PrintToScrollback("# LF antenna @ %3d mA / %5d mV [%d ohms] 134Khz",
2530 vLf134/((zLf*125)/134), vLf134, (zLf*125)/134);
2531 PrintToScrollback("# HF antenna @ %3d mA / %5d mV [%d ohms] 13.56Mhz",
2532 vHf/zHf, vHf, zHf);
2533 break;
2534 }
2535 default:
2536 PrintToScrollback("unrecognized command %08x\n", c->cmd);
2537 break;
2538 }
2539 }
Impressum, Datenschutz