#include "../common/iso14443_crc.c"\r
\r
#define arraylen(x) (sizeof(x)/sizeof((x)[0]))\r
+#define BIT(x) GraphBuffer[x * clock]\r
+#define BITS (GraphTraceLen / clock)\r
\r
+int go = 0;\r
static int CmdHisamplest(char *str, int nrlow);\r
\r
static void GetFromBigBuf(BYTE *dest, int bytes)\r
SendCommand(&c, FALSE);\r
ReceiveCommand(&c);\r
if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) {\r
- PrintToScrollback("bad resp\n");\r
+ PrintToScrollback("bad resp");\r
return;\r
}\r
\r
}\r
}\r
\r
+static void CmdReset(char *str)\r
+{\r
+ UsbCommand c;\r
+ c.cmd = CMD_HARDWARE_RESET;\r
+ SendCommand(&c, FALSE);\r
+}\r
+\r
+static void CmdBuffClear(char *str)\r
+{\r
+ UsbCommand c;\r
+ c.cmd = CMD_BUFF_CLEAR;\r
+ SendCommand(&c, FALSE);\r
+ CmdClearGraph(TRUE);\r
+}\r
+\r
static void CmdQuit(char *str)\r
{\r
exit(0);\r
SendCommand(&c, FALSE);\r
}\r
\r
+\r
+/* New command to read the contents of a SRI512 tag\r
+ * SRI512 tags are ISO14443-B modulated memory tags,\r
+ * this command just dumps the contents of the memory/\r
+ */\r
+static void CmdSri512read(char *str)\r
+{\r
+ UsbCommand c;\r
+ c.cmd = CMD_READ_SRI512_TAG;\r
+ c.ext1 = atoi(str);\r
+ SendCommand(&c, FALSE);\r
+}\r
+\r
// ## New command\r
static void CmdHi14areader(char *str)\r
{\r
c.cmd = CMD_SIMULATE_TAG_ISO_14443;\r
SendCommand(&c, FALSE);\r
}\r
-
-
\r
static void CmdHi14asim(char *str) // ## simulate iso14443a tag\r
{ // ## greg - added ability to specify tag UID\r
SendCommand(&c, FALSE);\r
}\r
\r
+/* clear out our graph window */\r
+int CmdClearGraph(int redraw)\r
+{\r
+ int gtl = GraphTraceLen;\r
+ GraphTraceLen = 0;\r
+\r
+ if (redraw)\r
+ RepaintGraphWindow();\r
+\r
+ return gtl;\r
+}\r
+\r
+/* write a bit to the graph */\r
+static void CmdAppendGraph(int redraw, int clock, int bit)\r
+{\r
+ int i;\r
+\r
+ for (i = 0; i < (int)(clock/2); i++)\r
+ GraphBuffer[GraphTraceLen++] = bit ^ 1;\r
+\r
+ for (i = (int)(clock/2); i < clock; i++)\r
+ GraphBuffer[GraphTraceLen++] = bit;\r
+\r
+ if (redraw)\r
+ RepaintGraphWindow();\r
+}\r
+\r
+/* Function is equivalent of loread + losamples + em410xread\r
+ * looped until an EM410x tag is detected */\r
+static void CmdEM410xwatch(char *str)\r
+{\r
+ char *zero = "";\r
+ char *twok = "2000";\r
+ go = 1;\r
+\r
+ do\r
+ {\r
+ CmdLoread(zero);\r
+ CmdLosamples(twok);\r
+ CmdEM410xread(zero);\r
+ } while (go);\r
+}\r
+\r
+/* Read the transmitted data of an EM4x50 tag\r
+ * Format:\r
+ *\r
+ * XXXXXXXX [row parity bit (even)] <- 8 bits plus parity\r
+ * XXXXXXXX [row parity bit (even)] <- 8 bits plus parity\r
+ * XXXXXXXX [row parity bit (even)] <- 8 bits plus parity\r
+ * XXXXXXXX [row parity bit (even)] <- 8 bits plus parity\r
+ * CCCCCCCC <- column parity bits\r
+ * 0 <- stop bit\r
+ * LW <- Listen Window\r
+ *\r
+ * This pattern repeats for every block of data being transmitted.\r
+ * Transmission starts with two Listen Windows (LW - a modulated\r
+ * pattern of 320 cycles each (32/32/128/64/64)).\r
+ *\r
+ * Note that this data may or may not be the UID. It is whatever data\r
+ * is stored in the blocks defined in the control word First and Last \r
+ * Word Read values. UID is stored in block 32.\r
+ */ \r
+static void CmdEM4x50read(char *str)\r
+{\r
+ int i, j, startblock, clock, skip, block, start, end, low, high;\r
+ BOOL complete= FALSE;\r
+ int tmpbuff[MAX_GRAPH_TRACE_LEN / 64];\r
+ char tmp[6];\r
+\r
+ high= low= 0;\r
+ clock= 64;\r
+\r
+ /* first get high and low values */\r
+ for (i = 0; i < GraphTraceLen; i++)\r
+ {\r
+ if (GraphBuffer[i] > high) \r
+ high = GraphBuffer[i];\r
+ else if (GraphBuffer[i] < low)\r
+ low = GraphBuffer[i];\r
+ }\r
+\r
+ /* populate a buffer with pulse lengths */\r
+ i= 0;\r
+ j= 0;\r
+ while(i < GraphTraceLen)\r
+ {\r
+ // measure from low to low\r
+ while(GraphBuffer[i] > low)\r
+ ++i;\r
+ start= i;\r
+ while(GraphBuffer[i] < high)\r
+ ++i;\r
+ while(GraphBuffer[i] > low)\r
+ ++i;\r
+ tmpbuff[j++]= i - start;\r
+ }\r
+\r
+ \r
+ /* look for data start - should be 2 pairs of LW (pulses of 192,128) */\r
+ start= -1;\r
+ skip= 0;\r
+ for (i= 0; i < j - 4 ; ++i)\r
+ {\r
+ skip += tmpbuff[i];\r
+ if (tmpbuff[i] >= 190 && tmpbuff[i] <= 194)\r
+ if (tmpbuff[i+1] >= 126 && tmpbuff[i+1] <= 130)\r
+ if (tmpbuff[i+2] >= 190 && tmpbuff[i+2] <= 194)\r
+ if (tmpbuff[i+3] >= 126 && tmpbuff[i+3] <= 130)\r
+ {\r
+ start= i + 3;\r
+ break;\r
+ }\r
+ }\r
+ startblock= i + 3;\r
+\r
+ /* skip over the remainder of the LW */\r
+ skip += tmpbuff[i+1]+tmpbuff[i+2];\r
+ while(GraphBuffer[skip] > low)\r
+ ++skip;\r
+ skip += 8;\r
+\r
+ /* now do it again to find the end */\r
+ end= start;\r
+ for (i += 3; i < j - 4 ; ++i)\r
+ {\r
+ end += tmpbuff[i];\r
+ if (tmpbuff[i] >= 190 && tmpbuff[i] <= 194)\r
+ if (tmpbuff[i+1] >= 126 && tmpbuff[i+1] <= 130)\r
+ if (tmpbuff[i+2] >= 190 && tmpbuff[i+2] <= 194)\r
+ if (tmpbuff[i+3] >= 126 && tmpbuff[i+3] <= 130)\r
+ {\r
+ complete= TRUE;\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (start >= 0)\r
+ PrintToScrollback("Found data at sample: %i",skip);\r
+ else\r
+ {\r
+ PrintToScrollback("No data found!");\r
+ PrintToScrollback("Try again with more samples.");\r
+ return;\r
+ }\r
+\r
+ if (!complete)\r
+ {\r
+ PrintToScrollback("*** Warning!");\r
+ PrintToScrollback("Partial data - no end found!");\r
+ PrintToScrollback("Try again with more samples.");\r
+ }\r
+\r
+ /* get rid of leading crap */\r
+ sprintf(tmp,"%i",skip);\r
+ CmdLtrim(tmp);\r
+\r
+ /* now work through remaining buffer printing out data blocks */\r
+ block= 0;\r
+ i= startblock;\r
+ while(block < 6)\r
+ {\r
+ PrintToScrollback("Block %i:", block);\r
+ // mandemod routine needs to be split so we can call it for data\r
+ // just print for now for debugging\r
+ Cmdmanchesterdemod("i 64");\r
+ skip= 0;\r
+ /* look for LW before start of next block */\r
+ for ( ; i < j - 4 ; ++i)\r
+ {\r
+ skip += tmpbuff[i];\r
+ if (tmpbuff[i] >= 190 && tmpbuff[i] <= 194)\r
+ if (tmpbuff[i+1] >= 126 && tmpbuff[i+1] <= 130)\r
+ break;\r
+ }\r
+ while(GraphBuffer[skip] > low)\r
+ ++skip;\r
+ skip += 8;\r
+ sprintf(tmp,"%i",skip);\r
+ CmdLtrim(tmp);\r
+ start += skip;\r
+ block++;\r
+ }\r
+}\r
+\r
+\r
+/* Read the ID of an EM410x tag.\r
+ * Format:\r
+ * 1111 1111 1 <-- standard non-repeatable header\r
+ * XXXX [row parity bit] <-- 10 rows of 5 bits for our 40 bit tag ID\r
+ * ....\r
+ * CCCC <-- each bit here is parity for the 10 bits above in corresponding column\r
+ * 0 <-- stop bit, end of tag\r
+ */\r
+static void CmdEM410xread(char *str)\r
+{\r
+ int i, j, clock, header, rows, bit, hithigh, hitlow, first, bit2idx, high, low;\r
+ int parity[4];\r
+ char id[11];\r
+ int retested = 0;\r
+ int BitStream[MAX_GRAPH_TRACE_LEN];\r
+ high = low = 0;\r
+\r
+ /* Detect high and lows and clock */\r
+ for (i = 0; i < GraphTraceLen; i++)\r
+ {\r
+ if (GraphBuffer[i] > high)\r
+ high = GraphBuffer[i];\r
+ else if (GraphBuffer[i] < low)\r
+ low = GraphBuffer[i];\r
+ }\r
+\r
+ /* get clock */\r
+ clock = GetClock(str, high);\r
+\r
+ /* parity for our 4 columns */\r
+ parity[0] = parity[1] = parity[2] = parity[3] = 0;\r
+ header = rows = 0;\r
+\r
+ /* manchester demodulate */\r
+ bit = bit2idx = 0;\r
+ for (i = 0; i < (int)(GraphTraceLen / clock); i++)\r
+ {\r
+ hithigh = 0;\r
+ hitlow = 0;\r
+ first = 1;\r
+\r
+ /* Find out if we hit both high and low peaks */\r
+ for (j = 0; j < clock; j++)\r
+ {\r
+ if (GraphBuffer[(i * clock) + j] == high)\r
+ hithigh = 1;\r
+ else if (GraphBuffer[(i * clock) + j] == low)\r
+ hitlow = 1;\r
+\r
+ /* it doesn't count if it's the first part of our read\r
+ because it's really just trailing from the last sequence */\r
+ if (first && (hithigh || hitlow))\r
+ hithigh = hitlow = 0;\r
+ else\r
+ first = 0;\r
+\r
+ if (hithigh && hitlow)\r
+ break;\r
+ }\r
+ \r
+ /* If we didn't hit both high and low peaks, we had a bit transition */\r
+ if (!hithigh || !hitlow)\r
+ bit ^= 1;\r
+ \r
+ BitStream[bit2idx++] = bit;\r
+ }\r
+ \r
+retest:\r
+ /* We go till 5 before the graph ends because we'll get that far below */\r
+ for (i = 1; i < bit2idx - 5; i++)\r
+ {\r
+ /* Step 2: We have our header but need our tag ID */\r
+ if (header == 9 && rows < 10)\r
+ {\r
+ /* Confirm parity is correct */\r
+ if ((BitStream[i] ^ BitStream[i+1] ^ BitStream[i+2] ^ BitStream[i+3]) == BitStream[i+4])\r
+ {\r
+ /* Read another byte! */\r
+ sprintf(id+rows, "%x", (8 * BitStream[i]) + (4 * BitStream[i+1]) + (2 * BitStream[i+2]) + (1 * BitStream[i+3]));\r
+ rows++;\r
+\r
+ /* Keep parity info */\r
+ parity[0] ^= BitStream[i];\r
+ parity[1] ^= BitStream[i+1];\r
+ parity[2] ^= BitStream[i+2];\r
+ parity[3] ^= BitStream[i+3];\r
+\r
+ /* Move 4 bits ahead */\r
+ i += 4;\r
+ }\r
+\r
+ /* Damn, something wrong! reset */\r
+ else\r
+ {\r
+ PrintToScrollback("Thought we had a valid tag but failed at word %d (i=%d)", rows + 1, i);\r
+\r
+ /* Start back rows * 5 + 9 header bits, -1 to not start at same place */\r
+ i -= 9 + (5 * rows) - 5;\r
+\r
+ rows = header = 0;\r
+ }\r
+ }\r
+\r
+ /* Step 3: Got our 40 bits! confirm column parity */\r
+ else if (rows == 10)\r
+ {\r
+ /* We need to make sure our 4 bits of parity are correct and we have a stop bit */\r
+ if (BitStream[i] == parity[0] && BitStream[i+1] == parity[1] &&\r
+ BitStream[i+2] == parity[2] && BitStream[i+3] == parity[3] &&\r
+ BitStream[i+4] == 0)\r
+ {\r
+ /* Sweet! */\r
+ PrintToScrollback("EM410x Tag ID: %s", id);\r
+\r
+ /* Stop any loops */\r
+ go = 0;\r
+ return;\r
+ }\r
+\r
+ /* Crap! Incorrect parity or no stop bit, start all over */\r
+ else\r
+ {\r
+ rows = header = 0;\r
+\r
+ /* Go back 59 bits (9 header bits + 10 rows at 4+1 parity) */\r
+ i -= 59;\r
+ }\r
+ }\r
+\r
+ /* Step 1: get our header */\r
+ else if (header < 9)\r
+ {\r
+ /* Need 9 consecutive 1's */\r
+ if (BitStream[i] == 1)\r
+ header++;\r
+\r
+ /* We don't have a header, not enough consecutive 1 bits */\r
+ else\r
+ header = 0;\r
+ }\r
+ }\r
+ \r
+ /* if we've already retested after flipping bits, return */\r
+ if (retested++)\r
+ return;\r
+\r
+ /* if this didn't work, try flipping bits */\r
+ for (i = 0; i < bit2idx; i++)\r
+ BitStream[i] ^= 1;\r
+\r
+ goto retest;\r
+}\r
+\r
+/* emulate an EM410X tag\r
+ * Format:\r
+ * 1111 1111 1 <-- standard non-repeatable header\r
+ * XXXX [row parity bit] <-- 10 rows of 5 bits for our 40 bit tag ID\r
+ * ....\r
+ * CCCC <-- each bit here is parity for the 10 bits above in corresponding column\r
+ * 0 <-- stop bit, end of tag\r
+ */\r
+static void CmdEM410xsim(char *str)\r
+{\r
+ int i, n, j, h, binary[4], parity[4];\r
+ char *s = "0";\r
+\r
+ /* clock is 64 in EM410x tags */\r
+ int clock = 64;\r
+\r
+ /* clear our graph */\r
+ CmdClearGraph(0);\r
+\r
+ /* write it out a few times */\r
+ for (h = 0; h < 4; h++)\r
+ {\r
+ /* write 9 start bits */\r
+ for (i = 0; i < 9; i++)\r
+ CmdAppendGraph(0, clock, 1);\r
+\r
+ /* for each hex char */\r
+ parity[0] = parity[1] = parity[2] = parity[3] = 0;\r
+ for (i = 0; i < 10; i++)\r
+ {\r
+ /* read each hex char */\r
+ sscanf(&str[i], "%1x", &n);\r
+ for (j = 3; j >= 0; j--, n/= 2)\r
+ binary[j] = n % 2;\r
+\r
+ /* append each bit */\r
+ CmdAppendGraph(0, clock, binary[0]);\r
+ CmdAppendGraph(0, clock, binary[1]);\r
+ CmdAppendGraph(0, clock, binary[2]);\r
+ CmdAppendGraph(0, clock, binary[3]);\r
+\r
+ /* append parity bit */\r
+ CmdAppendGraph(0, clock, binary[0] ^ binary[1] ^ binary[2] ^ binary[3]);\r
+\r
+ /* keep track of column parity */\r
+ parity[0] ^= binary[0];\r
+ parity[1] ^= binary[1];\r
+ parity[2] ^= binary[2];\r
+ parity[3] ^= binary[3];\r
+ }\r
+\r
+ /* parity columns */\r
+ CmdAppendGraph(0, clock, parity[0]);\r
+ CmdAppendGraph(0, clock, parity[1]);\r
+ CmdAppendGraph(0, clock, parity[2]);\r
+ CmdAppendGraph(0, clock, parity[3]);\r
+\r
+ /* stop bit */\r
+ CmdAppendGraph(0, clock, 0);\r
+ }\r
+\r
+ /* modulate that biatch */\r
+ Cmdmanchestermod(s);\r
+\r
+ /* booyah! */\r
+ RepaintGraphWindow();\r
+\r
+ CmdLosim(s);\r
+}\r
+\r
+static void ChkBitstream(char *str)\r
+{\r
+ int i;\r
+\r
+ /* convert to bitstream if necessary */\r
+ for (i = 0; i < (int)(GraphTraceLen / 2); i++)\r
+ {\r
+ if (GraphBuffer[i] > 1 || GraphBuffer[i] < 0)\r
+ {\r
+ Cmdbitstream(str);\r
+ break;\r
+ }\r
+ }\r
+}\r
+\r
static void CmdLosim(char *str)\r
{\r
int i;\r
\r
- for(i = 0; i < GraphTraceLen; i += 48) {\r
+ /* convert to bitstream if necessary */\r
+ ChkBitstream(str);\r
+\r
+ for (i = 0; i < GraphTraceLen; i += 48) {\r
UsbCommand c;\r
int j;\r
for(j = 0; j < 48; j++) {\r
SendCommand(&c, FALSE);\r
}\r
\r
+static void CmdDetectReader(char *str)\r
+{\r
+ UsbCommand c;\r
+ // 'l' means LF - 125/134 kHz\r
+ if(*str == 'l') {\r
+ c.ext1 = 1;\r
+ } else if (*str == 'h') {\r
+ c.ext1 = 2;\r
+ } else if (*str != '\0') {\r
+ PrintToScrollback("use 'detectreader' or 'detectreader l' or 'detectreader h'");\r
+ return;\r
+ }\r
+ c.cmd = CMD_LISTEN_READER_FIELD;\r
+ SendCommand(&c, FALSE);\r
+}\r
+\r
+/* send a command before reading */\r
+static void CmdLoCommandRead(char *str)\r
+{\r
+ static char dummy[3];\r
+\r
+ dummy[0]= ' ';\r
+ \r
+ UsbCommand c;\r
+ c.cmd = CMD_MOD_THEN_ACQUIRE_RAW_ADC_SAMPLES_125K;\r
+ sscanf(str, "%i %i %i %s %s", &c.ext1, &c.ext2, &c.ext3, &c.d.asBytes,&dummy+1);\r
+ // in case they specified 'h'\r
+ strcpy((char *)&c.d.asBytes + strlen((char *)c.d.asBytes), dummy);\r
+ SendCommand(&c, FALSE);\r
+}\r
+\r
static void CmdLosamples(char *str)\r
{\r
int cnt = 0;\r
SendCommand(&c, FALSE);\r
ReceiveCommand(&c);\r
if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) {\r
- PrintToScrollback("bad resp\n");\r
+ if (!go)\r
+ PrintToScrollback("bad resp");\r
return;\r
}\r
int j;\r
SendCommand(&c, FALSE);\r
ReceiveCommand(&c);\r
if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) {\r
- PrintToScrollback("bad resp\n");\r
+ PrintToScrollback("bad resp");\r
return;\r
}\r
int j, k;\r
SendCommand(&c, FALSE);\r
ReceiveCommand(&c);\r
if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) {\r
- PrintToScrollback("bad resp\n");\r
+ PrintToScrollback("bad resp");\r
return;\r
}\r
int j;\r
SendCommand(&c, FALSE);\r
ReceiveCommand(&c);\r
if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) {\r
- PrintToScrollback("bad resp\n");\r
+ PrintToScrollback("bad resp");\r
return 0;\r
}\r
int j;\r
SendCommand(&c, FALSE);\r
ReceiveCommand(&c);\r
if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) {\r
- PrintToScrollback("bad resp\n");\r
+ PrintToScrollback("bad resp");\r
return;\r
}\r
int j;\r
SendCommand(&c, FALSE);\r
ReceiveCommand(&c);\r
if(c.cmd != CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K) {\r
- PrintToScrollback("bad resp\n");\r
+ PrintToScrollback("bad resp");\r
return;\r
}\r
int j;\r
{\r
// The sampling rate is 106.353 ksps/s, for T = 18.8 us\r
\r
- // SOF defined as \r
+ // SOF defined as\r
// 1) Unmodulated time of 56.64us\r
// 2) 24 pulses of 423.75khz\r
// 3) logic '1' (unmodulated for 18.88us followed by 8 pulses of 423.75khz)\r
1, 1, 1, 1\r
};\r
\r
- // EOF defined as \r
+ // EOF defined as\r
// 1) logic '0' (8 pulses of 423.75khz followed by unmodulated for 18.88us)\r
// 2) 24 pulses of 423.75khz\r
// 3) Unmodulated time of 56.64us\r
SendCommand(&c, FALSE);\r
ReceiveCommand(&c);\r
if(c.cmd != CMD_DOWNLOADED_RAW_BITS_TI_TYPE) {\r
- PrintToScrollback("bad resp\n");\r
+ PrintToScrollback("bad resp");\r
return;\r
}\r
int j;\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
\r
RepaintGraphWindow();\r
}\r
-
-/*
- * Generic command to demodulate ASK. bit length in argument.
- * Giving the bit length helps discriminate ripple effects
- * upon zero crossing for noisy traces.
- *
- * Second is convention: positive or negative (High mod means zero
- * or high mod means one)
- *
- * Updates the Graph trace with 0/1 values
- *
- * Arguments:
- * sl : bit length in terms of number of samples per bit
- * (use yellow/purple markers to compute).
- * c : 0 or 1
- */
-
-static void Cmdaskdemod(char *str) {
- int i;
- int sign = 1;
- int n = 0;
- int c = 0;\r
- int t1 = 0;
-
- // TODO: complain if we do not give 2 arguments here !
- sscanf(str, "%i %i", &n, &c);
- if (c == 0) {
- c = 1 ;
- } else {
- c = -1;
- }
-
- if (GraphBuffer[0]*c > 0) {
- GraphBuffer[0] = 1;
- } else {
- GraphBuffer[0] = 0;
- }
- for(i=1;i<GraphTraceLen;i++) {
- /* Analyse signal within the symbol length */
- /* Decide if we crossed a zero */
- if (GraphBuffer[i]*sign < 0) {
- /* Crossed a zero, check if this is a ripple or not */
- if ( (i-t1) > n/4 ) {
- sign = -sign;
- t1=i;
- if (GraphBuffer[i]*c > 0){
- GraphBuffer[i]=1;
- } else {
- GraphBuffer[i]=0;
- }
- } else {
- /* This is a ripple, set the current sample value
- to the same as previous */
- GraphBuffer[i] = GraphBuffer[i-1];
- }
- } else {
- GraphBuffer[i] = GraphBuffer[i-1];
- }
- }
- RepaintGraphWindow();
-}
-
-
-/*
- * Manchester demodulate a bitstream. The bitstream needs to be already in
- * the GraphBuffer as 0 and 1 values
- *
- * Give the clock rate as argument in order to help the sync - the algorithm
- * resyncs at each pulse anyway.
- *
- * Not optimized by any means, this is the 1st time I'm writing this type of
- * routine, feel free to improve...
- *
- * 1st argument: clock rate (as number of samples per clock rate)
- */
-static void Cmdmanchesterdemod(char *str) {
- int i;
- int clock;
- int grouping=16;
- int lastval;
- int lc = 0;
- int bitidx = 0;
- int bitidx2;
-
-
- 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];
-
- /* Detect first transition */
- /* Lo-Hi (arbitrary) */
- for(i=1;i<GraphTraceLen;i++) {
- if (GraphBuffer[i-1]<GraphBuffer[i]) {
- lastval = i;
- BitStream[0]=0; // Previous state = 0;
- break;
- }
- }
-
- /* 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;
- // Then switch depending on lc length:
- // Tolerance is 1/4 of clock rate (arbitrary)
- if ((lc-clock/2) < tolerance) {
- // Short pulse
- BitStream[bitidx++]=GraphBuffer[i-1];
- } else if ((lc-clock) < tolerance) {
- // Long pulse
- BitStream[bitidx++]=GraphBuffer[i-1];
- BitStream[bitidx++]=GraphBuffer[i-1];
- } else {
- // Error
- PrintToScrollback("Warning: Manchester decode error for pulse width detection.");
- PrintToScrollback("(too many of those messages mean either the stream is not Manchester encoded, or clock is wrong)");
- }
- }
- }
-
- // 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;
- } else {
- // We cannot end up in this stage, this means we are unsynchronized,
- // move up 1 bit:
- bitidx2++;
- 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) {
- 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]);
- }
-}
-
-
-
-/*
- * Usage ???
+\r
+/*\r
+ * Generic command to demodulate ASK.\r
+ *\r
+ * Argument is convention: positive or negative (High mod means zero\r
+ * or high mod means one)\r
+ *\r
+ * Updates the Graph trace with 0/1 values\r
+ *\r
+ * Arguments:\r
+ * c : 0 or 1\r
+ */\r
+\r
+static void Cmdaskdemod(char *str) {\r
+ int i;\r
+ int c, high = 0, low = 0;\r
+\r
+ // TODO: complain if we do not give 2 arguments here !\r
+ sscanf(str, "%i", &c);\r
+\r
+ /* Detect high and lows and clock */\r
+ for (i = 0; i < GraphTraceLen; i++)\r
+ {\r
+ if (GraphBuffer[i] > high)\r
+ high = GraphBuffer[i];\r
+ else if (GraphBuffer[i] < low)\r
+ low = GraphBuffer[i];\r
+ }\r
+\r
+ if (GraphBuffer[0] > 0) {\r
+ GraphBuffer[0] = 1-c;\r
+ } else {\r
+ GraphBuffer[0] = c;\r
+ }\r
+ for(i=1;i<GraphTraceLen;i++) {\r
+ /* Transitions are detected at each peak\r
+ * Transitions are either:\r
+ * - we're low: transition if we hit a high\r
+ * - we're high: transition if we hit a low\r
+ * (we need to do it this way because some tags keep high or\r
+ * low for long periods, others just reach the peak and go\r
+ * down)\r
+ */\r
+ if ((GraphBuffer[i]==high) && (GraphBuffer[i-1] == c)) {\r
+ GraphBuffer[i]=1-c;\r
+ } else if ((GraphBuffer[i]==low) && (GraphBuffer[i-1] == (1-c))){\r
+ GraphBuffer[i] = c;\r
+ } else {\r
+ /* No transition */\r
+ GraphBuffer[i] = GraphBuffer[i-1];\r
+ }\r
+ }\r
+ RepaintGraphWindow();\r
+}\r
+\r
+/* Print our clock rate */\r
+static void Cmddetectclockrate(char *str)\r
+{\r
+ int clock = detectclock(0);\r
+ PrintToScrollback("Auto-detected clock rate: %d", clock);\r
+}\r
+\r
+/*\r
+ * Detect clock rate\r
+ */\r
+int detectclock(int peak)\r
+{\r
+ int i;\r
+ int clock = 0xFFFF;\r
+ int lastpeak = 0;\r
+\r
+ /* Detect peak if we don't have one */\r
+ if (!peak)\r
+ for (i = 0; i < GraphTraceLen; i++)\r
+ if (GraphBuffer[i] > peak)\r
+ peak = GraphBuffer[i];\r
+\r
+ for (i = 1; i < GraphTraceLen; i++)\r
+ {\r
+ /* If this is the beginning of a peak */\r
+ if (GraphBuffer[i-1] != GraphBuffer[i] && GraphBuffer[i] == peak)\r
+ {\r
+ /* Find lowest difference between peaks */\r
+ if (lastpeak && i - lastpeak < clock)\r
+ {\r
+ clock = i - lastpeak;\r
+ }\r
+ lastpeak = i;\r
+ }\r
+ }\r
+\r
+ return clock;\r
+}\r
+\r
+/* Get or auto-detect clock rate */\r
+int GetClock(char *str, int peak)\r
+{\r
+ int clock;\r
+\r
+ sscanf(str, "%i", &clock);\r
+ if (!strcmp(str, ""))\r
+ clock = 0;\r
+\r
+ /* Auto-detect clock */\r
+ if (!clock)\r
+ {\r
+ clock = detectclock(peak);\r
+\r
+ /* Only print this message if we're not looping something */\r
+ if (!go)\r
+ PrintToScrollback("Auto-detected clock rate: %d", clock);\r
+ }\r
+\r
+ return clock;\r
+}\r
+\r
+/*\r
+ * Convert to a bitstream\r
+ */\r
+static void Cmdbitstream(char *str) {\r
+ int i, j;\r
+ int bit;\r
+ int gtl;\r
+ int clock;\r
+ int low = 0;\r
+ int high = 0;\r
+ int hithigh, hitlow, first;\r
+\r
+ /* Detect high and lows and clock */\r
+ for (i = 0; i < GraphTraceLen; i++)\r
+ {\r
+ if (GraphBuffer[i] > high)\r
+ high = GraphBuffer[i];\r
+ else if (GraphBuffer[i] < low)\r
+ low = GraphBuffer[i];\r
+ }\r
+\r
+ /* Get our clock */\r
+ clock = GetClock(str, high);\r
+\r
+ gtl = CmdClearGraph(0);\r
+\r
+ bit = 0;\r
+ for (i = 0; i < (int)(gtl / clock); i++)\r
+ {\r
+ hithigh = 0;\r
+ hitlow = 0;\r
+ first = 1;\r
+\r
+ /* Find out if we hit both high and low peaks */\r
+ for (j = 0; j < clock; j++)\r
+ {\r
+ if (GraphBuffer[(i * clock) + j] == high)\r
+ hithigh = 1;\r
+ else if (GraphBuffer[(i * clock) + j] == low)\r
+ hitlow = 1;\r
+\r
+ /* it doesn't count if it's the first part of our read\r
+ because it's really just trailing from the last sequence */\r
+ if (first && (hithigh || hitlow))\r
+ hithigh = hitlow = 0;\r
+ else\r
+ first = 0;\r
+\r
+ if (hithigh && hitlow)\r
+ break;\r
+ }\r
+\r
+ /* If we didn't hit both high and low peaks, we had a bit transition */\r
+ if (!hithigh || !hitlow)\r
+ bit ^= 1;\r
+\r
+ CmdAppendGraph(0, clock, bit);\r
+// for (j = 0; j < (int)(clock/2); j++)\r
+// GraphBuffer[(i * clock) + j] = bit ^ 1;\r
+// for (j = (int)(clock/2); j < clock; j++)\r
+// GraphBuffer[(i * clock) + j] = bit;\r
+ }\r
+\r
+ RepaintGraphWindow();\r
+}\r
+\r
+/* Modulate our data into manchester */\r
+static void Cmdmanchestermod(char *str)\r
+{\r
+ int i, j;\r
+ int clock;\r
+ int bit, lastbit, wave;\r
+\r
+ /* Get our clock */\r
+ clock = GetClock(str, 0);\r
+\r
+ wave = 0;\r
+ lastbit = 1;\r
+ for (i = 0; i < (int)(GraphTraceLen / clock); i++)\r
+ {\r
+ bit = GraphBuffer[i * clock] ^ 1;\r
+\r
+ for (j = 0; j < (int)(clock/2); j++)\r
+ GraphBuffer[(i * clock) + j] = bit ^ lastbit ^ wave;\r
+ for (j = (int)(clock/2); j < clock; j++)\r
+ GraphBuffer[(i * clock) + j] = bit ^ lastbit ^ wave ^ 1;\r
+\r
+ /* Keep track of how we start our wave and if we changed or not this time */\r
+ wave ^= bit ^ lastbit;\r
+ lastbit = bit;\r
+ }\r
+\r
+ RepaintGraphWindow();\r
+}\r
+\r
+/*\r
+ * Manchester demodulate a bitstream. The bitstream needs to be already in\r
+ * the GraphBuffer as 0 and 1 values\r
+ *\r
+ * Give the clock rate as argument in order to help the sync - the algorithm\r
+ * resyncs at each pulse anyway.\r
+ *\r
+ * Not optimized by any means, this is the 1st time I'm writing this type of\r
+ * routine, feel free to improve...\r
+ *\r
+ * 1st argument: clock rate (as number of samples per clock rate)\r
+ * Typical values can be 64, 32, 128...\r
+ */\r
+static void Cmdmanchesterdemod(char *str) {\r
+ int i, j, invert= 0;\r
+ int bit;\r
+ int clock;\r
+ int lastval;\r
+ int low = 0;\r
+ int high = 0;\r
+ int hithigh, hitlow, first;\r
+ int lc = 0;\r
+ int bitidx = 0;\r
+ int bit2idx = 0;\r
+ int warnings = 0;\r
+\r
+ /* check if we're inverting output */\r
+ if(*str == 'i')\r
+ {\r
+ PrintToScrollback("Inverting output");\r
+ invert= 1;\r
+ do\r
+ ++str;\r
+ while(*str == ' '); // in case a 2nd argument was given\r
+ }\r
+\r
+ /* Holds the decoded bitstream: each clock period contains 2 bits */\r
+ /* later simplified to 1 bit after manchester decoding. */\r
+ /* Add 10 bits to allow for noisy / uncertain traces without aborting */\r
+ /* int BitStream[GraphTraceLen*2/clock+10]; */\r
+\r
+ /* But it does not work if compiling on WIndows: therefore we just allocate a */\r
+ /* large array */\r
+ int BitStream[MAX_GRAPH_TRACE_LEN];\r
+\r
+ /* Detect high and lows */\r
+ for (i = 0; i < GraphTraceLen; i++)\r
+ {\r
+ if (GraphBuffer[i] > high)\r
+ high = GraphBuffer[i];\r
+ else if (GraphBuffer[i] < low)\r
+ low = GraphBuffer[i];\r
+ }\r
+\r
+ /* Get our clock */\r
+ clock = GetClock(str, high);\r
+\r
+ int tolerance = clock/4;\r
+\r
+ /* Detect first transition */\r
+ /* Lo-Hi (arbitrary) */\r
+ for (i = 0; i < GraphTraceLen; i++)\r
+ {\r
+ if (GraphBuffer[i] == low)\r
+ {\r
+ lastval = i;\r
+ break;\r
+ }\r
+ }\r
+\r
+ /* If we're not working with 1/0s, demod based off clock */\r
+ if (high != 1)\r
+ {\r
+ bit = 0; /* We assume the 1st bit is zero, it may not be\r
+ * the case: this routine (I think) has an init problem.\r
+ * Ed.\r
+ */\r
+ for (; i < (int)(GraphTraceLen / clock); i++)\r
+ {\r
+ hithigh = 0;\r
+ hitlow = 0;\r
+ first = 1;\r
+\r
+ /* Find out if we hit both high and low peaks */\r
+ for (j = 0; j < clock; j++)\r
+ {\r
+ if (GraphBuffer[(i * clock) + j] == high)\r
+ hithigh = 1;\r
+ else if (GraphBuffer[(i * clock) + j] == low)\r
+ hitlow = 1;\r
+\r
+ /* it doesn't count if it's the first part of our read\r
+ because it's really just trailing from the last sequence */\r
+ if (first && (hithigh || hitlow))\r
+ hithigh = hitlow = 0;\r
+ else\r
+ first = 0;\r
+\r
+ if (hithigh && hitlow)\r
+ break;\r
+ }\r
+\r
+ /* If we didn't hit both high and low peaks, we had a bit transition */\r
+ if (!hithigh || !hitlow)\r
+ bit ^= 1;\r
+\r
+ BitStream[bit2idx++] = bit ^ invert;\r
+ }\r
+ }\r
+\r
+ /* standard 1/0 bitstream */\r
+ else\r
+ {\r
+\r
+ /* Then detect duration between 2 successive transitions */\r
+ for (bitidx = 1; i < GraphTraceLen; i++)\r
+ {\r
+ if (GraphBuffer[i-1] != GraphBuffer[i])\r
+ {\r
+ lc = i-lastval;\r
+ lastval = i;\r
+\r
+ // Error check: if bitidx becomes too large, we do not\r
+ // have a Manchester encoded bitstream or the clock is really\r
+ // wrong!\r
+ if (bitidx > (GraphTraceLen*2/clock+8) ) {\r
+ PrintToScrollback("Error: the clock you gave is probably wrong, aborting.");\r
+ return;\r
+ }\r
+ // Then switch depending on lc length:\r
+ // Tolerance is 1/4 of clock rate (arbitrary)\r
+ if (abs(lc-clock/2) < tolerance) {\r
+ // Short pulse : either "1" or "0"\r
+ BitStream[bitidx++]=GraphBuffer[i-1];\r
+ } else if (abs(lc-clock) < tolerance) {\r
+ // Long pulse: either "11" or "00"\r
+ BitStream[bitidx++]=GraphBuffer[i-1];\r
+ BitStream[bitidx++]=GraphBuffer[i-1];\r
+ } else {\r
+ // Error\r
+ warnings++;\r
+ PrintToScrollback("Warning: Manchester decode error for pulse width detection.");\r
+ PrintToScrollback("(too many of those messages mean either the stream is not Manchester encoded, or clock is wrong)");\r
+\r
+ if (warnings > 100)\r
+ {\r
+ PrintToScrollback("Error: too many detection errors, aborting.");\r
+ return;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ // At this stage, we now have a bitstream of "01" ("1") or "10" ("0"), parse it into final decoded bitstream\r
+ // Actually, we overwrite BitStream with the new decoded bitstream, we just need to be careful\r
+ // to stop output at the final bitidx2 value, not bitidx\r
+ for (i = 0; i < bitidx; i += 2) {\r
+ if ((BitStream[i] == 0) && (BitStream[i+1] == 1)) {\r
+ BitStream[bit2idx++] = 1 ^ invert;\r
+ } else if ((BitStream[i] == 1) && (BitStream[i+1] == 0)) {\r
+ BitStream[bit2idx++] = 0 ^ invert;\r
+ } else {\r
+ // We cannot end up in this state, this means we are unsynchronized,\r
+ // move up 1 bit:\r
+ i++;\r
+ warnings++;\r
+ PrintToScrollback("Unsynchronized, resync...");\r
+ PrintToScrollback("(too many of those messages mean the stream is not Manchester encoded)");\r
+\r
+ if (warnings > 100)\r
+ {\r
+ PrintToScrollback("Error: too many decode errors, aborting.");\r
+ return;\r
+ }\r
+ }\r
+ } \r
+ }\r
+\r
+ PrintToScrollback("Manchester decoded bitstream");\r
+ // Now output the bitstream to the scrollback by line of 16 bits\r
+ for (i = 0; i < (bit2idx-16); i+=16) {\r
+ PrintToScrollback("%i %i %i %i %i %i %i %i %i %i %i %i %i %i %i %i",\r
+ BitStream[i],\r
+ BitStream[i+1],\r
+ BitStream[i+2],\r
+ BitStream[i+3],\r
+ BitStream[i+4],\r
+ BitStream[i+5],\r
+ BitStream[i+6],\r
+ BitStream[i+7],\r
+ BitStream[i+8],\r
+ BitStream[i+9],\r
+ BitStream[i+10],\r
+ BitStream[i+11],\r
+ BitStream[i+12],\r
+ BitStream[i+13],\r
+ BitStream[i+14],\r
+ BitStream[i+15]);\r
+ }\r
+}\r
+\r
+\r
+\r
+/*\r
+ * Usage ???\r
*/\r
static void CmdHiddemod(char *str)\r
{\r
}\r
}\r
\r
+\r
+\r
static void CmdTest(char *str)\r
{\r
}\r
\r
+/*\r
+ * Sets the divisor for LF frequency clock: lets the user choose any LF frequency below\r
+ * 600kHz.\r
+ */\r
+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
+\r
typedef void HandlerFunction(char *cmdline);\r
\r
+/* in alphabetic order */\r
static struct {\r
- char *name;\r
- HandlerFunction *handler;\r
- char *docString;\r
+ char *name;\r
+ HandlerFunction *handler;\r
+ int offline; // 1 if the command can be used when in offline mode\r
+ char *docString;\r
} CommandTable[] = {\r
- "tune", CmdTune, "measure antenna tuning",\r
- "tiread", CmdTiread, "read a TI-type 134 kHz tag",\r
- "tibits", CmdTibits, "get raw bits for TI-type LF tag",\r
- "tidemod", CmdTidemod, "demod raw bits for TI-type LF tag",\r
- "vchdemod", CmdVchdemod, "demod samples for VeriChip",\r
- "plot", CmdPlot, "show graph window",\r
- "hide", CmdHide, "hide graph window",\r
- "losim", CmdLosim, "simulate LF tag",\r
- "loread", CmdLoread, "read (125/134 kHz) LF ID-only tag",\r
- "losamples", CmdLosamples, "get raw samples for LF tag",\r
- "hisamples", CmdHisamples, "get raw samples for HF tag",\r
- "hisampless", CmdHisampless, "get signed raw samples, HF tag",\r
- "hisamplest", CmdHi14readt, "get samples HF, for testing",\r
- "higet", CmdHi14read_sim, "get samples HF, 'analog'",\r
- "bitsamples", CmdBitsamples, "get raw samples as bitstring",\r
- "hexsamples", CmdHexsamples, "dump big buffer as hex bytes",\r
- "hi15read", CmdHi15read, "read HF tag (ISO 15693)",\r
- "hi15reader", CmdHi15reader, "act like an ISO15693 reader", // new command greg\r
- "hi15sim", CmdHi15tag, "fake an ISO15693 tag", // new command greg\r
- "hi14read", CmdHi14read, "read HF tag (ISO 14443)",\r
- "hi14areader", CmdHi14areader, "act like an ISO14443 Type A reader", // ## New reader command\r
- "hi15demod", CmdHi15demod, "demod ISO15693 from tag",\r
- "hi14bdemod", CmdHi14bdemod, "demod ISO14443 Type B from tag",\r
- "autocorr", CmdAutoCorr, "autocorrelation over window",\r
- "norm", CmdNorm, "normalize max/min to +/-500",\r
- "dec", CmdDec, "decimate",\r
- "hpf", CmdHpf, "remove DC offset from trace",\r
- "zerocrossings", CmdZerocrossings, "count time between zero-crossings",\r
- "ltrim", CmdLtrim, "trim from left of trace",\r
- "scale", CmdScale, "set cursor display scale",\r
- "flexdemod", CmdFlexdemod, "demod samples for FlexPass",\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
- "hi14sim", CmdHi14sim, "fake ISO 14443 tag",\r
- "hi14asim", CmdHi14asim, "fake ISO 14443a tag", // ## Simulate 14443a tag\r
- "hi14snoop", CmdHi14snoop, "eavesdrop ISO 14443",\r
- "hi14asnoop", CmdHi14asnoop, "eavesdrop ISO 14443 Type A", // ## New snoop command\r
- "hi14list", CmdHi14list, "list ISO 14443 history",\r
- "hi14alist", CmdHi14alist, "list ISO 14443a history", // ## New list command\r
- "hiddemod", CmdHiddemod, "HID Prox Card II (not optimal)",\r
- "hidfskdemod", CmdHIDdemodFSK, "HID FSK demodulator",\r
- "askdemod", Cmdaskdemod, "Attempt to demodulate simple ASK tags",
- "hidsimtag", CmdHIDsimTAG, "HID tag simulator",
- "mandemod", Cmdmanchesterdemod, "Try a Manchester demodulation on a binary stream",
- "fpgaoff", CmdFPGAOff, "set FPGA off", // ## FPGA Control\r
- "lcdreset", CmdLcdReset, "Hardware reset LCD",\r
- "lcd", CmdLcd, "Send command/data to LCD",\r
- "test", CmdTest, "Placeholder command for testing new code",\r
- "quit", CmdQuit, "quit program"\r
+ "askdemod", Cmdaskdemod,1, "<samples per bit> <0|1> -- Attempt to demodulate simple ASK tags",\r
+ "autocorr", CmdAutoCorr,1, "<window length> -- Autocorrelation over window",\r
+ "bitsamples", CmdBitsamples,0, " Get raw samples as bitstring",\r
+ "bitstream", Cmdbitstream,1, "[clock rate] -- Convert waveform into a bitstream",\r
+ "buffclear", CmdBuffClear,0, " Clear sample buffer and graph window",\r
+ "dec", CmdDec,1, " Decimate samples",\r
+ "detectclock", Cmddetectclockrate,1, " Detect clock rate",\r
+ "detectreader", CmdDetectReader,0, "['l'|'h'] -- Detect external reader field (option 'l' or 'h' to limit to LF or HF)",\r
+ "em410xsim", CmdEM410xsim,1, "<UID> -- Simulate EM410x tag",\r
+ "em410xread", CmdEM410xread,1, "[clock rate] -- Extract ID from EM410x tag",\r
+ "em410xwatch", CmdEM410xwatch,0, " Watches for EM410x tags",\r
+ "em4x50read", CmdEM4x50read,1, " Extract data from EM4x50 tag",\r
+ "exit", CmdQuit,1, " Exit program",\r
+ "flexdemod", CmdFlexdemod,1, " Demodulate samples for FlexPass",\r
+ "fpgaoff", CmdFPGAOff,0, " Set FPGA off", // ## FPGA Control\r
+ "hexsamples", CmdHexsamples,0, "<blocks> -- Dump big buffer as hex bytes",\r
+ "hi14alist", CmdHi14alist,0, " List ISO 14443a history", // ## New list command\r
+ "hi14areader", CmdHi14areader,0, " Act like an ISO14443 Type A reader", // ## New reader command\r
+ "hi14asim", CmdHi14asim,0, "<UID> -- Fake ISO 14443a tag", // ## Simulate 14443a tag\r
+ "hi14asnoop", CmdHi14asnoop,0, " Eavesdrop ISO 14443 Type A", // ## New snoop command\r
+ "hi14bdemod", CmdHi14bdemod,1, " Demodulate ISO14443 Type B from tag",\r
+ "hi14list", CmdHi14list,0, " List ISO 14443 history",\r
+ "hi14read", CmdHi14read,0, " Read HF tag (ISO 14443)",\r
+ "hi14sim", CmdHi14sim,0, " Fake ISO 14443 tag",\r
+ "hi14snoop", CmdHi14snoop,0, " Eavesdrop ISO 14443",\r
+ "hi15demod", CmdHi15demod,1, " Demodulate ISO15693 from tag",\r
+ "hi15read", CmdHi15read,0, " Read HF tag (ISO 15693)",\r
+ "hi15reader", CmdHi15reader,0, " Act like an ISO15693 reader", // new command greg\r
+ "hi15sim", CmdHi15tag,0, " Fake an ISO15693 tag", // new command greg\r
+ "hiddemod", CmdHiddemod,1, " Demodulate HID Prox Card II (not optimal)",\r
+ "hide", CmdHide,1, " Hide graph window",\r
+ "hidfskdemod", CmdHIDdemodFSK,0, " Realtime HID FSK demodulator",\r
+ "hidsimtag", CmdHIDsimTAG,0, "<ID> -- HID tag simulator",\r
+ "higet", CmdHi14read_sim,0, "<samples> -- Get samples HF, 'analog'",\r
+ "hisamples", CmdHisamples,0, " Get raw samples for HF tag",\r
+ "hisampless", CmdHisampless,0, "<samples> -- Get signed raw samples, HF tag",\r
+ "hisamplest", CmdHi14readt,0, " Get samples HF, for testing",\r
+ "hisimlisten", CmdHisimlisten,0, " Get HF samples as fake tag",\r
+ "hpf", CmdHpf,1, " Remove DC offset from trace",\r
+ "indalademod", CmdIndalademod,0, "['224'] -- Demodulate samples for Indala 64 bit UID (option '224' for 224 bit)",\r
+ "lcd", CmdLcd,0, "<HEX command> <count> -- Send command/data to LCD",\r
+ "lcdreset", CmdLcdReset,0, " Hardware reset LCD",\r
+ "load", CmdLoad,1, "<filename> -- Load trace (to graph window",\r
+ "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
+ "loread", CmdLoread,0, "['h'] -- Read 125/134 kHz LF ID-only tag (option 'h' for 134)",\r
+ "losamples", CmdLosamples,0, "[128 - 16000] -- Get raw samples for LF tag",\r
+ "losim", CmdLosim,0, " Simulate LF tag",\r
+ "ltrim", CmdLtrim,1, "<samples> -- Trim samples from left of trace",\r
+ "mandemod", Cmdmanchesterdemod,1, "[i] [clock rate] -- Manchester demodulate binary stream (option 'i' to invert output)",\r
+ "manmod", Cmdmanchestermod,1, "[clock rate] -- Manchester modulate a binary stream",\r
+ "norm", CmdNorm,1, " Normalize max/min to +/-500",\r
+ "plot", CmdPlot,1, " Show graph window",\r
+ "quit", CmdQuit,1, " Quit program",\r
+ "reset", CmdReset,0, " Reset the Proxmark3",\r
+ "save", CmdSave,1, "<filename> -- Save trace (from graph window)",\r
+ "scale", CmdScale,1, "<int> -- Set cursor display scale",\r
+ "setlfdivisor", CmdSetDivisor,0, "<19 - 255> -- Drive LF antenna at 12Mhz/(divisor+1)",\r
+ "sri512read", CmdSri512read,0, "<int> -- Read contents of a SRI512 tag",\r
+ "sweeplf", CmdSweepLF,0, " Sweep through LF freq range and store results in buffer",\r
+ "tibits", CmdTibits,0, " Get raw bits for TI-type LF tag",\r
+ "tidemod", CmdTidemod,0, " Demodulate raw bits for TI-type LF tag",\r
+ "tiread", CmdTiread,0, " Read a TI-type 134 kHz tag",\r
+ "tune", CmdTune,0, " Measure antenna tuning",\r
+ "vchdemod", CmdVchdemod,0, "['clone'] -- Demodulate samples for VeriChip",\r
+ "zerocrossings", CmdZerocrossings,1, " Count time between zero-crossings",\r
};\r
\r
+\r
//-----------------------------------------------------------------------------\r
// Entry point into our code: called whenever the user types a command and\r
// then presses Enter, which the full command line that they typed.\r
PrintToScrollback("> %s", cmd);\r
\r
if(strcmp(cmd, "help")==0) {\r
+ if (offline) PrintToScrollback("Operating in OFFLINE mode (no device connected)");\r
PrintToScrollback("\r\nAvailable commands:");\r
for(i = 0; i < sizeof(CommandTable) / sizeof(CommandTable[0]); i++) {\r
+ if (offline && (CommandTable[i].offline==0)) continue;\r
char line[256];\r
memset(line, ' ', sizeof(line));\r
strcpy(line+2, CommandTable[i].name);\r
while(*cmd == ' ') {\r
cmd++;\r
}\r
+ if (offline && (CommandTable[i].offline==0)) {\r
+ PrintToScrollback("Offline mode, cannot use this command.");\r
+ return;\r
+ }\r
(CommandTable[i].handler)(cmd);\r
return;\r
}\r
memcpy(s, c->d.asBytes, c->ext1);\r
s[c->ext1] = '\0';\r
PrintToScrollback("#db# %s", s);\r
- break;
+ break;\r
}\r
\r
case CMD_DEBUG_PRINT_INTEGERS:\r