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