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