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