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