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