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