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