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