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