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