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