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