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