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