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