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