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