]> git.zerfleddert.de Git - proxmark3-svn/blobdiff - winsrc/command.cpp
Added LF frequency adjustments from d18c7db, cleaned up code,
[proxmark3-svn] / winsrc / command.cpp
index 1da1e1c2c7d1f0192e1c6a5cdc67ca144719a4af..f947f45cfd1a470967e9ba5c35255ce0b1db85a9 100644 (file)
@@ -1302,6 +1302,146 @@ static void CmdVchdemod(char *str)
        }\r
 }\r
 \r
        }\r
 }\r
 \r
+static void CmdIndalademod(char *str)\r
+{\r
+       // Usage: recover 64bit UID by default, specify "224" as arg to recover a 224bit UID\r
+\r
+       int state = -1;\r
+       int count = 0;\r
+       int i, j;\r
+       // worst case with GraphTraceLen=64000 is < 4096\r
+       // under normal conditions it's < 2048\r
+       BYTE rawbits[4096];\r
+       int rawbit = 0;\r
+       int worst = 0, worstPos = 0;\r
+       PrintToScrollback("Expecting a bit less than %d raw bits", GraphTraceLen/32);\r
+       for(i = 0; i < GraphTraceLen-1; i += 2) {\r
+               count+=1;\r
+               if((GraphBuffer[i] > GraphBuffer[i + 1]) && (state != 1)) {\r
+                       if (state == 0) {\r
+                               for(j = 0; j <  count - 8; j += 16) {\r
+                                       rawbits[rawbit++] = 0;\r
+                               }\r
+                               if ((abs(count - j)) > worst) {\r
+                                       worst = abs(count - j);\r
+                                       worstPos = i;\r
+                               }\r
+                       }\r
+                       state = 1;\r
+                       count=0;\r
+               } else if((GraphBuffer[i] < GraphBuffer[i + 1]) && (state != 0)) {\r
+                       if (state == 1) {\r
+                               for(j = 0; j <  count - 8; j += 16) {\r
+                                       rawbits[rawbit++] = 1;\r
+                               }\r
+                               if ((abs(count - j)) > worst) {\r
+                                       worst = abs(count - j);\r
+                                       worstPos = i;\r
+                               }\r
+                       }\r
+                       state = 0;\r
+                       count=0;\r
+               }\r
+       }\r
+       PrintToScrollback("Recovered %d raw bits", rawbit);\r
+       PrintToScrollback("worst metric (0=best..7=worst): %d at pos %d", worst, worstPos);\r
+\r
+       // Finding the start of a UID\r
+       int uidlen, long_wait;\r
+       if(strcmp(str, "224") == 0) {\r
+               uidlen=224;\r
+               long_wait=30;\r
+       } else {\r
+               uidlen=64;\r
+               long_wait=29;\r
+       }\r
+       int start;\r
+       int first = 0;\r
+       for(start = 0; start <= rawbit - uidlen; start++) {\r
+               first = rawbits[start];\r
+               for(i = start; i < start + long_wait; i++) {\r
+                       if(rawbits[i] != first) {\r
+                               break;\r
+                       }\r
+               }\r
+               if(i == (start + long_wait)) {\r
+                       break;\r
+               }\r
+       }\r
+       if(start == rawbit - uidlen + 1) {\r
+               PrintToScrollback("nothing to wait for");\r
+               return;\r
+       }\r
+\r
+       // Inverting signal if needed\r
+       if(first == 1) {\r
+               for(i = start; i < rawbit; i++) {\r
+                       rawbits[i] = !rawbits[i];\r
+               }\r
+       }\r
+\r
+       // Dumping UID\r
+       BYTE bits[224];\r
+       char showbits[225];\r
+       showbits[uidlen]='\0';\r
+       int bit;\r
+       i = start;\r
+       int times = 0;\r
+       if(uidlen > rawbit) {\r
+               PrintToScrollback("Warning: not enough raw bits to get a full UID");\r
+               for(bit = 0; bit < rawbit; bit++) {\r
+                       bits[bit] = rawbits[i++];\r
+                       // As we cannot know the parity, let's use "." and "/"\r
+                       showbits[bit] = '.' + bits[bit];\r
+               }\r
+               showbits[bit+1]='\0';\r
+               PrintToScrollback("Partial UID=%s", showbits);\r
+               return;\r
+       } else {\r
+               for(bit = 0; bit < uidlen; bit++) {\r
+                       bits[bit] = rawbits[i++];\r
+                       showbits[bit] = '0' + bits[bit];\r
+               }\r
+               times = 1;\r
+       }\r
+       PrintToScrollback("UID=%s", showbits);\r
+\r
+       // Checking UID against next occurences\r
+       for(; i + uidlen <= rawbit;) {\r
+               int failed = 0;\r
+               for(bit = 0; bit < uidlen; bit++) {\r
+                       if(bits[bit] != rawbits[i++]) {\r
+                               failed = 1;\r
+                               break;\r
+                       }\r
+               }\r
+               if (failed == 1) {\r
+                       break;\r
+               }\r
+               times += 1;\r
+       }\r
+       PrintToScrollback("Occurences: %d (expected %d)", times, (rawbit - start) / uidlen);\r
+\r
+       // Remodulating for tag cloning\r
+       GraphTraceLen = 32*uidlen;\r
+       i = 0;\r
+       int phase = 0;\r
+       for(bit = 0; bit < uidlen; bit++) {\r
+               if(bits[bit] == 0) {\r
+                       phase = 0;\r
+               } else {\r
+                       phase = 1;\r
+               }\r
+               int j;\r
+               for(j = 0; j < 32; j++) {\r
+                       GraphBuffer[i++] = phase;\r
+                       phase = !phase;\r
+               }\r
+       }\r
+\r
+       RepaintGraphWindow();\r
+}\r
+\r
 static void CmdFlexdemod(char *str)\r
 {\r
        int i;\r
 static void CmdFlexdemod(char *str)\r
 {\r
        int i;\r
@@ -1458,26 +1598,31 @@ static void Cmdaskdemod(char *str) {
  * routine, feel free to improve...
  *
  * 1st argument: clock rate (as number of samples per clock rate)
  * routine, feel free to improve...
  *
  * 1st argument: clock rate (as number of samples per clock rate)
+ *               Typical values can be 64, 32, 128...
  */
 static void Cmdmanchesterdemod(char *str) {
        int i;
        int clock;
  */
 static void Cmdmanchesterdemod(char *str) {
        int i;
        int clock;
-       int grouping=16;
        int lastval;
        int lc = 0;
        int bitidx = 0;
        int lastval;
        int lc = 0;
        int bitidx = 0;
-       int bitidx2;
+       int bit2idx = 0;
 
 
        sscanf(str, "%i", &clock);
 
        int tolerance = clock/4;
 
 
        sscanf(str, "%i", &clock);
 
        int tolerance = clock/4;
-       /* Holds the decoded bitstream. */
-       int BitStream[MAX_GRAPH_TRACE_LEN*2];
-       int BitStream2[MAX_GRAPH_TRACE_LEN];
+       /* Holds the decoded bitstream: each clock period contains 2 bits       */
+       /* later simplified to 1 bit after manchester decoding.                 */
+       /* Add 10 bits to allow for noisy / uncertain traces without aborting   */
+       /* int BitStream[GraphTraceLen*2/clock+10]; */
+
+       /* But it does not work if compiling on WIndows: therefore we just allocate a */
+       /* large array */
+       int BitStream[MAX_GRAPH_TRACE_LEN];
 
        /* Detect first transition */
 
        /* Detect first transition */
-       /* Lo-Hi (arbitrary) */
+       /* Lo-Hi (arbitrary)       */
        for(i=1;i<GraphTraceLen;i++) {
                if (GraphBuffer[i-1]<GraphBuffer[i]) {
                lastval = i;
        for(i=1;i<GraphTraceLen;i++) {
                if (GraphBuffer[i-1]<GraphBuffer[i]) {
                lastval = i;
@@ -1487,18 +1632,24 @@ static void Cmdmanchesterdemod(char *str) {
        }
 
        /* Then detect duration between 2 successive transitions */
        }
 
        /* Then detect duration between 2 successive transitions */
-       /* At this stage, GraphTrace is either 0 or 1 */
        for(bitidx = 1 ;i<GraphTraceLen;i++) {
                if (GraphBuffer[i-1] != GraphBuffer[i]) {
                        lc = i-lastval;
                        lastval = i;
        for(bitidx = 1 ;i<GraphTraceLen;i++) {
                if (GraphBuffer[i-1] != GraphBuffer[i]) {
                        lc = i-lastval;
                        lastval = i;
+                       // Error check: if bitidx becomes too large, we do not
+                       // have a Manchester encoded bitstream or the clock is really
+                       // wrong!
+                       if (bitidx > (GraphTraceLen*2/clock+8) ) {
+                               PrintToScrollback("Error: the clock you gave is probably wrong, aborting.");
+                               return;
+                       }
                        // Then switch depending on lc length:
                        // Tolerance is 1/4 of clock rate (arbitrary)
                        // Then switch depending on lc length:
                        // Tolerance is 1/4 of clock rate (arbitrary)
-                       if ((lc-clock/2) < tolerance) {
-                               // Short pulse
+                       if (abs(lc-clock/2) < tolerance) {
+                               // Short pulse : either "1" or "0"
                                BitStream[bitidx++]=GraphBuffer[i-1];
                                BitStream[bitidx++]=GraphBuffer[i-1];
-                       } else if ((lc-clock) < tolerance) {
-                               // Long pulse
+                       } else if (abs(lc-clock) < tolerance) {
+                               // Long pulse: either "11" or "00"
                                BitStream[bitidx++]=GraphBuffer[i-1];
                                BitStream[bitidx++]=GraphBuffer[i-1];
                        } else {
                                BitStream[bitidx++]=GraphBuffer[i-1];
                                BitStream[bitidx++]=GraphBuffer[i-1];
                        } else {
@@ -1510,39 +1661,41 @@ static void Cmdmanchesterdemod(char *str) {
        }
 
        // At this stage, we now have a bitstream of "01" ("1") or "10" ("0"), parse it into final decoded bitstream
        }
 
        // At this stage, we now have a bitstream of "01" ("1") or "10" ("0"), parse it into final decoded bitstream
-       for (bitidx2 = 0; bitidx2<bitidx; bitidx2 += 2) {
-               if ((BitStream[bitidx2] == 0) && (BitStream[bitidx2+1] == 1)) {
-                       BitStream2[bitidx2/2] = 1;
-               } else if ((BitStream[bitidx2] == 1) && (BitStream[bitidx2+1] == 0)) {
-                       BitStream2[bitidx2/2] = 0;
+       // Actually, we overwrite BitStream with the new decoded bitstream, we just need to be careful
+       // to stop output at the final bitidx2 value, not bitidx
+       for (i = 0; i < bitidx; i += 2) {
+               if ((BitStream[i] == 0) && (BitStream[i+1] == 1)) {
+                       BitStream[bit2idx++] = 1;
+               } else if ((BitStream[i] == 1) && (BitStream[i+1] == 0)) {
+                       BitStream[bit2idx++] = 0;
                } else {
                } else {
-                       // We cannot end up in this stage, this means we are unsynchronized,
+                       // We cannot end up in this state, this means we are unsynchronized,
                        // move up 1 bit:
                        // move up 1 bit:
-                       bitidx2++;
+                       i++;
                        PrintToScrollback("Unsynchronized, resync...");
                        PrintToScrollback("(too many of those messages mean the stream is not Manchester encoded)");
                }
        }
        PrintToScrollback("Manchester decoded bitstream \n---------");
        // Now output the bitstream to the scrollback by line of 16 bits
                        PrintToScrollback("Unsynchronized, resync...");
                        PrintToScrollback("(too many of those messages mean the stream is not Manchester encoded)");
                }
        }
        PrintToScrollback("Manchester decoded bitstream \n---------");
        // Now output the bitstream to the scrollback by line of 16 bits
-       for (i = 0; i<bitidx/2; i+=16) {
+       for (i = 0; i < (bit2idx-16); i+=16) {
                PrintToScrollback("%i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i",
                PrintToScrollback("%i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i",
-                       BitStream2[i],
-                       BitStream2[i+1],
-                       BitStream2[i+2],
-                       BitStream2[i+3],
-                       BitStream2[i+4],
-                       BitStream2[i+5],
-                       BitStream2[i+6],
-                       BitStream2[i+7],
-                       BitStream2[i+8],
-                       BitStream2[i+9],
-                       BitStream2[i+10],
-                       BitStream2[i+11],
-                       BitStream2[i+12],
-                       BitStream2[i+13],
-                       BitStream2[i+14],
-                       BitStream2[i+15]);
+                       BitStream[i],
+                       BitStream[i+1],
+                       BitStream[i+2],
+                       BitStream[i+3],
+                       BitStream[i+4],
+                       BitStream[i+5],
+                       BitStream[i+6],
+                       BitStream[i+7],
+                       BitStream[i+8],
+                       BitStream[i+9],
+                       BitStream[i+10],
+                       BitStream[i+11],
+                       BitStream[i+12],
+                       BitStream[i+13],
+                       BitStream[i+14],
+                       BitStream[i+15]);
        }
 }
 
        }
 }
 
@@ -1666,6 +1819,32 @@ static void CmdLcd(char *str)
 static void CmdTest(char *str)\r
 {\r
 }\r
 static void CmdTest(char *str)\r
 {\r
 }\r
+
+/*
+ * Sets the divisor for LF frequency clock: lets the user choose any LF frequency below
+ * 600kHz.
+ */
+static void CmdSetDivisor(char *str)\r
+{\r
+       UsbCommand c;\r
+       c.cmd = CMD_SET_LF_DIVISOR;\r
+       c.ext1 = atoi(str);\r
+       if (( c.ext1<0) || (c.ext1>255)) {\r
+                       PrintToScrollback("divisor must be between 19 and 255");\r
+       } else {\r
+                       SendCommand(&c, FALSE);\r
+                       PrintToScrollback("Divisor set, expected freq=%dHz", 12000000/(c.ext1+1));\r
+       }\r
+}\r
+\r
+static void CmdSweepLF(char *str)\r
+{\r
+       UsbCommand c;\r
+       c.cmd = CMD_SWEEP_LF;\r
+       SendCommand(&c, FALSE);\r
+}\r
+
+
 \r
 typedef void HandlerFunction(char *cmdline);\r
 \r
 \r
 typedef void HandlerFunction(char *cmdline);\r
 \r
@@ -1705,6 +1884,7 @@ static struct {
        "ltrim",                        CmdLtrim,                       "trim from left of trace",\r
        "scale",                        CmdScale,                       "set cursor display scale",\r
        "flexdemod",            CmdFlexdemod,           "demod samples for FlexPass",\r
        "ltrim",                        CmdLtrim,                       "trim from left of trace",\r
        "scale",                        CmdScale,                       "set cursor display scale",\r
        "flexdemod",            CmdFlexdemod,           "demod samples for FlexPass",\r
+       "indalademod",          CmdIndalademod,         "demod samples for Indala",\r
        "save",                         CmdSave,                        "save trace (from graph window)",\r
        "load",                         CmdLoad,                        "load trace (to graph window",\r
        "hisimlisten",          CmdHisimlisten,         "get HF samples as fake tag",\r
        "save",                         CmdSave,                        "save trace (from graph window)",\r
        "load",                         CmdLoad,                        "load trace (to graph window",\r
        "hisimlisten",          CmdHisimlisten,         "get HF samples as fake tag",\r
@@ -1723,6 +1903,8 @@ static struct {
        "lcdreset",                     CmdLcdReset,            "Hardware reset LCD",\r
        "lcd",                          CmdLcd,                         "Send command/data to LCD",\r
        "test",                         CmdTest,                        "Placeholder command for testing new code",\r
        "lcdreset",                     CmdLcdReset,            "Hardware reset LCD",\r
        "lcd",                          CmdLcd,                         "Send command/data to LCD",\r
        "test",                         CmdTest,                        "Placeholder command for testing new code",\r
+       "setlfdivisor",         CmdSetDivisor,          "Drive LF antenna at 12Mhz/(divisor+1)",\r
+       "sweeplf",                      CmdSweepLF,                     "Sweep through LF freq range and store results in buffer",\r
        "quit",                         CmdQuit,                        "quit program"\r
 };\r
 \r
        "quit",                         CmdQuit,                        "quit program"\r
 };\r
 \r
Impressum, Datenschutz