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