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