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