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