]> git.zerfleddert.de Git - proxmark3-svn/blame - winsrc/command.cpp
Don't depend on local path/lib settings for easier compilation
[proxmark3-svn] / winsrc / command.cpp
CommitLineData
6658905f 1//-----------------------------------------------------------------------------\r
2// The actual command interpeter for what the user types at the command line.\r
3// Jonathan Westhues, Sept 2005\r
4// Edits by Gerhard de Koning Gans, Sep 2007 (##)\r
5//-----------------------------------------------------------------------------\r
6#include <windows.h>\r
7#include <stdlib.h>\r
8#include <string.h>\r
9#include <stdio.h>\r
10#include <limits.h>\r
11#include <math.h>\r
12\r
13#include "prox.h"\r
14#include "../common/iso14443_crc.c"\r
15\r
16#define arraylen(x) (sizeof(x)/sizeof((x)[0]))\r
17\r
18static int CmdHisamplest(char *str, int nrlow);\r
19\r
20static void GetFromBigBuf(BYTE *dest, int bytes)\r
21{\r
22 int n = bytes/4;\r
23\r
24 if(n % 48 != 0) {\r
25 PrintToScrollback("bad len in GetFromBigBuf");\r
26 return;\r
27 }\r
28\r
29 int i;\r
30 for(i = 0; i < n; i += 12) {\r
31 UsbCommand c;\r
32 c.cmd = CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K;\r
33 c.ext1 = i;\r
34 SendCommand(&c, FALSE);\r
35 ReceiveCommand(&c);\r
36 if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) {\r
37 PrintToScrollback("bad resp\n");\r
38 return;\r
39 }\r
40\r
41 memcpy(dest+(i*4), c.d.asBytes, 48);\r
42 }\r
43}\r
44\r
d722c4ce 45static void CmdReset(char *str)\r
46{\r
47 UsbCommand c;\r
48 c.cmd = CMD_HARDWARE_RESET;\r
49 SendCommand(&c, FALSE);\r
50}\r
51\r
52\r
6658905f 53static void CmdQuit(char *str)\r
54{\r
55 exit(0);\r
56}\r
57\r
58static void CmdHIDdemodFSK(char *str)\r
59{\r
60 UsbCommand c;\r
61 c.cmd = CMD_HID_DEMOD_FSK;\r
62 SendCommand(&c, FALSE);\r
63}\r
64\r
65static void CmdTune(char *str)\r
66{\r
67 UsbCommand c;\r
68 c.cmd = CMD_MEASURE_ANTENNA_TUNING;\r
69 SendCommand(&c, FALSE);\r
70}\r
71\r
72static void CmdHi15read(char *str)\r
73{\r
74 UsbCommand c;\r
75 c.cmd = CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693;\r
76 SendCommand(&c, FALSE);\r
77}\r
78\r
79static void CmdHi14read(char *str)\r
80{\r
81 UsbCommand c;\r
82 c.cmd = CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443;\r
83 c.ext1 = atoi(str);\r
84 SendCommand(&c, FALSE);\r
85}\r
fb25b483 86
87
88/* New command to read the contents of a SRI512 tag
89 * SRI512 tags are ISO14443-B modulated memory tags,
90 * this command just dumps the contents of the memory/
91 */
92static void CmdSri512read(char *str)
93{
94 UsbCommand c;\r
95 c.cmd = CMD_READ_SRI512_TAG;\r
96 c.ext1 = atoi(str);\r
97 SendCommand(&c, FALSE);
98}
6658905f 99\r
100// ## New command\r
101static void CmdHi14areader(char *str)\r
102{\r
103 UsbCommand c;\r
104 c.cmd = CMD_READER_ISO_14443a;\r
105 c.ext1 = atoi(str);\r
106 SendCommand(&c, FALSE);\r
107}\r
108\r
109// ## New command\r
110static void CmdHi15reader(char *str)\r
111{\r
112 UsbCommand c;\r
113 c.cmd = CMD_READER_ISO_15693;\r
114 c.ext1 = atoi(str);\r
115 SendCommand(&c, FALSE);\r
116}\r
117\r
118// ## New command\r
119static void CmdHi15tag(char *str)\r
120{\r
121 UsbCommand c;\r
122 c.cmd = CMD_SIMTAG_ISO_15693;\r
123 c.ext1 = atoi(str);\r
124 SendCommand(&c, FALSE);\r
125}\r
126\r
127static void CmdHi14read_sim(char *str)\r
128{\r
129 UsbCommand c;\r
130 c.cmd = CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443_SIM;\r
131 c.ext1 = atoi(str);\r
132 SendCommand(&c, FALSE);\r
133}\r
134\r
135static void CmdHi14readt(char *str)\r
136{\r
137 UsbCommand c;\r
138 c.cmd = CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443;\r
139 c.ext1 = atoi(str);\r
140 SendCommand(&c, FALSE);\r
141\r
142 //CmdHisamplest(str);\r
143 while(CmdHisamplest(str,atoi(str))==0) {\r
144 c.cmd = CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443;\r
145 c.ext1 = atoi(str);\r
146 SendCommand(&c, FALSE);\r
147 }\r
148 RepaintGraphWindow();\r
149}\r
150\r
151static void CmdHisimlisten(char *str)\r
152{\r
153 UsbCommand c;\r
154 c.cmd = CMD_SIMULATE_TAG_HF_LISTEN;\r
155 SendCommand(&c, FALSE);\r
156}\r
157\r
158static void CmdHi14sim(char *str)\r
159{\r
160 UsbCommand c;\r
161 c.cmd = CMD_SIMULATE_TAG_ISO_14443;\r
162 SendCommand(&c, FALSE);\r
163}\r
164
165
166\r
167static void CmdHi14asim(char *str) // ## simulate iso14443a tag\r
168{ // ## greg - added ability to specify tag UID\r
169\r
170 unsigned int hi=0, lo=0;\r
171 int n=0, i=0;\r
172 UsbCommand c;\r
173\r
174 while (sscanf(&str[i++], "%1x", &n ) == 1) {\r
175 hi=(hi<<4)|(lo>>28);\r
176 lo=(lo<<4)|(n&0xf);\r
177 }\r
178\r
179 c.cmd = CMD_SIMULATE_TAG_ISO_14443a;\r
180 // c.ext should be set to *str or convert *str to the correct format for a uid\r
181 c.ext1 = hi;\r
182 c.ext2 = lo;\r
183 PrintToScrollback("Emulating 14443A TAG with UID %x%16x", hi, lo);\r
184 SendCommand(&c, FALSE);\r
185}\r
186\r
187static void CmdHi14snoop(char *str)\r
188{\r
189 UsbCommand c;\r
190 c.cmd = CMD_SNOOP_ISO_14443;\r
191 SendCommand(&c, FALSE);\r
192}\r
193\r
194static void CmdHi14asnoop(char *str)\r
195{\r
196 UsbCommand c;\r
197 c.cmd = CMD_SNOOP_ISO_14443a;\r
198 SendCommand(&c, FALSE);\r
199}\r
200\r
201static void CmdFPGAOff(char *str) // ## FPGA Control\r
202{\r
203 UsbCommand c;\r
204 c.cmd = CMD_FPGA_MAJOR_MODE_OFF;\r
205 SendCommand(&c, FALSE);\r
206}\r
207\r
208static void CmdLosim(char *str)\r
209{\r
210 int i;\r
211\r
212 for(i = 0; i < GraphTraceLen; i += 48) {\r
213 UsbCommand c;\r
214 int j;\r
215 for(j = 0; j < 48; j++) {\r
216 c.d.asBytes[j] = GraphBuffer[i+j];\r
217 }\r
218 c.cmd = CMD_DOWNLOADED_SIM_SAMPLES_125K;\r
219 c.ext1 = i;\r
220 SendCommand(&c, FALSE);\r
221 }\r
222\r
223 UsbCommand c;\r
224 c.cmd = CMD_SIMULATE_TAG_125K;\r
225 c.ext1 = GraphTraceLen;\r
226 SendCommand(&c, FALSE);\r
227}\r
228\r
229static void CmdLoread(char *str)\r
230{\r
231 UsbCommand c;\r
232 // 'h' means higher-low-frequency, 134 kHz\r
233 if(*str == 'h') {\r
234 c.ext1 = 1;\r
235 } else if (*str == '\0') {\r
236 c.ext1 = 0;\r
237 } else {\r
238 PrintToScrollback("use 'loread' or 'loread h'");\r
239 return;\r
240 }\r
241 c.cmd = CMD_ACQUIRE_RAW_ADC_SAMPLES_125K;\r
242 SendCommand(&c, FALSE);\r
243}\r
244\r
245static void CmdLosamples(char *str)\r
246{\r
247 int cnt = 0;\r
248 int i;\r
249 int n;\r
250\r
251 n=atoi(str);\r
252 if (n==0) n=128;\r
253 if (n>16000) n=16000;\r
254\r
255 for(i = 0; i < n; i += 12) {\r
256 UsbCommand c;\r
257 c.cmd = CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K;\r
258 c.ext1 = i;\r
259 SendCommand(&c, FALSE);\r
260 ReceiveCommand(&c);\r
261 if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) {\r
262 PrintToScrollback("bad resp\n");\r
263 return;\r
264 }\r
265 int j;\r
266 for(j = 0; j < 48; j++) {\r
267 GraphBuffer[cnt++] = ((int)c.d.asBytes[j]) - 128;\r
268 }\r
269 }\r
270 GraphTraceLen = n*4;\r
271 RepaintGraphWindow();\r
272}\r
273\r
274static void CmdBitsamples(char *str)\r
275{\r
276 int cnt = 0;\r
277 int i;\r
278 int n;\r
279\r
280 n = 3072;\r
281 for(i = 0; i < n; i += 12) {\r
282 UsbCommand c;\r
283 c.cmd = CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K;\r
284 c.ext1 = i;\r
285 SendCommand(&c, FALSE);\r
286 ReceiveCommand(&c);\r
287 if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) {\r
288 PrintToScrollback("bad resp\n");\r
289 return;\r
290 }\r
291 int j, k;\r
292 for(j = 0; j < 48; j++) {\r
293 for(k = 0; k < 8; k++) {\r
294 if(c.d.asBytes[j] & (1 << (7 - k))) {\r
295 GraphBuffer[cnt++] = 1;\r
296 } else {\r
297 GraphBuffer[cnt++] = 0;\r
298 }\r
299 }\r
300 }\r
301 }\r
302 GraphTraceLen = cnt;\r
303 RepaintGraphWindow();\r
304}\r
305\r
306static void CmdHisamples(char *str)\r
307{\r
308 int cnt = 0;\r
309 int i;\r
310 int n;\r
311 n = 1000;\r
312 for(i = 0; i < n; i += 12) {\r
313 UsbCommand c;\r
314 c.cmd = CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K;\r
315 c.ext1 = i;\r
316 SendCommand(&c, FALSE);\r
317 ReceiveCommand(&c);\r
318 if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) {\r
319 PrintToScrollback("bad resp\n");\r
320 return;\r
321 }\r
322 int j;\r
323 for(j = 0; j < 48; j++) {\r
324 GraphBuffer[cnt++] = (int)((BYTE)c.d.asBytes[j]);\r
325 }\r
326 }\r
327 GraphTraceLen = n*4;\r
328\r
329 RepaintGraphWindow();\r
330}\r
331\r
332\r
333static int CmdHisamplest(char *str, int nrlow)\r
334{\r
335 int cnt = 0;\r
336 int t1, t2;\r
337 int i;\r
338 int n;\r
339 int hasbeennull;\r
340 int show;\r
341\r
342\r
343 n = 1000;\r
344 hasbeennull = 0;\r
345 for(i = 0; i < n; i += 12) {\r
346 UsbCommand c;\r
347 c.cmd = CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K;\r
348 c.ext1 = i;\r
349 SendCommand(&c, FALSE);\r
350 ReceiveCommand(&c);\r
351 if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) {\r
352 PrintToScrollback("bad resp\n");\r
353 return 0;\r
354 }\r
355 int j;\r
356 for(j = 0; j < 48; j++) {\r
357 t2 = (int)((BYTE)c.d.asBytes[j]);\r
358 if((t2 ^ 0xC0) & 0xC0) { hasbeennull++; }\r
359\r
360 show = 0;\r
361 switch(show) {\r
362 case 0:\r
363 // combined\r
364 t1 = (t2 & 0x80) ^ (t2 & 0x20);\r
365 t2 = ((t2 << 1) & 0x80) ^ ((t2 << 1) & 0x20);\r
366 break;\r
367\r
368 case 1:\r
369 // only reader\r
370 t1 = (t2 & 0x80);\r
371 t2 = ((t2 << 1) & 0x80);\r
372 break;\r
373\r
374 case 2:\r
375 // only tag\r
376 t1 = (t2 & 0x20);\r
377 t2 = ((t2 << 1) & 0x20);\r
378 break;\r
379\r
380 case 3:\r
381 // both, but tag with other algorithm\r
382 t1 = (t2 & 0x80) ^ (t2 & 0x08);\r
383 t2 = ((t2 << 1) & 0x80) ^ ((t2 << 1) & 0x08);\r
384 break;\r
385 }\r
386\r
387 GraphBuffer[cnt++] = t1;\r
388 GraphBuffer[cnt++] = t2;\r
389 }\r
390 }\r
391 GraphTraceLen = n*4;\r
392// 1130\r
393 if(hasbeennull>nrlow || nrlow==0) {\r
394 PrintToScrollback("hasbeennull=%d", hasbeennull);\r
395 return 1;\r
396 }\r
397 else {\r
398 return 0;\r
399 }\r
400}\r
401\r
402\r
403static void CmdHexsamples(char *str)\r
404{\r
405 int i;\r
406 int n;\r
407\r
408 if(atoi(str) == 0) {\r
409 n = 12;\r
410 } else {\r
411 n = atoi(str)/4;\r
412 }\r
413\r
414 for(i = 0; i < n; i += 12) {\r
415 UsbCommand c;\r
416 c.cmd = CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K;\r
417 c.ext1 = i;\r
418 SendCommand(&c, FALSE);\r
419 ReceiveCommand(&c);\r
420 if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) {\r
421 PrintToScrollback("bad resp\n");\r
422 return;\r
423 }\r
424 int j;\r
425 for(j = 0; j < 48; j += 8) {\r
426 PrintToScrollback("%02x %02x %02x %02x %02x %02x %02x %02x",\r
427 c.d.asBytes[j+0],\r
428 c.d.asBytes[j+1],\r
429 c.d.asBytes[j+2],\r
430 c.d.asBytes[j+3],\r
431 c.d.asBytes[j+4],\r
432 c.d.asBytes[j+5],\r
433 c.d.asBytes[j+6],\r
434 c.d.asBytes[j+7],\r
435 c.d.asBytes[j+8]\r
436 );\r
437 }\r
438 }\r
439}\r
440\r
441static void CmdHisampless(char *str)\r
442{\r
443 int cnt = 0;\r
444 int i;\r
445 int n;\r
446\r
447 if(atoi(str) == 0) {\r
448 n = 1000;\r
449 } else {\r
450 n = atoi(str)/4;\r
451 }\r
452\r
453 for(i = 0; i < n; i += 12) {\r
454 UsbCommand c;\r
455 c.cmd = CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K;\r
456 c.ext1 = i;\r
457 SendCommand(&c, FALSE);\r
458 ReceiveCommand(&c);\r
459 if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) {\r
460 PrintToScrollback("bad resp\n");\r
461 return;\r
462 }\r
463 int j;\r
464 for(j = 0; j < 48; j++) {\r
465 GraphBuffer[cnt++] = (int)((signed char)c.d.asBytes[j]);\r
466 }\r
467 }\r
468 GraphTraceLen = cnt;\r
469\r
470 RepaintGraphWindow();\r
471}\r
472\r
473static WORD Iso15693Crc(BYTE *v, int n)\r
474{\r
475 DWORD reg;\r
476 int i, j;\r
477\r
478 reg = 0xffff;\r
479 for(i = 0; i < n; i++) {\r
480 reg = reg ^ ((DWORD)v[i]);\r
481 for (j = 0; j < 8; j++) {\r
482 if (reg & 0x0001) {\r
483 reg = (reg >> 1) ^ 0x8408;\r
484 } else {\r
485 reg = (reg >> 1);\r
486 }\r
487 }\r
488 }\r
489\r
490 return (WORD)~reg;\r
491}\r
492\r
493static void CmdHi14bdemod(char *str)\r
494{\r
495 int i, j, iold;\r
496 int isum, qsum;\r
497 int outOfWeakAt;\r
498 BOOL negateI, negateQ;\r
499\r
500 BYTE data[256];\r
501 int dataLen=0;\r
502\r
503 // As received, the samples are pairs, correlations against I and Q\r
504 // square waves. So estimate angle of initial carrier (or just\r
505 // quadrant, actually), and then do the demod.\r
506\r
507 // First, estimate where the tag starts modulating.\r
508 for(i = 0; i < GraphTraceLen; i += 2) {\r
509 if(abs(GraphBuffer[i]) + abs(GraphBuffer[i+1]) > 40) {\r
510 break;\r
511 }\r
512 }\r
513 if(i >= GraphTraceLen) {\r
514 PrintToScrollback("too weak to sync");\r
515 return;\r
516 }\r
517 PrintToScrollback("out of weak at %d", i);\r
518 outOfWeakAt = i;\r
519\r
520 // Now, estimate the phase in the initial modulation of the tag\r
521 isum = 0;\r
522 qsum = 0;\r
523 for(; i < (outOfWeakAt + 16); i += 2) {\r
524 isum += GraphBuffer[i+0];\r
525 qsum += GraphBuffer[i+1];\r
526 }\r
527 negateI = (isum < 0);\r
528 negateQ = (qsum < 0);\r
529\r
530 // Turn the correlation pairs into soft decisions on the bit.\r
531 j = 0;\r
532 for(i = 0; i < GraphTraceLen/2; i++) {\r
533 int si = GraphBuffer[j];\r
534 int sq = GraphBuffer[j+1];\r
535 if(negateI) si = -si;\r
536 if(negateQ) sq = -sq;\r
537 GraphBuffer[i] = si + sq;\r
538 j += 2;\r
539 }\r
540 GraphTraceLen = i;\r
541\r
542 i = outOfWeakAt/2;\r
543 while(GraphBuffer[i] > 0 && i < GraphTraceLen)\r
544 i++;\r
545 if(i >= GraphTraceLen) goto demodError;\r
546\r
547 iold = i;\r
548 while(GraphBuffer[i] < 0 && i < GraphTraceLen)\r
549 i++;\r
550 if(i >= GraphTraceLen) goto demodError;\r
551 if((i - iold) > 23) goto demodError;\r
552\r
553 PrintToScrollback("make it to demod loop");\r
554\r
555 for(;;) {\r
556 iold = i;\r
557 while(GraphBuffer[i] >= 0 && i < GraphTraceLen)\r
558 i++;\r
559 if(i >= GraphTraceLen) goto demodError;\r
560 if((i - iold) > 6) goto demodError;\r
561\r
562 WORD shiftReg = 0;\r
563 if(i + 20 >= GraphTraceLen) goto demodError;\r
564\r
565 for(j = 0; j < 10; j++) {\r
566 int soft = GraphBuffer[i] + GraphBuffer[i+1];\r
567\r
568 if(abs(soft) < ((abs(isum) + abs(qsum))/20)) {\r
569 PrintToScrollback("weak bit");\r
570 }\r
571\r
572 shiftReg >>= 1;\r
573 if(GraphBuffer[i] + GraphBuffer[i+1] >= 0) {\r
574 shiftReg |= 0x200;\r
575 }\r
576\r
577 i+= 2;\r
578 }\r
579\r
580 if( (shiftReg & 0x200) &&\r
581 !(shiftReg & 0x001))\r
582 {\r
583 // valid data byte, start and stop bits okay\r
584 PrintToScrollback(" %02x", (shiftReg >> 1) & 0xff);\r
585 data[dataLen++] = (shiftReg >> 1) & 0xff;\r
586 if(dataLen >= sizeof(data)) {\r
587 return;\r
588 }\r
589 } else if(shiftReg == 0x000) {\r
590 // this is EOF\r
591 break;\r
592 } else {\r
593 goto demodError;\r
594 }\r
595 }\r
596\r
597 BYTE first, second;\r
598 ComputeCrc14443(CRC_14443_B, data, dataLen-2, &first, &second);\r
599 PrintToScrollback("CRC: %02x %02x (%s)\n", first, second,\r
600 (first == data[dataLen-2] && second == data[dataLen-1]) ?\r
601 "ok" : "****FAIL****");\r
602\r
603 RepaintGraphWindow();\r
604 return;\r
605\r
606demodError:\r
607 PrintToScrollback("demod error");\r
608 RepaintGraphWindow();\r
609}\r
610\r
611static void CmdHi14list(char *str)\r
612{\r
613 BYTE got[960];\r
614 GetFromBigBuf(got, sizeof(got));\r
615\r
616 PrintToScrollback("recorded activity:");\r
617 PrintToScrollback(" time :rssi: who bytes");\r
618 PrintToScrollback("---------+----+----+-----------");\r
619\r
620 int i = 0;\r
621 int prev = -1;\r
622\r
623 for(;;) {\r
624 if(i >= 900) {\r
625 break;\r
626 }\r
627\r
628 BOOL isResponse;\r
629 int timestamp = *((DWORD *)(got+i));\r
630 if(timestamp & 0x80000000) {\r
631 timestamp &= 0x7fffffff;\r
632 isResponse = 1;\r
633 } else {\r
634 isResponse = 0;\r
635 }\r
636 int metric = *((DWORD *)(got+i+4));\r
637\r
638 int len = got[i+8];\r
639\r
640 if(len > 100) {\r
641 break;\r
642 }\r
643 if(i + len >= 900) {\r
644 break;\r
645 }\r
646\r
647 BYTE *frame = (got+i+9);\r
648\r
649 char line[1000] = "";\r
650 int j;\r
651 for(j = 0; j < len; j++) {\r
652 sprintf(line+(j*3), "%02x ", frame[j]);\r
653 }\r
654\r
655 char *crc;\r
656 if(len > 2) {\r
657 BYTE b1, b2;\r
658 ComputeCrc14443(CRC_14443_B, frame, len-2, &b1, &b2);\r
659 if(b1 != frame[len-2] || b2 != frame[len-1]) {\r
660 crc = "**FAIL CRC**";\r
661 } else {\r
662 crc = "";\r
663 }\r
664 } else {\r
665 crc = "(SHORT)";\r
666 }\r
667\r
668 char metricString[100];\r
669 if(isResponse) {\r
670 sprintf(metricString, "%3d", metric);\r
671 } else {\r
672 strcpy(metricString, " ");\r
673 }\r
674\r
675 PrintToScrollback(" +%7d: %s: %s %s %s",\r
676 (prev < 0 ? 0 : timestamp - prev),\r
677 metricString,\r
678 (isResponse ? "TAG" : " "), line, crc);\r
679\r
680 prev = timestamp;\r
681 i += (len + 9);\r
682 }\r
683}\r
684\r
685static void CmdHi14alist(char *str)\r
686{\r
687 BYTE got[1920];\r
688 GetFromBigBuf(got, sizeof(got));\r
689\r
690 PrintToScrollback("recorded activity:");\r
691 PrintToScrollback(" ETU :rssi: who bytes");\r
692 PrintToScrollback("---------+----+----+-----------");\r
693\r
694 int i = 0;\r
695 int prev = -1;\r
696\r
697 for(;;) {\r
698 if(i >= 1900) {\r
699 break;\r
700 }\r
701\r
702 BOOL isResponse;\r
703 int timestamp = *((DWORD *)(got+i));\r
704 if(timestamp & 0x80000000) {\r
705 timestamp &= 0x7fffffff;\r
706 isResponse = 1;\r
707 } else {\r
708 isResponse = 0;\r
709 }\r
710\r
711 int metric = 0;\r
712 int parityBits = *((DWORD *)(got+i+4));\r
713 // 4 bytes of additional information...\r
714 // maximum of 32 additional parity bit information\r
715 //\r
716 // TODO:\r
717 // at each quarter bit period we can send power level (16 levels)\r
718 // or each half bit period in 256 levels.\r
719\r
720\r
721 int len = got[i+8];\r
722\r
723 if(len > 100) {\r
724 break;\r
725 }\r
726 if(i + len >= 1900) {\r
727 break;\r
728 }\r
729\r
730 BYTE *frame = (got+i+9);\r
731\r
732 // Break and stick with current result if buffer was not completely full\r
733 if(frame[0] == 0x44 && frame[1] == 0x44 && frame[3] == 0x44) { break; }\r
734\r
735 char line[1000] = "";\r
736 int j;\r
737 for(j = 0; j < len; j++) {\r
738 int oddparity = 0x01;\r
739 int k;\r
740\r
741 for(k=0;k<8;k++) {\r
742 oddparity ^= (((frame[j] & 0xFF) >> k) & 0x01);\r
743 }\r
744\r
745 //if((parityBits >> (len - j - 1)) & 0x01) {\r
746 if(isResponse && (oddparity != ((parityBits >> (len - j - 1)) & 0x01))) {\r
747 sprintf(line+(j*4), "%02x! ", frame[j]);\r
748 }\r
749 else {\r
750 sprintf(line+(j*4), "%02x ", frame[j]);\r
751 }\r
752 }\r
753\r
754 char *crc;\r
755 crc = "";\r
756 if(len > 2) {\r
757 BYTE b1, b2;\r
758 for(j = 0; j < (len - 1); j++) {\r
759 // gives problems... search for the reason..\r
760 /*if(frame[j] == 0xAA) {\r
761 switch(frame[j+1]) {\r
762 case 0x01:\r
763 crc = "[1] Two drops close after each other";\r
764 break;\r
765 case 0x02:\r
766 crc = "[2] Potential SOC with a drop in second half of bitperiod";\r
767 break;\r
768 case 0x03:\r
769 crc = "[3] Segment Z after segment X is not possible";\r
770 break;\r
771 case 0x04:\r
772 crc = "[4] Parity bit of a fully received byte was wrong";\r
773 break;\r
774 default:\r
775 crc = "[?] Unknown error";\r
776 break;\r
777 }\r
778 break;\r
779 }*/\r
780 }\r
781\r
782 if(strlen(crc)==0) {\r
783 ComputeCrc14443(CRC_14443_A, frame, len-2, &b1, &b2);\r
784 if(b1 != frame[len-2] || b2 != frame[len-1]) {\r
785 crc = (isResponse & (len < 6)) ? "" : " !crc";\r
786 } else {\r
787 crc = "";\r
788 }\r
789 }\r
790 } else {\r
791 crc = ""; // SHORT\r
792 }\r
793\r
794 char metricString[100];\r
795 if(isResponse) {\r
796 sprintf(metricString, "%3d", metric);\r
797 } else {\r
798 strcpy(metricString, " ");\r
799 }\r
800\r
801 PrintToScrollback(" +%7d: %s: %s %s %s",\r
802 (prev < 0 ? 0 : (timestamp - prev)),\r
803 metricString,\r
804 (isResponse ? "TAG" : " "), line, crc);\r
805\r
806 prev = timestamp;\r
807 i += (len + 9);\r
808 }\r
809 CommandFinished = 1;\r
810}\r
811\r
812static void CmdHi15demod(char *str)\r
813{\r
814 // The sampling rate is 106.353 ksps/s, for T = 18.8 us\r
815\r
0e25ae11 816 // SOF defined as\r
6658905f 817 // 1) Unmodulated time of 56.64us\r
818 // 2) 24 pulses of 423.75khz\r
819 // 3) logic '1' (unmodulated for 18.88us followed by 8 pulses of 423.75khz)\r
820\r
821 static const int FrameSOF[] = {\r
822 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\r
823 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\r
824 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\r
825 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\r
826 -1, -1, -1, -1,\r
827 -1, -1, -1, -1,\r
828 1, 1, 1, 1,\r
829 1, 1, 1, 1\r
830 };\r
831 static const int Logic0[] = {\r
832 1, 1, 1, 1,\r
833 1, 1, 1, 1,\r
834 -1, -1, -1, -1,\r
835 -1, -1, -1, -1\r
836 };\r
837 static const int Logic1[] = {\r
838 -1, -1, -1, -1,\r
839 -1, -1, -1, -1,\r
840 1, 1, 1, 1,\r
841 1, 1, 1, 1\r
842 };\r
843\r
0e25ae11 844 // EOF defined as\r
6658905f 845 // 1) logic '0' (8 pulses of 423.75khz followed by unmodulated for 18.88us)\r
846 // 2) 24 pulses of 423.75khz\r
847 // 3) Unmodulated time of 56.64us\r
848\r
849 static const int FrameEOF[] = {\r
850 1, 1, 1, 1,\r
851 1, 1, 1, 1,\r
852 -1, -1, -1, -1,\r
853 -1, -1, -1, -1,\r
854 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\r
855 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\r
856 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\r
857 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1\r
858 };\r
859\r
860 int i, j;\r
861 int max = 0, maxPos;\r
862\r
863 int skip = 4;\r
864\r
865 if(GraphTraceLen < 1000) return;\r
866\r
867 // First, correlate for SOF\r
868 for(i = 0; i < 100; i++) {\r
869 int corr = 0;\r
870 for(j = 0; j < arraylen(FrameSOF); j += skip) {\r
871 corr += FrameSOF[j]*GraphBuffer[i+(j/skip)];\r
872 }\r
873 if(corr > max) {\r
874 max = corr;\r
875 maxPos = i;\r
876 }\r
877 }\r
878 PrintToScrollback("SOF at %d, correlation %d", maxPos,\r
879 max/(arraylen(FrameSOF)/skip));\r
880\r
881 i = maxPos + arraylen(FrameSOF)/skip;\r
882 int k = 0;\r
883 BYTE outBuf[20];\r
884 memset(outBuf, 0, sizeof(outBuf));\r
885 BYTE mask = 0x01;\r
886 for(;;) {\r
887 int corr0 = 0, corr1 = 0, corrEOF = 0;\r
888 for(j = 0; j < arraylen(Logic0); j += skip) {\r
889 corr0 += Logic0[j]*GraphBuffer[i+(j/skip)];\r
890 }\r
891 for(j = 0; j < arraylen(Logic1); j += skip) {\r
892 corr1 += Logic1[j]*GraphBuffer[i+(j/skip)];\r
893 }\r
894 for(j = 0; j < arraylen(FrameEOF); j += skip) {\r
895 corrEOF += FrameEOF[j]*GraphBuffer[i+(j/skip)];\r
896 }\r
897 // Even things out by the length of the target waveform.\r
898 corr0 *= 4;\r
899 corr1 *= 4;\r
900\r
901 if(corrEOF > corr1 && corrEOF > corr0) {\r
902 PrintToScrollback("EOF at %d", i);\r
903 break;\r
904 } else if(corr1 > corr0) {\r
905 i += arraylen(Logic1)/skip;\r
906 outBuf[k] |= mask;\r
907 } else {\r
908 i += arraylen(Logic0)/skip;\r
909 }\r
910 mask <<= 1;\r
911 if(mask == 0) {\r
912 k++;\r
913 mask = 0x01;\r
914 }\r
915 if((i+(int)arraylen(FrameEOF)) >= GraphTraceLen) {\r
916 PrintToScrollback("ran off end!");\r
917 break;\r
918 }\r
919 }\r
920 if(mask != 0x01) {\r
921 PrintToScrollback("error, uneven octet! (discard extra bits!)");\r
922 PrintToScrollback(" mask=%02x", mask);\r
923 }\r
924 PrintToScrollback("%d octets", k);\r
925\r
926 for(i = 0; i < k; i++) {\r
927 PrintToScrollback("# %2d: %02x ", i, outBuf[i]);\r
928 }\r
929 PrintToScrollback("CRC=%04x", Iso15693Crc(outBuf, k-2));\r
930}\r
931\r
932static void CmdTiread(char *str)\r
933{\r
934 UsbCommand c;\r
935 c.cmd = CMD_ACQUIRE_RAW_BITS_TI_TYPE;\r
936 SendCommand(&c, FALSE);\r
937}\r
938\r
939static void CmdTibits(char *str)\r
940{\r
941 int cnt = 0;\r
942 int i;\r
943 for(i = 0; i < 1536; i += 12) {\r
944 UsbCommand c;\r
945 c.cmd = CMD_DOWNLOAD_RAW_BITS_TI_TYPE;\r
946 c.ext1 = i;\r
947 SendCommand(&c, FALSE);\r
948 ReceiveCommand(&c);\r
949 if(c.cmd != CMD_DOWNLOADED_RAW_BITS_TI_TYPE) {\r
950 PrintToScrollback("bad resp\n");\r
951 return;\r
952 }\r
953 int j;\r
954 for(j = 0; j < 12; j++) {\r
955 int k;\r
956 for(k = 31; k >= 0; k--) {\r
957 if(c.d.asDwords[j] & (1 << k)) {\r
958 GraphBuffer[cnt++] = 1;\r
959 } else {\r
960 GraphBuffer[cnt++] = -1;\r
961 }\r
962 }\r
963 }\r
964 }\r
965 GraphTraceLen = 1536*32;\r
966 RepaintGraphWindow();\r
967}\r
968\r
969static void CmdTidemod(char *cmdline)\r
970{\r
971 /* MATLAB as follows:\r
972f_s = 2000000; % sampling frequency\r
973f_l = 123200; % low FSK tone\r
974f_h = 134200; % high FSK tone\r
975\r
976T_l = 119e-6; % low bit duration\r
977T_h = 130e-6; % high bit duration\r
978\r
979l = 2*pi*ones(1, floor(f_s*T_l))*(f_l/f_s);\r
980h = 2*pi*ones(1, floor(f_s*T_h))*(f_h/f_s);\r
981\r
982l = sign(sin(cumsum(l)));\r
983h = sign(sin(cumsum(h)));\r
984 */\r
985 static const int LowTone[] = {\r
986 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1,\r
987 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1,\r
988 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1,\r
989 -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1,\r
990 -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1,\r
991 -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1,\r
992 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1,\r
993 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1,\r
994 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1,\r
995 -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1,\r
996 -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1,\r
997 -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1,\r
998 1, 1, 1, 1, 1, 1, 1, -1, -1, -1,\r
999 };\r
1000 static const int HighTone[] = {\r
1001 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1,\r
1002 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1,\r
1003 -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,\r
1004 -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1,\r
1005 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1,\r
1006 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1,\r
1007 -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,\r
1008 -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1,\r
1009 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1,\r
1010 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1,\r
1011 -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1,\r
1012 -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1,\r
1013 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1,\r
1014 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1,\r
1015 };\r
1016\r
1017 int convLen = max(arraylen(HighTone), arraylen(LowTone));\r
1018\r
1019 int i;\r
1020 for(i = 0; i < GraphTraceLen - convLen; i++) {\r
1021 int j;\r
1022 int lowSum = 0, highSum = 0;;\r
1023 int lowLen = arraylen(LowTone);\r
1024 int highLen = arraylen(HighTone);\r
1025\r
1026 for(j = 0; j < lowLen; j++) {\r
1027 lowSum += LowTone[j]*GraphBuffer[i+j];\r
1028 }\r
1029 for(j = 0; j < highLen; j++) {\r
1030 highSum += HighTone[j]*GraphBuffer[i+j];\r
1031 }\r
1032 lowSum = abs((100*lowSum) / lowLen);\r
1033 highSum = abs((100*highSum) / highLen);\r
1034 GraphBuffer[i] = (highSum << 16) | lowSum;\r
1035 }\r
1036\r
1037 for(i = 0; i < GraphTraceLen - convLen - 16; i++) {\r
1038 int j;\r
1039 int lowTot = 0, highTot = 0;\r
1040 // 16 and 15 are f_s divided by f_l and f_h, rounded\r
1041 for(j = 0; j < 16; j++) {\r
1042 lowTot += (GraphBuffer[i+j] & 0xffff);\r
1043 }\r
1044 for(j = 0; j < 15; j++) {\r
1045 highTot += (GraphBuffer[i+j] >> 16);\r
1046 }\r
1047 GraphBuffer[i] = lowTot - highTot;\r
1048 }\r
1049\r
1050 GraphTraceLen -= (convLen + 16);\r
1051\r
1052 RepaintGraphWindow();\r
1053\r
1054 // Okay, so now we have unsliced soft decisions; find bit-sync, and then\r
1055 // get some bits.\r
1056\r
1057 int max = 0, maxPos = 0;\r
1058 for(i = 0; i < 6000; i++) {\r
1059 int j;\r
1060 int dec = 0;\r
1061 for(j = 0; j < 8*arraylen(LowTone); j++) {\r
1062 dec -= GraphBuffer[i+j];\r
1063 }\r
1064 for(; j < 8*arraylen(LowTone) + 8*arraylen(HighTone); j++) {\r
1065 dec += GraphBuffer[i+j];\r
1066 }\r
1067 if(dec > max) {\r
1068 max = dec;\r
1069 maxPos = i;\r
1070 }\r
1071 }\r
1072 GraphBuffer[maxPos] = 800;\r
1073 GraphBuffer[maxPos+1] = -800;\r
1074\r
1075 maxPos += 8*arraylen(LowTone);\r
1076 GraphBuffer[maxPos] = 800;\r
1077 GraphBuffer[maxPos+1] = -800;\r
1078 maxPos += 8*arraylen(HighTone);\r
1079\r
1080 GraphBuffer[maxPos] = 800;\r
1081 GraphBuffer[maxPos+1] = -800;\r
1082\r
1083 PrintToScrollback("actual data bits start at sample %d", maxPos);\r
1084\r
1085 PrintToScrollback("length %d/%d", arraylen(HighTone), arraylen(LowTone));\r
1086\r
1087 GraphBuffer[maxPos] = 800;\r
1088 GraphBuffer[maxPos+1] = -800;\r
1089\r
1090 BYTE bits[64+16+8+1];\r
1091 bits[sizeof(bits)-1] = '\0';\r
1092\r
1093 for(i = 0; i < arraylen(bits); i++) {\r
1094 int high = 0;\r
1095 int low = 0;\r
1096 int j;\r
1097 for(j = 0; j < arraylen(LowTone); j++) {\r
1098 low -= GraphBuffer[maxPos+j];\r
1099 }\r
1100 for(j = 0; j < arraylen(HighTone); j++) {\r
1101 high += GraphBuffer[maxPos+j];\r
1102 }\r
1103 if(high > low) {\r
1104 bits[i] = '1';\r
1105 maxPos += arraylen(HighTone);\r
1106 } else {\r
1107 bits[i] = '.';\r
1108 maxPos += arraylen(LowTone);\r
1109 }\r
1110 GraphBuffer[maxPos] = 800;\r
1111 GraphBuffer[maxPos+1] = -800;\r
1112 }\r
1113 PrintToScrollback("bits: '%s'", bits);\r
1114\r
1115 DWORD h = 0, l = 0;\r
1116 for(i = 0; i < 32; i++) {\r
1117 if(bits[i] == '1') {\r
1118 l |= (1<<i);\r
1119 }\r
1120 }\r
1121 for(i = 32; i < 64; i++) {\r
1122 if(bits[i] == '1') {\r
1123 h |= (1<<(i-32));\r
1124 }\r
1125 }\r
1126 PrintToScrollback("hex: %08x %08x", h, l);\r
1127}\r
1128\r
1129static void CmdNorm(char *str)\r
1130{\r
1131 int i;\r
1132 int max = INT_MIN, min = INT_MAX;\r
1133 for(i = 10; i < GraphTraceLen; i++) {\r
1134 if(GraphBuffer[i] > max) {\r
1135 max = GraphBuffer[i];\r
1136 }\r
1137 if(GraphBuffer[i] < min) {\r
1138 min = GraphBuffer[i];\r
1139 }\r
1140 }\r
1141 if(max != min) {\r
1142 for(i = 0; i < GraphTraceLen; i++) {\r
1143 GraphBuffer[i] = (GraphBuffer[i] - ((max + min)/2))*1000/\r
1144 (max - min);\r
1145 }\r
1146 }\r
1147 RepaintGraphWindow();\r
1148}\r
1149\r
1150static void CmdDec(char *str)\r
1151{\r
1152 int i;\r
1153 for(i = 0; i < (GraphTraceLen/2); i++) {\r
1154 GraphBuffer[i] = GraphBuffer[i*2];\r
1155 }\r
1156 GraphTraceLen /= 2;\r
1157 PrintToScrollback("decimated by 2");\r
1158 RepaintGraphWindow();\r
1159}\r
1160\r
1161static void CmdHpf(char *str)\r
1162{\r
1163 int i;\r
1164 int accum = 0;\r
1165 for(i = 10; i < GraphTraceLen; i++) {\r
1166 accum += GraphBuffer[i];\r
1167 }\r
1168 accum /= (GraphTraceLen - 10);\r
1169 for(i = 0; i < GraphTraceLen; i++) {\r
1170 GraphBuffer[i] -= accum;\r
1171 }\r
1172\r
1173 RepaintGraphWindow();\r
1174}\r
1175\r
1176static void CmdZerocrossings(char *str)\r
1177{\r
1178 int i;\r
1179 // Zero-crossings aren't meaningful unless the signal is zero-mean.\r
1180 CmdHpf("");\r
1181\r
1182 int sign = 1;\r
1183 int zc = 0;\r
1184 int lastZc = 0;\r
1185 for(i = 0; i < GraphTraceLen; i++) {\r
1186 if(GraphBuffer[i]*sign >= 0) {\r
1187 // No change in sign, reproduce the previous sample count.\r
1188 zc++;\r
1189 GraphBuffer[i] = lastZc;\r
1190 } else {\r
1191 // Change in sign, reset the sample count.\r
1192 sign = -sign;\r
1193 GraphBuffer[i] = lastZc;\r
1194 if(sign > 0) {\r
1195 lastZc = zc;\r
1196 zc = 0;\r
1197 }\r
1198 }\r
1199 }\r
1200\r
1201 RepaintGraphWindow();\r
1202}\r
1203\r
1204static void CmdLtrim(char *str)\r
1205{\r
1206 int i;\r
1207 int ds = atoi(str);\r
1208\r
1209 for(i = ds; i < GraphTraceLen; i++) {\r
1210 GraphBuffer[i-ds] = GraphBuffer[i];\r
1211 }\r
1212 GraphTraceLen -= ds;\r
1213\r
1214 RepaintGraphWindow();\r
1215}\r
1216\r
1217static void CmdAutoCorr(char *str)\r
1218{\r
1219 static int CorrelBuffer[MAX_GRAPH_TRACE_LEN];\r
1220\r
1221 int window = atoi(str);\r
1222\r
1223 if(window == 0) {\r
1224 PrintToScrollback("needs a window");\r
1225 return;\r
1226 }\r
1227\r
1228 if(window >= GraphTraceLen) {\r
1229 PrintToScrollback("window must be smaller than trace (%d samples)",\r
1230 GraphTraceLen);\r
1231 return;\r
1232 }\r
1233\r
1234 PrintToScrollback("performing %d correlations", GraphTraceLen - window);\r
1235\r
1236 int i;\r
1237 for(i = 0; i < GraphTraceLen - window; i++) {\r
1238 int sum = 0;\r
1239 int j;\r
1240 for(j = 0; j < window; j++) {\r
1241 sum += (GraphBuffer[j]*GraphBuffer[i+j]) / 256;\r
1242 }\r
1243 CorrelBuffer[i] = sum;\r
1244 }\r
1245 GraphTraceLen = GraphTraceLen - window;\r
1246 memcpy(GraphBuffer, CorrelBuffer, GraphTraceLen*sizeof(int));\r
1247\r
1248 RepaintGraphWindow();\r
1249}\r
1250\r
1251static void CmdVchdemod(char *str)\r
1252{\r
1253 // Is this the entire sync pattern, or does this also include some\r
1254 // data bits that happen to be the same everywhere? That would be\r
1255 // lovely to know.\r
1256 static const int SyncPattern[] = {\r
1257 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\r
1258 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\r
1259 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\r
1260 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\r
1261 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\r
1262 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\r
1263 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\r
1264 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\r
1265 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\r
1266 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,\r
1267 };\r
1268\r
1269 // So first, we correlate for the sync pattern, and mark that.\r
1270 int bestCorrel = 0, bestPos = 0;\r
1271 int i;\r
1272 // It does us no good to find the sync pattern, with fewer than\r
1273 // 2048 samples after it...\r
1274 for(i = 0; i < (GraphTraceLen-2048); i++) {\r
1275 int sum = 0;\r
1276 int j;\r
1277 for(j = 0; j < arraylen(SyncPattern); j++) {\r
1278 sum += GraphBuffer[i+j]*SyncPattern[j];\r
1279 }\r
1280 if(sum > bestCorrel) {\r
1281 bestCorrel = sum;\r
1282 bestPos = i;\r
1283 }\r
1284 }\r
1285 PrintToScrollback("best sync at %d [metric %d]", bestPos, bestCorrel);\r
1286\r
1287 char bits[257];\r
1288 bits[256] = '\0';\r
1289\r
1290 int worst = INT_MAX;\r
1291 int worstPos;\r
1292\r
1293 for(i = 0; i < 2048; i += 8) {\r
1294 int sum = 0;\r
1295 int j;\r
1296 for(j = 0; j < 8; j++) {\r
1297 sum += GraphBuffer[bestPos+i+j];\r
1298 }\r
1299 if(sum < 0) {\r
1300 bits[i/8] = '.';\r
1301 } else {\r
1302 bits[i/8] = '1';\r
1303 }\r
1304 if(abs(sum) < worst) {\r
1305 worst = abs(sum);\r
1306 worstPos = i;\r
1307 }\r
1308 }\r
1309 PrintToScrollback("bits:");\r
1310 PrintToScrollback("%s", bits);\r
1311 PrintToScrollback("worst metric: %d at pos %d", worst, worstPos);\r
1312\r
1313 if(strcmp(str, "clone")==0) {\r
1314 GraphTraceLen = 0;\r
1315 char *s;\r
1316 for(s = bits; *s; s++) {\r
1317 int j;\r
1318 for(j = 0; j < 16; j++) {\r
1319 GraphBuffer[GraphTraceLen++] = (*s == '1') ? 1 : 0;\r
1320 }\r
1321 }\r
1322 RepaintGraphWindow();\r
1323 }\r
1324}\r
1325\r
a60612db 1326static void CmdIndalademod(char *str)\r
1327{\r
1328 // Usage: recover 64bit UID by default, specify "224" as arg to recover a 224bit UID\r
1329\r
1330 int state = -1;\r
1331 int count = 0;\r
1332 int i, j;\r
1333 // worst case with GraphTraceLen=64000 is < 4096\r
1334 // under normal conditions it's < 2048\r
1335 BYTE rawbits[4096];\r
1336 int rawbit = 0;\r
1337 int worst = 0, worstPos = 0;\r
1338 PrintToScrollback("Expecting a bit less than %d raw bits", GraphTraceLen/32);\r
1339 for(i = 0; i < GraphTraceLen-1; i += 2) {\r
1340 count+=1;\r
1341 if((GraphBuffer[i] > GraphBuffer[i + 1]) && (state != 1)) {\r
1342 if (state == 0) {\r
1343 for(j = 0; j < count - 8; j += 16) {\r
1344 rawbits[rawbit++] = 0;\r
1345 }\r
1346 if ((abs(count - j)) > worst) {\r
1347 worst = abs(count - j);\r
1348 worstPos = i;\r
1349 }\r
1350 }\r
1351 state = 1;\r
1352 count=0;\r
1353 } else if((GraphBuffer[i] < GraphBuffer[i + 1]) && (state != 0)) {\r
1354 if (state == 1) {\r
1355 for(j = 0; j < count - 8; j += 16) {\r
1356 rawbits[rawbit++] = 1;\r
1357 }\r
1358 if ((abs(count - j)) > worst) {\r
1359 worst = abs(count - j);\r
1360 worstPos = i;\r
1361 }\r
1362 }\r
1363 state = 0;\r
1364 count=0;\r
1365 }\r
1366 }\r
1367 PrintToScrollback("Recovered %d raw bits", rawbit);\r
1368 PrintToScrollback("worst metric (0=best..7=worst): %d at pos %d", worst, worstPos);\r
1369\r
1370 // Finding the start of a UID\r
1371 int uidlen, long_wait;\r
1372 if(strcmp(str, "224") == 0) {\r
1373 uidlen=224;\r
1374 long_wait=30;\r
1375 } else {\r
1376 uidlen=64;\r
1377 long_wait=29;\r
1378 }\r
1379 int start;\r
1380 int first = 0;\r
1381 for(start = 0; start <= rawbit - uidlen; start++) {\r
1382 first = rawbits[start];\r
1383 for(i = start; i < start + long_wait; i++) {\r
1384 if(rawbits[i] != first) {\r
1385 break;\r
1386 }\r
1387 }\r
1388 if(i == (start + long_wait)) {\r
1389 break;\r
1390 }\r
1391 }\r
1392 if(start == rawbit - uidlen + 1) {\r
1393 PrintToScrollback("nothing to wait for");\r
1394 return;\r
1395 }\r
1396\r
1397 // Inverting signal if needed\r
1398 if(first == 1) {\r
1399 for(i = start; i < rawbit; i++) {\r
1400 rawbits[i] = !rawbits[i];\r
1401 }\r
1402 }\r
1403\r
1404 // Dumping UID\r
1405 BYTE bits[224];\r
1406 char showbits[225];\r
1407 showbits[uidlen]='\0';\r
1408 int bit;\r
1409 i = start;\r
1410 int times = 0;\r
1411 if(uidlen > rawbit) {\r
1412 PrintToScrollback("Warning: not enough raw bits to get a full UID");\r
1413 for(bit = 0; bit < rawbit; bit++) {\r
1414 bits[bit] = rawbits[i++];\r
1415 // As we cannot know the parity, let's use "." and "/"\r
1416 showbits[bit] = '.' + bits[bit];\r
1417 }\r
1418 showbits[bit+1]='\0';\r
1419 PrintToScrollback("Partial UID=%s", showbits);\r
1420 return;\r
1421 } else {\r
1422 for(bit = 0; bit < uidlen; bit++) {\r
1423 bits[bit] = rawbits[i++];\r
1424 showbits[bit] = '0' + bits[bit];\r
1425 }\r
1426 times = 1;\r
1427 }\r
1428 PrintToScrollback("UID=%s", showbits);\r
1429\r
1430 // Checking UID against next occurences\r
1431 for(; i + uidlen <= rawbit;) {\r
1432 int failed = 0;\r
1433 for(bit = 0; bit < uidlen; bit++) {\r
1434 if(bits[bit] != rawbits[i++]) {\r
1435 failed = 1;\r
1436 break;\r
1437 }\r
1438 }\r
1439 if (failed == 1) {\r
1440 break;\r
1441 }\r
1442 times += 1;\r
1443 }\r
1444 PrintToScrollback("Occurences: %d (expected %d)", times, (rawbit - start) / uidlen);\r
1445\r
1446 // Remodulating for tag cloning\r
1447 GraphTraceLen = 32*uidlen;\r
1448 i = 0;\r
1449 int phase = 0;\r
1450 for(bit = 0; bit < uidlen; bit++) {\r
1451 if(bits[bit] == 0) {\r
1452 phase = 0;\r
1453 } else {\r
1454 phase = 1;\r
1455 }\r
1456 int j;\r
1457 for(j = 0; j < 32; j++) {\r
1458 GraphBuffer[i++] = phase;\r
1459 phase = !phase;\r
1460 }\r
1461 }\r
1462\r
1463 RepaintGraphWindow();\r
1464}\r
1465\r
6658905f 1466static void CmdFlexdemod(char *str)\r
1467{\r
1468 int i;\r
1469 for(i = 0; i < GraphTraceLen; i++) {\r
1470 if(GraphBuffer[i] < 0) {\r
1471 GraphBuffer[i] = -1;\r
1472 } else {\r
1473 GraphBuffer[i] = 1;\r
1474 }\r
1475 }\r
1476\r
1477#define LONG_WAIT 100\r
1478 int start;\r
1479 for(start = 0; start < GraphTraceLen - LONG_WAIT; start++) {\r
1480 int first = GraphBuffer[start];\r
1481 for(i = start; i < start + LONG_WAIT; i++) {\r
1482 if(GraphBuffer[i] != first) {\r
1483 break;\r
1484 }\r
1485 }\r
1486 if(i == (start + LONG_WAIT)) {\r
1487 break;\r
1488 }\r
1489 }\r
1490 if(start == GraphTraceLen - LONG_WAIT) {\r
1491 PrintToScrollback("nothing to wait for");\r
1492 return;\r
1493 }\r
1494\r
1495 GraphBuffer[start] = 2;\r
1496 GraphBuffer[start+1] = -2;\r
1497\r
1498 BYTE bits[64];\r
1499\r
1500 int bit;\r
1501 i = start;\r
1502 for(bit = 0; bit < 64; bit++) {\r
1503 int j;\r
1504 int sum = 0;\r
1505 for(j = 0; j < 16; j++) {\r
1506 sum += GraphBuffer[i++];\r
1507 }\r
1508 if(sum > 0) {\r
1509 bits[bit] = 1;\r
1510 } else {\r
1511 bits[bit] = 0;\r
1512 }\r
1513 PrintToScrollback("bit %d sum %d", bit, sum);\r
1514 }\r
1515\r
1516 for(bit = 0; bit < 64; bit++) {\r
1517 int j;\r
1518 int sum = 0;\r
1519 for(j = 0; j < 16; j++) {\r
1520 sum += GraphBuffer[i++];\r
1521 }\r
1522 if(sum > 0 && bits[bit] != 1) {\r
1523 PrintToScrollback("oops1 at %d", bit);\r
1524 }\r
1525 if(sum < 0 && bits[bit] != 0) {\r
1526 PrintToScrollback("oops2 at %d", bit);\r
1527 }\r
1528 }\r
1529\r
1530 GraphTraceLen = 32*64;\r
1531 i = 0;\r
1532 int phase = 0;\r
1533 for(bit = 0; bit < 64; bit++) {\r
1534 if(bits[bit] == 0) {\r
1535 phase = 0;\r
1536 } else {\r
1537 phase = 1;\r
1538 }\r
1539 int j;\r
1540 for(j = 0; j < 32; j++) {\r
1541 GraphBuffer[i++] = phase;\r
1542 phase = !phase;\r
1543 }\r
1544 }\r
1545\r
1546 RepaintGraphWindow();\r
1547}\r
1548
1549/*
1550 * Generic command to demodulate ASK. bit length in argument.
1551 * Giving the bit length helps discriminate ripple effects
1552 * upon zero crossing for noisy traces.
1553 *
1554 * Second is convention: positive or negative (High mod means zero
1555 * or high mod means one)
1556 *
1557 * Updates the Graph trace with 0/1 values
1558 *
1559 * Arguments:
1560 * sl : bit length in terms of number of samples per bit
1561 * (use yellow/purple markers to compute).
1562 * c : 0 or 1
1563 */
1564
1565static void Cmdaskdemod(char *str) {
1566 int i;
1567 int sign = 1;
1568 int n = 0;
1569 int c = 0;\r
1570 int t1 = 0;
1571
1572 // TODO: complain if we do not give 2 arguments here !
1573 sscanf(str, "%i %i", &n, &c);
1574 if (c == 0) {
1575 c = 1 ;
1576 } else {
1577 c = -1;
1578 }
1579
1580 if (GraphBuffer[0]*c > 0) {
1581 GraphBuffer[0] = 1;
1582 } else {
1583 GraphBuffer[0] = 0;
1584 }
1585 for(i=1;i<GraphTraceLen;i++) {
1586 /* Analyse signal within the symbol length */
1587 /* Decide if we crossed a zero */
1588 if (GraphBuffer[i]*sign < 0) {
1589 /* Crossed a zero, check if this is a ripple or not */
1590 if ( (i-t1) > n/4 ) {
1591 sign = -sign;
1592 t1=i;
1593 if (GraphBuffer[i]*c > 0){
1594 GraphBuffer[i]=1;
1595 } else {
1596 GraphBuffer[i]=0;
1597 }
1598 } else {
1599 /* This is a ripple, set the current sample value
1600 to the same as previous */
1601 GraphBuffer[i] = GraphBuffer[i-1];
1602 }
1603 } else {
1604 GraphBuffer[i] = GraphBuffer[i-1];
1605 }
1606 }
1607 RepaintGraphWindow();
1608}
1609
1610
1611/*
1612 * Manchester demodulate a bitstream. The bitstream needs to be already in
1613 * the GraphBuffer as 0 and 1 values
1614 *
1615 * Give the clock rate as argument in order to help the sync - the algorithm
1616 * resyncs at each pulse anyway.
1617 *
1618 * Not optimized by any means, this is the 1st time I'm writing this type of
1619 * routine, feel free to improve...
1620 *
1621 * 1st argument: clock rate (as number of samples per clock rate)
30f2a7d3 1622 * Typical values can be 64, 32, 128...
6658905f 1623 */
1624static void Cmdmanchesterdemod(char *str) {
c9f99c01 1625 int i, j;\r
1626 int bit;\r
6658905f 1627 int clock;
6658905f 1628 int lastval;
c9f99c01 1629 int low = 0;\r
1630 int high = 0;\r
1631 int hithigh, hitlow, first;\r
6658905f 1632 int lc = 0;
1633 int bitidx = 0;
30f2a7d3 1634 int bit2idx = 0;
c9f99c01 1635 int warnings = 0;\r
6658905f 1636
1637 sscanf(str, "%i", &clock);
c9f99c01 1638 if (!clock)\r
1639 {\r
1640 PrintToScrollback("You must provide a clock rate.");\r
1641 return;\r
1642 }\r
6658905f 1643
1644 int tolerance = clock/4;
30f2a7d3 1645 /* Holds the decoded bitstream: each clock period contains 2 bits */
1646 /* later simplified to 1 bit after manchester decoding. */
1647 /* Add 10 bits to allow for noisy / uncertain traces without aborting */
1648 /* int BitStream[GraphTraceLen*2/clock+10]; */
1649
1650 /* But it does not work if compiling on WIndows: therefore we just allocate a */
1651 /* large array */
1652 int BitStream[MAX_GRAPH_TRACE_LEN];
6658905f 1653
c9f99c01 1654 /* Detect high and lows */\r
1655 for (i = 0; i < GraphTraceLen; i++)\r
1656 {\r
1657 if (GraphBuffer[i] > high)\r
1658 high = GraphBuffer[i];\r
1659 else if (GraphBuffer[i] < low)\r
1660 low = GraphBuffer[i];\r
1661 }\r
1662\r
6658905f 1663 /* Detect first transition */
30f2a7d3 1664 /* Lo-Hi (arbitrary) */
c9f99c01 1665 for (i = 0; i < GraphTraceLen; i++)\r
1666 {\r
1667 if (GraphBuffer[i] == low)\r
1668 {\r
1669// BitStream[0]=0; // Previous state = 0;\r
6658905f 1670 lastval = i;
6658905f 1671 break;
1672 }
1673 }
c9f99c01 1674//PrintToScrollback("cool %d %d %d %d", low, high, lastval, GraphBuffer[i]);\r
1675\r
1676 /* If we're not working with 1/0s, demod based off clock */\r
1677 if (high != 1)\r
1678 {\r
1679 bit = 0;\r
1680 for (i = 0; i < (GraphTraceLen / clock); i++)\r
1681 {\r
1682 hithigh = 0;\r
1683 hitlow = 0;\r
1684 first = 1;\r
1685\r
1686 /* Find out if we hit both high and low peaks */\r
1687 for (j = 0; j < clock; j++)\r
1688 {\r
1689 if (GraphBuffer[(i * clock) + j] == high)\r
1690 hithigh = 1;\r
1691 else if (GraphBuffer[(i * clock) + j] == low)\r
1692 hitlow = 1;\r
1693\r
1694 /* it doesn't count if it's the first part of our read\r
1695 because it's really just trailing from the last sequence */\r
1696 if (first && (hithigh || hitlow))\r
1697 hithigh = hitlow = 0;\r
1698 else\r
1699 first = 0;\r
1700\r
1701 if (hithigh && hitlow)\r
1702 break;\r
1703 }\r
1704\r
1705 /* If we didn't hit both high and low peaks, we had a bit transition */\r
1706 if (!hithigh || !hitlow)\r
1707 bit ^= 1;\r
1708\r
1709 BitStream[bit2idx++] = bit;\r
1710 }\r
1711 }\r
1712\r
1713 /* standard 1/0 bitstream */\r
1714 else\r
1715 {\r
6658905f 1716
1717 /* Then detect duration between 2 successive transitions */
c9f99c01 1718 for (bitidx = 1; i < GraphTraceLen; i++)\r
1719 {\r
1720 if (GraphBuffer[i-1] != GraphBuffer[i])\r
1721 {\r
6658905f 1722 lc = i-lastval;
1723 lastval = i;
c9f99c01 1724\r
30f2a7d3 1725 // Error check: if bitidx becomes too large, we do not
1726 // have a Manchester encoded bitstream or the clock is really
1727 // wrong!
1728 if (bitidx > (GraphTraceLen*2/clock+8) ) {
1729 PrintToScrollback("Error: the clock you gave is probably wrong, aborting.");
1730 return;
1731 }
6658905f 1732 // Then switch depending on lc length:
1733 // Tolerance is 1/4 of clock rate (arbitrary)
30f2a7d3 1734 if (abs(lc-clock/2) < tolerance) {
1735 // Short pulse : either "1" or "0"
6658905f 1736 BitStream[bitidx++]=GraphBuffer[i-1];
30f2a7d3 1737 } else if (abs(lc-clock) < tolerance) {
1738 // Long pulse: either "11" or "00"
6658905f 1739 BitStream[bitidx++]=GraphBuffer[i-1];
1740 BitStream[bitidx++]=GraphBuffer[i-1];
1741 } else {
1742 // Error
c9f99c01 1743 warnings++;\r
0e25ae11 1744 PrintToScrollback("Warning: Manchester decode error for pulse width detection.");
6658905f 1745 PrintToScrollback("(too many of those messages mean either the stream is not Manchester encoded, or clock is wrong)");
c9f99c01 1746\r
1747 if (warnings > 100)\r
1748 {\r
1749 PrintToScrollback("Error: too many detection errors, aborting.");\r
1750 return;\r
1751 }\r
6658905f 1752 }
1753 }
1754 }
1755
1756 // At this stage, we now have a bitstream of "01" ("1") or "10" ("0"), parse it into final decoded bitstream
30f2a7d3 1757 // Actually, we overwrite BitStream with the new decoded bitstream, we just need to be careful
1758 // to stop output at the final bitidx2 value, not bitidx
1759 for (i = 0; i < bitidx; i += 2) {
1760 if ((BitStream[i] == 0) && (BitStream[i+1] == 1)) {
1761 BitStream[bit2idx++] = 1;
1762 } else if ((BitStream[i] == 1) && (BitStream[i+1] == 0)) {
1763 BitStream[bit2idx++] = 0;
6658905f 1764 } else {
974ba9a2 1765 // We cannot end up in this state, this means we are unsynchronized,
6658905f 1766 // move up 1 bit:
30f2a7d3 1767 i++;
c9f99c01 1768 warnings++;\r
6658905f 1769 PrintToScrollback("Unsynchronized, resync...");
1770 PrintToScrollback("(too many of those messages mean the stream is not Manchester encoded)");
c9f99c01 1771\r
1772 if (warnings > 100)\r
1773 {\r
1774 PrintToScrollback("Error: too many decode errors, aborting.");\r
1775 return;\r
1776 }\r
6658905f 1777 }
1778 }
c9f99c01 1779 }\r
1780\r
1781 PrintToScrollback("Manchester decoded bitstream");\r
6658905f 1782 // Now output the bitstream to the scrollback by line of 16 bits
30f2a7d3 1783 for (i = 0; i < (bit2idx-16); i+=16) {
6658905f 1784 PrintToScrollback("%i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i",
30f2a7d3 1785 BitStream[i],
1786 BitStream[i+1],
1787 BitStream[i+2],
1788 BitStream[i+3],
1789 BitStream[i+4],
1790 BitStream[i+5],
1791 BitStream[i+6],
1792 BitStream[i+7],
1793 BitStream[i+8],
1794 BitStream[i+9],
1795 BitStream[i+10],
1796 BitStream[i+11],
1797 BitStream[i+12],
1798 BitStream[i+13],
1799 BitStream[i+14],
1800 BitStream[i+15]);
6658905f 1801 }
1802}
1803
1804
1805
1806/*
1807 * Usage ???
1808 */\r
1809static void CmdHiddemod(char *str)\r
1810{\r
1811 if(GraphTraceLen < 4800) {\r
1812 PrintToScrollback("too short; need at least 4800 samples");\r
1813 return;\r
1814 }\r
1815\r
1816 GraphTraceLen = 4800;\r
1817 int i;\r
1818 for(i = 0; i < GraphTraceLen; i++) {\r
1819 if(GraphBuffer[i] < 0) {\r
1820 GraphBuffer[i] = 0;\r
1821 } else {\r
1822 GraphBuffer[i] = 1;\r
1823 }\r
1824 }\r
1825 RepaintGraphWindow();\r
1826}\r
1827\r
1828static void CmdPlot(char *str)\r
1829{\r
1830 ShowGraphWindow();\r
1831}\r
1832\r
1833static void CmdHide(char *str)\r
1834{\r
1835 HideGraphWindow();\r
1836}\r
1837\r
1838static void CmdScale(char *str)\r
1839{\r
1840 CursorScaleFactor = atoi(str);\r
1841 if(CursorScaleFactor == 0) {\r
1842 PrintToScrollback("bad, can't have zero scale");\r
1843 CursorScaleFactor = 1;\r
1844 }\r
1845 RepaintGraphWindow();\r
1846}\r
1847\r
1848static void CmdSave(char *str)\r
1849{\r
1850 FILE *f = fopen(str, "w");\r
1851 if(!f) {\r
1852 PrintToScrollback("couldn't open '%s'", str);\r
1853 return;\r
1854 }\r
1855 int i;\r
1856 for(i = 0; i < GraphTraceLen; i++) {\r
1857 fprintf(f, "%d\n", GraphBuffer[i]);\r
1858 }\r
1859 fclose(f);\r
1860 PrintToScrollback("saved to '%s'", str);\r
1861}\r
1862\r
1863static void CmdLoad(char *str)\r
1864{\r
1865 FILE *f = fopen(str, "r");\r
1866 if(!f) {\r
1867 PrintToScrollback("couldn't open '%s'", str);\r
1868 return;\r
1869 }\r
1870\r
1871 GraphTraceLen = 0;\r
1872 char line[80];\r
1873 while(fgets(line, sizeof(line), f)) {\r
1874 GraphBuffer[GraphTraceLen] = atoi(line);\r
1875 GraphTraceLen++;\r
1876 }\r
1877 fclose(f);\r
1878 PrintToScrollback("loaded %d samples", GraphTraceLen);\r
1879 RepaintGraphWindow();\r
1880}\r
1881\r
1882static void CmdHIDsimTAG(char *str)\r
1883{\r
1884 unsigned int hi=0, lo=0;\r
1885 int n=0, i=0;\r
1886 UsbCommand c;\r
1887\r
1888 while (sscanf(&str[i++], "%1x", &n ) == 1) {\r
1889 hi=(hi<<4)|(lo>>28);\r
1890 lo=(lo<<4)|(n&0xf);\r
1891 }\r
1892\r
1893 PrintToScrollback("Emulating tag with ID %x%16x", hi, lo);\r
1894\r
1895 c.cmd = CMD_HID_SIM_TAG;\r
1896 c.ext1 = hi;\r
1897 c.ext2 = lo;\r
1898 SendCommand(&c, FALSE);\r
1899}\r
1900\r
1901static void CmdLcdReset(char *str)\r
1902{\r
1903 UsbCommand c;\r
1904 c.cmd = CMD_LCD_RESET;\r
1905 c.ext1 = atoi(str);\r
1906 SendCommand(&c, FALSE);\r
1907}\r
1908\r
1909static void CmdLcd(char *str)\r
1910{\r
1911 int i, j;\r
1912 UsbCommand c;\r
1913 c.cmd = CMD_LCD;\r
1914 sscanf(str, "%x %d", &i, &j);\r
1915 while (j--) {\r
1916 c.ext1 = i&0x1ff;\r
1917 SendCommand(&c, FALSE);\r
1918 }\r
1919}\r
1920\r
d722c4ce 1921\r
1922\r
6658905f 1923static void CmdTest(char *str)\r
1924{\r
1925}\r
30f2a7d3 1926
1927/*
1928 * Sets the divisor for LF frequency clock: lets the user choose any LF frequency below
1929 * 600kHz.
1930 */
1931static void CmdSetDivisor(char *str)\r
1932{\r
1933 UsbCommand c;\r
1934 c.cmd = CMD_SET_LF_DIVISOR;\r
1935 c.ext1 = atoi(str);\r
1936 if (( c.ext1<0) || (c.ext1>255)) {\r
1937 PrintToScrollback("divisor must be between 19 and 255");\r
1938 } else {\r
1939 SendCommand(&c, FALSE);\r
1940 PrintToScrollback("Divisor set, expected freq=%dHz", 12000000/(c.ext1+1));\r
1941 }\r
1942}\r
1943\r
1944static void CmdSweepLF(char *str)\r
1945{\r
1946 UsbCommand c;\r
1947 c.cmd = CMD_SWEEP_LF;\r
1948 SendCommand(&c, FALSE);\r
1949}\r
1950
1951
6658905f 1952typedef void HandlerFunction(char *cmdline);\r
1953\r
1954static struct {\r
fb25b483 1955 char *name;\r
1956 HandlerFunction *handler;\r
1957 int offline; // 1 if the command can be used when in offline mode\r
1958 char *docString;
6658905f 1959} CommandTable[] = {\r
d722c4ce 1960 "tune", CmdTune,0, "measure antenna tuning",\r
1961 "tiread", CmdTiread,0, "read a TI-type 134 kHz tag",\r
1962 "tibits", CmdTibits,0, "get raw bits for TI-type LF tag",\r
1963 "tidemod", CmdTidemod,0, "demod raw bits for TI-type LF tag",\r
1964 "vchdemod", CmdVchdemod,0, "demod samples for VeriChip",\r
1965 "plot", CmdPlot,1, "show graph window",\r
1966 "hide", CmdHide,1, "hide graph window",\r
1967 "losim", CmdLosim,0, "simulate LF tag",\r
1968 "loread", CmdLoread,0, "read (125/134 kHz) LF ID-only tag",\r
fb25b483 1969 "losamples", CmdLosamples,0, "get raw samples for LF tag",\r
1970 "hisamples", CmdHisamples,0, "get raw samples for HF tag",\r
1971 "hisampless", CmdHisampless,0, "get signed raw samples, HF tag",\r
1972 "hisamplest", CmdHi14readt,0, "get samples HF, for testing",\r
d722c4ce 1973 "higet", CmdHi14read_sim,0, "get samples HF, 'analog'",\r
fb25b483 1974 "bitsamples", CmdBitsamples,0, "get raw samples as bitstring",\r
1975 "hexsamples", CmdHexsamples,0, "dump big buffer as hex bytes",\r
d722c4ce 1976 "hi15read", CmdHi15read,0, "read HF tag (ISO 15693)",\r
fb25b483 1977 "hi15reader", CmdHi15reader,0, "act like an ISO15693 reader", // new command greg\r
d722c4ce 1978 "hi15sim", CmdHi15tag,0, "fake an ISO15693 tag", // new command greg\r
1979 "hi14read", CmdHi14read,0, "read HF tag (ISO 14443)",\r
fb25b483 1980 "sri512read", CmdSri512read,0, "Read contents of a SRI512 tag",\r
1981 "hi14areader", CmdHi14areader,0, "act like an ISO14443 Type A reader", // ## New reader command\r
1982 "hi15demod", CmdHi15demod,1, "demod ISO15693 from tag",\r
1983 "hi14bdemod", CmdHi14bdemod,1, "demod ISO14443 Type B from tag",\r
d722c4ce 1984 "autocorr", CmdAutoCorr,1, "autocorrelation over window",\r
1985 "norm", CmdNorm,1, "normalize max/min to +/-500",\r
1986 "dec", CmdDec,1, "decimate",\r
1987 "hpf", CmdHpf,1, "remove DC offset from trace",\r
fb25b483 1988 "zerocrossings", CmdZerocrossings,1, "count time between zero-crossings",\r
d722c4ce 1989 "ltrim", CmdLtrim,1, "trim from left of trace",\r
1990 "scale", CmdScale,1, "set cursor display scale",\r
fb25b483 1991 "flexdemod", CmdFlexdemod,1, "demod samples for FlexPass",\r
d722c4ce 1992 "save", CmdSave,1, "save trace (from graph window)",\r
1993 "load", CmdLoad,1, "load trace (to graph window",\r
fb25b483 1994 "hisimlisten", CmdHisimlisten,0, "get HF samples as fake tag",\r
d722c4ce 1995 "hi14sim", CmdHi14sim,0, "fake ISO 14443 tag",\r
1996 "hi14asim", CmdHi14asim,0, "fake ISO 14443a tag", // ## Simulate 14443a tag\r
fb25b483 1997 "hi14snoop", CmdHi14snoop,0, "eavesdrop ISO 14443",\r
1998 "hi14asnoop", CmdHi14asnoop,0, "eavesdrop ISO 14443 Type A", // ## New snoop command\r
d722c4ce 1999 "hi14list", CmdHi14list,0, "list ISO 14443 history",\r
fb25b483 2000 "hi14alist", CmdHi14alist,0, "list ISO 14443a history", // ## New list command\r
d722c4ce 2001 "hiddemod", CmdHiddemod,1, "HID Prox Card II (not optimal)",\r
fb25b483 2002 "hidfskdemod", CmdHIDdemodFSK,0, "HID FSK demodulator",\r
d722c4ce 2003 "indalademod", CmdIndalademod,0, "demod samples for Indala",\r
2004 "askdemod", Cmdaskdemod,1, "Attempt to demodulate simple ASK tags",\r
fb25b483 2005 "hidsimtag", CmdHIDsimTAG,0, "HID tag simulator",\r
d722c4ce 2006 "mandemod", Cmdmanchesterdemod,1, "Try a Manchester demodulation on a binary stream",\r
2007 "fpgaoff", CmdFPGAOff,0, "set FPGA off", // ## FPGA Control\r
2008 "lcdreset", CmdLcdReset,0, "Hardware reset LCD",\r
2009 "lcd", CmdLcd,0, "Send command/data to LCD",\r
fb25b483 2010 "setlfdivisor", CmdSetDivisor,0, "Drive LF antenna at 12Mhz/(divisor+1)",\r
d722c4ce 2011 "sweeplf", CmdSweepLF,0, "Sweep through LF freq range and store results in buffer",\r
2012 "reset", CmdReset,0, "Reset the Proxmark3",\r
2013 "quit", CmdQuit,1, "quit program"\r
6658905f 2014};\r
2015\r
fb25b483 2016\r
6658905f 2017//-----------------------------------------------------------------------------\r
2018// Entry point into our code: called whenever the user types a command and\r
2019// then presses Enter, which the full command line that they typed.\r
2020//-----------------------------------------------------------------------------\r
2021void CommandReceived(char *cmd)\r
2022{\r
2023 int i;\r
2024\r
2025 PrintToScrollback("> %s", cmd);\r
2026\r
2027 if(strcmp(cmd, "help")==0) {\r
d722c4ce 2028 if (offline) PrintToScrollback("Operating in OFFLINE mode (no device connected)");\r
6658905f 2029 PrintToScrollback("\r\nAvailable commands:");\r
2030 for(i = 0; i < sizeof(CommandTable) / sizeof(CommandTable[0]); i++) {\r
d722c4ce 2031 if (offline && (CommandTable[i].offline==0)) continue;\r
6658905f 2032 char line[256];\r
2033 memset(line, ' ', sizeof(line));\r
2034 strcpy(line+2, CommandTable[i].name);\r
2035 line[strlen(line)] = ' ';\r
2036 sprintf(line+15, " -- %s", CommandTable[i].docString);\r
2037 PrintToScrollback("%s", line);\r
2038 }\r
2039 PrintToScrollback("");\r
2040 PrintToScrollback("and also: help, cls");\r
2041 return;\r
2042 }\r
2043\r
2044 for(i = 0; i < sizeof(CommandTable) / sizeof(CommandTable[0]); i++) {\r
2045 char *name = CommandTable[i].name;\r
2046 if(memcmp(cmd, name, strlen(name))==0 &&\r
2047 (cmd[strlen(name)] == ' ' || cmd[strlen(name)] == '\0'))\r
2048 {\r
2049 cmd += strlen(name);\r
2050 while(*cmd == ' ') {\r
2051 cmd++;\r
2052 }\r
d722c4ce 2053 if (offline && (CommandTable[i].offline==0)) {\r
2054 PrintToScrollback("Offline mode, cannot use this command.");\r
2055 return;\r
2056 }\r
6658905f 2057 (CommandTable[i].handler)(cmd);\r
2058 return;\r
2059 }\r
2060 }\r
2061 PrintToScrollback(">> bad command '%s'", cmd);\r
2062}\r
2063\r
2064//-----------------------------------------------------------------------------\r
2065// Entry point into our code: called whenever we received a packet over USB\r
2066// that we weren't necessarily expecting, for example a debug print.\r
2067//-----------------------------------------------------------------------------\r
2068void UsbCommandReceived(UsbCommand *c)\r
2069{\r
2070 switch(c->cmd) {\r
2071 case CMD_DEBUG_PRINT_STRING: {\r
2072 char s[100];\r
2073 if(c->ext1 > 70 || c->ext1 < 0) {\r
2074 c->ext1 = 0;\r
2075 }\r
2076 memcpy(s, c->d.asBytes, c->ext1);\r
2077 s[c->ext1] = '\0';\r
2078 PrintToScrollback("#db# %s", s);\r
2079 break;
2080 }\r
2081\r
2082 case CMD_DEBUG_PRINT_INTEGERS:\r
2083 PrintToScrollback("#db# %08x, %08x, %08x\r\n", c->ext1, c->ext2, c->ext3);\r
2084 break;\r
2085\r
2086 case CMD_MEASURED_ANTENNA_TUNING: {\r
2087 int zLf, zHf;\r
2088 int vLf125, vLf134, vHf;\r
2089 vLf125 = c->ext1 & 0xffff;\r
2090 vLf134 = c->ext1 >> 16;\r
2091 vHf = c->ext2;\r
2092 zLf = c->ext3 & 0xffff;\r
2093 zHf = c->ext3 >> 16;\r
2094 PrintToScrollback("# LF antenna @ %3d mA / %5d mV [%d ohms] 125Khz",\r
2095 vLf125/zLf, vLf125, zLf);\r
2096 PrintToScrollback("# LF antenna @ %3d mA / %5d mV [%d ohms] 134Khz",\r
2097 vLf134/((zLf*125)/134), vLf134, (zLf*125)/134);\r
2098 PrintToScrollback("# HF antenna @ %3d mA / %5d mV [%d ohms] 13.56Mhz",\r
2099 vHf/zHf, vHf, zHf);\r
2100 break;\r
2101 }\r
2102 default:\r
2103 PrintToScrollback("unrecognized command %08x\n", c->cmd);\r
2104 break;\r
2105 }\r
2106}\r
Impressum, Datenschutz